diff options
-rw-r--r-- | drivers/edac/amd76x_edac.c | 91 | ||||
-rw-r--r-- | drivers/edac/e752x_edac.c | 234 | ||||
-rw-r--r-- | drivers/edac/e7xxx_edac.c | 165 | ||||
-rw-r--r-- | drivers/edac/edac_mc.c | 325 | ||||
-rw-r--r-- | drivers/edac/edac_mc.h | 96 | ||||
-rw-r--r-- | drivers/edac/i82860_edac.c | 66 | ||||
-rw-r--r-- | drivers/edac/i82875p_edac.c | 112 | ||||
-rw-r--r-- | drivers/edac/r82600_edac.c | 71 |
8 files changed, 558 insertions, 602 deletions
diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index 87bd8b4d561..53423ad6d4a 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -12,33 +12,26 @@ * */ - #include <linux/config.h> #include <linux/module.h> #include <linux/init.h> - #include <linux/pci.h> #include <linux/pci_ids.h> - #include <linux/slab.h> - #include "edac_mc.h" - #define amd76x_printk(level, fmt, arg...) \ - edac_printk(level, "amd76x", fmt, ##arg) - + edac_printk(level, "amd76x", fmt, ##arg) #define amd76x_mc_printk(mci, level, fmt, arg...) \ - edac_mc_chipset_printk(mci, level, "amd76x", fmt, ##arg) - + edac_mc_chipset_printk(mci, level, "amd76x", fmt, ##arg) #define AMD76X_NR_CSROWS 8 #define AMD76X_NR_CHANS 1 #define AMD76X_NR_DIMMS 4 - /* AMD 76x register addresses - device 0 function 0 - PCI bridge */ + #define AMD76X_ECC_MODE_STATUS 0x48 /* Mode and status of ECC (32b) * * 31:16 reserved @@ -50,6 +43,7 @@ * 7:4 UE cs row * 3:0 CE cs row */ + #define AMD76X_DRAM_MODE_STATUS 0x58 /* DRAM Mode and status (32b) * * 31:26 clock disable 5 - 0 @@ -64,6 +58,7 @@ * 15:8 reserved * 7:0 x4 mode enable 7 - 0 */ + #define AMD76X_MEM_BASE_ADDR 0xC0 /* Memory base address (8 x 32b) * * 31:23 chip-select base @@ -74,29 +69,28 @@ * 0 chip-select enable */ - struct amd76x_error_info { u32 ecc_mode_status; }; - enum amd76x_chips { AMD761 = 0, AMD762 }; - struct amd76x_dev_info { const char *ctl_name; }; - static const struct amd76x_dev_info amd76x_devs[] = { - [AMD761] = {.ctl_name = "AMD761"}, - [AMD762] = {.ctl_name = "AMD762"}, + [AMD761] = { + .ctl_name = "AMD761" + }, + [AMD762] = { + .ctl_name = "AMD762" + }, }; - /** * amd76x_get_error_info - fetch error information * @mci: Memory controller @@ -105,23 +99,21 @@ static const struct amd76x_dev_info amd76x_devs[] = { * Fetch and store the AMD76x ECC status. Clear pending status * on the chip so that further errors will be reported */ - -static void amd76x_get_error_info (struct mem_ctl_info *mci, - struct amd76x_error_info *info) +static void amd76x_get_error_info(struct mem_ctl_info *mci, + struct amd76x_error_info *info) { pci_read_config_dword(mci->pdev, AMD76X_ECC_MODE_STATUS, &info->ecc_mode_status); if (info->ecc_mode_status & BIT(8)) pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS, - (u32) BIT(8), (u32) BIT(8)); + (u32) BIT(8), (u32) BIT(8)); if (info->ecc_mode_status & BIT(9)) pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS, - (u32) BIT(9), (u32) BIT(9)); + (u32) BIT(9), (u32) BIT(9)); } - /** * amd76x_process_error_info - Error check * @mci: Memory controller @@ -132,8 +124,7 @@ static void amd76x_get_error_info (struct mem_ctl_info *mci, * A return of 1 indicates an error. Also if handle_errors is true * then attempt to handle and clean up after the error */ - -static int amd76x_process_error_info (struct mem_ctl_info *mci, +static int amd76x_process_error_info(struct mem_ctl_info *mci, struct amd76x_error_info *info, int handle_errors) { int error_found; @@ -149,9 +140,8 @@ static int amd76x_process_error_info (struct mem_ctl_info *mci, if (handle_errors) { row = (info->ecc_mode_status >> 4) & 0xf; - edac_mc_handle_ue(mci, - mci->csrows[row].first_page, 0, row, - mci->ctl_name); + edac_mc_handle_ue(mci, mci->csrows[row].first_page, 0, + row, mci->ctl_name); } } @@ -163,11 +153,11 @@ static int amd76x_process_error_info (struct mem_ctl_info *mci, if (handle_errors) { row = info->ecc_mode_status & 0xf; - edac_mc_handle_ce(mci, - mci->csrows[row].first_page, 0, 0, row, 0, - mci->ctl_name); + edac_mc_handle_ce(mci, mci->csrows[row].first_page, 0, + 0, row, 0, mci->ctl_name); } } + return error_found; } @@ -178,7 +168,6 @@ static int amd76x_process_error_info (struct mem_ctl_info *mci, * Called by the poll handlers this function reads the status * from the controller and checks for errors. */ - static void amd76x_check(struct mem_ctl_info *mci) { struct amd76x_error_info info; @@ -187,7 +176,6 @@ static void amd76x_check(struct mem_ctl_info *mci) amd76x_process_error_info(mci, &info, 1); } - /** * amd76x_probe1 - Perform set up for detected device * @pdev; PCI device detected @@ -197,7 +185,6 @@ static void amd76x_check(struct mem_ctl_info *mci) * controller status reporting. We configure and set up the * memory controller reporting and claim the device. */ - static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) { int rc = -ENODEV; @@ -214,10 +201,8 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) struct amd76x_error_info discard; debugf0("%s()\n", __func__); - pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, &ems); ems_mode = (ems >> 10) & 0x3; - mci = edac_mc_alloc(0, AMD76X_NR_CSROWS, AMD76X_NR_CHANS); if (mci == NULL) { @@ -226,14 +211,11 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) } debugf0("%s(): mci = %p\n", __func__, mci); - mci->pdev = pdev; mci->mtype_cap = MEM_FLAG_RDDR; - mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; mci->edac_cap = ems_mode ? - (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE; - + (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE; mci->mod_name = EDAC_MOD_STR; mci->mod_ver = "$Revision: 1.4.2.5 $"; mci->ctl_name = amd76x_devs[dev_idx].ctl_name; @@ -249,18 +231,15 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) /* find the DRAM Chip Select Base address and mask */ pci_read_config_dword(mci->pdev, - AMD76X_MEM_BASE_ADDR + (index * 4), - &mba); + AMD76X_MEM_BASE_ADDR + (index * 4), &mba); if (!(mba & BIT(0))) continue; mba_base = mba & 0xff800000UL; mba_mask = ((mba & 0xff80) << 16) | 0x7fffffUL; - pci_read_config_dword(mci->pdev, AMD76X_DRAM_MODE_STATUS, - &dms); - + &dms); csrow->first_page = mba_base >> PAGE_SHIFT; csrow->nr_pages = (mba_mask + 1) >> PAGE_SHIFT; csrow->last_page = csrow->first_page + csrow->nr_pages - 1; @@ -290,7 +269,7 @@ fail: /* returns count (>= 0), or negative on error */ static int __devinit amd76x_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { debugf0("%s()\n", __func__); @@ -298,7 +277,6 @@ static int __devinit amd76x_init_one(struct pci_dev *pdev, return amd76x_probe1(pdev, ent->driver_data); } - /** * amd76x_remove_one - driver shutdown * @pdev: PCI device being handed back @@ -307,7 +285,6 @@ static int __devinit amd76x_init_one(struct pci_dev *pdev, * structure for the device then delete the mci and free the * resources. */ - static void __devexit amd76x_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; @@ -320,18 +297,22 @@ static void __devexit amd76x_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } - static const struct pci_device_id amd76x_pci_tbl[] __devinitdata = { - {PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - AMD762}, - {PCI_VEND_DEV(AMD, FE_GATE_700E), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - AMD761}, - {0,} /* 0 terminated list. */ + { + PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + AMD762 + }, + { + PCI_VEND_DEV(AMD, FE_GATE_700E), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + AMD761 + }, + { + 0, + } /* 0 terminated list. */ }; MODULE_DEVICE_TABLE(pci, amd76x_pci_tbl); - static struct pci_driver amd76x_driver = { .name = EDAC_MOD_STR, .probe = amd76x_init_one, diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index c86db23d3af..265cce72497 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -17,26 +17,19 @@ * */ - #include <linux/config.h> #include <linux/module.h> #include <linux/init.h> - #include <linux/pci.h> #include <linux/pci_ids.h> - #include <linux/slab.h> - #include "edac_mc.h" - #define e752x_printk(level, fmt, arg...) \ - edac_printk(level, "e752x", fmt, ##arg) - + edac_printk(level, "e752x", fmt, ##arg) #define e752x_mc_printk(mci, level, fmt, arg...) \ - edac_mc_chipset_printk(mci, level, "e752x", fmt, ##arg) - + edac_mc_chipset_printk(mci, level, "e752x", fmt, ##arg) #ifndef PCI_DEVICE_ID_INTEL_7520_0 #define PCI_DEVICE_ID_INTEL_7520_0 0x3590 @@ -64,7 +57,6 @@ #define E752X_NR_CSROWS 8 /* number of csrows */ - /* E752X register addresses - device 0 function 0 */ #define E752X_DRB 0x60 /* DRAM row boundary register (8b) */ #define E752X_DRA 0x70 /* DRAM row attribute register (8b) */ @@ -164,7 +156,6 @@ enum e752x_chips { E7320 = 2 }; - struct e752x_pvt { struct pci_dev *bridge_ck; struct pci_dev *dev_d0f0; @@ -178,7 +169,6 @@ struct e752x_pvt { const struct e752x_dev_info *dev_info; }; - struct e752x_dev_info { u16 err_dev; u16 ctl_dev; @@ -207,22 +197,24 @@ struct e752x_error_info { static const struct e752x_dev_info e752x_devs[] = { [E7520] = { - .err_dev = PCI_DEVICE_ID_INTEL_7520_1_ERR, - .ctl_dev = PCI_DEVICE_ID_INTEL_7520_0, - .ctl_name = "E7520"}, + .err_dev = PCI_DEVICE_ID_INTEL_7520_1_ERR, + .ctl_dev = PCI_DEVICE_ID_INTEL_7520_0, + .ctl_name = "E7520" + }, [E7525] = { - .err_dev = PCI_DEVICE_ID_INTEL_7525_1_ERR, - .ctl_dev = PCI_DEVICE_ID_INTEL_7525_0, - .ctl_name = "E7525"}, + .err_dev = PCI_DEVICE_ID_INTEL_7525_1_ERR, + .ctl_dev = PCI_DEVICE_ID_INTEL_7525_0, + .ctl_name = "E7525" + }, [E7320] = { - .err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR, - .ctl_dev = PCI_DEVICE_ID_INTEL_7320_0, - .ctl_name = "E7320"}, + .err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR, + .ctl_dev = PCI_DEVICE_ID_INTEL_7320_0, + .ctl_name = "E7320" + }, }; - static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, - unsigned long page) + unsigned long page) { u32 remap; struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; @@ -231,17 +223,21 @@ static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, if (page < pvt->tolm) return page; + if ((page >= 0x100000) && (page < pvt->remapbase)) return page; + remap = (page - pvt->tolm) + pvt->remapbase; + if (remap < pvt->remaplimit) return remap; + e752x_printk(KERN_ERR, "Invalid page %lx - out of range\n", page); return pvt->tolm - 1; } static void do_process_ce(struct mem_ctl_info *mci, u16 error_one, - u32 sec1_add, u16 sec1_syndrome) + u32 sec1_add, u16 sec1_syndrome) { u32 page; int row; @@ -259,34 +255,36 @@ static void do_process_ce(struct mem_ctl_info *mci, u16 error_one, /* chip select are bits 14 & 13 */ row = ((page >> 1) & 3); e752x_printk(KERN_WARNING, - "Test row %d Table %d %d %d %d %d %d %d %d\n", - row, pvt->map[0], pvt->map[1], pvt->map[2], - pvt->map[3], pvt->map[4], pvt->map[5], - pvt->map[6], pvt->map[7]); + "Test row %d Table %d %d %d %d %d %d %d %d\n", row, + pvt->map[0], pvt->map[1], pvt->map[2], pvt->map[3], + pvt->map[4], pvt->map[5], pvt->map[6], pvt->map[7]); /* test for channel remapping */ for (i = 0; i < 8; i++) { if (pvt->map[i] == row) break; } + e752x_printk(KERN_WARNING, "Test computed row %d\n", i); + if (i < 8) row = i; else e752x_mc_printk(mci, KERN_WARNING, - "row %d not found in remap table\n", row); + "row %d not found in remap table\n", row); } else row = edac_mc_find_csrow_by_page(mci, page); + /* 0 = channel A, 1 = channel B */ channel = !(error_one & 1); if (!pvt->map_type) row = 7 - row; + edac_mc_handle_ce(mci, page, 0, sec1_syndrome, row, channel, - "e752x CE"); + "e752x CE"); } - static inline void process_ce(struct mem_ctl_info *mci, u16 error_one, u32 sec1_add, u16 sec1_syndrome, int *error_found, int handle_error) @@ -297,8 +295,8 @@ static inline void process_ce(struct mem_ctl_info *mci, u16 error_one, do_process_ce(mci, error_one, sec1_add, sec1_syndrome); } -static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, u32 ded_add, - u32 scrb_add) +static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, + u32 ded_add, u32 scrb_add) { u32 error_2b, block_page; int row; @@ -308,25 +306,31 @@ static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, u32 ded_add, if (error_one & 0x0202) { error_2b = ded_add; + /* convert to 4k address */ block_page = error_2b >> (PAGE_SHIFT - 4); + row = pvt->mc_symmetric ? - /* chip select are bits 14 & 13 */ - ((block_page >> 1) & 3) : - edac_mc_find_csrow_by_page(mci, block_page); + /* chip select are bits 14 & 13 */ + ((block_page >> 1) & 3) : + edac_mc_find_csrow_by_page(mci, block_page); + edac_mc_handle_ue(mci, block_page, 0, row, - "e752x UE from Read"); + "e752x UE from Read"); } if (error_one & 0x0404) { error_2b = scrb_add; + /* convert to 4k address */ block_page = error_2b >> (PAGE_SHIFT - 4); + row = pvt->mc_symmetric ? - /* chip select are bits 14 & 13 */ - ((block_page >> 1) & 3) : - edac_mc_find_csrow_by_page(mci, block_page); + /* chip select are bits 14 & 13 */ + ((block_page >> 1) & 3) : + edac_mc_find_csrow_by_page(mci, block_page); + edac_mc_handle_ue(mci, block_page, 0, row, - "e752x UE from Scruber"); + "e752x UE from Scruber"); } } @@ -359,13 +363,13 @@ static void do_process_ded_retry(struct mem_ctl_info *mci, u16 error, struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; error_1b = retry_add; - page = error_1b >> (PAGE_SHIFT - 4); /* convert the addr to 4k page */ + page = error_1b >> (PAGE_SHIFT - 4); /* convert the addr to 4k page */ row = pvt->mc_symmetric ? - ((page >> 1) & 3) : /* chip select are bits 14 & 13 */ - edac_mc_find_csrow_by_page(mci, page); + ((page >> 1) & 3) : /* chip select are bits 14 & 13 */ + edac_mc_find_csrow_by_page(mci, page); e752x_mc_printk(mci, KERN_WARNING, - "CE page 0x%lx, row %d : Memory read retry\n", - (long unsigned int) page, row); + "CE page 0x%lx, row %d : Memory read retry\n", + (long unsigned int) page, row); } static inline void process_ded_retry(struct mem_ctl_info *mci, u16 error, @@ -402,7 +406,7 @@ static void do_global_error(int fatal, u32 errors) for (i = 0; i < 11; i++) { if (errors & (1 << i)) e752x_printk(KERN_WARNING, "%sError %s\n", - fatal_message[fatal], global_message[i]); + fatal_message[fatal], global_message[i]); } } @@ -429,7 +433,7 @@ static void do_hub_error(int fatal, u8 errors) for (i = 0; i < 7; i++) { if (errors & (1 << i)) e752x_printk(KERN_WARNING, "%sError %s\n", - fatal_message[fatal], hub_message[i]); + fatal_message[fatal], hub_message[i]); } } @@ -456,7 +460,7 @@ static void do_membuf_error(u8 errors) for (i = 0; i < 4; i++) { if (errors & (1 << i)) e752x_printk(KERN_WARNING, "Non-Fatal Error %s\n", - membuf_message[i]); + membuf_message[i]); } } @@ -489,7 +493,7 @@ static void do_sysbus_error(int fatal, u32 errors) for (i = 0; i < 10; i++) { if (errors & (1 << i)) e752x_printk(KERN_WARNING, "%sError System Bus %s\n", - fatal_message[fatal], global_message[i]); + fatal_message[fatal], global_message[i]); } } @@ -502,33 +506,42 @@ static inline void sysbus_error(int fatal, u32 errors, int *error_found, do_sysbus_error(fatal, errors); } -static void e752x_check_hub_interface (struct e752x_error_info *info, +static void e752x_check_hub_interface(struct e752x_error_info *info, int *error_found, int handle_error) { u8 stat8; //pci_read_config_byte(dev,E752X_HI_FERR,&stat8); + stat8 = info->hi_ferr; + if(stat8 & 0x7f) { /* Error, so process */ stat8 &= 0x7f; + if(stat8 & 0x2b) hub_error(1, stat8 & 0x2b, error_found, handle_error); + if(stat8 & 0x54) hub_error(0, stat8 & 0x54, error_found, handle_error); } + //pci_read_config_byte(dev,E752X_HI_NERR,&stat8); + stat8 = info->hi_nerr; + if(stat8 & 0x7f) { /* Error, so process */ stat8 &= 0x7f; + if (stat8 & 0x2b) hub_error(1, stat8 & 0x2b, error_found, handle_error); + if(stat8 & 0x54) hub_error(0, stat8 & 0x54, error_found, handle_error); } } -static void e752x_check_sysbus (struct e752x_error_info *info, int *error_found, - int handle_error) +static void e752x_check_sysbus(struct e752x_error_info *info, + int *error_found, int handle_error) { u32 stat32, error32; @@ -540,27 +553,34 @@ static void e752x_check_sysbus (struct e752x_error_info *info, int *error_found, error32 = (stat32 >> 16) & 0x3ff; stat32 = stat32 & 0x3ff; + if(stat32 & 0x083) sysbus_error(1, stat32 & 0x083, error_found, handle_error); + if(stat32 & 0x37c) sysbus_error(0, stat32 & 0x37c, error_found, handle_error); + if(error32 & 0x083) sysbus_error(1, error32 & 0x083, error_found, handle_error); + if(error32 & 0x37c) sysbus_error(0, error32 & 0x37c, error_found, handle_error); } -static void e752x_check_membuf (struct e752x_error_info *info, int *error_found, - int handle_error) +static void e752x_check_membuf (struct e752x_error_info *info, + int *error_found, int handle_error) { u8 stat8; stat8 = info->buf_ferr; + if (stat8 & 0x0f) { /* Error, so process */ stat8 &= 0x0f; membuf_error(stat8, error_found, handle_error); } + stat8 = info->buf_nerr; + if (stat8 & 0x0f) { /* Error, so process */ stat8 &= 0x0f; membuf_error(stat8, error_found, handle_error); @@ -568,7 +588,8 @@ static void e752x_check_membuf (struct e752x_error_info *info, int *error_found, } static void e752x_check_dram (struct mem_ctl_info *mci, - struct e752x_error_info *info, int *error_found, int handle_error) + struct e752x_error_info *info, int *error_found, + int handle_error) { u16 error_one, error_next; @@ -618,7 +639,7 @@ static void e752x_check_dram (struct mem_ctl_info *mci, } static void e752x_get_error_info (struct mem_ctl_info *mci, - struct e752x_error_info *info) + struct e752x_error_info *info) { struct pci_dev *dev; struct e752x_pvt *pvt; @@ -626,7 +647,6 @@ static void e752x_get_error_info (struct mem_ctl_info *mci, memset(info, 0, sizeof(*info)); pvt = (struct e752x_pvt *) mci->pvt_info; dev = pvt->dev_d0f1; - pci_read_config_dword(dev, E752X_FERR_GLOBAL, &info->ferr_global); if (info->ferr_global) { @@ -737,6 +757,7 @@ static int e752x_process_error_info (struct mem_ctl_info *mci, static void e752x_check(struct mem_ctl_info *mci) { struct e752x_error_info info; + debugf3("%s()\n", __func__); e752x_get_error_info(mci, &info); e752x_process_error_info(mci, &info, 1); @@ -752,9 +773,9 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) struct e752x_pvt *pvt = NULL; u16 ddrcsr; u32 drc; - int drc_chan; /* Number of channels 0=1chan,1=2chan */ - int drc_drbg; /* DRB granularity 0=64mb,1=128mb */ - int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ + int drc_chan; /* Number of channels 0=1chan,1=2chan */ + int drc_drbg; /* DRB granularity 0=64mb, 1=128mb */ + int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ u32 dra; unsigned long last_cumul_size; struct pci_dev *dev = NULL; @@ -785,7 +806,6 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) } debugf3("%s(): init mci\n", __func__); - mci->mtype_cap = MEM_FLAG_RDDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED; @@ -798,19 +818,21 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) pvt = (struct e752x_pvt *) mci->pvt_info; pvt->dev_info = &e752x_devs[dev_idx]; pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, - pvt->dev_info->err_dev, - pvt->bridge_ck); + pvt->dev_info->err_dev, + pvt->bridge_ck); + if (pvt->bridge_ck == NULL) pvt->bridge_ck = pci_scan_single_device(pdev->bus, - PCI_DEVFN(0, 1)); + PCI_DEVFN(0, 1)); + if (pvt->bridge_ck == NULL) { e752x_printk(KERN_ERR, "error reporting device not found:" - "vendor %x device 0x%x (broken BIOS?)\n", - PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].err_dev); + "vendor %x device 0x%x (broken BIOS?)\n", + PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].err_dev); goto fail; } - pvt->mc_symmetric = ((ddrcsr & 0x10) != 0); + pvt->mc_symmetric = ((ddrcsr & 0x10) != 0); debugf3("%s(): more mci init\n", __func__); mci->ctl_name = pvt->dev_info->ctl_name; mci->edac_check = e752x_check; @@ -828,6 +850,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) { u8 value; u32 cumul_size; + /* mem_dev 0=x8, 1=x4 */ int mem_dev = (dra >> (index * 4 + 2)) & 0x3; struct csrow_info *csrow = &mci->csrows[index]; @@ -838,15 +861,16 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, cumul_size); + if (cumul_size == last_cumul_size) - continue; /* not populated */ + continue; /* not populated */ csrow->first_page = last_cumul_size; csrow->last_page = cumul_size - 1; csrow->nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; - csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */ - csrow->mtype = MEM_RDDR; /* only one type supported */ + csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */ + csrow->mtype = MEM_RDDR; /* only one type supported */ csrow->dtype = mem_dev ? DEV_X4 : DEV_X8; /* @@ -870,29 +894,32 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) u8 value; u8 last = 0; u8 row = 0; - for (index = 0; index < 8; index += 2) { + for (index = 0; index < 8; index += 2) { pci_read_config_byte(mci->pdev, E752X_DRB + index, - &value); + &value); + /* test if there is a dimm in this slot */ if (value == last) { /* no dimm in the slot, so flag it as empty */ pvt->map[index] = 0xff; pvt->map[index + 1] = 0xff; - } else { /* there is a dimm in the slot */ + } else { /* there is a dimm in the slot */ pvt->map[index] = row; row++; last = value; /* test the next value to see if the dimm is double sided */ pci_read_config_byte(mci->pdev, - E752X_DRB + index + 1, - &value); + E752X_DRB + index + 1, + &value); pvt->map[index + 1] = (value == last) ? - 0xff : /* the dimm is single sided, - so flag as empty */ - row; /* this is a double sided dimm - to save the next row # */ + 0xff : /* the dimm is single sided, + * so flag as empty + */ + row; /* this is a double sided dimm + * to save the next row # + */ row++; last = value; } @@ -904,8 +931,8 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) pvt->map_type = ((stat8 & 0x0f) > ((stat8 >> 4) & 0x0f)); mci->edac_cap |= EDAC_FLAG_NONE; - debugf3("%s(): tolm, remapbase, remaplimit\n", __func__); + /* load the top of low memory, remap base, and remap limit vars */ pci_read_config_word(mci->pdev, E752X_TOLM, &pci_data); pvt->tolm = ((u32) pci_data) << 4; @@ -914,8 +941,8 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) pci_read_config_word(mci->pdev, E752X_REMAPLIMIT, &pci_data); pvt->remaplimit = ((u32) pci_data) << 14; e752x_printk(KERN_INFO, - "tolm = %x, remapbase = %x, remaplimit = %x\n", - pvt->tolm, pvt->remapbase, pvt->remaplimit); + "tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm, + pvt->remapbase, pvt->remaplimit); if (edac_mc_add_mc(mci)) { debugf3("%s(): failed edac_mc_add_mc()\n", __func__); @@ -923,7 +950,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) } dev = pci_get_device(PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].ctl_dev, - NULL); + NULL); pvt->dev_d0f0 = dev; /* find the error reporting device and clear errors */ dev = pvt->dev_d0f1 = pci_dev_get(pvt->bridge_ck); @@ -936,8 +963,8 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) pci_write_config_byte(dev, E752X_BUF_SMICMD, 0x00); pci_write_config_byte(dev, E752X_DRAM_ERRMASK, 0x00); pci_write_config_byte(dev, E752X_DRAM_SMICMD, 0x00); - /* clear other MCH errors */ - e752x_get_error_info(mci, &discard); + + e752x_get_error_info(mci, &discard); /* clear other MCH errors */ /* get this far and it's successful */ debugf3("%s(): success\n", __func__); @@ -947,28 +974,32 @@ fail: if (mci) { if (pvt->dev_d0f0) pci_dev_put(pvt->dev_d0f0); + if (pvt->dev_d0f1) pci_dev_put(pvt->dev_d0f1); + if (pvt->bridge_ck) pci_dev_put(pvt->bridge_ck); + edac_mc_free(mci); } + return rc; } /* returns count (>= 0), or negative on error */ static int __devinit e752x_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { debugf0("%s()\n", __func__); /* wake up and enable device */ if(pci_enable_device(pdev) < 0) return -EIO; + return e752x_probe1(pdev, ent->driver_data); } - static void __devexit e752x_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; @@ -986,20 +1017,26 @@ static void __devexit e752x_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } - static const struct pci_device_id e752x_pci_tbl[] __devinitdata = { - {PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - E7520}, - {PCI_VEND_DEV(INTEL, 7525_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - E7525}, - {PCI_VEND_DEV(INTEL, 7320_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - E7320}, - {0,} /* 0 terminated list. */ + { + PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7520 + }, + { + PCI_VEND_DEV(INTEL, 7525_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7525 + }, + { + PCI_VEND_DEV(INTEL, 7320_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7320 + }, + { + 0, + } /* 0 terminated list. */ }; MODULE_DEVICE_TABLE(pci, e752x_pci_tbl); - static struct pci_driver e752x_driver = { .name = EDAC_MOD_STR, .probe = e752x_init_one, @@ -1007,7 +1044,6 @@ static struct pci_driver e752x_driver = { .id_table = e752x_pci_tbl, }; - static int __init e752x_init(void) { int pci_rc; @@ -1017,14 +1053,12 @@ static int __init e752x_init(void) return (pci_rc < 0) ? pci_rc : 0; } - static void __exit e752x_exit(void) { debugf3("%s()\n", __func__); pci_unregister_driver(&e752x_driver); } - module_init(e752x_init); module_exit(e752x_exit); diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index 9b59c661f45..a9518d3e4be 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -11,9 +11,9 @@ * http://www.anime.net/~goemon/linux-ecc/ * * Contributors: - * Eric Biederman (Linux Networx) - * Tom Zimmerman (Linux Networx) - * Jim Garlick (Lawrence Livermore National Labs) + * Eric Biederman (Linux Networx) + * Tom Zimmerman (Linux Networx) + * Jim Garlick (Lawrence Livermore National Labs) * Dave Peterson (Lawrence Livermore National Labs) * That One Guy (Some other place) * Wang Zhenyu (intel.com) @@ -22,7 +22,6 @@ * */ - #include <linux/config.h> #include <linux/module.h> #include <linux/init.h> @@ -31,14 +30,11 @@ #include <linux/slab.h> #include "edac_mc.h" - #define e7xxx_printk(level, fmt, arg...) \ - edac_printk(level, "e7xxx", fmt, ##arg) - + edac_printk(level, "e7xxx", fmt, ##arg) #define e7xxx_mc_printk(mci, level, fmt, arg...) \ - edac_mc_chipset_printk(mci, level, "e7xxx", fmt, ##arg) - + edac_mc_chipset_printk(mci, level, "e7xxx", fmt, ##arg) #ifndef PCI_DEVICE_ID_INTEL_7205_0 #define PCI_DEVICE_ID_INTEL_7205_0 0x255d @@ -72,11 +68,9 @@ #define PCI_DEVICE_ID_INTEL_7505_1_ERR 0x2551 #endif /* PCI_DEVICE_ID_INTEL_7505_1_ERR */ - #define E7XXX_NR_CSROWS 8 /* number of csrows */ #define E7XXX_NR_DIMMS 8 /* FIXME - is this correct? */ - /* E7XXX register addresses - device 0 function 0 */ #define E7XXX_DRB 0x60 /* DRAM row boundary register (8b) */ #define E7XXX_DRA 0x70 /* DRAM row attribute register (8b) */ @@ -126,7 +120,6 @@ enum e7xxx_chips { E7205, }; - struct e7xxx_pvt { struct pci_dev *bridge_ck; u32 tolm; @@ -135,13 +128,11 @@ struct e7xxx_pvt { const struct e7xxx_dev_info *dev_info; }; - struct e7xxx_dev_info { u16 err_dev; const char *ctl_name; }; - struct e7xxx_error_info { u8 dram_ferr; u8 dram_nerr; @@ -152,20 +143,23 @@ struct e7xxx_error_info { static const struct e7xxx_dev_info e7xxx_devs[] = { [E7500] = { - .err_dev = PCI_DEVICE_ID_INTEL_7500_1_ERR, - .ctl_name = "E7500"}, + .err_dev = PCI_DEVICE_ID_INTEL_7500_1_ERR, + .ctl_name = "E7500" + }, [E7501] = { - .err_dev = PCI_DEVICE_ID_INTEL_7501_1_ERR, - .ctl_name = "E7501"}, + .err_dev = PCI_DEVICE_ID_INTEL_7501_1_ERR, + .ctl_name = "E7501" + }, [E7505] = { - .err_dev = PCI_DEVICE_ID_INTEL_7505_1_ERR, - .ctl_name = "E7505"}, + .err_dev = PCI_DEVICE_ID_INTEL_7505_1_ERR, + .ctl_name = "E7505" + }, [E7205] = { - .err_dev = PCI_DEVICE_ID_INTEL_7205_1_ERR, - .ctl_name = "E7205"}, + .err_dev = PCI_DEVICE_ID_INTEL_7205_1_ERR, + .ctl_name = "E7205" + }, }; - /* FIXME - is this valid for both SECDED and S4ECD4ED? */ static inline int e7xxx_find_channel(u16 syndrome) { @@ -173,16 +167,18 @@ static inline int e7xxx_find_channel(u16 syndrome) if ((syndrome & 0xff00) == 0) return 0; + if ((syndrome & 0x00ff) == 0) return 1; + if ((syndrome & 0xf000) == 0 || (syndrome & 0x0f00) == 0) return 0; + return 1; } - -static unsigned long -ctl_page_to_phys(struct mem_ctl_info *mci, unsigned long page) +static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, + unsigned long page) { u32 remap; struct e7xxx_pvt *pvt = (struct e7xxx_pvt *) mci->pvt_info; @@ -190,17 +186,20 @@ ctl_page_to_phys(struct mem_ctl_info *mci, unsigned long page) debugf3("%s()\n", __func__); if ((page < pvt->tolm) || - ((page >= 0x100000) && (page < pvt->remapbase))) + ((page >= 0x100000) && (page < pvt->remapbase))) return page; + remap = (page - pvt->tolm) + pvt->remapbase; + if (remap < pvt->remaplimit) return remap; + e7xxx_printk(KERN_ERR, "Invalid page %lx - out of range\n", page); return pvt->tolm - 1; } - -static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info) +static void process_ce(struct mem_ctl_info *mci, + struct e7xxx_error_info *info) { u32 error_1b, page; u16 syndrome; @@ -208,52 +207,46 @@ static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info) int channel; debugf3("%s()\n", __func__); - /* read the error address */ error_1b = info->dram_celog_add; /* FIXME - should use PAGE_SHIFT */ - page = error_1b >> 6; /* convert the address to 4k page */ + page = error_1b >> 6; /* convert the address to 4k page */ /* read the syndrome */ syndrome = info->dram_celog_syndrome; /* FIXME - check for -1 */ row = edac_mc_find_csrow_by_page(mci, page); /* convert syndrome to channel */ channel = e7xxx_find_channel(syndrome); - edac_mc_handle_ce(mci, page, 0, syndrome, row, channel, - "e7xxx CE"); + edac_mc_handle_ce(mci, page, 0, syndrome, row, channel, "e7xxx CE"); } - static void process_ce_no_info(struct mem_ctl_info *mci) { debugf3("%s()\n", __func__); edac_mc_handle_ce_no_info(mci, "e7xxx CE log register overflow"); } - -static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info) +static void process_ue(struct mem_ctl_info *mci, + struct e7xxx_error_info *info) { u32 error_2b, block_page; int row; debugf3("%s()\n", __func__); - /* read the error address */ error_2b = info->dram_uelog_add; /* FIXME - should use PAGE_SHIFT */ - block_page = error_2b >> 6; /* convert to 4k address */ + block_page = error_2b >> 6; /* convert to 4k address */ row = edac_mc_find_csrow_by_page(mci, block_page); edac_mc_handle_ue(mci, block_page, 0, row, "e7xxx UE"); } - static void process_ue_no_info(struct mem_ctl_info *mci) { debugf3("%s()\n", __func__); edac_mc_handle_ue_no_info(mci, "e7xxx UE log register overflow"); } - static void e7xxx_get_error_info (struct mem_ctl_info *mci, struct e7xxx_error_info *info) { @@ -261,31 +254,29 @@ static void e7xxx_get_error_info (struct mem_ctl_info *mci, pvt = (struct e7xxx_pvt *) mci->pvt_info; pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_FERR, - &info->dram_ferr); + &info->dram_ferr); pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_NERR, - &info->dram_nerr); + &info->dram_nerr); if ((info->dram_ferr & 1) || (info->dram_nerr & 1)) { pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_CELOG_ADD, - &info->dram_celog_add); + &info->dram_celog_add); pci_read_config_word(pvt->bridge_ck, - E7XXX_DRAM_CELOG_SYNDROME, &info->dram_celog_syndrome); + E7XXX_DRAM_CELOG_SYNDROME, + &info->dram_celog_syndrome); } if ((info->dram_ferr & 2) || (info->dram_nerr & 2)) pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_UELOG_ADD, - &info->dram_uelog_add); + &info->dram_uelog_add); if (info->dram_ferr & 3) - pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03, - 0x03); + pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03, 0x03); if (info->dram_nerr & 3) - pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03, - 0x03); + pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03, 0x03); } - static int e7xxx_process_error_info (struct mem_ctl_info *mci, struct e7xxx_error_info *info, int handle_errors) { @@ -333,7 +324,6 @@ static int e7xxx_process_error_info (struct mem_ctl_info *mci, return error_found; } - static void e7xxx_check(struct mem_ctl_info *mci) { struct e7xxx_error_info info; @@ -343,7 +333,6 @@ static void e7xxx_check(struct mem_ctl_info *mci) e7xxx_process_error_info(mci, &info, 1); } - static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) { int rc = -ENODEV; @@ -363,13 +352,14 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) /* need to find out the number of channels */ pci_read_config_dword(pdev, E7XXX_DRC, &drc); + /* only e7501 can be single channel */ if (dev_idx == E7501) { drc_chan = ((drc >> 22) & 0x1); drc_drbg = (drc >> 18) & 0x3; } - drc_ddim = (drc >> 20) & 0x3; + drc_ddim = (drc >> 20) & 0x3; mci = edac_mc_alloc(sizeof(*pvt), E7XXX_NR_CSROWS, drc_chan + 1); if (mci == NULL) { @@ -378,10 +368,9 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) } debugf3("%s(): init mci\n", __func__); - mci->mtype_cap = MEM_FLAG_RDDR; - mci->edac_ctl_cap = - EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED; + mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED | + EDAC_FLAG_S4ECD4ED; /* FIXME - what if different memory types are in different csrows? */ mci->mod_name = EDAC_MOD_STR; mci->mod_ver = "$Revision: 1.5.2.9 $"; @@ -391,19 +380,18 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) pvt = (struct e7xxx_pvt *) mci->pvt_info; pvt->dev_info = &e7xxx_devs[dev_idx]; pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, - pvt->dev_info->err_dev, - pvt->bridge_ck); + pvt->dev_info->err_dev, + pvt->bridge_ck); + if (!pvt->bridge_ck) { e7xxx_printk(KERN_ERR, "error reporting device not found:" - "vendor %x device 0x%x (broken BIOS?)\n", - PCI_VENDOR_ID_INTEL, - e7xxx_devs[dev_idx].err_dev); + "vendor %x device 0x%x (broken BIOS?)\n", + PCI_VENDOR_ID_INTEL, e7xxx_devs[dev_idx].err_dev); goto fail; } debugf3("%s(): more mci init\n", __func__); mci->ctl_name = pvt->dev_info->ctl_name; - mci->edac_check = e7xxx_check; mci->ctl_page_to_phys = ctl_page_to_phys; @@ -428,15 +416,16 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, cumul_size); + if (cumul_size == last_cumul_size) - continue; /* not populated */ + continue; /* not populated */ csrow->first_page = last_cumul_size; csrow->last_page = cumul_size - 1; csrow->nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; - csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */ - csrow->mtype = MEM_RDDR; /* only one type supported */ + csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */ + csrow->mtype = MEM_RDDR; /* only one type supported */ csrow->dtype = mem_dev ? DEV_X4 : DEV_X8; /* @@ -466,8 +455,8 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) pci_read_config_word(mci->pdev, E7XXX_REMAPLIMIT, &pci_data); pvt->remaplimit = ((u32) pci_data) << 14; e7xxx_printk(KERN_INFO, - "tolm = %x, remapbase = %x, remaplimit = %x\n", - pvt->tolm, pvt->remapbase, pvt->remaplimit); + "tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm, + pvt->remapbase, pvt->remaplimit); /* clear any pending errors, or initial state bits */ e7xxx_get_error_info(mci, &discard); @@ -492,17 +481,16 @@ fail: } /* returns count (>= 0), or negative on error */ -static int __devinit -e7xxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +static int __devinit e7xxx_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { debugf0("%s()\n", __func__); /* wake up and enable device */ return pci_enable_device(pdev) ? - -EIO : e7xxx_probe1(pdev, ent->driver_data); + -EIO : e7xxx_probe1(pdev, ent->driver_data); } - static void __devexit e7xxx_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; @@ -518,22 +506,30 @@ static void __devexit e7xxx_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } - static const struct pci_device_id e7xxx_pci_tbl[] __devinitdata = { - {PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - E7205}, - {PCI_VEND_DEV(INTEL, 7500_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - E7500}, - {PCI_VEND_DEV(INTEL, 7501_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - E7501}, - {PCI_VEND_DEV(INTEL, 7505_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - E7505}, - {0,} /* 0 terminated list. */ + { + PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7205 + }, + { + PCI_VEND_DEV(INTEL, 7500_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7500 + }, + { + PCI_VEND_DEV(INTEL, 7501_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7501 + }, + { + PCI_VEND_DEV(INTEL, 7505_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + E7505 + }, + { + 0, + } /* 0 terminated list. */ }; MODULE_DEVICE_TABLE(pci, e7xxx_pci_tbl); - static struct pci_driver e7xxx_driver = { .name = EDAC_MOD_STR, .probe = e7xxx_init_one, @@ -541,13 +537,11 @@ static struct pci_driver e7xxx_driver = { .id_table = e7xxx_pci_tbl, }; - static int __init e7xxx_init(void) { return pci_register_driver(&e7xxx_driver); } - static void __exit e7xxx_exit(void) { pci_unregister_driver(&e7xxx_driver); @@ -556,8 +550,7 @@ static void __exit e7xxx_exit(void) module_init(e7xxx_init); module_exit(e7xxx_exit); - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n" - "Based on.work by Dan Hollis et al"); + "Based on.work by Dan Hollis et al"); MODULE_DESCRIPTION("MC support for Intel e7xxx memory controllers"); diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index f67a4d6f897..bb3460457fa 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -12,7 +12,6 @@ * */ - #include <linux/config.h> #include <linux/module.h> #include <linux/proc_fs.h> @@ -30,14 +29,12 @@ #include <linux/sysdev.h> #include <linux/ctype.h> #include <linux/kthread.h> - #include <asm/uaccess.h> #include <asm/page.h> #include <asm/edac.h> - #include "edac_mc.h" -#define EDAC_MC_VERSION "Ver: 2.0.0 " __DATE__ +#define EDAC_MC_VERSION "Ver: 2.0.0 " __DATE__ /* For now, disable the EDAC sysfs code. The sysfs interface that EDAC * presents to user space needs more thought, and is likely to change @@ -73,7 +70,6 @@ struct edac_pci_device_list { unsigned int device; /* Deviice ID */ }; - #define MAX_LISTED_PCI_DEVICES 32 /* List of PCI devices (vendor-id:device-id) that should be skipped */ @@ -126,7 +122,6 @@ static const char *edac_caps[] = { [EDAC_S16ECD16ED] = "S16ECD16ED" }; - /* sysfs object: /sys/devices/system/edac */ static struct sysdev_class edac_class = { set_kset_name("edac"), @@ -147,7 +142,7 @@ static struct completion edac_pci_kobj_complete; /* * /sys/devices/system/edac/mc; - * data structures and methods + * data structures and methods */ #if 0 static ssize_t memctrl_string_show(void *ptr, char *buffer) @@ -174,33 +169,34 @@ static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count) } struct memctrl_dev_attribute { - struct attribute attr; - void *value; + struct attribute attr; + void *value; ssize_t (*show)(void *,char *); ssize_t (*store)(void *, const char *, size_t); }; /* Set of show/store abstract level functions for memory control object */ -static ssize_t -memctrl_dev_show(struct kobject *kobj, struct attribute *attr, char *buffer) +static ssize_t memctrl_dev_show(struct kobject *kobj, + struct attribute *attr, char *buffer) { struct memctrl_dev_attribute *memctrl_dev; memctrl_dev = (struct memctrl_dev_attribute*)attr; if (memctrl_dev->show) return memctrl_dev->show(memctrl_dev->value, buffer); + return -EIO; } -static ssize_t -memctrl_dev_store(struct kobject *kobj, struct attribute *attr, - const char *buffer, size_t count) +static ssize_t memctrl_dev_store(struct kobject *kobj, struct attribute *attr, + const char *buffer, size_t count) { struct memctrl_dev_attribute *memctrl_dev; memctrl_dev = (struct memctrl_dev_attribute*)attr; if (memctrl_dev->store) return memctrl_dev->store(memctrl_dev->value, buffer, count); + return -EIO; } @@ -236,7 +232,6 @@ MEMCTRL_ATTR(log_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store); MEMCTRL_ATTR(log_ce,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store); MEMCTRL_ATTR(poll_msec,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store); - /* Base Attributes of the memory ECC object */ static struct memctrl_dev_attribute *memctrl_attr[] = { &attr_panic_on_ue, @@ -254,9 +249,9 @@ static void edac_memctrl_master_release(struct kobject *kobj) } static struct kobj_type ktype_memctrl = { - .release = edac_memctrl_master_release, - .sysfs_ops = &memctrlfs_ops, - .default_attrs = (struct attribute **) memctrl_attr, + .release = edac_memctrl_master_release, + .sysfs_ops = &memctrlfs_ops, + .default_attrs = (struct attribute **) memctrl_attr, }; #endif /* DISABLE_EDAC_SYSFS */ @@ -282,6 +277,7 @@ static int edac_sysfs_memctrl_setup(void) /* create the /sys/devices/system/edac directory */ err = sysdev_class_register(&edac_class); + if (!err) { /* Init the MC's kobject */ memset(&edac_memctrl_kobj, 0, sizeof (edac_memctrl_kobj)); @@ -290,18 +286,18 @@ static int edac_sysfs_memctrl_setup(void) /* generate sysfs "..../edac/mc" */ err = kobject_set_name(&edac_memctrl_kobj,"mc"); + if (!err) { /* FIXME: maybe new sysdev_create_subdir() */ err = kobject_register(&edac_memctrl_kobj); - if (err) { + + if (err) debugf1("Failed to register '.../edac/mc'\n"); - } else { + else debugf1("Registered '.../edac/mc' kobject\n"); - } } - } else { + } else debugf1("%s() error=%d\n", __func__, err); - } return err; } @@ -340,7 +336,6 @@ struct list_control { int *count; }; - #if 0 /* Output the list as: vendor_id:device:id<,vendor_id:device_id> */ static ssize_t edac_pci_list_string_show(void *ptr, char *buffer) @@ -365,7 +360,6 @@ static ssize_t edac_pci_list_string_show(void *ptr, char *buffer) } len += snprintf(p + len,(PAGE_SIZE-len), "\n"); - return (ssize_t) len; } @@ -387,7 +381,7 @@ static int parse_one_device(const char **s,const char **e, /* if null byte, we are done */ if (!**s) { - (*s)++; /* keep *s moving */ + (*s)++; /* keep *s moving */ return 0; } @@ -404,6 +398,7 @@ static int parse_one_device(const char **s,const char **e, /* parse vendor_id */ runner = *s; + while (runner < *e) { /* scan for vendor:device delimiter */ if (*runner == ':') { @@ -411,6 +406,7 @@ static int parse_one_device(const char **s,const char **e, runner = p + 1; break; } + runner++; } @@ -426,12 +422,11 @@ static int parse_one_device(const char **s,const char **e, } *s = runner; - return 1; } static ssize_t edac_pci_list_string_store(void *ptr, const char *buffer, - size_t count) + size_t count) { struct list_control *listctl; struct edac_pci_device_list *list; @@ -441,14 +436,12 @@ static ssize_t edac_pci_list_string_store(void *ptr, const char *buffer, s = (char*)buffer; e = s + count; - listctl = ptr; list = listctl->list; index = listctl->count; - *index = 0; - while (*index < MAX_LISTED_PCI_DEVICES) { + while (*index < MAX_LISTED_PCI_DEVICES) { if (parse_one_device(&s,&e,&vendor_id,&device_id)) { list[ *index ].vendor = vendor_id; list[ *index ].device = device_id; @@ -481,15 +474,15 @@ static ssize_t edac_pci_int_store(void *ptr, const char *buffer, size_t count) } struct edac_pci_dev_attribute { - struct attribute attr; - void *value; + struct attribute attr; + void *value; ssize_t (*show)(void *,char *); ssize_t (*store)(void *, const char *,size_t); }; /* Set of show/store abstract level functions for PCI Parity object */ static ssize_t edac_pci_dev_show(struct kobject *kobj, struct attribute *attr, - char *buffer) + char *buffer) { struct edac_pci_dev_attribute *edac_pci_dev; edac_pci_dev= (struct edac_pci_dev_attribute*)attr; @@ -499,8 +492,8 @@ static ssize_t edac_pci_dev_show(struct kobject *kobj, struct attribute *attr, return -EIO; } -static ssize_t edac_pci_dev_store(struct kobject *kobj, struct attribute *attr, - const char *buffer, size_t count) +static ssize_t edac_pci_dev_store(struct kobject *kobj, + struct attribute *attr, const char *buffer, size_t count) { struct edac_pci_dev_attribute *edac_pci_dev; edac_pci_dev= (struct edac_pci_dev_attribute*)attr; @@ -515,7 +508,6 @@ static struct sysfs_ops edac_pci_sysfs_ops = { .store = edac_pci_dev_store }; - #define EDAC_PCI_ATTR(_name,_mode,_show,_store) \ struct edac_pci_dev_attribute edac_pci_attr_##_name = { \ .attr = {.name = __stringify(_name), .mode = _mode }, \ @@ -558,9 +550,11 @@ EDAC_PCI_STRING_ATTR(pci_parity_blacklist, #endif /* PCI Parity control files */ -EDAC_PCI_ATTR(check_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store); -EDAC_PCI_ATTR(panic_on_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store); -EDAC_PCI_ATTR(pci_parity_count,S_IRUGO,edac_pci_int_show,NULL); +EDAC_PCI_ATTR(check_pci_parity, S_IRUGO|S_IWUSR, edac_pci_int_show, + edac_pci_int_store); +EDAC_PCI_ATTR(panic_on_pci_parity, S_IRUGO|S_IWUSR, edac_pci_int_show, + edac_pci_int_store); +EDAC_PCI_ATTR(pci_parity_count, S_IRUGO, edac_pci_int_show, NULL); /* Base Attributes of the memory ECC object */ static struct edac_pci_dev_attribute *edac_pci_attr[] = { @@ -578,9 +572,9 @@ static void edac_pci_release(struct kobject *kobj) } static struct kobj_type ktype_edac_pci = { - .release = edac_pci_release, - .sysfs_ops = &edac_pci_sysfs_ops, - .default_attrs = (struct attribute **) edac_pci_attr, + .release = edac_pci_release, + .sysfs_ops = &edac_pci_sysfs_ops, + .default_attrs = (struct attribute **) edac_pci_attr, }; #endif /* DISABLE_EDAC_SYSFS */ @@ -603,17 +597,19 @@ static int edac_sysfs_pci_setup(void) memset(&edac_pci_kobj, 0, sizeof(edac_pci_kobj)); edac_pci_kobj.parent = &edac_class.kset.kobj; edac_pci_kobj.ktype = &ktype_edac_pci; - err = kobject_set_name(&edac_pci_kobj, "pci"); + if (!err) { /* Instanstiate the csrow object */ /* FIXME: maybe new sysdev_create_subdir() */ err = kobject_register(&edac_pci_kobj); + if (err) debugf1("Failed to register '.../edac/pci'\n"); else debugf1("Registered '.../edac/pci' kobject\n"); } + return err; } #endif /* DISABLE_EDAC_SYSFS */ @@ -641,6 +637,7 @@ static ssize_t csrow_ch0_dimm_label_show(struct csrow_info *csrow, char *data) size = snprintf(data, EDAC_MC_LABEL_LEN,"%s\n", csrow->channels[0].label); } + return size; } @@ -652,11 +649,12 @@ static ssize_t csrow_ch1_dimm_label_show(struct csrow_info *csrow, char *data) size = snprintf(data, EDAC_MC_LABEL_LEN, "%s\n", csrow->channels[1].label); } + return size; } static ssize_t csrow_ch0_dimm_label_store(struct csrow_info *csrow, - const char *data, size_t size) + const char *data, size_t size) { ssize_t max_size = 0; @@ -665,11 +663,12 @@ static ssize_t csrow_ch0_dimm_label_store(struct csrow_info *csrow, strncpy(csrow->channels[0].label, data, max_size); csrow->channels[0].label[max_size] = '\0'; } + return size; } static ssize_t csrow_ch1_dimm_label_store(struct csrow_info *csrow, - const char *data, size_t size) + const char *data, size_t size) { ssize_t max_size = 0; @@ -678,6 +677,7 @@ static ssize_t csrow_ch1_dimm_label_store(struct csrow_info *csrow, strncpy(csrow->channels[1].label, data, max_size); csrow->channels[1].label[max_size] = '\0'; } + return max_size; } @@ -698,6 +698,7 @@ static ssize_t csrow_ch0_ce_count_show(struct csrow_info *csrow, char *data) if (csrow->nr_channels > 0) { size = sprintf(data,"%u\n", csrow->channels[0].ce_count); } + return size; } @@ -708,6 +709,7 @@ static ssize_t csrow_ch1_ce_count_show(struct csrow_info *csrow, char *data) if (csrow->nr_channels > 1) { size = sprintf(data,"%u\n", csrow->channels[1].ce_count); } + return size; } @@ -732,7 +734,7 @@ static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data) } struct csrowdev_attribute { - struct attribute attr; + struct attribute attr; ssize_t (*show)(struct csrow_info *,char *); ssize_t (*store)(struct csrow_info *, const char *,size_t); }; @@ -742,24 +744,26 @@ struct csrowdev_attribute { /* Set of show/store higher level functions for csrow objects */ static ssize_t csrowdev_show(struct kobject *kobj, struct attribute *attr, - char *buffer) + char *buffer) { struct csrow_info *csrow = to_csrow(kobj); struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr); if (csrowdev_attr->show) return csrowdev_attr->show(csrow, buffer); + return -EIO; } static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr, - const char *buffer, size_t count) + const char *buffer, size_t count) { struct csrow_info *csrow = to_csrow(kobj); struct csrowdev_attribute * csrowdev_attr = to_csrowdev_attr(attr); if (csrowdev_attr->store) return csrowdev_attr->store(csrow, buffer, count); + return -EIO; } @@ -793,7 +797,6 @@ CSROWDEV_ATTR(ch1_dimm_label,S_IRUGO|S_IWUSR, csrow_ch1_dimm_label_show, csrow_ch1_dimm_label_store); - /* Attributes of the CSROW<id> object */ static struct csrowdev_attribute *csrow_attr[] = { &attr_dev_type, @@ -809,7 +812,6 @@ static struct csrowdev_attribute *csrow_attr[] = { NULL, }; - /* No memory to release */ static void edac_csrow_instance_release(struct kobject *kobj) { @@ -821,19 +823,18 @@ static void edac_csrow_instance_release(struct kobject *kobj) } static struct kobj_type ktype_csrow = { - .release = edac_csrow_instance_release, - .sysfs_ops = &csrowfs_ops, - .default_attrs = (struct attribute **) csrow_attr, + .release = edac_csrow_instance_release, + .sysfs_ops = &csrowfs_ops, + .default_attrs = (struct attribute **) csrow_attr, }; /* Create a CSROW object under specifed edac_mc_device */ static int edac_create_csrow_object(struct kobject *edac_mci_kobj, - struct csrow_info *csrow, int index ) + struct csrow_info *csrow, int index) { int err = 0; debugf0("%s()\n", __func__); - memset(&csrow->kobj, 0, sizeof(csrow->kobj)); /* generate ..../edac/mc/mc<id>/csrow<index> */ @@ -843,9 +844,11 @@ static int edac_create_csrow_object(struct kobject *edac_mci_kobj, /* name this instance of csrow<id> */ err = kobject_set_name(&csrow->kobj,"csrow%d",index); + if (!err) { /* Instanstiate the csrow object */ err = kobject_register(&csrow->kobj); + if (err) debugf0("Failed to register CSROW%d\n",index); else @@ -857,8 +860,8 @@ static int edac_create_csrow_object(struct kobject *edac_mci_kobj, /* sysfs data structures and methods for the MCI kobjects */ -static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci, - const char *data, size_t count ) +static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci, + const char *data, size_t count) { int row, chan; @@ -866,16 +869,18 @@ static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci, mci->ce_noinfo_count = 0; mci->ue_count = 0; mci->ce_count = 0; + for (row = 0; row < mci->nr_csrows; row++) { struct csrow_info *ri = &mci->csrows[row]; ri->ue_count = 0; ri->ce_count = 0; + for (chan = 0; chan < ri->nr_channels; chan++) ri->channels[chan].ce_count = 0; } - mci->start_time = jiffies; + mci->start_time = jiffies; return count; } @@ -933,18 +938,16 @@ static ssize_t mci_edac_capability_show(struct mem_ctl_info *mci, char *data) p += mci_output_edac_cap(p,mci->edac_ctl_cap); p += sprintf(p, "\n"); - return p - data; } static ssize_t mci_edac_current_capability_show(struct mem_ctl_info *mci, - char *data) + char *data) { char *p = data; p += mci_output_edac_cap(p,mci->edac_cap); p += sprintf(p, "\n"); - return p - data; } @@ -961,13 +964,13 @@ static int mci_output_mtype_cap(char *buf, unsigned long mtype_cap) return p - buf; } -static ssize_t mci_supported_mem_type_show(struct mem_ctl_info *mci, char *data) +static ssize_t mci_supported_mem_type_show(struct mem_ctl_info *mci, + char *data) { char *p = data; p += mci_output_mtype_cap(p,mci->mtype_cap); p += sprintf(p, "\n"); - return p - data; } @@ -981,6 +984,7 @@ static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data) if (!csrow->nr_pages) continue; + total_pages += csrow->nr_pages; } @@ -988,7 +992,7 @@ static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data) } struct mcidev_attribute { - struct attribute attr; + struct attribute attr; ssize_t (*show)(struct mem_ctl_info *,char *); ssize_t (*store)(struct mem_ctl_info *, const char *,size_t); }; @@ -997,30 +1001,32 @@ struct mcidev_attribute { #define to_mcidev_attr(a) container_of(a, struct mcidev_attribute, attr) static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr, - char *buffer) + char *buffer) { struct mem_ctl_info *mem_ctl_info = to_mci(kobj); struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr); if (mcidev_attr->show) return mcidev_attr->show(mem_ctl_info, buffer); + return -EIO; } static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr, - const char *buffer, size_t count) + const char *buffer, size_t count) { struct mem_ctl_info *mem_ctl_info = to_mci(kobj); struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr); if (mcidev_attr->store) return mcidev_attr->store(mem_ctl_info, buffer, count); + return -EIO; } static struct sysfs_ops mci_ops = { - .show = mcidev_show, - .store = mcidev_store + .show = mcidev_show, + .store = mcidev_store }; #define MCIDEV_ATTR(_name,_mode,_show,_store) \ @@ -1048,7 +1054,6 @@ MCIDEV_ATTR(edac_current_capability,S_IRUGO, MCIDEV_ATTR(supported_mem_type,S_IRUGO, mci_supported_mem_type_show,NULL); - static struct mcidev_attribute *mci_attr[] = { &mci_attr_reset_counters, &mci_attr_module_name, @@ -1065,7 +1070,6 @@ static struct mcidev_attribute *mci_attr[] = { NULL }; - /* * Release of a MC controlling instance */ @@ -1079,9 +1083,9 @@ static void edac_mci_instance_release(struct kobject *kobj) } static struct kobj_type ktype_mci = { - .release = edac_mci_instance_release, - .sysfs_ops = &mci_ops, - .default_attrs = (struct attribute **) mci_attr, + .release = edac_mci_instance_release, + .sysfs_ops = &mci_ops, + .default_attrs = (struct attribute **) mci_attr, }; #endif /* DISABLE_EDAC_SYSFS */ @@ -1109,11 +1113,11 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) struct kobject *edac_mci_kobj=&mci->edac_mci_kobj; debugf0("%s() idx=%d\n", __func__, mci->mc_idx); - memset(edac_mci_kobj, 0, sizeof(*edac_mci_kobj)); /* set the name of the mc<id> object */ err = kobject_set_name(edac_mci_kobj,"mc%d",mci->mc_idx); + if (err) return err; @@ -1123,12 +1127,14 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) /* register the mc<id> kobject */ err = kobject_register(edac_mci_kobj); + if (err) return err; /* create a symlink for the device */ err = sysfs_create_link(edac_mci_kobj, &mci->pdev->dev.kobj, EDAC_DEVICE_SYMLINK); + if (err) goto fail0; @@ -1136,12 +1142,12 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) * under the mc<id> kobject */ for (i = 0; i < mci->nr_csrows; i++) { - csrow = &mci->csrows[i]; /* Only expose populated CSROWs */ if (csrow->nr_pages > 0) { err = edac_create_csrow_object(edac_mci_kobj,csrow,i); + if (err) goto fail1; } @@ -1149,7 +1155,6 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) return 0; - /* CSROW error: backout what has already been registered, */ fail1: for ( i--; i >= 0; i--) { @@ -1164,7 +1169,6 @@ fail0: init_completion(&mci->kobj_complete); kobject_unregister(edac_mci_kobj); wait_for_completion(&mci->kobj_complete); - return err; } #endif /* DISABLE_EDAC_SYSFS */ @@ -1199,7 +1203,6 @@ static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) #ifdef CONFIG_EDAC_DEBUG - void edac_mc_dump_channel(struct channel_info *chan) { debugf4("\tchannel = %p\n", chan); @@ -1210,7 +1213,6 @@ void edac_mc_dump_channel(struct channel_info *chan) } EXPORT_SYMBOL(edac_mc_dump_channel); - void edac_mc_dump_csrow(struct csrow_info *csrow) { debugf4("\tcsrow = %p\n", csrow); @@ -1227,7 +1229,6 @@ void edac_mc_dump_csrow(struct csrow_info *csrow) } EXPORT_SYMBOL(edac_mc_dump_csrow); - void edac_mc_dump_mci(struct mem_ctl_info *mci) { debugf3("\tmci = %p\n", mci); @@ -1244,8 +1245,7 @@ void edac_mc_dump_mci(struct mem_ctl_info *mci) } EXPORT_SYMBOL(edac_mc_dump_mci); - -#endif /* CONFIG_EDAC_DEBUG */ +#endif /* CONFIG_EDAC_DEBUG */ /* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'. * Adjust 'ptr' so that its alignment is at least as stringent as what the @@ -1254,7 +1254,7 @@ EXPORT_SYMBOL(edac_mc_dump_mci); * If 'size' is a constant, the compiler will optimize this whole function * down to either a no-op or the addition of a constant to the value of 'ptr'. */ -static inline char * align_ptr (void *ptr, unsigned size) +static inline char * align_ptr(void *ptr, unsigned size) { unsigned align, r; @@ -1281,7 +1281,6 @@ static inline char * align_ptr (void *ptr, unsigned size) return (char *) (((unsigned long) ptr) + align - r); } - /** * edac_mc_alloc: Allocate a struct mem_ctl_info structure * @size_pvt: size of private storage needed @@ -1299,7 +1298,7 @@ static inline char * align_ptr (void *ptr, unsigned size) * struct mem_ctl_info pointer */ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows, - unsigned nr_chans) + unsigned nr_chans) { struct mem_ctl_info *mci; struct csrow_info *csi, *csrow; @@ -1330,8 +1329,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows, chi = (struct channel_info *) (((char *) mci) + ((unsigned long) chi)); pvt = sz_pvt ? (((char *) mci) + ((unsigned long) pvt)) : NULL; - memset(mci, 0, size); /* clear all fields */ - + memset(mci, 0, size); /* clear all fields */ mci->csrows = csi; mci->pvt_info = pvt; mci->nr_csrows = nr_csrows; @@ -1355,7 +1353,6 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows, } EXPORT_SYMBOL(edac_mc_alloc); - /** * edac_mc_free: Free a previously allocated 'mci' structure * @mci: pointer to a struct mem_ctl_info structure @@ -1383,7 +1380,7 @@ static struct mem_ctl_info *find_mci_by_pdev(struct pci_dev *pdev) return NULL; } -static int add_mc_to_global_list (struct mem_ctl_info *mci) +static int add_mc_to_global_list(struct mem_ctl_info *mci) { struct list_head *item, *insert_before; struct mem_ctl_info *p; @@ -1426,8 +1423,7 @@ static int add_mc_to_global_list (struct mem_ctl_info *mci) return 0; } - -static void complete_mc_list_del (struct rcu_head *head) +static void complete_mc_list_del(struct rcu_head *head) { struct mem_ctl_info *mci; @@ -1436,8 +1432,7 @@ static void complete_mc_list_del (struct rcu_head *head) complete(&mci->complete); } - -static void del_mc_from_global_list (struct mem_ctl_info *mci) +static void del_mc_from_global_list(struct mem_ctl_info *mci) { list_del_rcu(&mci->link); init_completion(&mci->complete); @@ -1445,7 +1440,6 @@ static void del_mc_from_global_list (struct mem_ctl_info *mci) wait_for_completion(&mci->complete); } - /** * edac_mc_add_mc: Insert the 'mci' structure into the mci global list and * create sysfs entries associated with mci structure @@ -1463,15 +1457,17 @@ int edac_mc_add_mc(struct mem_ctl_info *mci) #ifdef CONFIG_EDAC_DEBUG if (edac_debug_level >= 3) edac_mc_dump_mci(mci); + if (edac_debug_level >= 4) { int i; for (i = 0; i < mci->nr_csrows; i++) { int j; + edac_mc_dump_csrow(&mci->csrows[i]); for (j = 0; j < mci->csrows[i].nr_channels; j++) - edac_mc_dump_channel(&mci->csrows[i]. - channels[j]); + edac_mc_dump_channel( + &mci->csrows[i].channels[j]); } } #endif @@ -1505,7 +1501,6 @@ fail0: } EXPORT_SYMBOL(edac_mc_add_mc); - /** * edac_mc_del_mc: Remove sysfs entries for specified mci structure and * remove mci structure from global list @@ -1535,9 +1530,7 @@ struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev) } EXPORT_SYMBOL(edac_mc_del_mc); - -void edac_mc_scrub_block(unsigned long page, unsigned long offset, - u32 size) +void edac_mc_scrub_block(unsigned long page, unsigned long offset, u32 size) { struct page *pg; void *virt_addr; @@ -1568,10 +1561,8 @@ void edac_mc_scrub_block(unsigned long page, unsigned long offset, } EXPORT_SYMBOL(edac_mc_scrub_block); - /* FIXME - should return -1 */ -int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, - unsigned long page) +int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page) { struct csrow_info *csrows = mci->csrows; int row, i; @@ -1608,14 +1599,11 @@ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, } EXPORT_SYMBOL(edac_mc_find_csrow_by_page); - /* FIXME - setable log (warning/emerg) levels */ /* FIXME - integrate with evlog: http://evlog.sourceforge.net/ */ void edac_mc_handle_ce(struct mem_ctl_info *mci, - unsigned long page_frame_number, - unsigned long offset_in_page, - unsigned long syndrome, int row, int channel, - const char *msg) + unsigned long page_frame_number, unsigned long offset_in_page, + unsigned long syndrome, int row, int channel, const char *msg) { unsigned long remapped_page; @@ -1630,6 +1618,7 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci, edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR"); return; } + if (channel >= mci->csrows[row].nr_channels || channel < 0) { /* something is wrong */ edac_mc_printk(mci, KERN_ERR, @@ -1668,28 +1657,25 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci, page_frame_number; edac_mc_scrub_block(remapped_page, offset_in_page, - mci->csrows[row].grain); + mci->csrows[row].grain); } } EXPORT_SYMBOL(edac_mc_handle_ce); - -void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, - const char *msg) +void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, const char *msg) { if (log_ce) edac_mc_printk(mci, KERN_WARNING, "CE - no information available: %s\n", msg); + mci->ce_noinfo_count++; mci->ce_count++; } EXPORT_SYMBOL(edac_mc_handle_ce_no_info); - void edac_mc_handle_ue(struct mem_ctl_info *mci, - unsigned long page_frame_number, - unsigned long offset_in_page, int row, - const char *msg) + unsigned long page_frame_number, unsigned long offset_in_page, + int row, const char *msg) { int len = EDAC_MC_LABEL_LEN * 4; char labels[len + 1]; @@ -1710,13 +1696,14 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci, } chars = snprintf(pos, len + 1, "%s", - mci->csrows[row].channels[0].label); + mci->csrows[row].channels[0].label); len -= chars; pos += chars; + for (chan = 1; (chan < mci->csrows[row].nr_channels) && (len > 0); chan++) { chars = snprintf(pos, len + 1, ":%s", - mci->csrows[row].channels[chan].label); + mci->csrows[row].channels[chan].label); len -= chars; pos += chars; } @@ -1729,20 +1716,17 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci, msg); if (panic_on_ue) - panic - ("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, row %d," - " labels \"%s\": %s\n", mci->mc_idx, - page_frame_number, offset_in_page, - mci->csrows[row].grain, row, labels, msg); + panic("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, " + "row %d, labels \"%s\": %s\n", mci->mc_idx, + page_frame_number, offset_in_page, + mci->csrows[row].grain, row, labels, msg); mci->ue_count++; mci->csrows[row].ue_count++; } EXPORT_SYMBOL(edac_mc_handle_ue); - -void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, - const char *msg) +void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg) { if (panic_on_ue) panic("EDAC MC%d: Uncorrected Error", mci->mc_idx); @@ -1755,7 +1739,6 @@ void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, } EXPORT_SYMBOL(edac_mc_handle_ue_no_info); - #ifdef CONFIG_PCI static u16 get_pci_parity_status(struct pci_dev *dev, int secondary) @@ -1766,18 +1749,22 @@ static u16 get_pci_parity_status(struct pci_dev *dev, int secondary) where = secondary ? PCI_SEC_STATUS : PCI_STATUS; pci_read_config_word(dev, where, &status); - /* If we get back 0xFFFF then we must suspect that the card has been pulled but - the Linux PCI layer has not yet finished cleaning up. We don't want to report - on such devices */ + /* If we get back 0xFFFF then we must suspect that the card has been + * pulled but the Linux PCI layer has not yet finished cleaning up. + * We don't want to report on such devices + */ if (status == 0xFFFF) { u32 sanity; + pci_read_config_dword(dev, 0, &sanity); + if (sanity == 0xFFFFFFFF) return 0; } + status &= PCI_STATUS_DETECTED_PARITY | PCI_STATUS_SIG_SYSTEM_ERROR | - PCI_STATUS_PARITY; + PCI_STATUS_PARITY; if (status) /* reset only the bits we are interested in */ @@ -1789,7 +1776,7 @@ static u16 get_pci_parity_status(struct pci_dev *dev, int secondary) typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev); /* Clear any PCI parity errors logged by this device. */ -static void edac_pci_dev_parity_clear( struct pci_dev *dev ) +static void edac_pci_dev_parity_clear(struct pci_dev *dev) { u8 header_type; @@ -1890,58 +1877,55 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) * Returns: 0 not found * 1 found on list */ -static int check_dev_on_list(struct edac_pci_device_list *list, int free_index, - struct pci_dev *dev) -{ - int i; - int rc = 0; /* Assume not found */ - unsigned short vendor=dev->vendor; - unsigned short device=dev->device; - - /* Scan the list, looking for a vendor/device match - */ - for (i = 0; i < free_index; i++, list++ ) { - if ( (list->vendor == vendor ) && - (list->device == device )) { - rc = 1; - break; - } - } +static int check_dev_on_list(struct edac_pci_device_list *list, + int free_index, struct pci_dev *dev) +{ + int i; + int rc = 0; /* Assume not found */ + unsigned short vendor=dev->vendor; + unsigned short device=dev->device; + + /* Scan the list, looking for a vendor/device match */ + for (i = 0; i < free_index; i++, list++ ) { + if ((list->vendor == vendor ) && (list->device == device )) { + rc = 1; + break; + } + } - return rc; + return rc; } /* * pci_dev parity list iterator - * Scan the PCI device list for one iteration, looking for SERRORs + * Scan the PCI device list for one iteration, looking for SERRORs * Master Parity ERRORS or Parity ERRORs on primary or secondary devices */ static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn) { - struct pci_dev *dev=NULL; + struct pci_dev *dev = NULL; /* request for kernel access to the next PCI device, if any, * and while we are looking at it have its reference count * bumped until we are done with it */ while((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - - /* if whitelist exists then it has priority, so only scan those - * devices on the whitelist - */ - if (pci_whitelist_count > 0 ) { - if (check_dev_on_list(pci_whitelist, + /* if whitelist exists then it has priority, so only scan + * those devices on the whitelist + */ + if (pci_whitelist_count > 0 ) { + if (check_dev_on_list(pci_whitelist, pci_whitelist_count, dev)) fn(dev); - } else { + } else { /* * if no whitelist, then check if this devices is * blacklisted */ - if (!check_dev_on_list(pci_blacklist, + if (!check_dev_on_list(pci_blacklist, pci_blacklist_count, dev)) fn(dev); - } + } } } @@ -1972,7 +1956,6 @@ static void do_pci_parity_check(void) } } - static inline void clear_pci_parity_errors(void) { /* Clear any PCI bus parity errors that devices initially have logged @@ -1981,34 +1964,29 @@ static inline void clear_pci_parity_errors(void) edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear); } - #else /* CONFIG_PCI */ - static inline void do_pci_parity_check(void) { /* no-op */ } - static inline void clear_pci_parity_errors(void) { /* no-op */ } - #endif /* CONFIG_PCI */ /* * Iterate over all MC instances and check for ECC, et al, errors */ -static inline void check_mc_devices (void) +static inline void check_mc_devices(void) { struct list_head *item; struct mem_ctl_info *mci; debugf3("%s()\n", __func__); - down(&mem_ctls_mutex); list_for_each(item, &mc_devices) { @@ -2021,7 +1999,6 @@ static inline void check_mc_devices (void) up(&mem_ctls_mutex); } - /* * Check MC status every poll_msec. * Check PCI status every poll_msec as well. @@ -2084,6 +2061,7 @@ static int __init edac_mc_init(void) /* create our kernel thread */ edac_thread = kthread_run(edac_kernel_thread, NULL, "kedac"); + if (IS_ERR(edac_thread)) { /* remove the sysfs entries */ edac_sysfs_memctrl_teardown(); @@ -2094,7 +2072,6 @@ static int __init edac_mc_init(void) return 0; } - /* * edac_mc_exit() * module exit/termination functioni @@ -2102,7 +2079,6 @@ static int __init edac_mc_init(void) static void __exit edac_mc_exit(void) { debugf0("%s()\n", __func__); - kthread_stop(edac_thread); /* tear down the sysfs device */ @@ -2110,15 +2086,12 @@ static void __exit edac_mc_exit(void) edac_sysfs_pci_teardown(); } - - - module_init(edac_mc_init); module_exit(edac_mc_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n" - "Based on.work by Dan Hollis et al"); + "Based on work by Dan Hollis et al"); MODULE_DESCRIPTION("Core library routines for MC reporting"); module_param(panic_on_ue, int, 0644); diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h index 2cec157aaeb..8d9e83909b9 100644 --- a/drivers/edac/edac_mc.h +++ b/drivers/edac/edac_mc.h @@ -15,11 +15,9 @@ * */ - #ifndef _EDAC_MC_H_ #define _EDAC_MC_H_ - #include <linux/config.h> #include <linux/kernel.h> #include <linux/types.h> @@ -33,7 +31,6 @@ #include <linux/completion.h> #include <linux/kobject.h> - #define EDAC_MC_LABEL_LEN 31 #define MC_PROC_NAME_MAX_LEN 7 @@ -44,13 +41,13 @@ #endif #define edac_printk(level, prefix, fmt, arg...) \ - printk(level "EDAC " prefix ": " fmt, ##arg) + printk(level "EDAC " prefix ": " fmt, ##arg) #define edac_mc_printk(mci, level, fmt, arg...) \ - printk(level "EDAC MC%d: " fmt, mci->mc_idx, ##arg) + printk(level "EDAC MC%d: " fmt, mci->mc_idx, ##arg) #define edac_mc_chipset_printk(mci, level, prefix, fmt, arg...) \ - printk(level "EDAC " prefix " MC%d: " fmt, mci->mc_idx, ##arg) + printk(level "EDAC " prefix " MC%d: " fmt, mci->mc_idx, ##arg) /* prefixes for edac_printk() and edac_mc_printk() */ #define EDAC_MC "MC" @@ -71,14 +68,16 @@ extern int edac_debug_level; #define debugf2( ... ) edac_debug_printk(2, __VA_ARGS__ ) #define debugf3( ... ) edac_debug_printk(3, __VA_ARGS__ ) #define debugf4( ... ) edac_debug_printk(4, __VA_ARGS__ ) -#else /* !CONFIG_EDAC_DEBUG */ + +#else /* !CONFIG_EDAC_DEBUG */ + #define debugf0( ... ) #define debugf1( ... ) #define debugf2( ... ) #define debugf3( ... ) #define debugf4( ... ) -#endif /* !CONFIG_EDAC_DEBUG */ +#endif /* !CONFIG_EDAC_DEBUG */ #define edac_xstr(s) edac_str(s) #define edac_str(s) #s @@ -86,7 +85,8 @@ extern int edac_debug_level; #define BIT(x) (1 << (x)) -#define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, PCI_DEVICE_ID_ ## vend ## _ ## dev +#define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, \ + PCI_DEVICE_ID_ ## vend ## _ ## dev /* memory devices */ enum dev_type { @@ -136,7 +136,6 @@ enum mem_type { #define MEM_FLAG_RDDR BIT(MEM_RDDR) #define MEM_FLAG_RMBS BIT(MEM_RMBS) - /* chipset Error Detection and Correction capabilities and mode */ enum edac_type { EDAC_UNKNOWN = 0, /* Unknown if ECC is available */ @@ -161,7 +160,6 @@ enum edac_type { #define EDAC_FLAG_S8ECD8ED BIT(EDAC_S8ECD8ED) #define EDAC_FLAG_S16ECD16ED BIT(EDAC_S16ECD16ED) - /* scrubbing capabilities */ enum scrub_type { SCRUB_UNKNOWN = 0, /* Unknown if scrubber is available */ @@ -269,20 +267,19 @@ enum scrub_type { * PS - I enjoyed writing all that about as much as you enjoyed reading it. */ - struct channel_info { int chan_idx; /* channel index */ u32 ce_count; /* Correctable Errors for this CHANNEL */ - char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */ + char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */ struct csrow_info *csrow; /* the parent */ }; - struct csrow_info { unsigned long first_page; /* first page number in dimm */ unsigned long last_page; /* last page number in dimm */ unsigned long page_mask; /* used for interleaving - - 0UL for non intlv */ + * 0UL for non intlv + */ u32 nr_pages; /* number of pages in csrow */ u32 grain; /* granularity of reported error in bytes */ int csrow_idx; /* the chip-select row */ @@ -301,18 +298,18 @@ struct csrow_info { struct channel_info *channels; }; - struct mem_ctl_info { struct list_head link; /* for global list of mem_ctl_info structs */ unsigned long mtype_cap; /* memory types supported by mc */ unsigned long edac_ctl_cap; /* Mem controller EDAC capabilities */ unsigned long edac_cap; /* configuration capabilities - this is - closely related to edac_ctl_cap. The - difference is that the controller - may be capable of s4ecd4ed which would - be listed in edac_ctl_cap, but if - channels aren't capable of s4ecd4ed then the - edac_cap would not have that capability. */ + * closely related to edac_ctl_cap. The + * difference is that the controller may be + * capable of s4ecd4ed which would be listed + * in edac_ctl_cap, but if channels aren't + * capable of s4ecd4ed then the edac_cap would + * not have that capability. + */ unsigned long scrub_cap; /* chipset scrub capabilities */ enum scrub_type scrub_mode; /* current scrub mode */ @@ -324,7 +321,7 @@ struct mem_ctl_info { */ /* FIXME - why not send the phys page to begin with? */ unsigned long (*ctl_page_to_phys) (struct mem_ctl_info * mci, - unsigned long page); + unsigned long page); int mc_idx; int nr_csrows; struct csrow_info *csrows; @@ -356,67 +353,66 @@ struct mem_ctl_info { struct completion kobj_complete; }; - - /* write all or some bits in a byte-register*/ -static inline void pci_write_bits8(struct pci_dev *pdev, int offset, - u8 value, u8 mask) +static inline void pci_write_bits8(struct pci_dev *pdev, int offset, u8 value, + u8 mask) { if (mask != 0xff) { u8 buf; + pci_read_config_byte(pdev, offset, &buf); value &= mask; buf &= ~mask; value |= buf; } + pci_write_config_byte(pdev, offset, value); } - /* write all or some bits in a word-register*/ static inline void pci_write_bits16(struct pci_dev *pdev, int offset, - u16 value, u16 mask) + u16 value, u16 mask) { if (mask != 0xffff) { u16 buf; + pci_read_config_word(pdev, offset, &buf); value &= mask; buf &= ~mask; value |= buf; } + pci_write_config_word(pdev, offset, value); } - /* write all or some bits in a dword-register*/ static inline void pci_write_bits32(struct pci_dev *pdev, int offset, - u32 value, u32 mask) + u32 value, u32 mask) { if (mask != 0xffff) { u32 buf; + pci_read_config_dword(pdev, offset, &buf); value &= mask; buf &= ~mask; value |= buf; } + pci_write_config_dword(pdev, offset, value); } - #ifdef CONFIG_EDAC_DEBUG void edac_mc_dump_channel(struct channel_info *chan); void edac_mc_dump_mci(struct mem_ctl_info *mci); void edac_mc_dump_csrow(struct csrow_info *csrow); -#endif /* CONFIG_EDAC_DEBUG */ +#endif /* CONFIG_EDAC_DEBUG */ extern int edac_mc_add_mc(struct mem_ctl_info *mci); extern struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev); - extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, - unsigned long page); - -extern void edac_mc_scrub_block(unsigned long page, - unsigned long offset, u32 size); + unsigned long page); +extern void edac_mc_scrub_block(unsigned long page, unsigned long offset, + u32 size); /* * The no info errors are used when error overflows are reported. @@ -429,31 +425,25 @@ extern void edac_mc_scrub_block(unsigned long page, * statement clutter and extra function arguments. */ extern void edac_mc_handle_ce(struct mem_ctl_info *mci, - unsigned long page_frame_number, - unsigned long offset_in_page, - unsigned long syndrome, - int row, int channel, const char *msg); - + unsigned long page_frame_number, unsigned long offset_in_page, + unsigned long syndrome, int row, int channel, + const char *msg); extern void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, - const char *msg); - + const char *msg); extern void edac_mc_handle_ue(struct mem_ctl_info *mci, - unsigned long page_frame_number, - unsigned long offset_in_page, - int row, const char *msg); - + unsigned long page_frame_number, unsigned long offset_in_page, + int row, const char *msg); extern void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, - const char *msg); + const char *msg); /* * This kmalloc's and initializes all the structures. * Can't be used if all structures don't have the same lifetime. */ -extern struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, - unsigned nr_csrows, unsigned nr_chans); +extern struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows, + unsigned nr_chans); /* Free an mc previously allocated by edac_mc_alloc() */ extern void edac_mc_free(struct mem_ctl_info *mci); - #endif /* _EDAC_MC_H_ */ diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index 688854260a0..fd342163cf9 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -9,7 +9,6 @@ * by Thayne Harbaugh of Linux Networx. (http://lnxi.com) */ - #include <linux/config.h> #include <linux/module.h> #include <linux/init.h> @@ -18,14 +17,11 @@ #include <linux/slab.h> #include "edac_mc.h" - #define i82860_printk(level, fmt, arg...) \ - edac_printk(level, "i82860", fmt, ##arg) - + edac_printk(level, "i82860", fmt, ##arg) #define i82860_mc_printk(mci, level, fmt, arg...) \ - edac_mc_chipset_printk(mci, level, "i82860", fmt, ##arg) - + edac_mc_chipset_printk(mci, level, "i82860", fmt, ##arg) #ifndef PCI_DEVICE_ID_INTEL_82860_0 #define PCI_DEVICE_ID_INTEL_82860_0 0x2531 @@ -56,13 +52,15 @@ struct i82860_error_info { static const struct i82860_dev_info i82860_devs[] = { [I82860] = { - .ctl_name = "i82860"}, + .ctl_name = "i82860" + }, }; static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code - has already registered driver */ + * has already registered driver + */ -static void i82860_get_error_info (struct mem_ctl_info *mci, +static void i82860_get_error_info(struct mem_ctl_info *mci, struct i82860_error_info *info) { /* @@ -84,14 +82,15 @@ static void i82860_get_error_info (struct mem_ctl_info *mci, */ if (!(info->errsts2 & 0x0003)) return; + if ((info->errsts ^ info->errsts2) & 0x0003) { pci_read_config_dword(mci->pdev, I82860_EAP, &info->eap); pci_read_config_word(mci->pdev, I82860_DERRCTL_STS, - &info->derrsyn); + &info->derrsyn); } } -static int i82860_process_error_info (struct mem_ctl_info *mci, +static int i82860_process_error_info(struct mem_ctl_info *mci, struct i82860_error_info *info, int handle_errors) { int row; @@ -113,8 +112,8 @@ static int i82860_process_error_info (struct mem_ctl_info *mci, if (info->errsts & 0x0002) edac_mc_handle_ue(mci, info->eap, 0, row, "i82860 UE"); else - edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row, - 0, "i82860 UE"); + edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row, 0, + "i82860 UE"); return 1; } @@ -147,15 +146,14 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) going to make 1 channel for group. */ mci = edac_mc_alloc(0, 16, 1); + if (!mci) return -ENOMEM; debugf3("%s(): init mci\n", __func__); - mci->pdev = pdev; mci->mtype_cap = MEM_FLAG_DDR; - mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; /* I"m not sure about this but I think that all RDRAM is SECDED */ mci->edac_cap = EDAC_FLAG_SECDED; @@ -182,12 +180,13 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) struct csrow_info *csrow = &mci->csrows[index]; pci_read_config_word(mci->pdev, I82860_GBA + index * 2, - &value); + &value); cumul_size = (value & I82860_GBA_MASK) << (I82860_GBA_SHIFT - PAGE_SHIFT); debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, cumul_size); + if (cumul_size == last_cumul_size) continue; /* not populated */ @@ -195,7 +194,7 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) csrow->last_page = cumul_size - 1; csrow->nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; - csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */ + csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */ csrow->mtype = MEM_RMBS; csrow->dtype = DEV_UNKNOWN; csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE; @@ -211,23 +210,27 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) debugf3("%s(): success\n", __func__); rc = 0; } + return rc; } /* returns count (>= 0), or negative on error */ static int __devinit i82860_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { int rc; debugf0("%s()\n", __func__); - i82860_printk(KERN_INFO, "i82860 init one\n"); - if(pci_enable_device(pdev) < 0) + + if (pci_enable_device(pdev) < 0) return -EIO; + rc = i82860_probe1(pdev, ent->driver_data); - if(rc == 0) + + if (rc == 0) mci_pdev = pci_dev_get(pdev); + return rc; } @@ -244,9 +247,13 @@ static void __devexit i82860_remove_one(struct pci_dev *pdev) } static const struct pci_device_id i82860_pci_tbl[] __devinitdata = { - {PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - I82860}, - {0,} /* 0 terminated list. */ + { + PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + I82860 + }, + { + 0, + } /* 0 terminated list. */ }; MODULE_DEVICE_TABLE(pci, i82860_pci_tbl); @@ -263,24 +270,29 @@ static int __init i82860_init(void) int pci_rc; debugf3("%s()\n", __func__); + if ((pci_rc = pci_register_driver(&i82860_driver)) < 0) goto fail0; if (!mci_pdev) { mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82860_0, NULL); + PCI_DEVICE_ID_INTEL_82860_0, NULL); + if (mci_pdev == NULL) { debugf0("860 pci_get_device fail\n"); pci_rc = -ENODEV; goto fail1; } + pci_rc = i82860_init_one(mci_pdev, i82860_pci_tbl); + if (pci_rc < 0) { debugf0("860 init fail\n"); pci_rc = -ENODEV; goto fail1; } } + return 0; fail1: @@ -307,6 +319,6 @@ module_init(i82860_init); module_exit(i82860_exit); MODULE_LICENSE("GPL"); -MODULE_AUTHOR - ("Red Hat Inc. (http://www.redhat.com) Ben Woodard <woodard@redhat.com>"); +MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com) " + "Ben Woodard <woodard@redhat.com>"); MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers"); diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index aad1900a468..0aec92698f1 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -13,26 +13,19 @@ * Note: E7210 appears same as D82875P - zhenyu.z.wang at intel.com */ - #include <linux/config.h> #include <linux/module.h> #include <linux/init.h> - #include <linux/pci.h> #include <linux/pci_ids.h> - #include <linux/slab.h> - #include "edac_mc.h" - #define i82875p_printk(level, fmt, arg...) \ - edac_printk(level, "i82875p", fmt, ##arg) - + edac_printk(level, "i82875p", fmt, ##arg) #define i82875p_mc_printk(mci, level, fmt, arg...) \ - edac_mc_chipset_printk(mci, level, "i82875p", fmt, ##arg) - + edac_mc_chipset_printk(mci, level, "i82875p", fmt, ##arg) #ifndef PCI_DEVICE_ID_INTEL_82875_0 #define PCI_DEVICE_ID_INTEL_82875_0 0x2578 @@ -42,11 +35,9 @@ #define PCI_DEVICE_ID_INTEL_82875_6 0x257e #endif /* PCI_DEVICE_ID_INTEL_82875_6 */ - /* four csrows in dual channel, eight in single channel */ #define I82875P_NR_CSROWS(nr_chans) (8/(nr_chans)) - /* Intel 82875p register addresses - device 0 function 0 - DRAM Controller */ #define I82875P_EAP 0x58 /* Error Address Pointer (32b) * @@ -95,7 +86,6 @@ * 0 reserved */ - /* Intel 82875p register addresses - device 6 function 0 - DRAM Controller */ #define I82875P_PCICMD6 0x04 /* PCI Command Register (16b) * @@ -159,23 +149,19 @@ * 1:0 DRAM type 01=DDR */ - enum i82875p_chips { I82875P = 0, }; - struct i82875p_pvt { struct pci_dev *ovrfl_pdev; void __iomem *ovrfl_window; }; - struct i82875p_dev_info { const char *ctl_name; }; - struct i82875p_error_info { u16 errsts; u32 eap; @@ -184,17 +170,19 @@ struct i82875p_error_info { u16 errsts2; }; - static const struct i82875p_dev_info i82875p_devs[] = { [I82875P] = { - .ctl_name = "i82875p"}, + .ctl_name = "i82875p" + }, }; -static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code - has already registered driver */ +static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code has + * already registered driver + */ + static int i82875p_registered = 1; -static void i82875p_get_error_info (struct mem_ctl_info *mci, +static void i82875p_get_error_info(struct mem_ctl_info *mci, struct i82875p_error_info *info) { /* @@ -218,15 +206,16 @@ static void i82875p_get_error_info (struct mem_ctl_info *mci, */ if (!(info->errsts2 & 0x0081)) return; + if ((info->errsts ^ info->errsts2) & 0x0081) { pci_read_config_dword(mci->pdev, I82875P_EAP, &info->eap); pci_read_config_byte(mci->pdev, I82875P_DES, &info->des); pci_read_config_byte(mci->pdev, I82875P_DERRSYN, - &info->derrsyn); + &info->derrsyn); } } -static int i82875p_process_error_info (struct mem_ctl_info *mci, +static int i82875p_process_error_info(struct mem_ctl_info *mci, struct i82875p_error_info *info, int handle_errors) { int row, multi_chan; @@ -251,13 +240,12 @@ static int i82875p_process_error_info (struct mem_ctl_info *mci, edac_mc_handle_ue(mci, info->eap, 0, row, "i82875p UE"); else edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row, - multi_chan ? (info->des & 0x1) : 0, - "i82875p CE"); + multi_chan ? (info->des & 0x1) : 0, + "i82875p CE"); return 1; } - static void i82875p_check(struct mem_ctl_info *mci) { struct i82875p_error_info info; @@ -267,7 +255,6 @@ static void i82875p_check(struct mem_ctl_info *mci) i82875p_process_error_info(mci, &info, 1); } - #ifdef CONFIG_PROC_FS extern int pci_proc_attach_device(struct pci_dev *); #endif @@ -281,7 +268,6 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) unsigned long last_cumul_size; struct pci_dev *ovrfl_pdev; void __iomem *ovrfl_window = NULL; - u32 drc; u32 drc_chan; /* Number of channels 0=1chan,1=2chan */ u32 nr_chans; @@ -289,7 +275,6 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) struct i82875p_error_info discard; debugf0("%s()\n", __func__); - ovrfl_pdev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL); if (!ovrfl_pdev) { @@ -301,22 +286,23 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) */ pci_write_bits8(pdev, 0xf4, 0x2, 0x2); ovrfl_pdev = - pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0)); + pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0)); + if (!ovrfl_pdev) return -ENODEV; } + #ifdef CONFIG_PROC_FS if (!ovrfl_pdev->procent && pci_proc_attach_device(ovrfl_pdev)) { i82875p_printk(KERN_ERR, - "%s(): Failed to attach overflow device\n", - __func__); + "%s(): Failed to attach overflow device\n", __func__); return -ENODEV; } -#endif /* CONFIG_PROC_FS */ +#endif + /* CONFIG_PROC_FS */ if (pci_enable_device(ovrfl_pdev)) { i82875p_printk(KERN_ERR, - "%s(): Failed to enable overflow device\n", - __func__); + "%s(): Failed to enable overflow device\n", __func__); return -ENODEV; } @@ -325,13 +311,14 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) goto fail0; #endif } + /* cache is irrelevant for PCI bus reads/writes */ ovrfl_window = ioremap_nocache(pci_resource_start(ovrfl_pdev, 0), - pci_resource_len(ovrfl_pdev, 0)); + pci_resource_len(ovrfl_pdev, 0)); if (!ovrfl_window) { i82875p_printk(KERN_ERR, "%s(): Failed to ioremap bar6\n", - __func__); + __func__); goto fail1; } @@ -339,10 +326,10 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) drc = readl(ovrfl_window + I82875P_DRC); drc_chan = ((drc >> 21) & 0x1); nr_chans = drc_chan + 1; - drc_ddim = (drc >> 18) & 0x1; + drc_ddim = (drc >> 18) & 0x1; mci = edac_mc_alloc(sizeof(*pvt), I82875P_NR_CSROWS(nr_chans), - nr_chans); + nr_chans); if (!mci) { rc = -ENOMEM; @@ -350,10 +337,8 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) } debugf3("%s(): init mci\n", __func__); - mci->pdev = pdev; mci->mtype_cap = MEM_FLAG_DDR; - mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_UNKNOWN; /* adjust FLAGS */ @@ -363,9 +348,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) mci->ctl_name = i82875p_devs[dev_idx].ctl_name; mci->edac_check = i82875p_check; mci->ctl_page_to_phys = NULL; - debugf3("%s(): init pvt\n", __func__); - pvt = (struct i82875p_pvt *) mci->pvt_info; pvt->ovrfl_pdev = ovrfl_pdev; pvt->ovrfl_window = ovrfl_window; @@ -385,6 +368,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT); debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, cumul_size); + if (cumul_size == last_cumul_size) continue; /* not populated */ @@ -392,7 +376,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) csrow->last_page = cumul_size - 1; csrow->nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; - csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */ + csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */ csrow->mtype = MEM_DDR; csrow->dtype = DEV_UNKNOWN; csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE; @@ -426,25 +410,26 @@ fail0: return rc; } - /* returns count (>= 0), or negative on error */ static int __devinit i82875p_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { int rc; debugf0("%s()\n", __func__); - i82875p_printk(KERN_INFO, "i82875p init one\n"); - if(pci_enable_device(pdev) < 0) + + if (pci_enable_device(pdev) < 0) return -EIO; + rc = i82875p_probe1(pdev, ent->driver_data); + if (mci_pdev == NULL) mci_pdev = pci_dev_get(pdev); + return rc; } - static void __devexit i82875p_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; @@ -456,6 +441,7 @@ static void __devexit i82875p_remove_one(struct pci_dev *pdev) return; pvt = (struct i82875p_pvt *) mci->pvt_info; + if (pvt->ovrfl_window) iounmap(pvt->ovrfl_window); @@ -470,16 +456,18 @@ static void __devexit i82875p_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } - static const struct pci_device_id i82875p_pci_tbl[] __devinitdata = { - {PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, - I82875P}, - {0,} /* 0 terminated list. */ + { + PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + I82875P + }, + { + 0, + } /* 0 terminated list. */ }; MODULE_DEVICE_TABLE(pci, i82875p_pci_tbl); - static struct pci_driver i82875p_driver = { .name = EDAC_MOD_STR, .probe = i82875p_init_one, @@ -487,31 +475,35 @@ static struct pci_driver i82875p_driver = { .id_table = i82875p_pci_tbl, }; - static int __init i82875p_init(void) { int pci_rc; debugf3("%s()\n", __func__); pci_rc = pci_register_driver(&i82875p_driver); + if (pci_rc < 0) goto fail0; + if (mci_pdev == NULL) { - mci_pdev = - pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82875_0, NULL); + mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82875_0, NULL); + if (!mci_pdev) { debugf0("875p pci_get_device fail\n"); pci_rc = -ENODEV; goto fail1; } + pci_rc = i82875p_init_one(mci_pdev, i82875p_pci_tbl); + if (pci_rc < 0) { debugf0("875p init fail\n"); pci_rc = -ENODEV; goto fail1; } } + return 0; fail1: @@ -524,23 +516,21 @@ fail0: return pci_rc; } - static void __exit i82875p_exit(void) { debugf3("%s()\n", __func__); pci_unregister_driver(&i82875p_driver); + if (!i82875p_registered) { i82875p_remove_one(mci_pdev); pci_dev_put(mci_pdev); } } - module_init(i82875p_init); module_exit(i82875p_exit); - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh"); MODULE_DESCRIPTION("MC support for Intel 82875 memory hub controllers"); diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index 5966916d02b..2c29fafe67c 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -18,19 +18,16 @@ #include <linux/config.h> #include <linux/module.h> #include <linux/init.h> - #include <linux/pci.h> #include <linux/pci_ids.h> - #include <linux/slab.h> - #include "edac_mc.h" #define r82600_printk(level, fmt, arg...) \ - edac_printk(level, "r82600", fmt, ##arg) + edac_printk(level, "r82600", fmt, ##arg) #define r82600_mc_printk(mci, level, fmt, arg...) \ - edac_mc_chipset_printk(mci, level, "r82600", fmt, ##arg) + edac_mc_chipset_printk(mci, level, "r82600", fmt, ##arg) /* Radisys say "The 82600 integrates a main memory SDRAM controller that * supports up to four banks of memory. The four banks can support a mix of @@ -132,10 +129,8 @@ struct r82600_error_info { u32 eapr; }; - static unsigned int disable_hardware_scrub = 0; - static void r82600_get_error_info (struct mem_ctl_info *mci, struct r82600_error_info *info) { @@ -144,17 +139,16 @@ static void r82600_get_error_info (struct mem_ctl_info *mci, if (info->eapr & BIT(0)) /* Clear error to allow next error to be reported [p.62] */ pci_write_bits32(mci->pdev, R82600_EAP, - ((u32) BIT(0) & (u32) BIT(1)), - ((u32) BIT(0) & (u32) BIT(1))); + ((u32) BIT(0) & (u32) BIT(1)), + ((u32) BIT(0) & (u32) BIT(1))); if (info->eapr & BIT(1)) /* Clear error to allow next error to be reported [p.62] */ pci_write_bits32(mci->pdev, R82600_EAP, - ((u32) BIT(0) & (u32) BIT(1)), - ((u32) BIT(0) & (u32) BIT(1))); + ((u32) BIT(0) & (u32) BIT(1)), + ((u32) BIT(0) & (u32) BIT(1))); } - static int r82600_process_error_info (struct mem_ctl_info *mci, struct r82600_error_info *info, int handle_errors) { @@ -173,26 +167,25 @@ static int r82600_process_error_info (struct mem_ctl_info *mci, * granularity (upper 19 bits only) */ page = eapaddr >> PAGE_SHIFT; - if (info->eapr & BIT(0)) { /* CE? */ + if (info->eapr & BIT(0)) { /* CE? */ error_found = 1; if (handle_errors) - edac_mc_handle_ce( - mci, page, 0, /* not avail */ - syndrome, - edac_mc_find_csrow_by_page(mci, page), - 0, /* channel */ - mci->ctl_name); + edac_mc_handle_ce(mci, page, 0, /* not avail */ + syndrome, + edac_mc_find_csrow_by_page(mci, page), + 0, /* channel */ + mci->ctl_name); } - if (info->eapr & BIT(1)) { /* UE? */ + if (info->eapr & BIT(1)) { /* UE? */ error_found = 1; if (handle_errors) /* 82600 doesn't give enough info */ edac_mc_handle_ue(mci, page, 0, - edac_mc_find_csrow_by_page(mci, page), - mci->ctl_name); + edac_mc_find_csrow_by_page(mci, page), + mci->ctl_name); } return error_found; @@ -222,21 +215,15 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) struct r82600_error_info discard; debugf0("%s()\n", __func__); - - pci_read_config_byte(pdev, R82600_DRAMC, &dramcr); pci_read_config_dword(pdev, R82600_EAP, &eapr); - ecc_on = dramcr & BIT(5); reg_sdram = dramcr & BIT(4); scrub_disabled = eapr & BIT(31); sdram_refresh_rate = dramcr & (BIT(0) | BIT(1)); - debugf2("%s(): sdram refresh rate = %#0x\n", __func__, sdram_refresh_rate); - debugf2("%s(): DRAMC register = %#0x\n", __func__, dramcr); - mci = edac_mc_alloc(0, R82600_NR_CSROWS, R82600_NR_CHANS); if (mci == NULL) { @@ -245,19 +232,19 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) } debugf0("%s(): mci = %p\n", __func__, mci); - mci->pdev = pdev; mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; - mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; - /* FIXME try to work out if the chip leads have been * - * used for COM2 instead on this board? [MA6?] MAYBE: */ + /* FIXME try to work out if the chip leads have been used for COM2 + * instead on this board? [MA6?] MAYBE: + */ /* On the R82600, the pins for memory bits 72:65 - i.e. the * * EC bits are shared with the pins for COM2 (!), so if COM2 * * is enabled, we assume COM2 is wired up, and thus no EDAC * * is possible. */ mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; + if (ecc_on) { if (scrub_disabled) debugf3("%s(): mci = %p - Scrubbing disabled! EAP: " @@ -295,7 +282,6 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) continue; row_base = row_high_limit_last; - csrow->first_page = row_base >> PAGE_SHIFT; csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1; csrow->nr_pages = csrow->last_page - csrow->first_page + 1; @@ -338,7 +324,7 @@ fail: /* returns count (>= 0), or negative on error */ static int __devinit r82600_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { debugf0("%s()\n", __func__); @@ -346,7 +332,6 @@ static int __devinit r82600_init_one(struct pci_dev *pdev, return r82600_probe1(pdev, ent->driver_data); } - static void __devexit r82600_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; @@ -359,15 +344,17 @@ static void __devexit r82600_remove_one(struct pci_dev *pdev) edac_mc_free(mci); } - static const struct pci_device_id r82600_pci_tbl[] __devinitdata = { - {PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID)}, - {0,} /* 0 terminated list. */ + { + PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID) + }, + { + 0, + } /* 0 terminated list. */ }; MODULE_DEVICE_TABLE(pci, r82600_pci_tbl); - static struct pci_driver r82600_driver = { .name = EDAC_MOD_STR, .probe = r82600_init_one, @@ -375,26 +362,22 @@ static struct pci_driver r82600_driver = { .id_table = r82600_pci_tbl, }; - static int __init r82600_init(void) { return pci_register_driver(&r82600_driver); } - static void __exit r82600_exit(void) { pci_unregister_driver(&r82600_driver); } - module_init(r82600_init); module_exit(r82600_exit); - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD Ltd. " - "on behalf of EADS Astrium"); + "on behalf of EADS Astrium"); MODULE_DESCRIPTION("MC support for Radisys 82600 memory controllers"); module_param(disable_hardware_scrub, bool, 0644); |