Re: [RFC][PATCH] mmc: core: Disable HPI for certain Hynix eMMC cards

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 10 June 2016 at 00:09, George G. Davis <george_davis@xxxxxxxxxx> wrote:
> From: Pratibhasagar V <pratibha@xxxxxxxxxxxxxx>
>
> Certain Hynix eMMC 4.41 cards might get broken when HPI feature is used
> and hence this patch disables the HPI feature for such buggy cards.
>
> As some of the other features like BKOPs/Cache/Sanitize are dependent on
> HPI feature, those features would also get disabled if HPI is disabled.
>
> Signed-off-by: Pratibhasagar V <pratibha@xxxxxxxxxxxxxx>
> Signed-off-by: Subhash Jadavani <subhashj@xxxxxxxxxxxxxx>
> [gdavis: Forward port and cleanup https://gitlab.com/k2wl/g2_kernel/commit/84af3731019921a28d595dbf6cbf00539706a42c]
> Signed-off-by: George G. Davis <george_davis@xxxxxxxxxx>

Thanks, applied for next!

Kind regards
Uffe

> ---
>  drivers/mmc/card/block.c  |  6 ------
>  drivers/mmc/core/mmc.c    | 23 ++++++++++++++++++++---
>  drivers/mmc/core/quirks.c |  2 ++
>  include/linux/mmc/card.h  | 35 ++++++++++++++++++++++++++++++-----
>  4 files changed, 52 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
> index e62fde3..bb6e525 100644
> --- a/drivers/mmc/card/block.c
> +++ b/drivers/mmc/card/block.c
> @@ -2497,12 +2497,6 @@ force_ro_fail:
>         return ret;
>  }
>
> -#define CID_MANFID_SANDISK     0x2
> -#define CID_MANFID_TOSHIBA     0x11
> -#define CID_MANFID_MICRON      0x13
> -#define CID_MANFID_SAMSUNG     0x15
> -#define CID_MANFID_KINGSTON    0x70
> -
>  static const struct mmc_fixup blk_fixups[] =
>  {
>         MMC_FIXUP("SEM02G", CID_MANFID_SANDISK, 0x100, add_quirk,
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index 5d438ad..aede5a5 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -45,6 +45,17 @@ static const unsigned int tacc_mant[] = {
>         35,     40,     45,     50,     55,     60,     70,     80,
>  };
>
> +static const struct mmc_fixup mmc_ext_csd_fixups[] = {
> +       /*
> +        * Certain Hynix eMMC 4.41 cards might get broken when HPI feature
> +        * is used so disable the HPI feature for such buggy cards.
> +        */
> +       MMC_FIXUP_EXT_CSD_REV(CID_NAME_ANY, CID_MANFID_HYNIX,
> +                             0x014a, add_quirk, MMC_QUIRK_BROKEN_HPI, 5),
> +
> +       END_FIXUP
> +};
> +
>  #define UNSTUFF_BITS(resp,start,size)                                  \
>         ({                                                              \
>                 const int __size = size;                                \
> @@ -370,6 +381,9 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
>          */
>         card->ext_csd.rev = ext_csd[EXT_CSD_REV];
>
> +       /* fixup device after ext_csd revision field is updated */
> +       mmc_fixup_device(card, mmc_ext_csd_fixups);
> +
>         card->ext_csd.raw_sectors[0] = ext_csd[EXT_CSD_SEC_CNT + 0];
>         card->ext_csd.raw_sectors[1] = ext_csd[EXT_CSD_SEC_CNT + 1];
>         card->ext_csd.raw_sectors[2] = ext_csd[EXT_CSD_SEC_CNT + 2];
> @@ -500,7 +514,8 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
>                         card->cid.year += 16;
>
>                 /* check whether the eMMC card supports BKOPS */
> -               if (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) {
> +               if (!mmc_card_broken_hpi(card) &&
> +                   ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) {
>                         card->ext_csd.bkops = 1;
>                         card->ext_csd.man_bkops_en =
>                                         (ext_csd[EXT_CSD_BKOPS_EN] &
> @@ -513,7 +528,8 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
>                 }
>
>                 /* check whether the eMMC card supports HPI */
> -               if (!broken_hpi && (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1)) {
> +               if (!mmc_card_broken_hpi(card) &&
> +                   !broken_hpi && (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1)) {
>                         card->ext_csd.hpi = 1;
>                         if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2)
>                                 card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION;
> @@ -1616,7 +1632,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
>          * If cache size is higher than 0, this indicates
>          * the existence of cache and it can be turned on.
>          */
> -       if (card->ext_csd.cache_size > 0) {
> +       if (!mmc_card_broken_hpi(card) &&
> +           card->ext_csd.cache_size > 0) {
>                 err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>                                 EXT_CSD_CACHE_CTRL, 1,
>                                 card->ext_csd.generic_cmd6_time);
> diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c
> index fad660b..ca9cade 100644
> --- a/drivers/mmc/core/quirks.c
> +++ b/drivers/mmc/core/quirks.c
> @@ -72,6 +72,8 @@ void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table)
>                      f->cis_vendor == (u16) SDIO_ANY_ID) &&
>                     (f->cis_device == card->cis.device ||
>                      f->cis_device == (u16) SDIO_ANY_ID) &&
> +                   (f->ext_csd_rev == EXT_CSD_REV_ANY ||
> +                    f->ext_csd_rev == card->ext_csd.rev) &&
>                     rev >= f->rev_start && rev <= f->rev_end) {
>                         dev_dbg(&card->dev, "calling %pf\n", f->vendor_fixup);
>                         f->vendor_fixup(card, f->data);
> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
> index eb0151b..5a2db5e 100644
> --- a/include/linux/mmc/card.h
> +++ b/include/linux/mmc/card.h
> @@ -279,6 +279,7 @@ struct mmc_card {
>  #define MMC_QUIRK_SEC_ERASE_TRIM_BROKEN (1<<10)        /* Skip secure for erase/trim */
>  #define MMC_QUIRK_BROKEN_IRQ_POLLING   (1<<11) /* Polling SDIO_CCCR_INTx could create a fake interrupt */
>  #define MMC_QUIRK_TRIM_BROKEN  (1<<12)         /* Skip trim */
> +#define MMC_QUIRK_BROKEN_HPI   (1<<13)         /* Disable broken HPI support */
>
>
>         unsigned int            erase_size;     /* erase size in sectors */
> @@ -353,6 +354,9 @@ struct mmc_fixup {
>         /* SDIO-specfic fields. You can use SDIO_ANY_ID here of course */
>         u16 cis_vendor, cis_device;
>
> +       /* for MMC cards */
> +       unsigned int ext_csd_rev;
> +
>         void (*vendor_fixup)(struct mmc_card *card, int data);
>         int data;
>  };
> @@ -361,11 +365,20 @@ struct mmc_fixup {
>  #define CID_OEMID_ANY ((unsigned short) -1)
>  #define CID_NAME_ANY (NULL)
>
> +#define EXT_CSD_REV_ANY (-1u)
> +
> +#define CID_MANFID_SANDISK      0x2
> +#define CID_MANFID_TOSHIBA      0x11
> +#define CID_MANFID_MICRON       0x13
> +#define CID_MANFID_SAMSUNG      0x15
> +#define CID_MANFID_KINGSTON     0x70
> +#define CID_MANFID_HYNIX       0x90
> +
>  #define END_FIXUP { NULL }
>
>  #define _FIXUP_EXT(_name, _manfid, _oemid, _rev_start, _rev_end,       \
>                    _cis_vendor, _cis_device,                            \
> -                  _fixup, _data)                                       \
> +                  _fixup, _data, _ext_csd_rev)                         \
>         {                                                  \
>                 .name = (_name),                           \
>                 .manfid = (_manfid),                       \
> @@ -376,23 +389,30 @@ struct mmc_fixup {
>                 .cis_device = (_cis_device),               \
>                 .vendor_fixup = (_fixup),                  \
>                 .data = (_data),                           \
> +               .ext_csd_rev = (_ext_csd_rev),             \
>          }
>
>  #define MMC_FIXUP_REV(_name, _manfid, _oemid, _rev_start, _rev_end,    \
> -                     _fixup, _data)                                    \
> +                     _fixup, _data, _ext_csd_rev)                      \
>         _FIXUP_EXT(_name, _manfid,                                      \
>                    _oemid, _rev_start, _rev_end,                        \
>                    SDIO_ANY_ID, SDIO_ANY_ID,                            \
> -                  _fixup, _data)                                       \
> +                  _fixup, _data, _ext_csd_rev)                         \
>
>  #define MMC_FIXUP(_name, _manfid, _oemid, _fixup, _data) \
> -       MMC_FIXUP_REV(_name, _manfid, _oemid, 0, -1ull, _fixup, _data)
> +       MMC_FIXUP_REV(_name, _manfid, _oemid, 0, -1ull, _fixup, _data,  \
> +                     EXT_CSD_REV_ANY)
> +
> +#define MMC_FIXUP_EXT_CSD_REV(_name, _manfid, _oemid, _fixup, _data,   \
> +                             _ext_csd_rev)                             \
> +       MMC_FIXUP_REV(_name, _manfid, _oemid, 0, -1ull, _fixup, _data,  \
> +                     _ext_csd_rev)
>
>  #define SDIO_FIXUP(_vendor, _device, _fixup, _data)                    \
>         _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_ANY,                        \
>                     CID_OEMID_ANY, 0, -1ull,                            \
>                    _vendor, _device,                                    \
> -                  _fixup, _data)                                       \
> +                  _fixup, _data, EXT_CSD_REV_ANY)                      \
>
>  #define cid_rev(hwrev, fwrev, year, month)     \
>         (((u64) hwrev) << 40 |                  \
> @@ -511,6 +531,11 @@ static inline int mmc_card_broken_irq_polling(const struct mmc_card *c)
>         return c->quirks & MMC_QUIRK_BROKEN_IRQ_POLLING;
>  }
>
> +static inline int mmc_card_broken_hpi(const struct mmc_card *c)
> +{
> +       return c->quirks & MMC_QUIRK_BROKEN_HPI;
> +}
> +
>  #define mmc_card_name(c)       ((c)->cid.prod_name)
>  #define mmc_card_id(c)         (dev_name(&(c)->dev))
>
> --
> 1.9.3
>
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux