All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/8] Host1x context isolation support
@ 2021-02-08 16:38 ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: linux-tegra, dri-devel, iommu, linux-kernel, devicetree,
	linux-arm-kernel, Mikko Perttunen

Hi all,

this series adds support for Host1x 'context isolation'. Since
when programming engines through Host1x, userspace can program in
any addresses it wants, we need some way to isolate the engines'
memory spaces. Traditionally this has either been done imperfectly
with a single shared IOMMU domain, or by copying and verifying the
programming command stream at submit time (Host1x firewall).

Since Tegra186 there is a privileged (only usable by kernel)
Host1x opcode that allows setting the stream ID sent by the engine
to the SMMU. So, by allocating a number of context banks and stream
IDs for this purpose, and using this opcode at the beginning of
each job, we can implement isolation. Due to the limited number of
context banks only each process gets its own context, and not
each channel.

This feature also allows sharing engines among multiple VMs when
used with Host1x's hardware virtualization support - up to 8 VMs
can be configured with a subset of allowed stream IDs, enforced
at hardware level.

To implement this, this series adds a new host1x context bus, which
will contain the 'struct device's corresponding to each context
bank / stream ID, changes to device tree and SMMU code to allow
registering the devices and using the bus, as well as the Host1x
stream ID programming code and support in TegraDRM.

The series is based on v5 of the "Host1x/TegraDRM UAPI" series,
which still hasn't quite settled. Also, I haven't updated the
device tree bindings (or converted them to YAML) yet, so this
is RFC for now.

Thanks!

Mikko

Mikko Perttunen (8):
  of/device: Allow specifying a custom iommu_spec to of_dma_configure
  gpu: host1x: Add context bus
  gpu: host1x: Add context device management code
  gpu: host1x: Program context stream ID on submission
  iommu/arm-smmu: Attach to host1x context device bus
  arm64: tegra: Add Host1x context stream IDs on Tegra186+
  drm/tegra: Support context isolation
  drm/tegra: vic: Implement get_streamid_offset

 arch/arm64/boot/dts/nvidia/tegra186.dtsi  |   9 ++
 drivers/gpu/Makefile                      |   3 +-
 drivers/gpu/drm/tegra/drm.h               |   1 +
 drivers/gpu/drm/tegra/uapi.h              |   1 +
 drivers/gpu/drm/tegra/uapi/submit.c       |  13 ++
 drivers/gpu/drm/tegra/uapi/uapi.c         |  34 ++++-
 drivers/gpu/drm/tegra/vic.c               |  38 +++++
 drivers/gpu/host1x/Kconfig                |   5 +
 drivers/gpu/host1x/Makefile               |   2 +
 drivers/gpu/host1x/context.c              | 161 ++++++++++++++++++++++
 drivers/gpu/host1x/context.h              |  27 ++++
 drivers/gpu/host1x/context_bus.c          |  31 +++++
 drivers/gpu/host1x/dev.c                  |  12 +-
 drivers/gpu/host1x/dev.h                  |   2 +
 drivers/gpu/host1x/hw/channel_hw.c        |  52 ++++++-
 drivers/gpu/host1x/hw/host1x06_hardware.h |  10 ++
 drivers/gpu/host1x/hw/host1x07_hardware.h |  10 ++
 drivers/iommu/arm/arm-smmu/arm-smmu.c     |  13 ++
 drivers/iommu/of_iommu.c                  |  12 +-
 drivers/of/device.c                       |   9 +-
 include/linux/host1x.h                    |  21 +++
 include/linux/host1x_context_bus.h        |  15 ++
 include/linux/of_device.h                 |  34 ++++-
 include/linux/of_iommu.h                  |   6 +-
 24 files changed, 495 insertions(+), 26 deletions(-)
 create mode 100644 drivers/gpu/host1x/context.c
 create mode 100644 drivers/gpu/host1x/context.h
 create mode 100644 drivers/gpu/host1x/context_bus.c
 create mode 100644 include/linux/host1x_context_bus.h

-- 
2.30.0


^ permalink raw reply	[flat|nested] 48+ messages in thread

* [RFC PATCH 0/8] Host1x context isolation support
@ 2021-02-08 16:38 ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

Hi all,

this series adds support for Host1x 'context isolation'. Since
when programming engines through Host1x, userspace can program in
any addresses it wants, we need some way to isolate the engines'
memory spaces. Traditionally this has either been done imperfectly
with a single shared IOMMU domain, or by copying and verifying the
programming command stream at submit time (Host1x firewall).

Since Tegra186 there is a privileged (only usable by kernel)
Host1x opcode that allows setting the stream ID sent by the engine
to the SMMU. So, by allocating a number of context banks and stream
IDs for this purpose, and using this opcode at the beginning of
each job, we can implement isolation. Due to the limited number of
context banks only each process gets its own context, and not
each channel.

This feature also allows sharing engines among multiple VMs when
used with Host1x's hardware virtualization support - up to 8 VMs
can be configured with a subset of allowed stream IDs, enforced
at hardware level.

To implement this, this series adds a new host1x context bus, which
will contain the 'struct device's corresponding to each context
bank / stream ID, changes to device tree and SMMU code to allow
registering the devices and using the bus, as well as the Host1x
stream ID programming code and support in TegraDRM.

The series is based on v5 of the "Host1x/TegraDRM UAPI" series,
which still hasn't quite settled. Also, I haven't updated the
device tree bindings (or converted them to YAML) yet, so this
is RFC for now.

Thanks!

Mikko

Mikko Perttunen (8):
  of/device: Allow specifying a custom iommu_spec to of_dma_configure
  gpu: host1x: Add context bus
  gpu: host1x: Add context device management code
  gpu: host1x: Program context stream ID on submission
  iommu/arm-smmu: Attach to host1x context device bus
  arm64: tegra: Add Host1x context stream IDs on Tegra186+
  drm/tegra: Support context isolation
  drm/tegra: vic: Implement get_streamid_offset

 arch/arm64/boot/dts/nvidia/tegra186.dtsi  |   9 ++
 drivers/gpu/Makefile                      |   3 +-
 drivers/gpu/drm/tegra/drm.h               |   1 +
 drivers/gpu/drm/tegra/uapi.h              |   1 +
 drivers/gpu/drm/tegra/uapi/submit.c       |  13 ++
 drivers/gpu/drm/tegra/uapi/uapi.c         |  34 ++++-
 drivers/gpu/drm/tegra/vic.c               |  38 +++++
 drivers/gpu/host1x/Kconfig                |   5 +
 drivers/gpu/host1x/Makefile               |   2 +
 drivers/gpu/host1x/context.c              | 161 ++++++++++++++++++++++
 drivers/gpu/host1x/context.h              |  27 ++++
 drivers/gpu/host1x/context_bus.c          |  31 +++++
 drivers/gpu/host1x/dev.c                  |  12 +-
 drivers/gpu/host1x/dev.h                  |   2 +
 drivers/gpu/host1x/hw/channel_hw.c        |  52 ++++++-
 drivers/gpu/host1x/hw/host1x06_hardware.h |  10 ++
 drivers/gpu/host1x/hw/host1x07_hardware.h |  10 ++
 drivers/iommu/arm/arm-smmu/arm-smmu.c     |  13 ++
 drivers/iommu/of_iommu.c                  |  12 +-
 drivers/of/device.c                       |   9 +-
 include/linux/host1x.h                    |  21 +++
 include/linux/host1x_context_bus.h        |  15 ++
 include/linux/of_device.h                 |  34 ++++-
 include/linux/of_iommu.h                  |   6 +-
 24 files changed, 495 insertions(+), 26 deletions(-)
 create mode 100644 drivers/gpu/host1x/context.c
 create mode 100644 drivers/gpu/host1x/context.h
 create mode 100644 drivers/gpu/host1x/context_bus.c
 create mode 100644 include/linux/host1x_context_bus.h

-- 
2.30.0

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [RFC PATCH 0/8] Host1x context isolation support
@ 2021-02-08 16:38 ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

Hi all,

this series adds support for Host1x 'context isolation'. Since
when programming engines through Host1x, userspace can program in
any addresses it wants, we need some way to isolate the engines'
memory spaces. Traditionally this has either been done imperfectly
with a single shared IOMMU domain, or by copying and verifying the
programming command stream at submit time (Host1x firewall).

Since Tegra186 there is a privileged (only usable by kernel)
Host1x opcode that allows setting the stream ID sent by the engine
to the SMMU. So, by allocating a number of context banks and stream
IDs for this purpose, and using this opcode at the beginning of
each job, we can implement isolation. Due to the limited number of
context banks only each process gets its own context, and not
each channel.

This feature also allows sharing engines among multiple VMs when
used with Host1x's hardware virtualization support - up to 8 VMs
can be configured with a subset of allowed stream IDs, enforced
at hardware level.

To implement this, this series adds a new host1x context bus, which
will contain the 'struct device's corresponding to each context
bank / stream ID, changes to device tree and SMMU code to allow
registering the devices and using the bus, as well as the Host1x
stream ID programming code and support in TegraDRM.

The series is based on v5 of the "Host1x/TegraDRM UAPI" series,
which still hasn't quite settled. Also, I haven't updated the
device tree bindings (or converted them to YAML) yet, so this
is RFC for now.

Thanks!

Mikko

Mikko Perttunen (8):
  of/device: Allow specifying a custom iommu_spec to of_dma_configure
  gpu: host1x: Add context bus
  gpu: host1x: Add context device management code
  gpu: host1x: Program context stream ID on submission
  iommu/arm-smmu: Attach to host1x context device bus
  arm64: tegra: Add Host1x context stream IDs on Tegra186+
  drm/tegra: Support context isolation
  drm/tegra: vic: Implement get_streamid_offset

 arch/arm64/boot/dts/nvidia/tegra186.dtsi  |   9 ++
 drivers/gpu/Makefile                      |   3 +-
 drivers/gpu/drm/tegra/drm.h               |   1 +
 drivers/gpu/drm/tegra/uapi.h              |   1 +
 drivers/gpu/drm/tegra/uapi/submit.c       |  13 ++
 drivers/gpu/drm/tegra/uapi/uapi.c         |  34 ++++-
 drivers/gpu/drm/tegra/vic.c               |  38 +++++
 drivers/gpu/host1x/Kconfig                |   5 +
 drivers/gpu/host1x/Makefile               |   2 +
 drivers/gpu/host1x/context.c              | 161 ++++++++++++++++++++++
 drivers/gpu/host1x/context.h              |  27 ++++
 drivers/gpu/host1x/context_bus.c          |  31 +++++
 drivers/gpu/host1x/dev.c                  |  12 +-
 drivers/gpu/host1x/dev.h                  |   2 +
 drivers/gpu/host1x/hw/channel_hw.c        |  52 ++++++-
 drivers/gpu/host1x/hw/host1x06_hardware.h |  10 ++
 drivers/gpu/host1x/hw/host1x07_hardware.h |  10 ++
 drivers/iommu/arm/arm-smmu/arm-smmu.c     |  13 ++
 drivers/iommu/of_iommu.c                  |  12 +-
 drivers/of/device.c                       |   9 +-
 include/linux/host1x.h                    |  21 +++
 include/linux/host1x_context_bus.h        |  15 ++
 include/linux/of_device.h                 |  34 ++++-
 include/linux/of_iommu.h                  |   6 +-
 24 files changed, 495 insertions(+), 26 deletions(-)
 create mode 100644 drivers/gpu/host1x/context.c
 create mode 100644 drivers/gpu/host1x/context.h
 create mode 100644 drivers/gpu/host1x/context_bus.c
 create mode 100644 include/linux/host1x_context_bus.h

-- 
2.30.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [RFC PATCH 0/8] Host1x context isolation support
@ 2021-02-08 16:38 ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

Hi all,

this series adds support for Host1x 'context isolation'. Since
when programming engines through Host1x, userspace can program in
any addresses it wants, we need some way to isolate the engines'
memory spaces. Traditionally this has either been done imperfectly
with a single shared IOMMU domain, or by copying and verifying the
programming command stream at submit time (Host1x firewall).

Since Tegra186 there is a privileged (only usable by kernel)
Host1x opcode that allows setting the stream ID sent by the engine
to the SMMU. So, by allocating a number of context banks and stream
IDs for this purpose, and using this opcode at the beginning of
each job, we can implement isolation. Due to the limited number of
context banks only each process gets its own context, and not
each channel.

This feature also allows sharing engines among multiple VMs when
used with Host1x's hardware virtualization support - up to 8 VMs
can be configured with a subset of allowed stream IDs, enforced
at hardware level.

To implement this, this series adds a new host1x context bus, which
will contain the 'struct device's corresponding to each context
bank / stream ID, changes to device tree and SMMU code to allow
registering the devices and using the bus, as well as the Host1x
stream ID programming code and support in TegraDRM.

The series is based on v5 of the "Host1x/TegraDRM UAPI" series,
which still hasn't quite settled. Also, I haven't updated the
device tree bindings (or converted them to YAML) yet, so this
is RFC for now.

Thanks!

Mikko

Mikko Perttunen (8):
  of/device: Allow specifying a custom iommu_spec to of_dma_configure
  gpu: host1x: Add context bus
  gpu: host1x: Add context device management code
  gpu: host1x: Program context stream ID on submission
  iommu/arm-smmu: Attach to host1x context device bus
  arm64: tegra: Add Host1x context stream IDs on Tegra186+
  drm/tegra: Support context isolation
  drm/tegra: vic: Implement get_streamid_offset

 arch/arm64/boot/dts/nvidia/tegra186.dtsi  |   9 ++
 drivers/gpu/Makefile                      |   3 +-
 drivers/gpu/drm/tegra/drm.h               |   1 +
 drivers/gpu/drm/tegra/uapi.h              |   1 +
 drivers/gpu/drm/tegra/uapi/submit.c       |  13 ++
 drivers/gpu/drm/tegra/uapi/uapi.c         |  34 ++++-
 drivers/gpu/drm/tegra/vic.c               |  38 +++++
 drivers/gpu/host1x/Kconfig                |   5 +
 drivers/gpu/host1x/Makefile               |   2 +
 drivers/gpu/host1x/context.c              | 161 ++++++++++++++++++++++
 drivers/gpu/host1x/context.h              |  27 ++++
 drivers/gpu/host1x/context_bus.c          |  31 +++++
 drivers/gpu/host1x/dev.c                  |  12 +-
 drivers/gpu/host1x/dev.h                  |   2 +
 drivers/gpu/host1x/hw/channel_hw.c        |  52 ++++++-
 drivers/gpu/host1x/hw/host1x06_hardware.h |  10 ++
 drivers/gpu/host1x/hw/host1x07_hardware.h |  10 ++
 drivers/iommu/arm/arm-smmu/arm-smmu.c     |  13 ++
 drivers/iommu/of_iommu.c                  |  12 +-
 drivers/of/device.c                       |   9 +-
 include/linux/host1x.h                    |  21 +++
 include/linux/host1x_context_bus.h        |  15 ++
 include/linux/of_device.h                 |  34 ++++-
 include/linux/of_iommu.h                  |   6 +-
 24 files changed, 495 insertions(+), 26 deletions(-)
 create mode 100644 drivers/gpu/host1x/context.c
 create mode 100644 drivers/gpu/host1x/context.h
 create mode 100644 drivers/gpu/host1x/context_bus.c
 create mode 100644 include/linux/host1x_context_bus.h

-- 
2.30.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure
  2021-02-08 16:38 ` Mikko Perttunen
  (?)
  (?)
@ 2021-02-08 16:38   ` Mikko Perttunen
  -1 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: linux-tegra, dri-devel, iommu, linux-kernel, devicetree,
	linux-arm-kernel, Mikko Perttunen

To allow for more customized device tree bindings that point to IOMMUs,
allow manual specification of iommu_spec to of_dma_configure.

The initial use case for this is with Host1x, where the driver manages
a set of device tree-defined IOMMU contexts that are dynamically
allocated to various users. These contexts don't correspond to
platform devices and are instead attached to dummy devices on a custom
software bus.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/iommu/of_iommu.c  | 12 ++++++++----
 drivers/of/device.c       |  9 +++++----
 include/linux/of_device.h | 34 +++++++++++++++++++++++++++-------
 include/linux/of_iommu.h  |  6 ++++--
 4 files changed, 44 insertions(+), 17 deletions(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index e505b9130a1c..3fefa6c63863 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -87,8 +87,7 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
 }
 EXPORT_SYMBOL_GPL(of_get_dma_window);
 
-static int of_iommu_xlate(struct device *dev,
-			  struct of_phandle_args *iommu_spec)
+int of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec)
 {
 	const struct iommu_ops *ops;
 	struct fwnode_handle *fwnode = &iommu_spec->np->fwnode;
@@ -117,6 +116,7 @@ static int of_iommu_xlate(struct device *dev,
 	module_put(ops->owner);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(of_iommu_xlate);
 
 static int of_iommu_configure_dev_id(struct device_node *master_np,
 				     struct device *dev,
@@ -177,7 +177,8 @@ static int of_iommu_configure_device(struct device_node *master_np,
 
 const struct iommu_ops *of_iommu_configure(struct device *dev,
 					   struct device_node *master_np,
-					   const u32 *id)
+					   const u32 *id,
+					   struct of_phandle_args *iommu_spec)
 {
 	const struct iommu_ops *ops = NULL;
 	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
@@ -209,7 +210,10 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
 		err = pci_for_each_dma_alias(to_pci_dev(dev),
 					     of_pci_iommu_init, &info);
 	} else {
-		err = of_iommu_configure_device(master_np, dev, id);
+		if (iommu_spec)
+			err = of_iommu_xlate(dev, iommu_spec);
+		else
+			err = of_iommu_configure_device(master_np, dev, id);
 
 		fwspec = dev_iommu_fwspec_get(dev);
 		if (!err && fwspec)
diff --git a/drivers/of/device.c b/drivers/of/device.c
index aedfaaafd3e7..84ada2110c5b 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -88,8 +88,9 @@ int of_device_add(struct platform_device *ofdev)
  * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
  * to fix up DMA configuration.
  */
-int of_dma_configure_id(struct device *dev, struct device_node *np,
-			bool force_dma, const u32 *id)
+int __of_dma_configure(struct device *dev, struct device_node *np,
+			bool force_dma, const u32 *id,
+			struct of_phandle_args *iommu_spec)
 {
 	const struct iommu_ops *iommu;
 	const struct bus_dma_region *map = NULL;
@@ -170,7 +171,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
 	dev_dbg(dev, "device is%sdma coherent\n",
 		coherent ? " " : " not ");
 
-	iommu = of_iommu_configure(dev, np, id);
+	iommu = of_iommu_configure(dev, np, id, iommu_spec);
 	if (PTR_ERR(iommu) == -EPROBE_DEFER) {
 		kfree(map);
 		return -EPROBE_DEFER;
@@ -184,7 +185,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
 	dev->dma_range_map = map;
 	return 0;
 }
-EXPORT_SYMBOL_GPL(of_dma_configure_id);
+EXPORT_SYMBOL_GPL(__of_dma_configure);
 
 int of_device_register(struct platform_device *pdev)
 {
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index 07ca187fc5e4..40cc3e788cb9 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -55,14 +55,27 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
 	return of_node_get(cpu_dev->of_node);
 }
 
-int of_dma_configure_id(struct device *dev,
+int __of_dma_configure(struct device *dev,
 		     struct device_node *np,
-		     bool force_dma, const u32 *id);
+		     bool force_dma, const u32 *id,
+		     struct of_phandle_args *iommu_spec);
 static inline int of_dma_configure(struct device *dev,
 				   struct device_node *np,
 				   bool force_dma)
 {
-	return of_dma_configure_id(dev, np, force_dma, NULL);
+	return __of_dma_configure(dev, np, force_dma, NULL, NULL);
+}
+static inline int of_dma_configure_id(struct device *dev,
+				      struct device_node *np,
+				      bool force_dma, const u32 *id)
+{
+	return __of_dma_configure(dev, np, force_dma, id, NULL);
+}
+static inline int
+of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
+			    bool force_dma, struct of_phandle_args *iommu_spec)
+{
+	return __of_dma_configure(dev, np, force_dma, NULL, iommu_spec);
 }
 #else /* CONFIG_OF */
 
@@ -112,18 +125,25 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
 	return NULL;
 }
 
-static inline int of_dma_configure_id(struct device *dev,
+static inline int of_dma_configure(struct device *dev,
 				   struct device_node *np,
 				   bool force_dma)
 {
 	return 0;
 }
-static inline int of_dma_configure(struct device *dev,
-				   struct device_node *np,
-				   bool force_dma)
+
+static inline int of_dma_configure_id(struct device *dev,
+				      struct device_node *np,
+				      bool force_dma, const u32 *id)
 {
 	return 0;
 }
+
+static inline int
+of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
+			    bool force_dma, struct of_phandle_args *iommu_spec)
+{	return 0;
+}
 #endif /* CONFIG_OF */
 
 #endif /* _LINUX_OF_DEVICE_H */
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
index 16f4b3e87f20..e8d1e6d32d77 100644
--- a/include/linux/of_iommu.h
+++ b/include/linux/of_iommu.h
@@ -14,7 +14,8 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix,
 
 extern const struct iommu_ops *of_iommu_configure(struct device *dev,
 					struct device_node *master_np,
-					const u32 *id);
+					const u32 *id,
+					struct of_phandle_args *iommu_spec);
 
 #else
 
@@ -27,7 +28,8 @@ static inline int of_get_dma_window(struct device_node *dn, const char *prefix,
 
 static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
 					 struct device_node *master_np,
-					 const u32 *id)
+					 const u32 *id,
+					 struct of_phandle_args *iommu_spec);
 {
 	return NULL;
 }
-- 
2.30.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

To allow for more customized device tree bindings that point to IOMMUs,
allow manual specification of iommu_spec to of_dma_configure.

The initial use case for this is with Host1x, where the driver manages
a set of device tree-defined IOMMU contexts that are dynamically
allocated to various users. These contexts don't correspond to
platform devices and are instead attached to dummy devices on a custom
software bus.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/iommu/of_iommu.c  | 12 ++++++++----
 drivers/of/device.c       |  9 +++++----
 include/linux/of_device.h | 34 +++++++++++++++++++++++++++-------
 include/linux/of_iommu.h  |  6 ++++--
 4 files changed, 44 insertions(+), 17 deletions(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index e505b9130a1c..3fefa6c63863 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -87,8 +87,7 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
 }
 EXPORT_SYMBOL_GPL(of_get_dma_window);
 
-static int of_iommu_xlate(struct device *dev,
-			  struct of_phandle_args *iommu_spec)
+int of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec)
 {
 	const struct iommu_ops *ops;
 	struct fwnode_handle *fwnode = &iommu_spec->np->fwnode;
@@ -117,6 +116,7 @@ static int of_iommu_xlate(struct device *dev,
 	module_put(ops->owner);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(of_iommu_xlate);
 
 static int of_iommu_configure_dev_id(struct device_node *master_np,
 				     struct device *dev,
@@ -177,7 +177,8 @@ static int of_iommu_configure_device(struct device_node *master_np,
 
 const struct iommu_ops *of_iommu_configure(struct device *dev,
 					   struct device_node *master_np,
-					   const u32 *id)
+					   const u32 *id,
+					   struct of_phandle_args *iommu_spec)
 {
 	const struct iommu_ops *ops = NULL;
 	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
@@ -209,7 +210,10 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
 		err = pci_for_each_dma_alias(to_pci_dev(dev),
 					     of_pci_iommu_init, &info);
 	} else {
-		err = of_iommu_configure_device(master_np, dev, id);
+		if (iommu_spec)
+			err = of_iommu_xlate(dev, iommu_spec);
+		else
+			err = of_iommu_configure_device(master_np, dev, id);
 
 		fwspec = dev_iommu_fwspec_get(dev);
 		if (!err && fwspec)
diff --git a/drivers/of/device.c b/drivers/of/device.c
index aedfaaafd3e7..84ada2110c5b 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -88,8 +88,9 @@ int of_device_add(struct platform_device *ofdev)
  * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
  * to fix up DMA configuration.
  */
-int of_dma_configure_id(struct device *dev, struct device_node *np,
-			bool force_dma, const u32 *id)
+int __of_dma_configure(struct device *dev, struct device_node *np,
+			bool force_dma, const u32 *id,
+			struct of_phandle_args *iommu_spec)
 {
 	const struct iommu_ops *iommu;
 	const struct bus_dma_region *map = NULL;
@@ -170,7 +171,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
 	dev_dbg(dev, "device is%sdma coherent\n",
 		coherent ? " " : " not ");
 
-	iommu = of_iommu_configure(dev, np, id);
+	iommu = of_iommu_configure(dev, np, id, iommu_spec);
 	if (PTR_ERR(iommu) == -EPROBE_DEFER) {
 		kfree(map);
 		return -EPROBE_DEFER;
@@ -184,7 +185,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
 	dev->dma_range_map = map;
 	return 0;
 }
-EXPORT_SYMBOL_GPL(of_dma_configure_id);
+EXPORT_SYMBOL_GPL(__of_dma_configure);
 
 int of_device_register(struct platform_device *pdev)
 {
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index 07ca187fc5e4..40cc3e788cb9 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -55,14 +55,27 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
 	return of_node_get(cpu_dev->of_node);
 }
 
-int of_dma_configure_id(struct device *dev,
+int __of_dma_configure(struct device *dev,
 		     struct device_node *np,
-		     bool force_dma, const u32 *id);
+		     bool force_dma, const u32 *id,
+		     struct of_phandle_args *iommu_spec);
 static inline int of_dma_configure(struct device *dev,
 				   struct device_node *np,
 				   bool force_dma)
 {
-	return of_dma_configure_id(dev, np, force_dma, NULL);
+	return __of_dma_configure(dev, np, force_dma, NULL, NULL);
+}
+static inline int of_dma_configure_id(struct device *dev,
+				      struct device_node *np,
+				      bool force_dma, const u32 *id)
+{
+	return __of_dma_configure(dev, np, force_dma, id, NULL);
+}
+static inline int
+of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
+			    bool force_dma, struct of_phandle_args *iommu_spec)
+{
+	return __of_dma_configure(dev, np, force_dma, NULL, iommu_spec);
 }
 #else /* CONFIG_OF */
 
@@ -112,18 +125,25 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
 	return NULL;
 }
 
-static inline int of_dma_configure_id(struct device *dev,
+static inline int of_dma_configure(struct device *dev,
 				   struct device_node *np,
 				   bool force_dma)
 {
 	return 0;
 }
-static inline int of_dma_configure(struct device *dev,
-				   struct device_node *np,
-				   bool force_dma)
+
+static inline int of_dma_configure_id(struct device *dev,
+				      struct device_node *np,
+				      bool force_dma, const u32 *id)
 {
 	return 0;
 }
+
+static inline int
+of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
+			    bool force_dma, struct of_phandle_args *iommu_spec)
+{	return 0;
+}
 #endif /* CONFIG_OF */
 
 #endif /* _LINUX_OF_DEVICE_H */
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
index 16f4b3e87f20..e8d1e6d32d77 100644
--- a/include/linux/of_iommu.h
+++ b/include/linux/of_iommu.h
@@ -14,7 +14,8 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix,
 
 extern const struct iommu_ops *of_iommu_configure(struct device *dev,
 					struct device_node *master_np,
-					const u32 *id);
+					const u32 *id,
+					struct of_phandle_args *iommu_spec);
 
 #else
 
@@ -27,7 +28,8 @@ static inline int of_get_dma_window(struct device_node *dn, const char *prefix,
 
 static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
 					 struct device_node *master_np,
-					 const u32 *id)
+					 const u32 *id,
+					 struct of_phandle_args *iommu_spec);
 {
 	return NULL;
 }
-- 
2.30.0

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

To allow for more customized device tree bindings that point to IOMMUs,
allow manual specification of iommu_spec to of_dma_configure.

The initial use case for this is with Host1x, where the driver manages
a set of device tree-defined IOMMU contexts that are dynamically
allocated to various users. These contexts don't correspond to
platform devices and are instead attached to dummy devices on a custom
software bus.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/iommu/of_iommu.c  | 12 ++++++++----
 drivers/of/device.c       |  9 +++++----
 include/linux/of_device.h | 34 +++++++++++++++++++++++++++-------
 include/linux/of_iommu.h  |  6 ++++--
 4 files changed, 44 insertions(+), 17 deletions(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index e505b9130a1c..3fefa6c63863 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -87,8 +87,7 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
 }
 EXPORT_SYMBOL_GPL(of_get_dma_window);
 
-static int of_iommu_xlate(struct device *dev,
-			  struct of_phandle_args *iommu_spec)
+int of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec)
 {
 	const struct iommu_ops *ops;
 	struct fwnode_handle *fwnode = &iommu_spec->np->fwnode;
@@ -117,6 +116,7 @@ static int of_iommu_xlate(struct device *dev,
 	module_put(ops->owner);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(of_iommu_xlate);
 
 static int of_iommu_configure_dev_id(struct device_node *master_np,
 				     struct device *dev,
@@ -177,7 +177,8 @@ static int of_iommu_configure_device(struct device_node *master_np,
 
 const struct iommu_ops *of_iommu_configure(struct device *dev,
 					   struct device_node *master_np,
-					   const u32 *id)
+					   const u32 *id,
+					   struct of_phandle_args *iommu_spec)
 {
 	const struct iommu_ops *ops = NULL;
 	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
@@ -209,7 +210,10 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
 		err = pci_for_each_dma_alias(to_pci_dev(dev),
 					     of_pci_iommu_init, &info);
 	} else {
-		err = of_iommu_configure_device(master_np, dev, id);
+		if (iommu_spec)
+			err = of_iommu_xlate(dev, iommu_spec);
+		else
+			err = of_iommu_configure_device(master_np, dev, id);
 
 		fwspec = dev_iommu_fwspec_get(dev);
 		if (!err && fwspec)
diff --git a/drivers/of/device.c b/drivers/of/device.c
index aedfaaafd3e7..84ada2110c5b 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -88,8 +88,9 @@ int of_device_add(struct platform_device *ofdev)
  * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
  * to fix up DMA configuration.
  */
-int of_dma_configure_id(struct device *dev, struct device_node *np,
-			bool force_dma, const u32 *id)
+int __of_dma_configure(struct device *dev, struct device_node *np,
+			bool force_dma, const u32 *id,
+			struct of_phandle_args *iommu_spec)
 {
 	const struct iommu_ops *iommu;
 	const struct bus_dma_region *map = NULL;
@@ -170,7 +171,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
 	dev_dbg(dev, "device is%sdma coherent\n",
 		coherent ? " " : " not ");
 
-	iommu = of_iommu_configure(dev, np, id);
+	iommu = of_iommu_configure(dev, np, id, iommu_spec);
 	if (PTR_ERR(iommu) == -EPROBE_DEFER) {
 		kfree(map);
 		return -EPROBE_DEFER;
@@ -184,7 +185,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
 	dev->dma_range_map = map;
 	return 0;
 }
-EXPORT_SYMBOL_GPL(of_dma_configure_id);
+EXPORT_SYMBOL_GPL(__of_dma_configure);
 
 int of_device_register(struct platform_device *pdev)
 {
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index 07ca187fc5e4..40cc3e788cb9 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -55,14 +55,27 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
 	return of_node_get(cpu_dev->of_node);
 }
 
-int of_dma_configure_id(struct device *dev,
+int __of_dma_configure(struct device *dev,
 		     struct device_node *np,
-		     bool force_dma, const u32 *id);
+		     bool force_dma, const u32 *id,
+		     struct of_phandle_args *iommu_spec);
 static inline int of_dma_configure(struct device *dev,
 				   struct device_node *np,
 				   bool force_dma)
 {
-	return of_dma_configure_id(dev, np, force_dma, NULL);
+	return __of_dma_configure(dev, np, force_dma, NULL, NULL);
+}
+static inline int of_dma_configure_id(struct device *dev,
+				      struct device_node *np,
+				      bool force_dma, const u32 *id)
+{
+	return __of_dma_configure(dev, np, force_dma, id, NULL);
+}
+static inline int
+of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
+			    bool force_dma, struct of_phandle_args *iommu_spec)
+{
+	return __of_dma_configure(dev, np, force_dma, NULL, iommu_spec);
 }
 #else /* CONFIG_OF */
 
@@ -112,18 +125,25 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
 	return NULL;
 }
 
-static inline int of_dma_configure_id(struct device *dev,
+static inline int of_dma_configure(struct device *dev,
 				   struct device_node *np,
 				   bool force_dma)
 {
 	return 0;
 }
-static inline int of_dma_configure(struct device *dev,
-				   struct device_node *np,
-				   bool force_dma)
+
+static inline int of_dma_configure_id(struct device *dev,
+				      struct device_node *np,
+				      bool force_dma, const u32 *id)
 {
 	return 0;
 }
+
+static inline int
+of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
+			    bool force_dma, struct of_phandle_args *iommu_spec)
+{	return 0;
+}
 #endif /* CONFIG_OF */
 
 #endif /* _LINUX_OF_DEVICE_H */
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
index 16f4b3e87f20..e8d1e6d32d77 100644
--- a/include/linux/of_iommu.h
+++ b/include/linux/of_iommu.h
@@ -14,7 +14,8 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix,
 
 extern const struct iommu_ops *of_iommu_configure(struct device *dev,
 					struct device_node *master_np,
-					const u32 *id);
+					const u32 *id,
+					struct of_phandle_args *iommu_spec);
 
 #else
 
@@ -27,7 +28,8 @@ static inline int of_get_dma_window(struct device_node *dn, const char *prefix,
 
 static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
 					 struct device_node *master_np,
-					 const u32 *id)
+					 const u32 *id,
+					 struct of_phandle_args *iommu_spec);
 {
 	return NULL;
 }
-- 
2.30.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

To allow for more customized device tree bindings that point to IOMMUs,
allow manual specification of iommu_spec to of_dma_configure.

The initial use case for this is with Host1x, where the driver manages
a set of device tree-defined IOMMU contexts that are dynamically
allocated to various users. These contexts don't correspond to
platform devices and are instead attached to dummy devices on a custom
software bus.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/iommu/of_iommu.c  | 12 ++++++++----
 drivers/of/device.c       |  9 +++++----
 include/linux/of_device.h | 34 +++++++++++++++++++++++++++-------
 include/linux/of_iommu.h  |  6 ++++--
 4 files changed, 44 insertions(+), 17 deletions(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index e505b9130a1c..3fefa6c63863 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -87,8 +87,7 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
 }
 EXPORT_SYMBOL_GPL(of_get_dma_window);
 
-static int of_iommu_xlate(struct device *dev,
-			  struct of_phandle_args *iommu_spec)
+int of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec)
 {
 	const struct iommu_ops *ops;
 	struct fwnode_handle *fwnode = &iommu_spec->np->fwnode;
@@ -117,6 +116,7 @@ static int of_iommu_xlate(struct device *dev,
 	module_put(ops->owner);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(of_iommu_xlate);
 
 static int of_iommu_configure_dev_id(struct device_node *master_np,
 				     struct device *dev,
@@ -177,7 +177,8 @@ static int of_iommu_configure_device(struct device_node *master_np,
 
 const struct iommu_ops *of_iommu_configure(struct device *dev,
 					   struct device_node *master_np,
-					   const u32 *id)
+					   const u32 *id,
+					   struct of_phandle_args *iommu_spec)
 {
 	const struct iommu_ops *ops = NULL;
 	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
@@ -209,7 +210,10 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
 		err = pci_for_each_dma_alias(to_pci_dev(dev),
 					     of_pci_iommu_init, &info);
 	} else {
-		err = of_iommu_configure_device(master_np, dev, id);
+		if (iommu_spec)
+			err = of_iommu_xlate(dev, iommu_spec);
+		else
+			err = of_iommu_configure_device(master_np, dev, id);
 
 		fwspec = dev_iommu_fwspec_get(dev);
 		if (!err && fwspec)
diff --git a/drivers/of/device.c b/drivers/of/device.c
index aedfaaafd3e7..84ada2110c5b 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -88,8 +88,9 @@ int of_device_add(struct platform_device *ofdev)
  * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
  * to fix up DMA configuration.
  */
-int of_dma_configure_id(struct device *dev, struct device_node *np,
-			bool force_dma, const u32 *id)
+int __of_dma_configure(struct device *dev, struct device_node *np,
+			bool force_dma, const u32 *id,
+			struct of_phandle_args *iommu_spec)
 {
 	const struct iommu_ops *iommu;
 	const struct bus_dma_region *map = NULL;
@@ -170,7 +171,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
 	dev_dbg(dev, "device is%sdma coherent\n",
 		coherent ? " " : " not ");
 
-	iommu = of_iommu_configure(dev, np, id);
+	iommu = of_iommu_configure(dev, np, id, iommu_spec);
 	if (PTR_ERR(iommu) == -EPROBE_DEFER) {
 		kfree(map);
 		return -EPROBE_DEFER;
@@ -184,7 +185,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
 	dev->dma_range_map = map;
 	return 0;
 }
-EXPORT_SYMBOL_GPL(of_dma_configure_id);
+EXPORT_SYMBOL_GPL(__of_dma_configure);
 
 int of_device_register(struct platform_device *pdev)
 {
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index 07ca187fc5e4..40cc3e788cb9 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -55,14 +55,27 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
 	return of_node_get(cpu_dev->of_node);
 }
 
-int of_dma_configure_id(struct device *dev,
+int __of_dma_configure(struct device *dev,
 		     struct device_node *np,
-		     bool force_dma, const u32 *id);
+		     bool force_dma, const u32 *id,
+		     struct of_phandle_args *iommu_spec);
 static inline int of_dma_configure(struct device *dev,
 				   struct device_node *np,
 				   bool force_dma)
 {
-	return of_dma_configure_id(dev, np, force_dma, NULL);
+	return __of_dma_configure(dev, np, force_dma, NULL, NULL);
+}
+static inline int of_dma_configure_id(struct device *dev,
+				      struct device_node *np,
+				      bool force_dma, const u32 *id)
+{
+	return __of_dma_configure(dev, np, force_dma, id, NULL);
+}
+static inline int
+of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
+			    bool force_dma, struct of_phandle_args *iommu_spec)
+{
+	return __of_dma_configure(dev, np, force_dma, NULL, iommu_spec);
 }
 #else /* CONFIG_OF */
 
@@ -112,18 +125,25 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
 	return NULL;
 }
 
-static inline int of_dma_configure_id(struct device *dev,
+static inline int of_dma_configure(struct device *dev,
 				   struct device_node *np,
 				   bool force_dma)
 {
 	return 0;
 }
-static inline int of_dma_configure(struct device *dev,
-				   struct device_node *np,
-				   bool force_dma)
+
+static inline int of_dma_configure_id(struct device *dev,
+				      struct device_node *np,
+				      bool force_dma, const u32 *id)
 {
 	return 0;
 }
+
+static inline int
+of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
+			    bool force_dma, struct of_phandle_args *iommu_spec)
+{	return 0;
+}
 #endif /* CONFIG_OF */
 
 #endif /* _LINUX_OF_DEVICE_H */
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
index 16f4b3e87f20..e8d1e6d32d77 100644
--- a/include/linux/of_iommu.h
+++ b/include/linux/of_iommu.h
@@ -14,7 +14,8 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix,
 
 extern const struct iommu_ops *of_iommu_configure(struct device *dev,
 					struct device_node *master_np,
-					const u32 *id);
+					const u32 *id,
+					struct of_phandle_args *iommu_spec);
 
 #else
 
@@ -27,7 +28,8 @@ static inline int of_get_dma_window(struct device_node *dn, const char *prefix,
 
 static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
 					 struct device_node *master_np,
-					 const u32 *id)
+					 const u32 *id,
+					 struct of_phandle_args *iommu_spec);
 {
 	return NULL;
 }
-- 
2.30.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 2/8] gpu: host1x: Add context bus
  2021-02-08 16:38 ` Mikko Perttunen
  (?)
  (?)
@ 2021-02-08 16:38   ` Mikko Perttunen
  -1 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: linux-tegra, dri-devel, iommu, linux-kernel, devicetree,
	linux-arm-kernel, Mikko Perttunen

The context bus is a "dummy" bus that contains struct devices that
correspond to IOMMU contexts assigned through Host1x to processes.

Even when host1x itself is built as a module, the bus is registered
in built-in code so that the built-in ARM SMMU driver is able to
reference it.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/Makefile               |  3 +--
 drivers/gpu/host1x/Kconfig         |  5 +++++
 drivers/gpu/host1x/Makefile        |  1 +
 drivers/gpu/host1x/context_bus.c   | 31 ++++++++++++++++++++++++++++++
 include/linux/host1x_context_bus.h | 15 +++++++++++++++
 5 files changed, 53 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/host1x/context_bus.c
 create mode 100644 include/linux/host1x_context_bus.h

diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile
index 835c88318cec..8997f0096545 100644
--- a/drivers/gpu/Makefile
+++ b/drivers/gpu/Makefile
@@ -2,7 +2,6 @@
 # drm/tegra depends on host1x, so if both drivers are built-in care must be
 # taken to initialize them in the correct order. Link order is the only way
 # to ensure this currently.
-obj-$(CONFIG_TEGRA_HOST1X)	+= host1x/
-obj-y			+= drm/ vga/
+obj-y			+= host1x/ drm/ vga/
 obj-$(CONFIG_IMX_IPUV3_CORE)	+= ipu-v3/
 obj-$(CONFIG_TRACE_GPU_MEM)		+= trace/
diff --git a/drivers/gpu/host1x/Kconfig b/drivers/gpu/host1x/Kconfig
index 6dab94adf25e..8546dde3acc8 100644
--- a/drivers/gpu/host1x/Kconfig
+++ b/drivers/gpu/host1x/Kconfig
@@ -1,7 +1,12 @@
 # SPDX-License-Identifier: GPL-2.0-only
+
+config TEGRA_HOST1X_CONTEXT_BUS
+	bool
+
 config TEGRA_HOST1X
 	tristate "NVIDIA Tegra host1x driver"
 	depends on ARCH_TEGRA || (ARM && COMPILE_TEST)
+	select TEGRA_HOST1X_CONTEXT_BUS
 	select IOMMU_IOVA
 	help
 	  Driver for the NVIDIA Tegra host1x hardware.
diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index a48af2cefae1..d9fea2885658 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -19,3 +19,4 @@ host1x-y = \
 	hw/host1x07.o
 
 obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
+obj-$(CONFIG_TEGRA_HOST1X_CONTEXT_BUS) += context_bus.o
diff --git a/drivers/gpu/host1x/context_bus.c b/drivers/gpu/host1x/context_bus.c
new file mode 100644
index 000000000000..2625914f3c7d
--- /dev/null
+++ b/drivers/gpu/host1x/context_bus.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, NVIDIA Corporation.
+ */
+
+#include <linux/device.h>
+#include <linux/of.h>
+
+struct bus_type host1x_context_device_bus_type = {
+	.name = "host1x-context",
+};
+EXPORT_SYMBOL(host1x_context_device_bus_type);
+
+static int __init host1x_context_device_bus_init(void)
+{
+	int err;
+
+	if (!of_machine_is_compatible("nvidia,tegra186") &&
+	    !of_machine_is_compatible("nvidia,tegra194") &&
+	    !of_machine_is_compatible("nvidia,tegra234"))
+		return 0;
+
+	err = bus_register(&host1x_context_device_bus_type);
+	if (err < 0) {
+		pr_err("bus type registration failed: %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+postcore_initcall(host1x_context_device_bus_init);
diff --git a/include/linux/host1x_context_bus.h b/include/linux/host1x_context_bus.h
new file mode 100644
index 000000000000..72462737a6db
--- /dev/null
+++ b/include/linux/host1x_context_bus.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
+ */
+
+#ifndef __LINUX_HOST1X_CONTEXT_BUS_H
+#define __LINUX_HOST1X_CONTEXT_BUS_H
+
+#include <linux/device.h>
+
+#ifdef CONFIG_TEGRA_HOST1X_CONTEXT_BUS
+extern struct bus_type host1x_context_device_bus_type;
+#endif
+
+#endif
-- 
2.30.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 2/8] gpu: host1x: Add context bus
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

The context bus is a "dummy" bus that contains struct devices that
correspond to IOMMU contexts assigned through Host1x to processes.

Even when host1x itself is built as a module, the bus is registered
in built-in code so that the built-in ARM SMMU driver is able to
reference it.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/Makefile               |  3 +--
 drivers/gpu/host1x/Kconfig         |  5 +++++
 drivers/gpu/host1x/Makefile        |  1 +
 drivers/gpu/host1x/context_bus.c   | 31 ++++++++++++++++++++++++++++++
 include/linux/host1x_context_bus.h | 15 +++++++++++++++
 5 files changed, 53 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/host1x/context_bus.c
 create mode 100644 include/linux/host1x_context_bus.h

diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile
index 835c88318cec..8997f0096545 100644
--- a/drivers/gpu/Makefile
+++ b/drivers/gpu/Makefile
@@ -2,7 +2,6 @@
 # drm/tegra depends on host1x, so if both drivers are built-in care must be
 # taken to initialize them in the correct order. Link order is the only way
 # to ensure this currently.
-obj-$(CONFIG_TEGRA_HOST1X)	+= host1x/
-obj-y			+= drm/ vga/
+obj-y			+= host1x/ drm/ vga/
 obj-$(CONFIG_IMX_IPUV3_CORE)	+= ipu-v3/
 obj-$(CONFIG_TRACE_GPU_MEM)		+= trace/
diff --git a/drivers/gpu/host1x/Kconfig b/drivers/gpu/host1x/Kconfig
index 6dab94adf25e..8546dde3acc8 100644
--- a/drivers/gpu/host1x/Kconfig
+++ b/drivers/gpu/host1x/Kconfig
@@ -1,7 +1,12 @@
 # SPDX-License-Identifier: GPL-2.0-only
+
+config TEGRA_HOST1X_CONTEXT_BUS
+	bool
+
 config TEGRA_HOST1X
 	tristate "NVIDIA Tegra host1x driver"
 	depends on ARCH_TEGRA || (ARM && COMPILE_TEST)
+	select TEGRA_HOST1X_CONTEXT_BUS
 	select IOMMU_IOVA
 	help
 	  Driver for the NVIDIA Tegra host1x hardware.
diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index a48af2cefae1..d9fea2885658 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -19,3 +19,4 @@ host1x-y = \
 	hw/host1x07.o
 
 obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
+obj-$(CONFIG_TEGRA_HOST1X_CONTEXT_BUS) += context_bus.o
diff --git a/drivers/gpu/host1x/context_bus.c b/drivers/gpu/host1x/context_bus.c
new file mode 100644
index 000000000000..2625914f3c7d
--- /dev/null
+++ b/drivers/gpu/host1x/context_bus.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, NVIDIA Corporation.
+ */
+
+#include <linux/device.h>
+#include <linux/of.h>
+
+struct bus_type host1x_context_device_bus_type = {
+	.name = "host1x-context",
+};
+EXPORT_SYMBOL(host1x_context_device_bus_type);
+
+static int __init host1x_context_device_bus_init(void)
+{
+	int err;
+
+	if (!of_machine_is_compatible("nvidia,tegra186") &&
+	    !of_machine_is_compatible("nvidia,tegra194") &&
+	    !of_machine_is_compatible("nvidia,tegra234"))
+		return 0;
+
+	err = bus_register(&host1x_context_device_bus_type);
+	if (err < 0) {
+		pr_err("bus type registration failed: %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+postcore_initcall(host1x_context_device_bus_init);
diff --git a/include/linux/host1x_context_bus.h b/include/linux/host1x_context_bus.h
new file mode 100644
index 000000000000..72462737a6db
--- /dev/null
+++ b/include/linux/host1x_context_bus.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
+ */
+
+#ifndef __LINUX_HOST1X_CONTEXT_BUS_H
+#define __LINUX_HOST1X_CONTEXT_BUS_H
+
+#include <linux/device.h>
+
+#ifdef CONFIG_TEGRA_HOST1X_CONTEXT_BUS
+extern struct bus_type host1x_context_device_bus_type;
+#endif
+
+#endif
-- 
2.30.0

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 2/8] gpu: host1x: Add context bus
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

The context bus is a "dummy" bus that contains struct devices that
correspond to IOMMU contexts assigned through Host1x to processes.

Even when host1x itself is built as a module, the bus is registered
in built-in code so that the built-in ARM SMMU driver is able to
reference it.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/Makefile               |  3 +--
 drivers/gpu/host1x/Kconfig         |  5 +++++
 drivers/gpu/host1x/Makefile        |  1 +
 drivers/gpu/host1x/context_bus.c   | 31 ++++++++++++++++++++++++++++++
 include/linux/host1x_context_bus.h | 15 +++++++++++++++
 5 files changed, 53 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/host1x/context_bus.c
 create mode 100644 include/linux/host1x_context_bus.h

diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile
index 835c88318cec..8997f0096545 100644
--- a/drivers/gpu/Makefile
+++ b/drivers/gpu/Makefile
@@ -2,7 +2,6 @@
 # drm/tegra depends on host1x, so if both drivers are built-in care must be
 # taken to initialize them in the correct order. Link order is the only way
 # to ensure this currently.
-obj-$(CONFIG_TEGRA_HOST1X)	+= host1x/
-obj-y			+= drm/ vga/
+obj-y			+= host1x/ drm/ vga/
 obj-$(CONFIG_IMX_IPUV3_CORE)	+= ipu-v3/
 obj-$(CONFIG_TRACE_GPU_MEM)		+= trace/
diff --git a/drivers/gpu/host1x/Kconfig b/drivers/gpu/host1x/Kconfig
index 6dab94adf25e..8546dde3acc8 100644
--- a/drivers/gpu/host1x/Kconfig
+++ b/drivers/gpu/host1x/Kconfig
@@ -1,7 +1,12 @@
 # SPDX-License-Identifier: GPL-2.0-only
+
+config TEGRA_HOST1X_CONTEXT_BUS
+	bool
+
 config TEGRA_HOST1X
 	tristate "NVIDIA Tegra host1x driver"
 	depends on ARCH_TEGRA || (ARM && COMPILE_TEST)
+	select TEGRA_HOST1X_CONTEXT_BUS
 	select IOMMU_IOVA
 	help
 	  Driver for the NVIDIA Tegra host1x hardware.
diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index a48af2cefae1..d9fea2885658 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -19,3 +19,4 @@ host1x-y = \
 	hw/host1x07.o
 
 obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
+obj-$(CONFIG_TEGRA_HOST1X_CONTEXT_BUS) += context_bus.o
diff --git a/drivers/gpu/host1x/context_bus.c b/drivers/gpu/host1x/context_bus.c
new file mode 100644
index 000000000000..2625914f3c7d
--- /dev/null
+++ b/drivers/gpu/host1x/context_bus.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, NVIDIA Corporation.
+ */
+
+#include <linux/device.h>
+#include <linux/of.h>
+
+struct bus_type host1x_context_device_bus_type = {
+	.name = "host1x-context",
+};
+EXPORT_SYMBOL(host1x_context_device_bus_type);
+
+static int __init host1x_context_device_bus_init(void)
+{
+	int err;
+
+	if (!of_machine_is_compatible("nvidia,tegra186") &&
+	    !of_machine_is_compatible("nvidia,tegra194") &&
+	    !of_machine_is_compatible("nvidia,tegra234"))
+		return 0;
+
+	err = bus_register(&host1x_context_device_bus_type);
+	if (err < 0) {
+		pr_err("bus type registration failed: %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+postcore_initcall(host1x_context_device_bus_init);
diff --git a/include/linux/host1x_context_bus.h b/include/linux/host1x_context_bus.h
new file mode 100644
index 000000000000..72462737a6db
--- /dev/null
+++ b/include/linux/host1x_context_bus.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
+ */
+
+#ifndef __LINUX_HOST1X_CONTEXT_BUS_H
+#define __LINUX_HOST1X_CONTEXT_BUS_H
+
+#include <linux/device.h>
+
+#ifdef CONFIG_TEGRA_HOST1X_CONTEXT_BUS
+extern struct bus_type host1x_context_device_bus_type;
+#endif
+
+#endif
-- 
2.30.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 2/8] gpu: host1x: Add context bus
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

The context bus is a "dummy" bus that contains struct devices that
correspond to IOMMU contexts assigned through Host1x to processes.

Even when host1x itself is built as a module, the bus is registered
in built-in code so that the built-in ARM SMMU driver is able to
reference it.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/Makefile               |  3 +--
 drivers/gpu/host1x/Kconfig         |  5 +++++
 drivers/gpu/host1x/Makefile        |  1 +
 drivers/gpu/host1x/context_bus.c   | 31 ++++++++++++++++++++++++++++++
 include/linux/host1x_context_bus.h | 15 +++++++++++++++
 5 files changed, 53 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/host1x/context_bus.c
 create mode 100644 include/linux/host1x_context_bus.h

diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile
index 835c88318cec..8997f0096545 100644
--- a/drivers/gpu/Makefile
+++ b/drivers/gpu/Makefile
@@ -2,7 +2,6 @@
 # drm/tegra depends on host1x, so if both drivers are built-in care must be
 # taken to initialize them in the correct order. Link order is the only way
 # to ensure this currently.
-obj-$(CONFIG_TEGRA_HOST1X)	+= host1x/
-obj-y			+= drm/ vga/
+obj-y			+= host1x/ drm/ vga/
 obj-$(CONFIG_IMX_IPUV3_CORE)	+= ipu-v3/
 obj-$(CONFIG_TRACE_GPU_MEM)		+= trace/
diff --git a/drivers/gpu/host1x/Kconfig b/drivers/gpu/host1x/Kconfig
index 6dab94adf25e..8546dde3acc8 100644
--- a/drivers/gpu/host1x/Kconfig
+++ b/drivers/gpu/host1x/Kconfig
@@ -1,7 +1,12 @@
 # SPDX-License-Identifier: GPL-2.0-only
+
+config TEGRA_HOST1X_CONTEXT_BUS
+	bool
+
 config TEGRA_HOST1X
 	tristate "NVIDIA Tegra host1x driver"
 	depends on ARCH_TEGRA || (ARM && COMPILE_TEST)
+	select TEGRA_HOST1X_CONTEXT_BUS
 	select IOMMU_IOVA
 	help
 	  Driver for the NVIDIA Tegra host1x hardware.
diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index a48af2cefae1..d9fea2885658 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -19,3 +19,4 @@ host1x-y = \
 	hw/host1x07.o
 
 obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
+obj-$(CONFIG_TEGRA_HOST1X_CONTEXT_BUS) += context_bus.o
diff --git a/drivers/gpu/host1x/context_bus.c b/drivers/gpu/host1x/context_bus.c
new file mode 100644
index 000000000000..2625914f3c7d
--- /dev/null
+++ b/drivers/gpu/host1x/context_bus.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, NVIDIA Corporation.
+ */
+
+#include <linux/device.h>
+#include <linux/of.h>
+
+struct bus_type host1x_context_device_bus_type = {
+	.name = "host1x-context",
+};
+EXPORT_SYMBOL(host1x_context_device_bus_type);
+
+static int __init host1x_context_device_bus_init(void)
+{
+	int err;
+
+	if (!of_machine_is_compatible("nvidia,tegra186") &&
+	    !of_machine_is_compatible("nvidia,tegra194") &&
+	    !of_machine_is_compatible("nvidia,tegra234"))
+		return 0;
+
+	err = bus_register(&host1x_context_device_bus_type);
+	if (err < 0) {
+		pr_err("bus type registration failed: %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+postcore_initcall(host1x_context_device_bus_init);
diff --git a/include/linux/host1x_context_bus.h b/include/linux/host1x_context_bus.h
new file mode 100644
index 000000000000..72462737a6db
--- /dev/null
+++ b/include/linux/host1x_context_bus.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
+ */
+
+#ifndef __LINUX_HOST1X_CONTEXT_BUS_H
+#define __LINUX_HOST1X_CONTEXT_BUS_H
+
+#include <linux/device.h>
+
+#ifdef CONFIG_TEGRA_HOST1X_CONTEXT_BUS
+extern struct bus_type host1x_context_device_bus_type;
+#endif
+
+#endif
-- 
2.30.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 3/8] gpu: host1x: Add context device management code
  2021-02-08 16:38 ` Mikko Perttunen
  (?)
  (?)
@ 2021-02-08 16:38   ` Mikko Perttunen
  -1 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: linux-tegra, dri-devel, iommu, linux-kernel, devicetree,
	linux-arm-kernel, Mikko Perttunen

Add code to register context devices from device tree, allocate them
out and manage their refcounts.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/host1x/Makefile  |   1 +
 drivers/gpu/host1x/context.c | 161 +++++++++++++++++++++++++++++++++++
 drivers/gpu/host1x/context.h |  27 ++++++
 drivers/gpu/host1x/dev.c     |  12 ++-
 drivers/gpu/host1x/dev.h     |   2 +
 include/linux/host1x.h       |  17 ++++
 6 files changed, 219 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/host1x/context.c
 create mode 100644 drivers/gpu/host1x/context.h

diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index d9fea2885658..9f6797e39057 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -11,6 +11,7 @@ host1x-y = \
 	mipi.o \
 	uapi.o \
 	fence.o \
+	context.o \
 	hw/host1x01.o \
 	hw/host1x02.o \
 	hw/host1x04.o \
diff --git a/drivers/gpu/host1x/context.c b/drivers/gpu/host1x/context.c
new file mode 100644
index 000000000000..c3bbdb5484c3
--- /dev/null
+++ b/drivers/gpu/host1x/context.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, NVIDIA Corporation.
+ */
+
+#include <linux/device.h>
+#include <linux/kref.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pid.h>
+#include <linux/slab.h>
+
+#include "context.h"
+#include "dev.h"
+
+int host1x_context_list_init(struct host1x *host1x)
+{
+	struct host1x_context_list *cdl = &host1x->context_list;
+	struct host1x_context *ctx;
+	struct of_phandle_args iommu_spec;
+	int index;
+	int err;
+
+	cdl->devs = NULL;
+	cdl->len = 0;
+	mutex_init(&cdl->lock);
+
+	err = of_count_phandle_with_args(host1x->dev->of_node,
+					 "nvidia,context-iommus",
+					 "#iommu-cells");
+	if (err < 0)
+		return 0;
+
+	cdl->devs = kcalloc(err, sizeof(*cdl->devs), GFP_KERNEL);
+	if (!cdl->devs)
+		return -ENOMEM;
+	cdl->len = err;
+
+	for (index = 0; index < cdl->len; index++) {
+		err = of_parse_phandle_with_args(host1x->dev->of_node,
+						 "nvidia,context-iommus",
+						 "#iommu-cells", index,
+						 &iommu_spec);
+		if (err) {
+			dev_err(host1x->dev, "could not parse context device %d from device tree: %d\n",
+				index, err);
+			goto del_devices;
+		}
+
+		ctx = &cdl->devs[index];
+
+		ctx->host = host1x;
+
+		device_initialize(&ctx->dev);
+
+		ctx->dev.coherent_dma_mask = host1x->dev->coherent_dma_mask;
+		ctx->dev.dma_mask = &ctx->dev.coherent_dma_mask;
+		dev_set_name(&ctx->dev, "host1x-ctx.%d", index);
+		ctx->dev.bus = &host1x_context_device_bus_type;
+		ctx->dev.parent = host1x->dev;
+
+		dma_set_max_seg_size(&ctx->dev, UINT_MAX);
+
+		err = device_add(&ctx->dev);
+		if (err) {
+			dev_err(host1x->dev, "could not add context device %d: %d\n", index, err);
+			of_node_put(iommu_spec.np);
+			goto del_devices;
+		}
+
+		err = of_dma_configure_iommu_spec(
+			&ctx->dev, host1x->dev->of_node, false, &iommu_spec);
+		of_node_put(iommu_spec.np);
+		if (err) {
+			dev_err(host1x->dev, "IOMMU configuration failed for context device %d: %d\n",
+				index, err);
+			device_del(&ctx->dev);
+			goto del_devices;
+		}
+
+		ctx->stream_id = iommu_spec.args[0] & 0xffff;
+	}
+
+	return 0;
+
+del_devices:
+	while (--index >= 0)
+		device_del(&cdl->devs[index].dev);
+
+	kfree(cdl->devs);
+	cdl->len = 0;
+
+	return err;
+}
+
+void host1x_context_list_free(struct host1x_context_list *cdl)
+{
+	int i;
+
+	for (i = 0; i < cdl->len; i++)
+		device_del(&cdl->devs[i].dev);
+
+	kfree(cdl->devs);
+	cdl->len = 0;
+}
+
+struct host1x_context *host1x_context_alloc(struct host1x *host1x,
+					    struct pid *pid)
+{
+	struct host1x_context_list *cdl = &host1x->context_list;
+	struct host1x_context *free = NULL;
+	int i;
+
+	if (!cdl->len)
+		return ERR_PTR(-EOPNOTSUPP);
+
+	mutex_lock(&cdl->lock);
+
+	for (i = 0; i < cdl->len; i++) {
+		struct host1x_context *cd = &cdl->devs[i];
+
+		if (cd->owner == pid) {
+			refcount_inc(&cd->ref);
+			mutex_unlock(&cdl->lock);
+			return cd;
+		} else if (!cd->owner && !free) {
+			free = cd;
+		}
+	}
+
+	if (!free) {
+		mutex_unlock(&cdl->lock);
+		return ERR_PTR(-EBUSY);
+	}
+
+	refcount_set(&free->ref, 1);
+	free->owner = get_pid(pid);
+
+	mutex_unlock(&cdl->lock);
+
+	return free;
+}
+EXPORT_SYMBOL(host1x_context_alloc);
+
+void host1x_context_get(struct host1x_context *cd)
+{
+	refcount_inc(&cd->ref);
+}
+EXPORT_SYMBOL(host1x_context_get);
+
+void host1x_context_put(struct host1x_context *cd)
+{
+	struct host1x_context_list *cdl = &cd->host->context_list;
+
+	if (refcount_dec_and_mutex_lock(&cd->ref, &cdl->lock)) {
+		put_pid(cd->owner);
+		cd->owner = NULL;
+		mutex_unlock(&cdl->lock);
+	}
+}
+EXPORT_SYMBOL(host1x_context_put);
diff --git a/drivers/gpu/host1x/context.h b/drivers/gpu/host1x/context.h
new file mode 100644
index 000000000000..268ecdf6b1bb
--- /dev/null
+++ b/drivers/gpu/host1x/context.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Host1x context devices
+ *
+ * Copyright (c) 2020, NVIDIA Corporation.
+ */
+
+#ifndef __HOST1X_CONTEXT_H
+#define __HOST1X_CONTEXT_H
+
+#include <linux/mutex.h>
+#include <linux/refcount.h>
+
+struct host1x;
+
+extern struct bus_type host1x_context_device_bus_type;
+
+struct host1x_context_list {
+	struct mutex lock;
+	struct host1x_context *devs;
+	unsigned int len;
+};
+
+int host1x_context_list_init(struct host1x *host1x);
+void host1x_context_list_free(struct host1x_context_list *cdl);
+
+#endif
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index 8b50fbb22846..300592b5e9a2 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -20,6 +20,7 @@
 
 #include "bus.h"
 #include "channel.h"
+#include "context.h"
 #include "debug.h"
 #include "dev.h"
 #include "intr.h"
@@ -443,10 +444,16 @@ static int host1x_probe(struct platform_device *pdev)
 		goto iommu_exit;
 	}
 
+	err = host1x_context_list_init(host);
+	if (err) {
+		dev_err(&pdev->dev, "failed to initialize context list\n");
+		goto free_channels;
+	}
+
 	err = clk_prepare_enable(host->clk);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to enable clock\n");
-		goto free_channels;
+		goto free_contexts;
 	}
 
 	err = reset_control_deassert(host->rst);
@@ -501,6 +508,8 @@ static int host1x_probe(struct platform_device *pdev)
 	reset_control_assert(host->rst);
 unprepare_disable:
 	clk_disable_unprepare(host->clk);
+free_contexts:
+	host1x_context_list_free(&host->context_list);
 free_channels:
 	host1x_channel_list_free(&host->channel_list);
 iommu_exit:
@@ -520,6 +529,7 @@ static int host1x_remove(struct platform_device *pdev)
 	host1x_syncpt_deinit(host);
 	reset_control_assert(host->rst);
 	clk_disable_unprepare(host->clk);
+	host1x_context_list_free(&host->context_list);
 	host1x_iommu_exit(host);
 
 	return 0;
diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h
index e360bc4a25f6..50cbd6ad28e9 100644
--- a/drivers/gpu/host1x/dev.h
+++ b/drivers/gpu/host1x/dev.h
@@ -14,6 +14,7 @@
 
 #include "cdma.h"
 #include "channel.h"
+#include "context.h"
 #include "intr.h"
 #include "job.h"
 #include "syncpt.h"
@@ -141,6 +142,7 @@ struct host1x {
 	struct mutex syncpt_mutex;
 
 	struct host1x_channel_list channel_list;
+	struct host1x_context_list context_list;
 
 	struct dentry *debugfs;
 
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index 5890f91dd286..3cf3c6a0b225 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -371,4 +371,21 @@ int tegra_mipi_disable(struct tegra_mipi_device *device);
 int tegra_mipi_start_calibration(struct tegra_mipi_device *device);
 int tegra_mipi_finish_calibration(struct tegra_mipi_device *device);
 
+/* host1x context devices */
+
+struct host1x_context {
+	struct host1x *host;
+
+	refcount_t ref;
+	struct pid *owner;
+
+	struct device dev;
+	u32 stream_id;
+};
+
+struct host1x_context *host1x_context_alloc(struct host1x *host1x,
+					    struct pid *pid);
+void host1x_context_get(struct host1x_context *cd);
+void host1x_context_put(struct host1x_context *cd);
+
 #endif
-- 
2.30.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 3/8] gpu: host1x: Add context device management code
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

Add code to register context devices from device tree, allocate them
out and manage their refcounts.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/host1x/Makefile  |   1 +
 drivers/gpu/host1x/context.c | 161 +++++++++++++++++++++++++++++++++++
 drivers/gpu/host1x/context.h |  27 ++++++
 drivers/gpu/host1x/dev.c     |  12 ++-
 drivers/gpu/host1x/dev.h     |   2 +
 include/linux/host1x.h       |  17 ++++
 6 files changed, 219 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/host1x/context.c
 create mode 100644 drivers/gpu/host1x/context.h

diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index d9fea2885658..9f6797e39057 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -11,6 +11,7 @@ host1x-y = \
 	mipi.o \
 	uapi.o \
 	fence.o \
+	context.o \
 	hw/host1x01.o \
 	hw/host1x02.o \
 	hw/host1x04.o \
diff --git a/drivers/gpu/host1x/context.c b/drivers/gpu/host1x/context.c
new file mode 100644
index 000000000000..c3bbdb5484c3
--- /dev/null
+++ b/drivers/gpu/host1x/context.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, NVIDIA Corporation.
+ */
+
+#include <linux/device.h>
+#include <linux/kref.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pid.h>
+#include <linux/slab.h>
+
+#include "context.h"
+#include "dev.h"
+
+int host1x_context_list_init(struct host1x *host1x)
+{
+	struct host1x_context_list *cdl = &host1x->context_list;
+	struct host1x_context *ctx;
+	struct of_phandle_args iommu_spec;
+	int index;
+	int err;
+
+	cdl->devs = NULL;
+	cdl->len = 0;
+	mutex_init(&cdl->lock);
+
+	err = of_count_phandle_with_args(host1x->dev->of_node,
+					 "nvidia,context-iommus",
+					 "#iommu-cells");
+	if (err < 0)
+		return 0;
+
+	cdl->devs = kcalloc(err, sizeof(*cdl->devs), GFP_KERNEL);
+	if (!cdl->devs)
+		return -ENOMEM;
+	cdl->len = err;
+
+	for (index = 0; index < cdl->len; index++) {
+		err = of_parse_phandle_with_args(host1x->dev->of_node,
+						 "nvidia,context-iommus",
+						 "#iommu-cells", index,
+						 &iommu_spec);
+		if (err) {
+			dev_err(host1x->dev, "could not parse context device %d from device tree: %d\n",
+				index, err);
+			goto del_devices;
+		}
+
+		ctx = &cdl->devs[index];
+
+		ctx->host = host1x;
+
+		device_initialize(&ctx->dev);
+
+		ctx->dev.coherent_dma_mask = host1x->dev->coherent_dma_mask;
+		ctx->dev.dma_mask = &ctx->dev.coherent_dma_mask;
+		dev_set_name(&ctx->dev, "host1x-ctx.%d", index);
+		ctx->dev.bus = &host1x_context_device_bus_type;
+		ctx->dev.parent = host1x->dev;
+
+		dma_set_max_seg_size(&ctx->dev, UINT_MAX);
+
+		err = device_add(&ctx->dev);
+		if (err) {
+			dev_err(host1x->dev, "could not add context device %d: %d\n", index, err);
+			of_node_put(iommu_spec.np);
+			goto del_devices;
+		}
+
+		err = of_dma_configure_iommu_spec(
+			&ctx->dev, host1x->dev->of_node, false, &iommu_spec);
+		of_node_put(iommu_spec.np);
+		if (err) {
+			dev_err(host1x->dev, "IOMMU configuration failed for context device %d: %d\n",
+				index, err);
+			device_del(&ctx->dev);
+			goto del_devices;
+		}
+
+		ctx->stream_id = iommu_spec.args[0] & 0xffff;
+	}
+
+	return 0;
+
+del_devices:
+	while (--index >= 0)
+		device_del(&cdl->devs[index].dev);
+
+	kfree(cdl->devs);
+	cdl->len = 0;
+
+	return err;
+}
+
+void host1x_context_list_free(struct host1x_context_list *cdl)
+{
+	int i;
+
+	for (i = 0; i < cdl->len; i++)
+		device_del(&cdl->devs[i].dev);
+
+	kfree(cdl->devs);
+	cdl->len = 0;
+}
+
+struct host1x_context *host1x_context_alloc(struct host1x *host1x,
+					    struct pid *pid)
+{
+	struct host1x_context_list *cdl = &host1x->context_list;
+	struct host1x_context *free = NULL;
+	int i;
+
+	if (!cdl->len)
+		return ERR_PTR(-EOPNOTSUPP);
+
+	mutex_lock(&cdl->lock);
+
+	for (i = 0; i < cdl->len; i++) {
+		struct host1x_context *cd = &cdl->devs[i];
+
+		if (cd->owner == pid) {
+			refcount_inc(&cd->ref);
+			mutex_unlock(&cdl->lock);
+			return cd;
+		} else if (!cd->owner && !free) {
+			free = cd;
+		}
+	}
+
+	if (!free) {
+		mutex_unlock(&cdl->lock);
+		return ERR_PTR(-EBUSY);
+	}
+
+	refcount_set(&free->ref, 1);
+	free->owner = get_pid(pid);
+
+	mutex_unlock(&cdl->lock);
+
+	return free;
+}
+EXPORT_SYMBOL(host1x_context_alloc);
+
+void host1x_context_get(struct host1x_context *cd)
+{
+	refcount_inc(&cd->ref);
+}
+EXPORT_SYMBOL(host1x_context_get);
+
+void host1x_context_put(struct host1x_context *cd)
+{
+	struct host1x_context_list *cdl = &cd->host->context_list;
+
+	if (refcount_dec_and_mutex_lock(&cd->ref, &cdl->lock)) {
+		put_pid(cd->owner);
+		cd->owner = NULL;
+		mutex_unlock(&cdl->lock);
+	}
+}
+EXPORT_SYMBOL(host1x_context_put);
diff --git a/drivers/gpu/host1x/context.h b/drivers/gpu/host1x/context.h
new file mode 100644
index 000000000000..268ecdf6b1bb
--- /dev/null
+++ b/drivers/gpu/host1x/context.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Host1x context devices
+ *
+ * Copyright (c) 2020, NVIDIA Corporation.
+ */
+
+#ifndef __HOST1X_CONTEXT_H
+#define __HOST1X_CONTEXT_H
+
+#include <linux/mutex.h>
+#include <linux/refcount.h>
+
+struct host1x;
+
+extern struct bus_type host1x_context_device_bus_type;
+
+struct host1x_context_list {
+	struct mutex lock;
+	struct host1x_context *devs;
+	unsigned int len;
+};
+
+int host1x_context_list_init(struct host1x *host1x);
+void host1x_context_list_free(struct host1x_context_list *cdl);
+
+#endif
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index 8b50fbb22846..300592b5e9a2 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -20,6 +20,7 @@
 
 #include "bus.h"
 #include "channel.h"
+#include "context.h"
 #include "debug.h"
 #include "dev.h"
 #include "intr.h"
@@ -443,10 +444,16 @@ static int host1x_probe(struct platform_device *pdev)
 		goto iommu_exit;
 	}
 
+	err = host1x_context_list_init(host);
+	if (err) {
+		dev_err(&pdev->dev, "failed to initialize context list\n");
+		goto free_channels;
+	}
+
 	err = clk_prepare_enable(host->clk);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to enable clock\n");
-		goto free_channels;
+		goto free_contexts;
 	}
 
 	err = reset_control_deassert(host->rst);
@@ -501,6 +508,8 @@ static int host1x_probe(struct platform_device *pdev)
 	reset_control_assert(host->rst);
 unprepare_disable:
 	clk_disable_unprepare(host->clk);
+free_contexts:
+	host1x_context_list_free(&host->context_list);
 free_channels:
 	host1x_channel_list_free(&host->channel_list);
 iommu_exit:
@@ -520,6 +529,7 @@ static int host1x_remove(struct platform_device *pdev)
 	host1x_syncpt_deinit(host);
 	reset_control_assert(host->rst);
 	clk_disable_unprepare(host->clk);
+	host1x_context_list_free(&host->context_list);
 	host1x_iommu_exit(host);
 
 	return 0;
diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h
index e360bc4a25f6..50cbd6ad28e9 100644
--- a/drivers/gpu/host1x/dev.h
+++ b/drivers/gpu/host1x/dev.h
@@ -14,6 +14,7 @@
 
 #include "cdma.h"
 #include "channel.h"
+#include "context.h"
 #include "intr.h"
 #include "job.h"
 #include "syncpt.h"
@@ -141,6 +142,7 @@ struct host1x {
 	struct mutex syncpt_mutex;
 
 	struct host1x_channel_list channel_list;
+	struct host1x_context_list context_list;
 
 	struct dentry *debugfs;
 
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index 5890f91dd286..3cf3c6a0b225 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -371,4 +371,21 @@ int tegra_mipi_disable(struct tegra_mipi_device *device);
 int tegra_mipi_start_calibration(struct tegra_mipi_device *device);
 int tegra_mipi_finish_calibration(struct tegra_mipi_device *device);
 
+/* host1x context devices */
+
+struct host1x_context {
+	struct host1x *host;
+
+	refcount_t ref;
+	struct pid *owner;
+
+	struct device dev;
+	u32 stream_id;
+};
+
+struct host1x_context *host1x_context_alloc(struct host1x *host1x,
+					    struct pid *pid);
+void host1x_context_get(struct host1x_context *cd);
+void host1x_context_put(struct host1x_context *cd);
+
 #endif
-- 
2.30.0

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 3/8] gpu: host1x: Add context device management code
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

Add code to register context devices from device tree, allocate them
out and manage their refcounts.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/host1x/Makefile  |   1 +
 drivers/gpu/host1x/context.c | 161 +++++++++++++++++++++++++++++++++++
 drivers/gpu/host1x/context.h |  27 ++++++
 drivers/gpu/host1x/dev.c     |  12 ++-
 drivers/gpu/host1x/dev.h     |   2 +
 include/linux/host1x.h       |  17 ++++
 6 files changed, 219 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/host1x/context.c
 create mode 100644 drivers/gpu/host1x/context.h

diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index d9fea2885658..9f6797e39057 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -11,6 +11,7 @@ host1x-y = \
 	mipi.o \
 	uapi.o \
 	fence.o \
+	context.o \
 	hw/host1x01.o \
 	hw/host1x02.o \
 	hw/host1x04.o \
diff --git a/drivers/gpu/host1x/context.c b/drivers/gpu/host1x/context.c
new file mode 100644
index 000000000000..c3bbdb5484c3
--- /dev/null
+++ b/drivers/gpu/host1x/context.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, NVIDIA Corporation.
+ */
+
+#include <linux/device.h>
+#include <linux/kref.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pid.h>
+#include <linux/slab.h>
+
+#include "context.h"
+#include "dev.h"
+
+int host1x_context_list_init(struct host1x *host1x)
+{
+	struct host1x_context_list *cdl = &host1x->context_list;
+	struct host1x_context *ctx;
+	struct of_phandle_args iommu_spec;
+	int index;
+	int err;
+
+	cdl->devs = NULL;
+	cdl->len = 0;
+	mutex_init(&cdl->lock);
+
+	err = of_count_phandle_with_args(host1x->dev->of_node,
+					 "nvidia,context-iommus",
+					 "#iommu-cells");
+	if (err < 0)
+		return 0;
+
+	cdl->devs = kcalloc(err, sizeof(*cdl->devs), GFP_KERNEL);
+	if (!cdl->devs)
+		return -ENOMEM;
+	cdl->len = err;
+
+	for (index = 0; index < cdl->len; index++) {
+		err = of_parse_phandle_with_args(host1x->dev->of_node,
+						 "nvidia,context-iommus",
+						 "#iommu-cells", index,
+						 &iommu_spec);
+		if (err) {
+			dev_err(host1x->dev, "could not parse context device %d from device tree: %d\n",
+				index, err);
+			goto del_devices;
+		}
+
+		ctx = &cdl->devs[index];
+
+		ctx->host = host1x;
+
+		device_initialize(&ctx->dev);
+
+		ctx->dev.coherent_dma_mask = host1x->dev->coherent_dma_mask;
+		ctx->dev.dma_mask = &ctx->dev.coherent_dma_mask;
+		dev_set_name(&ctx->dev, "host1x-ctx.%d", index);
+		ctx->dev.bus = &host1x_context_device_bus_type;
+		ctx->dev.parent = host1x->dev;
+
+		dma_set_max_seg_size(&ctx->dev, UINT_MAX);
+
+		err = device_add(&ctx->dev);
+		if (err) {
+			dev_err(host1x->dev, "could not add context device %d: %d\n", index, err);
+			of_node_put(iommu_spec.np);
+			goto del_devices;
+		}
+
+		err = of_dma_configure_iommu_spec(
+			&ctx->dev, host1x->dev->of_node, false, &iommu_spec);
+		of_node_put(iommu_spec.np);
+		if (err) {
+			dev_err(host1x->dev, "IOMMU configuration failed for context device %d: %d\n",
+				index, err);
+			device_del(&ctx->dev);
+			goto del_devices;
+		}
+
+		ctx->stream_id = iommu_spec.args[0] & 0xffff;
+	}
+
+	return 0;
+
+del_devices:
+	while (--index >= 0)
+		device_del(&cdl->devs[index].dev);
+
+	kfree(cdl->devs);
+	cdl->len = 0;
+
+	return err;
+}
+
+void host1x_context_list_free(struct host1x_context_list *cdl)
+{
+	int i;
+
+	for (i = 0; i < cdl->len; i++)
+		device_del(&cdl->devs[i].dev);
+
+	kfree(cdl->devs);
+	cdl->len = 0;
+}
+
+struct host1x_context *host1x_context_alloc(struct host1x *host1x,
+					    struct pid *pid)
+{
+	struct host1x_context_list *cdl = &host1x->context_list;
+	struct host1x_context *free = NULL;
+	int i;
+
+	if (!cdl->len)
+		return ERR_PTR(-EOPNOTSUPP);
+
+	mutex_lock(&cdl->lock);
+
+	for (i = 0; i < cdl->len; i++) {
+		struct host1x_context *cd = &cdl->devs[i];
+
+		if (cd->owner == pid) {
+			refcount_inc(&cd->ref);
+			mutex_unlock(&cdl->lock);
+			return cd;
+		} else if (!cd->owner && !free) {
+			free = cd;
+		}
+	}
+
+	if (!free) {
+		mutex_unlock(&cdl->lock);
+		return ERR_PTR(-EBUSY);
+	}
+
+	refcount_set(&free->ref, 1);
+	free->owner = get_pid(pid);
+
+	mutex_unlock(&cdl->lock);
+
+	return free;
+}
+EXPORT_SYMBOL(host1x_context_alloc);
+
+void host1x_context_get(struct host1x_context *cd)
+{
+	refcount_inc(&cd->ref);
+}
+EXPORT_SYMBOL(host1x_context_get);
+
+void host1x_context_put(struct host1x_context *cd)
+{
+	struct host1x_context_list *cdl = &cd->host->context_list;
+
+	if (refcount_dec_and_mutex_lock(&cd->ref, &cdl->lock)) {
+		put_pid(cd->owner);
+		cd->owner = NULL;
+		mutex_unlock(&cdl->lock);
+	}
+}
+EXPORT_SYMBOL(host1x_context_put);
diff --git a/drivers/gpu/host1x/context.h b/drivers/gpu/host1x/context.h
new file mode 100644
index 000000000000..268ecdf6b1bb
--- /dev/null
+++ b/drivers/gpu/host1x/context.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Host1x context devices
+ *
+ * Copyright (c) 2020, NVIDIA Corporation.
+ */
+
+#ifndef __HOST1X_CONTEXT_H
+#define __HOST1X_CONTEXT_H
+
+#include <linux/mutex.h>
+#include <linux/refcount.h>
+
+struct host1x;
+
+extern struct bus_type host1x_context_device_bus_type;
+
+struct host1x_context_list {
+	struct mutex lock;
+	struct host1x_context *devs;
+	unsigned int len;
+};
+
+int host1x_context_list_init(struct host1x *host1x);
+void host1x_context_list_free(struct host1x_context_list *cdl);
+
+#endif
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index 8b50fbb22846..300592b5e9a2 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -20,6 +20,7 @@
 
 #include "bus.h"
 #include "channel.h"
+#include "context.h"
 #include "debug.h"
 #include "dev.h"
 #include "intr.h"
@@ -443,10 +444,16 @@ static int host1x_probe(struct platform_device *pdev)
 		goto iommu_exit;
 	}
 
+	err = host1x_context_list_init(host);
+	if (err) {
+		dev_err(&pdev->dev, "failed to initialize context list\n");
+		goto free_channels;
+	}
+
 	err = clk_prepare_enable(host->clk);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to enable clock\n");
-		goto free_channels;
+		goto free_contexts;
 	}
 
 	err = reset_control_deassert(host->rst);
@@ -501,6 +508,8 @@ static int host1x_probe(struct platform_device *pdev)
 	reset_control_assert(host->rst);
 unprepare_disable:
 	clk_disable_unprepare(host->clk);
+free_contexts:
+	host1x_context_list_free(&host->context_list);
 free_channels:
 	host1x_channel_list_free(&host->channel_list);
 iommu_exit:
@@ -520,6 +529,7 @@ static int host1x_remove(struct platform_device *pdev)
 	host1x_syncpt_deinit(host);
 	reset_control_assert(host->rst);
 	clk_disable_unprepare(host->clk);
+	host1x_context_list_free(&host->context_list);
 	host1x_iommu_exit(host);
 
 	return 0;
diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h
index e360bc4a25f6..50cbd6ad28e9 100644
--- a/drivers/gpu/host1x/dev.h
+++ b/drivers/gpu/host1x/dev.h
@@ -14,6 +14,7 @@
 
 #include "cdma.h"
 #include "channel.h"
+#include "context.h"
 #include "intr.h"
 #include "job.h"
 #include "syncpt.h"
@@ -141,6 +142,7 @@ struct host1x {
 	struct mutex syncpt_mutex;
 
 	struct host1x_channel_list channel_list;
+	struct host1x_context_list context_list;
 
 	struct dentry *debugfs;
 
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index 5890f91dd286..3cf3c6a0b225 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -371,4 +371,21 @@ int tegra_mipi_disable(struct tegra_mipi_device *device);
 int tegra_mipi_start_calibration(struct tegra_mipi_device *device);
 int tegra_mipi_finish_calibration(struct tegra_mipi_device *device);
 
+/* host1x context devices */
+
+struct host1x_context {
+	struct host1x *host;
+
+	refcount_t ref;
+	struct pid *owner;
+
+	struct device dev;
+	u32 stream_id;
+};
+
+struct host1x_context *host1x_context_alloc(struct host1x *host1x,
+					    struct pid *pid);
+void host1x_context_get(struct host1x_context *cd);
+void host1x_context_put(struct host1x_context *cd);
+
 #endif
-- 
2.30.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 3/8] gpu: host1x: Add context device management code
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

Add code to register context devices from device tree, allocate them
out and manage their refcounts.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/host1x/Makefile  |   1 +
 drivers/gpu/host1x/context.c | 161 +++++++++++++++++++++++++++++++++++
 drivers/gpu/host1x/context.h |  27 ++++++
 drivers/gpu/host1x/dev.c     |  12 ++-
 drivers/gpu/host1x/dev.h     |   2 +
 include/linux/host1x.h       |  17 ++++
 6 files changed, 219 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/host1x/context.c
 create mode 100644 drivers/gpu/host1x/context.h

diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index d9fea2885658..9f6797e39057 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -11,6 +11,7 @@ host1x-y = \
 	mipi.o \
 	uapi.o \
 	fence.o \
+	context.o \
 	hw/host1x01.o \
 	hw/host1x02.o \
 	hw/host1x04.o \
diff --git a/drivers/gpu/host1x/context.c b/drivers/gpu/host1x/context.c
new file mode 100644
index 000000000000..c3bbdb5484c3
--- /dev/null
+++ b/drivers/gpu/host1x/context.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, NVIDIA Corporation.
+ */
+
+#include <linux/device.h>
+#include <linux/kref.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pid.h>
+#include <linux/slab.h>
+
+#include "context.h"
+#include "dev.h"
+
+int host1x_context_list_init(struct host1x *host1x)
+{
+	struct host1x_context_list *cdl = &host1x->context_list;
+	struct host1x_context *ctx;
+	struct of_phandle_args iommu_spec;
+	int index;
+	int err;
+
+	cdl->devs = NULL;
+	cdl->len = 0;
+	mutex_init(&cdl->lock);
+
+	err = of_count_phandle_with_args(host1x->dev->of_node,
+					 "nvidia,context-iommus",
+					 "#iommu-cells");
+	if (err < 0)
+		return 0;
+
+	cdl->devs = kcalloc(err, sizeof(*cdl->devs), GFP_KERNEL);
+	if (!cdl->devs)
+		return -ENOMEM;
+	cdl->len = err;
+
+	for (index = 0; index < cdl->len; index++) {
+		err = of_parse_phandle_with_args(host1x->dev->of_node,
+						 "nvidia,context-iommus",
+						 "#iommu-cells", index,
+						 &iommu_spec);
+		if (err) {
+			dev_err(host1x->dev, "could not parse context device %d from device tree: %d\n",
+				index, err);
+			goto del_devices;
+		}
+
+		ctx = &cdl->devs[index];
+
+		ctx->host = host1x;
+
+		device_initialize(&ctx->dev);
+
+		ctx->dev.coherent_dma_mask = host1x->dev->coherent_dma_mask;
+		ctx->dev.dma_mask = &ctx->dev.coherent_dma_mask;
+		dev_set_name(&ctx->dev, "host1x-ctx.%d", index);
+		ctx->dev.bus = &host1x_context_device_bus_type;
+		ctx->dev.parent = host1x->dev;
+
+		dma_set_max_seg_size(&ctx->dev, UINT_MAX);
+
+		err = device_add(&ctx->dev);
+		if (err) {
+			dev_err(host1x->dev, "could not add context device %d: %d\n", index, err);
+			of_node_put(iommu_spec.np);
+			goto del_devices;
+		}
+
+		err = of_dma_configure_iommu_spec(
+			&ctx->dev, host1x->dev->of_node, false, &iommu_spec);
+		of_node_put(iommu_spec.np);
+		if (err) {
+			dev_err(host1x->dev, "IOMMU configuration failed for context device %d: %d\n",
+				index, err);
+			device_del(&ctx->dev);
+			goto del_devices;
+		}
+
+		ctx->stream_id = iommu_spec.args[0] & 0xffff;
+	}
+
+	return 0;
+
+del_devices:
+	while (--index >= 0)
+		device_del(&cdl->devs[index].dev);
+
+	kfree(cdl->devs);
+	cdl->len = 0;
+
+	return err;
+}
+
+void host1x_context_list_free(struct host1x_context_list *cdl)
+{
+	int i;
+
+	for (i = 0; i < cdl->len; i++)
+		device_del(&cdl->devs[i].dev);
+
+	kfree(cdl->devs);
+	cdl->len = 0;
+}
+
+struct host1x_context *host1x_context_alloc(struct host1x *host1x,
+					    struct pid *pid)
+{
+	struct host1x_context_list *cdl = &host1x->context_list;
+	struct host1x_context *free = NULL;
+	int i;
+
+	if (!cdl->len)
+		return ERR_PTR(-EOPNOTSUPP);
+
+	mutex_lock(&cdl->lock);
+
+	for (i = 0; i < cdl->len; i++) {
+		struct host1x_context *cd = &cdl->devs[i];
+
+		if (cd->owner == pid) {
+			refcount_inc(&cd->ref);
+			mutex_unlock(&cdl->lock);
+			return cd;
+		} else if (!cd->owner && !free) {
+			free = cd;
+		}
+	}
+
+	if (!free) {
+		mutex_unlock(&cdl->lock);
+		return ERR_PTR(-EBUSY);
+	}
+
+	refcount_set(&free->ref, 1);
+	free->owner = get_pid(pid);
+
+	mutex_unlock(&cdl->lock);
+
+	return free;
+}
+EXPORT_SYMBOL(host1x_context_alloc);
+
+void host1x_context_get(struct host1x_context *cd)
+{
+	refcount_inc(&cd->ref);
+}
+EXPORT_SYMBOL(host1x_context_get);
+
+void host1x_context_put(struct host1x_context *cd)
+{
+	struct host1x_context_list *cdl = &cd->host->context_list;
+
+	if (refcount_dec_and_mutex_lock(&cd->ref, &cdl->lock)) {
+		put_pid(cd->owner);
+		cd->owner = NULL;
+		mutex_unlock(&cdl->lock);
+	}
+}
+EXPORT_SYMBOL(host1x_context_put);
diff --git a/drivers/gpu/host1x/context.h b/drivers/gpu/host1x/context.h
new file mode 100644
index 000000000000..268ecdf6b1bb
--- /dev/null
+++ b/drivers/gpu/host1x/context.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Host1x context devices
+ *
+ * Copyright (c) 2020, NVIDIA Corporation.
+ */
+
+#ifndef __HOST1X_CONTEXT_H
+#define __HOST1X_CONTEXT_H
+
+#include <linux/mutex.h>
+#include <linux/refcount.h>
+
+struct host1x;
+
+extern struct bus_type host1x_context_device_bus_type;
+
+struct host1x_context_list {
+	struct mutex lock;
+	struct host1x_context *devs;
+	unsigned int len;
+};
+
+int host1x_context_list_init(struct host1x *host1x);
+void host1x_context_list_free(struct host1x_context_list *cdl);
+
+#endif
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index 8b50fbb22846..300592b5e9a2 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -20,6 +20,7 @@
 
 #include "bus.h"
 #include "channel.h"
+#include "context.h"
 #include "debug.h"
 #include "dev.h"
 #include "intr.h"
@@ -443,10 +444,16 @@ static int host1x_probe(struct platform_device *pdev)
 		goto iommu_exit;
 	}
 
+	err = host1x_context_list_init(host);
+	if (err) {
+		dev_err(&pdev->dev, "failed to initialize context list\n");
+		goto free_channels;
+	}
+
 	err = clk_prepare_enable(host->clk);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to enable clock\n");
-		goto free_channels;
+		goto free_contexts;
 	}
 
 	err = reset_control_deassert(host->rst);
@@ -501,6 +508,8 @@ static int host1x_probe(struct platform_device *pdev)
 	reset_control_assert(host->rst);
 unprepare_disable:
 	clk_disable_unprepare(host->clk);
+free_contexts:
+	host1x_context_list_free(&host->context_list);
 free_channels:
 	host1x_channel_list_free(&host->channel_list);
 iommu_exit:
@@ -520,6 +529,7 @@ static int host1x_remove(struct platform_device *pdev)
 	host1x_syncpt_deinit(host);
 	reset_control_assert(host->rst);
 	clk_disable_unprepare(host->clk);
+	host1x_context_list_free(&host->context_list);
 	host1x_iommu_exit(host);
 
 	return 0;
diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h
index e360bc4a25f6..50cbd6ad28e9 100644
--- a/drivers/gpu/host1x/dev.h
+++ b/drivers/gpu/host1x/dev.h
@@ -14,6 +14,7 @@
 
 #include "cdma.h"
 #include "channel.h"
+#include "context.h"
 #include "intr.h"
 #include "job.h"
 #include "syncpt.h"
@@ -141,6 +142,7 @@ struct host1x {
 	struct mutex syncpt_mutex;
 
 	struct host1x_channel_list channel_list;
+	struct host1x_context_list context_list;
 
 	struct dentry *debugfs;
 
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index 5890f91dd286..3cf3c6a0b225 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -371,4 +371,21 @@ int tegra_mipi_disable(struct tegra_mipi_device *device);
 int tegra_mipi_start_calibration(struct tegra_mipi_device *device);
 int tegra_mipi_finish_calibration(struct tegra_mipi_device *device);
 
+/* host1x context devices */
+
+struct host1x_context {
+	struct host1x *host;
+
+	refcount_t ref;
+	struct pid *owner;
+
+	struct device dev;
+	u32 stream_id;
+};
+
+struct host1x_context *host1x_context_alloc(struct host1x *host1x,
+					    struct pid *pid);
+void host1x_context_get(struct host1x_context *cd);
+void host1x_context_put(struct host1x_context *cd);
+
 #endif
-- 
2.30.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 4/8] gpu: host1x: Program context stream ID on submission
  2021-02-08 16:38 ` Mikko Perttunen
  (?)
  (?)
@ 2021-02-08 16:38   ` Mikko Perttunen
  -1 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: linux-tegra, dri-devel, iommu, linux-kernel, devicetree,
	linux-arm-kernel, Mikko Perttunen

Add code to do stream ID switching at the beginning of a job. The
stream ID is switched to the stream ID specified by the context
passed in the job structure.

Before switching the stream ID, an OP_DONE wait is done on the
channel's engine to ensure that there is no residual ongoing
work that might do DMA using the new stream ID.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/host1x/hw/channel_hw.c        | 52 +++++++++++++++++++++--
 drivers/gpu/host1x/hw/host1x06_hardware.h | 10 +++++
 drivers/gpu/host1x/hw/host1x07_hardware.h | 10 +++++
 include/linux/host1x.h                    |  4 ++
 4 files changed, 72 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/host1x/hw/channel_hw.c b/drivers/gpu/host1x/hw/channel_hw.c
index d88a32f73f5e..f97296864da8 100644
--- a/drivers/gpu/host1x/hw/channel_hw.c
+++ b/drivers/gpu/host1x/hw/channel_hw.c
@@ -129,6 +129,45 @@ static void host1x_channel_set_streamid(struct host1x_channel *channel)
 #endif
 }
 
+static void host1x_channel_program_engine_streamid(struct host1x_job *job)
+{
+#if HOST1X_HW >= 6
+	u32 fence;
+
+	if (!job->context)
+		return;
+
+	fence = host1x_syncpt_incr_max(job->syncpt, 1);
+
+	/* First, increment a syncpoint on OP_DONE condition.. */
+
+	host1x_cdma_push(&job->channel->cdma,
+		host1x_opcode_nonincr(HOST1X_UCLASS_INCR_SYNCPT, 1),
+		HOST1X_UCLASS_INCR_SYNCPT_INDX_F(job->syncpt->id) |
+			HOST1X_UCLASS_INCR_SYNCPT_COND_F(1));
+
+	/* Wait for syncpoint to increment */
+
+	host1x_cdma_push(&job->channel->cdma,
+		host1x_opcode_setclass(HOST1X_CLASS_HOST1X,
+			host1x_uclass_wait_syncpt_r(), 1),
+		host1x_class_host_wait_syncpt(job->syncpt->id, fence));
+
+	/*
+	 * Now that we know the engine is idle, return to class and
+	 * change stream ID.
+	 */
+
+	host1x_cdma_push(&job->channel->cdma,
+		host1x_opcode_setclass(job->class, 0, 0),
+		HOST1X_OPCODE_NOP);
+
+	host1x_cdma_push(&job->channel->cdma,
+		host1x_opcode_setpayload(job->context->stream_id),
+		host1x_opcode_setstreamid(job->engine_streamid_offset / 4));
+#endif
+}
+
 static int channel_submit(struct host1x_job *job)
 {
 	struct host1x_channel *ch = job->channel;
@@ -184,18 +223,23 @@ static int channel_submit(struct host1x_job *job)
 	if (sp->base)
 		synchronize_syncpt_base(job);
 
-	syncval = host1x_syncpt_incr_max(sp, user_syncpt_incrs);
-
 	host1x_hw_syncpt_assign_to_channel(host, sp, ch);
 
-	job->syncpt_end = syncval;
-
 	/* add a setclass for modules that require it */
 	if (job->class)
 		host1x_cdma_push(&ch->cdma,
 				 host1x_opcode_setclass(job->class, 0, 0),
 				 HOST1X_OPCODE_NOP);
 
+	/*
+	 * Ensure engine DMA is idle and set new stream ID. May increment
+	 * syncpt max.
+	 */
+	host1x_channel_program_engine_streamid(job);
+
+	syncval = host1x_syncpt_incr_max(sp, user_syncpt_incrs);
+	job->syncpt_end = syncval;
+
 	submit_gathers(job);
 
 	/* end CDMA submit & stash pinned hMems into sync queue */
diff --git a/drivers/gpu/host1x/hw/host1x06_hardware.h b/drivers/gpu/host1x/hw/host1x06_hardware.h
index 01a142a09800..5d515745eee7 100644
--- a/drivers/gpu/host1x/hw/host1x06_hardware.h
+++ b/drivers/gpu/host1x/hw/host1x06_hardware.h
@@ -127,6 +127,16 @@ static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count)
 	return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count;
 }
 
+static inline u32 host1x_opcode_setstreamid(unsigned streamid)
+{
+	return (7 << 28) | streamid;
+}
+
+static inline u32 host1x_opcode_setpayload(unsigned payload)
+{
+	return (9 << 28) | payload;
+}
+
 static inline u32 host1x_opcode_gather_wide(unsigned count)
 {
 	return (12 << 28) | count;
diff --git a/drivers/gpu/host1x/hw/host1x07_hardware.h b/drivers/gpu/host1x/hw/host1x07_hardware.h
index e6582172ebfd..82c0cc9bb0b5 100644
--- a/drivers/gpu/host1x/hw/host1x07_hardware.h
+++ b/drivers/gpu/host1x/hw/host1x07_hardware.h
@@ -127,6 +127,16 @@ static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count)
 	return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count;
 }
 
+static inline u32 host1x_opcode_setstreamid(unsigned streamid)
+{
+	return (7 << 28) | streamid;
+}
+
+static inline u32 host1x_opcode_setpayload(unsigned payload)
+{
+	return (9 << 28) | payload;
+}
+
 static inline u32 host1x_opcode_gather_wide(unsigned count)
 {
 	return (12 << 28) | count;
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index 3cf3c6a0b225..3bf19080f1c1 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -272,6 +272,10 @@ struct host1x_job {
 	/* Callback called when job is freed */
 	void (*release)(struct host1x_job *job);
 	void *user_data;
+
+	/* Options for configuring engine data stream ID */
+	struct host1x_context *context;
+	u32 engine_streamid_offset;
 };
 
 struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,
-- 
2.30.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 4/8] gpu: host1x: Program context stream ID on submission
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

Add code to do stream ID switching at the beginning of a job. The
stream ID is switched to the stream ID specified by the context
passed in the job structure.

Before switching the stream ID, an OP_DONE wait is done on the
channel's engine to ensure that there is no residual ongoing
work that might do DMA using the new stream ID.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/host1x/hw/channel_hw.c        | 52 +++++++++++++++++++++--
 drivers/gpu/host1x/hw/host1x06_hardware.h | 10 +++++
 drivers/gpu/host1x/hw/host1x07_hardware.h | 10 +++++
 include/linux/host1x.h                    |  4 ++
 4 files changed, 72 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/host1x/hw/channel_hw.c b/drivers/gpu/host1x/hw/channel_hw.c
index d88a32f73f5e..f97296864da8 100644
--- a/drivers/gpu/host1x/hw/channel_hw.c
+++ b/drivers/gpu/host1x/hw/channel_hw.c
@@ -129,6 +129,45 @@ static void host1x_channel_set_streamid(struct host1x_channel *channel)
 #endif
 }
 
+static void host1x_channel_program_engine_streamid(struct host1x_job *job)
+{
+#if HOST1X_HW >= 6
+	u32 fence;
+
+	if (!job->context)
+		return;
+
+	fence = host1x_syncpt_incr_max(job->syncpt, 1);
+
+	/* First, increment a syncpoint on OP_DONE condition.. */
+
+	host1x_cdma_push(&job->channel->cdma,
+		host1x_opcode_nonincr(HOST1X_UCLASS_INCR_SYNCPT, 1),
+		HOST1X_UCLASS_INCR_SYNCPT_INDX_F(job->syncpt->id) |
+			HOST1X_UCLASS_INCR_SYNCPT_COND_F(1));
+
+	/* Wait for syncpoint to increment */
+
+	host1x_cdma_push(&job->channel->cdma,
+		host1x_opcode_setclass(HOST1X_CLASS_HOST1X,
+			host1x_uclass_wait_syncpt_r(), 1),
+		host1x_class_host_wait_syncpt(job->syncpt->id, fence));
+
+	/*
+	 * Now that we know the engine is idle, return to class and
+	 * change stream ID.
+	 */
+
+	host1x_cdma_push(&job->channel->cdma,
+		host1x_opcode_setclass(job->class, 0, 0),
+		HOST1X_OPCODE_NOP);
+
+	host1x_cdma_push(&job->channel->cdma,
+		host1x_opcode_setpayload(job->context->stream_id),
+		host1x_opcode_setstreamid(job->engine_streamid_offset / 4));
+#endif
+}
+
 static int channel_submit(struct host1x_job *job)
 {
 	struct host1x_channel *ch = job->channel;
@@ -184,18 +223,23 @@ static int channel_submit(struct host1x_job *job)
 	if (sp->base)
 		synchronize_syncpt_base(job);
 
-	syncval = host1x_syncpt_incr_max(sp, user_syncpt_incrs);
-
 	host1x_hw_syncpt_assign_to_channel(host, sp, ch);
 
-	job->syncpt_end = syncval;
-
 	/* add a setclass for modules that require it */
 	if (job->class)
 		host1x_cdma_push(&ch->cdma,
 				 host1x_opcode_setclass(job->class, 0, 0),
 				 HOST1X_OPCODE_NOP);
 
+	/*
+	 * Ensure engine DMA is idle and set new stream ID. May increment
+	 * syncpt max.
+	 */
+	host1x_channel_program_engine_streamid(job);
+
+	syncval = host1x_syncpt_incr_max(sp, user_syncpt_incrs);
+	job->syncpt_end = syncval;
+
 	submit_gathers(job);
 
 	/* end CDMA submit & stash pinned hMems into sync queue */
diff --git a/drivers/gpu/host1x/hw/host1x06_hardware.h b/drivers/gpu/host1x/hw/host1x06_hardware.h
index 01a142a09800..5d515745eee7 100644
--- a/drivers/gpu/host1x/hw/host1x06_hardware.h
+++ b/drivers/gpu/host1x/hw/host1x06_hardware.h
@@ -127,6 +127,16 @@ static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count)
 	return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count;
 }
 
+static inline u32 host1x_opcode_setstreamid(unsigned streamid)
+{
+	return (7 << 28) | streamid;
+}
+
+static inline u32 host1x_opcode_setpayload(unsigned payload)
+{
+	return (9 << 28) | payload;
+}
+
 static inline u32 host1x_opcode_gather_wide(unsigned count)
 {
 	return (12 << 28) | count;
diff --git a/drivers/gpu/host1x/hw/host1x07_hardware.h b/drivers/gpu/host1x/hw/host1x07_hardware.h
index e6582172ebfd..82c0cc9bb0b5 100644
--- a/drivers/gpu/host1x/hw/host1x07_hardware.h
+++ b/drivers/gpu/host1x/hw/host1x07_hardware.h
@@ -127,6 +127,16 @@ static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count)
 	return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count;
 }
 
+static inline u32 host1x_opcode_setstreamid(unsigned streamid)
+{
+	return (7 << 28) | streamid;
+}
+
+static inline u32 host1x_opcode_setpayload(unsigned payload)
+{
+	return (9 << 28) | payload;
+}
+
 static inline u32 host1x_opcode_gather_wide(unsigned count)
 {
 	return (12 << 28) | count;
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index 3cf3c6a0b225..3bf19080f1c1 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -272,6 +272,10 @@ struct host1x_job {
 	/* Callback called when job is freed */
 	void (*release)(struct host1x_job *job);
 	void *user_data;
+
+	/* Options for configuring engine data stream ID */
+	struct host1x_context *context;
+	u32 engine_streamid_offset;
 };
 
 struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,
-- 
2.30.0

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 4/8] gpu: host1x: Program context stream ID on submission
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

Add code to do stream ID switching at the beginning of a job. The
stream ID is switched to the stream ID specified by the context
passed in the job structure.

Before switching the stream ID, an OP_DONE wait is done on the
channel's engine to ensure that there is no residual ongoing
work that might do DMA using the new stream ID.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/host1x/hw/channel_hw.c        | 52 +++++++++++++++++++++--
 drivers/gpu/host1x/hw/host1x06_hardware.h | 10 +++++
 drivers/gpu/host1x/hw/host1x07_hardware.h | 10 +++++
 include/linux/host1x.h                    |  4 ++
 4 files changed, 72 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/host1x/hw/channel_hw.c b/drivers/gpu/host1x/hw/channel_hw.c
index d88a32f73f5e..f97296864da8 100644
--- a/drivers/gpu/host1x/hw/channel_hw.c
+++ b/drivers/gpu/host1x/hw/channel_hw.c
@@ -129,6 +129,45 @@ static void host1x_channel_set_streamid(struct host1x_channel *channel)
 #endif
 }
 
+static void host1x_channel_program_engine_streamid(struct host1x_job *job)
+{
+#if HOST1X_HW >= 6
+	u32 fence;
+
+	if (!job->context)
+		return;
+
+	fence = host1x_syncpt_incr_max(job->syncpt, 1);
+
+	/* First, increment a syncpoint on OP_DONE condition.. */
+
+	host1x_cdma_push(&job->channel->cdma,
+		host1x_opcode_nonincr(HOST1X_UCLASS_INCR_SYNCPT, 1),
+		HOST1X_UCLASS_INCR_SYNCPT_INDX_F(job->syncpt->id) |
+			HOST1X_UCLASS_INCR_SYNCPT_COND_F(1));
+
+	/* Wait for syncpoint to increment */
+
+	host1x_cdma_push(&job->channel->cdma,
+		host1x_opcode_setclass(HOST1X_CLASS_HOST1X,
+			host1x_uclass_wait_syncpt_r(), 1),
+		host1x_class_host_wait_syncpt(job->syncpt->id, fence));
+
+	/*
+	 * Now that we know the engine is idle, return to class and
+	 * change stream ID.
+	 */
+
+	host1x_cdma_push(&job->channel->cdma,
+		host1x_opcode_setclass(job->class, 0, 0),
+		HOST1X_OPCODE_NOP);
+
+	host1x_cdma_push(&job->channel->cdma,
+		host1x_opcode_setpayload(job->context->stream_id),
+		host1x_opcode_setstreamid(job->engine_streamid_offset / 4));
+#endif
+}
+
 static int channel_submit(struct host1x_job *job)
 {
 	struct host1x_channel *ch = job->channel;
@@ -184,18 +223,23 @@ static int channel_submit(struct host1x_job *job)
 	if (sp->base)
 		synchronize_syncpt_base(job);
 
-	syncval = host1x_syncpt_incr_max(sp, user_syncpt_incrs);
-
 	host1x_hw_syncpt_assign_to_channel(host, sp, ch);
 
-	job->syncpt_end = syncval;
-
 	/* add a setclass for modules that require it */
 	if (job->class)
 		host1x_cdma_push(&ch->cdma,
 				 host1x_opcode_setclass(job->class, 0, 0),
 				 HOST1X_OPCODE_NOP);
 
+	/*
+	 * Ensure engine DMA is idle and set new stream ID. May increment
+	 * syncpt max.
+	 */
+	host1x_channel_program_engine_streamid(job);
+
+	syncval = host1x_syncpt_incr_max(sp, user_syncpt_incrs);
+	job->syncpt_end = syncval;
+
 	submit_gathers(job);
 
 	/* end CDMA submit & stash pinned hMems into sync queue */
diff --git a/drivers/gpu/host1x/hw/host1x06_hardware.h b/drivers/gpu/host1x/hw/host1x06_hardware.h
index 01a142a09800..5d515745eee7 100644
--- a/drivers/gpu/host1x/hw/host1x06_hardware.h
+++ b/drivers/gpu/host1x/hw/host1x06_hardware.h
@@ -127,6 +127,16 @@ static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count)
 	return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count;
 }
 
+static inline u32 host1x_opcode_setstreamid(unsigned streamid)
+{
+	return (7 << 28) | streamid;
+}
+
+static inline u32 host1x_opcode_setpayload(unsigned payload)
+{
+	return (9 << 28) | payload;
+}
+
 static inline u32 host1x_opcode_gather_wide(unsigned count)
 {
 	return (12 << 28) | count;
diff --git a/drivers/gpu/host1x/hw/host1x07_hardware.h b/drivers/gpu/host1x/hw/host1x07_hardware.h
index e6582172ebfd..82c0cc9bb0b5 100644
--- a/drivers/gpu/host1x/hw/host1x07_hardware.h
+++ b/drivers/gpu/host1x/hw/host1x07_hardware.h
@@ -127,6 +127,16 @@ static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count)
 	return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count;
 }
 
+static inline u32 host1x_opcode_setstreamid(unsigned streamid)
+{
+	return (7 << 28) | streamid;
+}
+
+static inline u32 host1x_opcode_setpayload(unsigned payload)
+{
+	return (9 << 28) | payload;
+}
+
 static inline u32 host1x_opcode_gather_wide(unsigned count)
 {
 	return (12 << 28) | count;
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index 3cf3c6a0b225..3bf19080f1c1 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -272,6 +272,10 @@ struct host1x_job {
 	/* Callback called when job is freed */
 	void (*release)(struct host1x_job *job);
 	void *user_data;
+
+	/* Options for configuring engine data stream ID */
+	struct host1x_context *context;
+	u32 engine_streamid_offset;
 };
 
 struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,
-- 
2.30.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 4/8] gpu: host1x: Program context stream ID on submission
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

Add code to do stream ID switching at the beginning of a job. The
stream ID is switched to the stream ID specified by the context
passed in the job structure.

Before switching the stream ID, an OP_DONE wait is done on the
channel's engine to ensure that there is no residual ongoing
work that might do DMA using the new stream ID.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/host1x/hw/channel_hw.c        | 52 +++++++++++++++++++++--
 drivers/gpu/host1x/hw/host1x06_hardware.h | 10 +++++
 drivers/gpu/host1x/hw/host1x07_hardware.h | 10 +++++
 include/linux/host1x.h                    |  4 ++
 4 files changed, 72 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/host1x/hw/channel_hw.c b/drivers/gpu/host1x/hw/channel_hw.c
index d88a32f73f5e..f97296864da8 100644
--- a/drivers/gpu/host1x/hw/channel_hw.c
+++ b/drivers/gpu/host1x/hw/channel_hw.c
@@ -129,6 +129,45 @@ static void host1x_channel_set_streamid(struct host1x_channel *channel)
 #endif
 }
 
+static void host1x_channel_program_engine_streamid(struct host1x_job *job)
+{
+#if HOST1X_HW >= 6
+	u32 fence;
+
+	if (!job->context)
+		return;
+
+	fence = host1x_syncpt_incr_max(job->syncpt, 1);
+
+	/* First, increment a syncpoint on OP_DONE condition.. */
+
+	host1x_cdma_push(&job->channel->cdma,
+		host1x_opcode_nonincr(HOST1X_UCLASS_INCR_SYNCPT, 1),
+		HOST1X_UCLASS_INCR_SYNCPT_INDX_F(job->syncpt->id) |
+			HOST1X_UCLASS_INCR_SYNCPT_COND_F(1));
+
+	/* Wait for syncpoint to increment */
+
+	host1x_cdma_push(&job->channel->cdma,
+		host1x_opcode_setclass(HOST1X_CLASS_HOST1X,
+			host1x_uclass_wait_syncpt_r(), 1),
+		host1x_class_host_wait_syncpt(job->syncpt->id, fence));
+
+	/*
+	 * Now that we know the engine is idle, return to class and
+	 * change stream ID.
+	 */
+
+	host1x_cdma_push(&job->channel->cdma,
+		host1x_opcode_setclass(job->class, 0, 0),
+		HOST1X_OPCODE_NOP);
+
+	host1x_cdma_push(&job->channel->cdma,
+		host1x_opcode_setpayload(job->context->stream_id),
+		host1x_opcode_setstreamid(job->engine_streamid_offset / 4));
+#endif
+}
+
 static int channel_submit(struct host1x_job *job)
 {
 	struct host1x_channel *ch = job->channel;
@@ -184,18 +223,23 @@ static int channel_submit(struct host1x_job *job)
 	if (sp->base)
 		synchronize_syncpt_base(job);
 
-	syncval = host1x_syncpt_incr_max(sp, user_syncpt_incrs);
-
 	host1x_hw_syncpt_assign_to_channel(host, sp, ch);
 
-	job->syncpt_end = syncval;
-
 	/* add a setclass for modules that require it */
 	if (job->class)
 		host1x_cdma_push(&ch->cdma,
 				 host1x_opcode_setclass(job->class, 0, 0),
 				 HOST1X_OPCODE_NOP);
 
+	/*
+	 * Ensure engine DMA is idle and set new stream ID. May increment
+	 * syncpt max.
+	 */
+	host1x_channel_program_engine_streamid(job);
+
+	syncval = host1x_syncpt_incr_max(sp, user_syncpt_incrs);
+	job->syncpt_end = syncval;
+
 	submit_gathers(job);
 
 	/* end CDMA submit & stash pinned hMems into sync queue */
diff --git a/drivers/gpu/host1x/hw/host1x06_hardware.h b/drivers/gpu/host1x/hw/host1x06_hardware.h
index 01a142a09800..5d515745eee7 100644
--- a/drivers/gpu/host1x/hw/host1x06_hardware.h
+++ b/drivers/gpu/host1x/hw/host1x06_hardware.h
@@ -127,6 +127,16 @@ static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count)
 	return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count;
 }
 
+static inline u32 host1x_opcode_setstreamid(unsigned streamid)
+{
+	return (7 << 28) | streamid;
+}
+
+static inline u32 host1x_opcode_setpayload(unsigned payload)
+{
+	return (9 << 28) | payload;
+}
+
 static inline u32 host1x_opcode_gather_wide(unsigned count)
 {
 	return (12 << 28) | count;
diff --git a/drivers/gpu/host1x/hw/host1x07_hardware.h b/drivers/gpu/host1x/hw/host1x07_hardware.h
index e6582172ebfd..82c0cc9bb0b5 100644
--- a/drivers/gpu/host1x/hw/host1x07_hardware.h
+++ b/drivers/gpu/host1x/hw/host1x07_hardware.h
@@ -127,6 +127,16 @@ static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count)
 	return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count;
 }
 
+static inline u32 host1x_opcode_setstreamid(unsigned streamid)
+{
+	return (7 << 28) | streamid;
+}
+
+static inline u32 host1x_opcode_setpayload(unsigned payload)
+{
+	return (9 << 28) | payload;
+}
+
 static inline u32 host1x_opcode_gather_wide(unsigned count)
 {
 	return (12 << 28) | count;
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index 3cf3c6a0b225..3bf19080f1c1 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -272,6 +272,10 @@ struct host1x_job {
 	/* Callback called when job is freed */
 	void (*release)(struct host1x_job *job);
 	void *user_data;
+
+	/* Options for configuring engine data stream ID */
+	struct host1x_context *context;
+	u32 engine_streamid_offset;
 };
 
 struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,
-- 
2.30.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 5/8] iommu/arm-smmu: Attach to host1x context device bus
  2021-02-08 16:38 ` Mikko Perttunen
  (?)
  (?)
@ 2021-02-08 16:38   ` Mikko Perttunen
  -1 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: linux-tegra, dri-devel, iommu, linux-kernel, devicetree,
	linux-arm-kernel, Mikko Perttunen

Set itself as the IOMMU for the host1x context device bus, containing
"dummy" devices used for Host1x context isolation.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index d8c6bfde6a61..ec746c2a08ae 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -40,6 +40,7 @@
 
 #include <linux/amba/bus.h>
 #include <linux/fsl/mc.h>
+#include <linux/host1x_context_bus.h>
 
 #include "arm-smmu.h"
 
@@ -2087,8 +2088,20 @@ static int arm_smmu_bus_init(struct iommu_ops *ops)
 			goto err_reset_pci_ops;
 	}
 #endif
+#ifdef CONFIG_TEGRA_HOST1X_CONTEXT_BUS
+	if (!iommu_present(&host1x_context_device_bus_type)) {
+		err = bus_set_iommu(&host1x_context_device_bus_type, ops);
+		if (err)
+			goto err_reset_fsl_mc_ops;
+	}
+#endif
+
 	return 0;
 
+err_reset_fsl_mc_ops: __maybe_unused;
+#ifdef CONFIG_FSL_MC_BUS
+	bus_set_iommu(&fsl_mc_bus_type, NULL);
+#endif
 err_reset_pci_ops: __maybe_unused;
 #ifdef CONFIG_PCI
 	bus_set_iommu(&pci_bus_type, NULL);
-- 
2.30.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 5/8] iommu/arm-smmu: Attach to host1x context device bus
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

Set itself as the IOMMU for the host1x context device bus, containing
"dummy" devices used for Host1x context isolation.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index d8c6bfde6a61..ec746c2a08ae 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -40,6 +40,7 @@
 
 #include <linux/amba/bus.h>
 #include <linux/fsl/mc.h>
+#include <linux/host1x_context_bus.h>
 
 #include "arm-smmu.h"
 
@@ -2087,8 +2088,20 @@ static int arm_smmu_bus_init(struct iommu_ops *ops)
 			goto err_reset_pci_ops;
 	}
 #endif
+#ifdef CONFIG_TEGRA_HOST1X_CONTEXT_BUS
+	if (!iommu_present(&host1x_context_device_bus_type)) {
+		err = bus_set_iommu(&host1x_context_device_bus_type, ops);
+		if (err)
+			goto err_reset_fsl_mc_ops;
+	}
+#endif
+
 	return 0;
 
+err_reset_fsl_mc_ops: __maybe_unused;
+#ifdef CONFIG_FSL_MC_BUS
+	bus_set_iommu(&fsl_mc_bus_type, NULL);
+#endif
 err_reset_pci_ops: __maybe_unused;
 #ifdef CONFIG_PCI
 	bus_set_iommu(&pci_bus_type, NULL);
-- 
2.30.0

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 5/8] iommu/arm-smmu: Attach to host1x context device bus
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

Set itself as the IOMMU for the host1x context device bus, containing
"dummy" devices used for Host1x context isolation.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index d8c6bfde6a61..ec746c2a08ae 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -40,6 +40,7 @@
 
 #include <linux/amba/bus.h>
 #include <linux/fsl/mc.h>
+#include <linux/host1x_context_bus.h>
 
 #include "arm-smmu.h"
 
@@ -2087,8 +2088,20 @@ static int arm_smmu_bus_init(struct iommu_ops *ops)
 			goto err_reset_pci_ops;
 	}
 #endif
+#ifdef CONFIG_TEGRA_HOST1X_CONTEXT_BUS
+	if (!iommu_present(&host1x_context_device_bus_type)) {
+		err = bus_set_iommu(&host1x_context_device_bus_type, ops);
+		if (err)
+			goto err_reset_fsl_mc_ops;
+	}
+#endif
+
 	return 0;
 
+err_reset_fsl_mc_ops: __maybe_unused;
+#ifdef CONFIG_FSL_MC_BUS
+	bus_set_iommu(&fsl_mc_bus_type, NULL);
+#endif
 err_reset_pci_ops: __maybe_unused;
 #ifdef CONFIG_PCI
 	bus_set_iommu(&pci_bus_type, NULL);
-- 
2.30.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 5/8] iommu/arm-smmu: Attach to host1x context device bus
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

Set itself as the IOMMU for the host1x context device bus, containing
"dummy" devices used for Host1x context isolation.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index d8c6bfde6a61..ec746c2a08ae 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -40,6 +40,7 @@
 
 #include <linux/amba/bus.h>
 #include <linux/fsl/mc.h>
+#include <linux/host1x_context_bus.h>
 
 #include "arm-smmu.h"
 
@@ -2087,8 +2088,20 @@ static int arm_smmu_bus_init(struct iommu_ops *ops)
 			goto err_reset_pci_ops;
 	}
 #endif
+#ifdef CONFIG_TEGRA_HOST1X_CONTEXT_BUS
+	if (!iommu_present(&host1x_context_device_bus_type)) {
+		err = bus_set_iommu(&host1x_context_device_bus_type, ops);
+		if (err)
+			goto err_reset_fsl_mc_ops;
+	}
+#endif
+
 	return 0;
 
+err_reset_fsl_mc_ops: __maybe_unused;
+#ifdef CONFIG_FSL_MC_BUS
+	bus_set_iommu(&fsl_mc_bus_type, NULL);
+#endif
 err_reset_pci_ops: __maybe_unused;
 #ifdef CONFIG_PCI
 	bus_set_iommu(&pci_bus_type, NULL);
-- 
2.30.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 6/8] arm64: tegra: Add Host1x context stream IDs on Tegra186+
  2021-02-08 16:38 ` Mikko Perttunen
  (?)
  (?)
@ 2021-02-08 16:38   ` Mikko Perttunen
  -1 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: linux-tegra, dri-devel, iommu, linux-kernel, devicetree,
	linux-arm-kernel, Mikko Perttunen

Add Host1x context stream IDs on systems that support Host1x context
isolation. Host1x and attached engines can use these stream IDs to
allow isolation between memory used by different processes.

The specified stream IDs must match those configured by the hypervisor,
if one is present.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index c567aa65418b..25a8cb1a97a6 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -1176,6 +1176,15 @@ host1x@13e00000 {
 		interconnect-names = "dma-mem";
 
 		iommus = <&smmu TEGRA186_SID_HOST1X>;
+		nvidia,context-iommus = <
+			&smmu TEGRA186_SID_HOST1X_CTX0
+			&smmu TEGRA186_SID_HOST1X_CTX1
+			&smmu TEGRA186_SID_HOST1X_CTX2
+			&smmu TEGRA186_SID_HOST1X_CTX3
+			&smmu TEGRA186_SID_HOST1X_CTX4
+			&smmu TEGRA186_SID_HOST1X_CTX5
+			&smmu TEGRA186_SID_HOST1X_CTX6
+			&smmu TEGRA186_SID_HOST1X_CTX7>;
 
 		dpaux1: dpaux@15040000 {
 			compatible = "nvidia,tegra186-dpaux";
-- 
2.30.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 6/8] arm64: tegra: Add Host1x context stream IDs on Tegra186+
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

Add Host1x context stream IDs on systems that support Host1x context
isolation. Host1x and attached engines can use these stream IDs to
allow isolation between memory used by different processes.

The specified stream IDs must match those configured by the hypervisor,
if one is present.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index c567aa65418b..25a8cb1a97a6 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -1176,6 +1176,15 @@ host1x@13e00000 {
 		interconnect-names = "dma-mem";
 
 		iommus = <&smmu TEGRA186_SID_HOST1X>;
+		nvidia,context-iommus = <
+			&smmu TEGRA186_SID_HOST1X_CTX0
+			&smmu TEGRA186_SID_HOST1X_CTX1
+			&smmu TEGRA186_SID_HOST1X_CTX2
+			&smmu TEGRA186_SID_HOST1X_CTX3
+			&smmu TEGRA186_SID_HOST1X_CTX4
+			&smmu TEGRA186_SID_HOST1X_CTX5
+			&smmu TEGRA186_SID_HOST1X_CTX6
+			&smmu TEGRA186_SID_HOST1X_CTX7>;
 
 		dpaux1: dpaux@15040000 {
 			compatible = "nvidia,tegra186-dpaux";
-- 
2.30.0

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 6/8] arm64: tegra: Add Host1x context stream IDs on Tegra186+
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

Add Host1x context stream IDs on systems that support Host1x context
isolation. Host1x and attached engines can use these stream IDs to
allow isolation between memory used by different processes.

The specified stream IDs must match those configured by the hypervisor,
if one is present.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index c567aa65418b..25a8cb1a97a6 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -1176,6 +1176,15 @@ host1x@13e00000 {
 		interconnect-names = "dma-mem";
 
 		iommus = <&smmu TEGRA186_SID_HOST1X>;
+		nvidia,context-iommus = <
+			&smmu TEGRA186_SID_HOST1X_CTX0
+			&smmu TEGRA186_SID_HOST1X_CTX1
+			&smmu TEGRA186_SID_HOST1X_CTX2
+			&smmu TEGRA186_SID_HOST1X_CTX3
+			&smmu TEGRA186_SID_HOST1X_CTX4
+			&smmu TEGRA186_SID_HOST1X_CTX5
+			&smmu TEGRA186_SID_HOST1X_CTX6
+			&smmu TEGRA186_SID_HOST1X_CTX7>;
 
 		dpaux1: dpaux@15040000 {
 			compatible = "nvidia,tegra186-dpaux";
-- 
2.30.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 6/8] arm64: tegra: Add Host1x context stream IDs on Tegra186+
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

Add Host1x context stream IDs on systems that support Host1x context
isolation. Host1x and attached engines can use these stream IDs to
allow isolation between memory used by different processes.

The specified stream IDs must match those configured by the hypervisor,
if one is present.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index c567aa65418b..25a8cb1a97a6 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -1176,6 +1176,15 @@ host1x@13e00000 {
 		interconnect-names = "dma-mem";
 
 		iommus = <&smmu TEGRA186_SID_HOST1X>;
+		nvidia,context-iommus = <
+			&smmu TEGRA186_SID_HOST1X_CTX0
+			&smmu TEGRA186_SID_HOST1X_CTX1
+			&smmu TEGRA186_SID_HOST1X_CTX2
+			&smmu TEGRA186_SID_HOST1X_CTX3
+			&smmu TEGRA186_SID_HOST1X_CTX4
+			&smmu TEGRA186_SID_HOST1X_CTX5
+			&smmu TEGRA186_SID_HOST1X_CTX6
+			&smmu TEGRA186_SID_HOST1X_CTX7>;
 
 		dpaux1: dpaux@15040000 {
 			compatible = "nvidia,tegra186-dpaux";
-- 
2.30.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 7/8] drm/tegra: Support context isolation
  2021-02-08 16:38 ` Mikko Perttunen
  (?)
  (?)
@ 2021-02-08 16:38   ` Mikko Perttunen
  -1 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: linux-tegra, dri-devel, iommu, linux-kernel, devicetree,
	linux-arm-kernel, Mikko Perttunen

For engines that support context isolation, allocate a context when
opening a channel, and set up stream ID offset and context fields
when submitting a job.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/drm/tegra/drm.h         |  1 +
 drivers/gpu/drm/tegra/uapi.h        |  1 +
 drivers/gpu/drm/tegra/uapi/submit.c | 13 +++++++++++
 drivers/gpu/drm/tegra/uapi/uapi.c   | 34 +++++++++++++++++++++++++++--
 4 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 1af57c2016eb..5d3903372041 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -81,6 +81,7 @@ struct tegra_drm_client_ops {
 	int (*submit)(struct tegra_drm_context *context,
 		      struct drm_tegra_submit *args, struct drm_device *drm,
 		      struct drm_file *file);
+	int (*get_streamid_offset)(struct tegra_drm_client *client);
 };
 
 int tegra_drm_submit(struct tegra_drm_context *context,
diff --git a/drivers/gpu/drm/tegra/uapi.h b/drivers/gpu/drm/tegra/uapi.h
index 5c422607e8fa..8efb30bbdb4b 100644
--- a/drivers/gpu/drm/tegra/uapi.h
+++ b/drivers/gpu/drm/tegra/uapi.h
@@ -26,6 +26,7 @@ struct tegra_drm_file {
 struct tegra_drm_channel_ctx {
 	struct tegra_drm_client *client;
 	struct host1x_channel *channel;
+	struct host1x_context *context;
 	struct xarray mappings;
 };
 
diff --git a/drivers/gpu/drm/tegra/uapi/submit.c b/drivers/gpu/drm/tegra/uapi/submit.c
index 8633844ae3d7..1d0dd28af99f 100644
--- a/drivers/gpu/drm/tegra/uapi/submit.c
+++ b/drivers/gpu/drm/tegra/uapi/submit.c
@@ -337,6 +337,9 @@ static void release_job(struct host1x_job *job)
 	struct tegra_drm_submit_data *job_data = job->user_data;
 	u32 i;
 
+	if (job->context)
+		host1x_context_put(job->context);
+
 	for (i = 0; i < job_data->num_used_mappings; i++)
 		tegra_drm_mapping_put(job_data->used_mappings[i].mapping);
 
@@ -398,6 +401,16 @@ int tegra_drm_ioctl_channel_submit(struct drm_device *drm, void *data,
 	job->release = release_job;
 	job->timeout = 10000;
 
+	if (ctx->context && ctx->client->ops->get_streamid_offset) {
+		int offset = ctx->client->ops->get_streamid_offset(ctx->client);
+
+		if (offset >= 0) {
+			job->context = ctx->context;
+			job->engine_streamid_offset = offset;
+			host1x_context_get(job->context);
+		}
+	}
+
 	/*
 	 * job_data is now part of job reference counting, so don't release
 	 * it from here.
diff --git a/drivers/gpu/drm/tegra/uapi/uapi.c b/drivers/gpu/drm/tegra/uapi/uapi.c
index d503b5e817c4..e2e0c88b858d 100644
--- a/drivers/gpu/drm/tegra/uapi/uapi.c
+++ b/drivers/gpu/drm/tegra/uapi/uapi.c
@@ -49,6 +49,9 @@ static void tegra_drm_channel_ctx_close(struct tegra_drm_channel_ctx *ctx)
 	unsigned long mapping_id;
 	struct tegra_drm_mapping *mapping;
 
+	if (ctx->context)
+		host1x_context_put(ctx->context);
+
 	xa_for_each(&ctx->mappings, mapping_id, mapping)
 		tegra_drm_mapping_put(mapping);
 
@@ -82,6 +85,7 @@ void tegra_drm_uapi_close_file(struct tegra_drm_file *file)
 int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data,
 				 struct drm_file *file)
 {
+	struct host1x *host = tegra_drm_to_host1x(drm->dev_private);
 	struct tegra_drm_file *fpriv = file->driver_priv;
 	struct tegra_drm *tegra = drm->dev_private;
 	struct drm_tegra_channel_open *args = data;
@@ -116,10 +120,29 @@ int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data,
 		}
 	}
 
+	/* Only allocate context if the engine supports context isolation. */
+	if (client->ops->get_streamid_offset &&
+	    client->ops->get_streamid_offset(client) >= 0) {
+		ctx->context =
+			host1x_context_alloc(host, get_task_pid(current, PIDTYPE_TGID));
+		if (IS_ERR(ctx->context)) {
+			if (PTR_ERR(ctx->context) != -EOPNOTSUPP) {
+				err = PTR_ERR(ctx->context);
+				goto put_channel;
+			} else {
+				/*
+				 * OK, HW does not support contexts or contexts
+				 * are disabled.
+				 */
+				ctx->context = NULL;
+			}
+		}
+	}
+
 	err = xa_alloc(&fpriv->contexts, &args->channel_ctx, ctx,
 		       XA_LIMIT(1, U32_MAX), GFP_KERNEL);
 	if (err < 0)
-		goto put_channel;
+		goto put_context;
 
 	ctx->client = client;
 	xa_init_flags(&ctx->mappings, XA_FLAGS_ALLOC1);
@@ -128,6 +151,9 @@ int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data,
 
 	return 0;
 
+put_context:
+	if (ctx->context)
+		host1x_context_put(ctx->context);
 put_channel:
 	host1x_channel_put(ctx->channel);
 free_ctx:
@@ -188,7 +214,11 @@ int tegra_drm_ioctl_channel_map(struct drm_device *drm, void *data,
 		goto unlock;
 	}
 
-	mapping->dev = ctx->client->base.dev;
+	if (ctx->context)
+		mapping->dev = &ctx->context->dev;
+	else
+		mapping->dev = ctx->client->base.dev;
+
 	mapping->bo = &container_of(gem, struct tegra_bo, gem)->base;
 
 	if (!iommu_get_domain_for_dev(mapping->dev) ||
-- 
2.30.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 7/8] drm/tegra: Support context isolation
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

For engines that support context isolation, allocate a context when
opening a channel, and set up stream ID offset and context fields
when submitting a job.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/drm/tegra/drm.h         |  1 +
 drivers/gpu/drm/tegra/uapi.h        |  1 +
 drivers/gpu/drm/tegra/uapi/submit.c | 13 +++++++++++
 drivers/gpu/drm/tegra/uapi/uapi.c   | 34 +++++++++++++++++++++++++++--
 4 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 1af57c2016eb..5d3903372041 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -81,6 +81,7 @@ struct tegra_drm_client_ops {
 	int (*submit)(struct tegra_drm_context *context,
 		      struct drm_tegra_submit *args, struct drm_device *drm,
 		      struct drm_file *file);
+	int (*get_streamid_offset)(struct tegra_drm_client *client);
 };
 
 int tegra_drm_submit(struct tegra_drm_context *context,
diff --git a/drivers/gpu/drm/tegra/uapi.h b/drivers/gpu/drm/tegra/uapi.h
index 5c422607e8fa..8efb30bbdb4b 100644
--- a/drivers/gpu/drm/tegra/uapi.h
+++ b/drivers/gpu/drm/tegra/uapi.h
@@ -26,6 +26,7 @@ struct tegra_drm_file {
 struct tegra_drm_channel_ctx {
 	struct tegra_drm_client *client;
 	struct host1x_channel *channel;
+	struct host1x_context *context;
 	struct xarray mappings;
 };
 
diff --git a/drivers/gpu/drm/tegra/uapi/submit.c b/drivers/gpu/drm/tegra/uapi/submit.c
index 8633844ae3d7..1d0dd28af99f 100644
--- a/drivers/gpu/drm/tegra/uapi/submit.c
+++ b/drivers/gpu/drm/tegra/uapi/submit.c
@@ -337,6 +337,9 @@ static void release_job(struct host1x_job *job)
 	struct tegra_drm_submit_data *job_data = job->user_data;
 	u32 i;
 
+	if (job->context)
+		host1x_context_put(job->context);
+
 	for (i = 0; i < job_data->num_used_mappings; i++)
 		tegra_drm_mapping_put(job_data->used_mappings[i].mapping);
 
@@ -398,6 +401,16 @@ int tegra_drm_ioctl_channel_submit(struct drm_device *drm, void *data,
 	job->release = release_job;
 	job->timeout = 10000;
 
+	if (ctx->context && ctx->client->ops->get_streamid_offset) {
+		int offset = ctx->client->ops->get_streamid_offset(ctx->client);
+
+		if (offset >= 0) {
+			job->context = ctx->context;
+			job->engine_streamid_offset = offset;
+			host1x_context_get(job->context);
+		}
+	}
+
 	/*
 	 * job_data is now part of job reference counting, so don't release
 	 * it from here.
diff --git a/drivers/gpu/drm/tegra/uapi/uapi.c b/drivers/gpu/drm/tegra/uapi/uapi.c
index d503b5e817c4..e2e0c88b858d 100644
--- a/drivers/gpu/drm/tegra/uapi/uapi.c
+++ b/drivers/gpu/drm/tegra/uapi/uapi.c
@@ -49,6 +49,9 @@ static void tegra_drm_channel_ctx_close(struct tegra_drm_channel_ctx *ctx)
 	unsigned long mapping_id;
 	struct tegra_drm_mapping *mapping;
 
+	if (ctx->context)
+		host1x_context_put(ctx->context);
+
 	xa_for_each(&ctx->mappings, mapping_id, mapping)
 		tegra_drm_mapping_put(mapping);
 
@@ -82,6 +85,7 @@ void tegra_drm_uapi_close_file(struct tegra_drm_file *file)
 int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data,
 				 struct drm_file *file)
 {
+	struct host1x *host = tegra_drm_to_host1x(drm->dev_private);
 	struct tegra_drm_file *fpriv = file->driver_priv;
 	struct tegra_drm *tegra = drm->dev_private;
 	struct drm_tegra_channel_open *args = data;
@@ -116,10 +120,29 @@ int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data,
 		}
 	}
 
+	/* Only allocate context if the engine supports context isolation. */
+	if (client->ops->get_streamid_offset &&
+	    client->ops->get_streamid_offset(client) >= 0) {
+		ctx->context =
+			host1x_context_alloc(host, get_task_pid(current, PIDTYPE_TGID));
+		if (IS_ERR(ctx->context)) {
+			if (PTR_ERR(ctx->context) != -EOPNOTSUPP) {
+				err = PTR_ERR(ctx->context);
+				goto put_channel;
+			} else {
+				/*
+				 * OK, HW does not support contexts or contexts
+				 * are disabled.
+				 */
+				ctx->context = NULL;
+			}
+		}
+	}
+
 	err = xa_alloc(&fpriv->contexts, &args->channel_ctx, ctx,
 		       XA_LIMIT(1, U32_MAX), GFP_KERNEL);
 	if (err < 0)
-		goto put_channel;
+		goto put_context;
 
 	ctx->client = client;
 	xa_init_flags(&ctx->mappings, XA_FLAGS_ALLOC1);
@@ -128,6 +151,9 @@ int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data,
 
 	return 0;
 
+put_context:
+	if (ctx->context)
+		host1x_context_put(ctx->context);
 put_channel:
 	host1x_channel_put(ctx->channel);
 free_ctx:
@@ -188,7 +214,11 @@ int tegra_drm_ioctl_channel_map(struct drm_device *drm, void *data,
 		goto unlock;
 	}
 
-	mapping->dev = ctx->client->base.dev;
+	if (ctx->context)
+		mapping->dev = &ctx->context->dev;
+	else
+		mapping->dev = ctx->client->base.dev;
+
 	mapping->bo = &container_of(gem, struct tegra_bo, gem)->base;
 
 	if (!iommu_get_domain_for_dev(mapping->dev) ||
-- 
2.30.0

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 7/8] drm/tegra: Support context isolation
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

For engines that support context isolation, allocate a context when
opening a channel, and set up stream ID offset and context fields
when submitting a job.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/drm/tegra/drm.h         |  1 +
 drivers/gpu/drm/tegra/uapi.h        |  1 +
 drivers/gpu/drm/tegra/uapi/submit.c | 13 +++++++++++
 drivers/gpu/drm/tegra/uapi/uapi.c   | 34 +++++++++++++++++++++++++++--
 4 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 1af57c2016eb..5d3903372041 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -81,6 +81,7 @@ struct tegra_drm_client_ops {
 	int (*submit)(struct tegra_drm_context *context,
 		      struct drm_tegra_submit *args, struct drm_device *drm,
 		      struct drm_file *file);
+	int (*get_streamid_offset)(struct tegra_drm_client *client);
 };
 
 int tegra_drm_submit(struct tegra_drm_context *context,
diff --git a/drivers/gpu/drm/tegra/uapi.h b/drivers/gpu/drm/tegra/uapi.h
index 5c422607e8fa..8efb30bbdb4b 100644
--- a/drivers/gpu/drm/tegra/uapi.h
+++ b/drivers/gpu/drm/tegra/uapi.h
@@ -26,6 +26,7 @@ struct tegra_drm_file {
 struct tegra_drm_channel_ctx {
 	struct tegra_drm_client *client;
 	struct host1x_channel *channel;
+	struct host1x_context *context;
 	struct xarray mappings;
 };
 
diff --git a/drivers/gpu/drm/tegra/uapi/submit.c b/drivers/gpu/drm/tegra/uapi/submit.c
index 8633844ae3d7..1d0dd28af99f 100644
--- a/drivers/gpu/drm/tegra/uapi/submit.c
+++ b/drivers/gpu/drm/tegra/uapi/submit.c
@@ -337,6 +337,9 @@ static void release_job(struct host1x_job *job)
 	struct tegra_drm_submit_data *job_data = job->user_data;
 	u32 i;
 
+	if (job->context)
+		host1x_context_put(job->context);
+
 	for (i = 0; i < job_data->num_used_mappings; i++)
 		tegra_drm_mapping_put(job_data->used_mappings[i].mapping);
 
@@ -398,6 +401,16 @@ int tegra_drm_ioctl_channel_submit(struct drm_device *drm, void *data,
 	job->release = release_job;
 	job->timeout = 10000;
 
+	if (ctx->context && ctx->client->ops->get_streamid_offset) {
+		int offset = ctx->client->ops->get_streamid_offset(ctx->client);
+
+		if (offset >= 0) {
+			job->context = ctx->context;
+			job->engine_streamid_offset = offset;
+			host1x_context_get(job->context);
+		}
+	}
+
 	/*
 	 * job_data is now part of job reference counting, so don't release
 	 * it from here.
diff --git a/drivers/gpu/drm/tegra/uapi/uapi.c b/drivers/gpu/drm/tegra/uapi/uapi.c
index d503b5e817c4..e2e0c88b858d 100644
--- a/drivers/gpu/drm/tegra/uapi/uapi.c
+++ b/drivers/gpu/drm/tegra/uapi/uapi.c
@@ -49,6 +49,9 @@ static void tegra_drm_channel_ctx_close(struct tegra_drm_channel_ctx *ctx)
 	unsigned long mapping_id;
 	struct tegra_drm_mapping *mapping;
 
+	if (ctx->context)
+		host1x_context_put(ctx->context);
+
 	xa_for_each(&ctx->mappings, mapping_id, mapping)
 		tegra_drm_mapping_put(mapping);
 
@@ -82,6 +85,7 @@ void tegra_drm_uapi_close_file(struct tegra_drm_file *file)
 int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data,
 				 struct drm_file *file)
 {
+	struct host1x *host = tegra_drm_to_host1x(drm->dev_private);
 	struct tegra_drm_file *fpriv = file->driver_priv;
 	struct tegra_drm *tegra = drm->dev_private;
 	struct drm_tegra_channel_open *args = data;
@@ -116,10 +120,29 @@ int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data,
 		}
 	}
 
+	/* Only allocate context if the engine supports context isolation. */
+	if (client->ops->get_streamid_offset &&
+	    client->ops->get_streamid_offset(client) >= 0) {
+		ctx->context =
+			host1x_context_alloc(host, get_task_pid(current, PIDTYPE_TGID));
+		if (IS_ERR(ctx->context)) {
+			if (PTR_ERR(ctx->context) != -EOPNOTSUPP) {
+				err = PTR_ERR(ctx->context);
+				goto put_channel;
+			} else {
+				/*
+				 * OK, HW does not support contexts or contexts
+				 * are disabled.
+				 */
+				ctx->context = NULL;
+			}
+		}
+	}
+
 	err = xa_alloc(&fpriv->contexts, &args->channel_ctx, ctx,
 		       XA_LIMIT(1, U32_MAX), GFP_KERNEL);
 	if (err < 0)
-		goto put_channel;
+		goto put_context;
 
 	ctx->client = client;
 	xa_init_flags(&ctx->mappings, XA_FLAGS_ALLOC1);
@@ -128,6 +151,9 @@ int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data,
 
 	return 0;
 
+put_context:
+	if (ctx->context)
+		host1x_context_put(ctx->context);
 put_channel:
 	host1x_channel_put(ctx->channel);
 free_ctx:
@@ -188,7 +214,11 @@ int tegra_drm_ioctl_channel_map(struct drm_device *drm, void *data,
 		goto unlock;
 	}
 
-	mapping->dev = ctx->client->base.dev;
+	if (ctx->context)
+		mapping->dev = &ctx->context->dev;
+	else
+		mapping->dev = ctx->client->base.dev;
+
 	mapping->bo = &container_of(gem, struct tegra_bo, gem)->base;
 
 	if (!iommu_get_domain_for_dev(mapping->dev) ||
-- 
2.30.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 7/8] drm/tegra: Support context isolation
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

For engines that support context isolation, allocate a context when
opening a channel, and set up stream ID offset and context fields
when submitting a job.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/drm/tegra/drm.h         |  1 +
 drivers/gpu/drm/tegra/uapi.h        |  1 +
 drivers/gpu/drm/tegra/uapi/submit.c | 13 +++++++++++
 drivers/gpu/drm/tegra/uapi/uapi.c   | 34 +++++++++++++++++++++++++++--
 4 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 1af57c2016eb..5d3903372041 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -81,6 +81,7 @@ struct tegra_drm_client_ops {
 	int (*submit)(struct tegra_drm_context *context,
 		      struct drm_tegra_submit *args, struct drm_device *drm,
 		      struct drm_file *file);
+	int (*get_streamid_offset)(struct tegra_drm_client *client);
 };
 
 int tegra_drm_submit(struct tegra_drm_context *context,
diff --git a/drivers/gpu/drm/tegra/uapi.h b/drivers/gpu/drm/tegra/uapi.h
index 5c422607e8fa..8efb30bbdb4b 100644
--- a/drivers/gpu/drm/tegra/uapi.h
+++ b/drivers/gpu/drm/tegra/uapi.h
@@ -26,6 +26,7 @@ struct tegra_drm_file {
 struct tegra_drm_channel_ctx {
 	struct tegra_drm_client *client;
 	struct host1x_channel *channel;
+	struct host1x_context *context;
 	struct xarray mappings;
 };
 
diff --git a/drivers/gpu/drm/tegra/uapi/submit.c b/drivers/gpu/drm/tegra/uapi/submit.c
index 8633844ae3d7..1d0dd28af99f 100644
--- a/drivers/gpu/drm/tegra/uapi/submit.c
+++ b/drivers/gpu/drm/tegra/uapi/submit.c
@@ -337,6 +337,9 @@ static void release_job(struct host1x_job *job)
 	struct tegra_drm_submit_data *job_data = job->user_data;
 	u32 i;
 
+	if (job->context)
+		host1x_context_put(job->context);
+
 	for (i = 0; i < job_data->num_used_mappings; i++)
 		tegra_drm_mapping_put(job_data->used_mappings[i].mapping);
 
@@ -398,6 +401,16 @@ int tegra_drm_ioctl_channel_submit(struct drm_device *drm, void *data,
 	job->release = release_job;
 	job->timeout = 10000;
 
+	if (ctx->context && ctx->client->ops->get_streamid_offset) {
+		int offset = ctx->client->ops->get_streamid_offset(ctx->client);
+
+		if (offset >= 0) {
+			job->context = ctx->context;
+			job->engine_streamid_offset = offset;
+			host1x_context_get(job->context);
+		}
+	}
+
 	/*
 	 * job_data is now part of job reference counting, so don't release
 	 * it from here.
diff --git a/drivers/gpu/drm/tegra/uapi/uapi.c b/drivers/gpu/drm/tegra/uapi/uapi.c
index d503b5e817c4..e2e0c88b858d 100644
--- a/drivers/gpu/drm/tegra/uapi/uapi.c
+++ b/drivers/gpu/drm/tegra/uapi/uapi.c
@@ -49,6 +49,9 @@ static void tegra_drm_channel_ctx_close(struct tegra_drm_channel_ctx *ctx)
 	unsigned long mapping_id;
 	struct tegra_drm_mapping *mapping;
 
+	if (ctx->context)
+		host1x_context_put(ctx->context);
+
 	xa_for_each(&ctx->mappings, mapping_id, mapping)
 		tegra_drm_mapping_put(mapping);
 
@@ -82,6 +85,7 @@ void tegra_drm_uapi_close_file(struct tegra_drm_file *file)
 int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data,
 				 struct drm_file *file)
 {
+	struct host1x *host = tegra_drm_to_host1x(drm->dev_private);
 	struct tegra_drm_file *fpriv = file->driver_priv;
 	struct tegra_drm *tegra = drm->dev_private;
 	struct drm_tegra_channel_open *args = data;
@@ -116,10 +120,29 @@ int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data,
 		}
 	}
 
+	/* Only allocate context if the engine supports context isolation. */
+	if (client->ops->get_streamid_offset &&
+	    client->ops->get_streamid_offset(client) >= 0) {
+		ctx->context =
+			host1x_context_alloc(host, get_task_pid(current, PIDTYPE_TGID));
+		if (IS_ERR(ctx->context)) {
+			if (PTR_ERR(ctx->context) != -EOPNOTSUPP) {
+				err = PTR_ERR(ctx->context);
+				goto put_channel;
+			} else {
+				/*
+				 * OK, HW does not support contexts or contexts
+				 * are disabled.
+				 */
+				ctx->context = NULL;
+			}
+		}
+	}
+
 	err = xa_alloc(&fpriv->contexts, &args->channel_ctx, ctx,
 		       XA_LIMIT(1, U32_MAX), GFP_KERNEL);
 	if (err < 0)
-		goto put_channel;
+		goto put_context;
 
 	ctx->client = client;
 	xa_init_flags(&ctx->mappings, XA_FLAGS_ALLOC1);
@@ -128,6 +151,9 @@ int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data,
 
 	return 0;
 
+put_context:
+	if (ctx->context)
+		host1x_context_put(ctx->context);
 put_channel:
 	host1x_channel_put(ctx->channel);
 free_ctx:
@@ -188,7 +214,11 @@ int tegra_drm_ioctl_channel_map(struct drm_device *drm, void *data,
 		goto unlock;
 	}
 
-	mapping->dev = ctx->client->base.dev;
+	if (ctx->context)
+		mapping->dev = &ctx->context->dev;
+	else
+		mapping->dev = ctx->client->base.dev;
+
 	mapping->bo = &container_of(gem, struct tegra_bo, gem)->base;
 
 	if (!iommu_get_domain_for_dev(mapping->dev) ||
-- 
2.30.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 8/8] drm/tegra: vic: Implement get_streamid_offset
  2021-02-08 16:38 ` Mikko Perttunen
  (?)
  (?)
@ 2021-02-08 16:38   ` Mikko Perttunen
  -1 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: linux-tegra, dri-devel, iommu, linux-kernel, devicetree,
	linux-arm-kernel, Mikko Perttunen

Implement the get_streamid_offset required for supporting context
isolation. Since old firmware cannot support context isolation
without hacks that we don't want to implement, check the firmware
binary to see if context isolation should be enabled.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/drm/tegra/vic.c | 38 +++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
index 6c2f03faec24..f8d5f381904d 100644
--- a/drivers/gpu/drm/tegra/vic.c
+++ b/drivers/gpu/drm/tegra/vic.c
@@ -37,6 +37,8 @@ struct vic {
 	struct clk *clk;
 	struct reset_control *rst;
 
+	bool can_use_context;
+
 	/* Platform configuration */
 	const struct vic_config *config;
 };
@@ -218,6 +220,7 @@ static int vic_load_firmware(struct vic *vic)
 {
 	struct host1x_client *client = &vic->client.base;
 	struct tegra_drm *tegra = vic->client.drm;
+	u32 fce_bin_data_offset;
 	dma_addr_t iova;
 	size_t size;
 	void *virt;
@@ -266,6 +269,25 @@ static int vic_load_firmware(struct vic *vic)
 		vic->falcon.firmware.phys = phys;
 	}
 
+	/*
+	 * Check if firmware is new enough to not require mapping firmware
+	 * to data buffer domains.
+	 */
+	fce_bin_data_offset = *(u32 *)(virt + VIC_UCODE_FCE_DATA_OFFSET);
+
+	if (!vic->config->supports_sid) {
+		vic->can_use_context = false;
+	} else if (fce_bin_data_offset != 0x0 && fce_bin_data_offset != 0xa5a5a5a5) {
+		/*
+		 * Firmware will access FCE through STREAMID0, so context
+		 * isolation cannot be used.
+		 */
+		vic->can_use_context = false;
+		dev_warn_once(vic->dev, "context isolation disabled due to old firmware\n");
+	} else {
+		vic->can_use_context = true;
+	}
+
 	return 0;
 
 cleanup:
@@ -357,10 +379,26 @@ static void vic_close_channel(struct tegra_drm_context *context)
 	pm_runtime_put(vic->dev);
 }
 
+static int vic_get_streamid_offset(struct tegra_drm_client *client)
+{
+	struct vic *vic = to_vic(client);
+	int err;
+
+	err = vic_load_firmware(vic);
+	if (err < 0)
+		return err;
+
+	if (vic->can_use_context)
+		return 0x30;
+	else
+		return -ENOTSUPP;
+}
+
 static const struct tegra_drm_client_ops vic_ops = {
 	.open_channel = vic_open_channel,
 	.close_channel = vic_close_channel,
 	.submit = tegra_drm_submit,
+	.get_streamid_offset = vic_get_streamid_offset,
 };
 
 #define NVIDIA_TEGRA_124_VIC_FIRMWARE "nvidia/tegra124/vic03_ucode.bin"
-- 
2.30.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 8/8] drm/tegra: vic: Implement get_streamid_offset
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

Implement the get_streamid_offset required for supporting context
isolation. Since old firmware cannot support context isolation
without hacks that we don't want to implement, check the firmware
binary to see if context isolation should be enabled.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/drm/tegra/vic.c | 38 +++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
index 6c2f03faec24..f8d5f381904d 100644
--- a/drivers/gpu/drm/tegra/vic.c
+++ b/drivers/gpu/drm/tegra/vic.c
@@ -37,6 +37,8 @@ struct vic {
 	struct clk *clk;
 	struct reset_control *rst;
 
+	bool can_use_context;
+
 	/* Platform configuration */
 	const struct vic_config *config;
 };
@@ -218,6 +220,7 @@ static int vic_load_firmware(struct vic *vic)
 {
 	struct host1x_client *client = &vic->client.base;
 	struct tegra_drm *tegra = vic->client.drm;
+	u32 fce_bin_data_offset;
 	dma_addr_t iova;
 	size_t size;
 	void *virt;
@@ -266,6 +269,25 @@ static int vic_load_firmware(struct vic *vic)
 		vic->falcon.firmware.phys = phys;
 	}
 
+	/*
+	 * Check if firmware is new enough to not require mapping firmware
+	 * to data buffer domains.
+	 */
+	fce_bin_data_offset = *(u32 *)(virt + VIC_UCODE_FCE_DATA_OFFSET);
+
+	if (!vic->config->supports_sid) {
+		vic->can_use_context = false;
+	} else if (fce_bin_data_offset != 0x0 && fce_bin_data_offset != 0xa5a5a5a5) {
+		/*
+		 * Firmware will access FCE through STREAMID0, so context
+		 * isolation cannot be used.
+		 */
+		vic->can_use_context = false;
+		dev_warn_once(vic->dev, "context isolation disabled due to old firmware\n");
+	} else {
+		vic->can_use_context = true;
+	}
+
 	return 0;
 
 cleanup:
@@ -357,10 +379,26 @@ static void vic_close_channel(struct tegra_drm_context *context)
 	pm_runtime_put(vic->dev);
 }
 
+static int vic_get_streamid_offset(struct tegra_drm_client *client)
+{
+	struct vic *vic = to_vic(client);
+	int err;
+
+	err = vic_load_firmware(vic);
+	if (err < 0)
+		return err;
+
+	if (vic->can_use_context)
+		return 0x30;
+	else
+		return -ENOTSUPP;
+}
+
 static const struct tegra_drm_client_ops vic_ops = {
 	.open_channel = vic_open_channel,
 	.close_channel = vic_close_channel,
 	.submit = tegra_drm_submit,
+	.get_streamid_offset = vic_get_streamid_offset,
 };
 
 #define NVIDIA_TEGRA_124_VIC_FIRMWARE "nvidia/tegra124/vic03_ucode.bin"
-- 
2.30.0

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 8/8] drm/tegra: vic: Implement get_streamid_offset
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

Implement the get_streamid_offset required for supporting context
isolation. Since old firmware cannot support context isolation
without hacks that we don't want to implement, check the firmware
binary to see if context isolation should be enabled.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/drm/tegra/vic.c | 38 +++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
index 6c2f03faec24..f8d5f381904d 100644
--- a/drivers/gpu/drm/tegra/vic.c
+++ b/drivers/gpu/drm/tegra/vic.c
@@ -37,6 +37,8 @@ struct vic {
 	struct clk *clk;
 	struct reset_control *rst;
 
+	bool can_use_context;
+
 	/* Platform configuration */
 	const struct vic_config *config;
 };
@@ -218,6 +220,7 @@ static int vic_load_firmware(struct vic *vic)
 {
 	struct host1x_client *client = &vic->client.base;
 	struct tegra_drm *tegra = vic->client.drm;
+	u32 fce_bin_data_offset;
 	dma_addr_t iova;
 	size_t size;
 	void *virt;
@@ -266,6 +269,25 @@ static int vic_load_firmware(struct vic *vic)
 		vic->falcon.firmware.phys = phys;
 	}
 
+	/*
+	 * Check if firmware is new enough to not require mapping firmware
+	 * to data buffer domains.
+	 */
+	fce_bin_data_offset = *(u32 *)(virt + VIC_UCODE_FCE_DATA_OFFSET);
+
+	if (!vic->config->supports_sid) {
+		vic->can_use_context = false;
+	} else if (fce_bin_data_offset != 0x0 && fce_bin_data_offset != 0xa5a5a5a5) {
+		/*
+		 * Firmware will access FCE through STREAMID0, so context
+		 * isolation cannot be used.
+		 */
+		vic->can_use_context = false;
+		dev_warn_once(vic->dev, "context isolation disabled due to old firmware\n");
+	} else {
+		vic->can_use_context = true;
+	}
+
 	return 0;
 
 cleanup:
@@ -357,10 +379,26 @@ static void vic_close_channel(struct tegra_drm_context *context)
 	pm_runtime_put(vic->dev);
 }
 
+static int vic_get_streamid_offset(struct tegra_drm_client *client)
+{
+	struct vic *vic = to_vic(client);
+	int err;
+
+	err = vic_load_firmware(vic);
+	if (err < 0)
+		return err;
+
+	if (vic->can_use_context)
+		return 0x30;
+	else
+		return -ENOTSUPP;
+}
+
 static const struct tegra_drm_client_ops vic_ops = {
 	.open_channel = vic_open_channel,
 	.close_channel = vic_close_channel,
 	.submit = tegra_drm_submit,
+	.get_streamid_offset = vic_get_streamid_offset,
 };
 
 #define NVIDIA_TEGRA_124_VIC_FIRMWARE "nvidia/tegra124/vic03_ucode.bin"
-- 
2.30.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH 8/8] drm/tegra: vic: Implement get_streamid_offset
@ 2021-02-08 16:38   ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:38 UTC (permalink / raw)
  To: thierry.reding, jonathanh, joro, will, robh+dt, frowand.list,
	robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, Mikko Perttunen, iommu,
	linux-tegra, linux-arm-kernel

Implement the get_streamid_offset required for supporting context
isolation. Since old firmware cannot support context isolation
without hacks that we don't want to implement, check the firmware
binary to see if context isolation should be enabled.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
---
 drivers/gpu/drm/tegra/vic.c | 38 +++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
index 6c2f03faec24..f8d5f381904d 100644
--- a/drivers/gpu/drm/tegra/vic.c
+++ b/drivers/gpu/drm/tegra/vic.c
@@ -37,6 +37,8 @@ struct vic {
 	struct clk *clk;
 	struct reset_control *rst;
 
+	bool can_use_context;
+
 	/* Platform configuration */
 	const struct vic_config *config;
 };
@@ -218,6 +220,7 @@ static int vic_load_firmware(struct vic *vic)
 {
 	struct host1x_client *client = &vic->client.base;
 	struct tegra_drm *tegra = vic->client.drm;
+	u32 fce_bin_data_offset;
 	dma_addr_t iova;
 	size_t size;
 	void *virt;
@@ -266,6 +269,25 @@ static int vic_load_firmware(struct vic *vic)
 		vic->falcon.firmware.phys = phys;
 	}
 
+	/*
+	 * Check if firmware is new enough to not require mapping firmware
+	 * to data buffer domains.
+	 */
+	fce_bin_data_offset = *(u32 *)(virt + VIC_UCODE_FCE_DATA_OFFSET);
+
+	if (!vic->config->supports_sid) {
+		vic->can_use_context = false;
+	} else if (fce_bin_data_offset != 0x0 && fce_bin_data_offset != 0xa5a5a5a5) {
+		/*
+		 * Firmware will access FCE through STREAMID0, so context
+		 * isolation cannot be used.
+		 */
+		vic->can_use_context = false;
+		dev_warn_once(vic->dev, "context isolation disabled due to old firmware\n");
+	} else {
+		vic->can_use_context = true;
+	}
+
 	return 0;
 
 cleanup:
@@ -357,10 +379,26 @@ static void vic_close_channel(struct tegra_drm_context *context)
 	pm_runtime_put(vic->dev);
 }
 
+static int vic_get_streamid_offset(struct tegra_drm_client *client)
+{
+	struct vic *vic = to_vic(client);
+	int err;
+
+	err = vic_load_firmware(vic);
+	if (err < 0)
+		return err;
+
+	if (vic->can_use_context)
+		return 0x30;
+	else
+		return -ENOTSUPP;
+}
+
 static const struct tegra_drm_client_ops vic_ops = {
 	.open_channel = vic_open_channel,
 	.close_channel = vic_close_channel,
 	.submit = tegra_drm_submit,
+	.get_streamid_offset = vic_get_streamid_offset,
 };
 
 #define NVIDIA_TEGRA_124_VIC_FIRMWARE "nvidia/tegra124/vic03_ucode.bin"
-- 
2.30.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure
  2021-02-08 16:38   ` Mikko Perttunen
  (?)
  (?)
@ 2021-02-08 16:53     ` Mikko Perttunen
  -1 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:53 UTC (permalink / raw)
  To: Mikko Perttunen, thierry.reding, jonathanh, joro, will, robh+dt,
	frowand.list, robin.murphy
  Cc: linux-tegra, dri-devel, iommu, linux-kernel, devicetree,
	linux-arm-kernel

On 2/8/21 6:38 PM, Mikko Perttunen wrote:
> ...
> -static int of_iommu_xlate(struct device *dev,
> -			  struct of_phandle_args *iommu_spec)
> +int of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec)
> ...
> +EXPORT_SYMBOL_GPL(of_iommu_xlate);
>   

These two chunks should not be needed.. looks like I left them in from 
some earlier experiments.

Sending patches out is really the best way to notice mistakes, even 
after reading through them 5 times before.. :)

Mikko

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure
@ 2021-02-08 16:53     ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:53 UTC (permalink / raw)
  To: Mikko Perttunen, thierry.reding, jonathanh, joro, will, robh+dt,
	frowand.list, robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, iommu, linux-tegra,
	linux-arm-kernel

On 2/8/21 6:38 PM, Mikko Perttunen wrote:
> ...
> -static int of_iommu_xlate(struct device *dev,
> -			  struct of_phandle_args *iommu_spec)
> +int of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec)
> ...
> +EXPORT_SYMBOL_GPL(of_iommu_xlate);
>   

These two chunks should not be needed.. looks like I left them in from 
some earlier experiments.

Sending patches out is really the best way to notice mistakes, even 
after reading through them 5 times before.. :)

Mikko
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure
@ 2021-02-08 16:53     ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:53 UTC (permalink / raw)
  To: Mikko Perttunen, thierry.reding, jonathanh, joro, will, robh+dt,
	frowand.list, robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, iommu, linux-tegra,
	linux-arm-kernel

On 2/8/21 6:38 PM, Mikko Perttunen wrote:
> ...
> -static int of_iommu_xlate(struct device *dev,
> -			  struct of_phandle_args *iommu_spec)
> +int of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec)
> ...
> +EXPORT_SYMBOL_GPL(of_iommu_xlate);
>   

These two chunks should not be needed.. looks like I left them in from 
some earlier experiments.

Sending patches out is really the best way to notice mistakes, even 
after reading through them 5 times before.. :)

Mikko

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure
@ 2021-02-08 16:53     ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-08 16:53 UTC (permalink / raw)
  To: Mikko Perttunen, thierry.reding, jonathanh, joro, will, robh+dt,
	frowand.list, robin.murphy
  Cc: devicetree, linux-kernel, dri-devel, iommu, linux-tegra,
	linux-arm-kernel

On 2/8/21 6:38 PM, Mikko Perttunen wrote:
> ...
> -static int of_iommu_xlate(struct device *dev,
> -			  struct of_phandle_args *iommu_spec)
> +int of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec)
> ...
> +EXPORT_SYMBOL_GPL(of_iommu_xlate);
>   

These two chunks should not be needed.. looks like I left them in from 
some earlier experiments.

Sending patches out is really the best way to notice mistakes, even 
after reading through them 5 times before.. :)

Mikko
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure
  2021-02-08 16:38   ` Mikko Perttunen
  (?)
  (?)
@ 2021-02-16 12:47     ` Robin Murphy
  -1 siblings, 0 replies; 48+ messages in thread
From: Robin Murphy @ 2021-02-16 12:47 UTC (permalink / raw)
  To: Mikko Perttunen, thierry.reding, jonathanh, joro, will, robh+dt,
	frowand.list
  Cc: devicetree, linux-kernel, dri-devel, iommu, linux-tegra,
	linux-arm-kernel

Hi Mikko,

On 2021-02-08 16:38, Mikko Perttunen wrote:
> To allow for more customized device tree bindings that point to IOMMUs,
> allow manual specification of iommu_spec to of_dma_configure.
> 
> The initial use case for this is with Host1x, where the driver manages
> a set of device tree-defined IOMMU contexts that are dynamically
> allocated to various users. These contexts don't correspond to
> platform devices and are instead attached to dummy devices on a custom
> software bus.

I'd suggest taking a closer look at the patches that made this 
of_dma_configure_id() in the first place, and the corresponding bus code 
in fsl-mc. At this level, Host1x sounds effectively identical to DPAA2 
in terms of being a bus of logical devices composed from bits of 
implicit behind-the-scenes hardware. I mean, compare your series title 
to the fact that their identifiers are literally named "Isolation 
Context ID" ;)

Please just use the existing mechanisms to describe a mapping between 
Host1x context IDs and SMMU Stream IDs, rather than what looks like a 
giant hacky mess here.

(This also reminds me I wanted to rip out all the PCI special-cases and 
convert pci_dma_configure() over to passing its own IDs too, so thanks 
for the memory-jog...)

Robin.

> Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
> ---
>   drivers/iommu/of_iommu.c  | 12 ++++++++----
>   drivers/of/device.c       |  9 +++++----
>   include/linux/of_device.h | 34 +++++++++++++++++++++++++++-------
>   include/linux/of_iommu.h  |  6 ++++--
>   4 files changed, 44 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
> index e505b9130a1c..3fefa6c63863 100644
> --- a/drivers/iommu/of_iommu.c
> +++ b/drivers/iommu/of_iommu.c
> @@ -87,8 +87,7 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
>   }
>   EXPORT_SYMBOL_GPL(of_get_dma_window);
>   
> -static int of_iommu_xlate(struct device *dev,
> -			  struct of_phandle_args *iommu_spec)
> +int of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec)
>   {
>   	const struct iommu_ops *ops;
>   	struct fwnode_handle *fwnode = &iommu_spec->np->fwnode;
> @@ -117,6 +116,7 @@ static int of_iommu_xlate(struct device *dev,
>   	module_put(ops->owner);
>   	return ret;
>   }
> +EXPORT_SYMBOL_GPL(of_iommu_xlate);
>   
>   static int of_iommu_configure_dev_id(struct device_node *master_np,
>   				     struct device *dev,
> @@ -177,7 +177,8 @@ static int of_iommu_configure_device(struct device_node *master_np,
>   
>   const struct iommu_ops *of_iommu_configure(struct device *dev,
>   					   struct device_node *master_np,
> -					   const u32 *id)
> +					   const u32 *id,
> +					   struct of_phandle_args *iommu_spec)
>   {
>   	const struct iommu_ops *ops = NULL;
>   	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
> @@ -209,7 +210,10 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
>   		err = pci_for_each_dma_alias(to_pci_dev(dev),
>   					     of_pci_iommu_init, &info);
>   	} else {
> -		err = of_iommu_configure_device(master_np, dev, id);
> +		if (iommu_spec)
> +			err = of_iommu_xlate(dev, iommu_spec);
> +		else
> +			err = of_iommu_configure_device(master_np, dev, id);
>   
>   		fwspec = dev_iommu_fwspec_get(dev);
>   		if (!err && fwspec)
> diff --git a/drivers/of/device.c b/drivers/of/device.c
> index aedfaaafd3e7..84ada2110c5b 100644
> --- a/drivers/of/device.c
> +++ b/drivers/of/device.c
> @@ -88,8 +88,9 @@ int of_device_add(struct platform_device *ofdev)
>    * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
>    * to fix up DMA configuration.
>    */
> -int of_dma_configure_id(struct device *dev, struct device_node *np,
> -			bool force_dma, const u32 *id)
> +int __of_dma_configure(struct device *dev, struct device_node *np,
> +			bool force_dma, const u32 *id,
> +			struct of_phandle_args *iommu_spec)
>   {
>   	const struct iommu_ops *iommu;
>   	const struct bus_dma_region *map = NULL;
> @@ -170,7 +171,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
>   	dev_dbg(dev, "device is%sdma coherent\n",
>   		coherent ? " " : " not ");
>   
> -	iommu = of_iommu_configure(dev, np, id);
> +	iommu = of_iommu_configure(dev, np, id, iommu_spec);
>   	if (PTR_ERR(iommu) == -EPROBE_DEFER) {
>   		kfree(map);
>   		return -EPROBE_DEFER;
> @@ -184,7 +185,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
>   	dev->dma_range_map = map;
>   	return 0;
>   }
> -EXPORT_SYMBOL_GPL(of_dma_configure_id);
> +EXPORT_SYMBOL_GPL(__of_dma_configure);
>   
>   int of_device_register(struct platform_device *pdev)
>   {
> diff --git a/include/linux/of_device.h b/include/linux/of_device.h
> index 07ca187fc5e4..40cc3e788cb9 100644
> --- a/include/linux/of_device.h
> +++ b/include/linux/of_device.h
> @@ -55,14 +55,27 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
>   	return of_node_get(cpu_dev->of_node);
>   }
>   
> -int of_dma_configure_id(struct device *dev,
> +int __of_dma_configure(struct device *dev,
>   		     struct device_node *np,
> -		     bool force_dma, const u32 *id);
> +		     bool force_dma, const u32 *id,
> +		     struct of_phandle_args *iommu_spec);
>   static inline int of_dma_configure(struct device *dev,
>   				   struct device_node *np,
>   				   bool force_dma)
>   {
> -	return of_dma_configure_id(dev, np, force_dma, NULL);
> +	return __of_dma_configure(dev, np, force_dma, NULL, NULL);
> +}
> +static inline int of_dma_configure_id(struct device *dev,
> +				      struct device_node *np,
> +				      bool force_dma, const u32 *id)
> +{
> +	return __of_dma_configure(dev, np, force_dma, id, NULL);
> +}
> +static inline int
> +of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
> +			    bool force_dma, struct of_phandle_args *iommu_spec)
> +{
> +	return __of_dma_configure(dev, np, force_dma, NULL, iommu_spec);
>   }
>   #else /* CONFIG_OF */
>   
> @@ -112,18 +125,25 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
>   	return NULL;
>   }
>   
> -static inline int of_dma_configure_id(struct device *dev,
> +static inline int of_dma_configure(struct device *dev,
>   				   struct device_node *np,
>   				   bool force_dma)
>   {
>   	return 0;
>   }
> -static inline int of_dma_configure(struct device *dev,
> -				   struct device_node *np,
> -				   bool force_dma)
> +
> +static inline int of_dma_configure_id(struct device *dev,
> +				      struct device_node *np,
> +				      bool force_dma, const u32 *id)
>   {
>   	return 0;
>   }
> +
> +static inline int
> +of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
> +			    bool force_dma, struct of_phandle_args *iommu_spec)
> +{	return 0;
> +}
>   #endif /* CONFIG_OF */
>   
>   #endif /* _LINUX_OF_DEVICE_H */
> diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
> index 16f4b3e87f20..e8d1e6d32d77 100644
> --- a/include/linux/of_iommu.h
> +++ b/include/linux/of_iommu.h
> @@ -14,7 +14,8 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix,
>   
>   extern const struct iommu_ops *of_iommu_configure(struct device *dev,
>   					struct device_node *master_np,
> -					const u32 *id);
> +					const u32 *id,
> +					struct of_phandle_args *iommu_spec);
>   
>   #else
>   
> @@ -27,7 +28,8 @@ static inline int of_get_dma_window(struct device_node *dn, const char *prefix,
>   
>   static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
>   					 struct device_node *master_np,
> -					 const u32 *id)
> +					 const u32 *id,
> +					 struct of_phandle_args *iommu_spec);
>   {
>   	return NULL;
>   }
> 

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure
@ 2021-02-16 12:47     ` Robin Murphy
  0 siblings, 0 replies; 48+ messages in thread
From: Robin Murphy @ 2021-02-16 12:47 UTC (permalink / raw)
  To: Mikko Perttunen, thierry.reding, jonathanh, joro, will, robh+dt,
	frowand.list
  Cc: devicetree, linux-kernel, dri-devel, iommu, linux-tegra,
	linux-arm-kernel

Hi Mikko,

On 2021-02-08 16:38, Mikko Perttunen wrote:
> To allow for more customized device tree bindings that point to IOMMUs,
> allow manual specification of iommu_spec to of_dma_configure.
> 
> The initial use case for this is with Host1x, where the driver manages
> a set of device tree-defined IOMMU contexts that are dynamically
> allocated to various users. These contexts don't correspond to
> platform devices and are instead attached to dummy devices on a custom
> software bus.

I'd suggest taking a closer look at the patches that made this 
of_dma_configure_id() in the first place, and the corresponding bus code 
in fsl-mc. At this level, Host1x sounds effectively identical to DPAA2 
in terms of being a bus of logical devices composed from bits of 
implicit behind-the-scenes hardware. I mean, compare your series title 
to the fact that their identifiers are literally named "Isolation 
Context ID" ;)

Please just use the existing mechanisms to describe a mapping between 
Host1x context IDs and SMMU Stream IDs, rather than what looks like a 
giant hacky mess here.

(This also reminds me I wanted to rip out all the PCI special-cases and 
convert pci_dma_configure() over to passing its own IDs too, so thanks 
for the memory-jog...)

Robin.

> Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
> ---
>   drivers/iommu/of_iommu.c  | 12 ++++++++----
>   drivers/of/device.c       |  9 +++++----
>   include/linux/of_device.h | 34 +++++++++++++++++++++++++++-------
>   include/linux/of_iommu.h  |  6 ++++--
>   4 files changed, 44 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
> index e505b9130a1c..3fefa6c63863 100644
> --- a/drivers/iommu/of_iommu.c
> +++ b/drivers/iommu/of_iommu.c
> @@ -87,8 +87,7 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
>   }
>   EXPORT_SYMBOL_GPL(of_get_dma_window);
>   
> -static int of_iommu_xlate(struct device *dev,
> -			  struct of_phandle_args *iommu_spec)
> +int of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec)
>   {
>   	const struct iommu_ops *ops;
>   	struct fwnode_handle *fwnode = &iommu_spec->np->fwnode;
> @@ -117,6 +116,7 @@ static int of_iommu_xlate(struct device *dev,
>   	module_put(ops->owner);
>   	return ret;
>   }
> +EXPORT_SYMBOL_GPL(of_iommu_xlate);
>   
>   static int of_iommu_configure_dev_id(struct device_node *master_np,
>   				     struct device *dev,
> @@ -177,7 +177,8 @@ static int of_iommu_configure_device(struct device_node *master_np,
>   
>   const struct iommu_ops *of_iommu_configure(struct device *dev,
>   					   struct device_node *master_np,
> -					   const u32 *id)
> +					   const u32 *id,
> +					   struct of_phandle_args *iommu_spec)
>   {
>   	const struct iommu_ops *ops = NULL;
>   	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
> @@ -209,7 +210,10 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
>   		err = pci_for_each_dma_alias(to_pci_dev(dev),
>   					     of_pci_iommu_init, &info);
>   	} else {
> -		err = of_iommu_configure_device(master_np, dev, id);
> +		if (iommu_spec)
> +			err = of_iommu_xlate(dev, iommu_spec);
> +		else
> +			err = of_iommu_configure_device(master_np, dev, id);
>   
>   		fwspec = dev_iommu_fwspec_get(dev);
>   		if (!err && fwspec)
> diff --git a/drivers/of/device.c b/drivers/of/device.c
> index aedfaaafd3e7..84ada2110c5b 100644
> --- a/drivers/of/device.c
> +++ b/drivers/of/device.c
> @@ -88,8 +88,9 @@ int of_device_add(struct platform_device *ofdev)
>    * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
>    * to fix up DMA configuration.
>    */
> -int of_dma_configure_id(struct device *dev, struct device_node *np,
> -			bool force_dma, const u32 *id)
> +int __of_dma_configure(struct device *dev, struct device_node *np,
> +			bool force_dma, const u32 *id,
> +			struct of_phandle_args *iommu_spec)
>   {
>   	const struct iommu_ops *iommu;
>   	const struct bus_dma_region *map = NULL;
> @@ -170,7 +171,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
>   	dev_dbg(dev, "device is%sdma coherent\n",
>   		coherent ? " " : " not ");
>   
> -	iommu = of_iommu_configure(dev, np, id);
> +	iommu = of_iommu_configure(dev, np, id, iommu_spec);
>   	if (PTR_ERR(iommu) == -EPROBE_DEFER) {
>   		kfree(map);
>   		return -EPROBE_DEFER;
> @@ -184,7 +185,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
>   	dev->dma_range_map = map;
>   	return 0;
>   }
> -EXPORT_SYMBOL_GPL(of_dma_configure_id);
> +EXPORT_SYMBOL_GPL(__of_dma_configure);
>   
>   int of_device_register(struct platform_device *pdev)
>   {
> diff --git a/include/linux/of_device.h b/include/linux/of_device.h
> index 07ca187fc5e4..40cc3e788cb9 100644
> --- a/include/linux/of_device.h
> +++ b/include/linux/of_device.h
> @@ -55,14 +55,27 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
>   	return of_node_get(cpu_dev->of_node);
>   }
>   
> -int of_dma_configure_id(struct device *dev,
> +int __of_dma_configure(struct device *dev,
>   		     struct device_node *np,
> -		     bool force_dma, const u32 *id);
> +		     bool force_dma, const u32 *id,
> +		     struct of_phandle_args *iommu_spec);
>   static inline int of_dma_configure(struct device *dev,
>   				   struct device_node *np,
>   				   bool force_dma)
>   {
> -	return of_dma_configure_id(dev, np, force_dma, NULL);
> +	return __of_dma_configure(dev, np, force_dma, NULL, NULL);
> +}
> +static inline int of_dma_configure_id(struct device *dev,
> +				      struct device_node *np,
> +				      bool force_dma, const u32 *id)
> +{
> +	return __of_dma_configure(dev, np, force_dma, id, NULL);
> +}
> +static inline int
> +of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
> +			    bool force_dma, struct of_phandle_args *iommu_spec)
> +{
> +	return __of_dma_configure(dev, np, force_dma, NULL, iommu_spec);
>   }
>   #else /* CONFIG_OF */
>   
> @@ -112,18 +125,25 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
>   	return NULL;
>   }
>   
> -static inline int of_dma_configure_id(struct device *dev,
> +static inline int of_dma_configure(struct device *dev,
>   				   struct device_node *np,
>   				   bool force_dma)
>   {
>   	return 0;
>   }
> -static inline int of_dma_configure(struct device *dev,
> -				   struct device_node *np,
> -				   bool force_dma)
> +
> +static inline int of_dma_configure_id(struct device *dev,
> +				      struct device_node *np,
> +				      bool force_dma, const u32 *id)
>   {
>   	return 0;
>   }
> +
> +static inline int
> +of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
> +			    bool force_dma, struct of_phandle_args *iommu_spec)
> +{	return 0;
> +}
>   #endif /* CONFIG_OF */
>   
>   #endif /* _LINUX_OF_DEVICE_H */
> diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
> index 16f4b3e87f20..e8d1e6d32d77 100644
> --- a/include/linux/of_iommu.h
> +++ b/include/linux/of_iommu.h
> @@ -14,7 +14,8 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix,
>   
>   extern const struct iommu_ops *of_iommu_configure(struct device *dev,
>   					struct device_node *master_np,
> -					const u32 *id);
> +					const u32 *id,
> +					struct of_phandle_args *iommu_spec);
>   
>   #else
>   
> @@ -27,7 +28,8 @@ static inline int of_get_dma_window(struct device_node *dn, const char *prefix,
>   
>   static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
>   					 struct device_node *master_np,
> -					 const u32 *id)
> +					 const u32 *id,
> +					 struct of_phandle_args *iommu_spec);
>   {
>   	return NULL;
>   }
> 
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure
@ 2021-02-16 12:47     ` Robin Murphy
  0 siblings, 0 replies; 48+ messages in thread
From: Robin Murphy @ 2021-02-16 12:47 UTC (permalink / raw)
  To: Mikko Perttunen, thierry.reding, jonathanh, joro, will, robh+dt,
	frowand.list
  Cc: devicetree, linux-kernel, dri-devel, iommu, linux-tegra,
	linux-arm-kernel

Hi Mikko,

On 2021-02-08 16:38, Mikko Perttunen wrote:
> To allow for more customized device tree bindings that point to IOMMUs,
> allow manual specification of iommu_spec to of_dma_configure.
> 
> The initial use case for this is with Host1x, where the driver manages
> a set of device tree-defined IOMMU contexts that are dynamically
> allocated to various users. These contexts don't correspond to
> platform devices and are instead attached to dummy devices on a custom
> software bus.

I'd suggest taking a closer look at the patches that made this 
of_dma_configure_id() in the first place, and the corresponding bus code 
in fsl-mc. At this level, Host1x sounds effectively identical to DPAA2 
in terms of being a bus of logical devices composed from bits of 
implicit behind-the-scenes hardware. I mean, compare your series title 
to the fact that their identifiers are literally named "Isolation 
Context ID" ;)

Please just use the existing mechanisms to describe a mapping between 
Host1x context IDs and SMMU Stream IDs, rather than what looks like a 
giant hacky mess here.

(This also reminds me I wanted to rip out all the PCI special-cases and 
convert pci_dma_configure() over to passing its own IDs too, so thanks 
for the memory-jog...)

Robin.

> Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
> ---
>   drivers/iommu/of_iommu.c  | 12 ++++++++----
>   drivers/of/device.c       |  9 +++++----
>   include/linux/of_device.h | 34 +++++++++++++++++++++++++++-------
>   include/linux/of_iommu.h  |  6 ++++--
>   4 files changed, 44 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
> index e505b9130a1c..3fefa6c63863 100644
> --- a/drivers/iommu/of_iommu.c
> +++ b/drivers/iommu/of_iommu.c
> @@ -87,8 +87,7 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
>   }
>   EXPORT_SYMBOL_GPL(of_get_dma_window);
>   
> -static int of_iommu_xlate(struct device *dev,
> -			  struct of_phandle_args *iommu_spec)
> +int of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec)
>   {
>   	const struct iommu_ops *ops;
>   	struct fwnode_handle *fwnode = &iommu_spec->np->fwnode;
> @@ -117,6 +116,7 @@ static int of_iommu_xlate(struct device *dev,
>   	module_put(ops->owner);
>   	return ret;
>   }
> +EXPORT_SYMBOL_GPL(of_iommu_xlate);
>   
>   static int of_iommu_configure_dev_id(struct device_node *master_np,
>   				     struct device *dev,
> @@ -177,7 +177,8 @@ static int of_iommu_configure_device(struct device_node *master_np,
>   
>   const struct iommu_ops *of_iommu_configure(struct device *dev,
>   					   struct device_node *master_np,
> -					   const u32 *id)
> +					   const u32 *id,
> +					   struct of_phandle_args *iommu_spec)
>   {
>   	const struct iommu_ops *ops = NULL;
>   	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
> @@ -209,7 +210,10 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
>   		err = pci_for_each_dma_alias(to_pci_dev(dev),
>   					     of_pci_iommu_init, &info);
>   	} else {
> -		err = of_iommu_configure_device(master_np, dev, id);
> +		if (iommu_spec)
> +			err = of_iommu_xlate(dev, iommu_spec);
> +		else
> +			err = of_iommu_configure_device(master_np, dev, id);
>   
>   		fwspec = dev_iommu_fwspec_get(dev);
>   		if (!err && fwspec)
> diff --git a/drivers/of/device.c b/drivers/of/device.c
> index aedfaaafd3e7..84ada2110c5b 100644
> --- a/drivers/of/device.c
> +++ b/drivers/of/device.c
> @@ -88,8 +88,9 @@ int of_device_add(struct platform_device *ofdev)
>    * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
>    * to fix up DMA configuration.
>    */
> -int of_dma_configure_id(struct device *dev, struct device_node *np,
> -			bool force_dma, const u32 *id)
> +int __of_dma_configure(struct device *dev, struct device_node *np,
> +			bool force_dma, const u32 *id,
> +			struct of_phandle_args *iommu_spec)
>   {
>   	const struct iommu_ops *iommu;
>   	const struct bus_dma_region *map = NULL;
> @@ -170,7 +171,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
>   	dev_dbg(dev, "device is%sdma coherent\n",
>   		coherent ? " " : " not ");
>   
> -	iommu = of_iommu_configure(dev, np, id);
> +	iommu = of_iommu_configure(dev, np, id, iommu_spec);
>   	if (PTR_ERR(iommu) == -EPROBE_DEFER) {
>   		kfree(map);
>   		return -EPROBE_DEFER;
> @@ -184,7 +185,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
>   	dev->dma_range_map = map;
>   	return 0;
>   }
> -EXPORT_SYMBOL_GPL(of_dma_configure_id);
> +EXPORT_SYMBOL_GPL(__of_dma_configure);
>   
>   int of_device_register(struct platform_device *pdev)
>   {
> diff --git a/include/linux/of_device.h b/include/linux/of_device.h
> index 07ca187fc5e4..40cc3e788cb9 100644
> --- a/include/linux/of_device.h
> +++ b/include/linux/of_device.h
> @@ -55,14 +55,27 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
>   	return of_node_get(cpu_dev->of_node);
>   }
>   
> -int of_dma_configure_id(struct device *dev,
> +int __of_dma_configure(struct device *dev,
>   		     struct device_node *np,
> -		     bool force_dma, const u32 *id);
> +		     bool force_dma, const u32 *id,
> +		     struct of_phandle_args *iommu_spec);
>   static inline int of_dma_configure(struct device *dev,
>   				   struct device_node *np,
>   				   bool force_dma)
>   {
> -	return of_dma_configure_id(dev, np, force_dma, NULL);
> +	return __of_dma_configure(dev, np, force_dma, NULL, NULL);
> +}
> +static inline int of_dma_configure_id(struct device *dev,
> +				      struct device_node *np,
> +				      bool force_dma, const u32 *id)
> +{
> +	return __of_dma_configure(dev, np, force_dma, id, NULL);
> +}
> +static inline int
> +of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
> +			    bool force_dma, struct of_phandle_args *iommu_spec)
> +{
> +	return __of_dma_configure(dev, np, force_dma, NULL, iommu_spec);
>   }
>   #else /* CONFIG_OF */
>   
> @@ -112,18 +125,25 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
>   	return NULL;
>   }
>   
> -static inline int of_dma_configure_id(struct device *dev,
> +static inline int of_dma_configure(struct device *dev,
>   				   struct device_node *np,
>   				   bool force_dma)
>   {
>   	return 0;
>   }
> -static inline int of_dma_configure(struct device *dev,
> -				   struct device_node *np,
> -				   bool force_dma)
> +
> +static inline int of_dma_configure_id(struct device *dev,
> +				      struct device_node *np,
> +				      bool force_dma, const u32 *id)
>   {
>   	return 0;
>   }
> +
> +static inline int
> +of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
> +			    bool force_dma, struct of_phandle_args *iommu_spec)
> +{	return 0;
> +}
>   #endif /* CONFIG_OF */
>   
>   #endif /* _LINUX_OF_DEVICE_H */
> diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
> index 16f4b3e87f20..e8d1e6d32d77 100644
> --- a/include/linux/of_iommu.h
> +++ b/include/linux/of_iommu.h
> @@ -14,7 +14,8 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix,
>   
>   extern const struct iommu_ops *of_iommu_configure(struct device *dev,
>   					struct device_node *master_np,
> -					const u32 *id);
> +					const u32 *id,
> +					struct of_phandle_args *iommu_spec);
>   
>   #else
>   
> @@ -27,7 +28,8 @@ static inline int of_get_dma_window(struct device_node *dn, const char *prefix,
>   
>   static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
>   					 struct device_node *master_np,
> -					 const u32 *id)
> +					 const u32 *id,
> +					 struct of_phandle_args *iommu_spec);
>   {
>   	return NULL;
>   }
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure
@ 2021-02-16 12:47     ` Robin Murphy
  0 siblings, 0 replies; 48+ messages in thread
From: Robin Murphy @ 2021-02-16 12:47 UTC (permalink / raw)
  To: Mikko Perttunen, thierry.reding, jonathanh, joro, will, robh+dt,
	frowand.list
  Cc: devicetree, linux-kernel, dri-devel, iommu, linux-tegra,
	linux-arm-kernel

Hi Mikko,

On 2021-02-08 16:38, Mikko Perttunen wrote:
> To allow for more customized device tree bindings that point to IOMMUs,
> allow manual specification of iommu_spec to of_dma_configure.
> 
> The initial use case for this is with Host1x, where the driver manages
> a set of device tree-defined IOMMU contexts that are dynamically
> allocated to various users. These contexts don't correspond to
> platform devices and are instead attached to dummy devices on a custom
> software bus.

I'd suggest taking a closer look at the patches that made this 
of_dma_configure_id() in the first place, and the corresponding bus code 
in fsl-mc. At this level, Host1x sounds effectively identical to DPAA2 
in terms of being a bus of logical devices composed from bits of 
implicit behind-the-scenes hardware. I mean, compare your series title 
to the fact that their identifiers are literally named "Isolation 
Context ID" ;)

Please just use the existing mechanisms to describe a mapping between 
Host1x context IDs and SMMU Stream IDs, rather than what looks like a 
giant hacky mess here.

(This also reminds me I wanted to rip out all the PCI special-cases and 
convert pci_dma_configure() over to passing its own IDs too, so thanks 
for the memory-jog...)

Robin.

> Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
> ---
>   drivers/iommu/of_iommu.c  | 12 ++++++++----
>   drivers/of/device.c       |  9 +++++----
>   include/linux/of_device.h | 34 +++++++++++++++++++++++++++-------
>   include/linux/of_iommu.h  |  6 ++++--
>   4 files changed, 44 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
> index e505b9130a1c..3fefa6c63863 100644
> --- a/drivers/iommu/of_iommu.c
> +++ b/drivers/iommu/of_iommu.c
> @@ -87,8 +87,7 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
>   }
>   EXPORT_SYMBOL_GPL(of_get_dma_window);
>   
> -static int of_iommu_xlate(struct device *dev,
> -			  struct of_phandle_args *iommu_spec)
> +int of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec)
>   {
>   	const struct iommu_ops *ops;
>   	struct fwnode_handle *fwnode = &iommu_spec->np->fwnode;
> @@ -117,6 +116,7 @@ static int of_iommu_xlate(struct device *dev,
>   	module_put(ops->owner);
>   	return ret;
>   }
> +EXPORT_SYMBOL_GPL(of_iommu_xlate);
>   
>   static int of_iommu_configure_dev_id(struct device_node *master_np,
>   				     struct device *dev,
> @@ -177,7 +177,8 @@ static int of_iommu_configure_device(struct device_node *master_np,
>   
>   const struct iommu_ops *of_iommu_configure(struct device *dev,
>   					   struct device_node *master_np,
> -					   const u32 *id)
> +					   const u32 *id,
> +					   struct of_phandle_args *iommu_spec)
>   {
>   	const struct iommu_ops *ops = NULL;
>   	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
> @@ -209,7 +210,10 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
>   		err = pci_for_each_dma_alias(to_pci_dev(dev),
>   					     of_pci_iommu_init, &info);
>   	} else {
> -		err = of_iommu_configure_device(master_np, dev, id);
> +		if (iommu_spec)
> +			err = of_iommu_xlate(dev, iommu_spec);
> +		else
> +			err = of_iommu_configure_device(master_np, dev, id);
>   
>   		fwspec = dev_iommu_fwspec_get(dev);
>   		if (!err && fwspec)
> diff --git a/drivers/of/device.c b/drivers/of/device.c
> index aedfaaafd3e7..84ada2110c5b 100644
> --- a/drivers/of/device.c
> +++ b/drivers/of/device.c
> @@ -88,8 +88,9 @@ int of_device_add(struct platform_device *ofdev)
>    * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
>    * to fix up DMA configuration.
>    */
> -int of_dma_configure_id(struct device *dev, struct device_node *np,
> -			bool force_dma, const u32 *id)
> +int __of_dma_configure(struct device *dev, struct device_node *np,
> +			bool force_dma, const u32 *id,
> +			struct of_phandle_args *iommu_spec)
>   {
>   	const struct iommu_ops *iommu;
>   	const struct bus_dma_region *map = NULL;
> @@ -170,7 +171,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
>   	dev_dbg(dev, "device is%sdma coherent\n",
>   		coherent ? " " : " not ");
>   
> -	iommu = of_iommu_configure(dev, np, id);
> +	iommu = of_iommu_configure(dev, np, id, iommu_spec);
>   	if (PTR_ERR(iommu) == -EPROBE_DEFER) {
>   		kfree(map);
>   		return -EPROBE_DEFER;
> @@ -184,7 +185,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
>   	dev->dma_range_map = map;
>   	return 0;
>   }
> -EXPORT_SYMBOL_GPL(of_dma_configure_id);
> +EXPORT_SYMBOL_GPL(__of_dma_configure);
>   
>   int of_device_register(struct platform_device *pdev)
>   {
> diff --git a/include/linux/of_device.h b/include/linux/of_device.h
> index 07ca187fc5e4..40cc3e788cb9 100644
> --- a/include/linux/of_device.h
> +++ b/include/linux/of_device.h
> @@ -55,14 +55,27 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
>   	return of_node_get(cpu_dev->of_node);
>   }
>   
> -int of_dma_configure_id(struct device *dev,
> +int __of_dma_configure(struct device *dev,
>   		     struct device_node *np,
> -		     bool force_dma, const u32 *id);
> +		     bool force_dma, const u32 *id,
> +		     struct of_phandle_args *iommu_spec);
>   static inline int of_dma_configure(struct device *dev,
>   				   struct device_node *np,
>   				   bool force_dma)
>   {
> -	return of_dma_configure_id(dev, np, force_dma, NULL);
> +	return __of_dma_configure(dev, np, force_dma, NULL, NULL);
> +}
> +static inline int of_dma_configure_id(struct device *dev,
> +				      struct device_node *np,
> +				      bool force_dma, const u32 *id)
> +{
> +	return __of_dma_configure(dev, np, force_dma, id, NULL);
> +}
> +static inline int
> +of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
> +			    bool force_dma, struct of_phandle_args *iommu_spec)
> +{
> +	return __of_dma_configure(dev, np, force_dma, NULL, iommu_spec);
>   }
>   #else /* CONFIG_OF */
>   
> @@ -112,18 +125,25 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
>   	return NULL;
>   }
>   
> -static inline int of_dma_configure_id(struct device *dev,
> +static inline int of_dma_configure(struct device *dev,
>   				   struct device_node *np,
>   				   bool force_dma)
>   {
>   	return 0;
>   }
> -static inline int of_dma_configure(struct device *dev,
> -				   struct device_node *np,
> -				   bool force_dma)
> +
> +static inline int of_dma_configure_id(struct device *dev,
> +				      struct device_node *np,
> +				      bool force_dma, const u32 *id)
>   {
>   	return 0;
>   }
> +
> +static inline int
> +of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
> +			    bool force_dma, struct of_phandle_args *iommu_spec)
> +{	return 0;
> +}
>   #endif /* CONFIG_OF */
>   
>   #endif /* _LINUX_OF_DEVICE_H */
> diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
> index 16f4b3e87f20..e8d1e6d32d77 100644
> --- a/include/linux/of_iommu.h
> +++ b/include/linux/of_iommu.h
> @@ -14,7 +14,8 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix,
>   
>   extern const struct iommu_ops *of_iommu_configure(struct device *dev,
>   					struct device_node *master_np,
> -					const u32 *id);
> +					const u32 *id,
> +					struct of_phandle_args *iommu_spec);
>   
>   #else
>   
> @@ -27,7 +28,8 @@ static inline int of_get_dma_window(struct device_node *dn, const char *prefix,
>   
>   static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
>   					 struct device_node *master_np,
> -					 const u32 *id)
> +					 const u32 *id,
> +					 struct of_phandle_args *iommu_spec);
>   {
>   	return NULL;
>   }
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure
  2021-02-16 12:47     ` Robin Murphy
  (?)
  (?)
@ 2021-02-16 13:20       ` Mikko Perttunen
  -1 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-16 13:20 UTC (permalink / raw)
  To: Robin Murphy, Mikko Perttunen, thierry.reding, jonathanh, joro,
	will, robh+dt, frowand.list
  Cc: devicetree, linux-kernel, dri-devel, iommu, linux-tegra,
	linux-arm-kernel

On 2/16/21 2:47 PM, Robin Murphy wrote:
> Hi Mikko,
> 
> On 2021-02-08 16:38, Mikko Perttunen wrote:
>> To allow for more customized device tree bindings that point to IOMMUs,
>> allow manual specification of iommu_spec to of_dma_configure.
>>
>> The initial use case for this is with Host1x, where the driver manages
>> a set of device tree-defined IOMMU contexts that are dynamically
>> allocated to various users. These contexts don't correspond to
>> platform devices and are instead attached to dummy devices on a custom
>> software bus.
> 
> I'd suggest taking a closer look at the patches that made this 
> of_dma_configure_id() in the first place, and the corresponding bus code 
> in fsl-mc. At this level, Host1x sounds effectively identical to DPAA2 
> in terms of being a bus of logical devices composed from bits of 
> implicit behind-the-scenes hardware. I mean, compare your series title 
> to the fact that their identifiers are literally named "Isolation 
> Context ID" ;)
> 
> Please just use the existing mechanisms to describe a mapping between 
> Host1x context IDs and SMMU Stream IDs, rather than what looks like a 
> giant hacky mess here.
> 
> (This also reminds me I wanted to rip out all the PCI special-cases and 
> convert pci_dma_configure() over to passing its own IDs too, so thanks 
> for the memory-jog...)

Thanks Robin, not sure how I missed that the first time :) Maybe because 
Host1x doesn't have a concept of its own "IDs" for these per se - the 
hardware just uses stream IDs as is. I would need to count the number of 
mapped IDs from the iommu-map property and introduce some 0..N range of 
IDs at the software level. But maybe that's not too bad if we're able to 
use the existing paths and bindings then.

I'll take a look at switching to iommu-map.

Thanks,
Mikko

> 
> Robin.
> 
>> Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
>> ---
>>   drivers/iommu/of_iommu.c  | 12 ++++++++----
>>   drivers/of/device.c       |  9 +++++----
>>   include/linux/of_device.h | 34 +++++++++++++++++++++++++++-------
>>   include/linux/of_iommu.h  |  6 ++++--
>>   4 files changed, 44 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
>> index e505b9130a1c..3fefa6c63863 100644
>> --- a/drivers/iommu/of_iommu.c
>> +++ b/drivers/iommu/of_iommu.c
>> @@ -87,8 +87,7 @@ int of_get_dma_window(struct device_node *dn, const 
>> char *prefix, int index,
>>   }
>>   EXPORT_SYMBOL_GPL(of_get_dma_window);
>> -static int of_iommu_xlate(struct device *dev,
>> -              struct of_phandle_args *iommu_spec)
>> +int of_iommu_xlate(struct device *dev, struct of_phandle_args 
>> *iommu_spec)
>>   {
>>       const struct iommu_ops *ops;
>>       struct fwnode_handle *fwnode = &iommu_spec->np->fwnode;
>> @@ -117,6 +116,7 @@ static int of_iommu_xlate(struct device *dev,
>>       module_put(ops->owner);
>>       return ret;
>>   }
>> +EXPORT_SYMBOL_GPL(of_iommu_xlate);
>>   static int of_iommu_configure_dev_id(struct device_node *master_np,
>>                        struct device *dev,
>> @@ -177,7 +177,8 @@ static int of_iommu_configure_device(struct 
>> device_node *master_np,
>>   const struct iommu_ops *of_iommu_configure(struct device *dev,
>>                          struct device_node *master_np,
>> -                       const u32 *id)
>> +                       const u32 *id,
>> +                       struct of_phandle_args *iommu_spec)
>>   {
>>       const struct iommu_ops *ops = NULL;
>>       struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
>> @@ -209,7 +210,10 @@ const struct iommu_ops *of_iommu_configure(struct 
>> device *dev,
>>           err = pci_for_each_dma_alias(to_pci_dev(dev),
>>                            of_pci_iommu_init, &info);
>>       } else {
>> -        err = of_iommu_configure_device(master_np, dev, id);
>> +        if (iommu_spec)
>> +            err = of_iommu_xlate(dev, iommu_spec);
>> +        else
>> +            err = of_iommu_configure_device(master_np, dev, id);
>>           fwspec = dev_iommu_fwspec_get(dev);
>>           if (!err && fwspec)
>> diff --git a/drivers/of/device.c b/drivers/of/device.c
>> index aedfaaafd3e7..84ada2110c5b 100644
>> --- a/drivers/of/device.c
>> +++ b/drivers/of/device.c
>> @@ -88,8 +88,9 @@ int of_device_add(struct platform_device *ofdev)
>>    * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE 
>> events
>>    * to fix up DMA configuration.
>>    */
>> -int of_dma_configure_id(struct device *dev, struct device_node *np,
>> -            bool force_dma, const u32 *id)
>> +int __of_dma_configure(struct device *dev, struct device_node *np,
>> +            bool force_dma, const u32 *id,
>> +            struct of_phandle_args *iommu_spec)
>>   {
>>       const struct iommu_ops *iommu;
>>       const struct bus_dma_region *map = NULL;
>> @@ -170,7 +171,7 @@ int of_dma_configure_id(struct device *dev, struct 
>> device_node *np,
>>       dev_dbg(dev, "device is%sdma coherent\n",
>>           coherent ? " " : " not ");
>> -    iommu = of_iommu_configure(dev, np, id);
>> +    iommu = of_iommu_configure(dev, np, id, iommu_spec);
>>       if (PTR_ERR(iommu) == -EPROBE_DEFER) {
>>           kfree(map);
>>           return -EPROBE_DEFER;
>> @@ -184,7 +185,7 @@ int of_dma_configure_id(struct device *dev, struct 
>> device_node *np,
>>       dev->dma_range_map = map;
>>       return 0;
>>   }
>> -EXPORT_SYMBOL_GPL(of_dma_configure_id);
>> +EXPORT_SYMBOL_GPL(__of_dma_configure);
>>   int of_device_register(struct platform_device *pdev)
>>   {
>> diff --git a/include/linux/of_device.h b/include/linux/of_device.h
>> index 07ca187fc5e4..40cc3e788cb9 100644
>> --- a/include/linux/of_device.h
>> +++ b/include/linux/of_device.h
>> @@ -55,14 +55,27 @@ static inline struct device_node 
>> *of_cpu_device_node_get(int cpu)
>>       return of_node_get(cpu_dev->of_node);
>>   }
>> -int of_dma_configure_id(struct device *dev,
>> +int __of_dma_configure(struct device *dev,
>>                struct device_node *np,
>> -             bool force_dma, const u32 *id);
>> +             bool force_dma, const u32 *id,
>> +             struct of_phandle_args *iommu_spec);
>>   static inline int of_dma_configure(struct device *dev,
>>                      struct device_node *np,
>>                      bool force_dma)
>>   {
>> -    return of_dma_configure_id(dev, np, force_dma, NULL);
>> +    return __of_dma_configure(dev, np, force_dma, NULL, NULL);
>> +}
>> +static inline int of_dma_configure_id(struct device *dev,
>> +                      struct device_node *np,
>> +                      bool force_dma, const u32 *id)
>> +{
>> +    return __of_dma_configure(dev, np, force_dma, id, NULL);
>> +}
>> +static inline int
>> +of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
>> +                bool force_dma, struct of_phandle_args *iommu_spec)
>> +{
>> +    return __of_dma_configure(dev, np, force_dma, NULL, iommu_spec);
>>   }
>>   #else /* CONFIG_OF */
>> @@ -112,18 +125,25 @@ static inline struct device_node 
>> *of_cpu_device_node_get(int cpu)
>>       return NULL;
>>   }
>> -static inline int of_dma_configure_id(struct device *dev,
>> +static inline int of_dma_configure(struct device *dev,
>>                      struct device_node *np,
>>                      bool force_dma)
>>   {
>>       return 0;
>>   }
>> -static inline int of_dma_configure(struct device *dev,
>> -                   struct device_node *np,
>> -                   bool force_dma)
>> +
>> +static inline int of_dma_configure_id(struct device *dev,
>> +                      struct device_node *np,
>> +                      bool force_dma, const u32 *id)
>>   {
>>       return 0;
>>   }
>> +
>> +static inline int
>> +of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
>> +                bool force_dma, struct of_phandle_args *iommu_spec)
>> +{    return 0;
>> +}
>>   #endif /* CONFIG_OF */
>>   #endif /* _LINUX_OF_DEVICE_H */
>> diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
>> index 16f4b3e87f20..e8d1e6d32d77 100644
>> --- a/include/linux/of_iommu.h
>> +++ b/include/linux/of_iommu.h
>> @@ -14,7 +14,8 @@ extern int of_get_dma_window(struct device_node *dn, 
>> const char *prefix,
>>   extern const struct iommu_ops *of_iommu_configure(struct device *dev,
>>                       struct device_node *master_np,
>> -                    const u32 *id);
>> +                    const u32 *id,
>> +                    struct of_phandle_args *iommu_spec);
>>   #else
>> @@ -27,7 +28,8 @@ static inline int of_get_dma_window(struct 
>> device_node *dn, const char *prefix,
>>   static inline const struct iommu_ops *of_iommu_configure(struct 
>> device *dev,
>>                        struct device_node *master_np,
>> -                     const u32 *id)
>> +                     const u32 *id,
>> +                     struct of_phandle_args *iommu_spec);
>>   {
>>       return NULL;
>>   }
>>

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure
@ 2021-02-16 13:20       ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-16 13:20 UTC (permalink / raw)
  To: Robin Murphy, Mikko Perttunen, thierry.reding, jonathanh, joro,
	will, robh+dt, frowand.list
  Cc: devicetree, linux-kernel, dri-devel, iommu, linux-tegra,
	linux-arm-kernel

On 2/16/21 2:47 PM, Robin Murphy wrote:
> Hi Mikko,
> 
> On 2021-02-08 16:38, Mikko Perttunen wrote:
>> To allow for more customized device tree bindings that point to IOMMUs,
>> allow manual specification of iommu_spec to of_dma_configure.
>>
>> The initial use case for this is with Host1x, where the driver manages
>> a set of device tree-defined IOMMU contexts that are dynamically
>> allocated to various users. These contexts don't correspond to
>> platform devices and are instead attached to dummy devices on a custom
>> software bus.
> 
> I'd suggest taking a closer look at the patches that made this 
> of_dma_configure_id() in the first place, and the corresponding bus code 
> in fsl-mc. At this level, Host1x sounds effectively identical to DPAA2 
> in terms of being a bus of logical devices composed from bits of 
> implicit behind-the-scenes hardware. I mean, compare your series title 
> to the fact that their identifiers are literally named "Isolation 
> Context ID" ;)
> 
> Please just use the existing mechanisms to describe a mapping between 
> Host1x context IDs and SMMU Stream IDs, rather than what looks like a 
> giant hacky mess here.
> 
> (This also reminds me I wanted to rip out all the PCI special-cases and 
> convert pci_dma_configure() over to passing its own IDs too, so thanks 
> for the memory-jog...)

Thanks Robin, not sure how I missed that the first time :) Maybe because 
Host1x doesn't have a concept of its own "IDs" for these per se - the 
hardware just uses stream IDs as is. I would need to count the number of 
mapped IDs from the iommu-map property and introduce some 0..N range of 
IDs at the software level. But maybe that's not too bad if we're able to 
use the existing paths and bindings then.

I'll take a look at switching to iommu-map.

Thanks,
Mikko

> 
> Robin.
> 
>> Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
>> ---
>>   drivers/iommu/of_iommu.c  | 12 ++++++++----
>>   drivers/of/device.c       |  9 +++++----
>>   include/linux/of_device.h | 34 +++++++++++++++++++++++++++-------
>>   include/linux/of_iommu.h  |  6 ++++--
>>   4 files changed, 44 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
>> index e505b9130a1c..3fefa6c63863 100644
>> --- a/drivers/iommu/of_iommu.c
>> +++ b/drivers/iommu/of_iommu.c
>> @@ -87,8 +87,7 @@ int of_get_dma_window(struct device_node *dn, const 
>> char *prefix, int index,
>>   }
>>   EXPORT_SYMBOL_GPL(of_get_dma_window);
>> -static int of_iommu_xlate(struct device *dev,
>> -              struct of_phandle_args *iommu_spec)
>> +int of_iommu_xlate(struct device *dev, struct of_phandle_args 
>> *iommu_spec)
>>   {
>>       const struct iommu_ops *ops;
>>       struct fwnode_handle *fwnode = &iommu_spec->np->fwnode;
>> @@ -117,6 +116,7 @@ static int of_iommu_xlate(struct device *dev,
>>       module_put(ops->owner);
>>       return ret;
>>   }
>> +EXPORT_SYMBOL_GPL(of_iommu_xlate);
>>   static int of_iommu_configure_dev_id(struct device_node *master_np,
>>                        struct device *dev,
>> @@ -177,7 +177,8 @@ static int of_iommu_configure_device(struct 
>> device_node *master_np,
>>   const struct iommu_ops *of_iommu_configure(struct device *dev,
>>                          struct device_node *master_np,
>> -                       const u32 *id)
>> +                       const u32 *id,
>> +                       struct of_phandle_args *iommu_spec)
>>   {
>>       const struct iommu_ops *ops = NULL;
>>       struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
>> @@ -209,7 +210,10 @@ const struct iommu_ops *of_iommu_configure(struct 
>> device *dev,
>>           err = pci_for_each_dma_alias(to_pci_dev(dev),
>>                            of_pci_iommu_init, &info);
>>       } else {
>> -        err = of_iommu_configure_device(master_np, dev, id);
>> +        if (iommu_spec)
>> +            err = of_iommu_xlate(dev, iommu_spec);
>> +        else
>> +            err = of_iommu_configure_device(master_np, dev, id);
>>           fwspec = dev_iommu_fwspec_get(dev);
>>           if (!err && fwspec)
>> diff --git a/drivers/of/device.c b/drivers/of/device.c
>> index aedfaaafd3e7..84ada2110c5b 100644
>> --- a/drivers/of/device.c
>> +++ b/drivers/of/device.c
>> @@ -88,8 +88,9 @@ int of_device_add(struct platform_device *ofdev)
>>    * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE 
>> events
>>    * to fix up DMA configuration.
>>    */
>> -int of_dma_configure_id(struct device *dev, struct device_node *np,
>> -            bool force_dma, const u32 *id)
>> +int __of_dma_configure(struct device *dev, struct device_node *np,
>> +            bool force_dma, const u32 *id,
>> +            struct of_phandle_args *iommu_spec)
>>   {
>>       const struct iommu_ops *iommu;
>>       const struct bus_dma_region *map = NULL;
>> @@ -170,7 +171,7 @@ int of_dma_configure_id(struct device *dev, struct 
>> device_node *np,
>>       dev_dbg(dev, "device is%sdma coherent\n",
>>           coherent ? " " : " not ");
>> -    iommu = of_iommu_configure(dev, np, id);
>> +    iommu = of_iommu_configure(dev, np, id, iommu_spec);
>>       if (PTR_ERR(iommu) == -EPROBE_DEFER) {
>>           kfree(map);
>>           return -EPROBE_DEFER;
>> @@ -184,7 +185,7 @@ int of_dma_configure_id(struct device *dev, struct 
>> device_node *np,
>>       dev->dma_range_map = map;
>>       return 0;
>>   }
>> -EXPORT_SYMBOL_GPL(of_dma_configure_id);
>> +EXPORT_SYMBOL_GPL(__of_dma_configure);
>>   int of_device_register(struct platform_device *pdev)
>>   {
>> diff --git a/include/linux/of_device.h b/include/linux/of_device.h
>> index 07ca187fc5e4..40cc3e788cb9 100644
>> --- a/include/linux/of_device.h
>> +++ b/include/linux/of_device.h
>> @@ -55,14 +55,27 @@ static inline struct device_node 
>> *of_cpu_device_node_get(int cpu)
>>       return of_node_get(cpu_dev->of_node);
>>   }
>> -int of_dma_configure_id(struct device *dev,
>> +int __of_dma_configure(struct device *dev,
>>                struct device_node *np,
>> -             bool force_dma, const u32 *id);
>> +             bool force_dma, const u32 *id,
>> +             struct of_phandle_args *iommu_spec);
>>   static inline int of_dma_configure(struct device *dev,
>>                      struct device_node *np,
>>                      bool force_dma)
>>   {
>> -    return of_dma_configure_id(dev, np, force_dma, NULL);
>> +    return __of_dma_configure(dev, np, force_dma, NULL, NULL);
>> +}
>> +static inline int of_dma_configure_id(struct device *dev,
>> +                      struct device_node *np,
>> +                      bool force_dma, const u32 *id)
>> +{
>> +    return __of_dma_configure(dev, np, force_dma, id, NULL);
>> +}
>> +static inline int
>> +of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
>> +                bool force_dma, struct of_phandle_args *iommu_spec)
>> +{
>> +    return __of_dma_configure(dev, np, force_dma, NULL, iommu_spec);
>>   }
>>   #else /* CONFIG_OF */
>> @@ -112,18 +125,25 @@ static inline struct device_node 
>> *of_cpu_device_node_get(int cpu)
>>       return NULL;
>>   }
>> -static inline int of_dma_configure_id(struct device *dev,
>> +static inline int of_dma_configure(struct device *dev,
>>                      struct device_node *np,
>>                      bool force_dma)
>>   {
>>       return 0;
>>   }
>> -static inline int of_dma_configure(struct device *dev,
>> -                   struct device_node *np,
>> -                   bool force_dma)
>> +
>> +static inline int of_dma_configure_id(struct device *dev,
>> +                      struct device_node *np,
>> +                      bool force_dma, const u32 *id)
>>   {
>>       return 0;
>>   }
>> +
>> +static inline int
>> +of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
>> +                bool force_dma, struct of_phandle_args *iommu_spec)
>> +{    return 0;
>> +}
>>   #endif /* CONFIG_OF */
>>   #endif /* _LINUX_OF_DEVICE_H */
>> diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
>> index 16f4b3e87f20..e8d1e6d32d77 100644
>> --- a/include/linux/of_iommu.h
>> +++ b/include/linux/of_iommu.h
>> @@ -14,7 +14,8 @@ extern int of_get_dma_window(struct device_node *dn, 
>> const char *prefix,
>>   extern const struct iommu_ops *of_iommu_configure(struct device *dev,
>>                       struct device_node *master_np,
>> -                    const u32 *id);
>> +                    const u32 *id,
>> +                    struct of_phandle_args *iommu_spec);
>>   #else
>> @@ -27,7 +28,8 @@ static inline int of_get_dma_window(struct 
>> device_node *dn, const char *prefix,
>>   static inline const struct iommu_ops *of_iommu_configure(struct 
>> device *dev,
>>                        struct device_node *master_np,
>> -                     const u32 *id)
>> +                     const u32 *id,
>> +                     struct of_phandle_args *iommu_spec);
>>   {
>>       return NULL;
>>   }
>>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure
@ 2021-02-16 13:20       ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-16 13:20 UTC (permalink / raw)
  To: Robin Murphy, Mikko Perttunen, thierry.reding, jonathanh, joro,
	will, robh+dt, frowand.list
  Cc: devicetree, linux-kernel, dri-devel, iommu, linux-tegra,
	linux-arm-kernel

On 2/16/21 2:47 PM, Robin Murphy wrote:
> Hi Mikko,
> 
> On 2021-02-08 16:38, Mikko Perttunen wrote:
>> To allow for more customized device tree bindings that point to IOMMUs,
>> allow manual specification of iommu_spec to of_dma_configure.
>>
>> The initial use case for this is with Host1x, where the driver manages
>> a set of device tree-defined IOMMU contexts that are dynamically
>> allocated to various users. These contexts don't correspond to
>> platform devices and are instead attached to dummy devices on a custom
>> software bus.
> 
> I'd suggest taking a closer look at the patches that made this 
> of_dma_configure_id() in the first place, and the corresponding bus code 
> in fsl-mc. At this level, Host1x sounds effectively identical to DPAA2 
> in terms of being a bus of logical devices composed from bits of 
> implicit behind-the-scenes hardware. I mean, compare your series title 
> to the fact that their identifiers are literally named "Isolation 
> Context ID" ;)
> 
> Please just use the existing mechanisms to describe a mapping between 
> Host1x context IDs and SMMU Stream IDs, rather than what looks like a 
> giant hacky mess here.
> 
> (This also reminds me I wanted to rip out all the PCI special-cases and 
> convert pci_dma_configure() over to passing its own IDs too, so thanks 
> for the memory-jog...)

Thanks Robin, not sure how I missed that the first time :) Maybe because 
Host1x doesn't have a concept of its own "IDs" for these per se - the 
hardware just uses stream IDs as is. I would need to count the number of 
mapped IDs from the iommu-map property and introduce some 0..N range of 
IDs at the software level. But maybe that's not too bad if we're able to 
use the existing paths and bindings then.

I'll take a look at switching to iommu-map.

Thanks,
Mikko

> 
> Robin.
> 
>> Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
>> ---
>>   drivers/iommu/of_iommu.c  | 12 ++++++++----
>>   drivers/of/device.c       |  9 +++++----
>>   include/linux/of_device.h | 34 +++++++++++++++++++++++++++-------
>>   include/linux/of_iommu.h  |  6 ++++--
>>   4 files changed, 44 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
>> index e505b9130a1c..3fefa6c63863 100644
>> --- a/drivers/iommu/of_iommu.c
>> +++ b/drivers/iommu/of_iommu.c
>> @@ -87,8 +87,7 @@ int of_get_dma_window(struct device_node *dn, const 
>> char *prefix, int index,
>>   }
>>   EXPORT_SYMBOL_GPL(of_get_dma_window);
>> -static int of_iommu_xlate(struct device *dev,
>> -              struct of_phandle_args *iommu_spec)
>> +int of_iommu_xlate(struct device *dev, struct of_phandle_args 
>> *iommu_spec)
>>   {
>>       const struct iommu_ops *ops;
>>       struct fwnode_handle *fwnode = &iommu_spec->np->fwnode;
>> @@ -117,6 +116,7 @@ static int of_iommu_xlate(struct device *dev,
>>       module_put(ops->owner);
>>       return ret;
>>   }
>> +EXPORT_SYMBOL_GPL(of_iommu_xlate);
>>   static int of_iommu_configure_dev_id(struct device_node *master_np,
>>                        struct device *dev,
>> @@ -177,7 +177,8 @@ static int of_iommu_configure_device(struct 
>> device_node *master_np,
>>   const struct iommu_ops *of_iommu_configure(struct device *dev,
>>                          struct device_node *master_np,
>> -                       const u32 *id)
>> +                       const u32 *id,
>> +                       struct of_phandle_args *iommu_spec)
>>   {
>>       const struct iommu_ops *ops = NULL;
>>       struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
>> @@ -209,7 +210,10 @@ const struct iommu_ops *of_iommu_configure(struct 
>> device *dev,
>>           err = pci_for_each_dma_alias(to_pci_dev(dev),
>>                            of_pci_iommu_init, &info);
>>       } else {
>> -        err = of_iommu_configure_device(master_np, dev, id);
>> +        if (iommu_spec)
>> +            err = of_iommu_xlate(dev, iommu_spec);
>> +        else
>> +            err = of_iommu_configure_device(master_np, dev, id);
>>           fwspec = dev_iommu_fwspec_get(dev);
>>           if (!err && fwspec)
>> diff --git a/drivers/of/device.c b/drivers/of/device.c
>> index aedfaaafd3e7..84ada2110c5b 100644
>> --- a/drivers/of/device.c
>> +++ b/drivers/of/device.c
>> @@ -88,8 +88,9 @@ int of_device_add(struct platform_device *ofdev)
>>    * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE 
>> events
>>    * to fix up DMA configuration.
>>    */
>> -int of_dma_configure_id(struct device *dev, struct device_node *np,
>> -            bool force_dma, const u32 *id)
>> +int __of_dma_configure(struct device *dev, struct device_node *np,
>> +            bool force_dma, const u32 *id,
>> +            struct of_phandle_args *iommu_spec)
>>   {
>>       const struct iommu_ops *iommu;
>>       const struct bus_dma_region *map = NULL;
>> @@ -170,7 +171,7 @@ int of_dma_configure_id(struct device *dev, struct 
>> device_node *np,
>>       dev_dbg(dev, "device is%sdma coherent\n",
>>           coherent ? " " : " not ");
>> -    iommu = of_iommu_configure(dev, np, id);
>> +    iommu = of_iommu_configure(dev, np, id, iommu_spec);
>>       if (PTR_ERR(iommu) == -EPROBE_DEFER) {
>>           kfree(map);
>>           return -EPROBE_DEFER;
>> @@ -184,7 +185,7 @@ int of_dma_configure_id(struct device *dev, struct 
>> device_node *np,
>>       dev->dma_range_map = map;
>>       return 0;
>>   }
>> -EXPORT_SYMBOL_GPL(of_dma_configure_id);
>> +EXPORT_SYMBOL_GPL(__of_dma_configure);
>>   int of_device_register(struct platform_device *pdev)
>>   {
>> diff --git a/include/linux/of_device.h b/include/linux/of_device.h
>> index 07ca187fc5e4..40cc3e788cb9 100644
>> --- a/include/linux/of_device.h
>> +++ b/include/linux/of_device.h
>> @@ -55,14 +55,27 @@ static inline struct device_node 
>> *of_cpu_device_node_get(int cpu)
>>       return of_node_get(cpu_dev->of_node);
>>   }
>> -int of_dma_configure_id(struct device *dev,
>> +int __of_dma_configure(struct device *dev,
>>                struct device_node *np,
>> -             bool force_dma, const u32 *id);
>> +             bool force_dma, const u32 *id,
>> +             struct of_phandle_args *iommu_spec);
>>   static inline int of_dma_configure(struct device *dev,
>>                      struct device_node *np,
>>                      bool force_dma)
>>   {
>> -    return of_dma_configure_id(dev, np, force_dma, NULL);
>> +    return __of_dma_configure(dev, np, force_dma, NULL, NULL);
>> +}
>> +static inline int of_dma_configure_id(struct device *dev,
>> +                      struct device_node *np,
>> +                      bool force_dma, const u32 *id)
>> +{
>> +    return __of_dma_configure(dev, np, force_dma, id, NULL);
>> +}
>> +static inline int
>> +of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
>> +                bool force_dma, struct of_phandle_args *iommu_spec)
>> +{
>> +    return __of_dma_configure(dev, np, force_dma, NULL, iommu_spec);
>>   }
>>   #else /* CONFIG_OF */
>> @@ -112,18 +125,25 @@ static inline struct device_node 
>> *of_cpu_device_node_get(int cpu)
>>       return NULL;
>>   }
>> -static inline int of_dma_configure_id(struct device *dev,
>> +static inline int of_dma_configure(struct device *dev,
>>                      struct device_node *np,
>>                      bool force_dma)
>>   {
>>       return 0;
>>   }
>> -static inline int of_dma_configure(struct device *dev,
>> -                   struct device_node *np,
>> -                   bool force_dma)
>> +
>> +static inline int of_dma_configure_id(struct device *dev,
>> +                      struct device_node *np,
>> +                      bool force_dma, const u32 *id)
>>   {
>>       return 0;
>>   }
>> +
>> +static inline int
>> +of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
>> +                bool force_dma, struct of_phandle_args *iommu_spec)
>> +{    return 0;
>> +}
>>   #endif /* CONFIG_OF */
>>   #endif /* _LINUX_OF_DEVICE_H */
>> diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
>> index 16f4b3e87f20..e8d1e6d32d77 100644
>> --- a/include/linux/of_iommu.h
>> +++ b/include/linux/of_iommu.h
>> @@ -14,7 +14,8 @@ extern int of_get_dma_window(struct device_node *dn, 
>> const char *prefix,
>>   extern const struct iommu_ops *of_iommu_configure(struct device *dev,
>>                       struct device_node *master_np,
>> -                    const u32 *id);
>> +                    const u32 *id,
>> +                    struct of_phandle_args *iommu_spec);
>>   #else
>> @@ -27,7 +28,8 @@ static inline int of_get_dma_window(struct 
>> device_node *dn, const char *prefix,
>>   static inline const struct iommu_ops *of_iommu_configure(struct 
>> device *dev,
>>                        struct device_node *master_np,
>> -                     const u32 *id)
>> +                     const u32 *id,
>> +                     struct of_phandle_args *iommu_spec);
>>   {
>>       return NULL;
>>   }
>>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure
@ 2021-02-16 13:20       ` Mikko Perttunen
  0 siblings, 0 replies; 48+ messages in thread
From: Mikko Perttunen @ 2021-02-16 13:20 UTC (permalink / raw)
  To: Robin Murphy, Mikko Perttunen, thierry.reding, jonathanh, joro,
	will, robh+dt, frowand.list
  Cc: devicetree, linux-kernel, dri-devel, iommu, linux-tegra,
	linux-arm-kernel

On 2/16/21 2:47 PM, Robin Murphy wrote:
> Hi Mikko,
> 
> On 2021-02-08 16:38, Mikko Perttunen wrote:
>> To allow for more customized device tree bindings that point to IOMMUs,
>> allow manual specification of iommu_spec to of_dma_configure.
>>
>> The initial use case for this is with Host1x, where the driver manages
>> a set of device tree-defined IOMMU contexts that are dynamically
>> allocated to various users. These contexts don't correspond to
>> platform devices and are instead attached to dummy devices on a custom
>> software bus.
> 
> I'd suggest taking a closer look at the patches that made this 
> of_dma_configure_id() in the first place, and the corresponding bus code 
> in fsl-mc. At this level, Host1x sounds effectively identical to DPAA2 
> in terms of being a bus of logical devices composed from bits of 
> implicit behind-the-scenes hardware. I mean, compare your series title 
> to the fact that their identifiers are literally named "Isolation 
> Context ID" ;)
> 
> Please just use the existing mechanisms to describe a mapping between 
> Host1x context IDs and SMMU Stream IDs, rather than what looks like a 
> giant hacky mess here.
> 
> (This also reminds me I wanted to rip out all the PCI special-cases and 
> convert pci_dma_configure() over to passing its own IDs too, so thanks 
> for the memory-jog...)

Thanks Robin, not sure how I missed that the first time :) Maybe because 
Host1x doesn't have a concept of its own "IDs" for these per se - the 
hardware just uses stream IDs as is. I would need to count the number of 
mapped IDs from the iommu-map property and introduce some 0..N range of 
IDs at the software level. But maybe that's not too bad if we're able to 
use the existing paths and bindings then.

I'll take a look at switching to iommu-map.

Thanks,
Mikko

> 
> Robin.
> 
>> Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
>> ---
>>   drivers/iommu/of_iommu.c  | 12 ++++++++----
>>   drivers/of/device.c       |  9 +++++----
>>   include/linux/of_device.h | 34 +++++++++++++++++++++++++++-------
>>   include/linux/of_iommu.h  |  6 ++++--
>>   4 files changed, 44 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
>> index e505b9130a1c..3fefa6c63863 100644
>> --- a/drivers/iommu/of_iommu.c
>> +++ b/drivers/iommu/of_iommu.c
>> @@ -87,8 +87,7 @@ int of_get_dma_window(struct device_node *dn, const 
>> char *prefix, int index,
>>   }
>>   EXPORT_SYMBOL_GPL(of_get_dma_window);
>> -static int of_iommu_xlate(struct device *dev,
>> -              struct of_phandle_args *iommu_spec)
>> +int of_iommu_xlate(struct device *dev, struct of_phandle_args 
>> *iommu_spec)
>>   {
>>       const struct iommu_ops *ops;
>>       struct fwnode_handle *fwnode = &iommu_spec->np->fwnode;
>> @@ -117,6 +116,7 @@ static int of_iommu_xlate(struct device *dev,
>>       module_put(ops->owner);
>>       return ret;
>>   }
>> +EXPORT_SYMBOL_GPL(of_iommu_xlate);
>>   static int of_iommu_configure_dev_id(struct device_node *master_np,
>>                        struct device *dev,
>> @@ -177,7 +177,8 @@ static int of_iommu_configure_device(struct 
>> device_node *master_np,
>>   const struct iommu_ops *of_iommu_configure(struct device *dev,
>>                          struct device_node *master_np,
>> -                       const u32 *id)
>> +                       const u32 *id,
>> +                       struct of_phandle_args *iommu_spec)
>>   {
>>       const struct iommu_ops *ops = NULL;
>>       struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
>> @@ -209,7 +210,10 @@ const struct iommu_ops *of_iommu_configure(struct 
>> device *dev,
>>           err = pci_for_each_dma_alias(to_pci_dev(dev),
>>                            of_pci_iommu_init, &info);
>>       } else {
>> -        err = of_iommu_configure_device(master_np, dev, id);
>> +        if (iommu_spec)
>> +            err = of_iommu_xlate(dev, iommu_spec);
>> +        else
>> +            err = of_iommu_configure_device(master_np, dev, id);
>>           fwspec = dev_iommu_fwspec_get(dev);
>>           if (!err && fwspec)
>> diff --git a/drivers/of/device.c b/drivers/of/device.c
>> index aedfaaafd3e7..84ada2110c5b 100644
>> --- a/drivers/of/device.c
>> +++ b/drivers/of/device.c
>> @@ -88,8 +88,9 @@ int of_device_add(struct platform_device *ofdev)
>>    * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE 
>> events
>>    * to fix up DMA configuration.
>>    */
>> -int of_dma_configure_id(struct device *dev, struct device_node *np,
>> -            bool force_dma, const u32 *id)
>> +int __of_dma_configure(struct device *dev, struct device_node *np,
>> +            bool force_dma, const u32 *id,
>> +            struct of_phandle_args *iommu_spec)
>>   {
>>       const struct iommu_ops *iommu;
>>       const struct bus_dma_region *map = NULL;
>> @@ -170,7 +171,7 @@ int of_dma_configure_id(struct device *dev, struct 
>> device_node *np,
>>       dev_dbg(dev, "device is%sdma coherent\n",
>>           coherent ? " " : " not ");
>> -    iommu = of_iommu_configure(dev, np, id);
>> +    iommu = of_iommu_configure(dev, np, id, iommu_spec);
>>       if (PTR_ERR(iommu) == -EPROBE_DEFER) {
>>           kfree(map);
>>           return -EPROBE_DEFER;
>> @@ -184,7 +185,7 @@ int of_dma_configure_id(struct device *dev, struct 
>> device_node *np,
>>       dev->dma_range_map = map;
>>       return 0;
>>   }
>> -EXPORT_SYMBOL_GPL(of_dma_configure_id);
>> +EXPORT_SYMBOL_GPL(__of_dma_configure);
>>   int of_device_register(struct platform_device *pdev)
>>   {
>> diff --git a/include/linux/of_device.h b/include/linux/of_device.h
>> index 07ca187fc5e4..40cc3e788cb9 100644
>> --- a/include/linux/of_device.h
>> +++ b/include/linux/of_device.h
>> @@ -55,14 +55,27 @@ static inline struct device_node 
>> *of_cpu_device_node_get(int cpu)
>>       return of_node_get(cpu_dev->of_node);
>>   }
>> -int of_dma_configure_id(struct device *dev,
>> +int __of_dma_configure(struct device *dev,
>>                struct device_node *np,
>> -             bool force_dma, const u32 *id);
>> +             bool force_dma, const u32 *id,
>> +             struct of_phandle_args *iommu_spec);
>>   static inline int of_dma_configure(struct device *dev,
>>                      struct device_node *np,
>>                      bool force_dma)
>>   {
>> -    return of_dma_configure_id(dev, np, force_dma, NULL);
>> +    return __of_dma_configure(dev, np, force_dma, NULL, NULL);
>> +}
>> +static inline int of_dma_configure_id(struct device *dev,
>> +                      struct device_node *np,
>> +                      bool force_dma, const u32 *id)
>> +{
>> +    return __of_dma_configure(dev, np, force_dma, id, NULL);
>> +}
>> +static inline int
>> +of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
>> +                bool force_dma, struct of_phandle_args *iommu_spec)
>> +{
>> +    return __of_dma_configure(dev, np, force_dma, NULL, iommu_spec);
>>   }
>>   #else /* CONFIG_OF */
>> @@ -112,18 +125,25 @@ static inline struct device_node 
>> *of_cpu_device_node_get(int cpu)
>>       return NULL;
>>   }
>> -static inline int of_dma_configure_id(struct device *dev,
>> +static inline int of_dma_configure(struct device *dev,
>>                      struct device_node *np,
>>                      bool force_dma)
>>   {
>>       return 0;
>>   }
>> -static inline int of_dma_configure(struct device *dev,
>> -                   struct device_node *np,
>> -                   bool force_dma)
>> +
>> +static inline int of_dma_configure_id(struct device *dev,
>> +                      struct device_node *np,
>> +                      bool force_dma, const u32 *id)
>>   {
>>       return 0;
>>   }
>> +
>> +static inline int
>> +of_dma_configure_iommu_spec(struct device *dev, struct device_node *np,
>> +                bool force_dma, struct of_phandle_args *iommu_spec)
>> +{    return 0;
>> +}
>>   #endif /* CONFIG_OF */
>>   #endif /* _LINUX_OF_DEVICE_H */
>> diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
>> index 16f4b3e87f20..e8d1e6d32d77 100644
>> --- a/include/linux/of_iommu.h
>> +++ b/include/linux/of_iommu.h
>> @@ -14,7 +14,8 @@ extern int of_get_dma_window(struct device_node *dn, 
>> const char *prefix,
>>   extern const struct iommu_ops *of_iommu_configure(struct device *dev,
>>                       struct device_node *master_np,
>> -                    const u32 *id);
>> +                    const u32 *id,
>> +                    struct of_phandle_args *iommu_spec);
>>   #else
>> @@ -27,7 +28,8 @@ static inline int of_get_dma_window(struct 
>> device_node *dn, const char *prefix,
>>   static inline const struct iommu_ops *of_iommu_configure(struct 
>> device *dev,
>>                        struct device_node *master_np,
>> -                     const u32 *id)
>> +                     const u32 *id,
>> +                     struct of_phandle_args *iommu_spec);
>>   {
>>       return NULL;
>>   }
>>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 48+ messages in thread

end of thread, other threads:[~2021-02-16 13:22 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-08 16:38 [RFC PATCH 0/8] Host1x context isolation support Mikko Perttunen
2021-02-08 16:38 ` Mikko Perttunen
2021-02-08 16:38 ` Mikko Perttunen
2021-02-08 16:38 ` Mikko Perttunen
2021-02-08 16:38 ` [RFC PATCH 1/8] of/device: Allow specifying a custom iommu_spec to of_dma_configure Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:53   ` Mikko Perttunen
2021-02-08 16:53     ` Mikko Perttunen
2021-02-08 16:53     ` Mikko Perttunen
2021-02-08 16:53     ` Mikko Perttunen
2021-02-16 12:47   ` Robin Murphy
2021-02-16 12:47     ` Robin Murphy
2021-02-16 12:47     ` Robin Murphy
2021-02-16 12:47     ` Robin Murphy
2021-02-16 13:20     ` Mikko Perttunen
2021-02-16 13:20       ` Mikko Perttunen
2021-02-16 13:20       ` Mikko Perttunen
2021-02-16 13:20       ` Mikko Perttunen
2021-02-08 16:38 ` [RFC PATCH 2/8] gpu: host1x: Add context bus Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38 ` [RFC PATCH 3/8] gpu: host1x: Add context device management code Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38 ` [RFC PATCH 4/8] gpu: host1x: Program context stream ID on submission Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38 ` [RFC PATCH 5/8] iommu/arm-smmu: Attach to host1x context device bus Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38 ` [RFC PATCH 6/8] arm64: tegra: Add Host1x context stream IDs on Tegra186+ Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38 ` [RFC PATCH 7/8] drm/tegra: Support context isolation Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38 ` [RFC PATCH 8/8] drm/tegra: vic: Implement get_streamid_offset Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen
2021-02-08 16:38   ` Mikko Perttunen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.