Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/sdmmc Add discard support to ld@sdmmc using the ERAS...



details:   https://anonhg.NetBSD.org/src/rev/f9bdce6960a3
branches:  trunk
changeset: 824965:f9bdce6960a3
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sat Jun 24 11:27:33 2017 +0000

description:
Add discard support to ld@sdmmc using the ERASE (CMD38) command.

diffstat:

 sys/dev/sdmmc/ld_sdmmc.c  |  14 ++++++++-
 sys/dev/sdmmc/sdmmc_mem.c |  69 +++++++++++++++++++++++++++++++++++++++++++++-
 sys/dev/sdmmc/sdmmcreg.h  |   4 ++-
 sys/dev/sdmmc/sdmmcvar.h  |   3 +-
 4 files changed, 84 insertions(+), 6 deletions(-)

diffs (170 lines):

diff -r 3f796cf5abc3 -r f9bdce6960a3 sys/dev/sdmmc/ld_sdmmc.c
--- a/sys/dev/sdmmc/ld_sdmmc.c  Sat Jun 24 11:23:35 2017 +0000
+++ b/sys/dev/sdmmc/ld_sdmmc.c  Sat Jun 24 11:27:33 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ld_sdmmc.c,v 1.27 2017/06/06 21:01:07 jmcneill Exp $   */
+/*     $NetBSD: ld_sdmmc.c,v 1.28 2017/06/24 11:27:33 jmcneill Exp $   */
 
 /*
  * Copyright (c) 2008 KIYOHARA Takashi
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ld_sdmmc.c,v 1.27 2017/06/06 21:01:07 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ld_sdmmc.c,v 1.28 2017/06/24 11:27:33 jmcneill Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -93,6 +93,7 @@
 static int ld_sdmmc_dump(struct ld_softc *, void *, int, int);
 static int ld_sdmmc_start(struct ld_softc *, struct buf *);
 static void ld_sdmmc_restart(void *);
+static int ld_sdmmc_discard(struct ld_softc *, off_t, off_t);
 
 static void ld_sdmmc_doattach(void *);
 static void ld_sdmmc_dobio(void *);
@@ -149,6 +150,7 @@
        ld->sc_maxqueuecnt = LD_SDMMC_MAXQUEUECNT;
        ld->sc_dump = ld_sdmmc_dump;
        ld->sc_start = ld_sdmmc_start;
+       ld->sc_discard = ld_sdmmc_discard;
 
        /*
         * It is avoided that the error occurs when the card attaches it,
@@ -297,6 +299,14 @@
            blkcnt * ld->sc_secsize);
 }
 
+static int
+ld_sdmmc_discard(struct ld_softc *ld, off_t pos, off_t len)
+{
+       struct ld_sdmmc_softc *sc = device_private(ld->sc_dv);
+
+       return sdmmc_mem_discard(sc->sc_sf, pos, len);
+}
+
 MODULE(MODULE_CLASS_DRIVER, ld_sdmmc, "ld");
 
 #ifdef _MODULE
diff -r 3f796cf5abc3 -r f9bdce6960a3 sys/dev/sdmmc/sdmmc_mem.c
--- a/sys/dev/sdmmc/sdmmc_mem.c Sat Jun 24 11:23:35 2017 +0000
+++ b/sys/dev/sdmmc/sdmmc_mem.c Sat Jun 24 11:27:33 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdmmc_mem.c,v 1.57 2017/06/04 15:00:02 jmcneill Exp $  */
+/*     $NetBSD: sdmmc_mem.c,v 1.58 2017/06/24 11:27:33 jmcneill 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.57 2017/06/04 15:00:02 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.58 2017/06/24 11:27:33 jmcneill Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_sdmmc.h"
@@ -1987,3 +1987,68 @@
 
        return error;
 }
+
+int
+sdmmc_mem_discard(struct sdmmc_function *sf, off_t pos, off_t len)
+{
+       struct sdmmc_softc *sc = sf->sc;
+       struct sdmmc_command cmd;
+       int error;
+
+       if (ISSET(sc->sc_caps, SMC_CAPS_SPI_MODE))
+               return ENODEV;  /* XXX not tested */
+
+       /* Erase what we can in the specified range. */
+       const off_t start = roundup(pos, SDMMC_SECTOR_SIZE);
+       const off_t end = rounddown(pos + len, SDMMC_SECTOR_SIZE) - 1;
+       if (end < start)
+               return EINVAL;
+       const uint32_t sblkno = start / SDMMC_SECTOR_SIZE;
+       const uint32_t eblkno = end / SDMMC_SECTOR_SIZE;
+
+       SDMMC_LOCK(sc);
+       mutex_enter(&sc->sc_mtx);
+
+       /* Set the address of the first write block to be erased */
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.c_opcode = ISSET(sc->sc_flags, SMF_SD_MODE) ?
+           SD_ERASE_WR_BLK_START : MMC_TAG_ERASE_GROUP_START;
+       cmd.c_arg = sblkno;
+       if (!ISSET(sf->flags, SFF_SDHC))
+               cmd.c_arg <<= SDMMC_SECTOR_SIZE_SB;
+       cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1;
+       error = sdmmc_mmc_command(sc, &cmd);
+       if (error)
+               goto out;
+
+       /* Set the address of the last write block to be erased */
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.c_opcode = ISSET(sc->sc_flags, SMF_SD_MODE) ?
+           SD_ERASE_WR_BLK_END : MMC_TAG_ERASE_GROUP_END;
+       cmd.c_arg = eblkno;
+       if (!ISSET(sf->flags, SFF_SDHC))
+               cmd.c_arg <<= SDMMC_SECTOR_SIZE_SB;
+       cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1;
+       error = sdmmc_mmc_command(sc, &cmd);
+       if (error)
+               goto out;
+
+       /* Start the erase operation */
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.c_opcode = MMC_ERASE;
+       cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1B;
+       error = sdmmc_mmc_command(sc, &cmd);
+       if (error)
+               goto out;
+
+out:
+       mutex_exit(&sc->sc_mtx);
+       SDMMC_UNLOCK(sc);
+
+#ifdef SDMMC_DEBUG
+       device_printf(sc->sc_dev, "discard blk %u-%u error %d\n",
+           sblkno, eblkno, error);
+#endif
+
+       return error;
+}
diff -r 3f796cf5abc3 -r f9bdce6960a3 sys/dev/sdmmc/sdmmcreg.h
--- a/sys/dev/sdmmc/sdmmcreg.h  Sat Jun 24 11:23:35 2017 +0000
+++ b/sys/dev/sdmmc/sdmmcreg.h  Sat Jun 24 11:27:33 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdmmcreg.h,v 1.29 2017/02/17 10:51:48 nonaka Exp $     */
+/*     $NetBSD: sdmmcreg.h,v 1.30 2017/06/24 11:27:33 jmcneill Exp $   */
 /*     $OpenBSD: sdmmcreg.h,v 1.4 2009/01/09 10:55:22 jsg Exp $        */
 
 /*
@@ -61,6 +61,8 @@
 #define SD_SEND_SWITCH_FUNC            6       /* R1 */
 #define SD_SEND_IF_COND                        8       /* R7 */
 #define SD_VOLTAGE_SWITCH              11      /* R1 */
+#define SD_ERASE_WR_BLK_START          32      /* R1 */
+#define SD_ERASE_WR_BLK_END            33      /* R1 */
 
 /* SD application commands */                  /* response type */
 #define SD_APP_SET_BUS_WIDTH           6       /* R1 */
diff -r 3f796cf5abc3 -r f9bdce6960a3 sys/dev/sdmmc/sdmmcvar.h
--- a/sys/dev/sdmmc/sdmmcvar.h  Sat Jun 24 11:23:35 2017 +0000
+++ b/sys/dev/sdmmc/sdmmcvar.h  Sat Jun 24 11:27:33 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdmmcvar.h,v 1.24 2017/06/04 15:00:02 jmcneill Exp $   */
+/*     $NetBSD: sdmmcvar.h,v 1.25 2017/06/24 11:27:33 jmcneill Exp $   */
 /*     $OpenBSD: sdmmcvar.h,v 1.13 2009/01/09 10:55:22 jsg Exp $       */
 
 /*
@@ -377,5 +377,6 @@
            size_t);
 int    sdmmc_mem_write_block(struct sdmmc_function *, uint32_t, u_char *,
            size_t);
+int    sdmmc_mem_discard(struct sdmmc_function *, off_t, off_t);
 
 #endif /* _SDMMCVAR_H_ */



Home | Main Index | Thread Index | Old Index