# 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.220   -> 1.220.2.1
#	 include/linux/usb.h	1.17    -> 1.18   
#	   drivers/usb/usb.c	1.27    -> 1.28   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/02/06	greg@soap.kroah.net	1.221
# patch from Wolfgang Mües <wmues@nexgo.de> for the usb auerswald.c driver:
#   	- Code-Review from Oliver Neukum: remove SMP races.
#   	- Added some wake_up calls after auerbuf_releasebuf to wake up tasks waiting
#   	  for cp buffers.
#   	- Change the module count handling to automatic (owner: THIS_MODULE).
# --------------------------------------------
# 02/02/06	greg@soap.kroah.net	1.220.1.1
# patch from dimitry for the usb ibmcam driver that does:
#   	- Updates the documentation
#   	- Adds Veo Stingray support
#   	- Fixes hotplug table dependency upon now-defunct symbol
#   	- deletes drivers/usb/ibmcam.h
# --------------------------------------------
# 02/02/06	greg@soap.kroah.net	1.220.2.1
# usb core:
# 	- initial add of the "int mem_flags" call to the usb_submit_urb() call
# --------------------------------------------
#
diff -Nru a/drivers/usb/usb.c b/drivers/usb/usb.c
--- a/drivers/usb/usb.c	Wed Feb  6 20:47:48 2002
+++ b/drivers/usb/usb.c	Wed Feb  6 20:47:48 2002
@@ -1148,6 +1148,7 @@
 /**
  * usb_submit_urb - asynchronously issue a transfer request for an endpoint
  * @urb: pointer to the urb describing the request
+ * @mem_flags: the type of memory to allocate, see kmalloc() for a list of valid options for this.
  *
  * This submits a transfer request, and transfers control of the URB
  * describing that request to the USB subsystem.  Request completion will
@@ -1197,12 +1198,49 @@
  *
  * If the USB subsystem can't reserve sufficient bandwidth to perform
  * the periodic request, and bandwidth reservation is being done for
- * this controller, submitting such a periodic request will fail. 
+ * this controller, submitting such a periodic request will fail.
+ *
+ * Memory Flags:
+ *
+ * General rules for how to decide which mem_flags to use:
+ * 
+ * Basically the rules are the same as for kmalloc.  There are four
+ * different possible values; GFP_KERNEL, GFP_NOFS, GFP_NOIO and
+ * GFP_ATOMIC.
+ *
+ * GFP_NOFS is not ever used, as it has not been implemented yet.
+ *
+ * There are three situations you must use GFP_ATOMIC.
+ *    a) you are inside a completion handler, an interrupt, bottom half,
+ *       tasklet or timer.
+ *    b) you are holding a spinlock or rwlock (does not apply to
+ *       semaphores)
+ *    c) current->state != TASK_RUNNING, this is the case only after
+ *       you've changed it.
+ * 
+ * GFP_NOIO is used in the block io path and error handling of storage
+ * devices.
+ *
+ * All other situations use GFP_KERNEL.
+ *
+ * Specfic rules for how to decide which mem_flags to use:
+ *
+ *    - start_xmit, timeout, and receive methods of network drivers must
+ *      use GFP_ATOMIC (spinlock)
+ *    - queuecommand methods of scsi drivers must use GFP_ATOMIC (spinlock)
+ *    - If you use a kernel thread with a network driver you must use
+ *      GFP_NOIO, unless b) or c) apply
+ *    - After you have done a down() you use GFP_KERNEL, unless b) or c)
+ *      apply or your are in a storage driver's block io path
+ *    - probe and disconnect use GFP_KERNEL unless b) or c) apply
+ *    - Changing firmware on a running storage or net device uses
+ *      GFP_NOIO, unless b) or c) apply
+ *
  */
-int usb_submit_urb(struct urb *urb)
+int usb_submit_urb(struct urb *urb, int mem_flags)
 {
 	if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
-		return urb->dev->bus->op->submit_urb(urb);
+		return urb->dev->bus->op->submit_urb(urb, mem_flags);
 	else
 		return -ENODEV;
 }
@@ -1272,7 +1310,7 @@
 	add_wait_queue(&awd.wqh, &wait);
 
 	urb->context = &awd;
-	status = usb_submit_urb(urb);
+	status = usb_submit_urb(urb, GFP_KERNEL);
 	if (status) {
 		// something went wrong
 		usb_free_urb(urb);
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h	Wed Feb  6 20:47:48 2002
+++ b/include/linux/usb.h	Wed Feb  6 20:47:48 2002
@@ -857,7 +857,7 @@
 extern void usb_free_urb(struct urb *urb);
 #define usb_put_urb usb_free_urb
 extern struct urb *usb_get_urb(struct urb *urb);
-extern int usb_submit_urb(struct urb *urb);
+extern int usb_submit_urb(struct urb *urb, int mem_flags);
 extern int usb_unlink_urb(struct urb *urb);
 
 /*-------------------------------------------------------------------*
@@ -906,7 +906,7 @@
 	int (*allocate)(struct usb_device *);
 	int (*deallocate)(struct usb_device *);
 	int (*get_frame_number) (struct usb_device *usb_dev);
-	int (*submit_urb) (struct urb *urb);
+	int (*submit_urb) (struct urb *urb, int mem_flags);
 	int (*unlink_urb) (struct urb *urb);
 };
 
