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

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

File Facts

System
Linux kernel
Corpus path
arch/mips/sgi-ip27/ip27-irq.c
Extension
.c
Size
7554 bytes
Lines
309
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 hub_irq_data {
	u64	*irq_mask[2];
	cpuid_t	cpu;
};

static DECLARE_BITMAP(hub_irq_map, IP27_HUB_IRQ_COUNT);

static DEFINE_PER_CPU(unsigned long [2], irq_enable_mask);

static inline int alloc_level(void)
{
	int level;

again:
	level = find_first_zero_bit(hub_irq_map, IP27_HUB_IRQ_COUNT);
	if (level >= IP27_HUB_IRQ_COUNT)
		return -ENOSPC;

	if (test_and_set_bit(level, hub_irq_map))
		goto again;

	return level;
}

static void enable_hub_irq(struct irq_data *d)
{
	struct hub_irq_data *hd = irq_data_get_irq_chip_data(d);
	unsigned long *mask = per_cpu(irq_enable_mask, hd->cpu);

	set_bit(d->hwirq, mask);
	__raw_writeq(mask[0], hd->irq_mask[0]);
	__raw_writeq(mask[1], hd->irq_mask[1]);
}

static void disable_hub_irq(struct irq_data *d)
{
	struct hub_irq_data *hd = irq_data_get_irq_chip_data(d);
	unsigned long *mask = per_cpu(irq_enable_mask, hd->cpu);

	clear_bit(d->hwirq, mask);
	__raw_writeq(mask[0], hd->irq_mask[0]);
	__raw_writeq(mask[1], hd->irq_mask[1]);
}

static void setup_hub_mask(struct hub_irq_data *hd, const struct cpumask *mask)
{
	nasid_t nasid;
	int cpu;

	cpu = cpumask_first_and(mask, cpu_online_mask);
	if (cpu >= nr_cpu_ids)
		cpu = cpumask_any(cpu_online_mask);

	nasid = cpu_to_node(cpu);
	hd->cpu = cpu;
	if (!cputoslice(cpu)) {
		hd->irq_mask[0] = REMOTE_HUB_PTR(nasid, PI_INT_MASK0_A);
		hd->irq_mask[1] = REMOTE_HUB_PTR(nasid, PI_INT_MASK1_A);
	} else {
		hd->irq_mask[0] = REMOTE_HUB_PTR(nasid, PI_INT_MASK0_B);
		hd->irq_mask[1] = REMOTE_HUB_PTR(nasid, PI_INT_MASK1_B);
	}
}

static int set_affinity_hub_irq(struct irq_data *d, const struct cpumask *mask,
				bool force)
{
	struct hub_irq_data *hd = irq_data_get_irq_chip_data(d);

	if (!hd)
		return -EINVAL;

	if (irqd_is_started(d))
		disable_hub_irq(d);

	setup_hub_mask(hd, mask);

	if (irqd_is_started(d))
		enable_hub_irq(d);

	irq_data_update_effective_affinity(d, cpumask_of(hd->cpu));

	return 0;
}

static struct irq_chip hub_irq_type = {
	.name		  = "HUB",
	.irq_mask	  = disable_hub_irq,
	.irq_unmask	  = enable_hub_irq,
	.irq_set_affinity = set_affinity_hub_irq,

Annotation

Implementation Notes