diff options
| -rw-r--r-- | drivers/edac/edac_mc.c | 59 |
1 files changed, 39 insertions, 20 deletions
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 9037ffa100d5..d5dc9da7f99f 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c | |||
| @@ -199,6 +199,36 @@ void *edac_align_ptr(void **p, unsigned size, int n_elems) | |||
| 199 | return (void *)(((unsigned long)ptr) + align - r); | 199 | return (void *)(((unsigned long)ptr) + align - r); |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | static void _edac_mc_free(struct mem_ctl_info *mci) | ||
| 203 | { | ||
| 204 | int i, chn, row; | ||
| 205 | struct csrow_info *csr; | ||
| 206 | const unsigned int tot_dimms = mci->tot_dimms; | ||
| 207 | const unsigned int tot_channels = mci->num_cschannel; | ||
| 208 | const unsigned int tot_csrows = mci->nr_csrows; | ||
| 209 | |||
| 210 | if (mci->dimms) { | ||
| 211 | for (i = 0; i < tot_dimms; i++) | ||
| 212 | kfree(mci->dimms[i]); | ||
| 213 | kfree(mci->dimms); | ||
| 214 | } | ||
| 215 | if (mci->csrows) { | ||
| 216 | for (row = 0; row < tot_csrows; row++) { | ||
| 217 | csr = mci->csrows[row]; | ||
| 218 | if (csr) { | ||
| 219 | if (csr->channels) { | ||
| 220 | for (chn = 0; chn < tot_channels; chn++) | ||
| 221 | kfree(csr->channels[chn]); | ||
| 222 | kfree(csr->channels); | ||
| 223 | } | ||
| 224 | kfree(csr); | ||
| 225 | } | ||
| 226 | } | ||
| 227 | kfree(mci->csrows); | ||
| 228 | } | ||
| 229 | kfree(mci); | ||
| 230 | } | ||
| 231 | |||
| 202 | /** | 232 | /** |
| 203 | * edac_mc_alloc: Allocate and partially fill a struct mem_ctl_info structure | 233 | * edac_mc_alloc: Allocate and partially fill a struct mem_ctl_info structure |
| 204 | * @mc_num: Memory controller number | 234 | * @mc_num: Memory controller number |
| @@ -413,26 +443,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, | |||
| 413 | return mci; | 443 | return mci; |
| 414 | 444 | ||
| 415 | error: | 445 | error: |
| 416 | if (mci->dimms) { | 446 | _edac_mc_free(mci); |
| 417 | for (i = 0; i < tot_dimms; i++) | ||
| 418 | kfree(mci->dimms[i]); | ||
| 419 | kfree(mci->dimms); | ||
| 420 | } | ||
| 421 | if (mci->csrows) { | ||
| 422 | for (row = 0; row < tot_csrows; row++) { | ||
| 423 | csr = mci->csrows[row]; | ||
| 424 | if (csr) { | ||
| 425 | if (csr->channels) { | ||
| 426 | for (chn = 0; chn < tot_channels; chn++) | ||
| 427 | kfree(csr->channels[chn]); | ||
| 428 | kfree(csr->channels); | ||
| 429 | } | ||
| 430 | kfree(csr); | ||
| 431 | } | ||
| 432 | } | ||
| 433 | kfree(mci->csrows); | ||
| 434 | } | ||
| 435 | kfree(mci); | ||
| 436 | 447 | ||
| 437 | return NULL; | 448 | return NULL; |
| 438 | } | 449 | } |
| @@ -447,6 +458,14 @@ void edac_mc_free(struct mem_ctl_info *mci) | |||
| 447 | { | 458 | { |
| 448 | edac_dbg(1, "\n"); | 459 | edac_dbg(1, "\n"); |
| 449 | 460 | ||
| 461 | /* If we're not yet registered with sysfs free only what was allocated | ||
| 462 | * in edac_mc_alloc(). | ||
| 463 | */ | ||
| 464 | if (!device_is_registered(&mci->dev)) { | ||
| 465 | _edac_mc_free(mci); | ||
| 466 | return; | ||
| 467 | } | ||
| 468 | |||
| 450 | /* the mci instance is freed here, when the sysfs object is dropped */ | 469 | /* the mci instance is freed here, when the sysfs object is dropped */ |
| 451 | edac_unregister_sysfs(mci); | 470 | edac_unregister_sysfs(mci); |
| 452 | } | 471 | } |
