diff options
author | Denis Joseph Barrow <D.Barow@option.com> | 2008-09-05 11:12:07 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-09-24 18:58:58 -0400 |
commit | 8ef5ba63b94b04b182ac4a6009dbbf1406beb3c5 (patch) | |
tree | 6029a8d5974cf4b03a83f2d95b714032c85f9468 /drivers/net | |
parent | ead7b9406c252014175bdf7c6c31894edfa0d1fa (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')
-rw-r--r-- | drivers/net/usb/hso.c | 326 |
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 | ||
179 | enum rx_ctrl_state{ | ||
180 | RX_IDLE, | ||
181 | RX_SENT, | ||
182 | RX_PENDING | ||
183 | }; | ||
184 | |||
182 | struct hso_serial { | 185 | struct 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 | ||
221 | struct hso_device { | 233 | struct hso_device { |
@@ -271,7 +283,7 @@ struct hso_device { | |||
271 | static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file, | 283 | static 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); |
273 | static void ctrl_callback(struct urb *urb); | 285 | static void ctrl_callback(struct urb *urb); |
274 | static void put_rxbuf_data(struct urb *urb, struct hso_serial *serial); | 286 | static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial); |
275 | static void hso_kick_transmit(struct hso_serial *serial); | 287 | static void hso_kick_transmit(struct hso_serial *serial); |
276 | /* Helper functions */ | 288 | /* Helper functions */ |
277 | static int hso_mux_submit_intr_urb(struct hso_shared_int *mux_int, | 289 | static 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); | |||
287 | static void hso_free_shared_int(struct hso_shared_int *shared_int); | 299 | static void hso_free_shared_int(struct hso_shared_int *shared_int); |
288 | static int hso_stop_net_device(struct hso_device *hso_dev); | 300 | static int hso_stop_net_device(struct hso_device *hso_dev); |
289 | static void hso_serial_ref_free(struct kref *ref); | 301 | static void hso_serial_ref_free(struct kref *ref); |
302 | static void hso_std_serial_read_bulk_callback(struct urb *urb); | ||
303 | static int hso_mux_serial_read(struct hso_serial *serial); | ||
290 | static void async_get_intf(struct work_struct *data); | 304 | static void async_get_intf(struct work_struct *data); |
291 | static void async_put_intf(struct work_struct *data); | 305 | static void async_put_intf(struct work_struct *data); |
292 | static int hso_put_activity(struct hso_device *hso_dev); | 306 | static 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 | } |
459 | static DEVICE_ATTR(hsotype, S_IRUGO, hso_sysfs_show_porttype, NULL); | 473 | static DEVICE_ATTR(hsotype, S_IRUGO, hso_sysfs_show_porttype, NULL); |
460 | 474 | ||
475 | static 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 */ |
462 | static u32 hso_mux_to_port(int mux) | 487 | static 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 | ||
1067 | static 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 | |||
1093 | static 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 | |||
1112 | static 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 */ | ||
1135 | static 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 | */ | ||
1192 | void 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 | |||
1204 | static 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 | |||
1211 | void 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 */ |
1043 | static int hso_serial_open(struct tty_struct *tty, struct file *filp) | 1220 | static 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 */ |
1555 | static void put_rxbuf_data(struct urb *urb, struct hso_serial *serial) | 1741 | static 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); |
1575 | static 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 | ||
1642 | static void hso_log_port(struct hso_device *hso_dev) | 1779 | static 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 | ||
2746 | static struct usb_driver hso_driver = { | 2888 | static struct usb_driver hso_driver = { |