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>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
f06da264cf
commit
94f341db3d
@@ -2604,6 +2604,10 @@ static int __devinit qe_udc_probe(struct of_device *ofdev,
|
|||||||
(unsigned long)udc_controller);
|
(unsigned long)udc_controller);
|
||||||
/* request irq and disable DR */
|
/* request irq and disable DR */
|
||||||
udc_controller->usb_irq = irq_of_parse_and_map(np, 0);
|
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,
|
ret = request_irq(udc_controller->usb_irq, qe_udc_irq, 0,
|
||||||
driver_name, udc_controller);
|
driver_name, udc_controller);
|
||||||
@@ -2625,6 +2629,8 @@ static int __devinit qe_udc_probe(struct of_device *ofdev,
|
|||||||
err6:
|
err6:
|
||||||
free_irq(udc_controller->usb_irq, udc_controller);
|
free_irq(udc_controller->usb_irq, udc_controller);
|
||||||
err5:
|
err5:
|
||||||
|
irq_dispose_mapping(udc_controller->usb_irq);
|
||||||
|
err_noirq:
|
||||||
if (udc_controller->nullmap) {
|
if (udc_controller->nullmap) {
|
||||||
dma_unmap_single(udc_controller->gadget.dev.parent,
|
dma_unmap_single(udc_controller->gadget.dev.parent,
|
||||||
udc_controller->nullp, 256,
|
udc_controller->nullp, 256,
|
||||||
@@ -2648,7 +2654,7 @@ err2:
|
|||||||
iounmap(udc_controller->usb_regs);
|
iounmap(udc_controller->usb_regs);
|
||||||
err1:
|
err1:
|
||||||
kfree(udc_controller);
|
kfree(udc_controller);
|
||||||
|
udc_controller = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2710,6 +2716,7 @@ static int __devexit qe_udc_remove(struct of_device *ofdev)
|
|||||||
kfree(ep->txframe);
|
kfree(ep->txframe);
|
||||||
|
|
||||||
free_irq(udc_controller->usb_irq, udc_controller);
|
free_irq(udc_controller->usb_irq, udc_controller);
|
||||||
|
irq_dispose_mapping(udc_controller->usb_irq);
|
||||||
|
|
||||||
tasklet_kill(&udc_controller->rx_tasklet);
|
tasklet_kill(&udc_controller->rx_tasklet);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user