- 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:
Olivier Houchard 2005-06-09 12:26:20 +00:00
parent 25029d6c31
commit f60e923b23
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=147166
7 changed files with 74 additions and 69 deletions

View file

@ -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--;
}

View file

@ -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)

View file

@ -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 */

View file

@ -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));
}

View file

@ -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);
}

View file

@ -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),

View file

@ -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},
};