Re: [BUG] musb: broken isochronous transfer at TI AM335x platform

2018-02-18 Thread Matwey V. Kornilov
2018-02-16 19:27 GMT+03:00 Tony Lindgren :
> * Matwey V. Kornilov  [180215 17:55]:
>> []   7.219456 d=  0.000997 [181.0 +  3.667] [  3] IN   : 4.5
>> [T   ]   7.219459 d=  0.03 [181.0 +  7.083] [800] DATA0: 53 da 
>> ...
>> []   7.220456 d=  0.000997 [182   +  3.667] [  3] IN   : 4.5
>> [T   ]   7.220459 d=  0.03 [182   +  7.000] [800] DATA0: 13 36 
>> ...
>> []   7.222456 d=  0.001997 [184   +  3.667] [  3] IN   : 4.5
>> []   7.222459 d=  0.03 [184   +  7.000] [  3] DATA0: 00 00
>> []   7.223456 d=  0.000997 [185.0 +  3.667] [  3] IN   : 4.5
>> []   7.223459 d=  0.03 [185.0 +  7.000] [  3] DATA0: 00 00
>>
>> Please note, that the time moment "7.221456" has missed IN request
>> packet which must be sent out every 1ms in this low-speed USB case.
>> Then, all incoming packets became empty ones. Such moments coincide
>> with frame discarding in pwc driver.
>
> Well sounds like you may be able to fix it since you have a test
> case for it :)

Well, I am not an USB expert and I need some guidance and advice to
find acceptable solution. No doubts I could implement and test it, but
I would like to spend time for something known to be useful.

>
>> Even though IN sending is usually handled by USB host hardware, it is
>> not fully true for MUSB. Every IN is triggered by musb kernel driver
>> (see MUSB_RXCSR_H_REQPKT usage in musb_host_packet_rx() and
>> musb_ep_program()) since auto IN is not used. Rather complicated logic
>> is incorporated to decide whether IN packet has to be sent. First,
>> musb_host_packet_rx() handles IN sending when current URB is not
>> completed (i.e. current URB has another packet which has to be
>> received next). Second, musb_advance_schedule() (via musb_start_urb())
>> handles the case when current URB is completed but there is another
>> URB pending. It seems that there is a hardware logic to fire IN packet
>> in a way to have exactly 1ms between two consequent INs. So,
>> MUSB_RXCSR_H_REQPKT is considered as IN requesting flag.
>
> Yeah this is a known issue with musb, there is not much ISO support
> currently really. The regression should be fixed though.
>
> Sorry I don't have much ideas on how to improve things here. One
> way might be to attempt to split the large musb functions into
> smaller functions and see if that then allows finer grained control.
>
> Just to try to come up with some new ideas.. Maybe there's some way
> to swap the hardware EP config dynamically and have some packets
> mostly preconfigured and waiting to be triggered?
>
> Regards,
>
> Tony
>



-- 
With best regards,
Matwey V. Kornilov.
Sternberg Astronomical Institute, Lomonosov Moscow State University, Russia
119234, Moscow, Universitetsky pr-k 13, +7 (495) 9392382


Re: [BUG] musb: broken isochronous transfer at TI AM335x platform

2018-02-16 Thread Tony Lindgren
* Matwey V. Kornilov  [180215 17:55]:
> []   7.219456 d=  0.000997 [181.0 +  3.667] [  3] IN   : 4.5
> [T   ]   7.219459 d=  0.03 [181.0 +  7.083] [800] DATA0: 53 da ...
> []   7.220456 d=  0.000997 [182   +  3.667] [  3] IN   : 4.5
> [T   ]   7.220459 d=  0.03 [182   +  7.000] [800] DATA0: 13 36 ...
> []   7.222456 d=  0.001997 [184   +  3.667] [  3] IN   : 4.5
> []   7.222459 d=  0.03 [184   +  7.000] [  3] DATA0: 00 00
> []   7.223456 d=  0.000997 [185.0 +  3.667] [  3] IN   : 4.5
> []   7.223459 d=  0.03 [185.0 +  7.000] [  3] DATA0: 00 00
> 
> Please note, that the time moment "7.221456" has missed IN request
> packet which must be sent out every 1ms in this low-speed USB case.
> Then, all incoming packets became empty ones. Such moments coincide
> with frame discarding in pwc driver.

Well sounds like you may be able to fix it since you have a test
case for it :)

> Even though IN sending is usually handled by USB host hardware, it is
> not fully true for MUSB. Every IN is triggered by musb kernel driver
> (see MUSB_RXCSR_H_REQPKT usage in musb_host_packet_rx() and
> musb_ep_program()) since auto IN is not used. Rather complicated logic
> is incorporated to decide whether IN packet has to be sent. First,
> musb_host_packet_rx() handles IN sending when current URB is not
> completed (i.e. current URB has another packet which has to be
> received next). Second, musb_advance_schedule() (via musb_start_urb())
> handles the case when current URB is completed but there is another
> URB pending. It seems that there is a hardware logic to fire IN packet
> in a way to have exactly 1ms between two consequent INs. So,
> MUSB_RXCSR_H_REQPKT is considered as IN requesting flag.

Yeah this is a known issue with musb, there is not much ISO support
currently really. The regression should be fixed though.

Sorry I don't have much ideas on how to improve things here. One
way might be to attempt to split the large musb functions into
smaller functions and see if that then allows finer grained control.

Just to try to come up with some new ideas.. Maybe there's some way
to swap the hardware EP config dynamically and have some packets
mostly preconfigured and waiting to be triggered?

Regards,

Tony


[BUG] musb: broken isochronous transfer at TI AM335x platform

2018-02-15 Thread Matwey V. Kornilov
Hi all,

Almost two years ago I faced an issue related to PWC-driven V4L2
webcam attached to BeagleBone Black SBC. [1][2] The issue still
persists in 4.16-rc1. However, some research has been carried out
since then. I would like to summarize my findings below. I also would
like to receive feedback since the issue appears not to have one
single source and probably may affect setups other than mine.

Initial issue signs were the following. When Philips SPC 900 webcam
(handled by pwc kernel module) is attached to BeagleBone Black SBC
(equipped with TI AM335x Cortex-A8 CPU and Inventra MUSB Dual-Role USB
controller), no frames can be received from the camera. In other
words, the major functional purpose of the camera was broken. From
user-space point of view,

ioctl(fd, VIDIOC_DQBUF, )

indefinitely waits for a frame, yet all other functionalities (i.e.
setting formats) works as usual. This happens always when "ondemand"
cpufreq policy is set and from time to time when "performance" is
used. This also happens disregarding whether DMA USB is used.

Other instances of the camera (same model) have been tested and found
to have same behavior. Then, I've found that the reason for such
behavior is that pwc module never feeds V4L2 subsystem with frames
from the module side, because frame completion criteria never
satisfied in pwc_isoc_handler(). PWC considers the "shorter" or empty
incoming USB ISO packet as end-of-frame sign. Usually, every URB has
10 packets and every packet consists of 956 payload data bytes in case
of PWC. Also, when end-of-frame is received the accumulated amount of
bytes must be equal to expected (known from frame format, i.e width *
height * pixel-depth). It appeared that it was never the case, empty
USB packet was always received in advance to expected frame end and
then every frame was discarded.

I've also bisected the following. The USB ISO transfer works well since commit

2035772010db ("usb: musb: musb_host: Enable HCD_BH flag to handle
urb return in bottom half")

and stops working after commit

f551e1352983 ("Revert "usb: musb: musb_host: Enable HCD_BH flag to
handle urb return in bottom half"")

To reliably connect these two facts, I had to assembly OpenVizsla
hardware USB monitor (sniffer). [3] Using this tool the following MUSB
Host + PWC webcam behavior patterns were found [4]:

[]   7.219456 d=  0.000997 [181.0 +  3.667] [  3] IN   : 4.5
[T   ]   7.219459 d=  0.03 [181.0 +  7.083] [800] DATA0: 53 da ...
[]   7.220456 d=  0.000997 [182   +  3.667] [  3] IN   : 4.5
[T   ]   7.220459 d=  0.03 [182   +  7.000] [800] DATA0: 13 36 ...
[]   7.222456 d=  0.001997 [184   +  3.667] [  3] IN   : 4.5
[]   7.222459 d=  0.03 [184   +  7.000] [  3] DATA0: 00 00
[]   7.223456 d=  0.000997 [185.0 +  3.667] [  3] IN   : 4.5
[]   7.223459 d=  0.03 [185.0 +  7.000] [  3] DATA0: 00 00

Please note, that the time moment "7.221456" has missed IN request
packet which must be sent out every 1ms in this low-speed USB case.
Then, all incoming packets became empty ones. Such moments coincide
with frame discarding in pwc driver.

Even though IN sending is usually handled by USB host hardware, it is
not fully true for MUSB. Every IN is triggered by musb kernel driver
(see MUSB_RXCSR_H_REQPKT usage in musb_host_packet_rx() and
musb_ep_program()) since auto IN is not used. Rather complicated logic
is incorporated to decide whether IN packet has to be sent. First,
musb_host_packet_rx() handles IN sending when current URB is not
completed (i.e. current URB has another packet which has to be
received next). Second, musb_advance_schedule() (via musb_start_urb())
handles the case when current URB is completed but there is another
URB pending. It seems that there is a hardware logic to fire IN packet
in a way to have exactly 1ms between two consequent INs. So,
MUSB_RXCSR_H_REQPKT is considered as IN requesting flag.

Both functions are triggered by musb_host_rx() interrupt handler. And
there are a lot of other important things between interrupt triggering
and next IN requesting. It appears that sometimes it takes 0.4-0.5 ms
between the interrupt and MUSB_RXCSR_H_REQPKT writing. This delays
also lead to missed IN (It is actually sent, but at (last)+2ms time
instead of (last)+1ms) and confusing the peripheral as shown above.
This is a case of URB-completion branch.

The most time-consuming part is urb->giveback() calling.
Unfortunately, it is performed synchronously before requesting IN.
This explains why commit

2035772010db ("usb: musb: musb_host: Enable HCD_BH flag to handle
urb return in bottom half")

masks the issue. Moving (postponing) urb->giveback() call out of
interrupt context eliminated extra delays between IN requesting.
(Un)fortunately, this commit was reverted and the issue returned back.
I proposed a patch to swap time-consuming urb->giveback() and
MUSB_RXCSR_H_REQPKT writing but the