mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-12-04 10:19:26 +00:00
- MFp4: modify slightly the arm intr API, there's arm CPUs with more than 32
interrupts. - Implement teardown methods where appropriate.
This commit is contained in:
parent
25029d6c31
commit
f60e923b23
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=147166
@ -54,21 +54,6 @@ static struct ithd *ithreads[NIRQ];
|
||||
static int intrcnt_tab[NIRQ];
|
||||
static int intrcnt_index = 0;
|
||||
static int last_printed = 0;
|
||||
struct arm_intr {
|
||||
driver_intr_t *handler;
|
||||
void *arg;
|
||||
void *cookiep;
|
||||
int irq;
|
||||
};
|
||||
|
||||
static void
|
||||
arm_intr_handler(void *arg)
|
||||
{
|
||||
struct arm_intr *intr = (struct arm_intr *)arg;
|
||||
|
||||
intr->handler(intr->arg);
|
||||
arm_unmask_irqs(1 << intr->irq);
|
||||
}
|
||||
|
||||
void arm_handler_execute(void *, int);
|
||||
|
||||
@ -77,17 +62,14 @@ arm_setup_irqhandler(const char *name, void (*hand)(void*), void *arg,
|
||||
int irq, int flags, void **cookiep)
|
||||
{
|
||||
struct ithd *cur_ith;
|
||||
struct arm_intr *intr = NULL;
|
||||
int error;
|
||||
|
||||
if (irq < 0 || irq >= NIRQ)
|
||||
return;
|
||||
if (!(flags & INTR_FAST))
|
||||
intr = malloc(sizeof(*intr), M_DEVBUF, M_WAITOK);
|
||||
cur_ith = ithreads[irq];
|
||||
if (cur_ith == NULL) {
|
||||
error = ithread_create(&cur_ith, irq, 0, NULL, NULL, "intr%d:",
|
||||
irq);
|
||||
error = ithread_create(&cur_ith, irq, 0, arm_mask_irq,
|
||||
arm_unmask_irq, "intr%d:", irq);
|
||||
if (error)
|
||||
return;
|
||||
ithreads[irq] = cur_ith;
|
||||
@ -100,16 +82,14 @@ arm_setup_irqhandler(const char *name, void (*hand)(void*), void *arg,
|
||||
intrcnt_index++;
|
||||
|
||||
}
|
||||
if (!(flags & INTR_FAST)) {
|
||||
intr->handler = hand;
|
||||
intr->arg = arg;
|
||||
intr->irq = irq;
|
||||
intr->cookiep = *cookiep;
|
||||
ithread_add_handler(cur_ith, name, arm_intr_handler, intr,
|
||||
ithread_priority(flags), flags, cookiep);
|
||||
} else
|
||||
ithread_add_handler(cur_ith, name, hand, arg,
|
||||
ithread_priority(flags), flags, cookiep);
|
||||
ithread_add_handler(cur_ith, name, hand, arg,
|
||||
ithread_priority(flags), flags, cookiep);
|
||||
}
|
||||
|
||||
int
|
||||
arm_remove_irqhandler(void *cookie)
|
||||
{
|
||||
return (ithread_remove_handler(cookie));
|
||||
}
|
||||
|
||||
void dosoftints(void);
|
||||
@ -127,13 +107,8 @@ arm_handler_execute(void *frame, int irqnb)
|
||||
struct thread *td = curthread;
|
||||
|
||||
td->td_intr_nesting_level++;
|
||||
if (irqnb == 0)
|
||||
irqnb = arm_get_irqnb(frame);
|
||||
while (irqnb != 0) {
|
||||
arm_mask_irqs(irqnb);
|
||||
i = ffs(irqnb) - 1;
|
||||
while ((i = arm_get_next_irq()) != -1) {
|
||||
intrcnt[intrcnt_tab[i]]++;
|
||||
irqnb &= ~(1U << i);
|
||||
ithd = ithreads[i];
|
||||
if (!ithd)
|
||||
continue;
|
||||
@ -144,10 +119,10 @@ arm_handler_execute(void *frame, int irqnb)
|
||||
ih->ih_handler(ih->ih_argument ?
|
||||
ih->ih_argument : frame);
|
||||
}
|
||||
arm_unmask_irqs(1 << i);
|
||||
} else if (ih)
|
||||
} else if (ih) {
|
||||
arm_mask_irq(i);
|
||||
ithread_schedule(ithd);
|
||||
irqnb |= arm_get_irqnb(frame);
|
||||
}
|
||||
}
|
||||
td->td_intr_nesting_level--;
|
||||
}
|
||||
|
@ -83,6 +83,9 @@ static int nexus_activate_resource(device_t, device_t, int, int,
|
||||
static int
|
||||
nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
|
||||
driver_intr_t *intr, void *arg, void **cookiep);
|
||||
static int
|
||||
nexus_teardown_intr(device_t, device_t, struct resource *, void *);
|
||||
|
||||
static device_method_t nexus_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, nexus_probe),
|
||||
@ -93,6 +96,7 @@ static device_method_t nexus_methods[] = {
|
||||
DEVMETHOD(bus_alloc_resource, nexus_alloc_resource),
|
||||
DEVMETHOD(bus_activate_resource, nexus_activate_resource),
|
||||
DEVMETHOD(bus_setup_intr, nexus_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@ -129,6 +133,15 @@ nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
|
||||
{
|
||||
int error;
|
||||
|
||||
arm_mask_irq(r->r_start);
|
||||
error = arm_remove_irqhandler(ih);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
nexus_attach(device_t dev)
|
||||
|
@ -47,10 +47,10 @@
|
||||
|
||||
#include <machine/psl.h>
|
||||
|
||||
int arm_get_irqnb(void *);
|
||||
void arm_mask_irqs(int);
|
||||
void arm_unmask_irqs(int);
|
||||
void set_splmasks(void);
|
||||
int arm_get_next_irq(void);
|
||||
void arm_mask_irq(uintptr_t);
|
||||
void arm_unmask_irq(uintptr_t);
|
||||
void arm_setup_irqhandler(const char *, void (*)(void*), void *, int, int,
|
||||
void **);
|
||||
int arm_remove_irqhandler(void *);
|
||||
#endif /* _MACHINE_INTR_H */
|
||||
|
@ -102,37 +102,35 @@ int current_intr_depth;
|
||||
extern struct sa11x0_softc *sa11x0_softc;
|
||||
|
||||
|
||||
/* Recalculate the interrupt masks from scratch.
|
||||
* We could code special registry and deregistry versions of this function that
|
||||
* would be faster, but the code would be nastier, and we don't expect this to
|
||||
* happen very much anyway.
|
||||
*/
|
||||
int
|
||||
arm_get_irqnb(void *frame)
|
||||
{
|
||||
struct sa11x0_softc *sc = sa11x0_softc;
|
||||
|
||||
return(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SAIPIC_IP));
|
||||
}
|
||||
|
||||
static uint32_t sa11x0_irq_mask = 0xfffffff;
|
||||
|
||||
extern vm_offset_t saipic_base;
|
||||
|
||||
int
|
||||
arm_get_next_irq()
|
||||
{
|
||||
int irq;
|
||||
|
||||
if ((irq = (bus_space_read_4(sc->sc_iot, sc->sc_ioh, SAIPIC_IP) &
|
||||
sa11x0_irq_mask)) != 0)
|
||||
return (ffs(irq) - 1);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
void
|
||||
arm_mask_irqs(int irq)
|
||||
arm_mask_irq(uintptr_t irq)
|
||||
{
|
||||
|
||||
sa11x0_irq_mask &= ~irq;
|
||||
sa11x0_irq_mask &= ~(1 << irq);
|
||||
__asm __volatile("str %0, [%1, #0x04]" /* SAIPIC_MR */
|
||||
: : "r" (sa11x0_irq_mask), "r" (saipic_base));
|
||||
}
|
||||
|
||||
void
|
||||
arm_unmask_irqs(int irq)
|
||||
arm_unmask_irq(uintptr_t irq)
|
||||
{
|
||||
|
||||
sa11x0_irq_mask |= irq;
|
||||
sa11x0_irq_mask |= (1 << irq);
|
||||
__asm __volatile("str %0, [%1, #0x04]" /* SAIPIC_MR */
|
||||
: : "r" (sa11x0_irq_mask), "r" (saipic_base));
|
||||
}
|
||||
|
@ -259,10 +259,11 @@ i80321_iintsrc_read(void)
|
||||
}
|
||||
|
||||
int
|
||||
arm_get_irqnb(void *clockframe)
|
||||
arm_get_next_irq()
|
||||
{
|
||||
int irq;
|
||||
|
||||
return (i80321_iintsrc_read());
|
||||
if ((irq = i80321_iintsrc_read()))
|
||||
return (ffs(irq) - 1);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -426,6 +426,14 @@ i80321_pci_setup_intr(device_t dev, device_t child,
|
||||
return (BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
|
||||
intr, arg, cookiep));
|
||||
}
|
||||
|
||||
static int
|
||||
i80321_pci_teardown_intr(device_t dev, device_t child, struct resource *res,
|
||||
void *cookie)
|
||||
{
|
||||
return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
|
||||
}
|
||||
|
||||
static device_method_t i80321_pci_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, i80321_pci_probe),
|
||||
@ -443,7 +451,7 @@ static device_method_t i80321_pci_methods[] = {
|
||||
DEVMETHOD(bus_activate_resource, i80321_pci_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||
DEVMETHOD(bus_setup_intr, i80321_pci_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
||||
DEVMETHOD(bus_teardown_intr, i80321_pci_teardown_intr),
|
||||
|
||||
/* pcib interface */
|
||||
DEVMETHOD(pcib_maxslots, i80321_pci_maxslots),
|
||||
|
@ -263,19 +263,20 @@ iq80321_attach(device_t dev)
|
||||
}
|
||||
|
||||
void
|
||||
arm_mask_irqs(int nb)
|
||||
arm_mask_irq(uintptr_t nb)
|
||||
{
|
||||
intr_enabled &= ~nb;
|
||||
intr_enabled &= ~(1 << nb);
|
||||
i80321_set_intrmask();
|
||||
}
|
||||
|
||||
void
|
||||
arm_unmask_irqs(int nb)
|
||||
arm_unmask_irq(uintptr_t nb)
|
||||
{
|
||||
intr_enabled |= nb;
|
||||
intr_enabled |= (1 << nb);
|
||||
i80321_set_intrmask();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cpu_reset()
|
||||
{
|
||||
@ -311,12 +312,21 @@ iq80321_setup_intr(device_t dev, device_t child,
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
iq80321_teardown_intr(device_t dev, device_t child, struct resource *res,
|
||||
void *cookie)
|
||||
{
|
||||
return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
|
||||
}
|
||||
|
||||
static device_method_t iq80321_methods[] = {
|
||||
DEVMETHOD(device_probe, iq80321_probe),
|
||||
DEVMETHOD(device_attach, iq80321_attach),
|
||||
DEVMETHOD(device_identify, iq80321_identify),
|
||||
DEVMETHOD(bus_alloc_resource, iq80321_alloc_resource),
|
||||
DEVMETHOD(bus_setup_intr, iq80321_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, iq80321_teardown_intr),
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user