diff options
Diffstat (limited to 'drivers/net/usb/hso.c')
| -rw-r--r-- | drivers/net/usb/hso.c | 62 |
1 files changed, 40 insertions, 22 deletions
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index e53883ad6107..d6916f787fce 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c | |||
| @@ -999,6 +999,7 @@ static void read_bulk_callback(struct urb *urb) | |||
| 999 | struct hso_net *odev = urb->context; | 999 | struct hso_net *odev = urb->context; |
| 1000 | struct net_device *net; | 1000 | struct net_device *net; |
| 1001 | int result; | 1001 | int result; |
| 1002 | unsigned long flags; | ||
| 1002 | int status = urb->status; | 1003 | int status = urb->status; |
| 1003 | 1004 | ||
| 1004 | /* is al ok? (Filip: Who's Al ?) */ | 1005 | /* is al ok? (Filip: Who's Al ?) */ |
| @@ -1028,11 +1029,11 @@ static void read_bulk_callback(struct urb *urb) | |||
| 1028 | if (urb->actual_length) { | 1029 | if (urb->actual_length) { |
| 1029 | /* Handle the IP stream, add header and push it onto network | 1030 | /* Handle the IP stream, add header and push it onto network |
| 1030 | * stack if the packet is complete. */ | 1031 | * stack if the packet is complete. */ |
| 1031 | spin_lock(&odev->net_lock); | 1032 | spin_lock_irqsave(&odev->net_lock, flags); |
| 1032 | packetizeRx(odev, urb->transfer_buffer, urb->actual_length, | 1033 | packetizeRx(odev, urb->transfer_buffer, urb->actual_length, |
| 1033 | (urb->transfer_buffer_length > | 1034 | (urb->transfer_buffer_length > |
| 1034 | urb->actual_length) ? 1 : 0); | 1035 | urb->actual_length) ? 1 : 0); |
| 1035 | spin_unlock(&odev->net_lock); | 1036 | spin_unlock_irqrestore(&odev->net_lock, flags); |
| 1036 | } | 1037 | } |
| 1037 | 1038 | ||
| 1038 | /* We are done with this URB, resubmit it. Prep the USB to wait for | 1039 | /* We are done with this URB, resubmit it. Prep the USB to wait for |
| @@ -1193,6 +1194,7 @@ static void hso_std_serial_read_bulk_callback(struct urb *urb) | |||
| 1193 | { | 1194 | { |
| 1194 | struct hso_serial *serial = urb->context; | 1195 | struct hso_serial *serial = urb->context; |
| 1195 | int status = urb->status; | 1196 | int status = urb->status; |
| 1197 | unsigned long flags; | ||
| 1196 | 1198 | ||
| 1197 | hso_dbg(0x8, "--- Got serial_read_bulk callback %02x ---\n", status); | 1199 | hso_dbg(0x8, "--- Got serial_read_bulk callback %02x ---\n", status); |
| 1198 | 1200 | ||
| @@ -1216,10 +1218,10 @@ static void hso_std_serial_read_bulk_callback(struct urb *urb) | |||
| 1216 | if (serial->parent->port_spec & HSO_INFO_CRC_BUG) | 1218 | if (serial->parent->port_spec & HSO_INFO_CRC_BUG) |
| 1217 | fix_crc_bug(urb, serial->in_endp->wMaxPacketSize); | 1219 | fix_crc_bug(urb, serial->in_endp->wMaxPacketSize); |
| 1218 | /* Valid data, handle RX data */ | 1220 | /* Valid data, handle RX data */ |
| 1219 | spin_lock(&serial->serial_lock); | 1221 | spin_lock_irqsave(&serial->serial_lock, flags); |
| 1220 | serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 1; | 1222 | serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 1; |
| 1221 | put_rxbuf_data_and_resubmit_bulk_urb(serial); | 1223 | put_rxbuf_data_and_resubmit_bulk_urb(serial); |
| 1222 | spin_unlock(&serial->serial_lock); | 1224 | spin_unlock_irqrestore(&serial->serial_lock, flags); |
| 1223 | } | 1225 | } |
| 1224 | 1226 | ||
| 1225 | /* | 1227 | /* |
| @@ -1502,12 +1504,13 @@ static void tiocmget_intr_callback(struct urb *urb) | |||
| 1502 | DUMP(serial_state_notification, | 1504 | DUMP(serial_state_notification, |
| 1503 | sizeof(struct hso_serial_state_notification)); | 1505 | sizeof(struct hso_serial_state_notification)); |
| 1504 | } else { | 1506 | } else { |
| 1507 | unsigned long flags; | ||
| 1505 | 1508 | ||
| 1506 | UART_state_bitmap = le16_to_cpu(serial_state_notification-> | 1509 | UART_state_bitmap = le16_to_cpu(serial_state_notification-> |
| 1507 | UART_state_bitmap); | 1510 | UART_state_bitmap); |
| 1508 | prev_UART_state_bitmap = tiocmget->prev_UART_state_bitmap; | 1511 | prev_UART_state_bitmap = tiocmget->prev_UART_state_bitmap; |
| 1509 | icount = &tiocmget->icount; | 1512 | icount = &tiocmget->icount; |
| 1510 | spin_lock(&serial->serial_lock); | 1513 | spin_lock_irqsave(&serial->serial_lock, flags); |
| 1511 | if ((UART_state_bitmap & B_OVERRUN) != | 1514 | if ((UART_state_bitmap & B_OVERRUN) != |
| 1512 | (prev_UART_state_bitmap & B_OVERRUN)) | 1515 | (prev_UART_state_bitmap & B_OVERRUN)) |
| 1513 | icount->parity++; | 1516 | icount->parity++; |
| @@ -1530,7 +1533,7 @@ static void tiocmget_intr_callback(struct urb *urb) | |||
| 1530 | (prev_UART_state_bitmap & B_RX_CARRIER)) | 1533 | (prev_UART_state_bitmap & B_RX_CARRIER)) |
| 1531 | icount->dcd++; | 1534 | icount->dcd++; |
| 1532 | tiocmget->prev_UART_state_bitmap = UART_state_bitmap; | 1535 | tiocmget->prev_UART_state_bitmap = UART_state_bitmap; |
| 1533 | spin_unlock(&serial->serial_lock); | 1536 | spin_unlock_irqrestore(&serial->serial_lock, flags); |
| 1534 | tiocmget->intr_completed = 1; | 1537 | tiocmget->intr_completed = 1; |
| 1535 | wake_up_interruptible(&tiocmget->waitq); | 1538 | wake_up_interruptible(&tiocmget->waitq); |
| 1536 | } | 1539 | } |
| @@ -1729,7 +1732,6 @@ static int hso_serial_ioctl(struct tty_struct *tty, | |||
| 1729 | /* starts a transmit */ | 1732 | /* starts a transmit */ |
| 1730 | static void hso_kick_transmit(struct hso_serial *serial) | 1733 | static void hso_kick_transmit(struct hso_serial *serial) |
| 1731 | { | 1734 | { |
| 1732 | u8 *temp; | ||
| 1733 | unsigned long flags; | 1735 | unsigned long flags; |
| 1734 | int res; | 1736 | int res; |
| 1735 | 1737 | ||
| @@ -1745,14 +1747,12 @@ static void hso_kick_transmit(struct hso_serial *serial) | |||
| 1745 | goto out; | 1747 | goto out; |
| 1746 | 1748 | ||
| 1747 | /* Switch pointers around to avoid memcpy */ | 1749 | /* Switch pointers around to avoid memcpy */ |
| 1748 | temp = serial->tx_buffer; | 1750 | swap(serial->tx_buffer, serial->tx_data); |
| 1749 | serial->tx_buffer = serial->tx_data; | ||
| 1750 | serial->tx_data = temp; | ||
| 1751 | serial->tx_data_count = serial->tx_buffer_count; | 1751 | serial->tx_data_count = serial->tx_buffer_count; |
| 1752 | serial->tx_buffer_count = 0; | 1752 | serial->tx_buffer_count = 0; |
| 1753 | 1753 | ||
| 1754 | /* If temp is set, it means we switched buffers */ | 1754 | /* If serial->tx_data is set, it means we switched buffers */ |
| 1755 | if (temp && serial->write_data) { | 1755 | if (serial->tx_data && serial->write_data) { |
| 1756 | res = serial->write_data(serial); | 1756 | res = serial->write_data(serial); |
| 1757 | if (res >= 0) | 1757 | if (res >= 0) |
| 1758 | serial->tx_urb_used = 1; | 1758 | serial->tx_urb_used = 1; |
| @@ -1852,6 +1852,7 @@ static void intr_callback(struct urb *urb) | |||
| 1852 | struct hso_serial *serial; | 1852 | struct hso_serial *serial; |
| 1853 | unsigned char *port_req; | 1853 | unsigned char *port_req; |
| 1854 | int status = urb->status; | 1854 | int status = urb->status; |
| 1855 | unsigned long flags; | ||
| 1855 | int i; | 1856 | int i; |
| 1856 | 1857 | ||
| 1857 | usb_mark_last_busy(urb->dev); | 1858 | usb_mark_last_busy(urb->dev); |
| @@ -1879,7 +1880,7 @@ static void intr_callback(struct urb *urb) | |||
| 1879 | if (serial != NULL) { | 1880 | if (serial != NULL) { |
| 1880 | hso_dbg(0x1, "Pending read interrupt on port %d\n", | 1881 | hso_dbg(0x1, "Pending read interrupt on port %d\n", |
| 1881 | i); | 1882 | i); |
| 1882 | spin_lock(&serial->serial_lock); | 1883 | spin_lock_irqsave(&serial->serial_lock, flags); |
| 1883 | if (serial->rx_state == RX_IDLE && | 1884 | if (serial->rx_state == RX_IDLE && |
| 1884 | serial->port.count > 0) { | 1885 | serial->port.count > 0) { |
| 1885 | /* Setup and send a ctrl req read on | 1886 | /* Setup and send a ctrl req read on |
| @@ -1893,7 +1894,8 @@ static void intr_callback(struct urb *urb) | |||
| 1893 | hso_dbg(0x1, "Already a read pending on port %d or port not open\n", | 1894 | hso_dbg(0x1, "Already a read pending on port %d or port not open\n", |
| 1894 | i); | 1895 | i); |
| 1895 | } | 1896 | } |
| 1896 | spin_unlock(&serial->serial_lock); | 1897 | spin_unlock_irqrestore(&serial->serial_lock, |
| 1898 | flags); | ||
| 1897 | } | 1899 | } |
| 1898 | } | 1900 | } |
| 1899 | } | 1901 | } |
| @@ -1920,6 +1922,7 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb) | |||
| 1920 | { | 1922 | { |
| 1921 | struct hso_serial *serial = urb->context; | 1923 | struct hso_serial *serial = urb->context; |
| 1922 | int status = urb->status; | 1924 | int status = urb->status; |
| 1925 | unsigned long flags; | ||
| 1923 | 1926 | ||
| 1924 | /* sanity check */ | 1927 | /* sanity check */ |
| 1925 | if (!serial) { | 1928 | if (!serial) { |
| @@ -1927,9 +1930,9 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb) | |||
| 1927 | return; | 1930 | return; |
| 1928 | } | 1931 | } |
| 1929 | 1932 | ||
| 1930 | spin_lock(&serial->serial_lock); | 1933 | spin_lock_irqsave(&serial->serial_lock, flags); |
| 1931 | serial->tx_urb_used = 0; | 1934 | serial->tx_urb_used = 0; |
| 1932 | spin_unlock(&serial->serial_lock); | 1935 | spin_unlock_irqrestore(&serial->serial_lock, flags); |
| 1933 | if (status) { | 1936 | if (status) { |
| 1934 | handle_usb_error(status, __func__, serial->parent); | 1937 | handle_usb_error(status, __func__, serial->parent); |
| 1935 | return; | 1938 | return; |
| @@ -1971,14 +1974,15 @@ static void ctrl_callback(struct urb *urb) | |||
| 1971 | struct hso_serial *serial = urb->context; | 1974 | struct hso_serial *serial = urb->context; |
| 1972 | struct usb_ctrlrequest *req; | 1975 | struct usb_ctrlrequest *req; |
| 1973 | int status = urb->status; | 1976 | int status = urb->status; |
| 1977 | unsigned long flags; | ||
| 1974 | 1978 | ||
| 1975 | /* sanity check */ | 1979 | /* sanity check */ |
| 1976 | if (!serial) | 1980 | if (!serial) |
| 1977 | return; | 1981 | return; |
| 1978 | 1982 | ||
| 1979 | spin_lock(&serial->serial_lock); | 1983 | spin_lock_irqsave(&serial->serial_lock, flags); |
| 1980 | serial->tx_urb_used = 0; | 1984 | serial->tx_urb_used = 0; |
| 1981 | spin_unlock(&serial->serial_lock); | 1985 | spin_unlock_irqrestore(&serial->serial_lock, flags); |
| 1982 | if (status) { | 1986 | if (status) { |
| 1983 | handle_usb_error(status, __func__, serial->parent); | 1987 | handle_usb_error(status, __func__, serial->parent); |
| 1984 | return; | 1988 | return; |
| @@ -1994,9 +1998,9 @@ static void ctrl_callback(struct urb *urb) | |||
| 1994 | (USB_DIR_IN | USB_TYPE_OPTION_VENDOR | USB_RECIP_INTERFACE)) { | 1998 | (USB_DIR_IN | USB_TYPE_OPTION_VENDOR | USB_RECIP_INTERFACE)) { |
| 1995 | /* response to a read command */ | 1999 | /* response to a read command */ |
| 1996 | serial->rx_urb_filled[0] = 1; | 2000 | serial->rx_urb_filled[0] = 1; |
| 1997 | spin_lock(&serial->serial_lock); | 2001 | spin_lock_irqsave(&serial->serial_lock, flags); |
| 1998 | put_rxbuf_data_and_resubmit_ctrl_urb(serial); | 2002 | put_rxbuf_data_and_resubmit_ctrl_urb(serial); |
| 1999 | spin_unlock(&serial->serial_lock); | 2003 | spin_unlock_irqrestore(&serial->serial_lock, flags); |
| 2000 | } else { | 2004 | } else { |
| 2001 | hso_put_activity(serial->parent); | 2005 | hso_put_activity(serial->parent); |
| 2002 | tty_port_tty_wakeup(&serial->port); | 2006 | tty_port_tty_wakeup(&serial->port); |
| @@ -2803,6 +2807,12 @@ static int hso_get_config_data(struct usb_interface *interface) | |||
| 2803 | return -EIO; | 2807 | return -EIO; |
| 2804 | } | 2808 | } |
| 2805 | 2809 | ||
| 2810 | /* check if we have a valid interface */ | ||
| 2811 | if (if_num > 16) { | ||
| 2812 | kfree(config_data); | ||
| 2813 | return -EINVAL; | ||
| 2814 | } | ||
| 2815 | |||
| 2806 | switch (config_data[if_num]) { | 2816 | switch (config_data[if_num]) { |
| 2807 | case 0x0: | 2817 | case 0x0: |
| 2808 | result = 0; | 2818 | result = 0; |
| @@ -2873,10 +2883,18 @@ static int hso_probe(struct usb_interface *interface, | |||
| 2873 | 2883 | ||
| 2874 | /* Get the interface/port specification from either driver_info or from | 2884 | /* Get the interface/port specification from either driver_info or from |
| 2875 | * the device itself */ | 2885 | * the device itself */ |
| 2876 | if (id->driver_info) | 2886 | if (id->driver_info) { |
| 2887 | /* if_num is controlled by the device, driver_info is a 0 terminated | ||
| 2888 | * array. Make sure, the access is in bounds! */ | ||
| 2889 | for (i = 0; i <= if_num; ++i) | ||
| 2890 | if (((u32 *)(id->driver_info))[i] == 0) | ||
| 2891 | goto exit; | ||
| 2877 | port_spec = ((u32 *)(id->driver_info))[if_num]; | 2892 | port_spec = ((u32 *)(id->driver_info))[if_num]; |
| 2878 | else | 2893 | } else { |
| 2879 | port_spec = hso_get_config_data(interface); | 2894 | port_spec = hso_get_config_data(interface); |
| 2895 | if (port_spec < 0) | ||
| 2896 | goto exit; | ||
| 2897 | } | ||
| 2880 | 2898 | ||
| 2881 | /* Check if we need to switch to alt interfaces prior to port | 2899 | /* Check if we need to switch to alt interfaces prior to port |
| 2882 | * configuration */ | 2900 | * configuration */ |
