|
@@ -199,6 +199,36 @@ void *edac_align_ptr(void **p, unsigned size, int n_elems)
|
|
|
return (void *)(((unsigned long)ptr) + align - r);
|
|
|
}
|
|
|
|
|
|
+static void _edac_mc_free(struct mem_ctl_info *mci)
|
|
|
+{
|
|
|
+ int i, chn, row;
|
|
|
+ struct csrow_info *csr;
|
|
|
+ const unsigned int tot_dimms = mci->tot_dimms;
|
|
|
+ const unsigned int tot_channels = mci->num_cschannel;
|
|
|
+ const unsigned int tot_csrows = mci->nr_csrows;
|
|
|
+
|
|
|
+ if (mci->dimms) {
|
|
|
+ for (i = 0; i < tot_dimms; i++)
|
|
|
+ kfree(mci->dimms[i]);
|
|
|
+ kfree(mci->dimms);
|
|
|
+ }
|
|
|
+ if (mci->csrows) {
|
|
|
+ for (row = 0; row < tot_csrows; row++) {
|
|
|
+ csr = mci->csrows[row];
|
|
|
+ if (csr) {
|
|
|
+ if (csr->channels) {
|
|
|
+ for (chn = 0; chn < tot_channels; chn++)
|
|
|
+ kfree(csr->channels[chn]);
|
|
|
+ kfree(csr->channels);
|
|
|
+ }
|
|
|
+ kfree(csr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ kfree(mci->csrows);
|
|
|
+ }
|
|
|
+ kfree(mci);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* edac_mc_alloc: Allocate and partially fill a struct mem_ctl_info structure
|
|
|
* @mc_num: Memory controller number
|
|
@@ -413,26 +443,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
|
|
|
return mci;
|
|
|
|
|
|
error:
|
|
|
- if (mci->dimms) {
|
|
|
- for (i = 0; i < tot_dimms; i++)
|
|
|
- kfree(mci->dimms[i]);
|
|
|
- kfree(mci->dimms);
|
|
|
- }
|
|
|
- if (mci->csrows) {
|
|
|
- for (row = 0; row < tot_csrows; row++) {
|
|
|
- csr = mci->csrows[row];
|
|
|
- if (csr) {
|
|
|
- if (csr->channels) {
|
|
|
- for (chn = 0; chn < tot_channels; chn++)
|
|
|
- kfree(csr->channels[chn]);
|
|
|
- kfree(csr->channels);
|
|
|
- }
|
|
|
- kfree(csr);
|
|
|
- }
|
|
|
- }
|
|
|
- kfree(mci->csrows);
|
|
|
- }
|
|
|
- kfree(mci);
|
|
|
+ _edac_mc_free(mci);
|
|
|
|
|
|
return NULL;
|
|
|
}
|
|
@@ -447,6 +458,14 @@ void edac_mc_free(struct mem_ctl_info *mci)
|
|
|
{
|
|
|
edac_dbg(1, "\n");
|
|
|
|
|
|
+ /* If we're not yet registered with sysfs free only what was allocated
|
|
|
+ * in edac_mc_alloc().
|
|
|
+ */
|
|
|
+ if (!device_is_registered(&mci->dev)) {
|
|
|
+ _edac_mc_free(mci);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
/* the mci instance is freed here, when the sysfs object is dropped */
|
|
|
edac_unregister_sysfs(mci);
|
|
|
}
|