diff options
author | litchipi | 2021-06-15 08:53:06 +0000 |
---|---|---|
committer | Peng Fan | 2021-07-30 17:12:15 +0800 |
commit | a9f7be509af90fa5f2c308867ad3b0bd48532c6e (patch) | |
tree | 25a6adaf951e33440574d5b1c33badc76700d790 /drivers | |
parent | 15f7e0dc01d8a851fb1bfbf0e47eab5b67ed26b3 (diff) |
mmc: rpmb: Fix driver routing memory alignment with tmp buffer
Fix mmc_rpmb_route_frames() implementation to comply with most MMC
drivers that expect some alignment of MMC data frames in memory.
When called from drivers/tee/optee/rpmb.c, the address passed is not
aligned properly. OP-TEE OS inserts a 6-byte header before a raw RPMB
frame which makes RPMB data buffer not 32bit aligned. To prevent breaking
ABI with OPTEE-OS RPC memrefs, allocate a temporary buffer to copy the
data into an aligned memory.
Many RPMB drivers implicitly expect 32bit alignment of the eMMC frame
including arm_pl180_mmci.c, sandbox_mmc.c and stm32_sdmmc2.c
Signed-off-by: Timothée Cercueil <timothee.cercueil@st.com>
Signed-off-by: Timothée Cercueil <litchi.pi@protonmail.com>
Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/rpmb.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/drivers/mmc/rpmb.c b/drivers/mmc/rpmb.c index ea7e506666b..b68d98573c9 100644 --- a/drivers/mmc/rpmb.c +++ b/drivers/mmc/rpmb.c @@ -480,10 +480,24 @@ int mmc_rpmb_route_frames(struct mmc *mmc, void *req, unsigned long reqlen, * and possibly just delay an eventual error which will be harder * to track down. */ + void *rpmb_data = NULL; + int ret; if (reqlen % sizeof(struct s_rpmb) || rsplen % sizeof(struct s_rpmb)) return -EINVAL; - return rpmb_route_frames(mmc, req, reqlen / sizeof(struct s_rpmb), - rsp, rsplen / sizeof(struct s_rpmb)); + if (!IS_ALIGNED((uintptr_t)req, ARCH_DMA_MINALIGN)) { + /* Memory alignment is required by MMC driver */ + rpmb_data = malloc(reqlen); + if (!rpmb_data) + return -ENOMEM; + + memcpy(rpmb_data, req, reqlen); + req = rpmb_data; + } + + ret = rpmb_route_frames(mmc, req, reqlen / sizeof(struct s_rpmb), + rsp, rsplen / sizeof(struct s_rpmb)); + free(rpmb_data); + return ret; } |