From b89dfc2fba02e75ae2bb0a2c21f7b6051271b0e6 Mon Sep 17 00:00:00 2001 From: zhongjiang-ali Date: Fri, 29 Aug 2025 20:38:35 +0800 Subject: [PATCH] anolis: mm: numa: establish a connection between gi_node and the device ANBZ: #24692 ACPI table record the relationship between gi_node and device bdf. Add a field in device to record the gi_node when pci device plug. hence the user can obtain the gi_node from specified device. Reviewed-by: Zelin Deng Reviewed-by: Wu Zongyong Reviewed-by: Baolin Wang Signed-off-by: zhongjiang-ali --- drivers/acpi/numa/srat.c | 18 ++++++++++++++++++ drivers/base/core.c | 1 + drivers/iommu/io-pgtable-arm.c | 7 ++++--- drivers/pci/pci-sysfs.c | 8 ++++++++ drivers/pci/probe.c | 33 +++++++++++++++++++++++++++++++++ include/acpi/acpi_numa.h | 1 + include/linux/device.h | 8 ++++++++ 7 files changed, 73 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/numa/srat.c b/drivers/acpi/numa/srat.c index 1dc1c66b8bdc..60b2fa03f79e 100644 --- a/drivers/acpi/numa/srat.c +++ b/drivers/acpi/numa/srat.c @@ -26,6 +26,9 @@ static int pxm_to_node_map[MAX_PXM_DOMAINS] static int node_to_pxm_map[MAX_NUMNODES] = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; +unsigned int node_to_bdf[MAX_NUMNODES] + = { [0 ... MAX_NUMNODES - 1] = NUMA_NO_NODE }; + unsigned char acpi_srat_revision __initdata; static int acpi_numa __initdata; @@ -433,6 +436,20 @@ acpi_parse_gicc_affinity(union acpi_subtable_headers *header, } #if defined(CONFIG_X86) || defined(CONFIG_ARM64) +static unsigned int get_bdf_from_srat_entry( + struct acpi_srat_generic_affinity *gi_affinity) +{ + unsigned int bdf; + int domain, bus, devfn; + + domain = *(u16 *)(&gi_affinity->device_handle[0]); + bus = *(u8 *)(&gi_affinity->device_handle[2]); + devfn = *(u8 *)(&gi_affinity->device_handle[3]); + + bdf = (domain << 16) | (bus << 8) | devfn; + return bdf; +} + static int __init acpi_parse_gi_affinity(union acpi_subtable_headers *header, const unsigned long end) @@ -455,6 +472,7 @@ acpi_parse_gi_affinity(union acpi_subtable_headers *header, } node_set(node, numa_nodes_parsed); node_set_state(node, N_GENERIC_INITIATOR); + node_to_bdf[node] = get_bdf_from_srat_entry(gi_affinity); return 0; } diff --git a/drivers/base/core.c b/drivers/base/core.c index cf97c75e27ad..a31a7997b7c4 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -3162,6 +3162,7 @@ void device_initialize(struct device *dev) INIT_LIST_HEAD(&dev->devres_head); device_pm_init(dev); set_dev_node(dev, NUMA_NO_NODE); + dev_gi_node_init(dev); INIT_LIST_HEAD(&dev->links.consumers); INIT_LIST_HEAD(&dev->links.suppliers); INIT_LIST_HEAD(&dev->links.defer_sync); diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index bc758ab70f49..1146d0e89885 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -1278,16 +1278,16 @@ static int __init arm_lpae_do_selftests(void) }; int i, j, pass = 0, fail = 0; - struct device dev; + struct device *dev = kmalloc(sizeof(struct device), GFP_KERNEL | __GFP_NOFAIL); struct io_pgtable_cfg cfg = { .tlb = &dummy_tlb_ops, .oas = 48, .coherent_walk = true, - .iommu_dev = &dev, + .iommu_dev = dev, }; /* __arm_lpae_alloc_pages() merely needs dev_to_node() to work */ - set_dev_node(&dev, NUMA_NO_NODE); + set_dev_node(dev, NUMA_NO_NODE); for (i = 0; i < ARRAY_SIZE(pgsize); ++i) { for (j = 0; j < ARRAY_SIZE(ias); ++j) { @@ -1302,6 +1302,7 @@ static int __init arm_lpae_do_selftests(void) } } + kfree(dev); pr_info("selftest: completed with %d PASS %d FAIL\n", pass, fail); return fail ? -EFAULT : 0; } diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 92e8ac85f58e..fa5c1eed7bcb 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -361,6 +361,13 @@ static ssize_t numa_node_show(struct device *dev, struct device_attribute *attr, return sysfs_emit(buf, "%d\n", dev->numa_node); } static DEVICE_ATTR_RW(numa_node); + +static ssize_t gi_node_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%*pbl\n", nodemask_pr_args(&dev->gi_node)); +} +static DEVICE_ATTR_RO(gi_node); #endif static ssize_t dma_mask_bits_show(struct device *dev, @@ -626,6 +633,7 @@ static struct attribute *pci_dev_attrs[] = { &dev_attr_modalias.attr, #ifdef CONFIG_NUMA &dev_attr_numa_node.attr, + &dev_attr_gi_node.attr, #endif &dev_attr_dma_mask_bits.attr, &dev_attr_consistent_dma_mask_bits.attr, diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index e9efc21a847d..bfab2fd8c18f 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "pci.h" #ifdef CONFIG_PSWIOTLB #include @@ -2520,6 +2521,37 @@ static void pci_set_msi_domain(struct pci_dev *dev) dev_set_msi_domain(&dev->dev, d); } +static void get_gi_node_by_bdf(struct device *dev, unsigned int bdf) +{ + int nid; + + for (nid = 0; nid < MAX_NUMNODES; nid++) { + if (node_to_bdf[nid] == bdf) + node_set(nid, dev->gi_node); + } +} + +static unsigned int pci_bdf_to_int(struct device *device) +{ + struct pci_dev *dev = to_pci_dev(device); + int domain, bus, slot, func; + + domain = pci_domain_nr(dev->bus); + bus = dev->bus->number; + slot = PCI_SLOT(dev->devfn); + func = PCI_FUNC(dev->devfn); + + return (domain << 16) | (bus << 8) | (slot << 3) | func; +} + +static void pci_set_gi_node(struct device *dev) +{ + unsigned int bdf_value; + + bdf_value = pci_bdf_to_int(dev); + get_gi_node_by_bdf(dev, bdf_value); +} + void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) { int ret; @@ -2530,6 +2562,7 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) dev->dev.release = pci_release_dev; set_dev_node(&dev->dev, pcibus_to_node(bus)); + pci_set_gi_node(&dev->dev); dev->dev.dma_mask = &dev->dma_mask; dev->dev.dma_parms = &dev->dma_parms; dev->dev.coherent_dma_mask = 0xffffffffull; diff --git a/include/acpi/acpi_numa.h b/include/acpi/acpi_numa.h index b5f594754a9e..25cbc7d5b8d9 100644 --- a/include/acpi/acpi_numa.h +++ b/include/acpi/acpi_numa.h @@ -18,6 +18,7 @@ extern int acpi_map_pxm_to_node(int); extern unsigned char acpi_srat_revision; extern void disable_srat(void); +extern unsigned int node_to_bdf[MAX_NUMNODES]; extern void bad_srat(void); extern int srat_disabled(void); diff --git a/include/linux/device.h b/include/linux/device.h index 4e2cd21e9f5e..5c7d4729369b 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -781,6 +781,7 @@ struct device { #ifdef CONFIG_NUMA int numa_node; /* NUMA node this device is close to */ + nodemask_t gi_node; /* GPU gi node the device is close to */ #ifdef CONFIG_PSWIOTLB int local_node; /* NUMA node this device is really belong to */ #endif @@ -914,6 +915,10 @@ static inline void set_dev_node(struct device *dev, int node) { dev->numa_node = node; } +static inline void dev_gi_node_init(struct device *dev) +{ + dev->gi_node = NODE_MASK_NONE; +} #else static inline int dev_to_node(struct device *dev) { @@ -922,6 +927,9 @@ static inline int dev_to_node(struct device *dev) static inline void set_dev_node(struct device *dev, int node) { } +static inline void dev_gi_node_init(struct device *dev) +{ +} #endif static inline struct irq_domain *dev_get_msi_domain(const struct device *dev) -- Gitee