lkml.org 
[lkml]   [2018]   [Jul]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Date
SubjectRe: [PATCH mmc-next v3 3/3] mmc: sdhci-of-dwcmshc: solve 128MB DMA boundary limitation
<div dir="ltr">
<span class="gmail-im">&gt;&gt; Hey Jisheng,<br>
<br>&gt;Hi,<br>
<br>
&gt;&gt; <br>
<br>
&gt;In LKML, we&#39;d better not top post.<br>
<span class="gmail-m_8245690094374767092gmail-im"></span><div><br></div></span><div>Noted. My apologies.<br></div><span class="gmail-im"><div><br></div><span class="gmail-m_8245690094374767092gmail-im">
&gt;&gt; Shouldn&#39;t we be splitting until all DMA blocks are less than 128M boundary?<br>
&gt;&gt; I am a noob, but I think we should be prepared for boundaries that when<br>
&gt;&gt; split in two, will still be greater than 128M. Feel free to disagree but<br>
&gt;&gt; please explain why I may be wrong. Thank-you.<br>
<br>
</span>&gt;the limitation is &quot;DMA addr can&#39;t span 128MB boundary&quot; rather than &quot;must be<br>
&gt;less than 128MB&quot;, they are different.<br>
<br>
&gt;And the max transfer size of one DMA desc is 64KB.<br>
<br><div>
&gt;thanks <br></div><div><br></div></span><div>I have misspoken. What
if the DMA transfer size is 1024M? If we split in two, then we have 2
transfers, each of which span 512M. So wouldn&#39;t we need to split again
to have 4 transfers, each of which span 128M?</div><div><br></div><div>Sincerely,<br></div><div>Matthew Leon</div>

<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Jul 29, 2018 at 10:59 PM, Jisheng Zhang <span dir="ltr">&lt;<a href="mailto:Jisheng.Zhang@synaptics.com" target="_blank">Jisheng.Zhang@synaptics.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Mon, 30 Jul 2018 02:56:20 +0000 Matthew Leon &lt;<a href="mailto:matthewleon@linux.com">matthewleon@linux.com</a>&gt; wrote:<br>
<br>
&gt; Hey Jisheng,<br>
<br>
Hi,<br>
<br>
&gt; <br>
<br>
In LKML, we&#39;d better not top post.<br>
<span class=""><br>
&gt; Shouldn&#39;t we be splitting until all DMA blocks are less than 128M boundary?<br>
&gt; I am a noob, but I think we should be prepared for boundaries that when<br>
&gt; split in two, will still be greater than 128M. Feel free to disagree but<br>
&gt; please explain why I may be wrong. Thank-you.<br>
<br>
</span>the limitation is &quot;DMA addr can&#39;t span 128MB boundary&quot; rather than &quot;must be<br>
less than 128MB&quot;, they are different.<br>
<br>
And the max transfer size of one DMA desc is 64KB.<br>
<br>
thanks<br>
<div class="HOEnZb"><div class="h5"><br>
&gt; <br>
&gt; Sincerely,<br>
&gt; Matthew Leon<br>
&gt; <br>
&gt; On Sun, Jul 29, 2018 at 10:46 PM, Jisheng Zhang &lt;<a href="mailto:Jisheng.Zhang@synaptics.com">Jisheng.Zhang@synaptics.com</a><br>
&gt; &gt; wrote:  <br>
&gt; <br>
&gt; &gt; When using DMA, if the DMA addr spans 128MB boundary, we have to split<br>
&gt; &gt; the DMA transfer into two so that each one doesn&#39;t exceed the boundary.<br>
&gt; &gt;<br>
&gt; &gt; Signed-off-by: Jisheng Zhang &lt;<a href="mailto:Jisheng.Zhang@synaptics.com">Jisheng.Zhang@synaptics.com</a>&gt;<br>
&gt; &gt; ---<br>
&gt; &gt;  drivers/mmc/host/sdhci-of-<wbr>dwcmshc.c | 43 +++++++++++++++++++++++++++++<br>
&gt; &gt;  1 file changed, 43 insertions(+)<br>
&gt; &gt;<br>
&gt; &gt; diff --git a/drivers/mmc/host/sdhci-of-<wbr>dwcmshc.c<br>
&gt; &gt; b/drivers/mmc/host/sdhci-of-<wbr>dwcmshc.c<br>
&gt; &gt; index 1b7cd144fb01..e890fc8f5284 100644<br>
&gt; &gt; --- a/drivers/mmc/host/sdhci-of-<wbr>dwcmshc.c<br>
&gt; &gt; +++ b/drivers/mmc/host/sdhci-of-<wbr>dwcmshc.c<br>
&gt; &gt; @@ -8,21 +8,52 @@<br>
&gt; &gt;   */<br>
&gt; &gt;<br>
&gt; &gt;  #include &lt;linux/clk.h&gt;<br>
&gt; &gt; +#include &lt;linux/mm.h&gt;<br>
&gt; &gt;  #include &lt;linux/module.h&gt;<br>
&gt; &gt;  #include &lt;linux/of.h&gt;<br>
&gt; &gt; +#include &lt;linux/sizes.h&gt;<br>
&gt; &gt;<br>
&gt; &gt;  #include &quot;sdhci-pltfm.h&quot;<br>
&gt; &gt;<br>
&gt; &gt; +#define BOUNDARY_OK(addr, len) \<br>
&gt; &gt; +       ((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1)))<br>
&gt; &gt; +<br>
&gt; &gt;  struct dwcmshc_priv {<br>
&gt; &gt;         struct clk      *bus_clk;<br>
&gt; &gt;  };<br>
&gt; &gt;<br>
&gt; &gt; +/*<br>
&gt; &gt; + * if DMA addr spans 128MB boundary, we split the DMA transfer into two<br>
&gt; &gt; + * so that the DMA transfer doesn&#39;t exceed the boundary.<br>
&gt; &gt; + */<br>
&gt; &gt; +static unsigned int dwcmshc_adma_write_desc(struct sdhci_host *host,<br>
&gt; &gt; +                                           void *desc, dma_addr_t addr,<br>
&gt; &gt; +                                           int len, unsigned int cmd)<br>
&gt; &gt; +{<br>
&gt; &gt; +       int tmplen, offset;<br>
&gt; &gt; +<br>
&gt; &gt; +       if (likely(!len || BOUNDARY_OK(addr, len)))<br>
&gt; &gt; +               return _sdhci_adma_write_desc(host, desc, addr, len, cmd);<br>
&gt; &gt; +<br>
&gt; &gt; +       offset = addr &amp; (SZ_128M - 1);<br>
&gt; &gt; +       tmplen = SZ_128M - offset;<br>
&gt; &gt; +       _sdhci_adma_write_desc(host, desc, addr, tmplen, cmd);<br>
&gt; &gt; +<br>
&gt; &gt; +       addr += tmplen;<br>
&gt; &gt; +       len -= tmplen;<br>
&gt; &gt; +       desc += host-&gt;desc_sz;<br>
&gt; &gt; +       _sdhci_adma_write_desc(host, desc, addr, len, cmd);<br>
&gt; &gt; +<br>
&gt; &gt; +       return host-&gt;desc_sz * 2;<br>
&gt; &gt; +}<br>
&gt; &gt; +<br>
&gt; &gt;  static const struct sdhci_ops sdhci_dwcmshc_ops = {<br>
&gt; &gt;         .set_clock              = sdhci_set_clock,<br>
&gt; &gt;         .set_bus_width          = sdhci_set_bus_width,<br>
&gt; &gt;         .set_uhs_signaling      = sdhci_set_uhs_signaling,<br>
&gt; &gt;         .get_max_clock          = sdhci_pltfm_clk_get_max_clock,<br>
&gt; &gt;         .reset                  = sdhci_reset,<br>
&gt; &gt; +       .adma_write_desc        = dwcmshc_adma_write_desc,<br>
&gt; &gt;  };<br>
&gt; &gt;<br>
&gt; &gt;  static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = {<br>
&gt; &gt; @@ -36,12 +67,24 @@ static int dwcmshc_probe(struct platform_device *pdev)<br>
&gt; &gt;         struct sdhci_host *host;<br>
&gt; &gt;         struct dwcmshc_priv *priv;<br>
&gt; &gt;         int err;<br>
&gt; &gt; +       u32 extra;<br>
&gt; &gt;<br>
&gt; &gt;         host = sdhci_pltfm_init(pdev, &amp;sdhci_dwcmshc_pdata,<br>
&gt; &gt;                                 sizeof(struct dwcmshc_priv));<br>
&gt; &gt;         if (IS_ERR(host))<br>
&gt; &gt;                 return PTR_ERR(host);<br>
&gt; &gt;<br>
&gt; &gt; +       /*<br>
&gt; &gt; +        * The DMA descriptor table number is calculated as the maximum<br>
&gt; &gt; +        * number of segments times 2, to allow for an alignment<br>
&gt; &gt; +        * descriptor for each segment, plus 1 for a nop end descriptor,<br>
&gt; &gt; +        * plus extra number for cross 128M boundary handling.<br>
&gt; &gt; +        */<br>
&gt; &gt; +       extra = DIV_ROUND_UP(totalram_pages, SZ_128M / PAGE_SIZE);<br>
&gt; &gt; +       if (extra &gt; SDHCI_MAX_SEGS)<br>
&gt; &gt; +               extra = SDHCI_MAX_SEGS;<br>
&gt; &gt; +       host-&gt;adma_table_num = SDHCI_MAX_SEGS * 2 + 1 + extra;<br>
&gt; &gt; +<br>
&gt; &gt;         pltfm_host = sdhci_priv(host);<br>
&gt; &gt;         priv = sdhci_pltfm_priv(pltfm_host);<br>
&gt; &gt;<br>
&gt; &gt; --<br>
&gt; &gt; 2.18.0<br>
&gt; &gt;<br>
&gt; &gt;  <br>
<br>
</div></div></blockquote></div><br></div>
\
 
 \ /
  Last update: 2018-07-30 05:13    [W:0.043 / U:25.920 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site