linux/drivers
Daniel Kurtz f0befcd64b HID: usbhid: hid-core: submit queued urbs before suspend
If any userspace program has opened a keyboard device, the input core
de-activates the keyboard's LEDs upon suspend().  It does this by sending
individual EV_LED[LED_X]=0 events to the underlying device driver by
directly calling the driver's registered event() handler.

The usb-hid driver event() handler processes each request by immediately
attempting to submit a CTRL URB to turn off the LED.  USB URB submission
is asynchronous.  First the URB is added to the head of the ctrl queue.
Then, if the CTRL_RUNNING flag is false, the URB is submitted immediately
(and CTRL_RUNNING is set).  If the CTRL_RUNNING flag was already true,
then the newly queued URB is submitted in the ctrl completion handler when
all previously submitted URBs have completed.  When all queued URBs have
been submitted, the completion handler clears the CTRL_RUNNING flag.

In the 2-LED suspend case, at input suspend(), 2 LED event CTRL URBs get
queued, with only the first actually submitted.  Soon after input
suspend() handler finishes, the usb-hid suspend() handler gets called.
Since this is NOT a PM_EVENT_AUTO suspend, the handler sets
REPORTED_IDLE, then waits for io to complete.

Unfortunately, this usually happens while the first LED request is
actually still being processed.  Thus when the completion handler tries
to submit the second LED request it fails, since REPORTED_IDLE is
already set!  This REPORTED_IDLE check failure causes the completion
handler to complete, however without clearing the CTRL_RUNNING flag.
This, in turn, means that the suspend() handler's wait_io() condition
is never satisfied, and instead it times out after 10 seconds, aborting
the original system suspend.

This patch changes the behavior to the following:
  (1) allow completion handler to finish submitting all queued URBs, even if
      REPORTED_IDLE is set.  This guarantees that all URBs queued before the
      hid-core suspend() call will be submitted before the system is
      suspended.
  (2) if REPORTED_IDLE is set and the URB queue is empty, queue, but
      don't submit, new URB submission requests.  These queued requests get
      submitted when resume() flushes the URB queue. This is similar to the
      existing behavior, however, any requests that arrive while the queue is
      not yet empty will still get submitted before suspend.
  (3) set the RUNNING flag when flushing the URB queue in resume().
      This keeps URBs that were queued in (2) from colliding with any new
      URBs that are being submitted during the resume process.  The new URB
      submission requests upon resume get properly queued behind the ones
      being flushed instead of the current situation where they collide,
      causing memory corruption and oopses.

Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2011-12-21 11:18:35 +01:00
..
accessibility
acpi Merge branch 'pstore' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux 2011-11-01 10:52:29 -07:00
amba
ata Merge branch 'depends/rmk/gpio' into next/devel 2011-10-31 23:46:42 +01:00
atm Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next 2011-10-25 13:25:22 +02:00
auxdisplay
base Merge branch 'pm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm 2011-10-25 15:18:39 +02:00
bcma
block virtio-blk: use ida to allocate disk index 2011-11-02 11:41:02 +10:30
bluetooth Merge branch 'pm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm 2011-10-25 15:18:39 +02:00
cdrom
char Merge branch 'misc-3.2' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux 2011-11-02 16:52:17 -07:00
clk
clocksource Merge branch 'next/timer' of git://git.linaro.org/people/arnd/arm-soc 2011-11-01 20:18:05 -07:00
connector
cpufreq Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2011-10-26 17:15:03 +02:00
cpuidle
crypto crypto: talitos - handle descriptor not found in error path 2011-10-21 15:20:28 +02:00
dca
devfreq
dio
dma
edac Merge branch 'linux_next' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac 2011-11-02 16:55:15 -07:00
eisa
firewire firewire: ohci: fix isochronous DMA synchronization 2011-10-18 12:32:39 +02:00
firmware Merge branch 'pstore' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux 2011-11-01 10:52:29 -07:00
gpio Merge branch 'next/devel' of git://git.linaro.org/people/arnd/arm-soc 2011-11-01 20:31:25 -07:00
gpu Merge branch 'drm-core-next' of git://people.freedesktop.org/~airlied/linux 2011-10-28 05:54:23 -07:00
hid HID: usbhid: hid-core: submit queued urbs before suspend 2011-12-21 11:18:35 +01:00
hv hv: remove struct hv_device_info from hyperv.h 2011-10-11 09:51:22 -06:00
hwmon drivers/hwmon/hwmon.c: convert idr to ida and use ida_simple_get() 2011-10-31 17:30:51 -07:00
hwspinlock
i2c Merge branch 'for-linus/i2c-3.2' of git://git.fluff.org/bjdooks/linux 2011-11-01 15:07:19 -07:00
ide Merge branch 'depends/rmk/gpio' into next/devel 2011-10-31 23:46:42 +01:00
idle
ieee802154
infiniband Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband 2011-11-01 10:51:38 -07:00
input Merge branch 'for-linus' of git://github.com/richardweinberger/linux 2011-11-02 09:45:39 -07:00
iommu Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu 2011-10-30 15:46:19 -07:00
isdn Merge branch 'for-linus' of git://github.com/richardweinberger/linux 2011-11-02 09:45:39 -07:00
leds drivers/leds/leds-lp5521.c: check if reset is successful 2011-10-31 17:30:55 -07:00
lguest lguest: move process freezing before pending signals check 2011-10-27 10:56:18 +10:30
macintosh
mca
md Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/linux-dm 2011-11-02 17:02:37 -07:00
media Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media 2011-10-31 15:42:54 -07:00
memstick
message
mfd Merge branch 'depends/rmk/gpio' into next/devel 2011-10-31 23:46:42 +01:00
misc drivers/misc/vmw_balloon.c: fix typo in code comment 2011-11-02 16:07:03 -07:00
mmc Merge branch 'next/devel' of git://git.linaro.org/people/arnd/arm-soc 2011-11-01 20:31:25 -07:00
mtd filesystems: add missing nlink wrappers 2011-11-02 12:53:43 +01:00
net Merge branch 'akpm' (Andrew's incoming - part two) 2011-11-02 16:07:27 -07:00
nfc
nubus
of Merge branch 'next/dt' of git://git.linaro.org/people/arnd/arm-soc 2011-11-01 21:02:35 -07:00
oprofile
parisc
parport parport_pc: release IO region properly if unsupported ITE887x card is found 2011-10-18 14:17:40 -07:00
pci Merge branch 'next-rebase' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci 2011-10-28 14:20:44 -07:00
pcmcia Merge branch 'next/fixes' of git://git.linaro.org/people/arnd/arm-soc 2011-11-01 19:55:06 -07:00
pinctrl pinctrl/sirf: fix sirfsoc_get_group_pins prototype 2011-10-25 10:43:57 +02:00
platform Merge branch 'akpm' (Andrew's incoming) 2011-10-31 17:46:07 -07:00
pnp
power Merge branch 'akpm' (Andrew's incoming - part two) 2011-11-02 16:07:27 -07:00
pps pps gpio client: add missing dependency 2011-11-02 16:07:02 -07:00
ps3
ptp
rapidio RapidIO: fix potential null deref in rio_setup_device() 2011-11-02 16:07:01 -07:00
regulator Merge branch 'for-linus' of git://opensource.wolfsonmicro.com/regulator 2011-11-01 15:06:20 -07:00
rtc Merge branch 'akpm' (Andrew's incoming - part two) 2011-11-02 16:07:27 -07:00
s390 [S390] qdio: prevent dsci access without adapter interrupts 2011-10-30 15:16:47 +01:00
sbus
scsi Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6 2011-10-28 16:44:18 -07:00
sfi
sh
sn
spi Merge branch 'depends/rmk/gpio' into next/devel 2011-10-31 23:46:42 +01:00
ssb
staging filesystems: add set_nlink() 2011-11-02 12:53:43 +01:00
target Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial 2011-10-25 12:11:02 +02:00
tc
telephony
thermal
tty Merge branch 'for-linus' of git://github.com/richardweinberger/linux 2011-11-02 09:45:39 -07:00
uio uio: Support physical addresses >32 bits on 32-bit systems 2011-10-18 11:18:57 -07:00
usb HID/usbled: add support for Dream Cheeky DL100B Mailbox Friends Alert 2011-11-20 10:21:30 +01:00
uwb
vhost
video Merge branch 'next/fixes' of git://git.linaro.org/people/arnd/arm-soc 2011-11-01 19:55:06 -07:00
virt
virtio virtio: Add platform bus driver for memory mapped virtio device 2011-11-02 11:41:01 +10:30
vlynq
w1 w1: disable irqs in critical section 2011-11-02 16:07:03 -07:00
watchdog Merge branch 'for-linus' of git://github.com/richardweinberger/linux 2011-11-02 09:45:39 -07:00
xen Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2011-10-26 16:44:09 +02:00
zorro zorro: Fix four checkpatch warnings 2011-10-24 21:00:34 +02:00
Kconfig Merge branch 'staging-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging 2011-10-26 15:39:02 +02:00
Makefile Merge branch 'staging-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging 2011-10-26 15:39:02 +02:00