<div class="gmail_quote">On Thu, Apr 28, 2011 at 7:03 PM, Russell King - ARM Linux <span dir="ltr">&lt;<a href="mailto:linux@arm.linux.org.uk">linux@arm.linux.org.uk</a>&gt;</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>
&gt; On Tue, Apr 19, 2011 at 2:03 PM, Russell King - ARM Linux<br>
&gt; &lt;<a href="mailto:linux@arm.linux.org.uk">linux@arm.linux.org.uk</a>&gt; wrote:<br>
&gt; &gt; On Tue, Apr 19, 2011 at 02:00:17PM +0200, Linus Walleij wrote:<br>
&gt; &gt;&gt;<br>
&gt; &gt;&gt; On a high-speeded ux500 the DATAEND IRQ will assert before the<br>
&gt; &gt;&gt; DMA data is actually finished, thus if we start hammering in the next<br>
&gt; &gt;&gt; request we break an ongoing transfer. :-(<br>
&gt; &gt;<br>
&gt; &gt; Yes, you&#39;ve already said that in the past.  And this is partly why we<br>
&gt; &gt; have this code in the dma unmap:<br>
&gt; &gt;<br>
&gt; &gt;        /* Wait up to 1ms for the DMA to complete */<br>
&gt; &gt;        for (i = 0; ; i++) {<br>
&gt; &gt;                status = readl(host-&gt;base + MMCISTATUS);<br>
&gt; &gt;                if (!(status &amp; MCI_RXDATAAVLBLMASK) || i &gt;= 100)<br>
&gt; &gt;                        break;<br>
&gt; &gt;                udelay(10);<br>
&gt; &gt;        }<br>
&gt; &gt;<br>
&gt; &gt; So, we wait until the DMA has drained the FIFO before we fire off the<br>
&gt; &gt; next request - or even unmap the DMA buffer.  Should the DMA fail to<br>
&gt; &gt; drain the FIFO in a reasonable time, we timeout and disable DMA.<br>
&gt; &gt;<br>
&gt; &gt; Again, I ask, why is this not sufficient to cover the case where the<br>
&gt; &gt; data end IRQ occurs before the DMA engine has completed the transfer -<br>
&gt; &gt; which is likely to take a very short time indeed.<br>
&gt;<br>
&gt; It doesn&#39;t help, we have really tested this and at high speed transfers<br>
&gt; (especially if we use Per Fridens speed-up patches) apparently<br>
&gt; the flag RXDATAAVLBL goes to zero before the block is really<br>
&gt; finished.<br>
&gt;<br>
&gt; My rough guess (after looking at the VHDL code) is that<br>
&gt; RXDATAVLBL flag goes low when the FIFO is empty, but that<br>
&gt; doesn&#39;t mean that the DMA handshake logic is out of its send/recieve<br>
&gt; state and thus we screw it up if we hammer in another transfer before<br>
&gt; it has had time to deassert the single/burst request signals and go to<br>
&gt; idle state. This can only be seen by the side effect of the DMA<br>
&gt; transfer actually terminating, and the DMA engine calling its<br>
&gt; 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&#39;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&#39;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&#39;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&#39;s visible<br>
on ARMs own implementation) I wouldn&#39;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&#39;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>