arch/mips/sgi-ip30/ip30-irq.c

Source file repositories/reference/linux-study-clean/arch/mips/sgi-ip30/ip30-irq.c

File Facts

System
Linux kernel
Corpus path
arch/mips/sgi-ip30/ip30-irq.c
Extension
.c
Size
8931 bytes
Lines
331
Domain
Architecture Layer
Bucket
arch/mips
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct heart_irq_data {
	u64	*irq_mask;
	int	cpu;
};

static DECLARE_BITMAP(heart_irq_map, HEART_NUM_IRQS);

static DEFINE_PER_CPU(unsigned long, irq_enable_mask);

static inline int heart_alloc_int(void)
{
	int bit;

again:
	bit = find_first_zero_bit(heart_irq_map, HEART_NUM_IRQS);
	if (bit >= HEART_NUM_IRQS)
		return -ENOSPC;

	if (test_and_set_bit(bit, heart_irq_map))
		goto again;

	return bit;
}

static void ip30_error_irq(struct irq_desc *desc)
{
	u64 pending, mask, cause, error_irqs, err_reg;
	int cpu = smp_processor_id();
	int i;

	pending = heart_read(&heart_regs->isr);
	mask = heart_read(&heart_regs->imr[cpu]);
	cause = heart_read(&heart_regs->cause);
	error_irqs = (pending & HEART_L4_INT_MASK & mask);

	/* Bail if there's nothing to process (how did we get here, then?) */
	if (unlikely(!error_irqs))
		return;

	/* Prevent any of the error IRQs from firing again. */
	heart_write(mask & ~(pending), &heart_regs->imr[cpu]);

	/* Ack all error IRQs. */
	heart_write(HEART_L4_INT_MASK, &heart_regs->clear_isr);

	/*
	 * If we also have a cause value, then something happened, so loop
	 * through the error IRQs and report a "heart attack" for each one
	 * and print the value of the HEART cause register.  This is really
	 * primitive right now, but it should hopefully work until a more
	 * robust error handling routine can be put together.
	 *
	 * Refer to heart.h for the HC_* macros to work out the cause
	 * that got us here.
	 */
	if (cause) {
		pr_alert("IP30: CPU%d: HEART ATTACK! ISR = 0x%.16llx, IMR = 0x%.16llx, CAUSE = 0x%.16llx\n",
			 cpu, pending, mask, cause);

		if (cause & HC_COR_MEM_ERR) {
			err_reg = heart_read(&heart_regs->mem_err_addr);
			pr_alert("  HEART_MEMERR_ADDR = 0x%.16llx\n", err_reg);
		}

		/* i = 63; i >= 51; i-- */
		for (i = HEART_ERR_MASK_END; i >= HEART_ERR_MASK_START; i--)
			if ((pending >> i) & 1)
				pr_alert("  HEART Error IRQ #%d\n", i);

		/* XXX: Seems possible to loop forever here, so panic(). */
		panic("IP30: Fatal Error !\n");
	}

	/* Unmask the error IRQs. */
	heart_write(mask, &heart_regs->imr[cpu]);
}

static void ip30_normal_irq(struct irq_desc *desc)
{
	int cpu = smp_processor_id();
	struct irq_domain *domain;
	u64 pend, mask;
	int ret;

	pend = heart_read(&heart_regs->isr);
	mask = (heart_read(&heart_regs->imr[cpu]) &
		(HEART_L0_INT_MASK | HEART_L1_INT_MASK | HEART_L2_INT_MASK));

	pend &= mask;
	if (unlikely(!pend))

Annotation

Implementation Notes