EDAC, sb_edac: Fix reporting wrong DIMM when patrol scrubber finds error
Borislav Petkov
maintainerPATCH 3/3 EDAC, sb_edac: Fix reporting wrong DIMM when patrol scrubber finds error
Quoted 3 lines · Tony Luck
From: Qiuxu Zhuo <[email protected]>
EDAC driver sometimes reports the wrong DIMM for a memory
"EDAC driver"? Which one?
Please be more precise when writing your commit messages. They're not write-only.
Quoted 23 lines
error found by the patrol scrubber. It's rooted in h/w that only provides a 4KB page aligned address for the error case. This means that the EDAC driver will point at the DIMM matching offset
0x0in the 4KB page, but because of interleaving across channels and ranks the actual DIMM involved may be different if the error is on some other cache line within the page.For this error case, we could pass the socket/iMC/channel information from the "mce" structure passed the EDAC driver and "dimm=-1" to the EDAC core. So it will report all the DIMMs on that channel may be affected.
Signed-off-by Qiuxu Zhuo <[email protected]>Signed-off-by Tony Luck <[email protected]>--- drivers/edac/sb_edac.c | 95 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 6 deletions(-)drivers/edac/sb_edac.c +0
-0
drivers/edac/sb_edac.c struct sbridge_info { · line 329
Quoted 4 lines
drivers/edac/sb_edac.c +1
-0@@ -326,6 +326,7 @@ struct sbridge_info {const struct interleave_pkg *interleave_pkg;u8 max_sad;u8 (*get_node_id)(struct sbridge_pvt *pvt); +u8 (*get_ha)(u8 bank);
I'm staring at all this code and wondering what this "ha" is. I could use a comment somewhere...
Quoted 38 lines
drivers/edac/sb_edac.c +24
-0enum mem_type (*get_memory_type)(struct sbridge_pvt *pvt);enum dev_type (*get_width)(struct sbridge_pvt *pvt,u32 mtr);struct pci_dev *pci_vtd;@@ -1002,6 +1003,22 @@ static u8 knl_get_node_id(struct sbridge_pvt *pvt)return GET_BITFIELD (reg,0 ,2 ); } +static u8 sbridge_get_ha (u8 bank) +{ +return 0 ; +} + +static u8 ibridge_get_ha (u8 bank) +{ +switch (bank) { + case 7 ... 8: +return bank -7 ; + case 9 ... 16: +return (bank -9 ) /4 ; +default : +return -EINVAL ; + } +}static u64 haswell_get_tolm (struct sbridge_pvt *pvt) {@@ -2207,6 +2224,56 @@ static int get_memory_error_data(struct mem_ctl_info *mci,return 0 ; } +static int get_memory_error_data_from_mce (struct mem_ctl_info *mci, +const struct mce *m,u8 *socket, +u8 *ha,long *channel_mask, +char *msg) +{ +u32 reg, channel =GET_BITFIELD (m->status,0 ,3 ); +struct mem_ctl_info *new_mci; +struct sbridge_pvt *pvt;
drivers/edac/sb_edac.c static int get_memory_error_data(struct mem_ctl_info *mci, · line 2244
Quoted 10 lines
drivers/edac/sb_edac.c +10
-0+struct pci_dev *pci_ha; +bool tad0; + +if (channel >=NUM_CHANNELS ) { +sprintf (msg,"Invalid channel 0x%x" , channel); +return -EINVAL ; + } + + pvt = mci->pvt_info; + *ha = pvt->info.get_ha (m->bank);
You need to check the get_ha pointer before calling it because KNIGHTS_LANDING assigns NULL to it.