diff options
author | Alan Cox <alan@redhat.com> | 2008-10-13 05:39:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-13 12:51:41 -0400 |
commit | 4a90f09b20f4622dcbff1f0e1e6bae1704f8ad8c (patch) | |
tree | 9b275f88f2705cb10121d5982741aef3a088a7c8 /drivers/usb/serial/keyspan.c | |
parent | 95f9bfc6b76e862265a2d70ae061eec18fe14140 (diff) |
tty: usb-serial krefs
Use kref in the USB serial drivers so that we don't free tty structures
from under the URB receive handlers as has historically been the case if
you were unlucky. This also gives us a framework for general tty drivers to
use tty_port objects and refcount.
Contains two err->dev_err changes merged together to fix clashes in the
-next tree.
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/usb/serial/keyspan.c')
-rw-r--r-- | drivers/usb/serial/keyspan.c | 77 |
1 files changed, 40 insertions, 37 deletions
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 704716f6f6d3..15447af48691 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c | |||
@@ -430,7 +430,7 @@ static void usa26_indat_callback(struct urb *urb) | |||
430 | } | 430 | } |
431 | 431 | ||
432 | port = urb->context; | 432 | port = urb->context; |
433 | tty = port->port.tty; | 433 | tty = tty_port_tty_get(&port->port); |
434 | if (tty && urb->actual_length) { | 434 | if (tty && urb->actual_length) { |
435 | /* 0x80 bit is error flag */ | 435 | /* 0x80 bit is error flag */ |
436 | if ((data[0] & 0x80) == 0) { | 436 | if ((data[0] & 0x80) == 0) { |
@@ -459,6 +459,7 @@ static void usa26_indat_callback(struct urb *urb) | |||
459 | } | 459 | } |
460 | tty_flip_buffer_push(tty); | 460 | tty_flip_buffer_push(tty); |
461 | } | 461 | } |
462 | tty_kref_put(tty); | ||
462 | 463 | ||
463 | /* Resubmit urb so we continue receiving */ | 464 | /* Resubmit urb so we continue receiving */ |
464 | urb->dev = port->serial->dev; | 465 | urb->dev = port->serial->dev; |
@@ -513,6 +514,7 @@ static void usa26_instat_callback(struct urb *urb) | |||
513 | struct usb_serial *serial; | 514 | struct usb_serial *serial; |
514 | struct usb_serial_port *port; | 515 | struct usb_serial_port *port; |
515 | struct keyspan_port_private *p_priv; | 516 | struct keyspan_port_private *p_priv; |
517 | struct tty_struct *tty; | ||
516 | int old_dcd_state, err; | 518 | int old_dcd_state, err; |
517 | int status = urb->status; | 519 | int status = urb->status; |
518 | 520 | ||
@@ -553,12 +555,11 @@ static void usa26_instat_callback(struct urb *urb) | |||
553 | p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0); | 555 | p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0); |
554 | p_priv->ri_state = ((msg->ri) ? 1 : 0); | 556 | p_priv->ri_state = ((msg->ri) ? 1 : 0); |
555 | 557 | ||
556 | if (port->port.tty && !C_CLOCAL(port->port.tty) | 558 | if (old_dcd_state != p_priv->dcd_state) { |
557 | && old_dcd_state != p_priv->dcd_state) { | 559 | tty = tty_port_tty_get(&port->port); |
558 | if (old_dcd_state) | 560 | if (tty && !C_CLOCAL(tty)) |
559 | tty_hangup(port->port.tty); | 561 | tty_hangup(tty); |
560 | /* else */ | 562 | tty_kref_put(tty); |
561 | /* wake_up_interruptible(&p_priv->open_wait); */ | ||
562 | } | 563 | } |
563 | 564 | ||
564 | /* Resubmit urb so we continue receiving */ | 565 | /* Resubmit urb so we continue receiving */ |
@@ -604,11 +605,12 @@ static void usa28_indat_callback(struct urb *urb) | |||
604 | p_priv = usb_get_serial_port_data(port); | 605 | p_priv = usb_get_serial_port_data(port); |
605 | data = urb->transfer_buffer; | 606 | data = urb->transfer_buffer; |
606 | 607 | ||
607 | tty = port->port.tty; | 608 | tty =tty_port_tty_get(&port->port); |
608 | if (urb->actual_length) { | 609 | if (tty && urb->actual_length) { |
609 | tty_insert_flip_string(tty, data, urb->actual_length); | 610 | tty_insert_flip_string(tty, data, urb->actual_length); |
610 | tty_flip_buffer_push(tty); | 611 | tty_flip_buffer_push(tty); |
611 | } | 612 | } |
613 | tty_kref_put(tty); | ||
612 | 614 | ||
613 | /* Resubmit urb so we continue receiving */ | 615 | /* Resubmit urb so we continue receiving */ |
614 | urb->dev = port->serial->dev; | 616 | urb->dev = port->serial->dev; |
@@ -652,6 +654,7 @@ static void usa28_instat_callback(struct urb *urb) | |||
652 | struct usb_serial *serial; | 654 | struct usb_serial *serial; |
653 | struct usb_serial_port *port; | 655 | struct usb_serial_port *port; |
654 | struct keyspan_port_private *p_priv; | 656 | struct keyspan_port_private *p_priv; |
657 | struct tty_struct *tty; | ||
655 | int old_dcd_state; | 658 | int old_dcd_state; |
656 | int status = urb->status; | 659 | int status = urb->status; |
657 | 660 | ||
@@ -689,12 +692,11 @@ static void usa28_instat_callback(struct urb *urb) | |||
689 | p_priv->dcd_state = ((msg->dcd) ? 1 : 0); | 692 | p_priv->dcd_state = ((msg->dcd) ? 1 : 0); |
690 | p_priv->ri_state = ((msg->ri) ? 1 : 0); | 693 | p_priv->ri_state = ((msg->ri) ? 1 : 0); |
691 | 694 | ||
692 | if (port->port.tty && !C_CLOCAL(port->port.tty) | 695 | if( old_dcd_state != p_priv->dcd_state && old_dcd_state) { |
693 | && old_dcd_state != p_priv->dcd_state) { | 696 | tty = tty_port_tty_get(&port->port); |
694 | if (old_dcd_state) | 697 | if (tty && !C_CLOCAL(tty)) |
695 | tty_hangup(port->port.tty); | 698 | tty_hangup(tty); |
696 | /* else */ | 699 | tty_kref_put(tty); |
697 | /* wake_up_interruptible(&p_priv->open_wait); */ | ||
698 | } | 700 | } |
699 | 701 | ||
700 | /* Resubmit urb so we continue receiving */ | 702 | /* Resubmit urb so we continue receiving */ |
@@ -785,12 +787,11 @@ static void usa49_instat_callback(struct urb *urb) | |||
785 | p_priv->dcd_state = ((msg->dcd) ? 1 : 0); | 787 | p_priv->dcd_state = ((msg->dcd) ? 1 : 0); |
786 | p_priv->ri_state = ((msg->ri) ? 1 : 0); | 788 | p_priv->ri_state = ((msg->ri) ? 1 : 0); |
787 | 789 | ||
788 | if (port->port.tty && !C_CLOCAL(port->port.tty) | 790 | if (old_dcd_state != p_priv->dcd_state && old_dcd_state) { |
789 | && old_dcd_state != p_priv->dcd_state) { | 791 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
790 | if (old_dcd_state) | 792 | if (tty && !C_CLOCAL(tty)) |
791 | tty_hangup(port->port.tty); | 793 | tty_hangup(tty); |
792 | /* else */ | 794 | tty_kref_put(tty); |
793 | /* wake_up_interruptible(&p_priv->open_wait); */ | ||
794 | } | 795 | } |
795 | 796 | ||
796 | /* Resubmit urb so we continue receiving */ | 797 | /* Resubmit urb so we continue receiving */ |
@@ -827,7 +828,7 @@ static void usa49_indat_callback(struct urb *urb) | |||
827 | } | 828 | } |
828 | 829 | ||
829 | port = urb->context; | 830 | port = urb->context; |
830 | tty = port->port.tty; | 831 | tty = tty_port_tty_get(&port->port); |
831 | if (tty && urb->actual_length) { | 832 | if (tty && urb->actual_length) { |
832 | /* 0x80 bit is error flag */ | 833 | /* 0x80 bit is error flag */ |
833 | if ((data[0] & 0x80) == 0) { | 834 | if ((data[0] & 0x80) == 0) { |
@@ -850,6 +851,7 @@ static void usa49_indat_callback(struct urb *urb) | |||
850 | } | 851 | } |
851 | tty_flip_buffer_push(tty); | 852 | tty_flip_buffer_push(tty); |
852 | } | 853 | } |
854 | tty_kref_put(tty); | ||
853 | 855 | ||
854 | /* Resubmit urb so we continue receiving */ | 856 | /* Resubmit urb so we continue receiving */ |
855 | urb->dev = port->serial->dev; | 857 | urb->dev = port->serial->dev; |
@@ -893,7 +895,7 @@ static void usa49wg_indat_callback(struct urb *urb) | |||
893 | return; | 895 | return; |
894 | } | 896 | } |
895 | port = serial->port[data[i++]]; | 897 | port = serial->port[data[i++]]; |
896 | tty = port->port.tty; | 898 | tty = tty_port_tty_get(&port->port); |
897 | len = data[i++]; | 899 | len = data[i++]; |
898 | 900 | ||
899 | /* 0x80 bit is error flag */ | 901 | /* 0x80 bit is error flag */ |
@@ -927,6 +929,7 @@ static void usa49wg_indat_callback(struct urb *urb) | |||
927 | } | 929 | } |
928 | if (port->port.count) | 930 | if (port->port.count) |
929 | tty_flip_buffer_push(tty); | 931 | tty_flip_buffer_push(tty); |
932 | tty_kref_put(tty); | ||
930 | } | 933 | } |
931 | } | 934 | } |
932 | 935 | ||
@@ -967,8 +970,8 @@ static void usa90_indat_callback(struct urb *urb) | |||
967 | port = urb->context; | 970 | port = urb->context; |
968 | p_priv = usb_get_serial_port_data(port); | 971 | p_priv = usb_get_serial_port_data(port); |
969 | 972 | ||
970 | tty = port->port.tty; | ||
971 | if (urb->actual_length) { | 973 | if (urb->actual_length) { |
974 | tty = tty_port_tty_get(&port->port); | ||
972 | /* if current mode is DMA, looks like usa28 format | 975 | /* if current mode is DMA, looks like usa28 format |
973 | otherwise looks like usa26 data format */ | 976 | otherwise looks like usa26 data format */ |
974 | 977 | ||
@@ -1004,6 +1007,7 @@ static void usa90_indat_callback(struct urb *urb) | |||
1004 | } | 1007 | } |
1005 | } | 1008 | } |
1006 | tty_flip_buffer_push(tty); | 1009 | tty_flip_buffer_push(tty); |
1010 | tty_kref_put(tty); | ||
1007 | } | 1011 | } |
1008 | 1012 | ||
1009 | /* Resubmit urb so we continue receiving */ | 1013 | /* Resubmit urb so we continue receiving */ |
@@ -1025,6 +1029,7 @@ static void usa90_instat_callback(struct urb *urb) | |||
1025 | struct usb_serial *serial; | 1029 | struct usb_serial *serial; |
1026 | struct usb_serial_port *port; | 1030 | struct usb_serial_port *port; |
1027 | struct keyspan_port_private *p_priv; | 1031 | struct keyspan_port_private *p_priv; |
1032 | struct tty_struct *tty; | ||
1028 | int old_dcd_state, err; | 1033 | int old_dcd_state, err; |
1029 | int status = urb->status; | 1034 | int status = urb->status; |
1030 | 1035 | ||
@@ -1053,12 +1058,11 @@ static void usa90_instat_callback(struct urb *urb) | |||
1053 | p_priv->dcd_state = ((msg->dcd) ? 1 : 0); | 1058 | p_priv->dcd_state = ((msg->dcd) ? 1 : 0); |
1054 | p_priv->ri_state = ((msg->ri) ? 1 : 0); | 1059 | p_priv->ri_state = ((msg->ri) ? 1 : 0); |
1055 | 1060 | ||
1056 | if (port->port.tty && !C_CLOCAL(port->port.tty) | 1061 | if (old_dcd_state != p_priv->dcd_state && old_dcd_state) { |
1057 | && old_dcd_state != p_priv->dcd_state) { | 1062 | tty = tty_port_tty_get(&port->port); |
1058 | if (old_dcd_state) | 1063 | if (tty && !C_CLOCAL(tty)) |
1059 | tty_hangup(port->port.tty); | 1064 | tty_hangup(tty); |
1060 | /* else */ | 1065 | tty_kref_put(tty); |
1061 | /* wake_up_interruptible(&p_priv->open_wait); */ | ||
1062 | } | 1066 | } |
1063 | 1067 | ||
1064 | /* Resubmit urb so we continue receiving */ | 1068 | /* Resubmit urb so we continue receiving */ |
@@ -1130,12 +1134,11 @@ static void usa67_instat_callback(struct urb *urb) | |||
1130 | p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0); | 1134 | p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0); |
1131 | p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0); | 1135 | p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0); |
1132 | 1136 | ||
1133 | if (port->port.tty && !C_CLOCAL(port->port.tty) | 1137 | if (old_dcd_state != p_priv->dcd_state && old_dcd_state) { |
1134 | && old_dcd_state != p_priv->dcd_state) { | 1138 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
1135 | if (old_dcd_state) | 1139 | if (tty && !C_CLOCAL(tty)) |
1136 | tty_hangup(port->port.tty); | 1140 | tty_hangup(tty); |
1137 | /* else */ | 1141 | tty_kref_put(tty); |
1138 | /* wake_up_interruptible(&p_priv->open_wait); */ | ||
1139 | } | 1142 | } |
1140 | 1143 | ||
1141 | /* Resubmit urb so we continue receiving */ | 1144 | /* Resubmit urb so we continue receiving */ |
@@ -1332,7 +1335,7 @@ static void keyspan_close(struct tty_struct *tty, | |||
1332 | stop_urb(p_priv->out_urbs[i]); | 1335 | stop_urb(p_priv->out_urbs[i]); |
1333 | } | 1336 | } |
1334 | } | 1337 | } |
1335 | port->port.tty = NULL; | 1338 | tty_port_tty_set(&port->port, NULL); |
1336 | } | 1339 | } |
1337 | 1340 | ||
1338 | /* download the firmware to a pre-renumeration device */ | 1341 | /* download the firmware to a pre-renumeration device */ |