drivers/irqchip/irq-mips-gic.c

Source file repositories/reference/linux-study-clean/drivers/irqchip/irq-mips-gic.c

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-mips-gic.c
Extension
.c
Size
26007 bytes
Lines
1018
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.

Dependency Surface

Detected Declarations

Annotated Snippet

if (gic_irq_lock_cluster(d)) {
			write_gic_redir_map_vp(irq, 0);
			mips_cm_unlock_other();
		} else {
			write_gic_map_vp(irq, 0);
		}
	}

	/*
	 * Update effective affinity - after this gic_irq_lock_cluster() will
	 * begin operating on the new cluster.
	 */
	irq_data_update_effective_affinity(d, cpumask_of(cpu));

	/*
	 * If we're moving affinity between clusters, configure the interrupt
	 * trigger type in the new cluster.
	 */
	if (cl != old_cl)
		gic_set_type(d, irqd_get_trigger_type(d));

	/* Route the interrupt to its new VP(E) */
	if (gic_irq_lock_cluster(d)) {
		write_gic_redir_map_pin(irq,
					GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin);
		write_gic_redir_map_vp(irq, BIT(mips_cm_vp_id(cpu)));

		/* Update the pcpu_masks */
		gic_clear_pcpu_masks(irq);
		if (read_gic_redir_mask(irq))
			set_bit(irq, per_cpu_ptr(pcpu_masks, cpu));

		mips_cm_unlock_other();
	} else {
		write_gic_map_pin(irq, GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin);
		write_gic_map_vp(irq, BIT(mips_cm_vp_id(cpu)));

		/* Update the pcpu_masks */
		gic_clear_pcpu_masks(irq);
		if (read_gic_mask(irq))
			set_bit(irq, per_cpu_ptr(pcpu_masks, cpu));
	}

	raw_spin_unlock_irqrestore(&gic_lock, flags);

	return IRQ_SET_MASK_OK;
}
#endif

static struct irq_chip gic_level_irq_controller = {
	.name			=	"MIPS GIC",
	.irq_mask		=	gic_mask_irq,
	.irq_unmask		=	gic_unmask_irq,
	.irq_set_type		=	gic_set_type,
#ifdef CONFIG_SMP
	.irq_set_affinity	=	gic_set_affinity,
#endif
};

static struct irq_chip gic_edge_irq_controller = {
	.name			=	"MIPS GIC",
	.irq_ack		=	gic_ack_irq,
	.irq_mask		=	gic_mask_irq,
	.irq_unmask		=	gic_unmask_irq,
	.irq_set_type		=	gic_set_type,
#ifdef CONFIG_SMP
	.irq_set_affinity	=	gic_set_affinity,
#endif
	.ipi_send_single	=	gic_send_ipi,
};

static void gic_handle_local_int(bool chained)
{
	unsigned long pending, masked;
	unsigned int intr;

	pending = read_gic_vl_pend();
	masked = read_gic_vl_mask();

	bitmap_and(&pending, &pending, &masked, GIC_NUM_LOCAL_INTRS);

	for_each_set_bit(intr, &pending, GIC_NUM_LOCAL_INTRS) {
		if (chained)
			generic_handle_domain_irq(gic_irq_domain,
						  GIC_LOCAL_TO_HWIRQ(intr));
		else
			do_domain_IRQ(gic_irq_domain,
				      GIC_LOCAL_TO_HWIRQ(intr));
	}
}

Annotation

Implementation Notes