From: Johan Hovold Date: Thu, 24 Dec 2009 11:42:09 +0000 (+0100) Subject: USB: ftdi_sio: fix DMA buffers on stack X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=66e47e6006a558b33c6f15bd2e072d52c40e0159;p=openwrt%2Fstaging%2Fblogic.git USB: ftdi_sio: fix DMA buffers on stack Also remove unnecessary buffer allocations for zero-length transfers. Reported-by: Matti Aarnio Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 59b6cbf020a0..a6e5a0d95566 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -935,7 +935,6 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned int clear) { struct ftdi_private *priv = usb_get_serial_port_data(port); - char *buf; unsigned urb_value; int rv; @@ -944,10 +943,6 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, return 0; /* no change */ } - buf = kmalloc(1, GFP_NOIO); - if (!buf) - return -ENOMEM; - clear &= ~set; /* 'set' takes precedence over 'clear' */ urb_value = 0; if (clear & TIOCM_DTR) @@ -963,9 +958,7 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, urb_value, priv->interface, - buf, 0, WDR_TIMEOUT); - - kfree(buf); + NULL, 0, WDR_TIMEOUT); if (rv < 0) { dbg("%s Error from MODEM_CTRL urb: DTR %s, RTS %s", __func__, @@ -1124,16 +1117,11 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty, static int change_speed(struct tty_struct *tty, struct usb_serial_port *port) { struct ftdi_private *priv = usb_get_serial_port_data(port); - char *buf; __u16 urb_value; __u16 urb_index; __u32 urb_index_value; int rv; - buf = kmalloc(1, GFP_NOIO); - if (!buf) - return -ENOMEM; - urb_index_value = get_ftdi_divisor(tty, port); urb_value = (__u16)urb_index_value; urb_index = (__u16)(urb_index_value >> 16); @@ -1146,9 +1134,7 @@ static int change_speed(struct tty_struct *tty, struct usb_serial_port *port) FTDI_SIO_SET_BAUDRATE_REQUEST, FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, urb_value, urb_index, - buf, 0, WDR_SHORT_TIMEOUT); - - kfree(buf); + NULL, 0, WDR_SHORT_TIMEOUT); return rv; } @@ -1156,7 +1142,6 @@ static int write_latency_timer(struct usb_serial_port *port) { struct ftdi_private *priv = usb_get_serial_port_data(port); struct usb_device *udev = port->serial->dev; - char buf[1]; int rv = 0; int l = priv->latency; @@ -1170,8 +1155,7 @@ static int write_latency_timer(struct usb_serial_port *port) FTDI_SIO_SET_LATENCY_TIMER_REQUEST, FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, l, priv->interface, - buf, 0, WDR_TIMEOUT); - + NULL, 0, WDR_TIMEOUT); if (rv < 0) dev_err(&port->dev, "Unable to write latency timer: %i\n", rv); return rv; @@ -1445,7 +1429,6 @@ static ssize_t store_event_char(struct device *dev, struct usb_serial_port *port = to_usb_serial_port(dev); struct ftdi_private *priv = usb_get_serial_port_data(port); struct usb_device *udev = port->serial->dev; - char buf[1]; int v = simple_strtoul(valbuf, NULL, 10); int rv = 0; @@ -1456,8 +1439,7 @@ static ssize_t store_event_char(struct device *dev, FTDI_SIO_SET_EVENT_CHAR_REQUEST, FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE, v, priv->interface, - buf, 0, WDR_TIMEOUT); - + NULL, 0, WDR_TIMEOUT); if (rv < 0) { dbg("Unable to write event character: %i", rv); return -EIO; @@ -1636,7 +1618,6 @@ static int ftdi_NDI_device_setup(struct usb_serial *serial) struct usb_device *udev = serial->dev; int latency = ndi_latency_timer; int rv = 0; - char buf[1]; if (latency == 0) latency = 1; @@ -1649,7 +1630,7 @@ static int ftdi_NDI_device_setup(struct usb_serial *serial) rv = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), FTDI_SIO_SET_LATENCY_TIMER_REQUEST, FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, - latency, 0, buf, 0, WDR_TIMEOUT); + latency, 0, NULL, 0, WDR_TIMEOUT); return 0; } @@ -1737,9 +1718,7 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) struct usb_device *dev = port->serial->dev; struct ftdi_private *priv = usb_get_serial_port_data(port); unsigned long flags; - int result = 0; - char buf[1]; /* Needed for the usb_control_msg I think */ dbg("%s", __func__); @@ -1754,7 +1733,7 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) usb_control_msg(dev, usb_sndctrlpipe(dev, 0), FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, FTDI_SIO_RESET_SIO, - priv->interface, buf, 0, WDR_TIMEOUT); + priv->interface, NULL, 0, WDR_TIMEOUT); /* Termios defaults are set by usb_serial_init. We don't change port->tty->termios - this would lose speed settings, etc. @@ -1782,7 +1761,6 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) static void ftdi_dtr_rts(struct usb_serial_port *port, int on) { struct ftdi_private *priv = usb_get_serial_port_data(port); - char buf[1]; mutex_lock(&port->serial->disc_mutex); if (!port->serial->disconnected) { @@ -1791,7 +1769,7 @@ static void ftdi_dtr_rts(struct usb_serial_port *port, int on) usb_sndctrlpipe(port->serial->dev, 0), FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, - 0, priv->interface, buf, 0, + 0, priv->interface, NULL, 0, WDR_TIMEOUT) < 0) { dev_err(&port->dev, "error from flowcontrol urb\n"); } @@ -2160,7 +2138,6 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state) struct usb_serial_port *port = tty->driver_data; struct ftdi_private *priv = usb_get_serial_port_data(port); __u16 urb_value = 0; - char buf[1]; /* break_state = -1 to turn on break, and 0 to turn off break */ /* see drivers/char/tty_io.c to see it used */ @@ -2176,7 +2153,7 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state) FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, urb_value , priv->interface, - buf, 0, WDR_TIMEOUT) < 0) { + NULL, 0, WDR_TIMEOUT) < 0) { dev_err(&port->dev, "%s FAILED to enable/disable break state " "(state was %d)\n", __func__, break_state); } @@ -2200,7 +2177,6 @@ static void ftdi_set_termios(struct tty_struct *tty, struct ktermios *termios = tty->termios; unsigned int cflag = termios->c_cflag; __u16 urb_value; /* will hold the new flags */ - char buf[1]; /* Perhaps I should dynamically alloc this? */ /* Added for xon/xoff support */ unsigned int iflag = termios->c_iflag; @@ -2266,7 +2242,7 @@ static void ftdi_set_termios(struct tty_struct *tty, FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, urb_value , priv->interface, - buf, 0, WDR_SHORT_TIMEOUT) < 0) { + NULL, 0, WDR_SHORT_TIMEOUT) < 0) { dev_err(&port->dev, "%s FAILED to set " "databits/stopbits/parity\n", __func__); } @@ -2278,7 +2254,7 @@ static void ftdi_set_termios(struct tty_struct *tty, FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0, priv->interface, - buf, 0, WDR_TIMEOUT) < 0) { + NULL, 0, WDR_TIMEOUT) < 0) { dev_err(&port->dev, "%s error from disable flowcontrol urb\n", __func__); @@ -2304,7 +2280,7 @@ static void ftdi_set_termios(struct tty_struct *tty, FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0 , (FTDI_SIO_RTS_CTS_HS | priv->interface), - buf, 0, WDR_TIMEOUT) < 0) { + NULL, 0, WDR_TIMEOUT) < 0) { dev_err(&port->dev, "urb failed to set to rts/cts flow control\n"); } @@ -2336,7 +2312,7 @@ static void ftdi_set_termios(struct tty_struct *tty, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, urb_value , (FTDI_SIO_XON_XOFF_HS | priv->interface), - buf, 0, WDR_TIMEOUT) < 0) { + NULL, 0, WDR_TIMEOUT) < 0) { dev_err(&port->dev, "urb failed to set to " "xon/xoff flow control\n"); } @@ -2350,7 +2326,7 @@ static void ftdi_set_termios(struct tty_struct *tty, FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0, priv->interface, - buf, 0, WDR_TIMEOUT) < 0) { + NULL, 0, WDR_TIMEOUT) < 0) { dev_err(&port->dev, "urb failed to clear flow control\n"); } @@ -2364,10 +2340,15 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) { struct usb_serial_port *port = tty->driver_data; struct ftdi_private *priv = usb_get_serial_port_data(port); - unsigned char buf[2]; + unsigned char *buf; int ret; dbg("%s TIOCMGET", __func__); + + buf = kmalloc(2, GFP_KERNEL); + if (!buf) + return -ENOMEM; + switch (priv->chip_type) { case SIO: /* Request the status from the device */ @@ -2378,7 +2359,7 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) 0, 0, buf, 1, WDR_TIMEOUT); if (ret < 0) - return ret; + goto out; break; case FT8U232AM: case FT232BM: @@ -2396,17 +2377,21 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) 0, priv->interface, buf, 2, WDR_TIMEOUT); if (ret < 0) - return ret; + goto out; break; default: - return -EFAULT; + ret = -EFAULT; + goto out; } - return (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | + ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) | (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) | (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) | priv->last_dtr_rts; +out: + kfree(buf); + return ret; } static int ftdi_tiocmset(struct tty_struct *tty, struct file *file,