summaryrefslogtreecommitdiff
path: root/drivers/scsi/ufs/ufshcd.c
diff options
context:
space:
mode:
authorGilad Broner <gbroner@codeaurora.org>2015-11-02 16:01:36 +0200
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:00:47 -0700
commit1057b4404c65092906d9925a027c0cf060423a67 (patch)
treeff8153feb4c47da24622bc4a31e82ae370137d23 /drivers/scsi/ufs/ufshcd.c
parentb18a536dcd0a7189af64de300f0ed512ef79bb06 (diff)
scsi: ufs: add crypto related operations
UFS specification has been updated and crypto operations were added. Update the UFS driver code with the new registers and sequences to facilitate future usage. Change-Id: I020870f628977c3ebad6cc0afaef3cb1cdd15063 Signed-off-by: Gilad Broner <gbroner@codeaurora.org>
Diffstat (limited to 'drivers/scsi/ufs/ufshcd.c')
-rw-r--r--drivers/scsi/ufs/ufshcd.c60
1 files changed, 55 insertions, 5 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 6932a81bb4fa..5d9fdaeaa5ec 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -737,6 +737,9 @@ static inline u32 ufshcd_get_intr_mask(struct ufs_hba *hba)
intr_mask = INTERRUPT_MASK_ALL_VER_21;
}
+ if (!ufshcd_is_crypto_supported(hba))
+ intr_mask &= ~CRYPTO_ENGINE_FATAL_ERROR;
+
return intr_mask;
}
@@ -999,7 +1002,11 @@ static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba)
*/
static inline void ufshcd_hba_start(struct ufs_hba *hba)
{
- ufshcd_writel(hba, CONTROLLER_ENABLE, REG_CONTROLLER_ENABLE);
+ u32 val = CONTROLLER_ENABLE;
+
+ if (ufshcd_is_crypto_supported(hba))
+ val |= CRYPTO_GENERAL_ENABLE;
+ ufshcd_writel(hba, val, REG_CONTROLLER_ENABLE);
}
/**
@@ -2264,15 +2271,52 @@ static void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs)
ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
}
+static int ufshcd_prepare_crypto_utrd(struct ufs_hba *hba,
+ struct ufshcd_lrb *lrbp)
+{
+ struct utp_transfer_req_desc *req_desc = lrbp->utr_descriptor_ptr;
+ u8 cc_index = 0;
+ bool enable = false;
+ u64 dun = 0;
+ int ret;
+
+ /*
+ * Call vendor specific code to get crypto info for this request:
+ * enable, crypto config. index, DUN.
+ * If bypass is set, don't bother setting the other fields.
+ */
+ ret = ufshcd_vops_crypto_req_setup(hba, lrbp, &cc_index, &enable, &dun);
+ if (ret) {
+ dev_err(hba->dev,
+ "%s: failed to setup crypto request (%d)\n",
+ __func__, ret);
+ return ret;
+ }
+
+ if (!enable)
+ goto out;
+
+ req_desc->header.dword_0 |= cc_index | UTRD_CRYPTO_ENABLE;
+ if (lrbp->cmd->request && lrbp->cmd->request->bio)
+ dun = lrbp->cmd->request->bio->bi_iter.bi_sector;
+
+ req_desc->header.dword_1 = (u32)(dun & 0xFFFFFFFF);
+ req_desc->header.dword_3 = (u32)((dun >> 32) & 0xFFFFFFFF);
+out:
+ return 0;
+}
+
/**
* ufshcd_prepare_req_desc_hdr() - Fills the requests header
* descriptor according to request
+ * @hba: per adapter instance
* @lrbp: pointer to local reference block
* @upiu_flags: flags required in the header
* @cmd_dir: requests data direction
*/
-static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp,
- u32 *upiu_flags, enum dma_data_direction cmd_dir)
+static void ufshcd_prepare_req_desc_hdr(struct ufs_hba *hba,
+ struct ufshcd_lrb *lrbp, u32 *upiu_flags,
+ enum dma_data_direction cmd_dir)
{
struct utp_transfer_req_desc *req_desc = lrbp->utr_descriptor_ptr;
u32 data_direction;
@@ -2309,6 +2353,9 @@ static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp,
req_desc->header.dword_3 = 0;
req_desc->prd_table_length = 0;
+
+ if (ufshcd_is_crypto_supported(hba))
+ ufshcd_prepare_crypto_utrd(hba, lrbp);
}
/**
@@ -2411,7 +2458,7 @@ static int ufshcd_compose_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
switch (lrbp->command_type) {
case UTP_CMD_TYPE_SCSI:
if (likely(lrbp->cmd)) {
- ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags,
+ ufshcd_prepare_req_desc_hdr(hba, lrbp, &upiu_flags,
lrbp->cmd->sc_data_direction);
ufshcd_prepare_utp_scsi_cmd_upiu(lrbp, upiu_flags);
} else {
@@ -2419,7 +2466,7 @@ static int ufshcd_compose_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
}
break;
case UTP_CMD_TYPE_DEV_MANAGE:
- ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, DMA_NONE);
+ ufshcd_prepare_req_desc_hdr(hba, lrbp, &upiu_flags, DMA_NONE);
if (hba->dev_cmd.type == DEV_CMD_TYPE_QUERY)
ufshcd_prepare_utp_query_req_upiu(
hba, lrbp, upiu_flags);
@@ -4809,6 +4856,9 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
case OCS_MISMATCH_RESP_UPIU_SIZE:
case OCS_PEER_COMM_FAILURE:
case OCS_FATAL_ERROR:
+ case OCS_DEVICE_FATAL_ERROR:
+ case OCS_INVALID_CRYPTO_CONFIG:
+ case OCS_GENERAL_CRYPTO_ERROR:
default:
result |= DID_ERROR << 16;
dev_err(hba->dev,