diff options
Diffstat (limited to 'drivers/edac/edac_mc.c')
| -rw-r--r-- | drivers/edac/edac_mc.c | 57 | 
1 files changed, 39 insertions, 18 deletions
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 616d90bcb3a..d5dc9da7f99 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)  	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,24 +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 (chn = 0; chn < tot_channels; chn++) { -			csr = mci->csrows[chn]; -			if (csr) { -				for (chn = 0; chn < tot_channels; chn++) -					kfree(csr->channels[chn]); -				kfree(csr); -			} -			kfree(mci->csrows[i]); -		} -		kfree(mci->csrows); -	} -	kfree(mci); +	_edac_mc_free(mci);  	return NULL;  } @@ -445,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);  }  |