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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html