drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c
Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c- Extension
.c- Size
- 18773 bytes
- Lines
- 626
- Domain
- Driver Families
- Bucket
- drivers/gpu
- 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.
- 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/list.hamdgpu.hamdgpu_ras_mgr.h
Detected Declarations
function __inc_entry_lengthfunction amdgpu_cper_get_timestampfunction amdgpu_cper_entry_fill_hdrfunction amdgpu_cper_entry_fill_section_descfunction amdgpu_cper_entry_fill_fatal_sectionfunction amdgpu_cper_entry_fill_runtime_sectionfunction amdgpu_cper_entry_fill_bad_page_threshold_sectionfunction amdgpu_cper_generate_ue_recordfunction amdgpu_cper_generate_bp_threshold_recordfunction amdgpu_aca_err_type_to_cper_sevfunction amdgpu_cper_generate_ce_recordsfunction amdgpu_cper_is_hdrfunction amdgpu_cper_ring_get_ent_szfunction amdgpu_cper_ring_writefunction amdgpu_cper_ring_get_rptrfunction amdgpu_cper_ring_get_wptrfunction amdgpu_cper_ring_initfunction amdgpu_cper_initfunction amdgpu_cper_fini
Annotated Snippet
if (bank->aca_err_type == ACA_ERROR_TYPE_DEFERRED) {
sev = CPER_SEV_NON_FATAL_UNCORRECTED;
break;
}
}
amdgpu_cper_entry_fill_hdr(adev, corrected, AMDGPU_CPER_TYPE_RUNTIME, sev);
/* Combine CE and DE in cper record */
list_for_each_entry(node, &banks->list, node) {
bank = &node->bank;
reg_data[CPER_ACA_REG_CTL_LO] = lower_32_bits(bank->regs[ACA_REG_IDX_CTL]);
reg_data[CPER_ACA_REG_CTL_HI] = upper_32_bits(bank->regs[ACA_REG_IDX_CTL]);
reg_data[CPER_ACA_REG_STATUS_LO] = lower_32_bits(bank->regs[ACA_REG_IDX_STATUS]);
reg_data[CPER_ACA_REG_STATUS_HI] = upper_32_bits(bank->regs[ACA_REG_IDX_STATUS]);
reg_data[CPER_ACA_REG_ADDR_LO] = lower_32_bits(bank->regs[ACA_REG_IDX_ADDR]);
reg_data[CPER_ACA_REG_ADDR_HI] = upper_32_bits(bank->regs[ACA_REG_IDX_ADDR]);
reg_data[CPER_ACA_REG_MISC0_LO] = lower_32_bits(bank->regs[ACA_REG_IDX_MISC0]);
reg_data[CPER_ACA_REG_MISC0_HI] = upper_32_bits(bank->regs[ACA_REG_IDX_MISC0]);
reg_data[CPER_ACA_REG_CONFIG_LO] = lower_32_bits(bank->regs[ACA_REG_IDX_CONFIG]);
reg_data[CPER_ACA_REG_CONFIG_HI] = upper_32_bits(bank->regs[ACA_REG_IDX_CONFIG]);
reg_data[CPER_ACA_REG_IPID_LO] = lower_32_bits(bank->regs[ACA_REG_IDX_IPID]);
reg_data[CPER_ACA_REG_IPID_HI] = upper_32_bits(bank->regs[ACA_REG_IDX_IPID]);
reg_data[CPER_ACA_REG_SYND_LO] = lower_32_bits(bank->regs[ACA_REG_IDX_SYND]);
reg_data[CPER_ACA_REG_SYND_HI] = upper_32_bits(bank->regs[ACA_REG_IDX_SYND]);
ret = amdgpu_cper_entry_fill_runtime_section(adev, corrected, i++,
amdgpu_aca_err_type_to_cper_sev(adev, bank->aca_err_type),
reg_data, CPER_ACA_REG_COUNT);
if (ret)
return ret;
}
amdgpu_cper_ring_write(ring, corrected, corrected->record_length);
kfree(corrected);
return 0;
}
static bool amdgpu_cper_is_hdr(struct amdgpu_ring *ring, u64 pos)
{
char signature[CPER_SIGNATURE_SZ];
if ((pos << 2) >= ring->ring_size)
return false;
if ((pos << 2) + CPER_SIGNATURE_SZ <= ring->ring_size) {
memcpy(signature, &ring->ring[pos], CPER_SIGNATURE_SZ);
} else {
u32 chunk = ring->ring_size - (pos << 2);
memcpy(signature, &ring->ring[pos], chunk);
memcpy(signature + chunk, ring->ring, CPER_SIGNATURE_SZ - chunk);
}
return !memcmp(signature, "CPER", CPER_SIGNATURE_SZ);
}
static u32 amdgpu_cper_ring_get_ent_sz(struct amdgpu_ring *ring, u64 pos)
{
struct cper_hdr chdr;
u64 p;
u32 chunk, rec_len = 0;
chunk = ring->ring_size - (pos << 2);
if (amdgpu_cper_is_hdr(ring, pos)) {
if (chunk >= sizeof(chdr)) {
memcpy(&chdr, &ring->ring[pos], sizeof(chdr));
} else {
memcpy(&chdr, &ring->ring[pos], chunk);
memcpy((u8 *)&chdr + chunk, ring->ring, sizeof(chdr) - chunk);
}
rec_len = chdr.record_length;
goto calc;
}
/* ring buffer is not full, no cper data after ring->wptr */
if (ring->count_dw)
goto calc;
for (p = pos + 1; p <= ring->buf_mask; p++) {
if (amdgpu_cper_is_hdr(ring, p)) {
rec_len = (p - pos) << 2;
goto calc;
}
}
calc:
Annotation
- Immediate include surface: `linux/list.h`, `amdgpu.h`, `amdgpu_ras_mgr.h`.
- Detected declarations: `function __inc_entry_length`, `function amdgpu_cper_get_timestamp`, `function amdgpu_cper_entry_fill_hdr`, `function amdgpu_cper_entry_fill_section_desc`, `function amdgpu_cper_entry_fill_fatal_section`, `function amdgpu_cper_entry_fill_runtime_section`, `function amdgpu_cper_entry_fill_bad_page_threshold_section`, `function amdgpu_cper_generate_ue_record`, `function amdgpu_cper_generate_bp_threshold_record`, `function amdgpu_aca_err_type_to_cper_sev`.
- Atlas domain: Driver Families / drivers/gpu.
- Implementation status: source 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.