diff --git a/drivers/ufs/Kconfig b/drivers/ufs/Kconfig index f662e7ce71f1..b62c00e7ff06 100644 --- a/drivers/ufs/Kconfig +++ b/drivers/ufs/Kconfig @@ -7,6 +7,7 @@ menuconfig SCSI_UFSHCD tristate "Universal Flash Storage Controller" depends on SCSI && SCSI_DMA depends on RPMB || !RPMB + select CRYPTO_LIB_BLAKE2B if RPMB select PM_DEVFREQ select DEVFREQ_GOV_SIMPLE_ONDEMAND select NLS diff --git a/drivers/ufs/core/ufs-rpmb.c b/drivers/ufs/core/ufs-rpmb.c index aa925cbb07e8..783ecfc7581d 100644 --- a/drivers/ufs/core/ufs-rpmb.c +++ b/drivers/ufs/core/ufs-rpmb.c @@ -10,6 +10,7 @@ * Can Guo */ +#include #include #include #include @@ -21,6 +22,8 @@ #include #include "ufshcd-priv.h" +#define UFS_RPMB_ID_LEN 16 /* Match eMMC CID Length */ +#define UFS_RPMB_UA_RETRIES 3 /* Retries for the power-on UNIT ATTENTION */ #define UFS_RPMB_SEC_PROTOCOL 0xEC /* JEDEC UFS application */ #define UFS_RPMB_SEC_PROTOCOL_ID 0x01 /* JEDEC UFS RPMB protocol ID, CDB byte3 */ @@ -40,6 +43,22 @@ struct ufs_rpmb_dev { static int ufs_sec_submit(struct ufs_hba *hba, u16 spsp, void *buffer, size_t len, bool send) { struct scsi_device *sdev = hba->ufs_rpmb_wlun; + struct scsi_failure failure_defs[] = { + { + .sense = UNIT_ATTENTION, + .asc = 0x29, /* power on, reset, or bus device reset occurred */ + .ascq = SCMD_FAILURE_ASCQ_ANY, + .allowed = UFS_RPMB_UA_RETRIES, + .result = SAM_STAT_CHECK_CONDITION, + }, + {} + }; + struct scsi_failures failures = { + .failure_definitions = failure_defs, + }; + const struct scsi_exec_args exec_args = { + .failures = &failures, + }; u8 cdb[12] = { }; cdb[0] = send ? SECURITY_PROTOCOL_OUT : SECURITY_PROTOCOL_IN; @@ -48,7 +67,8 @@ static int ufs_sec_submit(struct ufs_hba *hba, u16 spsp, void *buffer, size_t le put_unaligned_be32(len, &cdb[6]); return scsi_execute_cmd(sdev, cdb, send ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, - buffer, len, /*timeout=*/30 * HZ, 0, NULL); + buffer, len, /*timeout=*/30 * HZ, /*retries=*/0, + &exec_args); } /* UFS RPMB route frames implementation */ @@ -139,6 +159,7 @@ static void ufs_rpmb_device_release(struct device *dev) int ufs_rpmb_probe(struct ufs_hba *hba) { struct ufs_rpmb_dev *ufs_rpmb, *it, *tmp; + u8 dev_id[UFS_RPMB_ID_LEN]; struct rpmb_dev *rdev; char *cid = NULL; int region; @@ -197,8 +218,10 @@ int ufs_rpmb_probe(struct ufs_hba *hba) goto err_out; } - descr.dev_id = cid; - descr.dev_id_len = strlen(cid); + blake2b(NULL, 0, cid, strlen(cid), dev_id, UFS_RPMB_ID_LEN); + + descr.dev_id = dev_id; + descr.dev_id_len = UFS_RPMB_ID_LEN; descr.capacity = cap; /* Register RPMB device */