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 89a396
Subject: [PATCH 01/24] 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 89a396
Subject: [PATCH 02/24] 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 89a396
Subject: [PATCH 03/24] 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 89a396
index 2d6021644000..b49651349efb 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 89a396
Subject: [PATCH 04/24] 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 89a396
index b49651349efb..9e27978ce111 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 89a396
Subject: [PATCH 05/24] 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 89a396
index a388e318f86e..23acac6d89c7 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
@@ -2529,6 +2529,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 89a396
@@ -2552,20 +2565,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 89a396
Subject: [PATCH 06/24] =?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 89a396
index 23acac6d89c7..12b5c9677df8 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 89a396
@@ -3053,7 +3062,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 89a396
Subject: [PATCH 07/24] 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 89a396
index 12b5c9677df8..22fa2900ad44 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
@@ -3769,6 +3769,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 89a396
@@ -3850,6 +3878,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 89a396
Subject: [PATCH 08/24] 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 89a396
index 4bc75c4ce402..6c6b0b97756a 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 89a396
@@ -2192,6 +2236,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 89a396
Subject: [PATCH 09/24] 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 89a396
index 9e27978ce111..7164acaafcbd 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 89a396
Subject: [PATCH 10/24] 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 89a396
index 7164acaafcbd..a406c374be71 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 89a396
Subject: [PATCH 11/24] 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 89a396
 drivers/soc/fsl/guts.c | 27 ++++++++++++++++++++++-----
Pablo Greco 89a396
 1 file changed, 22 insertions(+), 5 deletions(-)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c
Pablo Greco 89a396
index d5e9a5f2c087..4353efd07d02 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 89a396
@@ -138,7 +139,7 @@ static u32 fsl_guts_get_svr(void)
Pablo Greco 89a396
 
Pablo Greco 89a396
 static int fsl_guts_probe(struct platform_device *pdev)
Pablo Greco 89a396
 {
Pablo Greco 89a396
-	struct device_node *np = pdev->dev.of_node;
Pablo Greco 89a396
+	struct device_node *root;
Pablo Greco 89a396
 	struct device *dev = &pdev->dev;
Pablo Greco 89a396
 	struct resource *res;
Pablo Greco 89a396
 	const struct fsl_soc_die_attr *soc_die;
Pablo Greco 89a396
@@ -150,7 +151,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 89a396
@@ -158,9 +160,17 @@ 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 89a396
 	if (machine)
Pablo Greco 89a396
 		soc_dev_attr.machine = machine;
Pablo Greco 89a396
 
Pablo Greco 89a396
@@ -234,10 +244,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 89a396
Subject: [PATCH 12/24] 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 1fd891
index 0f3658b36513..c11544f6047b 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 1fd891
@@ -1370,29 +1379,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 1fd891
@@ -1425,7 +1440,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 1fd891
@@ -1510,6 +1525,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 89a396
Subject: [PATCH 13/24] 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 1fd891
index 4c77837769c6..f478a0d10634 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 89a396
@@ -893,6 +894,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 1fd891
index c11544f6047b..6e67bff51454 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 89a396
Subject: [PATCH 14/24] 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 89a396
Subject: [PATCH 15/24] 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 89a396
Subject: [PATCH 16/24] 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: Jon Nettleton <jon@solid-run.com>
Pablo Greco 89a396
Date: Thu, 7 Oct 2021 03:11:29 -0400
Pablo Greco 89a396
Subject: [PATCH 17/24] arm64: Alter memcpy and memmove for better ACE compat
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Jon Nettleton <jon@solid-run.com>
Pablo Greco 89a396
---
Pablo Greco 89a396
 arch/arm64/lib/memcpy.S | 10 +++++-----
Pablo Greco 89a396
 1 file changed, 5 insertions(+), 5 deletions(-)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/arch/arm64/lib/memcpy.S b/arch/arm64/lib/memcpy.S
Pablo Greco 89a396
index b82fd64ee1e1..4aa907895e45 100644
Pablo Greco 89a396
--- a/arch/arm64/lib/memcpy.S
Pablo Greco 89a396
+++ b/arch/arm64/lib/memcpy.S
Pablo Greco 89a396
@@ -136,12 +136,12 @@ L(copy128):
Pablo Greco 89a396
 	stp	G_l, G_h, [dstend, -64]
Pablo Greco 89a396
 	stp	H_l, H_h, [dstend, -48]
Pablo Greco 89a396
 L(copy96):
Pablo Greco 89a396
+	stp	C_l, C_h, [dstend, -32]
Pablo Greco 89a396
+	stp	D_l, D_h, [dstend, -16]
Pablo Greco 89a396
 	stp	A_l, A_h, [dstin]
Pablo Greco 89a396
 	stp	B_l, B_h, [dstin, 16]
Pablo Greco 89a396
 	stp	E_l, E_h, [dstin, 32]
Pablo Greco 89a396
 	stp	F_l, F_h, [dstin, 48]
Pablo Greco 89a396
-	stp	C_l, C_h, [dstend, -32]
Pablo Greco 89a396
-	stp	D_l, D_h, [dstend, -16]
Pablo Greco 89a396
 	ret
Pablo Greco 89a396
 
Pablo Greco 89a396
 	.p2align 4
Pablo Greco 89a396
@@ -236,10 +236,10 @@ L(copy64_from_start):
Pablo Greco 89a396
 	stp	C_l, C_h, [dstend, -48]
Pablo Greco 89a396
 	ldp	C_l, C_h, [src]
Pablo Greco 89a396
 	stp	D_l, D_h, [dstend, -64]
Pablo Greco 89a396
-	stp	G_l, G_h, [dstin, 48]
Pablo Greco 89a396
-	stp	A_l, A_h, [dstin, 32]
Pablo Greco 89a396
-	stp	B_l, B_h, [dstin, 16]
Pablo Greco 89a396
 	stp	C_l, C_h, [dstin]
Pablo Greco 89a396
+	stp	B_l, B_h, [dstin, 16]
Pablo Greco 89a396
+	stp	A_l, A_h, [dstin, 32]
Pablo Greco 89a396
+	stp	G_l, G_h, [dstin, 48]
Pablo Greco 89a396
 	ret
Pablo Greco 89a396
 
Pablo Greco 89a396
 SYM_FUNC_END_PI(memcpy)
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: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Pablo Greco 89a396
Date: Fri, 24 Sep 2021 20:51:02 +1200
Pablo Greco 89a396
Subject: [PATCH 18/24] topology: Represent clusters of CPUs within a die
Pablo Greco 89a396
Pablo Greco 89a396
Both ACPI and DT provide the ability to describe additional layers of
Pablo Greco 89a396
topology between that of individual cores and higher level constructs
Pablo Greco 89a396
such as the level at which the last level cache is shared.
Pablo Greco 89a396
In ACPI this can be represented in PPTT as a Processor Hierarchy
Pablo Greco 89a396
Node Structure [1] that is the parent of the CPU cores and in turn
Pablo Greco 89a396
has a parent Processor Hierarchy Nodes Structure representing
Pablo Greco 89a396
a higher level of topology.
Pablo Greco 89a396
Pablo Greco 89a396
For example Kunpeng 920 has 6 or 8 clusters in each NUMA node, and each
Pablo Greco 89a396
cluster has 4 cpus. All clusters share L3 cache data, but each cluster
Pablo Greco 89a396
has local L3 tag. On the other hand, each clusters will share some
Pablo Greco 89a396
internal system bus.
Pablo Greco 89a396
Pablo Greco 89a396
+-----------------------------------+                          +---------+
Pablo Greco 89a396
|  +------+    +------+             +--------------------------+         |
Pablo Greco 89a396
|  | CPU0 |    | cpu1 |             |    +-----------+         |         |
Pablo Greco 89a396
|  +------+    +------+             |    |           |         |         |
Pablo Greco 89a396
|                                   +----+    L3     |         |         |
Pablo Greco 89a396
|  +------+    +------+   cluster   |    |    tag    |         |         |
Pablo Greco 89a396
|  | CPU2 |    | CPU3 |             |    |           |         |         |
Pablo Greco 89a396
|  +------+    +------+             |    +-----------+         |         |
Pablo Greco 89a396
|                                   |                          |         |
Pablo Greco 89a396
+-----------------------------------+                          |         |
Pablo Greco 89a396
+-----------------------------------+                          |         |
Pablo Greco 89a396
|  +------+    +------+             +--------------------------+         |
Pablo Greco 89a396
|  |      |    |      |             |    +-----------+         |         |
Pablo Greco 89a396
|  +------+    +------+             |    |           |         |         |
Pablo Greco 89a396
|                                   |    |    L3     |         |         |
Pablo Greco 89a396
|  +------+    +------+             +----+    tag    |         |         |
Pablo Greco 89a396
|  |      |    |      |             |    |           |         |         |
Pablo Greco 89a396
|  +------+    +------+             |    +-----------+         |         |
Pablo Greco 89a396
|                                   |                          |         |
Pablo Greco 89a396
+-----------------------------------+                          |   L3    |
Pablo Greco 89a396
                                                               |   data  |
Pablo Greco 89a396
+-----------------------------------+                          |         |
Pablo Greco 89a396
|  +------+    +------+             |    +-----------+         |         |
Pablo Greco 89a396
|  |      |    |      |             |    |           |         |         |
Pablo Greco 89a396
|  +------+    +------+             +----+    L3     |         |         |
Pablo Greco 89a396
|                                   |    |    tag    |         |         |
Pablo Greco 89a396
|  +------+    +------+             |    |           |         |         |
Pablo Greco 89a396
|  |      |    |      |             |    +-----------+         |         |
Pablo Greco 89a396
|  +------+    +------+             +--------------------------+         |
Pablo Greco 89a396
+-----------------------------------|                          |         |
Pablo Greco 89a396
+-----------------------------------|                          |         |
Pablo Greco 89a396
|  +------+    +------+             +--------------------------+         |
Pablo Greco 89a396
|  |      |    |      |             |    +-----------+         |         |
Pablo Greco 89a396
|  +------+    +------+             |    |           |         |         |
Pablo Greco 89a396
|                                   +----+    L3     |         |         |
Pablo Greco 89a396
|  +------+    +------+             |    |    tag    |         |         |
Pablo Greco 89a396
|  |      |    |      |             |    |           |         |         |
Pablo Greco 89a396
|  +------+    +------+             |    +-----------+         |         |
Pablo Greco 89a396
|                                   |                          |         |
Pablo Greco 89a396
+-----------------------------------+                          |         |
Pablo Greco 89a396
+-----------------------------------+                          |         |
Pablo Greco 89a396
|  +------+    +------+             +--------------------------+         |
Pablo Greco 89a396
|  |      |    |      |             |   +-----------+          |         |
Pablo Greco 89a396
|  +------+    +------+             |   |           |          |         |
Pablo Greco 89a396
|                                   |   |    L3     |          |         |
Pablo Greco 89a396
|  +------+    +------+             +---+    tag    |          |         |
Pablo Greco 89a396
|  |      |    |      |             |   |           |          |         |
Pablo Greco 89a396
|  +------+    +------+             |   +-----------+          |         |
Pablo Greco 89a396
|                                   |                          |         |
Pablo Greco 89a396
+-----------------------------------+                          |         |
Pablo Greco 89a396
+-----------------------------------+                          |         |
Pablo Greco 89a396
|  +------+    +------+             +--------------------------+         |
Pablo Greco 89a396
|  |      |    |      |             |  +-----------+           |         |
Pablo Greco 89a396
|  +------+    +------+             |  |           |           |         |
Pablo Greco 89a396
|                                   |  |    L3     |           |         |
Pablo Greco 89a396
|  +------+    +------+             +--+    tag    |           |         |
Pablo Greco 89a396
|  |      |    |      |             |  |           |           |         |
Pablo Greco 89a396
|  +------+    +------+             |  +-----------+           |         |
Pablo Greco 89a396
|                                   |                          +---------+
Pablo Greco 89a396
+-----------------------------------+
Pablo Greco 89a396
Pablo Greco 89a396
That means spreading tasks among clusters will bring more bandwidth
Pablo Greco 89a396
while packing tasks within one cluster will lead to smaller cache
Pablo Greco 89a396
synchronization latency. So both kernel and userspace will have
Pablo Greco 89a396
a chance to leverage this topology to deploy tasks accordingly to
Pablo Greco 89a396
achieve either smaller cache latency within one cluster or an even
Pablo Greco 89a396
distribution of load among clusters for higher throughput.
Pablo Greco 89a396
Pablo Greco 89a396
This patch exposes cluster topology to both kernel and userspace.
Pablo Greco 89a396
Libraried like hwloc will know cluster by cluster_cpus and related
Pablo Greco 89a396
sysfs attributes. PoC of HWLOC support at [2].
Pablo Greco 89a396
Pablo Greco 89a396
Note this patch only handle the ACPI case.
Pablo Greco 89a396
Pablo Greco 89a396
Special consideration is needed for SMT processors, where it is
Pablo Greco 89a396
necessary to move 2 levels up the hierarchy from the leaf nodes
Pablo Greco 89a396
(thus skipping the processor core level).
Pablo Greco 89a396
Pablo Greco 89a396
Note that arm64 / ACPI does not provide any means of identifying
Pablo Greco 89a396
a die level in the topology but that may be unrelate to the cluster
Pablo Greco 89a396
level.
Pablo Greco 89a396
Pablo Greco 89a396
[1] ACPI Specification 6.3 - section 5.2.29.1 processor hierarchy node
Pablo Greco 89a396
    structure (Type 0)
Pablo Greco 89a396
[2] https://github.com/hisilicon/hwloc/tree/linux-cluster
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Pablo Greco 89a396
Signed-off-by: Tian Tao <tiantao6@hisilicon.com>
Pablo Greco 89a396
Signed-off-by: Barry Song <song.bao.hua@hisilicon.com>
Pablo Greco 89a396
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Pablo Greco 89a396
Link: https://lore.kernel.org/r/20210924085104.44806-2-21cnbao@gmail.com
Pablo Greco 89a396
---
Pablo Greco 89a396
 .../ABI/stable/sysfs-devices-system-cpu       | 15 +++++
Pablo Greco 89a396
 Documentation/admin-guide/cputopology.rst     | 12 ++--
Pablo Greco 89a396
 arch/arm64/kernel/topology.c                  |  2 +
Pablo Greco 89a396
 drivers/acpi/pptt.c                           | 67 +++++++++++++++++++
Pablo Greco 89a396
 drivers/base/arch_topology.c                  | 15 +++++
Pablo Greco 89a396
 drivers/base/topology.c                       | 10 +++
Pablo Greco 89a396
 include/linux/acpi.h                          |  5 ++
Pablo Greco 89a396
 include/linux/arch_topology.h                 |  5 ++
Pablo Greco 89a396
 include/linux/topology.h                      |  6 ++
Pablo Greco 89a396
 9 files changed, 133 insertions(+), 4 deletions(-)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/Documentation/ABI/stable/sysfs-devices-system-cpu b/Documentation/ABI/stable/sysfs-devices-system-cpu
Pablo Greco 89a396
index 516dafea03eb..3965ce504484 100644
Pablo Greco 89a396
--- a/Documentation/ABI/stable/sysfs-devices-system-cpu
Pablo Greco 89a396
+++ b/Documentation/ABI/stable/sysfs-devices-system-cpu
Pablo Greco 89a396
@@ -42,6 +42,12 @@ Description:    the CPU core ID of cpuX. Typically it is the hardware platform's
Pablo Greco 89a396
                 architecture and platform dependent.
Pablo Greco 89a396
 Values:         integer
Pablo Greco 89a396
 
Pablo Greco 89a396
+What:           /sys/devices/system/cpu/cpuX/topology/cluster_id
Pablo Greco 89a396
+Description:    the cluster ID of cpuX.  Typically it is the hardware platform's
Pablo Greco 89a396
+                identifier (rather than the kernel's). The actual value is
Pablo Greco 89a396
+                architecture and platform dependent.
Pablo Greco 89a396
+Values:         integer
Pablo Greco 89a396
+
Pablo Greco 89a396
 What:           /sys/devices/system/cpu/cpuX/topology/book_id
Pablo Greco 89a396
 Description:    the book ID of cpuX. Typically it is the hardware platform's
Pablo Greco 89a396
                 identifier (rather than the kernel's). The actual value is
Pablo Greco 89a396
@@ -85,6 +91,15 @@ Description:    human-readable list of CPUs within the same die.
Pablo Greco 89a396
                 The format is like 0-3, 8-11, 14,17.
Pablo Greco 89a396
 Values:         decimal list.
Pablo Greco 89a396
 
Pablo Greco 89a396
+What:           /sys/devices/system/cpu/cpuX/topology/cluster_cpus
Pablo Greco 89a396
+Description:    internal kernel map of CPUs within the same cluster.
Pablo Greco 89a396
+Values:         hexadecimal bitmask.
Pablo Greco 89a396
+
Pablo Greco 89a396
+What:           /sys/devices/system/cpu/cpuX/topology/cluster_cpus_list
Pablo Greco 89a396
+Description:    human-readable list of CPUs within the same cluster.
Pablo Greco 89a396
+                The format is like 0-3, 8-11, 14,17.
Pablo Greco 89a396
+Values:         decimal list.
Pablo Greco 89a396
+
Pablo Greco 89a396
 What:           /sys/devices/system/cpu/cpuX/topology/book_siblings
Pablo Greco 89a396
 Description:    internal kernel map of cpuX's hardware threads within the same
Pablo Greco 89a396
                 book_id. it's only used on s390.
Pablo Greco 89a396
diff --git a/Documentation/admin-guide/cputopology.rst b/Documentation/admin-guide/cputopology.rst
Pablo Greco 89a396
index b085dbac60a5..6b62e182baf4 100644
Pablo Greco 89a396
--- a/Documentation/admin-guide/cputopology.rst
Pablo Greco 89a396
+++ b/Documentation/admin-guide/cputopology.rst
Pablo Greco 89a396
@@ -19,11 +19,13 @@ these macros in include/asm-XXX/topology.h::
Pablo Greco 89a396
 
Pablo Greco 89a396
 	#define topology_physical_package_id(cpu)
Pablo Greco 89a396
 	#define topology_die_id(cpu)
Pablo Greco 89a396
+	#define topology_cluster_id(cpu)
Pablo Greco 89a396
 	#define topology_core_id(cpu)
Pablo Greco 89a396
 	#define topology_book_id(cpu)
Pablo Greco 89a396
 	#define topology_drawer_id(cpu)
Pablo Greco 89a396
 	#define topology_sibling_cpumask(cpu)
Pablo Greco 89a396
 	#define topology_core_cpumask(cpu)
Pablo Greco 89a396
+	#define topology_cluster_cpumask(cpu)
Pablo Greco 89a396
 	#define topology_die_cpumask(cpu)
Pablo Greco 89a396
 	#define topology_book_cpumask(cpu)
Pablo Greco 89a396
 	#define topology_drawer_cpumask(cpu)
Pablo Greco 89a396
@@ -39,10 +41,12 @@ not defined by include/asm-XXX/topology.h:
Pablo Greco 89a396
 
Pablo Greco 89a396
 1) topology_physical_package_id: -1
Pablo Greco 89a396
 2) topology_die_id: -1
Pablo Greco 89a396
-3) topology_core_id: 0
Pablo Greco 89a396
-4) topology_sibling_cpumask: just the given CPU
Pablo Greco 89a396
-5) topology_core_cpumask: just the given CPU
Pablo Greco 89a396
-6) topology_die_cpumask: just the given CPU
Pablo Greco 89a396
+3) topology_cluster_id: -1
Pablo Greco 89a396
+4) topology_core_id: 0
Pablo Greco 89a396
+5) topology_sibling_cpumask: just the given CPU
Pablo Greco 89a396
+6) topology_core_cpumask: just the given CPU
Pablo Greco 89a396
+7) topology_cluster_cpumask: just the given CPU
Pablo Greco 89a396
+8) topology_die_cpumask: just the given CPU
Pablo Greco 89a396
 
Pablo Greco 89a396
 For architectures that don't support books (CONFIG_SCHED_BOOK) there are no
Pablo Greco 89a396
 default definitions for topology_book_id() and topology_book_cpumask().
Pablo Greco 89a396
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
Pablo Greco 89a396
index 4dd14a6620c1..9ab78ad826e2 100644
Pablo Greco 89a396
--- a/arch/arm64/kernel/topology.c
Pablo Greco 89a396
+++ b/arch/arm64/kernel/topology.c
Pablo Greco 89a396
@@ -103,6 +103,8 @@ int __init parse_acpi_topology(void)
Pablo Greco 89a396
 			cpu_topology[cpu].thread_id  = -1;
Pablo Greco 89a396
 			cpu_topology[cpu].core_id    = topology_id;
Pablo Greco 89a396
 		}
Pablo Greco 89a396
+		topology_id = find_acpi_cpu_topology_cluster(cpu);
Pablo Greco 89a396
+		cpu_topology[cpu].cluster_id = topology_id;
Pablo Greco 89a396
 		topology_id = find_acpi_cpu_topology_package(cpu);
Pablo Greco 89a396
 		cpu_topology[cpu].package_id = topology_id;
Pablo Greco 89a396
 
Pablo Greco 89a396
diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
Pablo Greco 89a396
index fe69dc518f31..701f61c01359 100644
Pablo Greco 89a396
--- a/drivers/acpi/pptt.c
Pablo Greco 89a396
+++ b/drivers/acpi/pptt.c
Pablo Greco 89a396
@@ -746,6 +746,73 @@ int find_acpi_cpu_topology_package(unsigned int cpu)
Pablo Greco 89a396
 					  ACPI_PPTT_PHYSICAL_PACKAGE);
Pablo Greco 89a396
 }
Pablo Greco 89a396
 
Pablo Greco 89a396
+/**
Pablo Greco 89a396
+ * find_acpi_cpu_topology_cluster() - Determine a unique CPU cluster value
Pablo Greco 89a396
+ * @cpu: Kernel logical CPU number
Pablo Greco 89a396
+ *
Pablo Greco 89a396
+ * Determine a topology unique cluster ID for the given CPU/thread.
Pablo Greco 89a396
+ * This ID can then be used to group peers, which will have matching ids.
Pablo Greco 89a396
+ *
Pablo Greco 89a396
+ * The cluster, if present is the level of topology above CPUs. In a
Pablo Greco 89a396
+ * multi-thread CPU, it will be the level above the CPU, not the thread.
Pablo Greco 89a396
+ * It may not exist in single CPU systems. In simple multi-CPU systems,
Pablo Greco 89a396
+ * it may be equal to the package topology level.
Pablo Greco 89a396
+ *
Pablo Greco 89a396
+ * Return: -ENOENT if the PPTT doesn't exist, the CPU cannot be found
Pablo Greco 89a396
+ * or there is no toplogy level above the CPU..
Pablo Greco 89a396
+ * Otherwise returns a value which represents the package for this CPU.
Pablo Greco 89a396
+ */
Pablo Greco 89a396
+
Pablo Greco 89a396
+int find_acpi_cpu_topology_cluster(unsigned int cpu)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	struct acpi_table_header *table;
Pablo Greco 89a396
+	acpi_status status;
Pablo Greco 89a396
+	struct acpi_pptt_processor *cpu_node, *cluster_node;
Pablo Greco 89a396
+	u32 acpi_cpu_id;
Pablo Greco 89a396
+	int retval;
Pablo Greco 89a396
+	int is_thread;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	status = acpi_get_table(ACPI_SIG_PPTT, 0, &table);
Pablo Greco 89a396
+	if (ACPI_FAILURE(status)) {
Pablo Greco 89a396
+		acpi_pptt_warn_missing();
Pablo Greco 89a396
+		return -ENOENT;
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+
Pablo Greco 89a396
+	acpi_cpu_id = get_acpi_id_for_cpu(cpu);
Pablo Greco 89a396
+	cpu_node = acpi_find_processor_node(table, acpi_cpu_id);
Pablo Greco 89a396
+	if (cpu_node == NULL || !cpu_node->parent) {
Pablo Greco 89a396
+		retval = -ENOENT;
Pablo Greco 89a396
+		goto put_table;
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+
Pablo Greco 89a396
+	is_thread = cpu_node->flags & ACPI_PPTT_ACPI_PROCESSOR_IS_THREAD;
Pablo Greco 89a396
+	cluster_node = fetch_pptt_node(table, cpu_node->parent);
Pablo Greco 89a396
+	if (cluster_node == NULL) {
Pablo Greco 89a396
+		retval = -ENOENT;
Pablo Greco 89a396
+		goto put_table;
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+	if (is_thread) {
Pablo Greco 89a396
+		if (!cluster_node->parent) {
Pablo Greco 89a396
+			retval = -ENOENT;
Pablo Greco 89a396
+			goto put_table;
Pablo Greco 89a396
+		}
Pablo Greco 89a396
+		cluster_node = fetch_pptt_node(table, cluster_node->parent);
Pablo Greco 89a396
+		if (cluster_node == NULL) {
Pablo Greco 89a396
+			retval = -ENOENT;
Pablo Greco 89a396
+			goto put_table;
Pablo Greco 89a396
+		}
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+	if (cluster_node->flags & ACPI_PPTT_ACPI_PROCESSOR_ID_VALID)
Pablo Greco 89a396
+		retval = cluster_node->acpi_processor_id;
Pablo Greco 89a396
+	else
Pablo Greco 89a396
+		retval = ACPI_PTR_DIFF(cluster_node, table);
Pablo Greco 89a396
+
Pablo Greco 89a396
+put_table:
Pablo Greco 89a396
+	acpi_put_table(table);
Pablo Greco 89a396
+
Pablo Greco 89a396
+	return retval;
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
 /**
Pablo Greco 89a396
  * find_acpi_cpu_topology_hetero_id() - Get a core architecture tag
Pablo Greco 89a396
  * @cpu: Kernel logical CPU number
Pablo Greco 89a396
diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c
Pablo Greco 89a396
index 43407665918f..fc0836f460fb 100644
Pablo Greco 89a396
--- a/drivers/base/arch_topology.c
Pablo Greco 89a396
+++ b/drivers/base/arch_topology.c
Pablo Greco 89a396
@@ -600,6 +600,11 @@ const struct cpumask *cpu_coregroup_mask(int cpu)
Pablo Greco 89a396
 	return core_mask;
Pablo Greco 89a396
 }
Pablo Greco 89a396
 
Pablo Greco 89a396
+const struct cpumask *cpu_clustergroup_mask(int cpu)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	return &cpu_topology[cpu].cluster_sibling;
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
 void update_siblings_masks(unsigned int cpuid)
Pablo Greco 89a396
 {
Pablo Greco 89a396
 	struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
Pablo Greco 89a396
@@ -617,6 +622,12 @@ void update_siblings_masks(unsigned int cpuid)
Pablo Greco 89a396
 		if (cpuid_topo->package_id != cpu_topo->package_id)
Pablo Greco 89a396
 			continue;
Pablo Greco 89a396
 
Pablo Greco 89a396
+		if (cpuid_topo->cluster_id == cpu_topo->cluster_id &&
Pablo Greco 89a396
+		    cpuid_topo->cluster_id != -1) {
Pablo Greco 89a396
+			cpumask_set_cpu(cpu, &cpuid_topo->cluster_sibling);
Pablo Greco 89a396
+			cpumask_set_cpu(cpuid, &cpu_topo->cluster_sibling);
Pablo Greco 89a396
+		}
Pablo Greco 89a396
+
Pablo Greco 89a396
 		cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
Pablo Greco 89a396
 		cpumask_set_cpu(cpu, &cpuid_topo->core_sibling);
Pablo Greco 89a396
 
Pablo Greco 89a396
@@ -635,6 +646,9 @@ static void clear_cpu_topology(int cpu)
Pablo Greco 89a396
 	cpumask_clear(&cpu_topo->llc_sibling);
Pablo Greco 89a396
 	cpumask_set_cpu(cpu, &cpu_topo->llc_sibling);
Pablo Greco 89a396
 
Pablo Greco 89a396
+	cpumask_clear(&cpu_topo->cluster_sibling);
Pablo Greco 89a396
+	cpumask_set_cpu(cpu, &cpu_topo->cluster_sibling);
Pablo Greco 89a396
+
Pablo Greco 89a396
 	cpumask_clear(&cpu_topo->core_sibling);
Pablo Greco 89a396
 	cpumask_set_cpu(cpu, &cpu_topo->core_sibling);
Pablo Greco 89a396
 	cpumask_clear(&cpu_topo->thread_sibling);
Pablo Greco 89a396
@@ -650,6 +664,7 @@ void __init reset_cpu_topology(void)
Pablo Greco 89a396
 
Pablo Greco 89a396
 		cpu_topo->thread_id = -1;
Pablo Greco 89a396
 		cpu_topo->core_id = -1;
Pablo Greco 89a396
+		cpu_topo->cluster_id = -1;
Pablo Greco 89a396
 		cpu_topo->package_id = -1;
Pablo Greco 89a396
 		cpu_topo->llc_id = -1;
Pablo Greco 89a396
 
Pablo Greco 89a396
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
Pablo Greco 89a396
index 43c0940643f5..8f2b641d0b8c 100644
Pablo Greco 89a396
--- a/drivers/base/topology.c
Pablo Greco 89a396
+++ b/drivers/base/topology.c
Pablo Greco 89a396
@@ -48,6 +48,9 @@ static DEVICE_ATTR_RO(physical_package_id);
Pablo Greco 89a396
 define_id_show_func(die_id);
Pablo Greco 89a396
 static DEVICE_ATTR_RO(die_id);
Pablo Greco 89a396
 
Pablo Greco 89a396
+define_id_show_func(cluster_id);
Pablo Greco 89a396
+static DEVICE_ATTR_RO(cluster_id);
Pablo Greco 89a396
+
Pablo Greco 89a396
 define_id_show_func(core_id);
Pablo Greco 89a396
 static DEVICE_ATTR_RO(core_id);
Pablo Greco 89a396
 
Pablo Greco 89a396
@@ -63,6 +66,10 @@ define_siblings_read_func(core_siblings, core_cpumask);
Pablo Greco 89a396
 static BIN_ATTR_RO(core_siblings, 0);
Pablo Greco 89a396
 static BIN_ATTR_RO(core_siblings_list, 0);
Pablo Greco 89a396
 
Pablo Greco 89a396
+define_siblings_read_func(cluster_cpus, cluster_cpumask);
Pablo Greco 89a396
+static BIN_ATTR_RO(cluster_cpus, 0);
Pablo Greco 89a396
+static BIN_ATTR_RO(cluster_cpus_list, 0);
Pablo Greco 89a396
+
Pablo Greco 89a396
 define_siblings_read_func(die_cpus, die_cpumask);
Pablo Greco 89a396
 static BIN_ATTR_RO(die_cpus, 0);
Pablo Greco 89a396
 static BIN_ATTR_RO(die_cpus_list, 0);
Pablo Greco 89a396
@@ -94,6 +101,8 @@ static struct bin_attribute *bin_attrs[] = {
Pablo Greco 89a396
 	&bin_attr_thread_siblings_list,
Pablo Greco 89a396
 	&bin_attr_core_siblings,
Pablo Greco 89a396
 	&bin_attr_core_siblings_list,
Pablo Greco 89a396
+	&bin_attr_cluster_cpus,
Pablo Greco 89a396
+	&bin_attr_cluster_cpus_list,
Pablo Greco 89a396
 	&bin_attr_die_cpus,
Pablo Greco 89a396
 	&bin_attr_die_cpus_list,
Pablo Greco 89a396
 	&bin_attr_package_cpus,
Pablo Greco 89a396
@@ -112,6 +121,7 @@ static struct bin_attribute *bin_attrs[] = {
Pablo Greco 89a396
 static struct attribute *default_attrs[] = {
Pablo Greco 89a396
 	&dev_attr_physical_package_id.attr,
Pablo Greco 89a396
 	&dev_attr_die_id.attr,
Pablo Greco 89a396
+	&dev_attr_cluster_id.attr,
Pablo Greco 89a396
 	&dev_attr_core_id.attr,
Pablo Greco 89a396
 #ifdef CONFIG_SCHED_BOOK
Pablo Greco 89a396
 	&dev_attr_book_id.attr,
Pablo Greco 89a396
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
Pablo Greco 89a396
index 6224b1e32681..878a62266304 100644
Pablo Greco 89a396
--- a/include/linux/acpi.h
Pablo Greco 89a396
+++ b/include/linux/acpi.h
Pablo Greco 89a396
@@ -1362,6 +1362,7 @@ static inline int lpit_read_residency_count_address(u64 *address)
Pablo Greco 89a396
 #ifdef CONFIG_ACPI_PPTT
Pablo Greco 89a396
 int acpi_pptt_cpu_is_thread(unsigned int cpu);
Pablo Greco 89a396
 int find_acpi_cpu_topology(unsigned int cpu, int level);
Pablo Greco 89a396
+int find_acpi_cpu_topology_cluster(unsigned int cpu);
Pablo Greco 89a396
 int find_acpi_cpu_topology_package(unsigned int cpu);
Pablo Greco 89a396
 int find_acpi_cpu_topology_hetero_id(unsigned int cpu);
Pablo Greco 89a396
 int find_acpi_cpu_cache_topology(unsigned int cpu, int level);
Pablo Greco 89a396
@@ -1374,6 +1375,10 @@ static inline int find_acpi_cpu_topology(unsigned int cpu, int level)
Pablo Greco 89a396
 {
Pablo Greco 89a396
 	return -EINVAL;
Pablo Greco 89a396
 }
Pablo Greco 89a396
+static inline int find_acpi_cpu_topology_cluster(unsigned int cpu)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	return -EINVAL;
Pablo Greco 89a396
+}
Pablo Greco 89a396
 static inline int find_acpi_cpu_topology_package(unsigned int cpu)
Pablo Greco 89a396
 {
Pablo Greco 89a396
 	return -EINVAL;
Pablo Greco 89a396
diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h
Pablo Greco 89a396
index f180240dc95f..b97cea83b25e 100644
Pablo Greco 89a396
--- a/include/linux/arch_topology.h
Pablo Greco 89a396
+++ b/include/linux/arch_topology.h
Pablo Greco 89a396
@@ -62,10 +62,12 @@ void topology_set_thermal_pressure(const struct cpumask *cpus,
Pablo Greco 89a396
 struct cpu_topology {
Pablo Greco 89a396
 	int thread_id;
Pablo Greco 89a396
 	int core_id;
Pablo Greco 89a396
+	int cluster_id;
Pablo Greco 89a396
 	int package_id;
Pablo Greco 89a396
 	int llc_id;
Pablo Greco 89a396
 	cpumask_t thread_sibling;
Pablo Greco 89a396
 	cpumask_t core_sibling;
Pablo Greco 89a396
+	cpumask_t cluster_sibling;
Pablo Greco 89a396
 	cpumask_t llc_sibling;
Pablo Greco 89a396
 };
Pablo Greco 89a396
 
Pablo Greco 89a396
@@ -73,13 +75,16 @@ struct cpu_topology {
Pablo Greco 89a396
 extern struct cpu_topology cpu_topology[NR_CPUS];
Pablo Greco 89a396
 
Pablo Greco 89a396
 #define topology_physical_package_id(cpu)	(cpu_topology[cpu].package_id)
Pablo Greco 89a396
+#define topology_cluster_id(cpu)	(cpu_topology[cpu].cluster_id)
Pablo Greco 89a396
 #define topology_core_id(cpu)		(cpu_topology[cpu].core_id)
Pablo Greco 89a396
 #define topology_core_cpumask(cpu)	(&cpu_topology[cpu].core_sibling)
Pablo Greco 89a396
 #define topology_sibling_cpumask(cpu)	(&cpu_topology[cpu].thread_sibling)
Pablo Greco 89a396
+#define topology_cluster_cpumask(cpu)	(&cpu_topology[cpu].cluster_sibling)
Pablo Greco 89a396
 #define topology_llc_cpumask(cpu)	(&cpu_topology[cpu].llc_sibling)
Pablo Greco 89a396
 void init_cpu_topology(void);
Pablo Greco 89a396
 void store_cpu_topology(unsigned int cpuid);
Pablo Greco 89a396
 const struct cpumask *cpu_coregroup_mask(int cpu);
Pablo Greco 89a396
+const struct cpumask *cpu_clustergroup_mask(int cpu);
Pablo Greco 89a396
 void update_siblings_masks(unsigned int cpu);
Pablo Greco 89a396
 void remove_cpu_topology(unsigned int cpuid);
Pablo Greco 89a396
 void reset_cpu_topology(void);
Pablo Greco 89a396
diff --git a/include/linux/topology.h b/include/linux/topology.h
Pablo Greco 89a396
index 7634cd737061..80d27d717631 100644
Pablo Greco 89a396
--- a/include/linux/topology.h
Pablo Greco 89a396
+++ b/include/linux/topology.h
Pablo Greco 89a396
@@ -186,6 +186,9 @@ static inline int cpu_to_mem(int cpu)
Pablo Greco 89a396
 #ifndef topology_die_id
Pablo Greco 89a396
 #define topology_die_id(cpu)			((void)(cpu), -1)
Pablo Greco 89a396
 #endif
Pablo Greco 89a396
+#ifndef topology_cluster_id
Pablo Greco 89a396
+#define topology_cluster_id(cpu)		((void)(cpu), -1)
Pablo Greco 89a396
+#endif
Pablo Greco 89a396
 #ifndef topology_core_id
Pablo Greco 89a396
 #define topology_core_id(cpu)			((void)(cpu), 0)
Pablo Greco 89a396
 #endif
Pablo Greco 89a396
@@ -195,6 +198,9 @@ static inline int cpu_to_mem(int cpu)
Pablo Greco 89a396
 #ifndef topology_core_cpumask
Pablo Greco 89a396
 #define topology_core_cpumask(cpu)		cpumask_of(cpu)
Pablo Greco 89a396
 #endif
Pablo Greco 89a396
+#ifndef topology_cluster_cpumask
Pablo Greco 89a396
+#define topology_cluster_cpumask(cpu)		cpumask_of(cpu)
Pablo Greco 89a396
+#endif
Pablo Greco 89a396
 #ifndef topology_die_cpumask
Pablo Greco 89a396
 #define topology_die_cpumask(cpu)		cpumask_of(cpu)
Pablo Greco 89a396
 #endif
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: Barry Song <song.bao.hua@hisilicon.com>
Pablo Greco 89a396
Date: Fri, 24 Sep 2021 20:51:03 +1200
Pablo Greco 89a396
Subject: [PATCH 19/24] sched: Add cluster scheduler level in core and related
Pablo Greco 89a396
 Kconfig for ARM64
Pablo Greco 89a396
Pablo Greco 89a396
This patch adds scheduler level for clusters and automatically enables
Pablo Greco 89a396
the load balance among clusters. It will directly benefit a lot of
Pablo Greco 89a396
workload which loves more resources such as memory bandwidth, caches.
Pablo Greco 89a396
Pablo Greco 89a396
Testing has widely been done in two different hardware configurations of
Pablo Greco 89a396
Kunpeng920:
Pablo Greco 89a396
Pablo Greco 89a396
 24 cores in one NUMA(6 clusters in each NUMA node);
Pablo Greco 89a396
 32 cores in one NUMA(8 clusters in each NUMA node)
Pablo Greco 89a396
Pablo Greco 89a396
Workload is running on either one NUMA node or four NUMA nodes, thus,
Pablo Greco 89a396
this can estimate the effect of cluster spreading w/ and w/o NUMA load
Pablo Greco 89a396
balance.
Pablo Greco 89a396
Pablo Greco 89a396
* Stream benchmark:
Pablo Greco 89a396
Pablo Greco 89a396
4threads stream (on 1NUMA * 24cores = 24cores)
Pablo Greco 89a396
                stream                 stream
Pablo Greco 89a396
                w/o patch              w/ patch
Pablo Greco 89a396
MB/sec copy     29929.64 (   0.00%)    32932.68 (  10.03%)
Pablo Greco 89a396
MB/sec scale    29861.10 (   0.00%)    32710.58 (   9.54%)
Pablo Greco 89a396
MB/sec add      27034.42 (   0.00%)    32400.68 (  19.85%)
Pablo Greco 89a396
MB/sec triad    27225.26 (   0.00%)    31965.36 (  17.41%)
Pablo Greco 89a396
Pablo Greco 89a396
6threads stream (on 1NUMA * 24cores = 24cores)
Pablo Greco 89a396
                stream                 stream
Pablo Greco 89a396
                w/o patch              w/ patch
Pablo Greco 89a396
MB/sec copy     40330.24 (   0.00%)    42377.68 (   5.08%)
Pablo Greco 89a396
MB/sec scale    40196.42 (   0.00%)    42197.90 (   4.98%)
Pablo Greco 89a396
MB/sec add      37427.00 (   0.00%)    41960.78 (  12.11%)
Pablo Greco 89a396
MB/sec triad    37841.36 (   0.00%)    42513.64 (  12.35%)
Pablo Greco 89a396
Pablo Greco 89a396
12threads stream (on 1NUMA * 24cores = 24cores)
Pablo Greco 89a396
                stream                 stream
Pablo Greco 89a396
                w/o patch              w/ patch
Pablo Greco 89a396
MB/sec copy     52639.82 (   0.00%)    53818.04 (   2.24%)
Pablo Greco 89a396
MB/sec scale    52350.30 (   0.00%)    53253.38 (   1.73%)
Pablo Greco 89a396
MB/sec add      53607.68 (   0.00%)    55198.82 (   2.97%)
Pablo Greco 89a396
MB/sec triad    54776.66 (   0.00%)    56360.40 (   2.89%)
Pablo Greco 89a396
Pablo Greco 89a396
Thus, it could help memory-bound workload especially under medium load.
Pablo Greco 89a396
Similar improvement is also seen in lkp-pbzip2:
Pablo Greco 89a396
Pablo Greco 89a396
* lkp-pbzip2 benchmark
Pablo Greco 89a396
Pablo Greco 89a396
2-96 threads (on 4NUMA * 24cores = 96cores)
Pablo Greco 89a396
                  lkp-pbzip2              lkp-pbzip2
Pablo Greco 89a396
                  w/o patch               w/ patch
Pablo Greco 89a396
Hmean     tput-2   11062841.57 (   0.00%)  11341817.51 *   2.52%*
Pablo Greco 89a396
Hmean     tput-5   26815503.70 (   0.00%)  27412872.65 *   2.23%*
Pablo Greco 89a396
Hmean     tput-8   41873782.21 (   0.00%)  43326212.92 *   3.47%*
Pablo Greco 89a396
Hmean     tput-12  61875980.48 (   0.00%)  64578337.51 *   4.37%*
Pablo Greco 89a396
Hmean     tput-21 105814963.07 (   0.00%) 111381851.01 *   5.26%*
Pablo Greco 89a396
Hmean     tput-30 150349470.98 (   0.00%) 156507070.73 *   4.10%*
Pablo Greco 89a396
Hmean     tput-48 237195937.69 (   0.00%) 242353597.17 *   2.17%*
Pablo Greco 89a396
Hmean     tput-79 360252509.37 (   0.00%) 362635169.23 *   0.66%*
Pablo Greco 89a396
Hmean     tput-96 394571737.90 (   0.00%) 400952978.48 *   1.62%*
Pablo Greco 89a396
Pablo Greco 89a396
2-24 threads (on 1NUMA * 24cores = 24cores)
Pablo Greco 89a396
                 lkp-pbzip2               lkp-pbzip2
Pablo Greco 89a396
                 w/o patch                w/ patch
Pablo Greco 89a396
Hmean     tput-2   11071705.49 (   0.00%)  11296869.10 *   2.03%*
Pablo Greco 89a396
Hmean     tput-4   20782165.19 (   0.00%)  21949232.15 *   5.62%*
Pablo Greco 89a396
Hmean     tput-6   30489565.14 (   0.00%)  33023026.96 *   8.31%*
Pablo Greco 89a396
Hmean     tput-8   40376495.80 (   0.00%)  42779286.27 *   5.95%*
Pablo Greco 89a396
Hmean     tput-12  61264033.85 (   0.00%)  62995632.78 *   2.83%*
Pablo Greco 89a396
Hmean     tput-18  86697139.39 (   0.00%)  86461545.74 (  -0.27%)
Pablo Greco 89a396
Hmean     tput-24 104854637.04 (   0.00%) 104522649.46 *  -0.32%*
Pablo Greco 89a396
Pablo Greco 89a396
In the case of 6 threads and 8 threads, we see the greatest performance
Pablo Greco 89a396
improvement.
Pablo Greco 89a396
Pablo Greco 89a396
Similar improvement can be seen on lkp-pixz though the improvement is
Pablo Greco 89a396
smaller:
Pablo Greco 89a396
Pablo Greco 89a396
* lkp-pixz benchmark
Pablo Greco 89a396
Pablo Greco 89a396
2-24 threads lkp-pixz (on 1NUMA * 24cores = 24cores)
Pablo Greco 89a396
                  lkp-pixz               lkp-pixz
Pablo Greco 89a396
                  w/o patch              w/ patch
Pablo Greco 89a396
Hmean     tput-2   6486981.16 (   0.00%)  6561515.98 *   1.15%*
Pablo Greco 89a396
Hmean     tput-4  11645766.38 (   0.00%) 11614628.43 (  -0.27%)
Pablo Greco 89a396
Hmean     tput-6  15429943.96 (   0.00%) 15957350.76 *   3.42%*
Pablo Greco 89a396
Hmean     tput-8  19974087.63 (   0.00%) 20413746.98 *   2.20%*
Pablo Greco 89a396
Hmean     tput-12 28172068.18 (   0.00%) 28751997.06 *   2.06%*
Pablo Greco 89a396
Hmean     tput-18 39413409.54 (   0.00%) 39896830.55 *   1.23%*
Pablo Greco 89a396
Hmean     tput-24 49101815.85 (   0.00%) 49418141.47 *   0.64%*
Pablo Greco 89a396
Pablo Greco 89a396
* SPECrate benchmark
Pablo Greco 89a396
Pablo Greco 89a396
4,8,16 copies mcf_r(on 1NUMA * 32cores = 32cores)
Pablo Greco 89a396
		Base     	 	Base
Pablo Greco 89a396
		Run Time   	 	Rate
Pablo Greco 89a396
		-------  	 	---------
Pablo Greco 89a396
4 Copies	w/o 580 (w/ 570)       	w/o 11.1 (w/ 11.3)
Pablo Greco 89a396
8 Copies	w/o 647 (w/ 605)       	w/o 20.0 (w/ 21.4, +7%)
Pablo Greco 89a396
16 Copies	w/o 844 (w/ 844)       	w/o 30.6 (w/ 30.6)
Pablo Greco 89a396
Pablo Greco 89a396
32 Copies(on 4NUMA * 32 cores = 128cores)
Pablo Greco 89a396
[w/o patch]
Pablo Greco 89a396
                 Base     Base        Base
Pablo Greco 89a396
Benchmarks       Copies  Run Time     Rate
Pablo Greco 89a396
--------------- -------  ---------  ---------
Pablo Greco 89a396
500.perlbench_r      32        584       87.2  *
Pablo Greco 89a396
502.gcc_r            32        503       90.2  *
Pablo Greco 89a396
505.mcf_r            32        745       69.4  *
Pablo Greco 89a396
520.omnetpp_r        32       1031       40.7  *
Pablo Greco 89a396
523.xalancbmk_r      32        597       56.6  *
Pablo Greco 89a396
525.x264_r            1         --            CE
Pablo Greco 89a396
531.deepsjeng_r      32        336      109    *
Pablo Greco 89a396
541.leela_r          32        556       95.4  *
Pablo Greco 89a396
548.exchange2_r      32        513      163    *
Pablo Greco 89a396
557.xz_r             32        530       65.2  *
Pablo Greco 89a396
 Est. SPECrate2017_int_base              80.3
Pablo Greco 89a396
Pablo Greco 89a396
[w/ patch]
Pablo Greco 89a396
                  Base     Base        Base
Pablo Greco 89a396
Benchmarks       Copies  Run Time     Rate
Pablo Greco 89a396
--------------- -------  ---------  ---------
Pablo Greco 89a396
500.perlbench_r      32        580      87.8 (+0.688%)  *
Pablo Greco 89a396
502.gcc_r            32        477      95.1 (+5.432%)  *
Pablo Greco 89a396
505.mcf_r            32        644      80.3 (+13.574%) *
Pablo Greco 89a396
520.omnetpp_r        32        942      44.6 (+9.58%)   *
Pablo Greco 89a396
523.xalancbmk_r      32        560      60.4 (+6.714%%) *
Pablo Greco 89a396
525.x264_r            1         --           CE
Pablo Greco 89a396
531.deepsjeng_r      32        337      109  (+0.000%) *
Pablo Greco 89a396
541.leela_r          32        554      95.6 (+0.210%) *
Pablo Greco 89a396
548.exchange2_r      32        515      163  (+0.000%) *
Pablo Greco 89a396
557.xz_r             32        524      66.0 (+1.227%) *
Pablo Greco 89a396
 Est. SPECrate2017_int_base              83.7 (+4.062%)
Pablo Greco 89a396
Pablo Greco 89a396
On the other hand, it is slightly helpful to CPU-bound tasks like
Pablo Greco 89a396
kernbench:
Pablo Greco 89a396
Pablo Greco 89a396
* 24-96 threads kernbench (on 4NUMA * 24cores = 96cores)
Pablo Greco 89a396
                     kernbench              kernbench
Pablo Greco 89a396
                     w/o cluster            w/ cluster
Pablo Greco 89a396
Min       user-24    12054.67 (   0.00%)    12024.19 (   0.25%)
Pablo Greco 89a396
Min       syst-24     1751.51 (   0.00%)     1731.68 (   1.13%)
Pablo Greco 89a396
Min       elsp-24      600.46 (   0.00%)      598.64 (   0.30%)
Pablo Greco 89a396
Min       user-48    12361.93 (   0.00%)    12315.32 (   0.38%)
Pablo Greco 89a396
Min       syst-48     1917.66 (   0.00%)     1892.73 (   1.30%)
Pablo Greco 89a396
Min       elsp-48      333.96 (   0.00%)      332.57 (   0.42%)
Pablo Greco 89a396
Min       user-96    12922.40 (   0.00%)    12921.17 (   0.01%)
Pablo Greco 89a396
Min       syst-96     2143.94 (   0.00%)     2110.39 (   1.56%)
Pablo Greco 89a396
Min       elsp-96      211.22 (   0.00%)      210.47 (   0.36%)
Pablo Greco 89a396
Amean     user-24    12063.99 (   0.00%)    12030.78 *   0.28%*
Pablo Greco 89a396
Amean     syst-24     1755.20 (   0.00%)     1735.53 *   1.12%*
Pablo Greco 89a396
Amean     elsp-24      601.60 (   0.00%)      600.19 (   0.23%)
Pablo Greco 89a396
Amean     user-48    12362.62 (   0.00%)    12315.56 *   0.38%*
Pablo Greco 89a396
Amean     syst-48     1921.59 (   0.00%)     1894.95 *   1.39%*
Pablo Greco 89a396
Amean     elsp-48      334.10 (   0.00%)      332.82 *   0.38%*
Pablo Greco 89a396
Amean     user-96    12925.27 (   0.00%)    12922.63 (   0.02%)
Pablo Greco 89a396
Amean     syst-96     2146.66 (   0.00%)     2122.20 *   1.14%*
Pablo Greco 89a396
Amean     elsp-96      211.96 (   0.00%)      211.79 (   0.08%)
Pablo Greco 89a396
Pablo Greco 89a396
Note this patch isn't an universal win, it might hurt those workload
Pablo Greco 89a396
which can benefit from packing. Though tasks which want to take
Pablo Greco 89a396
advantages of lower communication latency of one cluster won't
Pablo Greco 89a396
necessarily been packed in one cluster while kernel is not aware of
Pablo Greco 89a396
clusters, they have some chance to be randomly packed. But this
Pablo Greco 89a396
patch will make them more likely spread.
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Barry Song <song.bao.hua@hisilicon.com>
Pablo Greco 89a396
Tested-by: Yicong Yang <yangyicong@hisilicon.com>
Pablo Greco 89a396
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Pablo Greco 89a396
---
Pablo Greco 89a396
 arch/arm64/Kconfig             | 9 +++++++++
Pablo Greco 89a396
 include/linux/sched/topology.h | 7 +++++++
Pablo Greco 89a396
 include/linux/topology.h       | 7 +++++++
Pablo Greco 89a396
 kernel/sched/topology.c        | 5 +++++
Pablo Greco 89a396
 4 files changed, 28 insertions(+)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
Pablo Greco 1fd891
index 0758ea0717f9..359db6a4739e 100644
Pablo Greco 89a396
--- a/arch/arm64/Kconfig
Pablo Greco 89a396
+++ b/arch/arm64/Kconfig
Pablo Greco 89a396
@@ -989,6 +989,15 @@ config SCHED_MC
Pablo Greco 89a396
 	  making when dealing with multi-core CPU chips at a cost of slightly
Pablo Greco 89a396
 	  increased overhead in some places. If unsure say N here.
Pablo Greco 89a396
 
Pablo Greco 89a396
+config SCHED_CLUSTER
Pablo Greco 89a396
+	bool "Cluster scheduler support"
Pablo Greco 89a396
+	help
Pablo Greco 89a396
+	  Cluster scheduler support improves the CPU scheduler's decision
Pablo Greco 89a396
+	  making when dealing with machines that have clusters of CPUs.
Pablo Greco 89a396
+	  Cluster usually means a couple of CPUs which are placed closely
Pablo Greco 89a396
+	  by sharing mid-level caches, last-level cache tags or internal
Pablo Greco 89a396
+	  busses.
Pablo Greco 89a396
+
Pablo Greco 89a396
 config SCHED_SMT
Pablo Greco 89a396
 	bool "SMT scheduler support"
Pablo Greco 89a396
 	help
Pablo Greco 89a396
diff --git a/include/linux/sched/topology.h b/include/linux/sched/topology.h
Pablo Greco 89a396
index 8f0f778b7c91..2f9166f6dec8 100644
Pablo Greco 89a396
--- a/include/linux/sched/topology.h
Pablo Greco 89a396
+++ b/include/linux/sched/topology.h
Pablo Greco 89a396
@@ -42,6 +42,13 @@ static inline int cpu_smt_flags(void)
Pablo Greco 89a396
 }
Pablo Greco 89a396
 #endif
Pablo Greco 89a396
 
Pablo Greco 89a396
+#ifdef CONFIG_SCHED_CLUSTER
Pablo Greco 89a396
+static inline int cpu_cluster_flags(void)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	return SD_SHARE_PKG_RESOURCES;
Pablo Greco 89a396
+}
Pablo Greco 89a396
+#endif
Pablo Greco 89a396
+
Pablo Greco 89a396
 #ifdef CONFIG_SCHED_MC
Pablo Greco 89a396
 static inline int cpu_core_flags(void)
Pablo Greco 89a396
 {
Pablo Greco 89a396
diff --git a/include/linux/topology.h b/include/linux/topology.h
Pablo Greco 89a396
index 80d27d717631..0b3704ad13c8 100644
Pablo Greco 89a396
--- a/include/linux/topology.h
Pablo Greco 89a396
+++ b/include/linux/topology.h
Pablo Greco 89a396
@@ -212,6 +212,13 @@ static inline const struct cpumask *cpu_smt_mask(int cpu)
Pablo Greco 89a396
 }
Pablo Greco 89a396
 #endif
Pablo Greco 89a396
 
Pablo Greco 89a396
+#if defined(CONFIG_SCHED_CLUSTER) && !defined(cpu_cluster_mask)
Pablo Greco 89a396
+static inline const struct cpumask *cpu_cluster_mask(int cpu)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	return topology_cluster_cpumask(cpu);
Pablo Greco 89a396
+}
Pablo Greco 89a396
+#endif
Pablo Greco 89a396
+
Pablo Greco 89a396
 static inline const struct cpumask *cpu_cpu_mask(int cpu)
Pablo Greco 89a396
 {
Pablo Greco 89a396
 	return cpumask_of_node(cpu_to_node(cpu));
Pablo Greco 89a396
diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
Pablo Greco 89a396
index 4e8698e62f07..7d27559485ea 100644
Pablo Greco 89a396
--- a/kernel/sched/topology.c
Pablo Greco 89a396
+++ b/kernel/sched/topology.c
Pablo Greco 89a396
@@ -1627,6 +1627,11 @@ static struct sched_domain_topology_level default_topology[] = {
Pablo Greco 89a396
 #ifdef CONFIG_SCHED_SMT
Pablo Greco 89a396
 	{ cpu_smt_mask, cpu_smt_flags, SD_INIT_NAME(SMT) },
Pablo Greco 89a396
 #endif
Pablo Greco 89a396
+
Pablo Greco 89a396
+#ifdef CONFIG_SCHED_CLUSTER
Pablo Greco 89a396
+	{ cpu_clustergroup_mask, cpu_cluster_flags, SD_INIT_NAME(CLS) },
Pablo Greco 89a396
+#endif
Pablo Greco 89a396
+
Pablo Greco 89a396
 #ifdef CONFIG_SCHED_MC
Pablo Greco 89a396
 	{ cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) },
Pablo Greco 89a396
 #endif
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: Tim Chen <tim.c.chen@linux.intel.com>
Pablo Greco 89a396
Date: Fri, 24 Sep 2021 20:51:04 +1200
Pablo Greco 89a396
Subject: [PATCH 20/24] sched: Add cluster scheduler level for x86
Pablo Greco 89a396
Pablo Greco 89a396
There are x86 CPU architectures (e.g. Jacobsville) where L2 cahce is
Pablo Greco 89a396
shared among a cluster of cores instead of being exclusive to one
Pablo Greco 89a396
single core.
Pablo Greco 89a396
Pablo Greco 89a396
To prevent oversubscription of L2 cache, load should be balanced
Pablo Greco 89a396
between such L2 clusters, especially for tasks with no shared data.
Pablo Greco 89a396
On benchmark such as SPECrate mcf test, this change provides a boost
Pablo Greco 89a396
to performance especially on medium load system on Jacobsville.  on a
Pablo Greco 89a396
Jacobsville that has 24 Atom cores, arranged into 6 clusters of 4
Pablo Greco 89a396
cores each, the benchmark number is as follow:
Pablo Greco 89a396
Pablo Greco 89a396
 Improvement over baseline kernel for mcf_r
Pablo Greco 89a396
 copies		run time	base rate
Pablo Greco 89a396
 1		-0.1%		-0.2%
Pablo Greco 89a396
 6		25.1%		25.1%
Pablo Greco 89a396
 12		18.8%		19.0%
Pablo Greco 89a396
 24		0.3%		0.3%
Pablo Greco 89a396
Pablo Greco 89a396
So this looks pretty good. In terms of the system's task distribution,
Pablo Greco 89a396
some pretty bad clumping can be seen for the vanilla kernel without
Pablo Greco 89a396
the L2 cluster domain for the 6 and 12 copies case. With the extra
Pablo Greco 89a396
domain for cluster, the load does get evened out between the clusters.
Pablo Greco 89a396
Pablo Greco 89a396
Note this patch isn't an universal win as spreading isn't necessarily
Pablo Greco 89a396
a win, particually for those workload who can benefit from packing.
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Tim Chen <tim.c.chen@linux.intel.com>
Pablo Greco 89a396
Signed-off-by: Barry Song <song.bao.hua@hisilicon.com>
Pablo Greco 89a396
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Pablo Greco 89a396
Link: https://lore.kernel.org/r/20210924085104.44806-4-21cnbao@gmail.com
Pablo Greco 89a396
---
Pablo Greco 89a396
 arch/x86/Kconfig                | 11 +++++++++
Pablo Greco 89a396
 arch/x86/include/asm/smp.h      |  7 ++++++
Pablo Greco 89a396
 arch/x86/include/asm/topology.h |  3 +++
Pablo Greco 89a396
 arch/x86/kernel/cpu/cacheinfo.c |  1 +
Pablo Greco 89a396
 arch/x86/kernel/cpu/common.c    |  3 +++
Pablo Greco 89a396
 arch/x86/kernel/smpboot.c       | 44 ++++++++++++++++++++++++++++++++-
Pablo Greco 89a396
 6 files changed, 68 insertions(+), 1 deletion(-)
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
Pablo Greco 89a396
index 1f96809606ac..c5b8a428d0e7 100644
Pablo Greco 89a396
--- a/arch/x86/Kconfig
Pablo Greco 89a396
+++ b/arch/x86/Kconfig
Pablo Greco 89a396
@@ -1001,6 +1001,17 @@ config NR_CPUS
Pablo Greco 89a396
 	  This is purely to save memory: each supported CPU adds about 8KB
Pablo Greco 89a396
 	  to the kernel image.
Pablo Greco 89a396
 
Pablo Greco 89a396
+config SCHED_CLUSTER
Pablo Greco 89a396
+	bool "Cluster scheduler support"
Pablo Greco 89a396
+	depends on SMP
Pablo Greco 89a396
+	default y
Pablo Greco 89a396
+	help
Pablo Greco 89a396
+	  Cluster scheduler support improves the CPU scheduler's decision
Pablo Greco 89a396
+	  making when dealing with machines that have clusters of CPUs.
Pablo Greco 89a396
+	  Cluster usually means a couple of CPUs which are placed closely
Pablo Greco 89a396
+	  by sharing mid-level caches, last-level cache tags or internal
Pablo Greco 89a396
+	  busses.
Pablo Greco 89a396
+
Pablo Greco 89a396
 config SCHED_SMT
Pablo Greco 89a396
 	def_bool y if SMP
Pablo Greco 89a396
 
Pablo Greco 89a396
diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h
Pablo Greco 89a396
index 630ff08532be..08b0e90623ad 100644
Pablo Greco 89a396
--- a/arch/x86/include/asm/smp.h
Pablo Greco 89a396
+++ b/arch/x86/include/asm/smp.h
Pablo Greco 89a396
@@ -16,7 +16,9 @@ DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_core_map);
Pablo Greco 89a396
 DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_die_map);
Pablo Greco 89a396
 /* cpus sharing the last level cache: */
Pablo Greco 89a396
 DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map);
Pablo Greco 89a396
+DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_l2c_shared_map);
Pablo Greco 89a396
 DECLARE_PER_CPU_READ_MOSTLY(u16, cpu_llc_id);
Pablo Greco 89a396
+DECLARE_PER_CPU_READ_MOSTLY(u16, cpu_l2c_id);
Pablo Greco 89a396
 DECLARE_PER_CPU_READ_MOSTLY(int, cpu_number);
Pablo Greco 89a396
 
Pablo Greco 89a396
 static inline struct cpumask *cpu_llc_shared_mask(int cpu)
Pablo Greco 89a396
@@ -24,6 +26,11 @@ static inline struct cpumask *cpu_llc_shared_mask(int cpu)
Pablo Greco 89a396
 	return per_cpu(cpu_llc_shared_map, cpu);
Pablo Greco 89a396
 }
Pablo Greco 89a396
 
Pablo Greco 89a396
+static inline struct cpumask *cpu_l2c_shared_mask(int cpu)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	return per_cpu(cpu_l2c_shared_map, cpu);
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
 DECLARE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_cpu_to_apicid);
Pablo Greco 89a396
 DECLARE_EARLY_PER_CPU_READ_MOSTLY(u32, x86_cpu_to_acpiid);
Pablo Greco 89a396
 DECLARE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_bios_cpu_apicid);
Pablo Greco 89a396
diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
Pablo Greco 1fd891
index 55160445ea78..2f0b6be8eaab 100644
Pablo Greco 89a396
--- a/arch/x86/include/asm/topology.h
Pablo Greco 89a396
+++ b/arch/x86/include/asm/topology.h
Pablo Greco 89a396
@@ -103,6 +103,7 @@ static inline void setup_node_to_cpumask_map(void) { }
Pablo Greco 89a396
 #include <asm-generic/topology.h>
Pablo Greco 89a396
 
Pablo Greco 89a396
 extern const struct cpumask *cpu_coregroup_mask(int cpu);
Pablo Greco 89a396
+extern const struct cpumask *cpu_clustergroup_mask(int cpu);
Pablo Greco 89a396
 
Pablo Greco 89a396
 #define topology_logical_package_id(cpu)	(cpu_data(cpu).logical_proc_id)
Pablo Greco 89a396
 #define topology_physical_package_id(cpu)	(cpu_data(cpu).phys_proc_id)
Pablo Greco 89a396
@@ -113,7 +114,9 @@ extern const struct cpumask *cpu_coregroup_mask(int cpu);
Pablo Greco 89a396
 extern unsigned int __max_die_per_package;
Pablo Greco 89a396
 
Pablo Greco 89a396
 #ifdef CONFIG_SMP
Pablo Greco 89a396
+#define topology_cluster_id(cpu)		(per_cpu(cpu_l2c_id, cpu))
Pablo Greco 89a396
 #define topology_die_cpumask(cpu)		(per_cpu(cpu_die_map, cpu))
Pablo Greco 89a396
+#define topology_cluster_cpumask(cpu)		(cpu_clustergroup_mask(cpu))
Pablo Greco 89a396
 #define topology_core_cpumask(cpu)		(per_cpu(cpu_core_map, cpu))
Pablo Greco 89a396
 #define topology_sibling_cpumask(cpu)		(per_cpu(cpu_sibling_map, cpu))
Pablo Greco 89a396
 
Pablo Greco 89a396
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
Pablo Greco 89a396
index b5e36bd0425b..fe98a1465be6 100644
Pablo Greco 89a396
--- a/arch/x86/kernel/cpu/cacheinfo.c
Pablo Greco 89a396
+++ b/arch/x86/kernel/cpu/cacheinfo.c
Pablo Greco 89a396
@@ -846,6 +846,7 @@ void init_intel_cacheinfo(struct cpuinfo_x86 *c)
Pablo Greco 89a396
 		l2 = new_l2;
Pablo Greco 89a396
 #ifdef CONFIG_SMP
Pablo Greco 89a396
 		per_cpu(cpu_llc_id, cpu) = l2_id;
Pablo Greco 89a396
+		per_cpu(cpu_l2c_id, cpu) = l2_id;
Pablo Greco 89a396
 #endif
Pablo Greco 89a396
 	}
Pablo Greco 89a396
 
Pablo Greco 89a396
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
Pablo Greco 89a396
index 58b1416c05da..019ecf5b50ef 100644
Pablo Greco 89a396
--- a/arch/x86/kernel/cpu/common.c
Pablo Greco 89a396
+++ b/arch/x86/kernel/cpu/common.c
Pablo Greco 89a396
@@ -85,6 +85,9 @@ u16 get_llc_id(unsigned int cpu)
Pablo Greco 89a396
 }
Pablo Greco 89a396
 EXPORT_SYMBOL_GPL(get_llc_id);
Pablo Greco 89a396
 
Pablo Greco 89a396
+/* L2 cache ID of each logical CPU */
Pablo Greco 89a396
+DEFINE_PER_CPU_READ_MOSTLY(u16, cpu_l2c_id) = BAD_APICID;
Pablo Greco 89a396
+
Pablo Greco 89a396
 /* correctly size the local cpu masks */
Pablo Greco 89a396
 void __init setup_cpu_local_masks(void)
Pablo Greco 89a396
 {
Pablo Greco 89a396
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
Pablo Greco 89a396
index 85f6e242b6b4..5094ab0bae58 100644
Pablo Greco 89a396
--- a/arch/x86/kernel/smpboot.c
Pablo Greco 89a396
+++ b/arch/x86/kernel/smpboot.c
Pablo Greco 89a396
@@ -101,6 +101,8 @@ EXPORT_PER_CPU_SYMBOL(cpu_die_map);
Pablo Greco 89a396
 
Pablo Greco 89a396
 DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map);
Pablo Greco 89a396
 
Pablo Greco 89a396
+DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_l2c_shared_map);
Pablo Greco 89a396
+
Pablo Greco 89a396
 /* Per CPU bogomips and other parameters */
Pablo Greco 89a396
 DEFINE_PER_CPU_READ_MOSTLY(struct cpuinfo_x86, cpu_info);
Pablo Greco 89a396
 EXPORT_PER_CPU_SYMBOL(cpu_info);
Pablo Greco 89a396
@@ -464,6 +466,21 @@ static bool match_die(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
Pablo Greco 89a396
 	return false;
Pablo Greco 89a396
 }
Pablo Greco 89a396
 
Pablo Greco 89a396
+static bool match_l2c(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	int cpu1 = c->cpu_index, cpu2 = o->cpu_index;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	/* Do not match if we do not have a valid APICID for cpu: */
Pablo Greco 89a396
+	if (per_cpu(cpu_l2c_id, cpu1) == BAD_APICID)
Pablo Greco 89a396
+		return false;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	/* Do not match if L2 cache id does not match: */
Pablo Greco 89a396
+	if (per_cpu(cpu_l2c_id, cpu1) != per_cpu(cpu_l2c_id, cpu2))
Pablo Greco 89a396
+		return false;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	return topology_sane(c, o, "l2c");
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
 /*
Pablo Greco 89a396
  * Unlike the other levels, we do not enforce keeping a
Pablo Greco 89a396
  * multicore group inside a NUMA node.  If this happens, we will
Pablo Greco 89a396
@@ -523,7 +540,7 @@ static bool match_llc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
Pablo Greco 89a396
 }
Pablo Greco 89a396
 
Pablo Greco 89a396
 
Pablo Greco 89a396
-#if defined(CONFIG_SCHED_SMT) || defined(CONFIG_SCHED_MC)
Pablo Greco 89a396
+#if defined(CONFIG_SCHED_SMT) || defined(CONFIG_SCHED_CLUSTER) || defined(CONFIG_SCHED_MC)
Pablo Greco 89a396
 static inline int x86_sched_itmt_flags(void)
Pablo Greco 89a396
 {
Pablo Greco 89a396
 	return sysctl_sched_itmt_enabled ? SD_ASYM_PACKING : 0;
Pablo Greco 89a396
@@ -541,12 +558,21 @@ static int x86_smt_flags(void)
Pablo Greco 89a396
 	return cpu_smt_flags() | x86_sched_itmt_flags();
Pablo Greco 89a396
 }
Pablo Greco 89a396
 #endif
Pablo Greco 89a396
+#ifdef CONFIG_SCHED_CLUSTER
Pablo Greco 89a396
+static int x86_cluster_flags(void)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	return cpu_cluster_flags() | x86_sched_itmt_flags();
Pablo Greco 89a396
+}
Pablo Greco 89a396
+#endif
Pablo Greco 89a396
 #endif
Pablo Greco 89a396
 
Pablo Greco 89a396
 static struct sched_domain_topology_level x86_numa_in_package_topology[] = {
Pablo Greco 89a396
 #ifdef CONFIG_SCHED_SMT
Pablo Greco 89a396
 	{ cpu_smt_mask, x86_smt_flags, SD_INIT_NAME(SMT) },
Pablo Greco 89a396
 #endif
Pablo Greco 89a396
+#ifdef CONFIG_SCHED_CLUSTER
Pablo Greco 89a396
+	{ cpu_clustergroup_mask, x86_cluster_flags, SD_INIT_NAME(CLS) },
Pablo Greco 89a396
+#endif
Pablo Greco 89a396
 #ifdef CONFIG_SCHED_MC
Pablo Greco 89a396
 	{ cpu_coregroup_mask, x86_core_flags, SD_INIT_NAME(MC) },
Pablo Greco 89a396
 #endif
Pablo Greco 89a396
@@ -557,6 +583,9 @@ static struct sched_domain_topology_level x86_topology[] = {
Pablo Greco 89a396
 #ifdef CONFIG_SCHED_SMT
Pablo Greco 89a396
 	{ cpu_smt_mask, x86_smt_flags, SD_INIT_NAME(SMT) },
Pablo Greco 89a396
 #endif
Pablo Greco 89a396
+#ifdef CONFIG_SCHED_CLUSTER
Pablo Greco 89a396
+	{ cpu_clustergroup_mask, x86_cluster_flags, SD_INIT_NAME(CLS) },
Pablo Greco 89a396
+#endif
Pablo Greco 89a396
 #ifdef CONFIG_SCHED_MC
Pablo Greco 89a396
 	{ cpu_coregroup_mask, x86_core_flags, SD_INIT_NAME(MC) },
Pablo Greco 89a396
 #endif
Pablo Greco 89a396
@@ -584,6 +613,7 @@ void set_cpu_sibling_map(int cpu)
Pablo Greco 89a396
 	if (!has_mp) {
Pablo Greco 89a396
 		cpumask_set_cpu(cpu, topology_sibling_cpumask(cpu));
Pablo Greco 89a396
 		cpumask_set_cpu(cpu, cpu_llc_shared_mask(cpu));
Pablo Greco 89a396
+		cpumask_set_cpu(cpu, cpu_l2c_shared_mask(cpu));
Pablo Greco 89a396
 		cpumask_set_cpu(cpu, topology_core_cpumask(cpu));
Pablo Greco 89a396
 		cpumask_set_cpu(cpu, topology_die_cpumask(cpu));
Pablo Greco 89a396
 		c->booted_cores = 1;
Pablo Greco 89a396
@@ -602,6 +632,9 @@ void set_cpu_sibling_map(int cpu)
Pablo Greco 89a396
 		if ((i == cpu) || (has_mp && match_llc(c, o)))
Pablo Greco 89a396
 			link_mask(cpu_llc_shared_mask, cpu, i);
Pablo Greco 89a396
 
Pablo Greco 89a396
+		if ((i == cpu) || (has_mp && match_l2c(c, o)))
Pablo Greco 89a396
+			link_mask(cpu_l2c_shared_mask, cpu, i);
Pablo Greco 89a396
+
Pablo Greco 89a396
 		if ((i == cpu) || (has_mp && match_die(c, o)))
Pablo Greco 89a396
 			link_mask(topology_die_cpumask, cpu, i);
Pablo Greco 89a396
 	}
Pablo Greco 89a396
@@ -652,6 +685,11 @@ const struct cpumask *cpu_coregroup_mask(int cpu)
Pablo Greco 89a396
 	return cpu_llc_shared_mask(cpu);
Pablo Greco 89a396
 }
Pablo Greco 89a396
 
Pablo Greco 89a396
+const struct cpumask *cpu_clustergroup_mask(int cpu)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	return cpu_l2c_shared_mask(cpu);
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
 static void impress_friends(void)
Pablo Greco 89a396
 {
Pablo Greco 89a396
 	int cpu;
Pablo Greco 89a396
@@ -1335,6 +1373,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
Pablo Greco 89a396
 		zalloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL);
Pablo Greco 89a396
 		zalloc_cpumask_var(&per_cpu(cpu_die_map, i), GFP_KERNEL);
Pablo Greco 89a396
 		zalloc_cpumask_var(&per_cpu(cpu_llc_shared_map, i), GFP_KERNEL);
Pablo Greco 89a396
+		zalloc_cpumask_var(&per_cpu(cpu_l2c_shared_map, i), GFP_KERNEL);
Pablo Greco 89a396
 	}
Pablo Greco 89a396
 
Pablo Greco 89a396
 	/*
Pablo Greco 89a396
@@ -1564,7 +1603,10 @@ static void remove_siblinginfo(int cpu)
Pablo Greco 89a396
 
Pablo Greco 89a396
 	for_each_cpu(sibling, cpu_llc_shared_mask(cpu))
Pablo Greco 89a396
 		cpumask_clear_cpu(cpu, cpu_llc_shared_mask(sibling));
Pablo Greco 89a396
+	for_each_cpu(sibling, cpu_l2c_shared_mask(cpu))
Pablo Greco 89a396
+		cpumask_clear_cpu(cpu, cpu_l2c_shared_mask(sibling));
Pablo Greco 89a396
 	cpumask_clear(cpu_llc_shared_mask(cpu));
Pablo Greco 89a396
+	cpumask_clear(cpu_l2c_shared_mask(cpu));
Pablo Greco 89a396
 	cpumask_clear(topology_sibling_cpumask(cpu));
Pablo Greco 89a396
 	cpumask_clear(topology_core_cpumask(cpu));
Pablo Greco 89a396
 	cpumask_clear(topology_die_cpumask(cpu));
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, 10 Dec 2021 11:24:01 +0100
Pablo Greco 89a396
Subject: [PATCH 21/24] PCI: layerscape: Add LX2160a MCFG quirks for ECAM
Pablo Greco 89a396
 errata
Pablo Greco 89a396
Pablo Greco 89a396
The PCIe controller in Layerscape LX2160a SoC is not 100% ECAM-compliant.
Pablo Greco 89a396
For both V1 and V2 of the SOC which have different PCIe implementations
Pablo Greco 89a396
the devices behind the bus can be enumerated via ECAM, however the root
Pablo Greco 89a396
port is only accessible via the CCSR address space.
Pablo Greco 89a396
Pablo Greco 89a396
By default the firmware only exposes the devices so that most PCIe
Pablo Greco 89a396
devices will work out of the box on most distributions, however some
Pablo Greco 89a396
users may want to also have the root port exposed as well, especially
Pablo Greco 89a396
if working with SR-IOV. This quirk will work with the default firmware
Pablo Greco 89a396
as a normal ecam setup, but if the firmware exposes the root port as
Pablo Greco 89a396
bus 0 (the default) then this quirk will also allow access to a more
Pablo Greco 89a396
traditional PCIe layout.
Pablo Greco 89a396
Pablo Greco 89a396
Signed-off-by: Jon Nettleton <jon@solid-run.com>
Pablo Greco 89a396
---
Pablo Greco 89a396
 drivers/acpi/pci_mcfg.c                       | 10 +++
Pablo Greco 89a396
 drivers/pci/controller/Makefile               |  1 +
Pablo Greco 89a396
 drivers/pci/controller/pcie-layerscape-ecam.c | 89 +++++++++++++++++++
Pablo Greco 89a396
 include/linux/pci-ecam.h                      |  1 +
Pablo Greco 89a396
 4 files changed, 101 insertions(+)
Pablo Greco 89a396
 create mode 100644 drivers/pci/controller/pcie-layerscape-ecam.c
Pablo Greco 89a396
Pablo Greco 89a396
diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
Pablo Greco 89a396
index 53cab975f612..2fb54d5ceaf6 100644
Pablo Greco 89a396
--- a/drivers/acpi/pci_mcfg.c
Pablo Greco 89a396
+++ b/drivers/acpi/pci_mcfg.c
Pablo Greco 89a396
@@ -53,6 +53,16 @@ static struct mcfg_fixup mcfg_quirks[] = {
Pablo Greco 89a396
 	AL_ECAM("GRAVITON", 0, 6, &al_pcie_ops),
Pablo Greco 89a396
 	AL_ECAM("GRAVITON", 0, 7, &al_pcie_ops),
Pablo Greco 89a396
 
Pablo Greco 89a396
+#define NXP_ECAM(seg) \
Pablo Greco 89a396
+	{ "NXP   ", "LX2160  ", 0, seg, MCFG_BUS_ANY, &ls_pcie_ecam_ops }
Pablo Greco 89a396
+
Pablo Greco 89a396
+	NXP_ECAM(0),
Pablo Greco 89a396
+	NXP_ECAM(1),
Pablo Greco 89a396
+	NXP_ECAM(2),
Pablo Greco 89a396
+	NXP_ECAM(3),
Pablo Greco 89a396
+	NXP_ECAM(4),
Pablo Greco 89a396
+	NXP_ECAM(5),
Pablo Greco 89a396
+
Pablo Greco 89a396
 #define QCOM_ECAM32(seg) \
Pablo Greco 89a396
 	{ "QCOM  ", "QDF2432 ", 1, seg, MCFG_BUS_ANY, &pci_32b_ops }
Pablo Greco 89a396
 
Pablo Greco 89a396
diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
Pablo Greco 89a396
index aaf30b3dcc14..1bb8b5cdd6f8 100644
Pablo Greco 89a396
--- a/drivers/pci/controller/Makefile
Pablo Greco 89a396
+++ b/drivers/pci/controller/Makefile
Pablo Greco 89a396
@@ -54,6 +54,7 @@ obj-y				+= mobiveil/
Pablo Greco 89a396
 
Pablo Greco 89a396
 ifdef CONFIG_ACPI
Pablo Greco 89a396
 ifdef CONFIG_PCI_QUIRKS
Pablo Greco 89a396
+obj-$(CONFIG_ARM64) += pcie-layerscape-ecam.o
Pablo Greco 89a396
 obj-$(CONFIG_ARM64) += pci-thunder-ecam.o
Pablo Greco 89a396
 obj-$(CONFIG_ARM64) += pci-thunder-pem.o
Pablo Greco 89a396
 obj-$(CONFIG_ARM64) += pci-xgene.o
Pablo Greco 89a396
diff --git a/drivers/pci/controller/pcie-layerscape-ecam.c b/drivers/pci/controller/pcie-layerscape-ecam.c
Pablo Greco 89a396
new file mode 100644
Pablo Greco 89a396
index 000000000000..8ed303c47f2c
Pablo Greco 89a396
--- /dev/null
Pablo Greco 89a396
+++ b/drivers/pci/controller/pcie-layerscape-ecam.c
Pablo Greco 89a396
@@ -0,0 +1,89 @@
Pablo Greco 89a396
+// SPDX-License-Identifier: GPL-2.0
Pablo Greco 89a396
+/*
Pablo Greco 89a396
+ * PCIe ecam driver for NXP's Layerscape SOCs, adopted from
Pablo Greco 89a396
+ * Amazon's Graviton driver.
Pablo Greco 89a396
+ *
Pablo Greco 89a396
+ * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Pablo Greco 89a396
+ * Copyright 2021 SolidRun Ltd. All Rights Reserved.
Pablo Greco 89a396
+ *
Pablo Greco 89a396
+ * Author: Jonathan Chocron <jonnyc@amazon.com>
Pablo Greco 89a396
+ * Author: Jon Nettleton <jon@solid-run.com>
Pablo Greco 89a396
+ */
Pablo Greco 89a396
+
Pablo Greco 89a396
+#include <linux/pci.h>
Pablo Greco 89a396
+#include <linux/pci-ecam.h>
Pablo Greco 89a396
+#include <linux/pci-acpi.h>
Pablo Greco 89a396
+#include "../pci.h"
Pablo Greco 89a396
+
Pablo Greco 89a396
+#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
Pablo Greco 89a396
+
Pablo Greco 89a396
+struct ls_pcie_ecam  {
Pablo Greco 89a396
+	void __iomem *ccsr_base;
Pablo Greco 89a396
+};
Pablo Greco 89a396
+
Pablo Greco 89a396
+static void __iomem *ls_pcie_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
Pablo Greco 89a396
+				     int where)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	struct pci_config_window *cfg = bus->sysdata;
Pablo Greco 89a396
+	struct ls_pcie_ecam *pcie = cfg->priv;
Pablo Greco 89a396
+	void __iomem *ccsr_base = pcie->ccsr_base;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	if (bus->number == 0) {
Pablo Greco 89a396
+		/*
Pablo Greco 89a396
+		 *
Pablo Greco 89a396
+		 * No devices/functions on the root bus num, so we do this here.
Pablo Greco 89a396
+		 */
Pablo Greco 89a396
+		if (PCI_SLOT(devfn) > 0)
Pablo Greco 89a396
+			return NULL;
Pablo Greco 89a396
+		else
Pablo Greco 89a396
+			return ccsr_base + where;
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+
Pablo Greco 89a396
+	return pci_ecam_map_bus(bus, devfn, where);
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
+static int ls_pcie_ecam_init(struct pci_config_window *cfg)
Pablo Greco 89a396
+{
Pablo Greco 89a396
+	struct device *dev = cfg->parent;
Pablo Greco 89a396
+	struct acpi_device *adev = to_acpi_device(dev);
Pablo Greco 89a396
+	struct acpi_pci_root *root = acpi_driver_data(adev);
Pablo Greco 89a396
+	struct ls_pcie_ecam *ls_pcie;
Pablo Greco 89a396
+	struct resource *res;
Pablo Greco 89a396
+	int ret;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	ls_pcie = devm_kzalloc(dev, sizeof(*ls_pcie), GFP_KERNEL);
Pablo Greco 89a396
+	if (!ls_pcie)
Pablo Greco 89a396
+		return -ENOMEM;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
Pablo Greco 89a396
+	if (!res)
Pablo Greco 89a396
+		return -ENOMEM;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	ret = acpi_get_rc_resources(dev, "NXP0016", root->segment, res);
Pablo Greco 89a396
+	if (ret) {
Pablo Greco 89a396
+		dev_err(dev, "can't get rc csr base address for SEG %d\n",
Pablo Greco 89a396
+			root->segment);
Pablo Greco 89a396
+		return ret;
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+
Pablo Greco 89a396
+	dev_dbg(dev, "Root port ccsr res: %pR\n", res);
Pablo Greco 89a396
+
Pablo Greco 89a396
+	ls_pcie->ccsr_base = devm_pci_remap_cfg_resource(dev, res);
Pablo Greco 89a396
+	if (IS_ERR(ls_pcie->ccsr_base))
Pablo Greco 89a396
+		return PTR_ERR(ls_pcie->ccsr_base);
Pablo Greco 89a396
+
Pablo Greco 89a396
+	cfg->priv = ls_pcie;
Pablo Greco 89a396
+
Pablo Greco 89a396
+	return 0;
Pablo Greco 89a396
+}
Pablo Greco 89a396
+
Pablo Greco 89a396
+const struct pci_ecam_ops ls_pcie_ecam_ops = {
Pablo Greco 89a396
+	.init         =  ls_pcie_ecam_init,
Pablo Greco 89a396
+	.pci_ops      = {
Pablo Greco 89a396
+		.map_bus    = ls_pcie_ecam_map_bus,
Pablo Greco 89a396
+		.read       = pci_generic_config_read,
Pablo Greco 89a396
+		.write      = pci_generic_config_write,
Pablo Greco 89a396
+	}
Pablo Greco 89a396
+};
Pablo Greco 89a396
+
Pablo Greco 89a396
+#endif /* defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS) */
Pablo Greco 89a396
diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h
Pablo Greco 89a396
index adea5a4771cf..ab6c5c851976 100644
Pablo Greco 89a396
--- a/include/linux/pci-ecam.h
Pablo Greco 89a396
+++ b/include/linux/pci-ecam.h
Pablo Greco 89a396
@@ -87,6 +87,7 @@ extern const struct pci_ecam_ops xgene_v1_pcie_ecam_ops; /* APM X-Gene PCIe v1 *
Pablo Greco 89a396
 extern const struct pci_ecam_ops xgene_v2_pcie_ecam_ops; /* APM X-Gene PCIe v2.x */
Pablo Greco 89a396
 extern const struct pci_ecam_ops al_pcie_ops;	/* Amazon Annapurna Labs PCIe */
Pablo Greco 89a396
 extern const struct pci_ecam_ops tegra194_pcie_ops; /* Tegra194 PCIe */
Pablo Greco 89a396
+extern const struct pci_ecam_ops ls_pcie_ecam_ops;	/* NXP Layerscape LX2160a PCIe */
Pablo Greco 89a396
 #endif
Pablo Greco 89a396
 
Pablo Greco 89a396
 #if IS_ENABLED(CONFIG_PCI_HOST_COMMON)
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 89a396
Subject: [PATCH 22/24] 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 89a396
Subject: [PATCH 23/24] 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 89a396
Subject: [PATCH 24/24] 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