drivers/edac/edac_mc.c
Source file repositories/reference/linux-study-clean/drivers/edac/edac_mc.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/edac/edac_mc.c- Extension
.c- Size
- 26430 bytes
- Lines
- 1088
- Domain
- Driver Families
- Bucket
- drivers/edac
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/module.hlinux/proc_fs.hlinux/kernel.hlinux/types.hlinux/smp.hlinux/init.hlinux/sysctl.hlinux/highmem.hlinux/timer.hlinux/slab.hlinux/jiffies.hlinux/spinlock.hlinux/list.hlinux/ctype.hlinux/edac.hlinux/bitops.hlinux/uaccess.hasm/page.hedac_mc.hedac_module.hras/ras_event.hasm/edac.h
Detected Declarations
function edac_dimm_info_locationfunction edac_mc_dump_channelfunction edac_mc_dump_dimmfunction edac_mc_dump_csrowfunction edac_mc_dump_mcifunction _edac_mc_freefunction mci_releasefunction edac_mc_alloc_csrowsfunction edac_mc_alloc_dimmsfunction edac_mc_freefunction edac_has_mcsfunction list_for_eachfunction edac_mc_workq_functionfunction edac_mc_reset_delay_periodfunction list_for_eachfunction add_mc_to_global_listfunction list_for_eachfunction del_mc_from_global_listfunction list_for_eachfunction edac_mc_add_mc_with_groupsfunction edac_mc_scrub_blockfunction edac_mc_find_csrow_by_pagefunction edac_inc_ce_errorfunction edac_inc_ue_errorfunction edac_ce_errorfunction edac_ue_errorfunction edac_inc_csrowfunction edac_raw_mc_handle_errorfunction edac_mc_handle_errorfunction mci_for_each_dimmexport edac_op_stateexport edac_mem_typesexport edac_mc_allocexport edac_mc_freeexport edac_has_mcsexport find_mci_by_devexport edac_mc_findexport edac_get_ownerexport edac_mc_add_mc_with_groupsexport edac_mc_del_mcexport edac_mc_find_csrow_by_pageexport edac_layer_nameexport edac_raw_mc_handle_errorexport edac_mc_handle_error
Annotated Snippet
if (csr->channels) {
for (chn = 0; chn < mci->num_cschannel; chn++)
kfree(csr->channels[chn]);
kfree(csr->channels);
}
kfree(csr);
}
kfree(mci->csrows);
}
kfree(mci->pvt_info);
kfree(mci);
}
static int edac_mc_alloc_csrows(struct mem_ctl_info *mci)
{
unsigned int tot_channels = mci->num_cschannel;
unsigned int tot_csrows = mci->nr_csrows;
unsigned int row, chn;
/*
* Allocate and fill the csrow/channels structs
*/
mci->csrows = kzalloc_objs(*mci->csrows, tot_csrows);
if (!mci->csrows)
return -ENOMEM;
for (row = 0; row < tot_csrows; row++) {
struct csrow_info *csr;
csr = kzalloc_obj(**mci->csrows);
if (!csr)
return -ENOMEM;
mci->csrows[row] = csr;
csr->csrow_idx = row;
csr->mci = mci;
csr->nr_channels = tot_channels;
csr->channels = kzalloc_objs(*csr->channels, tot_channels);
if (!csr->channels)
return -ENOMEM;
for (chn = 0; chn < tot_channels; chn++) {
struct rank_info *chan;
chan = kzalloc_obj(**csr->channels);
if (!chan)
return -ENOMEM;
csr->channels[chn] = chan;
chan->chan_idx = chn;
chan->csrow = csr;
}
}
return 0;
}
static int edac_mc_alloc_dimms(struct mem_ctl_info *mci)
{
unsigned int pos[EDAC_MAX_LAYERS];
unsigned int row, chn, idx;
int layer;
void *p;
/*
* Allocate and fill the dimm structs
*/
mci->dimms = kzalloc_objs(*mci->dimms, mci->tot_dimms);
if (!mci->dimms)
return -ENOMEM;
memset(&pos, 0, sizeof(pos));
row = 0;
chn = 0;
for (idx = 0; idx < mci->tot_dimms; idx++) {
struct dimm_info *dimm;
struct rank_info *chan;
int n, len;
chan = mci->csrows[row]->channels[chn];
dimm = kzalloc_obj(**mci->dimms);
if (!dimm)
return -ENOMEM;
mci->dimms[idx] = dimm;
dimm->mci = mci;
dimm->idx = idx;
/*
* Copy DIMM location and initialize it.
Annotation
- Immediate include surface: `linux/module.h`, `linux/proc_fs.h`, `linux/kernel.h`, `linux/types.h`, `linux/smp.h`, `linux/init.h`, `linux/sysctl.h`, `linux/highmem.h`.
- Detected declarations: `function edac_dimm_info_location`, `function edac_mc_dump_channel`, `function edac_mc_dump_dimm`, `function edac_mc_dump_csrow`, `function edac_mc_dump_mci`, `function _edac_mc_free`, `function mci_release`, `function edac_mc_alloc_csrows`, `function edac_mc_alloc_dimms`, `function edac_mc_free`.
- Atlas domain: Driver Families / drivers/edac.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.