Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 9 Sep 2018 13:59:53 -0700
From:      Mark Millard <marklmi@yahoo.com>
To:        Kirk McKusick <mckusick@mckusick.com>
Cc:        bob prohaska <fbsd@www.zefox.net>, FreeBSD Filesystems <freebsd-fs@FreeBSD.org>
Subject:   Re: CFT: TRIM Consolodation on UFS/FFS filesystems
Message-ID:  <23C1A967-1E61-4055-B1A9-66E0FA51E2D9@yahoo.com>
In-Reply-To: <A3FFE52A-1163-4F1C-ADD2-B842810E4D4C@yahoo.com>
References:  <201809062330.w86NUphJ027262@chez.mckusick.com> <B9914A0D-69DC-4D3F-9BA4-D180462B2FA5@yahoo.com> <D2E536B0-B278-4E76-A3A4-3444BF840722@yahoo.com> <A3FFE52A-1163-4F1C-ADD2-B842810E4D4C@yahoo.com>

next in thread | previous in thread | raw e-mail | index | archive | help
[I looked up the e.MMC 4.41 information: TRIM was optional back
then. TRIM and DISCARD are Mandatory in e.MMC 4.51 . Also It
looks to me like microsd{hc,xc} cards do not use=20
EXT_CSD_INAND_CMD38_TRIM in FreeBSD, instead using
EXT_CSD_INAND_CMD38_ERASE .]

On 2018-Sep-8, at 2:32 AM, Mark Millard <marklmi at yahoo.com> wrote:

> On 2018-Sep-8, at 1:36 AM, Mark Millard <marklmi at yahoo.com> wrote:
>=20
>> Just an FYI.
>>=20
>> I figured out a hack that allows the e.MMC on a microsd card
>> adapter to be used to boot and operate the Pine64+ 2GB, in
>> DDR52 mode at that. (And so shows what was missing in the
>> FreeBSD operation even if the code change is not the
>> proper form of an official fix.)
>>=20
>> But in the process I discovered that FreeBSD is using
>> (for e.MMC in this tested context):
>>=20
>> mmc0: REQUEST: CMD38 arg 0x1 flags 0x1d
>>=20
>> That "0x1" means: TRIM that forces reads of zeros: the true
>> Data Removal command for mmc protocol, a form of erase. 0x3
>> would be DISCARD, the "performance command" that does not
>> guarantee what would be read afterwards: no erase required.
>>=20
>> TRIM is older (added in e/MCC 4.4). DISCARD is newer (added
>> in e.MMC 4.5). Each is mandatory when the version has the
>> function at all.

I looked up the e.MMC 4.41 information: TRIM was optional back
then. TRIM and DISCARD are Mandatory in e.MMC 4.51 .

Sorry for the error.

>> Does FreeBSD have a policy of preferring erasure when
>> there is also the option to not require it?
>=20
>=20
> I looked up published SD card material and that command
> set encodes differently for the argument:
>=20
> 0x1 is DISCARD (also not requiring an erase)
> 0x2 is FULE when start LBA=3DLBA0 and end LBA=3DMaxLBA.
> Otherwise it is ERASE.
> (FreeBSD's mmcsd_delete uses 0x0 for ERASE selection.)
>=20
> (I ignore handling violations of start LBA <=3D end LBA <=3D Max LBA
> or out of order command sequences. FULE: Full User Area Logical
> Erase.)
>=20
> It looks like FreeBSD uses mmcsd_delete for both SD and e.MMC
> and it is coded for SD to be more optimal (DISCARD), not
> differentiating e.MMC from SD for argument values to use.
>=20
> In e.MMC 4.5+ 0x2 is a "discard enable" bit in the argument,
> and never a FULE or other such.
>=20
> In e.MMC the 0x0 case for CMD38's argument is for performing
> an erase on erase group(s) instead of sector(s).
>=20
> (I'm not describing Secure Request or Force Garbage Collect
> being 0x1 for e.MMC: apparently unused by mmcsd_delete .)

[I'll note that on the e.MMC fsck_ffs -E with around 60 GiBytes
of free space, gstat -pd shows it taking a long time doing
deletes for the e.MMC that I have.]

It looks to me like microsd{hc,xc} cards and SD cards in
general do not use EXT_CSD_INAND_CMD38_TRIM. I say that
because . . .

Earlier I looked at what the CMD38 command encoding covered.
But that need not mean that TRIM is always used. So I looked
into that as well.

Example code uses MMCSD_USE_TRIM is:

        use_trim =3D sc->flags & MMCSD_USE_TRIM;
. . .
        if ((sc->flags & MMCSD_INAND_CMD38) !=3D 0) {
                err =3D mmc_switch(mmcbus, dev, sc->rca, =
EXT_CSD_CMD_SET_NORMAL,
                    EXT_CSD_INAND_CMD38, use_trim =3D=3D true ?
                    EXT_CSD_INAND_CMD38_TRIM : =
EXT_CSD_INAND_CMD38_ERASE,
                    sc->cmd6_time, true);
. . .

But the sc->flags bit involved is based on the mmcsd_attach's:

static int
mmcsd_attach(device_t dev)
{
        device_t mmcbus;
        struct mmcsd_softc *sc;
        const uint8_t *ext_csd;
        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];
       =20
        sc =3D device_get_softc(dev);
        sc->dev =3D dev;
        sc->mmcbus =3D mmcbus =3D device_get_parent(dev);
        sc->mode =3D mmc_get_card_type(dev);
        /*
         * Note that in principle with an SDHCI-like re-tuning =
implementation,
         * the maximum data size can change at runtime due to a device =
removal/
         * insertion that results in switches to/from a transfer mode =
involving
         * re-tuning, iff there are multiple devices on a given bus.  =
Until now
         * mmc(4) lacks support for rescanning already attached buses, =
however,
         * and sdhci(4) to date has no support for shared buses in the =
first
         * place either.
         */
        sc->max_data =3D mmc_get_max_data(dev);
        sc->high_cap =3D mmc_get_high_cap(dev);
        sc->rca =3D mmc_get_rca(dev);
        sc->cmd6_time =3D mmc_get_cmd6_timeout(dev);
        quirks =3D mmc_get_quirks(dev);

        /* Only MMC >=3D 4.x devices support EXT_CSD. */
        if (mmc_get_spec_vers(dev) >=3D 4) {
                MMCBUS_ACQUIRE_BUS(mmcbus, dev);
                err =3D mmc_send_ext_csd(mmcbus, dev, sc->ext_csd);
                MMCBUS_RELEASE_BUS(mmcbus, dev);
                if (err !=3D MMC_ERR_NONE) {
                        device_printf(dev, "Error reading EXT_CSD %s\n",
                            mmcsd_errmsg(err));
                        return (ENXIO);
                }
        }
        ext_csd =3D sc->ext_csd;

        if ((quirks & MMC_QUIRK_INAND_CMD38) !=3D 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 |=3D 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) !=3D 0 &&
            (quirks & MMC_QUIRK_BROKEN_TRIM) =3D=3D 0) {
                if (bootverbose)
                        device_printf(dev, "taking advantage of =
TRIM\n");
                sc->flags |=3D MMCSD_USE_TRIM;
                sc->erase_sector =3D 1;
        } else
                sc->erase_sector =3D mmc_get_erase_sector(dev);
. . .

microsd{hc,xc} cards do not have EXT_CSD and so would not appear
to ever assign sc->flags |=3D MMCSD_USE_TRIM . [mmc_send_ext_csd
establishes a zero'd area when the operation fails. For SD cards
CMD8 is only valid for the Idle state, which is not the
context here from what I can tell.]

So I get that EXT_CSD_INAND_CMD38_TRIM is only used for
e.MMC, not (micro)SD{hc,xc} cards.

This means my earlier microsdxc card testing was not testing what
I thought it was: instead testing EXT_CSD_INAND_CMD38_ERASE use.

=3D=3D=3D
Mark Millard
marklmi at yahoo.com
( dsl-only.net went
away in early 2018-Mar)




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?23C1A967-1E61-4055-B1A9-66E0FA51E2D9>