lkml.org 
[lkml]   [2012]   [Apr]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[ 33/68] USB: dont clear urb->dev in scatter-gather library
    3.2-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Alan Stern <stern@rowland.harvard.edu>

    commit bcf398537630bf20b4dbe59ba855b69f404c93cf upstream.

    This patch (as1517b) fixes an error in the USB scatter-gather library.
    The library code uses urb->dev to determine whether or nor an URB is
    currently active; the completion handler sets urb->dev to NULL.
    However the core unlinking routines need to use urb->dev. Since
    unlinking always racing with completion, the completion handler must
    not clear urb->dev -- it can lead to invalid memory accesses when a
    transfer has to be cancelled.

    This patch fixes the problem by getting rid of the lines that clear
    urb->dev after urb has been submitted. As a result we may end up
    trying to unlink an URB that failed in submission or that has already
    completed, so an extra check is added after each unlink to avoid
    printing an error message when this happens. The checks are updated
    in both sg_complete() and sg_cancel(), and the second is updated to
    match the first (currently it prints out unnecessary warning messages
    if a device is unplugged while a transfer is in progress).

    Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
    Reported-and-tested-by: Illia Zaitsev <I.Zaitsev@adbglobal.com>
    CC: Ming Lei <tom.leiming@gmail.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/usb/core/message.c | 11 ++++++-----
    1 file changed, 6 insertions(+), 5 deletions(-)

    --- a/drivers/usb/core/message.c
    +++ b/drivers/usb/core/message.c
    @@ -308,7 +308,8 @@ static void sg_complete(struct urb *urb)
    retval = usb_unlink_urb(io->urbs [i]);
    if (retval != -EINPROGRESS &&
    retval != -ENODEV &&
    - retval != -EBUSY)
    + retval != -EBUSY &&
    + retval != -EIDRM)
    dev_err(&io->dev->dev,
    "%s, unlink --> %d\n",
    __func__, retval);
    @@ -317,7 +318,6 @@ static void sg_complete(struct urb *urb)
    }
    spin_lock(&io->lock);
    }
    - urb->dev = NULL;

    /* on the last completion, signal usb_sg_wait() */
    io->bytes += urb->actual_length;
    @@ -524,7 +524,6 @@ void usb_sg_wait(struct usb_sg_request *
    case -ENXIO: /* hc didn't queue this one */
    case -EAGAIN:
    case -ENOMEM:
    - io->urbs[i]->dev = NULL;
    retval = 0;
    yield();
    break;
    @@ -542,7 +541,6 @@ void usb_sg_wait(struct usb_sg_request *

    /* fail any uncompleted urbs */
    default:
    - io->urbs[i]->dev = NULL;
    io->urbs[i]->status = retval;
    dev_dbg(&io->dev->dev, "%s, submit --> %d\n",
    __func__, retval);
    @@ -593,7 +591,10 @@ void usb_sg_cancel(struct usb_sg_request
    if (!io->urbs [i]->dev)
    continue;
    retval = usb_unlink_urb(io->urbs [i]);
    - if (retval != -EINPROGRESS && retval != -EBUSY)
    + if (retval != -EINPROGRESS
    + && retval != -ENODEV
    + && retval != -EBUSY
    + && retval != -EIDRM)
    dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
    __func__, retval);
    }



    \
     
     \ /
      Last update: 2012-04-19 23:19    [W:3.222 / U:0.036 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site