lkml.org 
[lkml]   [2015]   [Sep]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH] usb: gadget: amd5536udc: fix error handling in udc_pci_probe()
    Date
    If a failure happens early in udc_pci_probe(), error handling code
    just kfree(dev) and returns. The patch adds proper resource
    deallocations in udc_pci_probe() itself,
    since udc_pci_remove() is not suitabe to be called so early
    in initialization process.

    By the way, iounmap(dev->regs) is replaced by iounmap(dev->virt_addr)
    in udc_pci_remove() for clarity.

    Found by Linux Driver Verification project (linuxtesting.org).

    Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
    ---
    drivers/usb/gadget/udc/amd5536udc.c | 43 +++++++++++++++++--------------------
    1 file changed, 20 insertions(+), 23 deletions(-)

    diff --git a/drivers/usb/gadget/udc/amd5536udc.c b/drivers/usb/gadget/udc/amd5536udc.c
    index fdacddb18c00..175ca93fe5e2 100644
    --- a/drivers/usb/gadget/udc/amd5536udc.c
    +++ b/drivers/usb/gadget/udc/amd5536udc.c
    @@ -3138,8 +3138,8 @@ static void udc_pci_remove(struct pci_dev *pdev)
    writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
    if (dev->irq_registered)
    free_irq(pdev->irq, dev);
    - if (dev->regs)
    - iounmap(dev->regs);
    + if (dev->virt_addr)
    + iounmap(dev->virt_addr);
    if (dev->mem_region)
    release_mem_region(pci_resource_start(pdev, 0),
    pci_resource_len(pdev, 0));
    @@ -3226,17 +3226,13 @@ static int udc_pci_probe(

    /* init */
    dev = kzalloc(sizeof(struct udc), GFP_KERNEL);
    - if (!dev) {
    - retval = -ENOMEM;
    - goto finished;
    - }
    + if (!dev)
    + return -ENOMEM;

    /* pci setup */
    if (pci_enable_device(pdev) < 0) {
    - kfree(dev);
    - dev = NULL;
    retval = -ENODEV;
    - goto finished;
    + goto err_pcidev;
    }
    dev->active = 1;

    @@ -3246,28 +3242,22 @@ static int udc_pci_probe(

    if (!request_mem_region(resource, len, name)) {
    dev_dbg(&pdev->dev, "pci device used already\n");
    - kfree(dev);
    - dev = NULL;
    retval = -EBUSY;
    - goto finished;
    + goto err_memreg;
    }
    dev->mem_region = 1;

    dev->virt_addr = ioremap_nocache(resource, len);
    if (dev->virt_addr == NULL) {
    dev_dbg(&pdev->dev, "start address cannot be mapped\n");
    - kfree(dev);
    - dev = NULL;
    retval = -EFAULT;
    - goto finished;
    + goto err_ioremap;
    }

    if (!pdev->irq) {
    dev_err(&pdev->dev, "irq not set\n");
    - kfree(dev);
    - dev = NULL;
    retval = -ENODEV;
    - goto finished;
    + goto err_irq;
    }

    spin_lock_init(&dev->lock);
    @@ -3283,10 +3273,8 @@ static int udc_pci_probe(

    if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
    dev_dbg(&pdev->dev, "request_irq(%d) fail\n", pdev->irq);
    - kfree(dev);
    - dev = NULL;
    retval = -EBUSY;
    - goto finished;
    + goto err_irq;
    }
    dev->irq_registered = 1;

    @@ -3314,8 +3302,17 @@ static int udc_pci_probe(
    return 0;

    finished:
    - if (dev)
    - udc_pci_remove(pdev);
    + udc_pci_remove(pdev);
    + return retval;
    +
    +err_irq:
    + iounmap(dev->virt_addr);
    +err_ioremap:
    + release_mem_region(resource, len);
    +err_memreg:
    + pci_disable_device(pdev);
    +err_pcidev:
    + kfree(dev);
    return retval;
    }

    --
    1.9.1


    \
     
     \ /
      Last update: 2015-09-06 00:41    [W:5.061 / U:0.012 seconds]
    ©2003-2017 Jasper Spaans. hosted at Digital OceanAdvertise on this site