diff options
-rw-r--r-- | drivers/net/usb/cdc_ether.c | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 04ee044dde51..4393f1483126 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c | |||
@@ -215,6 +215,10 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) | |||
215 | goto bad_desc; | 215 | goto bad_desc; |
216 | } | 216 | } |
217 | 217 | ||
218 | /* some devices merge these - skip class check */ | ||
219 | if (info->control == info->data) | ||
220 | goto next_desc; | ||
221 | |||
218 | /* a data interface altsetting does the real i/o */ | 222 | /* a data interface altsetting does the real i/o */ |
219 | d = &info->data->cur_altsetting->desc; | 223 | d = &info->data->cur_altsetting->desc; |
220 | if (d->bInterfaceClass != USB_CLASS_CDC_DATA) { | 224 | if (d->bInterfaceClass != USB_CLASS_CDC_DATA) { |
@@ -304,19 +308,23 @@ next_desc: | |||
304 | /* claim data interface and set it up ... with side effects. | 308 | /* claim data interface and set it up ... with side effects. |
305 | * network traffic can't flow until an altsetting is enabled. | 309 | * network traffic can't flow until an altsetting is enabled. |
306 | */ | 310 | */ |
307 | status = usb_driver_claim_interface(driver, info->data, dev); | 311 | if (info->data != info->control) { |
308 | if (status < 0) | 312 | status = usb_driver_claim_interface(driver, info->data, dev); |
309 | return status; | 313 | if (status < 0) |
314 | return status; | ||
315 | } | ||
310 | status = usbnet_get_endpoints(dev, info->data); | 316 | status = usbnet_get_endpoints(dev, info->data); |
311 | if (status < 0) { | 317 | if (status < 0) { |
312 | /* ensure immediate exit from usbnet_disconnect */ | 318 | /* ensure immediate exit from usbnet_disconnect */ |
313 | usb_set_intfdata(info->data, NULL); | 319 | usb_set_intfdata(info->data, NULL); |
314 | usb_driver_release_interface(driver, info->data); | 320 | if (info->data != info->control) |
321 | usb_driver_release_interface(driver, info->data); | ||
315 | return status; | 322 | return status; |
316 | } | 323 | } |
317 | 324 | ||
318 | /* status endpoint: optional for CDC Ethernet, not RNDIS (or ACM) */ | 325 | /* status endpoint: optional for CDC Ethernet, not RNDIS (or ACM) */ |
319 | dev->status = NULL; | 326 | if (info->data != info->control) |
327 | dev->status = NULL; | ||
320 | if (info->control->cur_altsetting->desc.bNumEndpoints == 1) { | 328 | if (info->control->cur_altsetting->desc.bNumEndpoints == 1) { |
321 | struct usb_endpoint_descriptor *desc; | 329 | struct usb_endpoint_descriptor *desc; |
322 | 330 | ||
@@ -349,6 +357,10 @@ void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf) | |||
349 | struct cdc_state *info = (void *) &dev->data; | 357 | struct cdc_state *info = (void *) &dev->data; |
350 | struct usb_driver *driver = driver_of(intf); | 358 | struct usb_driver *driver = driver_of(intf); |
351 | 359 | ||
360 | /* combined interface - nothing to do */ | ||
361 | if (info->data == info->control) | ||
362 | return; | ||
363 | |||
352 | /* disconnect master --> disconnect slave */ | 364 | /* disconnect master --> disconnect slave */ |
353 | if (intf == info->control && info->data) { | 365 | if (intf == info->control && info->data) { |
354 | /* ensure immediate exit from usbnet_disconnect */ | 366 | /* ensure immediate exit from usbnet_disconnect */ |