diff options
author | Jason Baron <jbaron@akamai.com> | 2014-07-09 17:13:07 -0400 |
---|---|---|
committer | Borislav Petkov <bp@suse.de> | 2014-07-10 04:55:12 -0400 |
commit | 78fd4d1242e88fbe5ea269087a47bd7e05bf84a1 (patch) | |
tree | 8b2433163ac374ea191e74f784c36a994eb5fb87 /drivers/edac/ie31200_edac.c | |
parent | 7ee40b897d18ab03111eda9a6a0550e98166eada (diff) |
ie31200_edac: Allocate mci and map mchbar first
Check for memory allocation and mchbar mapping failures before
initializing the dimm info tables needlessly.
Signed-off-by: Jason Baron <jbaron@akamai.com>
Suggested-by: Borislav Petkov <bp@suse.de>
Link: http://lkml.kernel.org/r/ead8f53e699f1ce21c2e17f3cffb4685d4faf72a.1404939455.git.jbaron@akamai.com
Signed-off-by: Borislav Petkov <bp@suse.de>
Diffstat (limited to 'drivers/edac/ie31200_edac.c')
-rw-r--r-- | drivers/edac/ie31200_edac.c | 71 |
1 files changed, 33 insertions, 38 deletions
diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c index 6d3d2c3cb6d6..a981dc6fd88e 100644 --- a/drivers/edac/ie31200_edac.c +++ b/drivers/edac/ie31200_edac.c | |||
@@ -328,8 +328,7 @@ static void __iomem *ie31200_map_mchbar(struct pci_dev *pdev) | |||
328 | 328 | ||
329 | static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) | 329 | static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) |
330 | { | 330 | { |
331 | int rc; | 331 | int i, j, ret; |
332 | int i, j; | ||
333 | struct mem_ctl_info *mci = NULL; | 332 | struct mem_ctl_info *mci = NULL; |
334 | struct edac_mc_layer layers[2]; | 333 | struct edac_mc_layer layers[2]; |
335 | struct dimm_data dimm_info[IE31200_CHANNELS][IE31200_DIMMS_PER_CHANNEL]; | 334 | struct dimm_data dimm_info[IE31200_CHANNELS][IE31200_DIMMS_PER_CHANNEL]; |
@@ -344,31 +343,7 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) | |||
344 | return -ENODEV; | 343 | return -ENODEV; |
345 | } | 344 | } |
346 | 345 | ||
347 | window = ie31200_map_mchbar(pdev); | ||
348 | if (!window) | ||
349 | return -ENODEV; | ||
350 | |||
351 | /* populate DIMM info */ | ||
352 | for (i = 0; i < IE31200_CHANNELS; i++) { | ||
353 | addr_decode = readl(window + IE31200_MAD_DIMM_0_OFFSET + | ||
354 | (i * 4)); | ||
355 | edac_dbg(0, "addr_decode: 0x%x\n", addr_decode); | ||
356 | for (j = 0; j < IE31200_DIMMS_PER_CHANNEL; j++) { | ||
357 | dimm_info[i][j].size = (addr_decode >> (j * 8)) & | ||
358 | IE31200_MAD_DIMM_SIZE; | ||
359 | dimm_info[i][j].dual_rank = (addr_decode & | ||
360 | (IE31200_MAD_DIMM_A_RANK << j)) ? 1 : 0; | ||
361 | dimm_info[i][j].x16_width = (addr_decode & | ||
362 | (IE31200_MAD_DIMM_A_WIDTH << j)) ? 1 : 0; | ||
363 | edac_dbg(0, "size: 0x%x, rank: %d, width: %d\n", | ||
364 | dimm_info[i][j].size, | ||
365 | dimm_info[i][j].dual_rank, | ||
366 | dimm_info[i][j].x16_width); | ||
367 | } | ||
368 | } | ||
369 | |||
370 | nr_channels = how_many_channels(pdev); | 346 | nr_channels = how_many_channels(pdev); |
371 | |||
372 | layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; | 347 | layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; |
373 | layers[0].size = IE31200_DIMMS; | 348 | layers[0].size = IE31200_DIMMS; |
374 | layers[0].is_virt_csrow = true; | 349 | layers[0].is_virt_csrow = true; |
@@ -377,19 +352,20 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) | |||
377 | layers[1].is_virt_csrow = false; | 352 | layers[1].is_virt_csrow = false; |
378 | mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, | 353 | mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, |
379 | sizeof(struct ie31200_priv)); | 354 | sizeof(struct ie31200_priv)); |
380 | |||
381 | rc = -ENOMEM; | ||
382 | if (!mci) | 355 | if (!mci) |
383 | goto fail_unmap; | 356 | return -ENOMEM; |
384 | 357 | ||
385 | edac_dbg(3, "MC: init mci\n"); | 358 | window = ie31200_map_mchbar(pdev); |
359 | if (!window) { | ||
360 | ret = -ENODEV; | ||
361 | goto fail_free; | ||
362 | } | ||
386 | 363 | ||
364 | edac_dbg(3, "MC: init mci\n"); | ||
387 | mci->pdev = &pdev->dev; | 365 | mci->pdev = &pdev->dev; |
388 | mci->mtype_cap = MEM_FLAG_DDR3; | 366 | mci->mtype_cap = MEM_FLAG_DDR3; |
389 | |||
390 | mci->edac_ctl_cap = EDAC_FLAG_SECDED; | 367 | mci->edac_ctl_cap = EDAC_FLAG_SECDED; |
391 | mci->edac_cap = EDAC_FLAG_SECDED; | 368 | mci->edac_cap = EDAC_FLAG_SECDED; |
392 | |||
393 | mci->mod_name = EDAC_MOD_STR; | 369 | mci->mod_name = EDAC_MOD_STR; |
394 | mci->mod_ver = IE31200_REVISION; | 370 | mci->mod_ver = IE31200_REVISION; |
395 | mci->ctl_name = ie31200_devs[dev_idx].ctl_name; | 371 | mci->ctl_name = ie31200_devs[dev_idx].ctl_name; |
@@ -399,6 +375,25 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) | |||
399 | priv = mci->pvt_info; | 375 | priv = mci->pvt_info; |
400 | priv->window = window; | 376 | priv->window = window; |
401 | 377 | ||
378 | /* populate DIMM info */ | ||
379 | for (i = 0; i < IE31200_CHANNELS; i++) { | ||
380 | addr_decode = readl(window + IE31200_MAD_DIMM_0_OFFSET + | ||
381 | (i * 4)); | ||
382 | edac_dbg(0, "addr_decode: 0x%x\n", addr_decode); | ||
383 | for (j = 0; j < IE31200_DIMMS_PER_CHANNEL; j++) { | ||
384 | dimm_info[i][j].size = (addr_decode >> (j * 8)) & | ||
385 | IE31200_MAD_DIMM_SIZE; | ||
386 | dimm_info[i][j].dual_rank = (addr_decode & | ||
387 | (IE31200_MAD_DIMM_A_RANK << j)) ? 1 : 0; | ||
388 | dimm_info[i][j].x16_width = (addr_decode & | ||
389 | (IE31200_MAD_DIMM_A_WIDTH << j)) ? 1 : 0; | ||
390 | edac_dbg(0, "size: 0x%x, rank: %d, width: %d\n", | ||
391 | dimm_info[i][j].size, | ||
392 | dimm_info[i][j].dual_rank, | ||
393 | dimm_info[i][j].x16_width); | ||
394 | } | ||
395 | } | ||
396 | |||
402 | /* | 397 | /* |
403 | * The dram rank boundary (DRB) reg values are boundary addresses | 398 | * The dram rank boundary (DRB) reg values are boundary addresses |
404 | * for each DRAM rank with a granularity of 64MB. DRB regs are | 399 | * for each DRAM rank with a granularity of 64MB. DRB regs are |
@@ -439,23 +434,23 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) | |||
439 | 434 | ||
440 | ie31200_clear_error_info(mci); | 435 | ie31200_clear_error_info(mci); |
441 | 436 | ||
442 | rc = -ENODEV; | ||
443 | if (edac_mc_add_mc(mci)) { | 437 | if (edac_mc_add_mc(mci)) { |
444 | edac_dbg(3, "MC: failed edac_mc_add_mc()\n"); | 438 | edac_dbg(3, "MC: failed edac_mc_add_mc()\n"); |
445 | goto fail_free; | 439 | ret = -ENODEV; |
440 | goto fail_unmap; | ||
446 | } | 441 | } |
447 | 442 | ||
448 | /* get this far and it's successful */ | 443 | /* get this far and it's successful */ |
449 | edac_dbg(3, "MC: success\n"); | 444 | edac_dbg(3, "MC: success\n"); |
450 | return 0; | 445 | return 0; |
451 | 446 | ||
452 | fail_free: | ||
453 | if (mci) | ||
454 | edac_mc_free(mci); | ||
455 | fail_unmap: | 447 | fail_unmap: |
456 | iounmap(window); | 448 | iounmap(window); |
457 | 449 | ||
458 | return rc; | 450 | fail_free: |
451 | edac_mc_free(mci); | ||
452 | |||
453 | return ret; | ||
459 | } | 454 | } |
460 | 455 | ||
461 | static int ie31200_init_one(struct pci_dev *pdev, | 456 | static int ie31200_init_one(struct pci_dev *pdev, |