Commit d71942e8 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[PATCH] USB: USB keyboard works after reboot (ehci-hcd)

This resolves a problem caused by "reboot" not actually
doing a clean shutdown of drivers.  It uses a reboot
notifier to make sure that typical BIOS code (using the
USB 1.1 companion controllers) will see keyboards even
without an EHCI driver being active.
parent d3704370
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/reboot.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/version.h> #include <linux/version.h>
...@@ -306,6 +306,19 @@ static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap) ...@@ -306,6 +306,19 @@ static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)
return 0; return 0;
} }
static int
ehci_reboot (struct notifier_block *self, unsigned long code, void *null)
{
struct ehci_hcd *ehci;
ehci = container_of (self, struct ehci_hcd, reboot_notifier);
/* make BIOS/etc use companion controller during reboot */
writel (0, &ehci->regs->configured_flag);
return 0;
}
/* called by khubd or root hub init threads */ /* called by khubd or root hub init threads */
static int ehci_start (struct usb_hcd *hcd) static int ehci_start (struct usb_hcd *hcd)
...@@ -464,6 +477,9 @@ static int ehci_start (struct usb_hcd *hcd) ...@@ -464,6 +477,9 @@ static int ehci_start (struct usb_hcd *hcd)
* are explicitly handed to companion controller(s), so no TT is * are explicitly handed to companion controller(s), so no TT is
* involved with the root hub. * involved with the root hub.
*/ */
ehci->reboot_notifier.notifier_call = ehci_reboot;
register_reboot_notifier (&ehci->reboot_notifier);
ehci->hcd.state = USB_STATE_READY; ehci->hcd.state = USB_STATE_READY;
writel (FLAG_CF, &ehci->regs->configured_flag); writel (FLAG_CF, &ehci->regs->configured_flag);
readl (&ehci->regs->command); /* unblock posted write */ readl (&ehci->regs->command); /* unblock posted write */
...@@ -520,6 +536,7 @@ static void ehci_stop (struct usb_hcd *hcd) ...@@ -520,6 +536,7 @@ static void ehci_stop (struct usb_hcd *hcd)
/* let companion controllers work when we aren't */ /* let companion controllers work when we aren't */
writel (0, &ehci->regs->configured_flag); writel (0, &ehci->regs->configured_flag);
unregister_reboot_notifier (&ehci->reboot_notifier);
remove_debug_files (ehci); remove_debug_files (ehci);
......
...@@ -81,8 +81,10 @@ struct ehci_hcd { /* one per controller */ ...@@ -81,8 +81,10 @@ struct ehci_hcd { /* one per controller */
struct pci_pool *sitd_pool; /* sitd per split iso urb */ struct pci_pool *sitd_pool; /* sitd per split iso urb */
struct timer_list watchdog; struct timer_list watchdog;
struct notifier_block reboot_notifier;
unsigned stamp; unsigned stamp;
/* irq statistics */
#ifdef EHCI_STATS #ifdef EHCI_STATS
struct ehci_stats stats; struct ehci_stats stats;
# define COUNT(x) do { (x)++; } while (0) # define COUNT(x) do { (x)++; } while (0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment