aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb/qmi_wwan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/usb/qmi_wwan.c')
-rw-r--r--drivers/net/usb/qmi_wwan.c47
1 files changed, 17 insertions, 30 deletions
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 3543c9e57824..6883c371c59f 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -108,7 +108,7 @@ static int qmi_wwan_register_subdriver(struct usbnet *dev)
108 atomic_set(&info->pmcount, 0); 108 atomic_set(&info->pmcount, 0);
109 109
110 /* register subdriver */ 110 /* register subdriver */
111 subdriver = usb_cdc_wdm_register(info->control, &dev->status->desc, 512, &qmi_wwan_cdc_wdm_manage_power); 111 subdriver = usb_cdc_wdm_register(info->control, &dev->status->desc, 4096, &qmi_wwan_cdc_wdm_manage_power);
112 if (IS_ERR(subdriver)) { 112 if (IS_ERR(subdriver)) {
113 dev_err(&info->control->dev, "subdriver registration failed\n"); 113 dev_err(&info->control->dev, "subdriver registration failed\n");
114 rv = PTR_ERR(subdriver); 114 rv = PTR_ERR(subdriver);
@@ -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;
@@ -331,20 +326,12 @@ static const struct driver_info qmi_wwan_info = {
331 .manage_power = qmi_wwan_manage_power, 326 .manage_power = qmi_wwan_manage_power,
332}; 327};
333 328
334static const struct driver_info qmi_wwan_shared = {
335 .description = "WWAN/QMI device",
336 .flags = FLAG_WWAN,
337 .bind = qmi_wwan_bind_shared,
338 .unbind = qmi_wwan_unbind,
339 .manage_power = qmi_wwan_manage_power,
340};
341
342#define HUAWEI_VENDOR_ID 0x12D1 329#define HUAWEI_VENDOR_ID 0x12D1
343 330
344/* map QMI/wwan function by a fixed interface number */ 331/* map QMI/wwan function by a fixed interface number */
345#define QMI_FIXED_INTF(vend, prod, num) \ 332#define QMI_FIXED_INTF(vend, prod, num) \
346 USB_DEVICE_INTERFACE_NUMBER(vend, prod, num), \ 333 USB_DEVICE_INTERFACE_NUMBER(vend, prod, num), \
347 .driver_info = (unsigned long)&qmi_wwan_shared 334 .driver_info = (unsigned long)&qmi_wwan_info
348 335
349/* Gobi 1000 QMI/wwan interface number is 3 according to qcserial */ 336/* Gobi 1000 QMI/wwan interface number is 3 according to qcserial */
350#define QMI_GOBI1K_DEVICE(vend, prod) \ 337#define QMI_GOBI1K_DEVICE(vend, prod) \
@@ -372,15 +359,15 @@ static const struct usb_device_id products[] = {
372 }, 359 },
373 { /* Huawei E392, E398 and possibly others in "Windows mode" */ 360 { /* Huawei E392, E398 and possibly others in "Windows mode" */
374 USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17), 361 USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17),
375 .driver_info = (unsigned long)&qmi_wwan_shared, 362 .driver_info = (unsigned long)&qmi_wwan_info,
376 }, 363 },
377 { /* Pantech UML290, P4200 and more */ 364 { /* Pantech UML290, P4200 and more */
378 USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff), 365 USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff),
379 .driver_info = (unsigned long)&qmi_wwan_shared, 366 .driver_info = (unsigned long)&qmi_wwan_info,
380 }, 367 },
381 { /* Pantech UML290 - newer firmware */ 368 { /* Pantech UML290 - newer firmware */
382 USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff), 369 USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff),
383 .driver_info = (unsigned long)&qmi_wwan_shared, 370 .driver_info = (unsigned long)&qmi_wwan_info,
384 }, 371 },
385 372
386 /* 3. Combined interface devices matching on interface number */ 373 /* 3. Combined interface devices matching on interface number */
@@ -467,7 +454,7 @@ static int qmi_wwan_probe(struct usb_interface *intf, const struct usb_device_id
467 */ 454 */
468 if (!id->driver_info) { 455 if (!id->driver_info) {
469 dev_dbg(&intf->dev, "setting defaults for dynamic device id\n"); 456 dev_dbg(&intf->dev, "setting defaults for dynamic device id\n");
470 id->driver_info = (unsigned long)&qmi_wwan_shared; 457 id->driver_info = (unsigned long)&qmi_wwan_info;
471 } 458 }
472 459
473 return usbnet_probe(intf, id); 460 return usbnet_probe(intf, id);