This patch fixes a timing hole and possible kdb deadlock in the event
 that KDB is entered while the USB HCD (Host Controller Driver) is busy
 processing URBs and holding the HCD lock. We now check for the
 lock being held out of the OHCI and EHCI poll functions and if so,
 return -EBUSY. In the event of an -EBUSY return, kdb will output
 a NOTICE message and the keyboard will not be used for input.

 It is anticpated that the timing hole is small and therefore *very*
 rarely happen. It remains a project for someone in the future if they
 want to attempt to fix this in another way (perhaps by using a independent
 KDB URB?)...
 
Patch shjould be applied on top of my previous ehci support patch.

Signed-off-by:  Aaron Young ([EMAIL PROTECTED])


Index: linux/arch/ia64/kdb/kdba_io.c
===================================================================
--- linux.orig/arch/ia64/kdb/kdba_io.c  2007-11-28 14:09:31.000000000 -0600
+++ linux/arch/ia64/kdb/kdba_io.c       2007-11-28 14:16:07.715948546 -0600
@@ -169,7 +169,14 @@
 
                /* Transfer char */
                ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb);
-               if (ret == -1) /* error or no characters, try the next kbd */
+
+               if (ret == -EBUSY && kdb_usb_kbds[i].poll_ret != -EBUSY)
+                       kdb_printf("NOTICE: USB HCD driver BUSY. "
+                           "USB keyboard has been disabled.\n");
+
+               kdb_usb_kbds[i].poll_ret = ret;
+
+               if (ret < 0) /* error or no characters, try the next kbd */
                        continue;
 
                spec = kdb_usb_kbds[i].buffer[0];
Index: linux/arch/x86/kdb/kdba_io_32.c
===================================================================
--- linux.orig/arch/x86/kdb/kdba_io_32.c        2007-11-28 14:09:31.000000000 
-0600
+++ linux/arch/x86/kdb/kdba_io_32.c     2007-11-28 14:16:43.512398556 -0600
@@ -159,7 +159,14 @@
 
                 /* Transfer char */
                 ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb);
-                if (ret == -1) /* error or no characters, try the next kbd */
+
+                if (ret == -EBUSY && kdb_usb_kbds[i].poll_ret != -EBUSY)
+                        kdb_printf("NOTICE: USB HCD driver BUSY. "
+                            "USB keyboard has been disabled.\n");
+
+                kdb_usb_kbds[i].poll_ret = ret;
+
+                if (ret < 0) /* error or no characters, try the next kbd */
                         continue;
 
                 spec = kdb_usb_kbds[i].buffer[0];
Index: linux/arch/x86/kdb/kdba_io_64.c
===================================================================
--- linux.orig/arch/x86/kdb/kdba_io_64.c        2007-11-28 14:09:31.000000000 
-0600
+++ linux/arch/x86/kdb/kdba_io_64.c     2007-11-28 14:16:52.521518496 -0600
@@ -159,7 +159,14 @@
 
                 /* Transfer char */
                 ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb);
-                if (ret == -1) /* error or no characters, try the next kbd */
+
+                if (ret == -EBUSY && kdb_usb_kbds[i].poll_ret != -EBUSY)
+                        kdb_printf("NOTICE: USB HCD driver BUSY. "
+                            "USB keyboard has been disabled.\n");
+
+                kdb_usb_kbds[i].poll_ret = ret;
+
+                if (ret < 0) /* error or no characters, try the next kbd */
                         continue;
 
                 spec = kdb_usb_kbds[i].buffer[0];
Index: linux/drivers/usb/host/ehci-hcd.c
===================================================================
--- linux.orig/drivers/usb/host/ehci-hcd.c      2007-11-28 14:09:31.000000000 
-0600
+++ linux/drivers/usb/host/ehci-hcd.c   2007-11-28 14:17:07.455374932 -0600
@@ -948,6 +948,20 @@
         if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
                 return -1;
 
+       /*
+        * If ehci->lock is held coming into this routine, it could
+        * mean KDB was entered while the HC driver was in the midst
+        * of processing URBs. Therefore it could be dangerous to
+        * processes URBs from this poll routine. And, we can't wait on
+        * the lock since we are in KDB and kernel threads (including the
+        * one holding the lock) are suspended.
+        * So, we punt and return an error. Keyboards attached to this
+        * HC will not be useable from KDB at this time.
+        */
+       if (spin_is_locked(&ehci->lock))
+               return -EBUSY;
+
+       /* processes the URB */
         if (qh_completions_kdb(ehci, urb->hcpriv, urb))
                 return 0;
 
Index: linux/drivers/usb/host/ohci-hcd.c
===================================================================
--- linux.orig/drivers/usb/host/ohci-hcd.c      2007-11-28 14:09:31.000000000 
-0600
+++ linux/drivers/usb/host/ohci-hcd.c   2007-11-28 14:17:21.049064751 -0600
@@ -984,6 +984,19 @@
         if (!HC_IS_RUNNING (ohci_to_hcd(ohci)->state))
                 return -1;
 
+       /*
+        * If ohci->lock is held coming into this routine, it could
+        * mean KDB was entered while the HC driver was in the midst
+        * of processing URBs. Therefore it could be dangerous to
+        * processes URBs from this poll routine. And, we can't wait on
+        * the lock since we are in KDB and kernel threads (including the
+        * one holding the lock) are suspended.
+        * So, we punt and return an error. Keyboards attached to this
+        * HC will not be useable from KDB at this time.
+        */
+       if (spin_is_locked(&ohci->lock))
+               return -EBUSY;
+
        regs = ohci->regs;
 
        /* if the urb is not currently in progress resubmit it */
Index: linux/include/linux/kdbprivate.h
===================================================================
--- linux.orig/include/linux/kdbprivate.h       2007-11-28 14:09:28.000000000 
-0600
+++ linux/include/linux/kdbprivate.h    2007-11-28 14:17:29.446108569 -0600
@@ -489,6 +489,7 @@
        struct urb *urb;                /* pointer to the URB */
        unsigned char *buffer;          /* pointer to the kbd char buffer */
        int (*poll_func)(struct urb *urb); /* poll function to retrieve chars */
+       int     poll_ret;       /* return val from poll_func */
        int     caps_lock;      /* state of the caps lock for this keyboard */
 };
 #endif /* CONFIG_KDB_USB */
---------------------------
Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe.

Reply via email to