cdc-wdm: fix "out-of-sync" due to missing notifications
authorBjørn Mork <bjorn@mork.no>
Sun, 10 Jul 2016 15:45:14 +0000 (17:45 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 9 Aug 2016 13:50:17 +0000 (15:50 +0200)
commit833415a3e781a26fe480a34d45086bdb4fe1e4c0
treed6347b054ea78bd12e399decf6ad505ec24f8877
parentec7b1268510908157d4e8878bb753ea844446856
cdc-wdm: fix "out-of-sync" due to missing notifications

The driver enforces a strict one-to-one relationship between the
received RESPONSE_AVAILABLE notifications and messages read from
the device. At the same time, it will cancel the interrupt URB
when there is no client holding the character device open.

Many devices do not cope well with this behaviour.  They maintain
a FIFO queue of messages, and send notifications on a best effort
basis.  Messages are queued regardless of whether the notification
is successful or not. So if the driver loses a single notification,
which can easily happen when the interrupt URB is cancelled, then
the device and driver becomes out-of-sync. New messages end up
at the end of the queue, while the associated notification makes
the driver read only the first message from the queue.

This state is permanent from a user point of view. There is no
no way to flush the device queue without resetting the device or
using another driver.

The problem is easy to hit with current QMI and MBIM command line
tools, which typically close the character device after seeing
the reply they expect. Any pending unsolicited messages from the
device will then trigger the driver bug.

Fix by always reading all queued messages from the device when
the notification URB is first submitted.  This is expected to
end with an -EPIPE status when there are no more pending
messages, so demote the printk associated with -EPIPE to debug
level.

The workaround has been tested on a large number of different MBIM
and QMI devices, as well as the Ericsson F5521gw and H5321gw modems
with real Device Management functions.

Signed-off-by: Bjørn Mork <bjorn@mork.no>
Acked-by: Oliver Neukum <oneukum@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/class/cdc-wdm.c