diff options
-rw-r--r-- | drivers/usb/class/cdc-wdm.c | 103 |
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 | |||
232 | skip_error: | 212 | skip_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 | ||
246 | unlock: | ||
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 | ||
805 | static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor *ep, | 773 | static 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 | ||
1011 | err: | 916 | err: |
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 | ||