Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/sdmmc fix to simulate multi-segment dma transfer for...



details:   https://anonhg.NetBSD.org/src/rev/2e7fb9d211f1
branches:  trunk
changeset: 336372:2e7fb9d211f1
user:      nonaka <nonaka%NetBSD.org@localhost>
date:      Fri Feb 27 16:08:17 2015 +0000

description:
fix to simulate multi-segment dma transfer for pq3sdhc(4).

diffstat:

 sys/dev/sdmmc/sdmmc.c     |   25 ++-
 sys/dev/sdmmc/sdmmc_mem.c |  320 +++++++++++++++++++++++++++------------------
 sys/dev/sdmmc/sdmmcvar.h  |    3 +-
 3 files changed, 206 insertions(+), 142 deletions(-)

diffs (truncated from 564 to 300 lines):

diff -r 500ee90aaec8 -r 2e7fb9d211f1 sys/dev/sdmmc/sdmmc.c
--- a/sys/dev/sdmmc/sdmmc.c     Fri Feb 27 16:02:03 2015 +0000
+++ b/sys/dev/sdmmc/sdmmc.c     Fri Feb 27 16:08:17 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdmmc.c,v 1.23 2014/11/16 16:20:01 ozaki-r Exp $       */
+/*     $NetBSD: sdmmc.c,v 1.24 2015/02/27 16:08:17 nonaka Exp $        */
 /*     $OpenBSD: sdmmc.c,v 1.18 2009/01/09 10:58:38 jsg Exp $  */
 
 /*
@@ -49,7 +49,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdmmc.c,v 1.23 2014/11/16 16:20:01 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc.c,v 1.24 2015/02/27 16:08:17 nonaka Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -626,25 +626,31 @@
                bus_dma_segment_t ds;
                int rseg, error;
 
-               error = bus_dmamap_create(sc->sc_dmat, SDMMC_SECTOR_SIZE, 1,
-                   SDMMC_SECTOR_SIZE, 0, BUS_DMA_WAITOK, &sf->bbuf_dmap);
+               error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, 1,
+                   MAXPHYS, 0, BUS_DMA_WAITOK, &sf->bbuf_dmap);
                if (error)
                        goto fail1;
-               error = bus_dmamem_alloc(sc->sc_dmat, SDMMC_SECTOR_SIZE,
+               error = bus_dmamem_alloc(sc->sc_dmat, MAXPHYS,
                    PAGE_SIZE, 0, &ds, 1, &rseg, BUS_DMA_WAITOK);
                if (error)
                        goto fail2;
-               error = bus_dmamem_map(sc->sc_dmat, &ds, 1, SDMMC_SECTOR_SIZE,
+               error = bus_dmamem_map(sc->sc_dmat, &ds, 1, MAXPHYS,
                    &sf->bbuf, BUS_DMA_WAITOK);
                if (error)
                        goto fail3;
                error = bus_dmamap_load(sc->sc_dmat, sf->bbuf_dmap,
-                   sf->bbuf, SDMMC_SECTOR_SIZE, NULL,
+                   sf->bbuf, MAXPHYS, NULL,
                    BUS_DMA_WAITOK|BUS_DMA_READ|BUS_DMA_WRITE);
+               if (error)
+                       goto fail4;
+               error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, 1,
+                   MAXPHYS, 0, BUS_DMA_WAITOK, &sf->sseg_dmap);
                if (!error)
                        goto out;
 
-               bus_dmamem_unmap(sc->sc_dmat, sf->bbuf, SDMMC_SECTOR_SIZE);
+               bus_dmamap_unload(sc->sc_dmat, sf->bbuf_dmap);
+fail4:
+               bus_dmamem_unmap(sc->sc_dmat, sf->bbuf, MAXPHYS);
 fail3:
                bus_dmamem_free(sc->sc_dmat, &ds, 1);
 fail2:
@@ -666,8 +672,9 @@
        if (ISSET(sc->sc_flags, SMF_MEM_MODE) &&
            ISSET(sc->sc_caps, SMC_CAPS_DMA) &&
            !ISSET(sc->sc_caps, SMC_CAPS_MULTI_SEG_DMA)) {
+               bus_dmamap_destroy(sc->sc_dmat, sf->sseg_dmap);
                bus_dmamap_unload(sc->sc_dmat, sf->bbuf_dmap);
-               bus_dmamem_unmap(sc->sc_dmat, sf->bbuf, SDMMC_SECTOR_SIZE);
+               bus_dmamem_unmap(sc->sc_dmat, sf->bbuf, MAXPHYS);
                bus_dmamem_free(sc->sc_dmat,
                    sf->bbuf_dmap->dm_segs, sf->bbuf_dmap->dm_nsegs);
                bus_dmamap_destroy(sc->sc_dmat, sf->bbuf_dmap);
diff -r 500ee90aaec8 -r 2e7fb9d211f1 sys/dev/sdmmc/sdmmc_mem.c
--- a/sys/dev/sdmmc/sdmmc_mem.c Fri Feb 27 16:02:03 2015 +0000
+++ b/sys/dev/sdmmc/sdmmc_mem.c Fri Feb 27 16:08:17 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdmmc_mem.c,v 1.33 2015/02/07 04:13:26 christos Exp $  */
+/*     $NetBSD: sdmmc_mem.c,v 1.34 2015/02/27 16:08:17 nonaka Exp $    */
 /*     $OpenBSD: sdmmc_mem.c,v 1.10 2009/01/09 10:55:22 jsg Exp $      */
 
 /*
@@ -45,7 +45,7 @@
 /* Routines for SD/MMC memory cards. */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.33 2015/02/07 04:13:26 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.34 2015/02/27 16:08:17 nonaka Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -87,10 +87,14 @@
     u_char *, size_t);
 static int sdmmc_mem_single_write_block(struct sdmmc_function *, uint32_t,
     u_char *, size_t);
-static int sdmmc_mem_read_block_subr(struct sdmmc_function *, uint32_t,
-    u_char *, size_t);
-static int sdmmc_mem_write_block_subr(struct sdmmc_function *, uint32_t,
-    u_char *, size_t);
+static int sdmmc_mem_single_segment_dma_read_block(struct sdmmc_function *,
+    uint32_t, u_char *, size_t);
+static int sdmmc_mem_single_segment_dma_write_block(struct sdmmc_function *,
+    uint32_t, u_char *, size_t);
+static int sdmmc_mem_read_block_subr(struct sdmmc_function *, bus_dmamap_t,
+    uint32_t, u_char *, size_t);
+static int sdmmc_mem_write_block_subr(struct sdmmc_function *, bus_dmamap_t,
+    uint32_t, u_char *, size_t);
 
 /*
  * Initialize SD/MMC memory cards and memory in SDIO "combo" cards.
@@ -1251,7 +1255,7 @@
 sdmmc_mem_single_read_block(struct sdmmc_function *sf, uint32_t blkno,
     u_char *data, size_t datalen)
 {
-       struct sdmmc_softc *sc __diagused = sf->sc;
+       struct sdmmc_softc *sc = sf->sc;
        int error = 0;
        int i;
 
@@ -1259,7 +1263,7 @@
        KASSERT(!ISSET(sc->sc_caps, SMC_CAPS_DMA));
 
        for (i = 0; i < datalen / SDMMC_SECTOR_SIZE; i++) {
-               error = sdmmc_mem_read_block_subr(sf, blkno + i,
+               error = sdmmc_mem_read_block_subr(sf, sc->sc_dmap, blkno + i,
                    data + i * SDMMC_SECTOR_SIZE, SDMMC_SECTOR_SIZE);
                if (error)
                        break;
@@ -1267,13 +1271,81 @@
        return error;
 }
 
+/*
+ * Simulate multi-segment dma transfer.
+ */
 static int
-sdmmc_mem_read_block_subr(struct sdmmc_function *sf, uint32_t blkno,
-    u_char *data, size_t datalen)
+sdmmc_mem_single_segment_dma_read_block(struct sdmmc_function *sf,
+    uint32_t blkno, u_char *data, size_t datalen)
+{
+       struct sdmmc_softc *sc = sf->sc;
+       bool use_bbuf = false;
+       int error = 0;
+       int i;
+
+       for (i = 0; i < sc->sc_dmap->dm_nsegs; i++) {
+               size_t len = sc->sc_dmap->dm_segs[i].ds_len;
+               if ((len % SDMMC_SECTOR_SIZE) != 0) {
+                       use_bbuf = true;
+                       break;
+               }
+       }
+       if (use_bbuf) {
+               bus_dmamap_sync(sc->sc_dmat, sf->bbuf_dmap, 0, datalen,
+                   BUS_DMASYNC_PREREAD);
+
+               error = sdmmc_mem_read_block_subr(sf, sf->bbuf_dmap,
+                   blkno, data, datalen);
+               if (error) {
+                       bus_dmamap_unload(sc->sc_dmat, sf->bbuf_dmap);
+                       return error;
+               }
+
+               bus_dmamap_sync(sc->sc_dmat, sf->bbuf_dmap, 0, datalen,
+                   BUS_DMASYNC_POSTREAD);
+
+               /* Copy from bounce buffer */
+               memcpy(data, sf->bbuf, datalen);
+
+               return 0;
+       }
+
+       for (i = 0; i < sc->sc_dmap->dm_nsegs; i++) {
+               size_t len = sc->sc_dmap->dm_segs[i].ds_len;
+
+               error = bus_dmamap_load(sc->sc_dmat, sf->sseg_dmap,
+                   data, len, NULL, BUS_DMA_NOWAIT|BUS_DMA_READ);
+               if (error)
+                       return error;
+
+               bus_dmamap_sync(sc->sc_dmat, sf->sseg_dmap, 0, len,
+                   BUS_DMASYNC_PREREAD);
+
+               error = sdmmc_mem_read_block_subr(sf, sf->sseg_dmap,
+                   blkno, data, len);
+               if (error) {
+                       bus_dmamap_unload(sc->sc_dmat, sf->sseg_dmap);
+                       return error;
+               }
+
+               bus_dmamap_sync(sc->sc_dmat, sf->sseg_dmap, 0, len,
+                   BUS_DMASYNC_POSTREAD);
+
+               bus_dmamap_unload(sc->sc_dmat, sf->sseg_dmap);
+
+               blkno += len / SDMMC_SECTOR_SIZE;
+               data += len;
+       }
+       return 0;
+}
+
+static int
+sdmmc_mem_read_block_subr(struct sdmmc_function *sf, bus_dmamap_t dmap,
+    uint32_t blkno, u_char *data, size_t datalen)
 {
        struct sdmmc_softc *sc = sf->sc;
        struct sdmmc_command cmd;
-       int error, bbuf, seg, off, len, num;
+       int error;
 
        if (!ISSET(sc->sc_caps, SMC_CAPS_SPI_MODE)) {
                error = sdmmc_select_card(sc, sf);
@@ -1281,10 +1353,6 @@
                        goto out;
        }
 
-       bbuf = 0;
-       num = 0;
-       seg = off = len = 0;
-retry:
        memset(&cmd, 0, sizeof(cmd));
        cmd.c_data = data;
        cmd.c_datalen = datalen;
@@ -1295,30 +1363,8 @@
        if (!ISSET(sf->flags, SFF_SDHC))
                cmd.c_arg <<= SDMMC_SECTOR_SIZE_SB;
        cmd.c_flags = SCF_CMD_ADTC | SCF_CMD_READ | SCF_RSP_R1 | SCF_RSP_SPI_R1;
-       if (ISSET(sc->sc_caps, SMC_CAPS_DMA)) {
-               cmd.c_dmamap = sc->sc_dmap;
-               if (!ISSET(sc->sc_caps, SMC_CAPS_MULTI_SEG_DMA)) {
-                       len = sc->sc_dmap->dm_segs[seg].ds_len - off;
-                       len &= ~(SDMMC_SECTOR_SIZE - 1);
-                       cmd.c_datalen = len;
-                       cmd.c_dmaseg = seg;
-                       cmd.c_dmaoff = off;
-                       bbuf = 0;
-                       if (len == 0) {
-                               /* Use bounce buffer */
-                               bus_dmamap_sync(sc->sc_dmat, sf->bbuf_dmap,
-                                   0, SDMMC_SECTOR_SIZE, BUS_DMASYNC_PREREAD);
-                               cmd.c_datalen = SDMMC_SECTOR_SIZE;
-                               cmd.c_dmamap = sf->bbuf_dmap;
-                               cmd.c_dmaseg = 0;
-                               cmd.c_dmaoff = 0;
-                               bbuf = 1;
-                               len = SDMMC_SECTOR_SIZE;
-                       }
-                       cmd.c_opcode = (cmd.c_datalen / cmd.c_blklen) > 1 ?
-                           MMC_READ_BLOCK_MULTIPLE : MMC_READ_BLOCK_SINGLE;
-               }
-       }
+       if (ISSET(sc->sc_caps, SMC_CAPS_DMA))
+               cmd.c_dmamap = dmap;
 
        error = sdmmc_mmc_command(sc, &cmd);
        if (error)
@@ -1350,34 +1396,6 @@
                } while (!ISSET(MMC_R1(cmd.c_resp), MMC_R1_READY_FOR_DATA));
        }
 
-       if (ISSET(sc->sc_caps, SMC_CAPS_DMA) &&
-           !ISSET(sc->sc_caps, SMC_CAPS_MULTI_SEG_DMA)) {
-               bus_dma_segment_t *dm_segs = sc->sc_dmap->dm_segs;
-
-               if (bbuf) {
-                       bus_dmamap_sync(sc->sc_dmat, sf->bbuf_dmap,
-                           0, SDMMC_SECTOR_SIZE, BUS_DMASYNC_POSTREAD);
-                       bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap, num,
-                           SDMMC_SECTOR_SIZE, BUS_DMASYNC_POSTREAD);
-                       memcpy(data, sf->bbuf, SDMMC_SECTOR_SIZE);
-                       bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap, num,
-                           SDMMC_SECTOR_SIZE, BUS_DMASYNC_PREREAD);
-               }
-               num += len;
-               data += len;
-               datalen -= len;
-               blkno += (len / SDMMC_SECTOR_SIZE);
-
-               while (off + len >= dm_segs[seg].ds_len) {
-                       len -= dm_segs[seg++].ds_len;
-                       off = 0;
-               }
-               off += len;
-
-               if (seg < sc->sc_dmap->dm_nsegs)
-                       goto retry;
-       }
-
 out:
        return error;
 }
@@ -1397,7 +1415,8 @@
        }
 
        if (!ISSET(sc->sc_caps, SMC_CAPS_DMA)) {
-               error = sdmmc_mem_read_block_subr(sf, blkno, data, datalen);
+               error = sdmmc_mem_read_block_subr(sf, sc->sc_dmap, blkno, data,
+                   datalen);
                goto out;
        }
 
@@ -1408,6 +1427,7 @@
                goto out;
 
 #ifdef SDMMC_DEBUG



Home | Main Index | Thread Index | Old Index