diff options
Diffstat (limited to 'drivers/net/usb/hso.c')
-rw-r--r-- | drivers/net/usb/hso.c | 54 |
1 files changed, 42 insertions, 12 deletions
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 9f7896a25f1b..d345a6eec4ca 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c | |||
@@ -1015,7 +1015,7 @@ static void _hso_serial_set_termios(struct tty_struct *tty, | |||
1015 | struct hso_serial *serial = get_serial_by_tty(tty); | 1015 | struct hso_serial *serial = get_serial_by_tty(tty); |
1016 | struct ktermios *termios; | 1016 | struct ktermios *termios; |
1017 | 1017 | ||
1018 | if ((!tty) || (!tty->termios) || (!serial)) { | 1018 | if (!serial) { |
1019 | printk(KERN_ERR "%s: no tty structures", __func__); | 1019 | printk(KERN_ERR "%s: no tty structures", __func__); |
1020 | return; | 1020 | return; |
1021 | } | 1021 | } |
@@ -1057,14 +1057,14 @@ static void _hso_serial_set_termios(struct tty_struct *tty, | |||
1057 | termios->c_cflag |= CS8; /* character size 8 bits */ | 1057 | termios->c_cflag |= CS8; /* character size 8 bits */ |
1058 | 1058 | ||
1059 | /* baud rate 115200 */ | 1059 | /* baud rate 115200 */ |
1060 | tty_encode_baud_rate(serial->tty, 115200, 115200); | 1060 | tty_encode_baud_rate(tty, 115200, 115200); |
1061 | 1061 | ||
1062 | /* | 1062 | /* |
1063 | * Force low_latency on; otherwise the pushes are scheduled; | 1063 | * Force low_latency on; otherwise the pushes are scheduled; |
1064 | * this is bad as it opens up the possibility of dropping bytes | 1064 | * this is bad as it opens up the possibility of dropping bytes |
1065 | * on the floor. We don't want to drop bytes on the floor. :) | 1065 | * on the floor. We don't want to drop bytes on the floor. :) |
1066 | */ | 1066 | */ |
1067 | serial->tty->low_latency = 1; | 1067 | tty->low_latency = 1; |
1068 | return; | 1068 | return; |
1069 | } | 1069 | } |
1070 | 1070 | ||
@@ -1228,6 +1228,7 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp) | |||
1228 | 1228 | ||
1229 | /* sanity check */ | 1229 | /* sanity check */ |
1230 | if (serial == NULL || serial->magic != HSO_SERIAL_MAGIC) { | 1230 | if (serial == NULL || serial->magic != HSO_SERIAL_MAGIC) { |
1231 | WARN_ON(1); | ||
1231 | tty->driver_data = NULL; | 1232 | tty->driver_data = NULL; |
1232 | D1("Failed to open port"); | 1233 | D1("Failed to open port"); |
1233 | return -ENODEV; | 1234 | return -ENODEV; |
@@ -1242,8 +1243,10 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp) | |||
1242 | kref_get(&serial->parent->ref); | 1243 | kref_get(&serial->parent->ref); |
1243 | 1244 | ||
1244 | /* setup */ | 1245 | /* setup */ |
1246 | spin_lock_irq(&serial->serial_lock); | ||
1245 | tty->driver_data = serial; | 1247 | tty->driver_data = serial; |
1246 | serial->tty = tty; | 1248 | serial->tty = tty_kref_get(tty); |
1249 | spin_unlock_irq(&serial->serial_lock); | ||
1247 | 1250 | ||
1248 | /* check for port already opened, if not set the termios */ | 1251 | /* check for port already opened, if not set the termios */ |
1249 | serial->open_count++; | 1252 | serial->open_count++; |
@@ -1285,6 +1288,10 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp) | |||
1285 | 1288 | ||
1286 | D1("Closing serial port"); | 1289 | D1("Closing serial port"); |
1287 | 1290 | ||
1291 | /* Open failed, no close cleanup required */ | ||
1292 | if (serial == NULL) | ||
1293 | return; | ||
1294 | |||
1288 | mutex_lock(&serial->parent->mutex); | 1295 | mutex_lock(&serial->parent->mutex); |
1289 | usb_gone = serial->parent->usb_gone; | 1296 | usb_gone = serial->parent->usb_gone; |
1290 | 1297 | ||
@@ -1297,10 +1304,13 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp) | |||
1297 | kref_put(&serial->parent->ref, hso_serial_ref_free); | 1304 | kref_put(&serial->parent->ref, hso_serial_ref_free); |
1298 | if (serial->open_count <= 0) { | 1305 | if (serial->open_count <= 0) { |
1299 | serial->open_count = 0; | 1306 | serial->open_count = 0; |
1300 | if (serial->tty) { | 1307 | spin_lock_irq(&serial->serial_lock); |
1308 | if (serial->tty == tty) { | ||
1301 | serial->tty->driver_data = NULL; | 1309 | serial->tty->driver_data = NULL; |
1302 | serial->tty = NULL; | 1310 | serial->tty = NULL; |
1311 | tty_kref_put(tty); | ||
1303 | } | 1312 | } |
1313 | spin_unlock_irq(&serial->serial_lock); | ||
1304 | if (!usb_gone) | 1314 | if (!usb_gone) |
1305 | hso_stop_serial_device(serial->parent); | 1315 | hso_stop_serial_device(serial->parent); |
1306 | tasklet_kill(&serial->unthrottle_tasklet); | 1316 | tasklet_kill(&serial->unthrottle_tasklet); |
@@ -1653,6 +1663,7 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb) | |||
1653 | { | 1663 | { |
1654 | struct hso_serial *serial = urb->context; | 1664 | struct hso_serial *serial = urb->context; |
1655 | int status = urb->status; | 1665 | int status = urb->status; |
1666 | struct tty_struct *tty; | ||
1656 | 1667 | ||
1657 | /* sanity check */ | 1668 | /* sanity check */ |
1658 | if (!serial) { | 1669 | if (!serial) { |
@@ -1662,14 +1673,18 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb) | |||
1662 | 1673 | ||
1663 | spin_lock(&serial->serial_lock); | 1674 | spin_lock(&serial->serial_lock); |
1664 | serial->tx_urb_used = 0; | 1675 | serial->tx_urb_used = 0; |
1676 | tty = tty_kref_get(serial->tty); | ||
1665 | spin_unlock(&serial->serial_lock); | 1677 | spin_unlock(&serial->serial_lock); |
1666 | if (status) { | 1678 | if (status) { |
1667 | log_usb_status(status, __func__); | 1679 | log_usb_status(status, __func__); |
1680 | tty_kref_put(tty); | ||
1668 | return; | 1681 | return; |
1669 | } | 1682 | } |
1670 | hso_put_activity(serial->parent); | 1683 | hso_put_activity(serial->parent); |
1671 | if (serial->tty) | 1684 | if (tty) { |
1672 | tty_wakeup(serial->tty); | 1685 | tty_wakeup(tty); |
1686 | tty_kref_put(tty); | ||
1687 | } | ||
1673 | hso_kick_transmit(serial); | 1688 | hso_kick_transmit(serial); |
1674 | 1689 | ||
1675 | D1(" "); | 1690 | D1(" "); |
@@ -1706,6 +1721,7 @@ static void ctrl_callback(struct urb *urb) | |||
1706 | struct hso_serial *serial = urb->context; | 1721 | struct hso_serial *serial = urb->context; |
1707 | struct usb_ctrlrequest *req; | 1722 | struct usb_ctrlrequest *req; |
1708 | int status = urb->status; | 1723 | int status = urb->status; |
1724 | struct tty_struct *tty; | ||
1709 | 1725 | ||
1710 | /* sanity check */ | 1726 | /* sanity check */ |
1711 | if (!serial) | 1727 | if (!serial) |
@@ -1713,9 +1729,11 @@ static void ctrl_callback(struct urb *urb) | |||
1713 | 1729 | ||
1714 | spin_lock(&serial->serial_lock); | 1730 | spin_lock(&serial->serial_lock); |
1715 | serial->tx_urb_used = 0; | 1731 | serial->tx_urb_used = 0; |
1732 | tty = tty_kref_get(serial->tty); | ||
1716 | spin_unlock(&serial->serial_lock); | 1733 | spin_unlock(&serial->serial_lock); |
1717 | if (status) { | 1734 | if (status) { |
1718 | log_usb_status(status, __func__); | 1735 | log_usb_status(status, __func__); |
1736 | tty_kref_put(tty); | ||
1719 | return; | 1737 | return; |
1720 | } | 1738 | } |
1721 | 1739 | ||
@@ -1734,25 +1752,31 @@ static void ctrl_callback(struct urb *urb) | |||
1734 | spin_unlock(&serial->serial_lock); | 1752 | spin_unlock(&serial->serial_lock); |
1735 | } else { | 1753 | } else { |
1736 | hso_put_activity(serial->parent); | 1754 | hso_put_activity(serial->parent); |
1737 | if (serial->tty) | 1755 | if (tty) |
1738 | tty_wakeup(serial->tty); | 1756 | tty_wakeup(tty); |
1739 | /* response to a write command */ | 1757 | /* response to a write command */ |
1740 | hso_kick_transmit(serial); | 1758 | hso_kick_transmit(serial); |
1741 | } | 1759 | } |
1760 | tty_kref_put(tty); | ||
1742 | } | 1761 | } |
1743 | 1762 | ||
1744 | /* handle RX data for serial port */ | 1763 | /* handle RX data for serial port */ |
1745 | static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial) | 1764 | static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial) |
1746 | { | 1765 | { |
1747 | struct tty_struct *tty = serial->tty; | 1766 | struct tty_struct *tty; |
1748 | int write_length_remaining = 0; | 1767 | int write_length_remaining = 0; |
1749 | int curr_write_len; | 1768 | int curr_write_len; |
1769 | |||
1750 | /* Sanity check */ | 1770 | /* Sanity check */ |
1751 | if (urb == NULL || serial == NULL) { | 1771 | if (urb == NULL || serial == NULL) { |
1752 | D1("serial = NULL"); | 1772 | D1("serial = NULL"); |
1753 | return -2; | 1773 | return -2; |
1754 | } | 1774 | } |
1755 | 1775 | ||
1776 | spin_lock(&serial->serial_lock); | ||
1777 | tty = tty_kref_get(serial->tty); | ||
1778 | spin_unlock(&serial->serial_lock); | ||
1779 | |||
1756 | /* Push data to tty */ | 1780 | /* Push data to tty */ |
1757 | if (tty) { | 1781 | if (tty) { |
1758 | write_length_remaining = urb->actual_length - | 1782 | write_length_remaining = urb->actual_length - |
@@ -1774,6 +1798,7 @@ static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial) | |||
1774 | serial->curr_rx_urb_offset = 0; | 1798 | serial->curr_rx_urb_offset = 0; |
1775 | serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0; | 1799 | serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0; |
1776 | } | 1800 | } |
1801 | tty_kref_put(tty); | ||
1777 | return write_length_remaining; | 1802 | return write_length_remaining; |
1778 | } | 1803 | } |
1779 | 1804 | ||
@@ -2786,15 +2811,20 @@ static void hso_serial_ref_free(struct kref *ref) | |||
2786 | static void hso_free_interface(struct usb_interface *interface) | 2811 | static void hso_free_interface(struct usb_interface *interface) |
2787 | { | 2812 | { |
2788 | struct hso_serial *hso_dev; | 2813 | struct hso_serial *hso_dev; |
2814 | struct tty_struct *tty; | ||
2789 | int i; | 2815 | int i; |
2790 | 2816 | ||
2791 | for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) { | 2817 | for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) { |
2792 | if (serial_table[i] | 2818 | if (serial_table[i] |
2793 | && (serial_table[i]->interface == interface)) { | 2819 | && (serial_table[i]->interface == interface)) { |
2794 | hso_dev = dev2ser(serial_table[i]); | 2820 | hso_dev = dev2ser(serial_table[i]); |
2795 | if (hso_dev->tty) | 2821 | spin_lock_irq(&hso_dev->serial_lock); |
2796 | tty_hangup(hso_dev->tty); | 2822 | tty = tty_kref_get(hso_dev->tty); |
2823 | spin_unlock_irq(&hso_dev->serial_lock); | ||
2824 | if (tty) | ||
2825 | tty_hangup(tty); | ||
2797 | mutex_lock(&hso_dev->parent->mutex); | 2826 | mutex_lock(&hso_dev->parent->mutex); |
2827 | tty_kref_put(tty); | ||
2798 | hso_dev->parent->usb_gone = 1; | 2828 | hso_dev->parent->usb_gone = 1; |
2799 | mutex_unlock(&hso_dev->parent->mutex); | 2829 | mutex_unlock(&hso_dev->parent->mutex); |
2800 | kref_put(&serial_table[i]->ref, hso_serial_ref_free); | 2830 | kref_put(&serial_table[i]->ref, hso_serial_ref_free); |