Pablo Greco 89a396
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 89a396
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Pablo Greco 89a396
Date: Thu, 5 Aug 2021 09:07:16 +0100
Pablo Greco cd4fb3
Subject: [PATCH 01/19] iommu: Introduce a union to struct iommu_resv_region
Pablo Greco 89a396
Pablo Greco 89a396
A union is introduced to struct iommu_resv_region to hold
Pablo Greco 89a396
any firmware specific data. This is in preparation to add
Pablo Greco 89a396
support for IORT RMR reserve regions and the union now holds
Pablo Greco 89a396
the RMR specific information.
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Pablo Greco 89a396
---
Pablo Greco 89a396
 include/linux/iommu.h | 11 +++++++++++
Pablo Greco 89a396
 1 file changed, 11 insertions(+)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
Pablo Greco 89a396
index d2f3435e7d17..d5cfd0c6a217 100644
Pablo Greco 89a396
--- a/include/linux/iommu.h
Pablo Greco 89a396
+++ b/include/linux/iommu.h
Pablo Greco 89a396
@@ -126,6 +126,13 @@ enum iommu_resv_type {
Pablo Greco 89a396
 	IOMMU_RESV_SW_MSI,
Pablo Greco 89a396
 };
Pablo Greco 89a396
 
Pablo Greco 89a396
+struct iommu_iort_rmr_data {
Pablo Greco 89a396
+#define IOMMU_RMR_REMAP_PERMITTED	(1 << 0)
Pablo Greco 89a396
+	u32 flags;
Pablo Greco 89a396
+	u32 sid;	/* Stream Id associated with RMR entry */
Pablo Greco 89a396
+	void *smmu;	/* Associated IORT SMMU node pointer */
Pablo Greco 89a396
+};
Pablo Greco 89a396
+
Pablo Greco 89a396
 /**
Pablo Greco 89a396
  * struct iommu_resv_region - descriptor for a reserved memory region
Pablo Greco 89a396
  * @list: Linked list pointers
Pablo Greco 89a396
@@ -133,6 +140,7 @@ enum iommu_resv_type {
Pablo Greco 89a396
  * @length: Length of the region in bytes
Pablo Greco 89a396
  * @prot: IOMMU Protection flags (READ/WRITE/...)
Pablo Greco 89a396
  * @type: Type of the reserved region
Pablo Greco 89a396
+ * @rmr: ACPI IORT RMR specific data
Pablo Greco 89a396
  */
Pablo Greco 89a396
 struct iommu_resv_region {
Pablo Greco 89a396
 	struct list_head	list;
Pablo Greco 89a396
@@ -140,6 +148,9 @@ struct iommu_resv_region {
Pablo Greco 89a396
 	size_t			length;
Pablo Greco 89a396
 	int			prot;
Pablo Greco 89a396
 	enum iommu_resv_type	type;
Pablo Greco 89a396
+	union {
Pablo Greco 89a396
+		struct iommu_iort_rmr_data rmr;
Pablo Greco 89a396
+	} fw_data;
Pablo Greco 89a396
 };
Pablo Greco 89a396
 
Pablo Greco 89a396
 /**
Pablo Greco 89a396
-- 
Pablo Greco 89a396
2.18.4
Pablo Greco 89a396
Pablo Greco 89a396
Pablo Greco 89a396
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 89a396
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Pablo Greco 89a396
Date: Thu, 5 Aug 2021 09:07:17 +0100
Pablo Greco cd4fb3
Subject: [PATCH 02/19] ACPI/IORT: Add support for RMR node parsing
Pablo Greco 89a396
Pablo Greco 89a396
Add support for parsing RMR node information from ACPI.
Pablo Greco 89a396
Pablo Greco 89a396
Find the associated streamid and smmu node info from the
Pablo Greco 89a396
RMR node and populate a linked list with RMR memory
Pablo Greco 89a396
descriptors.
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Pablo Greco 89a396
---
Pablo Greco 89a396
 drivers/acpi/arm64/iort.c | 134 +++++++++++++++++++++++++++++++++++++-
Pablo Greco 89a396
 1 file changed, 133 insertions(+), 1 deletion(-)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
Pablo Greco 1fd891
index f2f8f05662de..7df83d80819b 100644
Pablo Greco 89a396
--- a/drivers/acpi/arm64/iort.c
Pablo Greco 89a396
+++ b/drivers/acpi/arm64/iort.c
Pablo Greco 89a396
@@ -40,6 +40,8 @@ struct iort_fwnode {
Pablo Greco 89a396
 static LIST_HEAD(iort_fwnode_list);
Pablo Greco 89a396
 static DEFINE_SPINLOCK(iort_fwnode_lock);
Pablo Greco 89a396
 
Pablo Greco 89a396
+static LIST_HEAD(iort_rmr_list);	/* list of RMR regions from ACPI */
Pablo Greco 89a396
+
Pablo Greco 89a396
 /**
Pablo Greco 89a396
  * iort_set_fwnode() - Create iort_fwnode and use it to register
Pablo Greco 89a396
  *		       iommu data in the iort_fwnode_list
Pablo Greco 89a396
@@ -393,7 +395,8 @@ static struct acpi_iort_node *iort_node_get_id(struct acpi_iort_node *node,
Pablo Greco 89a396
 		if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT ||
Pablo Greco 89a396
 		    node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX ||
Pablo Greco 89a396
 		    node->type == ACPI_IORT_NODE_SMMU_V3 ||
Pablo Greco 89a396
-		    node->type == ACPI_IORT_NODE_PMCG) {
Pablo Greco 89a396
+		    node->type == ACPI_IORT_NODE_PMCG ||
Pablo Greco 89a396
+		    node->type == ACPI_IORT_NODE_RMR) {
Pablo Greco 89a396
 			*id_out = map->output_base;
Pablo Greco 89a396
 			return parent;
Pablo Greco 89a396
 		}
Pablo Greco 1fd891
@@ -1574,6 +1577,134 @@ static void __init iort_enable_acs(struct acpi_iort_node *iort_node)
Pablo Greco 89a396
 #else
Pablo Greco 89a396
 static inline void iort_enable_acs(struct acpi_iort_node *iort_node) { }
Pablo Greco 89a396
 #endif
Pablo Greco 89a396
+static void iort_rmr_desc_check_overlap(struct acpi_iort_rmr_desc *desc, u32 count)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	int i, j;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	for (i = 0; i < count; i++) {
Pablo Greco 89a396
+		u64 end, start = desc[i].base_address, length = desc[i].length;
Pablo Greco 89a396
+
Pablo Greco 89a396
+		end = start + length - 1;
Pablo Greco 89a396
+
Pablo Greco 89a396
+		/* Check for address overlap */
Pablo Greco 89a396
+		for (j = i + 1; j < count; j++) {
Pablo Greco 89a396
+			u64 e_start = desc[j].base_address;
Pablo Greco 89a396
+			u64 e_end = e_start + desc[j].length - 1;
Pablo Greco 89a396
+
Pablo Greco 89a396
+			if (start <= e_end && end >= e_start)
Pablo Greco 89a396
+				pr_err(FW_BUG "RMR descriptor[0x%llx - 0x%llx] overlaps, continue anyway\n",
Pablo Greco 89a396
+				       start, end);
Pablo Greco 89a396
+		}
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
+static void __init iort_node_get_rmr_info(struct acpi_iort_node *iort_node)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	struct acpi_iort_node *smmu;
Pablo Greco 89a396
+	struct acpi_iort_rmr *rmr;
Pablo Greco 89a396
+	struct acpi_iort_rmr_desc *rmr_desc;
Pablo Greco 89a396
+	u32 map_count = iort_node->mapping_count;
Pablo Greco 89a396
+	u32 sid;
Pablo Greco 89a396
+	int i;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	if (!iort_node->mapping_offset || map_count != 1) {
Pablo Greco 89a396
+		pr_err(FW_BUG "Invalid ID mapping, skipping RMR node %p\n",
Pablo Greco 89a396
+		       iort_node);
Pablo Greco 89a396
+		return;
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+
Pablo Greco 89a396
+	/* Retrieve associated smmu and stream id */
Pablo Greco 89a396
+	smmu = iort_node_get_id(iort_node, &sid, 0);
Pablo Greco 89a396
+	if (!smmu) {
Pablo Greco 89a396
+		pr_err(FW_BUG "Invalid SMMU reference, skipping RMR node %p\n",
Pablo Greco 89a396
+		       iort_node);
Pablo Greco 89a396
+		return;
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+
Pablo Greco 89a396
+	/* Retrieve RMR data */
Pablo Greco 89a396
+	rmr = (struct acpi_iort_rmr *)iort_node->node_data;
Pablo Greco 89a396
+	if (!rmr->rmr_offset || !rmr->rmr_count) {
Pablo Greco 89a396
+		pr_err(FW_BUG "Invalid RMR descriptor array, skipping RMR node %p\n",
Pablo Greco 89a396
+		       iort_node);
Pablo Greco 89a396
+		return;
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+
Pablo Greco 89a396
+	rmr_desc = ACPI_ADD_PTR(struct acpi_iort_rmr_desc, iort_node,
Pablo Greco 89a396
+				rmr->rmr_offset);
Pablo Greco 89a396
+
Pablo Greco 89a396
+	iort_rmr_desc_check_overlap(rmr_desc, rmr->rmr_count);
Pablo Greco 89a396
+
Pablo Greco 89a396
+	for (i = 0; i < rmr->rmr_count; i++, rmr_desc++) {
Pablo Greco 89a396
+		struct iommu_resv_region *region;
Pablo Greco 89a396
+		enum iommu_resv_type type;
Pablo Greco 89a396
+		int prot = IOMMU_READ | IOMMU_WRITE;
Pablo Greco 89a396
+		u64 addr = rmr_desc->base_address, size = rmr_desc->length;
Pablo Greco 89a396
+
Pablo Greco 89a396
+		if (!IS_ALIGNED(addr, SZ_64K) || !IS_ALIGNED(size, SZ_64K)) {
Pablo Greco 89a396
+			/* PAGE align base addr and size */
Pablo Greco 89a396
+			addr &= PAGE_MASK;
Pablo Greco 89a396
+			size = PAGE_ALIGN(size + offset_in_page(rmr_desc->base_address));
Pablo Greco 89a396
+
Pablo Greco 89a396
+			pr_err(FW_BUG "RMR descriptor[0x%llx - 0x%llx] not aligned to 64K, continue with [0x%llx - 0x%llx]\n",
Pablo Greco 89a396
+			       rmr_desc->base_address,
Pablo Greco 89a396
+			       rmr_desc->base_address + rmr_desc->length - 1,
Pablo Greco 89a396
+			       addr, addr + size - 1);
Pablo Greco 89a396
+		}
Pablo Greco 89a396
+		if (rmr->flags & IOMMU_RMR_REMAP_PERMITTED) {
Pablo Greco 89a396
+			type = IOMMU_RESV_DIRECT_RELAXABLE;
Pablo Greco 89a396
+			/*
Pablo Greco 89a396
+			 * Set IOMMU_CACHE as IOMMU_RESV_DIRECT_RELAXABLE is
Pablo Greco 89a396
+			 * normally used for allocated system memory that is
Pablo Greco 89a396
+			 * then used for device specific reserved regions.
Pablo Greco 89a396
+			 */
Pablo Greco 89a396
+			prot |= IOMMU_CACHE;
Pablo Greco 89a396
+		} else {
Pablo Greco 89a396
+			type = IOMMU_RESV_DIRECT;
Pablo Greco 89a396
+			/*
Pablo Greco 89a396
+			 * Set IOMMU_MMIO as IOMMU_RESV_DIRECT is normally used
Pablo Greco 89a396
+			 * for device memory like MSI doorbell.
Pablo Greco 89a396
+			 */
Pablo Greco 89a396
+			prot |= IOMMU_MMIO;
Pablo Greco 89a396
+		}
Pablo Greco 89a396
+
Pablo Greco 89a396
+		region = iommu_alloc_resv_region(addr, size, prot, type);
Pablo Greco 89a396
+		if (region) {
Pablo Greco 89a396
+			region->fw_data.rmr.flags = rmr->flags;
Pablo Greco 89a396
+			region->fw_data.rmr.sid = sid;
Pablo Greco 89a396
+			region->fw_data.rmr.smmu = smmu;
Pablo Greco 89a396
+			list_add_tail(&region->list, &iort_rmr_list);
Pablo Greco 89a396
+		}
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
+static void __init iort_parse_rmr(void)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	struct acpi_iort_node *iort_node, *iort_end;
Pablo Greco 89a396
+	struct acpi_table_iort *iort;
Pablo Greco 89a396
+	int i;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	if (iort_table->revision < 3)
Pablo Greco 89a396
+		return;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	iort = (struct acpi_table_iort *)iort_table;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort,
Pablo Greco 89a396
+				 iort->node_offset);
Pablo Greco 89a396
+	iort_end = ACPI_ADD_PTR(struct acpi_iort_node, iort,
Pablo Greco 89a396
+				iort_table->length);
Pablo Greco 89a396
+
Pablo Greco 89a396
+	for (i = 0; i < iort->node_count; i++) {
Pablo Greco 89a396
+		if (WARN_TAINT(iort_node >= iort_end, TAINT_FIRMWARE_WORKAROUND,
Pablo Greco 89a396
+			       "IORT node pointer overflows, bad table!\n"))
Pablo Greco 89a396
+			return;
Pablo Greco 89a396
+
Pablo Greco 89a396
+		if (iort_node->type == ACPI_IORT_NODE_RMR)
Pablo Greco 89a396
+			iort_node_get_rmr_info(iort_node);
Pablo Greco 89a396
+
Pablo Greco 89a396
+		iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node,
Pablo Greco 89a396
+					 iort_node->length);
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+}
Pablo Greco 89a396
 
Pablo Greco 89a396
 static void __init iort_init_platform_devices(void)
Pablo Greco 89a396
 {
Pablo Greco 1fd891
@@ -1644,6 +1775,7 @@ void __init acpi_iort_init(void)
Pablo Greco 89a396
 	}
Pablo Greco 89a396
 
Pablo Greco 89a396
 	iort_init_platform_devices();
Pablo Greco 89a396
+	iort_parse_rmr();
Pablo Greco 89a396
 }
Pablo Greco 89a396
 
Pablo Greco 89a396
 #ifdef CONFIG_ZONE_DMA
Pablo Greco 89a396
-- 
Pablo Greco 89a396
2.18.4
Pablo Greco 89a396
Pablo Greco 89a396
Pablo Greco 89a396
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 89a396
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Pablo Greco 89a396
Date: Thu, 5 Aug 2021 09:07:18 +0100
Pablo Greco cd4fb3
Subject: [PATCH 03/19] iommu/dma: Introduce generic helper to retrieve RMR
Pablo Greco 89a396
 info
Pablo Greco 89a396
Pablo Greco 89a396
Reserved Memory Regions(RMR) associated with an IOMMU can be
Pablo Greco 89a396
described through ACPI IORT tables in systems with devices
Pablo Greco 89a396
that require a unity mapping or bypass for those
Pablo Greco 89a396
regions.
Pablo Greco 89a396
Pablo Greco 89a396
Introduce a generic interface so that IOMMU drivers can retrieve
Pablo Greco 89a396
and set up necessary mappings.
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Pablo Greco 89a396
---
Pablo Greco 89a396
 drivers/iommu/dma-iommu.c | 29 +++++++++++++++++++++++++++++
Pablo Greco 89a396
 include/linux/dma-iommu.h | 13 +++++++++++++
Pablo Greco 89a396
 2 files changed, 42 insertions(+)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
Pablo Greco 7163c5
index 48c6f7ff4aef..72d801a5a5f7 100644
Pablo Greco 89a396
--- a/drivers/iommu/dma-iommu.c
Pablo Greco 89a396
+++ b/drivers/iommu/dma-iommu.c
Pablo Greco 89a396
@@ -174,6 +174,35 @@ void iommu_put_dma_cookie(struct iommu_domain *domain)
Pablo Greco 89a396
 }
Pablo Greco 89a396
 EXPORT_SYMBOL(iommu_put_dma_cookie);
Pablo Greco 89a396
 
Pablo Greco 89a396
+/**
Pablo Greco 89a396
+ *
Pablo Greco 89a396
+ * iommu_dma_get_rmrs - Retrieve Reserved Memory Regions(RMRs) associated
Pablo Greco 89a396
+ *                      with a given IOMMU
Pablo Greco 89a396
+ * @iommu_fwnode: fwnode associated with IOMMU
Pablo Greco 89a396
+ * @list: RMR list to be populated
Pablo Greco 89a396
+ *
Pablo Greco 89a396
+ */
Pablo Greco 89a396
+int iommu_dma_get_rmrs(struct fwnode_handle *iommu_fwnode,
Pablo Greco 89a396
+		       struct list_head *list)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	return -EINVAL;
Pablo Greco 89a396
+}
Pablo Greco 89a396
+EXPORT_SYMBOL(iommu_dma_get_rmrs);
Pablo Greco 89a396
+
Pablo Greco 89a396
+/**
Pablo Greco 89a396
+ *
Pablo Greco 89a396
+ * iommu_dma_put_rmrs - Release Reserved Memory Regions(RMRs) associated
Pablo Greco 89a396
+ *                      with a given IOMMU
Pablo Greco 89a396
+ * @iommu_fwnode: fwnode associated with IOMMU
Pablo Greco 89a396
+ * @list: RMR list
Pablo Greco 89a396
+ *
Pablo Greco 89a396
+ */
Pablo Greco 89a396
+void iommu_dma_put_rmrs(struct fwnode_handle *iommu_fwnode,
Pablo Greco 89a396
+			struct list_head *list)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+}
Pablo Greco 89a396
+EXPORT_SYMBOL(iommu_dma_put_rmrs);
Pablo Greco 89a396
+
Pablo Greco 89a396
 /**
Pablo Greco 89a396
  * iommu_dma_get_resv_regions - Reserved region driver helper
Pablo Greco 89a396
  * @dev: Device from iommu_get_resv_regions()
Pablo Greco 89a396
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
Pablo Greco 89a396
index 24607dc3c2ac..7579c014e274 100644
Pablo Greco 89a396
--- a/include/linux/dma-iommu.h
Pablo Greco 89a396
+++ b/include/linux/dma-iommu.h
Pablo Greco 89a396
@@ -43,12 +43,16 @@ void iommu_dma_free_cpu_cached_iovas(unsigned int cpu,
Pablo Greco 89a396
 
Pablo Greco 89a396
 extern bool iommu_dma_forcedac;
Pablo Greco 89a396
 
Pablo Greco 89a396
+int iommu_dma_get_rmrs(struct fwnode_handle *iommu, struct list_head *list);
Pablo Greco 89a396
+void iommu_dma_put_rmrs(struct fwnode_handle *iommu, struct list_head *list);
Pablo Greco 89a396
+
Pablo Greco 89a396
 #else /* CONFIG_IOMMU_DMA */
Pablo Greco 89a396
 
Pablo Greco 89a396
 struct iommu_domain;
Pablo Greco 89a396
 struct msi_desc;
Pablo Greco 89a396
 struct msi_msg;
Pablo Greco 89a396
 struct device;
Pablo Greco 89a396
+struct fwnode_handle;
Pablo Greco 89a396
 
Pablo Greco 89a396
 static inline void iommu_setup_dma_ops(struct device *dev, u64 dma_base,
Pablo Greco 89a396
 				       u64 dma_limit)
Pablo Greco 89a396
@@ -89,5 +93,14 @@ static inline void iommu_dma_get_resv_regions(struct device *dev, struct list_he
Pablo Greco 89a396
 {
Pablo Greco 89a396
 }
Pablo Greco 89a396
 
Pablo Greco 89a396
+static int iommu_dma_get_rmrs(struct fwnode_handle *iommu, struct list_head *list)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	return -ENODEV;
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
+static void iommu_dma_put_rmrs(struct fwnode_handle *iommu, struct list_head *list)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
 #endif	/* CONFIG_IOMMU_DMA */
Pablo Greco 89a396
 #endif	/* __DMA_IOMMU_H */
Pablo Greco 89a396
-- 
Pablo Greco 89a396
2.18.4
Pablo Greco 89a396
Pablo Greco 89a396
Pablo Greco 89a396
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 89a396
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Pablo Greco 89a396
Date: Thu, 5 Aug 2021 09:07:19 +0100
Pablo Greco cd4fb3
Subject: [PATCH 04/19] ACPI/IORT: Add a helper to retrieve RMR memory regions
Pablo Greco 89a396
Pablo Greco 89a396
Add a helper function (iort_iommu_get_rmrs()) that retrieves RMR
Pablo Greco 89a396
memory descriptors associated with a given IOMMU. This will be used
Pablo Greco 89a396
by IOMMU drivers to setup necessary mappings.
Pablo Greco 89a396
Pablo Greco 89a396
Invoke it from the generic helper iommu_dma_get_rmrs().
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Pablo Greco 89a396
---
Pablo Greco 89a396
 drivers/acpi/arm64/iort.c | 38 ++++++++++++++++++++++++++++++++++++++
Pablo Greco 89a396
 drivers/iommu/dma-iommu.c |  4 ++++
Pablo Greco 89a396
 include/linux/acpi_iort.h |  7 +++++++
Pablo Greco 89a396
 3 files changed, 49 insertions(+)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
Pablo Greco 1fd891
index 7df83d80819b..66d200e577cb 100644
Pablo Greco 89a396
--- a/drivers/acpi/arm64/iort.c
Pablo Greco 89a396
+++ b/drivers/acpi/arm64/iort.c
Pablo Greco 89a396
@@ -809,6 +809,42 @@ static struct acpi_iort_node *iort_get_msi_resv_iommu(struct device *dev)
Pablo Greco 89a396
 	return NULL;
Pablo Greco 89a396
 }
Pablo Greco 89a396
 
Pablo Greco 89a396
+/**
Pablo Greco 89a396
+ * iort_iommu_get_rmrs() - Helper to retrieve RMR info associated with IOMMU
Pablo Greco 89a396
+ * @iommu_fwnode: fwnode for the IOMMU
Pablo Greco 89a396
+ * @head: RMR list head to be populated
Pablo Greco 89a396
+ *
Pablo Greco 89a396
+ * Returns: 0 on success, <0 failure. Please note, we will keep the already
Pablo Greco 89a396
+ *          allocated RMR reserve regions in case of a kmemdup()
Pablo Greco 89a396
+ *          failure.
Pablo Greco 89a396
+ */
Pablo Greco 89a396
+int iort_iommu_get_rmrs(struct fwnode_handle *iommu_fwnode,
Pablo Greco 89a396
+			struct list_head *head)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	struct iommu_resv_region *e;
Pablo Greco 89a396
+	struct acpi_iort_node *iommu;
Pablo Greco 89a396
+	int rmrs = 0;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	iommu = iort_get_iort_node(iommu_fwnode);
Pablo Greco 89a396
+	if (!iommu || list_empty(&iort_rmr_list))
Pablo Greco 89a396
+		return -ENODEV;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	list_for_each_entry(e, &iort_rmr_list, list) {
Pablo Greco 89a396
+		struct iommu_resv_region *region;
Pablo Greco 89a396
+
Pablo Greco 89a396
+		if (e->fw_data.rmr.smmu != iommu)
Pablo Greco 89a396
+			continue;
Pablo Greco 89a396
+
Pablo Greco 89a396
+		region = kmemdup(e, sizeof(*region), GFP_KERNEL);
Pablo Greco 89a396
+		if (region) {
Pablo Greco 89a396
+			list_add_tail(&region->list, head);
Pablo Greco 89a396
+			rmrs++;
Pablo Greco 89a396
+		}
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+
Pablo Greco 89a396
+	return (rmrs == 0) ? -ENODEV : 0;
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
 /**
Pablo Greco 89a396
  * iort_iommu_msi_get_resv_regions - Reserved region driver helper
Pablo Greco 89a396
  * @dev: Device from iommu_get_resv_regions()
Pablo Greco 89a396
@@ -1041,6 +1077,8 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
Pablo Greco 89a396
 { return 0; }
Pablo Greco 89a396
 int iort_iommu_configure_id(struct device *dev, const u32 *input_id)
Pablo Greco 89a396
 { return -ENODEV; }
Pablo Greco 89a396
+int iort_iommu_get_rmrs(struct fwnode_handle *fwnode, struct list_head *head)
Pablo Greco 89a396
+{ return -ENODEV; }
Pablo Greco 89a396
 #endif
Pablo Greco 89a396
 
Pablo Greco 89a396
 static int nc_dma_get_range(struct device *dev, u64 *size)
Pablo Greco 89a396
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
Pablo Greco 7163c5
index 72d801a5a5f7..4e4d00a3adaf 100644
Pablo Greco 89a396
--- a/drivers/iommu/dma-iommu.c
Pablo Greco 89a396
+++ b/drivers/iommu/dma-iommu.c
Pablo Greco 89a396
@@ -185,6 +185,9 @@ EXPORT_SYMBOL(iommu_put_dma_cookie);
Pablo Greco 89a396
 int iommu_dma_get_rmrs(struct fwnode_handle *iommu_fwnode,
Pablo Greco 89a396
 		       struct list_head *list)
Pablo Greco 89a396
 {
Pablo Greco 89a396
+	if (!is_of_node(iommu_fwnode))
Pablo Greco 89a396
+		return iort_iommu_get_rmrs(iommu_fwnode, list);
Pablo Greco 89a396
+
Pablo Greco 89a396
 	return -EINVAL;
Pablo Greco 89a396
 }
Pablo Greco 89a396
 EXPORT_SYMBOL(iommu_dma_get_rmrs);
Pablo Greco 89a396
@@ -200,6 +203,7 @@ EXPORT_SYMBOL(iommu_dma_get_rmrs);
Pablo Greco 89a396
 void iommu_dma_put_rmrs(struct fwnode_handle *iommu_fwnode,
Pablo Greco 89a396
 			struct list_head *list)
Pablo Greco 89a396
 {
Pablo Greco 89a396
+	generic_iommu_put_resv_regions(iommu_fwnode->dev, list);
Pablo Greco 89a396
 }
Pablo Greco 89a396
 EXPORT_SYMBOL(iommu_dma_put_rmrs);
Pablo Greco 89a396
 
Pablo Greco 89a396
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
Pablo Greco 89a396
index f1f0842a2cb2..d8c030c103f5 100644
Pablo Greco 89a396
--- a/include/linux/acpi_iort.h
Pablo Greco 89a396
+++ b/include/linux/acpi_iort.h
Pablo Greco 89a396
@@ -38,6 +38,8 @@ int iort_dma_get_ranges(struct device *dev, u64 *size);
Pablo Greco 89a396
 int iort_iommu_configure_id(struct device *dev, const u32 *id_in);
Pablo Greco 89a396
 int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head);
Pablo Greco 89a396
 phys_addr_t acpi_iort_dma_get_max_cpu_address(void);
Pablo Greco 89a396
+int iort_iommu_get_rmrs(struct fwnode_handle *iommu_fwnode,
Pablo Greco 89a396
+			struct list_head *list);
Pablo Greco 89a396
 #else
Pablo Greco 89a396
 static inline void acpi_iort_init(void) { }
Pablo Greco 89a396
 static inline u32 iort_msi_map_id(struct device *dev, u32 id)
Pablo Greco 89a396
@@ -57,6 +59,11 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
Pablo Greco 89a396
 
Pablo Greco 89a396
 static inline phys_addr_t acpi_iort_dma_get_max_cpu_address(void)
Pablo Greco 89a396
 { return PHYS_ADDR_MAX; }
Pablo Greco 89a396
+
Pablo Greco 89a396
+static inline
Pablo Greco 89a396
+int iort_iommu_get_rmrs(struct fwnode_handle *iommu_fwnode,
Pablo Greco 89a396
+			struct list_head *list)
Pablo Greco 89a396
+{ return -ENODEV; }
Pablo Greco 89a396
 #endif
Pablo Greco 89a396
 
Pablo Greco 89a396
 #endif /* __ACPI_IORT_H__ */
Pablo Greco 89a396
-- 
Pablo Greco 89a396
2.18.4
Pablo Greco 89a396
Pablo Greco 89a396
Pablo Greco 89a396
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 89a396
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Pablo Greco 89a396
Date: Thu, 5 Aug 2021 09:07:20 +0100
Pablo Greco cd4fb3
Subject: [PATCH 05/19] iommu/arm-smmu-v3: Introduce strtab init helper
Pablo Greco 89a396
Pablo Greco 89a396
Introduce a helper to check the sid range and to init the l2 strtab
Pablo Greco 89a396
entries(bypass). This will be useful when we have to initialize the
Pablo Greco 89a396
l2 strtab with bypass for RMR SIDs.
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Pablo Greco 89a396
---
Pablo Greco 89a396
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 28 +++++++++++----------
Pablo Greco 89a396
 1 file changed, 15 insertions(+), 13 deletions(-)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
Pablo Greco c57d7b
index e7da4a47ce52..4a8c2f5158ea 100644
Pablo Greco 89a396
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
Pablo Greco 89a396
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
Pablo Greco 118628
@@ -2530,6 +2530,19 @@ static bool arm_smmu_sid_in_range(struct arm_smmu_device *smmu, u32 sid)
Pablo Greco 89a396
 	return sid < limit;
Pablo Greco 89a396
 }
Pablo Greco 89a396
 
Pablo Greco 89a396
+static int arm_smmu_init_sid_strtab(struct arm_smmu_device *smmu, u32 sid)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	/* Check the SIDs are in range of the SMMU and our stream table */
Pablo Greco 89a396
+	if (!arm_smmu_sid_in_range(smmu, sid))
Pablo Greco 89a396
+		return -ERANGE;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	/* Ensure l2 strtab is initialised */
Pablo Greco 89a396
+	if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB)
Pablo Greco 89a396
+		return arm_smmu_init_l2_strtab(smmu, sid);
Pablo Greco 89a396
+
Pablo Greco 89a396
+	return 0;
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
 static int arm_smmu_insert_master(struct arm_smmu_device *smmu,
Pablo Greco 89a396
 				  struct arm_smmu_master *master)
Pablo Greco 89a396
 {
Pablo Greco 118628
@@ -2553,20 +2566,9 @@ static int arm_smmu_insert_master(struct arm_smmu_device *smmu,
Pablo Greco 89a396
 		new_stream->id = sid;
Pablo Greco 89a396
 		new_stream->master = master;
Pablo Greco 89a396
 
Pablo Greco 89a396
-		/*
Pablo Greco 89a396
-		 * Check the SIDs are in range of the SMMU and our stream table
Pablo Greco 89a396
-		 */
Pablo Greco 89a396
-		if (!arm_smmu_sid_in_range(smmu, sid)) {
Pablo Greco 89a396
-			ret = -ERANGE;
Pablo Greco 89a396
+		ret = arm_smmu_init_sid_strtab(smmu, sid);
Pablo Greco 89a396
+		if (ret)
Pablo Greco 89a396
 			break;
Pablo Greco 89a396
-		}
Pablo Greco 89a396
-
Pablo Greco 89a396
-		/* Ensure l2 strtab is initialised */
Pablo Greco 89a396
-		if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB) {
Pablo Greco 89a396
-			ret = arm_smmu_init_l2_strtab(smmu, sid);
Pablo Greco 89a396
-			if (ret)
Pablo Greco 89a396
-				break;
Pablo Greco 89a396
-		}
Pablo Greco 89a396
 
Pablo Greco 89a396
 		/* Insert into SID tree */
Pablo Greco 89a396
 		new_node = &(smmu->streams.rb_node);
Pablo Greco 89a396
-- 
Pablo Greco 89a396
2.18.4
Pablo Greco 89a396
Pablo Greco 89a396
Pablo Greco 89a396
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 89a396
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Pablo Greco 89a396
Date: Thu, 5 Aug 2021 09:07:21 +0100
Pablo Greco cd4fb3
Subject: [PATCH 06/19] =?UTF-8?q?iommu/arm-smmu-v3:=20Refactor=C2=A0arm=5F?=
Pablo Greco 89a396
 =?UTF-8?q?smmu=5Finit=5Fbypass=5Fstes()=20to=20force=20bypass?=
Pablo Greco 89a396
MIME-Version: 1.0
Pablo Greco 89a396
Content-Type: text/plain; charset=UTF-8
Pablo Greco 89a396
Content-Transfer-Encoding: 8bit
Pablo Greco 89a396
Pablo Greco 89a396
By default, disable_bypass flag is set and any dev without
Pablo Greco 89a396
an iommu domain installs STE with CFG_ABORT during
Pablo Greco 89a396
arm_smmu_init_bypass_stes(). Introduce a "force" flag and
Pablo Greco 89a396
move the STE update logic to arm_smmu_init_bypass_stes()
Pablo Greco 89a396
so that we can force it to install CFG_BYPASS STE for specific
Pablo Greco 89a396
SIDs.
Pablo Greco 89a396
Pablo Greco 89a396
This will be useful in follow-up patch to install bypass
Pablo Greco 89a396
for IORT RMR SIDs.
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Pablo Greco 89a396
---
Pablo Greco 89a396
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 17 +++++++++++++----
Pablo Greco 89a396
 1 file changed, 13 insertions(+), 4 deletions(-)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
Pablo Greco c57d7b
index 4a8c2f5158ea..ce47559cfca7 100644
Pablo Greco 89a396
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
Pablo Greco 89a396
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
Pablo Greco 89a396
@@ -1374,12 +1374,21 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
Pablo Greco 89a396
 		arm_smmu_cmdq_issue_cmd(smmu, &prefetch_cmd);
Pablo Greco 89a396
 }
Pablo Greco 89a396
 
Pablo Greco 89a396
-static void arm_smmu_init_bypass_stes(__le64 *strtab, unsigned int nent)
Pablo Greco 89a396
+static void arm_smmu_init_bypass_stes(__le64 *strtab, unsigned int nent, bool force)
Pablo Greco 89a396
 {
Pablo Greco 89a396
 	unsigned int i;
Pablo Greco 89a396
+	u64 val = STRTAB_STE_0_V;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	if (disable_bypass && !force)
Pablo Greco 89a396
+		val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_ABORT);
Pablo Greco 89a396
+	else
Pablo Greco 89a396
+		val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_BYPASS);
Pablo Greco 89a396
 
Pablo Greco 89a396
 	for (i = 0; i < nent; ++i) {
Pablo Greco 89a396
-		arm_smmu_write_strtab_ent(NULL, -1, strtab);
Pablo Greco 89a396
+		strtab[0] = cpu_to_le64(val);
Pablo Greco 89a396
+		strtab[1] = cpu_to_le64(FIELD_PREP(STRTAB_STE_1_SHCFG,
Pablo Greco 89a396
+						   STRTAB_STE_1_SHCFG_INCOMING));
Pablo Greco 89a396
+		strtab[2] = 0;
Pablo Greco 89a396
 		strtab += STRTAB_STE_DWORDS;
Pablo Greco 89a396
 	}
Pablo Greco 89a396
 }
Pablo Greco 89a396
@@ -1407,7 +1416,7 @@ static int arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid)
Pablo Greco 89a396
 		return -ENOMEM;
Pablo Greco 89a396
 	}
Pablo Greco 89a396
 
Pablo Greco 89a396
-	arm_smmu_init_bypass_stes(desc->l2ptr, 1 << STRTAB_SPLIT);
Pablo Greco 89a396
+	arm_smmu_init_bypass_stes(desc->l2ptr, 1 << STRTAB_SPLIT, false);
Pablo Greco 89a396
 	arm_smmu_write_strtab_l1_desc(strtab, desc);
Pablo Greco 89a396
 	return 0;
Pablo Greco 89a396
 }
Pablo Greco c57d7b
@@ -3075,7 +3084,7 @@ static int arm_smmu_init_strtab_linear(struct arm_smmu_device *smmu)
Pablo Greco 89a396
 	reg |= FIELD_PREP(STRTAB_BASE_CFG_LOG2SIZE, smmu->sid_bits);
Pablo Greco 89a396
 	cfg->strtab_base_cfg = reg;
Pablo Greco 89a396
 
Pablo Greco 89a396
-	arm_smmu_init_bypass_stes(strtab, cfg->num_l1_ents);
Pablo Greco 89a396
+	arm_smmu_init_bypass_stes(strtab, cfg->num_l1_ents, false);
Pablo Greco 89a396
 	return 0;
Pablo Greco 89a396
 }
Pablo Greco 89a396
 
Pablo Greco 89a396
-- 
Pablo Greco 89a396
2.18.4
Pablo Greco 89a396
Pablo Greco 89a396
Pablo Greco 89a396
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 89a396
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Pablo Greco 89a396
Date: Thu, 5 Aug 2021 09:07:22 +0100
Pablo Greco cd4fb3
Subject: [PATCH 07/19] iommu/arm-smmu-v3: Get associated RMR info and install
Pablo Greco 89a396
 bypass STE
Pablo Greco 89a396
MIME-Version: 1.0
Pablo Greco 89a396
Content-Type: text/plain; charset=UTF-8
Pablo Greco 89a396
Content-Transfer-Encoding: 8bit
Pablo Greco 89a396
Pablo Greco 89a396
Check if there is any RMR info associated with the devices behind
Pablo Greco 89a396
the SMMUv3 and if any, install bypass STEs for them. This is to
Pablo Greco 89a396
keep any ongoing traffic associated with these devices alive
Pablo Greco 89a396
when we enable/reset SMMUv3 during probe().
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Pablo Greco 89a396
---
Pablo Greco 89a396
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 31 +++++++++++++++++++++
Pablo Greco 89a396
 1 file changed, 31 insertions(+)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
Pablo Greco c57d7b
index ce47559cfca7..dbddb5ea2321 100644
Pablo Greco 89a396
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
Pablo Greco 89a396
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
Pablo Greco c57d7b
@@ -3791,6 +3791,34 @@ static void __iomem *arm_smmu_ioremap(struct device *dev, resource_size_t start,
Pablo Greco 89a396
 	return devm_ioremap_resource(dev, &res;;
Pablo Greco 89a396
 }
Pablo Greco 89a396
 
Pablo Greco 89a396
+static void arm_smmu_rmr_install_bypass_ste(struct arm_smmu_device *smmu)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	struct list_head rmr_list;
Pablo Greco 89a396
+	struct iommu_resv_region *e;
Pablo Greco 89a396
+	int ret;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	INIT_LIST_HEAD(&rmr_list);
Pablo Greco 89a396
+	if (iommu_dma_get_rmrs(dev_fwnode(smmu->dev), &rmr_list))
Pablo Greco 89a396
+		return;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	list_for_each_entry(e, &rmr_list, list) {
Pablo Greco 89a396
+		__le64 *step;
Pablo Greco 89a396
+		u32 sid = e->fw_data.rmr.sid;
Pablo Greco 89a396
+
Pablo Greco 89a396
+		ret = arm_smmu_init_sid_strtab(smmu, sid);
Pablo Greco 89a396
+		if (ret) {
Pablo Greco 89a396
+			dev_err(smmu->dev, "RMR SID(0x%x) bypass failed\n",
Pablo Greco 89a396
+				sid);
Pablo Greco 89a396
+			continue;
Pablo Greco 89a396
+		}
Pablo Greco 89a396
+
Pablo Greco 89a396
+		step = arm_smmu_get_step_for_sid(smmu, sid);
Pablo Greco 89a396
+		arm_smmu_init_bypass_stes(step, 1, true);
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+
Pablo Greco 89a396
+	iommu_dma_put_rmrs(dev_fwnode(smmu->dev), &rmr_list);
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
 static int arm_smmu_device_probe(struct platform_device *pdev)
Pablo Greco 89a396
 {
Pablo Greco 89a396
 	int irq, ret;
Pablo Greco c57d7b
@@ -3874,6 +3902,9 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
Pablo Greco 89a396
 	/* Record our private device structure */
Pablo Greco 89a396
 	platform_set_drvdata(pdev, smmu);
Pablo Greco 89a396
 
Pablo Greco 89a396
+	/* Check for RMRs and install bypass STEs if any */
Pablo Greco 89a396
+	arm_smmu_rmr_install_bypass_ste(smmu);
Pablo Greco 89a396
+
Pablo Greco 89a396
 	/* Reset the device */
Pablo Greco 89a396
 	ret = arm_smmu_device_reset(smmu, bypass);
Pablo Greco 89a396
 	if (ret)
Pablo Greco 89a396
-- 
Pablo Greco 89a396
2.18.4
Pablo Greco 89a396
Pablo Greco 89a396
Pablo Greco 89a396
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 89a396
From: Jon Nettleton <jon@solid-run.com>
Pablo Greco 89a396
Date: Thu, 5 Aug 2021 09:07:23 +0100
Pablo Greco cd4fb3
Subject: [PATCH 08/19] iommu/arm-smmu: Get associated RMR info and install
Pablo Greco 89a396
 bypass SMR
Pablo Greco 89a396
Pablo Greco 89a396
Check if there is any RMR info associated with the devices behind
Pablo Greco 89a396
the SMMU and if any, install bypass SMRs for them. This is to
Pablo Greco 89a396
keep any ongoing traffic associated with these devices alive
Pablo Greco 89a396
when we enable/reset SMMU during probe().
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Jon Nettleton <jon@solid-run.com>
Pablo Greco 89a396
Signed-off-by: Steven Price <steven.price@arm.com>
Pablo Greco 89a396
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Pablo Greco 89a396
---
Pablo Greco 89a396
 drivers/iommu/arm/arm-smmu/arm-smmu.c | 48 +++++++++++++++++++++++++++
Pablo Greco 89a396
 1 file changed, 48 insertions(+)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
Pablo Greco 7163c5
index 324e8f32962a..1d65dd243fee 100644
Pablo Greco 89a396
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
Pablo Greco 89a396
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
Pablo Greco 89a396
@@ -2066,6 +2066,50 @@ err_reset_platform_ops: __maybe_unused;
Pablo Greco 89a396
 	return err;
Pablo Greco 89a396
 }
Pablo Greco 89a396
 
Pablo Greco 89a396
+static void arm_smmu_rmr_install_bypass_smr(struct arm_smmu_device *smmu)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	struct list_head rmr_list;
Pablo Greco 89a396
+	struct iommu_resv_region *e;
Pablo Greco 89a396
+	int i, cnt = 0;
Pablo Greco 89a396
+	u32 reg;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	INIT_LIST_HEAD(&rmr_list);
Pablo Greco 89a396
+	if (iommu_dma_get_rmrs(dev_fwnode(smmu->dev), &rmr_list))
Pablo Greco 89a396
+		return;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	/*
Pablo Greco 89a396
+	 * Rather than trying to look at existing mappings that
Pablo Greco 89a396
+	 * are setup by the firmware and then invalidate the ones
Pablo Greco 89a396
+	 * that do no have matching RMR entries, just disable the
Pablo Greco 89a396
+	 * SMMU until it gets enabled again in the reset routine.
Pablo Greco 89a396
+	 */
Pablo Greco 89a396
+	reg = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sCR0);
Pablo Greco 89a396
+	reg |= ARM_SMMU_sCR0_CLIENTPD;
Pablo Greco 89a396
+	arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_sCR0, reg);
Pablo Greco 89a396
+
Pablo Greco 89a396
+	list_for_each_entry(e, &rmr_list, list) {
Pablo Greco 89a396
+		u32 sid = e->fw_data.rmr.sid;
Pablo Greco 89a396
+
Pablo Greco 89a396
+		i = arm_smmu_find_sme(smmu, sid, ~0);
Pablo Greco 89a396
+		if (i < 0)
Pablo Greco 89a396
+			continue;
Pablo Greco 89a396
+		if (smmu->s2crs[i].count == 0) {
Pablo Greco 89a396
+			smmu->smrs[i].id = sid;
Pablo Greco 89a396
+			smmu->smrs[i].mask = 0;
Pablo Greco 89a396
+			smmu->smrs[i].valid = true;
Pablo Greco 89a396
+		}
Pablo Greco 89a396
+		smmu->s2crs[i].count++;
Pablo Greco 89a396
+		smmu->s2crs[i].type = S2CR_TYPE_BYPASS;
Pablo Greco 89a396
+		smmu->s2crs[i].privcfg = S2CR_PRIVCFG_DEFAULT;
Pablo Greco 89a396
+
Pablo Greco 89a396
+		cnt++;
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+
Pablo Greco 89a396
+	dev_notice(smmu->dev, "\tpreserved %d boot mapping%s\n", cnt,
Pablo Greco 89a396
+		   cnt == 1 ? "" : "s");
Pablo Greco 89a396
+	iommu_dma_put_rmrs(dev_fwnode(smmu->dev), &rmr_list);
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
 static int arm_smmu_device_probe(struct platform_device *pdev)
Pablo Greco 89a396
 {
Pablo Greco 89a396
 	struct resource *res;
Pablo Greco 7163c5
@@ -2191,6 +2235,10 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
Pablo Greco 89a396
 	}
Pablo Greco 89a396
 
Pablo Greco 89a396
 	platform_set_drvdata(pdev, smmu);
Pablo Greco 89a396
+
Pablo Greco 89a396
+	/* Check for RMRs and install bypass SMRs if any */
Pablo Greco 89a396
+	arm_smmu_rmr_install_bypass_smr(smmu);
Pablo Greco 89a396
+
Pablo Greco 89a396
 	arm_smmu_device_reset(smmu);
Pablo Greco 89a396
 	arm_smmu_test_smr_masks(smmu);
Pablo Greco 89a396
 
Pablo Greco 89a396
-- 
Pablo Greco 89a396
2.18.4
Pablo Greco 89a396
Pablo Greco 89a396
Pablo Greco 89a396
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 89a396
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Pablo Greco 89a396
Date: Thu, 5 Aug 2021 09:07:24 +0100
Pablo Greco cd4fb3
Subject: [PATCH 09/19] iommu/dma: Reserve any RMR regions associated with a
Pablo Greco 89a396
 dev
Pablo Greco 89a396
Pablo Greco 89a396
Get ACPI IORT RMR regions associated with a dev reserved
Pablo Greco 89a396
so that there is a unity mapping for them in SMMU.
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Pablo Greco 89a396
---
Pablo Greco 89a396
 drivers/iommu/dma-iommu.c | 56 +++++++++++++++++++++++++++++++++++----
Pablo Greco 89a396
 1 file changed, 51 insertions(+), 5 deletions(-)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
Pablo Greco 7163c5
index 4e4d00a3adaf..0014a70597ef 100644
Pablo Greco 89a396
--- a/drivers/iommu/dma-iommu.c
Pablo Greco 89a396
+++ b/drivers/iommu/dma-iommu.c
Pablo Greco 89a396
@@ -207,22 +207,68 @@ void iommu_dma_put_rmrs(struct fwnode_handle *iommu_fwnode,
Pablo Greco 89a396
 }
Pablo Greco 89a396
 EXPORT_SYMBOL(iommu_dma_put_rmrs);
Pablo Greco 89a396
 
Pablo Greco 89a396
+static bool iommu_dma_dev_has_rmr(struct iommu_fwspec *fwspec,
Pablo Greco 89a396
+				  struct iommu_resv_region *e)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	int i;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	for (i = 0; i < fwspec->num_ids; i++) {
Pablo Greco 89a396
+		if (e->fw_data.rmr.sid == fwspec->ids[i])
Pablo Greco 89a396
+			return true;
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+
Pablo Greco 89a396
+	return false;
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
+static void iommu_dma_get_rmr_resv_regions(struct device *dev,
Pablo Greco 89a396
+					   struct list_head *list)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
Pablo Greco 89a396
+	struct list_head rmr_list;
Pablo Greco 89a396
+	struct iommu_resv_region *rmr, *tmp;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	INIT_LIST_HEAD(&rmr_list);
Pablo Greco 89a396
+	if (iommu_dma_get_rmrs(fwspec->iommu_fwnode, &rmr_list))
Pablo Greco 89a396
+		return;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	if (dev_is_pci(dev)) {
Pablo Greco 89a396
+		struct pci_dev *pdev = to_pci_dev(dev);
Pablo Greco 89a396
+		struct pci_host_bridge *host = pci_find_host_bridge(pdev->bus);
Pablo Greco 89a396
+
Pablo Greco 89a396
+		if (!host->preserve_config)
Pablo Greco 89a396
+			return;
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+
Pablo Greco 89a396
+	list_for_each_entry_safe(rmr, tmp, &rmr_list, list) {
Pablo Greco 89a396
+		if (!iommu_dma_dev_has_rmr(fwspec, rmr))
Pablo Greco 89a396
+			continue;
Pablo Greco 89a396
+
Pablo Greco 89a396
+		/* Remove from iommu RMR list and add to dev resv_regions */
Pablo Greco 89a396
+		list_del_init(&rmr->list);
Pablo Greco 89a396
+		list_add_tail(&rmr->list, list);
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+
Pablo Greco 89a396
+	iommu_dma_put_rmrs(fwspec->iommu_fwnode, &rmr_list);
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
 /**
Pablo Greco 89a396
  * iommu_dma_get_resv_regions - Reserved region driver helper
Pablo Greco 89a396
  * @dev: Device from iommu_get_resv_regions()
Pablo Greco 89a396
  * @list: Reserved region list from iommu_get_resv_regions()
Pablo Greco 89a396
  *
Pablo Greco 89a396
  * IOMMU drivers can use this to implement their .get_resv_regions callback
Pablo Greco 89a396
- * for general non-IOMMU-specific reservations. Currently, this covers GICv3
Pablo Greco 89a396
- * ITS region reservation on ACPI based ARM platforms that may require HW MSI
Pablo Greco 89a396
- * reservation.
Pablo Greco 89a396
+ * for general non-IOMMU-specific reservations. Currently this covers,
Pablo Greco 89a396
+ *  -GICv3 ITS region reservation on ACPI based ARM platforms that may
Pablo Greco 89a396
+ *   require HW MSI reservation.
Pablo Greco 89a396
+ *  -Any ACPI IORT RMR memory range reservations (IORT spec rev E.b)
Pablo Greco 89a396
  */
Pablo Greco 89a396
 void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
Pablo Greco 89a396
 {
Pablo Greco 89a396
 
Pablo Greco 89a396
-	if (!is_of_node(dev_iommu_fwspec_get(dev)->iommu_fwnode))
Pablo Greco 89a396
+	if (!is_of_node(dev_iommu_fwspec_get(dev)->iommu_fwnode)) {
Pablo Greco 89a396
 		iort_iommu_msi_get_resv_regions(dev, list);
Pablo Greco 89a396
-
Pablo Greco 89a396
+		iommu_dma_get_rmr_resv_regions(dev, list);
Pablo Greco 89a396
+	}
Pablo Greco 89a396
 }
Pablo Greco 89a396
 EXPORT_SYMBOL(iommu_dma_get_resv_regions);
Pablo Greco 89a396
 
Pablo Greco 89a396
-- 
Pablo Greco 89a396
2.18.4
Pablo Greco 89a396
Pablo Greco 89a396
Pablo Greco 89a396
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 89a396
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Pablo Greco 89a396
Date: Fri, 17 Sep 2021 12:07:26 +0100
Pablo Greco cd4fb3
Subject: [PATCH 10/19] iommu/dma: Update RMR mem attributes
Pablo Greco 89a396
Pablo Greco 89a396
Since we dont have enough information from the IORT spec,
Pablo Greco 89a396
make use of ACPI table and EFI memory map to set the RMR
Pablo Greco 89a396
reserved region prot value.
Pablo Greco 89a396
Pablo Greco 89a396
[Not tested]
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Pablo Greco 89a396
---
Pablo Greco 89a396
 drivers/acpi/arm64/iort.c | 24 +++++++++++++-----------
Pablo Greco 89a396
 drivers/iommu/dma-iommu.c |  1 +
Pablo Greco 89a396
 include/linux/acpi_iort.h |  8 ++++++++
Pablo Greco 89a396
 3 files changed, 22 insertions(+), 11 deletions(-)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
Pablo Greco 1fd891
index 66d200e577cb..c397c980a7f4 100644
Pablo Greco 89a396
--- a/drivers/acpi/arm64/iort.c
Pablo Greco 89a396
+++ b/drivers/acpi/arm64/iort.c
Pablo Greco 89a396
@@ -809,6 +809,16 @@ static struct acpi_iort_node *iort_get_msi_resv_iommu(struct device *dev)
Pablo Greco 89a396
 	return NULL;
Pablo Greco 89a396
 }
Pablo Greco 89a396
 
Pablo Greco 89a396
+void iort_iommu_rmr_update_mem_attr(struct device *dev,
Pablo Greco 89a396
+				    struct iommu_resv_region *rmr)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	if (device_get_dma_attr(dev) == DEV_DMA_COHERENT)
Pablo Greco 89a396
+		rmr->prot |= IOMMU_CACHE;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	if (efi_mem_type(rmr->start) == EFI_MEMORY_MAPPED_IO)
Pablo Greco 89a396
+		rmr->prot |= IOMMU_MMIO;
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
 /**
Pablo Greco 89a396
  * iort_iommu_get_rmrs() - Helper to retrieve RMR info associated with IOMMU
Pablo Greco 89a396
  * @iommu_fwnode: fwnode for the IOMMU
Pablo Greco 89a396
@@ -1079,6 +1089,9 @@ int iort_iommu_configure_id(struct device *dev, const u32 *input_id)
Pablo Greco 89a396
 { return -ENODEV; }
Pablo Greco 89a396
 int iort_iommu_get_rmrs(struct fwnode_handle *fwnode, struct list_head *head)
Pablo Greco 89a396
 { return -ENODEV; }
Pablo Greco 89a396
+void iort_iommu_rmr_update_mem_attr(struct device *dev,
Pablo Greco 89a396
+				    struct iommu_resv_region *rmr)
Pablo Greco 89a396
+{ }
Pablo Greco 89a396
 #endif
Pablo Greco 89a396
 
Pablo Greco 89a396
 static int nc_dma_get_range(struct device *dev, u64 *size)
Pablo Greco 1fd891
@@ -1690,19 +1703,8 @@ static void __init iort_node_get_rmr_info(struct acpi_iort_node *iort_node)
Pablo Greco 89a396
 		}
Pablo Greco 89a396
 		if (rmr->flags & IOMMU_RMR_REMAP_PERMITTED) {
Pablo Greco 89a396
 			type = IOMMU_RESV_DIRECT_RELAXABLE;
Pablo Greco 89a396
-			/*
Pablo Greco 89a396
-			 * Set IOMMU_CACHE as IOMMU_RESV_DIRECT_RELAXABLE is
Pablo Greco 89a396
-			 * normally used for allocated system memory that is
Pablo Greco 89a396
-			 * then used for device specific reserved regions.
Pablo Greco 89a396
-			 */
Pablo Greco 89a396
-			prot |= IOMMU_CACHE;
Pablo Greco 89a396
 		} else {
Pablo Greco 89a396
 			type = IOMMU_RESV_DIRECT;
Pablo Greco 89a396
-			/*
Pablo Greco 89a396
-			 * Set IOMMU_MMIO as IOMMU_RESV_DIRECT is normally used
Pablo Greco 89a396
-			 * for device memory like MSI doorbell.
Pablo Greco 89a396
-			 */
Pablo Greco 89a396
-			prot |= IOMMU_MMIO;
Pablo Greco 89a396
 		}
Pablo Greco 89a396
 
Pablo Greco 89a396
 		region = iommu_alloc_resv_region(addr, size, prot, type);
Pablo Greco 89a396
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
Pablo Greco 7163c5
index 0014a70597ef..2055151cfc3f 100644
Pablo Greco 89a396
--- a/drivers/iommu/dma-iommu.c
Pablo Greco 89a396
+++ b/drivers/iommu/dma-iommu.c
Pablo Greco 89a396
@@ -243,6 +243,7 @@ static void iommu_dma_get_rmr_resv_regions(struct device *dev,
Pablo Greco 89a396
 		if (!iommu_dma_dev_has_rmr(fwspec, rmr))
Pablo Greco 89a396
 			continue;
Pablo Greco 89a396
 
Pablo Greco 89a396
+		iort_iommu_rmr_update_mem_attr(dev, rmr);
Pablo Greco 89a396
 		/* Remove from iommu RMR list and add to dev resv_regions */
Pablo Greco 89a396
 		list_del_init(&rmr->list);
Pablo Greco 89a396
 		list_add_tail(&rmr->list, list);
Pablo Greco 89a396
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
Pablo Greco 89a396
index d8c030c103f5..f0a3882c26d4 100644
Pablo Greco 89a396
--- a/include/linux/acpi_iort.h
Pablo Greco 89a396
+++ b/include/linux/acpi_iort.h
Pablo Greco 89a396
@@ -10,6 +10,7 @@
Pablo Greco 89a396
 #include <linux/acpi.h>
Pablo Greco 89a396
 #include <linux/fwnode.h>
Pablo Greco 89a396
 #include <linux/irqdomain.h>
Pablo Greco 89a396
+#include <linux/iommu.h>
Pablo Greco 89a396
 
Pablo Greco 89a396
 #define IORT_IRQ_MASK(irq)		(irq & 0xffffffffULL)
Pablo Greco 89a396
 #define IORT_IRQ_TRIGGER_MASK(irq)	((irq >> 32) & 0xffffffffULL)
Pablo Greco 89a396
@@ -40,6 +41,8 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head);
Pablo Greco 89a396
 phys_addr_t acpi_iort_dma_get_max_cpu_address(void);
Pablo Greco 89a396
 int iort_iommu_get_rmrs(struct fwnode_handle *iommu_fwnode,
Pablo Greco 89a396
 			struct list_head *list);
Pablo Greco 89a396
+void iort_iommu_rmr_update_mem_attr(struct device *dev,
Pablo Greco 89a396
+				    struct iommu_resv_region *rmr);
Pablo Greco 89a396
 #else
Pablo Greco 89a396
 static inline void acpi_iort_init(void) { }
Pablo Greco 89a396
 static inline u32 iort_msi_map_id(struct device *dev, u32 id)
Pablo Greco 89a396
@@ -64,6 +67,11 @@ static inline
Pablo Greco 89a396
 int iort_iommu_get_rmrs(struct fwnode_handle *iommu_fwnode,
Pablo Greco 89a396
 			struct list_head *list)
Pablo Greco 89a396
 { return -ENODEV; }
Pablo Greco 89a396
+
Pablo Greco 89a396
+static inline
Pablo Greco 89a396
+void iort_iommu_rmr_update_mem_attr(struct device *dev,
Pablo Greco 89a396
+				    struct iommu_resv_region *rmr)
Pablo Greco 89a396
+{ }
Pablo Greco 89a396
 #endif
Pablo Greco 89a396
 
Pablo Greco 89a396
 #endif /* __ACPI_IORT_H__ */
Pablo Greco 89a396
-- 
Pablo Greco 89a396
2.18.4
Pablo Greco 89a396
Pablo Greco 89a396
Pablo Greco 89a396
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 89a396
From: Makarand Pawagi <makarand.pawagi@nxp.com>
Pablo Greco 89a396
Date: Tue, 21 Apr 2020 11:25:53 +0530
Pablo Greco cd4fb3
Subject: [PATCH 11/19] soc: fsl: enable acpi support for Guts driver
Pablo Greco 89a396
Pablo Greco 89a396
ACPI support is added in the Guts driver
Pablo Greco 89a396
This is in accordance with the DSDT table added for Guts
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Makarand Pawagi <makarand.pawagi@nxp.com>
Pablo Greco 89a396
---
Pablo Greco cd4fb3
 drivers/soc/fsl/guts.c | 27 +++++++++++++++++++++------
Pablo Greco cd4fb3
 1 file changed, 21 insertions(+), 6 deletions(-)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c
Pablo Greco 422940
index 0b2c7fdbaa5b..35b74bf4b65c 100644
Pablo Greco 89a396
--- a/drivers/soc/fsl/guts.c
Pablo Greco 89a396
+++ b/drivers/soc/fsl/guts.c
Pablo Greco 89a396
@@ -3,6 +3,7 @@
Pablo Greco 89a396
  * Freescale QorIQ Platforms GUTS Driver
Pablo Greco 89a396
  *
Pablo Greco 89a396
  * Copyright (C) 2016 Freescale Semiconductor, Inc.
Pablo Greco 89a396
+ * Copyright 2020 NXP
Pablo Greco 89a396
  */
Pablo Greco 89a396
 
Pablo Greco 89a396
 #include <linux/io.h>
Pablo Greco cd4fb3
@@ -149,7 +150,8 @@ static int fsl_guts_probe(struct platform_device *pdev)
Pablo Greco 89a396
 	if (!guts)
Pablo Greco 89a396
 		return -ENOMEM;
Pablo Greco 89a396
 
Pablo Greco 89a396
-	guts->little_endian = of_property_read_bool(np, "little-endian");
Pablo Greco 89a396
+	guts->little_endian = fwnode_property_read_bool(pdev->dev.fwnode,
Pablo Greco 89a396
+							"little-endian");
Pablo Greco 89a396
 
Pablo Greco 89a396
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Pablo Greco 89a396
 	guts->regs = devm_ioremap_resource(dev, res);
Pablo Greco cd4fb3
@@ -157,17 +159,23 @@ static int fsl_guts_probe(struct platform_device *pdev)
Pablo Greco 89a396
 		return PTR_ERR(guts->regs);
Pablo Greco 89a396
 
Pablo Greco 89a396
 	/* Register soc device */
Pablo Greco 89a396
-	root = of_find_node_by_path("/");
Pablo Greco 89a396
-	if (of_property_read_string(root, "model", &machine))
Pablo Greco 89a396
-		of_property_read_string_index(root, "compatible", 0, &machine);
Pablo Greco 89a396
+	if (dev_of_node(&pdev->dev)) {
Pablo Greco 89a396
+		root = of_find_node_by_path("/");
Pablo Greco 89a396
+		if (of_property_read_string(root, "model", &machine))
Pablo Greco 89a396
+			of_property_read_string_index(root,
Pablo Greco 89a396
+					"compatible", 0, &machine);
Pablo Greco 89a396
+		of_node_put(root);
Pablo Greco 89a396
+	} else {
Pablo Greco 89a396
+		fwnode_property_read_string(pdev->dev.fwnode,
Pablo Greco 89a396
+				"model", &machine);
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+
Pablo Greco cd4fb3
 	if (machine) {
Pablo Greco cd4fb3
 		soc_dev_attr.machine = devm_kstrdup(dev, machine, GFP_KERNEL);
Pablo Greco cd4fb3
 		if (!soc_dev_attr.machine) {
Pablo Greco cd4fb3
-			of_node_put(root);
Pablo Greco cd4fb3
 			return -ENOMEM;
Pablo Greco cd4fb3
 		}
Pablo Greco cd4fb3
 	}
Pablo Greco cd4fb3
-	of_node_put(root);
Pablo Greco 89a396
 
Pablo Greco cd4fb3
 	svr = fsl_guts_get_svr();
Pablo Greco cd4fb3
 	soc_die = fsl_soc_die_match(svr, fsl_soc_die);
Pablo Greco cd4fb3
@@ -238,10 +246,17 @@ static const struct of_device_id fsl_guts_of_match[] = {
Pablo Greco 89a396
 };
Pablo Greco 89a396
 MODULE_DEVICE_TABLE(of, fsl_guts_of_match);
Pablo Greco 89a396
 
Pablo Greco 89a396
+static const struct acpi_device_id fsl_guts_acpi_match[] = {
Pablo Greco 89a396
+	{"NXP0030", 0 },
Pablo Greco 89a396
+	{ }
Pablo Greco 89a396
+};
Pablo Greco 89a396
+MODULE_DEVICE_TABLE(acpi, fsl_guts_acpi_match);
Pablo Greco 89a396
+
Pablo Greco 89a396
 static struct platform_driver fsl_guts_driver = {
Pablo Greco 89a396
 	.driver = {
Pablo Greco 89a396
 		.name = "fsl-guts",
Pablo Greco 89a396
 		.of_match_table = fsl_guts_of_match,
Pablo Greco 89a396
+		.acpi_match_table = fsl_guts_acpi_match,
Pablo Greco 89a396
 	},
Pablo Greco 89a396
 	.probe = fsl_guts_probe,
Pablo Greco 89a396
 	.remove = fsl_guts_remove,
Pablo Greco 89a396
-- 
Pablo Greco 89a396
2.18.4
Pablo Greco 89a396
Pablo Greco 89a396
Pablo Greco 89a396
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 89a396
From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
Pablo Greco 89a396
Date: Wed, 27 May 2020 21:35:11 +0530
Pablo Greco cd4fb3
Subject: [PATCH 12/19] mmc: sdhci-of-esdhc: Add ACPI support
Pablo Greco 89a396
Pablo Greco 89a396
This patch is to add acpi support in esdhc controller driver
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
Pablo Greco 89a396
---
Pablo Greco 89a396
 drivers/mmc/host/sdhci-of-esdhc.c | 62 +++++++++++++++++++------------
Pablo Greco 89a396
 1 file changed, 39 insertions(+), 23 deletions(-)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
Pablo Greco 422940
index 04a37fd137ee..af25ec17801b 100644
Pablo Greco 89a396
--- a/drivers/mmc/host/sdhci-of-esdhc.c
Pablo Greco 89a396
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
Pablo Greco 89a396
@@ -10,6 +10,7 @@
Pablo Greco 89a396
  *	    Anton Vorontsov <avorontsov@ru.mvista.com>
Pablo Greco 89a396
  */
Pablo Greco 89a396
 
Pablo Greco 89a396
+#include <linux/acpi.h>
Pablo Greco 89a396
 #include <linux/err.h>
Pablo Greco 89a396
 #include <linux/io.h>
Pablo Greco 89a396
 #include <linux/of.h>
Pablo Greco 89a396
@@ -73,6 +74,14 @@ static const struct of_device_id sdhci_esdhc_of_match[] = {
Pablo Greco 89a396
 };
Pablo Greco 89a396
 MODULE_DEVICE_TABLE(of, sdhci_esdhc_of_match);
Pablo Greco 89a396
 
Pablo Greco 89a396
+#ifdef CONFIG_ACPI
Pablo Greco 89a396
+static const struct acpi_device_id sdhci_esdhc_ids[] = {
Pablo Greco 89a396
+	{"NXP0003" },
Pablo Greco 89a396
+	{ }
Pablo Greco 89a396
+};
Pablo Greco 89a396
+MODULE_DEVICE_TABLE(acpi, sdhci_esdhc_ids);
Pablo Greco 89a396
+#endif
Pablo Greco 89a396
+
Pablo Greco 89a396
 struct sdhci_esdhc {
Pablo Greco 89a396
 	u8 vendor_ver;
Pablo Greco 89a396
 	u8 spec_ver;
Pablo Greco 422940
@@ -1371,29 +1380,35 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
Pablo Greco 89a396
 		esdhc->clk_fixup = match->data;
Pablo Greco 89a396
 	np = pdev->dev.of_node;
Pablo Greco 89a396
 
Pablo Greco 89a396
-	if (of_device_is_compatible(np, "fsl,p2020-esdhc")) {
Pablo Greco 89a396
-		esdhc->quirk_delay_before_data_reset = true;
Pablo Greco 89a396
-		esdhc->quirk_trans_complete_erratum = true;
Pablo Greco 89a396
-	}
Pablo Greco 89a396
+	/* in case of device tree, get clock from framework */
Pablo Greco 89a396
+	if (np) {
Pablo Greco 89a396
+		if (of_device_is_compatible(np, "fsl,p2020-esdhc")) {
Pablo Greco 89a396
+			esdhc->quirk_delay_before_data_reset = true;
Pablo Greco 89a396
+			esdhc->quirk_trans_complete_erratum = true;
Pablo Greco 89a396
+		}
Pablo Greco 89a396
 
Pablo Greco 89a396
-	clk = of_clk_get(np, 0);
Pablo Greco 89a396
-	if (!IS_ERR(clk)) {
Pablo Greco 89a396
-		/*
Pablo Greco 89a396
-		 * esdhc->peripheral_clock would be assigned with a value
Pablo Greco 89a396
-		 * which is eSDHC base clock when use periperal clock.
Pablo Greco 89a396
-		 * For some platforms, the clock value got by common clk
Pablo Greco 89a396
-		 * API is peripheral clock while the eSDHC base clock is
Pablo Greco 89a396
-		 * 1/2 peripheral clock.
Pablo Greco 89a396
-		 */
Pablo Greco 89a396
-		if (of_device_is_compatible(np, "fsl,ls1046a-esdhc") ||
Pablo Greco 89a396
-		    of_device_is_compatible(np, "fsl,ls1028a-esdhc") ||
Pablo Greco 89a396
-		    of_device_is_compatible(np, "fsl,ls1088a-esdhc"))
Pablo Greco 89a396
-			esdhc->peripheral_clock = clk_get_rate(clk) / 2;
Pablo Greco 89a396
-		else
Pablo Greco 89a396
-			esdhc->peripheral_clock = clk_get_rate(clk);
Pablo Greco 89a396
-
Pablo Greco 89a396
-		clk_put(clk);
Pablo Greco 89a396
-	}
Pablo Greco 89a396
+		clk = of_clk_get(np, 0);
Pablo Greco 89a396
+		if (!IS_ERR(clk)) {
Pablo Greco 89a396
+			/*
Pablo Greco 89a396
+			 * esdhc->peripheral_clock would be assigned with a value
Pablo Greco 89a396
+			 * which is eSDHC base clock when use periperal clock.
Pablo Greco 89a396
+			 * For some platforms, the clock value got by common clk
Pablo Greco 89a396
+			 * API is peripheral clock while the eSDHC base clock is
Pablo Greco 89a396
+			 * 1/2 peripheral clock.
Pablo Greco 89a396
+			 */
Pablo Greco 89a396
+			if (of_device_is_compatible(np, "fsl,ls1046a-esdhc") ||
Pablo Greco 89a396
+			    of_device_is_compatible(np, "fsl,ls1028a-esdhc") ||
Pablo Greco 89a396
+			    of_device_is_compatible(np, "fsl,ls1088a-esdhc"))
Pablo Greco 89a396
+				esdhc->peripheral_clock = clk_get_rate(clk) / 2;
Pablo Greco 89a396
+			else
Pablo Greco 89a396
+				esdhc->peripheral_clock = clk_get_rate(clk);
Pablo Greco 89a396
+
Pablo Greco 89a396
+			clk_put(clk);
Pablo Greco 89a396
+		}
Pablo Greco 89a396
+	} else {
Pablo Greco 89a396
+		device_property_read_u32(&pdev->dev, "clock-frequency",
Pablo Greco 89a396
+					 &esdhc->peripheral_clock);
Pablo Greco 89a396
+        }
Pablo Greco 89a396
 
Pablo Greco 89a396
 	esdhc_clock_enable(host, false);
Pablo Greco 89a396
 	val = sdhci_readl(host, ESDHC_DMA_SYSCTL);
Pablo Greco 422940
@@ -1426,7 +1441,7 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
Pablo Greco 89a396
 
Pablo Greco 89a396
 	np = pdev->dev.of_node;
Pablo Greco 89a396
 
Pablo Greco 89a396
-	if (of_property_read_bool(np, "little-endian"))
Pablo Greco 89a396
+	if (device_property_read_bool(&pdev->dev, "little-endian"))
Pablo Greco 89a396
 		host = sdhci_pltfm_init(pdev, &sdhci_esdhc_le_pdata,
Pablo Greco 89a396
 					sizeof(struct sdhci_esdhc));
Pablo Greco 89a396
 	else
Pablo Greco 422940
@@ -1511,6 +1526,7 @@ static struct platform_driver sdhci_esdhc_driver = {
Pablo Greco 89a396
 		.name = "sdhci-esdhc",
Pablo Greco 89a396
 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
Pablo Greco 89a396
 		.of_match_table = sdhci_esdhc_of_match,
Pablo Greco 89a396
+		.acpi_match_table = sdhci_esdhc_ids,
Pablo Greco 89a396
 		.pm = &esdhc_of_dev_pm_ops,
Pablo Greco 89a396
 	},
Pablo Greco 89a396
 	.probe = sdhci_esdhc_probe,
Pablo Greco 89a396
-- 
Pablo Greco 89a396
2.18.4
Pablo Greco 89a396
Pablo Greco 89a396
Pablo Greco 89a396
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 89a396
From: Meharbaan <meharbaan.ali@puresoftware.com>
Pablo Greco 89a396
Date: Tue, 28 Jul 2020 17:41:31 +0530
Pablo Greco cd4fb3
Subject: [PATCH 13/19] drivers/mmc/host/sdhci-of-esdhc : Fix DMA coherent
Pablo Greco 89a396
 check in ACPI mode.
Pablo Greco 89a396
Pablo Greco 89a396
DMA-coherent check to set ESDHC_DMA_SNOOP mask was bypassed
Pablo Greco 89a396
when booted in ACPI mode. Now it also checks the acpi device and
Pablo Greco 89a396
its parents for _CCA property in the device, and sets the flag
Pablo Greco 89a396
accordingly.
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Meharbaan <meharbaan.ali@puresoftware.com>
Pablo Greco 89a396
---
Pablo Greco 89a396
 drivers/base/property.c           | 38 +++++++++++++++++++++++++++++++
Pablo Greco 89a396
 drivers/mmc/host/sdhci-of-esdhc.c |  7 ++++--
Pablo Greco 89a396
 include/linux/property.h          |  2 ++
Pablo Greco 89a396
 3 files changed, 45 insertions(+), 2 deletions(-)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/base/property.c b/drivers/base/property.c
Pablo Greco 7163c5
index 735a23db1b5e..1125b79a9ca6 100644
Pablo Greco 89a396
--- a/drivers/base/property.c
Pablo Greco 89a396
+++ b/drivers/base/property.c
Pablo Greco 89a396
@@ -17,6 +17,7 @@
Pablo Greco 89a396
 #include <linux/property.h>
Pablo Greco 89a396
 #include <linux/etherdevice.h>
Pablo Greco 89a396
 #include <linux/phy.h>
Pablo Greco 89a396
+#include <linux/platform_device.h>
Pablo Greco 89a396
 
Pablo Greco 89a396
 struct fwnode_handle *dev_fwnode(struct device *dev)
Pablo Greco 89a396
 {
Pablo Greco 7163c5
@@ -915,6 +916,43 @@ enum dev_dma_attr device_get_dma_attr(struct device *dev)
Pablo Greco 89a396
 }
Pablo Greco 89a396
 EXPORT_SYMBOL_GPL(device_get_dma_attr);
Pablo Greco 89a396
 
Pablo Greco 89a396
+/**
Pablo Greco 89a396
+ * device_match_fw_node - Check if the device is the parent node.
Pablo Greco 89a396
+ * @dev:		Pointer to the device.
Pablo Greco 89a396
+ * @parent_fwnode	Pointer to the parent's firmware node.
Pablo Greco 89a396
+ *
Pablo Greco 89a396
+ * The function returns true if the device has no parent.
Pablo Greco 89a396
+ *
Pablo Greco 89a396
+ */
Pablo Greco 89a396
+static int device_match_fw_node(struct device *dev, const void *parent_fwnode)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	return dev->fwnode == parent_fwnode;
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
+/**
Pablo Greco 89a396
+ * dev_dma_is_coherent - Check if the device or any of its parents has
Pablo Greco 89a396
+ * dma support enabled.
Pablo Greco 89a396
+ * @dev:     Pointer to the device.
Pablo Greco 89a396
+ *
Pablo Greco 89a396
+ * The function gets the device pointer and check for device_dma_supported()
Pablo Greco 89a396
+ * on the device pointer passed and then recursively on its parent nodes.
Pablo Greco 89a396
+ */
Pablo Greco 89a396
+
Pablo Greco 89a396
+bool dev_dma_is_coherent(struct device *dev)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	struct fwnode_handle *parent_fwnode;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	while (dev) {
Pablo Greco 89a396
+		if (device_dma_supported(dev))
Pablo Greco 89a396
+			return true;
Pablo Greco 89a396
+		parent_fwnode = fwnode_get_next_parent(dev->fwnode);
Pablo Greco 89a396
+		dev = bus_find_device(&platform_bus_type, NULL,	parent_fwnode,
Pablo Greco 89a396
+				      device_match_fw_node);
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+	return false;
Pablo Greco 89a396
+}
Pablo Greco 89a396
+EXPORT_SYMBOL_GPL(dev_dma_is_coherent);
Pablo Greco 89a396
+
Pablo Greco 89a396
 /**
Pablo Greco 89a396
  * fwnode_get_phy_mode - Get phy mode for given firmware node
Pablo Greco 89a396
  * @fwnode:	Pointer to the given node
Pablo Greco 89a396
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
Pablo Greco 422940
index af25ec17801b..94ec80e8f9a1 100644
Pablo Greco 89a396
--- a/drivers/mmc/host/sdhci-of-esdhc.c
Pablo Greco 89a396
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
Pablo Greco 1fd891
@@ -545,8 +545,11 @@ static int esdhc_of_enable_dma(struct sdhci_host *host)
Pablo Greco 1fd891
 	}
Pablo Greco 89a396
 
Pablo Greco 89a396
 	value = sdhci_readl(host, ESDHC_DMA_SYSCTL);
Pablo Greco 89a396
-
Pablo Greco 89a396
-	if (of_dma_is_coherent(dev->of_node))
Pablo Greco 89a396
+	/*
Pablo Greco 89a396
+	 * of_dma_is_coherent() returns false in case of acpi hence
Pablo Greco 89a396
+	 * dev_dma_is_coherent() is used along with it.
Pablo Greco 89a396
+	 */
Pablo Greco 89a396
+	if (of_dma_is_coherent(dev->of_node) ||  dev_dma_is_coherent(dev))
Pablo Greco 89a396
 		value |= ESDHC_DMA_SNOOP;
Pablo Greco 89a396
 	else
Pablo Greco 89a396
 		value &= ~ESDHC_DMA_SNOOP;
Pablo Greco 89a396
diff --git a/include/linux/property.h b/include/linux/property.h
Pablo Greco 89a396
index 357513a977e5..a9009883ab9e 100644
Pablo Greco 89a396
--- a/include/linux/property.h
Pablo Greco 89a396
+++ b/include/linux/property.h
Pablo Greco 89a396
@@ -385,6 +385,8 @@ bool device_dma_supported(struct device *dev);
Pablo Greco 89a396
 
Pablo Greco 89a396
 enum dev_dma_attr device_get_dma_attr(struct device *dev);
Pablo Greco 89a396
 
Pablo Greco 89a396
+bool dev_dma_is_coherent(struct device *dev);
Pablo Greco 89a396
+
Pablo Greco 89a396
 const void *device_get_match_data(struct device *dev);
Pablo Greco 89a396
 
Pablo Greco 89a396
 int device_get_phy_mode(struct device *dev);
Pablo Greco 89a396
-- 
Pablo Greco 89a396
2.18.4
Pablo Greco 89a396
Pablo Greco 89a396
Pablo Greco 89a396
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 89a396
From: Jon Nettleton <jon@solid-run.com>
Pablo Greco 89a396
Date: Fri, 2 Jul 2021 07:28:21 -0400
Pablo Greco cd4fb3
Subject: [PATCH 14/19] ACPI: APD: Allow apd device to override fixed_clk_rate
Pablo Greco 89a396
Pablo Greco 89a396
Currently by default the apd drivers are always using the
Pablo Greco 89a396
fixed_clk_rate assigned in the matched acpi_device_desc.
Pablo Greco 89a396
This causes an issue on the LX2160a platform because the
Pablo Greco 89a396
NXP0001 settings do not match the platform and instead the
Pablo Greco 89a396
I2C bus is only running at 24000kHZ rather than the expect
Pablo Greco 89a396
100000. Instead of patching the source with more static numbers
Pablo Greco 89a396
that may or may not change instead add a check for the device
Pablo Greco 89a396
property "fixed-clock-rate" that can be added to the ACPI
Pablo Greco 89a396
tables to instruct the driver what rate to use.
Pablo Greco 89a396
Pablo Greco 89a396
I have chosen fixed-clock-rate because clock-frequency is already
Pablo Greco 89a396
used by I2C devices in acpi and device-tree to specify by bus
Pablo Greco 89a396
speed, and fixed-clock-rate matches the fixed_clk_rate used by the
Pablo Greco 89a396
apd_device_desc.  If this device property is not set then the
Pablo Greco 89a396
default static values are used so this should cause no regressions.
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Jon Nettleton <jon@solid-run.com>
Pablo Greco 89a396
---
Pablo Greco 89a396
 drivers/acpi/acpi_apd.c | 13 +++++++++++--
Pablo Greco 89a396
 1 file changed, 11 insertions(+), 2 deletions(-)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
Pablo Greco 89a396
index 6e02448d15d9..f79757c34a77 100644
Pablo Greco 89a396
--- a/drivers/acpi/acpi_apd.c
Pablo Greco 89a396
+++ b/drivers/acpi/acpi_apd.c
Pablo Greco 89a396
@@ -46,12 +46,21 @@ struct apd_private_data {
Pablo Greco 89a396
 static int acpi_apd_setup(struct apd_private_data *pdata)
Pablo Greco 89a396
 {
Pablo Greco 89a396
 	const struct apd_device_desc *dev_desc = pdata->dev_desc;
Pablo Greco 89a396
+	struct acpi_device *adev = pdata->adev;
Pablo Greco 89a396
+	const union acpi_object *obj;
Pablo Greco 89a396
+	unsigned int fixed_clk_rate;
Pablo Greco 89a396
 	struct clk *clk;
Pablo Greco 89a396
 
Pablo Greco 89a396
-	if (dev_desc->fixed_clk_rate) {
Pablo Greco 89a396
+	if (!acpi_dev_get_property(adev, "uefi-clock-frequency", ACPI_TYPE_INTEGER, &obj)) {
Pablo Greco 89a396
+		fixed_clk_rate = obj->integer.value;
Pablo Greco 89a396
+	} else if (dev_desc->fixed_clk_rate) {
Pablo Greco 89a396
+		fixed_clk_rate = dev_desc->fixed_clk_rate;
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+
Pablo Greco 89a396
+	if (fixed_clk_rate) {
Pablo Greco 89a396
 		clk = clk_register_fixed_rate(&pdata->adev->dev,
Pablo Greco 89a396
 					dev_name(&pdata->adev->dev),
Pablo Greco 89a396
-					NULL, 0, dev_desc->fixed_clk_rate);
Pablo Greco 89a396
+					NULL, 0, fixed_clk_rate);
Pablo Greco 89a396
 		clk_register_clkdev(clk, NULL, dev_name(&pdata->adev->dev));
Pablo Greco 89a396
 		pdata->clk = clk;
Pablo Greco 89a396
 	}
Pablo Greco 89a396
-- 
Pablo Greco 89a396
2.18.4
Pablo Greco 89a396
Pablo Greco 89a396
Pablo Greco 89a396
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 89a396
From: Russell King <rmk+kernel@armlinux.org.uk>
Pablo Greco 89a396
Date: Tue, 24 Dec 2019 14:46:48 +0000
Pablo Greco cd4fb3
Subject: [PATCH 15/19] bus: fsl-mc: fix dprc object reading race
Pablo Greco 89a396
Pablo Greco 89a396
When modifying the objects attached to a DPRC, we may end up reading
Pablo Greco 89a396
the list of objects from the firmware while another thread is changing
Pablo Greco 89a396
changing the list. Since we read the objects via:
Pablo Greco 89a396
Pablo Greco 89a396
- Read the number of DPRC objects
Pablo Greco 89a396
- Iterate over this number of objects retrieving their details
Pablo Greco 89a396
Pablo Greco 89a396
and objects can be added in the middle of the list, this causes the
Pablo Greco 89a396
last few objects to unexpectedly disappear. The side effect of this
Pablo Greco 89a396
is if network interfaces are added after boot, they come and go. This
Pablo Greco 89a396
can result in already configured interfaces unexpectedly disappearing.
Pablo Greco 89a396
Pablo Greco 89a396
This has been easy to provoke with the restool interface added, and a
Pablo Greco 89a396
script which adds network interfaces one after each other; the kernel
Pablo Greco 89a396
rescanning runs asynchronously to restool.
Pablo Greco 89a396
Pablo Greco 89a396
NXP's approach to fixing this was to introduce a sysfs "attribute" in
Pablo Greco 89a396
their vendor tree, /sys/bus/fsl-mc/rescan, which userspace poked at to
Pablo Greco 89a396
request the kernel to rescan the DPRC object tree each time the
Pablo Greco 89a396
"restool" command completed (whether or not the tool changed anything.)
Pablo Greco 89a396
This has the effect of making the kernel's rescan synchronous with a
Pablo Greco 89a396
scripted restool, but still fails if we have multiple restools running
Pablo Greco 89a396
concurrently.
Pablo Greco 89a396
Pablo Greco 89a396
This patch takes a different approach:
Pablo Greco 89a396
- Read the number of DPRC objects
Pablo Greco 89a396
- Iterate over this number of objects retrieving their details
Pablo Greco 89a396
- Re-read the number of DPRC objects
Pablo Greco 89a396
- If the number of DPRC objects has changed while reading, repeat.
Pablo Greco 89a396
Pablo Greco 89a396
This solves the issue where network interfaces unexpectedly disappear
Pablo Greco 89a396
while adding others via ls-addni, because they've fallen off the end
Pablo Greco 89a396
of the object list.
Pablo Greco 89a396
Pablo Greco 89a396
This does *not* solve the issue that if an object is deleted while
Pablo Greco 89a396
another is added while we are reading the objects - that requires
Pablo Greco 89a396
firmware modification, or a more elaborate solution on the Linux side
Pablo Greco 89a396
(e.g., CRCing the object details and reading all objects at least
Pablo Greco 89a396
twice to check the CRC is stable.)
Pablo Greco 89a396
Pablo Greco 89a396
However, without firmware modification, this is probably the best way
Pablo Greco 89a396
to ensure that we read all the objects.
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Pablo Greco 89a396
---
Pablo Greco 89a396
 drivers/bus/fsl-mc/dprc-driver.c | 32 +++++++++++++++++++++++++++++---
Pablo Greco 89a396
 1 file changed, 29 insertions(+), 3 deletions(-)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/bus/fsl-mc/dprc-driver.c b/drivers/bus/fsl-mc/dprc-driver.c
Pablo Greco 89a396
index 315e830b6ecd..2268869bf6ab 100644
Pablo Greco 89a396
--- a/drivers/bus/fsl-mc/dprc-driver.c
Pablo Greco 89a396
+++ b/drivers/bus/fsl-mc/dprc-driver.c
Pablo Greco 89a396
@@ -240,11 +240,11 @@ static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev,
Pablo Greco 89a396
 int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
Pablo Greco 89a396
 		      bool alloc_interrupts)
Pablo Greco 89a396
 {
Pablo Greco 89a396
-	int num_child_objects;
Pablo Greco 89a396
+	int num_child_objects, num_child_objects2;
Pablo Greco 89a396
 	int dprc_get_obj_failures;
Pablo Greco 89a396
 	int error;
Pablo Greco 89a396
-	unsigned int irq_count = mc_bus_dev->obj_desc.irq_count;
Pablo Greco 89a396
-	struct fsl_mc_obj_desc *child_obj_desc_array = NULL;
Pablo Greco 89a396
+	unsigned int irq_count;
Pablo Greco 89a396
+	struct fsl_mc_obj_desc *child_obj_desc_array;
Pablo Greco 89a396
 	struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
Pablo Greco 89a396
 
Pablo Greco 89a396
 	error = dprc_get_obj_count(mc_bus_dev->mc_io,
Pablo Greco 89a396
@@ -257,6 +257,9 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
Pablo Greco 89a396
 		return error;
Pablo Greco 89a396
 	}
Pablo Greco 89a396
 
Pablo Greco 89a396
+retry:
Pablo Greco 89a396
+	irq_count = mc_bus_dev->obj_desc.irq_count;
Pablo Greco 89a396
+	child_obj_desc_array = NULL;
Pablo Greco 89a396
 	if (num_child_objects != 0) {
Pablo Greco 89a396
 		int i;
Pablo Greco 89a396
 
Pablo Greco 89a396
@@ -315,6 +318,29 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
Pablo Greco 89a396
 		}
Pablo Greco 89a396
 	}
Pablo Greco 89a396
 
Pablo Greco 89a396
+	error = dprc_get_obj_count(mc_bus_dev->mc_io,
Pablo Greco 89a396
+				   0,
Pablo Greco 89a396
+				   mc_bus_dev->mc_handle,
Pablo Greco 89a396
+				   &num_child_objects2);
Pablo Greco 89a396
+	if (error < 0) {
Pablo Greco 89a396
+		if (child_obj_desc_array)
Pablo Greco 89a396
+			devm_kfree(&mc_bus_dev->dev, child_obj_desc_array);
Pablo Greco 89a396
+		dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n",
Pablo Greco 89a396
+			error);
Pablo Greco 89a396
+		return error;
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+
Pablo Greco 89a396
+	if (num_child_objects != num_child_objects2) {
Pablo Greco 89a396
+		/*
Pablo Greco 89a396
+		 * Something changed while reading the number of objects.
Pablo Greco 89a396
+		 * Retry reading the child object list.
Pablo Greco 89a396
+		 */
Pablo Greco 89a396
+		if (child_obj_desc_array)
Pablo Greco 89a396
+			devm_kfree(&mc_bus_dev->dev, child_obj_desc_array);
Pablo Greco 89a396
+		num_child_objects = num_child_objects2;
Pablo Greco 89a396
+		goto retry;
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+
Pablo Greco 89a396
 	/*
Pablo Greco 89a396
 	 * Allocate IRQ's before binding the scanned devices with their
Pablo Greco 89a396
 	 * respective drivers.
Pablo Greco 89a396
-- 
Pablo Greco 89a396
2.18.4
Pablo Greco 89a396
Pablo Greco 89a396
Pablo Greco 89a396
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 89a396
From: Russell King <rmk+kernel@armlinux.org.uk>
Pablo Greco 89a396
Date: Fri, 24 Jan 2020 17:59:49 +0000
Pablo Greco cd4fb3
Subject: [PATCH 16/19] iommu: silence iommu group prints
Pablo Greco 89a396
Pablo Greco 89a396
On the LX2160A, there are lots (about 160) of IOMMU messages produced
Pablo Greco 89a396
during boot; this is excessive.  Reduce the severity of these messages
Pablo Greco 89a396
to debug level.
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Pablo Greco 89a396
---
Pablo Greco 89a396
 drivers/iommu/iommu.c | 4 ++--
Pablo Greco 89a396
 1 file changed, 2 insertions(+), 2 deletions(-)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
Pablo Greco 1fd891
index 7f409e9eea4b..2dc9592ff309 100644
Pablo Greco 89a396
--- a/drivers/iommu/iommu.c
Pablo Greco 89a396
+++ b/drivers/iommu/iommu.c
Pablo Greco 1fd891
@@ -905,7 +905,7 @@ int iommu_group_add_device(struct iommu_group *group, struct device *dev)
Pablo Greco 89a396
 
Pablo Greco 89a396
 	trace_add_device_to_group(group->id, dev);
Pablo Greco 89a396
 
Pablo Greco 89a396
-	dev_info(dev, "Adding to iommu group %d\n", group->id);
Pablo Greco 89a396
+	dev_dbg(dev, "Adding to iommu group %d\n", group->id);
Pablo Greco 89a396
 
Pablo Greco 89a396
 	return 0;
Pablo Greco 89a396
 
Pablo Greco 1fd891
@@ -942,7 +942,7 @@ void iommu_group_remove_device(struct device *dev)
Pablo Greco 89a396
 	if (!group)
Pablo Greco 89a396
 		return;
Pablo Greco 89a396
 
Pablo Greco 89a396
-	dev_info(dev, "Removing from iommu group %d\n", group->id);
Pablo Greco 89a396
+	dev_dbg(dev, "Removing from iommu group %d\n", group->id);
Pablo Greco 89a396
 
Pablo Greco 89a396
 	/* Pre-notify listeners that a device is being removed. */
Pablo Greco 89a396
 	blocking_notifier_call_chain(&group->notifier,
Pablo Greco 89a396
-- 
Pablo Greco 89a396
2.18.4
Pablo Greco 89a396
Pablo Greco 89a396
Pablo Greco 89a396
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 89a396
From: Diana Craciun <diana.craciun@oss.nxp.com>
Pablo Greco 89a396
Date: Wed, 22 Sep 2021 14:05:29 +0300
Pablo Greco cd4fb3
Subject: [PATCH 17/19] bus/fsl-mc: Add generic implementation for
Pablo Greco 89a396
 open/reset/close commands
Pablo Greco 89a396
Pablo Greco 89a396
The open/reset/close commands format is similar for all objects.
Pablo Greco 89a396
Currently there are multiple implementations for these commands
Pablo Greco 89a396
scattered through various drivers. The code is cavsi-identical.
Pablo Greco 89a396
Create a generic implementation for the open/reset/close commands.
Pablo Greco 89a396
One of the consumer will be the VFIO driver which needs to
Pablo Greco 89a396
be able to reset a device.
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Diana Craciun <diana.craciun@oss.nxp.com>
Pablo Greco 89a396
Reviewed-by: Laurentiu Tudor <laurentiu.tudor@nxp.com>
Pablo Greco 89a396
Link: https://lore.kernel.org/r/20210922110530.24736-1-diana.craciun@oss.nxp.com
Pablo Greco 89a396
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Pablo Greco 89a396
---
Pablo Greco 89a396
 drivers/bus/fsl-mc/Makefile         |   3 +-
Pablo Greco 89a396
 drivers/bus/fsl-mc/fsl-mc-private.h |  39 +++++++++--
Pablo Greco 89a396
 drivers/bus/fsl-mc/obj-api.c        | 103 ++++++++++++++++++++++++++++
Pablo Greco 89a396
 include/linux/fsl/mc.h              |  14 ++++
Pablo Greco 89a396
 4 files changed, 154 insertions(+), 5 deletions(-)
Pablo Greco 89a396
 create mode 100644 drivers/bus/fsl-mc/obj-api.c
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/bus/fsl-mc/Makefile b/drivers/bus/fsl-mc/Makefile
Pablo Greco 89a396
index 4ae292a30e53..892946245527 100644
Pablo Greco 89a396
--- a/drivers/bus/fsl-mc/Makefile
Pablo Greco 89a396
+++ b/drivers/bus/fsl-mc/Makefile
Pablo Greco 89a396
@@ -15,7 +15,8 @@ mc-bus-driver-objs := fsl-mc-bus.o \
Pablo Greco 89a396
 		      dprc-driver.o \
Pablo Greco 89a396
 		      fsl-mc-allocator.o \
Pablo Greco 89a396
 		      fsl-mc-msi.o \
Pablo Greco 89a396
-		      dpmcp.o
Pablo Greco 89a396
+		      dpmcp.o \
Pablo Greco 89a396
+		      obj-api.o
Pablo Greco 89a396
 
Pablo Greco 89a396
 # MC userspace support
Pablo Greco 89a396
 obj-$(CONFIG_FSL_MC_UAPI_SUPPORT) += fsl-mc-uapi.o
Pablo Greco 89a396
diff --git a/drivers/bus/fsl-mc/fsl-mc-private.h b/drivers/bus/fsl-mc/fsl-mc-private.h
Pablo Greco 89a396
index 1958fa065360..b3520ea1b9f4 100644
Pablo Greco 89a396
--- a/drivers/bus/fsl-mc/fsl-mc-private.h
Pablo Greco 89a396
+++ b/drivers/bus/fsl-mc/fsl-mc-private.h
Pablo Greco 89a396
@@ -48,7 +48,6 @@ struct dpmng_rsp_get_version {
Pablo Greco 89a396
 
Pablo Greco 89a396
 /* DPMCP command IDs */
Pablo Greco 89a396
 #define DPMCP_CMDID_CLOSE		DPMCP_CMD(0x800)
Pablo Greco 89a396
-#define DPMCP_CMDID_OPEN		DPMCP_CMD(0x80b)
Pablo Greco 89a396
 #define DPMCP_CMDID_RESET		DPMCP_CMD(0x005)
Pablo Greco 89a396
 
Pablo Greco 89a396
 struct dpmcp_cmd_open {
Pablo Greco 89a396
@@ -91,7 +90,6 @@ int dpmcp_reset(struct fsl_mc_io *mc_io,
Pablo Greco 89a396
 
Pablo Greco 89a396
 /* DPRC command IDs */
Pablo Greco 89a396
 #define DPRC_CMDID_CLOSE                        DPRC_CMD(0x800)
Pablo Greco 89a396
-#define DPRC_CMDID_OPEN                         DPRC_CMD(0x805)
Pablo Greco 89a396
 #define DPRC_CMDID_GET_API_VERSION              DPRC_CMD(0xa05)
Pablo Greco 89a396
 
Pablo Greco 89a396
 #define DPRC_CMDID_GET_ATTR                     DPRC_CMD(0x004)
Pablo Greco 89a396
@@ -453,7 +451,6 @@ int dprc_get_connection(struct fsl_mc_io *mc_io,
Pablo Greco 89a396
 
Pablo Greco 89a396
 /* Command IDs */
Pablo Greco 89a396
 #define DPBP_CMDID_CLOSE		DPBP_CMD(0x800)
Pablo Greco 89a396
-#define DPBP_CMDID_OPEN			DPBP_CMD(0x804)
Pablo Greco 89a396
 
Pablo Greco 89a396
 #define DPBP_CMDID_ENABLE		DPBP_CMD(0x002)
Pablo Greco 89a396
 #define DPBP_CMDID_DISABLE		DPBP_CMD(0x003)
Pablo Greco 89a396
@@ -492,7 +489,6 @@ struct dpbp_rsp_get_attributes {
Pablo Greco 89a396
 
Pablo Greco 89a396
 /* Command IDs */
Pablo Greco 89a396
 #define DPCON_CMDID_CLOSE			DPCON_CMD(0x800)
Pablo Greco 89a396
-#define DPCON_CMDID_OPEN			DPCON_CMD(0x808)
Pablo Greco 89a396
 
Pablo Greco 89a396
 #define DPCON_CMDID_ENABLE			DPCON_CMD(0x002)
Pablo Greco 89a396
 #define DPCON_CMDID_DISABLE			DPCON_CMD(0x003)
Pablo Greco 89a396
@@ -524,6 +520,41 @@ struct dpcon_cmd_set_notification {
Pablo Greco 89a396
 	__le64 user_ctx;
Pablo Greco 89a396
 };
Pablo Greco 89a396
 
Pablo Greco 89a396
+/*
Pablo Greco 89a396
+ * Generic FSL MC API
Pablo Greco 89a396
+ */
Pablo Greco 89a396
+
Pablo Greco 89a396
+/* generic command versioning */
Pablo Greco 89a396
+#define OBJ_CMD_BASE_VERSION		1
Pablo Greco 89a396
+#define OBJ_CMD_ID_OFFSET		4
Pablo Greco 89a396
+
Pablo Greco 89a396
+#define OBJ_CMD(id)	(((id) << OBJ_CMD_ID_OFFSET) | OBJ_CMD_BASE_VERSION)
Pablo Greco 89a396
+
Pablo Greco 89a396
+/* open command codes */
Pablo Greco 89a396
+#define DPRTC_CMDID_OPEN		OBJ_CMD(0x810)
Pablo Greco 89a396
+#define DPNI_CMDID_OPEN		OBJ_CMD(0x801)
Pablo Greco 89a396
+#define DPSW_CMDID_OPEN		OBJ_CMD(0x802)
Pablo Greco 89a396
+#define DPIO_CMDID_OPEN		OBJ_CMD(0x803)
Pablo Greco 89a396
+#define DPBP_CMDID_OPEN		OBJ_CMD(0x804)
Pablo Greco 89a396
+#define DPRC_CMDID_OPEN		OBJ_CMD(0x805)
Pablo Greco 89a396
+#define DPDMUX_CMDID_OPEN		OBJ_CMD(0x806)
Pablo Greco 89a396
+#define DPCI_CMDID_OPEN		OBJ_CMD(0x807)
Pablo Greco 89a396
+#define DPCON_CMDID_OPEN		OBJ_CMD(0x808)
Pablo Greco 89a396
+#define DPSECI_CMDID_OPEN		OBJ_CMD(0x809)
Pablo Greco 89a396
+#define DPAIOP_CMDID_OPEN		OBJ_CMD(0x80a)
Pablo Greco 89a396
+#define DPMCP_CMDID_OPEN		OBJ_CMD(0x80b)
Pablo Greco 89a396
+#define DPMAC_CMDID_OPEN		OBJ_CMD(0x80c)
Pablo Greco 89a396
+#define DPDCEI_CMDID_OPEN		OBJ_CMD(0x80d)
Pablo Greco 89a396
+#define DPDMAI_CMDID_OPEN		OBJ_CMD(0x80e)
Pablo Greco 89a396
+#define DPDBG_CMDID_OPEN		OBJ_CMD(0x80f)
Pablo Greco 89a396
+
Pablo Greco 89a396
+/* Generic object command IDs */
Pablo Greco 89a396
+#define OBJ_CMDID_CLOSE		OBJ_CMD(0x800)
Pablo Greco 89a396
+#define OBJ_CMDID_RESET		OBJ_CMD(0x005)
Pablo Greco 89a396
+
Pablo Greco 89a396
+struct fsl_mc_obj_cmd_open {
Pablo Greco 89a396
+	__le32 obj_id;
Pablo Greco 89a396
+};
Pablo Greco 89a396
 
Pablo Greco 89a396
 /**
Pablo Greco 89a396
  * struct fsl_mc_resource_pool - Pool of MC resources of a given
Pablo Greco 89a396
diff --git a/drivers/bus/fsl-mc/obj-api.c b/drivers/bus/fsl-mc/obj-api.c
Pablo Greco 89a396
new file mode 100644
Pablo Greco 89a396
index 000000000000..06c1dd84e38d
Pablo Greco 89a396
--- /dev/null
Pablo Greco 89a396
+++ b/drivers/bus/fsl-mc/obj-api.c
Pablo Greco 89a396
@@ -0,0 +1,103 @@
Pablo Greco 89a396
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
Pablo Greco 89a396
+/*
Pablo Greco 89a396
+ * Copyright 2021 NXP
Pablo Greco 89a396
+ *
Pablo Greco 89a396
+ */
Pablo Greco 89a396
+#include <linux/kernel.h>
Pablo Greco 89a396
+#include <linux/fsl/mc.h>
Pablo Greco 89a396
+
Pablo Greco 89a396
+#include "fsl-mc-private.h"
Pablo Greco 89a396
+
Pablo Greco 89a396
+static int fsl_mc_get_open_cmd_id(const char *type)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	static const struct {
Pablo Greco 89a396
+		int cmd_id;
Pablo Greco 89a396
+		const char *type;
Pablo Greco 89a396
+	} dev_ids[] = {
Pablo Greco 89a396
+		{ DPRTC_CMDID_OPEN, "dprtc" },
Pablo Greco 89a396
+		{ DPRC_CMDID_OPEN, "dprc" },
Pablo Greco 89a396
+		{ DPNI_CMDID_OPEN, "dpni" },
Pablo Greco 89a396
+		{ DPIO_CMDID_OPEN, "dpio" },
Pablo Greco 89a396
+		{ DPSW_CMDID_OPEN, "dpsw" },
Pablo Greco 89a396
+		{ DPBP_CMDID_OPEN, "dpbp" },
Pablo Greco 89a396
+		{ DPCON_CMDID_OPEN, "dpcon" },
Pablo Greco 89a396
+		{ DPMCP_CMDID_OPEN, "dpmcp" },
Pablo Greco 89a396
+		{ DPMAC_CMDID_OPEN, "dpmac" },
Pablo Greco 89a396
+		{ DPSECI_CMDID_OPEN, "dpseci" },
Pablo Greco 89a396
+		{ DPDMUX_CMDID_OPEN, "dpdmux" },
Pablo Greco 89a396
+		{ DPDCEI_CMDID_OPEN, "dpdcei" },
Pablo Greco 89a396
+		{ DPAIOP_CMDID_OPEN, "dpaiop" },
Pablo Greco 89a396
+		{ DPCI_CMDID_OPEN, "dpci" },
Pablo Greco 89a396
+		{ DPDMAI_CMDID_OPEN, "dpdmai" },
Pablo Greco 89a396
+		{ DPDBG_CMDID_OPEN, "dpdbg" },
Pablo Greco 89a396
+		{ 0, NULL }
Pablo Greco 89a396
+	};
Pablo Greco 89a396
+	int i;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	for (i = 0; dev_ids[i].type; i++)
Pablo Greco 89a396
+		if (!strcmp(dev_ids[i].type, type))
Pablo Greco 89a396
+			return dev_ids[i].cmd_id;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	return -1;
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
+int fsl_mc_obj_open(struct fsl_mc_io *mc_io,
Pablo Greco 89a396
+		    u32 cmd_flags,
Pablo Greco 89a396
+		    int obj_id,
Pablo Greco 89a396
+		    char *obj_type,
Pablo Greco 89a396
+		    u16 *token)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	struct fsl_mc_command cmd = { 0 };
Pablo Greco 89a396
+	struct fsl_mc_obj_cmd_open *cmd_params;
Pablo Greco 89a396
+	int err = 0;
Pablo Greco 89a396
+	int cmd_id = fsl_mc_get_open_cmd_id(obj_type);
Pablo Greco 89a396
+
Pablo Greco 89a396
+	if (cmd_id == -1)
Pablo Greco 89a396
+		return -ENODEV;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	/* prepare command */
Pablo Greco 89a396
+	cmd.header = mc_encode_cmd_header(cmd_id, cmd_flags, 0);
Pablo Greco 89a396
+	cmd_params = (struct fsl_mc_obj_cmd_open *)cmd.params;
Pablo Greco 89a396
+	cmd_params->obj_id = cpu_to_le32(obj_id);
Pablo Greco 89a396
+
Pablo Greco 89a396
+	/* send command to mc*/
Pablo Greco 89a396
+	err = mc_send_command(mc_io, &cmd);
Pablo Greco 89a396
+	if (err)
Pablo Greco 89a396
+		return err;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	/* retrieve response parameters */
Pablo Greco 89a396
+	*token = mc_cmd_hdr_read_token(&cmd);
Pablo Greco 89a396
+
Pablo Greco 89a396
+	return err;
Pablo Greco 89a396
+}
Pablo Greco 89a396
+EXPORT_SYMBOL_GPL(fsl_mc_obj_open);
Pablo Greco 89a396
+
Pablo Greco 89a396
+int fsl_mc_obj_close(struct fsl_mc_io *mc_io,
Pablo Greco 89a396
+		     u32 cmd_flags,
Pablo Greco 89a396
+		     u16 token)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	struct fsl_mc_command cmd = { 0 };
Pablo Greco 89a396
+
Pablo Greco 89a396
+	/* prepare command */
Pablo Greco 89a396
+	cmd.header = mc_encode_cmd_header(OBJ_CMDID_CLOSE, cmd_flags,
Pablo Greco 89a396
+					  token);
Pablo Greco 89a396
+
Pablo Greco 89a396
+	/* send command to mc*/
Pablo Greco 89a396
+	return mc_send_command(mc_io, &cmd);
Pablo Greco 89a396
+}
Pablo Greco 89a396
+EXPORT_SYMBOL_GPL(fsl_mc_obj_close);
Pablo Greco 89a396
+
Pablo Greco 89a396
+int fsl_mc_obj_reset(struct fsl_mc_io *mc_io,
Pablo Greco 89a396
+		     u32 cmd_flags,
Pablo Greco 89a396
+		     u16 token)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	struct fsl_mc_command cmd = { 0 };
Pablo Greco 89a396
+
Pablo Greco 89a396
+	/* prepare command */
Pablo Greco 89a396
+	cmd.header = mc_encode_cmd_header(OBJ_CMDID_RESET, cmd_flags,
Pablo Greco 89a396
+					  token);
Pablo Greco 89a396
+
Pablo Greco 89a396
+	/* send command to mc*/
Pablo Greco 89a396
+	return mc_send_command(mc_io, &cmd);
Pablo Greco 89a396
+}
Pablo Greco 89a396
+EXPORT_SYMBOL_GPL(fsl_mc_obj_reset);
Pablo Greco 89a396
diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h
Pablo Greco 89a396
index 30ece3ae6df7..e026f6c48b49 100644
Pablo Greco 89a396
--- a/include/linux/fsl/mc.h
Pablo Greco 89a396
+++ b/include/linux/fsl/mc.h
Pablo Greco 89a396
@@ -620,6 +620,20 @@ int dpcon_reset(struct fsl_mc_io *mc_io,
Pablo Greco 89a396
 		u32 cmd_flags,
Pablo Greco 89a396
 		u16 token);
Pablo Greco 89a396
 
Pablo Greco 89a396
+int fsl_mc_obj_open(struct fsl_mc_io *mc_io,
Pablo Greco 89a396
+		    u32 cmd_flags,
Pablo Greco 89a396
+		    int obj_id,
Pablo Greco 89a396
+		    char *obj_type,
Pablo Greco 89a396
+		    u16 *token);
Pablo Greco 89a396
+
Pablo Greco 89a396
+int fsl_mc_obj_close(struct fsl_mc_io *mc_io,
Pablo Greco 89a396
+		     u32 cmd_flags,
Pablo Greco 89a396
+		     u16 token);
Pablo Greco 89a396
+
Pablo Greco 89a396
+int fsl_mc_obj_reset(struct fsl_mc_io *mc_io,
Pablo Greco 89a396
+		     u32 cmd_flags,
Pablo Greco 89a396
+		     u16 token);
Pablo Greco 89a396
+
Pablo Greco 89a396
 /**
Pablo Greco 89a396
  * struct dpcon_attr - Structure representing DPCON attributes
Pablo Greco 89a396
  * @id: DPCON object ID
Pablo Greco 89a396
-- 
Pablo Greco 89a396
2.18.4
Pablo Greco 89a396
Pablo Greco 89a396
Pablo Greco 89a396
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 89a396
From: Diana Craciun <diana.craciun@oss.nxp.com>
Pablo Greco 89a396
Date: Wed, 22 Sep 2021 14:05:30 +0300
Pablo Greco cd4fb3
Subject: [PATCH 18/19] vfio/fsl-mc: Add per device reset support
Pablo Greco 89a396
Pablo Greco 89a396
Currently when a fsl-mc device is reset, the entire DPRC container
Pablo Greco 89a396
is reset which is very inefficient because the devices within a
Pablo Greco 89a396
container will be reset multiple times.
Pablo Greco 89a396
Add support for individually resetting a device.
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Diana Craciun <diana.craciun@oss.nxp.com>
Pablo Greco 89a396
Reviewed-by: Laurentiu Tudor <laurentiu.tudor@nxp.com>
Pablo Greco 89a396
Link: https://lore.kernel.org/r/20210922110530.24736-2-diana.craciun@oss.nxp.com
Pablo Greco 89a396
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Pablo Greco 89a396
---
Pablo Greco 89a396
 drivers/vfio/fsl-mc/vfio_fsl_mc.c | 45 ++++++++++++++++++++-----------
Pablo Greco 89a396
 1 file changed, 30 insertions(+), 15 deletions(-)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/vfio/fsl-mc/vfio_fsl_mc.c b/drivers/vfio/fsl-mc/vfio_fsl_mc.c
Pablo Greco 89a396
index 0ead91bfa838..6d7b2d2571a2 100644
Pablo Greco 89a396
--- a/drivers/vfio/fsl-mc/vfio_fsl_mc.c
Pablo Greco 89a396
+++ b/drivers/vfio/fsl-mc/vfio_fsl_mc.c
Pablo Greco 89a396
@@ -65,6 +65,34 @@ static void vfio_fsl_mc_regions_cleanup(struct vfio_fsl_mc_device *vdev)
Pablo Greco 89a396
 	kfree(vdev->regions);
Pablo Greco 89a396
 }
Pablo Greco 89a396
 
Pablo Greco 89a396
+static int vfio_fsl_mc_reset_device(struct vfio_fsl_mc_device *vdev)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	struct fsl_mc_device *mc_dev = vdev->mc_dev;
Pablo Greco 89a396
+	int ret = 0;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	if (is_fsl_mc_bus_dprc(vdev->mc_dev)) {
Pablo Greco 89a396
+		return dprc_reset_container(mc_dev->mc_io, 0,
Pablo Greco 89a396
+					mc_dev->mc_handle,
Pablo Greco 89a396
+					mc_dev->obj_desc.id,
Pablo Greco 89a396
+					DPRC_RESET_OPTION_NON_RECURSIVE);
Pablo Greco 89a396
+	} else {
Pablo Greco 89a396
+		u16 token;
Pablo Greco 89a396
+
Pablo Greco 89a396
+		ret = fsl_mc_obj_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
Pablo Greco 89a396
+				      mc_dev->obj_desc.type,
Pablo Greco 89a396
+				      &token);
Pablo Greco 89a396
+		if (ret)
Pablo Greco 89a396
+			goto out;
Pablo Greco 89a396
+		ret = fsl_mc_obj_reset(mc_dev->mc_io, 0, token);
Pablo Greco 89a396
+		if (ret) {
Pablo Greco 89a396
+			fsl_mc_obj_close(mc_dev->mc_io, 0, token);
Pablo Greco 89a396
+			goto out;
Pablo Greco 89a396
+		}
Pablo Greco 89a396
+		ret = fsl_mc_obj_close(mc_dev->mc_io, 0, token);
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+out:
Pablo Greco 89a396
+	return ret;
Pablo Greco 89a396
+}
Pablo Greco 89a396
 
Pablo Greco 89a396
 static void vfio_fsl_mc_close_device(struct vfio_device *core_vdev)
Pablo Greco 89a396
 {
Pablo Greco 89a396
@@ -78,9 +106,7 @@ static void vfio_fsl_mc_close_device(struct vfio_device *core_vdev)
Pablo Greco 89a396
 	vfio_fsl_mc_regions_cleanup(vdev);
Pablo Greco 89a396
 
Pablo Greco 89a396
 	/* reset the device before cleaning up the interrupts */
Pablo Greco 89a396
-	ret = dprc_reset_container(mc_cont->mc_io, 0, mc_cont->mc_handle,
Pablo Greco 89a396
-				   mc_cont->obj_desc.id,
Pablo Greco 89a396
-				   DPRC_RESET_OPTION_NON_RECURSIVE);
Pablo Greco 89a396
+	ret = vfio_fsl_mc_reset_device(vdev);
Pablo Greco 89a396
 
Pablo Greco 89a396
 	if (WARN_ON(ret))
Pablo Greco 89a396
 		dev_warn(&mc_cont->dev,
Pablo Greco 89a396
@@ -203,18 +229,7 @@ static long vfio_fsl_mc_ioctl(struct vfio_device *core_vdev,
Pablo Greco 89a396
 	}
Pablo Greco 89a396
 	case VFIO_DEVICE_RESET:
Pablo Greco 89a396
 	{
Pablo Greco 89a396
-		int ret;
Pablo Greco 89a396
-		struct fsl_mc_device *mc_dev = vdev->mc_dev;
Pablo Greco 89a396
-
Pablo Greco 89a396
-		/* reset is supported only for the DPRC */
Pablo Greco 89a396
-		if (!is_fsl_mc_bus_dprc(mc_dev))
Pablo Greco 89a396
-			return -ENOTTY;
Pablo Greco 89a396
-
Pablo Greco 89a396
-		ret = dprc_reset_container(mc_dev->mc_io, 0,
Pablo Greco 89a396
-					   mc_dev->mc_handle,
Pablo Greco 89a396
-					   mc_dev->obj_desc.id,
Pablo Greco 89a396
-					   DPRC_RESET_OPTION_NON_RECURSIVE);
Pablo Greco 89a396
-		return ret;
Pablo Greco 89a396
+		return vfio_fsl_mc_reset_device(vdev);
Pablo Greco 89a396
 
Pablo Greco 89a396
 	}
Pablo Greco 89a396
 	default:
Pablo Greco 89a396
-- 
Pablo Greco 89a396
2.18.4
Pablo Greco 89a396
Pablo Greco 89a396
Pablo Greco 89a396
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 89a396
From: Jon Nettleton <jon@solid-run.com>
Pablo Greco 89a396
Date: Mon, 20 Dec 2021 12:49:27 +0100
Pablo Greco cd4fb3
Subject: [PATCH 19/19] bus: fsl-mc: list more commands as accepted through the
Pablo Greco 89a396
 ioctl
Pablo Greco 89a396
Pablo Greco 89a396
This adds the commands needed to use the DCE engine from
Pablo Greco 89a396
userspace. It includes the generic reset,enable,disable as
Pablo Greco 89a396
well as DPDCEI_* ioctls.
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Jon Nettleton <jon@solid-run.com>
Pablo Greco 89a396
---
Pablo Greco 89a396
 drivers/bus/fsl-mc/fsl-mc-uapi.c | 42 ++++++++++++++++++++++++++++++++
Pablo Greco 89a396
 1 file changed, 42 insertions(+)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/bus/fsl-mc/fsl-mc-uapi.c b/drivers/bus/fsl-mc/fsl-mc-uapi.c
Pablo Greco 89a396
index 9c4c1395fcdb..0b8733f0f189 100644
Pablo Greco 89a396
--- a/drivers/bus/fsl-mc/fsl-mc-uapi.c
Pablo Greco 89a396
+++ b/drivers/bus/fsl-mc/fsl-mc-uapi.c
Pablo Greco 89a396
@@ -61,6 +61,9 @@ enum fsl_mc_cmd_index {
Pablo Greco 89a396
 	DPNI_GET_STATISTICS,
Pablo Greco 89a396
 	DPNI_GET_LINK_STATE,
Pablo Greco 89a396
 	DPNI_GET_MAX_FRAME_LENGTH,
Pablo Greco 89a396
+	DPDCEI_CMDID_SET_RX_QUEUE,
Pablo Greco 89a396
+	DPDCEI_CMDID_GET_RX_QUEUE,
Pablo Greco 89a396
+	DPDCEI_CMDID_GET_TX_QUEUE,
Pablo Greco 89a396
 	DPSW_GET_TAILDROP,
Pablo Greco 89a396
 	DPSW_SET_TAILDROP,
Pablo Greco 89a396
 	DPSW_IF_GET_COUNTER,
Pablo Greco 89a396
@@ -71,6 +74,9 @@ enum fsl_mc_cmd_index {
Pablo Greco 89a396
 	GET_IRQ_MASK,
Pablo Greco 89a396
 	GET_IRQ_STATUS,
Pablo Greco 89a396
 	CLOSE,
Pablo Greco 89a396
+	RESET,
Pablo Greco 89a396
+	ENABLE,
Pablo Greco 89a396
+	DISABLE,
Pablo Greco 89a396
 	OPEN,
Pablo Greco 89a396
 	GET_API_VERSION,
Pablo Greco 89a396
 	DESTROY,
Pablo Greco 89a396
@@ -311,6 +317,24 @@ static struct fsl_mc_cmd_desc fsl_mc_accepted_cmds[] = {
Pablo Greco 89a396
 		.token = true,
Pablo Greco 89a396
 		.size = 10,
Pablo Greco 89a396
 	},
Pablo Greco 89a396
+	[DPDCEI_CMDID_SET_RX_QUEUE] = {
Pablo Greco 89a396
+		.cmdid_value = 0x1b00,
Pablo Greco 89a396
+		.cmdid_mask = 0xFFF0,
Pablo Greco 89a396
+		.token = true,
Pablo Greco 89a396
+		.size = 8,
Pablo Greco 89a396
+	},
Pablo Greco 89a396
+	[DPDCEI_CMDID_GET_RX_QUEUE] = {
Pablo Greco 89a396
+		.cmdid_value = 0x1b10,
Pablo Greco 89a396
+		.cmdid_mask = 0xFFF0,
Pablo Greco 89a396
+		.token = true,
Pablo Greco 89a396
+		.size = 8,
Pablo Greco 89a396
+	},
Pablo Greco 89a396
+	[DPDCEI_CMDID_GET_TX_QUEUE] = {
Pablo Greco 89a396
+		.cmdid_value = 0x1b20,
Pablo Greco 89a396
+		.cmdid_mask = 0xFFF0,
Pablo Greco 89a396
+		.token = true,
Pablo Greco 89a396
+		.size = 8,
Pablo Greco 89a396
+	},
Pablo Greco 89a396
 	[GET_ATTR] = {
Pablo Greco 89a396
 		.cmdid_value = 0x0040,
Pablo Greco 89a396
 		.cmdid_mask = 0xFFF0,
Pablo Greco 89a396
@@ -335,6 +359,24 @@ static struct fsl_mc_cmd_desc fsl_mc_accepted_cmds[] = {
Pablo Greco 89a396
 		.token = true,
Pablo Greco 89a396
 		.size = 8,
Pablo Greco 89a396
 	},
Pablo Greco 89a396
+	[RESET] = {
Pablo Greco 89a396
+		.cmdid_value = 0x0050,
Pablo Greco 89a396
+		.cmdid_mask = 0xFFF0,
Pablo Greco 89a396
+		.token = true,
Pablo Greco 89a396
+		.size = 8,
Pablo Greco 89a396
+	},
Pablo Greco 89a396
+	[ENABLE] = {
Pablo Greco 89a396
+		.cmdid_value = 0x0020,
Pablo Greco 89a396
+		.cmdid_mask = 0xFFF0,
Pablo Greco 89a396
+		.token = true,
Pablo Greco 89a396
+		.size = 8,
Pablo Greco 89a396
+	},
Pablo Greco 89a396
+	[DISABLE] = {
Pablo Greco 89a396
+		.cmdid_value = 0x0030,
Pablo Greco 89a396
+		.cmdid_mask = 0xFFF0,
Pablo Greco 89a396
+		.token = true,
Pablo Greco 89a396
+		.size = 8,
Pablo Greco 89a396
+	},
Pablo Greco 89a396
 
Pablo Greco 89a396
 	/* Common commands amongst all types of objects. Must be checked last. */
Pablo Greco 89a396
 	[OPEN] = {
Pablo Greco 89a396
-- 
Pablo Greco 89a396
2.18.4
Pablo Greco 89a396