]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/usb/class/cdc-acm.c
USB: cdc-acm: fix rounding error in TIOCSSERIAL
[linux.git] / drivers / usb / class / cdc-acm.c
index 62f4fb9b362f14533c86ba324588158517787019..47f09a6ce7bda47a28d2b4390bce144548e49d6e 100644 (file)
@@ -896,10 +896,10 @@ static int get_serial_info(struct tty_struct *tty, struct serial_struct *ss)
 
        ss->xmit_fifo_size = acm->writesize;
        ss->baud_base = le32_to_cpu(acm->line.dwDTERate);
-       ss->close_delay = acm->port.close_delay / 10;
+       ss->close_delay = jiffies_to_msecs(acm->port.close_delay) / 10;
        ss->closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
                                ASYNC_CLOSING_WAIT_NONE :
-                               acm->port.closing_wait / 10;
+                               jiffies_to_msecs(acm->port.closing_wait) / 10;
        return 0;
 }
 
@@ -907,24 +907,32 @@ static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
 {
        struct acm *acm = tty->driver_data;
        unsigned int closing_wait, close_delay;
+       unsigned int old_closing_wait, old_close_delay;
        int retval = 0;
 
-       close_delay = ss->close_delay * 10;
+       close_delay = msecs_to_jiffies(ss->close_delay * 10);
        closing_wait = ss->closing_wait == ASYNC_CLOSING_WAIT_NONE ?
-                       ASYNC_CLOSING_WAIT_NONE : ss->closing_wait * 10;
+                       ASYNC_CLOSING_WAIT_NONE :
+                       msecs_to_jiffies(ss->closing_wait * 10);
+
+       /* we must redo the rounding here, so that the values match */
+       old_close_delay = jiffies_to_msecs(acm->port.close_delay) / 10;
+       old_closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
+                               ASYNC_CLOSING_WAIT_NONE :
+                               jiffies_to_msecs(acm->port.closing_wait) / 10;
 
        mutex_lock(&acm->port.mutex);
 
-       if (!capable(CAP_SYS_ADMIN)) {
-               if ((close_delay != acm->port.close_delay) ||
-                   (closing_wait != acm->port.closing_wait))
+       if ((ss->close_delay != old_close_delay) ||
+            (ss->closing_wait != old_closing_wait)) {
+               if (!capable(CAP_SYS_ADMIN))
                        retval = -EPERM;
-               else
-                       retval = -EOPNOTSUPP;
-       } else {
-               acm->port.close_delay  = close_delay;
-               acm->port.closing_wait = closing_wait;
-       }
+               else {
+                       acm->port.close_delay  = close_delay;
+                       acm->port.closing_wait = closing_wait;
+               }
+       } else
+               retval = -EOPNOTSUPP;
 
        mutex_unlock(&acm->port.mutex);
        return retval;