Re: USB Disconnects / resets after commit b963801164618e25fbdc0cd452ce49c3628b46c8

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

 



On 18 April 2011 20:51, Matej Kenda <matejken@xxxxxxxxx> wrote:
> On 18 April 2011 17:28, Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> wrote:
>>>
>>> A bug report 701011 in Launchpad contains additional description of
>>> the problem and kernel logs with traces created with
>>> options:
>>>
>>> CONFIG_USB_STORAGE_DEBUG=y
>>> CONFIG_USB=y
>>> CONFIG_USB_DEBUG=y
>>>
>>> https://bugs.launchpad.net/linux/+bug/701011
>>> https://launchpadlibrarian.net/62011653/hudson-slave-last-part.log
>>
>> Here's a patch for you to test. ÂIt isn't exactly a reversion of the
>> "USB: ehci-hcd unlink speedups" commit.
>
> Thank you. I'll try the patch.

It took me some time to set up the test environment with patched
kernel. There was some other work that I needed to complete. I had to
upgrade my LKM for custom piece of hardware to be able to run the
test.

I applied the patch to Linux kernel from Ubuntu Natty (2.6.38-10). I
needed to modify the patch slightly.

I will report how it works in a week or so.

Regards,

Matej
diff --git a/debian.master/changelog b/debian.master/changelog
index 7936595..9d4cb21 100644
--- a/debian.master/changelog
+++ b/debian.master/changelog
@@ -1,3 +1,10 @@
+linux (2.6.38-10.99) natty; urgency=low
+
+  * USB disconnect: Test patch from Alan Stern
+    - LP: #701011
+
+ -- Matej Kenda <matej.kenda@xxxxxxxxx>  Tue, 19 Apr 2011 13:16:59 +0200
+
 linux (2.6.38-9.43) natty-proposed; urgency=low
 
   [ Brad Figg ]
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 74dcf49..bbce753 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -90,7 +90,7 @@ static const char	hcd_name [] = "ehci_hcd";
 #define EHCI_IAA_MSECS		10		/* arbitrary */
 #define EHCI_IO_JIFFIES		(HZ/10)		/* io watchdog > irq_thresh */
 #define EHCI_ASYNC_JIFFIES	(HZ/20)		/* async idle timeout */
-#define EHCI_SHRINK_FRAMES	5		/* async qh unlink delay */
+#define EHCI_SHRINK_JIFFIES	(HZ/200 + 2)    /* async qh unlink delay */
 
 /* Initial IRQ latency:  faster than hw default */
 static int log2_irq_thresh = 0;		// 0 to 6
@@ -150,10 +150,7 @@ timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
 			break;
 		/* case TIMER_ASYNC_SHRINK: */
 		default:
-			/* add a jiffie since we synch against the
-			 * 8 KHz uframe counter.
-			 */
-			t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
+			t = EHCI_SHRINK_JIFFIES;
 			break;
 		}
 		mod_timer(&ehci->watchdog, t + jiffies);
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index baf7362..35e8957 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -1249,7 +1249,8 @@ static void scan_async (struct ehci_hcd *ehci)
 	struct ehci_qh		*qh;
 	enum ehci_timer_action	action = TIMER_IO_WATCHDOG;
 
-	ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
+	ehci->stamp++;
+	ehci->stamp += !ehci->stamp;
 	timer_action_done (ehci, TIMER_ASYNC_SHRINK);
 rescan:
 	stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state);
@@ -1272,6 +1273,7 @@ rescan:
 				temp = qh_completions (ehci, qh);
 				if (qh->needs_rescan)
 					unlink_async(ehci, qh);
+				qh->unlink_time = jiffies + EHCI_SHRINK_JIFFIES;
 				qh_put (qh);
 				if (temp != 0) {
 					goto rescan;
@@ -1286,9 +1288,8 @@ rescan:
 			 */
 			if (list_empty(&qh->qtd_list)
 					&& qh->qh_state == QH_STATE_LINKED) {
-				if (!ehci->reclaim && (stopped ||
-					((ehci->stamp - qh->stamp) & 0x1fff)
-						>= EHCI_SHRINK_FRAMES * 8))
+				if (!ehci->reclaim && (stopped || 
+					time_after_eq(jiffies, qh->unlink_time)))
 					start_unlink_async(ehci, qh);
 				else
 					action = TIMER_ASYNC_SHRINK;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 799ac16..8fd4cc9 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -336,6 +336,8 @@ struct ehci_qh {
 	struct ehci_qh		*reclaim;	/* next to reclaim */
 
 	struct ehci_hcd		*ehci;
+	unsigned long		unlink_time;
+	unsigned		stamp;
 
 	/*
 	 * Do NOT use atomic operations for QH refcounting. On some CPUs
@@ -344,7 +346,6 @@ struct ehci_qh {
 	 * Spinlocks are used to protect all QH fields.
 	 */
 	u32			refcount;
-	unsigned		stamp;
 
 	u8			needs_rescan;	/* Dequeue during giveback */
 	u8			qh_state;

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

  Powered by Linux