diff options
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 94 |
1 files changed, 60 insertions, 34 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index d9d87111f9a9..21c053c31b9e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -89,6 +89,7 @@ struct ftdi_private { | |||
89 | int force_rtscts; /* if non-zero, force RTS-CTS to always | 89 | int force_rtscts; /* if non-zero, force RTS-CTS to always |
90 | be enabled */ | 90 | be enabled */ |
91 | 91 | ||
92 | unsigned int latency; /* latency setting in use */ | ||
92 | spinlock_t tx_lock; /* spinlock for transmit state */ | 93 | spinlock_t tx_lock; /* spinlock for transmit state */ |
93 | unsigned long tx_bytes; | 94 | unsigned long tx_bytes; |
94 | unsigned long tx_outstanding_bytes; | 95 | unsigned long tx_outstanding_bytes; |
@@ -1038,7 +1039,54 @@ static int change_speed(struct tty_struct *tty, struct usb_serial_port *port) | |||
1038 | return rv; | 1039 | return rv; |
1039 | } | 1040 | } |
1040 | 1041 | ||
1042 | static int write_latency_timer(struct usb_serial_port *port) | ||
1043 | { | ||
1044 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
1045 | struct usb_device *udev = port->serial->dev; | ||
1046 | char buf[1]; | ||
1047 | int rv = 0; | ||
1048 | int l = priv->latency; | ||
1049 | |||
1050 | if (priv->flags & ASYNC_LOW_LATENCY) | ||
1051 | l = 1; | ||
1052 | |||
1053 | dbg("%s: setting latency timer = %i", __func__, l); | ||
1054 | |||
1055 | rv = usb_control_msg(udev, | ||
1056 | usb_sndctrlpipe(udev, 0), | ||
1057 | FTDI_SIO_SET_LATENCY_TIMER_REQUEST, | ||
1058 | FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, | ||
1059 | l, priv->interface, | ||
1060 | buf, 0, WDR_TIMEOUT); | ||
1041 | 1061 | ||
1062 | if (rv < 0) | ||
1063 | dev_err(&port->dev, "Unable to write latency timer: %i\n", rv); | ||
1064 | return rv; | ||
1065 | } | ||
1066 | |||
1067 | static int read_latency_timer(struct usb_serial_port *port) | ||
1068 | { | ||
1069 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
1070 | struct usb_device *udev = port->serial->dev; | ||
1071 | unsigned short latency = 0; | ||
1072 | int rv = 0; | ||
1073 | |||
1074 | |||
1075 | dbg("%s", __func__); | ||
1076 | |||
1077 | rv = usb_control_msg(udev, | ||
1078 | usb_rcvctrlpipe(udev, 0), | ||
1079 | FTDI_SIO_GET_LATENCY_TIMER_REQUEST, | ||
1080 | FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE, | ||
1081 | 0, priv->interface, | ||
1082 | (char *) &latency, 1, WDR_TIMEOUT); | ||
1083 | |||
1084 | if (rv < 0) { | ||
1085 | dev_err(&port->dev, "Unable to read latency timer: %i\n", rv); | ||
1086 | return -EIO; | ||
1087 | } | ||
1088 | return latency; | ||
1089 | } | ||
1042 | 1090 | ||
1043 | static int get_serial_info(struct usb_serial_port *port, | 1091 | static int get_serial_info(struct usb_serial_port *port, |
1044 | struct serial_struct __user *retinfo) | 1092 | struct serial_struct __user *retinfo) |
@@ -1098,6 +1146,7 @@ static int set_serial_info(struct tty_struct *tty, | |||
1098 | priv->custom_divisor = new_serial.custom_divisor; | 1146 | priv->custom_divisor = new_serial.custom_divisor; |
1099 | 1147 | ||
1100 | tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 1148 | tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
1149 | write_latency_timer(port); | ||
1101 | 1150 | ||
1102 | check_and_exit: | 1151 | check_and_exit: |
1103 | if ((old_priv.flags & ASYNC_SPD_MASK) != | 1152 | if ((old_priv.flags & ASYNC_SPD_MASK) != |
@@ -1193,27 +1242,13 @@ static ssize_t show_latency_timer(struct device *dev, | |||
1193 | { | 1242 | { |
1194 | struct usb_serial_port *port = to_usb_serial_port(dev); | 1243 | struct usb_serial_port *port = to_usb_serial_port(dev); |
1195 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1244 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1196 | struct usb_device *udev = port->serial->dev; | 1245 | if (priv->flags & ASYNC_LOW_LATENCY) |
1197 | unsigned short latency = 0; | 1246 | return sprintf(buf, "1\n"); |
1198 | int rv = 0; | 1247 | else |
1199 | 1248 | return sprintf(buf, "%i\n", priv->latency); | |
1200 | |||
1201 | dbg("%s", __func__); | ||
1202 | |||
1203 | rv = usb_control_msg(udev, | ||
1204 | usb_rcvctrlpipe(udev, 0), | ||
1205 | FTDI_SIO_GET_LATENCY_TIMER_REQUEST, | ||
1206 | FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE, | ||
1207 | 0, priv->interface, | ||
1208 | (char *) &latency, 1, WDR_TIMEOUT); | ||
1209 | |||
1210 | if (rv < 0) { | ||
1211 | dev_err(dev, "Unable to read latency timer: %i\n", rv); | ||
1212 | return -EIO; | ||
1213 | } | ||
1214 | return sprintf(buf, "%i\n", latency); | ||
1215 | } | 1249 | } |
1216 | 1250 | ||
1251 | |||
1217 | /* Write a new value of the latency timer, in units of milliseconds. */ | 1252 | /* Write a new value of the latency timer, in units of milliseconds. */ |
1218 | static ssize_t store_latency_timer(struct device *dev, | 1253 | static ssize_t store_latency_timer(struct device *dev, |
1219 | struct device_attribute *attr, const char *valbuf, | 1254 | struct device_attribute *attr, const char *valbuf, |
@@ -1221,25 +1256,13 @@ static ssize_t store_latency_timer(struct device *dev, | |||
1221 | { | 1256 | { |
1222 | struct usb_serial_port *port = to_usb_serial_port(dev); | 1257 | struct usb_serial_port *port = to_usb_serial_port(dev); |
1223 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1258 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1224 | struct usb_device *udev = port->serial->dev; | ||
1225 | char buf[1]; | ||
1226 | int v = simple_strtoul(valbuf, NULL, 10); | 1259 | int v = simple_strtoul(valbuf, NULL, 10); |
1227 | int rv = 0; | 1260 | int rv = 0; |
1228 | 1261 | ||
1229 | dbg("%s: setting latency timer = %i", __func__, v); | 1262 | priv->latency = v; |
1230 | 1263 | rv = write_latency_timer(port); | |
1231 | rv = usb_control_msg(udev, | 1264 | if (rv < 0) |
1232 | usb_sndctrlpipe(udev, 0), | ||
1233 | FTDI_SIO_SET_LATENCY_TIMER_REQUEST, | ||
1234 | FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, | ||
1235 | v, priv->interface, | ||
1236 | buf, 0, WDR_TIMEOUT); | ||
1237 | |||
1238 | if (rv < 0) { | ||
1239 | dev_err(dev, "Unable to write latency timer: %i\n", rv); | ||
1240 | return -EIO; | 1265 | return -EIO; |
1241 | } | ||
1242 | |||
1243 | return count; | 1266 | return count; |
1244 | } | 1267 | } |
1245 | 1268 | ||
@@ -1393,6 +1416,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) | |||
1393 | usb_set_serial_port_data(port, priv); | 1416 | usb_set_serial_port_data(port, priv); |
1394 | 1417 | ||
1395 | ftdi_determine_type(port); | 1418 | ftdi_determine_type(port); |
1419 | read_latency_timer(port); | ||
1396 | create_sysfs_attrs(port); | 1420 | create_sysfs_attrs(port); |
1397 | return 0; | 1421 | return 0; |
1398 | } | 1422 | } |
@@ -1515,6 +1539,8 @@ static int ftdi_open(struct tty_struct *tty, | |||
1515 | if (tty) | 1539 | if (tty) |
1516 | tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 1540 | tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
1517 | 1541 | ||
1542 | write_latency_timer(port); | ||
1543 | |||
1518 | /* No error checking for this (will get errors later anyway) */ | 1544 | /* No error checking for this (will get errors later anyway) */ |
1519 | /* See ftdi_sio.h for description of what is reset */ | 1545 | /* See ftdi_sio.h for description of what is reset */ |
1520 | usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 1546 | usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |