diff options
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 147 |
1 files changed, 121 insertions, 26 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index b2bfea7c815a..e774a27c6c98 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -245,7 +245,6 @@ | |||
245 | /* to talk to the device */ | 245 | /* to talk to the device */ |
246 | /* Thanx to gkh and the rest of the usb dev group for all code I have assimilated :-) */ | 246 | /* Thanx to gkh and the rest of the usb dev group for all code I have assimilated :-) */ |
247 | 247 | ||
248 | #include <linux/config.h> | ||
249 | #include <linux/kernel.h> | 248 | #include <linux/kernel.h> |
250 | #include <linux/errno.h> | 249 | #include <linux/errno.h> |
251 | #include <linux/init.h> | 250 | #include <linux/init.h> |
@@ -258,7 +257,7 @@ | |||
258 | #include <asm/uaccess.h> | 257 | #include <asm/uaccess.h> |
259 | #include <linux/usb.h> | 258 | #include <linux/usb.h> |
260 | #include <linux/serial.h> | 259 | #include <linux/serial.h> |
261 | #include "usb-serial.h" | 260 | #include <linux/usb/serial.h> |
262 | #include "ftdi_sio.h" | 261 | #include "ftdi_sio.h" |
263 | 262 | ||
264 | /* | 263 | /* |
@@ -307,6 +306,8 @@ static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { | |||
307 | 306 | ||
308 | 307 | ||
309 | static struct usb_device_id id_table_combined [] = { | 308 | static struct usb_device_id id_table_combined [] = { |
309 | { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) }, | ||
310 | { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) }, | ||
310 | { USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) }, | 311 | { USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) }, |
311 | { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, | 312 | { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, |
312 | { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) }, | 313 | { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) }, |
@@ -314,6 +315,7 @@ static struct usb_device_id id_table_combined [] = { | |||
314 | { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, | 315 | { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, |
315 | { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, | 316 | { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, |
316 | { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, | 317 | { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, |
318 | { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) }, | ||
317 | { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, | 319 | { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, |
318 | { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, | 320 | { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, |
319 | { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, | 321 | { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, |
@@ -337,10 +339,12 @@ static struct usb_device_id id_table_combined [] = { | |||
337 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) }, | 339 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) }, |
338 | { USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) }, | 340 | { USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) }, |
339 | { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) }, | 341 | { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) }, |
342 | { USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) }, | ||
340 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) }, | 343 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) }, |
341 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) }, | 344 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) }, |
342 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) }, | 345 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) }, |
343 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2104_PID) }, | 346 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2104_PID) }, |
347 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2106_PID) }, | ||
344 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_1_PID) }, | 348 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_1_PID) }, |
345 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_2_PID) }, | 349 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_2_PID) }, |
346 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_1_PID) }, | 350 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_1_PID) }, |
@@ -501,6 +505,12 @@ static struct usb_device_id id_table_combined [] = { | |||
501 | { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) }, | 505 | { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) }, |
502 | { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) }, | 506 | { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) }, |
503 | { USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) }, | 507 | { USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) }, |
508 | { USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) }, | ||
509 | { USB_DEVICE(TESTO_VID, TESTO_USB_INTERFACE_PID) }, | ||
510 | { USB_DEVICE(FTDI_VID, FTDI_GAMMA_SCOUT_PID) }, | ||
511 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13M_PID) }, | ||
512 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) }, | ||
513 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) }, | ||
504 | { }, /* Optional parameter entry */ | 514 | { }, /* Optional parameter entry */ |
505 | { } /* Terminating entry */ | 515 | { } /* Terminating entry */ |
506 | }; | 516 | }; |
@@ -549,11 +559,17 @@ struct ftdi_private { | |||
549 | spinlock_t rx_lock; /* spinlock for receive state */ | 559 | spinlock_t rx_lock; /* spinlock for receive state */ |
550 | struct work_struct rx_work; | 560 | struct work_struct rx_work; |
551 | int rx_processed; | 561 | int rx_processed; |
562 | unsigned long rx_bytes; | ||
552 | 563 | ||
553 | __u16 interface; /* FT2232C port interface (0 for FT232/245) */ | 564 | __u16 interface; /* FT2232C port interface (0 for FT232/245) */ |
554 | 565 | ||
555 | int force_baud; /* if non-zero, force the baud rate to this value */ | 566 | int force_baud; /* if non-zero, force the baud rate to this value */ |
556 | int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */ | 567 | int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */ |
568 | |||
569 | spinlock_t tx_lock; /* spinlock for transmit state */ | ||
570 | unsigned long tx_bytes; | ||
571 | unsigned long tx_outstanding_bytes; | ||
572 | unsigned long tx_outstanding_urbs; | ||
557 | }; | 573 | }; |
558 | 574 | ||
559 | /* Used for TIOCMIWAIT */ | 575 | /* Used for TIOCMIWAIT */ |
@@ -627,6 +643,9 @@ static struct usb_serial_driver ftdi_sio_device = { | |||
627 | #define HIGH 1 | 643 | #define HIGH 1 |
628 | #define LOW 0 | 644 | #define LOW 0 |
629 | 645 | ||
646 | /* number of outstanding urbs to prevent userspace DoS from happening */ | ||
647 | #define URB_UPPER_LIMIT 42 | ||
648 | |||
630 | /* | 649 | /* |
631 | * *************************************************************************** | 650 | * *************************************************************************** |
632 | * Utlity functions | 651 | * Utlity functions |
@@ -1086,25 +1105,29 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att | |||
1086 | static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer); | 1105 | static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer); |
1087 | static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char); | 1106 | static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char); |
1088 | 1107 | ||
1089 | static void create_sysfs_attrs(struct usb_serial *serial) | 1108 | static int create_sysfs_attrs(struct usb_serial *serial) |
1090 | { | 1109 | { |
1091 | struct ftdi_private *priv; | 1110 | struct ftdi_private *priv; |
1092 | struct usb_device *udev; | 1111 | struct usb_device *udev; |
1112 | int retval = 0; | ||
1093 | 1113 | ||
1094 | dbg("%s",__FUNCTION__); | 1114 | dbg("%s",__FUNCTION__); |
1095 | 1115 | ||
1096 | priv = usb_get_serial_port_data(serial->port[0]); | 1116 | priv = usb_get_serial_port_data(serial->port[0]); |
1097 | udev = serial->dev; | 1117 | udev = serial->dev; |
1098 | 1118 | ||
1099 | /* XXX I've no idea if the original SIO supports the event_char | 1119 | /* XXX I've no idea if the original SIO supports the event_char |
1100 | * sysfs parameter, so I'm playing it safe. */ | 1120 | * sysfs parameter, so I'm playing it safe. */ |
1101 | if (priv->chip_type != SIO) { | 1121 | if (priv->chip_type != SIO) { |
1102 | dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]); | 1122 | dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]); |
1103 | device_create_file(&udev->dev, &dev_attr_event_char); | 1123 | retval = device_create_file(&udev->dev, &dev_attr_event_char); |
1104 | if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) { | 1124 | if ((!retval) && |
1105 | device_create_file(&udev->dev, &dev_attr_latency_timer); | 1125 | (priv->chip_type == FT232BM || priv->chip_type == FT2232C)) { |
1126 | retval = device_create_file(&udev->dev, | ||
1127 | &dev_attr_latency_timer); | ||
1106 | } | 1128 | } |
1107 | } | 1129 | } |
1130 | return retval; | ||
1108 | } | 1131 | } |
1109 | 1132 | ||
1110 | static void remove_sysfs_attrs(struct usb_serial *serial) | 1133 | static void remove_sysfs_attrs(struct usb_serial *serial) |
@@ -1147,7 +1170,8 @@ static int ftdi_sio_attach (struct usb_serial *serial) | |||
1147 | struct usb_serial_port *port = serial->port[0]; | 1170 | struct usb_serial_port *port = serial->port[0]; |
1148 | struct ftdi_private *priv; | 1171 | struct ftdi_private *priv; |
1149 | struct ftdi_sio_quirk *quirk; | 1172 | struct ftdi_sio_quirk *quirk; |
1150 | 1173 | int retval; | |
1174 | |||
1151 | dbg("%s",__FUNCTION__); | 1175 | dbg("%s",__FUNCTION__); |
1152 | 1176 | ||
1153 | priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL); | 1177 | priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL); |
@@ -1157,6 +1181,7 @@ static int ftdi_sio_attach (struct usb_serial *serial) | |||
1157 | } | 1181 | } |
1158 | 1182 | ||
1159 | spin_lock_init(&priv->rx_lock); | 1183 | spin_lock_init(&priv->rx_lock); |
1184 | spin_lock_init(&priv->tx_lock); | ||
1160 | init_waitqueue_head(&priv->delta_msr_wait); | 1185 | init_waitqueue_head(&priv->delta_msr_wait); |
1161 | /* This will push the characters through immediately rather | 1186 | /* This will push the characters through immediately rather |
1162 | than queue a task to deliver them */ | 1187 | than queue a task to deliver them */ |
@@ -1187,15 +1212,18 @@ static int ftdi_sio_attach (struct usb_serial *serial) | |||
1187 | usb_set_serial_port_data(serial->port[0], priv); | 1212 | usb_set_serial_port_data(serial->port[0], priv); |
1188 | 1213 | ||
1189 | ftdi_determine_type (serial->port[0]); | 1214 | ftdi_determine_type (serial->port[0]); |
1190 | create_sysfs_attrs(serial); | 1215 | retval = create_sysfs_attrs(serial); |
1216 | if (retval) | ||
1217 | dev_err(&serial->dev->dev, "Error creating sysfs files, " | ||
1218 | "continuing\n"); | ||
1191 | 1219 | ||
1192 | /* Check for device requiring special set up. */ | 1220 | /* Check for device requiring special set up. */ |
1193 | quirk = (struct ftdi_sio_quirk *)usb_get_serial_data(serial); | 1221 | quirk = (struct ftdi_sio_quirk *)usb_get_serial_data(serial); |
1194 | if (quirk && quirk->setup) { | 1222 | if (quirk && quirk->setup) { |
1195 | quirk->setup(serial); | 1223 | quirk->setup(serial); |
1196 | } | 1224 | } |
1197 | 1225 | ||
1198 | return (0); | 1226 | return 0; |
1199 | } /* ftdi_sio_attach */ | 1227 | } /* ftdi_sio_attach */ |
1200 | 1228 | ||
1201 | 1229 | ||
@@ -1271,6 +1299,13 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) | |||
1271 | 1299 | ||
1272 | dbg("%s", __FUNCTION__); | 1300 | dbg("%s", __FUNCTION__); |
1273 | 1301 | ||
1302 | spin_lock_irqsave(&priv->tx_lock, flags); | ||
1303 | priv->tx_bytes = 0; | ||
1304 | spin_unlock_irqrestore(&priv->tx_lock, flags); | ||
1305 | spin_lock_irqsave(&priv->rx_lock, flags); | ||
1306 | priv->rx_bytes = 0; | ||
1307 | spin_unlock_irqrestore(&priv->rx_lock, flags); | ||
1308 | |||
1274 | if (port->tty) | 1309 | if (port->tty) |
1275 | port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 1310 | port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
1276 | 1311 | ||
@@ -1373,6 +1408,7 @@ static int ftdi_write (struct usb_serial_port *port, | |||
1373 | int data_offset ; /* will be 1 for the SIO and 0 otherwise */ | 1408 | int data_offset ; /* will be 1 for the SIO and 0 otherwise */ |
1374 | int status; | 1409 | int status; |
1375 | int transfer_size; | 1410 | int transfer_size; |
1411 | unsigned long flags; | ||
1376 | 1412 | ||
1377 | dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count); | 1413 | dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count); |
1378 | 1414 | ||
@@ -1380,6 +1416,13 @@ static int ftdi_write (struct usb_serial_port *port, | |||
1380 | dbg("write request of 0 bytes"); | 1416 | dbg("write request of 0 bytes"); |
1381 | return 0; | 1417 | return 0; |
1382 | } | 1418 | } |
1419 | spin_lock_irqsave(&priv->tx_lock, flags); | ||
1420 | if (priv->tx_outstanding_urbs > URB_UPPER_LIMIT) { | ||
1421 | spin_unlock_irqrestore(&priv->tx_lock, flags); | ||
1422 | dbg("%s - write limit hit\n", __FUNCTION__); | ||
1423 | return 0; | ||
1424 | } | ||
1425 | spin_unlock_irqrestore(&priv->tx_lock, flags); | ||
1383 | 1426 | ||
1384 | data_offset = priv->write_offset; | 1427 | data_offset = priv->write_offset; |
1385 | dbg("data_offset set to %d",data_offset); | 1428 | dbg("data_offset set to %d",data_offset); |
@@ -1446,6 +1489,12 @@ static int ftdi_write (struct usb_serial_port *port, | |||
1446 | err("%s - failed submitting write urb, error %d", __FUNCTION__, status); | 1489 | err("%s - failed submitting write urb, error %d", __FUNCTION__, status); |
1447 | count = status; | 1490 | count = status; |
1448 | kfree (buffer); | 1491 | kfree (buffer); |
1492 | } else { | ||
1493 | spin_lock_irqsave(&priv->tx_lock, flags); | ||
1494 | ++priv->tx_outstanding_urbs; | ||
1495 | priv->tx_outstanding_bytes += count; | ||
1496 | priv->tx_bytes += count; | ||
1497 | spin_unlock_irqrestore(&priv->tx_lock, flags); | ||
1449 | } | 1498 | } |
1450 | 1499 | ||
1451 | /* we are done with this urb, so let the host driver | 1500 | /* we are done with this urb, so let the host driver |
@@ -1461,7 +1510,11 @@ static int ftdi_write (struct usb_serial_port *port, | |||
1461 | 1510 | ||
1462 | static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | 1511 | static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs) |
1463 | { | 1512 | { |
1513 | unsigned long flags; | ||
1464 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 1514 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
1515 | struct ftdi_private *priv; | ||
1516 | int data_offset; /* will be 1 for the SIO and 0 otherwise */ | ||
1517 | unsigned long countback; | ||
1465 | 1518 | ||
1466 | /* free up the transfer buffer, as usb_free_urb() does not do this */ | 1519 | /* free up the transfer buffer, as usb_free_urb() does not do this */ |
1467 | kfree (urb->transfer_buffer); | 1520 | kfree (urb->transfer_buffer); |
@@ -1473,34 +1526,67 @@ static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
1473 | return; | 1526 | return; |
1474 | } | 1527 | } |
1475 | 1528 | ||
1529 | priv = usb_get_serial_port_data(port); | ||
1530 | if (!priv) { | ||
1531 | dbg("%s - bad port private data pointer - exiting", __FUNCTION__); | ||
1532 | return; | ||
1533 | } | ||
1534 | /* account for transferred data */ | ||
1535 | countback = urb->actual_length; | ||
1536 | data_offset = priv->write_offset; | ||
1537 | if (data_offset > 0) { | ||
1538 | /* Subtract the control bytes */ | ||
1539 | countback -= (data_offset * ((countback + (PKTSZ - 1)) / PKTSZ)); | ||
1540 | } | ||
1541 | spin_lock_irqsave(&priv->tx_lock, flags); | ||
1542 | --priv->tx_outstanding_urbs; | ||
1543 | priv->tx_outstanding_bytes -= countback; | ||
1544 | spin_unlock_irqrestore(&priv->tx_lock, flags); | ||
1545 | |||
1476 | usb_serial_port_softint(port); | 1546 | usb_serial_port_softint(port); |
1477 | } /* ftdi_write_bulk_callback */ | 1547 | } /* ftdi_write_bulk_callback */ |
1478 | 1548 | ||
1479 | 1549 | ||
1480 | static int ftdi_write_room( struct usb_serial_port *port ) | 1550 | static int ftdi_write_room( struct usb_serial_port *port ) |
1481 | { | 1551 | { |
1552 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
1553 | int room; | ||
1554 | unsigned long flags; | ||
1555 | |||
1482 | dbg("%s - port %d", __FUNCTION__, port->number); | 1556 | dbg("%s - port %d", __FUNCTION__, port->number); |
1483 | 1557 | ||
1484 | /* | 1558 | spin_lock_irqsave(&priv->tx_lock, flags); |
1485 | * We really can take anything the user throws at us | 1559 | if (priv->tx_outstanding_urbs < URB_UPPER_LIMIT) { |
1486 | * but let's pick a nice big number to tell the tty | 1560 | /* |
1487 | * layer that we have lots of free space | 1561 | * We really can take anything the user throws at us |
1488 | */ | 1562 | * but let's pick a nice big number to tell the tty |
1489 | return 2048; | 1563 | * layer that we have lots of free space |
1564 | */ | ||
1565 | room = 2048; | ||
1566 | } else { | ||
1567 | room = 0; | ||
1568 | } | ||
1569 | spin_unlock_irqrestore(&priv->tx_lock, flags); | ||
1570 | return room; | ||
1490 | } /* ftdi_write_room */ | 1571 | } /* ftdi_write_room */ |
1491 | 1572 | ||
1492 | 1573 | ||
1493 | static int ftdi_chars_in_buffer (struct usb_serial_port *port) | 1574 | static int ftdi_chars_in_buffer (struct usb_serial_port *port) |
1494 | { /* ftdi_chars_in_buffer */ | 1575 | { /* ftdi_chars_in_buffer */ |
1576 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
1577 | int buffered; | ||
1578 | unsigned long flags; | ||
1579 | |||
1495 | dbg("%s - port %d", __FUNCTION__, port->number); | 1580 | dbg("%s - port %d", __FUNCTION__, port->number); |
1496 | 1581 | ||
1497 | /* | 1582 | spin_lock_irqsave(&priv->tx_lock, flags); |
1498 | * We can't really account for how much data we | 1583 | buffered = (int)priv->tx_outstanding_bytes; |
1499 | * have sent out, but hasn't made it through to the | 1584 | spin_unlock_irqrestore(&priv->tx_lock, flags); |
1500 | * device, so just tell the tty layer that everything | 1585 | if (buffered < 0) { |
1501 | * is flushed. | 1586 | err("%s outstanding tx bytes is negative!", __FUNCTION__); |
1502 | */ | 1587 | buffered = 0; |
1503 | return 0; | 1588 | } |
1589 | return buffered; | ||
1504 | } /* ftdi_chars_in_buffer */ | 1590 | } /* ftdi_chars_in_buffer */ |
1505 | 1591 | ||
1506 | 1592 | ||
@@ -1510,6 +1596,8 @@ static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
1510 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 1596 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
1511 | struct tty_struct *tty; | 1597 | struct tty_struct *tty; |
1512 | struct ftdi_private *priv; | 1598 | struct ftdi_private *priv; |
1599 | unsigned long countread; | ||
1600 | unsigned long flags; | ||
1513 | 1601 | ||
1514 | if (urb->number_of_packets > 0) { | 1602 | if (urb->number_of_packets > 0) { |
1515 | err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__, | 1603 | err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__, |
@@ -1544,6 +1632,13 @@ static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
1544 | return; | 1632 | return; |
1545 | } | 1633 | } |
1546 | 1634 | ||
1635 | /* count data bytes, but not status bytes */ | ||
1636 | countread = urb->actual_length; | ||
1637 | countread -= 2 * ((countread + (PKTSZ - 1)) / PKTSZ); | ||
1638 | spin_lock_irqsave(&priv->rx_lock, flags); | ||
1639 | priv->rx_bytes += countread; | ||
1640 | spin_unlock_irqrestore(&priv->rx_lock, flags); | ||
1641 | |||
1547 | ftdi_process_read(port); | 1642 | ftdi_process_read(port); |
1548 | 1643 | ||
1549 | } /* ftdi_read_bulk_callback */ | 1644 | } /* ftdi_read_bulk_callback */ |