Introduce bus_bind_intr method for ARM64
It can be used to bind specific interrupt to a particular CPU. Requires PIC support for interrupts binding. Reviewed by: wma Obtained from: Semihalf Sponsored by: Cavium Differential Revision: https://reviews.freebsd.org/D5122
This commit is contained in:
parent
45b4fa372e
commit
95137856d1
@ -38,6 +38,7 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
@ -84,6 +85,7 @@ struct arm64_intr_entry {
|
||||
u_int i_hw_irq; /* Physical interrupt number */
|
||||
u_int i_cntidx; /* Index in intrcnt table */
|
||||
u_int i_handlers; /* Allocated handlers */
|
||||
u_int i_cpu; /* Assigned CPU */
|
||||
u_long *i_cntp; /* Interrupt hit counter */
|
||||
};
|
||||
|
||||
@ -162,6 +164,8 @@ intr_allocate(u_int hw_irq)
|
||||
if (intr == NULL)
|
||||
return (NULL);
|
||||
|
||||
/* The default CPU is 0 but can be changed later by bind or shuffle */
|
||||
intr->i_cpu = 0;
|
||||
intr->i_event = NULL;
|
||||
intr->i_handlers = 0;
|
||||
intr->i_trig = INTR_TRIGGER_CONFORM;
|
||||
@ -176,6 +180,44 @@ intr_allocate(u_int hw_irq)
|
||||
return intr;
|
||||
}
|
||||
|
||||
static int
|
||||
intr_assign_cpu(void *arg, int cpu)
|
||||
{
|
||||
#ifdef SMP
|
||||
struct arm64_intr_entry *intr;
|
||||
int error;
|
||||
|
||||
if (root_pic == NULL)
|
||||
panic("Cannot assing interrupt to CPU. No PIC configured");
|
||||
/*
|
||||
* Set the interrupt to CPU affinity.
|
||||
* Do not configure this in hardware during early boot.
|
||||
* We will pick up the assignment once the APs are started.
|
||||
*/
|
||||
if (cpu != NOCPU) {
|
||||
intr = arg;
|
||||
if (!cold && smp_started) {
|
||||
/*
|
||||
* Bind the interrupt immediately
|
||||
* if SMP is up and running.
|
||||
*/
|
||||
error = PIC_BIND(root_pic, intr->i_hw_irq, cpu);
|
||||
if (error == 0)
|
||||
intr->i_cpu = cpu;
|
||||
} else {
|
||||
/* Postpone binding until SMP is operational */
|
||||
intr->i_cpu = cpu;
|
||||
error = 0;
|
||||
}
|
||||
} else
|
||||
error = 0;
|
||||
|
||||
return (error);
|
||||
#else
|
||||
return (EOPNOTSUPP);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
intr_pre_ithread(void *arg)
|
||||
{
|
||||
@ -339,7 +381,7 @@ arm_setup_intr(const char *name, driver_filter_t *filt, driver_intr_t handler,
|
||||
if (intr->i_event == NULL) {
|
||||
error = intr_event_create(&intr->i_event, (void *)intr, 0,
|
||||
hw_irq, intr_pre_ithread, intr_post_ithread,
|
||||
intr_post_filter, NULL, "irq%u", hw_irq);
|
||||
intr_post_filter, intr_assign_cpu, "irq%u", hw_irq);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
@ -447,6 +489,42 @@ arm_cpu_intr(struct trapframe *tf)
|
||||
}
|
||||
|
||||
#ifdef SMP
|
||||
static void
|
||||
arm_intr_smp_init(void *dummy __unused)
|
||||
{
|
||||
struct arm64_intr_entry *intr;
|
||||
int error;
|
||||
|
||||
if (root_pic == NULL)
|
||||
panic("Cannot assing interrupts to CPUs. No PIC configured");
|
||||
|
||||
mtx_lock_spin(&intr_list_lock);
|
||||
SLIST_FOREACH(intr, &irq_slist_head, entries) {
|
||||
mtx_unlock_spin(&intr_list_lock);
|
||||
error = PIC_BIND(root_pic, intr->i_hw_irq, intr->i_cpu);
|
||||
if (error != 0)
|
||||
intr->i_cpu = 0;
|
||||
mtx_lock_spin(&intr_list_lock);
|
||||
}
|
||||
mtx_unlock_spin(&intr_list_lock);
|
||||
}
|
||||
SYSINIT(arm_intr_smp_init, SI_SUB_SMP, SI_ORDER_ANY, arm_intr_smp_init, NULL);
|
||||
|
||||
/* Attempt to bind the specified IRQ to the specified CPU. */
|
||||
int
|
||||
arm_intr_bind(u_int hw_irq, int cpu)
|
||||
{
|
||||
struct arm64_intr_entry *intr;
|
||||
|
||||
mtx_lock_spin(&intr_list_lock);
|
||||
intr = intr_lookup_locked(hw_irq);
|
||||
mtx_unlock_spin(&intr_list_lock);
|
||||
if (intr == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
return (intr_event_bind(intr->i_event, cpu));
|
||||
}
|
||||
|
||||
void
|
||||
arm_setup_ipihandler(driver_filter_t *filt, u_int ipi)
|
||||
{
|
||||
|
@ -113,6 +113,9 @@ static int nexus_deactivate_resource(device_t, device_t, int, int,
|
||||
static int nexus_setup_intr(device_t dev, device_t child, struct resource *res,
|
||||
int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep);
|
||||
static int nexus_teardown_intr(device_t, device_t, struct resource *, void *);
|
||||
#ifdef SMP
|
||||
static int nexus_bind_intr(device_t, device_t, struct resource *, int);
|
||||
#endif
|
||||
|
||||
#ifdef FDT
|
||||
static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent,
|
||||
@ -131,7 +134,9 @@ static device_method_t nexus_methods[] = {
|
||||
DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource),
|
||||
DEVMETHOD(bus_setup_intr, nexus_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
|
||||
|
||||
#ifdef SMP
|
||||
DEVMETHOD(bus_bind_intr, nexus_bind_intr),
|
||||
#endif
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@ -293,6 +298,15 @@ nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
|
||||
return (arm_teardown_intr(ih));
|
||||
}
|
||||
|
||||
#ifdef SMP
|
||||
static int
|
||||
nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu)
|
||||
{
|
||||
|
||||
return (arm_intr_bind(rman_get_start(irq), cpu));
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
nexus_activate_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
|
@ -34,7 +34,11 @@
|
||||
INTERFACE pic;
|
||||
|
||||
CODE {
|
||||
static pic_translate_code_t pic_translate_code_default;
|
||||
static int pic_bind_default(device_t dev, u_int irq, u_int cpu)
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static void pic_translate_code_default(device_t dev, u_int irq,
|
||||
int code, enum intr_trigger *trig, enum intr_polarity *pol)
|
||||
@ -60,11 +64,11 @@ CODE {
|
||||
}
|
||||
};
|
||||
|
||||
METHOD void bind {
|
||||
METHOD int bind {
|
||||
device_t dev;
|
||||
u_int irq;
|
||||
cpuset_t cpumask;
|
||||
};
|
||||
u_int cpu;
|
||||
} DEFAULT pic_bind_default;
|
||||
|
||||
METHOD void translate_code {
|
||||
device_t dev;
|
||||
|
@ -49,6 +49,7 @@ void arm_unmask_irq(u_int);
|
||||
|
||||
#ifdef SMP
|
||||
void arm_init_secondary(void);
|
||||
int arm_intr_bind(u_int, int);
|
||||
void arm_setup_ipihandler(driver_filter_t *, u_int);
|
||||
void arm_unmask_ipi(u_int);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user