Author: marius
Date: Fri Aug 11 00:41:43 2017
New Revision: 322389
URL: https://svnweb.freebsd.org/changeset/base/322389

Log:
  MFC: r322209
  
  - 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:
  stable/10/sys/dev/mmc/bridge.h
  stable/10/sys/dev/mmc/mmc.c
  stable/10/sys/dev/mmc/mmcreg.h
  stable/10/sys/dev/mmc/mmcsd.c
  stable/10/sys/dev/mmc/mmcvar.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/mmc/bridge.h
==============================================================================
--- stable/10/sys/dev/mmc/bridge.h      Fri Aug 11 00:41:19 2017        
(r322388)
+++ stable/10/sys/dev/mmc/bridge.h      Fri Aug 11 00:41:43 2017        
(r322389)
@@ -179,7 +179,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: stable/10/sys/dev/mmc/mmc.c
==============================================================================
--- stable/10/sys/dev/mmc/mmc.c Fri Aug 11 00:41:19 2017        (r322388)
+++ stable/10/sys/dev/mmc/mmc.c Fri Aug 11 00:41:43 2017        (r322389)
@@ -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;
@@ -1110,7 +1132,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 <SD SD01G 8.0 SN 2686905 Mfg 08/2008 by 3 TN> at mmc0
+        * mmcsd0: 968MB <SD SD01G 8.0 SN 2686905 MFG 08/2008 by 3 TN> at mmc0
         * 22.5MHz/4bit/128-block
         *
         * Also format just the card serial number, which the mmcsd driver will
@@ -1548,6 +1570,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)),
@@ -1564,6 +1587,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;
@@ -1871,6 +1895,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
@@ -2471,6 +2507,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: stable/10/sys/dev/mmc/mmcreg.h
==============================================================================
--- stable/10/sys/dev/mmc/mmcreg.h      Fri Aug 11 00:41:19 2017        
(r322388)
+++ stable/10/sys/dev/mmc/mmcreg.h      Fri Aug 11 00:41:43 2017        
(r322389)
@@ -238,6 +238,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
@@ -321,6 +328,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 */
@@ -405,6 +413,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
@@ -498,8 +522,7 @@ struct mmc_cid {
        uint8_t fwrev;
 };
 
-struct mmc_csd
-{
+struct mmc_csd {
        uint8_t csd_structure;
        uint8_t spec_vers;
        uint16_t ccc;
@@ -525,16 +548,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;
@@ -546,6 +567,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: stable/10/sys/dev/mmc/mmcsd.c
==============================================================================
--- stable/10/sys/dev/mmc/mmcsd.c       Fri Aug 11 00:41:19 2017        
(r322388)
+++ stable/10/sys/dev/mmc/mmcsd.c       Fri Aug 11 00:41:43 2017        
(r322389)
@@ -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: stable/10/sys/dev/mmc/mmcvar.h
==============================================================================
--- stable/10/sys/dev/mmc/mmcvar.h      Fri Aug 11 00:41:19 2017        
(r322388)
+++ stable/10/sys/dev/mmc/mmcvar.h      Fri Aug 11 00:41:43 2017        
(r322389)
@@ -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 *)
 
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to