diff options
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 57 |
1 files changed, 31 insertions, 26 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 23d14b98ae2a..c540de15aad2 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -1439,10 +1439,13 @@ static int read_latency_timer(struct usb_serial_port *port) | |||
1439 | FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE, | 1439 | FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE, |
1440 | 0, priv->interface, | 1440 | 0, priv->interface, |
1441 | buf, 1, WDR_TIMEOUT); | 1441 | buf, 1, WDR_TIMEOUT); |
1442 | if (rv < 0) | 1442 | if (rv < 1) { |
1443 | dev_err(&port->dev, "Unable to read latency timer: %i\n", rv); | 1443 | dev_err(&port->dev, "Unable to read latency timer: %i\n", rv); |
1444 | else | 1444 | if (rv >= 0) |
1445 | rv = -EIO; | ||
1446 | } else { | ||
1445 | priv->latency = buf[0]; | 1447 | priv->latency = buf[0]; |
1448 | } | ||
1446 | 1449 | ||
1447 | kfree(buf); | 1450 | kfree(buf); |
1448 | 1451 | ||
@@ -1531,7 +1534,7 @@ check_and_exit: | |||
1531 | } | 1534 | } |
1532 | 1535 | ||
1533 | static int get_lsr_info(struct usb_serial_port *port, | 1536 | static int get_lsr_info(struct usb_serial_port *port, |
1534 | struct serial_struct __user *retinfo) | 1537 | unsigned int __user *retinfo) |
1535 | { | 1538 | { |
1536 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1539 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1537 | unsigned int result = 0; | 1540 | unsigned int result = 0; |
@@ -1802,8 +1805,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) | |||
1802 | 1805 | ||
1803 | mutex_init(&priv->cfg_lock); | 1806 | mutex_init(&priv->cfg_lock); |
1804 | 1807 | ||
1805 | priv->flags = ASYNC_LOW_LATENCY; | ||
1806 | |||
1807 | if (quirk && quirk->port_probe) | 1808 | if (quirk && quirk->port_probe) |
1808 | quirk->port_probe(priv); | 1809 | quirk->port_probe(priv); |
1809 | 1810 | ||
@@ -2067,6 +2068,20 @@ static int ftdi_process_packet(struct usb_serial_port *port, | |||
2067 | priv->prev_status = status; | 2068 | priv->prev_status = status; |
2068 | } | 2069 | } |
2069 | 2070 | ||
2071 | /* save if the transmitter is empty or not */ | ||
2072 | if (packet[1] & FTDI_RS_TEMT) | ||
2073 | priv->transmit_empty = 1; | ||
2074 | else | ||
2075 | priv->transmit_empty = 0; | ||
2076 | |||
2077 | len -= 2; | ||
2078 | if (!len) | ||
2079 | return 0; /* status only */ | ||
2080 | |||
2081 | /* | ||
2082 | * Break and error status must only be processed for packets with | ||
2083 | * data payload to avoid over-reporting. | ||
2084 | */ | ||
2070 | flag = TTY_NORMAL; | 2085 | flag = TTY_NORMAL; |
2071 | if (packet[1] & FTDI_RS_ERR_MASK) { | 2086 | if (packet[1] & FTDI_RS_ERR_MASK) { |
2072 | /* Break takes precedence over parity, which takes precedence | 2087 | /* Break takes precedence over parity, which takes precedence |
@@ -2089,15 +2104,6 @@ static int ftdi_process_packet(struct usb_serial_port *port, | |||
2089 | } | 2104 | } |
2090 | } | 2105 | } |
2091 | 2106 | ||
2092 | /* save if the transmitter is empty or not */ | ||
2093 | if (packet[1] & FTDI_RS_TEMT) | ||
2094 | priv->transmit_empty = 1; | ||
2095 | else | ||
2096 | priv->transmit_empty = 0; | ||
2097 | |||
2098 | len -= 2; | ||
2099 | if (!len) | ||
2100 | return 0; /* status only */ | ||
2101 | port->icount.rx += len; | 2107 | port->icount.rx += len; |
2102 | ch = packet + 2; | 2108 | ch = packet + 2; |
2103 | 2109 | ||
@@ -2428,8 +2434,12 @@ static int ftdi_get_modem_status(struct usb_serial_port *port, | |||
2428 | FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, | 2434 | FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, |
2429 | 0, priv->interface, | 2435 | 0, priv->interface, |
2430 | buf, len, WDR_TIMEOUT); | 2436 | buf, len, WDR_TIMEOUT); |
2431 | if (ret < 0) { | 2437 | |
2438 | /* NOTE: We allow short responses and handle that below. */ | ||
2439 | if (ret < 1) { | ||
2432 | dev_err(&port->dev, "failed to get modem status: %d\n", ret); | 2440 | dev_err(&port->dev, "failed to get modem status: %d\n", ret); |
2441 | if (ret >= 0) | ||
2442 | ret = -EIO; | ||
2433 | ret = usb_translate_errors(ret); | 2443 | ret = usb_translate_errors(ret); |
2434 | goto out; | 2444 | goto out; |
2435 | } | 2445 | } |
@@ -2480,20 +2490,15 @@ static int ftdi_ioctl(struct tty_struct *tty, | |||
2480 | unsigned int cmd, unsigned long arg) | 2490 | unsigned int cmd, unsigned long arg) |
2481 | { | 2491 | { |
2482 | struct usb_serial_port *port = tty->driver_data; | 2492 | struct usb_serial_port *port = tty->driver_data; |
2493 | void __user *argp = (void __user *)arg; | ||
2483 | 2494 | ||
2484 | /* Based on code from acm.c and others */ | ||
2485 | switch (cmd) { | 2495 | switch (cmd) { |
2486 | 2496 | case TIOCGSERIAL: | |
2487 | case TIOCGSERIAL: /* gets serial port data */ | 2497 | return get_serial_info(port, argp); |
2488 | return get_serial_info(port, | 2498 | case TIOCSSERIAL: |
2489 | (struct serial_struct __user *) arg); | 2499 | return set_serial_info(tty, port, argp); |
2490 | |||
2491 | case TIOCSSERIAL: /* sets serial port data */ | ||
2492 | return set_serial_info(tty, port, | ||
2493 | (struct serial_struct __user *) arg); | ||
2494 | case TIOCSERGETLSR: | 2500 | case TIOCSERGETLSR: |
2495 | return get_lsr_info(port, (struct serial_struct __user *)arg); | 2501 | return get_lsr_info(port, argp); |
2496 | break; | ||
2497 | default: | 2502 | default: |
2498 | break; | 2503 | break; |
2499 | } | 2504 | } |