diff options
author | Johan Hovold <jhovold@gmail.com> | 2009-12-28 17:01:52 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-03-02 17:53:55 -0500 |
commit | abf492e7b3ae74873688cf9960283853a3054471 (patch) | |
tree | 9728dc754895006a14ac4c41ecda50892cd3eca6 /drivers/usb/serial/kl5kusb105.c | |
parent | ca65d256c8f1604f8ec8e258109d23280687186c (diff) |
USB: kl5kusb105: fix DMA buffers on stack
Cc: Oliver Neukum <oliver@neukum.name>
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/kl5kusb105.c')
-rw-r--r-- | drivers/usb/serial/kl5kusb105.c | 63 |
1 files changed, 45 insertions, 18 deletions
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 3a7873806f46..731964b5ded6 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c | |||
@@ -212,10 +212,19 @@ static int klsi_105_get_line_state(struct usb_serial_port *port, | |||
212 | unsigned long *line_state_p) | 212 | unsigned long *line_state_p) |
213 | { | 213 | { |
214 | int rc; | 214 | int rc; |
215 | __u8 status_buf[KLSI_STATUSBUF_LEN] = { -1, -1}; | 215 | u8 *status_buf; |
216 | __u16 status; | 216 | __u16 status; |
217 | 217 | ||
218 | dev_info(&port->serial->dev->dev, "sending SIO Poll request\n"); | 218 | dev_info(&port->serial->dev->dev, "sending SIO Poll request\n"); |
219 | |||
220 | status_buf = kmalloc(KLSI_STATUSBUF_LEN, GFP_KERNEL); | ||
221 | if (!status_buf) { | ||
222 | dev_err(&port->dev, "%s - out of memory for status buffer.\n", | ||
223 | __func__); | ||
224 | return -ENOMEM; | ||
225 | } | ||
226 | status_buf[0] = 0xff; | ||
227 | status_buf[1] = 0xff; | ||
219 | rc = usb_control_msg(port->serial->dev, | 228 | rc = usb_control_msg(port->serial->dev, |
220 | usb_rcvctrlpipe(port->serial->dev, 0), | 229 | usb_rcvctrlpipe(port->serial->dev, 0), |
221 | KL5KUSB105A_SIO_POLL, | 230 | KL5KUSB105A_SIO_POLL, |
@@ -236,6 +245,8 @@ static int klsi_105_get_line_state(struct usb_serial_port *port, | |||
236 | 245 | ||
237 | *line_state_p = klsi_105_status2linestate(status); | 246 | *line_state_p = klsi_105_status2linestate(status); |
238 | } | 247 | } |
248 | |||
249 | kfree(status_buf); | ||
239 | return rc; | 250 | return rc; |
240 | } | 251 | } |
241 | 252 | ||
@@ -364,7 +375,7 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
364 | int rc; | 375 | int rc; |
365 | int i; | 376 | int i; |
366 | unsigned long line_state; | 377 | unsigned long line_state; |
367 | struct klsi_105_port_settings cfg; | 378 | struct klsi_105_port_settings *cfg; |
368 | unsigned long flags; | 379 | unsigned long flags; |
369 | 380 | ||
370 | dbg("%s port %d", __func__, port->number); | 381 | dbg("%s port %d", __func__, port->number); |
@@ -376,12 +387,18 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
376 | * Then read the modem line control and store values in | 387 | * Then read the modem line control and store values in |
377 | * priv->line_state. | 388 | * priv->line_state. |
378 | */ | 389 | */ |
379 | cfg.pktlen = 5; | 390 | cfg = kmalloc(sizeof(*cfg), GFP_KERNEL); |
380 | cfg.baudrate = kl5kusb105a_sio_b9600; | 391 | if (!cfg) { |
381 | cfg.databits = kl5kusb105a_dtb_8; | 392 | dev_err(&port->dev, "%s - out of memory for config buffer.\n", |
382 | cfg.unknown1 = 0; | 393 | __func__); |
383 | cfg.unknown2 = 1; | 394 | return -ENOMEM; |
384 | klsi_105_chg_port_settings(port, &cfg); | 395 | } |
396 | cfg->pktlen = 5; | ||
397 | cfg->baudrate = kl5kusb105a_sio_b9600; | ||
398 | cfg->databits = kl5kusb105a_dtb_8; | ||
399 | cfg->unknown1 = 0; | ||
400 | cfg->unknown2 = 1; | ||
401 | klsi_105_chg_port_settings(port, cfg); | ||
385 | 402 | ||
386 | /* set up termios structure */ | 403 | /* set up termios structure */ |
387 | spin_lock_irqsave(&priv->lock, flags); | 404 | spin_lock_irqsave(&priv->lock, flags); |
@@ -391,11 +408,11 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
391 | priv->termios.c_lflag = tty->termios->c_lflag; | 408 | priv->termios.c_lflag = tty->termios->c_lflag; |
392 | for (i = 0; i < NCCS; i++) | 409 | for (i = 0; i < NCCS; i++) |
393 | priv->termios.c_cc[i] = tty->termios->c_cc[i]; | 410 | priv->termios.c_cc[i] = tty->termios->c_cc[i]; |
394 | priv->cfg.pktlen = cfg.pktlen; | 411 | priv->cfg.pktlen = cfg->pktlen; |
395 | priv->cfg.baudrate = cfg.baudrate; | 412 | priv->cfg.baudrate = cfg->baudrate; |
396 | priv->cfg.databits = cfg.databits; | 413 | priv->cfg.databits = cfg->databits; |
397 | priv->cfg.unknown1 = cfg.unknown1; | 414 | priv->cfg.unknown1 = cfg->unknown1; |
398 | priv->cfg.unknown2 = cfg.unknown2; | 415 | priv->cfg.unknown2 = cfg->unknown2; |
399 | spin_unlock_irqrestore(&priv->lock, flags); | 416 | spin_unlock_irqrestore(&priv->lock, flags); |
400 | 417 | ||
401 | /* READ_ON and urb submission */ | 418 | /* READ_ON and urb submission */ |
@@ -441,6 +458,7 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
441 | retval = rc; | 458 | retval = rc; |
442 | 459 | ||
443 | exit: | 460 | exit: |
461 | kfree(cfg); | ||
444 | return retval; | 462 | return retval; |
445 | } /* klsi_105_open */ | 463 | } /* klsi_105_open */ |
446 | 464 | ||
@@ -714,10 +732,17 @@ static void klsi_105_set_termios(struct tty_struct *tty, | |||
714 | unsigned int old_iflag = old_termios->c_iflag; | 732 | unsigned int old_iflag = old_termios->c_iflag; |
715 | unsigned int cflag = tty->termios->c_cflag; | 733 | unsigned int cflag = tty->termios->c_cflag; |
716 | unsigned int old_cflag = old_termios->c_cflag; | 734 | unsigned int old_cflag = old_termios->c_cflag; |
717 | struct klsi_105_port_settings cfg; | 735 | struct klsi_105_port_settings *cfg; |
718 | unsigned long flags; | 736 | unsigned long flags; |
719 | speed_t baud; | 737 | speed_t baud; |
720 | 738 | ||
739 | cfg = kmalloc(sizeof(*cfg), GFP_KERNEL); | ||
740 | if (!cfg) { | ||
741 | dev_err(&port->dev, "%s - out of memory for config buffer.\n", | ||
742 | __func__); | ||
743 | return; | ||
744 | } | ||
745 | |||
721 | /* lock while we are modifying the settings */ | 746 | /* lock while we are modifying the settings */ |
722 | spin_lock_irqsave(&priv->lock, flags); | 747 | spin_lock_irqsave(&priv->lock, flags); |
723 | 748 | ||
@@ -793,11 +818,11 @@ static void klsi_105_set_termios(struct tty_struct *tty, | |||
793 | case CS5: | 818 | case CS5: |
794 | dbg("%s - 5 bits/byte not supported", __func__); | 819 | dbg("%s - 5 bits/byte not supported", __func__); |
795 | spin_unlock_irqrestore(&priv->lock, flags); | 820 | spin_unlock_irqrestore(&priv->lock, flags); |
796 | return ; | 821 | goto err; |
797 | case CS6: | 822 | case CS6: |
798 | dbg("%s - 6 bits/byte not supported", __func__); | 823 | dbg("%s - 6 bits/byte not supported", __func__); |
799 | spin_unlock_irqrestore(&priv->lock, flags); | 824 | spin_unlock_irqrestore(&priv->lock, flags); |
800 | return ; | 825 | goto err; |
801 | case CS7: | 826 | case CS7: |
802 | priv->cfg.databits = kl5kusb105a_dtb_7; | 827 | priv->cfg.databits = kl5kusb105a_dtb_7; |
803 | break; | 828 | break; |
@@ -856,11 +881,13 @@ static void klsi_105_set_termios(struct tty_struct *tty, | |||
856 | #endif | 881 | #endif |
857 | ; | 882 | ; |
858 | } | 883 | } |
859 | memcpy(&cfg, &priv->cfg, sizeof(cfg)); | 884 | memcpy(cfg, &priv->cfg, sizeof(*cfg)); |
860 | spin_unlock_irqrestore(&priv->lock, flags); | 885 | spin_unlock_irqrestore(&priv->lock, flags); |
861 | 886 | ||
862 | /* now commit changes to device */ | 887 | /* now commit changes to device */ |
863 | klsi_105_chg_port_settings(port, &cfg); | 888 | klsi_105_chg_port_settings(port, cfg); |
889 | err: | ||
890 | kfree(cfg); | ||
864 | } /* klsi_105_set_termios */ | 891 | } /* klsi_105_set_termios */ |
865 | 892 | ||
866 | 893 | ||