aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/class/cdc-wdm.c103
1 files changed, 4 insertions, 99 deletions
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 0a6369510f2d..0b845e550fbd 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -58,7 +58,6 @@ MODULE_DEVICE_TABLE (usb, wdm_ids);
58#define WDM_SUSPENDING 8 58#define WDM_SUSPENDING 8
59#define WDM_RESETTING 9 59#define WDM_RESETTING 9
60#define WDM_OVERFLOW 10 60#define WDM_OVERFLOW 10
61#define WDM_DRAIN_ON_OPEN 11
62 61
63#define WDM_MAX 16 62#define WDM_MAX 16
64 63
@@ -182,7 +181,7 @@ static void wdm_in_callback(struct urb *urb)
182 "nonzero urb status received: -ESHUTDOWN\n"); 181 "nonzero urb status received: -ESHUTDOWN\n");
183 goto skip_error; 182 goto skip_error;
184 case -EPIPE: 183 case -EPIPE:
185 dev_dbg(&desc->intf->dev, 184 dev_err(&desc->intf->dev,
186 "nonzero urb status received: -EPIPE\n"); 185 "nonzero urb status received: -EPIPE\n");
187 break; 186 break;
188 default: 187 default:
@@ -210,25 +209,6 @@ static void wdm_in_callback(struct urb *urb)
210 desc->reslength = length; 209 desc->reslength = length;
211 } 210 }
212 } 211 }
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
232skip_error: 212skip_error:
233 set_bit(WDM_READ, &desc->flags); 213 set_bit(WDM_READ, &desc->flags);
234 wake_up(&desc->wait); 214 wake_up(&desc->wait);
@@ -243,7 +223,6 @@ skip_error:
243 service_outstanding_interrupt(desc); 223 service_outstanding_interrupt(desc);
244 } 224 }
245 225
246unlock:
247 spin_unlock(&desc->iuspin); 226 spin_unlock(&desc->iuspin);
248} 227}
249 228
@@ -686,17 +665,6 @@ static int wdm_open(struct inode *inode, struct file *file)
686 dev_err(&desc->intf->dev, 665 dev_err(&desc->intf->dev,
687 "Error submitting int urb - %d\n", rv); 666 "Error submitting int urb - %d\n", rv);
688 rv = usb_translate_errors(rv); 667 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);
700 } 668 }
701 } else { 669 } else {
702 rv = 0; 670 rv = 0;
@@ -803,8 +771,7 @@ static void wdm_rxwork(struct work_struct *work)
803/* --- hotplug --- */ 771/* --- hotplug --- */
804 772
805static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor *ep, 773static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor *ep,
806 u16 bufsize, int (*manage_power)(struct usb_interface *, int), 774 u16 bufsize, int (*manage_power)(struct usb_interface *, int))
807 bool drain_on_open)
808{ 775{
809 int rv = -ENOMEM; 776 int rv = -ENOMEM;
810 struct wdm_device *desc; 777 struct wdm_device *desc;
@@ -891,68 +858,6 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor
891 858
892 desc->manage_power = manage_power; 859 desc->manage_power = manage_power;
893 860
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
956 spin_lock(&wdm_device_list_lock); 861 spin_lock(&wdm_device_list_lock);
957 list_add(&desc->device_list, &wdm_device_list); 862 list_add(&desc->device_list, &wdm_device_list);
958 spin_unlock(&wdm_device_list_lock); 863 spin_unlock(&wdm_device_list_lock);
@@ -1006,7 +911,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
1006 goto err; 911 goto err;
1007 ep = &iface->endpoint[0].desc; 912 ep = &iface->endpoint[0].desc;
1008 913
1009 rv = wdm_create(intf, ep, maxcom, &wdm_manage_power, false); 914 rv = wdm_create(intf, ep, maxcom, &wdm_manage_power);
1010 915
1011err: 916err:
1012 return rv; 917 return rv;
@@ -1038,7 +943,7 @@ struct usb_driver *usb_cdc_wdm_register(struct usb_interface *intf,
1038{ 943{
1039 int rv = -EINVAL; 944 int rv = -EINVAL;
1040 945
1041 rv = wdm_create(intf, ep, bufsize, manage_power, true); 946 rv = wdm_create(intf, ep, bufsize, manage_power);
1042 if (rv < 0) 947 if (rv < 0)
1043 goto err; 948 goto err;
1044 949