On Fri, Nov 02, 2018 at 06:11:07PM +0000, Woods, Brian wrote: > Add support for new processors which have multiple PCI root complexes > per data fabric/SMN interface. The interfaces per root complex are > redundant and should be skipped. This makes sure the DF/SMN interfaces > get accessed via the correct root complex. SMN? > Ex: > DF/SMN 0 -> 60 > 40 > 20 > 00 > DF/SMN 1 -> e0 > c0 > a0 > 80 This isn't my code, and I'm not really objecting to these changes, but from where I sit, the fact that you need this sort of vendor-specific topology discovery is a little bit ugly and seems like something of a maintenance issue. You could argue that this is sort of an "AMD CPU driver", which is entitled to be device-specific, and that does make some sense. But device-specific code is typically packaged as a driver that uses driver registration interfaces like acpi_bus_register_driver(), pci_register_driver(), etc. That gives you a consistent structure and, more importantly, a framework for dealing with hotplug. It doesn't look like amd_nb.c would deal well with hot-add of CPUs. > Signed-off-by: Brian Woods <brian.woods@xxxxxxx> > --- > arch/x86/kernel/amd_nb.c | 41 +++++++++++++++++++++++++++++++++++------ > 1 file changed, 35 insertions(+), 6 deletions(-) > > diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c > index 19d489ee2b1e..c0bf26aeb7c3 100644 > --- a/arch/x86/kernel/amd_nb.c > +++ b/arch/x86/kernel/amd_nb.c > @@ -213,7 +213,10 @@ int amd_cache_northbridges(void) > const struct pci_device_id *root_ids = amd_root_ids; > struct pci_dev *root, *misc, *link; > struct amd_northbridge *nb; > - u16 i = 0; > + u16 roots_per_misc = 0; > + u16 misc_count = 0; > + u16 root_count = 0; > + u16 i, j; > > if (amd_northbridges.num) > return 0; > @@ -226,26 +229,52 @@ int amd_cache_northbridges(void) > > misc = NULL; > while ((misc = next_northbridge(misc, misc_ids)) != NULL) > - i++; > + misc_count++; > > - if (!i) > + root = NULL; > + while ((root = next_northbridge(root, root_ids)) != NULL) > + root_count++; > + > + if (!misc_count) > return -ENODEV; > > - nb = kcalloc(i, sizeof(struct amd_northbridge), GFP_KERNEL); > + if (root_count) { > + roots_per_misc = root_count / misc_count; > + > + /* > + * There should be _exactly_ N roots for each DF/SMN > + * interface. > + */ > + if (!roots_per_misc || (root_count % roots_per_misc)) { > + pr_info("Unsupported AMD DF/PCI configuration found\n"); > + return -ENODEV; > + } > + } > + > + nb = kcalloc(misc_count, sizeof(struct amd_northbridge), GFP_KERNEL); > if (!nb) > return -ENOMEM; > > amd_northbridges.nb = nb; > - amd_northbridges.num = i; > + amd_northbridges.num = misc_count; > > link = misc = root = NULL; > - for (i = 0; i != amd_northbridges.num; i++) { > + for (i = 0; i < amd_northbridges.num; i++) { > node_to_amd_nb(i)->root = root = > next_northbridge(root, root_ids); > node_to_amd_nb(i)->misc = misc = > next_northbridge(misc, misc_ids); > node_to_amd_nb(i)->link = link = > next_northbridge(link, link_ids); > + > + /* > + * If there are more root devices than data fabric/SMN, > + * interfaces, then the root devices per DF/SMN > + * interface are redundant and N-1 should be skipped so > + * they aren't mapped incorrectly. > + */ > + for (j = 1; j < roots_per_misc; j++) > + root = next_northbridge(root, root_ids); > } > > if (amd_gart_present()) > -- > 2.11.0 >