Module Name:    src
Committed By:   jmcneill
Date:           Sat Jun 24 11:27:33 UTC 2017

Modified Files:
        src/sys/dev/sdmmc: ld_sdmmc.c sdmmc_mem.c sdmmcreg.h sdmmcvar.h

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


To generate a diff of this commit:
cvs rdiff -u -r1.27 -r1.28 src/sys/dev/sdmmc/ld_sdmmc.c
cvs rdiff -u -r1.57 -r1.58 src/sys/dev/sdmmc/sdmmc_mem.c
cvs rdiff -u -r1.29 -r1.30 src/sys/dev/sdmmc/sdmmcreg.h
cvs rdiff -u -r1.24 -r1.25 src/sys/dev/sdmmc/sdmmcvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/sdmmc/ld_sdmmc.c
diff -u src/sys/dev/sdmmc/ld_sdmmc.c:1.27 src/sys/dev/sdmmc/ld_sdmmc.c:1.28
--- src/sys/dev/sdmmc/ld_sdmmc.c:1.27	Tue Jun  6 21:01:07 2017
+++ src/sys/dev/sdmmc/ld_sdmmc.c	Sat Jun 24 11:27:33 2017
@@ -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_detach(device_t, int
 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_sdmmc_attach(device_t parent, device_
 	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 @@ ld_sdmmc_dump(struct ld_softc *ld, void 
 	    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

Index: src/sys/dev/sdmmc/sdmmc_mem.c
diff -u src/sys/dev/sdmmc/sdmmc_mem.c:1.57 src/sys/dev/sdmmc/sdmmc_mem.c:1.58
--- src/sys/dev/sdmmc/sdmmc_mem.c:1.57	Sun Jun  4 15:00:02 2017
+++ src/sys/dev/sdmmc/sdmmc_mem.c	Sat Jun 24 11:27:33 2017
@@ -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 @@ out:
 
 	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;
+}

Index: src/sys/dev/sdmmc/sdmmcreg.h
diff -u src/sys/dev/sdmmc/sdmmcreg.h:1.29 src/sys/dev/sdmmc/sdmmcreg.h:1.30
--- src/sys/dev/sdmmc/sdmmcreg.h:1.29	Fri Feb 17 10:51:48 2017
+++ src/sys/dev/sdmmc/sdmmcreg.h	Sat Jun 24 11:27:33 2017
@@ -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 */

Index: src/sys/dev/sdmmc/sdmmcvar.h
diff -u src/sys/dev/sdmmc/sdmmcvar.h:1.24 src/sys/dev/sdmmc/sdmmcvar.h:1.25
--- src/sys/dev/sdmmc/sdmmcvar.h:1.24	Sun Jun  4 15:00:02 2017
+++ src/sys/dev/sdmmc/sdmmcvar.h	Sat Jun 24 11:27:33 2017
@@ -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 @@ int	sdmmc_mem_read_block(struct sdmmc_fu
 	    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_ */

Reply via email to