diff options
author | Michal Marek <mmarek@suse.cz> | 2011-03-09 10:15:44 -0500 |
---|---|---|
committer | Michal Marek <mmarek@suse.cz> | 2011-03-09 10:15:44 -0500 |
commit | 2d8ad8719591fa803b0d589ed057fa46f49b7155 (patch) | |
tree | 4ae051577dad1161c91dafbf4207bb10a9dc91bb /drivers/usb/class/cdc-acm.c | |
parent | 9b4ce7bce5f30712fd926ab4599a803314a07719 (diff) | |
parent | c56eb8fb6dccb83d9fe62fd4dc00c834de9bc470 (diff) |
Merge commit 'v2.6.38-rc1' into kbuild/packaging
Diffstat (limited to 'drivers/usb/class/cdc-acm.c')
-rw-r--r-- | drivers/usb/class/cdc-acm.c | 151 |
1 files changed, 98 insertions, 53 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 34d4eb98829e..d6ede989ff22 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * cdc-acm.c | 2 | * cdc-acm.c |
3 | * | 3 | * |
4 | * Copyright (c) 1999 Armin Fuerst <fuerst@in.tum.de> | 4 | * Copyright (c) 1999 Armin Fuerst <fuerst@in.tum.de> |
5 | * Copyright (c) 1999 Pavel Machek <pavel@suse.cz> | 5 | * Copyright (c) 1999 Pavel Machek <pavel@ucw.cz> |
6 | * Copyright (c) 1999 Johannes Erdfelt <johannes@erdfelt.com> | 6 | * Copyright (c) 1999 Johannes Erdfelt <johannes@erdfelt.com> |
7 | * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz> | 7 | * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz> |
8 | * Copyright (c) 2004 Oliver Neukum <oliver@neukum.name> | 8 | * Copyright (c) 2004 Oliver Neukum <oliver@neukum.name> |
@@ -170,6 +170,7 @@ static void acm_write_done(struct acm *acm, struct acm_wb *wb) | |||
170 | { | 170 | { |
171 | wb->use = 0; | 171 | wb->use = 0; |
172 | acm->transmitting--; | 172 | acm->transmitting--; |
173 | usb_autopm_put_interface_async(acm->control); | ||
173 | } | 174 | } |
174 | 175 | ||
175 | /* | 176 | /* |
@@ -211,9 +212,12 @@ static int acm_write_start(struct acm *acm, int wbn) | |||
211 | } | 212 | } |
212 | 213 | ||
213 | dbg("%s susp_count: %d", __func__, acm->susp_count); | 214 | dbg("%s susp_count: %d", __func__, acm->susp_count); |
215 | usb_autopm_get_interface_async(acm->control); | ||
214 | if (acm->susp_count) { | 216 | if (acm->susp_count) { |
215 | acm->delayed_wb = wb; | 217 | if (!acm->delayed_wb) |
216 | schedule_work(&acm->waker); | 218 | acm->delayed_wb = wb; |
219 | else | ||
220 | usb_autopm_put_interface_async(acm->control); | ||
217 | spin_unlock_irqrestore(&acm->write_lock, flags); | 221 | spin_unlock_irqrestore(&acm->write_lock, flags); |
218 | return 0; /* A white lie */ | 222 | return 0; /* A white lie */ |
219 | } | 223 | } |
@@ -424,7 +428,6 @@ next_buffer: | |||
424 | throttled = acm->throttle; | 428 | throttled = acm->throttle; |
425 | spin_unlock_irqrestore(&acm->throttle_lock, flags); | 429 | spin_unlock_irqrestore(&acm->throttle_lock, flags); |
426 | if (!throttled) { | 430 | if (!throttled) { |
427 | tty_buffer_request_room(tty, buf->size); | ||
428 | tty_insert_flip_string(tty, buf->base, buf->size); | 431 | tty_insert_flip_string(tty, buf->base, buf->size); |
429 | tty_flip_buffer_push(tty); | 432 | tty_flip_buffer_push(tty); |
430 | } else { | 433 | } else { |
@@ -534,23 +537,6 @@ static void acm_softint(struct work_struct *work) | |||
534 | tty_kref_put(tty); | 537 | tty_kref_put(tty); |
535 | } | 538 | } |
536 | 539 | ||
537 | static void acm_waker(struct work_struct *waker) | ||
538 | { | ||
539 | struct acm *acm = container_of(waker, struct acm, waker); | ||
540 | int rv; | ||
541 | |||
542 | rv = usb_autopm_get_interface(acm->control); | ||
543 | if (rv < 0) { | ||
544 | dev_err(&acm->dev->dev, "Autopm failure in %s\n", __func__); | ||
545 | return; | ||
546 | } | ||
547 | if (acm->delayed_wb) { | ||
548 | acm_start_wb(acm, acm->delayed_wb); | ||
549 | acm->delayed_wb = NULL; | ||
550 | } | ||
551 | usb_autopm_put_interface(acm->control); | ||
552 | } | ||
553 | |||
554 | /* | 540 | /* |
555 | * TTY handlers | 541 | * TTY handlers |
556 | */ | 542 | */ |
@@ -566,7 +552,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) | |||
566 | 552 | ||
567 | acm = acm_table[tty->index]; | 553 | acm = acm_table[tty->index]; |
568 | if (!acm || !acm->dev) | 554 | if (!acm || !acm->dev) |
569 | goto err_out; | 555 | goto out; |
570 | else | 556 | else |
571 | rv = 0; | 557 | rv = 0; |
572 | 558 | ||
@@ -582,8 +568,9 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) | |||
582 | 568 | ||
583 | mutex_lock(&acm->mutex); | 569 | mutex_lock(&acm->mutex); |
584 | if (acm->port.count++) { | 570 | if (acm->port.count++) { |
571 | mutex_unlock(&acm->mutex); | ||
585 | usb_autopm_put_interface(acm->control); | 572 | usb_autopm_put_interface(acm->control); |
586 | goto done; | 573 | goto out; |
587 | } | 574 | } |
588 | 575 | ||
589 | acm->ctrlurb->dev = acm->dev; | 576 | acm->ctrlurb->dev = acm->dev; |
@@ -612,18 +599,18 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) | |||
612 | set_bit(ASYNCB_INITIALIZED, &acm->port.flags); | 599 | set_bit(ASYNCB_INITIALIZED, &acm->port.flags); |
613 | rv = tty_port_block_til_ready(&acm->port, tty, filp); | 600 | rv = tty_port_block_til_ready(&acm->port, tty, filp); |
614 | tasklet_schedule(&acm->urb_task); | 601 | tasklet_schedule(&acm->urb_task); |
615 | done: | 602 | |
616 | mutex_unlock(&acm->mutex); | 603 | mutex_unlock(&acm->mutex); |
617 | err_out: | 604 | out: |
618 | mutex_unlock(&open_mutex); | 605 | mutex_unlock(&open_mutex); |
619 | return rv; | 606 | return rv; |
620 | 607 | ||
621 | full_bailout: | 608 | full_bailout: |
622 | usb_kill_urb(acm->ctrlurb); | 609 | usb_kill_urb(acm->ctrlurb); |
623 | bail_out: | 610 | bail_out: |
624 | usb_autopm_put_interface(acm->control); | ||
625 | acm->port.count--; | 611 | acm->port.count--; |
626 | mutex_unlock(&acm->mutex); | 612 | mutex_unlock(&acm->mutex); |
613 | usb_autopm_put_interface(acm->control); | ||
627 | early_bail: | 614 | early_bail: |
628 | mutex_unlock(&open_mutex); | 615 | mutex_unlock(&open_mutex); |
629 | tty_port_tty_set(&acm->port, NULL); | 616 | tty_port_tty_set(&acm->port, NULL); |
@@ -649,19 +636,13 @@ static void acm_tty_unregister(struct acm *acm) | |||
649 | 636 | ||
650 | static int acm_tty_chars_in_buffer(struct tty_struct *tty); | 637 | static int acm_tty_chars_in_buffer(struct tty_struct *tty); |
651 | 638 | ||
652 | static void acm_port_down(struct acm *acm, int drain) | 639 | static void acm_port_down(struct acm *acm) |
653 | { | 640 | { |
654 | int i, nr = acm->rx_buflimit; | 641 | int i, nr = acm->rx_buflimit; |
655 | mutex_lock(&open_mutex); | 642 | mutex_lock(&open_mutex); |
656 | if (acm->dev) { | 643 | if (acm->dev) { |
657 | usb_autopm_get_interface(acm->control); | 644 | usb_autopm_get_interface(acm->control); |
658 | acm_set_control(acm, acm->ctrlout = 0); | 645 | acm_set_control(acm, acm->ctrlout = 0); |
659 | /* try letting the last writes drain naturally */ | ||
660 | if (drain) { | ||
661 | wait_event_interruptible_timeout(acm->drain_wait, | ||
662 | (ACM_NW == acm_wb_is_avail(acm)) || !acm->dev, | ||
663 | ACM_CLOSE_TIMEOUT * HZ); | ||
664 | } | ||
665 | usb_kill_urb(acm->ctrlurb); | 646 | usb_kill_urb(acm->ctrlurb); |
666 | for (i = 0; i < ACM_NW; i++) | 647 | for (i = 0; i < ACM_NW; i++) |
667 | usb_kill_urb(acm->wb[i].urb); | 648 | usb_kill_urb(acm->wb[i].urb); |
@@ -677,7 +658,7 @@ static void acm_tty_hangup(struct tty_struct *tty) | |||
677 | { | 658 | { |
678 | struct acm *acm = tty->driver_data; | 659 | struct acm *acm = tty->driver_data; |
679 | tty_port_hangup(&acm->port); | 660 | tty_port_hangup(&acm->port); |
680 | acm_port_down(acm, 0); | 661 | acm_port_down(acm); |
681 | } | 662 | } |
682 | 663 | ||
683 | static void acm_tty_close(struct tty_struct *tty, struct file *filp) | 664 | static void acm_tty_close(struct tty_struct *tty, struct file *filp) |
@@ -698,7 +679,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp) | |||
698 | mutex_unlock(&open_mutex); | 679 | mutex_unlock(&open_mutex); |
699 | return; | 680 | return; |
700 | } | 681 | } |
701 | acm_port_down(acm, 0); | 682 | acm_port_down(acm); |
702 | tty_port_close_end(&acm->port, tty); | 683 | tty_port_close_end(&acm->port, tty); |
703 | tty_port_tty_set(&acm->port, NULL); | 684 | tty_port_tty_set(&acm->port, NULL); |
704 | } | 685 | } |
@@ -905,7 +886,7 @@ static void acm_write_buffers_free(struct acm *acm) | |||
905 | struct usb_device *usb_dev = interface_to_usbdev(acm->control); | 886 | struct usb_device *usb_dev = interface_to_usbdev(acm->control); |
906 | 887 | ||
907 | for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) | 888 | for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) |
908 | usb_buffer_free(usb_dev, acm->writesize, wb->buf, wb->dmah); | 889 | usb_free_coherent(usb_dev, acm->writesize, wb->buf, wb->dmah); |
909 | } | 890 | } |
910 | 891 | ||
911 | static void acm_read_buffers_free(struct acm *acm) | 892 | static void acm_read_buffers_free(struct acm *acm) |
@@ -914,8 +895,8 @@ static void acm_read_buffers_free(struct acm *acm) | |||
914 | int i, n = acm->rx_buflimit; | 895 | int i, n = acm->rx_buflimit; |
915 | 896 | ||
916 | for (i = 0; i < n; i++) | 897 | for (i = 0; i < n; i++) |
917 | usb_buffer_free(usb_dev, acm->readsize, | 898 | usb_free_coherent(usb_dev, acm->readsize, |
918 | acm->rb[i].base, acm->rb[i].dma); | 899 | acm->rb[i].base, acm->rb[i].dma); |
919 | } | 900 | } |
920 | 901 | ||
921 | /* Little helper: write buffers allocate */ | 902 | /* Little helper: write buffers allocate */ |
@@ -925,13 +906,13 @@ static int acm_write_buffers_alloc(struct acm *acm) | |||
925 | struct acm_wb *wb; | 906 | struct acm_wb *wb; |
926 | 907 | ||
927 | for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) { | 908 | for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) { |
928 | wb->buf = usb_buffer_alloc(acm->dev, acm->writesize, GFP_KERNEL, | 909 | wb->buf = usb_alloc_coherent(acm->dev, acm->writesize, GFP_KERNEL, |
929 | &wb->dmah); | 910 | &wb->dmah); |
930 | if (!wb->buf) { | 911 | if (!wb->buf) { |
931 | while (i != 0) { | 912 | while (i != 0) { |
932 | --i; | 913 | --i; |
933 | --wb; | 914 | --wb; |
934 | usb_buffer_free(acm->dev, acm->writesize, | 915 | usb_free_coherent(acm->dev, acm->writesize, |
935 | wb->buf, wb->dmah); | 916 | wb->buf, wb->dmah); |
936 | } | 917 | } |
937 | return -ENOMEM; | 918 | return -ENOMEM; |
@@ -984,7 +965,8 @@ static int acm_probe(struct usb_interface *intf, | |||
984 | } | 965 | } |
985 | 966 | ||
986 | if (!buflen) { | 967 | if (!buflen) { |
987 | if (intf->cur_altsetting->endpoint->extralen && | 968 | if (intf->cur_altsetting->endpoint && |
969 | intf->cur_altsetting->endpoint->extralen && | ||
988 | intf->cur_altsetting->endpoint->extra) { | 970 | intf->cur_altsetting->endpoint->extra) { |
989 | dev_dbg(&intf->dev, | 971 | dev_dbg(&intf->dev, |
990 | "Seeking extra descriptors on endpoint\n"); | 972 | "Seeking extra descriptors on endpoint\n"); |
@@ -1023,7 +1005,7 @@ static int acm_probe(struct usb_interface *intf, | |||
1023 | case USB_CDC_CALL_MANAGEMENT_TYPE: | 1005 | case USB_CDC_CALL_MANAGEMENT_TYPE: |
1024 | call_management_function = buffer[3]; | 1006 | call_management_function = buffer[3]; |
1025 | call_interface_num = buffer[4]; | 1007 | call_interface_num = buffer[4]; |
1026 | if ((call_management_function & 3) != 3) | 1008 | if ( (quirks & NOT_A_MODEM) == 0 && (call_management_function & 3) != 3) |
1027 | dev_err(&intf->dev, "This device cannot do calls on its own. It is not a modem.\n"); | 1009 | dev_err(&intf->dev, "This device cannot do calls on its own. It is not a modem.\n"); |
1028 | break; | 1010 | break; |
1029 | default: | 1011 | default: |
@@ -1178,7 +1160,6 @@ made_compressed_probe: | |||
1178 | acm->urb_task.func = acm_rx_tasklet; | 1160 | acm->urb_task.func = acm_rx_tasklet; |
1179 | acm->urb_task.data = (unsigned long) acm; | 1161 | acm->urb_task.data = (unsigned long) acm; |
1180 | INIT_WORK(&acm->work, acm_softint); | 1162 | INIT_WORK(&acm->work, acm_softint); |
1181 | INIT_WORK(&acm->waker, acm_waker); | ||
1182 | init_waitqueue_head(&acm->drain_wait); | 1163 | init_waitqueue_head(&acm->drain_wait); |
1183 | spin_lock_init(&acm->throttle_lock); | 1164 | spin_lock_init(&acm->throttle_lock); |
1184 | spin_lock_init(&acm->write_lock); | 1165 | spin_lock_init(&acm->write_lock); |
@@ -1191,7 +1172,7 @@ made_compressed_probe: | |||
1191 | tty_port_init(&acm->port); | 1172 | tty_port_init(&acm->port); |
1192 | acm->port.ops = &acm_port_ops; | 1173 | acm->port.ops = &acm_port_ops; |
1193 | 1174 | ||
1194 | buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); | 1175 | buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); |
1195 | if (!buf) { | 1176 | if (!buf) { |
1196 | dev_dbg(&intf->dev, "out of memory (ctrl buffer alloc)\n"); | 1177 | dev_dbg(&intf->dev, "out of memory (ctrl buffer alloc)\n"); |
1197 | goto alloc_fail2; | 1178 | goto alloc_fail2; |
@@ -1215,7 +1196,7 @@ made_compressed_probe: | |||
1215 | if (rcv->urb == NULL) { | 1196 | if (rcv->urb == NULL) { |
1216 | dev_dbg(&intf->dev, | 1197 | dev_dbg(&intf->dev, |
1217 | "out of memory (read urbs usb_alloc_urb)\n"); | 1198 | "out of memory (read urbs usb_alloc_urb)\n"); |
1218 | goto alloc_fail7; | 1199 | goto alloc_fail6; |
1219 | } | 1200 | } |
1220 | 1201 | ||
1221 | rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 1202 | rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
@@ -1224,11 +1205,11 @@ made_compressed_probe: | |||
1224 | for (i = 0; i < num_rx_buf; i++) { | 1205 | for (i = 0; i < num_rx_buf; i++) { |
1225 | struct acm_rb *rb = &(acm->rb[i]); | 1206 | struct acm_rb *rb = &(acm->rb[i]); |
1226 | 1207 | ||
1227 | rb->base = usb_buffer_alloc(acm->dev, readsize, | 1208 | rb->base = usb_alloc_coherent(acm->dev, readsize, |
1228 | GFP_KERNEL, &rb->dma); | 1209 | GFP_KERNEL, &rb->dma); |
1229 | if (!rb->base) { | 1210 | if (!rb->base) { |
1230 | dev_dbg(&intf->dev, | 1211 | dev_dbg(&intf->dev, |
1231 | "out of memory (read bufs usb_buffer_alloc)\n"); | 1212 | "out of memory (read bufs usb_alloc_coherent)\n"); |
1232 | goto alloc_fail7; | 1213 | goto alloc_fail7; |
1233 | } | 1214 | } |
1234 | } | 1215 | } |
@@ -1239,7 +1220,7 @@ made_compressed_probe: | |||
1239 | if (snd->urb == NULL) { | 1220 | if (snd->urb == NULL) { |
1240 | dev_dbg(&intf->dev, | 1221 | dev_dbg(&intf->dev, |
1241 | "out of memory (write urbs usb_alloc_urb)"); | 1222 | "out of memory (write urbs usb_alloc_urb)"); |
1242 | goto alloc_fail7; | 1223 | goto alloc_fail8; |
1243 | } | 1224 | } |
1244 | 1225 | ||
1245 | if (usb_endpoint_xfer_int(epwrite)) | 1226 | if (usb_endpoint_xfer_int(epwrite)) |
@@ -1278,6 +1259,7 @@ made_compressed_probe: | |||
1278 | i = device_create_file(&intf->dev, | 1259 | i = device_create_file(&intf->dev, |
1279 | &dev_attr_iCountryCodeRelDate); | 1260 | &dev_attr_iCountryCodeRelDate); |
1280 | if (i < 0) { | 1261 | if (i < 0) { |
1262 | device_remove_file(&intf->dev, &dev_attr_wCountryCodes); | ||
1281 | kfree(acm->country_codes); | 1263 | kfree(acm->country_codes); |
1282 | goto skip_countries; | 1264 | goto skip_countries; |
1283 | } | 1265 | } |
@@ -1314,13 +1296,14 @@ alloc_fail8: | |||
1314 | usb_free_urb(acm->wb[i].urb); | 1296 | usb_free_urb(acm->wb[i].urb); |
1315 | alloc_fail7: | 1297 | alloc_fail7: |
1316 | acm_read_buffers_free(acm); | 1298 | acm_read_buffers_free(acm); |
1299 | alloc_fail6: | ||
1317 | for (i = 0; i < num_rx_buf; i++) | 1300 | for (i = 0; i < num_rx_buf; i++) |
1318 | usb_free_urb(acm->ru[i].urb); | 1301 | usb_free_urb(acm->ru[i].urb); |
1319 | usb_free_urb(acm->ctrlurb); | 1302 | usb_free_urb(acm->ctrlurb); |
1320 | alloc_fail5: | 1303 | alloc_fail5: |
1321 | acm_write_buffers_free(acm); | 1304 | acm_write_buffers_free(acm); |
1322 | alloc_fail4: | 1305 | alloc_fail4: |
1323 | usb_buffer_free(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); | 1306 | usb_free_coherent(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); |
1324 | alloc_fail2: | 1307 | alloc_fail2: |
1325 | kfree(acm); | 1308 | kfree(acm); |
1326 | alloc_fail: | 1309 | alloc_fail: |
@@ -1343,7 +1326,6 @@ static void stop_data_traffic(struct acm *acm) | |||
1343 | tasklet_enable(&acm->urb_task); | 1326 | tasklet_enable(&acm->urb_task); |
1344 | 1327 | ||
1345 | cancel_work_sync(&acm->work); | 1328 | cancel_work_sync(&acm->work); |
1346 | cancel_work_sync(&acm->waker); | ||
1347 | } | 1329 | } |
1348 | 1330 | ||
1349 | static void acm_disconnect(struct usb_interface *intf) | 1331 | static void acm_disconnect(struct usb_interface *intf) |
@@ -1371,8 +1353,8 @@ static void acm_disconnect(struct usb_interface *intf) | |||
1371 | stop_data_traffic(acm); | 1353 | stop_data_traffic(acm); |
1372 | 1354 | ||
1373 | acm_write_buffers_free(acm); | 1355 | acm_write_buffers_free(acm); |
1374 | usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, | 1356 | usb_free_coherent(usb_dev, acm->ctrlsize, acm->ctrl_buffer, |
1375 | acm->ctrl_dma); | 1357 | acm->ctrl_dma); |
1376 | acm_read_buffers_free(acm); | 1358 | acm_read_buffers_free(acm); |
1377 | 1359 | ||
1378 | if (!acm->combined_interfaces) | 1360 | if (!acm->combined_interfaces) |
@@ -1435,6 +1417,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) | |||
1435 | static int acm_resume(struct usb_interface *intf) | 1417 | static int acm_resume(struct usb_interface *intf) |
1436 | { | 1418 | { |
1437 | struct acm *acm = usb_get_intfdata(intf); | 1419 | struct acm *acm = usb_get_intfdata(intf); |
1420 | struct acm_wb *wb; | ||
1438 | int rv = 0; | 1421 | int rv = 0; |
1439 | int cnt; | 1422 | int cnt; |
1440 | 1423 | ||
@@ -1449,6 +1432,21 @@ static int acm_resume(struct usb_interface *intf) | |||
1449 | mutex_lock(&acm->mutex); | 1432 | mutex_lock(&acm->mutex); |
1450 | if (acm->port.count) { | 1433 | if (acm->port.count) { |
1451 | rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); | 1434 | rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); |
1435 | |||
1436 | spin_lock_irq(&acm->write_lock); | ||
1437 | if (acm->delayed_wb) { | ||
1438 | wb = acm->delayed_wb; | ||
1439 | acm->delayed_wb = NULL; | ||
1440 | spin_unlock_irq(&acm->write_lock); | ||
1441 | acm_start_wb(acm, wb); | ||
1442 | } else { | ||
1443 | spin_unlock_irq(&acm->write_lock); | ||
1444 | } | ||
1445 | |||
1446 | /* | ||
1447 | * delayed error checking because we must | ||
1448 | * do the write path at all cost | ||
1449 | */ | ||
1452 | if (rv < 0) | 1450 | if (rv < 0) |
1453 | goto err_out; | 1451 | goto err_out; |
1454 | 1452 | ||
@@ -1460,6 +1458,23 @@ err_out: | |||
1460 | return rv; | 1458 | return rv; |
1461 | } | 1459 | } |
1462 | 1460 | ||
1461 | static int acm_reset_resume(struct usb_interface *intf) | ||
1462 | { | ||
1463 | struct acm *acm = usb_get_intfdata(intf); | ||
1464 | struct tty_struct *tty; | ||
1465 | |||
1466 | mutex_lock(&acm->mutex); | ||
1467 | if (acm->port.count) { | ||
1468 | tty = tty_port_tty_get(&acm->port); | ||
1469 | if (tty) { | ||
1470 | tty_hangup(tty); | ||
1471 | tty_kref_put(tty); | ||
1472 | } | ||
1473 | } | ||
1474 | mutex_unlock(&acm->mutex); | ||
1475 | return acm_resume(intf); | ||
1476 | } | ||
1477 | |||
1463 | #endif /* CONFIG_PM */ | 1478 | #endif /* CONFIG_PM */ |
1464 | 1479 | ||
1465 | #define NOKIA_PCSUITE_ACM_INFO(x) \ | 1480 | #define NOKIA_PCSUITE_ACM_INFO(x) \ |
@@ -1467,11 +1482,16 @@ err_out: | |||
1467 | USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \ | 1482 | USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \ |
1468 | USB_CDC_ACM_PROTO_VENDOR) | 1483 | USB_CDC_ACM_PROTO_VENDOR) |
1469 | 1484 | ||
1485 | #define SAMSUNG_PCSUITE_ACM_INFO(x) \ | ||
1486 | USB_DEVICE_AND_INTERFACE_INFO(0x04e7, x, \ | ||
1487 | USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \ | ||
1488 | USB_CDC_ACM_PROTO_VENDOR) | ||
1489 | |||
1470 | /* | 1490 | /* |
1471 | * USB driver structure. | 1491 | * USB driver structure. |
1472 | */ | 1492 | */ |
1473 | 1493 | ||
1474 | static struct usb_device_id acm_ids[] = { | 1494 | static const struct usb_device_id acm_ids[] = { |
1475 | /* quirky and broken devices */ | 1495 | /* quirky and broken devices */ |
1476 | { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ | 1496 | { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ |
1477 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1497 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
@@ -1524,6 +1544,9 @@ static struct usb_device_id acm_ids[] = { | |||
1524 | { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ | 1544 | { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ |
1525 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ | 1545 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ |
1526 | }, | 1546 | }, |
1547 | { USB_DEVICE(0x1576, 0x03b1), /* Maretron USB100 */ | ||
1548 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ | ||
1549 | }, | ||
1527 | 1550 | ||
1528 | /* Nokia S60 phones expose two ACM channels. The first is | 1551 | /* Nokia S60 phones expose two ACM channels. The first is |
1529 | * a modem and is picked up by the standard AT-command | 1552 | * a modem and is picked up by the standard AT-command |
@@ -1573,9 +1596,30 @@ static struct usb_device_id acm_ids[] = { | |||
1573 | { NOKIA_PCSUITE_ACM_INFO(0x00e9), }, /* Nokia 5320 XpressMusic */ | 1596 | { NOKIA_PCSUITE_ACM_INFO(0x00e9), }, /* Nokia 5320 XpressMusic */ |
1574 | { NOKIA_PCSUITE_ACM_INFO(0x0108), }, /* Nokia 5320 XpressMusic 2G */ | 1597 | { NOKIA_PCSUITE_ACM_INFO(0x0108), }, /* Nokia 5320 XpressMusic 2G */ |
1575 | { NOKIA_PCSUITE_ACM_INFO(0x01f5), }, /* Nokia N97, RM-505 */ | 1598 | { NOKIA_PCSUITE_ACM_INFO(0x01f5), }, /* Nokia N97, RM-505 */ |
1599 | { NOKIA_PCSUITE_ACM_INFO(0x02e3), }, /* Nokia 5230, RM-588 */ | ||
1600 | { NOKIA_PCSUITE_ACM_INFO(0x0178), }, /* Nokia E63 */ | ||
1601 | { NOKIA_PCSUITE_ACM_INFO(0x010e), }, /* Nokia E75 */ | ||
1602 | { NOKIA_PCSUITE_ACM_INFO(0x02d9), }, /* Nokia 6760 Slide */ | ||
1603 | { NOKIA_PCSUITE_ACM_INFO(0x01d0), }, /* Nokia E52 */ | ||
1604 | { NOKIA_PCSUITE_ACM_INFO(0x0223), }, /* Nokia E72 */ | ||
1605 | { NOKIA_PCSUITE_ACM_INFO(0x0275), }, /* Nokia X6 */ | ||
1606 | { NOKIA_PCSUITE_ACM_INFO(0x026c), }, /* Nokia N97 Mini */ | ||
1607 | { NOKIA_PCSUITE_ACM_INFO(0x0154), }, /* Nokia 5800 XpressMusic */ | ||
1608 | { NOKIA_PCSUITE_ACM_INFO(0x04ce), }, /* Nokia E90 */ | ||
1609 | { NOKIA_PCSUITE_ACM_INFO(0x01d4), }, /* Nokia E55 */ | ||
1610 | { SAMSUNG_PCSUITE_ACM_INFO(0x6651), }, /* Samsung GTi8510 (INNOV8) */ | ||
1576 | 1611 | ||
1577 | /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ | 1612 | /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ |
1578 | 1613 | ||
1614 | /* Support Lego NXT using pbLua firmware */ | ||
1615 | { USB_DEVICE(0x0694, 0xff00), | ||
1616 | .driver_info = NOT_A_MODEM, | ||
1617 | }, | ||
1618 | |||
1619 | /* control interfaces without any protocol set */ | ||
1620 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | ||
1621 | USB_CDC_PROTO_NONE) }, | ||
1622 | |||
1579 | /* control interfaces with various AT-command sets */ | 1623 | /* control interfaces with various AT-command sets */ |
1580 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | 1624 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, |
1581 | USB_CDC_ACM_PROTO_AT_V25TER) }, | 1625 | USB_CDC_ACM_PROTO_AT_V25TER) }, |
@@ -1602,6 +1646,7 @@ static struct usb_driver acm_driver = { | |||
1602 | #ifdef CONFIG_PM | 1646 | #ifdef CONFIG_PM |
1603 | .suspend = acm_suspend, | 1647 | .suspend = acm_suspend, |
1604 | .resume = acm_resume, | 1648 | .resume = acm_resume, |
1649 | .reset_resume = acm_reset_resume, | ||
1605 | #endif | 1650 | #endif |
1606 | .id_table = acm_ids, | 1651 | .id_table = acm_ids, |
1607 | #ifdef CONFIG_PM | 1652 | #ifdef CONFIG_PM |