Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mmc: core: Adjust ACMD22 to SDUC

ACMD22 is used to verify the previously write operation. Normally, it
returns the number of written sectors as u32. SDUC, however, returns it
as u64. This is not a superfluous requirement, because SDUC writes may
exceeds 2TB. For Linux mmc however, the previously write operation
could not be more than the block layer limits, thus we make room for a
u64 and cast the returning value to u32.

Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Avri Altman <avri.altman@wdc.com>
Link: https://lore.kernel.org/r/20241006051148.160278-8-avri.altman@wdc.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
[Stephen Rothwell: Fix build error when moving to new rc from Linus's tree]
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>

authored by

Avri Altman and committed by
Ulf Hansson
449f34a3 c2d8d495

+18 -6
+18 -6
drivers/mmc/core/block.c
··· 50 50 #include <linux/mmc/sd.h> 51 51 52 52 #include <linux/uaccess.h> 53 + #include <linux/unaligned.h> 53 54 54 55 #include "queue.h" 55 56 #include "block.h" ··· 994 993 int err; 995 994 u32 result; 996 995 __be32 *blocks; 997 - 996 + u8 resp_sz = mmc_card_ult_capacity(card) ? 8 : 4; 998 997 struct mmc_request mrq = {}; 999 998 struct mmc_command cmd = {}; 1000 999 struct mmc_data data = {}; 1001 - 1002 1000 struct scatterlist sg; 1003 1001 1004 1002 err = mmc_app_cmd(card->host, card); ··· 1008 1008 cmd.arg = 0; 1009 1009 cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; 1010 1010 1011 - data.blksz = 4; 1011 + data.blksz = resp_sz; 1012 1012 data.blocks = 1; 1013 1013 data.flags = MMC_DATA_READ; 1014 1014 data.sg = &sg; ··· 1018 1018 mrq.cmd = &cmd; 1019 1019 mrq.data = &data; 1020 1020 1021 - blocks = kmalloc(4, GFP_KERNEL); 1021 + blocks = kmalloc(resp_sz, GFP_KERNEL); 1022 1022 if (!blocks) 1023 1023 return -ENOMEM; 1024 1024 1025 - sg_init_one(&sg, blocks, 4); 1025 + sg_init_one(&sg, blocks, resp_sz); 1026 1026 1027 1027 mmc_wait_for_req(card->host, &mrq); 1028 1028 1029 - result = ntohl(*blocks); 1029 + if (mmc_card_ult_capacity(card)) { 1030 + /* 1031 + * Normally, ACMD22 returns the number of written sectors as 1032 + * u32. SDUC, however, returns it as u64. This is not a 1033 + * superfluous requirement, because SDUC writes may exceed 2TB. 1034 + * For Linux mmc however, the previously write operation could 1035 + * not be more than the block layer limits, thus just make room 1036 + * for a u64 and cast the response back to u32. 1037 + */ 1038 + result = clamp_val(get_unaligned_be64(blocks), 0, UINT_MAX); 1039 + } else { 1040 + result = ntohl(*blocks); 1041 + } 1030 1042 kfree(blocks); 1031 1043 1032 1044 if (cmd.error || data.error)