mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-17 18:36:00 +00:00
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>
This commit is contained in:
parent
c2d8d4954e
commit
449f34a340
@ -50,6 +50,7 @@
|
||||
#include <linux/mmc/sd.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/unaligned.h>
|
||||
|
||||
#include "queue.h"
|
||||
#include "block.h"
|
||||
@ -993,11 +994,10 @@ static int mmc_sd_num_wr_blocks(struct mmc_card *card, u32 *written_blocks)
|
||||
int err;
|
||||
u32 result;
|
||||
__be32 *blocks;
|
||||
|
||||
u8 resp_sz = mmc_card_ult_capacity(card) ? 8 : 4;
|
||||
struct mmc_request mrq = {};
|
||||
struct mmc_command cmd = {};
|
||||
struct mmc_data data = {};
|
||||
|
||||
struct scatterlist sg;
|
||||
|
||||
err = mmc_app_cmd(card->host, card);
|
||||
@ -1008,7 +1008,7 @@ static int mmc_sd_num_wr_blocks(struct mmc_card *card, u32 *written_blocks)
|
||||
cmd.arg = 0;
|
||||
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
|
||||
|
||||
data.blksz = 4;
|
||||
data.blksz = resp_sz;
|
||||
data.blocks = 1;
|
||||
data.flags = MMC_DATA_READ;
|
||||
data.sg = &sg;
|
||||
@ -1018,15 +1018,27 @@ static int mmc_sd_num_wr_blocks(struct mmc_card *card, u32 *written_blocks)
|
||||
mrq.cmd = &cmd;
|
||||
mrq.data = &data;
|
||||
|
||||
blocks = kmalloc(4, GFP_KERNEL);
|
||||
blocks = kmalloc(resp_sz, GFP_KERNEL);
|
||||
if (!blocks)
|
||||
return -ENOMEM;
|
||||
|
||||
sg_init_one(&sg, blocks, 4);
|
||||
sg_init_one(&sg, blocks, resp_sz);
|
||||
|
||||
mmc_wait_for_req(card->host, &mrq);
|
||||
|
||||
result = ntohl(*blocks);
|
||||
if (mmc_card_ult_capacity(card)) {
|
||||
/*
|
||||
* Normally, ACMD22 returns the number of written sectors as
|
||||
* u32. SDUC, however, returns it as u64. This is not a
|
||||
* superfluous requirement, because SDUC writes may exceed 2TB.
|
||||
* For Linux mmc however, the previously write operation could
|
||||
* not be more than the block layer limits, thus just make room
|
||||
* for a u64 and cast the response back to u32.
|
||||
*/
|
||||
result = clamp_val(get_unaligned_be64(blocks), 0, UINT_MAX);
|
||||
} else {
|
||||
result = ntohl(*blocks);
|
||||
}
|
||||
kfree(blocks);
|
||||
|
||||
if (cmd.error || data.error)
|
||||
|
Loading…
x
Reference in New Issue
Block a user