summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Vorontsov <avorontsov@ru.mvista.com>2008-12-25 17:15:02 +0300
committerGreg Kroah-Hartman <gregkh@suse.de>2009-02-09 11:19:46 -0800
commit94f341db3dd080851f918da37e84659ef760da26 (patch)
tree1efb67713bbe6aa8f2dd48367e5166256a7f5523
parentf06da264cfb0f9444d41ca247213e419f90aa72a (diff)
USB: fsl_qe_udc: Fix oops on QE UDC probe failure
In case of probing errors the driver kfrees the udc_controller, but it doesn't set the pointer to NULL. When usb_gadget_register_driver is called, it checks for udc_controller != NULL, the check passes and the driver accesses nonexistent memory. Fix this by setting udc_controller to NULL in case of errors. While at it, also implement irq_of_parse_and_map()'s failure and cleanup cases. Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com> Acked-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/gadget/fsl_qe_udc.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index d6c5bcd4006..e8f7862acb3 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -2604,6 +2604,10 @@ static int __devinit qe_udc_probe(struct of_device *ofdev,
(unsigned long)udc_controller);
/* request irq and disable DR */
udc_controller->usb_irq = irq_of_parse_and_map(np, 0);
+ if (!udc_controller->usb_irq) {
+ ret = -EINVAL;
+ goto err_noirq;
+ }
ret = request_irq(udc_controller->usb_irq, qe_udc_irq, 0,
driver_name, udc_controller);
@@ -2625,6 +2629,8 @@ static int __devinit qe_udc_probe(struct of_device *ofdev,
err6:
free_irq(udc_controller->usb_irq, udc_controller);
err5:
+ irq_dispose_mapping(udc_controller->usb_irq);
+err_noirq:
if (udc_controller->nullmap) {
dma_unmap_single(udc_controller->gadget.dev.parent,
udc_controller->nullp, 256,
@@ -2648,7 +2654,7 @@ err2:
iounmap(udc_controller->usb_regs);
err1:
kfree(udc_controller);
-
+ udc_controller = NULL;
return ret;
}
@@ -2710,6 +2716,7 @@ static int __devexit qe_udc_remove(struct of_device *ofdev)
kfree(ep->txframe);
free_irq(udc_controller->usb_irq, udc_controller);
+ irq_dispose_mapping(udc_controller->usb_irq);
tasklet_kill(&udc_controller->rx_tasklet);