diff options
Diffstat (limited to 'drivers/usb/class')
-rw-r--r-- | drivers/usb/class/cdc-acm.c | 22 | ||||
-rw-r--r-- | drivers/usb/class/cdc-wdm.c | 23 |
2 files changed, 39 insertions, 6 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 8ac25adf31b4..387dc6c8ad25 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -593,7 +593,6 @@ static void acm_port_destruct(struct tty_port *port) | |||
593 | 593 | ||
594 | dev_dbg(&acm->control->dev, "%s\n", __func__); | 594 | dev_dbg(&acm->control->dev, "%s\n", __func__); |
595 | 595 | ||
596 | tty_unregister_device(acm_tty_driver, acm->minor); | ||
597 | acm_release_minor(acm); | 596 | acm_release_minor(acm); |
598 | usb_put_intf(acm->control); | 597 | usb_put_intf(acm->control); |
599 | kfree(acm->country_codes); | 598 | kfree(acm->country_codes); |
@@ -977,6 +976,8 @@ static int acm_probe(struct usb_interface *intf, | |||
977 | int num_rx_buf; | 976 | int num_rx_buf; |
978 | int i; | 977 | int i; |
979 | int combined_interfaces = 0; | 978 | int combined_interfaces = 0; |
979 | struct device *tty_dev; | ||
980 | int rv = -ENOMEM; | ||
980 | 981 | ||
981 | /* normal quirks */ | 982 | /* normal quirks */ |
982 | quirks = (unsigned long)id->driver_info; | 983 | quirks = (unsigned long)id->driver_info; |
@@ -1339,11 +1340,24 @@ skip_countries: | |||
1339 | usb_set_intfdata(data_interface, acm); | 1340 | usb_set_intfdata(data_interface, acm); |
1340 | 1341 | ||
1341 | usb_get_intf(control_interface); | 1342 | usb_get_intf(control_interface); |
1342 | tty_port_register_device(&acm->port, acm_tty_driver, minor, | 1343 | tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor, |
1343 | &control_interface->dev); | 1344 | &control_interface->dev); |
1345 | if (IS_ERR(tty_dev)) { | ||
1346 | rv = PTR_ERR(tty_dev); | ||
1347 | goto alloc_fail8; | ||
1348 | } | ||
1344 | 1349 | ||
1345 | return 0; | 1350 | return 0; |
1351 | alloc_fail8: | ||
1352 | if (acm->country_codes) { | ||
1353 | device_remove_file(&acm->control->dev, | ||
1354 | &dev_attr_wCountryCodes); | ||
1355 | device_remove_file(&acm->control->dev, | ||
1356 | &dev_attr_iCountryCodeRelDate); | ||
1357 | } | ||
1358 | device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities); | ||
1346 | alloc_fail7: | 1359 | alloc_fail7: |
1360 | usb_set_intfdata(intf, NULL); | ||
1347 | for (i = 0; i < ACM_NW; i++) | 1361 | for (i = 0; i < ACM_NW; i++) |
1348 | usb_free_urb(acm->wb[i].urb); | 1362 | usb_free_urb(acm->wb[i].urb); |
1349 | alloc_fail6: | 1363 | alloc_fail6: |
@@ -1359,7 +1373,7 @@ alloc_fail2: | |||
1359 | acm_release_minor(acm); | 1373 | acm_release_minor(acm); |
1360 | kfree(acm); | 1374 | kfree(acm); |
1361 | alloc_fail: | 1375 | alloc_fail: |
1362 | return -ENOMEM; | 1376 | return rv; |
1363 | } | 1377 | } |
1364 | 1378 | ||
1365 | static void stop_data_traffic(struct acm *acm) | 1379 | static void stop_data_traffic(struct acm *acm) |
@@ -1411,6 +1425,8 @@ static void acm_disconnect(struct usb_interface *intf) | |||
1411 | 1425 | ||
1412 | stop_data_traffic(acm); | 1426 | stop_data_traffic(acm); |
1413 | 1427 | ||
1428 | tty_unregister_device(acm_tty_driver, acm->minor); | ||
1429 | |||
1414 | usb_free_urb(acm->ctrlurb); | 1430 | usb_free_urb(acm->ctrlurb); |
1415 | for (i = 0; i < ACM_NW; i++) | 1431 | for (i = 0; i < ACM_NW; i++) |
1416 | usb_free_urb(acm->wb[i].urb); | 1432 | usb_free_urb(acm->wb[i].urb); |
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 5f0cb417b736..122d056d96d5 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c | |||
@@ -56,6 +56,7 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); | |||
56 | #define WDM_RESPONDING 7 | 56 | #define WDM_RESPONDING 7 |
57 | #define WDM_SUSPENDING 8 | 57 | #define WDM_SUSPENDING 8 |
58 | #define WDM_RESETTING 9 | 58 | #define WDM_RESETTING 9 |
59 | #define WDM_OVERFLOW 10 | ||
59 | 60 | ||
60 | #define WDM_MAX 16 | 61 | #define WDM_MAX 16 |
61 | 62 | ||
@@ -155,6 +156,7 @@ static void wdm_in_callback(struct urb *urb) | |||
155 | { | 156 | { |
156 | struct wdm_device *desc = urb->context; | 157 | struct wdm_device *desc = urb->context; |
157 | int status = urb->status; | 158 | int status = urb->status; |
159 | int length = urb->actual_length; | ||
158 | 160 | ||
159 | spin_lock(&desc->iuspin); | 161 | spin_lock(&desc->iuspin); |
160 | clear_bit(WDM_RESPONDING, &desc->flags); | 162 | clear_bit(WDM_RESPONDING, &desc->flags); |
@@ -185,9 +187,17 @@ static void wdm_in_callback(struct urb *urb) | |||
185 | } | 187 | } |
186 | 188 | ||
187 | desc->rerr = status; | 189 | desc->rerr = status; |
188 | desc->reslength = urb->actual_length; | 190 | if (length + desc->length > desc->wMaxCommand) { |
189 | memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength); | 191 | /* The buffer would overflow */ |
190 | desc->length += desc->reslength; | 192 | set_bit(WDM_OVERFLOW, &desc->flags); |
193 | } else { | ||
194 | /* we may already be in overflow */ | ||
195 | if (!test_bit(WDM_OVERFLOW, &desc->flags)) { | ||
196 | memmove(desc->ubuf + desc->length, desc->inbuf, length); | ||
197 | desc->length += length; | ||
198 | desc->reslength = length; | ||
199 | } | ||
200 | } | ||
191 | skip_error: | 201 | skip_error: |
192 | wake_up(&desc->wait); | 202 | wake_up(&desc->wait); |
193 | 203 | ||
@@ -435,6 +445,11 @@ retry: | |||
435 | rv = -ENODEV; | 445 | rv = -ENODEV; |
436 | goto err; | 446 | goto err; |
437 | } | 447 | } |
448 | if (test_bit(WDM_OVERFLOW, &desc->flags)) { | ||
449 | clear_bit(WDM_OVERFLOW, &desc->flags); | ||
450 | rv = -ENOBUFS; | ||
451 | goto err; | ||
452 | } | ||
438 | i++; | 453 | i++; |
439 | if (file->f_flags & O_NONBLOCK) { | 454 | if (file->f_flags & O_NONBLOCK) { |
440 | if (!test_bit(WDM_READ, &desc->flags)) { | 455 | if (!test_bit(WDM_READ, &desc->flags)) { |
@@ -478,6 +493,7 @@ retry: | |||
478 | spin_unlock_irq(&desc->iuspin); | 493 | spin_unlock_irq(&desc->iuspin); |
479 | goto retry; | 494 | goto retry; |
480 | } | 495 | } |
496 | |||
481 | if (!desc->reslength) { /* zero length read */ | 497 | if (!desc->reslength) { /* zero length read */ |
482 | dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__); | 498 | dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__); |
483 | clear_bit(WDM_READ, &desc->flags); | 499 | clear_bit(WDM_READ, &desc->flags); |
@@ -1004,6 +1020,7 @@ static int wdm_post_reset(struct usb_interface *intf) | |||
1004 | struct wdm_device *desc = wdm_find_device(intf); | 1020 | struct wdm_device *desc = wdm_find_device(intf); |
1005 | int rv; | 1021 | int rv; |
1006 | 1022 | ||
1023 | clear_bit(WDM_OVERFLOW, &desc->flags); | ||
1007 | clear_bit(WDM_RESETTING, &desc->flags); | 1024 | clear_bit(WDM_RESETTING, &desc->flags); |
1008 | rv = recover_from_urb_loss(desc); | 1025 | rv = recover_from_urb_loss(desc); |
1009 | mutex_unlock(&desc->wlock); | 1026 | mutex_unlock(&desc->wlock); |