Skip to content

Commit 1944581

Browse files
bmorkgregkh
authored andcommitted
USB: Revert "cdc-wdm: fix "out-of-sync" due to missing notifications"
This reverts commit 833415a ("cdc-wdm: fix "out-of-sync" due to missing notifications") There have been several reports of wdm_read returning unexpected EIO errors with QMI devices using the qmi_wwan driver. The reporters confirm that reverting prevents these errors. I have been unable to reproduce the bug myself, and have no explanation to offer either. But reverting is the safe choice here, given that the commit was an attempt to work around a firmware problem. Living with a firmware problem is still better than adding driver bugs. Reported-by: Kasper Holtze <kasper@holtze.dk> Reported-by: Aleksander Morgado <aleksander@aleksander.es> Reported-by: Daniele Palmas <dnlplm@gmail.com> Cc: <stable@vger.kernel.org> # v4.9+ Fixes: 833415a ("cdc-wdm: fix "out-of-sync" due to missing notifications") 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>
1 parent 3d61596 commit 1944581

File tree

1 file changed

+4
-99
lines changed

1 file changed

+4
-99
lines changed

drivers/usb/class/cdc-wdm.c

Lines changed: 4 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ MODULE_DEVICE_TABLE (usb, wdm_ids);
5858
#define WDM_SUSPENDING 8
5959
#define WDM_RESETTING 9
6060
#define WDM_OVERFLOW 10
61-
#define WDM_DRAIN_ON_OPEN 11
6261

6362
#define WDM_MAX 16
6463

@@ -182,7 +181,7 @@ static void wdm_in_callback(struct urb *urb)
182181
"nonzero urb status received: -ESHUTDOWN\n");
183182
goto skip_error;
184183
case -EPIPE:
185-
dev_dbg(&desc->intf->dev,
184+
dev_err(&desc->intf->dev,
186185
"nonzero urb status received: -EPIPE\n");
187186
break;
188187
default:
@@ -210,25 +209,6 @@ static void wdm_in_callback(struct urb *urb)
210209
desc->reslength = length;
211210
}
212211
}
213-
214-
/*
215-
* Handling devices with the WDM_DRAIN_ON_OPEN flag set:
216-
* If desc->resp_count is unset, then the urb was submitted
217-
* without a prior notification. If the device returned any
218-
* data, then this implies that it had messages queued without
219-
* notifying us. Continue reading until that queue is flushed.
220-
*/
221-
if (!desc->resp_count) {
222-
if (!length) {
223-
/* do not propagate the expected -EPIPE */
224-
desc->rerr = 0;
225-
goto unlock;
226-
}
227-
dev_dbg(&desc->intf->dev, "got %d bytes without notification\n", length);
228-
set_bit(WDM_RESPONDING, &desc->flags);
229-
usb_submit_urb(desc->response, GFP_ATOMIC);
230-
}
231-
232212
skip_error:
233213
set_bit(WDM_READ, &desc->flags);
234214
wake_up(&desc->wait);
@@ -243,7 +223,6 @@ static void wdm_in_callback(struct urb *urb)
243223
service_outstanding_interrupt(desc);
244224
}
245225

246-
unlock:
247226
spin_unlock(&desc->iuspin);
248227
}
249228

@@ -686,17 +665,6 @@ static int wdm_open(struct inode *inode, struct file *file)
686665
dev_err(&desc->intf->dev,
687666
"Error submitting int urb - %d\n", rv);
688667
rv = usb_translate_errors(rv);
689-
} else if (test_bit(WDM_DRAIN_ON_OPEN, &desc->flags)) {
690-
/*
691-
* Some devices keep pending messages queued
692-
* without resending notifications. We must
693-
* flush the message queue before we can
694-
* assume a one-to-one relationship between
695-
* notifications and messages in the queue
696-
*/
697-
dev_dbg(&desc->intf->dev, "draining queued data\n");
698-
set_bit(WDM_RESPONDING, &desc->flags);
699-
rv = usb_submit_urb(desc->response, GFP_KERNEL);
700668
}
701669
} else {
702670
rv = 0;
@@ -803,8 +771,7 @@ static void wdm_rxwork(struct work_struct *work)
803771
/* --- hotplug --- */
804772

805773
static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor *ep,
806-
u16 bufsize, int (*manage_power)(struct usb_interface *, int),
807-
bool drain_on_open)
774+
u16 bufsize, int (*manage_power)(struct usb_interface *, int))
808775
{
809776
int rv = -ENOMEM;
810777
struct wdm_device *desc;
@@ -891,68 +858,6 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor
891858

892859
desc->manage_power = manage_power;
893860

894-
/*
895-
* "drain_on_open" enables a hack to work around a firmware
896-
* issue observed on network functions, in particular MBIM
897-
* functions.
898-
*
899-
* Quoting section 7 of the CDC-WMC r1.1 specification:
900-
*
901-
* "The firmware shall interpret GetEncapsulatedResponse as a
902-
* request to read response bytes. The firmware shall send
903-
* the next wLength bytes from the response. The firmware
904-
* shall allow the host to retrieve data using any number of
905-
* GetEncapsulatedResponse requests. The firmware shall
906-
* return a zero- length reply if there are no data bytes
907-
* available.
908-
*
909-
* The firmware shall send ResponseAvailable notifications
910-
* periodically, using any appropriate algorithm, to inform
911-
* the host that there is data available in the reply
912-
* buffer. The firmware is allowed to send ResponseAvailable
913-
* notifications even if there is no data available, but
914-
* this will obviously reduce overall performance."
915-
*
916-
* These requirements, although they make equally sense, are
917-
* often not implemented by network functions. Some firmwares
918-
* will queue data indefinitely, without ever resending a
919-
* notification. The result is that the driver and firmware
920-
* loses "syncronization" if the driver ever fails to respond
921-
* to a single notification, something which easily can happen
922-
* on release(). When this happens, the driver will appear to
923-
* never receive notifications for the most current data. Each
924-
* notification will only cause a single read, which returns
925-
* the oldest data in the firmware's queue.
926-
*
927-
* The "drain_on_open" hack resolves the situation by draining
928-
* data from the firmware until none is returned, without a
929-
* prior notification.
930-
*
931-
* This will inevitably race with the firmware, risking that
932-
* we read data from the device before handling the associated
933-
* notification. To make things worse, some of the devices
934-
* needing the hack do not implement the "return zero if no
935-
* data is available" requirement either. Instead they return
936-
* an error on the subsequent read in this case. This means
937-
* that "winning" the race can cause an unexpected EIO to
938-
* userspace.
939-
*
940-
* "winning" the race is more likely on resume() than on
941-
* open(), and the unexpected error is more harmful in the
942-
* middle of an open session. The hack is therefore only
943-
* applied on open(), and not on resume() where it logically
944-
* would be equally necessary. So we define open() as the only
945-
* driver <-> device "syncronization point". Should we happen
946-
* to lose a notification after open(), then syncronization
947-
* will be lost until release()
948-
*
949-
* The hack should not be enabled for CDC WDM devices
950-
* conforming to the CDC-WMC r1.1 specification. This is
951-
* ensured by setting drain_on_open to false in wdm_probe().
952-
*/
953-
if (drain_on_open)
954-
set_bit(WDM_DRAIN_ON_OPEN, &desc->flags);
955-
956861
spin_lock(&wdm_device_list_lock);
957862
list_add(&desc->device_list, &wdm_device_list);
958863
spin_unlock(&wdm_device_list_lock);
@@ -1006,7 +911,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
1006911
goto err;
1007912
ep = &iface->endpoint[0].desc;
1008913

1009-
rv = wdm_create(intf, ep, maxcom, &wdm_manage_power, false);
914+
rv = wdm_create(intf, ep, maxcom, &wdm_manage_power);
1010915

1011916
err:
1012917
return rv;
@@ -1038,7 +943,7 @@ struct usb_driver *usb_cdc_wdm_register(struct usb_interface *intf,
1038943
{
1039944
int rv = -EINVAL;
1040945

1041-
rv = wdm_create(intf, ep, bufsize, manage_power, true);
946+
rv = wdm_create(intf, ep, bufsize, manage_power);
1042947
if (rv < 0)
1043948
goto err;
1044949

0 commit comments

Comments
 (0)