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