USB: Sync interrupts

On systems that use multiple UHCI/EHCI controllers, synchronize access to low
level interrupt handler. Let 'device_may_wakeup' return 1, so suspended
controllers will send interrupts upon device connection. Make sure URBs are
shutdown upon disconnect.

Fixes #332
This commit is contained in:
Sebastian Sumpf 2012-08-27 16:43:13 +02:00 committed by Norman Feske
parent 71b2b42936
commit c98a80251c
3 changed files with 19 additions and 10 deletions

View File

@ -310,7 +310,7 @@ void pm_runtime_no_callbacks(struct device *dev) { TRACE; }
int device_init_wakeup(struct device *dev, bool val) { TRACE; return 0; }
int device_wakeup_enable(struct device *dev) { TRACE; return 0; }
bool device_may_wakeup(struct device *dev) { TRACE; return 0; }
bool device_may_wakeup(struct device *dev) { TRACE; return 1; }
int device_set_wakeup_enable(struct device *dev, bool enable) { TRACE; return 0; }
bool device_can_wakeup(struct device *dev) { TRACE; return 0; }

View File

@ -957,8 +957,6 @@ void breakpoint();
/* our wait event implementation */
void __wait_event(void);
#define wait_event(wq, condition) \
({ dde_kit_printf("wait_event, not yet implemented\n"); 0; })
#define _wait_event(condition) \
while(!(condition)) { \
@ -967,6 +965,10 @@ void __wait_event(void);
msleep(1); \
} \
#define wait_event(wq, condition) \
({ _wait_event(condition); })
#define _wait_event_timeout(condition, timeout) \
({ \
unsigned long _j = jiffies + (timeout / HZ); \

View File

@ -71,6 +71,13 @@ class Irq_context : public Driver_context,
/* called by the DDE kit upon IRQ */
static void _dde_handler(void *irq)
{
/*
* Make sure there is only one interrupt handled at a time, since dde_kit
* will use one thread per IRQ
*/
static Genode::Lock handler_lock;
Genode::Lock::Guard guard(handler_lock);
/* unlock if main thread is waiting */
_irq_wait.unlock();
@ -99,9 +106,6 @@ class Irq_context : public Driver_context,
if (h->handler(_irq, h->dev) != IRQ_HANDLED)
return handled;
if (!handled)
Routine::schedule_all();
handled = true;
} while (true);
@ -117,13 +121,16 @@ class Irq_context : public Driver_context,
/* report IRQ to all clients */
for (Irq_handler *h = _handler_list.first(); h; h = h->next()) {
handled = _handle_one(h);
dde_kit_log(DEBUG_IRQ, "IRQ: %u ret: %u %p", _irq, handled, h->handler);
if (handled)
break;
handled |= _handle_one(h);
dde_kit_log(DEBUG_IRQ, "IRQ: %u ret: %u h: %p dev: %p", _irq, handled, h->handler, h->dev);
}
/* interrupt should be acked at device now */
_irq_sync.unlock();
if (handled)
Routine::schedule_all();
return handled;
}