Hello,
We have a issue on uframe reservation order on ehci-sched.
The problem appears on a usb sound card pluged on a usb hub, when you
try to launch a arecord whereas a aplay is runnning.
The error "cannot submit datapipe for urb 0, error -28: not enough
bandwidth" occurs, and no recording is possible.
If you start recording before reading, both will work without problem.
The same comportment is present on OMAP with kernel 2.6.35 or on a
computer with 3.0.0-1 kernel.
Our hardware condition :
Informations from /proc/bus/usb/devices about the hub and Hercules usb
sound card used :
T: Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=480 MxCh= 3
B: Alloc= 0/800 us ( 0%), #Int= 2, #Iso= 0
D: Ver= 2.00 Cls=09(hub ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
P: Vendor=1d6b ProdID=0002 Rev= 2.06
S: Manufacturer=Linux 2.6.35.13-02111-ga9f2953-dirty ehci_hcd
S: Product=OMAP-EHCI Host Controller
S: SerialNumber=ehci-omap.0
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr= 0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 4 Ivl=256ms
T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=480 MxCh= 4
D: Ver= 2.00 Cls=09(hub ) Sub=00 Prot=02 MxPS=64 #Cfgs= 1
P: Vendor=0424 ProdID=2514 Rev= b.b3
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr= 2mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=01 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=256ms
I:* If#= 0 Alt= 1 #EPs= 1 Cls=09(hub ) Sub=00 Prot=02 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=256ms
T: Bus=01 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 3 Spd=12 MxCh= 0
D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
P: Vendor=06f8 ProdID=c000 Rev= 1.00
S: Product=USB Audio
C:* #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=500mA
I:* If#= 0 Alt= 0 #EPs= 0 Cls=01(audio) Sub=01 Prot=00 Driver=snd-usb-audio
I:* If#= 1 Alt= 0 #EPs= 0 Cls=01(audio) Sub=02 Prot=00 Driver=snd-usb-audio
I: If#= 1 Alt= 1 #EPs= 1 Cls=01(audio) Sub=02 Prot=00 Driver=snd-usb-audio
E: Ad=01(O) Atr=09(Isoc) MxPS= 200 Ivl=1ms
I: If#= 1 Alt= 2 #EPs= 1 Cls=01(audio) Sub=02 Prot=00 Driver=snd-usb-audio
E: Ad=01(O) Atr=09(Isoc) MxPS= 600 Ivl=1ms
I:* If#= 2 Alt= 0 #EPs= 0 Cls=01(audio) Sub=02 Prot=00 Driver=snd-usb-audio
I: If#= 2 Alt= 1 #EPs= 1 Cls=01(audio) Sub=02 Prot=00 Driver=snd-usb-audio
E: Ad=82(I) Atr=05(Isoc) MxPS= 200 Ivl=1ms
I:* If#= 3 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=00 Prot=00 Driver=usbhid
E: Ad=83(I) Atr=03(Int.) MxPS= 3 Ivl=32ms
Desription of the problem :
* Standard comportment :
Use ehci-logs.patch for information. Activation of standard ehci-hcd
debug modify comportement of driver.
Situation at start : 13 usec used for sound card hid.
uframe | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
----------------------------------------------------------------------
max_tt_usecs | 125 | 125 | 125 | 125 | 125 | 125 | 30 | 0 |
----------------------------------------------------------------------
used usecs on a frame | 13 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
----------------------------------------------------------------------
cat /dev/urandom | alsa_aplay -Dhw:2,0 -f S16_LE -c2&
uframe 0 : isoc 164 > 125us, first frame must be empty, but 13 usecs used
uframe 1 : sheduled
Situation is now :
uframe | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
----------------------------------------------------------------------
max_tt_usecs | 125 | 125 | 125 | 125 | 125 | 125 | 30 | 0 |
----------------------------------------------------------------------
used usecs on a frame | 13 | 125 | 39 | 0 | 0 | 0 | 0 | 0 |
----------------------------------------------------------------------
arecord -Dhw:2,0 --rate=48000 -c 2 -f S16_LE > /tmp/input
uframe 0 : isoc 165 > 125us, first frame must be empty, but 13 usecs used
uframe 1 is fully scheduled : 125/125 (needs 165 usecs)
uframe 2 : isoc 165 > 125us, first frame must be empty, but 39 usecs used
uframe 3, for IN, don't wrap CSPLIT into the next frame, not ok
uframe 4, for IN, don't wrap CSPLIT into the next frame, not ok
uframe 5, for IN, don't wrap CSPLIT into the next frame, not ok
ehci-omap ehci-omap.0: iso resched full c0caab40 (now 256 max 4352)
no room in the shedule
cannot submit datapipe for urb 0, error -28: not enough bandwidth
* Modified ehci-sched comportment :
The patch ehci-scheduler.patch invert uframe choice order in
iso_stream_schedule.
When scheduling, check when is the next uframe we could start from the
end of the period.
So the output usecs are not scheduled in the first uframes, allowing
input usecs to find a place.
Here is the new comportment with the patch :
uframe | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
----------------------------------------------------------------------
max_tt_usecs | 125 | 125 | 125 | 125 | 125 | 125 | 30 | 0 |
----------------------------------------------------------------------
used usecs on a frame | 13 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
----------------------------------------------------------------------
cat /dev/urandom | alsa_aplay -Dhw:2,0 -f S16_LE -c2&
uframe 5 : usecs 164 unavailable (remains 9/0 on uframe 7)
Note : On uframe 5 , the 164 usecs would be uframe 5 : 125, uframe 6 :
30, uframe 7 : 9,out of max
uframe 4 : sheduled
uframe | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
----------------------------------------------------------------------
max_tt_usecs | 125 | 125 | 125 | 125 | 125 | 125 | 30 | 0 |
----------------------------------------------------------------------
used usecs on a frame | 13 | 0 | 0 | 0 | 125 | 78 | 0 | 0 |
----------------------------------------------------------------------
arecord -Dhw:2,0 --rate=48000 -c 2 -f S16_LE > /tmp/input
uframe 5, for IN, don't wrap CSPLIT into the next frame, not ok
uframe 4, for IN, don't wrap CSPLIT into the next frame, not ok
uframe 3, for IN, don't wrap CSPLIT into the next frame, not ok
uframe 2 : sheduled
uframe | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
----------------------------------------------------------------------
max_tt_usecs | 125 | 125 | 125 | 125 | 125 | 125 | 30 | 0 |
----------------------------------------------------------------------
used usecs on a frame | 13 | 0 | 125 | 40 | 125 | 78 | 0 | 0 |
----------------------------------------------------------------------
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 724ba71..65fdf76 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1386,7 +1386,7 @@ iso_stream_schedule (
struct ehci_iso_stream *stream
)
{
- u32 now, next, start, period, span;
+ u32 now, previous, next, start, period, span;
int status;
unsigned mod = ehci->periodic_size << 3;
struct ehci_iso_sched *sched = urb->hcpriv;
@@ -1455,8 +1455,9 @@ iso_stream_schedule (
/* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */
/* find a uframe slot with enough bandwidth */
- next = start + period;
- for (; start < next; start++) {
+ previous = start-1;
+ start += period-1;
+ for (; start > previous; start--) {
/* check schedule: enough space? */
if (stream->highspeed) {
@@ -1473,7 +1474,7 @@ iso_stream_schedule (
}
/* no room in the schedule */
- if (start == next) {
+ if (start == previous) {
ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n",
urb, now, now + mod);
status = -ENOSPC;
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 724ba71..2c62ba9 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -331,6 +331,8 @@ static int tt_available (
if (max_tt_usecs[uframe] <= tt_usecs[uframe]) {
ehci_vdbg(ehci, "frame %d uframe %d fully scheduled\n",
frame, uframe);
+ printk(KERN_DEBUG "uframe %d is fully scheduled : %d/%d (needs %d usecs)\n",
+ uframe, tt_usecs[uframe], max_tt_usecs[uframe], usecs);
return 0;
}
@@ -348,6 +350,8 @@ static int tt_available (
"multi-uframe xfer can't fit "
"in frame %d uframe %d\n",
frame, i);
+ printk(KERN_DEBUG "uframe %d : isoc %d > 125us, first frame must be empty, but %d usecs used",
+ i, usecs, tt_usecs[i]);
return 0;
}
}
@@ -361,6 +365,7 @@ static int tt_available (
ehci_vdbg(ehci,
"tt unavailable usecs %d frame %d uframe %d\n",
usecs, frame, uframe);
+ printk(KERN_DEBUG "uframe %d : usecs %d unavailable (remains %d/%d on uframe 7)\n", uframe, usecs, tt_usecs[7], max_tt_usecs[7]);
return 0;
}
}
@@ -1304,6 +1309,10 @@ sitd_slot_ok (
mask = stream->raw_mask << (uframe & 7);
+ if (mask & ~0xffff)
+ printk(KERN_DEBUG "uframe %d, for IN, don't wrap CSPLIT into the next frame, not ok\n", (uframe & 7));
+
+
/* for IN, don't wrap CSPLIT into the next frame */
if (mask & ~0xffff)
return 0;
@@ -1477,8 +1486,10 @@ iso_stream_schedule (
ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n",
urb, now, now + mod);
status = -ENOSPC;
+ printk(KERN_DEBUG "no room in the shedule\n");
goto fail;
}
+ printk(KERN_DEBUG "uframe %d : scheduled\n", start % 8);
}
/* Tried to schedule too far into the future? */