lkml.org 
[lkml]   [2018]   [Sep]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.18 031/235] Input: pxrc - fix freeing URB on device teardown
    Date
    4.18-stable review patch.  If anyone has any objections, please let me know.

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

    From: Dmitry Torokhov <dmitry.torokhov@gmail.com>

    [ Upstream commit 34dad2cf1104869ce2db2bddb34f8e6780c2ddaa ]

    URB is the only resource that is not managed, and thus is destroyed too early,
    before we unregister input device and stop URB in pxrc_close(). To fix it let's
    install custom devm handler to free the URB at the right time in devm unwind
    sequence.

    Reviewed-by: Marcus Folkesson <marcus.folkesson@gmail.com>
    Tested-by: Marcus Folkesson <marcus.folkesson@gmail.com>
    Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
    Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/input/joystick/pxrc.c | 68 +++++++++++++++++++-----------------------
    1 file changed, 31 insertions(+), 37 deletions(-)

    --- a/drivers/input/joystick/pxrc.c
    +++ b/drivers/input/joystick/pxrc.c
    @@ -120,48 +120,51 @@ static void pxrc_close(struct input_dev
    mutex_unlock(&pxrc->pm_mutex);
    }

    +static void pxrc_free_urb(void *_pxrc)
    +{
    + struct pxrc *pxrc = _pxrc;
    +
    + usb_free_urb(pxrc->urb);
    +}
    +
    static int pxrc_usb_init(struct pxrc *pxrc)
    {
    struct usb_endpoint_descriptor *epirq;
    unsigned int pipe;
    - int retval;
    + int error;

    /* Set up the endpoint information */
    /* This device only has an interrupt endpoint */
    - retval = usb_find_common_endpoints(pxrc->intf->cur_altsetting,
    - NULL, NULL, &epirq, NULL);
    - if (retval) {
    - dev_err(&pxrc->intf->dev,
    - "Could not find endpoint\n");
    - goto error;
    + error = usb_find_common_endpoints(pxrc->intf->cur_altsetting,
    + NULL, NULL, &epirq, NULL);
    + if (error) {
    + dev_err(&pxrc->intf->dev, "Could not find endpoint\n");
    + return error;
    }

    pxrc->bsize = usb_endpoint_maxp(epirq);
    pxrc->epaddr = epirq->bEndpointAddress;
    pxrc->data = devm_kmalloc(&pxrc->intf->dev, pxrc->bsize, GFP_KERNEL);
    - if (!pxrc->data) {
    - retval = -ENOMEM;
    - goto error;
    - }
    + if (!pxrc->data)
    + return -ENOMEM;

    usb_set_intfdata(pxrc->intf, pxrc);
    usb_make_path(pxrc->udev, pxrc->phys, sizeof(pxrc->phys));
    strlcat(pxrc->phys, "/input0", sizeof(pxrc->phys));

    pxrc->urb = usb_alloc_urb(0, GFP_KERNEL);
    - if (!pxrc->urb) {
    - retval = -ENOMEM;
    - goto error;
    - }
    + if (!pxrc->urb)
    + return -ENOMEM;
    +
    + error = devm_add_action_or_reset(&pxrc->intf->dev, pxrc_free_urb, pxrc);
    + if (error)
    + return error;

    pipe = usb_rcvintpipe(pxrc->udev, pxrc->epaddr),
    usb_fill_int_urb(pxrc->urb, pxrc->udev, pipe, pxrc->data, pxrc->bsize,
    pxrc_usb_irq, pxrc, 1);

    -error:
    - return retval;
    -
    -
    + return 0;
    }

    static int pxrc_input_init(struct pxrc *pxrc)
    @@ -197,7 +200,7 @@ static int pxrc_probe(struct usb_interfa
    const struct usb_device_id *id)
    {
    struct pxrc *pxrc;
    - int retval;
    + int error;

    pxrc = devm_kzalloc(&intf->dev, sizeof(*pxrc), GFP_KERNEL);
    if (!pxrc)
    @@ -207,29 +210,20 @@ static int pxrc_probe(struct usb_interfa
    pxrc->udev = usb_get_dev(interface_to_usbdev(intf));
    pxrc->intf = intf;

    - retval = pxrc_usb_init(pxrc);
    - if (retval)
    - goto error;
    -
    - retval = pxrc_input_init(pxrc);
    - if (retval)
    - goto err_free_urb;
    + error = pxrc_usb_init(pxrc);
    + if (error)
    + return error;
    +
    + error = pxrc_input_init(pxrc);
    + if (error)
    + return error;

    return 0;
    -
    -err_free_urb:
    - usb_free_urb(pxrc->urb);
    -
    -error:
    - return retval;
    }

    static void pxrc_disconnect(struct usb_interface *intf)
    {
    - struct pxrc *pxrc = usb_get_intfdata(intf);
    -
    - usb_free_urb(pxrc->urb);
    - usb_set_intfdata(intf, NULL);
    + /* All driver resources are devm-managed. */
    }

    static int pxrc_suspend(struct usb_interface *intf, pm_message_t message)

    \
     
     \ /
      Last update: 2018-09-24 14:52    [W:4.078 / U:0.244 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site