diff mbox series

mmc: sd: Fix incorrect capacity calculation for SDHC/SDXC/SDUC cards

Message ID 20250128084226.15873-1-sooraj20636@gmail.com (mailing list archive)
State New
Headers show
Series mmc: sd: Fix incorrect capacity calculation for SDHC/SDXC/SDUC cards | expand

Commit Message

sooraj Jan. 28, 2025, 8:42 a.m. UTC
The capacity calculation for high-capacity SD cards (SDHC/SDXC/SDUC) used
an incorrect bit shift (10 bits instead of 19 or 22), leading to severely
underestimated storage capacities.

- For SDHC/SDXC (CSD structure version 1), the capacity is defined as:
  `(C_SIZE + 1) * 512 KiB` (SD Physical Layer Spec v3.01, section 5.3.3).
  This requires a left shift by 19 bits (2^19 = 512 KiB).

- For SDUC (CSD structure version 2), the capacity is:
  `(C_SIZE + 1) * 4096 KiB` (SD Physical Layer Spec v7.10, section 5.3.3),
  requiring a left shift by 22 bits (2^22 = 4096 KiB).

Update the shifts to 19 and 22 bits for versions 1 and 2 respectively,
ensuring accurate capacity reporting. This resolves issues where cards
(e.g., 64GB) were incorrectly identified as 1-4GB.

Signed-off-by: sooraj <sooraj20636@gmail.com>
---
 drivers/mmc/core/sd.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

Comments

Avri Altman Jan. 28, 2025, 8:16 a.m. UTC | #1
> The capacity calculation for high-capacity SD cards (SDHC/SDXC/SDUC) used
> an incorrect bit shift (10 bits instead of 19 or 22), leading to severely
> underestimated storage capacities.
> 
> - For SDHC/SDXC (CSD structure version 1), the capacity is defined as:
>   `(C_SIZE + 1) * 512 KiB` (SD Physical Layer Spec v3.01, section 5.3.3).
>   This requires a left shift by 19 bits (2^19 = 512 KiB).
> 
> - For SDUC (CSD structure version 2), the capacity is:
>   `(C_SIZE + 1) * 4096 KiB` (SD Physical Layer Spec v7.10, section 5.3.3),
>   requiring a left shift by 22 bits (2^22 = 4096 KiB).
> 
> Update the shifts to 19 and 22 bits for versions 1 and 2 respectively, ensuring
> accurate capacity reporting. This resolves issues where cards (e.g., 64GB)
> were incorrectly identified as 1-4GB.
> 
> Signed-off-by: sooraj <sooraj20636@gmail.com>
Please share the kernel info of your sd insert flow, e.g. something in the form of:
[ 5791.041876] mmc0: new ultra high speed SDR104 SDUC card at address d555
[ 5791.041916] mmcblk mmc0:d555: calling add_quirk_sd
[ 5791.042108] mmc0: calculated max. discard sectors 1957888 for timeout 60000 ms
[ 5791.042127] mmcblk0: mmc0:d555 SR04T 3.72 TiB

Also what your /sys/block/mmcblk<x>/size say?  where is <x> is your sd card block device.

Thanks,
Avri

> ---
>  drivers/mmc/core/sd.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index
> cc757b850e79..b60de859e978 100644
> --- a/drivers/mmc/core/sd.c
> +++ b/drivers/mmc/core/sd.c
> @@ -172,7 +172,11 @@ static int mmc_decode_csd(struct mmc_card *card,
> bool is_sduc)
>                 else if (csd->c_size >= 0xFFFF)
>                         mmc_card_set_ext_capacity(card);
> 
> -               csd->capacity     = (1 + (typeof(sector_t))m) << 10;
> +               /* Correct the capacity calculation based on CSD structure version
> */
> +               if (csd_struct == 1)
> +                       csd->capacity = (1 + (typeof(sector_t))m) << 19; /* SDHC/SDXC:
> (C_SIZE + 1) * 512KB */
> +               else
> +                       csd->capacity = (1 + (typeof(sector_t))m) << 22;
> + /* SDUC: (C_SIZE + 1) * 4096KB */
> 
>                 csd->read_blkbits = 9;
>                 csd->read_partial = 0;
> --
> 2.45.2
>
diff mbox series

Patch

diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index cc757b850e79..b60de859e978 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -172,7 +172,11 @@  static int mmc_decode_csd(struct mmc_card *card, bool is_sduc)
 		else if (csd->c_size >= 0xFFFF)
 			mmc_card_set_ext_capacity(card);
 
-		csd->capacity     = (1 + (typeof(sector_t))m) << 10;
+		/* Correct the capacity calculation based on CSD structure version */
+		if (csd_struct == 1)
+			csd->capacity = (1 + (typeof(sector_t))m) << 19; /* SDHC/SDXC: (C_SIZE + 1) * 512KB */
+		else
+			csd->capacity = (1 + (typeof(sector_t))m) << 22; /* SDUC: (C_SIZE + 1) * 4096KB */
 
 		csd->read_blkbits = 9;
 		csd->read_partial = 0;