drivers/edac/qcom_edac.c
Source file repositories/reference/linux-study-clean/drivers/edac/qcom_edac.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/edac/qcom_edac.c- Extension
.c- Size
- 11529 bytes
- Lines
- 420
- Domain
- Driver Families
- Bucket
- drivers/edac
- Inferred role
- Driver Families: implementation source
- Status
- source 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.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/edac.hlinux/interrupt.hlinux/kernel.hlinux/of.hlinux/platform_device.hlinux/regmap.hlinux/soc/qcom/llcc-qcom.hedac_mc.hedac_device.h
Detected Declarations
struct qcom_llcc_syn_regsfunction qcom_llcc_core_setupfunction qcom_llcc_clear_error_statusfunction get_reg_offsetsfunction dump_syn_reg_valuesfunction dump_syn_regfunction llcc_ecc_irq_handlerfunction llcc_ecc_checkfunction qcom_llcc_edac_probefunction qcom_llcc_edac_remove
Annotated Snippet
struct qcom_llcc_syn_regs {
u32 synd_reg;
u32 count_status_reg;
u32 ways_status_reg;
};
static void get_reg_offsets(struct llcc_drv_data *drv, int err_type,
struct qcom_llcc_syn_regs *syn_regs)
{
const struct llcc_edac_reg_offset *edac_reg_offset = drv->edac_reg_offset;
switch (err_type) {
case LLCC_DRAM_CE:
syn_regs->synd_reg = edac_reg_offset->drp_ecc_sb_err_syn0;
syn_regs->count_status_reg = edac_reg_offset->drp_ecc_error_status1;
syn_regs->ways_status_reg = edac_reg_offset->drp_ecc_error_status0;
break;
case LLCC_DRAM_UE:
syn_regs->synd_reg = edac_reg_offset->drp_ecc_db_err_syn0;
syn_regs->count_status_reg = edac_reg_offset->drp_ecc_error_status1;
syn_regs->ways_status_reg = edac_reg_offset->drp_ecc_error_status0;
break;
case LLCC_TRAM_CE:
syn_regs->synd_reg = edac_reg_offset->trp_ecc_sb_err_syn0;
syn_regs->count_status_reg = edac_reg_offset->trp_ecc_error_status1;
syn_regs->ways_status_reg = edac_reg_offset->trp_ecc_error_status0;
break;
case LLCC_TRAM_UE:
syn_regs->synd_reg = edac_reg_offset->trp_ecc_db_err_syn0;
syn_regs->count_status_reg = edac_reg_offset->trp_ecc_error_status1;
syn_regs->ways_status_reg = edac_reg_offset->trp_ecc_error_status0;
break;
}
}
/* Dump Syndrome registers data for Tag RAM, Data RAM bit errors*/
static int
dump_syn_reg_values(struct llcc_drv_data *drv, u32 bank, int err_type)
{
struct llcc_edac_reg_data reg_data = edac_reg_data[err_type];
struct qcom_llcc_syn_regs regs = { };
int err_cnt, err_ways, ret, i;
u32 synd_reg, synd_val;
get_reg_offsets(drv, err_type, ®s);
for (i = 0; i < reg_data.reg_cnt; i++) {
synd_reg = regs.synd_reg + (i * 4);
ret = regmap_read(drv->regmaps[bank], synd_reg,
&synd_val);
if (ret)
goto clear;
edac_printk(KERN_CRIT, EDAC_LLCC, "%s: ECC_SYN%d: 0x%8x\n",
reg_data.name, i, synd_val);
}
ret = regmap_read(drv->regmaps[bank], regs.count_status_reg,
&err_cnt);
if (ret)
goto clear;
err_cnt &= reg_data.count_mask;
err_cnt >>= reg_data.count_shift;
edac_printk(KERN_CRIT, EDAC_LLCC, "%s: Error count: 0x%4x\n",
reg_data.name, err_cnt);
ret = regmap_read(drv->regmaps[bank], regs.ways_status_reg,
&err_ways);
if (ret)
goto clear;
err_ways &= reg_data.ways_mask;
err_ways >>= reg_data.ways_shift;
edac_printk(KERN_CRIT, EDAC_LLCC, "%s: Error ways: 0x%4x\n",
reg_data.name, err_ways);
clear:
return qcom_llcc_clear_error_status(err_type, drv);
}
static int
dump_syn_reg(struct edac_device_ctl_info *edev_ctl, int err_type, u32 bank)
{
struct llcc_drv_data *drv = edev_ctl->dev->platform_data;
int ret;
ret = dump_syn_reg_values(drv, bank, err_type);
if (ret)
Annotation
- Immediate include surface: `linux/edac.h`, `linux/interrupt.h`, `linux/kernel.h`, `linux/of.h`, `linux/platform_device.h`, `linux/regmap.h`, `linux/soc/qcom/llcc-qcom.h`, `edac_mc.h`.
- Detected declarations: `struct qcom_llcc_syn_regs`, `function qcom_llcc_core_setup`, `function qcom_llcc_clear_error_status`, `function get_reg_offsets`, `function dump_syn_reg_values`, `function dump_syn_reg`, `function llcc_ecc_irq_handler`, `function llcc_ecc_check`, `function qcom_llcc_edac_probe`, `function qcom_llcc_edac_remove`.
- Atlas domain: Driver Families / drivers/edac.
- Implementation status: source implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
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.