aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2009-06-11 07:36:09 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-11 11:50:58 -0400
commit10077d4a6674f535abdbe25cdecb1202af7948f1 (patch)
tree44097ec16c58c6bab56c5af4b20eba96503eeb92 /drivers/usb
parentb39933fbd304021580800796683b8ddaa3dd0a6a (diff)
tty: cdc_acm add krefs
Now we have a port structure begin using the fields and kref counts Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/class/cdc-acm.c164
-rw-r--r--drivers/usb/class/cdc-acm.h2
2 files changed, 98 insertions, 68 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 41d4ca527f82..b4e73aa759d6 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -62,7 +62,7 @@
62#include <linux/tty_flip.h> 62#include <linux/tty_flip.h>
63#include <linux/module.h> 63#include <linux/module.h>
64#include <linux/mutex.h> 64#include <linux/mutex.h>
65#include <asm/uaccess.h> 65#include <linux/uaccess.h>
66#include <linux/usb.h> 66#include <linux/usb.h>
67#include <linux/usb/cdc.h> 67#include <linux/usb/cdc.h>
68#include <asm/byteorder.h> 68#include <asm/byteorder.h>
@@ -87,7 +87,7 @@ static struct acm *acm_table[ACM_TTY_MINORS];
87 87
88static DEFINE_MUTEX(open_mutex); 88static DEFINE_MUTEX(open_mutex);
89 89
90#define ACM_READY(acm) (acm && acm->dev && acm->used) 90#define ACM_READY(acm) (acm && acm->dev && acm->port.count)
91 91
92static const struct tty_port_operations acm_port_ops = { 92static const struct tty_port_operations acm_port_ops = {
93}; 93};
@@ -265,6 +265,7 @@ static void acm_ctrl_irq(struct urb *urb)
265{ 265{
266 struct acm *acm = urb->context; 266 struct acm *acm = urb->context;
267 struct usb_cdc_notification *dr = urb->transfer_buffer; 267 struct usb_cdc_notification *dr = urb->transfer_buffer;
268 struct tty_struct *tty;
268 unsigned char *data; 269 unsigned char *data;
269 int newctrl; 270 int newctrl;
270 int retval; 271 int retval;
@@ -297,12 +298,16 @@ static void acm_ctrl_irq(struct urb *urb)
297 break; 298 break;
298 299
299 case USB_CDC_NOTIFY_SERIAL_STATE: 300 case USB_CDC_NOTIFY_SERIAL_STATE:
300 301 tty = tty_port_tty_get(&acm->port);
301 newctrl = get_unaligned_le16(data); 302 newctrl = get_unaligned_le16(data);
302 303
303 if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { 304 if (tty) {
304 dbg("calling hangup"); 305 if (!acm->clocal &&
305 tty_hangup(acm->tty); 306 (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
307 dbg("calling hangup");
308 tty_hangup(tty);
309 }
310 tty_kref_put(tty);
306 } 311 }
307 312
308 acm->ctrlin = newctrl; 313 acm->ctrlin = newctrl;
@@ -374,15 +379,14 @@ static void acm_rx_tasklet(unsigned long _acm)
374{ 379{
375 struct acm *acm = (void *)_acm; 380 struct acm *acm = (void *)_acm;
376 struct acm_rb *buf; 381 struct acm_rb *buf;
377 struct tty_struct *tty = acm->tty; 382 struct tty_struct *tty;
378 struct acm_ru *rcv; 383 struct acm_ru *rcv;
379 unsigned long flags; 384 unsigned long flags;
380 unsigned char throttled; 385 unsigned char throttled;
381 386
382 dbg("Entering acm_rx_tasklet"); 387 dbg("Entering acm_rx_tasklet");
383 388
384 if (!ACM_READY(acm)) 389 if (!ACM_READY(acm)) {
385 {
386 dbg("acm_rx_tasklet: ACM not ready"); 390 dbg("acm_rx_tasklet: ACM not ready");
387 return; 391 return;
388 } 392 }
@@ -390,12 +394,13 @@ static void acm_rx_tasklet(unsigned long _acm)
390 spin_lock_irqsave(&acm->throttle_lock, flags); 394 spin_lock_irqsave(&acm->throttle_lock, flags);
391 throttled = acm->throttle; 395 throttled = acm->throttle;
392 spin_unlock_irqrestore(&acm->throttle_lock, flags); 396 spin_unlock_irqrestore(&acm->throttle_lock, flags);
393 if (throttled) 397 if (throttled) {
394 {
395 dbg("acm_rx_tasklet: throttled"); 398 dbg("acm_rx_tasklet: throttled");
396 return; 399 return;
397 } 400 }
398 401
402 tty = tty_port_tty_get(&acm->port);
403
399next_buffer: 404next_buffer:
400 spin_lock_irqsave(&acm->read_lock, flags); 405 spin_lock_irqsave(&acm->read_lock, flags);
401 if (list_empty(&acm->filled_read_bufs)) { 406 if (list_empty(&acm->filled_read_bufs)) {
@@ -409,20 +414,22 @@ next_buffer:
409 414
410 dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size); 415 dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size);
411 416
412 tty_buffer_request_room(tty, buf->size); 417 if (tty) {
413 spin_lock_irqsave(&acm->throttle_lock, flags); 418 spin_lock_irqsave(&acm->throttle_lock, flags);
414 throttled = acm->throttle; 419 throttled = acm->throttle;
415 spin_unlock_irqrestore(&acm->throttle_lock, flags); 420 spin_unlock_irqrestore(&acm->throttle_lock, flags);
416 if (!throttled) 421 if (!throttled) {
417 tty_insert_flip_string(tty, buf->base, buf->size); 422 tty_buffer_request_room(tty, buf->size);
418 tty_flip_buffer_push(tty); 423 tty_insert_flip_string(tty, buf->base, buf->size);
419 424 tty_flip_buffer_push(tty);
420 if (throttled) { 425 } else {
421 dbg("Throttling noticed"); 426 tty_kref_put(tty);
422 spin_lock_irqsave(&acm->read_lock, flags); 427 dbg("Throttling noticed");
423 list_add(&buf->list, &acm->filled_read_bufs); 428 spin_lock_irqsave(&acm->read_lock, flags);
424 spin_unlock_irqrestore(&acm->read_lock, flags); 429 list_add(&buf->list, &acm->filled_read_bufs);
425 return; 430 spin_unlock_irqrestore(&acm->read_lock, flags);
431 return;
432 }
426 } 433 }
427 434
428 spin_lock_irqsave(&acm->read_lock, flags); 435 spin_lock_irqsave(&acm->read_lock, flags);
@@ -431,6 +438,8 @@ next_buffer:
431 goto next_buffer; 438 goto next_buffer;
432 439
433urbs: 440urbs:
441 tty_kref_put(tty);
442
434 while (!list_empty(&acm->spare_read_bufs)) { 443 while (!list_empty(&acm->spare_read_bufs)) {
435 spin_lock_irqsave(&acm->read_lock, flags); 444 spin_lock_irqsave(&acm->read_lock, flags);
436 if (list_empty(&acm->spare_read_urbs)) { 445 if (list_empty(&acm->spare_read_urbs)) {
@@ -502,11 +511,14 @@ static void acm_write_bulk(struct urb *urb)
502static void acm_softint(struct work_struct *work) 511static void acm_softint(struct work_struct *work)
503{ 512{
504 struct acm *acm = container_of(work, struct acm, work); 513 struct acm *acm = container_of(work, struct acm, work);
514 struct tty_struct *tty;
505 515
506 dev_vdbg(&acm->data->dev, "tx work\n"); 516 dev_vdbg(&acm->data->dev, "tx work\n");
507 if (!ACM_READY(acm)) 517 if (!ACM_READY(acm))
508 return; 518 return;
509 tty_wakeup(acm->tty); 519 tty = tty_port_tty_get(&acm->port);
520 tty_wakeup(tty);
521 tty_kref_put(tty);
510} 522}
511 523
512static void acm_waker(struct work_struct *waker) 524static void acm_waker(struct work_struct *waker)
@@ -546,8 +558,9 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
546 rv = 0; 558 rv = 0;
547 559
548 set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); 560 set_bit(TTY_NO_WRITE_SPLIT, &tty->flags);
561
549 tty->driver_data = acm; 562 tty->driver_data = acm;
550 acm->tty = tty; 563 tty_port_tty_set(&acm->port, tty);
551 564
552 if (usb_autopm_get_interface(acm->control) < 0) 565 if (usb_autopm_get_interface(acm->control) < 0)
553 goto early_bail; 566 goto early_bail;
@@ -555,11 +568,10 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
555 acm->control->needs_remote_wakeup = 1; 568 acm->control->needs_remote_wakeup = 1;
556 569
557 mutex_lock(&acm->mutex); 570 mutex_lock(&acm->mutex);
558 if (acm->used++) { 571 if (acm->port.count++) {
559 usb_autopm_put_interface(acm->control); 572 usb_autopm_put_interface(acm->control);
560 goto done; 573 goto done;
561 } 574 }
562
563 575
564 acm->ctrlurb->dev = acm->dev; 576 acm->ctrlurb->dev = acm->dev;
565 if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { 577 if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
@@ -570,6 +582,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
570 if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) && 582 if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) &&
571 (acm->ctrl_caps & USB_CDC_CAP_LINE)) 583 (acm->ctrl_caps & USB_CDC_CAP_LINE))
572 goto full_bailout; 584 goto full_bailout;
585
573 usb_autopm_put_interface(acm->control); 586 usb_autopm_put_interface(acm->control);
574 587
575 INIT_LIST_HEAD(&acm->spare_read_urbs); 588 INIT_LIST_HEAD(&acm->spare_read_urbs);
@@ -585,7 +598,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
585 acm->throttle = 0; 598 acm->throttle = 0;
586 599
587 tasklet_schedule(&acm->urb_task); 600 tasklet_schedule(&acm->urb_task);
588 601 rv = tty_port_block_til_ready(&acm->port, tty, filp);
589done: 602done:
590 mutex_unlock(&acm->mutex); 603 mutex_unlock(&acm->mutex);
591err_out: 604err_out:
@@ -596,16 +609,17 @@ full_bailout:
596 usb_kill_urb(acm->ctrlurb); 609 usb_kill_urb(acm->ctrlurb);
597bail_out: 610bail_out:
598 usb_autopm_put_interface(acm->control); 611 usb_autopm_put_interface(acm->control);
599 acm->used--; 612 acm->port.count--;
600 mutex_unlock(&acm->mutex); 613 mutex_unlock(&acm->mutex);
601early_bail: 614early_bail:
602 mutex_unlock(&open_mutex); 615 mutex_unlock(&open_mutex);
616 tty_port_tty_set(&acm->port, NULL);
603 return -EIO; 617 return -EIO;
604} 618}
605 619
606static void acm_tty_unregister(struct acm *acm) 620static void acm_tty_unregister(struct acm *acm)
607{ 621{
608 int i,nr; 622 int i, nr;
609 623
610 nr = acm->rx_buflimit; 624 nr = acm->rx_buflimit;
611 tty_unregister_device(acm_tty_driver, acm->minor); 625 tty_unregister_device(acm_tty_driver, acm->minor);
@@ -622,37 +636,51 @@ static void acm_tty_unregister(struct acm *acm)
622 636
623static int acm_tty_chars_in_buffer(struct tty_struct *tty); 637static int acm_tty_chars_in_buffer(struct tty_struct *tty);
624 638
639static void acm_port_down(struct acm *acm, int drain)
640{
641 int i, nr = acm->rx_buflimit;
642 mutex_lock(&open_mutex);
643 if (acm->dev) {
644 usb_autopm_get_interface(acm->control);
645 acm_set_control(acm, acm->ctrlout = 0);
646 /* try letting the last writes drain naturally */
647 if (drain) {
648 wait_event_interruptible_timeout(acm->drain_wait,
649 (ACM_NW == acm_wb_is_avail(acm)) || !acm->dev,
650 ACM_CLOSE_TIMEOUT * HZ);
651 }
652 usb_kill_urb(acm->ctrlurb);
653 for (i = 0; i < ACM_NW; i++)
654 usb_kill_urb(acm->wb[i].urb);
655 for (i = 0; i < nr; i++)
656 usb_kill_urb(acm->ru[i].urb);
657 acm->control->needs_remote_wakeup = 0;
658 usb_autopm_put_interface(acm->control);
659 }
660 mutex_unlock(&open_mutex);
661}
662
663static void acm_tty_hangup(struct tty_struct *tty)
664{
665 struct acm *acm = tty->driver_data;
666 tty_port_hangup(&acm->port);
667 acm_port_down(acm, 0);
668}
669
625static void acm_tty_close(struct tty_struct *tty, struct file *filp) 670static void acm_tty_close(struct tty_struct *tty, struct file *filp)
626{ 671{
627 struct acm *acm = tty->driver_data; 672 struct acm *acm = tty->driver_data;
628 int i,nr;
629 673
630 if (!acm || !acm->used) 674 /* Perform the closing process and see if we need to do the hardware
675 shutdown */
676 if (tty_port_close_start(&acm->port, tty, filp) == 0)
631 return; 677 return;
632 678 acm_port_down(acm, 0);
633 nr = acm->rx_buflimit; 679 tty_port_close_end(&acm->port, tty);
634 mutex_lock(&open_mutex); 680 mutex_lock(&open_mutex);
635 if (!--acm->used) { 681 tty_port_tty_set(&acm->port, NULL);
636 if (acm->dev) { 682 if (!acm->dev)
637 usb_autopm_get_interface(acm->control); 683 acm_tty_unregister(acm);
638 acm_set_control(acm, acm->ctrlout = 0);
639
640 /* try letting the last writes drain naturally */
641 wait_event_interruptible_timeout(acm->drain_wait,
642 (ACM_NW == acm_wb_is_avail(acm))
643 || !acm->dev,
644 ACM_CLOSE_TIMEOUT * HZ);
645
646 usb_kill_urb(acm->ctrlurb);
647 for (i = 0; i < ACM_NW; i++)
648 usb_kill_urb(acm->wb[i].urb);
649 for (i = 0; i < nr; i++)
650 usb_kill_urb(acm->ru[i].urb);
651 acm->control->needs_remote_wakeup = 0;
652 usb_autopm_put_interface(acm->control);
653 } else
654 acm_tty_unregister(acm);
655 }
656 mutex_unlock(&open_mutex); 684 mutex_unlock(&open_mutex);
657} 685}
658 686
@@ -885,8 +913,8 @@ static int acm_write_buffers_alloc(struct acm *acm)
885 return 0; 913 return 0;
886} 914}
887 915
888static int acm_probe (struct usb_interface *intf, 916static int acm_probe(struct usb_interface *intf,
889 const struct usb_device_id *id) 917 const struct usb_device_id *id)
890{ 918{
891 struct usb_cdc_union_desc *union_header = NULL; 919 struct usb_cdc_union_desc *union_header = NULL;
892 struct usb_cdc_country_functional_desc *cfd = NULL; 920 struct usb_cdc_country_functional_desc *cfd = NULL;
@@ -1232,6 +1260,7 @@ static void acm_disconnect(struct usb_interface *intf)
1232{ 1260{
1233 struct acm *acm = usb_get_intfdata(intf); 1261 struct acm *acm = usb_get_intfdata(intf);
1234 struct usb_device *usb_dev = interface_to_usbdev(intf); 1262 struct usb_device *usb_dev = interface_to_usbdev(intf);
1263 struct tty_struct *tty;
1235 1264
1236 /* sibling interface is already cleaning up */ 1265 /* sibling interface is already cleaning up */
1237 if (!acm) 1266 if (!acm)
@@ -1258,16 +1287,18 @@ static void acm_disconnect(struct usb_interface *intf)
1258 usb_driver_release_interface(&acm_driver, intf == acm->control ? 1287 usb_driver_release_interface(&acm_driver, intf == acm->control ?
1259 acm->data : acm->control); 1288 acm->data : acm->control);
1260 1289
1261 if (!acm->used) { 1290 if (acm->port.count == 0) {
1262 acm_tty_unregister(acm); 1291 acm_tty_unregister(acm);
1263 mutex_unlock(&open_mutex); 1292 mutex_unlock(&open_mutex);
1264 return; 1293 return;
1265 } 1294 }
1266 1295
1267 mutex_unlock(&open_mutex); 1296 mutex_unlock(&open_mutex);
1268 1297 tty = tty_port_tty_get(&acm->port);
1269 if (acm->tty) 1298 if (tty) {
1270 tty_hangup(acm->tty); 1299 tty_hangup(tty);
1300 tty_kref_put(tty);
1301 }
1271} 1302}
1272 1303
1273#ifdef CONFIG_PM 1304#ifdef CONFIG_PM
@@ -1302,7 +1333,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message)
1302 */ 1333 */
1303 mutex_lock(&acm->mutex); 1334 mutex_lock(&acm->mutex);
1304 1335
1305 if (acm->used) 1336 if (acm->port.count)
1306 stop_data_traffic(acm); 1337 stop_data_traffic(acm);
1307 1338
1308 mutex_unlock(&acm->mutex); 1339 mutex_unlock(&acm->mutex);
@@ -1324,7 +1355,7 @@ static int acm_resume(struct usb_interface *intf)
1324 return 0; 1355 return 0;
1325 1356
1326 mutex_lock(&acm->mutex); 1357 mutex_lock(&acm->mutex);
1327 if (acm->used) { 1358 if (acm->port.count) {
1328 rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); 1359 rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);
1329 if (rv < 0) 1360 if (rv < 0)
1330 goto err_out; 1361 goto err_out;
@@ -1434,6 +1465,7 @@ static struct usb_driver acm_driver = {
1434static const struct tty_operations acm_ops = { 1465static const struct tty_operations acm_ops = {
1435 .open = acm_tty_open, 1466 .open = acm_tty_open,
1436 .close = acm_tty_close, 1467 .close = acm_tty_close,
1468 .hangup = acm_tty_hangup,
1437 .write = acm_tty_write, 1469 .write = acm_tty_write,
1438 .write_room = acm_tty_write_room, 1470 .write_room = acm_tty_write_room,
1439 .ioctl = acm_tty_ioctl, 1471 .ioctl = acm_tty_ioctl,
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index 19967cdb2691..4c3856420add 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -89,7 +89,6 @@ struct acm {
89 struct usb_device *dev; /* the corresponding usb device */ 89 struct usb_device *dev; /* the corresponding usb device */
90 struct usb_interface *control; /* control interface */ 90 struct usb_interface *control; /* control interface */
91 struct usb_interface *data; /* data interface */ 91 struct usb_interface *data; /* data interface */
92 struct tty_struct *tty; /* the corresponding tty */
93 struct tty_port port; /* our tty port data */ 92 struct tty_port port; /* our tty port data */
94 struct urb *ctrlurb; /* urbs */ 93 struct urb *ctrlurb; /* urbs */
95 u8 *ctrl_buffer; /* buffers of urbs */ 94 u8 *ctrl_buffer; /* buffers of urbs */
@@ -121,7 +120,6 @@ struct acm {
121 unsigned int ctrlout; /* output control lines (DTR, RTS) */ 120 unsigned int ctrlout; /* output control lines (DTR, RTS) */
122 unsigned int writesize; /* max packet size for the output bulk endpoint */ 121 unsigned int writesize; /* max packet size for the output bulk endpoint */
123 unsigned int readsize,ctrlsize; /* buffer sizes for freeing */ 122 unsigned int readsize,ctrlsize; /* buffer sizes for freeing */
124 unsigned int used; /* someone has this acm's device open */
125 unsigned int minor; /* acm minor number */ 123 unsigned int minor; /* acm minor number */
126 unsigned char throttle; /* throttled by tty layer */ 124 unsigned char throttle; /* throttled by tty layer */
127 unsigned char clocal; /* termios CLOCAL */ 125 unsigned char clocal; /* termios CLOCAL */