# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.236   -> 1.237  
#	  drivers/usb/uhci.c	1.22    -> 1.23   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/03/22	johannes@erdfelt.com	1.237
# USB uhci driver update
# 
# (3 updates in one, greg k-h merged them)
# 
# ***
# [PATCH] uhci.c 2.4.19-pre3 kmem_cache_alloc flags
#   
# My previous patch which cleaned up some of the spinlocks, moved one of
# the spinlocks around a call to kmem_cache_alloc. It would sometimes
# erroneously call it with GFP_KERNEL.
# 
# This patch fixes the problem by always calling it with GFP_ATOMIC.
# Thanks to Greg for pointing this out to me.
# 
# ***
# [PATCH] uhci.c 2.4.19-pre3 erroneous completion callback
#   
# uhci.c would call the completion callback when the call to submit_urb
# failed. This is a rare situation.
#   
# This patch only calls the completion handler if the URB successfully
# completed immediately (as in the case of talking to the virtual root
# hub).
# 
# ***
# [PATCH] uhci.c 2.4.19-pre3 interrupt deadlock
#   
# Unfortunately, I left out one line from my spinlock cleanup patch
# recently.
#   
# As a result, using interrupt URB's could cause a deadlock on SMP
# kernels.
# --------------------------------------------
#
diff -Nru a/drivers/usb/uhci.c b/drivers/usb/uhci.c
--- a/drivers/usb/uhci.c	Fri Mar 22 15:48:27 2002
+++ b/drivers/usb/uhci.c	Fri Mar 22 15:48:27 2002
@@ -618,7 +618,7 @@
 {
 	struct urb_priv *urbp;
 
-	urbp = kmem_cache_alloc(uhci_up_cachep, in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL);
+	urbp = kmem_cache_alloc(uhci_up_cachep, SLAB_ATOMIC);
 	if (!urbp) {
 		err("uhci_alloc_urb_priv: couldn't allocate memory for urb_priv\n");
 		return NULL;
@@ -1585,7 +1585,9 @@
 	spin_unlock(&urb->lock);
 	spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
 
-	uhci_call_completion(urb);
+	/* Only call completion if it was successful */
+	if (!ret)
+		uhci_call_completion(urb);
 
 	return ret;
 }
@@ -1651,6 +1653,7 @@
 		/* Interrupts are an exception */
 		if (urb->interval) {
 			uhci_add_complete(urb);
+			spin_unlock_irqrestore(&urb->lock, flags);
 			return;		/* <-- note return */
 		}
 
