which means that wake_lock_init() is called with interrupts disabled. However wake_lock_init() calls wakeup_source_add() which itself uses spinlocks like...
which assumes that it is called with interrupts enabled. As a consequence, the spin_unlock_irq() above unconditionally enables irqs which means the evdev code which called it is now holding the client->buffer_lock with interrupts enabled, opening up the opportunity for deadlock to occur if an interrupt happens for an event which then calls evdev_pass_event() and then waits on the same spinlock.
This bug is caused by the Android patch called " Input: evdev - Add ioctl to block suspend while event queue is not empty."
This is broken because evdev_enable_ suspend_ block() has
spin_lock_ irq(&client- >buffer_ lock); init(&client- >wake_lock, WAKE_LOCK_SUSPEND, client->name); irq(&client- >buffer_ lock);
wake_lock_
[...]
spin_unlock_
which means that wake_lock_init() is called with interrupts disabled. However wake_lock_init() calls wakeup_source_add() which itself uses spinlocks like...
spin_lock_ irq(&events_ lock); irq(&events_ lock);
[...]
spin_unlock_
which assumes that it is called with interrupts enabled. As a consequence, the spin_unlock_irq() above unconditionally enables irqs which means the evdev code which called it is now holding the client->buffer_lock with interrupts enabled, opening up the opportunity for deadlock to occur if an interrupt happens for an event which then calls evdev_pass_event() and then waits on the same spinlock.