linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node
@ 2022-04-04 12:41 Shameer Kolothum
  2022-04-04 12:41 ` [PATCH v9 01/11] ACPI/IORT: Add temporary RMR node flag definitions Shameer Kolothum
                   ` (12 more replies)
  0 siblings, 13 replies; 25+ messages in thread
From: Shameer Kolothum @ 2022-04-04 12:41 UTC (permalink / raw)
  To: linux-arm-kernel, linux-acpi, iommu
  Cc: linuxarm, lorenzo.pieralisi, joro, robin.murphy, will,
	wanghuiqiang, guohanjun, steven.price, Sami.Mujawar, jon,
	eric.auger, laurentiu.tudor, yangyicong

Hi

v8 --> v9
 - Adressed comments from Robin on interfaces as discussed here[0].
 - Addressed comments from Lorenzo.
 
Though functionally there aren't any major changes, the interfaces have
changed from v8 and for that reason not included the T-by tags from
Steve and Eric yet(Many thanks for that). Appreciate it if you could
give this a spin and let me know.

(The revised ACPICA pull request for IORT E.d related changes is
here[1] and this is now merged to acpica:master.)

Please take a look and let me know your thoughts.

Thanks,
Shameer
[0] https://lore.kernel.org/linux-arm-kernel/c982f1d7-c565-769a-abae-79c962969d88@arm.com/
[1] https://github.com/acpica/acpica/pull/765

From old:
We have faced issues with 3408iMR RAID controller cards which
fail to boot when SMMU is enabled. This is because these
controllers make use of host memory for various caching related
purposes and when SMMU is enabled the iMR firmware fails to
access these memory regions as there is no mapping for them.
IORT RMR provides a way for UEFI to describe and report these
memory regions so that the kernel can make a unity mapping for
these in SMMU.

Change History:

v7 --> v8
  - Patch #1 has temp definitions for RMR related changes till
    the ACPICA header changes are part of kernel.
  - No early parsing of RMR node info and is only parsed at the
    time of use.
  - Changes to the RMR get/put API format compared to the
    previous version.
  - Support for RMR descriptor shared by multiple stream IDs.

v6 --> v7
 -fix pointed out by Steve to the SMMUv2 SMR bypass install in patch #8.

v5 --> v6
- Addressed comments from Robin & Lorenzo.
  : Moved iort_parse_rmr() to acpi_iort_init() from
    iort_init_platform_devices().
  : Removed use of struct iort_rmr_entry during the initial
    parse. Using struct iommu_resv_region instead.
  : Report RMR address alignment and overlap errors, but continue.
  : Reworked arm_smmu_init_bypass_stes() (patch # 6).
- Updated SMMUv2 bypass SMR code. Thanks to Jon N (patch #8).
- Set IOMMU protection flags(IOMMU_CACHE, IOMMU_MMIO) based
  on Type of RMR region. Suggested by Jon N.

v4 --> v5
 -Added a fw_data union to struct iommu_resv_region and removed
  struct iommu_rmr (Based on comments from Joerg/Robin).
 -Added iommu_put_rmrs() to release mem.
 -Thanks to Steve for verifying on SMMUv2, but not added the Tested-by
  yet because of the above changes.

v3 -->v4
-Included the SMMUv2 SMR bypass install changes suggested by
 Steve(patch #7)
-As per Robin's comments, RMR reserve implementation is now
 more generic  (patch #8) and dropped v3 patches 8 and 10.
-Rebase to 5.13-rc1

RFC v2 --> v3
 -Dropped RFC tag as the ACPICA header changes are now ready to be
  part of 5.13[0]. But this series still has a dependency on that patch.
 -Added IORT E.b related changes(node flags, _DSM function 5 checks for
  PCIe).
 -Changed RMR to stream id mapping from M:N to M:1 as per the spec and
  discussion here[1].
 -Last two patches add support for SMMUv2(Thanks to Jon Nettleton!)

Jon Nettleton (1):
  iommu/arm-smmu: Get associated RMR info and install bypass SMR

Shameer Kolothum (10):
  ACPI/IORT: Add temporary RMR node flag definitions
  iommu: Introduce a union to struct iommu_resv_region
  ACPI/IORT: Make iort_iommu_msi_get_resv_regions() return void
  ACPI/IORT: Provide a generic helper to retrieve reserve regions
  iommu/dma: Introduce a helper to remove reserved regions
  ACPI/IORT: Add support to retrieve IORT RMR reserved regions
  ACPI/IORT: Add a helper to retrieve RMR info directly
  iommu/arm-smmu-v3: Introduce strtab init helper
  iommu/arm-smmu-v3: Refactor arm_smmu_init_bypass_stes() to force
    bypass
  iommu/arm-smmu-v3: Get associated RMR info and install bypass STE

 drivers/acpi/arm64/iort.c                   | 369 ++++++++++++++++++--
 drivers/iommu/apple-dart.c                  |   2 +-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c |  80 ++++-
 drivers/iommu/arm/arm-smmu/arm-smmu.c       |  54 ++-
 drivers/iommu/dma-iommu.c                   |  11 +-
 drivers/iommu/virtio-iommu.c                |   2 +-
 include/linux/acpi_iort.h                   |  18 +-
 include/linux/dma-iommu.h                   |   5 +
 include/linux/iommu.h                       |   9 +
 9 files changed, 505 insertions(+), 45 deletions(-)

-- 
2.25.1


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

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

* [PATCH v9 01/11] ACPI/IORT: Add temporary RMR node flag definitions
  2022-04-04 12:41 [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node Shameer Kolothum
@ 2022-04-04 12:41 ` Shameer Kolothum
  2022-04-06 15:53   ` Lorenzo Pieralisi
  2022-04-04 12:42 ` [PATCH v9 02/11] iommu: Introduce a union to struct iommu_resv_region Shameer Kolothum
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 25+ messages in thread
From: Shameer Kolothum @ 2022-04-04 12:41 UTC (permalink / raw)
  To: linux-arm-kernel, linux-acpi, iommu
  Cc: linuxarm, lorenzo.pieralisi, joro, robin.murphy, will,
	wanghuiqiang, guohanjun, steven.price, Sami.Mujawar, jon,
	eric.auger, laurentiu.tudor, yangyicong

IORT rev E.d introduces more details into the RMR node Flags
field. Add temporary definitions to describe and access these
Flags field until ACPICA header is updated to support E.d.

This patch can be reverted once the include/acpi/actbl2.h has
all the relevant definitions.

Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
Please find the ACPICA E.d related changes pull request here,
https://github.com/acpica/acpica/pull/765

This is now merged to acpica:master.

---
 drivers/acpi/arm64/iort.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index f2f8f05662de..fd06cf43ba31 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -25,6 +25,30 @@
 #define IORT_IOMMU_TYPE		((1 << ACPI_IORT_NODE_SMMU) |	\
 				(1 << ACPI_IORT_NODE_SMMU_V3))
 
+/*
+ * The following RMR related definitions are temporary and
+ * can be removed once ACPICA headers support IORT rev E.d
+ */
+#ifndef ACPI_IORT_RMR_REMAP_PERMITTED
+#define ACPI_IORT_RMR_REMAP_PERMITTED	(1)
+#endif
+
+#ifndef ACPI_IORT_RMR_ACCESS_PRIVILEGE
+#define ACPI_IORT_RMR_ACCESS_PRIVILEGE	(1 << 1)
+#endif
+
+#ifndef ACPI_IORT_RMR_ACCESS_ATTRIBUTES
+#define ACPI_IORT_RMR_ACCESS_ATTRIBUTES(flags)	(((flags) >> 2) & 0xFF)
+#endif
+
+#ifndef ACPI_IORT_RMR_ATTR_DEVICE_GRE
+#define ACPI_IORT_RMR_ATTR_DEVICE_GRE	0x03
+#endif
+
+#ifndef ACPI_IORT_RMR_ATTR_NORMAL_IWB_OWB
+#define ACPI_IORT_RMR_ATTR_NORMAL_IWB_OWB	0x05
+#endif
+
 struct iort_its_msi_chip {
 	struct list_head	list;
 	struct fwnode_handle	*fw_node;
-- 
2.25.1


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

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

* [PATCH v9 02/11] iommu: Introduce a union to struct iommu_resv_region
  2022-04-04 12:41 [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node Shameer Kolothum
  2022-04-04 12:41 ` [PATCH v9 01/11] ACPI/IORT: Add temporary RMR node flag definitions Shameer Kolothum
@ 2022-04-04 12:42 ` Shameer Kolothum
  2022-04-04 12:42 ` [PATCH v9 03/11] ACPI/IORT: Make iort_iommu_msi_get_resv_regions() return void Shameer Kolothum
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Shameer Kolothum @ 2022-04-04 12:42 UTC (permalink / raw)
  To: linux-arm-kernel, linux-acpi, iommu
  Cc: linuxarm, lorenzo.pieralisi, joro, robin.murphy, will,
	wanghuiqiang, guohanjun, steven.price, Sami.Mujawar, jon,
	eric.auger, laurentiu.tudor, yangyicong

A union is introduced to struct iommu_resv_region to hold
any firmware specific data. This is in preparation to add
support for IORT RMR reserve regions and the union now holds
the RMR specific information.

Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
 include/linux/iommu.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 9208eca4b0d1..733f46b14ac8 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -127,6 +127,11 @@ enum iommu_resv_type {
 	IOMMU_RESV_SW_MSI,
 };
 
+struct iommu_iort_rmr_data {
+	const u32 *sids;	/* Stream IDs associated with IORT RMR entry */
+	u32 num_sids;
+};
+
 /**
  * struct iommu_resv_region - descriptor for a reserved memory region
  * @list: Linked list pointers
@@ -134,6 +139,7 @@ enum iommu_resv_type {
  * @length: Length of the region in bytes
  * @prot: IOMMU Protection flags (READ/WRITE/...)
  * @type: Type of the reserved region
+ * @fw_data: Firmware-specific data
  */
 struct iommu_resv_region {
 	struct list_head	list;
@@ -141,6 +147,9 @@ struct iommu_resv_region {
 	size_t			length;
 	int			prot;
 	enum iommu_resv_type	type;
+	union {
+		struct iommu_iort_rmr_data rmr;
+	} fw_data;
 };
 
 /**
-- 
2.25.1


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

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

* [PATCH v9 03/11] ACPI/IORT: Make iort_iommu_msi_get_resv_regions() return void
  2022-04-04 12:41 [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node Shameer Kolothum
  2022-04-04 12:41 ` [PATCH v9 01/11] ACPI/IORT: Add temporary RMR node flag definitions Shameer Kolothum
  2022-04-04 12:42 ` [PATCH v9 02/11] iommu: Introduce a union to struct iommu_resv_region Shameer Kolothum
@ 2022-04-04 12:42 ` Shameer Kolothum
  2022-04-06 15:12   ` Lorenzo Pieralisi
  2022-04-04 12:42 ` [PATCH v9 04/11] ACPI/IORT: Provide a generic helper to retrieve reserve regions Shameer Kolothum
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 25+ messages in thread
From: Shameer Kolothum @ 2022-04-04 12:42 UTC (permalink / raw)
  To: linux-arm-kernel, linux-acpi, iommu
  Cc: linuxarm, lorenzo.pieralisi, joro, robin.murphy, will,
	wanghuiqiang, guohanjun, steven.price, Sami.Mujawar, jon,
	eric.auger, laurentiu.tudor, yangyicong

At present iort_iommu_msi_get_resv_regions() returns the number of
MSI reserved regions on success and there are no users for this.
The reserved region list will get populated anyway for platforms
that require the HW MSI region reservation. Hence, change the
function to return void instead.

Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
 drivers/acpi/arm64/iort.c | 26 ++++++++++----------------
 include/linux/acpi_iort.h |  6 +++---
 2 files changed, 13 insertions(+), 19 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index fd06cf43ba31..c5ebb2be9a19 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -832,25 +832,23 @@ static struct acpi_iort_node *iort_get_msi_resv_iommu(struct device *dev)
 
 /**
  * iort_iommu_msi_get_resv_regions - Reserved region driver helper
+ *                                   for HW MSI regions.
  * @dev: Device from iommu_get_resv_regions()
  * @head: Reserved region list from iommu_get_resv_regions()
  *
- * Returns: Number of msi reserved regions on success (0 if platform
- *          doesn't require the reservation or no associated msi regions),
- *          appropriate error value otherwise. The ITS interrupt translation
- *          spaces (ITS_base + SZ_64K, SZ_64K) associated with the device
- *          are the msi reserved regions.
+ * The ITS interrupt translation spaces (ITS_base + SZ_64K, SZ_64K)
+ * associated with the device are the HW MSI reserved regions.
  */
-int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
+void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
 {
 	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
 	struct acpi_iort_its_group *its;
 	struct acpi_iort_node *iommu_node, *its_node = NULL;
-	int i, resv = 0;
+	int i;
 
 	iommu_node = iort_get_msi_resv_iommu(dev);
 	if (!iommu_node)
-		return 0;
+		return;
 
 	/*
 	 * Current logic to reserve ITS regions relies on HW topologies
@@ -870,7 +868,7 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
 	}
 
 	if (!its_node)
-		return 0;
+		return;
 
 	/* Move to ITS specific data */
 	its = (struct acpi_iort_its_group *)its_node->node_data;
@@ -884,14 +882,10 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
 
 			region = iommu_alloc_resv_region(base + SZ_64K, SZ_64K,
 							 prot, IOMMU_RESV_MSI);
-			if (region) {
+			if (region)
 				list_add_tail(&region->list, head);
-				resv++;
-			}
 		}
 	}
-
-	return (resv == its->its_count) ? resv : -ENODEV;
 }
 
 static inline bool iort_iommu_driver_enabled(u8 type)
@@ -1058,8 +1052,8 @@ int iort_iommu_configure_id(struct device *dev, const u32 *id_in)
 }
 
 #else
-int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
-{ return 0; }
+void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
+{ }
 int iort_iommu_configure_id(struct device *dev, const u32 *input_id)
 { return -ENODEV; }
 #endif
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index f1f0842a2cb2..a8198b83753d 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -36,7 +36,7 @@ int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
 /* IOMMU interface */
 int iort_dma_get_ranges(struct device *dev, u64 *size);
 int iort_iommu_configure_id(struct device *dev, const u32 *id_in);
-int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head);
+void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head);
 phys_addr_t acpi_iort_dma_get_max_cpu_address(void);
 #else
 static inline void acpi_iort_init(void) { }
@@ -52,8 +52,8 @@ static inline int iort_dma_get_ranges(struct device *dev, u64 *size)
 static inline int iort_iommu_configure_id(struct device *dev, const u32 *id_in)
 { return -ENODEV; }
 static inline
-int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
-{ return 0; }
+void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
+{ }
 
 static inline phys_addr_t acpi_iort_dma_get_max_cpu_address(void)
 { return PHYS_ADDR_MAX; }
-- 
2.25.1


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

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

* [PATCH v9 04/11] ACPI/IORT: Provide a generic helper to retrieve reserve regions
  2022-04-04 12:41 [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node Shameer Kolothum
                   ` (2 preceding siblings ...)
  2022-04-04 12:42 ` [PATCH v9 03/11] ACPI/IORT: Make iort_iommu_msi_get_resv_regions() return void Shameer Kolothum
@ 2022-04-04 12:42 ` Shameer Kolothum
  2022-04-06 15:54   ` Lorenzo Pieralisi
  2022-04-04 12:42 ` [PATCH v9 05/11] iommu/dma: Introduce a helper to remove reserved regions Shameer Kolothum
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 25+ messages in thread
From: Shameer Kolothum @ 2022-04-04 12:42 UTC (permalink / raw)
  To: linux-arm-kernel, linux-acpi, iommu
  Cc: linuxarm, lorenzo.pieralisi, joro, robin.murphy, will,
	wanghuiqiang, guohanjun, steven.price, Sami.Mujawar, jon,
	eric.auger, laurentiu.tudor, yangyicong

Currently IORT provides a helper to retrieve HW MSI reserve regions.
Change this to a generic helper to retrieve any IORT related reserve
regions. This will be useful when we add support for RMR nodes in
subsequent patches.

Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
 drivers/acpi/arm64/iort.c | 23 +++++++++++++++--------
 drivers/iommu/dma-iommu.c |  2 +-
 include/linux/acpi_iort.h |  4 ++--
 3 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index c5ebb2be9a19..63acc3c5b275 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -830,16 +830,13 @@ static struct acpi_iort_node *iort_get_msi_resv_iommu(struct device *dev)
 	return NULL;
 }
 
-/**
- * iort_iommu_msi_get_resv_regions - Reserved region driver helper
- *                                   for HW MSI regions.
- * @dev: Device from iommu_get_resv_regions()
- * @head: Reserved region list from iommu_get_resv_regions()
- *
+/*
+ * Retrieve platform specific HW MSI reserve regions.
  * The ITS interrupt translation spaces (ITS_base + SZ_64K, SZ_64K)
  * associated with the device are the HW MSI reserved regions.
  */
-void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
+static void
+iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
 {
 	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
 	struct acpi_iort_its_group *its;
@@ -888,6 +885,16 @@ void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
 	}
 }
 
+/**
+ * iort_iommu_get_resv_regions - Generic helper to retrieve reserved regions.
+ * @dev: Device from iommu_get_resv_regions()
+ * @head: Reserved region list from iommu_get_resv_regions()
+ */
+void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head)
+{
+	iort_iommu_msi_get_resv_regions(dev, head);
+}
+
 static inline bool iort_iommu_driver_enabled(u8 type)
 {
 	switch (type) {
@@ -1052,7 +1059,7 @@ int iort_iommu_configure_id(struct device *dev, const u32 *id_in)
 }
 
 #else
-void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
+void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head)
 { }
 int iort_iommu_configure_id(struct device *dev, const u32 *input_id)
 { return -ENODEV; }
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 09f6e1c0f9c0..93d76b666888 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -384,7 +384,7 @@ void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
 {
 
 	if (!is_of_node(dev_iommu_fwspec_get(dev)->iommu_fwnode))
-		iort_iommu_msi_get_resv_regions(dev, list);
+		iort_iommu_get_resv_regions(dev, list);
 
 }
 EXPORT_SYMBOL(iommu_dma_get_resv_regions);
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index a8198b83753d..e5d2de9caf7f 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -36,7 +36,7 @@ int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
 /* IOMMU interface */
 int iort_dma_get_ranges(struct device *dev, u64 *size);
 int iort_iommu_configure_id(struct device *dev, const u32 *id_in);
-void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head);
+void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head);
 phys_addr_t acpi_iort_dma_get_max_cpu_address(void);
 #else
 static inline void acpi_iort_init(void) { }
@@ -52,7 +52,7 @@ static inline int iort_dma_get_ranges(struct device *dev, u64 *size)
 static inline int iort_iommu_configure_id(struct device *dev, const u32 *id_in)
 { return -ENODEV; }
 static inline
-void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
+void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head)
 { }
 
 static inline phys_addr_t acpi_iort_dma_get_max_cpu_address(void)
-- 
2.25.1


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

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

* [PATCH v9 05/11] iommu/dma: Introduce a helper to remove reserved regions
  2022-04-04 12:41 [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node Shameer Kolothum
                   ` (3 preceding siblings ...)
  2022-04-04 12:42 ` [PATCH v9 04/11] ACPI/IORT: Provide a generic helper to retrieve reserve regions Shameer Kolothum
@ 2022-04-04 12:42 ` Shameer Kolothum
  2022-04-07 13:26   ` Christoph Hellwig
  2022-04-04 12:42 ` [PATCH v9 06/11] ACPI/IORT: Add support to retrieve IORT RMR " Shameer Kolothum
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 25+ messages in thread
From: Shameer Kolothum @ 2022-04-04 12:42 UTC (permalink / raw)
  To: linux-arm-kernel, linux-acpi, iommu
  Cc: linuxarm, lorenzo.pieralisi, joro, robin.murphy, will,
	wanghuiqiang, guohanjun, steven.price, Sami.Mujawar, jon,
	eric.auger, laurentiu.tudor, yangyicong

Currently drivers use generic_iommu_put_resv_regions() to remove
reserved regions. Introduce a dma-iommu specific reserve region
removal helper(iommu_dma_put_resv_regions()). This will be useful
when we introduce reserve regions with any firmware specific memory
allocations(eg: IORT RMR) that have to be freed. Also update current
users of iommu_dma_get_resv_regions() to use iommu_dma_put_resv_regions()
for removal.

Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
 drivers/iommu/apple-dart.c                  | 2 +-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +-
 drivers/iommu/arm/arm-smmu/arm-smmu.c       | 2 +-
 drivers/iommu/dma-iommu.c                   | 6 ++++++
 drivers/iommu/virtio-iommu.c                | 2 +-
 include/linux/dma-iommu.h                   | 5 +++++
 6 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
index decafb07ad08..6c198a08e50f 100644
--- a/drivers/iommu/apple-dart.c
+++ b/drivers/iommu/apple-dart.c
@@ -771,7 +771,7 @@ static const struct iommu_ops apple_dart_iommu_ops = {
 	.of_xlate = apple_dart_of_xlate,
 	.def_domain_type = apple_dart_def_domain_type,
 	.get_resv_regions = apple_dart_get_resv_regions,
-	.put_resv_regions = generic_iommu_put_resv_regions,
+	.put_resv_regions = iommu_dma_put_resv_regions,
 	.pgsize_bitmap = -1UL, /* Restricted during dart probe */
 	.default_domain_ops = &(const struct iommu_domain_ops) {
 		.attach_dev	= apple_dart_attach_dev,
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 627a3ed5ee8f..efa38b4411f3 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2847,7 +2847,7 @@ static struct iommu_ops arm_smmu_ops = {
 	.device_group		= arm_smmu_device_group,
 	.of_xlate		= arm_smmu_of_xlate,
 	.get_resv_regions	= arm_smmu_get_resv_regions,
-	.put_resv_regions	= generic_iommu_put_resv_regions,
+	.put_resv_regions	= iommu_dma_put_resv_regions,
 	.dev_has_feat		= arm_smmu_dev_has_feature,
 	.dev_feat_enabled	= arm_smmu_dev_feature_enabled,
 	.dev_enable_feat	= arm_smmu_dev_enable_feature,
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index 568cce590ccc..9a5b785d28fd 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -1589,7 +1589,7 @@ static struct iommu_ops arm_smmu_ops = {
 	.device_group		= arm_smmu_device_group,
 	.of_xlate		= arm_smmu_of_xlate,
 	.get_resv_regions	= arm_smmu_get_resv_regions,
-	.put_resv_regions	= generic_iommu_put_resv_regions,
+	.put_resv_regions	= iommu_dma_put_resv_regions,
 	.def_domain_type	= arm_smmu_def_domain_type,
 	.pgsize_bitmap		= -1UL, /* Restricted during device attach */
 	.owner			= THIS_MODULE,
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 93d76b666888..44e3f3feaab6 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -389,6 +389,12 @@ void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
 }
 EXPORT_SYMBOL(iommu_dma_get_resv_regions);
 
+void iommu_dma_put_resv_regions(struct device *dev, struct list_head *list)
+{
+	generic_iommu_put_resv_regions(dev, list);
+}
+EXPORT_SYMBOL(iommu_dma_put_resv_regions);
+
 static int cookie_init_hw_msi_region(struct iommu_dma_cookie *cookie,
 		phys_addr_t start, phys_addr_t end)
 {
diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
index 25be4b822aa0..b8fea7576bbd 100644
--- a/drivers/iommu/virtio-iommu.c
+++ b/drivers/iommu/virtio-iommu.c
@@ -1013,7 +1013,7 @@ static struct iommu_ops viommu_ops = {
 	.release_device		= viommu_release_device,
 	.device_group		= viommu_device_group,
 	.get_resv_regions	= viommu_get_resv_regions,
-	.put_resv_regions	= generic_iommu_put_resv_regions,
+	.put_resv_regions	= iommu_dma_put_resv_regions,
 	.of_xlate		= viommu_of_xlate,
 	.owner			= THIS_MODULE,
 	.default_domain_ops = &(const struct iommu_domain_ops) {
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
index 24607dc3c2ac..0628db1e3272 100644
--- a/include/linux/dma-iommu.h
+++ b/include/linux/dma-iommu.h
@@ -37,6 +37,7 @@ void iommu_dma_compose_msi_msg(struct msi_desc *desc,
 			       struct msi_msg *msg);
 
 void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list);
+void iommu_dma_put_resv_regions(struct device *dev, struct list_head *list);
 
 void iommu_dma_free_cpu_cached_iovas(unsigned int cpu,
 		struct iommu_domain *domain);
@@ -89,5 +90,9 @@ static inline void iommu_dma_get_resv_regions(struct device *dev, struct list_he
 {
 }
 
+static inline void iommu_dma_put_resv_regions(struct device *dev, struct list_head *list)
+{
+}
+
 #endif	/* CONFIG_IOMMU_DMA */
 #endif	/* __DMA_IOMMU_H */
-- 
2.25.1


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

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

* [PATCH v9 06/11] ACPI/IORT: Add support to retrieve IORT RMR reserved regions
  2022-04-04 12:41 [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node Shameer Kolothum
                   ` (4 preceding siblings ...)
  2022-04-04 12:42 ` [PATCH v9 05/11] iommu/dma: Introduce a helper to remove reserved regions Shameer Kolothum
@ 2022-04-04 12:42 ` Shameer Kolothum
  2022-04-06 15:47   ` Lorenzo Pieralisi
  2022-04-07 13:28   ` Christoph Hellwig
  2022-04-04 12:42 ` [PATCH v9 07/11] ACPI/IORT: Add a helper to retrieve RMR info directly Shameer Kolothum
                   ` (6 subsequent siblings)
  12 siblings, 2 replies; 25+ messages in thread
From: Shameer Kolothum @ 2022-04-04 12:42 UTC (permalink / raw)
  To: linux-arm-kernel, linux-acpi, iommu
  Cc: linuxarm, lorenzo.pieralisi, joro, robin.murphy, will,
	wanghuiqiang, guohanjun, steven.price, Sami.Mujawar, jon,
	eric.auger, laurentiu.tudor, yangyicong

Parse through the IORT RMR nodes and populate the reserve region list
corresponding to a given IOMMU and device(optional). Also, go through
the ID mappings of the RMR node and retrieve all the SIDs associated
with it.

Now that we have this support, update iommu_dma_get/_put_resv_regions()
paths to include the RMR reserve regions.

Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
 drivers/acpi/arm64/iort.c | 275 ++++++++++++++++++++++++++++++++++++++
 drivers/iommu/dma-iommu.c |   3 +
 include/linux/acpi_iort.h |   4 +
 3 files changed, 282 insertions(+)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 63acc3c5b275..1147387cfddb 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -812,6 +812,259 @@ void acpi_configure_pmsi_domain(struct device *dev)
 }
 
 #ifdef CONFIG_IOMMU_API
+static void iort_rmr_desc_check_overlap(struct acpi_iort_rmr_desc *desc, u32 count)
+{
+	int i, j;
+
+	for (i = 0; i < count; i++) {
+		u64 end, start = desc[i].base_address, length = desc[i].length;
+
+		if (!length) {
+			pr_err(FW_BUG "RMR descriptor[0x%llx] with zero length, continue anyway\n",
+			       start);
+			continue;
+		}
+
+		end = start + length - 1;
+
+		/* Check for address overlap */
+		for (j = i + 1; j < count; j++) {
+			u64 e_start = desc[j].base_address;
+			u64 e_end = e_start + desc[j].length - 1;
+
+			if (start <= e_end && end >= e_start)
+				pr_err(FW_BUG "RMR descriptor[0x%llx - 0x%llx] overlaps, continue anyway\n",
+				       start, end);
+		}
+	}
+}
+
+/*
+ * Please note, we will keep the already allocated RMR reserve
+ * regions in case of a memory allocation failure.
+ */
+static void iort_get_rmrs(struct acpi_iort_node *node,
+			  struct acpi_iort_node *smmu,
+			  u32 *sids, u32 num_sids,
+			  struct list_head *head)
+{
+	struct acpi_iort_rmr *rmr = (struct acpi_iort_rmr *)node->node_data;
+	struct acpi_iort_rmr_desc *rmr_desc;
+	int i;
+
+	rmr_desc = ACPI_ADD_PTR(struct acpi_iort_rmr_desc, node,
+				rmr->rmr_offset);
+
+	iort_rmr_desc_check_overlap(rmr_desc, rmr->rmr_count);
+
+	for (i = 0; i < rmr->rmr_count; i++, rmr_desc++) {
+		struct iommu_resv_region *region;
+		enum iommu_resv_type type;
+		u32  *sids_copy;
+		int prot = IOMMU_READ | IOMMU_WRITE;
+		u64 addr = rmr_desc->base_address, size = rmr_desc->length;
+
+		if (!IS_ALIGNED(addr, SZ_64K) || !IS_ALIGNED(size, SZ_64K)) {
+			/* PAGE align base addr and size */
+			addr &= PAGE_MASK;
+			size = PAGE_ALIGN(size + offset_in_page(rmr_desc->base_address));
+
+			pr_err(FW_BUG "RMR descriptor[0x%llx - 0x%llx] not aligned to 64K, continue with [0x%llx - 0x%llx]\n",
+			       rmr_desc->base_address,
+			       rmr_desc->base_address + rmr_desc->length - 1,
+			       addr, addr + size - 1);
+		}
+
+		if (rmr->flags & ACPI_IORT_RMR_REMAP_PERMITTED)
+			type = IOMMU_RESV_DIRECT_RELAXABLE;
+		else
+			type = IOMMU_RESV_DIRECT;
+
+		if (rmr->flags & ACPI_IORT_RMR_ACCESS_PRIVILEGE)
+			prot |= IOMMU_PRIV;
+
+		/* Attributes 0x00 - 0x03 represents device memory */
+		if (ACPI_IORT_RMR_ACCESS_ATTRIBUTES(rmr->flags) <=
+				ACPI_IORT_RMR_ATTR_DEVICE_GRE)
+			prot |= IOMMU_MMIO;
+		else if (ACPI_IORT_RMR_ACCESS_ATTRIBUTES(rmr->flags) ==
+				ACPI_IORT_RMR_ATTR_NORMAL_IWB_OWB)
+			prot |= IOMMU_CACHE;
+
+		/* Create a copy of SIDs array to associate with this resv region */
+		sids_copy = kmemdup(sids, num_sids * sizeof(*sids), GFP_KERNEL);
+		if (!sids_copy)
+			return;
+
+		region = iommu_alloc_resv_region(addr, size, prot, type);
+		if (!region) {
+			kfree(sids_copy);
+			return;
+		}
+
+		region->fw_data.rmr.sids = sids_copy;
+		region->fw_data.rmr.num_sids = num_sids;
+		list_add_tail(&region->list, head);
+	}
+}
+
+static u32 *iort_rmr_alloc_sids(u32 *sids, u32 count, u32 id_start,
+				u32 new_count)
+{
+	u32 *new_sids;
+	u32 total_count = count + new_count;
+	int i;
+
+	new_sids = krealloc_array(sids, count + new_count,
+				  sizeof(*new_sids), GFP_KERNEL);
+	if (!new_sids)
+		return NULL;
+
+	for (i = count; i < total_count; i++)
+		new_sids[i] = id_start++;
+
+	return new_sids;
+}
+
+static bool iort_rmr_has_dev(struct device *dev, u32 id_start,
+			     u32 id_count)
+{
+	int i;
+	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+
+	/*
+	 * Make sure the kernel has preserved the boot firmware PCIe
+	 * configuration. This is required to ensure that the RMR PCIe
+	 * StreamIDs are still valid (Refer: ARM DEN 0049E.d Section 3.1.1.5).
+	 */
+	if (dev_is_pci(dev)) {
+		struct pci_dev *pdev = to_pci_dev(dev);
+		struct pci_host_bridge *host = pci_find_host_bridge(pdev->bus);
+
+		if (!host->preserve_config)
+			return false;
+	}
+
+	for (i = 0; i < fwspec->num_ids; i++) {
+		if (fwspec->ids[i] >= id_start &&
+		    fwspec->ids[i] <= id_start + id_count)
+			return true;
+	}
+
+	return false;
+}
+
+static void iort_node_get_rmr_info(struct acpi_iort_node *node,
+				   struct acpi_iort_node *iommu,
+				   struct device *dev, struct list_head *head)
+{
+	struct acpi_iort_node *smmu = NULL;
+	struct acpi_iort_rmr *rmr;
+	struct acpi_iort_id_mapping *map;
+	u32 *sids = NULL;
+	u32 num_sids = 0;
+	int i;
+
+	if (!node->mapping_offset || !node->mapping_count) {
+		pr_err(FW_BUG "Invalid ID mapping, skipping RMR node %p\n",
+		       node);
+		return;
+	}
+
+	rmr = (struct acpi_iort_rmr *)node->node_data;
+	if (!rmr->rmr_offset || !rmr->rmr_count)
+		return;
+
+	map = ACPI_ADD_PTR(struct acpi_iort_id_mapping, node,
+			   node->mapping_offset);
+
+	/*
+	 * Go through the ID mappings and see if we have a match for SMMU
+	 * and dev(if !NULL). If found, get the sids for the Node.
+	 * Please note, id_count is equal to the number of IDs  in the
+	 * range minus one.
+	 */
+	for (i = 0; i < node->mapping_count; i++, map++) {
+		struct acpi_iort_node *parent;
+
+		if (!map->id_count)
+			continue;
+
+		parent = ACPI_ADD_PTR(struct acpi_iort_node, iort_table,
+				      map->output_reference);
+		if (parent != iommu)
+			continue;
+
+		/* If dev is valid, check RMR node corresponds to the dev SID */
+		if (dev && !iort_rmr_has_dev(dev, map->output_base,
+					     map->id_count))
+			continue;
+
+		/* Retrieve SIDs associated with the Node. */
+		sids = iort_rmr_alloc_sids(sids, num_sids, map->output_base,
+					   map->id_count + 1);
+		if (!sids)
+			return;
+
+		num_sids += map->id_count + 1;
+	}
+
+	if (!sids)
+		return;
+
+	iort_get_rmrs(node, smmu, sids, num_sids, head);
+	kfree(sids);
+}
+
+static void iort_find_rmrs(struct acpi_iort_node *iommu, struct device *dev,
+			   struct list_head *head)
+{
+	struct acpi_table_iort *iort;
+	struct acpi_iort_node *iort_node, *iort_end;
+	int i;
+
+	/* Only supports ARM DEN 0049E.d onwards */
+	if (iort_table->revision < 5)
+		return;
+
+	iort = (struct acpi_table_iort *)iort_table;
+
+	iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort,
+				 iort->node_offset);
+	iort_end = ACPI_ADD_PTR(struct acpi_iort_node, iort,
+				iort_table->length);
+
+	for (i = 0; i < iort->node_count; i++) {
+		if (WARN_TAINT(iort_node >= iort_end, TAINT_FIRMWARE_WORKAROUND,
+			       "IORT node pointer overflows, bad table!\n"))
+			return;
+
+		if (iort_node->type == ACPI_IORT_NODE_RMR)
+			iort_node_get_rmr_info(iort_node, iommu, dev, head);
+
+		iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node,
+					 iort_node->length);
+	}
+}
+
+/*
+ * Populate the RMR list associated with a given IOMMU and dev(if provided).
+ * If dev is NULL, the function populates all the RMRs associated with the
+ * given IOMMU.
+ */
+static void
+iort_iommu_rmr_get_resv_regions(struct fwnode_handle *iommu_fwnode,
+				struct device *dev, struct list_head *head)
+{
+	struct acpi_iort_node *iommu;
+
+	iommu = iort_get_iort_node(iommu_fwnode);
+	if (!iommu)
+		return;
+
+	iort_find_rmrs(iommu, dev, head);
+}
+
 static struct acpi_iort_node *iort_get_msi_resv_iommu(struct device *dev)
 {
 	struct acpi_iort_node *iommu;
@@ -892,7 +1145,27 @@ iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
  */
 void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head)
 {
+	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+
 	iort_iommu_msi_get_resv_regions(dev, head);
+	iort_iommu_rmr_get_resv_regions(fwspec->iommu_fwnode, dev, head);
+}
+
+/**
+ * iort_iommu_put_resv_regions - Free any IORT specific memory allocations
+ *                               associated with reserve regions.
+ * @dev: Associated device(Optional)
+ * @head: Resereved region list
+ */
+void iort_iommu_put_resv_regions(struct device *dev, struct list_head *head)
+{
+	struct iommu_resv_region *e, *tmp;
+
+	/* RMR entries will have mem allocated for fw_data.rmr.sids. */
+	list_for_each_entry_safe(e, tmp, head, list) {
+		if (e->fw_data.rmr.sids)
+			kfree(e->fw_data.rmr.sids);
+	}
 }
 
 static inline bool iort_iommu_driver_enabled(u8 type)
@@ -1061,6 +1334,8 @@ int iort_iommu_configure_id(struct device *dev, const u32 *id_in)
 #else
 void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head)
 { }
+void iort_iommu_put_resv_regions(struct device *dev, struct list_head *head)
+{ }
 int iort_iommu_configure_id(struct device *dev, const u32 *input_id)
 { return -ENODEV; }
 #endif
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 44e3f3feaab6..5811233dc9fb 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -391,6 +391,9 @@ EXPORT_SYMBOL(iommu_dma_get_resv_regions);
 
 void iommu_dma_put_resv_regions(struct device *dev, struct list_head *list)
 {
+	if (!is_of_node(dev_iommu_fwspec_get(dev)->iommu_fwnode))
+		iort_iommu_put_resv_regions(dev, list);
+
 	generic_iommu_put_resv_regions(dev, list);
 }
 EXPORT_SYMBOL(iommu_dma_put_resv_regions);
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index e5d2de9caf7f..eb3c28853110 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -37,6 +37,7 @@ int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
 int iort_dma_get_ranges(struct device *dev, u64 *size);
 int iort_iommu_configure_id(struct device *dev, const u32 *id_in);
 void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head);
+void iort_iommu_put_resv_regions(struct device *dev, struct list_head *head);
 phys_addr_t acpi_iort_dma_get_max_cpu_address(void);
 #else
 static inline void acpi_iort_init(void) { }
@@ -54,6 +55,9 @@ static inline int iort_iommu_configure_id(struct device *dev, const u32 *id_in)
 static inline
 void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head)
 { }
+static inline
+void iort_iommu_put_resv_regions(struct device *dev, struct list_head *head)
+{ }
 
 static inline phys_addr_t acpi_iort_dma_get_max_cpu_address(void)
 { return PHYS_ADDR_MAX; }
-- 
2.25.1


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

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

* [PATCH v9 07/11] ACPI/IORT: Add a helper to retrieve RMR info directly
  2022-04-04 12:41 [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node Shameer Kolothum
                   ` (5 preceding siblings ...)
  2022-04-04 12:42 ` [PATCH v9 06/11] ACPI/IORT: Add support to retrieve IORT RMR " Shameer Kolothum
@ 2022-04-04 12:42 ` Shameer Kolothum
  2022-04-06 15:51   ` Lorenzo Pieralisi
  2022-04-04 12:42 ` [PATCH v9 08/11] iommu/arm-smmu-v3: Introduce strtab init helper Shameer Kolothum
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 25+ messages in thread
From: Shameer Kolothum @ 2022-04-04 12:42 UTC (permalink / raw)
  To: linux-arm-kernel, linux-acpi, iommu
  Cc: linuxarm, lorenzo.pieralisi, joro, robin.murphy, will,
	wanghuiqiang, guohanjun, steven.price, Sami.Mujawar, jon,
	eric.auger, laurentiu.tudor, yangyicong

This will provide a way for SMMU drivers to retrieve StreamIDs
associated with IORT RMR nodes and use that to set bypass settings
for those IDs.

Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
 drivers/acpi/arm64/iort.c | 29 +++++++++++++++++++++++++++++
 include/linux/acpi_iort.h |  8 ++++++++
 2 files changed, 37 insertions(+)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 1147387cfddb..fb2b0163c27d 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -1402,6 +1402,35 @@ int iort_dma_get_ranges(struct device *dev, u64 *size)
 		return nc_dma_get_range(dev, size);
 }
 
+/**
+ * iort_get_rmr_sids - Retrieve IORT RMR node reserved regions with
+ *                     associated StreamIDs information.
+ * @iommu_fwnode: fwnode associated with IOMMU
+ * @head: Resereved region list
+ */
+void iort_get_rmr_sids(struct fwnode_handle *iommu_fwnode,
+		       struct list_head *head)
+{
+	iort_iommu_rmr_get_resv_regions(iommu_fwnode, NULL, head);
+}
+EXPORT_SYMBOL_GPL(iort_get_rmr_sids);
+
+/**
+ * iort_put_rmr_sids - Free all the memory allocated for RMR reserved regions.
+ * @iommu_fwnode: fwnode associated with IOMMU
+ * @head: Resereved region list
+ */
+void iort_put_rmr_sids(struct fwnode_handle *iommu_fwnode,
+		       struct list_head *head)
+{
+	struct iommu_resv_region *entry, *next;
+
+	iort_iommu_put_resv_regions(NULL, head);
+	list_for_each_entry_safe(entry, next, head, list)
+		kfree(entry);
+}
+EXPORT_SYMBOL_GPL(iort_put_rmr_sids);
+
 static void __init acpi_iort_register_irq(int hwirq, const char *name,
 					  int trigger,
 					  struct resource *res)
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index eb3c28853110..774b8bc16573 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -33,6 +33,10 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
 					  enum irq_domain_bus_token bus_token);
 void acpi_configure_pmsi_domain(struct device *dev);
 int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
+void iort_get_rmr_sids(struct fwnode_handle *iommu_fwnode,
+		       struct list_head *head);
+void iort_put_rmr_sids(struct fwnode_handle *iommu_fwnode,
+		       struct list_head *head);
 /* IOMMU interface */
 int iort_dma_get_ranges(struct device *dev, u64 *size);
 int iort_iommu_configure_id(struct device *dev, const u32 *id_in);
@@ -47,6 +51,10 @@ static inline struct irq_domain *iort_get_device_domain(
 	struct device *dev, u32 id, enum irq_domain_bus_token bus_token)
 { return NULL; }
 static inline void acpi_configure_pmsi_domain(struct device *dev) { }
+static inline
+void iort_get_rmr_sids(struct fwnode_handle *iommu_fwnode, struct list_head *head) { }
+static inline
+void iort_put_rmr_sids(struct fwnode_handle *iommu_fwnode, struct list_head *head) { }
 /* IOMMU interface */
 static inline int iort_dma_get_ranges(struct device *dev, u64 *size)
 { return -ENODEV; }
-- 
2.25.1


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

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

* [PATCH v9 08/11] iommu/arm-smmu-v3: Introduce strtab init helper
  2022-04-04 12:41 [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node Shameer Kolothum
                   ` (6 preceding siblings ...)
  2022-04-04 12:42 ` [PATCH v9 07/11] ACPI/IORT: Add a helper to retrieve RMR info directly Shameer Kolothum
@ 2022-04-04 12:42 ` Shameer Kolothum
  2022-04-04 12:42 ` [PATCH v9 09/11] iommu/arm-smmu-v3: Refactor arm_smmu_init_bypass_stes() to force bypass Shameer Kolothum
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Shameer Kolothum @ 2022-04-04 12:42 UTC (permalink / raw)
  To: linux-arm-kernel, linux-acpi, iommu
  Cc: linuxarm, lorenzo.pieralisi, joro, robin.murphy, will,
	wanghuiqiang, guohanjun, steven.price, Sami.Mujawar, jon,
	eric.auger, laurentiu.tudor, yangyicong

Introduce a helper to check the sid range and to init the l2 strtab
entries(bypass). This will be useful when we have to initialize the
l2 strtab with bypass for RMR SIDs.

Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 28 +++++++++++----------
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index efa38b4411f3..61558fdabbe3 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2537,6 +2537,19 @@ static bool arm_smmu_sid_in_range(struct arm_smmu_device *smmu, u32 sid)
 	return sid < limit;
 }
 
+static int arm_smmu_init_sid_strtab(struct arm_smmu_device *smmu, u32 sid)
+{
+	/* Check the SIDs are in range of the SMMU and our stream table */
+	if (!arm_smmu_sid_in_range(smmu, sid))
+		return -ERANGE;
+
+	/* Ensure l2 strtab is initialised */
+	if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB)
+		return arm_smmu_init_l2_strtab(smmu, sid);
+
+	return 0;
+}
+
 static int arm_smmu_insert_master(struct arm_smmu_device *smmu,
 				  struct arm_smmu_master *master)
 {
@@ -2560,20 +2573,9 @@ static int arm_smmu_insert_master(struct arm_smmu_device *smmu,
 		new_stream->id = sid;
 		new_stream->master = master;
 
-		/*
-		 * Check the SIDs are in range of the SMMU and our stream table
-		 */
-		if (!arm_smmu_sid_in_range(smmu, sid)) {
-			ret = -ERANGE;
+		ret = arm_smmu_init_sid_strtab(smmu, sid);
+		if (ret)
 			break;
-		}
-
-		/* Ensure l2 strtab is initialised */
-		if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB) {
-			ret = arm_smmu_init_l2_strtab(smmu, sid);
-			if (ret)
-				break;
-		}
 
 		/* Insert into SID tree */
 		new_node = &(smmu->streams.rb_node);
-- 
2.25.1


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

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

* [PATCH v9 09/11] iommu/arm-smmu-v3: Refactor arm_smmu_init_bypass_stes() to force bypass
  2022-04-04 12:41 [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node Shameer Kolothum
                   ` (7 preceding siblings ...)
  2022-04-04 12:42 ` [PATCH v9 08/11] iommu/arm-smmu-v3: Introduce strtab init helper Shameer Kolothum
@ 2022-04-04 12:42 ` Shameer Kolothum
  2022-04-04 12:42 ` [PATCH v9 10/11] iommu/arm-smmu-v3: Get associated RMR info and install bypass STE Shameer Kolothum
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Shameer Kolothum @ 2022-04-04 12:42 UTC (permalink / raw)
  To: linux-arm-kernel, linux-acpi, iommu
  Cc: linuxarm, lorenzo.pieralisi, joro, robin.murphy, will,
	wanghuiqiang, guohanjun, steven.price, Sami.Mujawar, jon,
	eric.auger, laurentiu.tudor, yangyicong

By default, disable_bypass flag is set and any dev without
an iommu domain installs STE with CFG_ABORT during
arm_smmu_init_bypass_stes(). Introduce a "force" flag and
move the STE update logic to arm_smmu_init_bypass_stes()
so that we can force it to install CFG_BYPASS STE for specific
SIDs.

This will be useful in a follow-up patch to install bypass
for IORT RMR SIDs.

Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 61558fdabbe3..57f831c44155 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1380,12 +1380,21 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
 		arm_smmu_cmdq_issue_cmd(smmu, &prefetch_cmd);
 }
 
-static void arm_smmu_init_bypass_stes(__le64 *strtab, unsigned int nent)
+static void arm_smmu_init_bypass_stes(__le64 *strtab, unsigned int nent, bool force)
 {
 	unsigned int i;
+	u64 val = STRTAB_STE_0_V;
+
+	if (disable_bypass && !force)
+		val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_ABORT);
+	else
+		val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_BYPASS);
 
 	for (i = 0; i < nent; ++i) {
-		arm_smmu_write_strtab_ent(NULL, -1, strtab);
+		strtab[0] = cpu_to_le64(val);
+		strtab[1] = cpu_to_le64(FIELD_PREP(STRTAB_STE_1_SHCFG,
+						   STRTAB_STE_1_SHCFG_INCOMING));
+		strtab[2] = 0;
 		strtab += STRTAB_STE_DWORDS;
 	}
 }
@@ -1413,7 +1422,7 @@ static int arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid)
 		return -ENOMEM;
 	}
 
-	arm_smmu_init_bypass_stes(desc->l2ptr, 1 << STRTAB_SPLIT);
+	arm_smmu_init_bypass_stes(desc->l2ptr, 1 << STRTAB_SPLIT, false);
 	arm_smmu_write_strtab_l1_desc(strtab, desc);
 	return 0;
 }
@@ -3051,7 +3060,7 @@ static int arm_smmu_init_strtab_linear(struct arm_smmu_device *smmu)
 	reg |= FIELD_PREP(STRTAB_BASE_CFG_LOG2SIZE, smmu->sid_bits);
 	cfg->strtab_base_cfg = reg;
 
-	arm_smmu_init_bypass_stes(strtab, cfg->num_l1_ents);
+	arm_smmu_init_bypass_stes(strtab, cfg->num_l1_ents, false);
 	return 0;
 }
 
-- 
2.25.1


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

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

* [PATCH v9 10/11] iommu/arm-smmu-v3: Get associated RMR info and install bypass STE
  2022-04-04 12:41 [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node Shameer Kolothum
                   ` (8 preceding siblings ...)
  2022-04-04 12:42 ` [PATCH v9 09/11] iommu/arm-smmu-v3: Refactor arm_smmu_init_bypass_stes() to force bypass Shameer Kolothum
@ 2022-04-04 12:42 ` Shameer Kolothum
  2022-04-04 12:42 ` [PATCH v9 11/11] iommu/arm-smmu: Get associated RMR info and install bypass SMR Shameer Kolothum
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Shameer Kolothum @ 2022-04-04 12:42 UTC (permalink / raw)
  To: linux-arm-kernel, linux-acpi, iommu
  Cc: linuxarm, lorenzo.pieralisi, joro, robin.murphy, will,
	wanghuiqiang, guohanjun, steven.price, Sami.Mujawar, jon,
	eric.auger, laurentiu.tudor, yangyicong

Check if there is any RMR info associated with the devices behind
the SMMUv3 and if any, install bypass STEs for them. This is to
keep any ongoing traffic associated with these devices alive
when we enable/reset SMMUv3 during probe().

Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 33 +++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 57f831c44155..627a2b498e78 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -3754,6 +3754,36 @@ static void __iomem *arm_smmu_ioremap(struct device *dev, resource_size_t start,
 	return devm_ioremap_resource(dev, &res);
 }
 
+static void arm_smmu_rmr_install_bypass_ste(struct arm_smmu_device *smmu)
+{
+	struct list_head rmr_list;
+	struct iommu_resv_region *e;
+
+	INIT_LIST_HEAD(&rmr_list);
+	iort_get_rmr_sids(dev_fwnode(smmu->dev), &rmr_list);
+
+	list_for_each_entry(e, &rmr_list, list) {
+		__le64 *step;
+		const u32 *sids = e->fw_data.rmr.sids;
+		u32 num_sids = e->fw_data.rmr.num_sids;
+		int ret, i;
+
+		for (i = 0; i < num_sids; i++) {
+			ret = arm_smmu_init_sid_strtab(smmu, sids[i]);
+			if (ret) {
+				dev_err(smmu->dev, "RMR SID(0x%x) bypass failed\n",
+					sids[i]);
+				continue;
+			}
+
+			step = arm_smmu_get_step_for_sid(smmu, sids[i]);
+			arm_smmu_init_bypass_stes(step, 1, true);
+		}
+	}
+
+	iort_put_rmr_sids(dev_fwnode(smmu->dev), &rmr_list);
+}
+
 static int arm_smmu_device_probe(struct platform_device *pdev)
 {
 	int irq, ret;
@@ -3835,6 +3865,9 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
 	/* Record our private device structure */
 	platform_set_drvdata(pdev, smmu);
 
+	/* Check for RMRs and install bypass STEs if any */
+	arm_smmu_rmr_install_bypass_ste(smmu);
+
 	/* Reset the device */
 	ret = arm_smmu_device_reset(smmu, bypass);
 	if (ret)
-- 
2.25.1


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

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

* [PATCH v9 11/11] iommu/arm-smmu: Get associated RMR info and install bypass SMR
  2022-04-04 12:41 [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node Shameer Kolothum
                   ` (9 preceding siblings ...)
  2022-04-04 12:42 ` [PATCH v9 10/11] iommu/arm-smmu-v3: Get associated RMR info and install bypass STE Shameer Kolothum
@ 2022-04-04 12:42 ` Shameer Kolothum
  2022-04-07 15:43 ` [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node Steven Price
  2022-04-19 14:50 ` Laurentiu Tudor
  12 siblings, 0 replies; 25+ messages in thread
From: Shameer Kolothum @ 2022-04-04 12:42 UTC (permalink / raw)
  To: linux-arm-kernel, linux-acpi, iommu
  Cc: linuxarm, lorenzo.pieralisi, joro, robin.murphy, will,
	wanghuiqiang, guohanjun, steven.price, Sami.Mujawar, jon,
	eric.auger, laurentiu.tudor, yangyicong

From: Jon Nettleton <jon@solid-run.com>

Check if there is any RMR info associated with the devices behind
the SMMU and if any, install bypass SMRs for them. This is to
keep any ongoing traffic associated with these devices alive
when we enable/reset SMMU during probe().

Signed-off-by: Jon Nettleton <jon@solid-run.com>
Signed-off-by: Steven Price <steven.price@arm.com>
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu.c | 52 +++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index 9a5b785d28fd..d1d0473b8b88 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -2068,6 +2068,54 @@ err_reset_platform_ops: __maybe_unused;
 	return err;
 }
 
+static void arm_smmu_rmr_install_bypass_smr(struct arm_smmu_device *smmu)
+{
+	struct list_head rmr_list;
+	struct iommu_resv_region *e;
+	int idx, cnt = 0;
+	u32 reg;
+
+	INIT_LIST_HEAD(&rmr_list);
+	iort_get_rmr_sids(dev_fwnode(smmu->dev), &rmr_list);
+
+	/*
+	 * Rather than trying to look at existing mappings that
+	 * are setup by the firmware and then invalidate the ones
+	 * that do no have matching RMR entries, just disable the
+	 * SMMU until it gets enabled again in the reset routine.
+	 */
+	reg = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sCR0);
+	reg |= ARM_SMMU_sCR0_CLIENTPD;
+	arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_sCR0, reg);
+
+	list_for_each_entry(e, &rmr_list, list) {
+		const u32 *sids = e->fw_data.rmr.sids;
+		u32 num_sids = e->fw_data.rmr.num_sids;
+		int i;
+
+		for (i = 0; i < num_sids; i++) {
+			idx = arm_smmu_find_sme(smmu, sids[i], ~0);
+			if (idx < 0)
+				continue;
+
+			if (smmu->s2crs[idx].count == 0) {
+				smmu->smrs[idx].id = sids[i];
+				smmu->smrs[idx].mask = 0;
+				smmu->smrs[idx].valid = true;
+			}
+			smmu->s2crs[idx].count++;
+			smmu->s2crs[idx].type = S2CR_TYPE_BYPASS;
+			smmu->s2crs[idx].privcfg = S2CR_PRIVCFG_DEFAULT;
+
+			cnt++;
+		}
+	}
+
+	dev_notice(smmu->dev, "\tpreserved %d boot mapping%s\n", cnt,
+		   cnt == 1 ? "" : "s");
+	iort_put_rmr_sids(dev_fwnode(smmu->dev), &rmr_list);
+}
+
 static int arm_smmu_device_probe(struct platform_device *pdev)
 {
 	struct resource *res;
@@ -2189,6 +2237,10 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
 	}
 
 	platform_set_drvdata(pdev, smmu);
+
+	/* Check for RMRs and install bypass SMRs if any */
+	arm_smmu_rmr_install_bypass_smr(smmu);
+
 	arm_smmu_device_reset(smmu);
 	arm_smmu_test_smr_masks(smmu);
 
-- 
2.25.1


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

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

* Re: [PATCH v9 03/11] ACPI/IORT: Make iort_iommu_msi_get_resv_regions() return void
  2022-04-04 12:42 ` [PATCH v9 03/11] ACPI/IORT: Make iort_iommu_msi_get_resv_regions() return void Shameer Kolothum
@ 2022-04-06 15:12   ` Lorenzo Pieralisi
  0 siblings, 0 replies; 25+ messages in thread
From: Lorenzo Pieralisi @ 2022-04-06 15:12 UTC (permalink / raw)
  To: Shameer Kolothum
  Cc: linux-arm-kernel, linux-acpi, iommu, linuxarm, joro,
	robin.murphy, will, wanghuiqiang, guohanjun, steven.price,
	Sami.Mujawar, jon, eric.auger, laurentiu.tudor, yangyicong

On Mon, Apr 04, 2022 at 01:42:01PM +0100, Shameer Kolothum wrote:
> At present iort_iommu_msi_get_resv_regions() returns the number of
> MSI reserved regions on success and there are no users for this.
> The reserved region list will get populated anyway for platforms
> that require the HW MSI region reservation. Hence, change the
> function to return void instead.
> 
> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
> ---
>  drivers/acpi/arm64/iort.c | 26 ++++++++++----------------
>  include/linux/acpi_iort.h |  6 +++---
>  2 files changed, 13 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index fd06cf43ba31..c5ebb2be9a19 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -832,25 +832,23 @@ static struct acpi_iort_node *iort_get_msi_resv_iommu(struct device *dev)
>  
>  /**
>   * iort_iommu_msi_get_resv_regions - Reserved region driver helper
> + *                                   for HW MSI regions.

Very minor but is this a spurious change ?

>   * @dev: Device from iommu_get_resv_regions()
>   * @head: Reserved region list from iommu_get_resv_regions()
>   *
> - * Returns: Number of msi reserved regions on success (0 if platform
> - *          doesn't require the reservation or no associated msi regions),
> - *          appropriate error value otherwise. The ITS interrupt translation
> - *          spaces (ITS_base + SZ_64K, SZ_64K) associated with the device
> - *          are the msi reserved regions.
> + * The ITS interrupt translation spaces (ITS_base + SZ_64K, SZ_64K)
> + * associated with the device are the HW MSI reserved regions.
>   */
> -int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
> +void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
>  {
>  	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
>  	struct acpi_iort_its_group *its;
>  	struct acpi_iort_node *iommu_node, *its_node = NULL;
> -	int i, resv = 0;
> +	int i;
>  
>  	iommu_node = iort_get_msi_resv_iommu(dev);
>  	if (!iommu_node)
> -		return 0;
> +		return;
>  
>  	/*
>  	 * Current logic to reserve ITS regions relies on HW topologies
> @@ -870,7 +868,7 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
>  	}
>  
>  	if (!its_node)
> -		return 0;
> +		return;
>  
>  	/* Move to ITS specific data */
>  	its = (struct acpi_iort_its_group *)its_node->node_data;
> @@ -884,14 +882,10 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
>  
>  			region = iommu_alloc_resv_region(base + SZ_64K, SZ_64K,
>  							 prot, IOMMU_RESV_MSI);
> -			if (region) {
> +			if (region)
>  				list_add_tail(&region->list, head);
> -				resv++;
> -			}
>  		}
>  	}
> -
> -	return (resv == its->its_count) ? resv : -ENODEV;
>  }
>  
>  static inline bool iort_iommu_driver_enabled(u8 type)
> @@ -1058,8 +1052,8 @@ int iort_iommu_configure_id(struct device *dev, const u32 *id_in)
>  }
>  
>  #else
> -int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
> -{ return 0; }
> +void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
> +{ }
>  int iort_iommu_configure_id(struct device *dev, const u32 *input_id)
>  { return -ENODEV; }
>  #endif
> diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
> index f1f0842a2cb2..a8198b83753d 100644
> --- a/include/linux/acpi_iort.h
> +++ b/include/linux/acpi_iort.h
> @@ -36,7 +36,7 @@ int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
>  /* IOMMU interface */
>  int iort_dma_get_ranges(struct device *dev, u64 *size);
>  int iort_iommu_configure_id(struct device *dev, const u32 *id_in);
> -int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head);
> +void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head);
>  phys_addr_t acpi_iort_dma_get_max_cpu_address(void);
>  #else
>  static inline void acpi_iort_init(void) { }
> @@ -52,8 +52,8 @@ static inline int iort_dma_get_ranges(struct device *dev, u64 *size)
>  static inline int iort_iommu_configure_id(struct device *dev, const u32 *id_in)
>  { return -ENODEV; }
>  static inline
> -int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
> -{ return 0; }
> +void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
> +{ }
>  
>  static inline phys_addr_t acpi_iort_dma_get_max_cpu_address(void)
>  { return PHYS_ADDR_MAX; }
> -- 
> 2.25.1
> 

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

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

* Re: [PATCH v9 06/11] ACPI/IORT: Add support to retrieve IORT RMR reserved regions
  2022-04-04 12:42 ` [PATCH v9 06/11] ACPI/IORT: Add support to retrieve IORT RMR " Shameer Kolothum
@ 2022-04-06 15:47   ` Lorenzo Pieralisi
  2022-04-07 13:28   ` Christoph Hellwig
  1 sibling, 0 replies; 25+ messages in thread
From: Lorenzo Pieralisi @ 2022-04-06 15:47 UTC (permalink / raw)
  To: Shameer Kolothum
  Cc: linux-arm-kernel, linux-acpi, iommu, linuxarm, joro,
	robin.murphy, will, wanghuiqiang, guohanjun, steven.price,
	Sami.Mujawar, jon, eric.auger, laurentiu.tudor, yangyicong

On Mon, Apr 04, 2022 at 01:42:04PM +0100, Shameer Kolothum wrote:
> Parse through the IORT RMR nodes and populate the reserve region list
> corresponding to a given IOMMU and device(optional). Also, go through
> the ID mappings of the RMR node and retrieve all the SIDs associated
> with it.
> 
> Now that we have this support, update iommu_dma_get/_put_resv_regions()
> paths to include the RMR reserve regions.
> 
> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
> ---
>  drivers/acpi/arm64/iort.c | 275 ++++++++++++++++++++++++++++++++++++++
>  drivers/iommu/dma-iommu.c |   3 +
>  include/linux/acpi_iort.h |   4 +
>  3 files changed, 282 insertions(+)

Very minor style comment below, regardless:

Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> # for ACPI
IORT

> 
> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index 63acc3c5b275..1147387cfddb 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -812,6 +812,259 @@ void acpi_configure_pmsi_domain(struct device *dev)
>  }
>  
>  #ifdef CONFIG_IOMMU_API
> +static void iort_rmr_desc_check_overlap(struct acpi_iort_rmr_desc *desc, u32 count)
> +{
> +	int i, j;
> +
> +	for (i = 0; i < count; i++) {
> +		u64 end, start = desc[i].base_address, length = desc[i].length;
> +
> +		if (!length) {
> +			pr_err(FW_BUG "RMR descriptor[0x%llx] with zero length, continue anyway\n",
> +			       start);
> +			continue;
> +		}
> +
> +		end = start + length - 1;
> +
> +		/* Check for address overlap */
> +		for (j = i + 1; j < count; j++) {
> +			u64 e_start = desc[j].base_address;
> +			u64 e_end = e_start + desc[j].length - 1;
> +
> +			if (start <= e_end && end >= e_start)
> +				pr_err(FW_BUG "RMR descriptor[0x%llx - 0x%llx] overlaps, continue anyway\n",
> +				       start, end);
> +		}
> +	}
> +}
> +
> +/*
> + * Please note, we will keep the already allocated RMR reserve
> + * regions in case of a memory allocation failure.
> + */
> +static void iort_get_rmrs(struct acpi_iort_node *node,
> +			  struct acpi_iort_node *smmu,
> +			  u32 *sids, u32 num_sids,
> +			  struct list_head *head)
> +{
> +	struct acpi_iort_rmr *rmr = (struct acpi_iort_rmr *)node->node_data;
> +	struct acpi_iort_rmr_desc *rmr_desc;
> +	int i;
> +
> +	rmr_desc = ACPI_ADD_PTR(struct acpi_iort_rmr_desc, node,
> +				rmr->rmr_offset);
> +
> +	iort_rmr_desc_check_overlap(rmr_desc, rmr->rmr_count);
> +
> +	for (i = 0; i < rmr->rmr_count; i++, rmr_desc++) {
> +		struct iommu_resv_region *region;
> +		enum iommu_resv_type type;
> +		u32  *sids_copy;
> +		int prot = IOMMU_READ | IOMMU_WRITE;
> +		u64 addr = rmr_desc->base_address, size = rmr_desc->length;
> +
> +		if (!IS_ALIGNED(addr, SZ_64K) || !IS_ALIGNED(size, SZ_64K)) {
> +			/* PAGE align base addr and size */
> +			addr &= PAGE_MASK;
> +			size = PAGE_ALIGN(size + offset_in_page(rmr_desc->base_address));
> +
> +			pr_err(FW_BUG "RMR descriptor[0x%llx - 0x%llx] not aligned to 64K, continue with [0x%llx - 0x%llx]\n",
> +			       rmr_desc->base_address,
> +			       rmr_desc->base_address + rmr_desc->length - 1,
> +			       addr, addr + size - 1);
> +		}
> +
> +		if (rmr->flags & ACPI_IORT_RMR_REMAP_PERMITTED)
> +			type = IOMMU_RESV_DIRECT_RELAXABLE;
> +		else
> +			type = IOMMU_RESV_DIRECT;
> +
> +		if (rmr->flags & ACPI_IORT_RMR_ACCESS_PRIVILEGE)
> +			prot |= IOMMU_PRIV;
> +
> +		/* Attributes 0x00 - 0x03 represents device memory */
> +		if (ACPI_IORT_RMR_ACCESS_ATTRIBUTES(rmr->flags) <=
> +				ACPI_IORT_RMR_ATTR_DEVICE_GRE)
> +			prot |= IOMMU_MMIO;
> +		else if (ACPI_IORT_RMR_ACCESS_ATTRIBUTES(rmr->flags) ==
> +				ACPI_IORT_RMR_ATTR_NORMAL_IWB_OWB)
> +			prot |= IOMMU_CACHE;
> +
> +		/* Create a copy of SIDs array to associate with this resv region */
> +		sids_copy = kmemdup(sids, num_sids * sizeof(*sids), GFP_KERNEL);
> +		if (!sids_copy)
> +			return;
> +
> +		region = iommu_alloc_resv_region(addr, size, prot, type);
> +		if (!region) {
> +			kfree(sids_copy);
> +			return;
> +		}
> +
> +		region->fw_data.rmr.sids = sids_copy;
> +		region->fw_data.rmr.num_sids = num_sids;
> +		list_add_tail(&region->list, head);
> +	}
> +}
> +
> +static u32 *iort_rmr_alloc_sids(u32 *sids, u32 count, u32 id_start,
> +				u32 new_count)
> +{
> +	u32 *new_sids;
> +	u32 total_count = count + new_count;
> +	int i;
> +
> +	new_sids = krealloc_array(sids, count + new_count,
> +				  sizeof(*new_sids), GFP_KERNEL);
> +	if (!new_sids)
> +		return NULL;
> +
> +	for (i = count; i < total_count; i++)
> +		new_sids[i] = id_start++;
> +
> +	return new_sids;
> +}
> +
> +static bool iort_rmr_has_dev(struct device *dev, u32 id_start,
> +			     u32 id_count)
> +{
> +	int i;
> +	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
> +
> +	/*
> +	 * Make sure the kernel has preserved the boot firmware PCIe
> +	 * configuration. This is required to ensure that the RMR PCIe
> +	 * StreamIDs are still valid (Refer: ARM DEN 0049E.d Section 3.1.1.5).
> +	 */
> +	if (dev_is_pci(dev)) {
> +		struct pci_dev *pdev = to_pci_dev(dev);
> +		struct pci_host_bridge *host = pci_find_host_bridge(pdev->bus);
> +
> +		if (!host->preserve_config)
> +			return false;
> +	}
> +
> +	for (i = 0; i < fwspec->num_ids; i++) {
> +		if (fwspec->ids[i] >= id_start &&
> +		    fwspec->ids[i] <= id_start + id_count)
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
> +static void iort_node_get_rmr_info(struct acpi_iort_node *node,
> +				   struct acpi_iort_node *iommu,
> +				   struct device *dev, struct list_head *head)
> +{
> +	struct acpi_iort_node *smmu = NULL;
> +	struct acpi_iort_rmr *rmr;
> +	struct acpi_iort_id_mapping *map;
> +	u32 *sids = NULL;
> +	u32 num_sids = 0;
> +	int i;
> +
> +	if (!node->mapping_offset || !node->mapping_count) {
> +		pr_err(FW_BUG "Invalid ID mapping, skipping RMR node %p\n",
> +		       node);
> +		return;
> +	}
> +
> +	rmr = (struct acpi_iort_rmr *)node->node_data;
> +	if (!rmr->rmr_offset || !rmr->rmr_count)
> +		return;
> +
> +	map = ACPI_ADD_PTR(struct acpi_iort_id_mapping, node,
> +			   node->mapping_offset);
> +
> +	/*
> +	 * Go through the ID mappings and see if we have a match for SMMU
> +	 * and dev(if !NULL). If found, get the sids for the Node.
> +	 * Please note, id_count is equal to the number of IDs  in the
> +	 * range minus one.
> +	 */
> +	for (i = 0; i < node->mapping_count; i++, map++) {
> +		struct acpi_iort_node *parent;
> +
> +		if (!map->id_count)
> +			continue;
> +
> +		parent = ACPI_ADD_PTR(struct acpi_iort_node, iort_table,
> +				      map->output_reference);
> +		if (parent != iommu)
> +			continue;
> +
> +		/* If dev is valid, check RMR node corresponds to the dev SID */
> +		if (dev && !iort_rmr_has_dev(dev, map->output_base,
> +					     map->id_count))
> +			continue;
> +
> +		/* Retrieve SIDs associated with the Node. */
> +		sids = iort_rmr_alloc_sids(sids, num_sids, map->output_base,
> +					   map->id_count + 1);
> +		if (!sids)
> +			return;
> +
> +		num_sids += map->id_count + 1;
> +	}
> +
> +	if (!sids)
> +		return;
> +
> +	iort_get_rmrs(node, smmu, sids, num_sids, head);
> +	kfree(sids);
> +}
> +
> +static void iort_find_rmrs(struct acpi_iort_node *iommu, struct device *dev,
> +			   struct list_head *head)
> +{
> +	struct acpi_table_iort *iort;
> +	struct acpi_iort_node *iort_node, *iort_end;
> +	int i;
> +
> +	/* Only supports ARM DEN 0049E.d onwards */
> +	if (iort_table->revision < 5)
> +		return;
> +
> +	iort = (struct acpi_table_iort *)iort_table;
> +
> +	iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort,
> +				 iort->node_offset);
> +	iort_end = ACPI_ADD_PTR(struct acpi_iort_node, iort,
> +				iort_table->length);
> +
> +	for (i = 0; i < iort->node_count; i++) {
> +		if (WARN_TAINT(iort_node >= iort_end, TAINT_FIRMWARE_WORKAROUND,
> +			       "IORT node pointer overflows, bad table!\n"))
> +			return;
> +
> +		if (iort_node->type == ACPI_IORT_NODE_RMR)
> +			iort_node_get_rmr_info(iort_node, iommu, dev, head);
> +
> +		iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node,
> +					 iort_node->length);
> +	}
> +}
> +
> +/*
> + * Populate the RMR list associated with a given IOMMU and dev(if provided).
> + * If dev is NULL, the function populates all the RMRs associated with the
> + * given IOMMU.
> + */
> +static void
> +iort_iommu_rmr_get_resv_regions(struct fwnode_handle *iommu_fwnode,
> +				struct device *dev, struct list_head *head)

Function return value in a single line, for consistency with the file:

static void iort_iommu_rmr_get_resv_regions(
				struct fwnode_handle *iommu_fwnode,
				struct device *dev, struct list_head *head)

> +{
> +	struct acpi_iort_node *iommu;
> +
> +	iommu = iort_get_iort_node(iommu_fwnode);
> +	if (!iommu)
> +		return;
> +
> +	iort_find_rmrs(iommu, dev, head);
> +}
> +
>  static struct acpi_iort_node *iort_get_msi_resv_iommu(struct device *dev)
>  {
>  	struct acpi_iort_node *iommu;
> @@ -892,7 +1145,27 @@ iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
>   */
>  void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head)
>  {
> +	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
> +
>  	iort_iommu_msi_get_resv_regions(dev, head);
> +	iort_iommu_rmr_get_resv_regions(fwspec->iommu_fwnode, dev, head);
> +}
> +
> +/**
> + * iort_iommu_put_resv_regions - Free any IORT specific memory allocations
> + *                               associated with reserve regions.
> + * @dev: Associated device(Optional)
> + * @head: Resereved region list
> + */
> +void iort_iommu_put_resv_regions(struct device *dev, struct list_head *head)
> +{
> +	struct iommu_resv_region *e, *tmp;
> +
> +	/* RMR entries will have mem allocated for fw_data.rmr.sids. */
> +	list_for_each_entry_safe(e, tmp, head, list) {
> +		if (e->fw_data.rmr.sids)
> +			kfree(e->fw_data.rmr.sids);
> +	}
>  }
>  
>  static inline bool iort_iommu_driver_enabled(u8 type)
> @@ -1061,6 +1334,8 @@ int iort_iommu_configure_id(struct device *dev, const u32 *id_in)
>  #else
>  void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head)
>  { }
> +void iort_iommu_put_resv_regions(struct device *dev, struct list_head *head)
> +{ }
>  int iort_iommu_configure_id(struct device *dev, const u32 *input_id)
>  { return -ENODEV; }
>  #endif
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 44e3f3feaab6..5811233dc9fb 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -391,6 +391,9 @@ EXPORT_SYMBOL(iommu_dma_get_resv_regions);
>  
>  void iommu_dma_put_resv_regions(struct device *dev, struct list_head *list)
>  {
> +	if (!is_of_node(dev_iommu_fwspec_get(dev)->iommu_fwnode))
> +		iort_iommu_put_resv_regions(dev, list);
> +
>  	generic_iommu_put_resv_regions(dev, list);
>  }
>  EXPORT_SYMBOL(iommu_dma_put_resv_regions);
> diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
> index e5d2de9caf7f..eb3c28853110 100644
> --- a/include/linux/acpi_iort.h
> +++ b/include/linux/acpi_iort.h
> @@ -37,6 +37,7 @@ int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
>  int iort_dma_get_ranges(struct device *dev, u64 *size);
>  int iort_iommu_configure_id(struct device *dev, const u32 *id_in);
>  void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head);
> +void iort_iommu_put_resv_regions(struct device *dev, struct list_head *head);
>  phys_addr_t acpi_iort_dma_get_max_cpu_address(void);
>  #else
>  static inline void acpi_iort_init(void) { }
> @@ -54,6 +55,9 @@ static inline int iort_iommu_configure_id(struct device *dev, const u32 *id_in)
>  static inline
>  void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head)
>  { }
> +static inline
> +void iort_iommu_put_resv_regions(struct device *dev, struct list_head *head)
> +{ }
>  
>  static inline phys_addr_t acpi_iort_dma_get_max_cpu_address(void)
>  { return PHYS_ADDR_MAX; }
> -- 
> 2.25.1
> 

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

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

* Re: [PATCH v9 07/11] ACPI/IORT: Add a helper to retrieve RMR info directly
  2022-04-04 12:42 ` [PATCH v9 07/11] ACPI/IORT: Add a helper to retrieve RMR info directly Shameer Kolothum
@ 2022-04-06 15:51   ` Lorenzo Pieralisi
  0 siblings, 0 replies; 25+ messages in thread
From: Lorenzo Pieralisi @ 2022-04-06 15:51 UTC (permalink / raw)
  To: Shameer Kolothum
  Cc: linux-arm-kernel, linux-acpi, iommu, linuxarm, joro,
	robin.murphy, will, wanghuiqiang, guohanjun, steven.price,
	Sami.Mujawar, jon, eric.auger, laurentiu.tudor, yangyicong

On Mon, Apr 04, 2022 at 01:42:05PM +0100, Shameer Kolothum wrote:
> This will provide a way for SMMU drivers to retrieve StreamIDs
> associated with IORT RMR nodes and use that to set bypass settings
> for those IDs.
> 
> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
> ---
>  drivers/acpi/arm64/iort.c | 29 +++++++++++++++++++++++++++++
>  include/linux/acpi_iort.h |  8 ++++++++
>  2 files changed, 37 insertions(+)

Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>

> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index 1147387cfddb..fb2b0163c27d 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -1402,6 +1402,35 @@ int iort_dma_get_ranges(struct device *dev, u64 *size)
>  		return nc_dma_get_range(dev, size);
>  }
>  
> +/**
> + * iort_get_rmr_sids - Retrieve IORT RMR node reserved regions with
> + *                     associated StreamIDs information.
> + * @iommu_fwnode: fwnode associated with IOMMU
> + * @head: Resereved region list
> + */
> +void iort_get_rmr_sids(struct fwnode_handle *iommu_fwnode,
> +		       struct list_head *head)
> +{
> +	iort_iommu_rmr_get_resv_regions(iommu_fwnode, NULL, head);
> +}
> +EXPORT_SYMBOL_GPL(iort_get_rmr_sids);
> +
> +/**
> + * iort_put_rmr_sids - Free all the memory allocated for RMR reserved regions.
> + * @iommu_fwnode: fwnode associated with IOMMU
> + * @head: Resereved region list
> + */
> +void iort_put_rmr_sids(struct fwnode_handle *iommu_fwnode,
> +		       struct list_head *head)
> +{
> +	struct iommu_resv_region *entry, *next;
> +
> +	iort_iommu_put_resv_regions(NULL, head);
> +	list_for_each_entry_safe(entry, next, head, list)
> +		kfree(entry);
> +}
> +EXPORT_SYMBOL_GPL(iort_put_rmr_sids);
> +
>  static void __init acpi_iort_register_irq(int hwirq, const char *name,
>  					  int trigger,
>  					  struct resource *res)
> diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
> index eb3c28853110..774b8bc16573 100644
> --- a/include/linux/acpi_iort.h
> +++ b/include/linux/acpi_iort.h
> @@ -33,6 +33,10 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
>  					  enum irq_domain_bus_token bus_token);
>  void acpi_configure_pmsi_domain(struct device *dev);
>  int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
> +void iort_get_rmr_sids(struct fwnode_handle *iommu_fwnode,
> +		       struct list_head *head);
> +void iort_put_rmr_sids(struct fwnode_handle *iommu_fwnode,
> +		       struct list_head *head);
>  /* IOMMU interface */
>  int iort_dma_get_ranges(struct device *dev, u64 *size);
>  int iort_iommu_configure_id(struct device *dev, const u32 *id_in);
> @@ -47,6 +51,10 @@ static inline struct irq_domain *iort_get_device_domain(
>  	struct device *dev, u32 id, enum irq_domain_bus_token bus_token)
>  { return NULL; }
>  static inline void acpi_configure_pmsi_domain(struct device *dev) { }
> +static inline
> +void iort_get_rmr_sids(struct fwnode_handle *iommu_fwnode, struct list_head *head) { }
> +static inline
> +void iort_put_rmr_sids(struct fwnode_handle *iommu_fwnode, struct list_head *head) { }
>  /* IOMMU interface */
>  static inline int iort_dma_get_ranges(struct device *dev, u64 *size)
>  { return -ENODEV; }
> -- 
> 2.25.1
> 

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

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

* Re: [PATCH v9 01/11] ACPI/IORT: Add temporary RMR node flag definitions
  2022-04-04 12:41 ` [PATCH v9 01/11] ACPI/IORT: Add temporary RMR node flag definitions Shameer Kolothum
@ 2022-04-06 15:53   ` Lorenzo Pieralisi
  0 siblings, 0 replies; 25+ messages in thread
From: Lorenzo Pieralisi @ 2022-04-06 15:53 UTC (permalink / raw)
  To: Shameer Kolothum
  Cc: linux-arm-kernel, linux-acpi, iommu, linuxarm, joro,
	robin.murphy, will, wanghuiqiang, guohanjun, steven.price,
	Sami.Mujawar, jon, eric.auger, laurentiu.tudor, yangyicong

On Mon, Apr 04, 2022 at 01:41:59PM +0100, Shameer Kolothum wrote:
> IORT rev E.d introduces more details into the RMR node Flags
> field. Add temporary definitions to describe and access these
> Flags field until ACPICA header is updated to support E.d.
> 
> This patch can be reverted once the include/acpi/actbl2.h has
> all the relevant definitions.
> 
> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
> ---
> Please find the ACPICA E.d related changes pull request here,
> https://github.com/acpica/acpica/pull/765
> 
> This is now merged to acpica:master.

I assume we can drop this patch when ACPICA Linuxized patches hit
Rafael's tree.

> ---
>  drivers/acpi/arm64/iort.c | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
> 
> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index f2f8f05662de..fd06cf43ba31 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -25,6 +25,30 @@
>  #define IORT_IOMMU_TYPE		((1 << ACPI_IORT_NODE_SMMU) |	\
>  				(1 << ACPI_IORT_NODE_SMMU_V3))
>  
> +/*
> + * The following RMR related definitions are temporary and
> + * can be removed once ACPICA headers support IORT rev E.d
> + */
> +#ifndef ACPI_IORT_RMR_REMAP_PERMITTED
> +#define ACPI_IORT_RMR_REMAP_PERMITTED	(1)
> +#endif
> +
> +#ifndef ACPI_IORT_RMR_ACCESS_PRIVILEGE
> +#define ACPI_IORT_RMR_ACCESS_PRIVILEGE	(1 << 1)
> +#endif
> +
> +#ifndef ACPI_IORT_RMR_ACCESS_ATTRIBUTES
> +#define ACPI_IORT_RMR_ACCESS_ATTRIBUTES(flags)	(((flags) >> 2) & 0xFF)
> +#endif
> +
> +#ifndef ACPI_IORT_RMR_ATTR_DEVICE_GRE
> +#define ACPI_IORT_RMR_ATTR_DEVICE_GRE	0x03
> +#endif
> +
> +#ifndef ACPI_IORT_RMR_ATTR_NORMAL_IWB_OWB
> +#define ACPI_IORT_RMR_ATTR_NORMAL_IWB_OWB	0x05
> +#endif
> +
>  struct iort_its_msi_chip {
>  	struct list_head	list;
>  	struct fwnode_handle	*fw_node;
> -- 
> 2.25.1
> 

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

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

* Re: [PATCH v9 04/11] ACPI/IORT: Provide a generic helper to retrieve reserve regions
  2022-04-04 12:42 ` [PATCH v9 04/11] ACPI/IORT: Provide a generic helper to retrieve reserve regions Shameer Kolothum
@ 2022-04-06 15:54   ` Lorenzo Pieralisi
  0 siblings, 0 replies; 25+ messages in thread
From: Lorenzo Pieralisi @ 2022-04-06 15:54 UTC (permalink / raw)
  To: Shameer Kolothum
  Cc: linux-arm-kernel, linux-acpi, iommu, linuxarm, joro,
	robin.murphy, will, wanghuiqiang, guohanjun, steven.price,
	Sami.Mujawar, jon, eric.auger, laurentiu.tudor, yangyicong

On Mon, Apr 04, 2022 at 01:42:02PM +0100, Shameer Kolothum wrote:
> Currently IORT provides a helper to retrieve HW MSI reserve regions.
> Change this to a generic helper to retrieve any IORT related reserve
> regions. This will be useful when we add support for RMR nodes in
> subsequent patches.
> 
> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
> ---
>  drivers/acpi/arm64/iort.c | 23 +++++++++++++++--------
>  drivers/iommu/dma-iommu.c |  2 +-
>  include/linux/acpi_iort.h |  4 ++--
>  3 files changed, 18 insertions(+), 11 deletions(-)

Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> # for ACPI
IORT

> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index c5ebb2be9a19..63acc3c5b275 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -830,16 +830,13 @@ static struct acpi_iort_node *iort_get_msi_resv_iommu(struct device *dev)
>  	return NULL;
>  }
>  
> -/**
> - * iort_iommu_msi_get_resv_regions - Reserved region driver helper
> - *                                   for HW MSI regions.
> - * @dev: Device from iommu_get_resv_regions()
> - * @head: Reserved region list from iommu_get_resv_regions()
> - *
> +/*
> + * Retrieve platform specific HW MSI reserve regions.
>   * The ITS interrupt translation spaces (ITS_base + SZ_64K, SZ_64K)
>   * associated with the device are the HW MSI reserved regions.
>   */
> -void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
> +static void
> +iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
>  {
>  	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
>  	struct acpi_iort_its_group *its;
> @@ -888,6 +885,16 @@ void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
>  	}
>  }
>  
> +/**
> + * iort_iommu_get_resv_regions - Generic helper to retrieve reserved regions.
> + * @dev: Device from iommu_get_resv_regions()
> + * @head: Reserved region list from iommu_get_resv_regions()
> + */
> +void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head)
> +{
> +	iort_iommu_msi_get_resv_regions(dev, head);
> +}
> +
>  static inline bool iort_iommu_driver_enabled(u8 type)
>  {
>  	switch (type) {
> @@ -1052,7 +1059,7 @@ int iort_iommu_configure_id(struct device *dev, const u32 *id_in)
>  }
>  
>  #else
> -void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
> +void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head)
>  { }
>  int iort_iommu_configure_id(struct device *dev, const u32 *input_id)
>  { return -ENODEV; }
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 09f6e1c0f9c0..93d76b666888 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -384,7 +384,7 @@ void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
>  {
>  
>  	if (!is_of_node(dev_iommu_fwspec_get(dev)->iommu_fwnode))
> -		iort_iommu_msi_get_resv_regions(dev, list);
> +		iort_iommu_get_resv_regions(dev, list);
>  
>  }
>  EXPORT_SYMBOL(iommu_dma_get_resv_regions);
> diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
> index a8198b83753d..e5d2de9caf7f 100644
> --- a/include/linux/acpi_iort.h
> +++ b/include/linux/acpi_iort.h
> @@ -36,7 +36,7 @@ int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
>  /* IOMMU interface */
>  int iort_dma_get_ranges(struct device *dev, u64 *size);
>  int iort_iommu_configure_id(struct device *dev, const u32 *id_in);
> -void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head);
> +void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head);
>  phys_addr_t acpi_iort_dma_get_max_cpu_address(void);
>  #else
>  static inline void acpi_iort_init(void) { }
> @@ -52,7 +52,7 @@ static inline int iort_dma_get_ranges(struct device *dev, u64 *size)
>  static inline int iort_iommu_configure_id(struct device *dev, const u32 *id_in)
>  { return -ENODEV; }
>  static inline
> -void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
> +void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head)
>  { }
>  
>  static inline phys_addr_t acpi_iort_dma_get_max_cpu_address(void)
> -- 
> 2.25.1
> 

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

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

* Re: [PATCH v9 05/11] iommu/dma: Introduce a helper to remove reserved regions
  2022-04-04 12:42 ` [PATCH v9 05/11] iommu/dma: Introduce a helper to remove reserved regions Shameer Kolothum
@ 2022-04-07 13:26   ` Christoph Hellwig
  0 siblings, 0 replies; 25+ messages in thread
From: Christoph Hellwig @ 2022-04-07 13:26 UTC (permalink / raw)
  To: Shameer Kolothum
  Cc: linux-arm-kernel, linux-acpi, iommu, robin.murphy, jon, linuxarm,
	steven.price, guohanjun, yangyicong, Sami.Mujawar, will,
	wanghuiqiang

>  
> +static inline void iommu_dma_put_resv_regions(struct device *dev, struct list_head *list)
> +{
> +}
> +
>  #endif	/* CONFIG_IOMMU_DMA */

This changes behavior when CONFIG_IOMMU_DMA is not set.  So e.g. on
ARM all the drivers that are using the new helper now fail to release
reserved regions.

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

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

* Re: [PATCH v9 06/11] ACPI/IORT: Add support to retrieve IORT RMR reserved regions
  2022-04-04 12:42 ` [PATCH v9 06/11] ACPI/IORT: Add support to retrieve IORT RMR " Shameer Kolothum
  2022-04-06 15:47   ` Lorenzo Pieralisi
@ 2022-04-07 13:28   ` Christoph Hellwig
  2022-04-07 13:53     ` Robin Murphy
  1 sibling, 1 reply; 25+ messages in thread
From: Christoph Hellwig @ 2022-04-07 13:28 UTC (permalink / raw)
  To: Shameer Kolothum
  Cc: linux-arm-kernel, linux-acpi, iommu, robin.murphy, jon, linuxarm,
	steven.price, guohanjun, yangyicong, Sami.Mujawar, will,
	wanghuiqiang

> +static void iort_rmr_desc_check_overlap(struct acpi_iort_rmr_desc *desc, u32 count)

Overly long line.

>  void iommu_dma_put_resv_regions(struct device *dev, struct list_head *list)
>  {
> +	if (!is_of_node(dev_iommu_fwspec_get(dev)->iommu_fwnode))
> +		iort_iommu_put_resv_regions(dev, list);
> +
>  	generic_iommu_put_resv_regions(dev, list);
>  }

Why can't this just go into generic_iommu_put_resv_regions?  The idea
that the iommu low-level drivers need to call into dma-iommu which is
a consumer of the IOMMU API is odd.  Especially if that just calls out
to ACPI code and generic IOMMU code only anyway.

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

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

* Re: [PATCH v9 06/11] ACPI/IORT: Add support to retrieve IORT RMR reserved regions
  2022-04-07 13:28   ` Christoph Hellwig
@ 2022-04-07 13:53     ` Robin Murphy
  2022-04-07 13:59       ` Christoph Hellwig
  0 siblings, 1 reply; 25+ messages in thread
From: Robin Murphy @ 2022-04-07 13:53 UTC (permalink / raw)
  To: Christoph Hellwig, Shameer Kolothum
  Cc: linux-arm-kernel, linux-acpi, iommu, jon, linuxarm, steven.price,
	guohanjun, yangyicong, Sami.Mujawar, will, wanghuiqiang

On 2022-04-07 14:28, Christoph Hellwig wrote:
>> +static void iort_rmr_desc_check_overlap(struct acpi_iort_rmr_desc *desc, u32 count)
> 
> Overly long line.
> 
>>   void iommu_dma_put_resv_regions(struct device *dev, struct list_head *list)
>>   {
>> +	if (!is_of_node(dev_iommu_fwspec_get(dev)->iommu_fwnode))
>> +		iort_iommu_put_resv_regions(dev, list);
>> +
>>   	generic_iommu_put_resv_regions(dev, list);
>>   }
> 
> Why can't this just go into generic_iommu_put_resv_regions?  The idea
> that the iommu low-level drivers need to call into dma-iommu which is
> a consumer of the IOMMU API is odd.  Especially if that just calls out
> to ACPI code and generic IOMMU code only anyway.

Because assuming ACPI means IORT is not generic. Part of the aim in 
adding the union to iommu_resv_region is that stuff like AMD's 
unity_map_entry and Intel's dmar_rmrr_unit can be folded into it as 
well, and their reserved region handling correspondingly simplified too.

The iommu_dma_{get,put}_resv_region() helpers are kind of intended to be 
specific to the fwnode mechanism which deals with IORT and devicetree 
(once the reserved region bindings are fully worked out).

Thanks,
Robin.

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

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

* Re: [PATCH v9 06/11] ACPI/IORT: Add support to retrieve IORT RMR reserved regions
  2022-04-07 13:53     ` Robin Murphy
@ 2022-04-07 13:59       ` Christoph Hellwig
  2022-04-19  8:31         ` Shameerali Kolothum Thodi
  0 siblings, 1 reply; 25+ messages in thread
From: Christoph Hellwig @ 2022-04-07 13:59 UTC (permalink / raw)
  To: Robin Murphy
  Cc: Christoph Hellwig, Shameer Kolothum, jon, linuxarm, steven.price,
	linux-acpi, iommu, wanghuiqiang, guohanjun, yangyicong,
	Sami.Mujawar, will, linux-arm-kernel

On Thu, Apr 07, 2022 at 02:53:38PM +0100, Robin Murphy wrote:
> > Why can't this just go into generic_iommu_put_resv_regions?  The idea
> > that the iommu low-level drivers need to call into dma-iommu which is
> > a consumer of the IOMMU API is odd.  Especially if that just calls out
> > to ACPI code and generic IOMMU code only anyway.
> 
> Because assuming ACPI means IORT is not generic. Part of the aim in adding
> the union to iommu_resv_region is that stuff like AMD's unity_map_entry and
> Intel's dmar_rmrr_unit can be folded into it as well, and their reserved
> region handling correspondingly simplified too.
> 
> The iommu_dma_{get,put}_resv_region() helpers are kind of intended to be
> specific to the fwnode mechanism which deals with IORT and devicetree (once
> the reserved region bindings are fully worked out).

But IORT is not driver₋specific code.  So we'll need a USE_IORT flag
somewhere in core IOMMU code instead of trying to stuff this into
driver operations.  and dma-iommu mostly certainly implies IORT even
less than ACPI.

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

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

* Re: [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node
  2022-04-04 12:41 [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node Shameer Kolothum
                   ` (10 preceding siblings ...)
  2022-04-04 12:42 ` [PATCH v9 11/11] iommu/arm-smmu: Get associated RMR info and install bypass SMR Shameer Kolothum
@ 2022-04-07 15:43 ` Steven Price
  2022-04-19 14:50 ` Laurentiu Tudor
  12 siblings, 0 replies; 25+ messages in thread
From: Steven Price @ 2022-04-07 15:43 UTC (permalink / raw)
  To: Shameer Kolothum, linux-arm-kernel, linux-acpi, iommu
  Cc: linuxarm, lorenzo.pieralisi, joro, robin.murphy, will,
	wanghuiqiang, guohanjun, Sami.Mujawar, jon, eric.auger,
	laurentiu.tudor, yangyicong

Hi Shameer,

I've given it a spin on my Juno board and the EFIFB works fine with it.
However I am getting a warning:

ACPI: IORT: [Firmware Bug]: RMR descriptor[0xf80d0000] with zero length,
continue anyway

Which on examination of the IORT table is correct - the firmware does
indeed seem to have a bug and the length in the IORT table is 0,
hopefully I can get that fixed. However since it "all works" that points
out that the reserved memory region isn't actually used. Instead the
existing entries from the SMMU are reused (even though they don't match
the address/size region in the RMR).

I'm not sure if that matters but I thought it worth pointing out as it's
not currently spelt out that the RMR descriptor's content is currently
actually ignored.

Anyway, FWIW:

Tested-by: Steven Price <steven.price@arm.com>

Steve

On 04/04/2022 13:41, Shameer Kolothum wrote:
> Hi
> 
> v8 --> v9
>  - Adressed comments from Robin on interfaces as discussed here[0].
>  - Addressed comments from Lorenzo.
>  
> Though functionally there aren't any major changes, the interfaces have
> changed from v8 and for that reason not included the T-by tags from
> Steve and Eric yet(Many thanks for that). Appreciate it if you could
> give this a spin and let me know.
> 
> (The revised ACPICA pull request for IORT E.d related changes is
> here[1] and this is now merged to acpica:master.)
> 
> Please take a look and let me know your thoughts.
> 
> Thanks,
> Shameer
> [0] https://lore.kernel.org/linux-arm-kernel/c982f1d7-c565-769a-abae-79c962969d88@arm.com/
> [1] https://github.com/acpica/acpica/pull/765
> 
> From old:
> We have faced issues with 3408iMR RAID controller cards which
> fail to boot when SMMU is enabled. This is because these
> controllers make use of host memory for various caching related
> purposes and when SMMU is enabled the iMR firmware fails to
> access these memory regions as there is no mapping for them.
> IORT RMR provides a way for UEFI to describe and report these
> memory regions so that the kernel can make a unity mapping for
> these in SMMU.
> 
> Change History:
> 
> v7 --> v8
>   - Patch #1 has temp definitions for RMR related changes till
>     the ACPICA header changes are part of kernel.
>   - No early parsing of RMR node info and is only parsed at the
>     time of use.
>   - Changes to the RMR get/put API format compared to the
>     previous version.
>   - Support for RMR descriptor shared by multiple stream IDs.
> 
> v6 --> v7
>  -fix pointed out by Steve to the SMMUv2 SMR bypass install in patch #8.
> 
> v5 --> v6
> - Addressed comments from Robin & Lorenzo.
>   : Moved iort_parse_rmr() to acpi_iort_init() from
>     iort_init_platform_devices().
>   : Removed use of struct iort_rmr_entry during the initial
>     parse. Using struct iommu_resv_region instead.
>   : Report RMR address alignment and overlap errors, but continue.
>   : Reworked arm_smmu_init_bypass_stes() (patch # 6).
> - Updated SMMUv2 bypass SMR code. Thanks to Jon N (patch #8).
> - Set IOMMU protection flags(IOMMU_CACHE, IOMMU_MMIO) based
>   on Type of RMR region. Suggested by Jon N.
> 
> v4 --> v5
>  -Added a fw_data union to struct iommu_resv_region and removed
>   struct iommu_rmr (Based on comments from Joerg/Robin).
>  -Added iommu_put_rmrs() to release mem.
>  -Thanks to Steve for verifying on SMMUv2, but not added the Tested-by
>   yet because of the above changes.
> 
> v3 -->v4
> -Included the SMMUv2 SMR bypass install changes suggested by
>  Steve(patch #7)
> -As per Robin's comments, RMR reserve implementation is now
>  more generic  (patch #8) and dropped v3 patches 8 and 10.
> -Rebase to 5.13-rc1
> 
> RFC v2 --> v3
>  -Dropped RFC tag as the ACPICA header changes are now ready to be
>   part of 5.13[0]. But this series still has a dependency on that patch.
>  -Added IORT E.b related changes(node flags, _DSM function 5 checks for
>   PCIe).
>  -Changed RMR to stream id mapping from M:N to M:1 as per the spec and
>   discussion here[1].
>  -Last two patches add support for SMMUv2(Thanks to Jon Nettleton!)
> 
> Jon Nettleton (1):
>   iommu/arm-smmu: Get associated RMR info and install bypass SMR
> 
> Shameer Kolothum (10):
>   ACPI/IORT: Add temporary RMR node flag definitions
>   iommu: Introduce a union to struct iommu_resv_region
>   ACPI/IORT: Make iort_iommu_msi_get_resv_regions() return void
>   ACPI/IORT: Provide a generic helper to retrieve reserve regions
>   iommu/dma: Introduce a helper to remove reserved regions
>   ACPI/IORT: Add support to retrieve IORT RMR reserved regions
>   ACPI/IORT: Add a helper to retrieve RMR info directly
>   iommu/arm-smmu-v3: Introduce strtab init helper
>   iommu/arm-smmu-v3: Refactor arm_smmu_init_bypass_stes() to force
>     bypass
>   iommu/arm-smmu-v3: Get associated RMR info and install bypass STE
> 
>  drivers/acpi/arm64/iort.c                   | 369 ++++++++++++++++++--
>  drivers/iommu/apple-dart.c                  |   2 +-
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c |  80 ++++-
>  drivers/iommu/arm/arm-smmu/arm-smmu.c       |  54 ++-
>  drivers/iommu/dma-iommu.c                   |  11 +-
>  drivers/iommu/virtio-iommu.c                |   2 +-
>  include/linux/acpi_iort.h                   |  18 +-
>  include/linux/dma-iommu.h                   |   5 +
>  include/linux/iommu.h                       |   9 +
>  9 files changed, 505 insertions(+), 45 deletions(-)
> 


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

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

* RE: [PATCH v9 06/11] ACPI/IORT: Add support to retrieve IORT RMR reserved regions
  2022-04-07 13:59       ` Christoph Hellwig
@ 2022-04-19  8:31         ` Shameerali Kolothum Thodi
  2022-04-19  9:04           ` Christoph Hellwig
  0 siblings, 1 reply; 25+ messages in thread
From: Shameerali Kolothum Thodi @ 2022-04-19  8:31 UTC (permalink / raw)
  To: Christoph Hellwig, Robin Murphy
  Cc: jon, Linuxarm, steven.price, linux-acpi, iommu, wanghuiqiang,
	Guohanjun (Hanjun Guo),
	yangyicong, Sami.Mujawar, will, linux-arm-kernel



> -----Original Message-----
> From: Christoph Hellwig [mailto:hch@infradead.org]
> Sent: 07 April 2022 15:00
> To: Robin Murphy <robin.murphy@arm.com>
> Cc: Christoph Hellwig <hch@infradead.org>; Shameerali Kolothum Thodi
> <shameerali.kolothum.thodi@huawei.com>; jon@solid-run.com; Linuxarm
> <linuxarm@huawei.com>; steven.price@arm.com; linux-acpi@vger.kernel.org;
> iommu@lists.linux-foundation.org; wanghuiqiang
> <wanghuiqiang@huawei.com>; Guohanjun (Hanjun Guo)
> <guohanjun@huawei.com>; yangyicong <yangyicong@huawei.com>;
> Sami.Mujawar@arm.com; will@kernel.org;
> linux-arm-kernel@lists.infradead.org
> Subject: Re: [PATCH v9 06/11] ACPI/IORT: Add support to retrieve IORT RMR
> reserved regions
> 
> On Thu, Apr 07, 2022 at 02:53:38PM +0100, Robin Murphy wrote:
> > > Why can't this just go into generic_iommu_put_resv_regions?  The idea
> > > that the iommu low-level drivers need to call into dma-iommu which is
> > > a consumer of the IOMMU API is odd.  Especially if that just calls out
> > > to ACPI code and generic IOMMU code only anyway.
> >
> > Because assuming ACPI means IORT is not generic. Part of the aim in adding
> > the union to iommu_resv_region is that stuff like AMD's unity_map_entry
> and
> > Intel's dmar_rmrr_unit can be folded into it as well, and their reserved
> > region handling correspondingly simplified too.
> >
> > The iommu_dma_{get,put}_resv_region() helpers are kind of intended to be
> > specific to the fwnode mechanism which deals with IORT and devicetree
> (once
> > the reserved region bindings are fully worked out).
> 
> But IORT is not driver₋specific code.  So we'll need a USE_IORT flag
> somewhere in core IOMMU code instead of trying to stuff this into
> driver operations.  and dma-iommu mostly certainly implies IORT even
> less than ACPI.

Sorry for the delayed response(was on holidays). So if we move the
iommu_dma_put_resv_region() call to generic_iommu_put_resv_regions() ,
will that address the concerns here?

I think it will resolve the issue in 05/11 as well pointed out by Christoph
where we end up not releasing reserved regions when
CONFIG_IOMMU_DMA is not set.

Something like below,

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index f2c45b85b9fc..d08204a25ba8 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -2605,6 +2605,8 @@ void generic_iommu_put_resv_regions(struct
device *dev, struct list_head *list)
 {
        struct iommu_resv_region *entry, *next;

+       iommu_dma_put_resv_regions(dev, list);
+
        list_for_each_entry_safe(entry, next, list, list)
                kfree(entry);
 }

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 5811233dc9fb..8cb1e419db49 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -393,8 +393,6 @@ void iommu_dma_put_resv_regions(struct device
*dev, struct list_head *list)
 {
        if (!is_of_node(dev_iommu_fwspec_get(dev)->iommu_fwnode))
                iort_iommu_put_resv_regions(dev, list);
-
-       generic_iommu_put_resv_regions(dev, list);
 }

Please let me know if this is not good enough.

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

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

* Re: [PATCH v9 06/11] ACPI/IORT: Add support to retrieve IORT RMR reserved regions
  2022-04-19  8:31         ` Shameerali Kolothum Thodi
@ 2022-04-19  9:04           ` Christoph Hellwig
  0 siblings, 0 replies; 25+ messages in thread
From: Christoph Hellwig @ 2022-04-19  9:04 UTC (permalink / raw)
  To: Shameerali Kolothum Thodi
  Cc: Christoph Hellwig, Robin Murphy, jon, Linuxarm, steven.price,
	linux-acpi, iommu, linux-arm-kernel, Guohanjun (Hanjun Guo),
	yangyicong, Sami.Mujawar, will, wanghuiqiang

On Tue, Apr 19, 2022 at 08:31:55AM +0000, Shameerali Kolothum Thodi via iommu wrote:
> Sorry for the delayed response(was on holidays). So if we move the
> iommu_dma_put_resv_region() call to generic_iommu_put_resv_regions() ,
> will that address the concerns here?
> 
> I think it will resolve the issue in 05/11 as well pointed out by Christoph
> where we end up not releasing reserved regions when
> CONFIG_IOMMU_DMA is not set.

As Robin pointed out we might not really deduct that ACPI means RMR.

I suspect the best would be to just attach a free callback to the
regions.  Either by adding it directly to struct iommu_resv_region
if we thing there are few enough regions to not be worried about
the memory use, or other by adding a container struct for the list_head
that contains the free callback.

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

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

* Re: [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node
  2022-04-04 12:41 [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node Shameer Kolothum
                   ` (11 preceding siblings ...)
  2022-04-07 15:43 ` [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node Steven Price
@ 2022-04-19 14:50 ` Laurentiu Tudor
  12 siblings, 0 replies; 25+ messages in thread
From: Laurentiu Tudor @ 2022-04-19 14:50 UTC (permalink / raw)
  To: Shameer Kolothum, linux-arm-kernel, linux-acpi, iommu
  Cc: linuxarm, lorenzo.pieralisi, joro, robin.murphy, will,
	wanghuiqiang, guohanjun, steven.price, Sami.Mujawar, jon,
	eric.auger, yangyicong

Hi Shameer,

On 4/4/2022 3:41 PM, Shameer Kolothum wrote:
> Hi
> 
> v8 --> v9
>   - Adressed comments from Robin on interfaces as discussed here[0].
>   - Addressed comments from Lorenzo.
>   
> Though functionally there aren't any major changes, the interfaces have
> changed from v8 and for that reason not included the T-by tags from
> Steve and Eric yet(Many thanks for that). Appreciate it if you could
> give this a spin and let me know.
> 
> (The revised ACPICA pull request for IORT E.d related changes is
> here[1] and this is now merged to acpica:master.)
> 
> Please take a look and let me know your thoughts.
> 
> Thanks,
> Shameer
> [0] https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Flinux-arm-kernel%2Fc982f1d7-c565-769a-abae-79c962969d88%40arm.com%2F&amp;data=04%7C01%7Claurentiu.tudor%40nxp.com%7C2c1805513e0c4509194608da1638a306%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637846729754056888%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=R2Rw4JK1ugTN1QA4umzMuLVem2oS9BZucbvNoZqSJ3I%3D&amp;reserved=0
> [1] https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Facpica%2Facpica%2Fpull%2F765&amp;data=04%7C01%7Claurentiu.tudor%40nxp.com%7C2c1805513e0c4509194608da1638a306%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637846729754056888%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=0aC%2BwZXPL4b0ZWIXw3TGwFE3NqPUMVJ3IbpsxeQF8zw%3D&amp;reserved=0
> 
>  From old:
> We have faced issues with 3408iMR RAID controller cards which
> fail to boot when SMMU is enabled. This is because these
> controllers make use of host memory for various caching related
> purposes and when SMMU is enabled the iMR firmware fails to
> access these memory regions as there is no mapping for them.
> IORT RMR provides a way for UEFI to describe and report these
> memory regions so that the kernel can make a unity mapping for
> these in SMMU.
> 
> Change History:
> 
> v7 --> v8
>    - Patch #1 has temp definitions for RMR related changes till
>      the ACPICA header changes are part of kernel.
>    - No early parsing of RMR node info and is only parsed at the
>      time of use.
>    - Changes to the RMR get/put API format compared to the
>      previous version.
>    - Support for RMR descriptor shared by multiple stream IDs.
> 
> v6 --> v7
>   -fix pointed out by Steve to the SMMUv2 SMR bypass install in patch #8.
> 
> v5 --> v6
> - Addressed comments from Robin & Lorenzo.
>    : Moved iort_parse_rmr() to acpi_iort_init() from
>      iort_init_platform_devices().
>    : Removed use of struct iort_rmr_entry during the initial
>      parse. Using struct iommu_resv_region instead.
>    : Report RMR address alignment and overlap errors, but continue.
>    : Reworked arm_smmu_init_bypass_stes() (patch # 6).
> - Updated SMMUv2 bypass SMR code. Thanks to Jon N (patch #8).
> - Set IOMMU protection flags(IOMMU_CACHE, IOMMU_MMIO) based
>    on Type of RMR region. Suggested by Jon N.
> 
> v4 --> v5
>   -Added a fw_data union to struct iommu_resv_region and removed
>    struct iommu_rmr (Based on comments from Joerg/Robin).
>   -Added iommu_put_rmrs() to release mem.
>   -Thanks to Steve for verifying on SMMUv2, but not added the Tested-by
>    yet because of the above changes.
> 
> v3 -->v4
> -Included the SMMUv2 SMR bypass install changes suggested by
>   Steve(patch #7)
> -As per Robin's comments, RMR reserve implementation is now
>   more generic  (patch #8) and dropped v3 patches 8 and 10.
> -Rebase to 5.13-rc1
> 
> RFC v2 --> v3
>   -Dropped RFC tag as the ACPICA header changes are now ready to be
>    part of 5.13[0]. But this series still has a dependency on that patch.
>   -Added IORT E.b related changes(node flags, _DSM function 5 checks for
>    PCIe).
>   -Changed RMR to stream id mapping from M:N to M:1 as per the spec and
>    discussion here[1].
>   -Last two patches add support for SMMUv2(Thanks to Jon Nettleton!)
> 
> Jon Nettleton (1):
>    iommu/arm-smmu: Get associated RMR info and install bypass SMR
> 
> Shameer Kolothum (10):
>    ACPI/IORT: Add temporary RMR node flag definitions
>    iommu: Introduce a union to struct iommu_resv_region
>    ACPI/IORT: Make iort_iommu_msi_get_resv_regions() return void
>    ACPI/IORT: Provide a generic helper to retrieve reserve regions
>    iommu/dma: Introduce a helper to remove reserved regions
>    ACPI/IORT: Add support to retrieve IORT RMR reserved regions
>    ACPI/IORT: Add a helper to retrieve RMR info directly
>    iommu/arm-smmu-v3: Introduce strtab init helper
>    iommu/arm-smmu-v3: Refactor arm_smmu_init_bypass_stes() to force
>      bypass
>    iommu/arm-smmu-v3: Get associated RMR info and install bypass STE
> 
>   drivers/acpi/arm64/iort.c                   | 369 ++++++++++++++++++--
>   drivers/iommu/apple-dart.c                  |   2 +-
>   drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c |  80 ++++-
>   drivers/iommu/arm/arm-smmu/arm-smmu.c       |  54 ++-
>   drivers/iommu/dma-iommu.c                   |  11 +-
>   drivers/iommu/virtio-iommu.c                |   2 +-
>   include/linux/acpi_iort.h                   |  18 +-
>   include/linux/dma-iommu.h                   |   5 +
>   include/linux/iommu.h                       |   9 +
>   9 files changed, 505 insertions(+), 45 deletions(-)
> 

I've tested the patches on a NXP LX2160A with SMMUv2 and things look 
fine. Thanks!

Tested-by: Laurentiu Tudor <laurentiu.tudor@nxp.com>

---
Best Regards, Laurentiu

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

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

end of thread, other threads:[~2022-04-19 15:32 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-04 12:41 [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node Shameer Kolothum
2022-04-04 12:41 ` [PATCH v9 01/11] ACPI/IORT: Add temporary RMR node flag definitions Shameer Kolothum
2022-04-06 15:53   ` Lorenzo Pieralisi
2022-04-04 12:42 ` [PATCH v9 02/11] iommu: Introduce a union to struct iommu_resv_region Shameer Kolothum
2022-04-04 12:42 ` [PATCH v9 03/11] ACPI/IORT: Make iort_iommu_msi_get_resv_regions() return void Shameer Kolothum
2022-04-06 15:12   ` Lorenzo Pieralisi
2022-04-04 12:42 ` [PATCH v9 04/11] ACPI/IORT: Provide a generic helper to retrieve reserve regions Shameer Kolothum
2022-04-06 15:54   ` Lorenzo Pieralisi
2022-04-04 12:42 ` [PATCH v9 05/11] iommu/dma: Introduce a helper to remove reserved regions Shameer Kolothum
2022-04-07 13:26   ` Christoph Hellwig
2022-04-04 12:42 ` [PATCH v9 06/11] ACPI/IORT: Add support to retrieve IORT RMR " Shameer Kolothum
2022-04-06 15:47   ` Lorenzo Pieralisi
2022-04-07 13:28   ` Christoph Hellwig
2022-04-07 13:53     ` Robin Murphy
2022-04-07 13:59       ` Christoph Hellwig
2022-04-19  8:31         ` Shameerali Kolothum Thodi
2022-04-19  9:04           ` Christoph Hellwig
2022-04-04 12:42 ` [PATCH v9 07/11] ACPI/IORT: Add a helper to retrieve RMR info directly Shameer Kolothum
2022-04-06 15:51   ` Lorenzo Pieralisi
2022-04-04 12:42 ` [PATCH v9 08/11] iommu/arm-smmu-v3: Introduce strtab init helper Shameer Kolothum
2022-04-04 12:42 ` [PATCH v9 09/11] iommu/arm-smmu-v3: Refactor arm_smmu_init_bypass_stes() to force bypass Shameer Kolothum
2022-04-04 12:42 ` [PATCH v9 10/11] iommu/arm-smmu-v3: Get associated RMR info and install bypass STE Shameer Kolothum
2022-04-04 12:42 ` [PATCH v9 11/11] iommu/arm-smmu: Get associated RMR info and install bypass SMR Shameer Kolothum
2022-04-07 15:43 ` [PATCH v9 00/11] ACPI/IORT: Support for IORT RMR node Steven Price
2022-04-19 14:50 ` Laurentiu Tudor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).