x86, AMD, NB: Cleanup and improve NB descriptors handling
Subsystems (3)
PATCH 1/1 x86, AMD, NB: Cleanup and improve NB descriptors handling
From: Borislav Petkov <[email protected]>
First of all, the double loop of first counting the northbridges on the system, then allocating them and then going over them again was bugging me for a long time now. Fix it by moving the allocation of the descriptors in the initial iteration path.
Then, modify the enclosing _info structure to contain two NB descriptor
structures: and array of 8 NB descs which contains the first 8 possible NB descriptors for all single-board AMD systems out there. This is no different from the current state of affairs and is done this way so that lookup of those descriptors remains fast.
Then, there's a linked list of further NB descs which are for large, confederated systems like NumaScale where more than 8 nodes are present in the fabric and are visible to the single system Linux image. We keep those unique by introducing the PCI domain ID into the node ID used for descriptor lookup.
Rest of the code is cleanup and readability improvements.
--- arch/x86/include/asm/amd_nb.h | 31 +++++++++++++++-- arch/x86/kernel/amd_nb.c | 79 +++++++++++++++++++++++++------------------ drivers/edac/amd64_edac.c | 6 ++-- drivers/edac/amd64_edac.h | 6 ---- 4 files changed, 78 insertions(+), 44 deletions(-)
arch/x86/include/asm/amd_nb.h +29 -2
@@ -4,6 +4,8 @@#include <linux/ioport.h> #include <linux/pci.h> +#define NUM_POSSIBLE_NBS 8 +struct amd_nb_bus_dev_range {u8 bus;u8 dev_base;
@@ -51,12 +53,22 @@ struct amd_northbridge {struct pci_dev *link;struct amd_l3_cache l3_cache;struct threshold_bank *bank4; +u32 node; +struct list_head nbl; };struct amd_northbridge_info {u16 num;u64 flags; -struct amd_northbridge *nb; + +/* +* The first 8 elems are for fast lookup of NB descriptors on single- +* system image setups, i.e. "normal" boxes. The nb_list, OTOH, is a +* list of additional NB descriptors which exist on confederate systems +* like NumaScale. +*/ +struct amd_northbridge *nbs[NUM_POSSIBLE_NBS ]; +struct list_head nb_list; };extern struct amd_northbridge_info amd_northbridges;
@@ -78,7 +90,22 @@ static inline bool amd_nb_has_feature(unsigned feature)static inline struct amd_northbridge *node_to_amd_nb (int node) { -return (node < amd_northbridges.num) ? &amd_northbridges.nb[node] :NULL ; +struct amd_northbridge_info *nbi = &amd_northbridges; +struct amd_northbridge *nb, *nb_tmp; + +if (node <NUM_POSSIBLE_NBS && node < nbi->num) +return nbi->nbs[node]; + +list_for_each_entry_safe (nb, nb_tmp, &nbi->nb_list, nbl) +if (node == nb->node) +return nb; + +return NULL ; +} + +static inline u32 amd_get_node_id (struct pci_dev *pdev) +{ +return (pci_domain_nr (pdev->bus) <<8 ) | (PCI_SLOT (pdev->devfn) -0x18 ); }#else
arch/x86/kernel/amd_nb.c +46 -33
104 lines not on this page · raw message
drivers/edac/amd64_edac.c +3 -3
@@ -2549,7 +2549,7 @@ static int amd64_init_one_instance(struct pci_dev *F2)struct mem_ctl_info *mci =NULL ;struct edac_mc_layer layers[2 ];int err =0 , ret; -u8 nid =get_node_id (F2 ); +u8 nid =amd_get_node_id (F2 ); ret = -ENOMEM ; pvt =kzalloc (sizeof (struct amd64_pvt ),GFP_KERNEL );
@@ -2640,7 +2640,7 @@ err_ret:static int __devinit amd64_probe_one_instance (struct pci_dev *pdev,const struct pci_device_id *mc_type) { -u8 nid =get_node_id (pdev); +u8 nid =amd_get_node_id (pdev);struct pci_dev *F3 =node_to_amd_nb (nid)->misc;struct ecc_settings *s;int ret =0 ;
@@ -2690,7 +2690,7 @@ static void __devexit amd64_remove_one_instance(struct pci_dev *pdev) {struct mem_ctl_info *mci;struct amd64_pvt *pvt; -u8 nid =get_node_id (pdev); +u8 nid =amd_get_node_id (pdev);struct pci_dev *F3 =node_to_amd_nb (nid)->misc;struct ecc_settings *s = ecc_stngs[nid];
drivers/edac/amd64_edac.h +0 -6
@@ -290,12 +290,6 @@/* MSRs */ #define MSR_MCGCTL_NBE BIT(4) -/* AMD sets the first MC device at device ID 0x18. */ -static inline u8 get_node_id (struct pci_dev *pdev) -{ -return PCI_SLOT (pdev->devfn) -0x18 ; -} -enum amd_families {K8_CPUS =0 ,F10_CPUS ,
Signature · 1 line
1.8.0.rc0.18.gf84667d
Quoted 13 lines · Borislav Petkov
From: Borislav Petkov <[email protected]>
First of all, the double loop of first counting the northbridges on the system, then allocating them and then going over them again was bugging me for a long time now. Fix it by moving the allocation of the descriptors in the initial iteration path.
Then, modify the enclosing
_infostructure to contain two NB descriptor
structures: and array of 8 NB descs which contains the first 8 possible NB descriptors for all single-board AMD systems out there. This is no different from the current state of affairs and is done this way so that lookup of those descriptors remains fast.
Quoted 7 lines
Then, there's a linked list of further NB descs which are for large, confederated systems like NumaScale where more than 8 nodes are present in the fabric and are visible to the single system Linux image. We keep those unique by introducing the PCI domain ID into the node ID used for descriptor lookup.
Rest of the code is cleanup and readability improvements.
[...]
Looks good.
I recall there were some other areas that needed fixing, so I'll rebase on top of this tomorrow and present my change so far.
Thanks,
Daniel
Signature · 2 lines
Daniel J Blueman Principal Software Engineer, Numascale Asia