aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r--drivers/usb/serial/ftdi_sio.c41
1 files changed, 16 insertions, 25 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 9699580331a..8fe034d2d3e 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -2328,6 +2328,8 @@ static int ftdi_ioctl(struct tty_struct *tty,
2328{ 2328{
2329 struct usb_serial_port *port = tty->driver_data; 2329 struct usb_serial_port *port = tty->driver_data;
2330 struct ftdi_private *priv = usb_get_serial_port_data(port); 2330 struct ftdi_private *priv = usb_get_serial_port_data(port);
2331 struct async_icount cnow;
2332 struct async_icount cprev;
2331 2333
2332 dbg("%s cmd 0x%04x", __func__, cmd); 2334 dbg("%s cmd 0x%04x", __func__, cmd);
2333 2335
@@ -2347,41 +2349,30 @@ static int ftdi_ioctl(struct tty_struct *tty,
2347 * - mask passed in arg for lines of interest 2349 * - mask passed in arg for lines of interest
2348 * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) 2350 * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
2349 * Caller should use TIOCGICOUNT to see which one it was. 2351 * Caller should use TIOCGICOUNT to see which one it was.
2350 * (except that the driver doesn't support it !)
2351 * 2352 *
2352 * This code is borrowed from linux/drivers/char/serial.c 2353 * This code is borrowed from linux/drivers/char/serial.c
2353 */ 2354 */
2354 case TIOCMIWAIT: 2355 case TIOCMIWAIT:
2355 while (priv != NULL) { 2356 cprev = priv->icount;
2357 while (1) {
2356 interruptible_sleep_on(&priv->delta_msr_wait); 2358 interruptible_sleep_on(&priv->delta_msr_wait);
2357 /* see if a signal did it */ 2359 /* see if a signal did it */
2358 if (signal_pending(current)) 2360 if (signal_pending(current))
2359 return -ERESTARTSYS; 2361 return -ERESTARTSYS;
2360 else { 2362 cnow = priv->icount;
2361 char diff = priv->diff_status; 2363 if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
2362 2364 cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
2363 if (diff == 0) 2365 return -EIO; /* no change => error */
2364 return -EIO; /* no change => error */ 2366 if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
2365 2367 ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
2366 /* Consume all events */ 2368 ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
2367 priv->diff_status = 0; 2369 ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
2368 2370 return 0;
2369 /* Return 0 if caller wanted to know about
2370 these bits */
2371 if (((arg & TIOCM_RNG) && (diff & FTDI_RS0_RI)) ||
2372 ((arg & TIOCM_DSR) && (diff & FTDI_RS0_DSR)) ||
2373 ((arg & TIOCM_CD) && (diff & FTDI_RS0_RLSD)) ||
2374 ((arg & TIOCM_CTS) && (diff & FTDI_RS0_CTS))) {
2375 return 0;
2376 }
2377 /*
2378 * Otherwise caller can't care less about what
2379 * happened,and so we continue to wait for more
2380 * events.
2381 */
2382 } 2371 }
2372 cprev = cnow;
2383 } 2373 }
2384 return 0; 2374 /* not reached */
2375 break;
2385 case TIOCSERGETLSR: 2376 case TIOCSERGETLSR:
2386 return get_lsr_info(port, (struct serial_struct __user *)arg); 2377 return get_lsr_info(port, (struct serial_struct __user *)arg);
2387 break; 2378 break;