aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/serial/ftdi_sio.c103
1 files changed, 90 insertions, 13 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 9cf4069895c1..ff06c01a555b 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -550,11 +550,17 @@ struct ftdi_private {
550 spinlock_t rx_lock; /* spinlock for receive state */ 550 spinlock_t rx_lock; /* spinlock for receive state */
551 struct work_struct rx_work; 551 struct work_struct rx_work;
552 int rx_processed; 552 int rx_processed;
553 unsigned long rx_bytes;
553 554
554 __u16 interface; /* FT2232C port interface (0 for FT232/245) */ 555 __u16 interface; /* FT2232C port interface (0 for FT232/245) */
555 556
556 int force_baud; /* if non-zero, force the baud rate to this value */ 557 int force_baud; /* if non-zero, force the baud rate to this value */
557 int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */ 558 int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */
559
560 spinlock_t tx_lock; /* spinlock for transmit state */
561 unsigned long tx_bytes;
562 unsigned long tx_outstanding_bytes;
563 unsigned long tx_outstanding_urbs;
558}; 564};
559 565
560/* Used for TIOCMIWAIT */ 566/* Used for TIOCMIWAIT */
@@ -628,6 +634,9 @@ static struct usb_serial_driver ftdi_sio_device = {
628#define HIGH 1 634#define HIGH 1
629#define LOW 0 635#define LOW 0
630 636
637/* number of outstanding urbs to prevent userspace DoS from happening */
638#define URB_UPPER_LIMIT 42
639
631/* 640/*
632 * *************************************************************************** 641 * ***************************************************************************
633 * Utlity functions 642 * Utlity functions
@@ -1158,6 +1167,7 @@ static int ftdi_sio_attach (struct usb_serial *serial)
1158 } 1167 }
1159 1168
1160 spin_lock_init(&priv->rx_lock); 1169 spin_lock_init(&priv->rx_lock);
1170 spin_lock_init(&priv->tx_lock);
1161 init_waitqueue_head(&priv->delta_msr_wait); 1171 init_waitqueue_head(&priv->delta_msr_wait);
1162 /* This will push the characters through immediately rather 1172 /* This will push the characters through immediately rather
1163 than queue a task to deliver them */ 1173 than queue a task to deliver them */
@@ -1272,6 +1282,13 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp)
1272 1282
1273 dbg("%s", __FUNCTION__); 1283 dbg("%s", __FUNCTION__);
1274 1284
1285 spin_lock_irqsave(&priv->tx_lock, flags);
1286 priv->tx_bytes = 0;
1287 spin_unlock_irqrestore(&priv->tx_lock, flags);
1288 spin_lock_irqsave(&priv->rx_lock, flags);
1289 priv->rx_bytes = 0;
1290 spin_unlock_irqrestore(&priv->rx_lock, flags);
1291
1275 if (port->tty) 1292 if (port->tty)
1276 port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; 1293 port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
1277 1294
@@ -1374,6 +1391,7 @@ static int ftdi_write (struct usb_serial_port *port,
1374 int data_offset ; /* will be 1 for the SIO and 0 otherwise */ 1391 int data_offset ; /* will be 1 for the SIO and 0 otherwise */
1375 int status; 1392 int status;
1376 int transfer_size; 1393 int transfer_size;
1394 unsigned long flags;
1377 1395
1378 dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count); 1396 dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count);
1379 1397
@@ -1381,6 +1399,13 @@ static int ftdi_write (struct usb_serial_port *port,
1381 dbg("write request of 0 bytes"); 1399 dbg("write request of 0 bytes");
1382 return 0; 1400 return 0;
1383 } 1401 }
1402 spin_lock_irqsave(&priv->tx_lock, flags);
1403 if (priv->tx_outstanding_urbs > URB_UPPER_LIMIT) {
1404 spin_unlock_irqrestore(&priv->tx_lock, flags);
1405 dbg("%s - write limit hit\n", __FUNCTION__);
1406 return 0;
1407 }
1408 spin_unlock_irqrestore(&priv->tx_lock, flags);
1384 1409
1385 data_offset = priv->write_offset; 1410 data_offset = priv->write_offset;
1386 dbg("data_offset set to %d",data_offset); 1411 dbg("data_offset set to %d",data_offset);
@@ -1447,6 +1472,12 @@ static int ftdi_write (struct usb_serial_port *port,
1447 err("%s - failed submitting write urb, error %d", __FUNCTION__, status); 1472 err("%s - failed submitting write urb, error %d", __FUNCTION__, status);
1448 count = status; 1473 count = status;
1449 kfree (buffer); 1474 kfree (buffer);
1475 } else {
1476 spin_lock_irqsave(&priv->tx_lock, flags);
1477 ++priv->tx_outstanding_urbs;
1478 priv->tx_outstanding_bytes += count;
1479 priv->tx_bytes += count;
1480 spin_unlock_irqrestore(&priv->tx_lock, flags);
1450 } 1481 }
1451 1482
1452 /* we are done with this urb, so let the host driver 1483 /* we are done with this urb, so let the host driver
@@ -1462,7 +1493,11 @@ static int ftdi_write (struct usb_serial_port *port,
1462 1493
1463static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs) 1494static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
1464{ 1495{
1496 unsigned long flags;
1465 struct usb_serial_port *port = (struct usb_serial_port *)urb->context; 1497 struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
1498 struct ftdi_private *priv;
1499 int data_offset; /* will be 1 for the SIO and 0 otherwise */
1500 unsigned long countback;
1466 1501
1467 /* free up the transfer buffer, as usb_free_urb() does not do this */ 1502 /* free up the transfer buffer, as usb_free_urb() does not do this */
1468 kfree (urb->transfer_buffer); 1503 kfree (urb->transfer_buffer);
@@ -1474,34 +1509,67 @@ static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
1474 return; 1509 return;
1475 } 1510 }
1476 1511
1512 priv = usb_get_serial_port_data(port);
1513 if (!priv) {
1514 dbg("%s - bad port private data pointer - exiting", __FUNCTION__);
1515 return;
1516 }
1517 /* account for transferred data */
1518 countback = urb->actual_length;
1519 data_offset = priv->write_offset;
1520 if (data_offset > 0) {
1521 /* Subtract the control bytes */
1522 countback -= (data_offset * ((countback + (PKTSZ - 1)) / PKTSZ));
1523 }
1524 spin_lock_irqsave(&priv->tx_lock, flags);
1525 --priv->tx_outstanding_urbs;
1526 priv->tx_outstanding_bytes -= countback;
1527 spin_unlock_irqrestore(&priv->tx_lock, flags);
1528
1477 usb_serial_port_softint(port); 1529 usb_serial_port_softint(port);
1478} /* ftdi_write_bulk_callback */ 1530} /* ftdi_write_bulk_callback */
1479 1531
1480 1532
1481static int ftdi_write_room( struct usb_serial_port *port ) 1533static int ftdi_write_room( struct usb_serial_port *port )
1482{ 1534{
1535 struct ftdi_private *priv = usb_get_serial_port_data(port);
1536 int room;
1537 unsigned long flags;
1538
1483 dbg("%s - port %d", __FUNCTION__, port->number); 1539 dbg("%s - port %d", __FUNCTION__, port->number);
1484 1540
1485 /* 1541 spin_lock_irqsave(&priv->tx_lock, flags);
1486 * We really can take anything the user throws at us 1542 if (priv->tx_outstanding_urbs < URB_UPPER_LIMIT) {
1487 * but let's pick a nice big number to tell the tty 1543 /*
1488 * layer that we have lots of free space 1544 * We really can take anything the user throws at us
1489 */ 1545 * but let's pick a nice big number to tell the tty
1490 return 2048; 1546 * layer that we have lots of free space
1547 */
1548 room = 2048;
1549 } else {
1550 room = 0;
1551 }
1552 spin_unlock_irqrestore(&priv->tx_lock, flags);
1553 return room;
1491} /* ftdi_write_room */ 1554} /* ftdi_write_room */
1492 1555
1493 1556
1494static int ftdi_chars_in_buffer (struct usb_serial_port *port) 1557static int ftdi_chars_in_buffer (struct usb_serial_port *port)
1495{ /* ftdi_chars_in_buffer */ 1558{ /* ftdi_chars_in_buffer */
1559 struct ftdi_private *priv = usb_get_serial_port_data(port);
1560 int buffered;
1561 unsigned long flags;
1562
1496 dbg("%s - port %d", __FUNCTION__, port->number); 1563 dbg("%s - port %d", __FUNCTION__, port->number);
1497 1564
1498 /* 1565 spin_lock_irqsave(&priv->tx_lock, flags);
1499 * We can't really account for how much data we 1566 buffered = (int)priv->tx_outstanding_bytes;
1500 * have sent out, but hasn't made it through to the 1567 spin_unlock_irqrestore(&priv->tx_lock, flags);
1501 * device, so just tell the tty layer that everything 1568 if (buffered < 0) {
1502 * is flushed. 1569 err("%s outstanding tx bytes is negative!", __FUNCTION__);
1503 */ 1570 buffered = 0;
1504 return 0; 1571 }
1572 return buffered;
1505} /* ftdi_chars_in_buffer */ 1573} /* ftdi_chars_in_buffer */
1506 1574
1507 1575
@@ -1511,6 +1579,8 @@ static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
1511 struct usb_serial_port *port = (struct usb_serial_port *)urb->context; 1579 struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
1512 struct tty_struct *tty; 1580 struct tty_struct *tty;
1513 struct ftdi_private *priv; 1581 struct ftdi_private *priv;
1582 unsigned long countread;
1583 unsigned long flags;
1514 1584
1515 if (urb->number_of_packets > 0) { 1585 if (urb->number_of_packets > 0) {
1516 err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__, 1586 err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__,
@@ -1545,6 +1615,13 @@ static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
1545 return; 1615 return;
1546 } 1616 }
1547 1617
1618 /* count data bytes, but not status bytes */
1619 countread = urb->actual_length;
1620 countread -= 2 * ((countread + (PKTSZ - 1)) / PKTSZ);
1621 spin_lock_irqsave(&priv->rx_lock, flags);
1622 priv->rx_bytes += countread;
1623 spin_unlock_irqrestore(&priv->rx_lock, flags);
1624
1548 ftdi_process_read(port); 1625 ftdi_process_read(port);
1549 1626
1550} /* ftdi_read_bulk_callback */ 1627} /* ftdi_read_bulk_callback */