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/5495b5aff4db
branches: trunk
changeset: 354664:5495b5aff4db
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 4ec8c6a46693 -r 5495b5aff4db 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 4ec8c6a46693 -r 5495b5aff4db 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 4ec8c6a46693 -r 5495b5aff4db 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 4ec8c6a46693 -r 5495b5aff4db 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