Chris,

Just tested the mod on brownstone.  Works.

Philip

On May 24, 2011, at 6:14 PM, Philip Rakity wrote:

> 
> resend 
> 
> Note:  I cannot test test for a few days.  Following Chris
> suggestion posting to list.
> 
> version 2
> ---
> return -EINVAL when compare of ext_csd_fails
> combine two compare routines into one per suggestion
> from Chris.
> 
> ---
> version 1
> 
> CMD19 -- The offical way to validate bus widths from the
> JEDEC spec does not work on all platforms.  Some platforms
> that use PCI/PCIe to connect their SD controllers are known
> to fail.
> 
> If the quirk MMC_BUS_WIDTH_TEST is not defined we try
> to figure out the bus width by reading the ext_csd at different
> bus widths and compare this against the ext_csd read in 1 bit
> mode.  If no ext_csd is available we default to 1 bit operations.
> 
> Code has been tested on mmp2 against 8 bit eMMC and Transcend 2GB
> card that is known to not work in 4 bit mode.  The physical
> pins on the card are not present to support 4 bit operation.
> 
> Signed-off-by: Philip Rakity <[email protected]>
> ---
> drivers/mmc/core/mmc.c |  113 +++++++++++++++++++++++++++++++++++++++++++----
> 1 files changed, 103 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index baab027..6db91d6 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -174,14 +174,17 @@ static int mmc_decode_csd(struct mmc_card *card)
> }
> 
> /*
> - * Read and decode extended CSD.
> + * Read extended CSD.
>  */
> -static int mmc_read_ext_csd(struct mmc_card *card)
> +static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)
> {
>       int err;
>       u8 *ext_csd;
> 
>       BUG_ON(!card);
> +     BUG_ON(!new_ext_csd);
> +
> +     *new_ext_csd = NULL;
> 
>       if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
>               return 0;
> @@ -199,12 +202,15 @@ static int mmc_read_ext_csd(struct mmc_card *card)
> 
>       err = mmc_send_ext_csd(card, ext_csd);
>       if (err) {
> +             kfree(ext_csd);
> +             *new_ext_csd = NULL;
> +
>               /* If the host or the card can't do the switch,
>                * fail more gracefully. */
>               if ((err != -EINVAL)
>                && (err != -ENOSYS)
>                && (err != -EFAULT))
> -                     goto out;
> +                     return err;
> 
>               /*
>                * High capacity cards should have this "magic" size
> @@ -222,9 +228,23 @@ static int mmc_read_ext_csd(struct mmc_card *card)
>                               mmc_hostname(card->host));
>                       err = 0;
>               }
> +     } else
> +             *new_ext_csd = ext_csd;
> 
> -             goto out;
> -     }
> +     return err;
> +}
> +
> +/*
> + * Decode extended CSD.
> + */
> +static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
> +{
> +     int err = 0;
> +
> +     BUG_ON(!card);
> +
> +     if (!ext_csd)
> +             return 0;
> 
>       /* Version is coded in the CSD_STRUCTURE byte in the EXT_CSD register */
>       if (card->csd.structure == 3) {
> @@ -372,8 +392,70 @@ static int mmc_read_ext_csd(struct mmc_card *card)
>               card->erased_byte = 0x0;
> 
> out:
> +     return err;
> +}
> +
> +static inline void mmc_free_ext_csd(u8 *ext_csd)
> +{
>       kfree(ext_csd);
> +}
> +
> 
> +static int mmc_compare_ext_csds(struct mmc_card *card, u8 *ext_csd,
> +                     unsigned bus_width)
> +{
> +     u8 *bw_ext_csd;
> +     int err;
> +
> +     err = mmc_get_ext_csd(card, &bw_ext_csd);
> +     if (err)
> +             return err;
> +
> +     if ((ext_csd == NULL || bw_ext_csd == NULL)) {
> +             if (bus_width != MMC_BUS_WIDTH_1)
> +                     err = -EINVAL;
> +             goto out;
> +     }
> +
> +     if (bus_width == MMC_BUS_WIDTH_1)
> +             goto out;
> +
> +     /* only compare read only fields */
> +
> +     err =   (!(ext_csd[EXT_CSD_PARTITION_SUPPORT] ==
> +                     bw_ext_csd[EXT_CSD_PARTITION_SUPPORT]) &&
> +             (ext_csd[EXT_CSD_ERASED_MEM_CONT] ==
> +                     bw_ext_csd[EXT_CSD_ERASED_MEM_CONT]) &&
> +             (ext_csd[EXT_CSD_REV] ==
> +                     bw_ext_csd[EXT_CSD_REV]) &&
> +             (ext_csd[EXT_CSD_STRUCTURE] ==
> +                     bw_ext_csd[EXT_CSD_STRUCTURE]) &&
> +             (ext_csd[EXT_CSD_CARD_TYPE] ==
> +                     bw_ext_csd[EXT_CSD_CARD_TYPE]) &&
> +             (ext_csd[EXT_CSD_S_A_TIMEOUT] ==
> +                     bw_ext_csd[EXT_CSD_S_A_TIMEOUT]) &&
> +             (ext_csd[EXT_CSD_HC_WP_GRP_SIZE] ==
> +                     bw_ext_csd[EXT_CSD_HC_WP_GRP_SIZE]) &&
> +             (ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT] ==
> +                     bw_ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT]) &&
> +             (ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] ==
> +                     bw_ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]) &&
> +             (ext_csd[EXT_CSD_SEC_TRIM_MULT] ==
> +                     bw_ext_csd[EXT_CSD_SEC_TRIM_MULT]) &&
> +             (ext_csd[EXT_CSD_SEC_ERASE_MULT] ==
> +                     bw_ext_csd[EXT_CSD_SEC_ERASE_MULT]) &&
> +             (ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT] ==
> +                     bw_ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]) &&
> +             (ext_csd[EXT_CSD_TRIM_MULT] ==
> +                     bw_ext_csd[EXT_CSD_TRIM_MULT]) &&
> +             memcmp(&ext_csd[EXT_CSD_SEC_CNT],
> +                     &bw_ext_csd[EXT_CSD_SEC_CNT],
> +                     4) != 0);
> +     if (err)
> +             err = -EINVAL;
> +
> +out:
> +     mmc_free_ext_csd(bw_ext_csd);
>       return err;
> }
> 
> @@ -438,6 +520,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
>       u32 cid[4];
>       unsigned int max_dtr;
>       u32 rocr;
> +     u8 *ext_csd = NULL;
> 
>       BUG_ON(!host);
>       WARN_ON(!host->claimed);
> @@ -536,7 +619,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
>               /*
>                * Fetch and process extended CSD.
>                */
> -             err = mmc_read_ext_csd(card);
> +
> +             err = mmc_get_ext_csd(card, &ext_csd);
> +             if (err)
> +                     goto free_card;
> +             err = mmc_read_ext_csd(card, ext_csd);
>               if (err)
>                       goto free_card;
> 
> @@ -676,14 +763,18 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
>                                        0);
>                       if (!err) {
>                               mmc_set_bus_width(card->host, bus_width);
> +
>                               /*
>                                * If controller can't handle bus width test,
> -                              * use the highest bus width to maintain
> -                              * compatibility with previous MMC behavior.
> +                              * compare ext_csd previously read in 1 bit mode
> +                              * against ext_csd at new bus width
>                                */
>                               if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST))
> -                                     break;
> -                             err = mmc_bus_test(card, bus_width);
> +                                     err = mmc_compare_ext_csds(card,
> +                                             ext_csd,
> +                                             bus_width);
> +                             else
> +                                     err = mmc_bus_test(card, bus_width);
>                               if (!err)
>                                       break;
>                       }
> @@ -730,12 +821,14 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
>       if (!oldcard)
>               host->card = card;
> 
> +     mmc_free_ext_csd(ext_csd);
>       return 0;
> 
> free_card:
>       if (!oldcard)
>               mmc_remove_card(card);
> err:
> +     mmc_free_ext_csd(ext_csd);
> 
>       return err;
> }
> -- 
> 1.7.0.4
> 
> 
> 
> On May 23, 2011, at 9:42 PM, Chris Ball wrote:
> 
>> Hi Philip,
>> 
>> On Sun, May 22 2011, Philip Rakity wrote:
>>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
>>> index baab027..6db91d6 100644
>>> --- a/drivers/mmc/core/mmc.c
>>> +++ b/drivers/mmc/core/mmc.c
>>> @@ -174,14 +174,17 @@ static int mmc_decode_csd(struct mmc_card *card)
>>> }
>>> 
>>> /*
>>> - * Read and decode extended CSD.
>>> + * Read extended CSD.
>>> */
>>> -static int mmc_read_ext_csd(struct mmc_card *card)
>>> +static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
>> 
>> This one doesn't work -- you're missing the half of the patch that hooks
>> up the rest of mmc.c to the new code, which was in v1.  As-is, we get:
>> 
>> drivers/mmc/core/mmc.c: In function ‘mmc_init_card’:
>> drivers/mmc/core/mmc.c:621:3: error: too few arguments to function 
>> ‘mmc_read_ext_csd’
>> drivers/mmc/core/mmc.c:240:12: note: declared here
>> drivers/mmc/core/mmc.c: At top level:
>> drivers/mmc/core/mmc.c:404:12: warning: ‘mmc_compare_ext_csds’ defined but 
>> not used [-Wunused-function]
>> 
>> - Chris.
>> -- 
>> Chris Ball   <[email protected]>   <http://printf.net/>
>> One Laptop Per Child
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>> the body of a message to [email protected]
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to