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 | |
| 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>
| -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, |
