aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/ftdi_sio.c
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2009-06-11 08:55:34 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-11 11:51:05 -0400
commit557aaa7ffab639d0190b935a041b16ae44606342 (patch)
tree1b555b5ea37078177896ccff0648cd152a98698d /drivers/usb/serial/ftdi_sio.c
parent4cc27bd6d7d6750dba33b4ccb4585c00b8fca7d2 (diff)
ft232: support the ASYNC_LOW_LATENCY flag
This allows users to use the standard setserial command with this FT232 feature as well as obscure chip specific interfaces we have now. We keep track of and respect the sysfs value for non-low-latency cases. In theory we could do smart stuff with VTIME and the like but this seems of questionable worth. Closes-bug: http://bugzilla.kernel.org/show_bug.cgi?id=9120 Signed-off-by: Alan Cox <alan@linux.intel.com) Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
-rw-r--r--drivers/usb/serial/ftdi_sio.c94
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
1042static 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
1067static 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
1043static int get_serial_info(struct usb_serial_port *port, 1091static 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
1102check_and_exit: 1151check_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. */
1218static ssize_t store_latency_timer(struct device *dev, 1253static 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),