summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Markovytch <andreym@codeaurora.org>2016-06-09 13:26:18 +0300
committerKyle Yan <kyan@codeaurora.org>2016-06-09 15:12:13 -0700
commit110aebe86786a784dc3941cbe58bc87984454a2c (patch)
tree74e939ea3f7e6fc1f932cd8578b7d19ca695f1d3
parenta15fd37785f482227381630477fba07522e60fc2 (diff)
scsi: ufs: ICE 3.0 changes
ICE 3.0 crypto sequences were changed, CTRL_INFO register no longer exists and doesn't need to be configured. The configuration is done via utrd. Change-Id: I5d69436ec59476fc5cd427458d79f8c99266f243 Signed-off-by: Andrey Markovytch <andreym@codeaurora.org>
-rw-r--r--drivers/scsi/ufs/ufs-qcom-ice.c39
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c3
-rw-r--r--drivers/scsi/ufs/ufshcd.c37
-rw-r--r--security/pfe/pfk.c11
-rw-r--r--security/pfe/pfk_kc.c1
5 files changed, 68 insertions, 23 deletions
diff --git a/drivers/scsi/ufs/ufs-qcom-ice.c b/drivers/scsi/ufs/ufs-qcom-ice.c
index 6d2a8f8cf3c1..1ba4f2bafba3 100644
--- a/drivers/scsi/ufs/ufs-qcom-ice.c
+++ b/drivers/scsi/ufs/ufs-qcom-ice.c
@@ -175,8 +175,6 @@ static void ufs_qcom_ice_cfg_work(struct work_struct *work)
if (!qcom_host->ice.vops->config_start || !qcom_host->req_pending)
return;
- memset(&ice_set, 0, sizeof(ice_set));
-
/*
* config_start is called again as previous attempt returned -EAGAIN,
* this call shall now take care of the necessary key setup.
@@ -260,9 +258,30 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host,
err = qcom_host->ice.vops->config_start(qcom_host->ice.pdev,
cmd->request, &ice_set, true);
if (err) {
- dev_err(qcom_host->hba->dev,
- "%s: error in ice_vops->config %d\n",
- __func__, err);
+ /*
+ * config_start() returns -EAGAIN when a key slot is
+ * available but still not configured. As configuration
+ * requires a non-atomic context, this means we should
+ * call the function again from the worker thread to do
+ * the configuration. For this request the error will
+ * propagate so it will be re-queued and until the
+ * configuration is is completed we block further
+ * request processing.
+ */
+ if (err == -EAGAIN) {
+ dev_dbg(qcom_host->hba->dev,
+ "%s: scheduling task for ice setup\n",
+ __func__);
+ qcom_host->req_pending = cmd->request;
+ if (schedule_work(&qcom_host->ice_cfg_work))
+ ufshcd_scsi_block_requests(
+ qcom_host->hba);
+ } else {
+ dev_err(qcom_host->hba->dev,
+ "%s: error in ice_vops->config %d\n",
+ __func__, err);
+ }
+
return err;
}
@@ -313,6 +332,11 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host,
return -EINVAL;
}
+ if (qcom_host->hw_ver.major == 0x3) {
+ /* nothing to do here for version 0x3, exit silently */
+ return 0;
+ }
+
req = cmd->request;
if (req->bio)
lba = req->bio->bi_iter.bi_sector;
@@ -383,13 +407,14 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host,
(bypass & MASK_UFS_QCOM_ICE_CTRL_INFO_BYPASS)
<< OFFSET_UFS_QCOM_ICE_CTRL_INFO_BYPASS;
- if (qcom_host->hw_ver.major < 0x2) {
+ if (qcom_host->hw_ver.major == 0x1) {
ufshcd_writel(qcom_host->hba, lba,
(REG_UFS_QCOM_ICE_CTRL_INFO_1_n + 8 * slot));
ufshcd_writel(qcom_host->hba, ctrl_info_val,
(REG_UFS_QCOM_ICE_CTRL_INFO_2_n + 8 * slot));
- } else {
+ }
+ if (qcom_host->hw_ver.major == 0x2) {
ufshcd_writel(qcom_host->hba, (lba & 0xFFFFFFFF),
(REG_UFS_QCOM_ICE_CTRL_INFO_1_n + 16 * slot));
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 319ce7a4cfe2..52268783dd23 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -780,9 +780,6 @@ static int ufs_qcom_crypto_req_setup(struct ufs_hba *hba,
*dun = req->bio->bi_iter.bi_sector;
ret = ufs_qcom_ice_req_setup(host, lrbp->cmd, cc_index, enable);
- if (ret)
- dev_err(hba->dev, "%s: ufs_qcom_ice_req_setup failed (%d)\n",
- __func__, ret);
return ret;
}
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 54689aa4139f..75db00874979 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2310,9 +2310,12 @@ static int ufshcd_prepare_crypto_utrd(struct ufs_hba *hba,
*/
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);
+ if (ret != -EAGAIN) {
+ dev_err(hba->dev,
+ "%s: failed to setup crypto request (%d)\n",
+ __func__, ret);
+ }
+
return ret;
}
@@ -2337,7 +2340,7 @@ out:
* @upiu_flags: flags required in the header
* @cmd_dir: requests data direction
*/
-static void ufshcd_prepare_req_desc_hdr(struct ufs_hba *hba,
+static int ufshcd_prepare_req_desc_hdr(struct ufs_hba *hba,
struct ufshcd_lrb *lrbp, u32 *upiu_flags,
enum dma_data_direction cmd_dir)
{
@@ -2378,7 +2381,9 @@ static void ufshcd_prepare_req_desc_hdr(struct ufs_hba *hba,
req_desc->prd_table_length = 0;
if (ufshcd_is_crypto_supported(hba))
- ufshcd_prepare_crypto_utrd(hba, lrbp);
+ return ufshcd_prepare_crypto_utrd(hba, lrbp);
+
+ return 0;
}
/**
@@ -2481,15 +2486,16 @@ 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(hba, lrbp, &upiu_flags,
- lrbp->cmd->sc_data_direction);
+ ret = ufshcd_prepare_req_desc_hdr(hba, lrbp,
+ &upiu_flags, lrbp->cmd->sc_data_direction);
ufshcd_prepare_utp_scsi_cmd_upiu(lrbp, upiu_flags);
} else {
ret = -EINVAL;
}
break;
case UTP_CMD_TYPE_DEV_MANAGE:
- ufshcd_prepare_req_desc_hdr(hba, lrbp, &upiu_flags, DMA_NONE);
+ ret = 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);
@@ -2644,7 +2650,20 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
lrbp->req_abort_skip = false;
/* form UPIU before issuing the command */
- ufshcd_compose_upiu(hba, lrbp);
+ err = ufshcd_compose_upiu(hba, lrbp);
+ if (err) {
+ if (err != -EAGAIN)
+ dev_err(hba->dev,
+ "%s: failed to compose upiu %d\n",
+ __func__, err);
+
+ lrbp->cmd = NULL;
+ clear_bit_unlock(tag, &hba->lrb_in_use);
+ ufshcd_release_all(hba);
+ ufshcd_vops_pm_qos_req_end(hba, cmd->request, true);
+ goto out;
+ }
+
err = ufshcd_map_sg(lrbp);
if (err) {
lrbp->cmd = NULL;
diff --git a/security/pfe/pfk.c b/security/pfe/pfk.c
index 05afa19c792b..0ed4106d8f4b 100644
--- a/security/pfe/pfk.c
+++ b/security/pfe/pfk.c
@@ -335,7 +335,7 @@ static int pfk_key_size_to_key_type(size_t key_size,
static int pfk_bio_to_key(const struct bio *bio, unsigned char const **key,
size_t *key_size, unsigned char const **salt, size_t *salt_size,
- bool *is_pfe)
+ bool *is_pfe, bool start)
{
struct inode *inode = NULL;
int ret = 0;
@@ -369,7 +369,8 @@ static int pfk_bio_to_key(const struct bio *bio, unsigned char const **key,
return -EPERM;
}
- pr_debug("loading key for file %s\n", inode_to_filename(inode));
+ pr_debug("loading key for file %s, start %d\n",
+ inode_to_filename(inode), start);
ret = pfk_get_page_index(bio, &offset);
if (ret != 0) {
@@ -467,7 +468,8 @@ int pfk_load_key_start(const struct bio *bio,
return -EINVAL;
}
- ret = pfk_bio_to_key(bio, &key, &key_size, &salt, &salt_size, is_pfe);
+ ret = pfk_bio_to_key(bio, &key, &key_size, &salt, &salt_size, is_pfe,
+ true);
if (ret != 0)
return ret;
@@ -548,7 +550,8 @@ int pfk_load_key_end(const struct bio *bio, bool *is_pfe)
if (!pfk_is_ready())
return -ENODEV;
- ret = pfk_bio_to_key(bio, &key, &key_size, &salt, &salt_size, is_pfe);
+ ret = pfk_bio_to_key(bio, &key, &key_size, &salt, &salt_size, is_pfe,
+ false);
if (ret != 0)
return ret;
diff --git a/security/pfe/pfk_kc.c b/security/pfe/pfk_kc.c
index 56ab30ac3095..711cb4f905ea 100644
--- a/security/pfe/pfk_kc.c
+++ b/security/pfe/pfk_kc.c
@@ -493,6 +493,7 @@ int pfk_kc_load_key_start(const unsigned char *key, size_t key_size,
entry = kc_find_key(key, key_size, salt, salt_size);
if (!entry) {
if (async) {
+ pr_debug("found empty entry, a separate task will populate it\n");
kc_spin_unlock();
return -EAGAIN;
}