mmc: sd: Export SD Status via “ssr” device attribute
authorUri Yanai <uri.yanai@sandisk.com>
Sun, 14 Aug 2016 08:46:36 +0000 (11:46 +0300)
committerUlf Hansson <ulf.hansson@linaro.org>
Mon, 26 Sep 2016 19:31:09 +0000 (21:31 +0200)
The SD Status register contains several important fields related to the
SD Card proprietary features.
Those fields may be used by user space applications for vendor specific
usage.
None of those fields are exported today by the driver to user space.
In this patch, we are reading the SD Status register and exporting
(using MMC_DEV_ATTR) the SD Status register to the user space.

Signed-off-by: Uri Yanai <uri.yanai@sandisk.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/core/sd.c
include/linux/mmc/card.h

index 0123936241b06320cf15abb5463b87399c999838..73c762a28dfed886bc6a2dd2e91cfe43343b361f 100644 (file)
@@ -223,8 +223,7 @@ static int mmc_decode_scr(struct mmc_card *card)
 static int mmc_read_ssr(struct mmc_card *card)
 {
        unsigned int au, es, et, eo;
-       int err, i;
-       u32 *ssr;
+       int i;
 
        if (!(card->csd.cmdclass & CCC_APP_SPEC)) {
                pr_warn("%s: card lacks mandatory SD Status function\n",
@@ -232,33 +231,27 @@ static int mmc_read_ssr(struct mmc_card *card)
                return 0;
        }
 
-       ssr = kmalloc(64, GFP_KERNEL);
-       if (!ssr)
-               return -ENOMEM;
-
-       err = mmc_app_sd_status(card, ssr);
-       if (err) {
+       if (mmc_app_sd_status(card, card->raw_ssr)) {
                pr_warn("%s: problem reading SD Status register\n",
                        mmc_hostname(card->host));
-               err = 0;
-               goto out;
+               return 0;
        }
 
        for (i = 0; i < 16; i++)
-               ssr[i] = be32_to_cpu(ssr[i]);
+               card->raw_ssr[i] = be32_to_cpu(card->raw_ssr[i]);
 
        /*
         * UNSTUFF_BITS only works with four u32s so we have to offset the
         * bitfield positions accordingly.
         */
-       au = UNSTUFF_BITS(ssr, 428 - 384, 4);
+       au = UNSTUFF_BITS(card->raw_ssr, 428 - 384, 4);
        if (au) {
                if (au <= 9 || card->scr.sda_spec3) {
                        card->ssr.au = sd_au_size[au];
-                       es = UNSTUFF_BITS(ssr, 408 - 384, 16);
-                       et = UNSTUFF_BITS(ssr, 402 - 384, 6);
+                       es = UNSTUFF_BITS(card->raw_ssr, 408 - 384, 16);
+                       et = UNSTUFF_BITS(card->raw_ssr, 402 - 384, 6);
                        if (es && et) {
-                               eo = UNSTUFF_BITS(ssr, 400 - 384, 2);
+                               eo = UNSTUFF_BITS(card->raw_ssr, 400 - 384, 2);
                                card->ssr.erase_timeout = (et * 1000) / es;
                                card->ssr.erase_offset = eo * 1000;
                        }
@@ -267,9 +260,8 @@ static int mmc_read_ssr(struct mmc_card *card)
                                mmc_hostname(card->host));
                }
        }
-out:
-       kfree(ssr);
-       return err;
+
+       return 0;
 }
 
 /*
@@ -666,6 +658,14 @@ MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
 MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
        card->raw_csd[2], card->raw_csd[3]);
 MMC_DEV_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
+MMC_DEV_ATTR(ssr,
+       "%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x\n",
+               card->raw_ssr[0], card->raw_ssr[1], card->raw_ssr[2],
+               card->raw_ssr[3], card->raw_ssr[4], card->raw_ssr[5],
+               card->raw_ssr[6], card->raw_ssr[7], card->raw_ssr[8],
+               card->raw_ssr[9], card->raw_ssr[10], card->raw_ssr[11],
+               card->raw_ssr[12], card->raw_ssr[13], card->raw_ssr[14],
+               card->raw_ssr[15]);
 MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
 MMC_DEV_ATTR(erase_size, "%u\n", card->erase_size << 9);
 MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9);
@@ -698,6 +698,7 @@ static struct attribute *sd_std_attrs[] = {
        &dev_attr_cid.attr,
        &dev_attr_csd.attr,
        &dev_attr_scr.attr,
+       &dev_attr_ssr.attr,
        &dev_attr_date.attr,
        &dev_attr_erase_size.attr,
        &dev_attr_preferred_erase_size.attr,
index d8673ca968ba2d65fb3da39680583ca5152641e4..73fad83acbcb6a157587180516f9ffe7c61eb7d7 100644 (file)
@@ -292,6 +292,7 @@ struct mmc_card {
        u32                     raw_cid[4];     /* raw card CID */
        u32                     raw_csd[4];     /* raw card CSD */
        u32                     raw_scr[2];     /* raw card SCR */
+       u32                     raw_ssr[16];    /* raw card SSR */
        struct mmc_cid          cid;            /* card identification */
        struct mmc_csd          csd;            /* card specific */
        struct mmc_ext_csd      ext_csd;        /* mmc v4 extended card specific */