drivers/irqchip/irq-econet-en751221.c
Source file repositories/reference/linux-study-clean/drivers/irqchip/irq-econet-en751221.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/irqchip/irq-econet-en751221.c- Extension
.c- Size
- 13552 bytes
- Lines
- 481
- Domain
- Driver Families
- Bucket
- drivers/irqchip
- 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.
- 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/cleanup.hlinux/io.hlinux/of.hlinux/of_address.hlinux/of_irq.hlinux/irqdomain.hlinux/irqchip.hlinux/irqchip/chained_irq.hasm/setup.h
Detected Declarations
function econet_wregfunction econet_chmaskfunction econet_intc_maskfunction econet_intc_unmaskfunction econet_mask_allfunction econet_intc_handle_pendingfunction econet_intc_from_parentfunction econet_cpu_dispatch0function econet_cpu_dispatch1function econet_intc_mapfunction get_shadow_interruptsfunction econet_cpu_initfunction econet_intc_of_initfunction Manual
Annotated Snippet
if (shadow > IRQ_COUNT) {
pr_err("%pOF: %s[%d] shadow(%d) out of range\n",
node, field, i + 1, shadow);
continue;
}
if (target >= IRQ_COUNT) {
pr_err("%pOF: %s[%d] target(%d) out of range\n", node, field, i, target);
continue;
}
if (econet_intc.interrupt_shadows[target] != NOT_PERCPU) {
pr_err("%pOF: %s[%d] target(%d) already has a shadow\n",
node, field, i, target);
continue;
}
if (econet_intc.interrupt_shadows[shadow] != NOT_PERCPU) {
pr_err("%pOF: %s[%d] shadow(%d) already has a target\n",
node, field, i + 1, shadow);
continue;
}
econet_intc.interrupt_shadows[target] = shadow;
econet_intc.interrupt_shadows[shadow] = IS_SHADOW;
}
return 0;
}
/**
* econet_cpu_init() - configure routing of CPU interrupts to the correct domain.
* @node: The devicetree node of this interrupt controller.
*
* Interrupts that originate from the CPU are unconditionally unmasked here and are re-routed back
* to the IPI irq_domain in the CPU intc. Masking still takes place but the CPU intc is in charge
* of it, using the mask bits of the c0_status register.
*
* Note that because IP2 ... IP7 are repurposed as Interrupt Priority Level, only the two IPI
* interrupts are actually supported.
*/
static int __init econet_cpu_init(struct device_node *node)
{
const char *field = "econet,cpu-interrupt-map";
struct device_node *parent_intc;
int map_size;
u32 mask;
map_size = of_property_count_u32_elems(node, field);
if (map_size <= 0) {
return 0;
} else if (map_size % 2) {
pr_err("%pOF: %s count is odd, ignoring\n", node, field);
return 0;
}
u32 *maps __free(kfree) = kmalloc_array(map_size, sizeof(u32), GFP_KERNEL);
if (!maps)
return -ENOMEM;
if (of_property_read_u32_array(node, field, maps, map_size)) {
pr_err("%pOF: Failed to read %s\n", node, field);
return -EINVAL;
}
/* Validation */
for (int i = 0; i < map_size; i += 2) {
u32 receive = maps[i];
u32 dispatch = maps[i + 1];
u8 shadow;
if (receive >= IRQ_COUNT) {
pr_err("%pOF: Entry %d:%d in %s (%u) is out of bounds\n",
node, i, 0, field, receive);
return -EINVAL;
}
shadow = econet_intc.interrupt_shadows[receive];
if (shadow != NOT_PERCPU && shadow >= IRQ_COUNT) {
pr_err("%pOF: Entry %d:%d in %s (%u) has invalid shadow (%d)\n",
node, i, 0, field, receive, shadow);
return -EINVAL;
}
if (dispatch >= ARRAY_SIZE(econet_cpu_dispatchers)) {
pr_err("%pOF: Entry %d:%d in %s (%u) is out of bounds only IPI interrupts are supported\n",
node, i, 1, field, dispatch);
return -EINVAL;
}
Annotation
- Immediate include surface: `linux/cleanup.h`, `linux/io.h`, `linux/of.h`, `linux/of_address.h`, `linux/of_irq.h`, `linux/irqdomain.h`, `linux/irqchip.h`, `linux/irqchip/chained_irq.h`.
- Detected declarations: `function econet_wreg`, `function econet_chmask`, `function econet_intc_mask`, `function econet_intc_unmask`, `function econet_mask_all`, `function econet_intc_handle_pending`, `function econet_intc_from_parent`, `function econet_cpu_dispatch0`, `function econet_cpu_dispatch1`, `function econet_intc_map`.
- Atlas domain: Driver Families / drivers/irqchip.
- Implementation status: source implementation candidate.
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.