diff options
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/amd76x_edac.c | 98 | ||||
-rw-r--r-- | drivers/edac/e752x_edac.c | 344 | ||||
-rw-r--r-- | drivers/edac/e7xxx_edac.c | 175 | ||||
-rw-r--r-- | drivers/edac/edac_mc.c | 589 | ||||
-rw-r--r-- | drivers/edac/edac_mc.h | 18 | ||||
-rw-r--r-- | drivers/edac/i82860_edac.c | 131 | ||||
-rw-r--r-- | drivers/edac/i82875p_edac.c | 219 | ||||
-rw-r--r-- | drivers/edac/r82600_edac.c | 142 |
8 files changed, 930 insertions, 786 deletions
diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index 35599ed4bad5..d75864e35fef 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c | |||
@@ -19,6 +19,9 @@ | |||
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include "edac_mc.h" | 20 | #include "edac_mc.h" |
21 | 21 | ||
22 | #define AMD76X_REVISION " Ver: 2.0.0 " __DATE__ | ||
23 | |||
24 | |||
22 | #define amd76x_printk(level, fmt, arg...) \ | 25 | #define amd76x_printk(level, fmt, arg...) \ |
23 | edac_printk(level, "amd76x", fmt, ##arg) | 26 | edac_printk(level, "amd76x", fmt, ##arg) |
24 | 27 | ||
@@ -101,15 +104,18 @@ static const struct amd76x_dev_info amd76x_devs[] = { | |||
101 | static void amd76x_get_error_info(struct mem_ctl_info *mci, | 104 | static void amd76x_get_error_info(struct mem_ctl_info *mci, |
102 | struct amd76x_error_info *info) | 105 | struct amd76x_error_info *info) |
103 | { | 106 | { |
104 | pci_read_config_dword(mci->pdev, AMD76X_ECC_MODE_STATUS, | 107 | struct pci_dev *pdev; |
108 | |||
109 | pdev = to_pci_dev(mci->dev); | ||
110 | pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, | ||
105 | &info->ecc_mode_status); | 111 | &info->ecc_mode_status); |
106 | 112 | ||
107 | if (info->ecc_mode_status & BIT(8)) | 113 | if (info->ecc_mode_status & BIT(8)) |
108 | pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS, | 114 | pci_write_bits32(pdev, AMD76X_ECC_MODE_STATUS, |
109 | (u32) BIT(8), (u32) BIT(8)); | 115 | (u32) BIT(8), (u32) BIT(8)); |
110 | 116 | ||
111 | if (info->ecc_mode_status & BIT(9)) | 117 | if (info->ecc_mode_status & BIT(9)) |
112 | pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS, | 118 | pci_write_bits32(pdev, AMD76X_ECC_MODE_STATUS, |
113 | (u32) BIT(9), (u32) BIT(9)); | 119 | (u32) BIT(9), (u32) BIT(9)); |
114 | } | 120 | } |
115 | 121 | ||
@@ -175,6 +181,38 @@ static void amd76x_check(struct mem_ctl_info *mci) | |||
175 | amd76x_process_error_info(mci, &info, 1); | 181 | amd76x_process_error_info(mci, &info, 1); |
176 | } | 182 | } |
177 | 183 | ||
184 | static void amd76x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, | ||
185 | enum edac_type edac_mode) | ||
186 | { | ||
187 | struct csrow_info *csrow; | ||
188 | u32 mba, mba_base, mba_mask, dms; | ||
189 | int index; | ||
190 | |||
191 | for (index = 0; index < mci->nr_csrows; index++) { | ||
192 | csrow = &mci->csrows[index]; | ||
193 | |||
194 | /* find the DRAM Chip Select Base address and mask */ | ||
195 | pci_read_config_dword(pdev, | ||
196 | AMD76X_MEM_BASE_ADDR + (index * 4), | ||
197 | &mba); | ||
198 | |||
199 | if (!(mba & BIT(0))) | ||
200 | continue; | ||
201 | |||
202 | mba_base = mba & 0xff800000UL; | ||
203 | mba_mask = ((mba & 0xff80) << 16) | 0x7fffffUL; | ||
204 | pci_read_config_dword(pdev, AMD76X_DRAM_MODE_STATUS, &dms); | ||
205 | csrow->first_page = mba_base >> PAGE_SHIFT; | ||
206 | csrow->nr_pages = (mba_mask + 1) >> PAGE_SHIFT; | ||
207 | csrow->last_page = csrow->first_page + csrow->nr_pages - 1; | ||
208 | csrow->page_mask = mba_mask >> PAGE_SHIFT; | ||
209 | csrow->grain = csrow->nr_pages << PAGE_SHIFT; | ||
210 | csrow->mtype = MEM_RDDR; | ||
211 | csrow->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN; | ||
212 | csrow->edac_mode = edac_mode; | ||
213 | } | ||
214 | } | ||
215 | |||
178 | /** | 216 | /** |
179 | * amd76x_probe1 - Perform set up for detected device | 217 | * amd76x_probe1 - Perform set up for detected device |
180 | * @pdev; PCI device detected | 218 | * @pdev; PCI device detected |
@@ -186,15 +224,13 @@ static void amd76x_check(struct mem_ctl_info *mci) | |||
186 | */ | 224 | */ |
187 | static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) | 225 | static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) |
188 | { | 226 | { |
189 | int rc = -ENODEV; | 227 | static const enum edac_type ems_modes[] = { |
190 | int index; | ||
191 | struct mem_ctl_info *mci = NULL; | ||
192 | enum edac_type ems_modes[] = { | ||
193 | EDAC_NONE, | 228 | EDAC_NONE, |
194 | EDAC_EC, | 229 | EDAC_EC, |
195 | EDAC_SECDED, | 230 | EDAC_SECDED, |
196 | EDAC_SECDED | 231 | EDAC_SECDED |
197 | }; | 232 | }; |
233 | struct mem_ctl_info *mci = NULL; | ||
198 | u32 ems; | 234 | u32 ems; |
199 | u32 ems_mode; | 235 | u32 ems_mode; |
200 | struct amd76x_error_info discard; | 236 | struct amd76x_error_info discard; |
@@ -205,53 +241,28 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) | |||
205 | mci = edac_mc_alloc(0, AMD76X_NR_CSROWS, AMD76X_NR_CHANS); | 241 | mci = edac_mc_alloc(0, AMD76X_NR_CSROWS, AMD76X_NR_CHANS); |
206 | 242 | ||
207 | if (mci == NULL) { | 243 | if (mci == NULL) { |
208 | rc = -ENOMEM; | 244 | return -ENOMEM; |
209 | goto fail; | ||
210 | } | 245 | } |
211 | 246 | ||
212 | debugf0("%s(): mci = %p\n", __func__, mci); | 247 | debugf0("%s(): mci = %p\n", __func__, mci); |
213 | mci->pdev = pdev; | 248 | mci->dev = &pdev->dev; |
214 | mci->mtype_cap = MEM_FLAG_RDDR; | 249 | mci->mtype_cap = MEM_FLAG_RDDR; |
215 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; | 250 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; |
216 | mci->edac_cap = ems_mode ? | 251 | mci->edac_cap = ems_mode ? |
217 | (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE; | 252 | (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE; |
218 | mci->mod_name = EDAC_MOD_STR; | 253 | mci->mod_name = EDAC_MOD_STR; |
219 | mci->mod_ver = "$Revision: 1.4.2.5 $"; | 254 | mci->mod_ver = AMD76X_REVISION; |
220 | mci->ctl_name = amd76x_devs[dev_idx].ctl_name; | 255 | mci->ctl_name = amd76x_devs[dev_idx].ctl_name; |
221 | mci->edac_check = amd76x_check; | 256 | mci->edac_check = amd76x_check; |
222 | mci->ctl_page_to_phys = NULL; | 257 | mci->ctl_page_to_phys = NULL; |
223 | 258 | ||
224 | for (index = 0; index < mci->nr_csrows; index++) { | 259 | amd76x_init_csrows(mci, pdev, ems_modes[ems_mode]); |
225 | struct csrow_info *csrow = &mci->csrows[index]; | ||
226 | u32 mba; | ||
227 | u32 mba_base; | ||
228 | u32 mba_mask; | ||
229 | u32 dms; | ||
230 | |||
231 | /* find the DRAM Chip Select Base address and mask */ | ||
232 | pci_read_config_dword(mci->pdev, | ||
233 | AMD76X_MEM_BASE_ADDR + (index * 4), &mba); | ||
234 | |||
235 | if (!(mba & BIT(0))) | ||
236 | continue; | ||
237 | |||
238 | mba_base = mba & 0xff800000UL; | ||
239 | mba_mask = ((mba & 0xff80) << 16) | 0x7fffffUL; | ||
240 | pci_read_config_dword(mci->pdev, AMD76X_DRAM_MODE_STATUS, | ||
241 | &dms); | ||
242 | csrow->first_page = mba_base >> PAGE_SHIFT; | ||
243 | csrow->nr_pages = (mba_mask + 1) >> PAGE_SHIFT; | ||
244 | csrow->last_page = csrow->first_page + csrow->nr_pages - 1; | ||
245 | csrow->page_mask = mba_mask >> PAGE_SHIFT; | ||
246 | csrow->grain = csrow->nr_pages << PAGE_SHIFT; | ||
247 | csrow->mtype = MEM_RDDR; | ||
248 | csrow->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN; | ||
249 | csrow->edac_mode = ems_modes[ems_mode]; | ||
250 | } | ||
251 | |||
252 | amd76x_get_error_info(mci, &discard); /* clear counters */ | 260 | amd76x_get_error_info(mci, &discard); /* clear counters */ |
253 | 261 | ||
254 | if (edac_mc_add_mc(mci)) { | 262 | /* Here we assume that we will never see multiple instances of this |
263 | * type of memory controller. The ID is therefore hardcoded to 0. | ||
264 | */ | ||
265 | if (edac_mc_add_mc(mci,0)) { | ||
255 | debugf3("%s(): failed edac_mc_add_mc()\n", __func__); | 266 | debugf3("%s(): failed edac_mc_add_mc()\n", __func__); |
256 | goto fail; | 267 | goto fail; |
257 | } | 268 | } |
@@ -261,9 +272,8 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) | |||
261 | return 0; | 272 | return 0; |
262 | 273 | ||
263 | fail: | 274 | fail: |
264 | if (mci != NULL) | 275 | edac_mc_free(mci); |
265 | edac_mc_free(mci); | 276 | return -ENODEV; |
266 | return rc; | ||
267 | } | 277 | } |
268 | 278 | ||
269 | /* returns count (>= 0), or negative on error */ | 279 | /* returns count (>= 0), or negative on error */ |
@@ -290,7 +300,7 @@ static void __devexit amd76x_remove_one(struct pci_dev *pdev) | |||
290 | 300 | ||
291 | debugf0("%s()\n", __func__); | 301 | debugf0("%s()\n", __func__); |
292 | 302 | ||
293 | if ((mci = edac_mc_del_mc(pdev)) == NULL) | 303 | if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL) |
294 | return; | 304 | return; |
295 | 305 | ||
296 | edac_mc_free(mci); | 306 | edac_mc_free(mci); |
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index a52573b3280c..815c3eb783de 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c | |||
@@ -24,6 +24,8 @@ | |||
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include "edac_mc.h" | 25 | #include "edac_mc.h" |
26 | 26 | ||
27 | #define E752X_REVISION " Ver: 2.0.0 " __DATE__ | ||
28 | |||
27 | static int force_function_unhide; | 29 | static int force_function_unhide; |
28 | 30 | ||
29 | #define e752x_printk(level, fmt, arg...) \ | 31 | #define e752x_printk(level, fmt, arg...) \ |
@@ -762,22 +764,174 @@ static void e752x_check(struct mem_ctl_info *mci) | |||
762 | e752x_process_error_info(mci, &info, 1); | 764 | e752x_process_error_info(mci, &info, 1); |
763 | } | 765 | } |
764 | 766 | ||
765 | static int e752x_probe1(struct pci_dev *pdev, int dev_idx) | 767 | /* Return 1 if dual channel mode is active. Else return 0. */ |
768 | static inline int dual_channel_active(u16 ddrcsr) | ||
769 | { | ||
770 | return (((ddrcsr >> 12) & 3) == 3); | ||
771 | } | ||
772 | |||
773 | static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, | ||
774 | u16 ddrcsr) | ||
775 | { | ||
776 | struct csrow_info *csrow; | ||
777 | unsigned long last_cumul_size; | ||
778 | int index, mem_dev, drc_chan; | ||
779 | int drc_drbg; /* DRB granularity 0=64mb, 1=128mb */ | ||
780 | int drc_ddim; /* DRAM Data Integrity Mode 0=none, 2=edac */ | ||
781 | u8 value; | ||
782 | u32 dra, drc, cumul_size; | ||
783 | |||
784 | pci_read_config_dword(pdev, E752X_DRA, &dra); | ||
785 | pci_read_config_dword(pdev, E752X_DRC, &drc); | ||
786 | drc_chan = dual_channel_active(ddrcsr); | ||
787 | drc_drbg = drc_chan + 1; /* 128 in dual mode, 64 in single */ | ||
788 | drc_ddim = (drc >> 20) & 0x3; | ||
789 | |||
790 | /* The dram row boundary (DRB) reg values are boundary address for | ||
791 | * each DRAM row with a granularity of 64 or 128MB (single/dual | ||
792 | * channel operation). DRB regs are cumulative; therefore DRB7 will | ||
793 | * contain the total memory contained in all eight rows. | ||
794 | */ | ||
795 | for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) { | ||
796 | /* mem_dev 0=x8, 1=x4 */ | ||
797 | mem_dev = (dra >> (index * 4 + 2)) & 0x3; | ||
798 | csrow = &mci->csrows[index]; | ||
799 | |||
800 | mem_dev = (mem_dev == 2); | ||
801 | pci_read_config_byte(pdev, E752X_DRB + index, &value); | ||
802 | /* convert a 128 or 64 MiB DRB to a page size. */ | ||
803 | cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); | ||
804 | debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, | ||
805 | cumul_size); | ||
806 | if (cumul_size == last_cumul_size) | ||
807 | continue; /* not populated */ | ||
808 | |||
809 | csrow->first_page = last_cumul_size; | ||
810 | csrow->last_page = cumul_size - 1; | ||
811 | csrow->nr_pages = cumul_size - last_cumul_size; | ||
812 | last_cumul_size = cumul_size; | ||
813 | csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */ | ||
814 | csrow->mtype = MEM_RDDR; /* only one type supported */ | ||
815 | csrow->dtype = mem_dev ? DEV_X4 : DEV_X8; | ||
816 | |||
817 | /* | ||
818 | * if single channel or x8 devices then SECDED | ||
819 | * if dual channel and x4 then S4ECD4ED | ||
820 | */ | ||
821 | if (drc_ddim) { | ||
822 | if (drc_chan && mem_dev) { | ||
823 | csrow->edac_mode = EDAC_S4ECD4ED; | ||
824 | mci->edac_cap |= EDAC_FLAG_S4ECD4ED; | ||
825 | } else { | ||
826 | csrow->edac_mode = EDAC_SECDED; | ||
827 | mci->edac_cap |= EDAC_FLAG_SECDED; | ||
828 | } | ||
829 | } else | ||
830 | csrow->edac_mode = EDAC_NONE; | ||
831 | } | ||
832 | } | ||
833 | |||
834 | static void e752x_init_mem_map_table(struct pci_dev *pdev, | ||
835 | struct e752x_pvt *pvt) | ||
766 | { | 836 | { |
767 | int rc = -ENODEV; | ||
768 | int index; | 837 | int index; |
838 | u8 value, last, row, stat8; | ||
839 | |||
840 | last = 0; | ||
841 | row = 0; | ||
842 | |||
843 | for (index = 0; index < 8; index += 2) { | ||
844 | pci_read_config_byte(pdev, E752X_DRB + index, &value); | ||
845 | /* test if there is a dimm in this slot */ | ||
846 | if (value == last) { | ||
847 | /* no dimm in the slot, so flag it as empty */ | ||
848 | pvt->map[index] = 0xff; | ||
849 | pvt->map[index + 1] = 0xff; | ||
850 | } else { /* there is a dimm in the slot */ | ||
851 | pvt->map[index] = row; | ||
852 | row++; | ||
853 | last = value; | ||
854 | /* test the next value to see if the dimm is double | ||
855 | * sided | ||
856 | */ | ||
857 | pci_read_config_byte(pdev, E752X_DRB + index + 1, | ||
858 | &value); | ||
859 | pvt->map[index + 1] = (value == last) ? | ||
860 | 0xff : /* the dimm is single sided, | ||
861 | so flag as empty */ | ||
862 | row; /* this is a double sided dimm | ||
863 | to save the next row # */ | ||
864 | row++; | ||
865 | last = value; | ||
866 | } | ||
867 | } | ||
868 | |||
869 | /* set the map type. 1 = normal, 0 = reversed */ | ||
870 | pci_read_config_byte(pdev, E752X_DRM, &stat8); | ||
871 | pvt->map_type = ((stat8 & 0x0f) > ((stat8 >> 4) & 0x0f)); | ||
872 | } | ||
873 | |||
874 | /* Return 0 on success or 1 on failure. */ | ||
875 | static int e752x_get_devs(struct pci_dev *pdev, int dev_idx, | ||
876 | struct e752x_pvt *pvt) | ||
877 | { | ||
878 | struct pci_dev *dev; | ||
879 | |||
880 | pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
881 | pvt->dev_info->err_dev, | ||
882 | pvt->bridge_ck); | ||
883 | |||
884 | if (pvt->bridge_ck == NULL) | ||
885 | pvt->bridge_ck = pci_scan_single_device(pdev->bus, | ||
886 | PCI_DEVFN(0, 1)); | ||
887 | |||
888 | if (pvt->bridge_ck == NULL) { | ||
889 | e752x_printk(KERN_ERR, "error reporting device not found:" | ||
890 | "vendor %x device 0x%x (broken BIOS?)\n", | ||
891 | PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].err_dev); | ||
892 | return 1; | ||
893 | } | ||
894 | |||
895 | dev = pci_get_device(PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].ctl_dev, | ||
896 | NULL); | ||
897 | |||
898 | if (dev == NULL) | ||
899 | goto fail; | ||
900 | |||
901 | pvt->dev_d0f0 = dev; | ||
902 | pvt->dev_d0f1 = pci_dev_get(pvt->bridge_ck); | ||
903 | |||
904 | return 0; | ||
905 | |||
906 | fail: | ||
907 | pci_dev_put(pvt->bridge_ck); | ||
908 | return 1; | ||
909 | } | ||
910 | |||
911 | static void e752x_init_error_reporting_regs(struct e752x_pvt *pvt) | ||
912 | { | ||
913 | struct pci_dev *dev; | ||
914 | |||
915 | dev = pvt->dev_d0f1; | ||
916 | /* Turn off error disable & SMI in case the BIOS turned it on */ | ||
917 | pci_write_config_byte(dev, E752X_HI_ERRMASK, 0x00); | ||
918 | pci_write_config_byte(dev, E752X_HI_SMICMD, 0x00); | ||
919 | pci_write_config_word(dev, E752X_SYSBUS_ERRMASK, 0x00); | ||
920 | pci_write_config_word(dev, E752X_SYSBUS_SMICMD, 0x00); | ||
921 | pci_write_config_byte(dev, E752X_BUF_ERRMASK, 0x00); | ||
922 | pci_write_config_byte(dev, E752X_BUF_SMICMD, 0x00); | ||
923 | pci_write_config_byte(dev, E752X_DRAM_ERRMASK, 0x00); | ||
924 | pci_write_config_byte(dev, E752X_DRAM_SMICMD, 0x00); | ||
925 | } | ||
926 | |||
927 | static int e752x_probe1(struct pci_dev *pdev, int dev_idx) | ||
928 | { | ||
769 | u16 pci_data; | 929 | u16 pci_data; |
770 | u8 stat8; | 930 | u8 stat8; |
771 | struct mem_ctl_info *mci = NULL; | 931 | struct mem_ctl_info *mci; |
772 | struct e752x_pvt *pvt = NULL; | 932 | struct e752x_pvt *pvt; |
773 | u16 ddrcsr; | 933 | u16 ddrcsr; |
774 | u32 drc; | ||
775 | int drc_chan; /* Number of channels 0=1chan,1=2chan */ | 934 | int drc_chan; /* Number of channels 0=1chan,1=2chan */ |
776 | int drc_drbg; /* DRB granularity 0=64mb, 1=128mb */ | ||
777 | int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ | ||
778 | u32 dra; | ||
779 | unsigned long last_cumul_size; | ||
780 | struct pci_dev *dev = NULL; | ||
781 | struct e752x_error_info discard; | 935 | struct e752x_error_info discard; |
782 | 936 | ||
783 | debugf0("%s(): mci\n", __func__); | 937 | debugf0("%s(): mci\n", __func__); |
@@ -791,25 +945,20 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) | |||
791 | if (!force_function_unhide && !(stat8 & (1 << 5))) { | 945 | if (!force_function_unhide && !(stat8 & (1 << 5))) { |
792 | printk(KERN_INFO "Contact your BIOS vendor to see if the " | 946 | printk(KERN_INFO "Contact your BIOS vendor to see if the " |
793 | "E752x error registers can be safely un-hidden\n"); | 947 | "E752x error registers can be safely un-hidden\n"); |
794 | goto fail; | 948 | return -ENOMEM; |
795 | } | 949 | } |
796 | stat8 |= (1 << 5); | 950 | stat8 |= (1 << 5); |
797 | pci_write_config_byte(pdev, E752X_DEVPRES1, stat8); | 951 | pci_write_config_byte(pdev, E752X_DEVPRES1, stat8); |
798 | 952 | ||
799 | /* need to find out the number of channels */ | ||
800 | pci_read_config_dword(pdev, E752X_DRC, &drc); | ||
801 | pci_read_config_word(pdev, E752X_DDRCSR, &ddrcsr); | 953 | pci_read_config_word(pdev, E752X_DDRCSR, &ddrcsr); |
802 | /* FIXME: should check >>12 or 0xf, true for all? */ | 954 | /* FIXME: should check >>12 or 0xf, true for all? */ |
803 | /* Dual channel = 1, Single channel = 0 */ | 955 | /* Dual channel = 1, Single channel = 0 */ |
804 | drc_chan = (((ddrcsr >> 12) & 3) == 3); | 956 | drc_chan = dual_channel_active(ddrcsr); |
805 | drc_drbg = drc_chan + 1; /* 128 in dual mode, 64 in single */ | ||
806 | drc_ddim = (drc >> 20) & 0x3; | ||
807 | 957 | ||
808 | mci = edac_mc_alloc(sizeof(*pvt), E752X_NR_CSROWS, drc_chan + 1); | 958 | mci = edac_mc_alloc(sizeof(*pvt), E752X_NR_CSROWS, drc_chan + 1); |
809 | 959 | ||
810 | if (mci == NULL) { | 960 | if (mci == NULL) { |
811 | rc = -ENOMEM; | 961 | return -ENOMEM; |
812 | goto fail; | ||
813 | } | 962 | } |
814 | 963 | ||
815 | debugf3("%s(): init mci\n", __func__); | 964 | debugf3("%s(): init mci\n", __func__); |
@@ -818,159 +967,54 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) | |||
818 | EDAC_FLAG_S4ECD4ED; | 967 | EDAC_FLAG_S4ECD4ED; |
819 | /* FIXME - what if different memory types are in different csrows? */ | 968 | /* FIXME - what if different memory types are in different csrows? */ |
820 | mci->mod_name = EDAC_MOD_STR; | 969 | mci->mod_name = EDAC_MOD_STR; |
821 | mci->mod_ver = "$Revision: 1.5.2.11 $"; | 970 | mci->mod_ver = E752X_REVISION; |
822 | mci->pdev = pdev; | 971 | mci->dev = &pdev->dev; |
823 | 972 | ||
824 | debugf3("%s(): init pvt\n", __func__); | 973 | debugf3("%s(): init pvt\n", __func__); |
825 | pvt = (struct e752x_pvt *) mci->pvt_info; | 974 | pvt = (struct e752x_pvt *) mci->pvt_info; |
826 | pvt->dev_info = &e752x_devs[dev_idx]; | 975 | pvt->dev_info = &e752x_devs[dev_idx]; |
827 | pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, | 976 | pvt->mc_symmetric = ((ddrcsr & 0x10) != 0); |
828 | pvt->dev_info->err_dev, | ||
829 | pvt->bridge_ck); | ||
830 | |||
831 | if (pvt->bridge_ck == NULL) | ||
832 | pvt->bridge_ck = pci_scan_single_device(pdev->bus, | ||
833 | PCI_DEVFN(0, 1)); | ||
834 | 977 | ||
835 | if (pvt->bridge_ck == NULL) { | 978 | if (e752x_get_devs(pdev, dev_idx, pvt)) { |
836 | e752x_printk(KERN_ERR, "error reporting device not found:" | 979 | edac_mc_free(mci); |
837 | "vendor %x device 0x%x (broken BIOS?)\n", | 980 | return -ENODEV; |
838 | PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].err_dev); | ||
839 | goto fail; | ||
840 | } | 981 | } |
841 | 982 | ||
842 | pvt->mc_symmetric = ((ddrcsr & 0x10) != 0); | ||
843 | debugf3("%s(): more mci init\n", __func__); | 983 | debugf3("%s(): more mci init\n", __func__); |
844 | mci->ctl_name = pvt->dev_info->ctl_name; | 984 | mci->ctl_name = pvt->dev_info->ctl_name; |
845 | mci->edac_check = e752x_check; | 985 | mci->edac_check = e752x_check; |
846 | mci->ctl_page_to_phys = ctl_page_to_phys; | 986 | mci->ctl_page_to_phys = ctl_page_to_phys; |
847 | 987 | ||
848 | /* find out the device types */ | 988 | e752x_init_csrows(mci, pdev, ddrcsr); |
849 | pci_read_config_dword(pdev, E752X_DRA, &dra); | 989 | e752x_init_mem_map_table(pdev, pvt); |
850 | |||
851 | /* | ||
852 | * The dram row boundary (DRB) reg values are boundary address for | ||
853 | * each DRAM row with a granularity of 64 or 128MB (single/dual | ||
854 | * channel operation). DRB regs are cumulative; therefore DRB7 will | ||
855 | * contain the total memory contained in all eight rows. | ||
856 | */ | ||
857 | for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) { | ||
858 | u8 value; | ||
859 | u32 cumul_size; | ||
860 | |||
861 | /* mem_dev 0=x8, 1=x4 */ | ||
862 | int mem_dev = (dra >> (index * 4 + 2)) & 0x3; | ||
863 | struct csrow_info *csrow = &mci->csrows[index]; | ||
864 | |||
865 | mem_dev = (mem_dev == 2); | ||
866 | pci_read_config_byte(mci->pdev, E752X_DRB + index, &value); | ||
867 | /* convert a 128 or 64 MiB DRB to a page size. */ | ||
868 | cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); | ||
869 | debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, | ||
870 | cumul_size); | ||
871 | |||
872 | if (cumul_size == last_cumul_size) | ||
873 | continue; /* not populated */ | ||
874 | |||
875 | csrow->first_page = last_cumul_size; | ||
876 | csrow->last_page = cumul_size - 1; | ||
877 | csrow->nr_pages = cumul_size - last_cumul_size; | ||
878 | last_cumul_size = cumul_size; | ||
879 | csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */ | ||
880 | csrow->mtype = MEM_RDDR; /* only one type supported */ | ||
881 | csrow->dtype = mem_dev ? DEV_X4 : DEV_X8; | ||
882 | |||
883 | /* | ||
884 | * if single channel or x8 devices then SECDED | ||
885 | * if dual channel and x4 then S4ECD4ED | ||
886 | */ | ||
887 | if (drc_ddim) { | ||
888 | if (drc_chan && mem_dev) { | ||
889 | csrow->edac_mode = EDAC_S4ECD4ED; | ||
890 | mci->edac_cap |= EDAC_FLAG_S4ECD4ED; | ||
891 | } else { | ||
892 | csrow->edac_mode = EDAC_SECDED; | ||
893 | mci->edac_cap |= EDAC_FLAG_SECDED; | ||
894 | } | ||
895 | } else | ||
896 | csrow->edac_mode = EDAC_NONE; | ||
897 | } | ||
898 | |||
899 | /* Fill in the memory map table */ | ||
900 | { | ||
901 | u8 value; | ||
902 | u8 last = 0; | ||
903 | u8 row = 0; | ||
904 | |||
905 | for (index = 0; index < 8; index += 2) { | ||
906 | pci_read_config_byte(mci->pdev, E752X_DRB + index, | ||
907 | &value); | ||
908 | |||
909 | /* test if there is a dimm in this slot */ | ||
910 | if (value == last) { | ||
911 | /* no dimm in the slot, so flag it as empty */ | ||
912 | pvt->map[index] = 0xff; | ||
913 | pvt->map[index + 1] = 0xff; | ||
914 | } else { /* there is a dimm in the slot */ | ||
915 | pvt->map[index] = row; | ||
916 | row++; | ||
917 | last = value; | ||
918 | /* test the next value to see if the dimm is | ||
919 | double sided */ | ||
920 | pci_read_config_byte(mci->pdev, | ||
921 | E752X_DRB + index + 1, | ||
922 | &value); | ||
923 | pvt->map[index + 1] = (value == last) ? | ||
924 | 0xff : /* the dimm is single sided, | ||
925 | * so flag as empty | ||
926 | */ | ||
927 | row; /* this is a double sided dimm | ||
928 | * to save the next row # | ||
929 | */ | ||
930 | row++; | ||
931 | last = value; | ||
932 | } | ||
933 | } | ||
934 | } | ||
935 | 990 | ||
936 | /* set the map type. 1 = normal, 0 = reversed */ | 991 | /* set the map type. 1 = normal, 0 = reversed */ |
937 | pci_read_config_byte(mci->pdev, E752X_DRM, &stat8); | 992 | pci_read_config_byte(pdev, E752X_DRM, &stat8); |
938 | pvt->map_type = ((stat8 & 0x0f) > ((stat8 >> 4) & 0x0f)); | 993 | pvt->map_type = ((stat8 & 0x0f) > ((stat8 >> 4) & 0x0f)); |
939 | 994 | ||
940 | mci->edac_cap |= EDAC_FLAG_NONE; | 995 | mci->edac_cap |= EDAC_FLAG_NONE; |
941 | debugf3("%s(): tolm, remapbase, remaplimit\n", __func__); | 996 | debugf3("%s(): tolm, remapbase, remaplimit\n", __func__); |
942 | 997 | ||
943 | /* load the top of low memory, remap base, and remap limit vars */ | 998 | /* load the top of low memory, remap base, and remap limit vars */ |
944 | pci_read_config_word(mci->pdev, E752X_TOLM, &pci_data); | 999 | pci_read_config_word(pdev, E752X_TOLM, &pci_data); |
945 | pvt->tolm = ((u32) pci_data) << 4; | 1000 | pvt->tolm = ((u32) pci_data) << 4; |
946 | pci_read_config_word(mci->pdev, E752X_REMAPBASE, &pci_data); | 1001 | pci_read_config_word(pdev, E752X_REMAPBASE, &pci_data); |
947 | pvt->remapbase = ((u32) pci_data) << 14; | 1002 | pvt->remapbase = ((u32) pci_data) << 14; |
948 | pci_read_config_word(mci->pdev, E752X_REMAPLIMIT, &pci_data); | 1003 | pci_read_config_word(pdev, E752X_REMAPLIMIT, &pci_data); |
949 | pvt->remaplimit = ((u32) pci_data) << 14; | 1004 | pvt->remaplimit = ((u32) pci_data) << 14; |
950 | e752x_printk(KERN_INFO, | 1005 | e752x_printk(KERN_INFO, |
951 | "tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm, | 1006 | "tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm, |
952 | pvt->remapbase, pvt->remaplimit); | 1007 | pvt->remapbase, pvt->remaplimit); |
953 | 1008 | ||
954 | if (edac_mc_add_mc(mci)) { | 1009 | /* Here we assume that we will never see multiple instances of this |
1010 | * type of memory controller. The ID is therefore hardcoded to 0. | ||
1011 | */ | ||
1012 | if (edac_mc_add_mc(mci,0)) { | ||
955 | debugf3("%s(): failed edac_mc_add_mc()\n", __func__); | 1013 | debugf3("%s(): failed edac_mc_add_mc()\n", __func__); |
956 | goto fail; | 1014 | goto fail; |
957 | } | 1015 | } |
958 | 1016 | ||
959 | dev = pci_get_device(PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].ctl_dev, | 1017 | e752x_init_error_reporting_regs(pvt); |
960 | NULL); | ||
961 | pvt->dev_d0f0 = dev; | ||
962 | /* find the error reporting device and clear errors */ | ||
963 | dev = pvt->dev_d0f1 = pci_dev_get(pvt->bridge_ck); | ||
964 | /* Turn off error disable & SMI in case the BIOS turned it on */ | ||
965 | pci_write_config_byte(dev, E752X_HI_ERRMASK, 0x00); | ||
966 | pci_write_config_byte(dev, E752X_HI_SMICMD, 0x00); | ||
967 | pci_write_config_word(dev, E752X_SYSBUS_ERRMASK, 0x00); | ||
968 | pci_write_config_word(dev, E752X_SYSBUS_SMICMD, 0x00); | ||
969 | pci_write_config_byte(dev, E752X_BUF_ERRMASK, 0x00); | ||
970 | pci_write_config_byte(dev, E752X_BUF_SMICMD, 0x00); | ||
971 | pci_write_config_byte(dev, E752X_DRAM_ERRMASK, 0x00); | ||
972 | pci_write_config_byte(dev, E752X_DRAM_SMICMD, 0x00); | ||
973 | |||
974 | e752x_get_error_info(mci, &discard); /* clear other MCH errors */ | 1018 | e752x_get_error_info(mci, &discard); /* clear other MCH errors */ |
975 | 1019 | ||
976 | /* get this far and it's successful */ | 1020 | /* get this far and it's successful */ |
@@ -978,20 +1022,12 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) | |||
978 | return 0; | 1022 | return 0; |
979 | 1023 | ||
980 | fail: | 1024 | fail: |
981 | if (mci) { | 1025 | pci_dev_put(pvt->dev_d0f0); |
982 | if (pvt->dev_d0f0) | 1026 | pci_dev_put(pvt->dev_d0f1); |
983 | pci_dev_put(pvt->dev_d0f0); | 1027 | pci_dev_put(pvt->bridge_ck); |
984 | 1028 | edac_mc_free(mci); | |
985 | if (pvt->dev_d0f1) | ||
986 | pci_dev_put(pvt->dev_d0f1); | ||
987 | |||
988 | if (pvt->bridge_ck) | ||
989 | pci_dev_put(pvt->bridge_ck); | ||
990 | |||
991 | edac_mc_free(mci); | ||
992 | } | ||
993 | 1029 | ||
994 | return rc; | 1030 | return -ENODEV; |
995 | } | 1031 | } |
996 | 1032 | ||
997 | /* returns count (>= 0), or negative on error */ | 1033 | /* returns count (>= 0), or negative on error */ |
@@ -1014,7 +1050,7 @@ static void __devexit e752x_remove_one(struct pci_dev *pdev) | |||
1014 | 1050 | ||
1015 | debugf0("%s()\n", __func__); | 1051 | debugf0("%s()\n", __func__); |
1016 | 1052 | ||
1017 | if ((mci = edac_mc_del_mc(pdev)) == NULL) | 1053 | if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL) |
1018 | return; | 1054 | return; |
1019 | 1055 | ||
1020 | pvt = (struct e752x_pvt *) mci->pvt_info; | 1056 | pvt = (struct e752x_pvt *) mci->pvt_info; |
diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index ecfca7c6bba6..5a5ecd5a0409 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include "edac_mc.h" | 30 | #include "edac_mc.h" |
31 | 31 | ||
32 | #define E7XXX_REVISION " Ver: 2.0.0 " __DATE__ | ||
33 | |||
32 | #define e7xxx_printk(level, fmt, arg...) \ | 34 | #define e7xxx_printk(level, fmt, arg...) \ |
33 | edac_printk(level, "e7xxx", fmt, ##arg) | 35 | edac_printk(level, "e7xxx", fmt, ##arg) |
34 | 36 | ||
@@ -332,99 +334,61 @@ static void e7xxx_check(struct mem_ctl_info *mci) | |||
332 | e7xxx_process_error_info(mci, &info, 1); | 334 | e7xxx_process_error_info(mci, &info, 1); |
333 | } | 335 | } |
334 | 336 | ||
335 | static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) | 337 | /* Return 1 if dual channel mode is active. Else return 0. */ |
338 | static inline int dual_channel_active(u32 drc, int dev_idx) | ||
336 | { | 339 | { |
337 | int rc = -ENODEV; | 340 | return (dev_idx == E7501) ? ((drc >> 22) & 0x1) : 1; |
338 | int index; | 341 | } |
339 | u16 pci_data; | ||
340 | struct mem_ctl_info *mci = NULL; | ||
341 | struct e7xxx_pvt *pvt = NULL; | ||
342 | u32 drc; | ||
343 | int drc_chan = 1; /* Number of channels 0=1chan,1=2chan */ | ||
344 | int drc_drbg = 1; /* DRB granularity 0=32mb,1=64mb */ | ||
345 | int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ | ||
346 | u32 dra; | ||
347 | unsigned long last_cumul_size; | ||
348 | struct e7xxx_error_info discard; | ||
349 | |||
350 | debugf0("%s(): mci\n", __func__); | ||
351 | 342 | ||
352 | /* need to find out the number of channels */ | ||
353 | pci_read_config_dword(pdev, E7XXX_DRC, &drc); | ||
354 | 343 | ||
344 | /* Return DRB granularity (0=32mb, 1=64mb). */ | ||
345 | static inline int drb_granularity(u32 drc, int dev_idx) | ||
346 | { | ||
355 | /* only e7501 can be single channel */ | 347 | /* only e7501 can be single channel */ |
356 | if (dev_idx == E7501) { | 348 | return (dev_idx == E7501) ? ((drc >> 18) & 0x3) : 1; |
357 | drc_chan = ((drc >> 22) & 0x1); | 349 | } |
358 | drc_drbg = (drc >> 18) & 0x3; | ||
359 | } | ||
360 | |||
361 | drc_ddim = (drc >> 20) & 0x3; | ||
362 | mci = edac_mc_alloc(sizeof(*pvt), E7XXX_NR_CSROWS, drc_chan + 1); | ||
363 | |||
364 | if (mci == NULL) { | ||
365 | rc = -ENOMEM; | ||
366 | goto fail; | ||
367 | } | ||
368 | |||
369 | debugf3("%s(): init mci\n", __func__); | ||
370 | mci->mtype_cap = MEM_FLAG_RDDR; | ||
371 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED | | ||
372 | EDAC_FLAG_S4ECD4ED; | ||
373 | /* FIXME - what if different memory types are in different csrows? */ | ||
374 | mci->mod_name = EDAC_MOD_STR; | ||
375 | mci->mod_ver = "$Revision: 1.5.2.9 $"; | ||
376 | mci->pdev = pdev; | ||
377 | 350 | ||
378 | debugf3("%s(): init pvt\n", __func__); | ||
379 | pvt = (struct e7xxx_pvt *) mci->pvt_info; | ||
380 | pvt->dev_info = &e7xxx_devs[dev_idx]; | ||
381 | pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
382 | pvt->dev_info->err_dev, | ||
383 | pvt->bridge_ck); | ||
384 | 351 | ||
385 | if (!pvt->bridge_ck) { | 352 | static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, |
386 | e7xxx_printk(KERN_ERR, "error reporting device not found:" | 353 | int dev_idx, u32 drc) |
387 | "vendor %x device 0x%x (broken BIOS?)\n", | 354 | { |
388 | PCI_VENDOR_ID_INTEL, e7xxx_devs[dev_idx].err_dev); | 355 | unsigned long last_cumul_size; |
389 | goto fail; | 356 | int index; |
390 | } | 357 | u8 value; |
391 | 358 | u32 dra, cumul_size; | |
392 | debugf3("%s(): more mci init\n", __func__); | 359 | int drc_chan, drc_drbg, drc_ddim, mem_dev; |
393 | mci->ctl_name = pvt->dev_info->ctl_name; | 360 | struct csrow_info *csrow; |
394 | mci->edac_check = e7xxx_check; | ||
395 | mci->ctl_page_to_phys = ctl_page_to_phys; | ||
396 | 361 | ||
397 | /* find out the device types */ | ||
398 | pci_read_config_dword(pdev, E7XXX_DRA, &dra); | 362 | pci_read_config_dword(pdev, E7XXX_DRA, &dra); |
363 | drc_chan = dual_channel_active(drc, dev_idx); | ||
364 | drc_drbg = drb_granularity(drc, dev_idx); | ||
365 | drc_ddim = (drc >> 20) & 0x3; | ||
366 | last_cumul_size = 0; | ||
399 | 367 | ||
400 | /* | 368 | /* The dram row boundary (DRB) reg values are boundary address |
401 | * The dram row boundary (DRB) reg values are boundary address | ||
402 | * for each DRAM row with a granularity of 32 or 64MB (single/dual | 369 | * for each DRAM row with a granularity of 32 or 64MB (single/dual |
403 | * channel operation). DRB regs are cumulative; therefore DRB7 will | 370 | * channel operation). DRB regs are cumulative; therefore DRB7 will |
404 | * contain the total memory contained in all eight rows. | 371 | * contain the total memory contained in all eight rows. |
405 | */ | 372 | */ |
406 | for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) { | 373 | for (index = 0; index < mci->nr_csrows; index++) { |
407 | u8 value; | ||
408 | u32 cumul_size; | ||
409 | /* mem_dev 0=x8, 1=x4 */ | 374 | /* mem_dev 0=x8, 1=x4 */ |
410 | int mem_dev = (dra >> (index * 4 + 3)) & 0x1; | 375 | mem_dev = (dra >> (index * 4 + 3)) & 0x1; |
411 | struct csrow_info *csrow = &mci->csrows[index]; | 376 | csrow = &mci->csrows[index]; |
412 | 377 | ||
413 | pci_read_config_byte(mci->pdev, E7XXX_DRB + index, &value); | 378 | pci_read_config_byte(pdev, E7XXX_DRB + index, &value); |
414 | /* convert a 64 or 32 MiB DRB to a page size. */ | 379 | /* convert a 64 or 32 MiB DRB to a page size. */ |
415 | cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); | 380 | cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); |
416 | debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, | 381 | debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, |
417 | cumul_size); | 382 | cumul_size); |
418 | |||
419 | if (cumul_size == last_cumul_size) | 383 | if (cumul_size == last_cumul_size) |
420 | continue; /* not populated */ | 384 | continue; /* not populated */ |
421 | 385 | ||
422 | csrow->first_page = last_cumul_size; | 386 | csrow->first_page = last_cumul_size; |
423 | csrow->last_page = cumul_size - 1; | 387 | csrow->last_page = cumul_size - 1; |
424 | csrow->nr_pages = cumul_size - last_cumul_size; | 388 | csrow->nr_pages = cumul_size - last_cumul_size; |
425 | last_cumul_size = cumul_size; | 389 | last_cumul_size = cumul_size; |
426 | csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */ | 390 | csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */ |
427 | csrow->mtype = MEM_RDDR; /* only one type supported */ | 391 | csrow->mtype = MEM_RDDR; /* only one type supported */ |
428 | csrow->dtype = mem_dev ? DEV_X4 : DEV_X8; | 392 | csrow->dtype = mem_dev ? DEV_X4 : DEV_X8; |
429 | 393 | ||
430 | /* | 394 | /* |
@@ -442,16 +406,61 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) | |||
442 | } else | 406 | } else |
443 | csrow->edac_mode = EDAC_NONE; | 407 | csrow->edac_mode = EDAC_NONE; |
444 | } | 408 | } |
409 | } | ||
445 | 410 | ||
446 | mci->edac_cap |= EDAC_FLAG_NONE; | 411 | static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) |
412 | { | ||
413 | u16 pci_data; | ||
414 | struct mem_ctl_info *mci = NULL; | ||
415 | struct e7xxx_pvt *pvt = NULL; | ||
416 | u32 drc; | ||
417 | int drc_chan; | ||
418 | struct e7xxx_error_info discard; | ||
419 | |||
420 | debugf0("%s(): mci\n", __func__); | ||
421 | pci_read_config_dword(pdev, E7XXX_DRC, &drc); | ||
422 | |||
423 | drc_chan = dual_channel_active(drc, dev_idx); | ||
424 | mci = edac_mc_alloc(sizeof(*pvt), E7XXX_NR_CSROWS, drc_chan + 1); | ||
425 | |||
426 | if (mci == NULL) | ||
427 | return -ENOMEM; | ||
428 | |||
429 | debugf3("%s(): init mci\n", __func__); | ||
430 | mci->mtype_cap = MEM_FLAG_RDDR; | ||
431 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED | | ||
432 | EDAC_FLAG_S4ECD4ED; | ||
433 | /* FIXME - what if different memory types are in different csrows? */ | ||
434 | mci->mod_name = EDAC_MOD_STR; | ||
435 | mci->mod_ver = E7XXX_REVISION; | ||
436 | mci->dev = &pdev->dev; | ||
437 | debugf3("%s(): init pvt\n", __func__); | ||
438 | pvt = (struct e7xxx_pvt *) mci->pvt_info; | ||
439 | pvt->dev_info = &e7xxx_devs[dev_idx]; | ||
440 | pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
441 | pvt->dev_info->err_dev, | ||
442 | pvt->bridge_ck); | ||
447 | 443 | ||
444 | if (!pvt->bridge_ck) { | ||
445 | e7xxx_printk(KERN_ERR, "error reporting device not found:" | ||
446 | "vendor %x device 0x%x (broken BIOS?)\n", | ||
447 | PCI_VENDOR_ID_INTEL, e7xxx_devs[dev_idx].err_dev); | ||
448 | goto fail0; | ||
449 | } | ||
450 | |||
451 | debugf3("%s(): more mci init\n", __func__); | ||
452 | mci->ctl_name = pvt->dev_info->ctl_name; | ||
453 | mci->edac_check = e7xxx_check; | ||
454 | mci->ctl_page_to_phys = ctl_page_to_phys; | ||
455 | e7xxx_init_csrows(mci, pdev, dev_idx, drc); | ||
456 | mci->edac_cap |= EDAC_FLAG_NONE; | ||
448 | debugf3("%s(): tolm, remapbase, remaplimit\n", __func__); | 457 | debugf3("%s(): tolm, remapbase, remaplimit\n", __func__); |
449 | /* load the top of low memory, remap base, and remap limit vars */ | 458 | /* load the top of low memory, remap base, and remap limit vars */ |
450 | pci_read_config_word(mci->pdev, E7XXX_TOLM, &pci_data); | 459 | pci_read_config_word(pdev, E7XXX_TOLM, &pci_data); |
451 | pvt->tolm = ((u32) pci_data) << 4; | 460 | pvt->tolm = ((u32) pci_data) << 4; |
452 | pci_read_config_word(mci->pdev, E7XXX_REMAPBASE, &pci_data); | 461 | pci_read_config_word(pdev, E7XXX_REMAPBASE, &pci_data); |
453 | pvt->remapbase = ((u32) pci_data) << 14; | 462 | pvt->remapbase = ((u32) pci_data) << 14; |
454 | pci_read_config_word(mci->pdev, E7XXX_REMAPLIMIT, &pci_data); | 463 | pci_read_config_word(pdev, E7XXX_REMAPLIMIT, &pci_data); |
455 | pvt->remaplimit = ((u32) pci_data) << 14; | 464 | pvt->remaplimit = ((u32) pci_data) << 14; |
456 | e7xxx_printk(KERN_INFO, | 465 | e7xxx_printk(KERN_INFO, |
457 | "tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm, | 466 | "tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm, |
@@ -460,23 +469,25 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) | |||
460 | /* clear any pending errors, or initial state bits */ | 469 | /* clear any pending errors, or initial state bits */ |
461 | e7xxx_get_error_info(mci, &discard); | 470 | e7xxx_get_error_info(mci, &discard); |
462 | 471 | ||
463 | if (edac_mc_add_mc(mci) != 0) { | 472 | /* Here we assume that we will never see multiple instances of this |
473 | * type of memory controller. The ID is therefore hardcoded to 0. | ||
474 | */ | ||
475 | if (edac_mc_add_mc(mci,0)) { | ||
464 | debugf3("%s(): failed edac_mc_add_mc()\n", __func__); | 476 | debugf3("%s(): failed edac_mc_add_mc()\n", __func__); |
465 | goto fail; | 477 | goto fail1; |
466 | } | 478 | } |
467 | 479 | ||
468 | /* get this far and it's successful */ | 480 | /* get this far and it's successful */ |
469 | debugf3("%s(): success\n", __func__); | 481 | debugf3("%s(): success\n", __func__); |
470 | return 0; | 482 | return 0; |
471 | 483 | ||
472 | fail: | 484 | fail1: |
473 | if (mci != NULL) { | 485 | pci_dev_put(pvt->bridge_ck); |
474 | if(pvt != NULL && pvt->bridge_ck) | 486 | |
475 | pci_dev_put(pvt->bridge_ck); | 487 | fail0: |
476 | edac_mc_free(mci); | 488 | edac_mc_free(mci); |
477 | } | ||
478 | 489 | ||
479 | return rc; | 490 | return -ENODEV; |
480 | } | 491 | } |
481 | 492 | ||
482 | /* returns count (>= 0), or negative on error */ | 493 | /* returns count (>= 0), or negative on error */ |
@@ -497,7 +508,7 @@ static void __devexit e7xxx_remove_one(struct pci_dev *pdev) | |||
497 | 508 | ||
498 | debugf0("%s()\n", __func__); | 509 | debugf0("%s()\n", __func__); |
499 | 510 | ||
500 | if ((mci = edac_mc_del_mc(pdev)) == NULL) | 511 | if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL) |
501 | return; | 512 | return; |
502 | 513 | ||
503 | pvt = (struct e7xxx_pvt *) mci->pvt_info; | 514 | pvt = (struct e7xxx_pvt *) mci->pvt_info; |
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 0499782db7c7..3a7cfe88b169 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c | |||
@@ -53,16 +53,17 @@ static int log_ce = 1; | |||
53 | static int panic_on_ue; | 53 | static int panic_on_ue; |
54 | static int poll_msec = 1000; | 54 | static int poll_msec = 1000; |
55 | 55 | ||
56 | static int check_pci_parity = 0; /* default YES check PCI parity */ | ||
57 | static int panic_on_pci_parity; /* default no panic on PCI Parity */ | ||
58 | static atomic_t pci_parity_count = ATOMIC_INIT(0); | ||
59 | |||
60 | /* lock to memory controller's control array */ | 56 | /* lock to memory controller's control array */ |
61 | static DECLARE_MUTEX(mem_ctls_mutex); | 57 | static DECLARE_MUTEX(mem_ctls_mutex); |
62 | static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices); | 58 | static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices); |
63 | 59 | ||
64 | static struct task_struct *edac_thread; | 60 | static struct task_struct *edac_thread; |
65 | 61 | ||
62 | #ifdef CONFIG_PCI | ||
63 | static int check_pci_parity = 0; /* default YES check PCI parity */ | ||
64 | static int panic_on_pci_parity; /* default no panic on PCI Parity */ | ||
65 | static atomic_t pci_parity_count = ATOMIC_INIT(0); | ||
66 | |||
66 | /* Structure of the whitelist and blacklist arrays */ | 67 | /* Structure of the whitelist and blacklist arrays */ |
67 | struct edac_pci_device_list { | 68 | struct edac_pci_device_list { |
68 | unsigned int vendor; /* Vendor ID */ | 69 | unsigned int vendor; /* Vendor ID */ |
@@ -79,6 +80,12 @@ static int pci_blacklist_count; | |||
79 | static struct edac_pci_device_list pci_whitelist[MAX_LISTED_PCI_DEVICES]; | 80 | static struct edac_pci_device_list pci_whitelist[MAX_LISTED_PCI_DEVICES]; |
80 | static int pci_whitelist_count ; | 81 | static int pci_whitelist_count ; |
81 | 82 | ||
83 | #ifndef DISABLE_EDAC_SYSFS | ||
84 | static struct kobject edac_pci_kobj; /* /sys/devices/system/edac/pci */ | ||
85 | static struct completion edac_pci_kobj_complete; | ||
86 | #endif /* DISABLE_EDAC_SYSFS */ | ||
87 | #endif /* CONFIG_PCI */ | ||
88 | |||
82 | /* START sysfs data and methods */ | 89 | /* START sysfs data and methods */ |
83 | 90 | ||
84 | #ifndef DISABLE_EDAC_SYSFS | 91 | #ifndef DISABLE_EDAC_SYSFS |
@@ -126,18 +133,15 @@ static struct sysdev_class edac_class = { | |||
126 | set_kset_name("edac"), | 133 | set_kset_name("edac"), |
127 | }; | 134 | }; |
128 | 135 | ||
129 | /* sysfs objects: | 136 | /* sysfs object: |
130 | * /sys/devices/system/edac/mc | 137 | * /sys/devices/system/edac/mc |
131 | * /sys/devices/system/edac/pci | ||
132 | */ | 138 | */ |
133 | static struct kobject edac_memctrl_kobj; | 139 | static struct kobject edac_memctrl_kobj; |
134 | static struct kobject edac_pci_kobj; | ||
135 | 140 | ||
136 | /* We use these to wait for the reference counts on edac_memctrl_kobj and | 141 | /* We use these to wait for the reference counts on edac_memctrl_kobj and |
137 | * edac_pci_kobj to reach 0. | 142 | * edac_pci_kobj to reach 0. |
138 | */ | 143 | */ |
139 | static struct completion edac_memctrl_kobj_complete; | 144 | static struct completion edac_memctrl_kobj_complete; |
140 | static struct completion edac_pci_kobj_complete; | ||
141 | 145 | ||
142 | /* | 146 | /* |
143 | * /sys/devices/system/edac/mc; | 147 | * /sys/devices/system/edac/mc; |
@@ -323,6 +327,8 @@ static void edac_sysfs_memctrl_teardown(void) | |||
323 | #endif /* DISABLE_EDAC_SYSFS */ | 327 | #endif /* DISABLE_EDAC_SYSFS */ |
324 | } | 328 | } |
325 | 329 | ||
330 | #ifdef CONFIG_PCI | ||
331 | |||
326 | #ifndef DISABLE_EDAC_SYSFS | 332 | #ifndef DISABLE_EDAC_SYSFS |
327 | 333 | ||
328 | /* | 334 | /* |
@@ -623,6 +629,252 @@ static void edac_sysfs_pci_teardown(void) | |||
623 | #endif | 629 | #endif |
624 | } | 630 | } |
625 | 631 | ||
632 | |||
633 | static u16 get_pci_parity_status(struct pci_dev *dev, int secondary) | ||
634 | { | ||
635 | int where; | ||
636 | u16 status; | ||
637 | |||
638 | where = secondary ? PCI_SEC_STATUS : PCI_STATUS; | ||
639 | pci_read_config_word(dev, where, &status); | ||
640 | |||
641 | /* If we get back 0xFFFF then we must suspect that the card has been | ||
642 | * pulled but the Linux PCI layer has not yet finished cleaning up. | ||
643 | * We don't want to report on such devices | ||
644 | */ | ||
645 | |||
646 | if (status == 0xFFFF) { | ||
647 | u32 sanity; | ||
648 | |||
649 | pci_read_config_dword(dev, 0, &sanity); | ||
650 | |||
651 | if (sanity == 0xFFFFFFFF) | ||
652 | return 0; | ||
653 | } | ||
654 | |||
655 | status &= PCI_STATUS_DETECTED_PARITY | PCI_STATUS_SIG_SYSTEM_ERROR | | ||
656 | PCI_STATUS_PARITY; | ||
657 | |||
658 | if (status) | ||
659 | /* reset only the bits we are interested in */ | ||
660 | pci_write_config_word(dev, where, status); | ||
661 | |||
662 | return status; | ||
663 | } | ||
664 | |||
665 | typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev); | ||
666 | |||
667 | /* Clear any PCI parity errors logged by this device. */ | ||
668 | static void edac_pci_dev_parity_clear(struct pci_dev *dev) | ||
669 | { | ||
670 | u8 header_type; | ||
671 | |||
672 | get_pci_parity_status(dev, 0); | ||
673 | |||
674 | /* read the device TYPE, looking for bridges */ | ||
675 | pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); | ||
676 | |||
677 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) | ||
678 | get_pci_parity_status(dev, 1); | ||
679 | } | ||
680 | |||
681 | /* | ||
682 | * PCI Parity polling | ||
683 | * | ||
684 | */ | ||
685 | static void edac_pci_dev_parity_test(struct pci_dev *dev) | ||
686 | { | ||
687 | u16 status; | ||
688 | u8 header_type; | ||
689 | |||
690 | /* read the STATUS register on this device | ||
691 | */ | ||
692 | status = get_pci_parity_status(dev, 0); | ||
693 | |||
694 | debugf2("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id ); | ||
695 | |||
696 | /* check the status reg for errors */ | ||
697 | if (status) { | ||
698 | if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) | ||
699 | edac_printk(KERN_CRIT, EDAC_PCI, | ||
700 | "Signaled System Error on %s\n", | ||
701 | pci_name(dev)); | ||
702 | |||
703 | if (status & (PCI_STATUS_PARITY)) { | ||
704 | edac_printk(KERN_CRIT, EDAC_PCI, | ||
705 | "Master Data Parity Error on %s\n", | ||
706 | pci_name(dev)); | ||
707 | |||
708 | atomic_inc(&pci_parity_count); | ||
709 | } | ||
710 | |||
711 | if (status & (PCI_STATUS_DETECTED_PARITY)) { | ||
712 | edac_printk(KERN_CRIT, EDAC_PCI, | ||
713 | "Detected Parity Error on %s\n", | ||
714 | pci_name(dev)); | ||
715 | |||
716 | atomic_inc(&pci_parity_count); | ||
717 | } | ||
718 | } | ||
719 | |||
720 | /* read the device TYPE, looking for bridges */ | ||
721 | pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); | ||
722 | |||
723 | debugf2("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev->dev.bus_id ); | ||
724 | |||
725 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { | ||
726 | /* On bridges, need to examine secondary status register */ | ||
727 | status = get_pci_parity_status(dev, 1); | ||
728 | |||
729 | debugf2("PCI SEC_STATUS= 0x%04x %s\n", | ||
730 | status, dev->dev.bus_id ); | ||
731 | |||
732 | /* check the secondary status reg for errors */ | ||
733 | if (status) { | ||
734 | if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) | ||
735 | edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " | ||
736 | "Signaled System Error on %s\n", | ||
737 | pci_name(dev)); | ||
738 | |||
739 | if (status & (PCI_STATUS_PARITY)) { | ||
740 | edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " | ||
741 | "Master Data Parity Error on " | ||
742 | "%s\n", pci_name(dev)); | ||
743 | |||
744 | atomic_inc(&pci_parity_count); | ||
745 | } | ||
746 | |||
747 | if (status & (PCI_STATUS_DETECTED_PARITY)) { | ||
748 | edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " | ||
749 | "Detected Parity Error on %s\n", | ||
750 | pci_name(dev)); | ||
751 | |||
752 | atomic_inc(&pci_parity_count); | ||
753 | } | ||
754 | } | ||
755 | } | ||
756 | } | ||
757 | |||
758 | /* | ||
759 | * check_dev_on_list: Scan for a PCI device on a white/black list | ||
760 | * @list: an EDAC &edac_pci_device_list white/black list pointer | ||
761 | * @free_index: index of next free entry on the list | ||
762 | * @pci_dev: PCI Device pointer | ||
763 | * | ||
764 | * see if list contains the device. | ||
765 | * | ||
766 | * Returns: 0 not found | ||
767 | * 1 found on list | ||
768 | */ | ||
769 | static int check_dev_on_list(struct edac_pci_device_list *list, | ||
770 | int free_index, struct pci_dev *dev) | ||
771 | { | ||
772 | int i; | ||
773 | int rc = 0; /* Assume not found */ | ||
774 | unsigned short vendor=dev->vendor; | ||
775 | unsigned short device=dev->device; | ||
776 | |||
777 | /* Scan the list, looking for a vendor/device match */ | ||
778 | for (i = 0; i < free_index; i++, list++ ) { | ||
779 | if ((list->vendor == vendor ) && (list->device == device )) { | ||
780 | rc = 1; | ||
781 | break; | ||
782 | } | ||
783 | } | ||
784 | |||
785 | return rc; | ||
786 | } | ||
787 | |||
788 | /* | ||
789 | * pci_dev parity list iterator | ||
790 | * Scan the PCI device list for one iteration, looking for SERRORs | ||
791 | * Master Parity ERRORS or Parity ERRORs on primary or secondary devices | ||
792 | */ | ||
793 | static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn) | ||
794 | { | ||
795 | struct pci_dev *dev = NULL; | ||
796 | |||
797 | /* request for kernel access to the next PCI device, if any, | ||
798 | * and while we are looking at it have its reference count | ||
799 | * bumped until we are done with it | ||
800 | */ | ||
801 | while((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | ||
802 | /* if whitelist exists then it has priority, so only scan | ||
803 | * those devices on the whitelist | ||
804 | */ | ||
805 | if (pci_whitelist_count > 0 ) { | ||
806 | if (check_dev_on_list(pci_whitelist, | ||
807 | pci_whitelist_count, dev)) | ||
808 | fn(dev); | ||
809 | } else { | ||
810 | /* | ||
811 | * if no whitelist, then check if this devices is | ||
812 | * blacklisted | ||
813 | */ | ||
814 | if (!check_dev_on_list(pci_blacklist, | ||
815 | pci_blacklist_count, dev)) | ||
816 | fn(dev); | ||
817 | } | ||
818 | } | ||
819 | } | ||
820 | |||
821 | static void do_pci_parity_check(void) | ||
822 | { | ||
823 | unsigned long flags; | ||
824 | int before_count; | ||
825 | |||
826 | debugf3("%s()\n", __func__); | ||
827 | |||
828 | if (!check_pci_parity) | ||
829 | return; | ||
830 | |||
831 | before_count = atomic_read(&pci_parity_count); | ||
832 | |||
833 | /* scan all PCI devices looking for a Parity Error on devices and | ||
834 | * bridges | ||
835 | */ | ||
836 | local_irq_save(flags); | ||
837 | edac_pci_dev_parity_iterator(edac_pci_dev_parity_test); | ||
838 | local_irq_restore(flags); | ||
839 | |||
840 | /* Only if operator has selected panic on PCI Error */ | ||
841 | if (panic_on_pci_parity) { | ||
842 | /* If the count is different 'after' from 'before' */ | ||
843 | if (before_count != atomic_read(&pci_parity_count)) | ||
844 | panic("EDAC: PCI Parity Error"); | ||
845 | } | ||
846 | } | ||
847 | |||
848 | static inline void clear_pci_parity_errors(void) | ||
849 | { | ||
850 | /* Clear any PCI bus parity errors that devices initially have logged | ||
851 | * in their registers. | ||
852 | */ | ||
853 | edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear); | ||
854 | } | ||
855 | |||
856 | #else /* CONFIG_PCI */ | ||
857 | |||
858 | static inline void do_pci_parity_check(void) | ||
859 | { | ||
860 | /* no-op */ | ||
861 | } | ||
862 | |||
863 | static inline void clear_pci_parity_errors(void) | ||
864 | { | ||
865 | /* no-op */ | ||
866 | } | ||
867 | |||
868 | static void edac_sysfs_pci_teardown(void) | ||
869 | { | ||
870 | } | ||
871 | |||
872 | static int edac_sysfs_pci_setup(void) | ||
873 | { | ||
874 | return 0; | ||
875 | } | ||
876 | #endif /* CONFIG_PCI */ | ||
877 | |||
626 | #ifndef DISABLE_EDAC_SYSFS | 878 | #ifndef DISABLE_EDAC_SYSFS |
627 | 879 | ||
628 | /* EDAC sysfs CSROW data structures and methods */ | 880 | /* EDAC sysfs CSROW data structures and methods */ |
@@ -1131,7 +1383,7 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) | |||
1131 | return err; | 1383 | return err; |
1132 | 1384 | ||
1133 | /* create a symlink for the device */ | 1385 | /* create a symlink for the device */ |
1134 | err = sysfs_create_link(edac_mci_kobj, &mci->pdev->dev.kobj, | 1386 | err = sysfs_create_link(edac_mci_kobj, &mci->dev->kobj, |
1135 | EDAC_DEVICE_SYMLINK); | 1387 | EDAC_DEVICE_SYMLINK); |
1136 | 1388 | ||
1137 | if (err) | 1389 | if (err) |
@@ -1237,7 +1489,7 @@ void edac_mc_dump_mci(struct mem_ctl_info *mci) | |||
1237 | debugf4("\tmci->edac_check = %p\n", mci->edac_check); | 1489 | debugf4("\tmci->edac_check = %p\n", mci->edac_check); |
1238 | debugf3("\tmci->nr_csrows = %d, csrows = %p\n", | 1490 | debugf3("\tmci->nr_csrows = %d, csrows = %p\n", |
1239 | mci->nr_csrows, mci->csrows); | 1491 | mci->nr_csrows, mci->csrows); |
1240 | debugf3("\tpdev = %p\n", mci->pdev); | 1492 | debugf3("\tdev = %p\n", mci->dev); |
1241 | debugf3("\tmod_name:ctl_name = %s:%s\n", | 1493 | debugf3("\tmod_name:ctl_name = %s:%s\n", |
1242 | mci->mod_name, mci->ctl_name); | 1494 | mci->mod_name, mci->ctl_name); |
1243 | debugf3("\tpvt_info = %p\n\n", mci->pvt_info); | 1495 | debugf3("\tpvt_info = %p\n\n", mci->pvt_info); |
@@ -1362,7 +1614,7 @@ void edac_mc_free(struct mem_ctl_info *mci) | |||
1362 | } | 1614 | } |
1363 | EXPORT_SYMBOL_GPL(edac_mc_free); | 1615 | EXPORT_SYMBOL_GPL(edac_mc_free); |
1364 | 1616 | ||
1365 | static struct mem_ctl_info *find_mci_by_pdev(struct pci_dev *pdev) | 1617 | static struct mem_ctl_info *find_mci_by_dev(struct device *dev) |
1366 | { | 1618 | { |
1367 | struct mem_ctl_info *mci; | 1619 | struct mem_ctl_info *mci; |
1368 | struct list_head *item; | 1620 | struct list_head *item; |
@@ -1372,54 +1624,53 @@ static struct mem_ctl_info *find_mci_by_pdev(struct pci_dev *pdev) | |||
1372 | list_for_each(item, &mc_devices) { | 1624 | list_for_each(item, &mc_devices) { |
1373 | mci = list_entry(item, struct mem_ctl_info, link); | 1625 | mci = list_entry(item, struct mem_ctl_info, link); |
1374 | 1626 | ||
1375 | if (mci->pdev == pdev) | 1627 | if (mci->dev == dev) |
1376 | return mci; | 1628 | return mci; |
1377 | } | 1629 | } |
1378 | 1630 | ||
1379 | return NULL; | 1631 | return NULL; |
1380 | } | 1632 | } |
1381 | 1633 | ||
1382 | static int add_mc_to_global_list(struct mem_ctl_info *mci) | 1634 | /* Return 0 on success, 1 on failure. |
1635 | * Before calling this function, caller must | ||
1636 | * assign a unique value to mci->mc_idx. | ||
1637 | */ | ||
1638 | static int add_mc_to_global_list (struct mem_ctl_info *mci) | ||
1383 | { | 1639 | { |
1384 | struct list_head *item, *insert_before; | 1640 | struct list_head *item, *insert_before; |
1385 | struct mem_ctl_info *p; | 1641 | struct mem_ctl_info *p; |
1386 | int i; | ||
1387 | 1642 | ||
1388 | if (list_empty(&mc_devices)) { | 1643 | insert_before = &mc_devices; |
1389 | mci->mc_idx = 0; | ||
1390 | insert_before = &mc_devices; | ||
1391 | } else { | ||
1392 | if (find_mci_by_pdev(mci->pdev)) { | ||
1393 | edac_printk(KERN_WARNING, EDAC_MC, | ||
1394 | "%s (%s) %s %s already assigned %d\n", | ||
1395 | mci->pdev->dev.bus_id, | ||
1396 | pci_name(mci->pdev), mci->mod_name, | ||
1397 | mci->ctl_name, mci->mc_idx); | ||
1398 | return 1; | ||
1399 | } | ||
1400 | 1644 | ||
1401 | insert_before = NULL; | 1645 | if (unlikely((p = find_mci_by_dev(mci->dev)) != NULL)) |
1402 | i = 0; | 1646 | goto fail0; |
1403 | 1647 | ||
1404 | list_for_each(item, &mc_devices) { | 1648 | list_for_each(item, &mc_devices) { |
1405 | p = list_entry(item, struct mem_ctl_info, link); | 1649 | p = list_entry(item, struct mem_ctl_info, link); |
1406 | 1650 | ||
1407 | if (p->mc_idx != i) { | 1651 | if (p->mc_idx >= mci->mc_idx) { |
1408 | insert_before = item; | 1652 | if (unlikely(p->mc_idx == mci->mc_idx)) |
1409 | break; | 1653 | goto fail1; |
1410 | } | ||
1411 | 1654 | ||
1412 | i++; | 1655 | insert_before = item; |
1656 | break; | ||
1413 | } | 1657 | } |
1414 | |||
1415 | mci->mc_idx = i; | ||
1416 | |||
1417 | if (insert_before == NULL) | ||
1418 | insert_before = &mc_devices; | ||
1419 | } | 1658 | } |
1420 | 1659 | ||
1421 | list_add_tail_rcu(&mci->link, insert_before); | 1660 | list_add_tail_rcu(&mci->link, insert_before); |
1422 | return 0; | 1661 | return 0; |
1662 | |||
1663 | fail0: | ||
1664 | edac_printk(KERN_WARNING, EDAC_MC, | ||
1665 | "%s (%s) %s %s already assigned %d\n", p->dev->bus_id, | ||
1666 | dev_name(p->dev), p->mod_name, p->ctl_name, p->mc_idx); | ||
1667 | return 1; | ||
1668 | |||
1669 | fail1: | ||
1670 | edac_printk(KERN_WARNING, EDAC_MC, | ||
1671 | "bug in low-level driver: attempt to assign\n" | ||
1672 | " duplicate mc_idx %d in %s()\n", p->mc_idx, __func__); | ||
1673 | return 1; | ||
1423 | } | 1674 | } |
1424 | 1675 | ||
1425 | static void complete_mc_list_del(struct rcu_head *head) | 1676 | static void complete_mc_list_del(struct rcu_head *head) |
@@ -1443,6 +1694,7 @@ static void del_mc_from_global_list(struct mem_ctl_info *mci) | |||
1443 | * edac_mc_add_mc: Insert the 'mci' structure into the mci global list and | 1694 | * edac_mc_add_mc: Insert the 'mci' structure into the mci global list and |
1444 | * create sysfs entries associated with mci structure | 1695 | * create sysfs entries associated with mci structure |
1445 | * @mci: pointer to the mci structure to be added to the list | 1696 | * @mci: pointer to the mci structure to be added to the list |
1697 | * @mc_idx: A unique numeric identifier to be assigned to the 'mci' structure. | ||
1446 | * | 1698 | * |
1447 | * Return: | 1699 | * Return: |
1448 | * 0 Success | 1700 | * 0 Success |
@@ -1450,9 +1702,10 @@ static void del_mc_from_global_list(struct mem_ctl_info *mci) | |||
1450 | */ | 1702 | */ |
1451 | 1703 | ||
1452 | /* FIXME - should a warning be printed if no error detection? correction? */ | 1704 | /* FIXME - should a warning be printed if no error detection? correction? */ |
1453 | int edac_mc_add_mc(struct mem_ctl_info *mci) | 1705 | int edac_mc_add_mc(struct mem_ctl_info *mci, int mc_idx) |
1454 | { | 1706 | { |
1455 | debugf0("%s()\n", __func__); | 1707 | debugf0("%s()\n", __func__); |
1708 | mci->mc_idx = mc_idx; | ||
1456 | #ifdef CONFIG_EDAC_DEBUG | 1709 | #ifdef CONFIG_EDAC_DEBUG |
1457 | if (edac_debug_level >= 3) | 1710 | if (edac_debug_level >= 3) |
1458 | edac_mc_dump_mci(mci); | 1711 | edac_mc_dump_mci(mci); |
@@ -1485,8 +1738,8 @@ int edac_mc_add_mc(struct mem_ctl_info *mci) | |||
1485 | } | 1738 | } |
1486 | 1739 | ||
1487 | /* Report action taken */ | 1740 | /* Report action taken */ |
1488 | edac_mc_printk(mci, KERN_INFO, "Giving out device to %s %s: PCI %s\n", | 1741 | edac_mc_printk(mci, KERN_INFO, "Giving out device to %s %s: DEV %s\n", |
1489 | mci->mod_name, mci->ctl_name, pci_name(mci->pdev)); | 1742 | mci->mod_name, mci->ctl_name, dev_name(mci->dev)); |
1490 | 1743 | ||
1491 | up(&mem_ctls_mutex); | 1744 | up(&mem_ctls_mutex); |
1492 | return 0; | 1745 | return 0; |
@@ -1503,18 +1756,18 @@ EXPORT_SYMBOL_GPL(edac_mc_add_mc); | |||
1503 | /** | 1756 | /** |
1504 | * edac_mc_del_mc: Remove sysfs entries for specified mci structure and | 1757 | * edac_mc_del_mc: Remove sysfs entries for specified mci structure and |
1505 | * remove mci structure from global list | 1758 | * remove mci structure from global list |
1506 | * @pdev: Pointer to 'struct pci_dev' representing mci structure to remove. | 1759 | * @pdev: Pointer to 'struct device' representing mci structure to remove. |
1507 | * | 1760 | * |
1508 | * Return pointer to removed mci structure, or NULL if device not found. | 1761 | * Return pointer to removed mci structure, or NULL if device not found. |
1509 | */ | 1762 | */ |
1510 | struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev) | 1763 | struct mem_ctl_info * edac_mc_del_mc(struct device *dev) |
1511 | { | 1764 | { |
1512 | struct mem_ctl_info *mci; | 1765 | struct mem_ctl_info *mci; |
1513 | 1766 | ||
1514 | debugf0("MC: %s()\n", __func__); | 1767 | debugf0("MC: %s()\n", __func__); |
1515 | down(&mem_ctls_mutex); | 1768 | down(&mem_ctls_mutex); |
1516 | 1769 | ||
1517 | if ((mci = find_mci_by_pdev(pdev)) == NULL) { | 1770 | if ((mci = find_mci_by_dev(dev)) == NULL) { |
1518 | up(&mem_ctls_mutex); | 1771 | up(&mem_ctls_mutex); |
1519 | return NULL; | 1772 | return NULL; |
1520 | } | 1773 | } |
@@ -1523,8 +1776,8 @@ struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev) | |||
1523 | del_mc_from_global_list(mci); | 1776 | del_mc_from_global_list(mci); |
1524 | up(&mem_ctls_mutex); | 1777 | up(&mem_ctls_mutex); |
1525 | edac_printk(KERN_INFO, EDAC_MC, | 1778 | edac_printk(KERN_INFO, EDAC_MC, |
1526 | "Removed device %d for %s %s: PCI %s\n", mci->mc_idx, | 1779 | "Removed device %d for %s %s: DEV %s\n", mci->mc_idx, |
1527 | mci->mod_name, mci->ctl_name, pci_name(mci->pdev)); | 1780 | mci->mod_name, mci->ctl_name, dev_name(mci->dev)); |
1528 | return mci; | 1781 | return mci; |
1529 | } | 1782 | } |
1530 | EXPORT_SYMBOL_GPL(edac_mc_del_mc); | 1783 | EXPORT_SYMBOL_GPL(edac_mc_del_mc); |
@@ -1738,244 +1991,6 @@ void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg) | |||
1738 | } | 1991 | } |
1739 | EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info); | 1992 | EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info); |
1740 | 1993 | ||
1741 | #ifdef CONFIG_PCI | ||
1742 | |||
1743 | static u16 get_pci_parity_status(struct pci_dev *dev, int secondary) | ||
1744 | { | ||
1745 | int where; | ||
1746 | u16 status; | ||
1747 | |||
1748 | where = secondary ? PCI_SEC_STATUS : PCI_STATUS; | ||
1749 | pci_read_config_word(dev, where, &status); | ||
1750 | |||
1751 | /* If we get back 0xFFFF then we must suspect that the card has been | ||
1752 | * pulled but the Linux PCI layer has not yet finished cleaning up. | ||
1753 | * We don't want to report on such devices | ||
1754 | */ | ||
1755 | |||
1756 | if (status == 0xFFFF) { | ||
1757 | u32 sanity; | ||
1758 | |||
1759 | pci_read_config_dword(dev, 0, &sanity); | ||
1760 | |||
1761 | if (sanity == 0xFFFFFFFF) | ||
1762 | return 0; | ||
1763 | } | ||
1764 | |||
1765 | status &= PCI_STATUS_DETECTED_PARITY | PCI_STATUS_SIG_SYSTEM_ERROR | | ||
1766 | PCI_STATUS_PARITY; | ||
1767 | |||
1768 | if (status) | ||
1769 | /* reset only the bits we are interested in */ | ||
1770 | pci_write_config_word(dev, where, status); | ||
1771 | |||
1772 | return status; | ||
1773 | } | ||
1774 | |||
1775 | typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev); | ||
1776 | |||
1777 | /* Clear any PCI parity errors logged by this device. */ | ||
1778 | static void edac_pci_dev_parity_clear(struct pci_dev *dev) | ||
1779 | { | ||
1780 | u8 header_type; | ||
1781 | |||
1782 | get_pci_parity_status(dev, 0); | ||
1783 | |||
1784 | /* read the device TYPE, looking for bridges */ | ||
1785 | pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); | ||
1786 | |||
1787 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) | ||
1788 | get_pci_parity_status(dev, 1); | ||
1789 | } | ||
1790 | |||
1791 | /* | ||
1792 | * PCI Parity polling | ||
1793 | * | ||
1794 | */ | ||
1795 | static void edac_pci_dev_parity_test(struct pci_dev *dev) | ||
1796 | { | ||
1797 | u16 status; | ||
1798 | u8 header_type; | ||
1799 | |||
1800 | /* read the STATUS register on this device | ||
1801 | */ | ||
1802 | status = get_pci_parity_status(dev, 0); | ||
1803 | |||
1804 | debugf2("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id ); | ||
1805 | |||
1806 | /* check the status reg for errors */ | ||
1807 | if (status) { | ||
1808 | if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) | ||
1809 | edac_printk(KERN_CRIT, EDAC_PCI, | ||
1810 | "Signaled System Error on %s\n", | ||
1811 | pci_name(dev)); | ||
1812 | |||
1813 | if (status & (PCI_STATUS_PARITY)) { | ||
1814 | edac_printk(KERN_CRIT, EDAC_PCI, | ||
1815 | "Master Data Parity Error on %s\n", | ||
1816 | pci_name(dev)); | ||
1817 | |||
1818 | atomic_inc(&pci_parity_count); | ||
1819 | } | ||
1820 | |||
1821 | if (status & (PCI_STATUS_DETECTED_PARITY)) { | ||
1822 | edac_printk(KERN_CRIT, EDAC_PCI, | ||
1823 | "Detected Parity Error on %s\n", | ||
1824 | pci_name(dev)); | ||
1825 | |||
1826 | atomic_inc(&pci_parity_count); | ||
1827 | } | ||
1828 | } | ||
1829 | |||
1830 | /* read the device TYPE, looking for bridges */ | ||
1831 | pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); | ||
1832 | |||
1833 | debugf2("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev->dev.bus_id ); | ||
1834 | |||
1835 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { | ||
1836 | /* On bridges, need to examine secondary status register */ | ||
1837 | status = get_pci_parity_status(dev, 1); | ||
1838 | |||
1839 | debugf2("PCI SEC_STATUS= 0x%04x %s\n", | ||
1840 | status, dev->dev.bus_id ); | ||
1841 | |||
1842 | /* check the secondary status reg for errors */ | ||
1843 | if (status) { | ||
1844 | if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) | ||
1845 | edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " | ||
1846 | "Signaled System Error on %s\n", | ||
1847 | pci_name(dev)); | ||
1848 | |||
1849 | if (status & (PCI_STATUS_PARITY)) { | ||
1850 | edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " | ||
1851 | "Master Data Parity Error on " | ||
1852 | "%s\n", pci_name(dev)); | ||
1853 | |||
1854 | atomic_inc(&pci_parity_count); | ||
1855 | } | ||
1856 | |||
1857 | if (status & (PCI_STATUS_DETECTED_PARITY)) { | ||
1858 | edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " | ||
1859 | "Detected Parity Error on %s\n", | ||
1860 | pci_name(dev)); | ||
1861 | |||
1862 | atomic_inc(&pci_parity_count); | ||
1863 | } | ||
1864 | } | ||
1865 | } | ||
1866 | } | ||
1867 | |||
1868 | /* | ||
1869 | * check_dev_on_list: Scan for a PCI device on a white/black list | ||
1870 | * @list: an EDAC &edac_pci_device_list white/black list pointer | ||
1871 | * @free_index: index of next free entry on the list | ||
1872 | * @pci_dev: PCI Device pointer | ||
1873 | * | ||
1874 | * see if list contains the device. | ||
1875 | * | ||
1876 | * Returns: 0 not found | ||
1877 | * 1 found on list | ||
1878 | */ | ||
1879 | static int check_dev_on_list(struct edac_pci_device_list *list, | ||
1880 | int free_index, struct pci_dev *dev) | ||
1881 | { | ||
1882 | int i; | ||
1883 | int rc = 0; /* Assume not found */ | ||
1884 | unsigned short vendor=dev->vendor; | ||
1885 | unsigned short device=dev->device; | ||
1886 | |||
1887 | /* Scan the list, looking for a vendor/device match */ | ||
1888 | for (i = 0; i < free_index; i++, list++ ) { | ||
1889 | if ((list->vendor == vendor ) && (list->device == device )) { | ||
1890 | rc = 1; | ||
1891 | break; | ||
1892 | } | ||
1893 | } | ||
1894 | |||
1895 | return rc; | ||
1896 | } | ||
1897 | |||
1898 | /* | ||
1899 | * pci_dev parity list iterator | ||
1900 | * Scan the PCI device list for one iteration, looking for SERRORs | ||
1901 | * Master Parity ERRORS or Parity ERRORs on primary or secondary devices | ||
1902 | */ | ||
1903 | static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn) | ||
1904 | { | ||
1905 | struct pci_dev *dev = NULL; | ||
1906 | |||
1907 | /* request for kernel access to the next PCI device, if any, | ||
1908 | * and while we are looking at it have its reference count | ||
1909 | * bumped until we are done with it | ||
1910 | */ | ||
1911 | while((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | ||
1912 | /* if whitelist exists then it has priority, so only scan | ||
1913 | * those devices on the whitelist | ||
1914 | */ | ||
1915 | if (pci_whitelist_count > 0 ) { | ||
1916 | if (check_dev_on_list(pci_whitelist, | ||
1917 | pci_whitelist_count, dev)) | ||
1918 | fn(dev); | ||
1919 | } else { | ||
1920 | /* | ||
1921 | * if no whitelist, then check if this devices is | ||
1922 | * blacklisted | ||
1923 | */ | ||
1924 | if (!check_dev_on_list(pci_blacklist, | ||
1925 | pci_blacklist_count, dev)) | ||
1926 | fn(dev); | ||
1927 | } | ||
1928 | } | ||
1929 | } | ||
1930 | |||
1931 | static void do_pci_parity_check(void) | ||
1932 | { | ||
1933 | unsigned long flags; | ||
1934 | int before_count; | ||
1935 | |||
1936 | debugf3("%s()\n", __func__); | ||
1937 | |||
1938 | if (!check_pci_parity) | ||
1939 | return; | ||
1940 | |||
1941 | before_count = atomic_read(&pci_parity_count); | ||
1942 | |||
1943 | /* scan all PCI devices looking for a Parity Error on devices and | ||
1944 | * bridges | ||
1945 | */ | ||
1946 | local_irq_save(flags); | ||
1947 | edac_pci_dev_parity_iterator(edac_pci_dev_parity_test); | ||
1948 | local_irq_restore(flags); | ||
1949 | |||
1950 | /* Only if operator has selected panic on PCI Error */ | ||
1951 | if (panic_on_pci_parity) { | ||
1952 | /* If the count is different 'after' from 'before' */ | ||
1953 | if (before_count != atomic_read(&pci_parity_count)) | ||
1954 | panic("EDAC: PCI Parity Error"); | ||
1955 | } | ||
1956 | } | ||
1957 | |||
1958 | static inline void clear_pci_parity_errors(void) | ||
1959 | { | ||
1960 | /* Clear any PCI bus parity errors that devices initially have logged | ||
1961 | * in their registers. | ||
1962 | */ | ||
1963 | edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear); | ||
1964 | } | ||
1965 | |||
1966 | #else /* CONFIG_PCI */ | ||
1967 | |||
1968 | static inline void do_pci_parity_check(void) | ||
1969 | { | ||
1970 | /* no-op */ | ||
1971 | } | ||
1972 | |||
1973 | static inline void clear_pci_parity_errors(void) | ||
1974 | { | ||
1975 | /* no-op */ | ||
1976 | } | ||
1977 | |||
1978 | #endif /* CONFIG_PCI */ | ||
1979 | 1994 | ||
1980 | /* | 1995 | /* |
1981 | * Iterate over all MC instances and check for ECC, et al, errors | 1996 | * Iterate over all MC instances and check for ECC, et al, errors |
@@ -2095,10 +2110,12 @@ MODULE_DESCRIPTION("Core library routines for MC reporting"); | |||
2095 | 2110 | ||
2096 | module_param(panic_on_ue, int, 0644); | 2111 | module_param(panic_on_ue, int, 0644); |
2097 | MODULE_PARM_DESC(panic_on_ue, "Panic on uncorrected error: 0=off 1=on"); | 2112 | MODULE_PARM_DESC(panic_on_ue, "Panic on uncorrected error: 0=off 1=on"); |
2113 | #ifdef CONFIG_PCI | ||
2098 | module_param(check_pci_parity, int, 0644); | 2114 | module_param(check_pci_parity, int, 0644); |
2099 | MODULE_PARM_DESC(check_pci_parity, "Check for PCI bus parity errors: 0=off 1=on"); | 2115 | MODULE_PARM_DESC(check_pci_parity, "Check for PCI bus parity errors: 0=off 1=on"); |
2100 | module_param(panic_on_pci_parity, int, 0644); | 2116 | module_param(panic_on_pci_parity, int, 0644); |
2101 | MODULE_PARM_DESC(panic_on_pci_parity, "Panic on PCI Bus Parity error: 0=off 1=on"); | 2117 | MODULE_PARM_DESC(panic_on_pci_parity, "Panic on PCI Bus Parity error: 0=off 1=on"); |
2118 | #endif | ||
2102 | module_param(log_ue, int, 0644); | 2119 | module_param(log_ue, int, 0644); |
2103 | MODULE_PARM_DESC(log_ue, "Log uncorrectable error to console: 0=off 1=on"); | 2120 | MODULE_PARM_DESC(log_ue, "Log uncorrectable error to console: 0=off 1=on"); |
2104 | module_param(log_ce, int, 0644); | 2121 | module_param(log_ce, int, 0644); |
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h index ad578eb0969d..1be4947e28af 100644 --- a/drivers/edac/edac_mc.h +++ b/drivers/edac/edac_mc.h | |||
@@ -87,6 +87,12 @@ extern int edac_debug_level; | |||
87 | #define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, \ | 87 | #define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, \ |
88 | PCI_DEVICE_ID_ ## vend ## _ ## dev | 88 | PCI_DEVICE_ID_ ## vend ## _ ## dev |
89 | 89 | ||
90 | #if defined(CONFIG_X86) && defined(CONFIG_PCI) | ||
91 | #define dev_name(dev) pci_name(to_pci_dev(dev)) | ||
92 | #else | ||
93 | #define dev_name(dev) to_platform_device(dev)->name | ||
94 | #endif | ||
95 | |||
90 | /* memory devices */ | 96 | /* memory devices */ |
91 | enum dev_type { | 97 | enum dev_type { |
92 | DEV_UNKNOWN = 0, | 98 | DEV_UNKNOWN = 0, |
@@ -326,10 +332,10 @@ struct mem_ctl_info { | |||
326 | struct csrow_info *csrows; | 332 | struct csrow_info *csrows; |
327 | /* | 333 | /* |
328 | * FIXME - what about controllers on other busses? - IDs must be | 334 | * FIXME - what about controllers on other busses? - IDs must be |
329 | * unique. pdev pointer should be sufficiently unique, but | 335 | * unique. dev pointer should be sufficiently unique, but |
330 | * BUS:SLOT.FUNC numbers may not be unique. | 336 | * BUS:SLOT.FUNC numbers may not be unique. |
331 | */ | 337 | */ |
332 | struct pci_dev *pdev; | 338 | struct device *dev; |
333 | const char *mod_name; | 339 | const char *mod_name; |
334 | const char *mod_ver; | 340 | const char *mod_ver; |
335 | const char *ctl_name; | 341 | const char *ctl_name; |
@@ -352,6 +358,8 @@ struct mem_ctl_info { | |||
352 | struct completion kobj_complete; | 358 | struct completion kobj_complete; |
353 | }; | 359 | }; |
354 | 360 | ||
361 | #ifdef CONFIG_PCI | ||
362 | |||
355 | /* write all or some bits in a byte-register*/ | 363 | /* write all or some bits in a byte-register*/ |
356 | static inline void pci_write_bits8(struct pci_dev *pdev, int offset, u8 value, | 364 | static inline void pci_write_bits8(struct pci_dev *pdev, int offset, u8 value, |
357 | u8 mask) | 365 | u8 mask) |
@@ -400,14 +408,16 @@ static inline void pci_write_bits32(struct pci_dev *pdev, int offset, | |||
400 | pci_write_config_dword(pdev, offset, value); | 408 | pci_write_config_dword(pdev, offset, value); |
401 | } | 409 | } |
402 | 410 | ||
411 | #endif /* CONFIG_PCI */ | ||
412 | |||
403 | #ifdef CONFIG_EDAC_DEBUG | 413 | #ifdef CONFIG_EDAC_DEBUG |
404 | void edac_mc_dump_channel(struct channel_info *chan); | 414 | void edac_mc_dump_channel(struct channel_info *chan); |
405 | void edac_mc_dump_mci(struct mem_ctl_info *mci); | 415 | void edac_mc_dump_mci(struct mem_ctl_info *mci); |
406 | void edac_mc_dump_csrow(struct csrow_info *csrow); | 416 | void edac_mc_dump_csrow(struct csrow_info *csrow); |
407 | #endif /* CONFIG_EDAC_DEBUG */ | 417 | #endif /* CONFIG_EDAC_DEBUG */ |
408 | 418 | ||
409 | extern int edac_mc_add_mc(struct mem_ctl_info *mci); | 419 | extern int edac_mc_add_mc(struct mem_ctl_info *mci,int mc_idx); |
410 | extern struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev); | 420 | extern struct mem_ctl_info * edac_mc_del_mc(struct device *dev); |
411 | extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, | 421 | extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, |
412 | unsigned long page); | 422 | unsigned long page); |
413 | extern void edac_mc_scrub_block(unsigned long page, unsigned long offset, | 423 | extern void edac_mc_scrub_block(unsigned long page, unsigned long offset, |
diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index 56ba31f85f13..e30a4a2eaf38 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include "edac_mc.h" | 17 | #include "edac_mc.h" |
18 | 18 | ||
19 | #define I82860_REVISION " Ver: 2.0.0 " __DATE__ | ||
20 | |||
19 | #define i82860_printk(level, fmt, arg...) \ | 21 | #define i82860_printk(level, fmt, arg...) \ |
20 | edac_printk(level, "i82860", fmt, ##arg) | 22 | edac_printk(level, "i82860", fmt, ##arg) |
21 | 23 | ||
@@ -62,17 +64,21 @@ static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code | |||
62 | static void i82860_get_error_info(struct mem_ctl_info *mci, | 64 | static void i82860_get_error_info(struct mem_ctl_info *mci, |
63 | struct i82860_error_info *info) | 65 | struct i82860_error_info *info) |
64 | { | 66 | { |
67 | struct pci_dev *pdev; | ||
68 | |||
69 | pdev = to_pci_dev(mci->dev); | ||
70 | |||
65 | /* | 71 | /* |
66 | * This is a mess because there is no atomic way to read all the | 72 | * This is a mess because there is no atomic way to read all the |
67 | * registers at once and the registers can transition from CE being | 73 | * registers at once and the registers can transition from CE being |
68 | * overwritten by UE. | 74 | * overwritten by UE. |
69 | */ | 75 | */ |
70 | pci_read_config_word(mci->pdev, I82860_ERRSTS, &info->errsts); | 76 | pci_read_config_word(pdev, I82860_ERRSTS, &info->errsts); |
71 | pci_read_config_dword(mci->pdev, I82860_EAP, &info->eap); | 77 | pci_read_config_dword(pdev, I82860_EAP, &info->eap); |
72 | pci_read_config_word(mci->pdev, I82860_DERRCTL_STS, &info->derrsyn); | 78 | pci_read_config_word(pdev, I82860_DERRCTL_STS, &info->derrsyn); |
73 | pci_read_config_word(mci->pdev, I82860_ERRSTS, &info->errsts2); | 79 | pci_read_config_word(pdev, I82860_ERRSTS, &info->errsts2); |
74 | 80 | ||
75 | pci_write_bits16(mci->pdev, I82860_ERRSTS, 0x0003, 0x0003); | 81 | pci_write_bits16(pdev, I82860_ERRSTS, 0x0003, 0x0003); |
76 | 82 | ||
77 | /* | 83 | /* |
78 | * If the error is the same for both reads then the first set of reads | 84 | * If the error is the same for both reads then the first set of reads |
@@ -83,8 +89,8 @@ static void i82860_get_error_info(struct mem_ctl_info *mci, | |||
83 | return; | 89 | return; |
84 | 90 | ||
85 | if ((info->errsts ^ info->errsts2) & 0x0003) { | 91 | if ((info->errsts ^ info->errsts2) & 0x0003) { |
86 | pci_read_config_dword(mci->pdev, I82860_EAP, &info->eap); | 92 | pci_read_config_dword(pdev, I82860_EAP, &info->eap); |
87 | pci_read_config_word(mci->pdev, I82860_DERRCTL_STS, | 93 | pci_read_config_word(pdev, I82860_DERRCTL_STS, |
88 | &info->derrsyn); | 94 | &info->derrsyn); |
89 | } | 95 | } |
90 | } | 96 | } |
@@ -126,15 +132,50 @@ static void i82860_check(struct mem_ctl_info *mci) | |||
126 | i82860_process_error_info(mci, &info, 1); | 132 | i82860_process_error_info(mci, &info, 1); |
127 | } | 133 | } |
128 | 134 | ||
129 | static int i82860_probe1(struct pci_dev *pdev, int dev_idx) | 135 | static void i82860_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev) |
130 | { | 136 | { |
131 | int rc = -ENODEV; | ||
132 | int index; | ||
133 | struct mem_ctl_info *mci = NULL; | ||
134 | unsigned long last_cumul_size; | 137 | unsigned long last_cumul_size; |
135 | struct i82860_error_info discard; | 138 | u16 mchcfg_ddim; /* DRAM Data Integrity Mode 0=none, 2=edac */ |
139 | u16 value; | ||
140 | u32 cumul_size; | ||
141 | struct csrow_info *csrow; | ||
142 | int index; | ||
143 | |||
144 | pci_read_config_word(pdev, I82860_MCHCFG, &mchcfg_ddim); | ||
145 | mchcfg_ddim = mchcfg_ddim & 0x180; | ||
146 | last_cumul_size = 0; | ||
147 | |||
148 | /* The group row boundary (GRA) reg values are boundary address | ||
149 | * for each DRAM row with a granularity of 16MB. GRA regs are | ||
150 | * cumulative; therefore GRA15 will contain the total memory contained | ||
151 | * in all eight rows. | ||
152 | */ | ||
153 | for (index = 0; index < mci->nr_csrows; index++) { | ||
154 | csrow = &mci->csrows[index]; | ||
155 | pci_read_config_word(pdev, I82860_GBA + index * 2, &value); | ||
156 | cumul_size = (value & I82860_GBA_MASK) << | ||
157 | (I82860_GBA_SHIFT - PAGE_SHIFT); | ||
158 | debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, | ||
159 | cumul_size); | ||
136 | 160 | ||
137 | u16 mchcfg_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ | 161 | if (cumul_size == last_cumul_size) |
162 | continue; /* not populated */ | ||
163 | |||
164 | csrow->first_page = last_cumul_size; | ||
165 | csrow->last_page = cumul_size - 1; | ||
166 | csrow->nr_pages = cumul_size - last_cumul_size; | ||
167 | last_cumul_size = cumul_size; | ||
168 | csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */ | ||
169 | csrow->mtype = MEM_RMBS; | ||
170 | csrow->dtype = DEV_UNKNOWN; | ||
171 | csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | static int i82860_probe1(struct pci_dev *pdev, int dev_idx) | ||
176 | { | ||
177 | struct mem_ctl_info *mci; | ||
178 | struct i82860_error_info discard; | ||
138 | 179 | ||
139 | /* RDRAM has channels but these don't map onto the abstractions that | 180 | /* RDRAM has channels but these don't map onto the abstractions that |
140 | edac uses. | 181 | edac uses. |
@@ -150,67 +191,35 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) | |||
150 | return -ENOMEM; | 191 | return -ENOMEM; |
151 | 192 | ||
152 | debugf3("%s(): init mci\n", __func__); | 193 | debugf3("%s(): init mci\n", __func__); |
153 | mci->pdev = pdev; | 194 | mci->dev = &pdev->dev; |
154 | mci->mtype_cap = MEM_FLAG_DDR; | 195 | mci->mtype_cap = MEM_FLAG_DDR; |
155 | |||
156 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; | 196 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; |
157 | /* I"m not sure about this but I think that all RDRAM is SECDED */ | 197 | /* I"m not sure about this but I think that all RDRAM is SECDED */ |
158 | mci->edac_cap = EDAC_FLAG_SECDED; | 198 | mci->edac_cap = EDAC_FLAG_SECDED; |
159 | /* adjust FLAGS */ | ||
160 | |||
161 | mci->mod_name = EDAC_MOD_STR; | 199 | mci->mod_name = EDAC_MOD_STR; |
162 | mci->mod_ver = "$Revision: 1.1.2.6 $"; | 200 | mci->mod_ver = I82860_REVISION; |
163 | mci->ctl_name = i82860_devs[dev_idx].ctl_name; | 201 | mci->ctl_name = i82860_devs[dev_idx].ctl_name; |
164 | mci->edac_check = i82860_check; | 202 | mci->edac_check = i82860_check; |
165 | mci->ctl_page_to_phys = NULL; | 203 | mci->ctl_page_to_phys = NULL; |
204 | i82860_init_csrows(mci, pdev); | ||
205 | i82860_get_error_info(mci, &discard); /* clear counters */ | ||
166 | 206 | ||
167 | pci_read_config_word(mci->pdev, I82860_MCHCFG, &mchcfg_ddim); | 207 | /* Here we assume that we will never see multiple instances of this |
168 | mchcfg_ddim = mchcfg_ddim & 0x180; | 208 | * type of memory controller. The ID is therefore hardcoded to 0. |
169 | |||
170 | /* | ||
171 | * The group row boundary (GRA) reg values are boundary address | ||
172 | * for each DRAM row with a granularity of 16MB. GRA regs are | ||
173 | * cumulative; therefore GRA15 will contain the total memory contained | ||
174 | * in all eight rows. | ||
175 | */ | 209 | */ |
176 | for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) { | 210 | if (edac_mc_add_mc(mci,0)) { |
177 | u16 value; | 211 | debugf3("%s(): failed edac_mc_add_mc()\n", __func__); |
178 | u32 cumul_size; | 212 | goto fail; |
179 | struct csrow_info *csrow = &mci->csrows[index]; | ||
180 | |||
181 | pci_read_config_word(mci->pdev, I82860_GBA + index * 2, | ||
182 | &value); | ||
183 | |||
184 | cumul_size = (value & I82860_GBA_MASK) << | ||
185 | (I82860_GBA_SHIFT - PAGE_SHIFT); | ||
186 | debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, | ||
187 | cumul_size); | ||
188 | |||
189 | if (cumul_size == last_cumul_size) | ||
190 | continue; /* not populated */ | ||
191 | |||
192 | csrow->first_page = last_cumul_size; | ||
193 | csrow->last_page = cumul_size - 1; | ||
194 | csrow->nr_pages = cumul_size - last_cumul_size; | ||
195 | last_cumul_size = cumul_size; | ||
196 | csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */ | ||
197 | csrow->mtype = MEM_RMBS; | ||
198 | csrow->dtype = DEV_UNKNOWN; | ||
199 | csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE; | ||
200 | } | 213 | } |
201 | 214 | ||
202 | i82860_get_error_info(mci, &discard); /* clear counters */ | 215 | /* get this far and it's successful */ |
216 | debugf3("%s(): success\n", __func__); | ||
203 | 217 | ||
204 | if (edac_mc_add_mc(mci)) { | 218 | return 0; |
205 | debugf3("%s(): failed edac_mc_add_mc()\n", __func__); | ||
206 | edac_mc_free(mci); | ||
207 | } else { | ||
208 | /* get this far and it's successful */ | ||
209 | debugf3("%s(): success\n", __func__); | ||
210 | rc = 0; | ||
211 | } | ||
212 | 219 | ||
213 | return rc; | 220 | fail: |
221 | edac_mc_free(mci); | ||
222 | return -ENODEV; | ||
214 | } | 223 | } |
215 | 224 | ||
216 | /* returns count (>= 0), or negative on error */ | 225 | /* returns count (>= 0), or negative on error */ |
@@ -239,7 +248,7 @@ static void __devexit i82860_remove_one(struct pci_dev *pdev) | |||
239 | 248 | ||
240 | debugf0("%s()\n", __func__); | 249 | debugf0("%s()\n", __func__); |
241 | 250 | ||
242 | if ((mci = edac_mc_del_mc(pdev)) == NULL) | 251 | if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL) |
243 | return; | 252 | return; |
244 | 253 | ||
245 | edac_mc_free(mci); | 254 | edac_mc_free(mci); |
diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index e1d751d39736..9423ee5e7edd 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include "edac_mc.h" | 21 | #include "edac_mc.h" |
22 | 22 | ||
23 | #define I82875P_REVISION " Ver: 2.0.0 " __DATE__ | ||
24 | |||
23 | #define i82875p_printk(level, fmt, arg...) \ | 25 | #define i82875p_printk(level, fmt, arg...) \ |
24 | edac_printk(level, "i82875p", fmt, ##arg) | 26 | edac_printk(level, "i82875p", fmt, ##arg) |
25 | 27 | ||
@@ -184,18 +186,22 @@ static int i82875p_registered = 1; | |||
184 | static void i82875p_get_error_info(struct mem_ctl_info *mci, | 186 | static void i82875p_get_error_info(struct mem_ctl_info *mci, |
185 | struct i82875p_error_info *info) | 187 | struct i82875p_error_info *info) |
186 | { | 188 | { |
189 | struct pci_dev *pdev; | ||
190 | |||
191 | pdev = to_pci_dev(mci->dev); | ||
192 | |||
187 | /* | 193 | /* |
188 | * This is a mess because there is no atomic way to read all the | 194 | * This is a mess because there is no atomic way to read all the |
189 | * registers at once and the registers can transition from CE being | 195 | * registers at once and the registers can transition from CE being |
190 | * overwritten by UE. | 196 | * overwritten by UE. |
191 | */ | 197 | */ |
192 | pci_read_config_word(mci->pdev, I82875P_ERRSTS, &info->errsts); | 198 | pci_read_config_word(pdev, I82875P_ERRSTS, &info->errsts); |
193 | pci_read_config_dword(mci->pdev, I82875P_EAP, &info->eap); | 199 | pci_read_config_dword(pdev, I82875P_EAP, &info->eap); |
194 | pci_read_config_byte(mci->pdev, I82875P_DES, &info->des); | 200 | pci_read_config_byte(pdev, I82875P_DES, &info->des); |
195 | pci_read_config_byte(mci->pdev, I82875P_DERRSYN, &info->derrsyn); | 201 | pci_read_config_byte(pdev, I82875P_DERRSYN, &info->derrsyn); |
196 | pci_read_config_word(mci->pdev, I82875P_ERRSTS, &info->errsts2); | 202 | pci_read_config_word(pdev, I82875P_ERRSTS, &info->errsts2); |
197 | 203 | ||
198 | pci_write_bits16(mci->pdev, I82875P_ERRSTS, 0x0081, 0x0081); | 204 | pci_write_bits16(pdev, I82875P_ERRSTS, 0x0081, 0x0081); |
199 | 205 | ||
200 | /* | 206 | /* |
201 | * If the error is the same then we can for both reads then | 207 | * If the error is the same then we can for both reads then |
@@ -207,9 +213,9 @@ static void i82875p_get_error_info(struct mem_ctl_info *mci, | |||
207 | return; | 213 | return; |
208 | 214 | ||
209 | if ((info->errsts ^ info->errsts2) & 0x0081) { | 215 | if ((info->errsts ^ info->errsts2) & 0x0081) { |
210 | pci_read_config_dword(mci->pdev, I82875P_EAP, &info->eap); | 216 | pci_read_config_dword(pdev, I82875P_EAP, &info->eap); |
211 | pci_read_config_byte(mci->pdev, I82875P_DES, &info->des); | 217 | pci_read_config_byte(pdev, I82875P_DES, &info->des); |
212 | pci_read_config_byte(mci->pdev, I82875P_DERRSYN, | 218 | pci_read_config_byte(pdev, I82875P_DERRSYN, |
213 | &info->derrsyn); | 219 | &info->derrsyn); |
214 | } | 220 | } |
215 | } | 221 | } |
@@ -258,116 +264,109 @@ static void i82875p_check(struct mem_ctl_info *mci) | |||
258 | extern int pci_proc_attach_device(struct pci_dev *); | 264 | extern int pci_proc_attach_device(struct pci_dev *); |
259 | #endif | 265 | #endif |
260 | 266 | ||
261 | static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) | 267 | /* Return 0 on success or 1 on failure. */ |
268 | static int i82875p_setup_overfl_dev(struct pci_dev *pdev, | ||
269 | struct pci_dev **ovrfl_pdev, void __iomem **ovrfl_window) | ||
262 | { | 270 | { |
263 | int rc = -ENODEV; | 271 | struct pci_dev *dev; |
264 | int index; | 272 | void __iomem *window; |
265 | struct mem_ctl_info *mci = NULL; | ||
266 | struct i82875p_pvt *pvt = NULL; | ||
267 | unsigned long last_cumul_size; | ||
268 | struct pci_dev *ovrfl_pdev; | ||
269 | void __iomem *ovrfl_window = NULL; | ||
270 | u32 drc; | ||
271 | u32 drc_chan; /* Number of channels 0=1chan,1=2chan */ | ||
272 | u32 nr_chans; | ||
273 | u32 drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ | ||
274 | struct i82875p_error_info discard; | ||
275 | 273 | ||
276 | debugf0("%s()\n", __func__); | 274 | *ovrfl_pdev = NULL; |
277 | ovrfl_pdev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL); | 275 | *ovrfl_window = NULL; |
276 | dev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL); | ||
278 | 277 | ||
279 | if (!ovrfl_pdev) { | 278 | if (dev == NULL) { |
280 | /* | 279 | /* Intel tells BIOS developers to hide device 6 which |
281 | * Intel tells BIOS developers to hide device 6 which | ||
282 | * configures the overflow device access containing | 280 | * configures the overflow device access containing |
283 | * the DRBs - this is where we expose device 6. | 281 | * the DRBs - this is where we expose device 6. |
284 | * http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm | 282 | * http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm |
285 | */ | 283 | */ |
286 | pci_write_bits8(pdev, 0xf4, 0x2, 0x2); | 284 | pci_write_bits8(pdev, 0xf4, 0x2, 0x2); |
287 | ovrfl_pdev = | 285 | dev = pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0)); |
288 | pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0)); | ||
289 | 286 | ||
290 | if (!ovrfl_pdev) | 287 | if (dev == NULL) |
291 | return -ENODEV; | 288 | return 1; |
292 | } | 289 | } |
293 | 290 | ||
291 | *ovrfl_pdev = dev; | ||
292 | |||
294 | #ifdef CONFIG_PROC_FS | 293 | #ifdef CONFIG_PROC_FS |
295 | if (!ovrfl_pdev->procent && pci_proc_attach_device(ovrfl_pdev)) { | 294 | if ((dev->procent == NULL) && pci_proc_attach_device(dev)) { |
296 | i82875p_printk(KERN_ERR, | 295 | i82875p_printk(KERN_ERR, "%s(): Failed to attach overflow " |
297 | "%s(): Failed to attach overflow device\n", __func__); | 296 | "device\n", __func__); |
298 | return -ENODEV; | 297 | return 1; |
299 | } | 298 | } |
300 | #endif | 299 | #endif /* CONFIG_PROC_FS */ |
301 | /* CONFIG_PROC_FS */ | 300 | if (pci_enable_device(dev)) { |
302 | if (pci_enable_device(ovrfl_pdev)) { | 301 | i82875p_printk(KERN_ERR, "%s(): Failed to enable overflow " |
303 | i82875p_printk(KERN_ERR, | 302 | "device\n", __func__); |
304 | "%s(): Failed to enable overflow device\n", __func__); | 303 | return 1; |
305 | return -ENODEV; | ||
306 | } | 304 | } |
307 | 305 | ||
308 | if (pci_request_regions(ovrfl_pdev, pci_name(ovrfl_pdev))) { | 306 | if (pci_request_regions(dev, pci_name(dev))) { |
309 | #ifdef CORRECT_BIOS | 307 | #ifdef CORRECT_BIOS |
310 | goto fail0; | 308 | goto fail0; |
311 | #endif | 309 | #endif |
312 | } | 310 | } |
313 | 311 | ||
314 | /* cache is irrelevant for PCI bus reads/writes */ | 312 | /* cache is irrelevant for PCI bus reads/writes */ |
315 | ovrfl_window = ioremap_nocache(pci_resource_start(ovrfl_pdev, 0), | 313 | window = ioremap_nocache(pci_resource_start(dev, 0), |
316 | pci_resource_len(ovrfl_pdev, 0)); | 314 | pci_resource_len(dev, 0)); |
317 | 315 | ||
318 | if (!ovrfl_window) { | 316 | if (window == NULL) { |
319 | i82875p_printk(KERN_ERR, "%s(): Failed to ioremap bar6\n", | 317 | i82875p_printk(KERN_ERR, "%s(): Failed to ioremap bar6\n", |
320 | __func__); | 318 | __func__); |
321 | goto fail1; | 319 | goto fail1; |
322 | } | 320 | } |
323 | 321 | ||
324 | /* need to find out the number of channels */ | 322 | *ovrfl_window = window; |
325 | drc = readl(ovrfl_window + I82875P_DRC); | 323 | return 0; |
326 | drc_chan = ((drc >> 21) & 0x1); | ||
327 | nr_chans = drc_chan + 1; | ||
328 | 324 | ||
329 | drc_ddim = (drc >> 18) & 0x1; | 325 | fail1: |
330 | mci = edac_mc_alloc(sizeof(*pvt), I82875P_NR_CSROWS(nr_chans), | 326 | pci_release_regions(dev); |
331 | nr_chans); | ||
332 | 327 | ||
333 | if (!mci) { | 328 | #ifdef CORRECT_BIOS |
334 | rc = -ENOMEM; | 329 | fail0: |
335 | goto fail2; | 330 | pci_disable_device(dev); |
336 | } | 331 | #endif |
332 | /* NOTE: the ovrfl proc entry and pci_dev are intentionally left */ | ||
333 | return 1; | ||
334 | } | ||
337 | 335 | ||
338 | debugf3("%s(): init mci\n", __func__); | ||
339 | mci->pdev = pdev; | ||
340 | mci->mtype_cap = MEM_FLAG_DDR; | ||
341 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; | ||
342 | mci->edac_cap = EDAC_FLAG_UNKNOWN; | ||
343 | /* adjust FLAGS */ | ||
344 | 336 | ||
345 | mci->mod_name = EDAC_MOD_STR; | 337 | /* Return 1 if dual channel mode is active. Else return 0. */ |
346 | mci->mod_ver = "$Revision: 1.5.2.11 $"; | 338 | static inline int dual_channel_active(u32 drc) |
347 | mci->ctl_name = i82875p_devs[dev_idx].ctl_name; | 339 | { |
348 | mci->edac_check = i82875p_check; | 340 | return (drc >> 21) & 0x1; |
349 | mci->ctl_page_to_phys = NULL; | 341 | } |
350 | debugf3("%s(): init pvt\n", __func__); | ||
351 | pvt = (struct i82875p_pvt *) mci->pvt_info; | ||
352 | pvt->ovrfl_pdev = ovrfl_pdev; | ||
353 | pvt->ovrfl_window = ovrfl_window; | ||
354 | 342 | ||
355 | /* | 343 | |
356 | * The dram row boundary (DRB) reg values are boundary address | 344 | static void i82875p_init_csrows(struct mem_ctl_info *mci, |
345 | struct pci_dev *pdev, void __iomem *ovrfl_window, u32 drc) | ||
346 | { | ||
347 | struct csrow_info *csrow; | ||
348 | unsigned long last_cumul_size; | ||
349 | u8 value; | ||
350 | u32 drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ | ||
351 | u32 cumul_size; | ||
352 | int index; | ||
353 | |||
354 | drc_ddim = (drc >> 18) & 0x1; | ||
355 | last_cumul_size = 0; | ||
356 | |||
357 | /* The dram row boundary (DRB) reg values are boundary address | ||
357 | * for each DRAM row with a granularity of 32 or 64MB (single/dual | 358 | * for each DRAM row with a granularity of 32 or 64MB (single/dual |
358 | * channel operation). DRB regs are cumulative; therefore DRB7 will | 359 | * channel operation). DRB regs are cumulative; therefore DRB7 will |
359 | * contain the total memory contained in all eight rows. | 360 | * contain the total memory contained in all eight rows. |
360 | */ | 361 | */ |
361 | for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) { | 362 | |
362 | u8 value; | 363 | for (index = 0; index < mci->nr_csrows; index++) { |
363 | u32 cumul_size; | 364 | csrow = &mci->csrows[index]; |
364 | struct csrow_info *csrow = &mci->csrows[index]; | ||
365 | 365 | ||
366 | value = readb(ovrfl_window + I82875P_DRB + index); | 366 | value = readb(ovrfl_window + I82875P_DRB + index); |
367 | cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT); | 367 | cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT); |
368 | debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, | 368 | debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, |
369 | cumul_size); | 369 | cumul_size); |
370 | |||
371 | if (cumul_size == last_cumul_size) | 370 | if (cumul_size == last_cumul_size) |
372 | continue; /* not populated */ | 371 | continue; /* not populated */ |
373 | 372 | ||
@@ -375,35 +374,75 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) | |||
375 | csrow->last_page = cumul_size - 1; | 374 | csrow->last_page = cumul_size - 1; |
376 | csrow->nr_pages = cumul_size - last_cumul_size; | 375 | csrow->nr_pages = cumul_size - last_cumul_size; |
377 | last_cumul_size = cumul_size; | 376 | last_cumul_size = cumul_size; |
378 | csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */ | 377 | csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */ |
379 | csrow->mtype = MEM_DDR; | 378 | csrow->mtype = MEM_DDR; |
380 | csrow->dtype = DEV_UNKNOWN; | 379 | csrow->dtype = DEV_UNKNOWN; |
381 | csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE; | 380 | csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE; |
382 | } | 381 | } |
382 | } | ||
383 | |||
384 | static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) | ||
385 | { | ||
386 | int rc = -ENODEV; | ||
387 | struct mem_ctl_info *mci; | ||
388 | struct i82875p_pvt *pvt; | ||
389 | struct pci_dev *ovrfl_pdev; | ||
390 | void __iomem *ovrfl_window; | ||
391 | u32 drc; | ||
392 | u32 nr_chans; | ||
393 | struct i82875p_error_info discard; | ||
394 | |||
395 | debugf0("%s()\n", __func__); | ||
396 | ovrfl_pdev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL); | ||
397 | |||
398 | if (i82875p_setup_overfl_dev(pdev, &ovrfl_pdev, &ovrfl_window)) | ||
399 | return -ENODEV; | ||
400 | drc = readl(ovrfl_window + I82875P_DRC); | ||
401 | nr_chans = dual_channel_active(drc) + 1; | ||
402 | mci = edac_mc_alloc(sizeof(*pvt), I82875P_NR_CSROWS(nr_chans), | ||
403 | nr_chans); | ||
404 | |||
405 | if (!mci) { | ||
406 | rc = -ENOMEM; | ||
407 | goto fail0; | ||
408 | } | ||
383 | 409 | ||
410 | debugf3("%s(): init mci\n", __func__); | ||
411 | mci->dev = &pdev->dev; | ||
412 | mci->mtype_cap = MEM_FLAG_DDR; | ||
413 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; | ||
414 | mci->edac_cap = EDAC_FLAG_UNKNOWN; | ||
415 | mci->mod_name = EDAC_MOD_STR; | ||
416 | mci->mod_ver = I82875P_REVISION; | ||
417 | mci->ctl_name = i82875p_devs[dev_idx].ctl_name; | ||
418 | mci->edac_check = i82875p_check; | ||
419 | mci->ctl_page_to_phys = NULL; | ||
420 | debugf3("%s(): init pvt\n", __func__); | ||
421 | pvt = (struct i82875p_pvt *) mci->pvt_info; | ||
422 | pvt->ovrfl_pdev = ovrfl_pdev; | ||
423 | pvt->ovrfl_window = ovrfl_window; | ||
424 | i82875p_init_csrows(mci, pdev, ovrfl_window, drc); | ||
384 | i82875p_get_error_info(mci, &discard); /* clear counters */ | 425 | i82875p_get_error_info(mci, &discard); /* clear counters */ |
385 | 426 | ||
386 | if (edac_mc_add_mc(mci)) { | 427 | /* Here we assume that we will never see multiple instances of this |
428 | * type of memory controller. The ID is therefore hardcoded to 0. | ||
429 | */ | ||
430 | if (edac_mc_add_mc(mci,0)) { | ||
387 | debugf3("%s(): failed edac_mc_add_mc()\n", __func__); | 431 | debugf3("%s(): failed edac_mc_add_mc()\n", __func__); |
388 | goto fail3; | 432 | goto fail1; |
389 | } | 433 | } |
390 | 434 | ||
391 | /* get this far and it's successful */ | 435 | /* get this far and it's successful */ |
392 | debugf3("%s(): success\n", __func__); | 436 | debugf3("%s(): success\n", __func__); |
393 | return 0; | 437 | return 0; |
394 | 438 | ||
395 | fail3: | 439 | fail1: |
396 | edac_mc_free(mci); | 440 | edac_mc_free(mci); |
397 | 441 | ||
398 | fail2: | 442 | fail0: |
399 | iounmap(ovrfl_window); | 443 | iounmap(ovrfl_window); |
400 | |||
401 | fail1: | ||
402 | pci_release_regions(ovrfl_pdev); | 444 | pci_release_regions(ovrfl_pdev); |
403 | 445 | ||
404 | #ifdef CORRECT_BIOS | ||
405 | fail0: | ||
406 | #endif | ||
407 | pci_disable_device(ovrfl_pdev); | 446 | pci_disable_device(ovrfl_pdev); |
408 | /* NOTE: the ovrfl proc entry and pci_dev are intentionally left */ | 447 | /* NOTE: the ovrfl proc entry and pci_dev are intentionally left */ |
409 | return rc; | 448 | return rc; |
@@ -436,7 +475,7 @@ static void __devexit i82875p_remove_one(struct pci_dev *pdev) | |||
436 | 475 | ||
437 | debugf0("%s()\n", __func__); | 476 | debugf0("%s()\n", __func__); |
438 | 477 | ||
439 | if ((mci = edac_mc_del_mc(pdev)) == NULL) | 478 | if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL) |
440 | return; | 479 | return; |
441 | 480 | ||
442 | pvt = (struct i82875p_pvt *) mci->pvt_info; | 481 | pvt = (struct i82875p_pvt *) mci->pvt_info; |
diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index 4275b148c15e..a0e248d11ed9 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c | |||
@@ -22,6 +22,8 @@ | |||
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include "edac_mc.h" | 23 | #include "edac_mc.h" |
24 | 24 | ||
25 | #define R82600_REVISION " Ver: 2.0.0 " __DATE__ | ||
26 | |||
25 | #define r82600_printk(level, fmt, arg...) \ | 27 | #define r82600_printk(level, fmt, arg...) \ |
26 | edac_printk(level, "r82600", fmt, ##arg) | 28 | edac_printk(level, "r82600", fmt, ##arg) |
27 | 29 | ||
@@ -133,17 +135,20 @@ static unsigned int disable_hardware_scrub = 0; | |||
133 | static void r82600_get_error_info (struct mem_ctl_info *mci, | 135 | static void r82600_get_error_info (struct mem_ctl_info *mci, |
134 | struct r82600_error_info *info) | 136 | struct r82600_error_info *info) |
135 | { | 137 | { |
136 | pci_read_config_dword(mci->pdev, R82600_EAP, &info->eapr); | 138 | struct pci_dev *pdev; |
139 | |||
140 | pdev = to_pci_dev(mci->dev); | ||
141 | pci_read_config_dword(pdev, R82600_EAP, &info->eapr); | ||
137 | 142 | ||
138 | if (info->eapr & BIT(0)) | 143 | if (info->eapr & BIT(0)) |
139 | /* Clear error to allow next error to be reported [p.62] */ | 144 | /* Clear error to allow next error to be reported [p.62] */ |
140 | pci_write_bits32(mci->pdev, R82600_EAP, | 145 | pci_write_bits32(pdev, R82600_EAP, |
141 | ((u32) BIT(0) & (u32) BIT(1)), | 146 | ((u32) BIT(0) & (u32) BIT(1)), |
142 | ((u32) BIT(0) & (u32) BIT(1))); | 147 | ((u32) BIT(0) & (u32) BIT(1))); |
143 | 148 | ||
144 | if (info->eapr & BIT(1)) | 149 | if (info->eapr & BIT(1)) |
145 | /* Clear error to allow next error to be reported [p.62] */ | 150 | /* Clear error to allow next error to be reported [p.62] */ |
146 | pci_write_bits32(mci->pdev, R82600_EAP, | 151 | pci_write_bits32(pdev, R82600_EAP, |
147 | ((u32) BIT(0) & (u32) BIT(1)), | 152 | ((u32) BIT(0) & (u32) BIT(1)), |
148 | ((u32) BIT(0) & (u32) BIT(1))); | 153 | ((u32) BIT(0) & (u32) BIT(1))); |
149 | } | 154 | } |
@@ -199,25 +204,72 @@ static void r82600_check(struct mem_ctl_info *mci) | |||
199 | r82600_process_error_info(mci, &info, 1); | 204 | r82600_process_error_info(mci, &info, 1); |
200 | } | 205 | } |
201 | 206 | ||
202 | static int r82600_probe1(struct pci_dev *pdev, int dev_idx) | 207 | static inline int ecc_enabled(u8 dramcr) |
208 | { | ||
209 | return dramcr & BIT(5); | ||
210 | } | ||
211 | |||
212 | static void r82600_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, | ||
213 | u8 dramcr) | ||
203 | { | 214 | { |
204 | int rc = -ENODEV; | 215 | struct csrow_info *csrow; |
205 | int index; | 216 | int index; |
206 | struct mem_ctl_info *mci = NULL; | 217 | u8 drbar; /* SDRAM Row Boundry Address Register */ |
218 | u32 row_high_limit, row_high_limit_last; | ||
219 | u32 reg_sdram, ecc_on, row_base; | ||
220 | |||
221 | ecc_on = ecc_enabled(dramcr); | ||
222 | reg_sdram = dramcr & BIT(4); | ||
223 | row_high_limit_last = 0; | ||
224 | |||
225 | for (index = 0; index < mci->nr_csrows; index++) { | ||
226 | csrow = &mci->csrows[index]; | ||
227 | |||
228 | /* find the DRAM Chip Select Base address and mask */ | ||
229 | pci_read_config_byte(pdev, R82600_DRBA + index, &drbar); | ||
230 | |||
231 | debugf1("%s() Row=%d DRBA = %#0x\n", __func__, index, drbar); | ||
232 | |||
233 | row_high_limit = ((u32) drbar << 24); | ||
234 | /* row_high_limit = ((u32)drbar << 24) | 0xffffffUL; */ | ||
235 | |||
236 | debugf1("%s() Row=%d, Boundry Address=%#0x, Last = %#0x\n", | ||
237 | __func__, index, row_high_limit, row_high_limit_last); | ||
238 | |||
239 | /* Empty row [p.57] */ | ||
240 | if (row_high_limit == row_high_limit_last) | ||
241 | continue; | ||
242 | |||
243 | row_base = row_high_limit_last; | ||
244 | |||
245 | csrow->first_page = row_base >> PAGE_SHIFT; | ||
246 | csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1; | ||
247 | csrow->nr_pages = csrow->last_page - csrow->first_page + 1; | ||
248 | /* Error address is top 19 bits - so granularity is * | ||
249 | * 14 bits */ | ||
250 | csrow->grain = 1 << 14; | ||
251 | csrow->mtype = reg_sdram ? MEM_RDDR : MEM_DDR; | ||
252 | /* FIXME - check that this is unknowable with this chipset */ | ||
253 | csrow->dtype = DEV_UNKNOWN; | ||
254 | |||
255 | /* Mode is global on 82600 */ | ||
256 | csrow->edac_mode = ecc_on ? EDAC_SECDED : EDAC_NONE; | ||
257 | row_high_limit_last = row_high_limit; | ||
258 | } | ||
259 | } | ||
260 | |||
261 | static int r82600_probe1(struct pci_dev *pdev, int dev_idx) | ||
262 | { | ||
263 | struct mem_ctl_info *mci; | ||
207 | u8 dramcr; | 264 | u8 dramcr; |
208 | u32 ecc_on; | ||
209 | u32 reg_sdram; | ||
210 | u32 eapr; | 265 | u32 eapr; |
211 | u32 scrub_disabled; | 266 | u32 scrub_disabled; |
212 | u32 sdram_refresh_rate; | 267 | u32 sdram_refresh_rate; |
213 | u32 row_high_limit_last = 0; | ||
214 | struct r82600_error_info discard; | 268 | struct r82600_error_info discard; |
215 | 269 | ||
216 | debugf0("%s()\n", __func__); | 270 | debugf0("%s()\n", __func__); |
217 | pci_read_config_byte(pdev, R82600_DRAMC, &dramcr); | 271 | pci_read_config_byte(pdev, R82600_DRAMC, &dramcr); |
218 | pci_read_config_dword(pdev, R82600_EAP, &eapr); | 272 | pci_read_config_dword(pdev, R82600_EAP, &eapr); |
219 | ecc_on = dramcr & BIT(5); | ||
220 | reg_sdram = dramcr & BIT(4); | ||
221 | scrub_disabled = eapr & BIT(31); | 273 | scrub_disabled = eapr & BIT(31); |
222 | sdram_refresh_rate = dramcr & (BIT(0) | BIT(1)); | 274 | sdram_refresh_rate = dramcr & (BIT(0) | BIT(1)); |
223 | debugf2("%s(): sdram refresh rate = %#0x\n", __func__, | 275 | debugf2("%s(): sdram refresh rate = %#0x\n", __func__, |
@@ -225,13 +277,11 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) | |||
225 | debugf2("%s(): DRAMC register = %#0x\n", __func__, dramcr); | 277 | debugf2("%s(): DRAMC register = %#0x\n", __func__, dramcr); |
226 | mci = edac_mc_alloc(0, R82600_NR_CSROWS, R82600_NR_CHANS); | 278 | mci = edac_mc_alloc(0, R82600_NR_CSROWS, R82600_NR_CHANS); |
227 | 279 | ||
228 | if (mci == NULL) { | 280 | if (mci == NULL) |
229 | rc = -ENOMEM; | 281 | return -ENOMEM; |
230 | goto fail; | ||
231 | } | ||
232 | 282 | ||
233 | debugf0("%s(): mci = %p\n", __func__, mci); | 283 | debugf0("%s(): mci = %p\n", __func__, mci); |
234 | mci->pdev = pdev; | 284 | mci->dev = &pdev->dev; |
235 | mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; | 285 | mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; |
236 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; | 286 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; |
237 | /* FIXME try to work out if the chip leads have been used for COM2 | 287 | /* FIXME try to work out if the chip leads have been used for COM2 |
@@ -244,7 +294,7 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) | |||
244 | * is possible. */ | 294 | * is possible. */ |
245 | mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; | 295 | mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; |
246 | 296 | ||
247 | if (ecc_on) { | 297 | if (ecc_enabled(dramcr)) { |
248 | if (scrub_disabled) | 298 | if (scrub_disabled) |
249 | debugf3("%s(): mci = %p - Scrubbing disabled! EAP: " | 299 | debugf3("%s(): mci = %p - Scrubbing disabled! EAP: " |
250 | "%#0x\n", __func__, mci, eapr); | 300 | "%#0x\n", __func__, mci, eapr); |
@@ -252,53 +302,17 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) | |||
252 | mci->edac_cap = EDAC_FLAG_NONE; | 302 | mci->edac_cap = EDAC_FLAG_NONE; |
253 | 303 | ||
254 | mci->mod_name = EDAC_MOD_STR; | 304 | mci->mod_name = EDAC_MOD_STR; |
255 | mci->mod_ver = "$Revision: 1.1.2.6 $"; | 305 | mci->mod_ver = R82600_REVISION; |
256 | mci->ctl_name = "R82600"; | 306 | mci->ctl_name = "R82600"; |
257 | mci->edac_check = r82600_check; | 307 | mci->edac_check = r82600_check; |
258 | mci->ctl_page_to_phys = NULL; | 308 | mci->ctl_page_to_phys = NULL; |
259 | 309 | r82600_init_csrows(mci, pdev, dramcr); | |
260 | for (index = 0; index < mci->nr_csrows; index++) { | ||
261 | struct csrow_info *csrow = &mci->csrows[index]; | ||
262 | u8 drbar; /* sDram Row Boundry Address Register */ | ||
263 | u32 row_high_limit; | ||
264 | u32 row_base; | ||
265 | |||
266 | /* find the DRAM Chip Select Base address and mask */ | ||
267 | pci_read_config_byte(mci->pdev, R82600_DRBA + index, &drbar); | ||
268 | |||
269 | debugf1("MC%d: %s() Row=%d DRBA = %#0x\n", mci->mc_idx, | ||
270 | __func__, index, drbar); | ||
271 | |||
272 | row_high_limit = ((u32) drbar << 24); | ||
273 | /* row_high_limit = ((u32)drbar << 24) | 0xffffffUL; */ | ||
274 | |||
275 | debugf1("MC%d: %s() Row=%d, Boundry Address=%#0x, Last = " | ||
276 | "%#0x \n", mci->mc_idx, __func__, index, | ||
277 | row_high_limit, row_high_limit_last); | ||
278 | |||
279 | /* Empty row [p.57] */ | ||
280 | if (row_high_limit == row_high_limit_last) | ||
281 | continue; | ||
282 | |||
283 | row_base = row_high_limit_last; | ||
284 | csrow->first_page = row_base >> PAGE_SHIFT; | ||
285 | csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1; | ||
286 | csrow->nr_pages = csrow->last_page - csrow->first_page + 1; | ||
287 | /* Error address is top 19 bits - so granularity is * | ||
288 | * 14 bits */ | ||
289 | csrow->grain = 1 << 14; | ||
290 | csrow->mtype = reg_sdram ? MEM_RDDR : MEM_DDR; | ||
291 | /* FIXME - check that this is unknowable with this chipset */ | ||
292 | csrow->dtype = DEV_UNKNOWN; | ||
293 | |||
294 | /* Mode is global on 82600 */ | ||
295 | csrow->edac_mode = ecc_on ? EDAC_SECDED : EDAC_NONE; | ||
296 | row_high_limit_last = row_high_limit; | ||
297 | } | ||
298 | |||
299 | r82600_get_error_info(mci, &discard); /* clear counters */ | 310 | r82600_get_error_info(mci, &discard); /* clear counters */ |
300 | 311 | ||
301 | if (edac_mc_add_mc(mci)) { | 312 | /* Here we assume that we will never see multiple instances of this |
313 | * type of memory controller. The ID is therefore hardcoded to 0. | ||
314 | */ | ||
315 | if (edac_mc_add_mc(mci,0)) { | ||
302 | debugf3("%s(): failed edac_mc_add_mc()\n", __func__); | 316 | debugf3("%s(): failed edac_mc_add_mc()\n", __func__); |
303 | goto fail; | 317 | goto fail; |
304 | } | 318 | } |
@@ -308,17 +322,15 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) | |||
308 | if (disable_hardware_scrub) { | 322 | if (disable_hardware_scrub) { |
309 | debugf3("%s(): Disabling Hardware Scrub (scrub on error)\n", | 323 | debugf3("%s(): Disabling Hardware Scrub (scrub on error)\n", |
310 | __func__); | 324 | __func__); |
311 | pci_write_bits32(mci->pdev, R82600_EAP, BIT(31), BIT(31)); | 325 | pci_write_bits32(pdev, R82600_EAP, BIT(31), BIT(31)); |
312 | } | 326 | } |
313 | 327 | ||
314 | debugf3("%s(): success\n", __func__); | 328 | debugf3("%s(): success\n", __func__); |
315 | return 0; | 329 | return 0; |
316 | 330 | ||
317 | fail: | 331 | fail: |
318 | if (mci) | 332 | edac_mc_free(mci); |
319 | edac_mc_free(mci); | 333 | return -ENODEV; |
320 | |||
321 | return rc; | ||
322 | } | 334 | } |
323 | 335 | ||
324 | /* returns count (>= 0), or negative on error */ | 336 | /* returns count (>= 0), or negative on error */ |
@@ -337,7 +349,7 @@ static void __devexit r82600_remove_one(struct pci_dev *pdev) | |||
337 | 349 | ||
338 | debugf0("%s()\n", __func__); | 350 | debugf0("%s()\n", __func__); |
339 | 351 | ||
340 | if ((mci = edac_mc_del_mc(pdev)) == NULL) | 352 | if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL) |
341 | return; | 353 | return; |
342 | 354 | ||
343 | edac_mc_free(mci); | 355 | edac_mc_free(mci); |