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

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

File Facts

System
Linux kernel
Corpus path
arch/powerpc/sysdev/xics/ics-opal.c
Extension
.c
Size
5178 bytes
Lines
222
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

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * ICS backend for OPAL managed interrupts.
 *
 * Copyright 2011 IBM Corp.
 */

#undef DEBUG

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/smp.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/cpu.h>
#include <linux/of.h>
#include <linux/spinlock.h>
#include <linux/msi.h>

#include <asm/smp.h>
#include <asm/machdep.h>
#include <asm/irq.h>
#include <asm/errno.h>
#include <asm/xics.h>
#include <asm/opal.h>
#include <asm/firmware.h>

static int ics_opal_mangle_server(int server)
{
	/* No link for now */
	return server << 2;
}

static int ics_opal_unmangle_server(int server)
{
	/* No link for now */
	return server >> 2;
}

static void ics_opal_unmask_irq(struct irq_data *d)
{
	unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
	int64_t rc;
	int server;

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

	if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
		return;

	server = xics_get_irq_server(d->irq, irq_data_get_affinity_mask(d), 0);
	server = ics_opal_mangle_server(server);

	rc = opal_set_xive(hw_irq, server, DEFAULT_PRIORITY);
	if (rc != OPAL_SUCCESS)
		pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)"
		       " error %lld\n",
		       __func__, d->irq, hw_irq, server, rc);
}

static unsigned int ics_opal_startup(struct irq_data *d)
{
	ics_opal_unmask_irq(d);
	return 0;
}

static void ics_opal_mask_real_irq(unsigned int hw_irq)
{
	int server = ics_opal_mangle_server(xics_default_server);
	int64_t rc;

	if (hw_irq == XICS_IPI)
		return;

	/* Have to set XIVE to 0xff to be able to remove a slot */
	rc = opal_set_xive(hw_irq, server, 0xff);
	if (rc != OPAL_SUCCESS)
		pr_err("%s: opal_set_xive(0xff) irq=%u returned %lld\n",
		       __func__, hw_irq, rc);
}

static void ics_opal_mask_irq(struct irq_data *d)
{
	unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);

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

	if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
		return;

Annotation

Implementation Notes