ARM interrupts improvements.

- Fix nexus_setup_intr() abuse of setting up multiple IRQs in one go. Calling
  arm_setup_irqhandler() in loop is bogus, as there's just one cookie given
  from the caller and it is overwritten in each iteration so that only the
  last handler's cookie value prevails.

- Proper intr masking/unmasking handling: the IRQ source is masked at PIC level
  only after the last handler has been removed from the list.

Reviewed by:	cognet, imp, sam, stass
Obtained from:	Grzegorz Bernacki gjb ! semihalf dot com
This commit is contained in:
Rafal Jaworowski 2008-09-11 12:36:13 +00:00
parent e29b1b389b
commit f4e42148d7
3 changed files with 16 additions and 14 deletions

View File

@ -92,9 +92,19 @@ arm_setup_irqhandler(const char *name, driver_filter_t *filt,
}
int
arm_remove_irqhandler(void *cookie)
arm_remove_irqhandler(int irq, void *cookie)
{
return (intr_event_remove_handler(cookie));
struct intr_event *event;
int error;
event = intr_events[irq];
arm_mask_irq(irq);
error = intr_event_remove_handler(cookie);
if (!TAILQ_EMPTY(&event->ie_handlers))
arm_unmask_irq(irq);
return (error);
}
void dosoftints(void);

View File

@ -120,34 +120,26 @@ nexus_probe(device_t dev)
panic("nexus_probe mem_rman");
return (0);
return bus_generic_probe(dev);
}
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)
{
int i;
if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
flags |= INTR_EXCL;
for (i = rman_get_start(res); i <= rman_get_end(res); i++)
arm_setup_irqhandler(device_get_nameunit(child),
filt, intr, arg, i, flags, cookiep);
arm_setup_irqhandler(device_get_nameunit(child),
filt, intr, arg, rman_get_start(res), flags, cookiep);
return (0);
}
static int
nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
{
int error;
int i;
for (i = rman_get_start(r); i <= rman_get_end(r); i++)
arm_mask_irq(i);
error = arm_remove_irqhandler(ih);
return (error);
return (arm_remove_irqhandler(rman_get_start(r), ih));
}
static int

View File

@ -57,6 +57,6 @@ void arm_mask_irq(uintptr_t);
void arm_unmask_irq(uintptr_t);
void arm_setup_irqhandler(const char *, int (*)(void*), void (*)(void*),
void *, int, int, void **);
int arm_remove_irqhandler(void *);
int arm_remove_irqhandler(int, void *);
extern void (*arm_post_filter)(void *);
#endif /* _MACHINE_INTR_H */