From: Arnd Bergmann <arnd@arndb.de>
To: linux-kernel@vger.kernel.org
Cc: Arnd Bergmann <arnd@arndb.de>, Johan Hovold <jhovold@gmail.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
linux-usb@vger.kernel.org
Subject: [PATCH, RFC 15/30] usbserial: stop using interruptible_sleep_on
Date: Thu, 2 Jan 2014 13:07:39 +0100 [thread overview]
Message-ID: <1388664474-1710039-16-git-send-email-arnd@arndb.de> (raw)
In-Reply-To: <1388664474-1710039-1-git-send-email-arnd@arndb.de>
We really want to kill off interruptible_sleep_on, which is defined
in a way that is always racy. There are four usb-serial drivers using
it to implement their tiocmiwait() functions, which is defined in
a way that always has a race when called from user space.
This patch changes the four drivers in the same way to use an open-coded
prepare_to_wait/finish_wait loop to get rid of the deprecated function
call, but it does not address the fundamental race.
This particular method of implementing it was chosen because it is
least invasive, a better but more invasive alternative would be
to use usb_serial_generic_tiocmiwait, which is something I did not
dare try without access to hardware.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Johan Hovold <jhovold@gmail.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-usb@vger.kernel.org
---
drivers/usb/serial/ch341.c | 29 ++++++++++++++++--------
drivers/usb/serial/cypress_m8.c | 49 ++++++++++++++++++++++++++---------------
drivers/usb/serial/f81232.c | 29 ++++++++++++++++--------
drivers/usb/serial/pl2303.c | 29 ++++++++++++++++--------
4 files changed, 91 insertions(+), 45 deletions(-)
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index c2a4171..f5e0eea 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -508,20 +508,22 @@ static int ch341_tiocmiwait(struct tty_struct *tty, unsigned long arg)
u8 status;
u8 changed;
u8 multi_change = 0;
+ DEFINE_WAIT(wait);
+ int ret;
spin_lock_irqsave(&priv->lock, flags);
prevstatus = priv->line_status;
priv->multi_status_change = 0;
spin_unlock_irqrestore(&priv->lock, flags);
+ ret = 0;
while (!multi_change) {
- interruptible_sleep_on(&port->port.delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
+ prepare_to_wait(&port->port.delta_msr_wait, &wait, TASK_INTERRUPTIBLE);
- if (port->serial->disconnected)
- return -EIO;
+ if (port->serial->disconnected) {
+ ret = -EIO;
+ break;
+ }
spin_lock_irqsave(&priv->lock, flags);
status = priv->line_status;
@@ -534,12 +536,21 @@ static int ch341_tiocmiwait(struct tty_struct *tty, unsigned long arg)
((arg & TIOCM_DSR) && (changed & CH341_BIT_DSR)) ||
((arg & TIOCM_CD) && (changed & CH341_BIT_DCD)) ||
((arg & TIOCM_CTS) && (changed & CH341_BIT_CTS))) {
- return 0;
+ break;
}
+
+ schedule();
+
+ /* see if a signal did it */
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+
prevstatus = status;
}
-
- return 0;
+ finish_wait(&port->port.delta_msr_wait, &wait);
+ return ret;
}
static int ch341_tiocmget(struct tty_struct *tty)
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 558605d..e05c9c6 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -869,38 +869,51 @@ static int cypress_tiocmiwait(struct tty_struct *tty, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
- char diff;
+ char changed;
+ DEFINE_WAIT(wait);
+ int ret;
- for (;;) {
- interruptible_sleep_on(&port->port.delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
+ while (1) {
+ prepare_to_wait(&port->port.delta_msr_wait, &wait, TASK_INTERRUPTIBLE);
- if (port->serial->disconnected)
- return -EIO;
+ if (port->serial->disconnected) {
+ ret = -EIO;
+ break;
+ }
- diff = priv->diff_status;
- if (diff == 0)
- return -EIO; /* no change => error */
+ changed = priv->diff_status;
+ if (changed == 0) {
+ ret = -EIO; /* no change => error */
+ break;
+ }
/* consume all events */
priv->diff_status = 0;
/* return 0 if caller wanted to know about
these bits */
- if (((arg & TIOCM_RNG) && (diff & UART_RI)) ||
- ((arg & TIOCM_DSR) && (diff & UART_DSR)) ||
- ((arg & TIOCM_CD) && (diff & UART_CD)) ||
- ((arg & TIOCM_CTS) && (diff & UART_CTS)))
- return 0;
+ if (((arg & TIOCM_RNG) && (changed & UART_RI)) ||
+ ((arg & TIOCM_DSR) && (changed & UART_DSR)) ||
+ ((arg & TIOCM_CD) && (changed & UART_CD)) ||
+ ((arg & TIOCM_CTS) && (changed & UART_CTS))) {
+ ret = 0;
+ break;
+ }
+
+ schedule();
+
+ /* see if a signal did it */
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
/* otherwise caller can't care less about what
* happened, and so we continue to wait for
* more events.
*/
}
-
- return 0;
+ finish_wait(&port->port.delta_msr_wait, &wait);
+ return ret;
}
static void cypress_set_termios(struct tty_struct *tty,
diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c
index 639a18f..935f2e5 100644
--- a/drivers/usb/serial/f81232.c
+++ b/drivers/usb/serial/f81232.c
@@ -249,19 +249,20 @@ static int f81232_tiocmiwait(struct tty_struct *tty, unsigned long arg)
unsigned int prevstatus;
unsigned int status;
unsigned int changed;
+ DEFINE_WAIT(wait);
+ int ret;
spin_lock_irqsave(&priv->lock, flags);
prevstatus = priv->line_status;
spin_unlock_irqrestore(&priv->lock, flags);
while (1) {
- interruptible_sleep_on(&port->port.delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
+ prepare_to_wait(&port->port.delta_msr_wait, &wait, TASK_INTERRUPTIBLE);
- if (port->serial->disconnected)
- return -EIO;
+ if (port->serial->disconnected) {
+ ret = -EIO;
+ break;
+ }
spin_lock_irqsave(&priv->lock, flags);
status = priv->line_status;
@@ -273,12 +274,22 @@ static int f81232_tiocmiwait(struct tty_struct *tty, unsigned long arg)
((arg & TIOCM_DSR) && (changed & UART_DSR)) ||
((arg & TIOCM_CD) && (changed & UART_DCD)) ||
((arg & TIOCM_CTS) && (changed & UART_CTS))) {
- return 0;
+ ret = 0;
+ break;
+ }
+
+ schedule();
+
+ /* see if a signal did it */
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
}
+
prevstatus = status;
}
- /* NOTREACHED */
- return 0;
+ finish_wait(&port->port.delta_msr_wait, &wait);
+ return ret;
}
static int f81232_ioctl(struct tty_struct *tty,
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 1e3318d..e8f30bc 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -594,19 +594,20 @@ static int pl2303_tiocmiwait(struct tty_struct *tty, unsigned long arg)
unsigned int prevstatus;
unsigned int status;
unsigned int changed;
+ DEFINE_WAIT(wait);
+ int ret;
spin_lock_irqsave(&priv->lock, flags);
prevstatus = priv->line_status;
spin_unlock_irqrestore(&priv->lock, flags);
while (1) {
- interruptible_sleep_on(&port->port.delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
+ prepare_to_wait(&port->port.delta_msr_wait, &wait, TASK_INTERRUPTIBLE);
- if (port->serial->disconnected)
- return -EIO;
+ if (port->serial->disconnected) {
+ ret = -EIO;
+ break;
+ }
spin_lock_irqsave(&priv->lock, flags);
status = priv->line_status;
@@ -618,12 +619,22 @@ static int pl2303_tiocmiwait(struct tty_struct *tty, unsigned long arg)
((arg & TIOCM_DSR) && (changed & UART_DSR)) ||
((arg & TIOCM_CD) && (changed & UART_DCD)) ||
((arg & TIOCM_CTS) && (changed & UART_CTS))) {
- return 0;
+ ret = 0;
+ break;
+ }
+
+ schedule();
+
+ /* see if a signal did it */
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
}
+
prevstatus = status;
}
- /* NOTREACHED */
- return 0;
+ finish_wait(&port->port.delta_msr_wait, &wait);
+ return ret;
}
static int pl2303_ioctl(struct tty_struct *tty,
--
1.8.3.2
next prev parent reply other threads:[~2014-01-02 12:12 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-01-02 12:07 [PATCH, RFC 00/30] sleep_on removal Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 01/30] ataflop: fix sleep_on races Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 02/30] scsi: atari_scsi: fix sleep_on race Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 03/30] DAC960: remove sleep_on usage Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 04/30] swim3: fix interruptible_sleep_on race Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 05/30] [media] omap_vout: avoid sleep_on race Arnd Bergmann
2014-01-17 10:23 ` Hans Verkuil
2014-02-26 9:03 ` Arnd Bergmann
2014-02-26 9:56 ` Hans Verkuil
2014-01-02 12:07 ` [PATCH, RFC 06/30] [media] usbvision: remove bogus sleep_on_timeout Arnd Bergmann
2014-01-17 10:26 ` Hans Verkuil
2014-01-02 12:07 ` [PATCH, RFC 07/30] [media] radio-cadet: avoid interruptible_sleep_on race Arnd Bergmann
2014-01-17 10:47 ` Hans Verkuil
2014-01-17 14:28 ` Arnd Bergmann
2014-02-07 9:32 ` Hans Verkuil
2014-02-07 9:47 ` Hans Verkuil
2014-02-07 10:17 ` Arnd Bergmann
2014-02-07 11:35 ` Hans Verkuil
2014-02-09 20:53 ` Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 08/30] [media] arv: fix sleep_on race Arnd Bergmann
2014-01-17 10:51 ` Hans Verkuil
2014-02-07 9:16 ` Hans Verkuil
2014-02-26 8:57 ` Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 09/30] staging: serqt_usb2: don't use sleep_on Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 10/30] staging: gdm72xx: fix interruptible_sleep_on race Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 11/30] staging: panel: " Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 12/30] parport: " Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 13/30] cris: sync_serial: remove interruptible_sleep_on Arnd Bergmann
2014-01-09 9:52 ` Jesper Nilsson
2014-01-02 12:07 ` [PATCH, RFC 14/30] tty/amiserial: avoid interruptible_sleep_on Arnd Bergmann
2014-01-02 12:07 ` Arnd Bergmann [this message]
2014-01-02 21:36 ` [PATCH, RFC 15/30] usbserial: stop using interruptible_sleep_on Johan Hovold
2014-01-03 14:01 ` Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 16/30] tty: synclink: avoid sleep_on race Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 17/30] atm: nicstar: remove interruptible_sleep_on_timeout Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 18/30] atm: firestream: fix interruptible_sleep_on race Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 19/30] isdn: pcbit: " Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 20/30] isdn: hisax/elsa: fix sleep_on race in elsa FSM Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 21/30] isdn: divert, hysdn: fix interruptible_sleep_on race Arnd Bergmann
2014-01-02 15:01 ` Sergei Shtylyov
2014-01-02 16:48 ` Arnd Bergmann
2014-01-02 23:00 ` Sergei Shtylyov
2014-01-02 12:07 ` [PATCH, RFC 22/30] isdn: fix multiple sleep_on races Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 23/30] oss: msnd_pinnacle: avoid interruptible_sleep_on_timeout Arnd Bergmann
2014-01-14 15:16 ` Takashi Iwai
2014-01-02 12:07 ` [PATCH, RFC 24/30] oss: midibuf: fix sleep_on races Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 25/30] oss: vwsnd: avoid interruptible_sleep_on Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 26/30] oss: dmasound: kill SLEEP() macro to avoid race Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 27/30] oss: remove last sleep_on users Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 28/30] sgi-xp: open-code interruptible_sleep_on_timeout Arnd Bergmann
2014-01-02 16:04 ` Robin Holt
2014-01-02 12:07 ` [PATCH, RFC 29/30] char: nwbutton: open-code interruptible_sleep_on Arnd Bergmann
2014-01-02 12:07 ` [PATCH, RFC 30/30] sched: remove sleep_on() and friends Arnd Bergmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1388664474-1710039-16-git-send-email-arnd@arndb.de \
--to=arnd@arndb.de \
--cc=gregkh@linuxfoundation.org \
--cc=jhovold@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®