<div class="gmail_quote">On Thu, Apr 28, 2011 at 7:03 PM, Russell King - ARM Linux <span dir="ltr"><<a href="mailto:linux@arm.linux.org.uk">linux@arm.linux.org.uk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div><div></div><div class="h5">On Wed, Apr 20, 2011 at 06:29:40PM +0200, Linus Walleij wrote:<br>
> On Tue, Apr 19, 2011 at 2:03 PM, Russell King - ARM Linux<br>
> <<a href="mailto:linux@arm.linux.org.uk">linux@arm.linux.org.uk</a>> wrote:<br>
> > On Tue, Apr 19, 2011 at 02:00:17PM +0200, Linus Walleij wrote:<br>
> >><br>
> >> On a high-speeded ux500 the DATAEND IRQ will assert before the<br>
> >> DMA data is actually finished, thus if we start hammering in the next<br>
> >> request we break an ongoing transfer. :-(<br>
> ><br>
> > Yes, you've already said that in the past. And this is partly why we<br>
> > have this code in the dma unmap:<br>
> ><br>
> > /* Wait up to 1ms for the DMA to complete */<br>
> > for (i = 0; ; i++) {<br>
> > status = readl(host->base + MMCISTATUS);<br>
> > if (!(status & MCI_RXDATAAVLBLMASK) || i >= 100)<br>
> > break;<br>
> > udelay(10);<br>
> > }<br>
> ><br>
> > So, we wait until the DMA has drained the FIFO before we fire off the<br>
> > next request - or even unmap the DMA buffer. Should the DMA fail to<br>
> > drain the FIFO in a reasonable time, we timeout and disable DMA.<br>
> ><br>
> > Again, I ask, why is this not sufficient to cover the case where the<br>
> > data end IRQ occurs before the DMA engine has completed the transfer -<br>
> > which is likely to take a very short time indeed.<br>
><br>
> It doesn't help, we have really tested this and at high speed transfers<br>
> (especially if we use Per Fridens speed-up patches) apparently<br>
> the flag RXDATAAVLBL goes to zero before the block is really<br>
> finished.<br>
><br>
> My rough guess (after looking at the VHDL code) is that<br>
> RXDATAVLBL flag goes low when the FIFO is empty, but that<br>
> doesn't mean that the DMA handshake logic is out of its send/recieve<br>
> state and thus we screw it up if we hammer in another transfer before<br>
> it has had time to deassert the single/burst request signals and go to<br>
> idle state. This can only be seen by the side effect of the DMA<br>
> transfer actually terminating, and the DMA engine calling its<br>
> callback.<br>
<br></div></div></blockquote><div><br>Even this would be no guarantee. The callback is hopefully a guarantee<br>that the clr has been asserted, but for the peripheral's state machine<br>there is still an uncertain time left, so the callback is a guess as good as<br>
any other, although the reference point has been shifted forwards. Since the<br>time is uncertain, might just add a suitable delay. Preferably based on VHDL<br>analysis and as a function of peripheral clock. <br><br>At the very least the last data element should be out of the FIFO when RxDataAvlbl<br>
deasserts and a read of status should not arrive any sooner than that element<br>to the DMAC. If this is true, then the read of status itself implies that the DMAC<br>has asserted clr (or in some very pessimistic scenario within a few cycles?), <br>
and the delay can be chosen fixed from this point in time. Since udelays are<br>already tolerated, I don't see much more ugliness added by this.<br> </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div><div class="h5">
</div></div>That's rather unfortunate, because it means that trying it on ARM<br>
hardware is going to hang indefinitely waiting for the nonexistent<br>
DMA stuff to finish.<br>
<br>
I remain unconvinced whether this problem applies only to ARMs<br>
evaluation boards as I believe the whole primecell DMA stuff from<br>
the outset is fundamentally misdesigned. I suspect there maybe SoCs<br>
out there which suffer from the same broken DMA issues which ARMs<br>
eval boards do.<br>
<br>
Maybe an alternative solution is on data end to set a timer, which<br>
is cancelled when the DMA engine callback arrives. If the timer<br>
expires, it means we have broken DMA and that needs to be shutdown<br>
for that instance.<br>
<br>
However, one thing worries me - what if the DMA callback comes before<br>
we get the data end interrupt. Given the weirdnesses of your<br>
implementation found so far (which are well beyond what's visible<br>
on ARMs own implementation) I wouldn't put any guarantees on the<br>
relative ordering of that either.<br>
<div><div></div><div class="h5"><br></div></div></blockquote><div><br>So this would build on the old solution, and won't break the broken ones.<br> </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div><div class="h5">
_______________________________________________<br>
linux-arm-kernel mailing list<br>
<a href="mailto:linux-arm-kernel@lists.infradead.org">linux-arm-kernel@lists.infradead.org</a><br>
<a href="http://lists.infradead.org/mailman/listinfo/linux-arm-kernel" target="_blank">http://lists.infradead.org/mailman/listinfo/linux-arm-kernel</a><br>
</div></div></blockquote></div><br>