aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb
diff options
context:
space:
mode:
authorDenis Joseph Barrow <D.Barow@option.com>2008-09-05 11:12:07 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-09-24 18:58:58 -0400
commit8ef5ba63b94b04b182ac4a6009dbbf1406beb3c5 (patch)
tree6029a8d5974cf4b03a83f2d95b714032c85f9468 /drivers/net/usb
parentead7b9406c252014175bdf7c6c31894edfa0d1fa (diff)
[netdrvr] usb/hso: throttle to prevent loss of serial data
Patch to stop loss of characters on the hso modems, this patch throttles & unthrottles the modem by not putting out urbs until the tty/line discipline layer has enough space for newly received packets. serial ports. This is required for firmware diagnostics being done at Option. Signed-off-by: Denis Joseph Barrow <D.Barow@option.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/net/usb')
-rw-r--r--drivers/net/usb/hso.c326
1 files changed, 234 insertions, 92 deletions
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 8b2b947b6757..1164c52e2c0a 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -92,9 +92,6 @@
92 92
93#define HSO_NET_TX_TIMEOUT (HZ*10) 93#define HSO_NET_TX_TIMEOUT (HZ*10)
94 94
95/* Serial port defines and structs. */
96#define HSO_SERIAL_FLAG_RX_SENT 0
97
98#define HSO_SERIAL_MAGIC 0x48534f31 95#define HSO_SERIAL_MAGIC 0x48534f31
99 96
100/* Number of ttys to handle */ 97/* Number of ttys to handle */
@@ -179,6 +176,12 @@ struct hso_net {
179 unsigned long flags; 176 unsigned long flags;
180}; 177};
181 178
179enum rx_ctrl_state{
180 RX_IDLE,
181 RX_SENT,
182 RX_PENDING
183};
184
182struct hso_serial { 185struct hso_serial {
183 struct hso_device *parent; 186 struct hso_device *parent;
184 int magic; 187 int magic;
@@ -205,7 +208,7 @@ struct hso_serial {
205 struct usb_endpoint_descriptor *in_endp; 208 struct usb_endpoint_descriptor *in_endp;
206 struct usb_endpoint_descriptor *out_endp; 209 struct usb_endpoint_descriptor *out_endp;
207 210
208 unsigned long flags; 211 enum rx_ctrl_state rx_state;
209 u8 rts_state; 212 u8 rts_state;
210 u8 dtr_state; 213 u8 dtr_state;
211 unsigned tx_urb_used:1; 214 unsigned tx_urb_used:1;
@@ -216,6 +219,15 @@ struct hso_serial {
216 spinlock_t serial_lock; 219 spinlock_t serial_lock;
217 220
218 int (*write_data) (struct hso_serial *serial); 221 int (*write_data) (struct hso_serial *serial);
222 /* Hacks required to get flow control
223 * working on the serial receive buffers
224 * so as not to drop characters on the floor.
225 */
226 int curr_rx_urb_idx;
227 u16 curr_rx_urb_offset;
228 u8 rx_urb_filled[MAX_RX_URBS];
229 struct tasklet_struct unthrottle_tasklet;
230 struct work_struct retry_unthrottle_workqueue;
219}; 231};
220 232
221struct hso_device { 233struct hso_device {
@@ -271,7 +283,7 @@ struct hso_device {
271static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file, 283static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file,
272 unsigned int set, unsigned int clear); 284 unsigned int set, unsigned int clear);
273static void ctrl_callback(struct urb *urb); 285static void ctrl_callback(struct urb *urb);
274static void put_rxbuf_data(struct urb *urb, struct hso_serial *serial); 286static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial);
275static void hso_kick_transmit(struct hso_serial *serial); 287static void hso_kick_transmit(struct hso_serial *serial);
276/* Helper functions */ 288/* Helper functions */
277static int hso_mux_submit_intr_urb(struct hso_shared_int *mux_int, 289static int hso_mux_submit_intr_urb(struct hso_shared_int *mux_int,
@@ -287,6 +299,8 @@ static int hso_start_net_device(struct hso_device *hso_dev);
287static void hso_free_shared_int(struct hso_shared_int *shared_int); 299static void hso_free_shared_int(struct hso_shared_int *shared_int);
288static int hso_stop_net_device(struct hso_device *hso_dev); 300static int hso_stop_net_device(struct hso_device *hso_dev);
289static void hso_serial_ref_free(struct kref *ref); 301static void hso_serial_ref_free(struct kref *ref);
302static void hso_std_serial_read_bulk_callback(struct urb *urb);
303static int hso_mux_serial_read(struct hso_serial *serial);
290static void async_get_intf(struct work_struct *data); 304static void async_get_intf(struct work_struct *data);
291static void async_put_intf(struct work_struct *data); 305static void async_put_intf(struct work_struct *data);
292static int hso_put_activity(struct hso_device *hso_dev); 306static int hso_put_activity(struct hso_device *hso_dev);
@@ -458,6 +472,17 @@ static ssize_t hso_sysfs_show_porttype(struct device *dev,
458} 472}
459static DEVICE_ATTR(hsotype, S_IRUGO, hso_sysfs_show_porttype, NULL); 473static DEVICE_ATTR(hsotype, S_IRUGO, hso_sysfs_show_porttype, NULL);
460 474
475static int hso_urb_to_index(struct hso_serial *serial, struct urb *urb)
476{
477 int idx;
478
479 for (idx = 0; idx < serial->num_rx_urbs; idx++)
480 if (serial->rx_urb[idx] == urb)
481 return idx;
482 dev_err(serial->parent->dev, "hso_urb_to_index failed\n");
483 return -1;
484}
485
461/* converts mux value to a port spec value */ 486/* converts mux value to a port spec value */
462static u32 hso_mux_to_port(int mux) 487static u32 hso_mux_to_port(int mux)
463{ 488{
@@ -1039,6 +1064,158 @@ static void _hso_serial_set_termios(struct tty_struct *tty,
1039 return; 1064 return;
1040} 1065}
1041 1066
1067static void hso_resubmit_rx_bulk_urb(struct hso_serial *serial, struct urb *urb)
1068{
1069 int result;
1070#ifdef CONFIG_HSO_AUTOPM
1071 usb_mark_last_busy(urb->dev);
1072#endif
1073 /* We are done with this URB, resubmit it. Prep the USB to wait for
1074 * another frame */
1075 usb_fill_bulk_urb(urb, serial->parent->usb,
1076 usb_rcvbulkpipe(serial->parent->usb,
1077 serial->in_endp->
1078 bEndpointAddress & 0x7F),
1079 urb->transfer_buffer, serial->rx_data_length,
1080 hso_std_serial_read_bulk_callback, serial);
1081 /* Give this to the USB subsystem so it can tell us when more data
1082 * arrives. */
1083 result = usb_submit_urb(urb, GFP_ATOMIC);
1084 if (result) {
1085 dev_err(&urb->dev->dev, "%s failed submit serial rx_urb %d\n",
1086 __func__, result);
1087 }
1088}
1089
1090
1091
1092
1093static void put_rxbuf_data_and_resubmit_bulk_urb(struct hso_serial *serial)
1094{
1095 int count;
1096 struct urb *curr_urb;
1097
1098 while (serial->rx_urb_filled[serial->curr_rx_urb_idx]) {
1099 curr_urb = serial->rx_urb[serial->curr_rx_urb_idx];
1100 count = put_rxbuf_data(curr_urb, serial);
1101 if (count == -1)
1102 return;
1103 if (count == 0) {
1104 serial->curr_rx_urb_idx++;
1105 if (serial->curr_rx_urb_idx >= serial->num_rx_urbs)
1106 serial->curr_rx_urb_idx = 0;
1107 hso_resubmit_rx_bulk_urb(serial, curr_urb);
1108 }
1109 }
1110}
1111
1112static void put_rxbuf_data_and_resubmit_ctrl_urb(struct hso_serial *serial)
1113{
1114 int count = 0;
1115 struct urb *urb;
1116
1117 urb = serial->rx_urb[0];
1118 if (serial->open_count > 0) {
1119 count = put_rxbuf_data(urb, serial);
1120 if (count == -1)
1121 return;
1122 }
1123 /* Re issue a read as long as we receive data. */
1124
1125 if (count == 0 && ((urb->actual_length != 0) ||
1126 (serial->rx_state == RX_PENDING))) {
1127 serial->rx_state = RX_SENT;
1128 hso_mux_serial_read(serial);
1129 } else
1130 serial->rx_state = RX_IDLE;
1131}
1132
1133
1134/* read callback for Diag and CS port */
1135static void hso_std_serial_read_bulk_callback(struct urb *urb)
1136{
1137 struct hso_serial *serial = urb->context;
1138 int status = urb->status;
1139
1140 /* sanity check */
1141 if (!serial) {
1142 D1("serial == NULL");
1143 return;
1144 } else if (status) {
1145 log_usb_status(status, __func__);
1146 return;
1147 }
1148
1149 D4("\n--- Got serial_read_bulk callback %02x ---", status);
1150 D1("Actual length = %d\n", urb->actual_length);
1151 DUMP1(urb->transfer_buffer, urb->actual_length);
1152
1153 /* Anyone listening? */
1154 if (serial->open_count == 0)
1155 return;
1156
1157 if (status == 0) {
1158 if (serial->parent->port_spec & HSO_INFO_CRC_BUG) {
1159 u32 rest;
1160 u8 crc_check[4] = { 0xDE, 0xAD, 0xBE, 0xEF };
1161 rest =
1162 urb->actual_length %
1163 serial->in_endp->wMaxPacketSize;
1164 if (((rest == 5) || (rest == 6))
1165 && !memcmp(((u8 *) urb->transfer_buffer) +
1166 urb->actual_length - 4, crc_check, 4)) {
1167 urb->actual_length -= 4;
1168 }
1169 }
1170 /* Valid data, handle RX data */
1171 spin_lock(&serial->serial_lock);
1172 serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 1;
1173 put_rxbuf_data_and_resubmit_bulk_urb(serial);
1174 spin_unlock(&serial->serial_lock);
1175 } else if (status == -ENOENT || status == -ECONNRESET) {
1176 /* Unlinked - check for throttled port. */
1177 D2("Port %d, successfully unlinked urb", serial->minor);
1178 spin_lock(&serial->serial_lock);
1179 serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0;
1180 hso_resubmit_rx_bulk_urb(serial, urb);
1181 spin_unlock(&serial->serial_lock);
1182 } else {
1183 D2("Port %d, status = %d for read urb", serial->minor, status);
1184 return;
1185 }
1186}
1187
1188/*
1189 * This needs to be a tasklet otherwise we will
1190 * end up recursively calling this function.
1191 */
1192void hso_unthrottle_tasklet(struct hso_serial *serial)
1193{
1194 unsigned long flags;
1195
1196 spin_lock_irqsave(&serial->serial_lock, flags);
1197 if ((serial->parent->port_spec & HSO_INTF_MUX))
1198 put_rxbuf_data_and_resubmit_ctrl_urb(serial);
1199 else
1200 put_rxbuf_data_and_resubmit_bulk_urb(serial);
1201 spin_unlock_irqrestore(&serial->serial_lock, flags);
1202}
1203
1204static void hso_unthrottle(struct tty_struct *tty)
1205{
1206 struct hso_serial *serial = get_serial_by_tty(tty);
1207
1208 tasklet_hi_schedule(&serial->unthrottle_tasklet);
1209}
1210
1211void hso_unthrottle_workfunc(struct work_struct *work)
1212{
1213 struct hso_serial *serial =
1214 container_of(work, struct hso_serial,
1215 retry_unthrottle_workqueue);
1216 hso_unthrottle_tasklet(serial);
1217}
1218
1042/* open the requested serial port */ 1219/* open the requested serial port */
1043static int hso_serial_open(struct tty_struct *tty, struct file *filp) 1220static int hso_serial_open(struct tty_struct *tty, struct file *filp)
1044{ 1221{
@@ -1064,13 +1241,18 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp)
1064 tty->driver_data = serial; 1241 tty->driver_data = serial;
1065 serial->tty = tty; 1242 serial->tty = tty;
1066 1243
1067 /* check for port allready opened, if not set the termios */ 1244 /* check for port already opened, if not set the termios */
1068 serial->open_count++; 1245 serial->open_count++;
1069 if (serial->open_count == 1) { 1246 if (serial->open_count == 1) {
1070 tty->low_latency = 1; 1247 tty->low_latency = 1;
1071 serial->flags = 0; 1248 serial->rx_state = RX_IDLE;
1072 /* Force default termio settings */ 1249 /* Force default termio settings */
1073 _hso_serial_set_termios(tty, NULL); 1250 _hso_serial_set_termios(tty, NULL);
1251 tasklet_init(&serial->unthrottle_tasklet,
1252 (void (*)(unsigned long))hso_unthrottle_tasklet,
1253 (unsigned long)serial);
1254 INIT_WORK(&serial->retry_unthrottle_workqueue,
1255 hso_unthrottle_workfunc);
1074 result = hso_start_serial_device(serial->parent, GFP_KERNEL); 1256 result = hso_start_serial_device(serial->parent, GFP_KERNEL);
1075 if (result) { 1257 if (result) {
1076 hso_stop_serial_device(serial->parent); 1258 hso_stop_serial_device(serial->parent);
@@ -1117,9 +1299,13 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp)
1117 } 1299 }
1118 if (!usb_gone) 1300 if (!usb_gone)
1119 hso_stop_serial_device(serial->parent); 1301 hso_stop_serial_device(serial->parent);
1302 tasklet_kill(&serial->unthrottle_tasklet);
1303 cancel_work_sync(&serial->retry_unthrottle_workqueue);
1120 } 1304 }
1305
1121 if (!usb_gone) 1306 if (!usb_gone)
1122 usb_autopm_put_interface(serial->parent->interface); 1307 usb_autopm_put_interface(serial->parent->interface);
1308
1123 mutex_unlock(&serial->parent->mutex); 1309 mutex_unlock(&serial->parent->mutex);
1124} 1310}
1125 1311
@@ -1422,15 +1608,21 @@ static void intr_callback(struct urb *urb)
1422 (1 << i)); 1608 (1 << i));
1423 if (serial != NULL) { 1609 if (serial != NULL) {
1424 D1("Pending read interrupt on port %d\n", i); 1610 D1("Pending read interrupt on port %d\n", i);
1425 if (!test_and_set_bit(HSO_SERIAL_FLAG_RX_SENT, 1611 spin_lock(&serial->serial_lock);
1426 &serial->flags)) { 1612 if (serial->rx_state == RX_IDLE) {
1427 /* Setup and send a ctrl req read on 1613 /* Setup and send a ctrl req read on
1428 * port i */ 1614 * port i */
1429 hso_mux_serial_read(serial); 1615 if (!serial->rx_urb_filled[0]) {
1616 serial->rx_state = RX_SENT;
1617 hso_mux_serial_read(serial);
1618 } else
1619 serial->rx_state = RX_PENDING;
1620
1430 } else { 1621 } else {
1431 D1("Already pending a read on " 1622 D1("Already pending a read on "
1432 "port %d\n", i); 1623 "port %d\n", i);
1433 } 1624 }
1625 spin_unlock(&serial->serial_lock);
1434 } 1626 }
1435 } 1627 }
1436 } 1628 }
@@ -1532,16 +1724,10 @@ static void ctrl_callback(struct urb *urb)
1532 if (req->bRequestType == 1724 if (req->bRequestType ==
1533 (USB_DIR_IN | USB_TYPE_OPTION_VENDOR | USB_RECIP_INTERFACE)) { 1725 (USB_DIR_IN | USB_TYPE_OPTION_VENDOR | USB_RECIP_INTERFACE)) {
1534 /* response to a read command */ 1726 /* response to a read command */
1535 if (serial->open_count > 0) { 1727 serial->rx_urb_filled[0] = 1;
1536 /* handle RX data the normal way */ 1728 spin_lock(&serial->serial_lock);
1537 put_rxbuf_data(urb, serial); 1729 put_rxbuf_data_and_resubmit_ctrl_urb(serial);
1538 } 1730 spin_unlock(&serial->serial_lock);
1539
1540 /* Re issue a read as long as we receive data. */
1541 if (urb->actual_length != 0)
1542 hso_mux_serial_read(serial);
1543 else
1544 clear_bit(HSO_SERIAL_FLAG_RX_SENT, &serial->flags);
1545 } else { 1731 } else {
1546 hso_put_activity(serial->parent); 1732 hso_put_activity(serial->parent);
1547 if (serial->tty) 1733 if (serial->tty)
@@ -1552,91 +1738,42 @@ static void ctrl_callback(struct urb *urb)
1552} 1738}
1553 1739
1554/* handle RX data for serial port */ 1740/* handle RX data for serial port */
1555static void put_rxbuf_data(struct urb *urb, struct hso_serial *serial) 1741static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial)
1556{ 1742{
1557 struct tty_struct *tty = serial->tty; 1743 struct tty_struct *tty = serial->tty;
1558 1744 int write_length_remaining = 0;
1745 int curr_write_len;
1559 /* Sanity check */ 1746 /* Sanity check */
1560 if (urb == NULL || serial == NULL) { 1747 if (urb == NULL || serial == NULL) {
1561 D1("serial = NULL"); 1748 D1("serial = NULL");
1562 return; 1749 return -2;
1563 } 1750 }
1564 1751
1565 /* Push data to tty */ 1752 /* Push data to tty */
1566 if (tty && urb->actual_length) { 1753 if (tty) {
1754 write_length_remaining = urb->actual_length -
1755 serial->curr_rx_urb_offset;
1567 D1("data to push to tty"); 1756 D1("data to push to tty");
1568 tty_insert_flip_string(tty, urb->transfer_buffer, 1757 while (write_length_remaining) {
1569 urb->actual_length); 1758 if (test_bit(TTY_THROTTLED, &tty->flags))
1570 tty_flip_buffer_push(tty); 1759 return -1;
1571 } 1760 curr_write_len = tty_insert_flip_string
1572} 1761 (tty, urb->transfer_buffer +
1573 1762 serial->curr_rx_urb_offset,
1574/* read callback for Diag and CS port */ 1763 write_length_remaining);
1575static void hso_std_serial_read_bulk_callback(struct urb *urb) 1764 serial->curr_rx_urb_offset += curr_write_len;
1576{ 1765 write_length_remaining -= curr_write_len;
1577 struct hso_serial *serial = urb->context; 1766 tty_flip_buffer_push(tty);
1578 int result;
1579 int status = urb->status;
1580
1581 /* sanity check */
1582 if (!serial) {
1583 D1("serial == NULL");
1584 return;
1585 } else if (status) {
1586 log_usb_status(status, __func__);
1587 return;
1588 }
1589
1590 D4("\n--- Got serial_read_bulk callback %02x ---", status);
1591 D1("Actual length = %d\n", urb->actual_length);
1592 DUMP1(urb->transfer_buffer, urb->actual_length);
1593
1594 /* Anyone listening? */
1595 if (serial->open_count == 0)
1596 return;
1597
1598 if (status == 0) {
1599 if (serial->parent->port_spec & HSO_INFO_CRC_BUG) {
1600 u32 rest;
1601 u8 crc_check[4] = { 0xDE, 0xAD, 0xBE, 0xEF };
1602 rest =
1603 urb->actual_length %
1604 serial->in_endp->wMaxPacketSize;
1605 if (((rest == 5) || (rest == 6))
1606 && !memcmp(((u8 *) urb->transfer_buffer) +
1607 urb->actual_length - 4, crc_check, 4)) {
1608 urb->actual_length -= 4;
1609 }
1610 } 1767 }
1611 /* Valid data, handle RX data */
1612 put_rxbuf_data(urb, serial);
1613 } else if (status == -ENOENT || status == -ECONNRESET) {
1614 /* Unlinked - check for throttled port. */
1615 D2("Port %d, successfully unlinked urb", serial->minor);
1616 } else {
1617 D2("Port %d, status = %d for read urb", serial->minor, status);
1618 return;
1619 } 1768 }
1620 1769 if (write_length_remaining == 0) {
1621 usb_mark_last_busy(urb->dev); 1770 serial->curr_rx_urb_offset = 0;
1622 1771 serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0;
1623 /* We are done with this URB, resubmit it. Prep the USB to wait for
1624 * another frame */
1625 usb_fill_bulk_urb(urb, serial->parent->usb,
1626 usb_rcvbulkpipe(serial->parent->usb,
1627 serial->in_endp->
1628 bEndpointAddress & 0x7F),
1629 urb->transfer_buffer, serial->rx_data_length,
1630 hso_std_serial_read_bulk_callback, serial);
1631 /* Give this to the USB subsystem so it can tell us when more data
1632 * arrives. */
1633 result = usb_submit_urb(urb, GFP_ATOMIC);
1634 if (result) {
1635 dev_err(&urb->dev->dev, "%s failed submit serial rx_urb %d",
1636 __func__, result);
1637 } 1772 }
1773 return write_length_remaining;
1638} 1774}
1639 1775
1776
1640/* Base driver functions */ 1777/* Base driver functions */
1641 1778
1642static void hso_log_port(struct hso_device *hso_dev) 1779static void hso_log_port(struct hso_device *hso_dev)
@@ -1794,9 +1931,13 @@ static int hso_stop_serial_device(struct hso_device *hso_dev)
1794 return -ENODEV; 1931 return -ENODEV;
1795 1932
1796 for (i = 0; i < serial->num_rx_urbs; i++) { 1933 for (i = 0; i < serial->num_rx_urbs; i++) {
1797 if (serial->rx_urb[i]) 1934 if (serial->rx_urb[i]) {
1798 usb_kill_urb(serial->rx_urb[i]); 1935 usb_kill_urb(serial->rx_urb[i]);
1936 serial->rx_urb_filled[i] = 0;
1937 }
1799 } 1938 }
1939 serial->curr_rx_urb_idx = 0;
1940 serial->curr_rx_urb_offset = 0;
1800 1941
1801 if (serial->tx_urb) 1942 if (serial->tx_urb)
1802 usb_kill_urb(serial->tx_urb); 1943 usb_kill_urb(serial->tx_urb);
@@ -2741,6 +2882,7 @@ static const struct tty_operations hso_serial_ops = {
2741 .chars_in_buffer = hso_serial_chars_in_buffer, 2882 .chars_in_buffer = hso_serial_chars_in_buffer,
2742 .tiocmget = hso_serial_tiocmget, 2883 .tiocmget = hso_serial_tiocmget,
2743 .tiocmset = hso_serial_tiocmset, 2884 .tiocmset = hso_serial_tiocmset,
2885 .unthrottle = hso_unthrottle
2744}; 2886};
2745 2887
2746static struct usb_driver hso_driver = { 2888static struct usb_driver hso_driver = {