diff options
author | Johan Hovold <jhovold@gmail.com> | 2009-12-28 17:01:51 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-03-02 17:53:54 -0500 |
commit | ca65d256c8f1604f8ec8e258109d23280687186c (patch) | |
tree | bc3f73c7b003e6a09930d97fdf5ee0eb80d1c04b /drivers/usb | |
parent | e9305d2f4b5ffa9ea0261212d542956bede2a2ff (diff) |
USB: keyspan_pda: fix DMA buffers on stack
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/keyspan_pda.c | 45 |
1 files changed, 33 insertions, 12 deletions
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 1296a097f5c3..427d377c9d3e 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c | |||
@@ -429,13 +429,20 @@ static int keyspan_pda_get_modem_info(struct usb_serial *serial, | |||
429 | unsigned char *value) | 429 | unsigned char *value) |
430 | { | 430 | { |
431 | int rc; | 431 | int rc; |
432 | unsigned char data; | 432 | u8 *data; |
433 | |||
434 | data = kmalloc(1, GFP_KERNEL); | ||
435 | if (!data) | ||
436 | return -ENOMEM; | ||
437 | |||
433 | rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | 438 | rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), |
434 | 3, /* get pins */ | 439 | 3, /* get pins */ |
435 | USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_IN, | 440 | USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_IN, |
436 | 0, 0, &data, 1, 2000); | 441 | 0, 0, data, 1, 2000); |
437 | if (rc >= 0) | 442 | if (rc >= 0) |
438 | *value = data; | 443 | *value = *data; |
444 | |||
445 | kfree(data); | ||
439 | return rc; | 446 | return rc; |
440 | } | 447 | } |
441 | 448 | ||
@@ -543,7 +550,14 @@ static int keyspan_pda_write(struct tty_struct *tty, | |||
543 | device how much room it really has. This is done only on | 550 | device how much room it really has. This is done only on |
544 | scheduler time, since usb_control_msg() sleeps. */ | 551 | scheduler time, since usb_control_msg() sleeps. */ |
545 | if (count > priv->tx_room && !in_interrupt()) { | 552 | if (count > priv->tx_room && !in_interrupt()) { |
546 | unsigned char room; | 553 | u8 *room; |
554 | |||
555 | room = kmalloc(1, GFP_KERNEL); | ||
556 | if (!room) { | ||
557 | rc = -ENOMEM; | ||
558 | goto exit; | ||
559 | } | ||
560 | |||
547 | rc = usb_control_msg(serial->dev, | 561 | rc = usb_control_msg(serial->dev, |
548 | usb_rcvctrlpipe(serial->dev, 0), | 562 | usb_rcvctrlpipe(serial->dev, 0), |
549 | 6, /* write_room */ | 563 | 6, /* write_room */ |
@@ -551,9 +565,14 @@ static int keyspan_pda_write(struct tty_struct *tty, | |||
551 | | USB_DIR_IN, | 565 | | USB_DIR_IN, |
552 | 0, /* value: 0 means "remaining room" */ | 566 | 0, /* value: 0 means "remaining room" */ |
553 | 0, /* index */ | 567 | 0, /* index */ |
554 | &room, | 568 | room, |
555 | 1, | 569 | 1, |
556 | 2000); | 570 | 2000); |
571 | if (rc > 0) { | ||
572 | dbg(" roomquery says %d", *room); | ||
573 | priv->tx_room = *room; | ||
574 | } | ||
575 | kfree(room); | ||
557 | if (rc < 0) { | 576 | if (rc < 0) { |
558 | dbg(" roomquery failed"); | 577 | dbg(" roomquery failed"); |
559 | goto exit; | 578 | goto exit; |
@@ -563,8 +582,6 @@ static int keyspan_pda_write(struct tty_struct *tty, | |||
563 | rc = -EIO; /* device didn't return any data */ | 582 | rc = -EIO; /* device didn't return any data */ |
564 | goto exit; | 583 | goto exit; |
565 | } | 584 | } |
566 | dbg(" roomquery says %d", room); | ||
567 | priv->tx_room = room; | ||
568 | } | 585 | } |
569 | if (count > priv->tx_room) { | 586 | if (count > priv->tx_room) { |
570 | /* we're about to completely fill the Tx buffer, so | 587 | /* we're about to completely fill the Tx buffer, so |
@@ -684,18 +701,22 @@ static int keyspan_pda_open(struct tty_struct *tty, | |||
684 | struct usb_serial_port *port) | 701 | struct usb_serial_port *port) |
685 | { | 702 | { |
686 | struct usb_serial *serial = port->serial; | 703 | struct usb_serial *serial = port->serial; |
687 | unsigned char room; | 704 | u8 *room; |
688 | int rc = 0; | 705 | int rc = 0; |
689 | struct keyspan_pda_private *priv; | 706 | struct keyspan_pda_private *priv; |
690 | 707 | ||
691 | /* find out how much room is in the Tx ring */ | 708 | /* find out how much room is in the Tx ring */ |
709 | room = kmalloc(1, GFP_KERNEL); | ||
710 | if (!room) | ||
711 | return -ENOMEM; | ||
712 | |||
692 | rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | 713 | rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), |
693 | 6, /* write_room */ | 714 | 6, /* write_room */ |
694 | USB_TYPE_VENDOR | USB_RECIP_INTERFACE | 715 | USB_TYPE_VENDOR | USB_RECIP_INTERFACE |
695 | | USB_DIR_IN, | 716 | | USB_DIR_IN, |
696 | 0, /* value */ | 717 | 0, /* value */ |
697 | 0, /* index */ | 718 | 0, /* index */ |
698 | &room, | 719 | room, |
699 | 1, | 720 | 1, |
700 | 2000); | 721 | 2000); |
701 | if (rc < 0) { | 722 | if (rc < 0) { |
@@ -708,8 +729,8 @@ static int keyspan_pda_open(struct tty_struct *tty, | |||
708 | goto error; | 729 | goto error; |
709 | } | 730 | } |
710 | priv = usb_get_serial_port_data(port); | 731 | priv = usb_get_serial_port_data(port); |
711 | priv->tx_room = room; | 732 | priv->tx_room = *room; |
712 | priv->tx_throttled = room ? 0 : 1; | 733 | priv->tx_throttled = *room ? 0 : 1; |
713 | 734 | ||
714 | /*Start reading from the device*/ | 735 | /*Start reading from the device*/ |
715 | port->interrupt_in_urb->dev = serial->dev; | 736 | port->interrupt_in_urb->dev = serial->dev; |
@@ -718,8 +739,8 @@ static int keyspan_pda_open(struct tty_struct *tty, | |||
718 | dbg("%s - usb_submit_urb(read int) failed", __func__); | 739 | dbg("%s - usb_submit_urb(read int) failed", __func__); |
719 | goto error; | 740 | goto error; |
720 | } | 741 | } |
721 | |||
722 | error: | 742 | error: |
743 | kfree(room); | ||
723 | return rc; | 744 | return rc; |
724 | } | 745 | } |
725 | static void keyspan_pda_close(struct usb_serial_port *port) | 746 | static void keyspan_pda_close(struct usb_serial_port *port) |