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:
parent
e29b1b389b
commit
f4e42148d7
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user