Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 94f341db authored by Anton Vorontsov's avatar Anton Vorontsov Committed by Greg Kroah-Hartman
Browse files

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: default avatarAnton Vorontsov <avorontsov@ru.mvista.com>
Acked-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent f06da264
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -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 @@ static int __devinit qe_udc_probe(struct of_device *ofdev,
	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);