EHCI isoc free-list recycling

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

 



Dear Alan

I'm facing an issue on isoc sitd dma recycling. I'm using an omap3 (beableboard xM) board
and after a while I don't have anymore the possibity to allocate dma sitd from the pool 
(128Kb, 1M, 4M, it is a matter of time).
I'm playing flac music from usb disk and send on a dac connected to another usb port of the same 
controller.

Right now I'm experimenting this patch (not for any submission) and it seems that it masks/fixes
the problem.


diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index b476daf..183d4ec 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1166,7 +1166,8 @@ itd_urb_transaction (
 	gfp_t			mem_flags
 )
 {
-	struct ehci_itd		*itd;
+	struct ehci_itd		*itd = NULL;
+	bool			found;
 	dma_addr_t		itd_dma;
 	int			i;
 	unsigned		num_itds;
@@ -1187,18 +1188,24 @@ itd_urb_transaction (
 	/* allocate/init ITDs */
 	spin_lock_irqsave (&ehci->lock, flags);
 	for (i = 0; i < num_itds; i++) {
+		found = false;
 
 		/*
 		 * Use iTDs from the free list, but not iTDs that may
 		 * still be in use by the hardware.
 		 */
 		if (likely(!list_empty(&stream->free_list))) {
-			itd = list_first_entry(&stream->free_list,
-					struct ehci_itd, itd_list);
-			if (itd->frame == ehci->now_frame)
+			list_for_each_entry(itd, &stream->free_list,
+						itd_list) {
+				if (itd->frame != ehci->now_frame) {
+					list_del(&itd->itd_list);
+					itd_dma = itd->itd_dma;
+					found = true;
+					break;
+				}
+			}
+			if (found == false)
 				goto alloc_itd;
-			list_del (&itd->itd_list);
-			itd_dma = itd->itd_dma;
 		} else {
  alloc_itd:
 			spin_unlock_irqrestore (&ehci->lock, flags);
@@ -1868,7 +1875,8 @@ sitd_urb_transaction (
 	gfp_t			mem_flags
 )
 {
-	struct ehci_sitd	*sitd;
+	struct ehci_sitd	*sitd = NULL;
+	bool			found = false;
 	dma_addr_t		sitd_dma;
 	int			i;
 	struct ehci_iso_sched	*iso_sched;
@@ -1894,12 +1902,17 @@ sitd_urb_transaction (
 		 * still be in use by the hardware.
 		 */
 		if (likely(!list_empty(&stream->free_list))) {
-			sitd = list_first_entry(&stream->free_list,
-					 struct ehci_sitd, sitd_list);
-			if (sitd->frame == ehci->now_frame)
+			list_for_each_entry(sitd, &stream->free_list,
+						sitd_list) {
+				if (sitd->frame != ehci->now_frame) {
+					list_del(&sitd->sitd_list);
+					sitd_dma = sitd->sitd_dma;
+					found = true;
+					break;
+				}
+			}
+			if (found == false)
 				goto alloc_sitd;
-			list_del (&sitd->sitd_list);
-			sitd_dma = sitd->sitd_dma;
 		} else {
  alloc_sitd:
 			spin_unlock_irqrestore (&ehci->lock, flags);

What do you think?

Michael

--
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