diff options
Diffstat (limited to 'drivers/edac/r82600_edac.c')
-rw-r--r-- | drivers/edac/r82600_edac.c | 71 |
1 files changed, 27 insertions, 44 deletions
diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index 5966916d02bd..2c29fafe67c7 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c | |||
@@ -18,19 +18,16 @@ | |||
18 | #include <linux/config.h> | 18 | #include <linux/config.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | |||
22 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
23 | #include <linux/pci_ids.h> | 22 | #include <linux/pci_ids.h> |
24 | |||
25 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
26 | |||
27 | #include "edac_mc.h" | 24 | #include "edac_mc.h" |
28 | 25 | ||
29 | #define r82600_printk(level, fmt, arg...) \ | 26 | #define r82600_printk(level, fmt, arg...) \ |
30 | edac_printk(level, "r82600", fmt, ##arg) | 27 | edac_printk(level, "r82600", fmt, ##arg) |
31 | 28 | ||
32 | #define r82600_mc_printk(mci, level, fmt, arg...) \ | 29 | #define r82600_mc_printk(mci, level, fmt, arg...) \ |
33 | edac_mc_chipset_printk(mci, level, "r82600", fmt, ##arg) | 30 | edac_mc_chipset_printk(mci, level, "r82600", fmt, ##arg) |
34 | 31 | ||
35 | /* Radisys say "The 82600 integrates a main memory SDRAM controller that | 32 | /* Radisys say "The 82600 integrates a main memory SDRAM controller that |
36 | * supports up to four banks of memory. The four banks can support a mix of | 33 | * supports up to four banks of memory. The four banks can support a mix of |
@@ -132,10 +129,8 @@ struct r82600_error_info { | |||
132 | u32 eapr; | 129 | u32 eapr; |
133 | }; | 130 | }; |
134 | 131 | ||
135 | |||
136 | static unsigned int disable_hardware_scrub = 0; | 132 | static unsigned int disable_hardware_scrub = 0; |
137 | 133 | ||
138 | |||
139 | static void r82600_get_error_info (struct mem_ctl_info *mci, | 134 | static void r82600_get_error_info (struct mem_ctl_info *mci, |
140 | struct r82600_error_info *info) | 135 | struct r82600_error_info *info) |
141 | { | 136 | { |
@@ -144,17 +139,16 @@ static void r82600_get_error_info (struct mem_ctl_info *mci, | |||
144 | if (info->eapr & BIT(0)) | 139 | if (info->eapr & BIT(0)) |
145 | /* Clear error to allow next error to be reported [p.62] */ | 140 | /* Clear error to allow next error to be reported [p.62] */ |
146 | pci_write_bits32(mci->pdev, R82600_EAP, | 141 | pci_write_bits32(mci->pdev, R82600_EAP, |
147 | ((u32) BIT(0) & (u32) BIT(1)), | 142 | ((u32) BIT(0) & (u32) BIT(1)), |
148 | ((u32) BIT(0) & (u32) BIT(1))); | 143 | ((u32) BIT(0) & (u32) BIT(1))); |
149 | 144 | ||
150 | if (info->eapr & BIT(1)) | 145 | if (info->eapr & BIT(1)) |
151 | /* Clear error to allow next error to be reported [p.62] */ | 146 | /* Clear error to allow next error to be reported [p.62] */ |
152 | pci_write_bits32(mci->pdev, R82600_EAP, | 147 | pci_write_bits32(mci->pdev, R82600_EAP, |
153 | ((u32) BIT(0) & (u32) BIT(1)), | 148 | ((u32) BIT(0) & (u32) BIT(1)), |
154 | ((u32) BIT(0) & (u32) BIT(1))); | 149 | ((u32) BIT(0) & (u32) BIT(1))); |
155 | } | 150 | } |
156 | 151 | ||
157 | |||
158 | static int r82600_process_error_info (struct mem_ctl_info *mci, | 152 | static int r82600_process_error_info (struct mem_ctl_info *mci, |
159 | struct r82600_error_info *info, int handle_errors) | 153 | struct r82600_error_info *info, int handle_errors) |
160 | { | 154 | { |
@@ -173,26 +167,25 @@ static int r82600_process_error_info (struct mem_ctl_info *mci, | |||
173 | * granularity (upper 19 bits only) */ | 167 | * granularity (upper 19 bits only) */ |
174 | page = eapaddr >> PAGE_SHIFT; | 168 | page = eapaddr >> PAGE_SHIFT; |
175 | 169 | ||
176 | if (info->eapr & BIT(0)) { /* CE? */ | 170 | if (info->eapr & BIT(0)) { /* CE? */ |
177 | error_found = 1; | 171 | error_found = 1; |
178 | 172 | ||
179 | if (handle_errors) | 173 | if (handle_errors) |
180 | edac_mc_handle_ce( | 174 | edac_mc_handle_ce(mci, page, 0, /* not avail */ |
181 | mci, page, 0, /* not avail */ | 175 | syndrome, |
182 | syndrome, | 176 | edac_mc_find_csrow_by_page(mci, page), |
183 | edac_mc_find_csrow_by_page(mci, page), | 177 | 0, /* channel */ |
184 | 0, /* channel */ | 178 | mci->ctl_name); |
185 | mci->ctl_name); | ||
186 | } | 179 | } |
187 | 180 | ||
188 | if (info->eapr & BIT(1)) { /* UE? */ | 181 | if (info->eapr & BIT(1)) { /* UE? */ |
189 | error_found = 1; | 182 | error_found = 1; |
190 | 183 | ||
191 | if (handle_errors) | 184 | if (handle_errors) |
192 | /* 82600 doesn't give enough info */ | 185 | /* 82600 doesn't give enough info */ |
193 | edac_mc_handle_ue(mci, page, 0, | 186 | edac_mc_handle_ue(mci, page, 0, |
194 | edac_mc_find_csrow_by_page(mci, page), | 187 | edac_mc_find_csrow_by_page(mci, page), |
195 | mci->ctl_name); | 188 | mci->ctl_name); |
196 | } | 189 | } |
197 | 190 | ||
198 | return error_found; | 191 | return error_found; |
@@ -222,21 +215,15 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) | |||
222 | struct r82600_error_info discard; | 215 | struct r82600_error_info discard; |
223 | 216 | ||
224 | debugf0("%s()\n", __func__); | 217 | debugf0("%s()\n", __func__); |
225 | |||
226 | |||
227 | pci_read_config_byte(pdev, R82600_DRAMC, &dramcr); | 218 | pci_read_config_byte(pdev, R82600_DRAMC, &dramcr); |
228 | pci_read_config_dword(pdev, R82600_EAP, &eapr); | 219 | pci_read_config_dword(pdev, R82600_EAP, &eapr); |
229 | |||
230 | ecc_on = dramcr & BIT(5); | 220 | ecc_on = dramcr & BIT(5); |
231 | reg_sdram = dramcr & BIT(4); | 221 | reg_sdram = dramcr & BIT(4); |
232 | scrub_disabled = eapr & BIT(31); | 222 | scrub_disabled = eapr & BIT(31); |
233 | sdram_refresh_rate = dramcr & (BIT(0) | BIT(1)); | 223 | sdram_refresh_rate = dramcr & (BIT(0) | BIT(1)); |
234 | |||
235 | debugf2("%s(): sdram refresh rate = %#0x\n", __func__, | 224 | debugf2("%s(): sdram refresh rate = %#0x\n", __func__, |
236 | sdram_refresh_rate); | 225 | sdram_refresh_rate); |
237 | |||
238 | debugf2("%s(): DRAMC register = %#0x\n", __func__, dramcr); | 226 | debugf2("%s(): DRAMC register = %#0x\n", __func__, dramcr); |
239 | |||
240 | mci = edac_mc_alloc(0, R82600_NR_CSROWS, R82600_NR_CHANS); | 227 | mci = edac_mc_alloc(0, R82600_NR_CSROWS, R82600_NR_CHANS); |
241 | 228 | ||
242 | if (mci == NULL) { | 229 | if (mci == NULL) { |
@@ -245,19 +232,19 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) | |||
245 | } | 232 | } |
246 | 233 | ||
247 | debugf0("%s(): mci = %p\n", __func__, mci); | 234 | debugf0("%s(): mci = %p\n", __func__, mci); |
248 | |||
249 | mci->pdev = pdev; | 235 | mci->pdev = pdev; |
250 | mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; | 236 | mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; |
251 | |||
252 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; | 237 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; |
253 | /* FIXME try to work out if the chip leads have been * | 238 | /* FIXME try to work out if the chip leads have been used for COM2 |
254 | * used for COM2 instead on this board? [MA6?] MAYBE: */ | 239 | * instead on this board? [MA6?] MAYBE: |
240 | */ | ||
255 | 241 | ||
256 | /* On the R82600, the pins for memory bits 72:65 - i.e. the * | 242 | /* On the R82600, the pins for memory bits 72:65 - i.e. the * |
257 | * EC bits are shared with the pins for COM2 (!), so if COM2 * | 243 | * EC bits are shared with the pins for COM2 (!), so if COM2 * |
258 | * is enabled, we assume COM2 is wired up, and thus no EDAC * | 244 | * is enabled, we assume COM2 is wired up, and thus no EDAC * |
259 | * is possible. */ | 245 | * is possible. */ |
260 | mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; | 246 | mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; |
247 | |||
261 | if (ecc_on) { | 248 | if (ecc_on) { |
262 | if (scrub_disabled) | 249 | if (scrub_disabled) |
263 | debugf3("%s(): mci = %p - Scrubbing disabled! EAP: " | 250 | debugf3("%s(): mci = %p - Scrubbing disabled! EAP: " |
@@ -295,7 +282,6 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) | |||
295 | continue; | 282 | continue; |
296 | 283 | ||
297 | row_base = row_high_limit_last; | 284 | row_base = row_high_limit_last; |
298 | |||
299 | csrow->first_page = row_base >> PAGE_SHIFT; | 285 | csrow->first_page = row_base >> PAGE_SHIFT; |
300 | csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1; | 286 | csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1; |
301 | csrow->nr_pages = csrow->last_page - csrow->first_page + 1; | 287 | csrow->nr_pages = csrow->last_page - csrow->first_page + 1; |
@@ -338,7 +324,7 @@ fail: | |||
338 | 324 | ||
339 | /* returns count (>= 0), or negative on error */ | 325 | /* returns count (>= 0), or negative on error */ |
340 | static int __devinit r82600_init_one(struct pci_dev *pdev, | 326 | static int __devinit r82600_init_one(struct pci_dev *pdev, |
341 | const struct pci_device_id *ent) | 327 | const struct pci_device_id *ent) |
342 | { | 328 | { |
343 | debugf0("%s()\n", __func__); | 329 | debugf0("%s()\n", __func__); |
344 | 330 | ||
@@ -346,7 +332,6 @@ static int __devinit r82600_init_one(struct pci_dev *pdev, | |||
346 | return r82600_probe1(pdev, ent->driver_data); | 332 | return r82600_probe1(pdev, ent->driver_data); |
347 | } | 333 | } |
348 | 334 | ||
349 | |||
350 | static void __devexit r82600_remove_one(struct pci_dev *pdev) | 335 | static void __devexit r82600_remove_one(struct pci_dev *pdev) |
351 | { | 336 | { |
352 | struct mem_ctl_info *mci; | 337 | struct mem_ctl_info *mci; |
@@ -359,15 +344,17 @@ static void __devexit r82600_remove_one(struct pci_dev *pdev) | |||
359 | edac_mc_free(mci); | 344 | edac_mc_free(mci); |
360 | } | 345 | } |
361 | 346 | ||
362 | |||
363 | static const struct pci_device_id r82600_pci_tbl[] __devinitdata = { | 347 | static const struct pci_device_id r82600_pci_tbl[] __devinitdata = { |
364 | {PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID)}, | 348 | { |
365 | {0,} /* 0 terminated list. */ | 349 | PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID) |
350 | }, | ||
351 | { | ||
352 | 0, | ||
353 | } /* 0 terminated list. */ | ||
366 | }; | 354 | }; |
367 | 355 | ||
368 | MODULE_DEVICE_TABLE(pci, r82600_pci_tbl); | 356 | MODULE_DEVICE_TABLE(pci, r82600_pci_tbl); |
369 | 357 | ||
370 | |||
371 | static struct pci_driver r82600_driver = { | 358 | static struct pci_driver r82600_driver = { |
372 | .name = EDAC_MOD_STR, | 359 | .name = EDAC_MOD_STR, |
373 | .probe = r82600_init_one, | 360 | .probe = r82600_init_one, |
@@ -375,26 +362,22 @@ static struct pci_driver r82600_driver = { | |||
375 | .id_table = r82600_pci_tbl, | 362 | .id_table = r82600_pci_tbl, |
376 | }; | 363 | }; |
377 | 364 | ||
378 | |||
379 | static int __init r82600_init(void) | 365 | static int __init r82600_init(void) |
380 | { | 366 | { |
381 | return pci_register_driver(&r82600_driver); | 367 | return pci_register_driver(&r82600_driver); |
382 | } | 368 | } |
383 | 369 | ||
384 | |||
385 | static void __exit r82600_exit(void) | 370 | static void __exit r82600_exit(void) |
386 | { | 371 | { |
387 | pci_unregister_driver(&r82600_driver); | 372 | pci_unregister_driver(&r82600_driver); |
388 | } | 373 | } |
389 | 374 | ||
390 | |||
391 | module_init(r82600_init); | 375 | module_init(r82600_init); |
392 | module_exit(r82600_exit); | 376 | module_exit(r82600_exit); |
393 | 377 | ||
394 | |||
395 | MODULE_LICENSE("GPL"); | 378 | MODULE_LICENSE("GPL"); |
396 | MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD Ltd. " | 379 | MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD Ltd. " |
397 | "on behalf of EADS Astrium"); | 380 | "on behalf of EADS Astrium"); |
398 | MODULE_DESCRIPTION("MC support for Radisys 82600 memory controllers"); | 381 | MODULE_DESCRIPTION("MC support for Radisys 82600 memory controllers"); |
399 | 382 | ||
400 | module_param(disable_hardware_scrub, bool, 0644); | 383 | module_param(disable_hardware_scrub, bool, 0644); |