arch/powerpc/sysdev/xics/ics-native.c

Source file repositories/reference/linux-study-clean/arch/powerpc/sysdev/xics/ics-native.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/sysdev/xics/ics-native.c
Extension
.c
Size
6156 bytes
Lines
255
Domain
Architecture Layer
Bucket
arch/powerpc
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 ics_native {
	struct ics		ics;
	struct device_node	*node;
	void __iomem    	*base;
	u32             	ibase;
	u32             	icount;
};
#define to_ics_native(_ics)     container_of(_ics, struct ics_native, ics)

static void __iomem *ics_native_xive(struct ics_native *in, unsigned int vec)
{
	return in->base + 0x800 + ((vec - in->ibase) << 2);
}

static void ics_native_unmask_irq(struct irq_data *d)
{
	unsigned int vec = (unsigned int)irqd_to_hwirq(d);
	struct ics *ics = irq_data_get_irq_chip_data(d);
	struct ics_native *in = to_ics_native(ics);
	unsigned int server;

	pr_devel("ics-native: unmask virq %d [hw 0x%x]\n", d->irq, vec);

	if (vec < in->ibase || vec >= (in->ibase + in->icount))
		return;

	server = xics_get_irq_server(d->irq, irq_data_get_affinity_mask(d), 0);
	out_be32(ics_native_xive(in, vec), (server << 8) | DEFAULT_PRIORITY);
}

static unsigned int ics_native_startup(struct irq_data *d)
{
#ifdef CONFIG_PCI_MSI
	/*
	 * The generic MSI code returns with the interrupt disabled on the
	 * card, using the MSI mask bits. Firmware doesn't appear to unmask
	 * at that level, so we do it here by hand.
	 */
	if (irq_data_get_msi_desc(d))
		pci_msi_unmask_irq(d);
#endif

	/* unmask it */
	ics_native_unmask_irq(d);
	return 0;
}

static void ics_native_do_mask(struct ics_native *in, unsigned int vec)
{
	out_be32(ics_native_xive(in, vec), 0xff);
}

static void ics_native_mask_irq(struct irq_data *d)
{
	unsigned int vec = (unsigned int)irqd_to_hwirq(d);
	struct ics *ics = irq_data_get_irq_chip_data(d);
	struct ics_native *in = to_ics_native(ics);

	pr_devel("ics-native: mask virq %d [hw 0x%x]\n", d->irq, vec);

	if (vec < in->ibase || vec >= (in->ibase + in->icount))
		return;
	ics_native_do_mask(in, vec);
}

static int ics_native_set_affinity(struct irq_data *d,
				   const struct cpumask *cpumask,
				   bool force)
{
	unsigned int vec = (unsigned int)irqd_to_hwirq(d);
	struct ics *ics = irq_data_get_irq_chip_data(d);
	struct ics_native *in = to_ics_native(ics);
	int server;
	u32 xive;

	if (vec < in->ibase || vec >= (in->ibase + in->icount))
		return -EINVAL;

	server = xics_get_irq_server(d->irq, cpumask, 1);
	if (server == -1) {
		pr_warn("%s: No online cpus in the mask %*pb for irq %d\n",
			__func__, cpumask_pr_args(cpumask), d->irq);
		return -1;
	}

	xive = in_be32(ics_native_xive(in, vec));
	xive = (xive & 0xff) | (server << 8);
	out_be32(ics_native_xive(in, vec), xive);

	return IRQ_SET_MASK_OK;

Annotation

Implementation Notes