diff options
author | Anton Vorontsov <avorontsov@ru.mvista.com> | 2008-12-25 09:15:02 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-02-09 14:19:46 -0500 |
commit | 94f341db3dd080851f918da37e84659ef760da26 (patch) | |
tree | 1efb67713bbe6aa8f2dd48367e5166256a7f5523 /drivers | |
parent | f06da264cfb0f9444d41ca247213e419f90aa72a (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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/gadget/fsl_qe_udc.c | 9 |
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 d6c5bcd40064..e8f7862acb3d 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, | |||
2604 | (unsigned long)udc_controller); | 2604 | (unsigned long)udc_controller); |
2605 | /* request irq and disable DR */ | 2605 | /* request irq and disable DR */ |
2606 | udc_controller->usb_irq = irq_of_parse_and_map(np, 0); | 2606 | udc_controller->usb_irq = irq_of_parse_and_map(np, 0); |
2607 | if (!udc_controller->usb_irq) { | ||
2608 | ret = -EINVAL; | ||
2609 | goto err_noirq; | ||
2610 | } | ||
2607 | 2611 | ||
2608 | ret = request_irq(udc_controller->usb_irq, qe_udc_irq, 0, | 2612 | ret = request_irq(udc_controller->usb_irq, qe_udc_irq, 0, |
2609 | driver_name, udc_controller); | 2613 | driver_name, udc_controller); |
@@ -2625,6 +2629,8 @@ static int __devinit qe_udc_probe(struct of_device *ofdev, | |||
2625 | err6: | 2629 | err6: |
2626 | free_irq(udc_controller->usb_irq, udc_controller); | 2630 | free_irq(udc_controller->usb_irq, udc_controller); |
2627 | err5: | 2631 | err5: |
2632 | irq_dispose_mapping(udc_controller->usb_irq); | ||
2633 | err_noirq: | ||
2628 | if (udc_controller->nullmap) { | 2634 | if (udc_controller->nullmap) { |
2629 | dma_unmap_single(udc_controller->gadget.dev.parent, | 2635 | dma_unmap_single(udc_controller->gadget.dev.parent, |
2630 | udc_controller->nullp, 256, | 2636 | udc_controller->nullp, 256, |
@@ -2648,7 +2654,7 @@ err2: | |||
2648 | iounmap(udc_controller->usb_regs); | 2654 | iounmap(udc_controller->usb_regs); |
2649 | err1: | 2655 | err1: |
2650 | kfree(udc_controller); | 2656 | kfree(udc_controller); |
2651 | 2657 | udc_controller = NULL; | |
2652 | return ret; | 2658 | return ret; |
2653 | } | 2659 | } |
2654 | 2660 | ||
@@ -2710,6 +2716,7 @@ static int __devexit qe_udc_remove(struct of_device *ofdev) | |||
2710 | kfree(ep->txframe); | 2716 | kfree(ep->txframe); |
2711 | 2717 | ||
2712 | free_irq(udc_controller->usb_irq, udc_controller); | 2718 | free_irq(udc_controller->usb_irq, udc_controller); |
2719 | irq_dispose_mapping(udc_controller->usb_irq); | ||
2713 | 2720 | ||
2714 | tasklet_kill(&udc_controller->rx_tasklet); | 2721 | tasklet_kill(&udc_controller->rx_tasklet); |
2715 | 2722 | ||