aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/usb/qmi_wwan.c45
1 files changed, 16 insertions, 29 deletions
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 516653f39512..84923334ca5b 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -139,10 +139,18 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
139 139
140 BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < sizeof(struct qmi_wwan_state))); 140 BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < sizeof(struct qmi_wwan_state)));
141 141
142 /* require a single interrupt status endpoint for subdriver */ 142 /* control and data is shared? */
143 if (intf->cur_altsetting->desc.bNumEndpoints == 3) {
144 info->control = intf;
145 info->data = intf;
146 goto shared;
147 }
148
149 /* else require a single interrupt status endpoint on control intf */
143 if (intf->cur_altsetting->desc.bNumEndpoints != 1) 150 if (intf->cur_altsetting->desc.bNumEndpoints != 1)
144 goto err; 151 goto err;
145 152
153 /* and a number of CDC descriptors */
146 while (len > 3) { 154 while (len > 3) {
147 struct usb_descriptor_header *h = (void *)buf; 155 struct usb_descriptor_header *h = (void *)buf;
148 156
@@ -231,8 +239,9 @@ next_desc:
231 if (status < 0) 239 if (status < 0)
232 goto err; 240 goto err;
233 241
242shared:
234 status = qmi_wwan_register_subdriver(dev); 243 status = qmi_wwan_register_subdriver(dev);
235 if (status < 0) { 244 if (status < 0 && info->control != info->data) {
236 usb_set_intfdata(info->data, NULL); 245 usb_set_intfdata(info->data, NULL);
237 usb_driver_release_interface(driver, info->data); 246 usb_driver_release_interface(driver, info->data);
238 } 247 }
@@ -241,20 +250,6 @@ err:
241 return status; 250 return status;
242} 251}
243 252
244/* Some devices combine the "control" and "data" functions into a
245 * single interface with all three endpoints: interrupt + bulk in and
246 * out
247 */
248static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf)
249{
250 struct qmi_wwan_state *info = (void *)&dev->data;
251
252 /* control and data is shared */
253 info->control = intf;
254 info->data = intf;
255 return qmi_wwan_register_subdriver(dev);
256}
257
258static void qmi_wwan_unbind(struct usbnet *dev, struct usb_interface *intf) 253static void qmi_wwan_unbind(struct usbnet *dev, struct usb_interface *intf)
259{ 254{
260 struct qmi_wwan_state *info = (void *)&dev->data; 255 struct qmi_wwan_state *info = (void *)&dev->data;
@@ -330,20 +325,12 @@ static const struct driver_info qmi_wwan_info = {
330 .manage_power = qmi_wwan_manage_power, 325 .manage_power = qmi_wwan_manage_power,
331}; 326};
332 327
333static const struct driver_info qmi_wwan_shared = {
334 .description = "WWAN/QMI device",
335 .flags = FLAG_WWAN,
336 .bind = qmi_wwan_bind_shared,
337 .unbind = qmi_wwan_unbind,
338 .manage_power = qmi_wwan_manage_power,
339};
340
341#define HUAWEI_VENDOR_ID 0x12D1 328#define HUAWEI_VENDOR_ID 0x12D1
342 329
343/* map QMI/wwan function by a fixed interface number */ 330/* map QMI/wwan function by a fixed interface number */
344#define QMI_FIXED_INTF(vend, prod, num) \ 331#define QMI_FIXED_INTF(vend, prod, num) \
345 USB_DEVICE_INTERFACE_NUMBER(vend, prod, num), \ 332 USB_DEVICE_INTERFACE_NUMBER(vend, prod, num), \
346 .driver_info = (unsigned long)&qmi_wwan_shared 333 .driver_info = (unsigned long)&qmi_wwan_info
347 334
348/* Gobi 1000 QMI/wwan interface number is 3 according to qcserial */ 335/* Gobi 1000 QMI/wwan interface number is 3 according to qcserial */
349#define QMI_GOBI1K_DEVICE(vend, prod) \ 336#define QMI_GOBI1K_DEVICE(vend, prod) \
@@ -367,15 +354,15 @@ static const struct usb_device_id products[] = {
367 /* 2. Combined interface devices matching on class+protocol */ 354 /* 2. Combined interface devices matching on class+protocol */
368 { /* Huawei E392, E398 and possibly others in "Windows mode" */ 355 { /* Huawei E392, E398 and possibly others in "Windows mode" */
369 USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17), 356 USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17),
370 .driver_info = (unsigned long)&qmi_wwan_shared, 357 .driver_info = (unsigned long)&qmi_wwan_info,
371 }, 358 },
372 { /* Pantech UML290 */ 359 { /* Pantech UML290 */
373 USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff), 360 USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff),
374 .driver_info = (unsigned long)&qmi_wwan_shared, 361 .driver_info = (unsigned long)&qmi_wwan_info,
375 }, 362 },
376 { /* Pantech UML290 - newer firmware */ 363 { /* Pantech UML290 - newer firmware */
377 USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff), 364 USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff),
378 .driver_info = (unsigned long)&qmi_wwan_shared, 365 .driver_info = (unsigned long)&qmi_wwan_info,
379 }, 366 },
380 367
381 /* 3. Combined interface devices matching on interface number */ 368 /* 3. Combined interface devices matching on interface number */
@@ -457,7 +444,7 @@ static int qmi_wwan_probe(struct usb_interface *intf, const struct usb_device_id
457 */ 444 */
458 if (!id->driver_info) { 445 if (!id->driver_info) {
459 dev_dbg(&intf->dev, "setting defaults for dynamic device id\n"); 446 dev_dbg(&intf->dev, "setting defaults for dynamic device id\n");
460 id->driver_info = (unsigned long)&qmi_wwan_shared; 447 id->driver_info = (unsigned long)&qmi_wwan_info;
461 } 448 }
462 449
463 return usbnet_probe(intf, id); 450 return usbnet_probe(intf, id);