Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/sdmmc Completely rework (and enable) SDHC 1.0 DMA da...



details:   https://anonhg.NetBSD.org/src/rev/d5102a840b8d
branches:  trunk
changeset: 780135:d5102a840b8d
user:      jakllsch <jakllsch%NetBSD.org@localhost>
date:      Thu Jul 12 17:27:42 2012 +0000

description:
Completely rework (and enable) SDHC 1.0 DMA data transfer.

While without a large physically-contiguous buffer the performance
suffers severly, this should still be better than PIO.

diffstat:

 sys/dev/sdmmc/sdhc.c |  85 +++++++++++++++++++++++----------------------------
 1 files changed, 39 insertions(+), 46 deletions(-)

diffs (166 lines):

diff -r bf4c9c583c0e -r d5102a840b8d sys/dev/sdmmc/sdhc.c
--- a/sys/dev/sdmmc/sdhc.c      Thu Jul 12 17:26:42 2012 +0000
+++ b/sys/dev/sdmmc/sdhc.c      Thu Jul 12 17:27:42 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdhc.c,v 1.18 2012/07/12 17:15:27 jakllsch Exp $       */
+/*     $NetBSD: sdhc.c,v 1.19 2012/07/12 17:27:42 jakllsch Exp $       */
 /*     $OpenBSD: sdhc.c,v 1.25 2009/01/13 19:44:20 grange Exp $        */
 
 /*
@@ -23,7 +23,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.18 2012/07/12 17:15:27 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdhc.c,v 1.19 2012/07/12 17:27:42 jakllsch Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -296,7 +296,6 @@
        caps = HREAD4(hp, SDHC_CAPABILITIES);
        mutex_exit(&hp->host_mtx);
 
-#if notyet
        /* Use DMA if the host system and the controller support it. */
        if (ISSET(sc->sc_flags, SDHC_FLAG_FORCE_DMA)
         || ((ISSET(sc->sc_flags, SDHC_FLAG_USE_DMA)
@@ -304,7 +303,6 @@
                SET(hp->flags, SHF_USE_DMA);
                aprint_normal_dev(sc->sc_dev, "using DMA transfer\n");
        }
-#endif
 
        /*
         * Determine the base clock frequency. (2.2.24)
@@ -401,10 +399,8 @@
                saa.saa_caps |= SMC_CAPS_8BIT_MODE;
        if (ISSET(caps, SDHC_HIGH_SPEED_SUPP))
                saa.saa_caps |= SMC_CAPS_SD_HIGHSPEED;
-#if notyet
        if (ISSET(hp->flags, SHF_USE_DMA))
-               saa.saa_caps |= SMC_CAPS_DMA;
-#endif
+               saa.saa_caps |= SMC_CAPS_DMA | SMC_CAPS_MULTI_SEG_DMA;
        hp->sdmmc = config_found(sc->sc_dev, &saa, sdhc_cfprint);
 
        return 0;
@@ -1037,19 +1033,6 @@
                sdhc_transfer_data(hp, cmd);
 
 out:
-#if 0
-       if (cmd->c_dmamap != NULL && cmd->c_error == 0
-           && ISSET(hp->flags, SHF_USE_DMA)
-           && ISSET(cmd->c_flags, SCF_CMD_READ) {                           
-               if (((uintptr_t)cmd->c_data & PAGE_MASK) + cmd->c_datalen > PAGE_SIZE) {
-                       memcpy(cmd->c_data,
-                           (void *)hp->sc->dma_map->dm_segs[0].ds_addr,
-                           cmd->c_datalen);
-               }
-               bus_dmamap_unload(hp->sc->dt, hp->sc->dma_map);
-       }
-#endif
-
        if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)
            && !ISSET(hp->sc->sc_flags, SDHC_FLAG_NO_LED_ON)) {
                mutex_enter(&hp->host_mtx);
@@ -1111,11 +1094,7 @@
                mode |= SDHC_AUTO_CMD12_ENABLE;
        }
        if (cmd->c_dmamap != NULL && cmd->c_datalen > 0) {
-               if (cmd->c_dmamap->dm_nsegs == 1) {
-                       mode |= SDHC_DMA_ENABLE;
-               } else {
-                       cmd->c_dmamap = NULL;
-               }
+               mode |= SDHC_DMA_ENABLE;
        }
 
        /*
@@ -1147,6 +1126,9 @@
        DPRINTF(1,("%s: writing cmd: blksize=%d blkcnt=%d mode=%04x cmd=%04x\n",
            HDEVNAME(hp), blksize, blkcount, mode, command));
 
+       blksize |= (MAX(0, PAGE_SHIFT - 12) & SDHC_DMA_BOUNDARY_MASK) <<
+           SDHC_DMA_BOUNDARY_SHIFT;    /* PAGE_SIZE DMA boundary */
+
        mutex_enter(&hp->host_mtx);
 
        if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) {
@@ -1212,11 +1194,13 @@
 static int
 sdhc_transfer_data_dma(struct sdhc_host *hp, struct sdmmc_command *cmd)
 {
-       bus_dmamap_t dmap = cmd->c_dmamap;
-       uint16_t blklen = cmd->c_blklen;
-       uint16_t blkcnt = cmd->c_datalen / blklen;
-       uint16_t remain;
+       bus_dma_segment_t *dm_segs = cmd->c_dmamap->dm_segs;
+       bus_addr_t posaddr;
+       bus_addr_t segaddr;
+       bus_size_t seglen;
+       u_int seg = 0;
        int error = 0;
+       int status;
 
        KASSERT(HREAD2(hp, SDHC_NINTR_STATUS_EN) & SDHC_DMA_INTERRUPT);
        KASSERT(HREAD2(hp, SDHC_NINTR_SIGNAL_EN) & SDHC_DMA_INTERRUPT);
@@ -1224,32 +1208,41 @@
        KASSERT(HREAD2(hp, SDHC_NINTR_SIGNAL_EN) & SDHC_TRANSFER_COMPLETE);
 
        for (;;) {
-               if (!sdhc_wait_intr(hp,
+               status = sdhc_wait_intr(hp,
                    SDHC_DMA_INTERRUPT|SDHC_TRANSFER_COMPLETE,
-                   SDHC_DMA_TIMEOUT)) {
+                   SDHC_DMA_TIMEOUT);
+
+               if (status & SDHC_TRANSFER_COMPLETE) {
+                       break;
+               }
+               if (!status) {
                        error = ETIMEDOUT;
                        break;
                }
+               if ((status & SDHC_DMA_INTERRUPT) == 0) {
+                       continue;
+               }
 
-               /* single block mode */
-               if (blkcnt == 1)
-                       break;
+               /* DMA Interrupt (boundary crossing) */
 
-               /* multi block mode */
-               remain = HREAD2(hp, SDHC_BLOCK_COUNT);
-               if (remain == 0)
-                       break;
+               segaddr = dm_segs[seg].ds_addr;
+               seglen = dm_segs[seg].ds_len;
+               mutex_enter(&hp->host_mtx);
+               posaddr = HREAD4(hp, SDHC_DMA_ADDR);
+               mutex_exit(&hp->host_mtx);
 
-               HWRITE4(hp, SDHC_DMA_ADDR,
-                   dmap->dm_segs[0].ds_addr + (blkcnt - remain) * blklen);
+               if ((seg == (cmd->c_dmamap->dm_nsegs-1)) && (posaddr == (segaddr + seglen))) {
+                       break;
+               }
+               mutex_enter(&hp->host_mtx);
+               if ((posaddr >= segaddr) && (posaddr < (segaddr + seglen)))
+                       HWRITE4(hp, SDHC_DMA_ADDR, posaddr);
+               else if ((posaddr >= segaddr) && (posaddr == (segaddr + seglen)) && (seg + 1) < cmd->c_dmamap->dm_nsegs)
+                       HWRITE4(hp, SDHC_DMA_ADDR, dm_segs[++seg].ds_addr);
+               mutex_exit(&hp->host_mtx);
+               KASSERT(seg < cmd->c_dmamap->dm_nsegs);
        }
 
-#if 0
-       if (error == 0 && !sdhc_wait_intr(hp, SDHC_TRANSFER_COMPLETE,
-           SDHC_TRANSFER_TIMEOUT))
-               error = ETIMEDOUT;
-#endif
-
        return error;
 }
 



Home | Main Index | Thread Index | Old Index