From owner-svn-src-head@freebsd.org Mon Aug 7 23:33:07 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 60399DD02AD; Mon, 7 Aug 2017 23:33:07 +0000 (UTC) (envelope-from marius@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 2F04F636E2; Mon, 7 Aug 2017 23:33:07 +0000 (UTC) (envelope-from marius@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v77NX6L5058684; Mon, 7 Aug 2017 23:33:06 GMT (envelope-from marius@FreeBSD.org) Received: (from marius@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v77NX6T7058679; Mon, 7 Aug 2017 23:33:06 GMT (envelope-from marius@FreeBSD.org) Message-Id: <201708072333.v77NX6T7058679@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: marius set sender to marius@FreeBSD.org using -f From: Marius Strobl Date: Mon, 7 Aug 2017 23:33:06 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r322209 - head/sys/dev/mmc X-SVN-Group: head X-SVN-Commit-Author: marius X-SVN-Commit-Paths: head/sys/dev/mmc X-SVN-Commit-Revision: 322209 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 07 Aug 2017 23:33:07 -0000 Author: marius Date: Mon Aug 7 23:33:05 2017 New Revision: 322209 URL: https://svnweb.freebsd.org/changeset/base/322209 Log: - If available, use TRIM instead of ERASE for implementing BIO_DELETE. This also involves adding a quirk table as TRIM is broken for some Kingston eMMC devices, though. Compared to ERASE (declared "legacy" in the eMMC specification v5.1), TRIM has the advantage of operating on write sectors rather than on erase sectors, which typically are of a much larger size. Thus, employing TRIM, we don't need to fiddle with coalescing BIO_DELETE requests that are also of (write) sector units into erase sectors, which might not even add up in all cases. - For some SanDisk iNAND devices, the CMD38 argument, e. g. ERASE, TRIM etc., has to be specified via EXT_CSD[113], which now is also handled via a quirk. - My initial understanding was that for eMMC partitions, the granularity should be used as erase sector size, e. g. 128 KB for boot partitions. However, rereading the relevant parts of the eMMC specification v5.1, this isn't actually correct. So drop the code which used partition granularities for delmaxsize and stripesize. For the most part, this change is a NOP, though, because a) for ERASE, mmcsd_delete() used the erase sector size unconditionally for all partitions anyway and b) g_disk_limit() doesn't actually take the stripesize into account. - Take some more advantage of mmcsd_errmsg() in mmcsd(4) for making error codes human readable. Modified: head/sys/dev/mmc/bridge.h head/sys/dev/mmc/mmc.c head/sys/dev/mmc/mmcreg.h head/sys/dev/mmc/mmcsd.c head/sys/dev/mmc/mmcvar.h Modified: head/sys/dev/mmc/bridge.h ============================================================================== --- head/sys/dev/mmc/bridge.h Mon Aug 7 23:32:00 2017 (r322208) +++ head/sys/dev/mmc/bridge.h Mon Aug 7 23:33:05 2017 (r322209) @@ -180,7 +180,7 @@ struct mmc_host { extern driver_t mmc_driver; extern devclass_t mmc_devclass; -#define MMC_VERSION 4 +#define MMC_VERSION 5 #define MMC_DECLARE_BRIDGE(name) \ DRIVER_MODULE(mmc, name, mmc_driver, mmc_devclass, NULL, NULL); \ Modified: head/sys/dev/mmc/mmc.c ============================================================================== --- head/sys/dev/mmc/mmc.c Mon Aug 7 23:32:00 2017 (r322208) +++ head/sys/dev/mmc/mmc.c Mon Aug 7 23:33:05 2017 (r322209) @@ -104,12 +104,34 @@ struct mmc_ivars { uint32_t hs_tran_speed; /* Max speed in high speed mode */ uint32_t erase_sector; /* Card native erase sector size */ uint32_t cmd6_time; /* Generic switch timeout [us] */ + uint32_t quirks; /* Quirks as per mmc_quirk->quirks */ char card_id_string[64];/* Formatted CID info (serial, MFG, etc) */ char card_sn_string[16];/* Formatted serial # for disk->d_ident */ }; #define CMD_RETRIES 3 +static const struct mmc_quirk mmc_quirks[] = { + /* + * For some SanDisk iNAND devices, the CMD38 argument needs to be + * provided in EXT_CSD[113]. + */ + { 0x2, 0x100, "SEM02G", MMC_QUIRK_INAND_CMD38 }, + { 0x2, 0x100, "SEM04G", MMC_QUIRK_INAND_CMD38 }, + { 0x2, 0x100, "SEM08G", MMC_QUIRK_INAND_CMD38 }, + { 0x2, 0x100, "SEM16G", MMC_QUIRK_INAND_CMD38 }, + { 0x2, 0x100, "SEM32G", MMC_QUIRK_INAND_CMD38 }, + + /* + * Disable TRIM for Kingston eMMCs where a firmware bug can lead to + * unrecoverable data corruption. + */ + { 0x70, MMC_QUIRK_OID_ANY, "V10008", MMC_QUIRK_BROKEN_TRIM }, + { 0x70, MMC_QUIRK_OID_ANY, "V10016", MMC_QUIRK_BROKEN_TRIM }, + + { 0x0, 0x0, NULL, 0x0 } +}; + static SYSCTL_NODE(_hw, OID_AUTO, mmc, CTLFLAG_RD, NULL, "mmc driver"); static int mmc_debug; @@ -1109,7 +1131,7 @@ mmc_format_card_id_string(struct mmc_ivars *ivar) /* * Format a card ID string for use by the mmcsd driver, it's what * appears between the <> in the following: - * mmcsd0: 968MB at mmc0 + * mmcsd0: 968MB at mmc0 * 22.5MHz/4bit/128-block * * Also format just the card serial number, which the mmcsd driver will @@ -1547,6 +1569,7 @@ mmc_log_card(device_t dev, struct mmc_ivars *ivar, int break; } } + device_printf(dev, " quirks: %b\n", ivar->quirks, MMC_QUIRKS_FMT); device_printf(dev, " bus: %ubit, %uMHz (%s timing)\n", (ivar->bus_width == bus_width_1 ? 1 : (ivar->bus_width == bus_width_4 ? 4 : 8)), @@ -1563,6 +1586,7 @@ mmc_discover_cards(struct mmc_softc *sc) u_char switch_res[64]; uint32_t raw_cid[4]; struct mmc_ivars *ivar = NULL; + const struct mmc_quirk *quirk; device_t child; int err, host_caps, i, newcard; uint32_t resp, sec_count, status; @@ -1870,6 +1894,18 @@ mmc_discover_cards(struct mmc_softc *sc) ivar->raw_ext_csd[EXT_CSD_REV] >= 5); child_common: + for (quirk = &mmc_quirks[0]; quirk->mid != 0x0; quirk++) { + if ((quirk->mid == MMC_QUIRK_MID_ANY || + quirk->mid == ivar->cid.mid) && + (quirk->oid == MMC_QUIRK_OID_ANY || + quirk->oid == ivar->cid.oid) && + strncmp(quirk->pnm, ivar->cid.pnm, + sizeof(ivar->cid.pnm)) == 0) { + ivar->quirks = quirk->quirks; + break; + } + } + /* * Some cards that report maximum I/O block sizes greater * than 512 require the block length to be set to 512, even @@ -2470,6 +2506,12 @@ mmc_read_ivar(device_t bus, device_t child, int which, break; case MMC_IVAR_MAX_DATA: *result = mmcbr_get_max_data(bus); + break; + case MMC_IVAR_CMD6_TIMEOUT: + *result = ivar->cmd6_time; + break; + case MMC_IVAR_QUIRKS: + *result = ivar->quirks; break; case MMC_IVAR_CARD_ID_STRING: *(char **)result = ivar->card_id_string; Modified: head/sys/dev/mmc/mmcreg.h ============================================================================== --- head/sys/dev/mmc/mmcreg.h Mon Aug 7 23:32:00 2017 (r322208) +++ head/sys/dev/mmc/mmcreg.h Mon Aug 7 23:33:05 2017 (r322209) @@ -268,6 +268,13 @@ struct mmc_request { #define MMC_ERASE_GROUP_END 36 /* 37 -- reserved old command */ #define MMC_ERASE 38 +#define MMC_ERASE_ERASE 0x00000000 +#define MMC_ERASE_TRIM 0x00000001 +#define MMC_ERASE_FULE 0x00000002 +#define MMC_ERASE_DISCARD 0x00000003 +#define MMC_ERASE_SECURE_ERASE 0x80000000 +#define MMC_ERASE_SECURE_TRIM1 0x80000001 +#define MMC_ERASE_SECURE_TRIM2 0x80008000 /* Class 9: I/O mode commands */ #define MMC_FAST_IO 39 @@ -375,6 +382,7 @@ struct mmc_request { #define EXT_CSD_ERASE_TO_MULT 223 /* RO */ #define EXT_CSD_ERASE_GRP_SIZE 224 /* RO */ #define EXT_CSD_BOOT_SIZE_MULT 226 /* RO */ +#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */ #define EXT_CSD_PWR_CL_200_195 236 /* RO */ #define EXT_CSD_PWR_CL_200_360 237 /* RO */ #define EXT_CSD_PWR_CL_52_195_DDR 238 /* RO */ @@ -459,6 +467,22 @@ struct mmc_request { #define EXT_CSD_STROBE_SUPPORT_EN 0x01 +#define EXT_CSD_SEC_FEATURE_SUPPORT_ER_EN 0x01 +#define EXT_CSD_SEC_FEATURE_SUPPORT_BD_BLK_EN 0x04 +#define EXT_CSD_SEC_FEATURE_SUPPORT_GB_CL_EN 0x10 +#define EXT_CSD_SEC_FEATURE_SUPPORT_SANITIZE 0x40 + +/* + * Vendor specific EXT_CSD fields + */ +/* SanDisk iNAND */ +#define EXT_CSD_INAND_CMD38 113 +#define EXT_CSD_INAND_CMD38_ERASE 0x00 +#define EXT_CSD_INAND_CMD38_TRIM 0x01 +#define EXT_CSD_INAND_CMD38_SECURE_ERASE 0x80 +#define EXT_CSD_INAND_CMD38_SECURE_TRIM1 0x81 +#define EXT_CSD_INAND_CMD38_SECURE_TRIM2 0x82 + #define MMC_TYPE_HS_26_MAX 26000000 #define MMC_TYPE_HS_52_MAX 52000000 #define MMC_TYPE_DDR52_MAX 52000000 @@ -600,8 +624,7 @@ struct mmc_cid { uint8_t fwrev; }; -struct mmc_csd -{ +struct mmc_csd { uint8_t csd_structure; uint8_t spec_vers; uint16_t ccc; @@ -627,16 +650,14 @@ struct mmc_csd wp_grp_enable:1; }; -struct mmc_scr -{ +struct mmc_scr { unsigned char sda_vsn; unsigned char bus_widths; #define SD_SCR_BUS_WIDTH_1 (1 << 0) #define SD_SCR_BUS_WIDTH_4 (1 << 2) }; -struct mmc_sd_status -{ +struct mmc_sd_status { uint8_t bus_width; uint8_t secured_mode; uint16_t card_type; @@ -648,6 +669,19 @@ struct mmc_sd_status uint8_t erase_timeout; uint8_t erase_offset; }; + +struct mmc_quirk { + uint32_t mid; +#define MMC_QUIRK_MID_ANY ((uint32_t)-1) + uint16_t oid; +#define MMC_QUIRK_OID_ANY ((uint16_t)-1) + const char *pnm; + uint32_t quirks; +#define MMC_QUIRK_INAND_CMD38 0x0001 +#define MMC_QUIRK_BROKEN_TRIM 0x0002 +}; + +#define MMC_QUIRKS_FMT "\020" "\001INAND_CMD38" "\002BROKEN_TRIM" /* * Various MMC/SD constants Modified: head/sys/dev/mmc/mmcsd.c ============================================================================== --- head/sys/dev/mmc/mmcsd.c Mon Aug 7 23:32:00 2017 (r322208) +++ head/sys/dev/mmc/mmcsd.c Mon Aug 7 23:33:05 2017 (r322209) @@ -126,6 +126,10 @@ struct mmcsd_softc { uint8_t part_curr; /* Partition currently switched to */ uint8_t ext_csd[MMC_EXTCSD_SIZE]; uint16_t rca; + uint32_t flags; +#define MMCSD_INAND_CMD38 0x0001 +#define MMCSD_USE_TRIM 0x0002 + uint32_t cmd6_time; /* Generic switch timeout [us] */ uint32_t part_time; /* Partition switch timeout [us] */ off_t enh_base; /* Enhanced user data area slice base ... */ off_t enh_size; /* ... and size [bytes] */ @@ -168,9 +172,10 @@ static int mmcsd_ioctl_rpmb(struct cdev *dev, u_long c int fflag, struct thread *td); static void mmcsd_add_part(struct mmcsd_softc *sc, u_int type, - const char *name, u_int cnt, off_t media_size, off_t erase_size, bool ro); + const char *name, u_int cnt, off_t media_size, bool ro); static int mmcsd_bus_bit_width(device_t dev); static daddr_t mmcsd_delete(struct mmcsd_part *part, struct bio *bp); +static const char *mmcsd_errmsg(int e); static int mmcsd_ioctl(struct mmcsd_part *part, u_long cmd, void *data, int fflag); static int mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic, @@ -221,6 +226,7 @@ mmcsd_attach(device_t dev) off_t erase_size, sector_size, size, wp_size; uintmax_t bytes; int err, i; + uint32_t quirks; uint8_t rev; bool comp, ro; char unit[2]; @@ -239,21 +245,48 @@ mmcsd_attach(device_t dev) * place either. */ sc->max_data = mmc_get_max_data(dev); - sc->erase_sector = mmc_get_erase_sector(dev); sc->high_cap = mmc_get_high_cap(dev); sc->rca = mmc_get_rca(dev); + sc->cmd6_time = mmc_get_cmd6_timeout(dev); + quirks = mmc_get_quirks(dev); /* Only MMC >= 4.x devices support EXT_CSD. */ if (mmc_get_spec_vers(dev) >= 4) { MMCBUS_ACQUIRE_BUS(mmcbus, dev); err = mmc_send_ext_csd(mmcbus, dev, sc->ext_csd); MMCBUS_RELEASE_BUS(mmcbus, dev); - if (err != MMC_ERR_NONE) - bzero(sc->ext_csd, sizeof(sc->ext_csd)); + if (err != MMC_ERR_NONE) { + device_printf(dev, "Error reading EXT_CSD %s\n", + mmcsd_errmsg(err)); + return (ENXIO); + } } ext_csd = sc->ext_csd; + if ((quirks & MMC_QUIRK_INAND_CMD38) != 0) { + if (mmc_get_spec_vers(dev) < 4) { + device_printf(dev, + "MMC_QUIRK_INAND_CMD38 set but no EXT_CSD\n"); + return (EINVAL); + } + sc->flags |= MMCSD_INAND_CMD38; + } + /* + * EXT_CSD_SEC_FEATURE_SUPPORT_GB_CL_EN denotes support for both + * insecure and secure TRIM. + */ + if ((ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT] & + EXT_CSD_SEC_FEATURE_SUPPORT_GB_CL_EN) != 0 && + (quirks & MMC_QUIRK_BROKEN_TRIM) == 0) { + if (bootverbose) + device_printf(dev, "taking advantage of TRIM\n"); + sc->flags |= MMCSD_USE_TRIM; + sc->erase_sector = 1; + } else + sc->erase_sector = mmc_get_erase_sector(dev); + + /* * Enhanced user data area and general purpose partitions are only * supported in revision 1.4 (EXT_CSD_REV == 4) and later, the RPMB * partition in revision 1.5 (MMC v4.41, EXT_CSD_REV == 5) and later. @@ -306,8 +339,7 @@ mmcsd_attach(device_t dev) */ ro = mmc_get_read_only(dev); mmcsd_add_part(sc, EXT_CSD_PART_CONFIG_ACC_DEFAULT, "mmcsd", - device_get_unit(dev), mmc_get_media_size(dev) * sector_size, - sc->erase_sector * sector_size, ro); + device_get_unit(dev), mmc_get_media_size(dev) * sector_size, ro); if (mmc_get_spec_vers(dev) < 3) return (0); @@ -332,11 +364,11 @@ mmcsd_attach(device_t dev) size = ext_csd[EXT_CSD_BOOT_SIZE_MULT] * MMC_BOOT_RPMB_BLOCK_SIZE; if (size > 0 && (mmcbr_get_caps(mmcbus) & MMC_CAP_BOOT_NOACC) == 0) { mmcsd_add_part(sc, EXT_CSD_PART_CONFIG_ACC_BOOT0, - MMCSD_FMT_BOOT, 0, size, MMC_BOOT_RPMB_BLOCK_SIZE, + MMCSD_FMT_BOOT, 0, size, ro | ((ext_csd[EXT_CSD_BOOT_WP_STATUS] & EXT_CSD_BOOT_WP_STATUS_BOOT0_MASK) != 0)); mmcsd_add_part(sc, EXT_CSD_PART_CONFIG_ACC_BOOT1, - MMCSD_FMT_BOOT, 1, size, MMC_BOOT_RPMB_BLOCK_SIZE, + MMCSD_FMT_BOOT, 1, size, ro | ((ext_csd[EXT_CSD_BOOT_WP_STATUS] & EXT_CSD_BOOT_WP_STATUS_BOOT1_MASK) != 0)); } @@ -345,7 +377,7 @@ mmcsd_attach(device_t dev) size = ext_csd[EXT_CSD_RPMB_MULT] * MMC_BOOT_RPMB_BLOCK_SIZE; if (rev >= 5 && size > 0) mmcsd_add_part(sc, EXT_CSD_PART_CONFIG_ACC_RPMB, - MMCSD_FMT_RPMB, 0, size, MMC_BOOT_RPMB_BLOCK_SIZE, ro); + MMCSD_FMT_RPMB, 0, size, ro); if (rev <= 3 || comp == FALSE) return (0); @@ -365,8 +397,7 @@ mmcsd_attach(device_t dev) if (size == 0) continue; mmcsd_add_part(sc, EXT_CSD_PART_CONFIG_ACC_GP0 + i, - MMCSD_FMT_GP, i, size * erase_size * wp_size, - erase_size, ro); + MMCSD_FMT_GP, i, size * erase_size * wp_size, ro); } } return (0); @@ -419,7 +450,7 @@ static struct cdevsw mmcsd_rpmb_cdevsw = { static void mmcsd_add_part(struct mmcsd_softc *sc, u_int type, const char *name, u_int cnt, - off_t media_size, off_t erase_size, bool ro) + off_t media_size, bool ro) { struct make_dev_args args; device_t dev, mmcbus; @@ -482,10 +513,10 @@ mmcsd_add_part(struct mmcsd_softc *sc, u_int type, con d->d_sectorsize = mmc_get_sector_size(dev); d->d_maxsize = sc->max_data * d->d_sectorsize; d->d_mediasize = media_size; - d->d_stripesize = erase_size; + d->d_stripesize = sc->erase_sector * d->d_sectorsize; d->d_unit = cnt; d->d_flags = DISKFLAG_CANDELETE; - d->d_delmaxsize = erase_size; + d->d_delmaxsize = mmc_get_erase_sector(dev) * d->d_sectorsize; strlcpy(d->d_ident, mmc_get_card_sn_string(dev), sizeof(d->d_ident)); strlcpy(d->d_descr, mmc_get_card_id_string(dev), @@ -1151,6 +1182,8 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp) struct mmcsd_softc *sc; device_t dev, mmcbus; u_int erase_sector, sz; + int err; + bool use_trim; sc = part->sc; dev = sc->dev; @@ -1159,24 +1192,46 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp) block = bp->bio_pblkno; sz = part->disk->d_sectorsize; end = bp->bio_pblkno + (bp->bio_bcount / sz); - /* Coalesce with part remaining from previous request. */ - if (block > part->eblock && block <= part->eend) - block = part->eblock; - if (end >= part->eblock && end < part->eend) - end = part->eend; - /* Safe round to the erase sector boundaries. */ - erase_sector = sc->erase_sector; - start = block + erase_sector - 1; /* Round up. */ - start -= start % erase_sector; - stop = end; /* Round down. */ - stop -= end % erase_sector; - /* We can't erase an area smaller than a sector, store it for later. */ - if (start >= stop) { - part->eblock = block; - part->eend = end; - return (end); + use_trim = sc->flags & MMCSD_USE_TRIM; + if (use_trim == true) { + start = block; + stop = end; + } else { + /* Coalesce with the remainder of the previous request. */ + if (block > part->eblock && block <= part->eend) + block = part->eblock; + if (end >= part->eblock && end < part->eend) + end = part->eend; + /* Safely round to the erase sector boundaries. */ + erase_sector = sc->erase_sector; + start = block + erase_sector - 1; /* Round up. */ + start -= start % erase_sector; + stop = end; /* Round down. */ + stop -= end % erase_sector; + /* + * We can't erase an area smaller than an erase sector, so + * store it for later. + */ + if (start >= stop) { + part->eblock = block; + part->eend = end; + return (end); + } } + if ((sc->flags & MMCSD_INAND_CMD38) != 0) { + err = mmc_switch(mmcbus, dev, sc->rca, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_INAND_CMD38, use_trim == true ? + EXT_CSD_INAND_CMD38_TRIM : EXT_CSD_INAND_CMD38_ERASE, + sc->cmd6_time, true); + if (err != MMC_ERR_NONE) { + device_printf(dev, + "Setting iNAND erase command failed %s\n", + mmcsd_errmsg(err)); + return (block); + } + } + /* * Pause re-tuning so it won't interfere with the order of erase * commands. Note that these latter don't use the data lines, so @@ -1198,8 +1253,8 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp) cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; MMCBUS_WAIT_FOR_REQUEST(mmcbus, dev, &req); if (req.cmd->error != MMC_ERR_NONE) { - device_printf(dev, "Setting erase start position failed %d\n", - req.cmd->error); + device_printf(dev, "Setting erase start position failed %s\n", + mmcsd_errmsg(req.cmd->error)); block = bp->bio_pblkno; goto unpause; } @@ -1218,8 +1273,8 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp) cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; MMCBUS_WAIT_FOR_REQUEST(mmcbus, dev, &req); if (req.cmd->error != MMC_ERR_NONE) { - device_printf(dev, "Setting erase stop position failed %d\n", - req.cmd->error); + device_printf(dev, "Setting erase stop position failed %s\n", + mmcsd_errmsg(req.cmd->error)); block = bp->bio_pblkno; goto unpause; } @@ -1228,23 +1283,24 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp) memset(&cmd, 0, sizeof(cmd)); req.cmd = &cmd; cmd.opcode = MMC_ERASE; - cmd.arg = 0; + cmd.arg = use_trim == true ? MMC_ERASE_TRIM : MMC_ERASE_ERASE; cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; MMCBUS_WAIT_FOR_REQUEST(mmcbus, dev, &req); if (req.cmd->error != MMC_ERR_NONE) { - device_printf(dev, "erase err3: %d\n", req.cmd->error); - device_printf(dev, "Issuing erase command failed %d\n", - req.cmd->error); + device_printf(dev, "Issuing erase command failed %s\n", + mmcsd_errmsg(req.cmd->error)); block = bp->bio_pblkno; goto unpause; } - /* Store one of remaining parts for the next call. */ - if (bp->bio_pblkno >= part->eblock || block == start) { - part->eblock = stop; /* Predict next forward. */ - part->eend = end; - } else { - part->eblock = block; /* Predict next backward. */ - part->eend = start; + if (use_trim == false) { + /* Store one of the remaining parts for the next call. */ + if (bp->bio_pblkno >= part->eblock || block == start) { + part->eblock = stop; /* Predict next forward. */ + part->eend = end; + } else { + part->eblock = block; /* Predict next backward. */ + part->eend = start; + } } block = end; unpause: Modified: head/sys/dev/mmc/mmcvar.h ============================================================================== --- head/sys/dev/mmc/mmcvar.h Mon Aug 7 23:32:00 2017 (r322208) +++ head/sys/dev/mmc/mmcvar.h Mon Aug 7 23:33:05 2017 (r322209) @@ -68,6 +68,8 @@ enum mmc_device_ivars { MMC_IVAR_BUS_WIDTH, MMC_IVAR_ERASE_SECTOR, MMC_IVAR_MAX_DATA, + MMC_IVAR_CMD6_TIMEOUT, + MMC_IVAR_QUIRKS, MMC_IVAR_CARD_ID_STRING, MMC_IVAR_CARD_SN_STRING, }; @@ -90,6 +92,8 @@ MMC_ACCESSOR(card_type, CARD_TYPE, int) MMC_ACCESSOR(bus_width, BUS_WIDTH, int) MMC_ACCESSOR(erase_sector, ERASE_SECTOR, int) MMC_ACCESSOR(max_data, MAX_DATA, int) +MMC_ACCESSOR(cmd6_timeout, CMD6_TIMEOUT, u_int) +MMC_ACCESSOR(quirks, QUIRKS, u_int) MMC_ACCESSOR(card_id_string, CARD_ID_STRING, const char *) MMC_ACCESSOR(card_sn_string, CARD_SN_STRING, const char *)