[RFC PATCH 2/3] USB: kill urb->use_count atomic variable

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch kills atomic_inc/atomic_dec operations on
urb->use_count in URB submit/complete path.

The urb->use_count is only used for unlinking URB, and it isn't
necessary defined as atomic counter, so the variable is renamed
as urb->use_flag for this purpose, then reading/writing the
flag is still kept as atomic but ARCH's atomic operations(atomic_inc/
atomic_dec) are saved.

Cc: Oliver Neukum <oliver@xxxxxxxxxx>
Cc: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>
Signed-off-by: Ming Lei <ming.lei@xxxxxxxxxxxxx>
---
 drivers/usb/core/hcd.c |   14 +++++++++-----
 drivers/usb/core/urb.c |    8 ++++++--
 drivers/usb/core/usb.h |    5 +++++
 include/linux/usb.h    |    2 +-
 4 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 0b4d1ae..9457c4e 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1555,7 +1555,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
 	 * an error or calls giveback(), but not both.
 	 */
 	usb_get_urb(urb);
-	atomic_inc(&urb->use_count);
+	atomic_set(&urb->use_flag, URB_USING);
 	this_cpu_inc(*urb->dev->urbnum);
 	usbmon_urb_submit(&hcd->self, urb);
 
@@ -1582,7 +1582,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
 		usbmon_urb_submit_error(&hcd->self, urb, status);
 		urb->hcpriv = NULL;
 		INIT_LIST_HEAD(&urb->urb_list);
-		atomic_dec(&urb->use_count);
+		atomic_set(&urb->use_flag, URB_UNUSED);
 		this_cpu_dec(*urb->dev->urbnum);
 		if (atomic_read(&urb->reject))
 			wake_up(&usb_kill_urb_queue);
@@ -1628,11 +1628,11 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
 
 	/* Prevent the device and bus from going away while
 	 * the unlink is carried out.  If they are already gone
-	 * then urb->use_count must be 0, since disconnected
+	 * then urb->use_flag must be URB_UNUSED, since disconnected
 	 * devices can't have any active URBs.
 	 */
 	spin_lock_irqsave(&hcd_urb_unlink_lock, flags);
-	if (atomic_read(&urb->use_count) > 0) {
+	if (atomic_read(&urb->use_flag) != URB_UNUSED) {
 		retval = 0;
 		usb_get_dev(urb->dev);
 	}
@@ -1672,6 +1672,8 @@ static void __usb_hcd_giveback_urb(struct urb *urb)
 	/* pass ownership to the completion handler */
 	urb->status = status;
 
+	atomic_set(&urb->use_flag, URB_UNUSING);
+
 	/*
 	 * We disable local IRQs here avoid possible deadlock because
 	 * drivers may call spin_lock() to hold lock which might be
@@ -1686,7 +1688,9 @@ static void __usb_hcd_giveback_urb(struct urb *urb)
 	urb->complete(urb);
 	local_irq_restore(flags);
 
-	atomic_dec(&urb->use_count);
+	if (atomic_read(&urb->use_flag) == URB_UNUSING)
+		atomic_set(&urb->use_flag, URB_UNUSED);
+
 	if (unlikely(atomic_read(&urb->reject)))
 		wake_up(&usb_kill_urb_queue);
 	usb_put_urb(urb);
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index c12bc79..79d2534 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -9,6 +9,8 @@
 #include <linux/usb/hcd.h>
 #include <linux/scatterlist.h>
 
+#include "usb.h"
+
 #define to_urb(d) container_of(d, struct urb, kref)
 
 
@@ -661,7 +663,8 @@ void usb_kill_urb(struct urb *urb)
 	atomic_inc(&urb->reject);
 
 	usb_hcd_unlink_urb(urb, -ENOENT);
-	wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
+	wait_event(usb_kill_urb_queue,
+		   atomic_read(&urb->use_flag) == URB_UNUSED);
 
 	atomic_dec(&urb->reject);
 }
@@ -705,7 +708,8 @@ void usb_poison_urb(struct urb *urb)
 		return;
 
 	usb_hcd_unlink_urb(urb, -ENOENT);
-	wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
+	wait_event(usb_kill_urb_queue,
+		   atomic_read(&urb->use_flag) == URB_UNUSED);
 }
 EXPORT_SYMBOL_GPL(usb_poison_urb);
 
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 12a0181..bbdcf93 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -5,6 +5,11 @@
 struct usb_hub_descriptor;
 struct dev_state;
 
+/* urb use flag*/
+#define URB_UNUSED	0
+#define URB_USING	1
+#define URB_UNUSING	2
+
 /* Functions local to drivers/usb/core/ */
 
 extern int usb_create_sysfs_dev_files(struct usb_device *dev);
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 75332dc..7f5f629 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1408,7 +1408,7 @@ struct urb {
 	/* private: usb core and host controller only fields in the urb */
 	struct kref kref;		/* reference count of the URB */
 	void *hcpriv;			/* private data for host controller */
-	atomic_t use_count;		/* concurrent submissions counter */
+	atomic_t use_flag;		/* urb using flag */
 	atomic_t reject;		/* submissions will fail */
 	int unlinked;			/* unlink error code */
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux