diff options
| author | Andrey Markovytch <andreym@codeaurora.org> | 2016-06-09 13:26:18 +0300 |
|---|---|---|
| committer | Kyle Yan <kyan@codeaurora.org> | 2016-06-09 15:12:13 -0700 |
| commit | 110aebe86786a784dc3941cbe58bc87984454a2c (patch) | |
| tree | 74e939ea3f7e6fc1f932cd8578b7d19ca695f1d3 | |
| parent | a15fd37785f482227381630477fba07522e60fc2 (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.c | 39 | ||||
| -rw-r--r-- | drivers/scsi/ufs/ufs-qcom.c | 3 | ||||
| -rw-r--r-- | drivers/scsi/ufs/ufshcd.c | 37 | ||||
| -rw-r--r-- | security/pfe/pfk.c | 11 | ||||
| -rw-r--r-- | security/pfe/pfk_kc.c | 1 |
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; } |
