aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/i82875p_edac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/edac/i82875p_edac.c')
-rw-r--r--drivers/edac/i82875p_edac.c188
1 files changed, 109 insertions, 79 deletions
diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c
index 2be18ca96408..6787403463a1 100644
--- a/drivers/edac/i82875p_edac.c
+++ b/drivers/edac/i82875p_edac.c
@@ -265,116 +265,109 @@ static void i82875p_check(struct mem_ctl_info *mci)
265extern int pci_proc_attach_device(struct pci_dev *); 265extern int pci_proc_attach_device(struct pci_dev *);
266#endif 266#endif
267 267
268static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) 268/* Return 0 on success or 1 on failure. */
269static int i82875p_setup_overfl_dev(struct pci_dev *pdev,
270 struct pci_dev **ovrfl_pdev, void __iomem **ovrfl_window)
269{ 271{
270 int rc = -ENODEV; 272 struct pci_dev *dev;
271 int index; 273 void __iomem *window;
272 struct mem_ctl_info *mci = NULL;
273 struct i82875p_pvt *pvt = NULL;
274 unsigned long last_cumul_size;
275 struct pci_dev *ovrfl_pdev;
276 void __iomem *ovrfl_window = NULL;
277 u32 drc;
278 u32 drc_chan; /* Number of channels 0=1chan,1=2chan */
279 u32 nr_chans;
280 u32 drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
281 struct i82875p_error_info discard;
282 274
283 debugf0("%s()\n", __func__); 275 *ovrfl_pdev = NULL;
284 ovrfl_pdev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL); 276 *ovrfl_window = NULL;
277 dev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL);
285 278
286 if (!ovrfl_pdev) { 279 if (dev == NULL) {
287 /* 280 /* Intel tells BIOS developers to hide device 6 which
288 * Intel tells BIOS developers to hide device 6 which
289 * configures the overflow device access containing 281 * configures the overflow device access containing
290 * the DRBs - this is where we expose device 6. 282 * the DRBs - this is where we expose device 6.
291 * http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm 283 * http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm
292 */ 284 */
293 pci_write_bits8(pdev, 0xf4, 0x2, 0x2); 285 pci_write_bits8(pdev, 0xf4, 0x2, 0x2);
294 ovrfl_pdev = 286 dev = pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0));
295 pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0));
296 287
297 if (!ovrfl_pdev) 288 if (dev == NULL)
298 return -ENODEV; 289 return 1;
299 } 290 }
300 291
292 *ovrfl_pdev = dev;
293
301#ifdef CONFIG_PROC_FS 294#ifdef CONFIG_PROC_FS
302 if (!ovrfl_pdev->procent && pci_proc_attach_device(ovrfl_pdev)) { 295 if ((dev->procent == NULL) && pci_proc_attach_device(dev)) {
303 i82875p_printk(KERN_ERR, 296 i82875p_printk(KERN_ERR, "%s(): Failed to attach overflow "
304 "%s(): Failed to attach overflow device\n", __func__); 297 "device\n", __func__);
305 return -ENODEV; 298 return 1;
306 } 299 }
307#endif 300#endif /* CONFIG_PROC_FS */
308 /* CONFIG_PROC_FS */ 301 if (pci_enable_device(dev)) {
309 if (pci_enable_device(ovrfl_pdev)) { 302 i82875p_printk(KERN_ERR, "%s(): Failed to enable overflow "
310 i82875p_printk(KERN_ERR, 303 "device\n", __func__);
311 "%s(): Failed to enable overflow device\n", __func__); 304 return 1;
312 return -ENODEV;
313 } 305 }
314 306
315 if (pci_request_regions(ovrfl_pdev, pci_name(ovrfl_pdev))) { 307 if (pci_request_regions(dev, pci_name(dev))) {
316#ifdef CORRECT_BIOS 308#ifdef CORRECT_BIOS
317 goto fail0; 309 goto fail0;
318#endif 310#endif
319 } 311 }
320 312
321 /* cache is irrelevant for PCI bus reads/writes */ 313 /* cache is irrelevant for PCI bus reads/writes */
322 ovrfl_window = ioremap_nocache(pci_resource_start(ovrfl_pdev, 0), 314 window = ioremap_nocache(pci_resource_start(dev, 0),
323 pci_resource_len(ovrfl_pdev, 0)); 315 pci_resource_len(dev, 0));
324 316
325 if (!ovrfl_window) { 317 if (window == NULL) {
326 i82875p_printk(KERN_ERR, "%s(): Failed to ioremap bar6\n", 318 i82875p_printk(KERN_ERR, "%s(): Failed to ioremap bar6\n",
327 __func__); 319 __func__);
328 goto fail1; 320 goto fail1;
329 } 321 }
330 322
331 /* need to find out the number of channels */ 323 *ovrfl_window = window;
332 drc = readl(ovrfl_window + I82875P_DRC); 324 return 0;
333 drc_chan = ((drc >> 21) & 0x1);
334 nr_chans = drc_chan + 1;
335 325
336 drc_ddim = (drc >> 18) & 0x1; 326fail1:
337 mci = edac_mc_alloc(sizeof(*pvt), I82875P_NR_CSROWS(nr_chans), 327 pci_release_regions(dev);
338 nr_chans);
339 328
340 if (!mci) { 329#ifdef CORRECT_BIOS
341 rc = -ENOMEM; 330fail0:
342 goto fail2; 331 pci_disable_device(dev);
343 } 332#endif
333 /* NOTE: the ovrfl proc entry and pci_dev are intentionally left */
334 return 1;
335}
344 336
345 debugf3("%s(): init mci\n", __func__);
346 mci->dev = &pdev->dev;
347 mci->mtype_cap = MEM_FLAG_DDR;
348 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
349 mci->edac_cap = EDAC_FLAG_UNKNOWN;
350 /* adjust FLAGS */
351 337
352 mci->mod_name = EDAC_MOD_STR; 338/* Return 1 if dual channel mode is active. Else return 0. */
353 mci->mod_ver = I82875P_REVISION; 339static inline int dual_channel_active(u32 drc)
354 mci->ctl_name = i82875p_devs[dev_idx].ctl_name; 340{
355 mci->edac_check = i82875p_check; 341 return (drc >> 21) & 0x1;
356 mci->ctl_page_to_phys = NULL; 342}
357 debugf3("%s(): init pvt\n", __func__);
358 pvt = (struct i82875p_pvt *) mci->pvt_info;
359 pvt->ovrfl_pdev = ovrfl_pdev;
360 pvt->ovrfl_window = ovrfl_window;
361 343
362 /* 344
363 * The dram row boundary (DRB) reg values are boundary address 345static void i82875p_init_csrows(struct mem_ctl_info *mci,
346 struct pci_dev *pdev, void __iomem *ovrfl_window, u32 drc)
347{
348 struct csrow_info *csrow;
349 unsigned long last_cumul_size;
350 u8 value;
351 u32 drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
352 u32 cumul_size;
353 int index;
354
355 drc_ddim = (drc >> 18) & 0x1;
356 last_cumul_size = 0;
357
358 /* The dram row boundary (DRB) reg values are boundary address
364 * for each DRAM row with a granularity of 32 or 64MB (single/dual 359 * for each DRAM row with a granularity of 32 or 64MB (single/dual
365 * channel operation). DRB regs are cumulative; therefore DRB7 will 360 * channel operation). DRB regs are cumulative; therefore DRB7 will
366 * contain the total memory contained in all eight rows. 361 * contain the total memory contained in all eight rows.
367 */ 362 */
368 for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) { 363
369 u8 value; 364 for (index = 0; index < mci->nr_csrows; index++) {
370 u32 cumul_size; 365 csrow = &mci->csrows[index];
371 struct csrow_info *csrow = &mci->csrows[index];
372 366
373 value = readb(ovrfl_window + I82875P_DRB + index); 367 value = readb(ovrfl_window + I82875P_DRB + index);
374 cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT); 368 cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT);
375 debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, 369 debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
376 cumul_size); 370 cumul_size);
377
378 if (cumul_size == last_cumul_size) 371 if (cumul_size == last_cumul_size)
379 continue; /* not populated */ 372 continue; /* not populated */
380 373
@@ -382,12 +375,54 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
382 csrow->last_page = cumul_size - 1; 375 csrow->last_page = cumul_size - 1;
383 csrow->nr_pages = cumul_size - last_cumul_size; 376 csrow->nr_pages = cumul_size - last_cumul_size;
384 last_cumul_size = cumul_size; 377 last_cumul_size = cumul_size;
385 csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */ 378 csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */
386 csrow->mtype = MEM_DDR; 379 csrow->mtype = MEM_DDR;
387 csrow->dtype = DEV_UNKNOWN; 380 csrow->dtype = DEV_UNKNOWN;
388 csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE; 381 csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE;
389 } 382 }
383}
384
385static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
386{
387 int rc = -ENODEV;
388 struct mem_ctl_info *mci;
389 struct i82875p_pvt *pvt;
390 struct pci_dev *ovrfl_pdev;
391 void __iomem *ovrfl_window;
392 u32 drc;
393 u32 nr_chans;
394 struct i82875p_error_info discard;
395
396 debugf0("%s()\n", __func__);
397 ovrfl_pdev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL);
398
399 if (i82875p_setup_overfl_dev(pdev, &ovrfl_pdev, &ovrfl_window))
400 return -ENODEV;
401 drc = readl(ovrfl_window + I82875P_DRC);
402 nr_chans = dual_channel_active(drc) + 1;
403 mci = edac_mc_alloc(sizeof(*pvt), I82875P_NR_CSROWS(nr_chans),
404 nr_chans);
405
406 if (!mci) {
407 rc = -ENOMEM;
408 goto fail0;
409 }
390 410
411 debugf3("%s(): init mci\n", __func__);
412 mci->dev = &pdev->dev;
413 mci->mtype_cap = MEM_FLAG_DDR;
414 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
415 mci->edac_cap = EDAC_FLAG_UNKNOWN;
416 mci->mod_name = EDAC_MOD_STR;
417 mci->mod_ver = I82875P_REVISION;
418 mci->ctl_name = i82875p_devs[dev_idx].ctl_name;
419 mci->edac_check = i82875p_check;
420 mci->ctl_page_to_phys = NULL;
421 debugf3("%s(): init pvt\n", __func__);
422 pvt = (struct i82875p_pvt *) mci->pvt_info;
423 pvt->ovrfl_pdev = ovrfl_pdev;
424 pvt->ovrfl_window = ovrfl_window;
425 i82875p_init_csrows(mci, pdev, ovrfl_window, drc);
391 i82875p_get_error_info(mci, &discard); /* clear counters */ 426 i82875p_get_error_info(mci, &discard); /* clear counters */
392 427
393 /* Here we assume that we will never see multiple instances of this 428 /* Here we assume that we will never see multiple instances of this
@@ -395,25 +430,20 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
395 */ 430 */
396 if (edac_mc_add_mc(mci,0)) { 431 if (edac_mc_add_mc(mci,0)) {
397 debugf3("%s(): failed edac_mc_add_mc()\n", __func__); 432 debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
398 goto fail3; 433 goto fail1;
399 } 434 }
400 435
401 /* get this far and it's successful */ 436 /* get this far and it's successful */
402 debugf3("%s(): success\n", __func__); 437 debugf3("%s(): success\n", __func__);
403 return 0; 438 return 0;
404 439
405fail3: 440fail1:
406 edac_mc_free(mci); 441 edac_mc_free(mci);
407 442
408fail2: 443fail0:
409 iounmap(ovrfl_window); 444 iounmap(ovrfl_window);
410
411fail1:
412 pci_release_regions(ovrfl_pdev); 445 pci_release_regions(ovrfl_pdev);
413 446
414#ifdef CORRECT_BIOS
415fail0:
416#endif
417 pci_disable_device(ovrfl_pdev); 447 pci_disable_device(ovrfl_pdev);
418 /* NOTE: the ovrfl proc entry and pci_dev are intentionally left */ 448 /* NOTE: the ovrfl proc entry and pci_dev are intentionally left */
419 return rc; 449 return rc;