All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v3 00/13] ACPI IORT ARM SMMU v3 support
@ 2016-07-20 11:23 ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu
  Cc: Lorenzo Pieralisi, Will Deacon, Marc Zyngier, Robin Murphy,
	Joerg Roedel, Rafael J. Wysocki, Tomasz Nowicki, Hanjun Guo,
	Jon Masters, Sinan Kaya, linux-acpi, linux-pci, linux-kernel,
	linux-arm-kernel

This RFC patch series is v3 of a previous posting:

https://lkml.org/lkml/2016/6/7/523

v2 -> v3
	- Rebased on top of dependencies series [1][2][3](v4.7-rc3)
	- Added back reliance on ACPI early probing infrastructure
	- Patch[1-3] merged through other dependent series
	- Added back IOMMU fwnode generalization
	- Move SMMU v3 static functions configuration to IORT code
	- Implemented generic IOMMU fwspec API
	- Added code to implement fwnode platform device look-up

v1 -> v2:
	- Rebased on top of dependencies series [1][2][3](v4.7-rc1)
	- Removed IOMMU fwnode generalization
	- Implemented ARM SMMU v3 ACPI probing instead of ARM SMMU v2
	  owing to patch series dependencies [1]
	- Moved platform device creation logic to IORT code to
	  generalize its usage for ARM SMMU v1-v2-v3 components
	- Removed reliance on ACPI early device probing
	- Created IORT specific iommu_xlate() translation hook leaving
	  OF code unchanged according to v1 reviews

The ACPI IORT table provides information that allows instantiating
ARM SMMU devices and carrying out id mappings between components on
ARM based systems (devices, IOMMUs, interrupt controllers).

http://infocenter.arm.com/help/topic/com.arm.doc.den0049b/DEN0049B_IO_Remapping_Table.pdf

Building on basic IORT support, available through [2]:

this patchset enables ARM SMMU v3 support on ACPI systems.

Most of the code is aimed at building the required generic ACPI
infrastructure to create and enable IOMMU components and to bring
the IOMMU infrastructure for ACPI on par with DT, which is going to
make future ARM SMMU components easier to integrate.

PATCH (1) adds a FWNODE_IOMMU type to the struct fwnode_handle type.
          It is required to attach a fwnode identifier to platform
          devices allocated/detected through IORT tables entries;
          IOMMU devices have to have an identifier to look them up
          eg IOMMU core layer carrying out id translation. This can be
          done through a fwnode_handle (ie IOMMU platform devices created
          out of IORT tables are not ACPI devices hence they can't be
          allocated as such, otherwise they would have a fwnode_handle of
          type FWNODE_ACPI). This patch requires discussion and it is key
          to the RFC.

PATCH (2) makes use of the ACPI early probing API to add a linker script
          section for probing devices via IORT ACPI kernel code.

PATCH (3) provides IORT support for registering IOMMU IORT node through
          their fwnode handle.

PATCH (4) implements core code fwnode based platform devices look-up.

PATCH (5) extends iommu_fwspec so that it can be used on ACPI based
          system by creating a generic IOMMU fwspec kernel layer.

PATCH (6) implements the of_dma_configure() API in ACPI world -
          acpi_dma_configure() - and patches PCI and ACPI core code to
          start making use of it.

PATCH (7) provides an IORT function to detect existence of specific type
          of IORT components.

PATCH (8) creates the kernel infrastructure required to create ARM SMMU
          platform devices for IORT nodes.

PATCH (9) refactors the ARM SMMU v3 driver so that the init functions are
          split in a way that groups together code that probes through DT
          and code that carries out HW registers FW agnostic probing, in
          preparation for adding the ACPI probing path.

PATCH (10) rework ARM SMMU v3 platform driver registration to make it work
           on ACPI systems.

PATCH (11) Building on patch (8), it adds ARM SMMU v3 IORT IOMMU
           operations to create and probe ARM SMMU v3 components.

PATCH (12) Extend the IORT iort_node_map_rid() to work on a type mask
           instead of a single type so that the translation API can
           be used on a range of components.

PATCH (13) provides IORT infrastructure to carry out IOMMU configuration
           for devices and hook it up to the previously introduced ACPI
           DMA configure API.

This patchset is built on top and depends on these three patch series:

[1] R.Murphy "Generic DT bindings for PCI and ARM SMMU v3" v4
    https://marc.info/?l=devicetree&m=146739193215518&w=2

[2] T.Nowicki "Introduce ACPI world to ITS irqchip" v7
    https://marc.info/?l=linux-arm-kernel&m=146642080022289&w=2

[3] T.Nowicki "Support for ARM64 ACPI based PCI host controller" v8
    http://marc.info/?l=linux-acpi&m=146462129816292&w=2

and is provided for early review/testing purposes here:

git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git acpi/iort-smmu-v3

Tested on FVP models for ARM SMMU v3 probing path.

Lorenzo Pieralisi (13):
  drivers: iommu: add FWNODE_IOMMU fwnode type
  drivers: acpi: iort: introduce linker section for IORT entries probing
  drivers: acpi: iort: add support for IOMMU fwnode registration
  drivers: platform: add fwnode base platform devices retrieval
  drivers: iommu: make iommu_fwspec OF agnostic
  drivers: acpi: implement acpi_dma_configure
  drivers: acpi: iort: add node match function
  drivers: acpi: iort: add support for ARM SMMU platform devices
    creation
  drivers: iommu: arm-smmu-v3: split probe functions into DT/generic
    portions
  drivers: iommu: arm-smmu-v3: enable ACPI driver initialization
  drivers: iommu: arm-smmu-v3: add IORT platform device creation
  drivers: acpi: iort: replace rid map type with type mask
  drivers: acpi: iort: introduce iort_iommu_configure

 drivers/acpi/glue.c               |   4 +-
 drivers/acpi/iort.c               | 360 +++++++++++++++++++++++++++++++++++++-
 drivers/acpi/scan.c               |  29 +++
 drivers/base/platform.c           |  23 +++
 drivers/iommu/Kconfig             |   4 +
 drivers/iommu/Makefile            |   1 +
 drivers/iommu/arm-smmu-v3.c       | 147 ++++++++++++++--
 drivers/iommu/iommu-fwspec.c      | 114 ++++++++++++
 drivers/iommu/of_iommu.c          |  52 ------
 drivers/pci/probe.c               |   3 +-
 include/acpi/acpi_bus.h           |   2 +
 include/asm-generic/vmlinux.lds.h |   1 +
 include/linux/acpi.h              |   5 +
 include/linux/fwnode.h            |   1 +
 include/linux/iommu-fwspec.h      |  60 +++++++
 include/linux/iommu.h             |  25 +++
 include/linux/iort.h              |  19 ++
 include/linux/of_iommu.h          |  24 +--
 include/linux/platform_device.h   |   3 +
 19 files changed, 782 insertions(+), 95 deletions(-)
 create mode 100644 drivers/iommu/iommu-fwspec.c
 create mode 100644 include/linux/iommu-fwspec.h

-- 
2.6.4


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

* [RFC PATCH v3 00/13] ACPI IORT ARM SMMU v3 support
@ 2016-07-20 11:23 ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

This RFC patch series is v3 of a previous posting:

https://lkml.org/lkml/2016/6/7/523

v2 -> v3
	- Rebased on top of dependencies series [1][2][3](v4.7-rc3)
	- Added back reliance on ACPI early probing infrastructure
	- Patch[1-3] merged through other dependent series
	- Added back IOMMU fwnode generalization
	- Move SMMU v3 static functions configuration to IORT code
	- Implemented generic IOMMU fwspec API
	- Added code to implement fwnode platform device look-up

v1 -> v2:
	- Rebased on top of dependencies series [1][2][3](v4.7-rc1)
	- Removed IOMMU fwnode generalization
	- Implemented ARM SMMU v3 ACPI probing instead of ARM SMMU v2
	  owing to patch series dependencies [1]
	- Moved platform device creation logic to IORT code to
	  generalize its usage for ARM SMMU v1-v2-v3 components
	- Removed reliance on ACPI early device probing
	- Created IORT specific iommu_xlate() translation hook leaving
	  OF code unchanged according to v1 reviews

The ACPI IORT table provides information that allows instantiating
ARM SMMU devices and carrying out id mappings between components on
ARM based systems (devices, IOMMUs, interrupt controllers).

http://infocenter.arm.com/help/topic/com.arm.doc.den0049b/DEN0049B_IO_Remapping_Table.pdf

Building on basic IORT support, available through [2]:

this patchset enables ARM SMMU v3 support on ACPI systems.

Most of the code is aimed at building the required generic ACPI
infrastructure to create and enable IOMMU components and to bring
the IOMMU infrastructure for ACPI on par with DT, which is going to
make future ARM SMMU components easier to integrate.

PATCH (1) adds a FWNODE_IOMMU type to the struct fwnode_handle type.
          It is required to attach a fwnode identifier to platform
          devices allocated/detected through IORT tables entries;
          IOMMU devices have to have an identifier to look them up
          eg IOMMU core layer carrying out id translation. This can be
          done through a fwnode_handle (ie IOMMU platform devices created
          out of IORT tables are not ACPI devices hence they can't be
          allocated as such, otherwise they would have a fwnode_handle of
          type FWNODE_ACPI). This patch requires discussion and it is key
          to the RFC.

PATCH (2) makes use of the ACPI early probing API to add a linker script
          section for probing devices via IORT ACPI kernel code.

PATCH (3) provides IORT support for registering IOMMU IORT node through
          their fwnode handle.

PATCH (4) implements core code fwnode based platform devices look-up.

PATCH (5) extends iommu_fwspec so that it can be used on ACPI based
          system by creating a generic IOMMU fwspec kernel layer.

PATCH (6) implements the of_dma_configure() API in ACPI world -
          acpi_dma_configure() - and patches PCI and ACPI core code to
          start making use of it.

PATCH (7) provides an IORT function to detect existence of specific type
          of IORT components.

PATCH (8) creates the kernel infrastructure required to create ARM SMMU
          platform devices for IORT nodes.

PATCH (9) refactors the ARM SMMU v3 driver so that the init functions are
          split in a way that groups together code that probes through DT
          and code that carries out HW registers FW agnostic probing, in
          preparation for adding the ACPI probing path.

PATCH (10) rework ARM SMMU v3 platform driver registration to make it work
           on ACPI systems.

PATCH (11) Building on patch (8), it adds ARM SMMU v3 IORT IOMMU
           operations to create and probe ARM SMMU v3 components.

PATCH (12) Extend the IORT iort_node_map_rid() to work on a type mask
           instead of a single type so that the translation API can
           be used on a range of components.

PATCH (13) provides IORT infrastructure to carry out IOMMU configuration
           for devices and hook it up to the previously introduced ACPI
           DMA configure API.

This patchset is built on top and depends on these three patch series:

[1] R.Murphy "Generic DT bindings for PCI and ARM SMMU v3" v4
    https://marc.info/?l=devicetree&m=146739193215518&w=2

[2] T.Nowicki "Introduce ACPI world to ITS irqchip" v7
    https://marc.info/?l=linux-arm-kernel&m=146642080022289&w=2

[3] T.Nowicki "Support for ARM64 ACPI based PCI host controller" v8
    http://marc.info/?l=linux-acpi&m=146462129816292&w=2

and is provided for early review/testing purposes here:

git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git acpi/iort-smmu-v3

Tested on FVP models for ARM SMMU v3 probing path.

Lorenzo Pieralisi (13):
  drivers: iommu: add FWNODE_IOMMU fwnode type
  drivers: acpi: iort: introduce linker section for IORT entries probing
  drivers: acpi: iort: add support for IOMMU fwnode registration
  drivers: platform: add fwnode base platform devices retrieval
  drivers: iommu: make iommu_fwspec OF agnostic
  drivers: acpi: implement acpi_dma_configure
  drivers: acpi: iort: add node match function
  drivers: acpi: iort: add support for ARM SMMU platform devices
    creation
  drivers: iommu: arm-smmu-v3: split probe functions into DT/generic
    portions
  drivers: iommu: arm-smmu-v3: enable ACPI driver initialization
  drivers: iommu: arm-smmu-v3: add IORT platform device creation
  drivers: acpi: iort: replace rid map type with type mask
  drivers: acpi: iort: introduce iort_iommu_configure

 drivers/acpi/glue.c               |   4 +-
 drivers/acpi/iort.c               | 360 +++++++++++++++++++++++++++++++++++++-
 drivers/acpi/scan.c               |  29 +++
 drivers/base/platform.c           |  23 +++
 drivers/iommu/Kconfig             |   4 +
 drivers/iommu/Makefile            |   1 +
 drivers/iommu/arm-smmu-v3.c       | 147 ++++++++++++++--
 drivers/iommu/iommu-fwspec.c      | 114 ++++++++++++
 drivers/iommu/of_iommu.c          |  52 ------
 drivers/pci/probe.c               |   3 +-
 include/acpi/acpi_bus.h           |   2 +
 include/asm-generic/vmlinux.lds.h |   1 +
 include/linux/acpi.h              |   5 +
 include/linux/fwnode.h            |   1 +
 include/linux/iommu-fwspec.h      |  60 +++++++
 include/linux/iommu.h             |  25 +++
 include/linux/iort.h              |  19 ++
 include/linux/of_iommu.h          |  24 +--
 include/linux/platform_device.h   |   3 +
 19 files changed, 782 insertions(+), 95 deletions(-)
 create mode 100644 drivers/iommu/iommu-fwspec.c
 create mode 100644 include/linux/iommu-fwspec.h

-- 
2.6.4

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

* [RFC PATCH v3 01/13] drivers: iommu: add FWNODE_IOMMU fwnode type
  2016-07-20 11:23 ` Lorenzo Pieralisi
  (?)
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Marc Zyngier,
	Rafael J. Wysocki, Will Deacon,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA, Sinan Kaya,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA, Hanjun Guo, Tomasz Nowicki,
	Jon Masters

On systems booting with a device tree, every struct device is
associated with a struct device_node, that represents its DT
representation. The device node can be used in generic kernel
contexts (eg IRQ translation, IOMMU streamid mapping), to
retrieve the properties associated with the device and carry
out kernel operation accordingly. Owing to the 1:1 relationship
between the device and its device_node, the device_node can also
be used as a look-up token for the device (eg looking up a device
through its device_node), to retrieve the device in kernel paths
where the device_node is available.

On systems booting with ACPI, the same abstraction provided by
the device_node is required to provide look-up functionality.

Therefore, mirroring the approach implemented in the IRQ domain
kernel layer, this patch adds an additional fwnode type FWNODE_IOMMU.

This patch also implements a glue kernel layer that allows to
allocate/free FWNODE_IOMMU fwnode_handle structures and associate
them with IOMMU devices.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
Cc: Joerg Roedel <joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
Cc: "Rafael J. Wysocki" <rjw-LthD3rsA81gm4RdzfppkhA@public.gmane.org>
---
 include/linux/fwnode.h |  1 +
 include/linux/iommu.h  | 25 +++++++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index 8516717..6e10050 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -19,6 +19,7 @@ enum fwnode_type {
 	FWNODE_ACPI_DATA,
 	FWNODE_PDATA,
 	FWNODE_IRQCHIP,
+	FWNODE_IOMMU,
 };
 
 struct fwnode_handle {
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 664683a..298328a 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -38,6 +38,7 @@ struct bus_type;
 struct device;
 struct iommu_domain;
 struct notifier_block;
+struct fwnode_handle;
 
 /* iommu fault flags */
 #define IOMMU_FAULT_READ	0x0
@@ -540,4 +541,28 @@ static inline void iommu_device_unlink(struct device *dev, struct device *link)
 
 #endif /* CONFIG_IOMMU_API */
 
+/* IOMMU fwnode handling */
+static inline bool is_fwnode_iommu(struct fwnode_handle *fwnode)
+{
+	return fwnode && fwnode->type == FWNODE_IOMMU;
+}
+
+static inline struct fwnode_handle *iommu_alloc_fwnode(void)
+{
+	struct fwnode_handle *fwnode;
+
+	fwnode = kzalloc(sizeof(struct fwnode_handle), GFP_KERNEL);
+	fwnode->type = FWNODE_IOMMU;
+
+	return fwnode;
+}
+
+static inline void iommu_free_fwnode(struct fwnode_handle *fwnode)
+{
+	if (WARN_ON(!is_fwnode_iommu(fwnode)))
+		return;
+
+	kfree(fwnode);
+}
+
 #endif /* __LINUX_IOMMU_H */
-- 
2.6.4

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

* [RFC PATCH v3 01/13] drivers: iommu: add FWNODE_IOMMU fwnode type
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu
  Cc: Lorenzo Pieralisi, Joerg Roedel, Rafael J. Wysocki, Will Deacon,
	Marc Zyngier, Robin Murphy, Tomasz Nowicki, Hanjun Guo,
	Jon Masters, Sinan Kaya, linux-acpi, linux-pci, linux-kernel,
	linux-arm-kernel

On systems booting with a device tree, every struct device is
associated with a struct device_node, that represents its DT
representation. The device node can be used in generic kernel
contexts (eg IRQ translation, IOMMU streamid mapping), to
retrieve the properties associated with the device and carry
out kernel operation accordingly. Owing to the 1:1 relationship
between the device and its device_node, the device_node can also
be used as a look-up token for the device (eg looking up a device
through its device_node), to retrieve the device in kernel paths
where the device_node is available.

On systems booting with ACPI, the same abstraction provided by
the device_node is required to provide look-up functionality.

Therefore, mirroring the approach implemented in the IRQ domain
kernel layer, this patch adds an additional fwnode type FWNODE_IOMMU.

This patch also implements a glue kernel layer that allows to
allocate/free FWNODE_IOMMU fwnode_handle structures and associate
them with IOMMU devices.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
 include/linux/fwnode.h |  1 +
 include/linux/iommu.h  | 25 +++++++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index 8516717..6e10050 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -19,6 +19,7 @@ enum fwnode_type {
 	FWNODE_ACPI_DATA,
 	FWNODE_PDATA,
 	FWNODE_IRQCHIP,
+	FWNODE_IOMMU,
 };
 
 struct fwnode_handle {
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 664683a..298328a 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -38,6 +38,7 @@ struct bus_type;
 struct device;
 struct iommu_domain;
 struct notifier_block;
+struct fwnode_handle;
 
 /* iommu fault flags */
 #define IOMMU_FAULT_READ	0x0
@@ -540,4 +541,28 @@ static inline void iommu_device_unlink(struct device *dev, struct device *link)
 
 #endif /* CONFIG_IOMMU_API */
 
+/* IOMMU fwnode handling */
+static inline bool is_fwnode_iommu(struct fwnode_handle *fwnode)
+{
+	return fwnode && fwnode->type == FWNODE_IOMMU;
+}
+
+static inline struct fwnode_handle *iommu_alloc_fwnode(void)
+{
+	struct fwnode_handle *fwnode;
+
+	fwnode = kzalloc(sizeof(struct fwnode_handle), GFP_KERNEL);
+	fwnode->type = FWNODE_IOMMU;
+
+	return fwnode;
+}
+
+static inline void iommu_free_fwnode(struct fwnode_handle *fwnode)
+{
+	if (WARN_ON(!is_fwnode_iommu(fwnode)))
+		return;
+
+	kfree(fwnode);
+}
+
 #endif /* __LINUX_IOMMU_H */
-- 
2.6.4

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

* [RFC PATCH v3 01/13] drivers: iommu: add FWNODE_IOMMU fwnode type
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

On systems booting with a device tree, every struct device is
associated with a struct device_node, that represents its DT
representation. The device node can be used in generic kernel
contexts (eg IRQ translation, IOMMU streamid mapping), to
retrieve the properties associated with the device and carry
out kernel operation accordingly. Owing to the 1:1 relationship
between the device and its device_node, the device_node can also
be used as a look-up token for the device (eg looking up a device
through its device_node), to retrieve the device in kernel paths
where the device_node is available.

On systems booting with ACPI, the same abstraction provided by
the device_node is required to provide look-up functionality.

Therefore, mirroring the approach implemented in the IRQ domain
kernel layer, this patch adds an additional fwnode type FWNODE_IOMMU.

This patch also implements a glue kernel layer that allows to
allocate/free FWNODE_IOMMU fwnode_handle structures and associate
them with IOMMU devices.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
 include/linux/fwnode.h |  1 +
 include/linux/iommu.h  | 25 +++++++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index 8516717..6e10050 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -19,6 +19,7 @@ enum fwnode_type {
 	FWNODE_ACPI_DATA,
 	FWNODE_PDATA,
 	FWNODE_IRQCHIP,
+	FWNODE_IOMMU,
 };
 
 struct fwnode_handle {
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 664683a..298328a 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -38,6 +38,7 @@ struct bus_type;
 struct device;
 struct iommu_domain;
 struct notifier_block;
+struct fwnode_handle;
 
 /* iommu fault flags */
 #define IOMMU_FAULT_READ	0x0
@@ -540,4 +541,28 @@ static inline void iommu_device_unlink(struct device *dev, struct device *link)
 
 #endif /* CONFIG_IOMMU_API */
 
+/* IOMMU fwnode handling */
+static inline bool is_fwnode_iommu(struct fwnode_handle *fwnode)
+{
+	return fwnode && fwnode->type == FWNODE_IOMMU;
+}
+
+static inline struct fwnode_handle *iommu_alloc_fwnode(void)
+{
+	struct fwnode_handle *fwnode;
+
+	fwnode = kzalloc(sizeof(struct fwnode_handle), GFP_KERNEL);
+	fwnode->type = FWNODE_IOMMU;
+
+	return fwnode;
+}
+
+static inline void iommu_free_fwnode(struct fwnode_handle *fwnode)
+{
+	if (WARN_ON(!is_fwnode_iommu(fwnode)))
+		return;
+
+	kfree(fwnode);
+}
+
 #endif /* __LINUX_IOMMU_H */
-- 
2.6.4

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

* [RFC PATCH v3 02/13] drivers: acpi: iort: introduce linker section for IORT entries probing
  2016-07-20 11:23 ` Lorenzo Pieralisi
  (?)
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
  Cc: Marc Zyngier, Tomasz Nowicki, Rafael J. Wysocki,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Will Deacon, Sinan Kaya,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA, Hanjun Guo, Jon Masters,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Since commit e647b532275b ("ACPI: Add early device probing
infrastructure") the kernel has gained the infrastructure that allows
adding linker script section entries to execute ACPI driver callbacks
(ie probe routines) for all subsystems that register a table entry
in the respective kernel section (eg clocksource, irqchip).

Since ARM IOMMU devices data is described through IORT tables when
booting with ACPI, the ARM IOMMU drivers must be made able to hook ACPI
callback routines that are called to probe IORT entries and initialize
the respective IOMMU devices.

To avoid adding driver specific hooks into IORT table initialization
code (breaking therefore code modularity - ie ACPI IORT code must be made
aware of ARM SMMU drivers ACPI init callbacks), this patch adds code
that allows ARM SMMU drivers to take advantage of the ACPI early probing
infrastructure, so that they can add linker script section entries
containing drivers callback to be executed on IORT tables detection.

Since IORT nodes are differentiated by a type, the callback routines
can easily parse the IORT table entries, check the IORT nodes and
carry out some actions whenever the IORT node type associated with
the driver specific callback is matched.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
Cc: Tomasz Nowicki <tn-nYOzD4b6Jr9Wk0Htik3J/w@public.gmane.org>
Cc: "Rafael J. Wysocki" <rjw-LthD3rsA81gm4RdzfppkhA@public.gmane.org>
Cc: Marc Zyngier <marc.zyngier-5wv7dgnIgG8@public.gmane.org>
---
 drivers/acpi/iort.c               | 2 ++
 include/asm-generic/vmlinux.lds.h | 1 +
 include/linux/iort.h              | 3 +++
 3 files changed, 6 insertions(+)

diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
index 6611607..1f440d2 100644
--- a/drivers/acpi/iort.c
+++ b/drivers/acpi/iort.c
@@ -383,4 +383,6 @@ void __init iort_table_detect(void)
 		const char *msg = acpi_format_exception(status);
 		pr_err("Failed to get table, %s\n", msg);
 	}
+
+	acpi_probe_device_table(iort);
 }
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 6a67ab9..b896ab2 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -538,6 +538,7 @@
 	IRQCHIP_OF_MATCH_TABLE()					\
 	ACPI_PROBE_TABLE(irqchip)					\
 	ACPI_PROBE_TABLE(clksrc)					\
+	ACPI_PROBE_TABLE(iort)						\
 	EARLYCON_TABLE()
 
 #define INIT_TEXT							\
diff --git a/include/linux/iort.h b/include/linux/iort.h
index d7daba1..9bb30c5 100644
--- a/include/linux/iort.h
+++ b/include/linux/iort.h
@@ -38,4 +38,7 @@ static inline struct irq_domain *
 iort_get_device_domain(struct device *dev, u32 req_id) { return NULL; }
 #endif
 
+#define IORT_ACPI_DECLARE(name, table_id, fn)		\
+	ACPI_DECLARE_PROBE_ENTRY(iort, name, table_id, 0, NULL, 0, fn)
+
 #endif /* __IORT_H__ */
-- 
2.6.4

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

* [RFC PATCH v3 02/13] drivers: acpi: iort: introduce linker section for IORT entries probing
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu
  Cc: Lorenzo Pieralisi, Tomasz Nowicki, Rafael J. Wysocki,
	Marc Zyngier, Will Deacon, Robin Murphy, Joerg Roedel,
	Hanjun Guo, Jon Masters, Sinan Kaya, linux-acpi, linux-pci,
	linux-kernel, linux-arm-kernel

Since commit e647b532275b ("ACPI: Add early device probing
infrastructure") the kernel has gained the infrastructure that allows
adding linker script section entries to execute ACPI driver callbacks
(ie probe routines) for all subsystems that register a table entry
in the respective kernel section (eg clocksource, irqchip).

Since ARM IOMMU devices data is described through IORT tables when
booting with ACPI, the ARM IOMMU drivers must be made able to hook ACPI
callback routines that are called to probe IORT entries and initialize
the respective IOMMU devices.

To avoid adding driver specific hooks into IORT table initialization
code (breaking therefore code modularity - ie ACPI IORT code must be made
aware of ARM SMMU drivers ACPI init callbacks), this patch adds code
that allows ARM SMMU drivers to take advantage of the ACPI early probing
infrastructure, so that they can add linker script section entries
containing drivers callback to be executed on IORT tables detection.

Since IORT nodes are differentiated by a type, the callback routines
can easily parse the IORT table entries, check the IORT nodes and
carry out some actions whenever the IORT node type associated with
the driver specific callback is matched.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/acpi/iort.c               | 2 ++
 include/asm-generic/vmlinux.lds.h | 1 +
 include/linux/iort.h              | 3 +++
 3 files changed, 6 insertions(+)

diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
index 6611607..1f440d2 100644
--- a/drivers/acpi/iort.c
+++ b/drivers/acpi/iort.c
@@ -383,4 +383,6 @@ void __init iort_table_detect(void)
 		const char *msg = acpi_format_exception(status);
 		pr_err("Failed to get table, %s\n", msg);
 	}
+
+	acpi_probe_device_table(iort);
 }
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 6a67ab9..b896ab2 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -538,6 +538,7 @@
 	IRQCHIP_OF_MATCH_TABLE()					\
 	ACPI_PROBE_TABLE(irqchip)					\
 	ACPI_PROBE_TABLE(clksrc)					\
+	ACPI_PROBE_TABLE(iort)						\
 	EARLYCON_TABLE()
 
 #define INIT_TEXT							\
diff --git a/include/linux/iort.h b/include/linux/iort.h
index d7daba1..9bb30c5 100644
--- a/include/linux/iort.h
+++ b/include/linux/iort.h
@@ -38,4 +38,7 @@ static inline struct irq_domain *
 iort_get_device_domain(struct device *dev, u32 req_id) { return NULL; }
 #endif
 
+#define IORT_ACPI_DECLARE(name, table_id, fn)		\
+	ACPI_DECLARE_PROBE_ENTRY(iort, name, table_id, 0, NULL, 0, fn)
+
 #endif /* __IORT_H__ */
-- 
2.6.4

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

* [RFC PATCH v3 02/13] drivers: acpi: iort: introduce linker section for IORT entries probing
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

Since commit e647b532275b ("ACPI: Add early device probing
infrastructure") the kernel has gained the infrastructure that allows
adding linker script section entries to execute ACPI driver callbacks
(ie probe routines) for all subsystems that register a table entry
in the respective kernel section (eg clocksource, irqchip).

Since ARM IOMMU devices data is described through IORT tables when
booting with ACPI, the ARM IOMMU drivers must be made able to hook ACPI
callback routines that are called to probe IORT entries and initialize
the respective IOMMU devices.

To avoid adding driver specific hooks into IORT table initialization
code (breaking therefore code modularity - ie ACPI IORT code must be made
aware of ARM SMMU drivers ACPI init callbacks), this patch adds code
that allows ARM SMMU drivers to take advantage of the ACPI early probing
infrastructure, so that they can add linker script section entries
containing drivers callback to be executed on IORT tables detection.

Since IORT nodes are differentiated by a type, the callback routines
can easily parse the IORT table entries, check the IORT nodes and
carry out some actions whenever the IORT node type associated with
the driver specific callback is matched.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/acpi/iort.c               | 2 ++
 include/asm-generic/vmlinux.lds.h | 1 +
 include/linux/iort.h              | 3 +++
 3 files changed, 6 insertions(+)

diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
index 6611607..1f440d2 100644
--- a/drivers/acpi/iort.c
+++ b/drivers/acpi/iort.c
@@ -383,4 +383,6 @@ void __init iort_table_detect(void)
 		const char *msg = acpi_format_exception(status);
 		pr_err("Failed to get table, %s\n", msg);
 	}
+
+	acpi_probe_device_table(iort);
 }
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 6a67ab9..b896ab2 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -538,6 +538,7 @@
 	IRQCHIP_OF_MATCH_TABLE()					\
 	ACPI_PROBE_TABLE(irqchip)					\
 	ACPI_PROBE_TABLE(clksrc)					\
+	ACPI_PROBE_TABLE(iort)						\
 	EARLYCON_TABLE()
 
 #define INIT_TEXT							\
diff --git a/include/linux/iort.h b/include/linux/iort.h
index d7daba1..9bb30c5 100644
--- a/include/linux/iort.h
+++ b/include/linux/iort.h
@@ -38,4 +38,7 @@ static inline struct irq_domain *
 iort_get_device_domain(struct device *dev, u32 req_id) { return NULL; }
 #endif
 
+#define IORT_ACPI_DECLARE(name, table_id, fn)		\
+	ACPI_DECLARE_PROBE_ENTRY(iort, name, table_id, 0, NULL, 0, fn)
+
 #endif /* __IORT_H__ */
-- 
2.6.4

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

* [RFC PATCH v3 03/13] drivers: acpi: iort: add support for IOMMU fwnode registration
  2016-07-20 11:23 ` Lorenzo Pieralisi
@ 2016-07-20 11:23   ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu
  Cc: Lorenzo Pieralisi, Hanjun Guo, Tomasz Nowicki, Rafael J. Wysocki,
	Will Deacon, Marc Zyngier, Robin Murphy, Joerg Roedel,
	Jon Masters, Sinan Kaya, linux-acpi, linux-pci, linux-kernel,
	linux-arm-kernel

The ACPI IORT table provide entries for IOMMU (aka SMMU in ARM world)
components that allow creating the kernel data structures required to
probe and initialize the IOMMU devices.

This patch provides support in the IORT kernel code to register IOMMU
components and their respective fwnode.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
 drivers/acpi/iort.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
index 1f440d2..86f6985 100644
--- a/drivers/acpi/iort.c
+++ b/drivers/acpi/iort.c
@@ -20,7 +20,9 @@
 
 #include <linux/iort.h>
 #include <linux/kernel.h>
+#include <linux/list.h>
 #include <linux/pci.h>
+#include <linux/slab.h>
 
 struct iort_its_msi_chip {
 	struct list_head	list;
@@ -28,6 +30,69 @@ struct iort_its_msi_chip {
 	u32			translation_id;
 };
 
+struct iort_fwnode {
+	struct list_head list;
+	struct acpi_iort_node *iort_node;
+	struct fwnode_handle *fwnode;
+};
+static LIST_HEAD(iort_fwnode_list);
+static DEFINE_SPINLOCK(iort_fwnode_lock);
+
+/**
+ * iort_set_fwnode() - Create iort_fwnode and use it to register
+ *		       iommu data in the iort_fwnode_list
+ *
+ * @node: IORT table node associated with the IOMMU
+ * @fwnode: fwnode associated with the IORT node
+ *
+ * Returns: 0 on success
+ *          -ENOMEM on failure
+ */
+static inline int iort_set_fwnode(struct acpi_iort_node *iort_node,
+				  struct fwnode_handle *fwnode)
+{
+	struct iort_fwnode *np;
+
+	np = kzalloc(sizeof(struct iort_fwnode), GFP_KERNEL);
+
+	if (WARN_ON(!np))
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&np->list);
+	np->iort_node = iort_node;
+	np->fwnode = fwnode;
+
+	spin_lock(&iort_fwnode_lock);
+	list_add_tail(&np->list, &iort_fwnode_list);
+	spin_unlock(&iort_fwnode_lock);
+
+	return 0;
+}
+
+/**
+ * iort_get_fwnode() - Retrieve fwnode associated with an IORT node
+ *
+ * @node: IORT table node to be looked-up
+ *
+ * Returns: fwnode_handle pointer on success NULL on failure
+*/
+static inline struct fwnode_handle *
+iort_get_fwnode(struct acpi_iort_node *node)
+{
+	struct iort_fwnode *curr, *iommu_fwnode = NULL;
+
+	spin_lock(&iort_fwnode_lock);
+	list_for_each_entry(curr, &iort_fwnode_list, list) {
+		if (curr->iort_node == node) {
+			iommu_fwnode = curr;
+			break;
+		}
+	}
+	spin_unlock(&iort_fwnode_lock);
+
+	return iommu_fwnode ? iommu_fwnode->fwnode : NULL;
+}
+
 typedef acpi_status (*iort_find_node_callback)
 	(struct acpi_iort_node *node, void *context);
 
-- 
2.6.4


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

* [RFC PATCH v3 03/13] drivers: acpi: iort: add support for IOMMU fwnode registration
@ 2016-07-20 11:23   ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

The ACPI IORT table provide entries for IOMMU (aka SMMU in ARM world)
components that allow creating the kernel data structures required to
probe and initialize the IOMMU devices.

This patch provides support in the IORT kernel code to register IOMMU
components and their respective fwnode.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
 drivers/acpi/iort.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
index 1f440d2..86f6985 100644
--- a/drivers/acpi/iort.c
+++ b/drivers/acpi/iort.c
@@ -20,7 +20,9 @@
 
 #include <linux/iort.h>
 #include <linux/kernel.h>
+#include <linux/list.h>
 #include <linux/pci.h>
+#include <linux/slab.h>
 
 struct iort_its_msi_chip {
 	struct list_head	list;
@@ -28,6 +30,69 @@ struct iort_its_msi_chip {
 	u32			translation_id;
 };
 
+struct iort_fwnode {
+	struct list_head list;
+	struct acpi_iort_node *iort_node;
+	struct fwnode_handle *fwnode;
+};
+static LIST_HEAD(iort_fwnode_list);
+static DEFINE_SPINLOCK(iort_fwnode_lock);
+
+/**
+ * iort_set_fwnode() - Create iort_fwnode and use it to register
+ *		       iommu data in the iort_fwnode_list
+ *
+ * @node: IORT table node associated with the IOMMU
+ * @fwnode: fwnode associated with the IORT node
+ *
+ * Returns: 0 on success
+ *          -ENOMEM on failure
+ */
+static inline int iort_set_fwnode(struct acpi_iort_node *iort_node,
+				  struct fwnode_handle *fwnode)
+{
+	struct iort_fwnode *np;
+
+	np = kzalloc(sizeof(struct iort_fwnode), GFP_KERNEL);
+
+	if (WARN_ON(!np))
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&np->list);
+	np->iort_node = iort_node;
+	np->fwnode = fwnode;
+
+	spin_lock(&iort_fwnode_lock);
+	list_add_tail(&np->list, &iort_fwnode_list);
+	spin_unlock(&iort_fwnode_lock);
+
+	return 0;
+}
+
+/**
+ * iort_get_fwnode() - Retrieve fwnode associated with an IORT node
+ *
+ * @node: IORT table node to be looked-up
+ *
+ * Returns: fwnode_handle pointer on success NULL on failure
+*/
+static inline struct fwnode_handle *
+iort_get_fwnode(struct acpi_iort_node *node)
+{
+	struct iort_fwnode *curr, *iommu_fwnode = NULL;
+
+	spin_lock(&iort_fwnode_lock);
+	list_for_each_entry(curr, &iort_fwnode_list, list) {
+		if (curr->iort_node == node) {
+			iommu_fwnode = curr;
+			break;
+		}
+	}
+	spin_unlock(&iort_fwnode_lock);
+
+	return iommu_fwnode ? iommu_fwnode->fwnode : NULL;
+}
+
 typedef acpi_status (*iort_find_node_callback)
 	(struct acpi_iort_node *node, void *context);
 
-- 
2.6.4

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

* [RFC PATCH v3 04/13] drivers: platform: add fwnode base platform devices retrieval
  2016-07-20 11:23 ` Lorenzo Pieralisi
  (?)
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Marc Zyngier,
	Greg Kroah-Hartman, Rafael J. Wysocki,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Will Deacon, Sinan Kaya,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA, Hanjun Guo, Tomasz Nowicki,
	Jon Masters

The platform device kernel API does not provide functions to
retrieve a platform device through the corresponding struct
device fwnode pointer.

Implement the fwnode platform_device look-up in drivers core
code by using the bus_find_device() API and a corresponding
matching function. The OF equivalent (eg of_find_device_by_node())
will reuse the newly introduced function when OF code will
take care of setting up the device->fwnode value that is
currently left dangling for platform devices instantiated out
of device tree nodes.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
Cc: Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>
Cc: "Rafael J. Wysocki" <rjw-LthD3rsA81gm4RdzfppkhA@public.gmane.org>
---
 drivers/base/platform.c         | 23 +++++++++++++++++++++++
 include/linux/platform_device.h |  3 +++
 2 files changed, 26 insertions(+)

diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 6482d47..3ef150d 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -760,6 +760,29 @@ err_out:
 }
 EXPORT_SYMBOL_GPL(__platform_create_bundle);
 
+static int fwnode_dev_match(struct device *dev, void *data)
+{
+	return dev->fwnode == data;
+}
+
+/**
+ * platform_find_device_by_fwnode() - Find the platform_device associated
+ *				      with a fwnode
+ * @fwnode: Pointer to firmware node
+ *
+ * Returns platform_device pointer, or NULL if not found
+ */
+struct platform_device *
+platform_find_device_by_fwnode(struct fwnode_handle *fwnode)
+{
+	struct device *dev;
+
+	dev = bus_find_device(&platform_bus_type, NULL, fwnode,
+			      fwnode_dev_match);
+	return dev ? to_platform_device(dev) : NULL;
+}
+EXPORT_SYMBOL(platform_find_device_by_fwnode);
+
 /**
  * __platform_register_drivers - register an array of platform drivers
  * @drivers: an array of drivers to register
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 98c2a7c..01a3eb2 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -276,6 +276,9 @@ extern struct platform_device *__platform_create_bundle(
 	struct resource *res, unsigned int n_res,
 	const void *data, size_t size, struct module *module);
 
+extern struct platform_device *
+platform_find_device_by_fwnode(struct fwnode_handle *fwnode);
+
 int __platform_register_drivers(struct platform_driver * const *drivers,
 				unsigned int count, struct module *owner);
 void platform_unregister_drivers(struct platform_driver * const *drivers,
-- 
2.6.4

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

* [RFC PATCH v3 04/13] drivers: platform: add fwnode base platform devices retrieval
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu
  Cc: Lorenzo Pieralisi, Greg Kroah-Hartman, Rafael J. Wysocki,
	Will Deacon, Marc Zyngier, Robin Murphy, Joerg Roedel,
	Tomasz Nowicki, Hanjun Guo, Jon Masters, Sinan Kaya, linux-acpi,
	linux-pci, linux-kernel, linux-arm-kernel

The platform device kernel API does not provide functions to
retrieve a platform device through the corresponding struct
device fwnode pointer.

Implement the fwnode platform_device look-up in drivers core
code by using the bus_find_device() API and a corresponding
matching function. The OF equivalent (eg of_find_device_by_node())
will reuse the newly introduced function when OF code will
take care of setting up the device->fwnode value that is
currently left dangling for platform devices instantiated out
of device tree nodes.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
 drivers/base/platform.c         | 23 +++++++++++++++++++++++
 include/linux/platform_device.h |  3 +++
 2 files changed, 26 insertions(+)

diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 6482d47..3ef150d 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -760,6 +760,29 @@ err_out:
 }
 EXPORT_SYMBOL_GPL(__platform_create_bundle);
 
+static int fwnode_dev_match(struct device *dev, void *data)
+{
+	return dev->fwnode == data;
+}
+
+/**
+ * platform_find_device_by_fwnode() - Find the platform_device associated
+ *				      with a fwnode
+ * @fwnode: Pointer to firmware node
+ *
+ * Returns platform_device pointer, or NULL if not found
+ */
+struct platform_device *
+platform_find_device_by_fwnode(struct fwnode_handle *fwnode)
+{
+	struct device *dev;
+
+	dev = bus_find_device(&platform_bus_type, NULL, fwnode,
+			      fwnode_dev_match);
+	return dev ? to_platform_device(dev) : NULL;
+}
+EXPORT_SYMBOL(platform_find_device_by_fwnode);
+
 /**
  * __platform_register_drivers - register an array of platform drivers
  * @drivers: an array of drivers to register
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 98c2a7c..01a3eb2 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -276,6 +276,9 @@ extern struct platform_device *__platform_create_bundle(
 	struct resource *res, unsigned int n_res,
 	const void *data, size_t size, struct module *module);
 
+extern struct platform_device *
+platform_find_device_by_fwnode(struct fwnode_handle *fwnode);
+
 int __platform_register_drivers(struct platform_driver * const *drivers,
 				unsigned int count, struct module *owner);
 void platform_unregister_drivers(struct platform_driver * const *drivers,
-- 
2.6.4

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

* [RFC PATCH v3 04/13] drivers: platform: add fwnode base platform devices retrieval
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

The platform device kernel API does not provide functions to
retrieve a platform device through the corresponding struct
device fwnode pointer.

Implement the fwnode platform_device look-up in drivers core
code by using the bus_find_device() API and a corresponding
matching function. The OF equivalent (eg of_find_device_by_node())
will reuse the newly introduced function when OF code will
take care of setting up the device->fwnode value that is
currently left dangling for platform devices instantiated out
of device tree nodes.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
 drivers/base/platform.c         | 23 +++++++++++++++++++++++
 include/linux/platform_device.h |  3 +++
 2 files changed, 26 insertions(+)

diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 6482d47..3ef150d 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -760,6 +760,29 @@ err_out:
 }
 EXPORT_SYMBOL_GPL(__platform_create_bundle);
 
+static int fwnode_dev_match(struct device *dev, void *data)
+{
+	return dev->fwnode == data;
+}
+
+/**
+ * platform_find_device_by_fwnode() - Find the platform_device associated
+ *				      with a fwnode
+ * @fwnode: Pointer to firmware node
+ *
+ * Returns platform_device pointer, or NULL if not found
+ */
+struct platform_device *
+platform_find_device_by_fwnode(struct fwnode_handle *fwnode)
+{
+	struct device *dev;
+
+	dev = bus_find_device(&platform_bus_type, NULL, fwnode,
+			      fwnode_dev_match);
+	return dev ? to_platform_device(dev) : NULL;
+}
+EXPORT_SYMBOL(platform_find_device_by_fwnode);
+
 /**
  * __platform_register_drivers - register an array of platform drivers
  * @drivers: an array of drivers to register
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 98c2a7c..01a3eb2 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -276,6 +276,9 @@ extern struct platform_device *__platform_create_bundle(
 	struct resource *res, unsigned int n_res,
 	const void *data, size_t size, struct module *module);
 
+extern struct platform_device *
+platform_find_device_by_fwnode(struct fwnode_handle *fwnode);
+
 int __platform_register_drivers(struct platform_driver * const *drivers,
 				unsigned int count, struct module *owner);
 void platform_unregister_drivers(struct platform_driver * const *drivers,
-- 
2.6.4

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

* [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
  2016-07-20 11:23 ` Lorenzo Pieralisi
  (?)
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Marc Zyngier,
	Rafael J. Wysocki, Will Deacon,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA, Sinan Kaya,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA, Hanjun Guo, Tomasz Nowicki,
	Jon Masters

The iommu_fwspec structure, used to hold per device iommu configuration
data is not OF specific and therefore can be moved to a generic
and OF independent compilation unit.

In particular, the iommu_fwspec handling hinges on the device_node
pointer to identify the IOMMU device associated with the iommu_fwspec
structure, that is easily converted to a more generic fwnode_handle
pointer that can cater for OF and non-OF (ie ACPI) systems.

Create the files and related Kconfig entry to decouple iommu_fwspec
structure from the OF iommu kernel layer.

Given that the current iommu_fwspec implementation relies on
the arch specific struct device.archdata.iommu field in its
implementation, by making the code standalone and independent
of the OF layer this patch makes sure that the iommu_fwspec
kernel code can be selected only on arches implementing the
struct device.archdata.iommu field by adding an explicit
arch dependency in its config entry.

Current drivers using the iommu_fwspec for streamid translation
are converted to the new iommu_fwspec API by simply converting
the device_node to its fwnode_handle pointer.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
Cc: Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org>
Cc: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: Robin Murphy <robin.murphy-5wv7dgnIgG8@public.gmane.org>
Cc: Joerg Roedel <joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
---
 drivers/iommu/Kconfig        |   4 ++
 drivers/iommu/Makefile       |   1 +
 drivers/iommu/arm-smmu-v3.c  |  13 +++--
 drivers/iommu/iommu-fwspec.c | 114 +++++++++++++++++++++++++++++++++++++++++++
 drivers/iommu/of_iommu.c     |  52 --------------------
 include/linux/iommu-fwspec.h |  60 +++++++++++++++++++++++
 include/linux/of_iommu.h     |  24 +++------
 7 files changed, 196 insertions(+), 72 deletions(-)
 create mode 100644 drivers/iommu/iommu-fwspec.c
 create mode 100644 include/linux/iommu-fwspec.h

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index d1c66af..2b26bfb 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -67,6 +67,10 @@ config OF_IOMMU
        def_bool y
        depends on OF && IOMMU_API
 
+config IOMMU_FWSPEC
+       def_bool y
+       depends on ARM64 && IOMMU_API
+
 # IOMMU-agnostic DMA-mapping layer
 config IOMMU_DMA
 	bool
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index c6edb31..dd85337 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) += io-pgtable-arm-v7s.o
 obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
 obj-$(CONFIG_IOMMU_IOVA) += iova.o
 obj-$(CONFIG_OF_IOMMU)	+= of_iommu.o
+obj-$(CONFIG_IOMMU_FWSPEC) += iommu-fwspec.o
 obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
 obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
 obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 98e6441..052a26c 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -25,6 +25,7 @@
 #include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/iommu.h>
+#include <linux/iommu-fwspec.h>
 #include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/msi.h>
@@ -1739,9 +1740,13 @@ arm_smmu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova)
 	return ret;
 }
 
-static struct arm_smmu_device *arm_smmu_get_by_node(struct device_node *np)
+static struct arm_smmu_device *
+arm_smmu_get_by_fwnode(struct fwnode_handle *handle)
 {
-	struct platform_device *smmu_pdev = of_find_device_by_node(np);
+	struct platform_device *smmu_pdev = NULL;
+
+	if (is_of_node(handle))
+		smmu_pdev = of_find_device_by_node(to_of_node(handle));
 
 	if (!smmu_pdev)
 		return NULL;
@@ -1780,7 +1785,7 @@ static int arm_smmu_add_device(struct device *dev)
 		master = fwspec->iommu_priv;
 		smmu = master->smmu;
 	} else {
-		smmu = arm_smmu_get_by_node(fwspec->iommu_np);
+		smmu = arm_smmu_get_by_fwnode(fwspec->iommu_fwnode);
 		if (!smmu)
 			return -ENODEV;
 		master = kzalloc(sizeof(*master), GFP_KERNEL);
@@ -1892,7 +1897,7 @@ out_unlock:
 
 static int arm_smmu_of_xlate(struct device *dev, struct of_phandle_args *args)
 {
-	int ret = iommu_fwspec_init(dev, args->np);
+	int ret = iommu_fwspec_init(dev, &args->np->fwnode);
 
 	if (!ret)
 		ret = iommu_fwspec_add_ids(dev, &args->args[0], 1);
diff --git a/drivers/iommu/iommu-fwspec.c b/drivers/iommu/iommu-fwspec.c
new file mode 100644
index 0000000..0600c17
--- /dev/null
+++ b/drivers/iommu/iommu-fwspec.c
@@ -0,0 +1,114 @@
+/*
+ * Firmware handling helpers for IOMMU
+ *
+ * Copyright (c) 2016 ARM Ltd.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/iommu.h>
+#include <linux/iommu-fwspec.h>
+#include <linux/of_iommu.h>
+#include <linux/slab.h>
+
+struct fwspec_iommu_node {
+	struct list_head list;
+	struct fwnode_handle *fwnode;
+	const struct iommu_ops *ops;
+};
+static LIST_HEAD(fwnode_iommu_list);
+static DEFINE_SPINLOCK(fwspec_iommu_lock);
+
+void fwspec_iommu_set_ops(struct fwnode_handle *fwnode,
+			  const struct iommu_ops *ops)
+{
+	struct fwspec_iommu_node *iommu =
+				kzalloc(sizeof(*iommu), GFP_KERNEL);
+
+	if (WARN_ON(!iommu))
+		return;
+
+	INIT_LIST_HEAD(&iommu->list);
+	iommu->fwnode = fwnode;
+	iommu->ops = ops;
+	spin_lock(&fwspec_iommu_lock);
+	list_add_tail(&iommu->list, &fwnode_iommu_list);
+	spin_unlock(&fwspec_iommu_lock);
+}
+
+const struct iommu_ops *fwspec_iommu_get_ops(struct fwnode_handle *fwnode)
+{
+	struct fwspec_iommu_node *node;
+	const struct iommu_ops *ops = NULL;
+
+	spin_lock(&fwspec_iommu_lock);
+	list_for_each_entry(node, &fwnode_iommu_list, list)
+		if (node->fwnode == fwnode) {
+			ops = node->ops;
+			break;
+		}
+	spin_unlock(&fwspec_iommu_lock);
+	return ops;
+}
+
+int iommu_fwspec_init(struct device *dev,
+		      struct fwnode_handle *iommu_fwnode)
+{
+	struct iommu_fwspec *fwspec = dev->archdata.iommu;
+	const struct iommu_ops *ops;
+
+	if (fwspec)
+		return 0;
+
+	fwspec = kzalloc(sizeof(*fwspec), GFP_KERNEL);
+	if (!fwspec)
+		return -ENOMEM;
+
+	if (is_of_node(iommu_fwnode))
+		ops = of_iommu_get_ops(to_of_node(iommu_fwnode));
+	else
+		ops = fwspec_iommu_get_ops(iommu_fwnode);
+
+	fwspec->iommu_fwnode = iommu_fwnode;
+	fwspec->iommu_ops = ops;
+
+	dev->archdata.iommu = fwspec;
+	return 0;
+}
+
+void iommu_fwspec_free(struct device *dev)
+{
+	kfree(dev->archdata.iommu);
+}
+
+int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids)
+{
+	struct iommu_fwspec *fwspec = dev->archdata.iommu;
+	size_t size;
+
+	if (!fwspec)
+		return -EINVAL;
+
+	size = offsetof(struct iommu_fwspec, ids[fwspec->num_ids + 1]);
+	fwspec = krealloc(dev->archdata.iommu, size, GFP_KERNEL);
+	if (!fwspec)
+		return -ENOMEM;
+
+	while (num_ids--)
+		fwspec->ids[fwspec->num_ids++] = *ids++;
+
+	dev->archdata.iommu = fwspec;
+	return 0;
+}
+
+inline struct iommu_fwspec *dev_iommu_fwspec(struct device *dev)
+{
+	return dev->archdata.iommu;
+}
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 4618e89..1fe1f62 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -216,55 +216,3 @@ void __init of_iommu_init(void)
 				of_node_full_name(np));
 	}
 }
-
-int iommu_fwspec_init(struct device *dev, struct device_node *iommu_np)
-{
-	struct iommu_fwspec *fwspec = dev->archdata.iommu;
-
-	if (fwspec)
-		return 0;
-
-	fwspec = kzalloc(sizeof(*fwspec), GFP_KERNEL);
-	if (!fwspec)
-		return -ENOMEM;
-
-	fwspec->iommu_np = of_node_get(iommu_np);
-	fwspec->iommu_ops = of_iommu_get_ops(iommu_np);
-	dev->archdata.iommu = fwspec;
-	return 0;
-}
-
-void iommu_fwspec_free(struct device *dev)
-{
-	struct iommu_fwspec *fwspec = dev->archdata.iommu;
-
-	if (fwspec) {
-		of_node_put(fwspec->iommu_np);
-		kfree(fwspec);
-	}
-}
-
-int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids)
-{
-	struct iommu_fwspec *fwspec = dev->archdata.iommu;
-	size_t size;
-
-	if (!fwspec)
-		return -EINVAL;
-
-	size = offsetof(struct iommu_fwspec, ids[fwspec->num_ids + 1]);
-	fwspec = krealloc(dev->archdata.iommu, size, GFP_KERNEL);
-	if (!fwspec)
-		return -ENOMEM;
-
-	while (num_ids--)
-		fwspec->ids[fwspec->num_ids++] = *ids++;
-
-	dev->archdata.iommu = fwspec;
-	return 0;
-}
-
-inline struct iommu_fwspec *dev_iommu_fwspec(struct device *dev)
-{
-	return dev->archdata.iommu;
-}
diff --git a/include/linux/iommu-fwspec.h b/include/linux/iommu-fwspec.h
new file mode 100644
index 0000000..3a572c6
--- /dev/null
+++ b/include/linux/iommu-fwspec.h
@@ -0,0 +1,60 @@
+#ifndef __IOMMU_FWSPEC_H
+#define __IOMMU_FWSPEC_H
+
+#include <linux/device.h>
+#include <linux/iommu.h>
+
+struct iommu_fwspec {
+	const struct iommu_ops	*iommu_ops;
+	struct fwnode_handle	*iommu_fwnode;
+	void			*iommu_priv;
+	unsigned int		num_ids;
+	u32			ids[];
+};
+
+#ifdef CONFIG_IOMMU_FWSPEC
+int iommu_fwspec_init(struct device *dev,
+		      struct fwnode_handle *iommu_fwnode);
+void iommu_fwspec_free(struct device *dev);
+int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
+struct iommu_fwspec *dev_iommu_fwspec(struct device *dev);
+
+void fwspec_iommu_set_ops(struct fwnode_handle *fwnode,
+			  const struct iommu_ops *ops);
+const struct iommu_ops *fwspec_iommu_get_ops(struct fwnode_handle *fwnode);
+#else /* CONFIG_IOMMU_FWSPEC */
+static inline int iommu_fwspec_init(struct device *dev,
+				    struct fwnode_handle *iommu_fwnode)
+{
+	return -ENODEV;
+}
+
+static inline void iommu_fwspec_free(struct device *dev)
+{
+}
+
+static inline int iommu_fwspec_add_ids(struct device *dev, u32 *ids,
+				       int num_ids)
+{
+	return -ENODEV;
+}
+
+static inline struct iommu_fwspec *dev_iommu_fwspec(struct device *dev)
+{
+	return NULL;
+}
+
+static inline void fwspec_iommu_set_ops(struct fwnode_handle *fwnode,
+					const struct iommu_ops *ops)
+{
+}
+
+static inline const struct iommu_ops *
+fwspec_iommu_get_ops(struct fwnode_handle *fwnode)
+{
+	return NULL;
+}
+
+#endif /* CONFIG_IOMMU_FWSPEC */
+
+#endif /* __IOMMU_FWSPEC_H */
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
index 308791f..2362232 100644
--- a/include/linux/of_iommu.h
+++ b/include/linux/of_iommu.h
@@ -15,13 +15,8 @@ extern void of_iommu_init(void);
 extern const struct iommu_ops *of_iommu_configure(struct device *dev,
 					struct device_node *master_np);
 
-struct iommu_fwspec {
-	const struct iommu_ops	*iommu_ops;
-	struct device_node	*iommu_np;
-	void			*iommu_priv;
-	unsigned int		num_ids;
-	u32			ids[];
-};
+void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
+const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
 
 #else
 
@@ -39,17 +34,14 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
 	return NULL;
 }
 
-struct iommu_fwspec;
-
-#endif	/* CONFIG_OF_IOMMU */
+static inline void of_iommu_set_ops(struct device_node *np,
+				    const struct iommu_ops *ops)
+{ }
 
-int iommu_fwspec_init(struct device *dev, struct device_node *iommu_np);
-void iommu_fwspec_free(struct device *dev);
-int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
-struct iommu_fwspec *dev_iommu_fwspec(struct device *dev);
+static inline const struct iommu_ops *
+of_iommu_get_ops(struct device_node *np) { return NULL; }
 
-void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
-const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
+#endif	/* CONFIG_OF_IOMMU */
 
 extern struct of_device_id __iommu_of_table;
 
-- 
2.6.4

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

* [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu
  Cc: Lorenzo Pieralisi, Will Deacon, Hanjun Guo, Robin Murphy,
	Joerg Roedel, Marc Zyngier, Rafael J. Wysocki, Tomasz Nowicki,
	Jon Masters, Sinan Kaya, linux-acpi, linux-pci, linux-kernel,
	linux-arm-kernel

The iommu_fwspec structure, used to hold per device iommu configuration
data is not OF specific and therefore can be moved to a generic
and OF independent compilation unit.

In particular, the iommu_fwspec handling hinges on the device_node
pointer to identify the IOMMU device associated with the iommu_fwspec
structure, that is easily converted to a more generic fwnode_handle
pointer that can cater for OF and non-OF (ie ACPI) systems.

Create the files and related Kconfig entry to decouple iommu_fwspec
structure from the OF iommu kernel layer.

Given that the current iommu_fwspec implementation relies on
the arch specific struct device.archdata.iommu field in its
implementation, by making the code standalone and independent
of the OF layer this patch makes sure that the iommu_fwspec
kernel code can be selected only on arches implementing the
struct device.archdata.iommu field by adding an explicit
arch dependency in its config entry.

Current drivers using the iommu_fwspec for streamid translation
are converted to the new iommu_fwspec API by simply converting
the device_node to its fwnode_handle pointer.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
---
 drivers/iommu/Kconfig        |   4 ++
 drivers/iommu/Makefile       |   1 +
 drivers/iommu/arm-smmu-v3.c  |  13 +++--
 drivers/iommu/iommu-fwspec.c | 114 +++++++++++++++++++++++++++++++++++++++++++
 drivers/iommu/of_iommu.c     |  52 --------------------
 include/linux/iommu-fwspec.h |  60 +++++++++++++++++++++++
 include/linux/of_iommu.h     |  24 +++------
 7 files changed, 196 insertions(+), 72 deletions(-)
 create mode 100644 drivers/iommu/iommu-fwspec.c
 create mode 100644 include/linux/iommu-fwspec.h

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index d1c66af..2b26bfb 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -67,6 +67,10 @@ config OF_IOMMU
        def_bool y
        depends on OF && IOMMU_API
 
+config IOMMU_FWSPEC
+       def_bool y
+       depends on ARM64 && IOMMU_API
+
 # IOMMU-agnostic DMA-mapping layer
 config IOMMU_DMA
 	bool
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index c6edb31..dd85337 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) += io-pgtable-arm-v7s.o
 obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
 obj-$(CONFIG_IOMMU_IOVA) += iova.o
 obj-$(CONFIG_OF_IOMMU)	+= of_iommu.o
+obj-$(CONFIG_IOMMU_FWSPEC) += iommu-fwspec.o
 obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
 obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
 obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 98e6441..052a26c 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -25,6 +25,7 @@
 #include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/iommu.h>
+#include <linux/iommu-fwspec.h>
 #include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/msi.h>
@@ -1739,9 +1740,13 @@ arm_smmu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova)
 	return ret;
 }
 
-static struct arm_smmu_device *arm_smmu_get_by_node(struct device_node *np)
+static struct arm_smmu_device *
+arm_smmu_get_by_fwnode(struct fwnode_handle *handle)
 {
-	struct platform_device *smmu_pdev = of_find_device_by_node(np);
+	struct platform_device *smmu_pdev = NULL;
+
+	if (is_of_node(handle))
+		smmu_pdev = of_find_device_by_node(to_of_node(handle));
 
 	if (!smmu_pdev)
 		return NULL;
@@ -1780,7 +1785,7 @@ static int arm_smmu_add_device(struct device *dev)
 		master = fwspec->iommu_priv;
 		smmu = master->smmu;
 	} else {
-		smmu = arm_smmu_get_by_node(fwspec->iommu_np);
+		smmu = arm_smmu_get_by_fwnode(fwspec->iommu_fwnode);
 		if (!smmu)
 			return -ENODEV;
 		master = kzalloc(sizeof(*master), GFP_KERNEL);
@@ -1892,7 +1897,7 @@ out_unlock:
 
 static int arm_smmu_of_xlate(struct device *dev, struct of_phandle_args *args)
 {
-	int ret = iommu_fwspec_init(dev, args->np);
+	int ret = iommu_fwspec_init(dev, &args->np->fwnode);
 
 	if (!ret)
 		ret = iommu_fwspec_add_ids(dev, &args->args[0], 1);
diff --git a/drivers/iommu/iommu-fwspec.c b/drivers/iommu/iommu-fwspec.c
new file mode 100644
index 0000000..0600c17
--- /dev/null
+++ b/drivers/iommu/iommu-fwspec.c
@@ -0,0 +1,114 @@
+/*
+ * Firmware handling helpers for IOMMU
+ *
+ * Copyright (c) 2016 ARM Ltd.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/iommu.h>
+#include <linux/iommu-fwspec.h>
+#include <linux/of_iommu.h>
+#include <linux/slab.h>
+
+struct fwspec_iommu_node {
+	struct list_head list;
+	struct fwnode_handle *fwnode;
+	const struct iommu_ops *ops;
+};
+static LIST_HEAD(fwnode_iommu_list);
+static DEFINE_SPINLOCK(fwspec_iommu_lock);
+
+void fwspec_iommu_set_ops(struct fwnode_handle *fwnode,
+			  const struct iommu_ops *ops)
+{
+	struct fwspec_iommu_node *iommu =
+				kzalloc(sizeof(*iommu), GFP_KERNEL);
+
+	if (WARN_ON(!iommu))
+		return;
+
+	INIT_LIST_HEAD(&iommu->list);
+	iommu->fwnode = fwnode;
+	iommu->ops = ops;
+	spin_lock(&fwspec_iommu_lock);
+	list_add_tail(&iommu->list, &fwnode_iommu_list);
+	spin_unlock(&fwspec_iommu_lock);
+}
+
+const struct iommu_ops *fwspec_iommu_get_ops(struct fwnode_handle *fwnode)
+{
+	struct fwspec_iommu_node *node;
+	const struct iommu_ops *ops = NULL;
+
+	spin_lock(&fwspec_iommu_lock);
+	list_for_each_entry(node, &fwnode_iommu_list, list)
+		if (node->fwnode == fwnode) {
+			ops = node->ops;
+			break;
+		}
+	spin_unlock(&fwspec_iommu_lock);
+	return ops;
+}
+
+int iommu_fwspec_init(struct device *dev,
+		      struct fwnode_handle *iommu_fwnode)
+{
+	struct iommu_fwspec *fwspec = dev->archdata.iommu;
+	const struct iommu_ops *ops;
+
+	if (fwspec)
+		return 0;
+
+	fwspec = kzalloc(sizeof(*fwspec), GFP_KERNEL);
+	if (!fwspec)
+		return -ENOMEM;
+
+	if (is_of_node(iommu_fwnode))
+		ops = of_iommu_get_ops(to_of_node(iommu_fwnode));
+	else
+		ops = fwspec_iommu_get_ops(iommu_fwnode);
+
+	fwspec->iommu_fwnode = iommu_fwnode;
+	fwspec->iommu_ops = ops;
+
+	dev->archdata.iommu = fwspec;
+	return 0;
+}
+
+void iommu_fwspec_free(struct device *dev)
+{
+	kfree(dev->archdata.iommu);
+}
+
+int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids)
+{
+	struct iommu_fwspec *fwspec = dev->archdata.iommu;
+	size_t size;
+
+	if (!fwspec)
+		return -EINVAL;
+
+	size = offsetof(struct iommu_fwspec, ids[fwspec->num_ids + 1]);
+	fwspec = krealloc(dev->archdata.iommu, size, GFP_KERNEL);
+	if (!fwspec)
+		return -ENOMEM;
+
+	while (num_ids--)
+		fwspec->ids[fwspec->num_ids++] = *ids++;
+
+	dev->archdata.iommu = fwspec;
+	return 0;
+}
+
+inline struct iommu_fwspec *dev_iommu_fwspec(struct device *dev)
+{
+	return dev->archdata.iommu;
+}
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 4618e89..1fe1f62 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -216,55 +216,3 @@ void __init of_iommu_init(void)
 				of_node_full_name(np));
 	}
 }
-
-int iommu_fwspec_init(struct device *dev, struct device_node *iommu_np)
-{
-	struct iommu_fwspec *fwspec = dev->archdata.iommu;
-
-	if (fwspec)
-		return 0;
-
-	fwspec = kzalloc(sizeof(*fwspec), GFP_KERNEL);
-	if (!fwspec)
-		return -ENOMEM;
-
-	fwspec->iommu_np = of_node_get(iommu_np);
-	fwspec->iommu_ops = of_iommu_get_ops(iommu_np);
-	dev->archdata.iommu = fwspec;
-	return 0;
-}
-
-void iommu_fwspec_free(struct device *dev)
-{
-	struct iommu_fwspec *fwspec = dev->archdata.iommu;
-
-	if (fwspec) {
-		of_node_put(fwspec->iommu_np);
-		kfree(fwspec);
-	}
-}
-
-int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids)
-{
-	struct iommu_fwspec *fwspec = dev->archdata.iommu;
-	size_t size;
-
-	if (!fwspec)
-		return -EINVAL;
-
-	size = offsetof(struct iommu_fwspec, ids[fwspec->num_ids + 1]);
-	fwspec = krealloc(dev->archdata.iommu, size, GFP_KERNEL);
-	if (!fwspec)
-		return -ENOMEM;
-
-	while (num_ids--)
-		fwspec->ids[fwspec->num_ids++] = *ids++;
-
-	dev->archdata.iommu = fwspec;
-	return 0;
-}
-
-inline struct iommu_fwspec *dev_iommu_fwspec(struct device *dev)
-{
-	return dev->archdata.iommu;
-}
diff --git a/include/linux/iommu-fwspec.h b/include/linux/iommu-fwspec.h
new file mode 100644
index 0000000..3a572c6
--- /dev/null
+++ b/include/linux/iommu-fwspec.h
@@ -0,0 +1,60 @@
+#ifndef __IOMMU_FWSPEC_H
+#define __IOMMU_FWSPEC_H
+
+#include <linux/device.h>
+#include <linux/iommu.h>
+
+struct iommu_fwspec {
+	const struct iommu_ops	*iommu_ops;
+	struct fwnode_handle	*iommu_fwnode;
+	void			*iommu_priv;
+	unsigned int		num_ids;
+	u32			ids[];
+};
+
+#ifdef CONFIG_IOMMU_FWSPEC
+int iommu_fwspec_init(struct device *dev,
+		      struct fwnode_handle *iommu_fwnode);
+void iommu_fwspec_free(struct device *dev);
+int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
+struct iommu_fwspec *dev_iommu_fwspec(struct device *dev);
+
+void fwspec_iommu_set_ops(struct fwnode_handle *fwnode,
+			  const struct iommu_ops *ops);
+const struct iommu_ops *fwspec_iommu_get_ops(struct fwnode_handle *fwnode);
+#else /* CONFIG_IOMMU_FWSPEC */
+static inline int iommu_fwspec_init(struct device *dev,
+				    struct fwnode_handle *iommu_fwnode)
+{
+	return -ENODEV;
+}
+
+static inline void iommu_fwspec_free(struct device *dev)
+{
+}
+
+static inline int iommu_fwspec_add_ids(struct device *dev, u32 *ids,
+				       int num_ids)
+{
+	return -ENODEV;
+}
+
+static inline struct iommu_fwspec *dev_iommu_fwspec(struct device *dev)
+{
+	return NULL;
+}
+
+static inline void fwspec_iommu_set_ops(struct fwnode_handle *fwnode,
+					const struct iommu_ops *ops)
+{
+}
+
+static inline const struct iommu_ops *
+fwspec_iommu_get_ops(struct fwnode_handle *fwnode)
+{
+	return NULL;
+}
+
+#endif /* CONFIG_IOMMU_FWSPEC */
+
+#endif /* __IOMMU_FWSPEC_H */
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
index 308791f..2362232 100644
--- a/include/linux/of_iommu.h
+++ b/include/linux/of_iommu.h
@@ -15,13 +15,8 @@ extern void of_iommu_init(void);
 extern const struct iommu_ops *of_iommu_configure(struct device *dev,
 					struct device_node *master_np);
 
-struct iommu_fwspec {
-	const struct iommu_ops	*iommu_ops;
-	struct device_node	*iommu_np;
-	void			*iommu_priv;
-	unsigned int		num_ids;
-	u32			ids[];
-};
+void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
+const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
 
 #else
 
@@ -39,17 +34,14 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
 	return NULL;
 }
 
-struct iommu_fwspec;
-
-#endif	/* CONFIG_OF_IOMMU */
+static inline void of_iommu_set_ops(struct device_node *np,
+				    const struct iommu_ops *ops)
+{ }
 
-int iommu_fwspec_init(struct device *dev, struct device_node *iommu_np);
-void iommu_fwspec_free(struct device *dev);
-int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
-struct iommu_fwspec *dev_iommu_fwspec(struct device *dev);
+static inline const struct iommu_ops *
+of_iommu_get_ops(struct device_node *np) { return NULL; }
 
-void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
-const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
+#endif	/* CONFIG_OF_IOMMU */
 
 extern struct of_device_id __iommu_of_table;
 
-- 
2.6.4

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

* [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

The iommu_fwspec structure, used to hold per device iommu configuration
data is not OF specific and therefore can be moved to a generic
and OF independent compilation unit.

In particular, the iommu_fwspec handling hinges on the device_node
pointer to identify the IOMMU device associated with the iommu_fwspec
structure, that is easily converted to a more generic fwnode_handle
pointer that can cater for OF and non-OF (ie ACPI) systems.

Create the files and related Kconfig entry to decouple iommu_fwspec
structure from the OF iommu kernel layer.

Given that the current iommu_fwspec implementation relies on
the arch specific struct device.archdata.iommu field in its
implementation, by making the code standalone and independent
of the OF layer this patch makes sure that the iommu_fwspec
kernel code can be selected only on arches implementing the
struct device.archdata.iommu field by adding an explicit
arch dependency in its config entry.

Current drivers using the iommu_fwspec for streamid translation
are converted to the new iommu_fwspec API by simply converting
the device_node to its fwnode_handle pointer.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
---
 drivers/iommu/Kconfig        |   4 ++
 drivers/iommu/Makefile       |   1 +
 drivers/iommu/arm-smmu-v3.c  |  13 +++--
 drivers/iommu/iommu-fwspec.c | 114 +++++++++++++++++++++++++++++++++++++++++++
 drivers/iommu/of_iommu.c     |  52 --------------------
 include/linux/iommu-fwspec.h |  60 +++++++++++++++++++++++
 include/linux/of_iommu.h     |  24 +++------
 7 files changed, 196 insertions(+), 72 deletions(-)
 create mode 100644 drivers/iommu/iommu-fwspec.c
 create mode 100644 include/linux/iommu-fwspec.h

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index d1c66af..2b26bfb 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -67,6 +67,10 @@ config OF_IOMMU
        def_bool y
        depends on OF && IOMMU_API
 
+config IOMMU_FWSPEC
+       def_bool y
+       depends on ARM64 && IOMMU_API
+
 # IOMMU-agnostic DMA-mapping layer
 config IOMMU_DMA
 	bool
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index c6edb31..dd85337 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) += io-pgtable-arm-v7s.o
 obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
 obj-$(CONFIG_IOMMU_IOVA) += iova.o
 obj-$(CONFIG_OF_IOMMU)	+= of_iommu.o
+obj-$(CONFIG_IOMMU_FWSPEC) += iommu-fwspec.o
 obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
 obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
 obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 98e6441..052a26c 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -25,6 +25,7 @@
 #include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/iommu.h>
+#include <linux/iommu-fwspec.h>
 #include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/msi.h>
@@ -1739,9 +1740,13 @@ arm_smmu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova)
 	return ret;
 }
 
-static struct arm_smmu_device *arm_smmu_get_by_node(struct device_node *np)
+static struct arm_smmu_device *
+arm_smmu_get_by_fwnode(struct fwnode_handle *handle)
 {
-	struct platform_device *smmu_pdev = of_find_device_by_node(np);
+	struct platform_device *smmu_pdev = NULL;
+
+	if (is_of_node(handle))
+		smmu_pdev = of_find_device_by_node(to_of_node(handle));
 
 	if (!smmu_pdev)
 		return NULL;
@@ -1780,7 +1785,7 @@ static int arm_smmu_add_device(struct device *dev)
 		master = fwspec->iommu_priv;
 		smmu = master->smmu;
 	} else {
-		smmu = arm_smmu_get_by_node(fwspec->iommu_np);
+		smmu = arm_smmu_get_by_fwnode(fwspec->iommu_fwnode);
 		if (!smmu)
 			return -ENODEV;
 		master = kzalloc(sizeof(*master), GFP_KERNEL);
@@ -1892,7 +1897,7 @@ out_unlock:
 
 static int arm_smmu_of_xlate(struct device *dev, struct of_phandle_args *args)
 {
-	int ret = iommu_fwspec_init(dev, args->np);
+	int ret = iommu_fwspec_init(dev, &args->np->fwnode);
 
 	if (!ret)
 		ret = iommu_fwspec_add_ids(dev, &args->args[0], 1);
diff --git a/drivers/iommu/iommu-fwspec.c b/drivers/iommu/iommu-fwspec.c
new file mode 100644
index 0000000..0600c17
--- /dev/null
+++ b/drivers/iommu/iommu-fwspec.c
@@ -0,0 +1,114 @@
+/*
+ * Firmware handling helpers for IOMMU
+ *
+ * Copyright (c) 2016 ARM Ltd.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/iommu.h>
+#include <linux/iommu-fwspec.h>
+#include <linux/of_iommu.h>
+#include <linux/slab.h>
+
+struct fwspec_iommu_node {
+	struct list_head list;
+	struct fwnode_handle *fwnode;
+	const struct iommu_ops *ops;
+};
+static LIST_HEAD(fwnode_iommu_list);
+static DEFINE_SPINLOCK(fwspec_iommu_lock);
+
+void fwspec_iommu_set_ops(struct fwnode_handle *fwnode,
+			  const struct iommu_ops *ops)
+{
+	struct fwspec_iommu_node *iommu =
+				kzalloc(sizeof(*iommu), GFP_KERNEL);
+
+	if (WARN_ON(!iommu))
+		return;
+
+	INIT_LIST_HEAD(&iommu->list);
+	iommu->fwnode = fwnode;
+	iommu->ops = ops;
+	spin_lock(&fwspec_iommu_lock);
+	list_add_tail(&iommu->list, &fwnode_iommu_list);
+	spin_unlock(&fwspec_iommu_lock);
+}
+
+const struct iommu_ops *fwspec_iommu_get_ops(struct fwnode_handle *fwnode)
+{
+	struct fwspec_iommu_node *node;
+	const struct iommu_ops *ops = NULL;
+
+	spin_lock(&fwspec_iommu_lock);
+	list_for_each_entry(node, &fwnode_iommu_list, list)
+		if (node->fwnode == fwnode) {
+			ops = node->ops;
+			break;
+		}
+	spin_unlock(&fwspec_iommu_lock);
+	return ops;
+}
+
+int iommu_fwspec_init(struct device *dev,
+		      struct fwnode_handle *iommu_fwnode)
+{
+	struct iommu_fwspec *fwspec = dev->archdata.iommu;
+	const struct iommu_ops *ops;
+
+	if (fwspec)
+		return 0;
+
+	fwspec = kzalloc(sizeof(*fwspec), GFP_KERNEL);
+	if (!fwspec)
+		return -ENOMEM;
+
+	if (is_of_node(iommu_fwnode))
+		ops = of_iommu_get_ops(to_of_node(iommu_fwnode));
+	else
+		ops = fwspec_iommu_get_ops(iommu_fwnode);
+
+	fwspec->iommu_fwnode = iommu_fwnode;
+	fwspec->iommu_ops = ops;
+
+	dev->archdata.iommu = fwspec;
+	return 0;
+}
+
+void iommu_fwspec_free(struct device *dev)
+{
+	kfree(dev->archdata.iommu);
+}
+
+int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids)
+{
+	struct iommu_fwspec *fwspec = dev->archdata.iommu;
+	size_t size;
+
+	if (!fwspec)
+		return -EINVAL;
+
+	size = offsetof(struct iommu_fwspec, ids[fwspec->num_ids + 1]);
+	fwspec = krealloc(dev->archdata.iommu, size, GFP_KERNEL);
+	if (!fwspec)
+		return -ENOMEM;
+
+	while (num_ids--)
+		fwspec->ids[fwspec->num_ids++] = *ids++;
+
+	dev->archdata.iommu = fwspec;
+	return 0;
+}
+
+inline struct iommu_fwspec *dev_iommu_fwspec(struct device *dev)
+{
+	return dev->archdata.iommu;
+}
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 4618e89..1fe1f62 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -216,55 +216,3 @@ void __init of_iommu_init(void)
 				of_node_full_name(np));
 	}
 }
-
-int iommu_fwspec_init(struct device *dev, struct device_node *iommu_np)
-{
-	struct iommu_fwspec *fwspec = dev->archdata.iommu;
-
-	if (fwspec)
-		return 0;
-
-	fwspec = kzalloc(sizeof(*fwspec), GFP_KERNEL);
-	if (!fwspec)
-		return -ENOMEM;
-
-	fwspec->iommu_np = of_node_get(iommu_np);
-	fwspec->iommu_ops = of_iommu_get_ops(iommu_np);
-	dev->archdata.iommu = fwspec;
-	return 0;
-}
-
-void iommu_fwspec_free(struct device *dev)
-{
-	struct iommu_fwspec *fwspec = dev->archdata.iommu;
-
-	if (fwspec) {
-		of_node_put(fwspec->iommu_np);
-		kfree(fwspec);
-	}
-}
-
-int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids)
-{
-	struct iommu_fwspec *fwspec = dev->archdata.iommu;
-	size_t size;
-
-	if (!fwspec)
-		return -EINVAL;
-
-	size = offsetof(struct iommu_fwspec, ids[fwspec->num_ids + 1]);
-	fwspec = krealloc(dev->archdata.iommu, size, GFP_KERNEL);
-	if (!fwspec)
-		return -ENOMEM;
-
-	while (num_ids--)
-		fwspec->ids[fwspec->num_ids++] = *ids++;
-
-	dev->archdata.iommu = fwspec;
-	return 0;
-}
-
-inline struct iommu_fwspec *dev_iommu_fwspec(struct device *dev)
-{
-	return dev->archdata.iommu;
-}
diff --git a/include/linux/iommu-fwspec.h b/include/linux/iommu-fwspec.h
new file mode 100644
index 0000000..3a572c6
--- /dev/null
+++ b/include/linux/iommu-fwspec.h
@@ -0,0 +1,60 @@
+#ifndef __IOMMU_FWSPEC_H
+#define __IOMMU_FWSPEC_H
+
+#include <linux/device.h>
+#include <linux/iommu.h>
+
+struct iommu_fwspec {
+	const struct iommu_ops	*iommu_ops;
+	struct fwnode_handle	*iommu_fwnode;
+	void			*iommu_priv;
+	unsigned int		num_ids;
+	u32			ids[];
+};
+
+#ifdef CONFIG_IOMMU_FWSPEC
+int iommu_fwspec_init(struct device *dev,
+		      struct fwnode_handle *iommu_fwnode);
+void iommu_fwspec_free(struct device *dev);
+int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
+struct iommu_fwspec *dev_iommu_fwspec(struct device *dev);
+
+void fwspec_iommu_set_ops(struct fwnode_handle *fwnode,
+			  const struct iommu_ops *ops);
+const struct iommu_ops *fwspec_iommu_get_ops(struct fwnode_handle *fwnode);
+#else /* CONFIG_IOMMU_FWSPEC */
+static inline int iommu_fwspec_init(struct device *dev,
+				    struct fwnode_handle *iommu_fwnode)
+{
+	return -ENODEV;
+}
+
+static inline void iommu_fwspec_free(struct device *dev)
+{
+}
+
+static inline int iommu_fwspec_add_ids(struct device *dev, u32 *ids,
+				       int num_ids)
+{
+	return -ENODEV;
+}
+
+static inline struct iommu_fwspec *dev_iommu_fwspec(struct device *dev)
+{
+	return NULL;
+}
+
+static inline void fwspec_iommu_set_ops(struct fwnode_handle *fwnode,
+					const struct iommu_ops *ops)
+{
+}
+
+static inline const struct iommu_ops *
+fwspec_iommu_get_ops(struct fwnode_handle *fwnode)
+{
+	return NULL;
+}
+
+#endif /* CONFIG_IOMMU_FWSPEC */
+
+#endif /* __IOMMU_FWSPEC_H */
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
index 308791f..2362232 100644
--- a/include/linux/of_iommu.h
+++ b/include/linux/of_iommu.h
@@ -15,13 +15,8 @@ extern void of_iommu_init(void);
 extern const struct iommu_ops *of_iommu_configure(struct device *dev,
 					struct device_node *master_np);
 
-struct iommu_fwspec {
-	const struct iommu_ops	*iommu_ops;
-	struct device_node	*iommu_np;
-	void			*iommu_priv;
-	unsigned int		num_ids;
-	u32			ids[];
-};
+void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
+const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
 
 #else
 
@@ -39,17 +34,14 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
 	return NULL;
 }
 
-struct iommu_fwspec;
-
-#endif	/* CONFIG_OF_IOMMU */
+static inline void of_iommu_set_ops(struct device_node *np,
+				    const struct iommu_ops *ops)
+{ }
 
-int iommu_fwspec_init(struct device *dev, struct device_node *iommu_np);
-void iommu_fwspec_free(struct device *dev);
-int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
-struct iommu_fwspec *dev_iommu_fwspec(struct device *dev);
+static inline const struct iommu_ops *
+of_iommu_get_ops(struct device_node *np) { return NULL; }
 
-void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
-const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
+#endif	/* CONFIG_OF_IOMMU */
 
 extern struct of_device_id __iommu_of_table;
 
-- 
2.6.4

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

* [RFC PATCH v3 06/13] drivers: acpi: implement acpi_dma_configure
  2016-07-20 11:23 ` Lorenzo Pieralisi
@ 2016-07-20 11:23   ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Robin Murphy, Tomasz Nowicki,
	Joerg Roedel, Rafael J. Wysocki, Will Deacon, Marc Zyngier,
	Hanjun Guo, Jon Masters, Sinan Kaya, linux-acpi, linux-pci,
	linux-kernel, linux-arm-kernel

On DT based systems, the of_dma_configure() API implements DMA
configuration for a given device. On ACPI systems an API equivalent to
of_dma_configure() is missing which implies that it is currently not
possible to set-up DMA operations for devices through the ACPI generic
kernel layer.

This patch fills the gap by introducing acpi_dma_configure/deconfigure()
calls that for now are just wrappers around arch_setup_dma_ops() and
arch_teardown_dma_ops() and also updates ACPI and PCI core code to use
the newly introduced acpi_dma_configure/acpi_dma_deconfigure functions.

The DMA range size passed to arch_setup_dma_ops() is sized according
to the device coherent_dma_mask (starting at address 0x0), mirroring the
DT probing path behaviour when a dma-ranges property is not provided
for the device being probed; this changes the current arch_setup_dma_ops()
call parameters in the ACPI probing case, but since arch_setup_dma_ops()
is a NOP on all architectures but ARM/ARM64 this patch does not change
the current kernel behaviour on them.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com> [pci]
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
 drivers/acpi/glue.c     |  4 ++--
 drivers/acpi/scan.c     | 24 ++++++++++++++++++++++++
 drivers/pci/probe.c     |  3 +--
 include/acpi/acpi_bus.h |  2 ++
 include/linux/acpi.h    |  5 +++++
 5 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 5ea5dc2..f8d6564 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -227,8 +227,7 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
 
 	attr = acpi_get_dma_attr(acpi_dev);
 	if (attr != DEV_DMA_NOT_SUPPORTED)
-		arch_setup_dma_ops(dev, 0, 0, NULL,
-				   attr == DEV_DMA_COHERENT);
+		acpi_dma_configure(dev, attr);
 
 	acpi_physnode_link_name(physical_node_name, node_id);
 	retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
@@ -251,6 +250,7 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
 	return 0;
 
  err:
+	acpi_dma_deconfigure(dev);
 	ACPI_COMPANION_SET(dev, NULL);
 	put_device(dev);
 	put_device(&acpi_dev->dev);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 5f28cf7..b4b9064 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1358,6 +1358,30 @@ enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
 		return DEV_DMA_NON_COHERENT;
 }
 
+/**
+ * acpi_dma_configure - Set-up DMA configuration for the device.
+ * @dev: The pointer to the device
+ * @attr: device dma attributes
+ */
+void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
+{
+	/*
+	 * Assume dma valid range starts at 0 and covers the whole
+	 * coherent_dma_mask.
+	 */
+	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, NULL,
+			   attr == DEV_DMA_COHERENT);
+}
+
+/**
+ * acpi_dma_deconfigure - Tear-down DMA configuration for the device.
+ * @dev: The pointer to the device
+ */
+void acpi_dma_deconfigure(struct device *dev)
+{
+	arch_teardown_dma_ops(dev);
+}
+
 static void acpi_init_coherency(struct acpi_device *adev)
 {
 	unsigned long long cca = 0;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 380d46d..7ef3933 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1725,8 +1725,7 @@ static void pci_dma_configure(struct pci_dev *dev)
 		if (attr == DEV_DMA_NOT_SUPPORTED)
 			dev_warn(&dev->dev, "DMA not supported.\n");
 		else
-			arch_setup_dma_ops(&dev->dev, 0, 0, NULL,
-					   attr == DEV_DMA_COHERENT);
+			acpi_dma_configure(&dev->dev, attr);
 	}
 
 	pci_put_host_bridge_device(bridge);
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 788c6c35..8b5039a 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -566,6 +566,8 @@ struct acpi_pci_root {
 
 bool acpi_dma_supported(struct acpi_device *adev);
 enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev);
+void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr);
+void acpi_dma_deconfigure(struct device *dev);
 
 struct acpi_device *acpi_find_child_device(struct acpi_device *parent,
 					   u64 address, bool check_children);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 288fac5..135a452 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -676,6 +676,11 @@ static inline enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
 	return DEV_DMA_NOT_SUPPORTED;
 }
 
+static inline void acpi_dma_configure(struct device *dev,
+				      enum dev_dma_attr attr) { }
+
+static inline void acpi_dma_deconfigure(struct device *dev) { }
+
 #define ACPI_PTR(_ptr)	(NULL)
 
 #endif	/* !CONFIG_ACPI */
-- 
2.6.4

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

* [RFC PATCH v3 06/13] drivers: acpi: implement acpi_dma_configure
@ 2016-07-20 11:23   ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

On DT based systems, the of_dma_configure() API implements DMA
configuration for a given device. On ACPI systems an API equivalent to
of_dma_configure() is missing which implies that it is currently not
possible to set-up DMA operations for devices through the ACPI generic
kernel layer.

This patch fills the gap by introducing acpi_dma_configure/deconfigure()
calls that for now are just wrappers around arch_setup_dma_ops() and
arch_teardown_dma_ops() and also updates ACPI and PCI core code to use
the newly introduced acpi_dma_configure/acpi_dma_deconfigure functions.

The DMA range size passed to arch_setup_dma_ops() is sized according
to the device coherent_dma_mask (starting at address 0x0), mirroring the
DT probing path behaviour when a dma-ranges property is not provided
for the device being probed; this changes the current arch_setup_dma_ops()
call parameters in the ACPI probing case, but since arch_setup_dma_ops()
is a NOP on all architectures but ARM/ARM64 this patch does not change
the current kernel behaviour on them.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com> [pci]
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
 drivers/acpi/glue.c     |  4 ++--
 drivers/acpi/scan.c     | 24 ++++++++++++++++++++++++
 drivers/pci/probe.c     |  3 +--
 include/acpi/acpi_bus.h |  2 ++
 include/linux/acpi.h    |  5 +++++
 5 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 5ea5dc2..f8d6564 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -227,8 +227,7 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
 
 	attr = acpi_get_dma_attr(acpi_dev);
 	if (attr != DEV_DMA_NOT_SUPPORTED)
-		arch_setup_dma_ops(dev, 0, 0, NULL,
-				   attr == DEV_DMA_COHERENT);
+		acpi_dma_configure(dev, attr);
 
 	acpi_physnode_link_name(physical_node_name, node_id);
 	retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
@@ -251,6 +250,7 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
 	return 0;
 
  err:
+	acpi_dma_deconfigure(dev);
 	ACPI_COMPANION_SET(dev, NULL);
 	put_device(dev);
 	put_device(&acpi_dev->dev);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 5f28cf7..b4b9064 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1358,6 +1358,30 @@ enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
 		return DEV_DMA_NON_COHERENT;
 }
 
+/**
+ * acpi_dma_configure - Set-up DMA configuration for the device.
+ * @dev: The pointer to the device
+ * @attr: device dma attributes
+ */
+void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
+{
+	/*
+	 * Assume dma valid range starts at 0 and covers the whole
+	 * coherent_dma_mask.
+	 */
+	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, NULL,
+			   attr == DEV_DMA_COHERENT);
+}
+
+/**
+ * acpi_dma_deconfigure - Tear-down DMA configuration for the device.
+ * @dev: The pointer to the device
+ */
+void acpi_dma_deconfigure(struct device *dev)
+{
+	arch_teardown_dma_ops(dev);
+}
+
 static void acpi_init_coherency(struct acpi_device *adev)
 {
 	unsigned long long cca = 0;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 380d46d..7ef3933 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1725,8 +1725,7 @@ static void pci_dma_configure(struct pci_dev *dev)
 		if (attr == DEV_DMA_NOT_SUPPORTED)
 			dev_warn(&dev->dev, "DMA not supported.\n");
 		else
-			arch_setup_dma_ops(&dev->dev, 0, 0, NULL,
-					   attr == DEV_DMA_COHERENT);
+			acpi_dma_configure(&dev->dev, attr);
 	}
 
 	pci_put_host_bridge_device(bridge);
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 788c6c35..8b5039a 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -566,6 +566,8 @@ struct acpi_pci_root {
 
 bool acpi_dma_supported(struct acpi_device *adev);
 enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev);
+void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr);
+void acpi_dma_deconfigure(struct device *dev);
 
 struct acpi_device *acpi_find_child_device(struct acpi_device *parent,
 					   u64 address, bool check_children);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 288fac5..135a452 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -676,6 +676,11 @@ static inline enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
 	return DEV_DMA_NOT_SUPPORTED;
 }
 
+static inline void acpi_dma_configure(struct device *dev,
+				      enum dev_dma_attr attr) { }
+
+static inline void acpi_dma_deconfigure(struct device *dev) { }
+
 #define ACPI_PTR(_ptr)	(NULL)
 
 #endif	/* !CONFIG_ACPI */
-- 
2.6.4

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

* [RFC PATCH v3 07/13] drivers: acpi: iort: add node match function
  2016-07-20 11:23 ` Lorenzo Pieralisi
  (?)
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
  Cc: Marc Zyngier, Tomasz Nowicki, Rafael J. Wysocki,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Will Deacon, Sinan Kaya,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA, Hanjun Guo, Jon Masters,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Device drivers (eg ARM SMMU) need to know if a specific component
is part of the IORT table, so that kernel data structures are not
initialized at initcalls time if the respective component is not
part of the IORT table.

To this end, this patch adds a trivial function that allows detecting
if a given IORT node type is present or not in the ACPI table, providing
an ACPI IORT equivalent for of_find_matching_node().

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
Cc: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: Tomasz Nowicki <tn-nYOzD4b6Jr9Wk0Htik3J/w@public.gmane.org>
Cc: "Rafael J. Wysocki" <rjw-LthD3rsA81gm4RdzfppkhA@public.gmane.org>
---
 drivers/acpi/iort.c  | 15 +++++++++++++++
 include/linux/iort.h |  2 ++
 2 files changed, 17 insertions(+)

diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
index 86f6985..71516e8 100644
--- a/drivers/acpi/iort.c
+++ b/drivers/acpi/iort.c
@@ -205,6 +205,21 @@ iort_scan_node(enum acpi_iort_node_type type,
 }
 
 static acpi_status
+iort_match_callback(struct acpi_iort_node *node, void *context)
+{
+	return AE_OK;
+}
+
+bool iort_node_match(u8 type)
+{
+	struct acpi_iort_node *node;
+
+	node = iort_scan_node(type, iort_match_callback, NULL);
+
+	return node != NULL;
+}
+
+static acpi_status
 iort_match_node_callback(struct acpi_iort_node *node, void *context)
 {
 	struct device *dev = context;
diff --git a/include/linux/iort.h b/include/linux/iort.h
index 9bb30c5..ac2706a 100644
--- a/include/linux/iort.h
+++ b/include/linux/iort.h
@@ -27,10 +27,12 @@ int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node);
 void iort_deregister_domain_token(int trans_id);
 struct fwnode_handle *iort_find_domain_token(int trans_id);
 #ifdef CONFIG_IORT_TABLE
+bool iort_node_match(u8 type);
 void iort_table_detect(void);
 u32 iort_msi_map_rid(struct device *dev, u32 req_id);
 struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
 #else
+static inline bool iort_node_match(u8 type) { return false; }
 static inline void iort_table_detect(void) { }
 static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
 { return req_id; }
-- 
2.6.4

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

* [RFC PATCH v3 07/13] drivers: acpi: iort: add node match function
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu
  Cc: Lorenzo Pieralisi, Hanjun Guo, Tomasz Nowicki, Rafael J. Wysocki,
	Will Deacon, Marc Zyngier, Robin Murphy, Joerg Roedel,
	Jon Masters, Sinan Kaya, linux-acpi, linux-pci, linux-kernel,
	linux-arm-kernel

Device drivers (eg ARM SMMU) need to know if a specific component
is part of the IORT table, so that kernel data structures are not
initialized at initcalls time if the respective component is not
part of the IORT table.

To this end, this patch adds a trivial function that allows detecting
if a given IORT node type is present or not in the ACPI table, providing
an ACPI IORT equivalent for of_find_matching_node().

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
 drivers/acpi/iort.c  | 15 +++++++++++++++
 include/linux/iort.h |  2 ++
 2 files changed, 17 insertions(+)

diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
index 86f6985..71516e8 100644
--- a/drivers/acpi/iort.c
+++ b/drivers/acpi/iort.c
@@ -205,6 +205,21 @@ iort_scan_node(enum acpi_iort_node_type type,
 }
 
 static acpi_status
+iort_match_callback(struct acpi_iort_node *node, void *context)
+{
+	return AE_OK;
+}
+
+bool iort_node_match(u8 type)
+{
+	struct acpi_iort_node *node;
+
+	node = iort_scan_node(type, iort_match_callback, NULL);
+
+	return node != NULL;
+}
+
+static acpi_status
 iort_match_node_callback(struct acpi_iort_node *node, void *context)
 {
 	struct device *dev = context;
diff --git a/include/linux/iort.h b/include/linux/iort.h
index 9bb30c5..ac2706a 100644
--- a/include/linux/iort.h
+++ b/include/linux/iort.h
@@ -27,10 +27,12 @@ int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node);
 void iort_deregister_domain_token(int trans_id);
 struct fwnode_handle *iort_find_domain_token(int trans_id);
 #ifdef CONFIG_IORT_TABLE
+bool iort_node_match(u8 type);
 void iort_table_detect(void);
 u32 iort_msi_map_rid(struct device *dev, u32 req_id);
 struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
 #else
+static inline bool iort_node_match(u8 type) { return false; }
 static inline void iort_table_detect(void) { }
 static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
 { return req_id; }
-- 
2.6.4

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

* [RFC PATCH v3 07/13] drivers: acpi: iort: add node match function
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

Device drivers (eg ARM SMMU) need to know if a specific component
is part of the IORT table, so that kernel data structures are not
initialized at initcalls time if the respective component is not
part of the IORT table.

To this end, this patch adds a trivial function that allows detecting
if a given IORT node type is present or not in the ACPI table, providing
an ACPI IORT equivalent for of_find_matching_node().

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
 drivers/acpi/iort.c  | 15 +++++++++++++++
 include/linux/iort.h |  2 ++
 2 files changed, 17 insertions(+)

diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
index 86f6985..71516e8 100644
--- a/drivers/acpi/iort.c
+++ b/drivers/acpi/iort.c
@@ -205,6 +205,21 @@ iort_scan_node(enum acpi_iort_node_type type,
 }
 
 static acpi_status
+iort_match_callback(struct acpi_iort_node *node, void *context)
+{
+	return AE_OK;
+}
+
+bool iort_node_match(u8 type)
+{
+	struct acpi_iort_node *node;
+
+	node = iort_scan_node(type, iort_match_callback, NULL);
+
+	return node != NULL;
+}
+
+static acpi_status
 iort_match_node_callback(struct acpi_iort_node *node, void *context)
 {
 	struct device *dev = context;
diff --git a/include/linux/iort.h b/include/linux/iort.h
index 9bb30c5..ac2706a 100644
--- a/include/linux/iort.h
+++ b/include/linux/iort.h
@@ -27,10 +27,12 @@ int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node);
 void iort_deregister_domain_token(int trans_id);
 struct fwnode_handle *iort_find_domain_token(int trans_id);
 #ifdef CONFIG_IORT_TABLE
+bool iort_node_match(u8 type);
 void iort_table_detect(void);
 u32 iort_msi_map_rid(struct device *dev, u32 req_id);
 struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
 #else
+static inline bool iort_node_match(u8 type) { return false; }
 static inline void iort_table_detect(void) { }
 static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
 { return req_id; }
-- 
2.6.4

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

* [RFC PATCH v3 08/13] drivers: acpi: iort: add support for ARM SMMU platform devices creation
  2016-07-20 11:23 ` Lorenzo Pieralisi
  (?)
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
  Cc: Marc Zyngier, Tomasz Nowicki, Rafael J. Wysocki,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Will Deacon, Sinan Kaya,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA, Hanjun Guo, Jon Masters,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

In ARM ACPI systems, IOMMU components are specified through static
IORT table entries. In order to create platform devices for the
corresponding ARM SMMU components, IORT kernel code should be made
able to parse IORT table entries and create platform devices
dynamically.

This patch adds the generic IORT infrastructure required to create
platform devices for ARM SMMUs.

ARM SMMU versions have different resources requirement therefore this
patch also introduces an IORT specific structure (ie iort_iommu_config)
that contains hooks (to be defined when the corresponding ARM SMMU
driver support is added to the kernel) to be used to define the
platform devices names, init the IOMMUs, count their resources and
finally initialize them.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
Cc: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: Tomasz Nowicki <tn-nYOzD4b6Jr9Wk0Htik3J/w@public.gmane.org>
Cc: "Rafael J. Wysocki" <rjw-LthD3rsA81gm4RdzfppkhA@public.gmane.org>
---
 drivers/acpi/iort.c  | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/iort.h |  10 +++++
 2 files changed, 117 insertions(+)

diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
index 71516e8..23c80c7 100644
--- a/drivers/acpi/iort.c
+++ b/drivers/acpi/iort.c
@@ -22,6 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/pci.h>
+#include <linux/platform_device.h>
 #include <linux/slab.h>
 
 struct iort_its_msi_chip {
@@ -454,6 +455,112 @@ iort_get_device_domain(struct device *dev, u32 req_id)
 	return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
 }
 
+struct iort_iommu_config {
+	const char *name;
+	int (*iommu_init)(struct acpi_iort_node *node);
+	bool (*iommu_is_coherent)(struct acpi_iort_node *node);
+	int (*iommu_count_resources)(struct acpi_iort_node *node);
+	void (*iommu_init_resources)(struct resource *res,
+				     struct acpi_iort_node *node);
+};
+
+static inline const struct iort_iommu_config *
+iort_get_iommu_config(struct acpi_iort_node *node)
+{
+	return NULL;
+}
+
+/**
+ * iort_add_smmu_platform_device() - Allocate a platform device for SMMU
+ * @fwnode: Pointer to SMMU firmware node
+ * @node: Pointer to SMMU ACPI IORT node
+ *
+ * Returns: 0 on success, <0 failure
+ */
+int iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
+				  struct acpi_iort_node *node)
+{
+	struct platform_device *pdev;
+	struct resource *r;
+	enum dev_dma_attr attr;
+	int ret, count;
+	const struct iort_iommu_config *ops =
+				iort_get_iommu_config(node);
+
+	if (!ops)
+		return -ENODEV;
+
+	pdev = platform_device_alloc(ops->name, PLATFORM_DEVID_AUTO);
+	if (!pdev)
+		return PTR_ERR(pdev);
+
+	count = ops->iommu_count_resources(node);
+
+	r = kcalloc(count, sizeof(*r), GFP_KERNEL);
+	if (!r) {
+		ret = -ENOMEM;
+		goto dev_put;
+	}
+
+	ops->iommu_init_resources(r, node);
+
+	ret = platform_device_add_resources(pdev, r, count);
+	/*
+	 * Resources are duplicated in platform_device_add_resources,
+	 * free their allocated memory
+	 */
+	kfree(r);
+
+	if (ret)
+		goto dev_put;
+
+	/*
+	 * Add a copy of IORT node pointer to platform_data to
+	 * be used to retrieve IORT data information.
+	 */
+	ret = platform_device_add_data(pdev, &node, sizeof(node));
+	if (ret)
+		goto dev_put;
+
+	pdev->dev.dma_mask = kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
+	if (!pdev->dev.dma_mask) {
+		ret = -ENOMEM;
+		goto dev_put;
+	}
+
+	pdev->dev.fwnode = fwnode;
+
+	/*
+	 * Set default dma mask value for the table walker,
+	 * to be overridden on probing with correct value.
+	 */
+	*pdev->dev.dma_mask = DMA_BIT_MASK(32);
+	pdev->dev.coherent_dma_mask = *pdev->dev.dma_mask;
+
+	attr = ops->iommu_is_coherent(node) ?
+			     DEV_DMA_COHERENT : DEV_DMA_NON_COHERENT;
+
+	/* Configure DMA for the page table walker */
+	acpi_dma_configure(&pdev->dev, attr);
+
+	ret = platform_device_add(pdev);
+	if (ret)
+		goto dma_deconfigure;
+
+	iort_set_fwnode(node, pdev->dev.fwnode);
+
+	return 0;
+
+dma_deconfigure:
+	acpi_dma_deconfigure(&pdev->dev);
+	kfree(pdev->dev.dma_mask);
+
+dev_put:
+	platform_device_put(pdev);
+
+	return ret;
+}
+
 void __init iort_table_detect(void)
 {
 	acpi_status status;
diff --git a/include/linux/iort.h b/include/linux/iort.h
index ac2706a..18e6836 100644
--- a/include/linux/iort.h
+++ b/include/linux/iort.h
@@ -31,6 +31,9 @@ bool iort_node_match(u8 type);
 void iort_table_detect(void);
 u32 iort_msi_map_rid(struct device *dev, u32 req_id);
 struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
+/* IOMMU interface */
+int iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
+				  struct acpi_iort_node *node);
 #else
 static inline bool iort_node_match(u8 type) { return false; }
 static inline void iort_table_detect(void) { }
@@ -38,6 +41,13 @@ static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
 { return req_id; }
 static inline struct irq_domain *
 iort_get_device_domain(struct device *dev, u32 req_id) { return NULL; }
+/* IOMMU interface */
+static inline int
+iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
+			      struct acpi_iort_node *node)
+{
+	return -ENODEV;
+}
 #endif
 
 #define IORT_ACPI_DECLARE(name, table_id, fn)		\
-- 
2.6.4

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

* [RFC PATCH v3 08/13] drivers: acpi: iort: add support for ARM SMMU platform devices creation
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu
  Cc: Lorenzo Pieralisi, Hanjun Guo, Tomasz Nowicki, Rafael J. Wysocki,
	Will Deacon, Marc Zyngier, Robin Murphy, Joerg Roedel,
	Jon Masters, Sinan Kaya, linux-acpi, linux-pci, linux-kernel,
	linux-arm-kernel

In ARM ACPI systems, IOMMU components are specified through static
IORT table entries. In order to create platform devices for the
corresponding ARM SMMU components, IORT kernel code should be made
able to parse IORT table entries and create platform devices
dynamically.

This patch adds the generic IORT infrastructure required to create
platform devices for ARM SMMUs.

ARM SMMU versions have different resources requirement therefore this
patch also introduces an IORT specific structure (ie iort_iommu_config)
that contains hooks (to be defined when the corresponding ARM SMMU
driver support is added to the kernel) to be used to define the
platform devices names, init the IOMMUs, count their resources and
finally initialize them.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
 drivers/acpi/iort.c  | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/iort.h |  10 +++++
 2 files changed, 117 insertions(+)

diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
index 71516e8..23c80c7 100644
--- a/drivers/acpi/iort.c
+++ b/drivers/acpi/iort.c
@@ -22,6 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/pci.h>
+#include <linux/platform_device.h>
 #include <linux/slab.h>
 
 struct iort_its_msi_chip {
@@ -454,6 +455,112 @@ iort_get_device_domain(struct device *dev, u32 req_id)
 	return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
 }
 
+struct iort_iommu_config {
+	const char *name;
+	int (*iommu_init)(struct acpi_iort_node *node);
+	bool (*iommu_is_coherent)(struct acpi_iort_node *node);
+	int (*iommu_count_resources)(struct acpi_iort_node *node);
+	void (*iommu_init_resources)(struct resource *res,
+				     struct acpi_iort_node *node);
+};
+
+static inline const struct iort_iommu_config *
+iort_get_iommu_config(struct acpi_iort_node *node)
+{
+	return NULL;
+}
+
+/**
+ * iort_add_smmu_platform_device() - Allocate a platform device for SMMU
+ * @fwnode: Pointer to SMMU firmware node
+ * @node: Pointer to SMMU ACPI IORT node
+ *
+ * Returns: 0 on success, <0 failure
+ */
+int iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
+				  struct acpi_iort_node *node)
+{
+	struct platform_device *pdev;
+	struct resource *r;
+	enum dev_dma_attr attr;
+	int ret, count;
+	const struct iort_iommu_config *ops =
+				iort_get_iommu_config(node);
+
+	if (!ops)
+		return -ENODEV;
+
+	pdev = platform_device_alloc(ops->name, PLATFORM_DEVID_AUTO);
+	if (!pdev)
+		return PTR_ERR(pdev);
+
+	count = ops->iommu_count_resources(node);
+
+	r = kcalloc(count, sizeof(*r), GFP_KERNEL);
+	if (!r) {
+		ret = -ENOMEM;
+		goto dev_put;
+	}
+
+	ops->iommu_init_resources(r, node);
+
+	ret = platform_device_add_resources(pdev, r, count);
+	/*
+	 * Resources are duplicated in platform_device_add_resources,
+	 * free their allocated memory
+	 */
+	kfree(r);
+
+	if (ret)
+		goto dev_put;
+
+	/*
+	 * Add a copy of IORT node pointer to platform_data to
+	 * be used to retrieve IORT data information.
+	 */
+	ret = platform_device_add_data(pdev, &node, sizeof(node));
+	if (ret)
+		goto dev_put;
+
+	pdev->dev.dma_mask = kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
+	if (!pdev->dev.dma_mask) {
+		ret = -ENOMEM;
+		goto dev_put;
+	}
+
+	pdev->dev.fwnode = fwnode;
+
+	/*
+	 * Set default dma mask value for the table walker,
+	 * to be overridden on probing with correct value.
+	 */
+	*pdev->dev.dma_mask = DMA_BIT_MASK(32);
+	pdev->dev.coherent_dma_mask = *pdev->dev.dma_mask;
+
+	attr = ops->iommu_is_coherent(node) ?
+			     DEV_DMA_COHERENT : DEV_DMA_NON_COHERENT;
+
+	/* Configure DMA for the page table walker */
+	acpi_dma_configure(&pdev->dev, attr);
+
+	ret = platform_device_add(pdev);
+	if (ret)
+		goto dma_deconfigure;
+
+	iort_set_fwnode(node, pdev->dev.fwnode);
+
+	return 0;
+
+dma_deconfigure:
+	acpi_dma_deconfigure(&pdev->dev);
+	kfree(pdev->dev.dma_mask);
+
+dev_put:
+	platform_device_put(pdev);
+
+	return ret;
+}
+
 void __init iort_table_detect(void)
 {
 	acpi_status status;
diff --git a/include/linux/iort.h b/include/linux/iort.h
index ac2706a..18e6836 100644
--- a/include/linux/iort.h
+++ b/include/linux/iort.h
@@ -31,6 +31,9 @@ bool iort_node_match(u8 type);
 void iort_table_detect(void);
 u32 iort_msi_map_rid(struct device *dev, u32 req_id);
 struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
+/* IOMMU interface */
+int iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
+				  struct acpi_iort_node *node);
 #else
 static inline bool iort_node_match(u8 type) { return false; }
 static inline void iort_table_detect(void) { }
@@ -38,6 +41,13 @@ static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
 { return req_id; }
 static inline struct irq_domain *
 iort_get_device_domain(struct device *dev, u32 req_id) { return NULL; }
+/* IOMMU interface */
+static inline int
+iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
+			      struct acpi_iort_node *node)
+{
+	return -ENODEV;
+}
 #endif
 
 #define IORT_ACPI_DECLARE(name, table_id, fn)		\
-- 
2.6.4

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

* [RFC PATCH v3 08/13] drivers: acpi: iort: add support for ARM SMMU platform devices creation
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

In ARM ACPI systems, IOMMU components are specified through static
IORT table entries. In order to create platform devices for the
corresponding ARM SMMU components, IORT kernel code should be made
able to parse IORT table entries and create platform devices
dynamically.

This patch adds the generic IORT infrastructure required to create
platform devices for ARM SMMUs.

ARM SMMU versions have different resources requirement therefore this
patch also introduces an IORT specific structure (ie iort_iommu_config)
that contains hooks (to be defined when the corresponding ARM SMMU
driver support is added to the kernel) to be used to define the
platform devices names, init the IOMMUs, count their resources and
finally initialize them.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
 drivers/acpi/iort.c  | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/iort.h |  10 +++++
 2 files changed, 117 insertions(+)

diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
index 71516e8..23c80c7 100644
--- a/drivers/acpi/iort.c
+++ b/drivers/acpi/iort.c
@@ -22,6 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/pci.h>
+#include <linux/platform_device.h>
 #include <linux/slab.h>
 
 struct iort_its_msi_chip {
@@ -454,6 +455,112 @@ iort_get_device_domain(struct device *dev, u32 req_id)
 	return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
 }
 
+struct iort_iommu_config {
+	const char *name;
+	int (*iommu_init)(struct acpi_iort_node *node);
+	bool (*iommu_is_coherent)(struct acpi_iort_node *node);
+	int (*iommu_count_resources)(struct acpi_iort_node *node);
+	void (*iommu_init_resources)(struct resource *res,
+				     struct acpi_iort_node *node);
+};
+
+static inline const struct iort_iommu_config *
+iort_get_iommu_config(struct acpi_iort_node *node)
+{
+	return NULL;
+}
+
+/**
+ * iort_add_smmu_platform_device() - Allocate a platform device for SMMU
+ * @fwnode: Pointer to SMMU firmware node
+ * @node: Pointer to SMMU ACPI IORT node
+ *
+ * Returns: 0 on success, <0 failure
+ */
+int iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
+				  struct acpi_iort_node *node)
+{
+	struct platform_device *pdev;
+	struct resource *r;
+	enum dev_dma_attr attr;
+	int ret, count;
+	const struct iort_iommu_config *ops =
+				iort_get_iommu_config(node);
+
+	if (!ops)
+		return -ENODEV;
+
+	pdev = platform_device_alloc(ops->name, PLATFORM_DEVID_AUTO);
+	if (!pdev)
+		return PTR_ERR(pdev);
+
+	count = ops->iommu_count_resources(node);
+
+	r = kcalloc(count, sizeof(*r), GFP_KERNEL);
+	if (!r) {
+		ret = -ENOMEM;
+		goto dev_put;
+	}
+
+	ops->iommu_init_resources(r, node);
+
+	ret = platform_device_add_resources(pdev, r, count);
+	/*
+	 * Resources are duplicated in platform_device_add_resources,
+	 * free their allocated memory
+	 */
+	kfree(r);
+
+	if (ret)
+		goto dev_put;
+
+	/*
+	 * Add a copy of IORT node pointer to platform_data to
+	 * be used to retrieve IORT data information.
+	 */
+	ret = platform_device_add_data(pdev, &node, sizeof(node));
+	if (ret)
+		goto dev_put;
+
+	pdev->dev.dma_mask = kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
+	if (!pdev->dev.dma_mask) {
+		ret = -ENOMEM;
+		goto dev_put;
+	}
+
+	pdev->dev.fwnode = fwnode;
+
+	/*
+	 * Set default dma mask value for the table walker,
+	 * to be overridden on probing with correct value.
+	 */
+	*pdev->dev.dma_mask = DMA_BIT_MASK(32);
+	pdev->dev.coherent_dma_mask = *pdev->dev.dma_mask;
+
+	attr = ops->iommu_is_coherent(node) ?
+			     DEV_DMA_COHERENT : DEV_DMA_NON_COHERENT;
+
+	/* Configure DMA for the page table walker */
+	acpi_dma_configure(&pdev->dev, attr);
+
+	ret = platform_device_add(pdev);
+	if (ret)
+		goto dma_deconfigure;
+
+	iort_set_fwnode(node, pdev->dev.fwnode);
+
+	return 0;
+
+dma_deconfigure:
+	acpi_dma_deconfigure(&pdev->dev);
+	kfree(pdev->dev.dma_mask);
+
+dev_put:
+	platform_device_put(pdev);
+
+	return ret;
+}
+
 void __init iort_table_detect(void)
 {
 	acpi_status status;
diff --git a/include/linux/iort.h b/include/linux/iort.h
index ac2706a..18e6836 100644
--- a/include/linux/iort.h
+++ b/include/linux/iort.h
@@ -31,6 +31,9 @@ bool iort_node_match(u8 type);
 void iort_table_detect(void);
 u32 iort_msi_map_rid(struct device *dev, u32 req_id);
 struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
+/* IOMMU interface */
+int iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
+				  struct acpi_iort_node *node);
 #else
 static inline bool iort_node_match(u8 type) { return false; }
 static inline void iort_table_detect(void) { }
@@ -38,6 +41,13 @@ static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
 { return req_id; }
 static inline struct irq_domain *
 iort_get_device_domain(struct device *dev, u32 req_id) { return NULL; }
+/* IOMMU interface */
+static inline int
+iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
+			      struct acpi_iort_node *node)
+{
+	return -ENODEV;
+}
 #endif
 
 #define IORT_ACPI_DECLARE(name, table_id, fn)		\
-- 
2.6.4

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

* [RFC PATCH v3 09/13] drivers: iommu: arm-smmu-v3: split probe functions into DT/generic portions
  2016-07-20 11:23 ` Lorenzo Pieralisi
@ 2016-07-20 11:23   ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu
  Cc: Lorenzo Pieralisi, Will Deacon, Hanjun Guo, Robin Murphy,
	Joerg Roedel, Marc Zyngier, Rafael J. Wysocki, Tomasz Nowicki,
	Jon Masters, Sinan Kaya, linux-acpi, linux-pci, linux-kernel,
	linux-arm-kernel

Current ARM SMMUv3 probe functions intermingle HW and DT probing in the
initialization functions to detect and programme the ARM SMMU v3 driver
features. In order to allow probing the ARM SMMUv3 with other firmwares
than DT, this patch splits the ARM SMMUv3 init functions into DT and HW
specific portions so that other FW interfaces (ie ACPI) can reuse the HW
probing functions and skip the DT portion accordingly.

This patch implements no functional change, only code reshuffling.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Will Deacon <will.deacon@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
---
 drivers/iommu/arm-smmu-v3.c | 63 +++++++++++++++++++++++++++++++++++++--------
 1 file changed, 52 insertions(+), 11 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 052a26c..15e74da 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -20,6 +20,7 @@
  * This driver is powered by bad coffee and bombay mix.
  */
 
+#include <linux/acpi.h>
 #include <linux/delay.h>
 #include <linux/dma-iommu.h>
 #include <linux/err.h>
@@ -27,6 +28,7 @@
 #include <linux/iommu.h>
 #include <linux/iommu-fwspec.h>
 #include <linux/iopoll.h>
+#include <linux/iort.h>
 #include <linux/module.h>
 #include <linux/msi.h>
 #include <linux/of.h>
@@ -2377,10 +2379,10 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu)
 	return 0;
 }
 
-static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
+static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
 {
 	u32 reg;
-	bool coherent;
+	bool coherent = smmu->features & ARM_SMMU_FEAT_COHERENCY;
 
 	/* IDR0 */
 	reg = readl_relaxed(smmu->base + ARM_SMMU_IDR0);
@@ -2432,13 +2434,9 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
 		smmu->features |= ARM_SMMU_FEAT_HYP;
 
 	/*
-	 * The dma-coherent property is used in preference to the ID
+	 * The coherency feature as set by FW is used in preference to the ID
 	 * register, but warn on mismatch.
 	 */
-	coherent = of_dma_is_coherent(smmu->dev->of_node);
-	if (coherent)
-		smmu->features |= ARM_SMMU_FEAT_COHERENCY;
-
 	if (!!(reg & IDR0_COHACC) != coherent)
 		dev_warn(smmu->dev, "IDR0.COHACC overridden by dma-coherent property (%s)\n",
 			 coherent ? "true" : "false");
@@ -2559,7 +2557,44 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
 	return 0;
 }
 
-static int arm_smmu_device_dt_probe(struct platform_device *pdev)
+#ifdef CONFIG_ACPI
+static int arm_smmu_device_acpi_probe(struct platform_device *pdev,
+				      struct arm_smmu_device *smmu)
+{
+	struct acpi_iort_smmu_v3 *iort_smmu;
+	struct device *dev = smmu->dev;
+	struct acpi_iort_node *node;
+
+	node = *(struct acpi_iort_node **)dev_get_platdata(dev);
+
+	/* Retrieve SMMUv3 specific data */
+	iort_smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+	if (iort_smmu->flags & ACPI_IORT_SMMU_V3_COHACC_OVERRIDE)
+		smmu->features |= ARM_SMMU_FEAT_COHERENCY;
+
+	return 0;
+}
+#else
+static int arm_smmu_device_acpi_probe(struct platform_device *pdev,
+				      struct arm_smmu_device *smmu)
+{
+	return -ENODEV;
+}
+#endif
+
+static int arm_smmu_device_dt_probe(struct platform_device *pdev,
+				    struct arm_smmu_device *smmu)
+{
+	parse_driver_options(smmu);
+
+	if (of_dma_is_coherent(smmu->dev->of_node))
+		smmu->features |= ARM_SMMU_FEAT_COHERENCY;
+
+	return 0;
+}
+
+static int arm_smmu_device_probe(struct platform_device *pdev)
 {
 	int irq, ret;
 	struct resource *res;
@@ -2601,10 +2636,16 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
 	if (irq > 0)
 		smmu->gerr_irq = irq;
 
-	parse_driver_options(smmu);
+	if (acpi_disabled)
+		ret = arm_smmu_device_dt_probe(pdev, smmu);
+	else
+		ret = arm_smmu_device_acpi_probe(pdev, smmu);
+
+	if (ret)
+		return ret;
 
 	/* Probe the h/w */
-	ret = arm_smmu_device_probe(smmu);
+	ret = arm_smmu_device_hw_probe(smmu);
 	if (ret)
 		return ret;
 
@@ -2639,7 +2680,7 @@ static struct platform_driver arm_smmu_driver = {
 		.name		= "arm-smmu-v3",
 		.of_match_table	= of_match_ptr(arm_smmu_of_match),
 	},
-	.probe	= arm_smmu_device_dt_probe,
+	.probe	= arm_smmu_device_probe,
 	.remove	= arm_smmu_device_remove,
 };
 
-- 
2.6.4


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

* [RFC PATCH v3 09/13] drivers: iommu: arm-smmu-v3: split probe functions into DT/generic portions
@ 2016-07-20 11:23   ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

Current ARM SMMUv3 probe functions intermingle HW and DT probing in the
initialization functions to detect and programme the ARM SMMU v3 driver
features. In order to allow probing the ARM SMMUv3 with other firmwares
than DT, this patch splits the ARM SMMUv3 init functions into DT and HW
specific portions so that other FW interfaces (ie ACPI) can reuse the HW
probing functions and skip the DT portion accordingly.

This patch implements no functional change, only code reshuffling.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Will Deacon <will.deacon@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
---
 drivers/iommu/arm-smmu-v3.c | 63 +++++++++++++++++++++++++++++++++++++--------
 1 file changed, 52 insertions(+), 11 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 052a26c..15e74da 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -20,6 +20,7 @@
  * This driver is powered by bad coffee and bombay mix.
  */
 
+#include <linux/acpi.h>
 #include <linux/delay.h>
 #include <linux/dma-iommu.h>
 #include <linux/err.h>
@@ -27,6 +28,7 @@
 #include <linux/iommu.h>
 #include <linux/iommu-fwspec.h>
 #include <linux/iopoll.h>
+#include <linux/iort.h>
 #include <linux/module.h>
 #include <linux/msi.h>
 #include <linux/of.h>
@@ -2377,10 +2379,10 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu)
 	return 0;
 }
 
-static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
+static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
 {
 	u32 reg;
-	bool coherent;
+	bool coherent = smmu->features & ARM_SMMU_FEAT_COHERENCY;
 
 	/* IDR0 */
 	reg = readl_relaxed(smmu->base + ARM_SMMU_IDR0);
@@ -2432,13 +2434,9 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
 		smmu->features |= ARM_SMMU_FEAT_HYP;
 
 	/*
-	 * The dma-coherent property is used in preference to the ID
+	 * The coherency feature as set by FW is used in preference to the ID
 	 * register, but warn on mismatch.
 	 */
-	coherent = of_dma_is_coherent(smmu->dev->of_node);
-	if (coherent)
-		smmu->features |= ARM_SMMU_FEAT_COHERENCY;
-
 	if (!!(reg & IDR0_COHACC) != coherent)
 		dev_warn(smmu->dev, "IDR0.COHACC overridden by dma-coherent property (%s)\n",
 			 coherent ? "true" : "false");
@@ -2559,7 +2557,44 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
 	return 0;
 }
 
-static int arm_smmu_device_dt_probe(struct platform_device *pdev)
+#ifdef CONFIG_ACPI
+static int arm_smmu_device_acpi_probe(struct platform_device *pdev,
+				      struct arm_smmu_device *smmu)
+{
+	struct acpi_iort_smmu_v3 *iort_smmu;
+	struct device *dev = smmu->dev;
+	struct acpi_iort_node *node;
+
+	node = *(struct acpi_iort_node **)dev_get_platdata(dev);
+
+	/* Retrieve SMMUv3 specific data */
+	iort_smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+	if (iort_smmu->flags & ACPI_IORT_SMMU_V3_COHACC_OVERRIDE)
+		smmu->features |= ARM_SMMU_FEAT_COHERENCY;
+
+	return 0;
+}
+#else
+static int arm_smmu_device_acpi_probe(struct platform_device *pdev,
+				      struct arm_smmu_device *smmu)
+{
+	return -ENODEV;
+}
+#endif
+
+static int arm_smmu_device_dt_probe(struct platform_device *pdev,
+				    struct arm_smmu_device *smmu)
+{
+	parse_driver_options(smmu);
+
+	if (of_dma_is_coherent(smmu->dev->of_node))
+		smmu->features |= ARM_SMMU_FEAT_COHERENCY;
+
+	return 0;
+}
+
+static int arm_smmu_device_probe(struct platform_device *pdev)
 {
 	int irq, ret;
 	struct resource *res;
@@ -2601,10 +2636,16 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
 	if (irq > 0)
 		smmu->gerr_irq = irq;
 
-	parse_driver_options(smmu);
+	if (acpi_disabled)
+		ret = arm_smmu_device_dt_probe(pdev, smmu);
+	else
+		ret = arm_smmu_device_acpi_probe(pdev, smmu);
+
+	if (ret)
+		return ret;
 
 	/* Probe the h/w */
-	ret = arm_smmu_device_probe(smmu);
+	ret = arm_smmu_device_hw_probe(smmu);
 	if (ret)
 		return ret;
 
@@ -2639,7 +2680,7 @@ static struct platform_driver arm_smmu_driver = {
 		.name		= "arm-smmu-v3",
 		.of_match_table	= of_match_ptr(arm_smmu_of_match),
 	},
-	.probe	= arm_smmu_device_dt_probe,
+	.probe	= arm_smmu_device_probe,
 	.remove	= arm_smmu_device_remove,
 };
 
-- 
2.6.4

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

* [RFC PATCH v3 10/13] drivers: iommu: arm-smmu-v3: enable ACPI driver initialization
  2016-07-20 11:23 ` Lorenzo Pieralisi
  (?)
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Marc Zyngier,
	Rafael J. Wysocki, Will Deacon,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA, Sinan Kaya,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA, Hanjun Guo, Tomasz Nowicki,
	Jon Masters

On systems booting with ACPI that enable the ARM SMMU components
in the kernel config options, the ARM SMMU v3 init function
(ie arm_smmu_init(), that registers the driver and sets-up bus
iommu operations) does not run only because the device tree interface
(of_find_matching_node()) fails to find the respective device tree
nodes for ARM SMMU devices.

This works as long as there are no ARM SMMU devices to be probed
with ACPI. If ARM SMMU v3 components are part of the IORT tables,
for them to be instantiated and probed the function registering
the ARM SMMU v3 driver must be able to register the driver and
initialize the bus IOMMU operations accordingly.

This patch changes the logic in arm-smmu-v3 init call to allow
for it to be probed in ACPI systems.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
Acked-by: Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org>
Cc: Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org>
Cc: Robin Murphy <robin.murphy-5wv7dgnIgG8@public.gmane.org>
Cc: Joerg Roedel <joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
---
 drivers/iommu/arm-smmu-v3.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 15e74da..1a4e9ce 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -2689,11 +2689,16 @@ static int __init arm_smmu_init(void)
 	struct device_node *np;
 	int ret;
 
-	np = of_find_matching_node(NULL, arm_smmu_of_match);
-	if (!np)
-		return 0;
+	if (acpi_disabled) {
+		np = of_find_matching_node(NULL, arm_smmu_of_match);
+		if (!np)
+			return 0;
 
-	of_node_put(np);
+		of_node_put(np);
+	} else {
+		if (!iort_node_match(ACPI_IORT_NODE_SMMU_V3))
+			return 0;
+	}
 
 	ret = platform_driver_register(&arm_smmu_driver);
 	if (ret)
-- 
2.6.4

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

* [RFC PATCH v3 10/13] drivers: iommu: arm-smmu-v3: enable ACPI driver initialization
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu
  Cc: Lorenzo Pieralisi, Will Deacon, Robin Murphy, Joerg Roedel,
	Marc Zyngier, Rafael J. Wysocki, Tomasz Nowicki, Hanjun Guo,
	Jon Masters, Sinan Kaya, linux-acpi, linux-pci, linux-kernel,
	linux-arm-kernel

On systems booting with ACPI that enable the ARM SMMU components
in the kernel config options, the ARM SMMU v3 init function
(ie arm_smmu_init(), that registers the driver and sets-up bus
iommu operations) does not run only because the device tree interface
(of_find_matching_node()) fails to find the respective device tree
nodes for ARM SMMU devices.

This works as long as there are no ARM SMMU devices to be probed
with ACPI. If ARM SMMU v3 components are part of the IORT tables,
for them to be instantiated and probed the function registering
the ARM SMMU v3 driver must be able to register the driver and
initialize the bus IOMMU operations accordingly.

This patch changes the logic in arm-smmu-v3 init call to allow
for it to be probed in ACPI systems.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Will Deacon <will.deacon@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
---
 drivers/iommu/arm-smmu-v3.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 15e74da..1a4e9ce 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -2689,11 +2689,16 @@ static int __init arm_smmu_init(void)
 	struct device_node *np;
 	int ret;
 
-	np = of_find_matching_node(NULL, arm_smmu_of_match);
-	if (!np)
-		return 0;
+	if (acpi_disabled) {
+		np = of_find_matching_node(NULL, arm_smmu_of_match);
+		if (!np)
+			return 0;
 
-	of_node_put(np);
+		of_node_put(np);
+	} else {
+		if (!iort_node_match(ACPI_IORT_NODE_SMMU_V3))
+			return 0;
+	}
 
 	ret = platform_driver_register(&arm_smmu_driver);
 	if (ret)
-- 
2.6.4

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

* [RFC PATCH v3 10/13] drivers: iommu: arm-smmu-v3: enable ACPI driver initialization
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

On systems booting with ACPI that enable the ARM SMMU components
in the kernel config options, the ARM SMMU v3 init function
(ie arm_smmu_init(), that registers the driver and sets-up bus
iommu operations) does not run only because the device tree interface
(of_find_matching_node()) fails to find the respective device tree
nodes for ARM SMMU devices.

This works as long as there are no ARM SMMU devices to be probed
with ACPI. If ARM SMMU v3 components are part of the IORT tables,
for them to be instantiated and probed the function registering
the ARM SMMU v3 driver must be able to register the driver and
initialize the bus IOMMU operations accordingly.

This patch changes the logic in arm-smmu-v3 init call to allow
for it to be probed in ACPI systems.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Will Deacon <will.deacon@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
---
 drivers/iommu/arm-smmu-v3.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 15e74da..1a4e9ce 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -2689,11 +2689,16 @@ static int __init arm_smmu_init(void)
 	struct device_node *np;
 	int ret;
 
-	np = of_find_matching_node(NULL, arm_smmu_of_match);
-	if (!np)
-		return 0;
+	if (acpi_disabled) {
+		np = of_find_matching_node(NULL, arm_smmu_of_match);
+		if (!np)
+			return 0;
 
-	of_node_put(np);
+		of_node_put(np);
+	} else {
+		if (!iort_node_match(ACPI_IORT_NODE_SMMU_V3))
+			return 0;
+	}
 
 	ret = platform_driver_register(&arm_smmu_driver);
 	if (ret)
-- 
2.6.4

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

* [RFC PATCH v3 11/13] drivers: iommu: arm-smmu-v3: add IORT platform device creation
  2016-07-20 11:23 ` Lorenzo Pieralisi
  (?)
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Marc Zyngier,
	Rafael J. Wysocki, Will Deacon,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA, Sinan Kaya,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA, Hanjun Guo, Tomasz Nowicki,
	Jon Masters

In ACPI bases systems, in order to be able to create platform
devices and initialize them for ARM SMMU v3 components, the IORT
kernel implementation requires a set of static functions to be
used by the IORT kernel layer to configure platform devices for
ARM SMMU v3 components.

Add static configuration functions to the IORT kernel layer for
the ARM SMMU v3 components, so that the ARM SMMU v3 driver can
initialize its respective platform device by relying on the IORT
kernel infrastructure and by adding a corresponding ACPI device
early probe section entry.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
Cc: Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org>
Cc: Robin Murphy <robin.murphy-5wv7dgnIgG8@public.gmane.org>
Cc: Joerg Roedel <joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
---
 drivers/acpi/iort.c         | 98 ++++++++++++++++++++++++++++++++++++++++++++-
 drivers/iommu/arm-smmu-v3.c | 58 +++++++++++++++++++++++++++
 2 files changed, 155 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
index 23c80c7..c91e45d 100644
--- a/drivers/acpi/iort.c
+++ b/drivers/acpi/iort.c
@@ -455,6 +455,90 @@ iort_get_device_domain(struct device *dev, u32 req_id)
 	return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
 }
 
+static void acpi_smmu_v3_register_irq(int hwirq, const char *name,
+				      struct resource *res)
+{
+	int irq = acpi_register_gsi(NULL, hwirq, ACPI_EDGE_SENSITIVE,
+				    ACPI_ACTIVE_HIGH);
+
+	if (irq < 0) {
+		pr_err("could not register gsi hwirq %d name [%s]\n", hwirq,
+								      name);
+		return;
+	}
+
+	res->start = irq;
+	res->end = irq;
+	res->flags = IORESOURCE_IRQ;
+	res->name = name;
+}
+
+static int arm_smmu_v3_count_resources(struct acpi_iort_node *node)
+{
+	struct acpi_iort_smmu_v3 *smmu;
+	/* Always present mem resource */
+	int num_res = 1;
+
+	/* Retrieve SMMUv3 specific data */
+	smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+	if (smmu->event_gsiv)
+		num_res++;
+
+	if (smmu->pri_gsiv)
+		num_res++;
+
+	if (smmu->gerr_gsiv)
+		num_res++;
+
+	if (smmu->sync_gsiv)
+		num_res++;
+
+	return num_res;
+}
+
+static void arm_smmu_v3_init_resources(struct resource *res,
+				       struct acpi_iort_node *node)
+{
+	struct acpi_iort_smmu_v3 *smmu;
+	int num_res = 0;
+
+	/* Retrieve SMMUv3 specific data */
+	smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+	res[num_res].start = smmu->base_address;
+	res[num_res].end = smmu->base_address + SZ_128K - 1;
+	res[num_res].flags = IORESOURCE_MEM;
+
+	num_res++;
+
+	if (smmu->event_gsiv)
+		acpi_smmu_v3_register_irq(smmu->event_gsiv, "eventq",
+					  &res[num_res++]);
+
+	if (smmu->pri_gsiv)
+		acpi_smmu_v3_register_irq(smmu->pri_gsiv, "priq",
+				       &res[num_res++]);
+
+	if (smmu->gerr_gsiv)
+		acpi_smmu_v3_register_irq(smmu->gerr_gsiv, "gerror",
+					  &res[num_res++]);
+
+	if (smmu->sync_gsiv)
+		acpi_smmu_v3_register_irq(smmu->sync_gsiv, "cmdq-sync",
+					  &res[num_res++]);
+}
+
+static bool arm_smmu_v3_is_coherent(struct acpi_iort_node *node)
+{
+	struct acpi_iort_smmu_v3 *smmu;
+
+	/* Retrieve SMMUv3 specific data */
+	smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+	return smmu->flags & ACPI_IORT_SMMU_V3_COHACC_OVERRIDE;
+}
+
 struct iort_iommu_config {
 	const char *name;
 	int (*iommu_init)(struct acpi_iort_node *node);
@@ -464,10 +548,22 @@ struct iort_iommu_config {
 				     struct acpi_iort_node *node);
 };
 
+const struct iort_iommu_config iort_arm_smmu_v3_cfg = {
+	.name = "arm-smmu-v3",
+	.iommu_is_coherent = arm_smmu_v3_is_coherent,
+	.iommu_count_resources = arm_smmu_v3_count_resources,
+	.iommu_init_resources = arm_smmu_v3_init_resources
+};
+
 static inline const struct iort_iommu_config *
 iort_get_iommu_config(struct acpi_iort_node *node)
 {
-	return NULL;
+	switch (node->type) {
+	case ACPI_IORT_NODE_SMMU_V3:
+		return &iort_arm_smmu_v3_cfg;
+	default:
+		return NULL;
+	}
 }
 
 /**
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 1a4e9ce..294ed5e 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -1749,6 +1749,8 @@ arm_smmu_get_by_fwnode(struct fwnode_handle *handle)
 
 	if (is_of_node(handle))
 		smmu_pdev = of_find_device_by_node(to_of_node(handle));
+	else if (is_fwnode_iommu(handle))
+		smmu_pdev = platform_find_device_by_fwnode(handle);
 
 	if (!smmu_pdev)
 		return NULL;
@@ -1771,6 +1773,7 @@ static struct iommu_ops arm_smmu_ops;
 static int arm_smmu_add_device(struct device *dev)
 {
 	int i, ret;
+
 	struct arm_smmu_device *smmu;
 	struct arm_smmu_master_data *master;
 	struct iommu_fwspec *fwspec = dev_iommu_fwspec(dev);
@@ -2741,6 +2744,61 @@ static int __init arm_smmu_of_init(struct device_node *np)
 }
 IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3", arm_smmu_of_init);
 
+#ifdef CONFIG_ACPI
+static int acpi_smmu_v3_init(struct acpi_table_header *table)
+{
+	struct acpi_iort_node *iort_node, *iort_end;
+	struct acpi_table_iort *iort;
+	struct fwnode_handle *fwnode;
+	int i, ret;
+
+	/*
+	 * table and iort will both point to the start of IORT table, but
+	 * have different struct types
+	 */
+	iort = (struct acpi_table_iort *)table;
+
+	/* Get the first IORT node */
+	iort_node = ACPI_ADD_PTR(struct acpi_iort_node, table,
+				 iort->node_offset);
+	iort_end = ACPI_ADD_PTR(struct acpi_iort_node, table,
+				table->length);
+
+	for (i = 0; i < iort->node_count; i++) {
+
+		if (iort_node >= iort_end) {
+			pr_err("iort node pointer overflows, bad table\n");
+			return -EINVAL;
+		}
+
+		if (iort_node->type == ACPI_IORT_NODE_SMMU_V3) {
+			fwnode = iommu_alloc_fwnode();
+
+			if (!fwnode)
+				return -ENOMEM;
+
+			ret = iort_add_smmu_platform_device(fwnode,
+							    iort_node);
+			if (ret)
+				goto free;
+
+			fwspec_iommu_set_ops(fwnode, &arm_smmu_ops);
+		}
+
+		iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node,
+					 iort_node->length);
+	}
+
+	return 0;
+free:
+	iommu_free_fwnode(fwnode);
+	return ret;
+
+}
+IORT_ACPI_DECLARE(arm_smmu_v3, ACPI_SIG_IORT, acpi_smmu_v3_init);
+
+#endif
+
 MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations");
 MODULE_AUTHOR("Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org>");
 MODULE_LICENSE("GPL v2");
-- 
2.6.4

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

* [RFC PATCH v3 11/13] drivers: iommu: arm-smmu-v3: add IORT platform device creation
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu
  Cc: Lorenzo Pieralisi, Will Deacon, Robin Murphy, Joerg Roedel,
	Marc Zyngier, Rafael J. Wysocki, Tomasz Nowicki, Hanjun Guo,
	Jon Masters, Sinan Kaya, linux-acpi, linux-pci, linux-kernel,
	linux-arm-kernel

In ACPI bases systems, in order to be able to create platform
devices and initialize them for ARM SMMU v3 components, the IORT
kernel implementation requires a set of static functions to be
used by the IORT kernel layer to configure platform devices for
ARM SMMU v3 components.

Add static configuration functions to the IORT kernel layer for
the ARM SMMU v3 components, so that the ARM SMMU v3 driver can
initialize its respective platform device by relying on the IORT
kernel infrastructure and by adding a corresponding ACPI device
early probe section entry.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
---
 drivers/acpi/iort.c         | 98 ++++++++++++++++++++++++++++++++++++++++++++-
 drivers/iommu/arm-smmu-v3.c | 58 +++++++++++++++++++++++++++
 2 files changed, 155 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
index 23c80c7..c91e45d 100644
--- a/drivers/acpi/iort.c
+++ b/drivers/acpi/iort.c
@@ -455,6 +455,90 @@ iort_get_device_domain(struct device *dev, u32 req_id)
 	return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
 }
 
+static void acpi_smmu_v3_register_irq(int hwirq, const char *name,
+				      struct resource *res)
+{
+	int irq = acpi_register_gsi(NULL, hwirq, ACPI_EDGE_SENSITIVE,
+				    ACPI_ACTIVE_HIGH);
+
+	if (irq < 0) {
+		pr_err("could not register gsi hwirq %d name [%s]\n", hwirq,
+								      name);
+		return;
+	}
+
+	res->start = irq;
+	res->end = irq;
+	res->flags = IORESOURCE_IRQ;
+	res->name = name;
+}
+
+static int arm_smmu_v3_count_resources(struct acpi_iort_node *node)
+{
+	struct acpi_iort_smmu_v3 *smmu;
+	/* Always present mem resource */
+	int num_res = 1;
+
+	/* Retrieve SMMUv3 specific data */
+	smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+	if (smmu->event_gsiv)
+		num_res++;
+
+	if (smmu->pri_gsiv)
+		num_res++;
+
+	if (smmu->gerr_gsiv)
+		num_res++;
+
+	if (smmu->sync_gsiv)
+		num_res++;
+
+	return num_res;
+}
+
+static void arm_smmu_v3_init_resources(struct resource *res,
+				       struct acpi_iort_node *node)
+{
+	struct acpi_iort_smmu_v3 *smmu;
+	int num_res = 0;
+
+	/* Retrieve SMMUv3 specific data */
+	smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+	res[num_res].start = smmu->base_address;
+	res[num_res].end = smmu->base_address + SZ_128K - 1;
+	res[num_res].flags = IORESOURCE_MEM;
+
+	num_res++;
+
+	if (smmu->event_gsiv)
+		acpi_smmu_v3_register_irq(smmu->event_gsiv, "eventq",
+					  &res[num_res++]);
+
+	if (smmu->pri_gsiv)
+		acpi_smmu_v3_register_irq(smmu->pri_gsiv, "priq",
+				       &res[num_res++]);
+
+	if (smmu->gerr_gsiv)
+		acpi_smmu_v3_register_irq(smmu->gerr_gsiv, "gerror",
+					  &res[num_res++]);
+
+	if (smmu->sync_gsiv)
+		acpi_smmu_v3_register_irq(smmu->sync_gsiv, "cmdq-sync",
+					  &res[num_res++]);
+}
+
+static bool arm_smmu_v3_is_coherent(struct acpi_iort_node *node)
+{
+	struct acpi_iort_smmu_v3 *smmu;
+
+	/* Retrieve SMMUv3 specific data */
+	smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+	return smmu->flags & ACPI_IORT_SMMU_V3_COHACC_OVERRIDE;
+}
+
 struct iort_iommu_config {
 	const char *name;
 	int (*iommu_init)(struct acpi_iort_node *node);
@@ -464,10 +548,22 @@ struct iort_iommu_config {
 				     struct acpi_iort_node *node);
 };
 
+const struct iort_iommu_config iort_arm_smmu_v3_cfg = {
+	.name = "arm-smmu-v3",
+	.iommu_is_coherent = arm_smmu_v3_is_coherent,
+	.iommu_count_resources = arm_smmu_v3_count_resources,
+	.iommu_init_resources = arm_smmu_v3_init_resources
+};
+
 static inline const struct iort_iommu_config *
 iort_get_iommu_config(struct acpi_iort_node *node)
 {
-	return NULL;
+	switch (node->type) {
+	case ACPI_IORT_NODE_SMMU_V3:
+		return &iort_arm_smmu_v3_cfg;
+	default:
+		return NULL;
+	}
 }
 
 /**
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 1a4e9ce..294ed5e 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -1749,6 +1749,8 @@ arm_smmu_get_by_fwnode(struct fwnode_handle *handle)
 
 	if (is_of_node(handle))
 		smmu_pdev = of_find_device_by_node(to_of_node(handle));
+	else if (is_fwnode_iommu(handle))
+		smmu_pdev = platform_find_device_by_fwnode(handle);
 
 	if (!smmu_pdev)
 		return NULL;
@@ -1771,6 +1773,7 @@ static struct iommu_ops arm_smmu_ops;
 static int arm_smmu_add_device(struct device *dev)
 {
 	int i, ret;
+
 	struct arm_smmu_device *smmu;
 	struct arm_smmu_master_data *master;
 	struct iommu_fwspec *fwspec = dev_iommu_fwspec(dev);
@@ -2741,6 +2744,61 @@ static int __init arm_smmu_of_init(struct device_node *np)
 }
 IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3", arm_smmu_of_init);
 
+#ifdef CONFIG_ACPI
+static int acpi_smmu_v3_init(struct acpi_table_header *table)
+{
+	struct acpi_iort_node *iort_node, *iort_end;
+	struct acpi_table_iort *iort;
+	struct fwnode_handle *fwnode;
+	int i, ret;
+
+	/*
+	 * table and iort will both point to the start of IORT table, but
+	 * have different struct types
+	 */
+	iort = (struct acpi_table_iort *)table;
+
+	/* Get the first IORT node */
+	iort_node = ACPI_ADD_PTR(struct acpi_iort_node, table,
+				 iort->node_offset);
+	iort_end = ACPI_ADD_PTR(struct acpi_iort_node, table,
+				table->length);
+
+	for (i = 0; i < iort->node_count; i++) {
+
+		if (iort_node >= iort_end) {
+			pr_err("iort node pointer overflows, bad table\n");
+			return -EINVAL;
+		}
+
+		if (iort_node->type == ACPI_IORT_NODE_SMMU_V3) {
+			fwnode = iommu_alloc_fwnode();
+
+			if (!fwnode)
+				return -ENOMEM;
+
+			ret = iort_add_smmu_platform_device(fwnode,
+							    iort_node);
+			if (ret)
+				goto free;
+
+			fwspec_iommu_set_ops(fwnode, &arm_smmu_ops);
+		}
+
+		iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node,
+					 iort_node->length);
+	}
+
+	return 0;
+free:
+	iommu_free_fwnode(fwnode);
+	return ret;
+
+}
+IORT_ACPI_DECLARE(arm_smmu_v3, ACPI_SIG_IORT, acpi_smmu_v3_init);
+
+#endif
+
 MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations");
 MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
 MODULE_LICENSE("GPL v2");
-- 
2.6.4

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

* [RFC PATCH v3 11/13] drivers: iommu: arm-smmu-v3: add IORT platform device creation
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

In ACPI bases systems, in order to be able to create platform
devices and initialize them for ARM SMMU v3 components, the IORT
kernel implementation requires a set of static functions to be
used by the IORT kernel layer to configure platform devices for
ARM SMMU v3 components.

Add static configuration functions to the IORT kernel layer for
the ARM SMMU v3 components, so that the ARM SMMU v3 driver can
initialize its respective platform device by relying on the IORT
kernel infrastructure and by adding a corresponding ACPI device
early probe section entry.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
---
 drivers/acpi/iort.c         | 98 ++++++++++++++++++++++++++++++++++++++++++++-
 drivers/iommu/arm-smmu-v3.c | 58 +++++++++++++++++++++++++++
 2 files changed, 155 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
index 23c80c7..c91e45d 100644
--- a/drivers/acpi/iort.c
+++ b/drivers/acpi/iort.c
@@ -455,6 +455,90 @@ iort_get_device_domain(struct device *dev, u32 req_id)
 	return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
 }
 
+static void acpi_smmu_v3_register_irq(int hwirq, const char *name,
+				      struct resource *res)
+{
+	int irq = acpi_register_gsi(NULL, hwirq, ACPI_EDGE_SENSITIVE,
+				    ACPI_ACTIVE_HIGH);
+
+	if (irq < 0) {
+		pr_err("could not register gsi hwirq %d name [%s]\n", hwirq,
+								      name);
+		return;
+	}
+
+	res->start = irq;
+	res->end = irq;
+	res->flags = IORESOURCE_IRQ;
+	res->name = name;
+}
+
+static int arm_smmu_v3_count_resources(struct acpi_iort_node *node)
+{
+	struct acpi_iort_smmu_v3 *smmu;
+	/* Always present mem resource */
+	int num_res = 1;
+
+	/* Retrieve SMMUv3 specific data */
+	smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+	if (smmu->event_gsiv)
+		num_res++;
+
+	if (smmu->pri_gsiv)
+		num_res++;
+
+	if (smmu->gerr_gsiv)
+		num_res++;
+
+	if (smmu->sync_gsiv)
+		num_res++;
+
+	return num_res;
+}
+
+static void arm_smmu_v3_init_resources(struct resource *res,
+				       struct acpi_iort_node *node)
+{
+	struct acpi_iort_smmu_v3 *smmu;
+	int num_res = 0;
+
+	/* Retrieve SMMUv3 specific data */
+	smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+	res[num_res].start = smmu->base_address;
+	res[num_res].end = smmu->base_address + SZ_128K - 1;
+	res[num_res].flags = IORESOURCE_MEM;
+
+	num_res++;
+
+	if (smmu->event_gsiv)
+		acpi_smmu_v3_register_irq(smmu->event_gsiv, "eventq",
+					  &res[num_res++]);
+
+	if (smmu->pri_gsiv)
+		acpi_smmu_v3_register_irq(smmu->pri_gsiv, "priq",
+				       &res[num_res++]);
+
+	if (smmu->gerr_gsiv)
+		acpi_smmu_v3_register_irq(smmu->gerr_gsiv, "gerror",
+					  &res[num_res++]);
+
+	if (smmu->sync_gsiv)
+		acpi_smmu_v3_register_irq(smmu->sync_gsiv, "cmdq-sync",
+					  &res[num_res++]);
+}
+
+static bool arm_smmu_v3_is_coherent(struct acpi_iort_node *node)
+{
+	struct acpi_iort_smmu_v3 *smmu;
+
+	/* Retrieve SMMUv3 specific data */
+	smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+	return smmu->flags & ACPI_IORT_SMMU_V3_COHACC_OVERRIDE;
+}
+
 struct iort_iommu_config {
 	const char *name;
 	int (*iommu_init)(struct acpi_iort_node *node);
@@ -464,10 +548,22 @@ struct iort_iommu_config {
 				     struct acpi_iort_node *node);
 };
 
+const struct iort_iommu_config iort_arm_smmu_v3_cfg = {
+	.name = "arm-smmu-v3",
+	.iommu_is_coherent = arm_smmu_v3_is_coherent,
+	.iommu_count_resources = arm_smmu_v3_count_resources,
+	.iommu_init_resources = arm_smmu_v3_init_resources
+};
+
 static inline const struct iort_iommu_config *
 iort_get_iommu_config(struct acpi_iort_node *node)
 {
-	return NULL;
+	switch (node->type) {
+	case ACPI_IORT_NODE_SMMU_V3:
+		return &iort_arm_smmu_v3_cfg;
+	default:
+		return NULL;
+	}
 }
 
 /**
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 1a4e9ce..294ed5e 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -1749,6 +1749,8 @@ arm_smmu_get_by_fwnode(struct fwnode_handle *handle)
 
 	if (is_of_node(handle))
 		smmu_pdev = of_find_device_by_node(to_of_node(handle));
+	else if (is_fwnode_iommu(handle))
+		smmu_pdev = platform_find_device_by_fwnode(handle);
 
 	if (!smmu_pdev)
 		return NULL;
@@ -1771,6 +1773,7 @@ static struct iommu_ops arm_smmu_ops;
 static int arm_smmu_add_device(struct device *dev)
 {
 	int i, ret;
+
 	struct arm_smmu_device *smmu;
 	struct arm_smmu_master_data *master;
 	struct iommu_fwspec *fwspec = dev_iommu_fwspec(dev);
@@ -2741,6 +2744,61 @@ static int __init arm_smmu_of_init(struct device_node *np)
 }
 IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3", arm_smmu_of_init);
 
+#ifdef CONFIG_ACPI
+static int acpi_smmu_v3_init(struct acpi_table_header *table)
+{
+	struct acpi_iort_node *iort_node, *iort_end;
+	struct acpi_table_iort *iort;
+	struct fwnode_handle *fwnode;
+	int i, ret;
+
+	/*
+	 * table and iort will both point to the start of IORT table, but
+	 * have different struct types
+	 */
+	iort = (struct acpi_table_iort *)table;
+
+	/* Get the first IORT node */
+	iort_node = ACPI_ADD_PTR(struct acpi_iort_node, table,
+				 iort->node_offset);
+	iort_end = ACPI_ADD_PTR(struct acpi_iort_node, table,
+				table->length);
+
+	for (i = 0; i < iort->node_count; i++) {
+
+		if (iort_node >= iort_end) {
+			pr_err("iort node pointer overflows, bad table\n");
+			return -EINVAL;
+		}
+
+		if (iort_node->type == ACPI_IORT_NODE_SMMU_V3) {
+			fwnode = iommu_alloc_fwnode();
+
+			if (!fwnode)
+				return -ENOMEM;
+
+			ret = iort_add_smmu_platform_device(fwnode,
+							    iort_node);
+			if (ret)
+				goto free;
+
+			fwspec_iommu_set_ops(fwnode, &arm_smmu_ops);
+		}
+
+		iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node,
+					 iort_node->length);
+	}
+
+	return 0;
+free:
+	iommu_free_fwnode(fwnode);
+	return ret;
+
+}
+IORT_ACPI_DECLARE(arm_smmu_v3, ACPI_SIG_IORT, acpi_smmu_v3_init);
+
+#endif
+
 MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations");
 MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
 MODULE_LICENSE("GPL v2");
-- 
2.6.4

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

* [RFC PATCH v3 12/13] drivers: acpi: iort: replace rid map type with type mask
  2016-07-20 11:23 ` Lorenzo Pieralisi
  (?)
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
  Cc: Marc Zyngier, Tomasz Nowicki, Rafael J. Wysocki,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Will Deacon, Sinan Kaya,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA, Hanjun Guo, Jon Masters,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

IORT tables provide data that allow the kernel to carry out
device ID mappings between endpoints and system components
(eg interrupt controllers, IOMMUs). When the mapping for a
given device ID is carried out, the translation mechanism
is done on a per-subsystem basis rather than a component
subtype (ie the IOMMU kernel layer will look for mappings
from a device to all IORT node types corresponding to IOMMU
components), therefore the corresponding mapping API should
work on a range (ie mask) of IORT node types corresponding
to a common set of components (eg IOMMUs) rather than a
specific node type.

Upgrade the IORT iort_node_map_rid() API to work with a
type mask instead of a single node type so that it can
be used for mappings that span multiple components types
(ie IOMMUs).

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
Cc: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: Tomasz Nowicki <tn-nYOzD4b6Jr9Wk0Htik3J/w@public.gmane.org>
Cc: "Rafael J. Wysocki" <rjw-LthD3rsA81gm4RdzfppkhA@public.gmane.org>
---
 drivers/acpi/iort.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
index c91e45d..c116b68 100644
--- a/drivers/acpi/iort.c
+++ b/drivers/acpi/iort.c
@@ -25,6 +25,9 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
+#define IORT_TYPE_MASK(type)	(1 << (type))
+#define IORT_MSI_TYPE		(1 << ACPI_IORT_NODE_ITS_GROUP)
+
 struct iort_its_msi_chip {
 	struct list_head	list;
 	struct fwnode_handle	*fw_node;
@@ -299,7 +302,7 @@ iort_id_map(struct acpi_iort_id_mapping *map, u8 type, u32 rid_in, u32 *rid_out)
 
 static struct acpi_iort_node *
 iort_node_map_rid(struct acpi_iort_node *node, u32 rid_in,
-		  u32 *rid_out, u8 type)
+		  u32 *rid_out, u8 type_mask)
 {
 	u32 rid = rid_in;
 
@@ -308,7 +311,7 @@ iort_node_map_rid(struct acpi_iort_node *node, u32 rid_in,
 		struct acpi_iort_id_mapping *map;
 		int i;
 
-		if (node->type == type) {
+		if (IORT_TYPE_MASK(node->type) & type_mask) {
 			if (rid_out)
 				*rid_out = rid;
 			return node;
@@ -386,7 +389,7 @@ u32 iort_msi_map_rid(struct device *dev, u32 req_id)
 		return req_id;
 	}
 
-	iort_node_map_rid(node, req_id, &dev_id, ACPI_IORT_NODE_ITS_GROUP);
+	iort_node_map_rid(node, req_id, &dev_id, IORT_MSI_TYPE);
 	return dev_id;
 }
 
@@ -411,7 +414,7 @@ iort_dev_find_its_id(struct device *dev, u32 req_id, unsigned int idx,
 		return -ENXIO;
 	}
 
-	node = iort_node_map_rid(node, req_id, NULL, ACPI_IORT_NODE_ITS_GROUP);
+	node = iort_node_map_rid(node, req_id, NULL, IORT_MSI_TYPE);
 	if (!node) {
 		dev_err(dev, "can't find related ITS node\n");
 		return -ENXIO;
-- 
2.6.4

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

* [RFC PATCH v3 12/13] drivers: acpi: iort: replace rid map type with type mask
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu
  Cc: Lorenzo Pieralisi, Hanjun Guo, Tomasz Nowicki, Rafael J. Wysocki,
	Will Deacon, Marc Zyngier, Robin Murphy, Joerg Roedel,
	Jon Masters, Sinan Kaya, linux-acpi, linux-pci, linux-kernel,
	linux-arm-kernel

IORT tables provide data that allow the kernel to carry out
device ID mappings between endpoints and system components
(eg interrupt controllers, IOMMUs). When the mapping for a
given device ID is carried out, the translation mechanism
is done on a per-subsystem basis rather than a component
subtype (ie the IOMMU kernel layer will look for mappings
from a device to all IORT node types corresponding to IOMMU
components), therefore the corresponding mapping API should
work on a range (ie mask) of IORT node types corresponding
to a common set of components (eg IOMMUs) rather than a
specific node type.

Upgrade the IORT iort_node_map_rid() API to work with a
type mask instead of a single node type so that it can
be used for mappings that span multiple components types
(ie IOMMUs).

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
 drivers/acpi/iort.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
index c91e45d..c116b68 100644
--- a/drivers/acpi/iort.c
+++ b/drivers/acpi/iort.c
@@ -25,6 +25,9 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
+#define IORT_TYPE_MASK(type)	(1 << (type))
+#define IORT_MSI_TYPE		(1 << ACPI_IORT_NODE_ITS_GROUP)
+
 struct iort_its_msi_chip {
 	struct list_head	list;
 	struct fwnode_handle	*fw_node;
@@ -299,7 +302,7 @@ iort_id_map(struct acpi_iort_id_mapping *map, u8 type, u32 rid_in, u32 *rid_out)
 
 static struct acpi_iort_node *
 iort_node_map_rid(struct acpi_iort_node *node, u32 rid_in,
-		  u32 *rid_out, u8 type)
+		  u32 *rid_out, u8 type_mask)
 {
 	u32 rid = rid_in;
 
@@ -308,7 +311,7 @@ iort_node_map_rid(struct acpi_iort_node *node, u32 rid_in,
 		struct acpi_iort_id_mapping *map;
 		int i;
 
-		if (node->type == type) {
+		if (IORT_TYPE_MASK(node->type) & type_mask) {
 			if (rid_out)
 				*rid_out = rid;
 			return node;
@@ -386,7 +389,7 @@ u32 iort_msi_map_rid(struct device *dev, u32 req_id)
 		return req_id;
 	}
 
-	iort_node_map_rid(node, req_id, &dev_id, ACPI_IORT_NODE_ITS_GROUP);
+	iort_node_map_rid(node, req_id, &dev_id, IORT_MSI_TYPE);
 	return dev_id;
 }
 
@@ -411,7 +414,7 @@ iort_dev_find_its_id(struct device *dev, u32 req_id, unsigned int idx,
 		return -ENXIO;
 	}
 
-	node = iort_node_map_rid(node, req_id, NULL, ACPI_IORT_NODE_ITS_GROUP);
+	node = iort_node_map_rid(node, req_id, NULL, IORT_MSI_TYPE);
 	if (!node) {
 		dev_err(dev, "can't find related ITS node\n");
 		return -ENXIO;
-- 
2.6.4

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

* [RFC PATCH v3 12/13] drivers: acpi: iort: replace rid map type with type mask
@ 2016-07-20 11:23     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

IORT tables provide data that allow the kernel to carry out
device ID mappings between endpoints and system components
(eg interrupt controllers, IOMMUs). When the mapping for a
given device ID is carried out, the translation mechanism
is done on a per-subsystem basis rather than a component
subtype (ie the IOMMU kernel layer will look for mappings
from a device to all IORT node types corresponding to IOMMU
components), therefore the corresponding mapping API should
work on a range (ie mask) of IORT node types corresponding
to a common set of components (eg IOMMUs) rather than a
specific node type.

Upgrade the IORT iort_node_map_rid() API to work with a
type mask instead of a single node type so that it can
be used for mappings that span multiple components types
(ie IOMMUs).

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
 drivers/acpi/iort.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
index c91e45d..c116b68 100644
--- a/drivers/acpi/iort.c
+++ b/drivers/acpi/iort.c
@@ -25,6 +25,9 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
+#define IORT_TYPE_MASK(type)	(1 << (type))
+#define IORT_MSI_TYPE		(1 << ACPI_IORT_NODE_ITS_GROUP)
+
 struct iort_its_msi_chip {
 	struct list_head	list;
 	struct fwnode_handle	*fw_node;
@@ -299,7 +302,7 @@ iort_id_map(struct acpi_iort_id_mapping *map, u8 type, u32 rid_in, u32 *rid_out)
 
 static struct acpi_iort_node *
 iort_node_map_rid(struct acpi_iort_node *node, u32 rid_in,
-		  u32 *rid_out, u8 type)
+		  u32 *rid_out, u8 type_mask)
 {
 	u32 rid = rid_in;
 
@@ -308,7 +311,7 @@ iort_node_map_rid(struct acpi_iort_node *node, u32 rid_in,
 		struct acpi_iort_id_mapping *map;
 		int i;
 
-		if (node->type == type) {
+		if (IORT_TYPE_MASK(node->type) & type_mask) {
 			if (rid_out)
 				*rid_out = rid;
 			return node;
@@ -386,7 +389,7 @@ u32 iort_msi_map_rid(struct device *dev, u32 req_id)
 		return req_id;
 	}
 
-	iort_node_map_rid(node, req_id, &dev_id, ACPI_IORT_NODE_ITS_GROUP);
+	iort_node_map_rid(node, req_id, &dev_id, IORT_MSI_TYPE);
 	return dev_id;
 }
 
@@ -411,7 +414,7 @@ iort_dev_find_its_id(struct device *dev, u32 req_id, unsigned int idx,
 		return -ENXIO;
 	}
 
-	node = iort_node_map_rid(node, req_id, NULL, ACPI_IORT_NODE_ITS_GROUP);
+	node = iort_node_map_rid(node, req_id, NULL, IORT_MSI_TYPE);
 	if (!node) {
 		dev_err(dev, "can't find related ITS node\n");
 		return -ENXIO;
-- 
2.6.4

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

* [RFC PATCH v3 13/13] drivers: acpi: iort: introduce iort_iommu_configure
  2016-07-20 11:23 ` Lorenzo Pieralisi
@ 2016-07-20 11:23   ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: iommu
  Cc: Lorenzo Pieralisi, Hanjun Guo, Tomasz Nowicki, Rafael J. Wysocki,
	Will Deacon, Marc Zyngier, Robin Murphy, Joerg Roedel,
	Jon Masters, Sinan Kaya, linux-acpi, linux-pci, linux-kernel,
	linux-arm-kernel

DT based systems have a generic kernel API to configure IOMMUs
for devices (ie of_iommu_configure()).

On ARM based ACPI systems, the of_iommu_configure() equivalent can
be implemented atop ACPI IORT kernel API, with the corresponding
functions to map device identifiers to IOMMUs and retrieve the
corresponding IOMMU operations necessary for DMA operations set-up.

By relying on the iommu_fwspec generic kernel infrastructure,
implement the IORT based IOMMU configuration for ARM ACPI systems
and hook it up in the ACPI kernel layer that implements DMA
configuration for a device.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
 drivers/acpi/iort.c  | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/acpi/scan.c  |  7 +++++-
 include/linux/iort.h |  4 ++++
 3 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
index c116b68..a12a4ff 100644
--- a/drivers/acpi/iort.c
+++ b/drivers/acpi/iort.c
@@ -18,6 +18,7 @@
 
 #define pr_fmt(fmt)	"ACPI: IORT: " fmt
 
+#include <linux/iommu-fwspec.h>
 #include <linux/iort.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
@@ -27,6 +28,8 @@
 
 #define IORT_TYPE_MASK(type)	(1 << (type))
 #define IORT_MSI_TYPE		(1 << ACPI_IORT_NODE_ITS_GROUP)
+#define IORT_IOMMU_TYPE		((1 << ACPI_IORT_NODE_SMMU) |	\
+				(1 << ACPI_IORT_NODE_SMMU_V3))
 
 struct iort_its_msi_chip {
 	struct list_head	list;
@@ -458,6 +461,67 @@ iort_get_device_domain(struct device *dev, u32 req_id)
 	return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
 }
 
+static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
+{
+	u32 *rid = data;
+
+	*rid = alias;
+	return 0;
+}
+
+static int arm_smmu_iort_xlate(struct device *dev, u32 streamid,
+			       struct fwnode_handle *fwnode)
+{
+	int ret = iommu_fwspec_init(dev, fwnode);
+
+	if (!ret)
+		ret = iommu_fwspec_add_ids(dev, &streamid, 1);
+
+	return 0;
+}
+
+/**
+ * iort_iommu_configure - Set-up IOMMU configuration for a device.
+ *
+ * @dev: device to configure
+ *
+ * Returns: iommu_ops pointer on configuration success
+ *          NULL on configuration failure
+ */
+const struct iommu_ops *iort_iommu_configure(struct device *dev)
+{
+	struct acpi_iort_node *node, *parent;
+	struct fwnode_handle *iort_fwnode;
+	u32 rid = 0, devid = 0;
+
+	if (dev_is_pci(dev)) {
+		struct pci_bus *bus = to_pci_dev(dev)->bus;
+
+		pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid,
+				       &rid);
+
+		node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
+				      iort_match_node_callback, &bus->dev);
+	} else {
+		node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
+				      iort_match_node_callback, dev);
+	}
+
+	if (!node)
+		return NULL;
+
+	parent = iort_node_map_rid(node, rid, &devid, IORT_IOMMU_TYPE);
+	if (parent) {
+		iort_fwnode = iort_get_fwnode(parent);
+		if (iort_fwnode) {
+			arm_smmu_iort_xlate(dev, devid, iort_fwnode);
+			return fwspec_iommu_get_ops(iort_fwnode);
+		}
+	}
+
+	return NULL;
+}
+
 static void acpi_smmu_v3_register_irq(int hwirq, const char *name,
 				      struct resource *res)
 {
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index b4b9064..de28825 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -7,6 +7,7 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/acpi.h>
+#include <linux/iort.h>
 #include <linux/signal.h>
 #include <linux/kthread.h>
 #include <linux/dmi.h>
@@ -1365,11 +1366,15 @@ enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
  */
 void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
 {
+	const struct iommu_ops *iommu;
+
+	iommu = iort_iommu_configure(dev);
+
 	/*
 	 * Assume dma valid range starts at 0 and covers the whole
 	 * coherent_dma_mask.
 	 */
-	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, NULL,
+	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, iommu,
 			   attr == DEV_DMA_COHERENT);
 }
 
diff --git a/include/linux/iort.h b/include/linux/iort.h
index 18e6836..bbe08ef 100644
--- a/include/linux/iort.h
+++ b/include/linux/iort.h
@@ -34,6 +34,8 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
 /* IOMMU interface */
 int iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
 				  struct acpi_iort_node *node);
+
+const struct iommu_ops *iort_iommu_configure(struct device *dev);
 #else
 static inline bool iort_node_match(u8 type) { return false; }
 static inline void iort_table_detect(void) { }
@@ -48,6 +50,8 @@ iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
 {
 	return -ENODEV;
 }
+static inline const struct iommu_ops *
+iort_iommu_configure(struct device *dev) { return NULL; }
 #endif
 
 #define IORT_ACPI_DECLARE(name, table_id, fn)		\
-- 
2.6.4


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

* [RFC PATCH v3 13/13] drivers: acpi: iort: introduce iort_iommu_configure
@ 2016-07-20 11:23   ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-20 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

DT based systems have a generic kernel API to configure IOMMUs
for devices (ie of_iommu_configure()).

On ARM based ACPI systems, the of_iommu_configure() equivalent can
be implemented atop ACPI IORT kernel API, with the corresponding
functions to map device identifiers to IOMMUs and retrieve the
corresponding IOMMU operations necessary for DMA operations set-up.

By relying on the iommu_fwspec generic kernel infrastructure,
implement the IORT based IOMMU configuration for ARM ACPI systems
and hook it up in the ACPI kernel layer that implements DMA
configuration for a device.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
 drivers/acpi/iort.c  | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/acpi/scan.c  |  7 +++++-
 include/linux/iort.h |  4 ++++
 3 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
index c116b68..a12a4ff 100644
--- a/drivers/acpi/iort.c
+++ b/drivers/acpi/iort.c
@@ -18,6 +18,7 @@
 
 #define pr_fmt(fmt)	"ACPI: IORT: " fmt
 
+#include <linux/iommu-fwspec.h>
 #include <linux/iort.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
@@ -27,6 +28,8 @@
 
 #define IORT_TYPE_MASK(type)	(1 << (type))
 #define IORT_MSI_TYPE		(1 << ACPI_IORT_NODE_ITS_GROUP)
+#define IORT_IOMMU_TYPE		((1 << ACPI_IORT_NODE_SMMU) |	\
+				(1 << ACPI_IORT_NODE_SMMU_V3))
 
 struct iort_its_msi_chip {
 	struct list_head	list;
@@ -458,6 +461,67 @@ iort_get_device_domain(struct device *dev, u32 req_id)
 	return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
 }
 
+static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
+{
+	u32 *rid = data;
+
+	*rid = alias;
+	return 0;
+}
+
+static int arm_smmu_iort_xlate(struct device *dev, u32 streamid,
+			       struct fwnode_handle *fwnode)
+{
+	int ret = iommu_fwspec_init(dev, fwnode);
+
+	if (!ret)
+		ret = iommu_fwspec_add_ids(dev, &streamid, 1);
+
+	return 0;
+}
+
+/**
+ * iort_iommu_configure - Set-up IOMMU configuration for a device.
+ *
+ * @dev: device to configure
+ *
+ * Returns: iommu_ops pointer on configuration success
+ *          NULL on configuration failure
+ */
+const struct iommu_ops *iort_iommu_configure(struct device *dev)
+{
+	struct acpi_iort_node *node, *parent;
+	struct fwnode_handle *iort_fwnode;
+	u32 rid = 0, devid = 0;
+
+	if (dev_is_pci(dev)) {
+		struct pci_bus *bus = to_pci_dev(dev)->bus;
+
+		pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid,
+				       &rid);
+
+		node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
+				      iort_match_node_callback, &bus->dev);
+	} else {
+		node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
+				      iort_match_node_callback, dev);
+	}
+
+	if (!node)
+		return NULL;
+
+	parent = iort_node_map_rid(node, rid, &devid, IORT_IOMMU_TYPE);
+	if (parent) {
+		iort_fwnode = iort_get_fwnode(parent);
+		if (iort_fwnode) {
+			arm_smmu_iort_xlate(dev, devid, iort_fwnode);
+			return fwspec_iommu_get_ops(iort_fwnode);
+		}
+	}
+
+	return NULL;
+}
+
 static void acpi_smmu_v3_register_irq(int hwirq, const char *name,
 				      struct resource *res)
 {
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index b4b9064..de28825 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -7,6 +7,7 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/acpi.h>
+#include <linux/iort.h>
 #include <linux/signal.h>
 #include <linux/kthread.h>
 #include <linux/dmi.h>
@@ -1365,11 +1366,15 @@ enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
  */
 void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
 {
+	const struct iommu_ops *iommu;
+
+	iommu = iort_iommu_configure(dev);
+
 	/*
 	 * Assume dma valid range starts at 0 and covers the whole
 	 * coherent_dma_mask.
 	 */
-	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, NULL,
+	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, iommu,
 			   attr == DEV_DMA_COHERENT);
 }
 
diff --git a/include/linux/iort.h b/include/linux/iort.h
index 18e6836..bbe08ef 100644
--- a/include/linux/iort.h
+++ b/include/linux/iort.h
@@ -34,6 +34,8 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
 /* IOMMU interface */
 int iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
 				  struct acpi_iort_node *node);
+
+const struct iommu_ops *iort_iommu_configure(struct device *dev);
 #else
 static inline bool iort_node_match(u8 type) { return false; }
 static inline void iort_table_detect(void) { }
@@ -48,6 +50,8 @@ iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
 {
 	return -ENODEV;
 }
+static inline const struct iommu_ops *
+iort_iommu_configure(struct device *dev) { return NULL; }
 #endif
 
 #define IORT_ACPI_DECLARE(name, table_id, fn)		\
-- 
2.6.4

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

* Re: [RFC PATCH v3 00/13] ACPI IORT ARM SMMU v3 support
  2016-07-20 11:23 ` Lorenzo Pieralisi
  (?)
@ 2016-07-25  5:53     ` Dennis Chen
  -1 siblings, 0 replies; 72+ messages in thread
From: Dennis Chen @ 2016-07-25  5:53 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Marc Zyngier,
	Rafael J. Wysocki, Will Deacon,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA, Sinan Kaya,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Hanjun Guo,
	Tomasz Nowicki, nd-5wv7dgnIgG8, Jon Masters

Hi
On Wed, Jul 20, 2016 at 12:23:22PM +0100, Lorenzo Pieralisi wrote:
> This RFC patch series is v3 of a previous posting:
> 
> https://lkml.org/lkml/2016/6/7/523
> 
> v2 -> v3
> 	- Rebased on top of dependencies series [1][2][3](v4.7-rc3)
> 	- Added back reliance on ACPI early probing infrastructure
> 	- Patch[1-3] merged through other dependent series
> 	- Added back IOMMU fwnode generalization
> 	- Move SMMU v3 static functions configuration to IORT code
> 	- Implemented generic IOMMU fwspec API
> 	- Added code to implement fwnode platform device look-up
> 
> v1 -> v2:
> 	- Rebased on top of dependencies series [1][2][3](v4.7-rc1)
> 	- Removed IOMMU fwnode generalization
> 	- Implemented ARM SMMU v3 ACPI probing instead of ARM SMMU v2
> 	  owing to patch series dependencies [1]
> 	- Moved platform device creation logic to IORT code to
> 	  generalize its usage for ARM SMMU v1-v2-v3 components
> 	- Removed reliance on ACPI early device probing
> 	- Created IORT specific iommu_xlate() translation hook leaving
> 	  OF code unchanged according to v1 reviews
> 
> The ACPI IORT table provides information that allows instantiating
> ARM SMMU devices and carrying out id mappings between components on
> ARM based systems (devices, IOMMUs, interrupt controllers).
> 
> http://infocenter.arm.com/help/topic/com.arm.doc.den0049b/DEN0049B_IO_Remapping_Table.pdf
> 
> Building on basic IORT support, available through [2]:
> 
> this patchset enables ARM SMMU v3 support on ACPI systems.
> 
> Most of the code is aimed at building the required generic ACPI
> infrastructure to create and enable IOMMU components and to bring
> the IOMMU infrastructure for ACPI on par with DT, which is going to
> make future ARM SMMU components easier to integrate.
> 
> PATCH (1) adds a FWNODE_IOMMU type to the struct fwnode_handle type.
>           It is required to attach a fwnode identifier to platform
>           devices allocated/detected through IORT tables entries;
>           IOMMU devices have to have an identifier to look them up
>           eg IOMMU core layer carrying out id translation. This can be
>           done through a fwnode_handle (ie IOMMU platform devices created
>           out of IORT tables are not ACPI devices hence they can't be
>           allocated as such, otherwise they would have a fwnode_handle of
>           type FWNODE_ACPI). This patch requires discussion and it is key
>           to the RFC.
> 
> PATCH (2) makes use of the ACPI early probing API to add a linker script
>           section for probing devices via IORT ACPI kernel code.
> 
> PATCH (3) provides IORT support for registering IOMMU IORT node through
>           their fwnode handle.
> 
> PATCH (4) implements core code fwnode based platform devices look-up.
> 
> PATCH (5) extends iommu_fwspec so that it can be used on ACPI based
>           system by creating a generic IOMMU fwspec kernel layer.
> 
> PATCH (6) implements the of_dma_configure() API in ACPI world -
>           acpi_dma_configure() - and patches PCI and ACPI core code to
>           start making use of it.
> 
> PATCH (7) provides an IORT function to detect existence of specific type
>           of IORT components.
> 
> PATCH (8) creates the kernel infrastructure required to create ARM SMMU
>           platform devices for IORT nodes.
> 
> PATCH (9) refactors the ARM SMMU v3 driver so that the init functions are
>           split in a way that groups together code that probes through DT
>           and code that carries out HW registers FW agnostic probing, in
>           preparation for adding the ACPI probing path.
> 
> PATCH (10) rework ARM SMMU v3 platform driver registration to make it work
>            on ACPI systems.
> 
> PATCH (11) Building on patch (8), it adds ARM SMMU v3 IORT IOMMU
>            operations to create and probe ARM SMMU v3 components.
> 
> PATCH (12) Extend the IORT iort_node_map_rid() to work on a type mask
>            instead of a single type so that the translation API can
>            be used on a range of components.
> 
> PATCH (13) provides IORT infrastructure to carry out IOMMU configuration
>            for devices and hook it up to the previously introduced ACPI
>            DMA configure API.
> 
> This patchset is built on top and depends on these three patch series:
> 
> [1] R.Murphy "Generic DT bindings for PCI and ARM SMMU v3" v4
>     https://marc.info/?l=devicetree&m=146739193215518&w=2
> 
> [2] T.Nowicki "Introduce ACPI world to ITS irqchip" v7
>     https://marc.info/?l=linux-arm-kernel&m=146642080022289&w=2
> 
> [3] T.Nowicki "Support for ARM64 ACPI based PCI host controller" v8
>     http://marc.info/?l=linux-acpi&m=146462129816292&w=2
> 
> and is provided for early review/testing purposes here:
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git acpi/iort-smmu-v3i
>
I thought I can got all the 13 patches applied with the above git tree, but I can't find
any ACPI related stuff after I cloned the git repos to my local machine, am I missing
something here?

Thanks,
Dennis
> 
> Tested on FVP models for ARM SMMU v3 probing path.
> 
> Lorenzo Pieralisi (13):
>   drivers: iommu: add FWNODE_IOMMU fwnode type
>   drivers: acpi: iort: introduce linker section for IORT entries probing
>   drivers: acpi: iort: add support for IOMMU fwnode registration
>   drivers: platform: add fwnode base platform devices retrieval
>   drivers: iommu: make iommu_fwspec OF agnostic
>   drivers: acpi: implement acpi_dma_configure
>   drivers: acpi: iort: add node match function
>   drivers: acpi: iort: add support for ARM SMMU platform devices
>     creation
>   drivers: iommu: arm-smmu-v3: split probe functions into DT/generic
>     portions
>   drivers: iommu: arm-smmu-v3: enable ACPI driver initialization
>   drivers: iommu: arm-smmu-v3: add IORT platform device creation
>   drivers: acpi: iort: replace rid map type with type mask
>   drivers: acpi: iort: introduce iort_iommu_configure
> 
>  drivers/acpi/glue.c               |   4 +-
>  drivers/acpi/iort.c               | 360 +++++++++++++++++++++++++++++++++++++-
>  drivers/acpi/scan.c               |  29 +++
>  drivers/base/platform.c           |  23 +++
>  drivers/iommu/Kconfig             |   4 +
>  drivers/iommu/Makefile            |   1 +
>  drivers/iommu/arm-smmu-v3.c       | 147 ++++++++++++++--
>  drivers/iommu/iommu-fwspec.c      | 114 ++++++++++++
>  drivers/iommu/of_iommu.c          |  52 ------
>  drivers/pci/probe.c               |   3 +-
>  include/acpi/acpi_bus.h           |   2 +
>  include/asm-generic/vmlinux.lds.h |   1 +
>  include/linux/acpi.h              |   5 +
>  include/linux/fwnode.h            |   1 +
>  include/linux/iommu-fwspec.h      |  60 +++++++
>  include/linux/iommu.h             |  25 +++
>  include/linux/iort.h              |  19 ++
>  include/linux/of_iommu.h          |  24 +--
>  include/linux/platform_device.h   |   3 +
>  19 files changed, 782 insertions(+), 95 deletions(-)
>  create mode 100644 drivers/iommu/iommu-fwspec.c
>  create mode 100644 include/linux/iommu-fwspec.h
> 
> -- 
> 2.6.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [RFC PATCH v3 00/13] ACPI IORT ARM SMMU v3 support
@ 2016-07-25  5:53     ` Dennis Chen
  0 siblings, 0 replies; 72+ messages in thread
From: Dennis Chen @ 2016-07-25  5:53 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: iommu, Will Deacon, Marc Zyngier, Robin Murphy, Joerg Roedel,
	Rafael J. Wysocki, Tomasz Nowicki, Hanjun Guo, Jon Masters,
	Sinan Kaya, linux-acpi, linux-pci, linux-kernel,
	linux-arm-kernel, nd

Hi
On Wed, Jul 20, 2016 at 12:23:22PM +0100, Lorenzo Pieralisi wrote:
> This RFC patch series is v3 of a previous posting:
> 
> https://lkml.org/lkml/2016/6/7/523
> 
> v2 -> v3
> 	- Rebased on top of dependencies series [1][2][3](v4.7-rc3)
> 	- Added back reliance on ACPI early probing infrastructure
> 	- Patch[1-3] merged through other dependent series
> 	- Added back IOMMU fwnode generalization
> 	- Move SMMU v3 static functions configuration to IORT code
> 	- Implemented generic IOMMU fwspec API
> 	- Added code to implement fwnode platform device look-up
> 
> v1 -> v2:
> 	- Rebased on top of dependencies series [1][2][3](v4.7-rc1)
> 	- Removed IOMMU fwnode generalization
> 	- Implemented ARM SMMU v3 ACPI probing instead of ARM SMMU v2
> 	  owing to patch series dependencies [1]
> 	- Moved platform device creation logic to IORT code to
> 	  generalize its usage for ARM SMMU v1-v2-v3 components
> 	- Removed reliance on ACPI early device probing
> 	- Created IORT specific iommu_xlate() translation hook leaving
> 	  OF code unchanged according to v1 reviews
> 
> The ACPI IORT table provides information that allows instantiating
> ARM SMMU devices and carrying out id mappings between components on
> ARM based systems (devices, IOMMUs, interrupt controllers).
> 
> http://infocenter.arm.com/help/topic/com.arm.doc.den0049b/DEN0049B_IO_Remapping_Table.pdf
> 
> Building on basic IORT support, available through [2]:
> 
> this patchset enables ARM SMMU v3 support on ACPI systems.
> 
> Most of the code is aimed at building the required generic ACPI
> infrastructure to create and enable IOMMU components and to bring
> the IOMMU infrastructure for ACPI on par with DT, which is going to
> make future ARM SMMU components easier to integrate.
> 
> PATCH (1) adds a FWNODE_IOMMU type to the struct fwnode_handle type.
>           It is required to attach a fwnode identifier to platform
>           devices allocated/detected through IORT tables entries;
>           IOMMU devices have to have an identifier to look them up
>           eg IOMMU core layer carrying out id translation. This can be
>           done through a fwnode_handle (ie IOMMU platform devices created
>           out of IORT tables are not ACPI devices hence they can't be
>           allocated as such, otherwise they would have a fwnode_handle of
>           type FWNODE_ACPI). This patch requires discussion and it is key
>           to the RFC.
> 
> PATCH (2) makes use of the ACPI early probing API to add a linker script
>           section for probing devices via IORT ACPI kernel code.
> 
> PATCH (3) provides IORT support for registering IOMMU IORT node through
>           their fwnode handle.
> 
> PATCH (4) implements core code fwnode based platform devices look-up.
> 
> PATCH (5) extends iommu_fwspec so that it can be used on ACPI based
>           system by creating a generic IOMMU fwspec kernel layer.
> 
> PATCH (6) implements the of_dma_configure() API in ACPI world -
>           acpi_dma_configure() - and patches PCI and ACPI core code to
>           start making use of it.
> 
> PATCH (7) provides an IORT function to detect existence of specific type
>           of IORT components.
> 
> PATCH (8) creates the kernel infrastructure required to create ARM SMMU
>           platform devices for IORT nodes.
> 
> PATCH (9) refactors the ARM SMMU v3 driver so that the init functions are
>           split in a way that groups together code that probes through DT
>           and code that carries out HW registers FW agnostic probing, in
>           preparation for adding the ACPI probing path.
> 
> PATCH (10) rework ARM SMMU v3 platform driver registration to make it work
>            on ACPI systems.
> 
> PATCH (11) Building on patch (8), it adds ARM SMMU v3 IORT IOMMU
>            operations to create and probe ARM SMMU v3 components.
> 
> PATCH (12) Extend the IORT iort_node_map_rid() to work on a type mask
>            instead of a single type so that the translation API can
>            be used on a range of components.
> 
> PATCH (13) provides IORT infrastructure to carry out IOMMU configuration
>            for devices and hook it up to the previously introduced ACPI
>            DMA configure API.
> 
> This patchset is built on top and depends on these three patch series:
> 
> [1] R.Murphy "Generic DT bindings for PCI and ARM SMMU v3" v4
>     https://marc.info/?l=devicetree&m=146739193215518&w=2
> 
> [2] T.Nowicki "Introduce ACPI world to ITS irqchip" v7
>     https://marc.info/?l=linux-arm-kernel&m=146642080022289&w=2
> 
> [3] T.Nowicki "Support for ARM64 ACPI based PCI host controller" v8
>     http://marc.info/?l=linux-acpi&m=146462129816292&w=2
> 
> and is provided for early review/testing purposes here:
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git acpi/iort-smmu-v3i
>
I thought I can got all the 13 patches applied with the above git tree, but I can't find
any ACPI related stuff after I cloned the git repos to my local machine, am I missing
something here?

Thanks,
Dennis
> 
> Tested on FVP models for ARM SMMU v3 probing path.
> 
> Lorenzo Pieralisi (13):
>   drivers: iommu: add FWNODE_IOMMU fwnode type
>   drivers: acpi: iort: introduce linker section for IORT entries probing
>   drivers: acpi: iort: add support for IOMMU fwnode registration
>   drivers: platform: add fwnode base platform devices retrieval
>   drivers: iommu: make iommu_fwspec OF agnostic
>   drivers: acpi: implement acpi_dma_configure
>   drivers: acpi: iort: add node match function
>   drivers: acpi: iort: add support for ARM SMMU platform devices
>     creation
>   drivers: iommu: arm-smmu-v3: split probe functions into DT/generic
>     portions
>   drivers: iommu: arm-smmu-v3: enable ACPI driver initialization
>   drivers: iommu: arm-smmu-v3: add IORT platform device creation
>   drivers: acpi: iort: replace rid map type with type mask
>   drivers: acpi: iort: introduce iort_iommu_configure
> 
>  drivers/acpi/glue.c               |   4 +-
>  drivers/acpi/iort.c               | 360 +++++++++++++++++++++++++++++++++++++-
>  drivers/acpi/scan.c               |  29 +++
>  drivers/base/platform.c           |  23 +++
>  drivers/iommu/Kconfig             |   4 +
>  drivers/iommu/Makefile            |   1 +
>  drivers/iommu/arm-smmu-v3.c       | 147 ++++++++++++++--
>  drivers/iommu/iommu-fwspec.c      | 114 ++++++++++++
>  drivers/iommu/of_iommu.c          |  52 ------
>  drivers/pci/probe.c               |   3 +-
>  include/acpi/acpi_bus.h           |   2 +
>  include/asm-generic/vmlinux.lds.h |   1 +
>  include/linux/acpi.h              |   5 +
>  include/linux/fwnode.h            |   1 +
>  include/linux/iommu-fwspec.h      |  60 +++++++
>  include/linux/iommu.h             |  25 +++
>  include/linux/iort.h              |  19 ++
>  include/linux/of_iommu.h          |  24 +--
>  include/linux/platform_device.h   |   3 +
>  19 files changed, 782 insertions(+), 95 deletions(-)
>  create mode 100644 drivers/iommu/iommu-fwspec.c
>  create mode 100644 include/linux/iommu-fwspec.h
> 
> -- 
> 2.6.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* [RFC PATCH v3 00/13] ACPI IORT ARM SMMU v3 support
@ 2016-07-25  5:53     ` Dennis Chen
  0 siblings, 0 replies; 72+ messages in thread
From: Dennis Chen @ 2016-07-25  5:53 UTC (permalink / raw)
  To: linux-arm-kernel

Hi
On Wed, Jul 20, 2016 at 12:23:22PM +0100, Lorenzo Pieralisi wrote:
> This RFC patch series is v3 of a previous posting:
> 
> https://lkml.org/lkml/2016/6/7/523
> 
> v2 -> v3
> 	- Rebased on top of dependencies series [1][2][3](v4.7-rc3)
> 	- Added back reliance on ACPI early probing infrastructure
> 	- Patch[1-3] merged through other dependent series
> 	- Added back IOMMU fwnode generalization
> 	- Move SMMU v3 static functions configuration to IORT code
> 	- Implemented generic IOMMU fwspec API
> 	- Added code to implement fwnode platform device look-up
> 
> v1 -> v2:
> 	- Rebased on top of dependencies series [1][2][3](v4.7-rc1)
> 	- Removed IOMMU fwnode generalization
> 	- Implemented ARM SMMU v3 ACPI probing instead of ARM SMMU v2
> 	  owing to patch series dependencies [1]
> 	- Moved platform device creation logic to IORT code to
> 	  generalize its usage for ARM SMMU v1-v2-v3 components
> 	- Removed reliance on ACPI early device probing
> 	- Created IORT specific iommu_xlate() translation hook leaving
> 	  OF code unchanged according to v1 reviews
> 
> The ACPI IORT table provides information that allows instantiating
> ARM SMMU devices and carrying out id mappings between components on
> ARM based systems (devices, IOMMUs, interrupt controllers).
> 
> http://infocenter.arm.com/help/topic/com.arm.doc.den0049b/DEN0049B_IO_Remapping_Table.pdf
> 
> Building on basic IORT support, available through [2]:
> 
> this patchset enables ARM SMMU v3 support on ACPI systems.
> 
> Most of the code is aimed at building the required generic ACPI
> infrastructure to create and enable IOMMU components and to bring
> the IOMMU infrastructure for ACPI on par with DT, which is going to
> make future ARM SMMU components easier to integrate.
> 
> PATCH (1) adds a FWNODE_IOMMU type to the struct fwnode_handle type.
>           It is required to attach a fwnode identifier to platform
>           devices allocated/detected through IORT tables entries;
>           IOMMU devices have to have an identifier to look them up
>           eg IOMMU core layer carrying out id translation. This can be
>           done through a fwnode_handle (ie IOMMU platform devices created
>           out of IORT tables are not ACPI devices hence they can't be
>           allocated as such, otherwise they would have a fwnode_handle of
>           type FWNODE_ACPI). This patch requires discussion and it is key
>           to the RFC.
> 
> PATCH (2) makes use of the ACPI early probing API to add a linker script
>           section for probing devices via IORT ACPI kernel code.
> 
> PATCH (3) provides IORT support for registering IOMMU IORT node through
>           their fwnode handle.
> 
> PATCH (4) implements core code fwnode based platform devices look-up.
> 
> PATCH (5) extends iommu_fwspec so that it can be used on ACPI based
>           system by creating a generic IOMMU fwspec kernel layer.
> 
> PATCH (6) implements the of_dma_configure() API in ACPI world -
>           acpi_dma_configure() - and patches PCI and ACPI core code to
>           start making use of it.
> 
> PATCH (7) provides an IORT function to detect existence of specific type
>           of IORT components.
> 
> PATCH (8) creates the kernel infrastructure required to create ARM SMMU
>           platform devices for IORT nodes.
> 
> PATCH (9) refactors the ARM SMMU v3 driver so that the init functions are
>           split in a way that groups together code that probes through DT
>           and code that carries out HW registers FW agnostic probing, in
>           preparation for adding the ACPI probing path.
> 
> PATCH (10) rework ARM SMMU v3 platform driver registration to make it work
>            on ACPI systems.
> 
> PATCH (11) Building on patch (8), it adds ARM SMMU v3 IORT IOMMU
>            operations to create and probe ARM SMMU v3 components.
> 
> PATCH (12) Extend the IORT iort_node_map_rid() to work on a type mask
>            instead of a single type so that the translation API can
>            be used on a range of components.
> 
> PATCH (13) provides IORT infrastructure to carry out IOMMU configuration
>            for devices and hook it up to the previously introduced ACPI
>            DMA configure API.
> 
> This patchset is built on top and depends on these three patch series:
> 
> [1] R.Murphy "Generic DT bindings for PCI and ARM SMMU v3" v4
>     https://marc.info/?l=devicetree&m=146739193215518&w=2
> 
> [2] T.Nowicki "Introduce ACPI world to ITS irqchip" v7
>     https://marc.info/?l=linux-arm-kernel&m=146642080022289&w=2
> 
> [3] T.Nowicki "Support for ARM64 ACPI based PCI host controller" v8
>     http://marc.info/?l=linux-acpi&m=146462129816292&w=2
> 
> and is provided for early review/testing purposes here:
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git acpi/iort-smmu-v3i
>
I thought I can got all the 13 patches applied with the above git tree, but I can't find
any ACPI related stuff after I cloned the git repos to my local machine, am I missing
something here?

Thanks,
Dennis
> 
> Tested on FVP models for ARM SMMU v3 probing path.
> 
> Lorenzo Pieralisi (13):
>   drivers: iommu: add FWNODE_IOMMU fwnode type
>   drivers: acpi: iort: introduce linker section for IORT entries probing
>   drivers: acpi: iort: add support for IOMMU fwnode registration
>   drivers: platform: add fwnode base platform devices retrieval
>   drivers: iommu: make iommu_fwspec OF agnostic
>   drivers: acpi: implement acpi_dma_configure
>   drivers: acpi: iort: add node match function
>   drivers: acpi: iort: add support for ARM SMMU platform devices
>     creation
>   drivers: iommu: arm-smmu-v3: split probe functions into DT/generic
>     portions
>   drivers: iommu: arm-smmu-v3: enable ACPI driver initialization
>   drivers: iommu: arm-smmu-v3: add IORT platform device creation
>   drivers: acpi: iort: replace rid map type with type mask
>   drivers: acpi: iort: introduce iort_iommu_configure
> 
>  drivers/acpi/glue.c               |   4 +-
>  drivers/acpi/iort.c               | 360 +++++++++++++++++++++++++++++++++++++-
>  drivers/acpi/scan.c               |  29 +++
>  drivers/base/platform.c           |  23 +++
>  drivers/iommu/Kconfig             |   4 +
>  drivers/iommu/Makefile            |   1 +
>  drivers/iommu/arm-smmu-v3.c       | 147 ++++++++++++++--
>  drivers/iommu/iommu-fwspec.c      | 114 ++++++++++++
>  drivers/iommu/of_iommu.c          |  52 ------
>  drivers/pci/probe.c               |   3 +-
>  include/acpi/acpi_bus.h           |   2 +
>  include/asm-generic/vmlinux.lds.h |   1 +
>  include/linux/acpi.h              |   5 +
>  include/linux/fwnode.h            |   1 +
>  include/linux/iommu-fwspec.h      |  60 +++++++
>  include/linux/iommu.h             |  25 +++
>  include/linux/iort.h              |  19 ++
>  include/linux/of_iommu.h          |  24 +--
>  include/linux/platform_device.h   |   3 +
>  19 files changed, 782 insertions(+), 95 deletions(-)
>  create mode 100644 drivers/iommu/iommu-fwspec.c
>  create mode 100644 include/linux/iommu-fwspec.h
> 
> -- 
> 2.6.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [RFC PATCH v3 00/13] ACPI IORT ARM SMMU v3 support
  2016-07-25  5:53     ` Dennis Chen
  (?)
@ 2016-07-25  8:36         ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-25  8:36 UTC (permalink / raw)
  To: Dennis Chen
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Marc Zyngier,
	Rafael J. Wysocki, Will Deacon,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA, Sinan Kaya,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Hanjun Guo,
	Tomasz Nowicki, nd-5wv7dgnIgG8, Jon Masters

On Mon, Jul 25, 2016 at 01:53:32PM +0800, Dennis Chen wrote:
> Hi
> On Wed, Jul 20, 2016 at 12:23:22PM +0100, Lorenzo Pieralisi wrote:
> > This RFC patch series is v3 of a previous posting:
> > 
> > https://lkml.org/lkml/2016/6/7/523
> > 
> > v2 -> v3
> > 	- Rebased on top of dependencies series [1][2][3](v4.7-rc3)
> > 	- Added back reliance on ACPI early probing infrastructure
> > 	- Patch[1-3] merged through other dependent series
> > 	- Added back IOMMU fwnode generalization
> > 	- Move SMMU v3 static functions configuration to IORT code
> > 	- Implemented generic IOMMU fwspec API
> > 	- Added code to implement fwnode platform device look-up
> > 
> > v1 -> v2:
> > 	- Rebased on top of dependencies series [1][2][3](v4.7-rc1)
> > 	- Removed IOMMU fwnode generalization
> > 	- Implemented ARM SMMU v3 ACPI probing instead of ARM SMMU v2
> > 	  owing to patch series dependencies [1]
> > 	- Moved platform device creation logic to IORT code to
> > 	  generalize its usage for ARM SMMU v1-v2-v3 components
> > 	- Removed reliance on ACPI early device probing
> > 	- Created IORT specific iommu_xlate() translation hook leaving
> > 	  OF code unchanged according to v1 reviews
> > 
> > The ACPI IORT table provides information that allows instantiating
> > ARM SMMU devices and carrying out id mappings between components on
> > ARM based systems (devices, IOMMUs, interrupt controllers).
> > 
> > http://infocenter.arm.com/help/topic/com.arm.doc.den0049b/DEN0049B_IO_Remapping_Table.pdf
> > 
> > Building on basic IORT support, available through [2]:
> > 
> > this patchset enables ARM SMMU v3 support on ACPI systems.
> > 
> > Most of the code is aimed at building the required generic ACPI
> > infrastructure to create and enable IOMMU components and to bring
> > the IOMMU infrastructure for ACPI on par with DT, which is going to
> > make future ARM SMMU components easier to integrate.
> > 
> > PATCH (1) adds a FWNODE_IOMMU type to the struct fwnode_handle type.
> >           It is required to attach a fwnode identifier to platform
> >           devices allocated/detected through IORT tables entries;
> >           IOMMU devices have to have an identifier to look them up
> >           eg IOMMU core layer carrying out id translation. This can be
> >           done through a fwnode_handle (ie IOMMU platform devices created
> >           out of IORT tables are not ACPI devices hence they can't be
> >           allocated as such, otherwise they would have a fwnode_handle of
> >           type FWNODE_ACPI). This patch requires discussion and it is key
> >           to the RFC.
> > 
> > PATCH (2) makes use of the ACPI early probing API to add a linker script
> >           section for probing devices via IORT ACPI kernel code.
> > 
> > PATCH (3) provides IORT support for registering IOMMU IORT node through
> >           their fwnode handle.
> > 
> > PATCH (4) implements core code fwnode based platform devices look-up.
> > 
> > PATCH (5) extends iommu_fwspec so that it can be used on ACPI based
> >           system by creating a generic IOMMU fwspec kernel layer.
> > 
> > PATCH (6) implements the of_dma_configure() API in ACPI world -
> >           acpi_dma_configure() - and patches PCI and ACPI core code to
> >           start making use of it.
> > 
> > PATCH (7) provides an IORT function to detect existence of specific type
> >           of IORT components.
> > 
> > PATCH (8) creates the kernel infrastructure required to create ARM SMMU
> >           platform devices for IORT nodes.
> > 
> > PATCH (9) refactors the ARM SMMU v3 driver so that the init functions are
> >           split in a way that groups together code that probes through DT
> >           and code that carries out HW registers FW agnostic probing, in
> >           preparation for adding the ACPI probing path.
> > 
> > PATCH (10) rework ARM SMMU v3 platform driver registration to make it work
> >            on ACPI systems.
> > 
> > PATCH (11) Building on patch (8), it adds ARM SMMU v3 IORT IOMMU
> >            operations to create and probe ARM SMMU v3 components.
> > 
> > PATCH (12) Extend the IORT iort_node_map_rid() to work on a type mask
> >            instead of a single type so that the translation API can
> >            be used on a range of components.
> > 
> > PATCH (13) provides IORT infrastructure to carry out IOMMU configuration
> >            for devices and hook it up to the previously introduced ACPI
> >            DMA configure API.
> > 
> > This patchset is built on top and depends on these three patch series:
> > 
> > [1] R.Murphy "Generic DT bindings for PCI and ARM SMMU v3" v4
> >     https://marc.info/?l=devicetree&m=146739193215518&w=2
> > 
> > [2] T.Nowicki "Introduce ACPI world to ITS irqchip" v7
> >     https://marc.info/?l=linux-arm-kernel&m=146642080022289&w=2
> > 
> > [3] T.Nowicki "Support for ARM64 ACPI based PCI host controller" v8
> >     http://marc.info/?l=linux-acpi&m=146462129816292&w=2
> > 
> > and is provided for early review/testing purposes here:
> > 
> > git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git acpi/iort-smmu-v3i
> >
> I thought I can got all the 13 patches applied with the above git
> tree, but I can't find any ACPI related stuff after I cloned the git
> repos to my local machine, am I missing something here?

Have you pulled the acpi/iort-smmu-v3 branch ?

Thanks,
Lorenzo

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

* Re: [RFC PATCH v3 00/13] ACPI IORT ARM SMMU v3 support
@ 2016-07-25  8:36         ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-25  8:36 UTC (permalink / raw)
  To: Dennis Chen
  Cc: iommu, Will Deacon, Marc Zyngier, Robin Murphy, Joerg Roedel,
	Rafael J. Wysocki, Tomasz Nowicki, Hanjun Guo, Jon Masters,
	Sinan Kaya, linux-acpi, linux-pci, linux-kernel,
	linux-arm-kernel, nd

On Mon, Jul 25, 2016 at 01:53:32PM +0800, Dennis Chen wrote:
> Hi
> On Wed, Jul 20, 2016 at 12:23:22PM +0100, Lorenzo Pieralisi wrote:
> > This RFC patch series is v3 of a previous posting:
> > 
> > https://lkml.org/lkml/2016/6/7/523
> > 
> > v2 -> v3
> > 	- Rebased on top of dependencies series [1][2][3](v4.7-rc3)
> > 	- Added back reliance on ACPI early probing infrastructure
> > 	- Patch[1-3] merged through other dependent series
> > 	- Added back IOMMU fwnode generalization
> > 	- Move SMMU v3 static functions configuration to IORT code
> > 	- Implemented generic IOMMU fwspec API
> > 	- Added code to implement fwnode platform device look-up
> > 
> > v1 -> v2:
> > 	- Rebased on top of dependencies series [1][2][3](v4.7-rc1)
> > 	- Removed IOMMU fwnode generalization
> > 	- Implemented ARM SMMU v3 ACPI probing instead of ARM SMMU v2
> > 	  owing to patch series dependencies [1]
> > 	- Moved platform device creation logic to IORT code to
> > 	  generalize its usage for ARM SMMU v1-v2-v3 components
> > 	- Removed reliance on ACPI early device probing
> > 	- Created IORT specific iommu_xlate() translation hook leaving
> > 	  OF code unchanged according to v1 reviews
> > 
> > The ACPI IORT table provides information that allows instantiating
> > ARM SMMU devices and carrying out id mappings between components on
> > ARM based systems (devices, IOMMUs, interrupt controllers).
> > 
> > http://infocenter.arm.com/help/topic/com.arm.doc.den0049b/DEN0049B_IO_Remapping_Table.pdf
> > 
> > Building on basic IORT support, available through [2]:
> > 
> > this patchset enables ARM SMMU v3 support on ACPI systems.
> > 
> > Most of the code is aimed at building the required generic ACPI
> > infrastructure to create and enable IOMMU components and to bring
> > the IOMMU infrastructure for ACPI on par with DT, which is going to
> > make future ARM SMMU components easier to integrate.
> > 
> > PATCH (1) adds a FWNODE_IOMMU type to the struct fwnode_handle type.
> >           It is required to attach a fwnode identifier to platform
> >           devices allocated/detected through IORT tables entries;
> >           IOMMU devices have to have an identifier to look them up
> >           eg IOMMU core layer carrying out id translation. This can be
> >           done through a fwnode_handle (ie IOMMU platform devices created
> >           out of IORT tables are not ACPI devices hence they can't be
> >           allocated as such, otherwise they would have a fwnode_handle of
> >           type FWNODE_ACPI). This patch requires discussion and it is key
> >           to the RFC.
> > 
> > PATCH (2) makes use of the ACPI early probing API to add a linker script
> >           section for probing devices via IORT ACPI kernel code.
> > 
> > PATCH (3) provides IORT support for registering IOMMU IORT node through
> >           their fwnode handle.
> > 
> > PATCH (4) implements core code fwnode based platform devices look-up.
> > 
> > PATCH (5) extends iommu_fwspec so that it can be used on ACPI based
> >           system by creating a generic IOMMU fwspec kernel layer.
> > 
> > PATCH (6) implements the of_dma_configure() API in ACPI world -
> >           acpi_dma_configure() - and patches PCI and ACPI core code to
> >           start making use of it.
> > 
> > PATCH (7) provides an IORT function to detect existence of specific type
> >           of IORT components.
> > 
> > PATCH (8) creates the kernel infrastructure required to create ARM SMMU
> >           platform devices for IORT nodes.
> > 
> > PATCH (9) refactors the ARM SMMU v3 driver so that the init functions are
> >           split in a way that groups together code that probes through DT
> >           and code that carries out HW registers FW agnostic probing, in
> >           preparation for adding the ACPI probing path.
> > 
> > PATCH (10) rework ARM SMMU v3 platform driver registration to make it work
> >            on ACPI systems.
> > 
> > PATCH (11) Building on patch (8), it adds ARM SMMU v3 IORT IOMMU
> >            operations to create and probe ARM SMMU v3 components.
> > 
> > PATCH (12) Extend the IORT iort_node_map_rid() to work on a type mask
> >            instead of a single type so that the translation API can
> >            be used on a range of components.
> > 
> > PATCH (13) provides IORT infrastructure to carry out IOMMU configuration
> >            for devices and hook it up to the previously introduced ACPI
> >            DMA configure API.
> > 
> > This patchset is built on top and depends on these three patch series:
> > 
> > [1] R.Murphy "Generic DT bindings for PCI and ARM SMMU v3" v4
> >     https://marc.info/?l=devicetree&m=146739193215518&w=2
> > 
> > [2] T.Nowicki "Introduce ACPI world to ITS irqchip" v7
> >     https://marc.info/?l=linux-arm-kernel&m=146642080022289&w=2
> > 
> > [3] T.Nowicki "Support for ARM64 ACPI based PCI host controller" v8
> >     http://marc.info/?l=linux-acpi&m=146462129816292&w=2
> > 
> > and is provided for early review/testing purposes here:
> > 
> > git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git acpi/iort-smmu-v3i
> >
> I thought I can got all the 13 patches applied with the above git
> tree, but I can't find any ACPI related stuff after I cloned the git
> repos to my local machine, am I missing something here?

Have you pulled the acpi/iort-smmu-v3 branch ?

Thanks,
Lorenzo

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

* [RFC PATCH v3 00/13] ACPI IORT ARM SMMU v3 support
@ 2016-07-25  8:36         ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-25  8:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2016 at 01:53:32PM +0800, Dennis Chen wrote:
> Hi
> On Wed, Jul 20, 2016 at 12:23:22PM +0100, Lorenzo Pieralisi wrote:
> > This RFC patch series is v3 of a previous posting:
> > 
> > https://lkml.org/lkml/2016/6/7/523
> > 
> > v2 -> v3
> > 	- Rebased on top of dependencies series [1][2][3](v4.7-rc3)
> > 	- Added back reliance on ACPI early probing infrastructure
> > 	- Patch[1-3] merged through other dependent series
> > 	- Added back IOMMU fwnode generalization
> > 	- Move SMMU v3 static functions configuration to IORT code
> > 	- Implemented generic IOMMU fwspec API
> > 	- Added code to implement fwnode platform device look-up
> > 
> > v1 -> v2:
> > 	- Rebased on top of dependencies series [1][2][3](v4.7-rc1)
> > 	- Removed IOMMU fwnode generalization
> > 	- Implemented ARM SMMU v3 ACPI probing instead of ARM SMMU v2
> > 	  owing to patch series dependencies [1]
> > 	- Moved platform device creation logic to IORT code to
> > 	  generalize its usage for ARM SMMU v1-v2-v3 components
> > 	- Removed reliance on ACPI early device probing
> > 	- Created IORT specific iommu_xlate() translation hook leaving
> > 	  OF code unchanged according to v1 reviews
> > 
> > The ACPI IORT table provides information that allows instantiating
> > ARM SMMU devices and carrying out id mappings between components on
> > ARM based systems (devices, IOMMUs, interrupt controllers).
> > 
> > http://infocenter.arm.com/help/topic/com.arm.doc.den0049b/DEN0049B_IO_Remapping_Table.pdf
> > 
> > Building on basic IORT support, available through [2]:
> > 
> > this patchset enables ARM SMMU v3 support on ACPI systems.
> > 
> > Most of the code is aimed at building the required generic ACPI
> > infrastructure to create and enable IOMMU components and to bring
> > the IOMMU infrastructure for ACPI on par with DT, which is going to
> > make future ARM SMMU components easier to integrate.
> > 
> > PATCH (1) adds a FWNODE_IOMMU type to the struct fwnode_handle type.
> >           It is required to attach a fwnode identifier to platform
> >           devices allocated/detected through IORT tables entries;
> >           IOMMU devices have to have an identifier to look them up
> >           eg IOMMU core layer carrying out id translation. This can be
> >           done through a fwnode_handle (ie IOMMU platform devices created
> >           out of IORT tables are not ACPI devices hence they can't be
> >           allocated as such, otherwise they would have a fwnode_handle of
> >           type FWNODE_ACPI). This patch requires discussion and it is key
> >           to the RFC.
> > 
> > PATCH (2) makes use of the ACPI early probing API to add a linker script
> >           section for probing devices via IORT ACPI kernel code.
> > 
> > PATCH (3) provides IORT support for registering IOMMU IORT node through
> >           their fwnode handle.
> > 
> > PATCH (4) implements core code fwnode based platform devices look-up.
> > 
> > PATCH (5) extends iommu_fwspec so that it can be used on ACPI based
> >           system by creating a generic IOMMU fwspec kernel layer.
> > 
> > PATCH (6) implements the of_dma_configure() API in ACPI world -
> >           acpi_dma_configure() - and patches PCI and ACPI core code to
> >           start making use of it.
> > 
> > PATCH (7) provides an IORT function to detect existence of specific type
> >           of IORT components.
> > 
> > PATCH (8) creates the kernel infrastructure required to create ARM SMMU
> >           platform devices for IORT nodes.
> > 
> > PATCH (9) refactors the ARM SMMU v3 driver so that the init functions are
> >           split in a way that groups together code that probes through DT
> >           and code that carries out HW registers FW agnostic probing, in
> >           preparation for adding the ACPI probing path.
> > 
> > PATCH (10) rework ARM SMMU v3 platform driver registration to make it work
> >            on ACPI systems.
> > 
> > PATCH (11) Building on patch (8), it adds ARM SMMU v3 IORT IOMMU
> >            operations to create and probe ARM SMMU v3 components.
> > 
> > PATCH (12) Extend the IORT iort_node_map_rid() to work on a type mask
> >            instead of a single type so that the translation API can
> >            be used on a range of components.
> > 
> > PATCH (13) provides IORT infrastructure to carry out IOMMU configuration
> >            for devices and hook it up to the previously introduced ACPI
> >            DMA configure API.
> > 
> > This patchset is built on top and depends on these three patch series:
> > 
> > [1] R.Murphy "Generic DT bindings for PCI and ARM SMMU v3" v4
> >     https://marc.info/?l=devicetree&m=146739193215518&w=2
> > 
> > [2] T.Nowicki "Introduce ACPI world to ITS irqchip" v7
> >     https://marc.info/?l=linux-arm-kernel&m=146642080022289&w=2
> > 
> > [3] T.Nowicki "Support for ARM64 ACPI based PCI host controller" v8
> >     http://marc.info/?l=linux-acpi&m=146462129816292&w=2
> > 
> > and is provided for early review/testing purposes here:
> > 
> > git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git acpi/iort-smmu-v3i
> >
> I thought I can got all the 13 patches applied with the above git
> tree, but I can't find any ACPI related stuff after I cloned the git
> repos to my local machine, am I missing something here?

Have you pulled the acpi/iort-smmu-v3 branch ?

Thanks,
Lorenzo

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

* Re: [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
  2016-07-20 11:23     ` Lorenzo Pieralisi
@ 2016-07-25 15:09       ` Robin Murphy
  -1 siblings, 0 replies; 72+ messages in thread
From: Robin Murphy @ 2016-07-25 15:09 UTC (permalink / raw)
  To: Lorenzo Pieralisi, iommu
  Cc: Will Deacon, Hanjun Guo, Joerg Roedel, Marc Zyngier,
	Rafael J. Wysocki, Tomasz Nowicki, Jon Masters, Sinan Kaya,
	linux-acpi, linux-pci, linux-kernel, linux-arm-kernel

Hi Lorenzo,

On 20/07/16 12:23, Lorenzo Pieralisi wrote:
> The iommu_fwspec structure, used to hold per device iommu configuration
> data is not OF specific and therefore can be moved to a generic
> and OF independent compilation unit.
> 
> In particular, the iommu_fwspec handling hinges on the device_node
> pointer to identify the IOMMU device associated with the iommu_fwspec
> structure, that is easily converted to a more generic fwnode_handle
> pointer that can cater for OF and non-OF (ie ACPI) systems.
> 
> Create the files and related Kconfig entry to decouple iommu_fwspec
> structure from the OF iommu kernel layer.
> 
> Given that the current iommu_fwspec implementation relies on
> the arch specific struct device.archdata.iommu field in its
> implementation, by making the code standalone and independent
> of the OF layer this patch makes sure that the iommu_fwspec
> kernel code can be selected only on arches implementing the
> struct device.archdata.iommu field by adding an explicit
> arch dependency in its config entry.
> 
> Current drivers using the iommu_fwspec for streamid translation
> are converted to the new iommu_fwspec API by simply converting
> the device_node to its fwnode_handle pointer.
> 
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Hanjun Guo <hanjun.guo@linaro.org>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Joerg Roedel <joro@8bytes.org>
> ---
>  drivers/iommu/Kconfig        |   4 ++
>  drivers/iommu/Makefile       |   1 +
>  drivers/iommu/arm-smmu-v3.c  |  13 +++--
>  drivers/iommu/iommu-fwspec.c | 114 +++++++++++++++++++++++++++++++++++++++++++
>  drivers/iommu/of_iommu.c     |  52 --------------------
>  include/linux/iommu-fwspec.h |  60 +++++++++++++++++++++++
>  include/linux/of_iommu.h     |  24 +++------
>  7 files changed, 196 insertions(+), 72 deletions(-)
>  create mode 100644 drivers/iommu/iommu-fwspec.c
>  create mode 100644 include/linux/iommu-fwspec.h
> 
> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> index d1c66af..2b26bfb 100644
> --- a/drivers/iommu/Kconfig
> +++ b/drivers/iommu/Kconfig
> @@ -67,6 +67,10 @@ config OF_IOMMU
>         def_bool y
>         depends on OF && IOMMU_API
>  
> +config IOMMU_FWSPEC
> +       def_bool y
> +       depends on ARM64 && IOMMU_API

I think that could be at least (ARM || ARM64).

> +
>  # IOMMU-agnostic DMA-mapping layer
>  config IOMMU_DMA
>  	bool

[...]

> diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
> index 308791f..2362232 100644
> --- a/include/linux/of_iommu.h
> +++ b/include/linux/of_iommu.h
> @@ -15,13 +15,8 @@ extern void of_iommu_init(void);
>  extern const struct iommu_ops *of_iommu_configure(struct device *dev,
>  					struct device_node *master_np);
>  
> -struct iommu_fwspec {
> -	const struct iommu_ops	*iommu_ops;
> -	struct device_node	*iommu_np;
> -	void			*iommu_priv;
> -	unsigned int		num_ids;
> -	u32			ids[];
> -};
> +void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
> +const struct iommu_ops *of_iommu_get_ops(struct device_node *np);

Is there some reason we need to retain the existing definitions of
these? I was assuming we'd be able to move the entire implementation
over to the fwspec code and leave behind nothing more than trivial
wrappers, e.g.:

#define of_iommu_get_ops(np) iommu_fwspec_get_ops(&(np)->fwnode_handle)

Robin.

>  #else
>  
> @@ -39,17 +34,14 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
>  	return NULL;
>  }
>  
> -struct iommu_fwspec;
> -
> -#endif	/* CONFIG_OF_IOMMU */
> +static inline void of_iommu_set_ops(struct device_node *np,
> +				    const struct iommu_ops *ops)
> +{ }
>  
> -int iommu_fwspec_init(struct device *dev, struct device_node *iommu_np);
> -void iommu_fwspec_free(struct device *dev);
> -int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
> -struct iommu_fwspec *dev_iommu_fwspec(struct device *dev);
> +static inline const struct iommu_ops *
> +of_iommu_get_ops(struct device_node *np) { return NULL; }
>  
> -void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
> -const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
> +#endif	/* CONFIG_OF_IOMMU */
>  
>  extern struct of_device_id __iommu_of_table;
>  
> 


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

* [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
@ 2016-07-25 15:09       ` Robin Murphy
  0 siblings, 0 replies; 72+ messages in thread
From: Robin Murphy @ 2016-07-25 15:09 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Lorenzo,

On 20/07/16 12:23, Lorenzo Pieralisi wrote:
> The iommu_fwspec structure, used to hold per device iommu configuration
> data is not OF specific and therefore can be moved to a generic
> and OF independent compilation unit.
> 
> In particular, the iommu_fwspec handling hinges on the device_node
> pointer to identify the IOMMU device associated with the iommu_fwspec
> structure, that is easily converted to a more generic fwnode_handle
> pointer that can cater for OF and non-OF (ie ACPI) systems.
> 
> Create the files and related Kconfig entry to decouple iommu_fwspec
> structure from the OF iommu kernel layer.
> 
> Given that the current iommu_fwspec implementation relies on
> the arch specific struct device.archdata.iommu field in its
> implementation, by making the code standalone and independent
> of the OF layer this patch makes sure that the iommu_fwspec
> kernel code can be selected only on arches implementing the
> struct device.archdata.iommu field by adding an explicit
> arch dependency in its config entry.
> 
> Current drivers using the iommu_fwspec for streamid translation
> are converted to the new iommu_fwspec API by simply converting
> the device_node to its fwnode_handle pointer.
> 
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Hanjun Guo <hanjun.guo@linaro.org>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Joerg Roedel <joro@8bytes.org>
> ---
>  drivers/iommu/Kconfig        |   4 ++
>  drivers/iommu/Makefile       |   1 +
>  drivers/iommu/arm-smmu-v3.c  |  13 +++--
>  drivers/iommu/iommu-fwspec.c | 114 +++++++++++++++++++++++++++++++++++++++++++
>  drivers/iommu/of_iommu.c     |  52 --------------------
>  include/linux/iommu-fwspec.h |  60 +++++++++++++++++++++++
>  include/linux/of_iommu.h     |  24 +++------
>  7 files changed, 196 insertions(+), 72 deletions(-)
>  create mode 100644 drivers/iommu/iommu-fwspec.c
>  create mode 100644 include/linux/iommu-fwspec.h
> 
> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> index d1c66af..2b26bfb 100644
> --- a/drivers/iommu/Kconfig
> +++ b/drivers/iommu/Kconfig
> @@ -67,6 +67,10 @@ config OF_IOMMU
>         def_bool y
>         depends on OF && IOMMU_API
>  
> +config IOMMU_FWSPEC
> +       def_bool y
> +       depends on ARM64 && IOMMU_API

I think that could be at least (ARM || ARM64).

> +
>  # IOMMU-agnostic DMA-mapping layer
>  config IOMMU_DMA
>  	bool

[...]

> diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
> index 308791f..2362232 100644
> --- a/include/linux/of_iommu.h
> +++ b/include/linux/of_iommu.h
> @@ -15,13 +15,8 @@ extern void of_iommu_init(void);
>  extern const struct iommu_ops *of_iommu_configure(struct device *dev,
>  					struct device_node *master_np);
>  
> -struct iommu_fwspec {
> -	const struct iommu_ops	*iommu_ops;
> -	struct device_node	*iommu_np;
> -	void			*iommu_priv;
> -	unsigned int		num_ids;
> -	u32			ids[];
> -};
> +void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
> +const struct iommu_ops *of_iommu_get_ops(struct device_node *np);

Is there some reason we need to retain the existing definitions of
these? I was assuming we'd be able to move the entire implementation
over to the fwspec code and leave behind nothing more than trivial
wrappers, e.g.:

#define of_iommu_get_ops(np) iommu_fwspec_get_ops(&(np)->fwnode_handle)

Robin.

>  #else
>  
> @@ -39,17 +34,14 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
>  	return NULL;
>  }
>  
> -struct iommu_fwspec;
> -
> -#endif	/* CONFIG_OF_IOMMU */
> +static inline void of_iommu_set_ops(struct device_node *np,
> +				    const struct iommu_ops *ops)
> +{ }
>  
> -int iommu_fwspec_init(struct device *dev, struct device_node *iommu_np);
> -void iommu_fwspec_free(struct device *dev);
> -int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
> -struct iommu_fwspec *dev_iommu_fwspec(struct device *dev);
> +static inline const struct iommu_ops *
> +of_iommu_get_ops(struct device_node *np) { return NULL; }
>  
> -void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
> -const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
> +#endif	/* CONFIG_OF_IOMMU */
>  
>  extern struct of_device_id __iommu_of_table;
>  
> 

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

* Re: [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
  2016-07-25 15:09       ` Robin Murphy
  (?)
  (?)
@ 2016-07-25 15:21           ` Rob Herring
  -1 siblings, 0 replies; 72+ messages in thread
From: Rob Herring @ 2016-07-25 15:21 UTC (permalink / raw)
  To: Robin Murphy
  Cc: Jon Masters, Marc Zyngier, Rafael J. Wysocki, Will Deacon,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Sinan Kaya,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA, Linux IOMMU, Hanjun Guo,
	linux-pci-u79uwXL29TY76Z2rM5mHXA, Tomasz Nowicki,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On Mon, Jul 25, 2016 at 10:09 AM, Robin Murphy <robin.murphy-5wv7dgnIgG8@public.gmane.org> wrote:
> Hi Lorenzo,
>
> On 20/07/16 12:23, Lorenzo Pieralisi wrote:
>> The iommu_fwspec structure, used to hold per device iommu configuration
>> data is not OF specific and therefore can be moved to a generic
>> and OF independent compilation unit.
>>
>> In particular, the iommu_fwspec handling hinges on the device_node
>> pointer to identify the IOMMU device associated with the iommu_fwspec
>> structure, that is easily converted to a more generic fwnode_handle
>> pointer that can cater for OF and non-OF (ie ACPI) systems.
>>
>> Create the files and related Kconfig entry to decouple iommu_fwspec
>> structure from the OF iommu kernel layer.
>>
>> Given that the current iommu_fwspec implementation relies on
>> the arch specific struct device.archdata.iommu field in its
>> implementation, by making the code standalone and independent
>> of the OF layer this patch makes sure that the iommu_fwspec
>> kernel code can be selected only on arches implementing the
>> struct device.archdata.iommu field by adding an explicit
>> arch dependency in its config entry.
>>
>> Current drivers using the iommu_fwspec for streamid translation
>> are converted to the new iommu_fwspec API by simply converting
>> the device_node to its fwnode_handle pointer.
>>
>> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
>> Cc: Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org>
>> Cc: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> Cc: Robin Murphy <robin.murphy-5wv7dgnIgG8@public.gmane.org>
>> Cc: Joerg Roedel <joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
>> ---
>>  drivers/iommu/Kconfig        |   4 ++
>>  drivers/iommu/Makefile       |   1 +
>>  drivers/iommu/arm-smmu-v3.c  |  13 +++--
>>  drivers/iommu/iommu-fwspec.c | 114 +++++++++++++++++++++++++++++++++++++++++++
>>  drivers/iommu/of_iommu.c     |  52 --------------------
>>  include/linux/iommu-fwspec.h |  60 +++++++++++++++++++++++
>>  include/linux/of_iommu.h     |  24 +++------
>>  7 files changed, 196 insertions(+), 72 deletions(-)
>>  create mode 100644 drivers/iommu/iommu-fwspec.c
>>  create mode 100644 include/linux/iommu-fwspec.h
>>
>> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
>> index d1c66af..2b26bfb 100644
>> --- a/drivers/iommu/Kconfig
>> +++ b/drivers/iommu/Kconfig
>> @@ -67,6 +67,10 @@ config OF_IOMMU
>>         def_bool y
>>         depends on OF && IOMMU_API
>>
>> +config IOMMU_FWSPEC
>> +       def_bool y
>> +       depends on ARM64 && IOMMU_API
>
> I think that could be at least (ARM || ARM64).

Why any arch dependency?

Seems like OF_IOMMU (and ACPI?) should select this.

Rob

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

* Re: [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
@ 2016-07-25 15:21           ` Rob Herring
  0 siblings, 0 replies; 72+ messages in thread
From: Rob Herring @ 2016-07-25 15:21 UTC (permalink / raw)
  To: Robin Murphy
  Cc: Lorenzo Pieralisi, Linux IOMMU, linux-arm-kernel, Marc Zyngier,
	Will Deacon, Joerg Roedel, Rafael J. Wysocki, linux-kernel,
	linux-pci, Sinan Kaya, linux-acpi, Hanjun Guo, Tomasz Nowicki,
	Jon Masters

On Mon, Jul 25, 2016 at 10:09 AM, Robin Murphy <robin.murphy@arm.com> wrote:
> Hi Lorenzo,
>
> On 20/07/16 12:23, Lorenzo Pieralisi wrote:
>> The iommu_fwspec structure, used to hold per device iommu configuration
>> data is not OF specific and therefore can be moved to a generic
>> and OF independent compilation unit.
>>
>> In particular, the iommu_fwspec handling hinges on the device_node
>> pointer to identify the IOMMU device associated with the iommu_fwspec
>> structure, that is easily converted to a more generic fwnode_handle
>> pointer that can cater for OF and non-OF (ie ACPI) systems.
>>
>> Create the files and related Kconfig entry to decouple iommu_fwspec
>> structure from the OF iommu kernel layer.
>>
>> Given that the current iommu_fwspec implementation relies on
>> the arch specific struct device.archdata.iommu field in its
>> implementation, by making the code standalone and independent
>> of the OF layer this patch makes sure that the iommu_fwspec
>> kernel code can be selected only on arches implementing the
>> struct device.archdata.iommu field by adding an explicit
>> arch dependency in its config entry.
>>
>> Current drivers using the iommu_fwspec for streamid translation
>> are converted to the new iommu_fwspec API by simply converting
>> the device_node to its fwnode_handle pointer.
>>
>> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Hanjun Guo <hanjun.guo@linaro.org>
>> Cc: Robin Murphy <robin.murphy@arm.com>
>> Cc: Joerg Roedel <joro@8bytes.org>
>> ---
>>  drivers/iommu/Kconfig        |   4 ++
>>  drivers/iommu/Makefile       |   1 +
>>  drivers/iommu/arm-smmu-v3.c  |  13 +++--
>>  drivers/iommu/iommu-fwspec.c | 114 +++++++++++++++++++++++++++++++++++++++++++
>>  drivers/iommu/of_iommu.c     |  52 --------------------
>>  include/linux/iommu-fwspec.h |  60 +++++++++++++++++++++++
>>  include/linux/of_iommu.h     |  24 +++------
>>  7 files changed, 196 insertions(+), 72 deletions(-)
>>  create mode 100644 drivers/iommu/iommu-fwspec.c
>>  create mode 100644 include/linux/iommu-fwspec.h
>>
>> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
>> index d1c66af..2b26bfb 100644
>> --- a/drivers/iommu/Kconfig
>> +++ b/drivers/iommu/Kconfig
>> @@ -67,6 +67,10 @@ config OF_IOMMU
>>         def_bool y
>>         depends on OF && IOMMU_API
>>
>> +config IOMMU_FWSPEC
>> +       def_bool y
>> +       depends on ARM64 && IOMMU_API
>
> I think that could be at least (ARM || ARM64).

Why any arch dependency?

Seems like OF_IOMMU (and ACPI?) should select this.

Rob

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

* Re: [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
@ 2016-07-25 15:21           ` Rob Herring
  0 siblings, 0 replies; 72+ messages in thread
From: Rob Herring @ 2016-07-25 15:21 UTC (permalink / raw)
  To: Robin Murphy
  Cc: Lorenzo Pieralisi, Linux IOMMU, linux-arm-kernel, Marc Zyngier,
	Will Deacon, Joerg Roedel, Rafael J. Wysocki, linux-kernel,
	linux-pci, Sinan Kaya, linux-acpi, Hanjun Guo, Tomasz Nowicki,
	Jon Masters

On Mon, Jul 25, 2016 at 10:09 AM, Robin Murphy <robin.murphy@arm.com> wrote:
> Hi Lorenzo,
>
> On 20/07/16 12:23, Lorenzo Pieralisi wrote:
>> The iommu_fwspec structure, used to hold per device iommu configuration
>> data is not OF specific and therefore can be moved to a generic
>> and OF independent compilation unit.
>>
>> In particular, the iommu_fwspec handling hinges on the device_node
>> pointer to identify the IOMMU device associated with the iommu_fwspec
>> structure, that is easily converted to a more generic fwnode_handle
>> pointer that can cater for OF and non-OF (ie ACPI) systems.
>>
>> Create the files and related Kconfig entry to decouple iommu_fwspec
>> structure from the OF iommu kernel layer.
>>
>> Given that the current iommu_fwspec implementation relies on
>> the arch specific struct device.archdata.iommu field in its
>> implementation, by making the code standalone and independent
>> of the OF layer this patch makes sure that the iommu_fwspec
>> kernel code can be selected only on arches implementing the
>> struct device.archdata.iommu field by adding an explicit
>> arch dependency in its config entry.
>>
>> Current drivers using the iommu_fwspec for streamid translation
>> are converted to the new iommu_fwspec API by simply converting
>> the device_node to its fwnode_handle pointer.
>>
>> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Hanjun Guo <hanjun.guo@linaro.org>
>> Cc: Robin Murphy <robin.murphy@arm.com>
>> Cc: Joerg Roedel <joro@8bytes.org>
>> ---
>>  drivers/iommu/Kconfig        |   4 ++
>>  drivers/iommu/Makefile       |   1 +
>>  drivers/iommu/arm-smmu-v3.c  |  13 +++--
>>  drivers/iommu/iommu-fwspec.c | 114 +++++++++++++++++++++++++++++++++++++++++++
>>  drivers/iommu/of_iommu.c     |  52 --------------------
>>  include/linux/iommu-fwspec.h |  60 +++++++++++++++++++++++
>>  include/linux/of_iommu.h     |  24 +++------
>>  7 files changed, 196 insertions(+), 72 deletions(-)
>>  create mode 100644 drivers/iommu/iommu-fwspec.c
>>  create mode 100644 include/linux/iommu-fwspec.h
>>
>> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
>> index d1c66af..2b26bfb 100644
>> --- a/drivers/iommu/Kconfig
>> +++ b/drivers/iommu/Kconfig
>> @@ -67,6 +67,10 @@ config OF_IOMMU
>>         def_bool y
>>         depends on OF && IOMMU_API
>>
>> +config IOMMU_FWSPEC
>> +       def_bool y
>> +       depends on ARM64 && IOMMU_API
>
> I think that could be at least (ARM || ARM64).

Why any arch dependency?

Seems like OF_IOMMU (and ACPI?) should select this.

Rob

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

* [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
@ 2016-07-25 15:21           ` Rob Herring
  0 siblings, 0 replies; 72+ messages in thread
From: Rob Herring @ 2016-07-25 15:21 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2016 at 10:09 AM, Robin Murphy <robin.murphy@arm.com> wrote:
> Hi Lorenzo,
>
> On 20/07/16 12:23, Lorenzo Pieralisi wrote:
>> The iommu_fwspec structure, used to hold per device iommu configuration
>> data is not OF specific and therefore can be moved to a generic
>> and OF independent compilation unit.
>>
>> In particular, the iommu_fwspec handling hinges on the device_node
>> pointer to identify the IOMMU device associated with the iommu_fwspec
>> structure, that is easily converted to a more generic fwnode_handle
>> pointer that can cater for OF and non-OF (ie ACPI) systems.
>>
>> Create the files and related Kconfig entry to decouple iommu_fwspec
>> structure from the OF iommu kernel layer.
>>
>> Given that the current iommu_fwspec implementation relies on
>> the arch specific struct device.archdata.iommu field in its
>> implementation, by making the code standalone and independent
>> of the OF layer this patch makes sure that the iommu_fwspec
>> kernel code can be selected only on arches implementing the
>> struct device.archdata.iommu field by adding an explicit
>> arch dependency in its config entry.
>>
>> Current drivers using the iommu_fwspec for streamid translation
>> are converted to the new iommu_fwspec API by simply converting
>> the device_node to its fwnode_handle pointer.
>>
>> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Hanjun Guo <hanjun.guo@linaro.org>
>> Cc: Robin Murphy <robin.murphy@arm.com>
>> Cc: Joerg Roedel <joro@8bytes.org>
>> ---
>>  drivers/iommu/Kconfig        |   4 ++
>>  drivers/iommu/Makefile       |   1 +
>>  drivers/iommu/arm-smmu-v3.c  |  13 +++--
>>  drivers/iommu/iommu-fwspec.c | 114 +++++++++++++++++++++++++++++++++++++++++++
>>  drivers/iommu/of_iommu.c     |  52 --------------------
>>  include/linux/iommu-fwspec.h |  60 +++++++++++++++++++++++
>>  include/linux/of_iommu.h     |  24 +++------
>>  7 files changed, 196 insertions(+), 72 deletions(-)
>>  create mode 100644 drivers/iommu/iommu-fwspec.c
>>  create mode 100644 include/linux/iommu-fwspec.h
>>
>> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
>> index d1c66af..2b26bfb 100644
>> --- a/drivers/iommu/Kconfig
>> +++ b/drivers/iommu/Kconfig
>> @@ -67,6 +67,10 @@ config OF_IOMMU
>>         def_bool y
>>         depends on OF && IOMMU_API
>>
>> +config IOMMU_FWSPEC
>> +       def_bool y
>> +       depends on ARM64 && IOMMU_API
>
> I think that could be at least (ARM || ARM64).

Why any arch dependency?

Seems like OF_IOMMU (and ACPI?) should select this.

Rob

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

* Re: [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
  2016-07-25 15:09       ` Robin Murphy
@ 2016-07-25 15:41         ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-25 15:41 UTC (permalink / raw)
  To: Robin Murphy
  Cc: iommu, Will Deacon, Hanjun Guo, Joerg Roedel, Marc Zyngier,
	Rafael J. Wysocki, Tomasz Nowicki, Jon Masters, Sinan Kaya,
	linux-acpi, linux-pci, linux-kernel, linux-arm-kernel

On Mon, Jul 25, 2016 at 04:09:55PM +0100, Robin Murphy wrote:
> Hi Lorenzo,
> 
> On 20/07/16 12:23, Lorenzo Pieralisi wrote:
> > The iommu_fwspec structure, used to hold per device iommu configuration
> > data is not OF specific and therefore can be moved to a generic
> > and OF independent compilation unit.
> > 
> > In particular, the iommu_fwspec handling hinges on the device_node
> > pointer to identify the IOMMU device associated with the iommu_fwspec
> > structure, that is easily converted to a more generic fwnode_handle
> > pointer that can cater for OF and non-OF (ie ACPI) systems.
> > 
> > Create the files and related Kconfig entry to decouple iommu_fwspec
> > structure from the OF iommu kernel layer.
> > 
> > Given that the current iommu_fwspec implementation relies on
> > the arch specific struct device.archdata.iommu field in its
> > implementation, by making the code standalone and independent
> > of the OF layer this patch makes sure that the iommu_fwspec
> > kernel code can be selected only on arches implementing the
> > struct device.archdata.iommu field by adding an explicit
> > arch dependency in its config entry.
> > 
> > Current drivers using the iommu_fwspec for streamid translation
> > are converted to the new iommu_fwspec API by simply converting
> > the device_node to its fwnode_handle pointer.
> > 
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > Cc: Will Deacon <will.deacon@arm.com>
> > Cc: Hanjun Guo <hanjun.guo@linaro.org>
> > Cc: Robin Murphy <robin.murphy@arm.com>
> > Cc: Joerg Roedel <joro@8bytes.org>
> > ---
> >  drivers/iommu/Kconfig        |   4 ++
> >  drivers/iommu/Makefile       |   1 +
> >  drivers/iommu/arm-smmu-v3.c  |  13 +++--
> >  drivers/iommu/iommu-fwspec.c | 114 +++++++++++++++++++++++++++++++++++++++++++
> >  drivers/iommu/of_iommu.c     |  52 --------------------
> >  include/linux/iommu-fwspec.h |  60 +++++++++++++++++++++++
> >  include/linux/of_iommu.h     |  24 +++------
> >  7 files changed, 196 insertions(+), 72 deletions(-)
> >  create mode 100644 drivers/iommu/iommu-fwspec.c
> >  create mode 100644 include/linux/iommu-fwspec.h
> > 
> > diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> > index d1c66af..2b26bfb 100644
> > --- a/drivers/iommu/Kconfig
> > +++ b/drivers/iommu/Kconfig
> > @@ -67,6 +67,10 @@ config OF_IOMMU
> >         def_bool y
> >         depends on OF && IOMMU_API
> >  
> > +config IOMMU_FWSPEC
> > +       def_bool y
> > +       depends on ARM64 && IOMMU_API
> 
> I think that could be at least (ARM || ARM64).

Yes agreed.

> >  # IOMMU-agnostic DMA-mapping layer
> >  config IOMMU_DMA
> >  	bool
> 
> [...]
> 
> > diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
> > index 308791f..2362232 100644
> > --- a/include/linux/of_iommu.h
> > +++ b/include/linux/of_iommu.h
> > @@ -15,13 +15,8 @@ extern void of_iommu_init(void);
> >  extern const struct iommu_ops *of_iommu_configure(struct device *dev,
> >  					struct device_node *master_np);
> >  
> > -struct iommu_fwspec {
> > -	const struct iommu_ops	*iommu_ops;
> > -	struct device_node	*iommu_np;
> > -	void			*iommu_priv;
> > -	unsigned int		num_ids;
> > -	u32			ids[];
> > -};
> > +void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
> > +const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
> 
> Is there some reason we need to retain the existing definitions of
> these? I was assuming we'd be able to move the entire implementation
> over to the fwspec code and leave behind nothing more than trivial
> wrappers, e.g.:
> 
> #define of_iommu_get_ops(np) iommu_fwspec_get_ops(&(np)->fwnode_handle)

Yep, that's exactly what I did but then I was bitten by config
dependencies. If we implement of_iommu_get/set_ops() as wrappers,
we have to compile iommu_fwspec_get/set_ops() on arches that may
not have struct dev_archdata.iommu, unless we introduce yet another
config symbol to avoid compiling that code (see eg iommu_fwspec_init(),
we can't compile it on eg x86 even though we do need of_iommu_get_ops()
on it - so iommu_fwspec_get_ops(), that lives in the same compilation
unit as eg iommu_fwspec_init()).

So short answer is: there is no reason apart from dev_archdata.iommu
being arch specific, if we were able to move iommu_fwspec to generic
code (ie struct device, somehow) I would certainly get rid of this
stupid code duplication (or as I said I can add a config entry for
that, more ideas are welcome).

Thanks,
Lorenzo

> 
> Robin.
> 
> >  #else
> >  
> > @@ -39,17 +34,14 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
> >  	return NULL;
> >  }
> >  
> > -struct iommu_fwspec;
> > -
> > -#endif	/* CONFIG_OF_IOMMU */
> > +static inline void of_iommu_set_ops(struct device_node *np,
> > +				    const struct iommu_ops *ops)
> > +{ }
> >  
> > -int iommu_fwspec_init(struct device *dev, struct device_node *iommu_np);
> > -void iommu_fwspec_free(struct device *dev);
> > -int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
> > -struct iommu_fwspec *dev_iommu_fwspec(struct device *dev);
> > +static inline const struct iommu_ops *
> > +of_iommu_get_ops(struct device_node *np) { return NULL; }
> >  
> > -void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
> > -const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
> > +#endif	/* CONFIG_OF_IOMMU */
> >  
> >  extern struct of_device_id __iommu_of_table;
> >  
> > 
> 

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

* [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
@ 2016-07-25 15:41         ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-25 15:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2016 at 04:09:55PM +0100, Robin Murphy wrote:
> Hi Lorenzo,
> 
> On 20/07/16 12:23, Lorenzo Pieralisi wrote:
> > The iommu_fwspec structure, used to hold per device iommu configuration
> > data is not OF specific and therefore can be moved to a generic
> > and OF independent compilation unit.
> > 
> > In particular, the iommu_fwspec handling hinges on the device_node
> > pointer to identify the IOMMU device associated with the iommu_fwspec
> > structure, that is easily converted to a more generic fwnode_handle
> > pointer that can cater for OF and non-OF (ie ACPI) systems.
> > 
> > Create the files and related Kconfig entry to decouple iommu_fwspec
> > structure from the OF iommu kernel layer.
> > 
> > Given that the current iommu_fwspec implementation relies on
> > the arch specific struct device.archdata.iommu field in its
> > implementation, by making the code standalone and independent
> > of the OF layer this patch makes sure that the iommu_fwspec
> > kernel code can be selected only on arches implementing the
> > struct device.archdata.iommu field by adding an explicit
> > arch dependency in its config entry.
> > 
> > Current drivers using the iommu_fwspec for streamid translation
> > are converted to the new iommu_fwspec API by simply converting
> > the device_node to its fwnode_handle pointer.
> > 
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > Cc: Will Deacon <will.deacon@arm.com>
> > Cc: Hanjun Guo <hanjun.guo@linaro.org>
> > Cc: Robin Murphy <robin.murphy@arm.com>
> > Cc: Joerg Roedel <joro@8bytes.org>
> > ---
> >  drivers/iommu/Kconfig        |   4 ++
> >  drivers/iommu/Makefile       |   1 +
> >  drivers/iommu/arm-smmu-v3.c  |  13 +++--
> >  drivers/iommu/iommu-fwspec.c | 114 +++++++++++++++++++++++++++++++++++++++++++
> >  drivers/iommu/of_iommu.c     |  52 --------------------
> >  include/linux/iommu-fwspec.h |  60 +++++++++++++++++++++++
> >  include/linux/of_iommu.h     |  24 +++------
> >  7 files changed, 196 insertions(+), 72 deletions(-)
> >  create mode 100644 drivers/iommu/iommu-fwspec.c
> >  create mode 100644 include/linux/iommu-fwspec.h
> > 
> > diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> > index d1c66af..2b26bfb 100644
> > --- a/drivers/iommu/Kconfig
> > +++ b/drivers/iommu/Kconfig
> > @@ -67,6 +67,10 @@ config OF_IOMMU
> >         def_bool y
> >         depends on OF && IOMMU_API
> >  
> > +config IOMMU_FWSPEC
> > +       def_bool y
> > +       depends on ARM64 && IOMMU_API
> 
> I think that could be at least (ARM || ARM64).

Yes agreed.

> >  # IOMMU-agnostic DMA-mapping layer
> >  config IOMMU_DMA
> >  	bool
> 
> [...]
> 
> > diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
> > index 308791f..2362232 100644
> > --- a/include/linux/of_iommu.h
> > +++ b/include/linux/of_iommu.h
> > @@ -15,13 +15,8 @@ extern void of_iommu_init(void);
> >  extern const struct iommu_ops *of_iommu_configure(struct device *dev,
> >  					struct device_node *master_np);
> >  
> > -struct iommu_fwspec {
> > -	const struct iommu_ops	*iommu_ops;
> > -	struct device_node	*iommu_np;
> > -	void			*iommu_priv;
> > -	unsigned int		num_ids;
> > -	u32			ids[];
> > -};
> > +void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
> > +const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
> 
> Is there some reason we need to retain the existing definitions of
> these? I was assuming we'd be able to move the entire implementation
> over to the fwspec code and leave behind nothing more than trivial
> wrappers, e.g.:
> 
> #define of_iommu_get_ops(np) iommu_fwspec_get_ops(&(np)->fwnode_handle)

Yep, that's exactly what I did but then I was bitten by config
dependencies. If we implement of_iommu_get/set_ops() as wrappers,
we have to compile iommu_fwspec_get/set_ops() on arches that may
not have struct dev_archdata.iommu, unless we introduce yet another
config symbol to avoid compiling that code (see eg iommu_fwspec_init(),
we can't compile it on eg x86 even though we do need of_iommu_get_ops()
on it - so iommu_fwspec_get_ops(), that lives in the same compilation
unit as eg iommu_fwspec_init()).

So short answer is: there is no reason apart from dev_archdata.iommu
being arch specific, if we were able to move iommu_fwspec to generic
code (ie struct device, somehow) I would certainly get rid of this
stupid code duplication (or as I said I can add a config entry for
that, more ideas are welcome).

Thanks,
Lorenzo

> 
> Robin.
> 
> >  #else
> >  
> > @@ -39,17 +34,14 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
> >  	return NULL;
> >  }
> >  
> > -struct iommu_fwspec;
> > -
> > -#endif	/* CONFIG_OF_IOMMU */
> > +static inline void of_iommu_set_ops(struct device_node *np,
> > +				    const struct iommu_ops *ops)
> > +{ }
> >  
> > -int iommu_fwspec_init(struct device *dev, struct device_node *iommu_np);
> > -void iommu_fwspec_free(struct device *dev);
> > -int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
> > -struct iommu_fwspec *dev_iommu_fwspec(struct device *dev);
> > +static inline const struct iommu_ops *
> > +of_iommu_get_ops(struct device_node *np) { return NULL; }
> >  
> > -void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
> > -const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
> > +#endif	/* CONFIG_OF_IOMMU */
> >  
> >  extern struct of_device_id __iommu_of_table;
> >  
> > 
> 

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

* Re: [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
  2016-07-25 15:41         ` Lorenzo Pieralisi
@ 2016-07-25 15:51           ` Robin Murphy
  -1 siblings, 0 replies; 72+ messages in thread
From: Robin Murphy @ 2016-07-25 15:51 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: iommu, Will Deacon, Hanjun Guo, Joerg Roedel, Marc Zyngier,
	Rafael J. Wysocki, Tomasz Nowicki, Jon Masters, Sinan Kaya,
	linux-acpi, linux-pci, linux-kernel, linux-arm-kernel

On 25/07/16 16:41, Lorenzo Pieralisi wrote:
[...]
>>> diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
>>> index 308791f..2362232 100644
>>> --- a/include/linux/of_iommu.h
>>> +++ b/include/linux/of_iommu.h
>>> @@ -15,13 +15,8 @@ extern void of_iommu_init(void);
>>>  extern const struct iommu_ops *of_iommu_configure(struct device *dev,
>>>  					struct device_node *master_np);
>>>  
>>> -struct iommu_fwspec {
>>> -	const struct iommu_ops	*iommu_ops;
>>> -	struct device_node	*iommu_np;
>>> -	void			*iommu_priv;
>>> -	unsigned int		num_ids;
>>> -	u32			ids[];
>>> -};
>>> +void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
>>> +const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
>>
>> Is there some reason we need to retain the existing definitions of
>> these? I was assuming we'd be able to move the entire implementation
>> over to the fwspec code and leave behind nothing more than trivial
>> wrappers, e.g.:
>>
>> #define of_iommu_get_ops(np) iommu_fwspec_get_ops(&(np)->fwnode_handle)
> 
> Yep, that's exactly what I did but then I was bitten by config
> dependencies. If we implement of_iommu_get/set_ops() as wrappers,
> we have to compile iommu_fwspec_get/set_ops() on arches that may
> not have struct dev_archdata.iommu, unless we introduce yet another
> config symbol to avoid compiling that code (see eg iommu_fwspec_init(),
> we can't compile it on eg x86 even though we do need of_iommu_get_ops()
> on it - so iommu_fwspec_get_ops(), that lives in the same compilation
> unit as eg iommu_fwspec_init()).
> 
> So short answer is: there is no reason apart from dev_archdata.iommu
> being arch specific, if we were able to move iommu_fwspec to generic
> code (ie struct device, somehow) I would certainly get rid of this
> stupid code duplication (or as I said I can add a config entry for
> that, more ideas are welcome).

OK, given Rob's comment as well, I guess breaking that dependency is to
everyone's benefit. Since it's quite closely related, how about if we
follow the arch_setup_dma_ops() pattern with an
arch_{get,set}_iommu_fwspec(dev) type thing?

Robin.

> 
> Thanks,
> Lorenzo
> 
>>
>> Robin.
>>
>>>  #else
>>>  
>>> @@ -39,17 +34,14 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
>>>  	return NULL;
>>>  }
>>>  
>>> -struct iommu_fwspec;
>>> -
>>> -#endif	/* CONFIG_OF_IOMMU */
>>> +static inline void of_iommu_set_ops(struct device_node *np,
>>> +				    const struct iommu_ops *ops)
>>> +{ }
>>>  
>>> -int iommu_fwspec_init(struct device *dev, struct device_node *iommu_np);
>>> -void iommu_fwspec_free(struct device *dev);
>>> -int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
>>> -struct iommu_fwspec *dev_iommu_fwspec(struct device *dev);
>>> +static inline const struct iommu_ops *
>>> +of_iommu_get_ops(struct device_node *np) { return NULL; }
>>>  
>>> -void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
>>> -const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
>>> +#endif	/* CONFIG_OF_IOMMU */
>>>  
>>>  extern struct of_device_id __iommu_of_table;
>>>  
>>>
>>
> 

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

* [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
@ 2016-07-25 15:51           ` Robin Murphy
  0 siblings, 0 replies; 72+ messages in thread
From: Robin Murphy @ 2016-07-25 15:51 UTC (permalink / raw)
  To: linux-arm-kernel

On 25/07/16 16:41, Lorenzo Pieralisi wrote:
[...]
>>> diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
>>> index 308791f..2362232 100644
>>> --- a/include/linux/of_iommu.h
>>> +++ b/include/linux/of_iommu.h
>>> @@ -15,13 +15,8 @@ extern void of_iommu_init(void);
>>>  extern const struct iommu_ops *of_iommu_configure(struct device *dev,
>>>  					struct device_node *master_np);
>>>  
>>> -struct iommu_fwspec {
>>> -	const struct iommu_ops	*iommu_ops;
>>> -	struct device_node	*iommu_np;
>>> -	void			*iommu_priv;
>>> -	unsigned int		num_ids;
>>> -	u32			ids[];
>>> -};
>>> +void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
>>> +const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
>>
>> Is there some reason we need to retain the existing definitions of
>> these? I was assuming we'd be able to move the entire implementation
>> over to the fwspec code and leave behind nothing more than trivial
>> wrappers, e.g.:
>>
>> #define of_iommu_get_ops(np) iommu_fwspec_get_ops(&(np)->fwnode_handle)
> 
> Yep, that's exactly what I did but then I was bitten by config
> dependencies. If we implement of_iommu_get/set_ops() as wrappers,
> we have to compile iommu_fwspec_get/set_ops() on arches that may
> not have struct dev_archdata.iommu, unless we introduce yet another
> config symbol to avoid compiling that code (see eg iommu_fwspec_init(),
> we can't compile it on eg x86 even though we do need of_iommu_get_ops()
> on it - so iommu_fwspec_get_ops(), that lives in the same compilation
> unit as eg iommu_fwspec_init()).
> 
> So short answer is: there is no reason apart from dev_archdata.iommu
> being arch specific, if we were able to move iommu_fwspec to generic
> code (ie struct device, somehow) I would certainly get rid of this
> stupid code duplication (or as I said I can add a config entry for
> that, more ideas are welcome).

OK, given Rob's comment as well, I guess breaking that dependency is to
everyone's benefit. Since it's quite closely related, how about if we
follow the arch_setup_dma_ops() pattern with an
arch_{get,set}_iommu_fwspec(dev) type thing?

Robin.

> 
> Thanks,
> Lorenzo
> 
>>
>> Robin.
>>
>>>  #else
>>>  
>>> @@ -39,17 +34,14 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
>>>  	return NULL;
>>>  }
>>>  
>>> -struct iommu_fwspec;
>>> -
>>> -#endif	/* CONFIG_OF_IOMMU */
>>> +static inline void of_iommu_set_ops(struct device_node *np,
>>> +				    const struct iommu_ops *ops)
>>> +{ }
>>>  
>>> -int iommu_fwspec_init(struct device *dev, struct device_node *iommu_np);
>>> -void iommu_fwspec_free(struct device *dev);
>>> -int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
>>> -struct iommu_fwspec *dev_iommu_fwspec(struct device *dev);
>>> +static inline const struct iommu_ops *
>>> +of_iommu_get_ops(struct device_node *np) { return NULL; }
>>>  
>>> -void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
>>> -const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
>>> +#endif	/* CONFIG_OF_IOMMU */
>>>  
>>>  extern struct of_device_id __iommu_of_table;
>>>  
>>>
>>
> 

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

* Re: [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
  2016-07-25 15:21           ` Rob Herring
  (?)
@ 2016-07-25 15:56             ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-25 15:56 UTC (permalink / raw)
  To: Rob Herring
  Cc: Robin Murphy, Linux IOMMU, linux-arm-kernel, Marc Zyngier,
	Will Deacon, Joerg Roedel, Rafael J. Wysocki, linux-kernel,
	linux-pci, Sinan Kaya, linux-acpi, Hanjun Guo, Tomasz Nowicki,
	Jon Masters

On Mon, Jul 25, 2016 at 10:21:10AM -0500, Rob Herring wrote:
> On Mon, Jul 25, 2016 at 10:09 AM, Robin Murphy <robin.murphy@arm.com> wrote:
> > Hi Lorenzo,
> >
> > On 20/07/16 12:23, Lorenzo Pieralisi wrote:
> >> The iommu_fwspec structure, used to hold per device iommu configuration
> >> data is not OF specific and therefore can be moved to a generic
> >> and OF independent compilation unit.
> >>
> >> In particular, the iommu_fwspec handling hinges on the device_node
> >> pointer to identify the IOMMU device associated with the iommu_fwspec
> >> structure, that is easily converted to a more generic fwnode_handle
> >> pointer that can cater for OF and non-OF (ie ACPI) systems.
> >>
> >> Create the files and related Kconfig entry to decouple iommu_fwspec
> >> structure from the OF iommu kernel layer.
> >>
> >> Given that the current iommu_fwspec implementation relies on
> >> the arch specific struct device.archdata.iommu field in its
> >> implementation, by making the code standalone and independent
> >> of the OF layer this patch makes sure that the iommu_fwspec
> >> kernel code can be selected only on arches implementing the
> >> struct device.archdata.iommu field by adding an explicit
> >> arch dependency in its config entry.
> >>
> >> Current drivers using the iommu_fwspec for streamid translation
> >> are converted to the new iommu_fwspec API by simply converting
> >> the device_node to its fwnode_handle pointer.
> >>
> >> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> >> Cc: Will Deacon <will.deacon@arm.com>
> >> Cc: Hanjun Guo <hanjun.guo@linaro.org>
> >> Cc: Robin Murphy <robin.murphy@arm.com>
> >> Cc: Joerg Roedel <joro@8bytes.org>
> >> ---
> >>  drivers/iommu/Kconfig        |   4 ++
> >>  drivers/iommu/Makefile       |   1 +
> >>  drivers/iommu/arm-smmu-v3.c  |  13 +++--
> >>  drivers/iommu/iommu-fwspec.c | 114 +++++++++++++++++++++++++++++++++++++++++++
> >>  drivers/iommu/of_iommu.c     |  52 --------------------
> >>  include/linux/iommu-fwspec.h |  60 +++++++++++++++++++++++
> >>  include/linux/of_iommu.h     |  24 +++------
> >>  7 files changed, 196 insertions(+), 72 deletions(-)
> >>  create mode 100644 drivers/iommu/iommu-fwspec.c
> >>  create mode 100644 include/linux/iommu-fwspec.h
> >>
> >> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> >> index d1c66af..2b26bfb 100644
> >> --- a/drivers/iommu/Kconfig
> >> +++ b/drivers/iommu/Kconfig
> >> @@ -67,6 +67,10 @@ config OF_IOMMU
> >>         def_bool y
> >>         depends on OF && IOMMU_API
> >>
> >> +config IOMMU_FWSPEC
> >> +       def_bool y
> >> +       depends on ARM64 && IOMMU_API
> >
> > I think that could be at least (ARM || ARM64).
> 
> Why any arch dependency?
> 
> Seems like OF_IOMMU (and ACPI?) should select this.

Absolutely, that's the end goal. Current issue is that the iommu_fwspec
mechanism relies on dev_archdata.iommu pointer internally to work and
since that's arch specific I can't select it on arches that do not have
that field, it would break the compilation.

I will follow up with Robin to make sure we will be able to
implement what you request above.

Thanks !
Lorenzo

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

* Re: [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
@ 2016-07-25 15:56             ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-25 15:56 UTC (permalink / raw)
  To: Rob Herring
  Cc: Robin Murphy, Linux IOMMU, linux-arm-kernel, Marc Zyngier,
	Will Deacon, Joerg Roedel, Rafael J. Wysocki, linux-kernel,
	linux-pci, Sinan Kaya, linux-acpi, Hanjun Guo, Tomasz Nowicki,
	Jon Masters

On Mon, Jul 25, 2016 at 10:21:10AM -0500, Rob Herring wrote:
> On Mon, Jul 25, 2016 at 10:09 AM, Robin Murphy <robin.murphy@arm.com> wrote:
> > Hi Lorenzo,
> >
> > On 20/07/16 12:23, Lorenzo Pieralisi wrote:
> >> The iommu_fwspec structure, used to hold per device iommu configuration
> >> data is not OF specific and therefore can be moved to a generic
> >> and OF independent compilation unit.
> >>
> >> In particular, the iommu_fwspec handling hinges on the device_node
> >> pointer to identify the IOMMU device associated with the iommu_fwspec
> >> structure, that is easily converted to a more generic fwnode_handle
> >> pointer that can cater for OF and non-OF (ie ACPI) systems.
> >>
> >> Create the files and related Kconfig entry to decouple iommu_fwspec
> >> structure from the OF iommu kernel layer.
> >>
> >> Given that the current iommu_fwspec implementation relies on
> >> the arch specific struct device.archdata.iommu field in its
> >> implementation, by making the code standalone and independent
> >> of the OF layer this patch makes sure that the iommu_fwspec
> >> kernel code can be selected only on arches implementing the
> >> struct device.archdata.iommu field by adding an explicit
> >> arch dependency in its config entry.
> >>
> >> Current drivers using the iommu_fwspec for streamid translation
> >> are converted to the new iommu_fwspec API by simply converting
> >> the device_node to its fwnode_handle pointer.
> >>
> >> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> >> Cc: Will Deacon <will.deacon@arm.com>
> >> Cc: Hanjun Guo <hanjun.guo@linaro.org>
> >> Cc: Robin Murphy <robin.murphy@arm.com>
> >> Cc: Joerg Roedel <joro@8bytes.org>
> >> ---
> >>  drivers/iommu/Kconfig        |   4 ++
> >>  drivers/iommu/Makefile       |   1 +
> >>  drivers/iommu/arm-smmu-v3.c  |  13 +++--
> >>  drivers/iommu/iommu-fwspec.c | 114 +++++++++++++++++++++++++++++++++++++++++++
> >>  drivers/iommu/of_iommu.c     |  52 --------------------
> >>  include/linux/iommu-fwspec.h |  60 +++++++++++++++++++++++
> >>  include/linux/of_iommu.h     |  24 +++------
> >>  7 files changed, 196 insertions(+), 72 deletions(-)
> >>  create mode 100644 drivers/iommu/iommu-fwspec.c
> >>  create mode 100644 include/linux/iommu-fwspec.h
> >>
> >> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> >> index d1c66af..2b26bfb 100644
> >> --- a/drivers/iommu/Kconfig
> >> +++ b/drivers/iommu/Kconfig
> >> @@ -67,6 +67,10 @@ config OF_IOMMU
> >>         def_bool y
> >>         depends on OF && IOMMU_API
> >>
> >> +config IOMMU_FWSPEC
> >> +       def_bool y
> >> +       depends on ARM64 && IOMMU_API
> >
> > I think that could be at least (ARM || ARM64).
> 
> Why any arch dependency?
> 
> Seems like OF_IOMMU (and ACPI?) should select this.

Absolutely, that's the end goal. Current issue is that the iommu_fwspec
mechanism relies on dev_archdata.iommu pointer internally to work and
since that's arch specific I can't select it on arches that do not have
that field, it would break the compilation.

I will follow up with Robin to make sure we will be able to
implement what you request above.

Thanks !
Lorenzo

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

* [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
@ 2016-07-25 15:56             ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-25 15:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2016 at 10:21:10AM -0500, Rob Herring wrote:
> On Mon, Jul 25, 2016 at 10:09 AM, Robin Murphy <robin.murphy@arm.com> wrote:
> > Hi Lorenzo,
> >
> > On 20/07/16 12:23, Lorenzo Pieralisi wrote:
> >> The iommu_fwspec structure, used to hold per device iommu configuration
> >> data is not OF specific and therefore can be moved to a generic
> >> and OF independent compilation unit.
> >>
> >> In particular, the iommu_fwspec handling hinges on the device_node
> >> pointer to identify the IOMMU device associated with the iommu_fwspec
> >> structure, that is easily converted to a more generic fwnode_handle
> >> pointer that can cater for OF and non-OF (ie ACPI) systems.
> >>
> >> Create the files and related Kconfig entry to decouple iommu_fwspec
> >> structure from the OF iommu kernel layer.
> >>
> >> Given that the current iommu_fwspec implementation relies on
> >> the arch specific struct device.archdata.iommu field in its
> >> implementation, by making the code standalone and independent
> >> of the OF layer this patch makes sure that the iommu_fwspec
> >> kernel code can be selected only on arches implementing the
> >> struct device.archdata.iommu field by adding an explicit
> >> arch dependency in its config entry.
> >>
> >> Current drivers using the iommu_fwspec for streamid translation
> >> are converted to the new iommu_fwspec API by simply converting
> >> the device_node to its fwnode_handle pointer.
> >>
> >> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> >> Cc: Will Deacon <will.deacon@arm.com>
> >> Cc: Hanjun Guo <hanjun.guo@linaro.org>
> >> Cc: Robin Murphy <robin.murphy@arm.com>
> >> Cc: Joerg Roedel <joro@8bytes.org>
> >> ---
> >>  drivers/iommu/Kconfig        |   4 ++
> >>  drivers/iommu/Makefile       |   1 +
> >>  drivers/iommu/arm-smmu-v3.c  |  13 +++--
> >>  drivers/iommu/iommu-fwspec.c | 114 +++++++++++++++++++++++++++++++++++++++++++
> >>  drivers/iommu/of_iommu.c     |  52 --------------------
> >>  include/linux/iommu-fwspec.h |  60 +++++++++++++++++++++++
> >>  include/linux/of_iommu.h     |  24 +++------
> >>  7 files changed, 196 insertions(+), 72 deletions(-)
> >>  create mode 100644 drivers/iommu/iommu-fwspec.c
> >>  create mode 100644 include/linux/iommu-fwspec.h
> >>
> >> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> >> index d1c66af..2b26bfb 100644
> >> --- a/drivers/iommu/Kconfig
> >> +++ b/drivers/iommu/Kconfig
> >> @@ -67,6 +67,10 @@ config OF_IOMMU
> >>         def_bool y
> >>         depends on OF && IOMMU_API
> >>
> >> +config IOMMU_FWSPEC
> >> +       def_bool y
> >> +       depends on ARM64 && IOMMU_API
> >
> > I think that could be at least (ARM || ARM64).
> 
> Why any arch dependency?
> 
> Seems like OF_IOMMU (and ACPI?) should select this.

Absolutely, that's the end goal. Current issue is that the iommu_fwspec
mechanism relies on dev_archdata.iommu pointer internally to work and
since that's arch specific I can't select it on arches that do not have
that field, it would break the compilation.

I will follow up with Robin to make sure we will be able to
implement what you request above.

Thanks !
Lorenzo

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

* Re: [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
  2016-07-25 15:51           ` Robin Murphy
@ 2016-07-25 16:12             ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-25 16:12 UTC (permalink / raw)
  To: Robin Murphy
  Cc: iommu, Will Deacon, Hanjun Guo, Joerg Roedel, Marc Zyngier,
	Rafael J. Wysocki, Tomasz Nowicki, Jon Masters, Sinan Kaya,
	linux-acpi, linux-pci, linux-kernel, linux-arm-kernel

On Mon, Jul 25, 2016 at 04:51:00PM +0100, Robin Murphy wrote:
> On 25/07/16 16:41, Lorenzo Pieralisi wrote:
> [...]
> >>> diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
> >>> index 308791f..2362232 100644
> >>> --- a/include/linux/of_iommu.h
> >>> +++ b/include/linux/of_iommu.h
> >>> @@ -15,13 +15,8 @@ extern void of_iommu_init(void);
> >>>  extern const struct iommu_ops *of_iommu_configure(struct device *dev,
> >>>  					struct device_node *master_np);
> >>>  
> >>> -struct iommu_fwspec {
> >>> -	const struct iommu_ops	*iommu_ops;
> >>> -	struct device_node	*iommu_np;
> >>> -	void			*iommu_priv;
> >>> -	unsigned int		num_ids;
> >>> -	u32			ids[];
> >>> -};
> >>> +void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
> >>> +const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
> >>
> >> Is there some reason we need to retain the existing definitions of
> >> these? I was assuming we'd be able to move the entire implementation
> >> over to the fwspec code and leave behind nothing more than trivial
> >> wrappers, e.g.:
> >>
> >> #define of_iommu_get_ops(np) iommu_fwspec_get_ops(&(np)->fwnode_handle)
> > 
> > Yep, that's exactly what I did but then I was bitten by config
> > dependencies. If we implement of_iommu_get/set_ops() as wrappers,
> > we have to compile iommu_fwspec_get/set_ops() on arches that may
> > not have struct dev_archdata.iommu, unless we introduce yet another
> > config symbol to avoid compiling that code (see eg iommu_fwspec_init(),
> > we can't compile it on eg x86 even though we do need of_iommu_get_ops()
> > on it - so iommu_fwspec_get_ops(), that lives in the same compilation
> > unit as eg iommu_fwspec_init()).
> > 
> > So short answer is: there is no reason apart from dev_archdata.iommu
> > being arch specific, if we were able to move iommu_fwspec to generic
> > code (ie struct device, somehow) I would certainly get rid of this
> > stupid code duplication (or as I said I can add a config entry for
> > that, more ideas are welcome).
> 
> OK, given Rob's comment as well, I guess breaking that dependency is to
> everyone's benefit. Since it's quite closely related, how about if we
> follow the arch_setup_dma_ops() pattern with an
> arch_{get,set}_iommu_fwspec(dev) type thing?

Yes we can do that too as an intermediate step, that solves the
problem (and it makes this patch much simpler), it is cleaner
than doing it with a(nother) Kconfig entry.

Thanks,
Lorenzo

> Robin.
> 
> > 
> > Thanks,
> > Lorenzo
> > 
> >>
> >> Robin.
> >>
> >>>  #else
> >>>  
> >>> @@ -39,17 +34,14 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
> >>>  	return NULL;
> >>>  }
> >>>  
> >>> -struct iommu_fwspec;
> >>> -
> >>> -#endif	/* CONFIG_OF_IOMMU */
> >>> +static inline void of_iommu_set_ops(struct device_node *np,
> >>> +				    const struct iommu_ops *ops)
> >>> +{ }
> >>>  
> >>> -int iommu_fwspec_init(struct device *dev, struct device_node *iommu_np);
> >>> -void iommu_fwspec_free(struct device *dev);
> >>> -int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
> >>> -struct iommu_fwspec *dev_iommu_fwspec(struct device *dev);
> >>> +static inline const struct iommu_ops *
> >>> +of_iommu_get_ops(struct device_node *np) { return NULL; }
> >>>  
> >>> -void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
> >>> -const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
> >>> +#endif	/* CONFIG_OF_IOMMU */
> >>>  
> >>>  extern struct of_device_id __iommu_of_table;
> >>>  
> >>>
> >>
> > 
> 

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

* [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
@ 2016-07-25 16:12             ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-07-25 16:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2016 at 04:51:00PM +0100, Robin Murphy wrote:
> On 25/07/16 16:41, Lorenzo Pieralisi wrote:
> [...]
> >>> diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
> >>> index 308791f..2362232 100644
> >>> --- a/include/linux/of_iommu.h
> >>> +++ b/include/linux/of_iommu.h
> >>> @@ -15,13 +15,8 @@ extern void of_iommu_init(void);
> >>>  extern const struct iommu_ops *of_iommu_configure(struct device *dev,
> >>>  					struct device_node *master_np);
> >>>  
> >>> -struct iommu_fwspec {
> >>> -	const struct iommu_ops	*iommu_ops;
> >>> -	struct device_node	*iommu_np;
> >>> -	void			*iommu_priv;
> >>> -	unsigned int		num_ids;
> >>> -	u32			ids[];
> >>> -};
> >>> +void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
> >>> +const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
> >>
> >> Is there some reason we need to retain the existing definitions of
> >> these? I was assuming we'd be able to move the entire implementation
> >> over to the fwspec code and leave behind nothing more than trivial
> >> wrappers, e.g.:
> >>
> >> #define of_iommu_get_ops(np) iommu_fwspec_get_ops(&(np)->fwnode_handle)
> > 
> > Yep, that's exactly what I did but then I was bitten by config
> > dependencies. If we implement of_iommu_get/set_ops() as wrappers,
> > we have to compile iommu_fwspec_get/set_ops() on arches that may
> > not have struct dev_archdata.iommu, unless we introduce yet another
> > config symbol to avoid compiling that code (see eg iommu_fwspec_init(),
> > we can't compile it on eg x86 even though we do need of_iommu_get_ops()
> > on it - so iommu_fwspec_get_ops(), that lives in the same compilation
> > unit as eg iommu_fwspec_init()).
> > 
> > So short answer is: there is no reason apart from dev_archdata.iommu
> > being arch specific, if we were able to move iommu_fwspec to generic
> > code (ie struct device, somehow) I would certainly get rid of this
> > stupid code duplication (or as I said I can add a config entry for
> > that, more ideas are welcome).
> 
> OK, given Rob's comment as well, I guess breaking that dependency is to
> everyone's benefit. Since it's quite closely related, how about if we
> follow the arch_setup_dma_ops() pattern with an
> arch_{get,set}_iommu_fwspec(dev) type thing?

Yes we can do that too as an intermediate step, that solves the
problem (and it makes this patch much simpler), it is cleaner
than doing it with a(nother) Kconfig entry.

Thanks,
Lorenzo

> Robin.
> 
> > 
> > Thanks,
> > Lorenzo
> > 
> >>
> >> Robin.
> >>
> >>>  #else
> >>>  
> >>> @@ -39,17 +34,14 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
> >>>  	return NULL;
> >>>  }
> >>>  
> >>> -struct iommu_fwspec;
> >>> -
> >>> -#endif	/* CONFIG_OF_IOMMU */
> >>> +static inline void of_iommu_set_ops(struct device_node *np,
> >>> +				    const struct iommu_ops *ops)
> >>> +{ }
> >>>  
> >>> -int iommu_fwspec_init(struct device *dev, struct device_node *iommu_np);
> >>> -void iommu_fwspec_free(struct device *dev);
> >>> -int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
> >>> -struct iommu_fwspec *dev_iommu_fwspec(struct device *dev);
> >>> +static inline const struct iommu_ops *
> >>> +of_iommu_get_ops(struct device_node *np) { return NULL; }
> >>>  
> >>> -void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
> >>> -const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
> >>> +#endif	/* CONFIG_OF_IOMMU */
> >>>  
> >>>  extern struct of_device_id __iommu_of_table;
> >>>  
> >>>
> >>
> > 
> 

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

* Re: [RFC PATCH v3 00/13] ACPI IORT ARM SMMU v3 support
  2016-07-25  8:36         ` Lorenzo Pieralisi
  (?)
@ 2016-07-26  1:16           ` Dennis Chen
  -1 siblings, 0 replies; 72+ messages in thread
From: Dennis Chen @ 2016-07-26  1:16 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Marc Zyngier,
	Rafael J. Wysocki, Will Deacon,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA, Sinan Kaya,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Hanjun Guo,
	Tomasz Nowicki, nd-5wv7dgnIgG8, Jon Masters

On Mon, Jul 25, 2016 at 09:36:41AM +0100, Lorenzo Pieralisi wrote:
> On Mon, Jul 25, 2016 at 01:53:32PM +0800, Dennis Chen wrote:
> > Hi
> > On Wed, Jul 20, 2016 at 12:23:22PM +0100, Lorenzo Pieralisi wrote:
> > > This RFC patch series is v3 of a previous posting:
> > > 
> > > https://lkml.org/lkml/2016/6/7/523
> > > 
> > > v2 -> v3
> > > 	- Rebased on top of dependencies series [1][2][3](v4.7-rc3)
> > > 	- Added back reliance on ACPI early probing infrastructure
> > > 	- Patch[1-3] merged through other dependent series
> > > 	- Added back IOMMU fwnode generalization
> > > 	- Move SMMU v3 static functions configuration to IORT code
> > > 	- Implemented generic IOMMU fwspec API
> > > 	- Added code to implement fwnode platform device look-up
> > > 
> > > v1 -> v2:
> > > 	- Rebased on top of dependencies series [1][2][3](v4.7-rc1)
> > > 	- Removed IOMMU fwnode generalization
> > > 	- Implemented ARM SMMU v3 ACPI probing instead of ARM SMMU v2
> > > 	  owing to patch series dependencies [1]
> > > 	- Moved platform device creation logic to IORT code to
> > > 	  generalize its usage for ARM SMMU v1-v2-v3 components
> > > 	- Removed reliance on ACPI early device probing
> > > 	- Created IORT specific iommu_xlate() translation hook leaving
> > > 	  OF code unchanged according to v1 reviews
> > > 
> > > The ACPI IORT table provides information that allows instantiating
> > > ARM SMMU devices and carrying out id mappings between components on
> > > ARM based systems (devices, IOMMUs, interrupt controllers).
> > > 
> > > http://infocenter.arm.com/help/topic/com.arm.doc.den0049b/DEN0049B_IO_Remapping_Table.pdf
> > > 
> > > Building on basic IORT support, available through [2]:
> > > 
> > > this patchset enables ARM SMMU v3 support on ACPI systems.
> > > 
> > > Most of the code is aimed at building the required generic ACPI
> > > infrastructure to create and enable IOMMU components and to bring
> > > the IOMMU infrastructure for ACPI on par with DT, which is going to
> > > make future ARM SMMU components easier to integrate.
> > > 
> > > PATCH (1) adds a FWNODE_IOMMU type to the struct fwnode_handle type.
> > >           It is required to attach a fwnode identifier to platform
> > >           devices allocated/detected through IORT tables entries;
> > >           IOMMU devices have to have an identifier to look them up
> > >           eg IOMMU core layer carrying out id translation. This can be
> > >           done through a fwnode_handle (ie IOMMU platform devices created
> > >           out of IORT tables are not ACPI devices hence they can't be
> > >           allocated as such, otherwise they would have a fwnode_handle of
> > >           type FWNODE_ACPI). This patch requires discussion and it is key
> > >           to the RFC.
> > > 
> > > PATCH (2) makes use of the ACPI early probing API to add a linker script
> > >           section for probing devices via IORT ACPI kernel code.
> > > 
> > > PATCH (3) provides IORT support for registering IOMMU IORT node through
> > >           their fwnode handle.
> > > 
> > > PATCH (4) implements core code fwnode based platform devices look-up.
> > > 
> > > PATCH (5) extends iommu_fwspec so that it can be used on ACPI based
> > >           system by creating a generic IOMMU fwspec kernel layer.
> > > 
> > > PATCH (6) implements the of_dma_configure() API in ACPI world -
> > >           acpi_dma_configure() - and patches PCI and ACPI core code to
> > >           start making use of it.
> > > 
> > > PATCH (7) provides an IORT function to detect existence of specific type
> > >           of IORT components.
> > > 
> > > PATCH (8) creates the kernel infrastructure required to create ARM SMMU
> > >           platform devices for IORT nodes.
> > > 
> > > PATCH (9) refactors the ARM SMMU v3 driver so that the init functions are
> > >           split in a way that groups together code that probes through DT
> > >           and code that carries out HW registers FW agnostic probing, in
> > >           preparation for adding the ACPI probing path.
> > > 
> > > PATCH (10) rework ARM SMMU v3 platform driver registration to make it work
> > >            on ACPI systems.
> > > 
> > > PATCH (11) Building on patch (8), it adds ARM SMMU v3 IORT IOMMU
> > >            operations to create and probe ARM SMMU v3 components.
> > > 
> > > PATCH (12) Extend the IORT iort_node_map_rid() to work on a type mask
> > >            instead of a single type so that the translation API can
> > >            be used on a range of components.
> > > 
> > > PATCH (13) provides IORT infrastructure to carry out IOMMU configuration
> > >            for devices and hook it up to the previously introduced ACPI
> > >            DMA configure API.
> > > 
> > > This patchset is built on top and depends on these three patch series:
> > > 
> > > [1] R.Murphy "Generic DT bindings for PCI and ARM SMMU v3" v4
> > >     https://marc.info/?l=devicetree&m=146739193215518&w=2
> > > 
> > > [2] T.Nowicki "Introduce ACPI world to ITS irqchip" v7
> > >     https://marc.info/?l=linux-arm-kernel&m=146642080022289&w=2
> > > 
> > > [3] T.Nowicki "Support for ARM64 ACPI based PCI host controller" v8
> > >     http://marc.info/?l=linux-acpi&m=146462129816292&w=2
> > > 
> > > and is provided for early review/testing purposes here:
> > > 
> > > git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git acpi/iort-smmu-v3i
> > >
> > I thought I can got all the 13 patches applied with the above git
> > tree, but I can't find any ACPI related stuff after I cloned the git
> > repos to my local machine, am I missing something here?
> 
> Have you pulled the acpi/iort-smmu-v3 branch ?
>
Hello Lorenzo, forgive my carelessness missing the additional checkout of that branch. 
Thanks and have a nice day :)

> 
> Thanks,
> Lorenzo
> 

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

* Re: [RFC PATCH v3 00/13] ACPI IORT ARM SMMU v3 support
@ 2016-07-26  1:16           ` Dennis Chen
  0 siblings, 0 replies; 72+ messages in thread
From: Dennis Chen @ 2016-07-26  1:16 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: iommu, Will Deacon, Marc Zyngier, Robin Murphy, Joerg Roedel,
	Rafael J. Wysocki, Tomasz Nowicki, Hanjun Guo, Jon Masters,
	Sinan Kaya, linux-acpi, linux-pci, linux-kernel,
	linux-arm-kernel, nd

On Mon, Jul 25, 2016 at 09:36:41AM +0100, Lorenzo Pieralisi wrote:
> On Mon, Jul 25, 2016 at 01:53:32PM +0800, Dennis Chen wrote:
> > Hi
> > On Wed, Jul 20, 2016 at 12:23:22PM +0100, Lorenzo Pieralisi wrote:
> > > This RFC patch series is v3 of a previous posting:
> > > 
> > > https://lkml.org/lkml/2016/6/7/523
> > > 
> > > v2 -> v3
> > > 	- Rebased on top of dependencies series [1][2][3](v4.7-rc3)
> > > 	- Added back reliance on ACPI early probing infrastructure
> > > 	- Patch[1-3] merged through other dependent series
> > > 	- Added back IOMMU fwnode generalization
> > > 	- Move SMMU v3 static functions configuration to IORT code
> > > 	- Implemented generic IOMMU fwspec API
> > > 	- Added code to implement fwnode platform device look-up
> > > 
> > > v1 -> v2:
> > > 	- Rebased on top of dependencies series [1][2][3](v4.7-rc1)
> > > 	- Removed IOMMU fwnode generalization
> > > 	- Implemented ARM SMMU v3 ACPI probing instead of ARM SMMU v2
> > > 	  owing to patch series dependencies [1]
> > > 	- Moved platform device creation logic to IORT code to
> > > 	  generalize its usage for ARM SMMU v1-v2-v3 components
> > > 	- Removed reliance on ACPI early device probing
> > > 	- Created IORT specific iommu_xlate() translation hook leaving
> > > 	  OF code unchanged according to v1 reviews
> > > 
> > > The ACPI IORT table provides information that allows instantiating
> > > ARM SMMU devices and carrying out id mappings between components on
> > > ARM based systems (devices, IOMMUs, interrupt controllers).
> > > 
> > > http://infocenter.arm.com/help/topic/com.arm.doc.den0049b/DEN0049B_IO_Remapping_Table.pdf
> > > 
> > > Building on basic IORT support, available through [2]:
> > > 
> > > this patchset enables ARM SMMU v3 support on ACPI systems.
> > > 
> > > Most of the code is aimed at building the required generic ACPI
> > > infrastructure to create and enable IOMMU components and to bring
> > > the IOMMU infrastructure for ACPI on par with DT, which is going to
> > > make future ARM SMMU components easier to integrate.
> > > 
> > > PATCH (1) adds a FWNODE_IOMMU type to the struct fwnode_handle type.
> > >           It is required to attach a fwnode identifier to platform
> > >           devices allocated/detected through IORT tables entries;
> > >           IOMMU devices have to have an identifier to look them up
> > >           eg IOMMU core layer carrying out id translation. This can be
> > >           done through a fwnode_handle (ie IOMMU platform devices created
> > >           out of IORT tables are not ACPI devices hence they can't be
> > >           allocated as such, otherwise they would have a fwnode_handle of
> > >           type FWNODE_ACPI). This patch requires discussion and it is key
> > >           to the RFC.
> > > 
> > > PATCH (2) makes use of the ACPI early probing API to add a linker script
> > >           section for probing devices via IORT ACPI kernel code.
> > > 
> > > PATCH (3) provides IORT support for registering IOMMU IORT node through
> > >           their fwnode handle.
> > > 
> > > PATCH (4) implements core code fwnode based platform devices look-up.
> > > 
> > > PATCH (5) extends iommu_fwspec so that it can be used on ACPI based
> > >           system by creating a generic IOMMU fwspec kernel layer.
> > > 
> > > PATCH (6) implements the of_dma_configure() API in ACPI world -
> > >           acpi_dma_configure() - and patches PCI and ACPI core code to
> > >           start making use of it.
> > > 
> > > PATCH (7) provides an IORT function to detect existence of specific type
> > >           of IORT components.
> > > 
> > > PATCH (8) creates the kernel infrastructure required to create ARM SMMU
> > >           platform devices for IORT nodes.
> > > 
> > > PATCH (9) refactors the ARM SMMU v3 driver so that the init functions are
> > >           split in a way that groups together code that probes through DT
> > >           and code that carries out HW registers FW agnostic probing, in
> > >           preparation for adding the ACPI probing path.
> > > 
> > > PATCH (10) rework ARM SMMU v3 platform driver registration to make it work
> > >            on ACPI systems.
> > > 
> > > PATCH (11) Building on patch (8), it adds ARM SMMU v3 IORT IOMMU
> > >            operations to create and probe ARM SMMU v3 components.
> > > 
> > > PATCH (12) Extend the IORT iort_node_map_rid() to work on a type mask
> > >            instead of a single type so that the translation API can
> > >            be used on a range of components.
> > > 
> > > PATCH (13) provides IORT infrastructure to carry out IOMMU configuration
> > >            for devices and hook it up to the previously introduced ACPI
> > >            DMA configure API.
> > > 
> > > This patchset is built on top and depends on these three patch series:
> > > 
> > > [1] R.Murphy "Generic DT bindings for PCI and ARM SMMU v3" v4
> > >     https://marc.info/?l=devicetree&m=146739193215518&w=2
> > > 
> > > [2] T.Nowicki "Introduce ACPI world to ITS irqchip" v7
> > >     https://marc.info/?l=linux-arm-kernel&m=146642080022289&w=2
> > > 
> > > [3] T.Nowicki "Support for ARM64 ACPI based PCI host controller" v8
> > >     http://marc.info/?l=linux-acpi&m=146462129816292&w=2
> > > 
> > > and is provided for early review/testing purposes here:
> > > 
> > > git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git acpi/iort-smmu-v3i
> > >
> > I thought I can got all the 13 patches applied with the above git
> > tree, but I can't find any ACPI related stuff after I cloned the git
> > repos to my local machine, am I missing something here?
> 
> Have you pulled the acpi/iort-smmu-v3 branch ?
>
Hello Lorenzo, forgive my carelessness missing the additional checkout of that branch. 
Thanks and have a nice day :)

> 
> Thanks,
> Lorenzo
> 

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

* [RFC PATCH v3 00/13] ACPI IORT ARM SMMU v3 support
@ 2016-07-26  1:16           ` Dennis Chen
  0 siblings, 0 replies; 72+ messages in thread
From: Dennis Chen @ 2016-07-26  1:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2016 at 09:36:41AM +0100, Lorenzo Pieralisi wrote:
> On Mon, Jul 25, 2016 at 01:53:32PM +0800, Dennis Chen wrote:
> > Hi
> > On Wed, Jul 20, 2016 at 12:23:22PM +0100, Lorenzo Pieralisi wrote:
> > > This RFC patch series is v3 of a previous posting:
> > > 
> > > https://lkml.org/lkml/2016/6/7/523
> > > 
> > > v2 -> v3
> > > 	- Rebased on top of dependencies series [1][2][3](v4.7-rc3)
> > > 	- Added back reliance on ACPI early probing infrastructure
> > > 	- Patch[1-3] merged through other dependent series
> > > 	- Added back IOMMU fwnode generalization
> > > 	- Move SMMU v3 static functions configuration to IORT code
> > > 	- Implemented generic IOMMU fwspec API
> > > 	- Added code to implement fwnode platform device look-up
> > > 
> > > v1 -> v2:
> > > 	- Rebased on top of dependencies series [1][2][3](v4.7-rc1)
> > > 	- Removed IOMMU fwnode generalization
> > > 	- Implemented ARM SMMU v3 ACPI probing instead of ARM SMMU v2
> > > 	  owing to patch series dependencies [1]
> > > 	- Moved platform device creation logic to IORT code to
> > > 	  generalize its usage for ARM SMMU v1-v2-v3 components
> > > 	- Removed reliance on ACPI early device probing
> > > 	- Created IORT specific iommu_xlate() translation hook leaving
> > > 	  OF code unchanged according to v1 reviews
> > > 
> > > The ACPI IORT table provides information that allows instantiating
> > > ARM SMMU devices and carrying out id mappings between components on
> > > ARM based systems (devices, IOMMUs, interrupt controllers).
> > > 
> > > http://infocenter.arm.com/help/topic/com.arm.doc.den0049b/DEN0049B_IO_Remapping_Table.pdf
> > > 
> > > Building on basic IORT support, available through [2]:
> > > 
> > > this patchset enables ARM SMMU v3 support on ACPI systems.
> > > 
> > > Most of the code is aimed at building the required generic ACPI
> > > infrastructure to create and enable IOMMU components and to bring
> > > the IOMMU infrastructure for ACPI on par with DT, which is going to
> > > make future ARM SMMU components easier to integrate.
> > > 
> > > PATCH (1) adds a FWNODE_IOMMU type to the struct fwnode_handle type.
> > >           It is required to attach a fwnode identifier to platform
> > >           devices allocated/detected through IORT tables entries;
> > >           IOMMU devices have to have an identifier to look them up
> > >           eg IOMMU core layer carrying out id translation. This can be
> > >           done through a fwnode_handle (ie IOMMU platform devices created
> > >           out of IORT tables are not ACPI devices hence they can't be
> > >           allocated as such, otherwise they would have a fwnode_handle of
> > >           type FWNODE_ACPI). This patch requires discussion and it is key
> > >           to the RFC.
> > > 
> > > PATCH (2) makes use of the ACPI early probing API to add a linker script
> > >           section for probing devices via IORT ACPI kernel code.
> > > 
> > > PATCH (3) provides IORT support for registering IOMMU IORT node through
> > >           their fwnode handle.
> > > 
> > > PATCH (4) implements core code fwnode based platform devices look-up.
> > > 
> > > PATCH (5) extends iommu_fwspec so that it can be used on ACPI based
> > >           system by creating a generic IOMMU fwspec kernel layer.
> > > 
> > > PATCH (6) implements the of_dma_configure() API in ACPI world -
> > >           acpi_dma_configure() - and patches PCI and ACPI core code to
> > >           start making use of it.
> > > 
> > > PATCH (7) provides an IORT function to detect existence of specific type
> > >           of IORT components.
> > > 
> > > PATCH (8) creates the kernel infrastructure required to create ARM SMMU
> > >           platform devices for IORT nodes.
> > > 
> > > PATCH (9) refactors the ARM SMMU v3 driver so that the init functions are
> > >           split in a way that groups together code that probes through DT
> > >           and code that carries out HW registers FW agnostic probing, in
> > >           preparation for adding the ACPI probing path.
> > > 
> > > PATCH (10) rework ARM SMMU v3 platform driver registration to make it work
> > >            on ACPI systems.
> > > 
> > > PATCH (11) Building on patch (8), it adds ARM SMMU v3 IORT IOMMU
> > >            operations to create and probe ARM SMMU v3 components.
> > > 
> > > PATCH (12) Extend the IORT iort_node_map_rid() to work on a type mask
> > >            instead of a single type so that the translation API can
> > >            be used on a range of components.
> > > 
> > > PATCH (13) provides IORT infrastructure to carry out IOMMU configuration
> > >            for devices and hook it up to the previously introduced ACPI
> > >            DMA configure API.
> > > 
> > > This patchset is built on top and depends on these three patch series:
> > > 
> > > [1] R.Murphy "Generic DT bindings for PCI and ARM SMMU v3" v4
> > >     https://marc.info/?l=devicetree&m=146739193215518&w=2
> > > 
> > > [2] T.Nowicki "Introduce ACPI world to ITS irqchip" v7
> > >     https://marc.info/?l=linux-arm-kernel&m=146642080022289&w=2
> > > 
> > > [3] T.Nowicki "Support for ARM64 ACPI based PCI host controller" v8
> > >     http://marc.info/?l=linux-acpi&m=146462129816292&w=2
> > > 
> > > and is provided for early review/testing purposes here:
> > > 
> > > git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git acpi/iort-smmu-v3i
> > >
> > I thought I can got all the 13 patches applied with the above git
> > tree, but I can't find any ACPI related stuff after I cloned the git
> > repos to my local machine, am I missing something here?
> 
> Have you pulled the acpi/iort-smmu-v3 branch ?
>
Hello Lorenzo, forgive my carelessness missing the additional checkout of that branch. 
Thanks and have a nice day :)

> 
> Thanks,
> Lorenzo
> 

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

* Re: [RFC PATCH v3 13/13] drivers: acpi: iort: introduce iort_iommu_configure
  2016-07-20 11:23   ` Lorenzo Pieralisi
  (?)
@ 2016-08-03 14:19       ` nwatters
  -1 siblings, 0 replies; 72+ messages in thread
From: nwatters-sgV2jX0FEOL9JmXXK+q4OQ @ 2016-08-03 14:19 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Marc Zyngier,
	Tomasz Nowicki, Rafael J. Wysocki,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Will Deacon, Sinan Kaya,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Hanjun Guo,
	linux-pci-u79uwXL29TY76Z2rM5mHXA, Jon Masters

On 2016-07-20 07:23, Lorenzo Pieralisi wrote:
> DT based systems have a generic kernel API to configure IOMMUs
> for devices (ie of_iommu_configure()).
> 
> On ARM based ACPI systems, the of_iommu_configure() equivalent can
> be implemented atop ACPI IORT kernel API, with the corresponding
> functions to map device identifiers to IOMMUs and retrieve the
> corresponding IOMMU operations necessary for DMA operations set-up.
> 
> By relying on the iommu_fwspec generic kernel infrastructure,
> implement the IORT based IOMMU configuration for ARM ACPI systems
> and hook it up in the ACPI kernel layer that implements DMA
> configuration for a device.
> 
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
> Cc: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Cc: Tomasz Nowicki <tn-nYOzD4b6Jr9Wk0Htik3J/w@public.gmane.org>
> Cc: "Rafael J. Wysocki" <rjw-LthD3rsA81gm4RdzfppkhA@public.gmane.org>
> ---
>  drivers/acpi/iort.c  | 64 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/acpi/scan.c  |  7 +++++-
>  include/linux/iort.h |  4 ++++
>  3 files changed, 74 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
> index c116b68..a12a4ff 100644
> --- a/drivers/acpi/iort.c
> +++ b/drivers/acpi/iort.c
> @@ -18,6 +18,7 @@
> 
>  #define pr_fmt(fmt)	"ACPI: IORT: " fmt
> 
> +#include <linux/iommu-fwspec.h>
>  #include <linux/iort.h>
>  #include <linux/kernel.h>
>  #include <linux/list.h>
> @@ -27,6 +28,8 @@
> 
>  #define IORT_TYPE_MASK(type)	(1 << (type))
>  #define IORT_MSI_TYPE		(1 << ACPI_IORT_NODE_ITS_GROUP)
> +#define IORT_IOMMU_TYPE		((1 << ACPI_IORT_NODE_SMMU) |	\
> +				(1 << ACPI_IORT_NODE_SMMU_V3))
> 
>  struct iort_its_msi_chip {
>  	struct list_head	list;
> @@ -458,6 +461,67 @@ iort_get_device_domain(struct device *dev, u32 
> req_id)
>  	return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
>  }
> 
> +static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
> +{
> +	u32 *rid = data;
> +
> +	*rid = alias;
> +	return 0;
> +}
> +
> +static int arm_smmu_iort_xlate(struct device *dev, u32 streamid,
> +			       struct fwnode_handle *fwnode)
> +{
> +	int ret = iommu_fwspec_init(dev, fwnode);
> +
> +	if (!ret)
> +		ret = iommu_fwspec_add_ids(dev, &streamid, 1);
> +
> +	return 0;

Are you intentionally returning 0 instead of ret? How about doing this 
instead?

	return ret ? ret : iommu_fwspec_add_ids(dev, &streamid, 1);

> +}
> +
> +/**
> + * iort_iommu_configure - Set-up IOMMU configuration for a device.
> + *
> + * @dev: device to configure
> + *
> + * Returns: iommu_ops pointer on configuration success
> + *          NULL on configuration failure
> + */
> +const struct iommu_ops *iort_iommu_configure(struct device *dev)
> +{
> +	struct acpi_iort_node *node, *parent;
> +	struct fwnode_handle *iort_fwnode;
> +	u32 rid = 0, devid = 0;

Since this routine maps the RID space of a device to the StreamID space 
of its
parent smmu, would you consider renaming the devid variable to some form 
of sid
or streamid?

> +
> +	if (dev_is_pci(dev)) {
> +		struct pci_bus *bus = to_pci_dev(dev)->bus;
> +
> +		pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid,
> +				       &rid);
> +
> +		node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
> +				      iort_match_node_callback, &bus->dev);
> +	} else {
> +		node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
> +				      iort_match_node_callback, dev);
> +	}
> +
> +	if (!node)
> +		return NULL;
> +
> +	parent = iort_node_map_rid(node, rid, &devid, IORT_IOMMU_TYPE);
> +	if (parent) {
> +		iort_fwnode = iort_get_fwnode(parent);
> +		if (iort_fwnode) {
> +			arm_smmu_iort_xlate(dev, devid, iort_fwnode);

What about named components with multiple stream ids? Since establishing 
the
relationship between a named component and its parent smmu is already 
dependent
on there being an appropriate mapping of rid 0, it stands to reason that 
all of
the stream ids for a named component could be enumerated by mapping 
increasing
rid values until the output parent no longer matches that returned for 
rid 0.

> +			return fwspec_iommu_get_ops(iort_fwnode);
> +		}
> +	}
> +
> +	return NULL;
> +}

It should be noted that while trying out the approach described above, I 
noticed
that each of the smmu attached named components described in my iort 
were ending
up with an extra stream id. The culprit appears to be that the range 
checking in
iort_id_map() is overly permissive on the upper bounds. For example, 
mappings
with input_base=N and id_count=1 were matching both N and N+1. The 
following
change fixed the issue.

@@ -296,7 +296,7 @@ iort_id_map(struct acpi_iort_id_mapping *map, u8 
type, u32 rid_in, u32 *rid_out)
         }

         if (rid_in < map->input_base ||
-           (rid_in > map->input_base + map->id_count))
+           (rid_in >= map->input_base + map->id_count))
                 return -ENXIO;

         *rid_out = map->output_base + (rid_in - map->input_base);

> +
>  static void acpi_smmu_v3_register_irq(int hwirq, const char *name,
>  				      struct resource *res)
>  {
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index b4b9064..de28825 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -7,6 +7,7 @@
>  #include <linux/slab.h>
>  #include <linux/kernel.h>
>  #include <linux/acpi.h>
> +#include <linux/iort.h>
>  #include <linux/signal.h>
>  #include <linux/kthread.h>
>  #include <linux/dmi.h>
> @@ -1365,11 +1366,15 @@ enum dev_dma_attr acpi_get_dma_attr(struct
> acpi_device *adev)
>   */
>  void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
>  {
> +	const struct iommu_ops *iommu;
> +
> +	iommu = iort_iommu_configure(dev);
> +
>  	/*
>  	 * Assume dma valid range starts at 0 and covers the whole
>  	 * coherent_dma_mask.
>  	 */
> -	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, NULL,
> +	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, iommu,
>  			   attr == DEV_DMA_COHERENT);

If dev has a matching named component iort entry with a non-zero value 
for
memory_address_limit, why not use that as the size input to 
arch_setup_dma_ops?

>  }
> 
> diff --git a/include/linux/iort.h b/include/linux/iort.h
> index 18e6836..bbe08ef 100644
> --- a/include/linux/iort.h
> +++ b/include/linux/iort.h
> @@ -34,6 +34,8 @@ struct irq_domain *iort_get_device_domain(struct
> device *dev, u32 req_id);
>  /* IOMMU interface */
>  int iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
>  				  struct acpi_iort_node *node);
> +
> +const struct iommu_ops *iort_iommu_configure(struct device *dev);
>  #else
>  static inline bool iort_node_match(u8 type) { return false; }
>  static inline void iort_table_detect(void) { }
> @@ -48,6 +50,8 @@ iort_add_smmu_platform_device(struct fwnode_handle 
> *fwnode,
>  {
>  	return -ENODEV;
>  }
> +static inline const struct iommu_ops *
> +iort_iommu_configure(struct device *dev) { return NULL; }
>  #endif
> 
>  #define IORT_ACPI_DECLARE(name, table_id, fn)		\

-- 
Qualcomm Datacenter Technologies, Inc. on behalf of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a 
Linux Foundation Collaborative Project.

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

* Re: [RFC PATCH v3 13/13] drivers: acpi: iort: introduce iort_iommu_configure
@ 2016-08-03 14:19       ` nwatters
  0 siblings, 0 replies; 72+ messages in thread
From: nwatters @ 2016-08-03 14:19 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: iommu, Marc Zyngier, Tomasz Nowicki, Rafael J. Wysocki,
	linux-kernel, Will Deacon, Sinan Kaya, linux-acpi, linux-pci,
	Hanjun Guo, Jon Masters, linux-arm-kernel

On 2016-07-20 07:23, Lorenzo Pieralisi wrote:
> DT based systems have a generic kernel API to configure IOMMUs
> for devices (ie of_iommu_configure()).
> 
> On ARM based ACPI systems, the of_iommu_configure() equivalent can
> be implemented atop ACPI IORT kernel API, with the corresponding
> functions to map device identifiers to IOMMUs and retrieve the
> corresponding IOMMU operations necessary for DMA operations set-up.
> 
> By relying on the iommu_fwspec generic kernel infrastructure,
> implement the IORT based IOMMU configuration for ARM ACPI systems
> and hook it up in the ACPI kernel layer that implements DMA
> configuration for a device.
> 
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Hanjun Guo <hanjun.guo@linaro.org>
> Cc: Tomasz Nowicki <tn@semihalf.com>
> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
> ---
>  drivers/acpi/iort.c  | 64 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/acpi/scan.c  |  7 +++++-
>  include/linux/iort.h |  4 ++++
>  3 files changed, 74 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
> index c116b68..a12a4ff 100644
> --- a/drivers/acpi/iort.c
> +++ b/drivers/acpi/iort.c
> @@ -18,6 +18,7 @@
> 
>  #define pr_fmt(fmt)	"ACPI: IORT: " fmt
> 
> +#include <linux/iommu-fwspec.h>
>  #include <linux/iort.h>
>  #include <linux/kernel.h>
>  #include <linux/list.h>
> @@ -27,6 +28,8 @@
> 
>  #define IORT_TYPE_MASK(type)	(1 << (type))
>  #define IORT_MSI_TYPE		(1 << ACPI_IORT_NODE_ITS_GROUP)
> +#define IORT_IOMMU_TYPE		((1 << ACPI_IORT_NODE_SMMU) |	\
> +				(1 << ACPI_IORT_NODE_SMMU_V3))
> 
>  struct iort_its_msi_chip {
>  	struct list_head	list;
> @@ -458,6 +461,67 @@ iort_get_device_domain(struct device *dev, u32 
> req_id)
>  	return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
>  }
> 
> +static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
> +{
> +	u32 *rid = data;
> +
> +	*rid = alias;
> +	return 0;
> +}
> +
> +static int arm_smmu_iort_xlate(struct device *dev, u32 streamid,
> +			       struct fwnode_handle *fwnode)
> +{
> +	int ret = iommu_fwspec_init(dev, fwnode);
> +
> +	if (!ret)
> +		ret = iommu_fwspec_add_ids(dev, &streamid, 1);
> +
> +	return 0;

Are you intentionally returning 0 instead of ret? How about doing this 
instead?

	return ret ? ret : iommu_fwspec_add_ids(dev, &streamid, 1);

> +}
> +
> +/**
> + * iort_iommu_configure - Set-up IOMMU configuration for a device.
> + *
> + * @dev: device to configure
> + *
> + * Returns: iommu_ops pointer on configuration success
> + *          NULL on configuration failure
> + */
> +const struct iommu_ops *iort_iommu_configure(struct device *dev)
> +{
> +	struct acpi_iort_node *node, *parent;
> +	struct fwnode_handle *iort_fwnode;
> +	u32 rid = 0, devid = 0;

Since this routine maps the RID space of a device to the StreamID space 
of its
parent smmu, would you consider renaming the devid variable to some form 
of sid
or streamid?

> +
> +	if (dev_is_pci(dev)) {
> +		struct pci_bus *bus = to_pci_dev(dev)->bus;
> +
> +		pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid,
> +				       &rid);
> +
> +		node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
> +				      iort_match_node_callback, &bus->dev);
> +	} else {
> +		node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
> +				      iort_match_node_callback, dev);
> +	}
> +
> +	if (!node)
> +		return NULL;
> +
> +	parent = iort_node_map_rid(node, rid, &devid, IORT_IOMMU_TYPE);
> +	if (parent) {
> +		iort_fwnode = iort_get_fwnode(parent);
> +		if (iort_fwnode) {
> +			arm_smmu_iort_xlate(dev, devid, iort_fwnode);

What about named components with multiple stream ids? Since establishing 
the
relationship between a named component and its parent smmu is already 
dependent
on there being an appropriate mapping of rid 0, it stands to reason that 
all of
the stream ids for a named component could be enumerated by mapping 
increasing
rid values until the output parent no longer matches that returned for 
rid 0.

> +			return fwspec_iommu_get_ops(iort_fwnode);
> +		}
> +	}
> +
> +	return NULL;
> +}

It should be noted that while trying out the approach described above, I 
noticed
that each of the smmu attached named components described in my iort 
were ending
up with an extra stream id. The culprit appears to be that the range 
checking in
iort_id_map() is overly permissive on the upper bounds. For example, 
mappings
with input_base=N and id_count=1 were matching both N and N+1. The 
following
change fixed the issue.

@@ -296,7 +296,7 @@ iort_id_map(struct acpi_iort_id_mapping *map, u8 
type, u32 rid_in, u32 *rid_out)
         }

         if (rid_in < map->input_base ||
-           (rid_in > map->input_base + map->id_count))
+           (rid_in >= map->input_base + map->id_count))
                 return -ENXIO;

         *rid_out = map->output_base + (rid_in - map->input_base);

> +
>  static void acpi_smmu_v3_register_irq(int hwirq, const char *name,
>  				      struct resource *res)
>  {
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index b4b9064..de28825 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -7,6 +7,7 @@
>  #include <linux/slab.h>
>  #include <linux/kernel.h>
>  #include <linux/acpi.h>
> +#include <linux/iort.h>
>  #include <linux/signal.h>
>  #include <linux/kthread.h>
>  #include <linux/dmi.h>
> @@ -1365,11 +1366,15 @@ enum dev_dma_attr acpi_get_dma_attr(struct
> acpi_device *adev)
>   */
>  void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
>  {
> +	const struct iommu_ops *iommu;
> +
> +	iommu = iort_iommu_configure(dev);
> +
>  	/*
>  	 * Assume dma valid range starts at 0 and covers the whole
>  	 * coherent_dma_mask.
>  	 */
> -	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, NULL,
> +	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, iommu,
>  			   attr == DEV_DMA_COHERENT);

If dev has a matching named component iort entry with a non-zero value 
for
memory_address_limit, why not use that as the size input to 
arch_setup_dma_ops?

>  }
> 
> diff --git a/include/linux/iort.h b/include/linux/iort.h
> index 18e6836..bbe08ef 100644
> --- a/include/linux/iort.h
> +++ b/include/linux/iort.h
> @@ -34,6 +34,8 @@ struct irq_domain *iort_get_device_domain(struct
> device *dev, u32 req_id);
>  /* IOMMU interface */
>  int iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
>  				  struct acpi_iort_node *node);
> +
> +const struct iommu_ops *iort_iommu_configure(struct device *dev);
>  #else
>  static inline bool iort_node_match(u8 type) { return false; }
>  static inline void iort_table_detect(void) { }
> @@ -48,6 +50,8 @@ iort_add_smmu_platform_device(struct fwnode_handle 
> *fwnode,
>  {
>  	return -ENODEV;
>  }
> +static inline const struct iommu_ops *
> +iort_iommu_configure(struct device *dev) { return NULL; }
>  #endif
> 
>  #define IORT_ACPI_DECLARE(name, table_id, fn)		\

-- 
Qualcomm Datacenter Technologies, Inc. on behalf of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a 
Linux Foundation Collaborative Project.

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

* [RFC PATCH v3 13/13] drivers: acpi: iort: introduce iort_iommu_configure
@ 2016-08-03 14:19       ` nwatters
  0 siblings, 0 replies; 72+ messages in thread
From: nwatters at codeaurora.org @ 2016-08-03 14:19 UTC (permalink / raw)
  To: linux-arm-kernel

On 2016-07-20 07:23, Lorenzo Pieralisi wrote:
> DT based systems have a generic kernel API to configure IOMMUs
> for devices (ie of_iommu_configure()).
> 
> On ARM based ACPI systems, the of_iommu_configure() equivalent can
> be implemented atop ACPI IORT kernel API, with the corresponding
> functions to map device identifiers to IOMMUs and retrieve the
> corresponding IOMMU operations necessary for DMA operations set-up.
> 
> By relying on the iommu_fwspec generic kernel infrastructure,
> implement the IORT based IOMMU configuration for ARM ACPI systems
> and hook it up in the ACPI kernel layer that implements DMA
> configuration for a device.
> 
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Hanjun Guo <hanjun.guo@linaro.org>
> Cc: Tomasz Nowicki <tn@semihalf.com>
> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
> ---
>  drivers/acpi/iort.c  | 64 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/acpi/scan.c  |  7 +++++-
>  include/linux/iort.h |  4 ++++
>  3 files changed, 74 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
> index c116b68..a12a4ff 100644
> --- a/drivers/acpi/iort.c
> +++ b/drivers/acpi/iort.c
> @@ -18,6 +18,7 @@
> 
>  #define pr_fmt(fmt)	"ACPI: IORT: " fmt
> 
> +#include <linux/iommu-fwspec.h>
>  #include <linux/iort.h>
>  #include <linux/kernel.h>
>  #include <linux/list.h>
> @@ -27,6 +28,8 @@
> 
>  #define IORT_TYPE_MASK(type)	(1 << (type))
>  #define IORT_MSI_TYPE		(1 << ACPI_IORT_NODE_ITS_GROUP)
> +#define IORT_IOMMU_TYPE		((1 << ACPI_IORT_NODE_SMMU) |	\
> +				(1 << ACPI_IORT_NODE_SMMU_V3))
> 
>  struct iort_its_msi_chip {
>  	struct list_head	list;
> @@ -458,6 +461,67 @@ iort_get_device_domain(struct device *dev, u32 
> req_id)
>  	return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
>  }
> 
> +static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
> +{
> +	u32 *rid = data;
> +
> +	*rid = alias;
> +	return 0;
> +}
> +
> +static int arm_smmu_iort_xlate(struct device *dev, u32 streamid,
> +			       struct fwnode_handle *fwnode)
> +{
> +	int ret = iommu_fwspec_init(dev, fwnode);
> +
> +	if (!ret)
> +		ret = iommu_fwspec_add_ids(dev, &streamid, 1);
> +
> +	return 0;

Are you intentionally returning 0 instead of ret? How about doing this 
instead?

	return ret ? ret : iommu_fwspec_add_ids(dev, &streamid, 1);

> +}
> +
> +/**
> + * iort_iommu_configure - Set-up IOMMU configuration for a device.
> + *
> + * @dev: device to configure
> + *
> + * Returns: iommu_ops pointer on configuration success
> + *          NULL on configuration failure
> + */
> +const struct iommu_ops *iort_iommu_configure(struct device *dev)
> +{
> +	struct acpi_iort_node *node, *parent;
> +	struct fwnode_handle *iort_fwnode;
> +	u32 rid = 0, devid = 0;

Since this routine maps the RID space of a device to the StreamID space 
of its
parent smmu, would you consider renaming the devid variable to some form 
of sid
or streamid?

> +
> +	if (dev_is_pci(dev)) {
> +		struct pci_bus *bus = to_pci_dev(dev)->bus;
> +
> +		pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid,
> +				       &rid);
> +
> +		node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
> +				      iort_match_node_callback, &bus->dev);
> +	} else {
> +		node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
> +				      iort_match_node_callback, dev);
> +	}
> +
> +	if (!node)
> +		return NULL;
> +
> +	parent = iort_node_map_rid(node, rid, &devid, IORT_IOMMU_TYPE);
> +	if (parent) {
> +		iort_fwnode = iort_get_fwnode(parent);
> +		if (iort_fwnode) {
> +			arm_smmu_iort_xlate(dev, devid, iort_fwnode);

What about named components with multiple stream ids? Since establishing 
the
relationship between a named component and its parent smmu is already 
dependent
on there being an appropriate mapping of rid 0, it stands to reason that 
all of
the stream ids for a named component could be enumerated by mapping 
increasing
rid values until the output parent no longer matches that returned for 
rid 0.

> +			return fwspec_iommu_get_ops(iort_fwnode);
> +		}
> +	}
> +
> +	return NULL;
> +}

It should be noted that while trying out the approach described above, I 
noticed
that each of the smmu attached named components described in my iort 
were ending
up with an extra stream id. The culprit appears to be that the range 
checking in
iort_id_map() is overly permissive on the upper bounds. For example, 
mappings
with input_base=N and id_count=1 were matching both N and N+1. The 
following
change fixed the issue.

@@ -296,7 +296,7 @@ iort_id_map(struct acpi_iort_id_mapping *map, u8 
type, u32 rid_in, u32 *rid_out)
         }

         if (rid_in < map->input_base ||
-           (rid_in > map->input_base + map->id_count))
+           (rid_in >= map->input_base + map->id_count))
                 return -ENXIO;

         *rid_out = map->output_base + (rid_in - map->input_base);

> +
>  static void acpi_smmu_v3_register_irq(int hwirq, const char *name,
>  				      struct resource *res)
>  {
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index b4b9064..de28825 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -7,6 +7,7 @@
>  #include <linux/slab.h>
>  #include <linux/kernel.h>
>  #include <linux/acpi.h>
> +#include <linux/iort.h>
>  #include <linux/signal.h>
>  #include <linux/kthread.h>
>  #include <linux/dmi.h>
> @@ -1365,11 +1366,15 @@ enum dev_dma_attr acpi_get_dma_attr(struct
> acpi_device *adev)
>   */
>  void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
>  {
> +	const struct iommu_ops *iommu;
> +
> +	iommu = iort_iommu_configure(dev);
> +
>  	/*
>  	 * Assume dma valid range starts at 0 and covers the whole
>  	 * coherent_dma_mask.
>  	 */
> -	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, NULL,
> +	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, iommu,
>  			   attr == DEV_DMA_COHERENT);

If dev has a matching named component iort entry with a non-zero value 
for
memory_address_limit, why not use that as the size input to 
arch_setup_dma_ops?

>  }
> 
> diff --git a/include/linux/iort.h b/include/linux/iort.h
> index 18e6836..bbe08ef 100644
> --- a/include/linux/iort.h
> +++ b/include/linux/iort.h
> @@ -34,6 +34,8 @@ struct irq_domain *iort_get_device_domain(struct
> device *dev, u32 req_id);
>  /* IOMMU interface */
>  int iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
>  				  struct acpi_iort_node *node);
> +
> +const struct iommu_ops *iort_iommu_configure(struct device *dev);
>  #else
>  static inline bool iort_node_match(u8 type) { return false; }
>  static inline void iort_table_detect(void) { }
> @@ -48,6 +50,8 @@ iort_add_smmu_platform_device(struct fwnode_handle 
> *fwnode,
>  {
>  	return -ENODEV;
>  }
> +static inline const struct iommu_ops *
> +iort_iommu_configure(struct device *dev) { return NULL; }
>  #endif
> 
>  #define IORT_ACPI_DECLARE(name, table_id, fn)		\

-- 
Qualcomm Datacenter Technologies, Inc. on behalf of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a 
Linux Foundation Collaborative Project.

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

* Re: [RFC PATCH v3 13/13] drivers: acpi: iort: introduce iort_iommu_configure
  2016-08-03 14:19       ` nwatters
  (?)
@ 2016-08-08 16:16           ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-08-08 16:16 UTC (permalink / raw)
  To: nwatters-sgV2jX0FEOL9JmXXK+q4OQ
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Marc Zyngier,
	Tomasz Nowicki, Rafael J. Wysocki,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Will Deacon, Sinan Kaya,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Hanjun Guo,
	linux-pci-u79uwXL29TY76Z2rM5mHXA, Jon Masters

Hi Nate,

thanks for having a look.

On Wed, Aug 03, 2016 at 10:19:43AM -0400, nwatters-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org wrote:
> On 2016-07-20 07:23, Lorenzo Pieralisi wrote:
> >DT based systems have a generic kernel API to configure IOMMUs
> >for devices (ie of_iommu_configure()).
> >
> >On ARM based ACPI systems, the of_iommu_configure() equivalent can
> >be implemented atop ACPI IORT kernel API, with the corresponding
> >functions to map device identifiers to IOMMUs and retrieve the
> >corresponding IOMMU operations necessary for DMA operations set-up.
> >
> >By relying on the iommu_fwspec generic kernel infrastructure,
> >implement the IORT based IOMMU configuration for ARM ACPI systems
> >and hook it up in the ACPI kernel layer that implements DMA
> >configuration for a device.
> >
> >Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
> >Cc: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> >Cc: Tomasz Nowicki <tn-nYOzD4b6Jr9Wk0Htik3J/w@public.gmane.org>
> >Cc: "Rafael J. Wysocki" <rjw-LthD3rsA81gm4RdzfppkhA@public.gmane.org>
> >---
> > drivers/acpi/iort.c  | 64
> >++++++++++++++++++++++++++++++++++++++++++++++++++++
> > drivers/acpi/scan.c  |  7 +++++-
> > include/linux/iort.h |  4 ++++
> > 3 files changed, 74 insertions(+), 1 deletion(-)
> >
> >diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
> >index c116b68..a12a4ff 100644
> >--- a/drivers/acpi/iort.c
> >+++ b/drivers/acpi/iort.c
> >@@ -18,6 +18,7 @@
> >
> > #define pr_fmt(fmt)	"ACPI: IORT: " fmt
> >
> >+#include <linux/iommu-fwspec.h>
> > #include <linux/iort.h>
> > #include <linux/kernel.h>
> > #include <linux/list.h>
> >@@ -27,6 +28,8 @@
> >
> > #define IORT_TYPE_MASK(type)	(1 << (type))
> > #define IORT_MSI_TYPE		(1 << ACPI_IORT_NODE_ITS_GROUP)
> >+#define IORT_IOMMU_TYPE		((1 << ACPI_IORT_NODE_SMMU) |	\
> >+				(1 << ACPI_IORT_NODE_SMMU_V3))
> >
> > struct iort_its_msi_chip {
> > 	struct list_head	list;
> >@@ -458,6 +461,67 @@ iort_get_device_domain(struct device *dev,
> >u32 req_id)
> > 	return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
> > }
> >
> >+static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
> >+{
> >+	u32 *rid = data;
> >+
> >+	*rid = alias;
> >+	return 0;
> >+}
> >+
> >+static int arm_smmu_iort_xlate(struct device *dev, u32 streamid,
> >+			       struct fwnode_handle *fwnode)
> >+{
> >+	int ret = iommu_fwspec_init(dev, fwnode);
> >+
> >+	if (!ret)
> >+		ret = iommu_fwspec_add_ids(dev, &streamid, 1);
> >+
> >+	return 0;
> 
> Are you intentionally returning 0 instead of ret? How about doing
> this instead?
> 
> 	return ret ? ret : iommu_fwspec_add_ids(dev, &streamid, 1);

No, that's a bug, I will return ret as the of_xlate() function in
the ARM SMMU v3 driver does, thanks.

> >+}
> >+
> >+/**
> >+ * iort_iommu_configure - Set-up IOMMU configuration for a device.
> >+ *
> >+ * @dev: device to configure
> >+ *
> >+ * Returns: iommu_ops pointer on configuration success
> >+ *          NULL on configuration failure
> >+ */
> >+const struct iommu_ops *iort_iommu_configure(struct device *dev)
> >+{
> >+	struct acpi_iort_node *node, *parent;
> >+	struct fwnode_handle *iort_fwnode;
> >+	u32 rid = 0, devid = 0;
> 
> Since this routine maps the RID space of a device to the StreamID
> space of its parent smmu, would you consider renaming the devid
> variable to some form of sid or streamid?

Yes, I will do.

> >+	if (dev_is_pci(dev)) {
> >+		struct pci_bus *bus = to_pci_dev(dev)->bus;
> >+
> >+		pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid,
> >+				       &rid);
> >+
> >+		node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
> >+				      iort_match_node_callback, &bus->dev);
> >+	} else {
> >+		node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
> >+				      iort_match_node_callback, dev);
> >+	}
> >+
> >+	if (!node)
> >+		return NULL;
> >+
> >+	parent = iort_node_map_rid(node, rid, &devid, IORT_IOMMU_TYPE);
> >+	if (parent) {
> >+		iort_fwnode = iort_get_fwnode(parent);
> >+		if (iort_fwnode) {
> >+			arm_smmu_iort_xlate(dev, devid, iort_fwnode);
> 
> What about named components with multiple stream ids? Since
> establishing the relationship between a named component and its parent
> smmu is already dependent on there being an appropriate mapping of rid
> 0, it stands to reason that all of the stream ids for a named
> component could be enumerated by mapping increasing rid values until
> the output parent no longer matches that returned for rid 0.

Yes, that's a good point, what I am doing currently for named
components is not correct I will update the handling in the next
version. In particular, I think that we should support only
single mappings for named components for the time being and add
code to carry out the mapping as it is done in DT through the
iommus property handling in of_iommu_configure().

> >+			return fwspec_iommu_get_ops(iort_fwnode);
> >+		}
> >+	}
> >+
> >+	return NULL;
> >+}
> 
> It should be noted that while trying out the approach described above,
> I noticed that each of the smmu attached named components described in
> my iort were ending up with an extra stream id. The culprit appears to
> be that the range checking in iort_id_map() is overly permissive on
> the upper bounds. For example, mappings with input_base=N and
> id_count=1 were matching both N and N+1. The following change fixed
> the issue.

I will ask Tomasz to fix it up.

> @@ -296,7 +296,7 @@ iort_id_map(struct acpi_iort_id_mapping *map, u8
> type, u32 rid_in, u32 *rid_out)
>         }
> 
>         if (rid_in < map->input_base ||
> -           (rid_in > map->input_base + map->id_count))
> +           (rid_in >= map->input_base + map->id_count))
>                 return -ENXIO;
> 
>         *rid_out = map->output_base + (rid_in - map->input_base);
> 
> >+
> > static void acpi_smmu_v3_register_irq(int hwirq, const char *name,
> > 				      struct resource *res)
> > {
> >diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> >index b4b9064..de28825 100644
> >--- a/drivers/acpi/scan.c
> >+++ b/drivers/acpi/scan.c
> >@@ -7,6 +7,7 @@
> > #include <linux/slab.h>
> > #include <linux/kernel.h>
> > #include <linux/acpi.h>
> >+#include <linux/iort.h>
> > #include <linux/signal.h>
> > #include <linux/kthread.h>
> > #include <linux/dmi.h>
> >@@ -1365,11 +1366,15 @@ enum dev_dma_attr acpi_get_dma_attr(struct
> >acpi_device *adev)
> >  */
> > void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
> > {
> >+	const struct iommu_ops *iommu;
> >+
> >+	iommu = iort_iommu_configure(dev);
> >+
> > 	/*
> > 	 * Assume dma valid range starts at 0 and covers the whole
> > 	 * coherent_dma_mask.
> > 	 */
> >-	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, NULL,
> >+	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, iommu,
> > 			   attr == DEV_DMA_COHERENT);
> 
> If dev has a matching named component iort entry with a non-zero value
> for memory_address_limit, why not use that as the size input to
> arch_setup_dma_ops?

I was hoping to address this through something more generic (ie
_DMA object - I am not sure it was ever used in x86 world though)
in ACPI rather than relying on IORT named component specific
firmware data (similar to "dma-ranges" handling in DT), I will
certainly keep this in mind though.

Thanks !
Lorenzo

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

* Re: [RFC PATCH v3 13/13] drivers: acpi: iort: introduce iort_iommu_configure
@ 2016-08-08 16:16           ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-08-08 16:16 UTC (permalink / raw)
  To: nwatters
  Cc: iommu, Marc Zyngier, Tomasz Nowicki, Rafael J. Wysocki,
	linux-kernel, Will Deacon, Sinan Kaya, linux-acpi, linux-pci,
	Hanjun Guo, Jon Masters, linux-arm-kernel

Hi Nate,

thanks for having a look.

On Wed, Aug 03, 2016 at 10:19:43AM -0400, nwatters@codeaurora.org wrote:
> On 2016-07-20 07:23, Lorenzo Pieralisi wrote:
> >DT based systems have a generic kernel API to configure IOMMUs
> >for devices (ie of_iommu_configure()).
> >
> >On ARM based ACPI systems, the of_iommu_configure() equivalent can
> >be implemented atop ACPI IORT kernel API, with the corresponding
> >functions to map device identifiers to IOMMUs and retrieve the
> >corresponding IOMMU operations necessary for DMA operations set-up.
> >
> >By relying on the iommu_fwspec generic kernel infrastructure,
> >implement the IORT based IOMMU configuration for ARM ACPI systems
> >and hook it up in the ACPI kernel layer that implements DMA
> >configuration for a device.
> >
> >Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> >Cc: Hanjun Guo <hanjun.guo@linaro.org>
> >Cc: Tomasz Nowicki <tn@semihalf.com>
> >Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
> >---
> > drivers/acpi/iort.c  | 64
> >++++++++++++++++++++++++++++++++++++++++++++++++++++
> > drivers/acpi/scan.c  |  7 +++++-
> > include/linux/iort.h |  4 ++++
> > 3 files changed, 74 insertions(+), 1 deletion(-)
> >
> >diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
> >index c116b68..a12a4ff 100644
> >--- a/drivers/acpi/iort.c
> >+++ b/drivers/acpi/iort.c
> >@@ -18,6 +18,7 @@
> >
> > #define pr_fmt(fmt)	"ACPI: IORT: " fmt
> >
> >+#include <linux/iommu-fwspec.h>
> > #include <linux/iort.h>
> > #include <linux/kernel.h>
> > #include <linux/list.h>
> >@@ -27,6 +28,8 @@
> >
> > #define IORT_TYPE_MASK(type)	(1 << (type))
> > #define IORT_MSI_TYPE		(1 << ACPI_IORT_NODE_ITS_GROUP)
> >+#define IORT_IOMMU_TYPE		((1 << ACPI_IORT_NODE_SMMU) |	\
> >+				(1 << ACPI_IORT_NODE_SMMU_V3))
> >
> > struct iort_its_msi_chip {
> > 	struct list_head	list;
> >@@ -458,6 +461,67 @@ iort_get_device_domain(struct device *dev,
> >u32 req_id)
> > 	return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
> > }
> >
> >+static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
> >+{
> >+	u32 *rid = data;
> >+
> >+	*rid = alias;
> >+	return 0;
> >+}
> >+
> >+static int arm_smmu_iort_xlate(struct device *dev, u32 streamid,
> >+			       struct fwnode_handle *fwnode)
> >+{
> >+	int ret = iommu_fwspec_init(dev, fwnode);
> >+
> >+	if (!ret)
> >+		ret = iommu_fwspec_add_ids(dev, &streamid, 1);
> >+
> >+	return 0;
> 
> Are you intentionally returning 0 instead of ret? How about doing
> this instead?
> 
> 	return ret ? ret : iommu_fwspec_add_ids(dev, &streamid, 1);

No, that's a bug, I will return ret as the of_xlate() function in
the ARM SMMU v3 driver does, thanks.

> >+}
> >+
> >+/**
> >+ * iort_iommu_configure - Set-up IOMMU configuration for a device.
> >+ *
> >+ * @dev: device to configure
> >+ *
> >+ * Returns: iommu_ops pointer on configuration success
> >+ *          NULL on configuration failure
> >+ */
> >+const struct iommu_ops *iort_iommu_configure(struct device *dev)
> >+{
> >+	struct acpi_iort_node *node, *parent;
> >+	struct fwnode_handle *iort_fwnode;
> >+	u32 rid = 0, devid = 0;
> 
> Since this routine maps the RID space of a device to the StreamID
> space of its parent smmu, would you consider renaming the devid
> variable to some form of sid or streamid?

Yes, I will do.

> >+	if (dev_is_pci(dev)) {
> >+		struct pci_bus *bus = to_pci_dev(dev)->bus;
> >+
> >+		pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid,
> >+				       &rid);
> >+
> >+		node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
> >+				      iort_match_node_callback, &bus->dev);
> >+	} else {
> >+		node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
> >+				      iort_match_node_callback, dev);
> >+	}
> >+
> >+	if (!node)
> >+		return NULL;
> >+
> >+	parent = iort_node_map_rid(node, rid, &devid, IORT_IOMMU_TYPE);
> >+	if (parent) {
> >+		iort_fwnode = iort_get_fwnode(parent);
> >+		if (iort_fwnode) {
> >+			arm_smmu_iort_xlate(dev, devid, iort_fwnode);
> 
> What about named components with multiple stream ids? Since
> establishing the relationship between a named component and its parent
> smmu is already dependent on there being an appropriate mapping of rid
> 0, it stands to reason that all of the stream ids for a named
> component could be enumerated by mapping increasing rid values until
> the output parent no longer matches that returned for rid 0.

Yes, that's a good point, what I am doing currently for named
components is not correct I will update the handling in the next
version. In particular, I think that we should support only
single mappings for named components for the time being and add
code to carry out the mapping as it is done in DT through the
iommus property handling in of_iommu_configure().

> >+			return fwspec_iommu_get_ops(iort_fwnode);
> >+		}
> >+	}
> >+
> >+	return NULL;
> >+}
> 
> It should be noted that while trying out the approach described above,
> I noticed that each of the smmu attached named components described in
> my iort were ending up with an extra stream id. The culprit appears to
> be that the range checking in iort_id_map() is overly permissive on
> the upper bounds. For example, mappings with input_base=N and
> id_count=1 were matching both N and N+1. The following change fixed
> the issue.

I will ask Tomasz to fix it up.

> @@ -296,7 +296,7 @@ iort_id_map(struct acpi_iort_id_mapping *map, u8
> type, u32 rid_in, u32 *rid_out)
>         }
> 
>         if (rid_in < map->input_base ||
> -           (rid_in > map->input_base + map->id_count))
> +           (rid_in >= map->input_base + map->id_count))
>                 return -ENXIO;
> 
>         *rid_out = map->output_base + (rid_in - map->input_base);
> 
> >+
> > static void acpi_smmu_v3_register_irq(int hwirq, const char *name,
> > 				      struct resource *res)
> > {
> >diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> >index b4b9064..de28825 100644
> >--- a/drivers/acpi/scan.c
> >+++ b/drivers/acpi/scan.c
> >@@ -7,6 +7,7 @@
> > #include <linux/slab.h>
> > #include <linux/kernel.h>
> > #include <linux/acpi.h>
> >+#include <linux/iort.h>
> > #include <linux/signal.h>
> > #include <linux/kthread.h>
> > #include <linux/dmi.h>
> >@@ -1365,11 +1366,15 @@ enum dev_dma_attr acpi_get_dma_attr(struct
> >acpi_device *adev)
> >  */
> > void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
> > {
> >+	const struct iommu_ops *iommu;
> >+
> >+	iommu = iort_iommu_configure(dev);
> >+
> > 	/*
> > 	 * Assume dma valid range starts at 0 and covers the whole
> > 	 * coherent_dma_mask.
> > 	 */
> >-	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, NULL,
> >+	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, iommu,
> > 			   attr == DEV_DMA_COHERENT);
> 
> If dev has a matching named component iort entry with a non-zero value
> for memory_address_limit, why not use that as the size input to
> arch_setup_dma_ops?

I was hoping to address this through something more generic (ie
_DMA object - I am not sure it was ever used in x86 world though)
in ACPI rather than relying on IORT named component specific
firmware data (similar to "dma-ranges" handling in DT), I will
certainly keep this in mind though.

Thanks !
Lorenzo

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

* [RFC PATCH v3 13/13] drivers: acpi: iort: introduce iort_iommu_configure
@ 2016-08-08 16:16           ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-08-08 16:16 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Nate,

thanks for having a look.

On Wed, Aug 03, 2016 at 10:19:43AM -0400, nwatters at codeaurora.org wrote:
> On 2016-07-20 07:23, Lorenzo Pieralisi wrote:
> >DT based systems have a generic kernel API to configure IOMMUs
> >for devices (ie of_iommu_configure()).
> >
> >On ARM based ACPI systems, the of_iommu_configure() equivalent can
> >be implemented atop ACPI IORT kernel API, with the corresponding
> >functions to map device identifiers to IOMMUs and retrieve the
> >corresponding IOMMU operations necessary for DMA operations set-up.
> >
> >By relying on the iommu_fwspec generic kernel infrastructure,
> >implement the IORT based IOMMU configuration for ARM ACPI systems
> >and hook it up in the ACPI kernel layer that implements DMA
> >configuration for a device.
> >
> >Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> >Cc: Hanjun Guo <hanjun.guo@linaro.org>
> >Cc: Tomasz Nowicki <tn@semihalf.com>
> >Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
> >---
> > drivers/acpi/iort.c  | 64
> >++++++++++++++++++++++++++++++++++++++++++++++++++++
> > drivers/acpi/scan.c  |  7 +++++-
> > include/linux/iort.h |  4 ++++
> > 3 files changed, 74 insertions(+), 1 deletion(-)
> >
> >diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
> >index c116b68..a12a4ff 100644
> >--- a/drivers/acpi/iort.c
> >+++ b/drivers/acpi/iort.c
> >@@ -18,6 +18,7 @@
> >
> > #define pr_fmt(fmt)	"ACPI: IORT: " fmt
> >
> >+#include <linux/iommu-fwspec.h>
> > #include <linux/iort.h>
> > #include <linux/kernel.h>
> > #include <linux/list.h>
> >@@ -27,6 +28,8 @@
> >
> > #define IORT_TYPE_MASK(type)	(1 << (type))
> > #define IORT_MSI_TYPE		(1 << ACPI_IORT_NODE_ITS_GROUP)
> >+#define IORT_IOMMU_TYPE		((1 << ACPI_IORT_NODE_SMMU) |	\
> >+				(1 << ACPI_IORT_NODE_SMMU_V3))
> >
> > struct iort_its_msi_chip {
> > 	struct list_head	list;
> >@@ -458,6 +461,67 @@ iort_get_device_domain(struct device *dev,
> >u32 req_id)
> > 	return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
> > }
> >
> >+static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
> >+{
> >+	u32 *rid = data;
> >+
> >+	*rid = alias;
> >+	return 0;
> >+}
> >+
> >+static int arm_smmu_iort_xlate(struct device *dev, u32 streamid,
> >+			       struct fwnode_handle *fwnode)
> >+{
> >+	int ret = iommu_fwspec_init(dev, fwnode);
> >+
> >+	if (!ret)
> >+		ret = iommu_fwspec_add_ids(dev, &streamid, 1);
> >+
> >+	return 0;
> 
> Are you intentionally returning 0 instead of ret? How about doing
> this instead?
> 
> 	return ret ? ret : iommu_fwspec_add_ids(dev, &streamid, 1);

No, that's a bug, I will return ret as the of_xlate() function in
the ARM SMMU v3 driver does, thanks.

> >+}
> >+
> >+/**
> >+ * iort_iommu_configure - Set-up IOMMU configuration for a device.
> >+ *
> >+ * @dev: device to configure
> >+ *
> >+ * Returns: iommu_ops pointer on configuration success
> >+ *          NULL on configuration failure
> >+ */
> >+const struct iommu_ops *iort_iommu_configure(struct device *dev)
> >+{
> >+	struct acpi_iort_node *node, *parent;
> >+	struct fwnode_handle *iort_fwnode;
> >+	u32 rid = 0, devid = 0;
> 
> Since this routine maps the RID space of a device to the StreamID
> space of its parent smmu, would you consider renaming the devid
> variable to some form of sid or streamid?

Yes, I will do.

> >+	if (dev_is_pci(dev)) {
> >+		struct pci_bus *bus = to_pci_dev(dev)->bus;
> >+
> >+		pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid,
> >+				       &rid);
> >+
> >+		node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
> >+				      iort_match_node_callback, &bus->dev);
> >+	} else {
> >+		node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
> >+				      iort_match_node_callback, dev);
> >+	}
> >+
> >+	if (!node)
> >+		return NULL;
> >+
> >+	parent = iort_node_map_rid(node, rid, &devid, IORT_IOMMU_TYPE);
> >+	if (parent) {
> >+		iort_fwnode = iort_get_fwnode(parent);
> >+		if (iort_fwnode) {
> >+			arm_smmu_iort_xlate(dev, devid, iort_fwnode);
> 
> What about named components with multiple stream ids? Since
> establishing the relationship between a named component and its parent
> smmu is already dependent on there being an appropriate mapping of rid
> 0, it stands to reason that all of the stream ids for a named
> component could be enumerated by mapping increasing rid values until
> the output parent no longer matches that returned for rid 0.

Yes, that's a good point, what I am doing currently for named
components is not correct I will update the handling in the next
version. In particular, I think that we should support only
single mappings for named components for the time being and add
code to carry out the mapping as it is done in DT through the
iommus property handling in of_iommu_configure().

> >+			return fwspec_iommu_get_ops(iort_fwnode);
> >+		}
> >+	}
> >+
> >+	return NULL;
> >+}
> 
> It should be noted that while trying out the approach described above,
> I noticed that each of the smmu attached named components described in
> my iort were ending up with an extra stream id. The culprit appears to
> be that the range checking in iort_id_map() is overly permissive on
> the upper bounds. For example, mappings with input_base=N and
> id_count=1 were matching both N and N+1. The following change fixed
> the issue.

I will ask Tomasz to fix it up.

> @@ -296,7 +296,7 @@ iort_id_map(struct acpi_iort_id_mapping *map, u8
> type, u32 rid_in, u32 *rid_out)
>         }
> 
>         if (rid_in < map->input_base ||
> -           (rid_in > map->input_base + map->id_count))
> +           (rid_in >= map->input_base + map->id_count))
>                 return -ENXIO;
> 
>         *rid_out = map->output_base + (rid_in - map->input_base);
> 
> >+
> > static void acpi_smmu_v3_register_irq(int hwirq, const char *name,
> > 				      struct resource *res)
> > {
> >diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> >index b4b9064..de28825 100644
> >--- a/drivers/acpi/scan.c
> >+++ b/drivers/acpi/scan.c
> >@@ -7,6 +7,7 @@
> > #include <linux/slab.h>
> > #include <linux/kernel.h>
> > #include <linux/acpi.h>
> >+#include <linux/iort.h>
> > #include <linux/signal.h>
> > #include <linux/kthread.h>
> > #include <linux/dmi.h>
> >@@ -1365,11 +1366,15 @@ enum dev_dma_attr acpi_get_dma_attr(struct
> >acpi_device *adev)
> >  */
> > void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
> > {
> >+	const struct iommu_ops *iommu;
> >+
> >+	iommu = iort_iommu_configure(dev);
> >+
> > 	/*
> > 	 * Assume dma valid range starts at 0 and covers the whole
> > 	 * coherent_dma_mask.
> > 	 */
> >-	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, NULL,
> >+	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, iommu,
> > 			   attr == DEV_DMA_COHERENT);
> 
> If dev has a matching named component iort entry with a non-zero value
> for memory_address_limit, why not use that as the size input to
> arch_setup_dma_ops?

I was hoping to address this through something more generic (ie
_DMA object - I am not sure it was ever used in x86 world though)
in ACPI rather than relying on IORT named component specific
firmware data (similar to "dma-ranges" handling in DT), I will
certainly keep this in mind though.

Thanks !
Lorenzo

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

* Re: [RFC PATCH v3 13/13] drivers: acpi: iort: introduce iort_iommu_configure
  2016-08-03 14:19       ` nwatters
  (?)
@ 2016-08-11  8:44           ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-08-11  8:44 UTC (permalink / raw)
  To: nwatters-sgV2jX0FEOL9JmXXK+q4OQ
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Marc Zyngier,
	Tomasz Nowicki, Rafael J. Wysocki,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Will Deacon, Sinan Kaya,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Hanjun Guo,
	linux-pci-u79uwXL29TY76Z2rM5mHXA, Jon Masters

On Wed, Aug 03, 2016 at 10:19:43AM -0400, nwatters-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org wrote:

[...]

> >+const struct iommu_ops *iort_iommu_configure(struct device *dev)
> >+{
> >+	struct acpi_iort_node *node, *parent;
> >+	struct fwnode_handle *iort_fwnode;
> >+	u32 rid = 0, devid = 0;
> 
> Since this routine maps the RID space of a device to the StreamID
> space of its
> parent smmu, would you consider renaming the devid variable to some
> form of sid
> or streamid?
> 
> >+
> >+	if (dev_is_pci(dev)) {
> >+		struct pci_bus *bus = to_pci_dev(dev)->bus;
> >+
> >+		pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid,
> >+				       &rid);
> >+
> >+		node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
> >+				      iort_match_node_callback, &bus->dev);
> >+	} else {
> >+		node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
> >+				      iort_match_node_callback, dev);
> >+	}
> >+
> >+	if (!node)
> >+		return NULL;
> >+
> >+	parent = iort_node_map_rid(node, rid, &devid, IORT_IOMMU_TYPE);
> >+	if (parent) {
> >+		iort_fwnode = iort_get_fwnode(parent);
> >+		if (iort_fwnode) {
> >+			arm_smmu_iort_xlate(dev, devid, iort_fwnode);
> 
> What about named components with multiple stream ids? Since
> establishing the relationship between a named component and its parent
> smmu is already dependent on there being an appropriate mapping of rid
> 0, it stands to reason that all of the stream ids for a named
> component could be enumerated by mapping increasing rid values until
> the output parent no longer matches that returned for rid 0.

I have reworked the code since for named component it makes no
sense to carry out a mapping that depends on an input id given
that we do not have one. Instead what we will do is the same
thing DT does (ie "iommus" property), namely walk the array of
single mappings for a given named component (that do not depend
on the input rid, there is not any) and add them to the translation
as we find them.

Ergo, mappings that are not single mappings are pretty much useless
for named components (for the time being), and I won't allow them.

Thoughts ?

Lorenzo

> 
> >+			return fwspec_iommu_get_ops(iort_fwnode);
> >+		}
> >+	}
> >+
> >+	return NULL;
> >+}
> 
> It should be noted that while trying out the approach described
> above, I noticed
> that each of the smmu attached named components described in my iort
> were ending
> up with an extra stream id. The culprit appears to be that the range
> checking in
> iort_id_map() is overly permissive on the upper bounds. For example,
> mappings
> with input_base=N and id_count=1 were matching both N and N+1. The
> following
> change fixed the issue.
> 
> @@ -296,7 +296,7 @@ iort_id_map(struct acpi_iort_id_mapping *map, u8
> type, u32 rid_in, u32 *rid_out)
>         }
> 
>         if (rid_in < map->input_base ||
> -           (rid_in > map->input_base + map->id_count))
> +           (rid_in >= map->input_base + map->id_count))
>                 return -ENXIO;
> 
>         *rid_out = map->output_base + (rid_in - map->input_base);
> 
> >+
> > static void acpi_smmu_v3_register_irq(int hwirq, const char *name,
> > 				      struct resource *res)
> > {
> >diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> >index b4b9064..de28825 100644
> >--- a/drivers/acpi/scan.c
> >+++ b/drivers/acpi/scan.c
> >@@ -7,6 +7,7 @@
> > #include <linux/slab.h>
> > #include <linux/kernel.h>
> > #include <linux/acpi.h>
> >+#include <linux/iort.h>
> > #include <linux/signal.h>
> > #include <linux/kthread.h>
> > #include <linux/dmi.h>
> >@@ -1365,11 +1366,15 @@ enum dev_dma_attr acpi_get_dma_attr(struct
> >acpi_device *adev)
> >  */
> > void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
> > {
> >+	const struct iommu_ops *iommu;
> >+
> >+	iommu = iort_iommu_configure(dev);
> >+
> > 	/*
> > 	 * Assume dma valid range starts at 0 and covers the whole
> > 	 * coherent_dma_mask.
> > 	 */
> >-	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, NULL,
> >+	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, iommu,
> > 			   attr == DEV_DMA_COHERENT);
> 
> If dev has a matching named component iort entry with a non-zero
> value for
> memory_address_limit, why not use that as the size input to
> arch_setup_dma_ops?
> 
> > }
> >
> >diff --git a/include/linux/iort.h b/include/linux/iort.h
> >index 18e6836..bbe08ef 100644
> >--- a/include/linux/iort.h
> >+++ b/include/linux/iort.h
> >@@ -34,6 +34,8 @@ struct irq_domain *iort_get_device_domain(struct
> >device *dev, u32 req_id);
> > /* IOMMU interface */
> > int iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
> > 				  struct acpi_iort_node *node);
> >+
> >+const struct iommu_ops *iort_iommu_configure(struct device *dev);
> > #else
> > static inline bool iort_node_match(u8 type) { return false; }
> > static inline void iort_table_detect(void) { }
> >@@ -48,6 +50,8 @@ iort_add_smmu_platform_device(struct
> >fwnode_handle *fwnode,
> > {
> > 	return -ENODEV;
> > }
> >+static inline const struct iommu_ops *
> >+iort_iommu_configure(struct device *dev) { return NULL; }
> > #endif
> >
> > #define IORT_ACPI_DECLARE(name, table_id, fn)		\
> 
> -- 
> Qualcomm Datacenter Technologies, Inc. on behalf of Qualcomm
> Technologies, Inc.
> Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a
> Linux Foundation Collaborative Project.
> 

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

* Re: [RFC PATCH v3 13/13] drivers: acpi: iort: introduce iort_iommu_configure
@ 2016-08-11  8:44           ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-08-11  8:44 UTC (permalink / raw)
  To: nwatters
  Cc: iommu, Marc Zyngier, Tomasz Nowicki, Rafael J. Wysocki,
	linux-kernel, Will Deacon, Sinan Kaya, linux-acpi, linux-pci,
	Hanjun Guo, Jon Masters, linux-arm-kernel

On Wed, Aug 03, 2016 at 10:19:43AM -0400, nwatters@codeaurora.org wrote:

[...]

> >+const struct iommu_ops *iort_iommu_configure(struct device *dev)
> >+{
> >+	struct acpi_iort_node *node, *parent;
> >+	struct fwnode_handle *iort_fwnode;
> >+	u32 rid = 0, devid = 0;
> 
> Since this routine maps the RID space of a device to the StreamID
> space of its
> parent smmu, would you consider renaming the devid variable to some
> form of sid
> or streamid?
> 
> >+
> >+	if (dev_is_pci(dev)) {
> >+		struct pci_bus *bus = to_pci_dev(dev)->bus;
> >+
> >+		pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid,
> >+				       &rid);
> >+
> >+		node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
> >+				      iort_match_node_callback, &bus->dev);
> >+	} else {
> >+		node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
> >+				      iort_match_node_callback, dev);
> >+	}
> >+
> >+	if (!node)
> >+		return NULL;
> >+
> >+	parent = iort_node_map_rid(node, rid, &devid, IORT_IOMMU_TYPE);
> >+	if (parent) {
> >+		iort_fwnode = iort_get_fwnode(parent);
> >+		if (iort_fwnode) {
> >+			arm_smmu_iort_xlate(dev, devid, iort_fwnode);
> 
> What about named components with multiple stream ids? Since
> establishing the relationship between a named component and its parent
> smmu is already dependent on there being an appropriate mapping of rid
> 0, it stands to reason that all of the stream ids for a named
> component could be enumerated by mapping increasing rid values until
> the output parent no longer matches that returned for rid 0.

I have reworked the code since for named component it makes no
sense to carry out a mapping that depends on an input id given
that we do not have one. Instead what we will do is the same
thing DT does (ie "iommus" property), namely walk the array of
single mappings for a given named component (that do not depend
on the input rid, there is not any) and add them to the translation
as we find them.

Ergo, mappings that are not single mappings are pretty much useless
for named components (for the time being), and I won't allow them.

Thoughts ?

Lorenzo

> 
> >+			return fwspec_iommu_get_ops(iort_fwnode);
> >+		}
> >+	}
> >+
> >+	return NULL;
> >+}
> 
> It should be noted that while trying out the approach described
> above, I noticed
> that each of the smmu attached named components described in my iort
> were ending
> up with an extra stream id. The culprit appears to be that the range
> checking in
> iort_id_map() is overly permissive on the upper bounds. For example,
> mappings
> with input_base=N and id_count=1 were matching both N and N+1. The
> following
> change fixed the issue.
> 
> @@ -296,7 +296,7 @@ iort_id_map(struct acpi_iort_id_mapping *map, u8
> type, u32 rid_in, u32 *rid_out)
>         }
> 
>         if (rid_in < map->input_base ||
> -           (rid_in > map->input_base + map->id_count))
> +           (rid_in >= map->input_base + map->id_count))
>                 return -ENXIO;
> 
>         *rid_out = map->output_base + (rid_in - map->input_base);
> 
> >+
> > static void acpi_smmu_v3_register_irq(int hwirq, const char *name,
> > 				      struct resource *res)
> > {
> >diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> >index b4b9064..de28825 100644
> >--- a/drivers/acpi/scan.c
> >+++ b/drivers/acpi/scan.c
> >@@ -7,6 +7,7 @@
> > #include <linux/slab.h>
> > #include <linux/kernel.h>
> > #include <linux/acpi.h>
> >+#include <linux/iort.h>
> > #include <linux/signal.h>
> > #include <linux/kthread.h>
> > #include <linux/dmi.h>
> >@@ -1365,11 +1366,15 @@ enum dev_dma_attr acpi_get_dma_attr(struct
> >acpi_device *adev)
> >  */
> > void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
> > {
> >+	const struct iommu_ops *iommu;
> >+
> >+	iommu = iort_iommu_configure(dev);
> >+
> > 	/*
> > 	 * Assume dma valid range starts at 0 and covers the whole
> > 	 * coherent_dma_mask.
> > 	 */
> >-	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, NULL,
> >+	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, iommu,
> > 			   attr == DEV_DMA_COHERENT);
> 
> If dev has a matching named component iort entry with a non-zero
> value for
> memory_address_limit, why not use that as the size input to
> arch_setup_dma_ops?
> 
> > }
> >
> >diff --git a/include/linux/iort.h b/include/linux/iort.h
> >index 18e6836..bbe08ef 100644
> >--- a/include/linux/iort.h
> >+++ b/include/linux/iort.h
> >@@ -34,6 +34,8 @@ struct irq_domain *iort_get_device_domain(struct
> >device *dev, u32 req_id);
> > /* IOMMU interface */
> > int iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
> > 				  struct acpi_iort_node *node);
> >+
> >+const struct iommu_ops *iort_iommu_configure(struct device *dev);
> > #else
> > static inline bool iort_node_match(u8 type) { return false; }
> > static inline void iort_table_detect(void) { }
> >@@ -48,6 +50,8 @@ iort_add_smmu_platform_device(struct
> >fwnode_handle *fwnode,
> > {
> > 	return -ENODEV;
> > }
> >+static inline const struct iommu_ops *
> >+iort_iommu_configure(struct device *dev) { return NULL; }
> > #endif
> >
> > #define IORT_ACPI_DECLARE(name, table_id, fn)		\
> 
> -- 
> Qualcomm Datacenter Technologies, Inc. on behalf of Qualcomm
> Technologies, Inc.
> Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a
> Linux Foundation Collaborative Project.
> 

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

* [RFC PATCH v3 13/13] drivers: acpi: iort: introduce iort_iommu_configure
@ 2016-08-11  8:44           ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-08-11  8:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 03, 2016 at 10:19:43AM -0400, nwatters at codeaurora.org wrote:

[...]

> >+const struct iommu_ops *iort_iommu_configure(struct device *dev)
> >+{
> >+	struct acpi_iort_node *node, *parent;
> >+	struct fwnode_handle *iort_fwnode;
> >+	u32 rid = 0, devid = 0;
> 
> Since this routine maps the RID space of a device to the StreamID
> space of its
> parent smmu, would you consider renaming the devid variable to some
> form of sid
> or streamid?
> 
> >+
> >+	if (dev_is_pci(dev)) {
> >+		struct pci_bus *bus = to_pci_dev(dev)->bus;
> >+
> >+		pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid,
> >+				       &rid);
> >+
> >+		node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
> >+				      iort_match_node_callback, &bus->dev);
> >+	} else {
> >+		node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
> >+				      iort_match_node_callback, dev);
> >+	}
> >+
> >+	if (!node)
> >+		return NULL;
> >+
> >+	parent = iort_node_map_rid(node, rid, &devid, IORT_IOMMU_TYPE);
> >+	if (parent) {
> >+		iort_fwnode = iort_get_fwnode(parent);
> >+		if (iort_fwnode) {
> >+			arm_smmu_iort_xlate(dev, devid, iort_fwnode);
> 
> What about named components with multiple stream ids? Since
> establishing the relationship between a named component and its parent
> smmu is already dependent on there being an appropriate mapping of rid
> 0, it stands to reason that all of the stream ids for a named
> component could be enumerated by mapping increasing rid values until
> the output parent no longer matches that returned for rid 0.

I have reworked the code since for named component it makes no
sense to carry out a mapping that depends on an input id given
that we do not have one. Instead what we will do is the same
thing DT does (ie "iommus" property), namely walk the array of
single mappings for a given named component (that do not depend
on the input rid, there is not any) and add them to the translation
as we find them.

Ergo, mappings that are not single mappings are pretty much useless
for named components (for the time being), and I won't allow them.

Thoughts ?

Lorenzo

> 
> >+			return fwspec_iommu_get_ops(iort_fwnode);
> >+		}
> >+	}
> >+
> >+	return NULL;
> >+}
> 
> It should be noted that while trying out the approach described
> above, I noticed
> that each of the smmu attached named components described in my iort
> were ending
> up with an extra stream id. The culprit appears to be that the range
> checking in
> iort_id_map() is overly permissive on the upper bounds. For example,
> mappings
> with input_base=N and id_count=1 were matching both N and N+1. The
> following
> change fixed the issue.
> 
> @@ -296,7 +296,7 @@ iort_id_map(struct acpi_iort_id_mapping *map, u8
> type, u32 rid_in, u32 *rid_out)
>         }
> 
>         if (rid_in < map->input_base ||
> -           (rid_in > map->input_base + map->id_count))
> +           (rid_in >= map->input_base + map->id_count))
>                 return -ENXIO;
> 
>         *rid_out = map->output_base + (rid_in - map->input_base);
> 
> >+
> > static void acpi_smmu_v3_register_irq(int hwirq, const char *name,
> > 				      struct resource *res)
> > {
> >diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> >index b4b9064..de28825 100644
> >--- a/drivers/acpi/scan.c
> >+++ b/drivers/acpi/scan.c
> >@@ -7,6 +7,7 @@
> > #include <linux/slab.h>
> > #include <linux/kernel.h>
> > #include <linux/acpi.h>
> >+#include <linux/iort.h>
> > #include <linux/signal.h>
> > #include <linux/kthread.h>
> > #include <linux/dmi.h>
> >@@ -1365,11 +1366,15 @@ enum dev_dma_attr acpi_get_dma_attr(struct
> >acpi_device *adev)
> >  */
> > void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
> > {
> >+	const struct iommu_ops *iommu;
> >+
> >+	iommu = iort_iommu_configure(dev);
> >+
> > 	/*
> > 	 * Assume dma valid range starts at 0 and covers the whole
> > 	 * coherent_dma_mask.
> > 	 */
> >-	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, NULL,
> >+	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, iommu,
> > 			   attr == DEV_DMA_COHERENT);
> 
> If dev has a matching named component iort entry with a non-zero
> value for
> memory_address_limit, why not use that as the size input to
> arch_setup_dma_ops?
> 
> > }
> >
> >diff --git a/include/linux/iort.h b/include/linux/iort.h
> >index 18e6836..bbe08ef 100644
> >--- a/include/linux/iort.h
> >+++ b/include/linux/iort.h
> >@@ -34,6 +34,8 @@ struct irq_domain *iort_get_device_domain(struct
> >device *dev, u32 req_id);
> > /* IOMMU interface */
> > int iort_add_smmu_platform_device(struct fwnode_handle *fwnode,
> > 				  struct acpi_iort_node *node);
> >+
> >+const struct iommu_ops *iort_iommu_configure(struct device *dev);
> > #else
> > static inline bool iort_node_match(u8 type) { return false; }
> > static inline void iort_table_detect(void) { }
> >@@ -48,6 +50,8 @@ iort_add_smmu_platform_device(struct
> >fwnode_handle *fwnode,
> > {
> > 	return -ENODEV;
> > }
> >+static inline const struct iommu_ops *
> >+iort_iommu_configure(struct device *dev) { return NULL; }
> > #endif
> >
> > #define IORT_ACPI_DECLARE(name, table_id, fn)		\
> 
> -- 
> Qualcomm Datacenter Technologies, Inc. on behalf of Qualcomm
> Technologies, Inc.
> Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a
> Linux Foundation Collaborative Project.
> 

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

* Re: [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
  2016-07-25 15:51           ` Robin Murphy
@ 2016-08-11 11:26             ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-08-11 11:26 UTC (permalink / raw)
  To: Robin Murphy
  Cc: iommu, Will Deacon, Hanjun Guo, Joerg Roedel, Marc Zyngier,
	Rafael J. Wysocki, Tomasz Nowicki, Jon Masters, Sinan Kaya,
	linux-acpi, linux-pci, linux-kernel, linux-arm-kernel

On Mon, Jul 25, 2016 at 04:51:00PM +0100, Robin Murphy wrote:
> On 25/07/16 16:41, Lorenzo Pieralisi wrote:
> [...]
> >>> diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
> >>> index 308791f..2362232 100644
> >>> --- a/include/linux/of_iommu.h
> >>> +++ b/include/linux/of_iommu.h
> >>> @@ -15,13 +15,8 @@ extern void of_iommu_init(void);
> >>>  extern const struct iommu_ops *of_iommu_configure(struct device *dev,
> >>>  					struct device_node *master_np);
> >>>  
> >>> -struct iommu_fwspec {
> >>> -	const struct iommu_ops	*iommu_ops;
> >>> -	struct device_node	*iommu_np;
> >>> -	void			*iommu_priv;
> >>> -	unsigned int		num_ids;
> >>> -	u32			ids[];
> >>> -};
> >>> +void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
> >>> +const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
> >>
> >> Is there some reason we need to retain the existing definitions of
> >> these? I was assuming we'd be able to move the entire implementation
> >> over to the fwspec code and leave behind nothing more than trivial
> >> wrappers, e.g.:
> >>
> >> #define of_iommu_get_ops(np) iommu_fwspec_get_ops(&(np)->fwnode_handle)
> > 
> > Yep, that's exactly what I did but then I was bitten by config
> > dependencies. If we implement of_iommu_get/set_ops() as wrappers,
> > we have to compile iommu_fwspec_get/set_ops() on arches that may
> > not have struct dev_archdata.iommu, unless we introduce yet another
> > config symbol to avoid compiling that code (see eg iommu_fwspec_init(),
> > we can't compile it on eg x86 even though we do need of_iommu_get_ops()
> > on it - so iommu_fwspec_get_ops(), that lives in the same compilation
> > unit as eg iommu_fwspec_init()).
> > 
> > So short answer is: there is no reason apart from dev_archdata.iommu
> > being arch specific, if we were able to move iommu_fwspec to generic
> > code (ie struct device, somehow) I would certainly get rid of this
> > stupid code duplication (or as I said I can add a config entry for
> > that, more ideas are welcome).
> 
> OK, given Rob's comment as well, I guess breaking that dependency is to
> everyone's benefit. Since it's quite closely related, how about if we
> follow the arch_setup_dma_ops() pattern with an
> arch_{get,set}_iommu_fwspec(dev) type thing?

How about this (on top of your current iommu/generic branch):

If that's ok feel free to squash it in for the next posting,
or I can add it to my IORT series (I'd argue though that the
problem it solves is not strictly related to ACPI), please
let me know.

Thanks !
Lorenzo

-- >8 --
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2d601d7..dfd331d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -58,6 +58,7 @@ config ARM
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7))
 	select HAVE_IDE if PCI || ISA || PCMCIA
+	select HAVE_IOMMU_FWSPEC if IOMMU_API
 	select HAVE_IRQ_TIME_ACCOUNTING
 	select HAVE_KERNEL_GZIP
 	select HAVE_KERNEL_LZ4
diff --git a/arch/arm/include/asm/iommu-fwspec.h b/arch/arm/include/asm/iommu-fwspec.h
new file mode 100644
index 0000000..d6581a1
--- /dev/null
+++ b/arch/arm/include/asm/iommu-fwspec.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_IOMMU_FWSPEC_H
+#define __ASM_IOMMU_FWSPEC_H
+
+static inline void arch_set_iommu_fwspec(struct device *dev,
+				         struct iommu_fwspec *fwspec)
+{
+	dev->archdata.iommu = fwspec;
+}
+
+static inline struct iommu_fwspec *arch_get_iommu_fwspec(struct device *dev)
+{
+	return dev->archdata.iommu;
+}
+#endif
+
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 69c8787..90d420f 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -82,6 +82,7 @@ config ARM64
 	select HAVE_GCC_PLUGINS
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
+	select HAVE_IOMMU_FWSPEC if IOMMU_API
 	select HAVE_IRQ_TIME_ACCOUNTING
 	select HAVE_MEMBLOCK
 	select HAVE_MEMBLOCK_NODE_MAP if NUMA
diff --git a/arch/arm64/include/asm/iommu-fwspec.h b/arch/arm64/include/asm/iommu-fwspec.h
new file mode 100644
index 0000000..d6581a1
--- /dev/null
+++ b/arch/arm64/include/asm/iommu-fwspec.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_IOMMU_FWSPEC_H
+#define __ASM_IOMMU_FWSPEC_H
+
+static inline void arch_set_iommu_fwspec(struct device *dev,
+				         struct iommu_fwspec *fwspec)
+{
+	dev->archdata.iommu = fwspec;
+}
+
+static inline struct iommu_fwspec *arch_get_iommu_fwspec(struct device *dev)
+{
+	return dev->archdata.iommu;
+}
+#endif
+
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 8ee54d7..101cb17 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -67,6 +67,9 @@ config OF_IOMMU
        def_bool y
        depends on OF && IOMMU_API
 
+config HAVE_IOMMU_FWSPEC
+	bool
+
 # IOMMU-agnostic DMA-mapping layer
 config IOMMU_DMA
 	bool
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index bec51eb..e30f860 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -222,7 +222,7 @@ postcore_initcall_sync(of_iommu_init);
 
 int iommu_fwspec_init(struct device *dev, struct device_node *iommu_np)
 {
-	struct iommu_fwspec *fwspec = dev->archdata.iommu;
+	struct iommu_fwspec *fwspec = arch_get_iommu_fwspec(dev);
 
 	if (fwspec)
 		return 0;
@@ -233,13 +233,13 @@ int iommu_fwspec_init(struct device *dev, struct device_node *iommu_np)
 
 	fwspec->iommu_np = of_node_get(iommu_np);
 	fwspec->iommu_ops = of_iommu_get_ops(iommu_np);
-	dev->archdata.iommu = fwspec;
+	arch_set_iommu_fwspec(dev, fwspec);
 	return 0;
 }
 
 void iommu_fwspec_free(struct device *dev)
 {
-	struct iommu_fwspec *fwspec = dev->archdata.iommu;
+	struct iommu_fwspec *fwspec = arch_get_iommu_fwspec(dev);
 
 	if (fwspec) {
 		of_node_put(fwspec->iommu_np);
@@ -249,7 +249,7 @@ void iommu_fwspec_free(struct device *dev)
 
 int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids)
 {
-	struct iommu_fwspec *fwspec = dev->archdata.iommu;
+	struct iommu_fwspec *fwspec = arch_get_iommu_fwspec(dev);
 	size_t size;
 
 	if (!fwspec)
@@ -263,11 +263,11 @@ int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids)
 	while (num_ids--)
 		fwspec->ids[fwspec->num_ids++] = *ids++;
 
-	dev->archdata.iommu = fwspec;
+	arch_set_iommu_fwspec(dev, fwspec);
 	return 0;
 }
 
 inline struct iommu_fwspec *dev_iommu_fwspec(struct device *dev)
 {
-	return dev->archdata.iommu;
+	return arch_get_iommu_fwspec(dev);
 }
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
index accdc05..358db49 100644
--- a/include/linux/of_iommu.h
+++ b/include/linux/of_iommu.h
@@ -46,6 +46,16 @@ void iommu_fwspec_free(struct device *dev);
 int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
 struct iommu_fwspec *dev_iommu_fwspec(struct device *dev);
 
+#ifdef CONFIG_HAVE_IOMMU_FWSPEC
+#include <asm/iommu-fwspec.h>
+#else /* !CONFIG_HAVE_IOMMU_FWSPEC */
+static inline void arch_set_iommu_fwspec(struct device *dev,
+					 struct iommu_fwspec *fwspec) {}
+
+static inline struct iommu_fwspec *
+arch_get_iommu_fwspec(struct device *dev) { return NULL; }
+#endif
+
 void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
 const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
 

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

* [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic
@ 2016-08-11 11:26             ` Lorenzo Pieralisi
  0 siblings, 0 replies; 72+ messages in thread
From: Lorenzo Pieralisi @ 2016-08-11 11:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2016 at 04:51:00PM +0100, Robin Murphy wrote:
> On 25/07/16 16:41, Lorenzo Pieralisi wrote:
> [...]
> >>> diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
> >>> index 308791f..2362232 100644
> >>> --- a/include/linux/of_iommu.h
> >>> +++ b/include/linux/of_iommu.h
> >>> @@ -15,13 +15,8 @@ extern void of_iommu_init(void);
> >>>  extern const struct iommu_ops *of_iommu_configure(struct device *dev,
> >>>  					struct device_node *master_np);
> >>>  
> >>> -struct iommu_fwspec {
> >>> -	const struct iommu_ops	*iommu_ops;
> >>> -	struct device_node	*iommu_np;
> >>> -	void			*iommu_priv;
> >>> -	unsigned int		num_ids;
> >>> -	u32			ids[];
> >>> -};
> >>> +void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
> >>> +const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
> >>
> >> Is there some reason we need to retain the existing definitions of
> >> these? I was assuming we'd be able to move the entire implementation
> >> over to the fwspec code and leave behind nothing more than trivial
> >> wrappers, e.g.:
> >>
> >> #define of_iommu_get_ops(np) iommu_fwspec_get_ops(&(np)->fwnode_handle)
> > 
> > Yep, that's exactly what I did but then I was bitten by config
> > dependencies. If we implement of_iommu_get/set_ops() as wrappers,
> > we have to compile iommu_fwspec_get/set_ops() on arches that may
> > not have struct dev_archdata.iommu, unless we introduce yet another
> > config symbol to avoid compiling that code (see eg iommu_fwspec_init(),
> > we can't compile it on eg x86 even though we do need of_iommu_get_ops()
> > on it - so iommu_fwspec_get_ops(), that lives in the same compilation
> > unit as eg iommu_fwspec_init()).
> > 
> > So short answer is: there is no reason apart from dev_archdata.iommu
> > being arch specific, if we were able to move iommu_fwspec to generic
> > code (ie struct device, somehow) I would certainly get rid of this
> > stupid code duplication (or as I said I can add a config entry for
> > that, more ideas are welcome).
> 
> OK, given Rob's comment as well, I guess breaking that dependency is to
> everyone's benefit. Since it's quite closely related, how about if we
> follow the arch_setup_dma_ops() pattern with an
> arch_{get,set}_iommu_fwspec(dev) type thing?

How about this (on top of your current iommu/generic branch):

If that's ok feel free to squash it in for the next posting,
or I can add it to my IORT series (I'd argue though that the
problem it solves is not strictly related to ACPI), please
let me know.

Thanks !
Lorenzo

-- >8 --
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2d601d7..dfd331d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -58,6 +58,7 @@ config ARM
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7))
 	select HAVE_IDE if PCI || ISA || PCMCIA
+	select HAVE_IOMMU_FWSPEC if IOMMU_API
 	select HAVE_IRQ_TIME_ACCOUNTING
 	select HAVE_KERNEL_GZIP
 	select HAVE_KERNEL_LZ4
diff --git a/arch/arm/include/asm/iommu-fwspec.h b/arch/arm/include/asm/iommu-fwspec.h
new file mode 100644
index 0000000..d6581a1
--- /dev/null
+++ b/arch/arm/include/asm/iommu-fwspec.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_IOMMU_FWSPEC_H
+#define __ASM_IOMMU_FWSPEC_H
+
+static inline void arch_set_iommu_fwspec(struct device *dev,
+				         struct iommu_fwspec *fwspec)
+{
+	dev->archdata.iommu = fwspec;
+}
+
+static inline struct iommu_fwspec *arch_get_iommu_fwspec(struct device *dev)
+{
+	return dev->archdata.iommu;
+}
+#endif
+
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 69c8787..90d420f 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -82,6 +82,7 @@ config ARM64
 	select HAVE_GCC_PLUGINS
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
+	select HAVE_IOMMU_FWSPEC if IOMMU_API
 	select HAVE_IRQ_TIME_ACCOUNTING
 	select HAVE_MEMBLOCK
 	select HAVE_MEMBLOCK_NODE_MAP if NUMA
diff --git a/arch/arm64/include/asm/iommu-fwspec.h b/arch/arm64/include/asm/iommu-fwspec.h
new file mode 100644
index 0000000..d6581a1
--- /dev/null
+++ b/arch/arm64/include/asm/iommu-fwspec.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_IOMMU_FWSPEC_H
+#define __ASM_IOMMU_FWSPEC_H
+
+static inline void arch_set_iommu_fwspec(struct device *dev,
+				         struct iommu_fwspec *fwspec)
+{
+	dev->archdata.iommu = fwspec;
+}
+
+static inline struct iommu_fwspec *arch_get_iommu_fwspec(struct device *dev)
+{
+	return dev->archdata.iommu;
+}
+#endif
+
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 8ee54d7..101cb17 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -67,6 +67,9 @@ config OF_IOMMU
        def_bool y
        depends on OF && IOMMU_API
 
+config HAVE_IOMMU_FWSPEC
+	bool
+
 # IOMMU-agnostic DMA-mapping layer
 config IOMMU_DMA
 	bool
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index bec51eb..e30f860 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -222,7 +222,7 @@ postcore_initcall_sync(of_iommu_init);
 
 int iommu_fwspec_init(struct device *dev, struct device_node *iommu_np)
 {
-	struct iommu_fwspec *fwspec = dev->archdata.iommu;
+	struct iommu_fwspec *fwspec = arch_get_iommu_fwspec(dev);
 
 	if (fwspec)
 		return 0;
@@ -233,13 +233,13 @@ int iommu_fwspec_init(struct device *dev, struct device_node *iommu_np)
 
 	fwspec->iommu_np = of_node_get(iommu_np);
 	fwspec->iommu_ops = of_iommu_get_ops(iommu_np);
-	dev->archdata.iommu = fwspec;
+	arch_set_iommu_fwspec(dev, fwspec);
 	return 0;
 }
 
 void iommu_fwspec_free(struct device *dev)
 {
-	struct iommu_fwspec *fwspec = dev->archdata.iommu;
+	struct iommu_fwspec *fwspec = arch_get_iommu_fwspec(dev);
 
 	if (fwspec) {
 		of_node_put(fwspec->iommu_np);
@@ -249,7 +249,7 @@ void iommu_fwspec_free(struct device *dev)
 
 int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids)
 {
-	struct iommu_fwspec *fwspec = dev->archdata.iommu;
+	struct iommu_fwspec *fwspec = arch_get_iommu_fwspec(dev);
 	size_t size;
 
 	if (!fwspec)
@@ -263,11 +263,11 @@ int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids)
 	while (num_ids--)
 		fwspec->ids[fwspec->num_ids++] = *ids++;
 
-	dev->archdata.iommu = fwspec;
+	arch_set_iommu_fwspec(dev, fwspec);
 	return 0;
 }
 
 inline struct iommu_fwspec *dev_iommu_fwspec(struct device *dev)
 {
-	return dev->archdata.iommu;
+	return arch_get_iommu_fwspec(dev);
 }
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
index accdc05..358db49 100644
--- a/include/linux/of_iommu.h
+++ b/include/linux/of_iommu.h
@@ -46,6 +46,16 @@ void iommu_fwspec_free(struct device *dev);
 int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
 struct iommu_fwspec *dev_iommu_fwspec(struct device *dev);
 
+#ifdef CONFIG_HAVE_IOMMU_FWSPEC
+#include <asm/iommu-fwspec.h>
+#else /* !CONFIG_HAVE_IOMMU_FWSPEC */
+static inline void arch_set_iommu_fwspec(struct device *dev,
+					 struct iommu_fwspec *fwspec) {}
+
+static inline struct iommu_fwspec *
+arch_get_iommu_fwspec(struct device *dev) { return NULL; }
+#endif
+
 void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
 const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
 

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

end of thread, other threads:[~2016-08-11 11:26 UTC | newest]

Thread overview: 72+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-20 11:23 [RFC PATCH v3 00/13] ACPI IORT ARM SMMU v3 support Lorenzo Pieralisi
2016-07-20 11:23 ` Lorenzo Pieralisi
     [not found] ` <1469013815-24380-1-git-send-email-lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
2016-07-20 11:23   ` [RFC PATCH v3 01/13] drivers: iommu: add FWNODE_IOMMU fwnode type Lorenzo Pieralisi
2016-07-20 11:23     ` Lorenzo Pieralisi
2016-07-20 11:23     ` Lorenzo Pieralisi
2016-07-20 11:23   ` [RFC PATCH v3 02/13] drivers: acpi: iort: introduce linker section for IORT entries probing Lorenzo Pieralisi
2016-07-20 11:23     ` Lorenzo Pieralisi
2016-07-20 11:23     ` Lorenzo Pieralisi
2016-07-20 11:23   ` [RFC PATCH v3 04/13] drivers: platform: add fwnode base platform devices retrieval Lorenzo Pieralisi
2016-07-20 11:23     ` Lorenzo Pieralisi
2016-07-20 11:23     ` Lorenzo Pieralisi
2016-07-20 11:23   ` [RFC PATCH v3 05/13] drivers: iommu: make iommu_fwspec OF agnostic Lorenzo Pieralisi
2016-07-20 11:23     ` Lorenzo Pieralisi
2016-07-20 11:23     ` Lorenzo Pieralisi
2016-07-25 15:09     ` Robin Murphy
2016-07-25 15:09       ` Robin Murphy
     [not found]       ` <1499f802-5f98-b0c0-d3aa-dabcac81e84e-5wv7dgnIgG8@public.gmane.org>
2016-07-25 15:21         ` Rob Herring
2016-07-25 15:21           ` Rob Herring
2016-07-25 15:21           ` Rob Herring
2016-07-25 15:21           ` Rob Herring
2016-07-25 15:56           ` Lorenzo Pieralisi
2016-07-25 15:56             ` Lorenzo Pieralisi
2016-07-25 15:56             ` Lorenzo Pieralisi
2016-07-25 15:41       ` Lorenzo Pieralisi
2016-07-25 15:41         ` Lorenzo Pieralisi
2016-07-25 15:51         ` Robin Murphy
2016-07-25 15:51           ` Robin Murphy
2016-07-25 16:12           ` Lorenzo Pieralisi
2016-07-25 16:12             ` Lorenzo Pieralisi
2016-08-11 11:26           ` Lorenzo Pieralisi
2016-08-11 11:26             ` Lorenzo Pieralisi
2016-07-20 11:23   ` [RFC PATCH v3 07/13] drivers: acpi: iort: add node match function Lorenzo Pieralisi
2016-07-20 11:23     ` Lorenzo Pieralisi
2016-07-20 11:23     ` Lorenzo Pieralisi
2016-07-20 11:23   ` [RFC PATCH v3 08/13] drivers: acpi: iort: add support for ARM SMMU platform devices creation Lorenzo Pieralisi
2016-07-20 11:23     ` Lorenzo Pieralisi
2016-07-20 11:23     ` Lorenzo Pieralisi
2016-07-20 11:23   ` [RFC PATCH v3 10/13] drivers: iommu: arm-smmu-v3: enable ACPI driver initialization Lorenzo Pieralisi
2016-07-20 11:23     ` Lorenzo Pieralisi
2016-07-20 11:23     ` Lorenzo Pieralisi
2016-07-20 11:23   ` [RFC PATCH v3 11/13] drivers: iommu: arm-smmu-v3: add IORT platform device creation Lorenzo Pieralisi
2016-07-20 11:23     ` Lorenzo Pieralisi
2016-07-20 11:23     ` Lorenzo Pieralisi
2016-07-20 11:23   ` [RFC PATCH v3 12/13] drivers: acpi: iort: replace rid map type with type mask Lorenzo Pieralisi
2016-07-20 11:23     ` Lorenzo Pieralisi
2016-07-20 11:23     ` Lorenzo Pieralisi
2016-07-25  5:53   ` [RFC PATCH v3 00/13] ACPI IORT ARM SMMU v3 support Dennis Chen
2016-07-25  5:53     ` Dennis Chen
2016-07-25  5:53     ` Dennis Chen
     [not found]     ` <20160725055330.GA21004-5wv7dgnIgG8@public.gmane.org>
2016-07-25  8:36       ` Lorenzo Pieralisi
2016-07-25  8:36         ` Lorenzo Pieralisi
2016-07-25  8:36         ` Lorenzo Pieralisi
2016-07-26  1:16         ` Dennis Chen
2016-07-26  1:16           ` Dennis Chen
2016-07-26  1:16           ` Dennis Chen
2016-07-20 11:23 ` [RFC PATCH v3 03/13] drivers: acpi: iort: add support for IOMMU fwnode registration Lorenzo Pieralisi
2016-07-20 11:23   ` Lorenzo Pieralisi
2016-07-20 11:23 ` [RFC PATCH v3 06/13] drivers: acpi: implement acpi_dma_configure Lorenzo Pieralisi
2016-07-20 11:23   ` Lorenzo Pieralisi
2016-07-20 11:23 ` [RFC PATCH v3 09/13] drivers: iommu: arm-smmu-v3: split probe functions into DT/generic portions Lorenzo Pieralisi
2016-07-20 11:23   ` Lorenzo Pieralisi
2016-07-20 11:23 ` [RFC PATCH v3 13/13] drivers: acpi: iort: introduce iort_iommu_configure Lorenzo Pieralisi
2016-07-20 11:23   ` Lorenzo Pieralisi
     [not found]   ` <1469013815-24380-14-git-send-email-lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
2016-08-03 14:19     ` nwatters-sgV2jX0FEOL9JmXXK+q4OQ
2016-08-03 14:19       ` nwatters at codeaurora.org
2016-08-03 14:19       ` nwatters
     [not found]       ` <016fb1080595ef61ec7a91da15ef2430-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2016-08-08 16:16         ` Lorenzo Pieralisi
2016-08-08 16:16           ` Lorenzo Pieralisi
2016-08-08 16:16           ` Lorenzo Pieralisi
2016-08-11  8:44         ` Lorenzo Pieralisi
2016-08-11  8:44           ` Lorenzo Pieralisi
2016-08-11  8:44           ` Lorenzo Pieralisi

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.