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

Commit 64a21d02 authored by Aleksey Gorelov's avatar Aleksey Gorelov Committed by Greg Kroah-Hartman
Browse files

USB: Properly unregister reboot notifier in case of failure in ehci hcd



If some problem occurs during ehci startup, for instance, request_irq fails,
echi hcd driver tries it best to cleanup, but fails to unregister reboot
notifier, which in turn leads to crash on reboot/poweroff.

The following patch resolves this problem by not using reboot notifiers
anymore, but instead making ehci/ohci driver get its own shutdown method.  For
PCI, it is done through pci glue, for everything else through platform driver
glue.

One downside: sa1111 does not use platform driver stuff, and does not have its
own shutdown hook, so no 'shutdown' is called for it now.  I'm not sure if it
is really necessary on that platform, though.

Signed-off-by: default avatarAleks Gorelov <dared1st@yahoo.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent a94da897
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -413,4 +413,20 @@ EXPORT_SYMBOL (usb_hcd_pci_resume);

#endif	/* CONFIG_PM */

/**
 * usb_hcd_pci_shutdown - shutdown host controller
 * @dev: USB Host Controller being shutdown
 */
void usb_hcd_pci_shutdown (struct pci_dev *dev)
{
	struct usb_hcd		*hcd;

	hcd = pci_get_drvdata(dev);
	if (!hcd)
		return;

	if (hcd->driver->shutdown)
		hcd->driver->shutdown(hcd);
}
EXPORT_SYMBOL (usb_hcd_pci_shutdown);
+11 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include <linux/mutex.h>
#include <asm/irq.h>
#include <asm/byteorder.h>
#include <linux/platform_device.h>

#include <linux/usb.h>

@@ -1915,6 +1916,16 @@ void usb_remove_hcd(struct usb_hcd *hcd)
}
EXPORT_SYMBOL (usb_remove_hcd);

void
usb_hcd_platform_shutdown(struct platform_device* dev)
{
	struct usb_hcd *hcd = platform_get_drvdata(dev);

	if (hcd->driver->shutdown)
		hcd->driver->shutdown(hcd);
}
EXPORT_SYMBOL (usb_hcd_platform_shutdown);

/*-------------------------------------------------------------------------*/

#if defined(CONFIG_USB_MON)
+8 −0
Original line number Diff line number Diff line
@@ -192,6 +192,9 @@ struct hc_driver {
	/* cleanly make HCD stop writing memory and doing I/O */
	void	(*stop) (struct usb_hcd *hcd);

	/* shutdown HCD */
	void	(*shutdown) (struct usb_hcd *hcd);

	/* return current frame number */
	int	(*get_frame_number) (struct usb_hcd *hcd);

@@ -227,6 +230,9 @@ extern int usb_add_hcd(struct usb_hcd *hcd,
		unsigned int irqnum, unsigned long irqflags);
extern void usb_remove_hcd(struct usb_hcd *hcd);

struct platform_device;
extern void usb_hcd_platform_shutdown(struct platform_device* dev);

#ifdef CONFIG_PCI
struct pci_dev;
struct pci_device_id;
@@ -239,6 +245,8 @@ extern int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t state);
extern int usb_hcd_pci_resume (struct pci_dev *dev);
#endif /* CONFIG_PM */

extern void usb_hcd_pci_shutdown (struct pci_dev *dev);

#endif /* CONFIG_PCI */

/* pci-ish (pdev null is ok) buffer alloc/mapping support */
+2 −0
Original line number Diff line number Diff line
@@ -200,6 +200,7 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
	.reset = ehci_init,
	.start = ehci_run,
	.stop = ehci_stop,
	.shutdown = ehci_shutdown,

	/*
	 * managing i/o requests and associated device resources
@@ -268,6 +269,7 @@ MODULE_ALIAS("au1xxx-ehci");
static struct platform_driver ehci_hcd_au1xxx_driver = {
	.probe = ehci_hcd_au1xxx_drv_probe,
	.remove = ehci_hcd_au1xxx_drv_remove,
	.shutdown = usb_hcd_platform_shutdown,
	/*.suspend      = ehci_hcd_au1xxx_drv_suspend, */
	/*.resume       = ehci_hcd_au1xxx_drv_resume, */
	.driver = {
+2 −0
Original line number Diff line number Diff line
@@ -285,6 +285,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {
	.resume = ehci_bus_resume,
#endif
	.stop = ehci_stop,
	.shutdown = ehci_shutdown,

	/*
	 * managing i/o requests and associated device resources
@@ -329,6 +330,7 @@ MODULE_ALIAS("fsl-ehci");
static struct platform_driver ehci_fsl_driver = {
	.probe = ehci_fsl_drv_probe,
	.remove = ehci_fsl_drv_remove,
	.shutdown = usb_hcd_platform_shutdown,
	.driver = {
		   .name = "fsl-ehci",
		   },
Loading