scsi: ufs: qcom-ice: block further requests until ICE config is complete
Requests that need to go through the ICE must be setup with a key before and have a key index ready. In cases where the key is not ready as it is not in the key cache, the ICE 'config_start' callback returns -EAGAIN and we need to block further requests and call 'config_start' again from a non-atomic context until key setup is ready and then resume requests handling. Change-Id: I51ff1e99240386ce533b5ab3f5f024043532b0ad Signed-off-by: Gilad Broner <gbroner@codeaurora.org> Signed-off-by: Andrey Markovytch <andreym@codeaurora.org>
This commit is contained in:
parent
fe9cbb77bf
commit
d9d0ee4b78
3 changed files with 74 additions and 12 deletions
|
@ -164,7 +164,35 @@ int ufs_qcom_ice_get_dev(struct ufs_qcom_host *qcom_host)
|
|||
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void ufs_qcom_ice_cfg_work(struct work_struct *work)
|
||||
{
|
||||
struct ice_data_setting ice_set;
|
||||
struct ufs_qcom_host *qcom_host =
|
||||
container_of(work, struct ufs_qcom_host, ice_cfg_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.
|
||||
* 'ice_set' will not actually be used, instead the next call to
|
||||
* config_start() for this request, in the normal call flow, will
|
||||
* succeed as the key has now been setup.
|
||||
*/
|
||||
qcom_host->ice.vops->config_start(qcom_host->ice.pdev,
|
||||
qcom_host->req_pending, &ice_set, false);
|
||||
|
||||
/*
|
||||
* Resume with requests processing. We assume config_start has been
|
||||
* successful, but even if it wasn't we still must resume in order to
|
||||
* allow for the request to be retried.
|
||||
*/
|
||||
ufshcd_scsi_unblock_requests(qcom_host->hba);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -193,6 +221,7 @@ int ufs_qcom_ice_init(struct ufs_qcom_host *qcom_host)
|
|||
}
|
||||
|
||||
qcom_host->dbg_print_en |= UFS_QCOM_ICE_DEFAULT_DBG_PRINT_EN;
|
||||
INIT_WORK(&qcom_host->ice_cfg_work, ufs_qcom_ice_cfg_work);
|
||||
|
||||
out:
|
||||
return err;
|
||||
|
@ -300,8 +329,22 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host,
|
|||
err = qcom_host->ice.vops->config_start(qcom_host->ice.pdev,
|
||||
req, &ice_set, true);
|
||||
if (err) {
|
||||
dev_err(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) {
|
||||
qcom_host->req_pending = req;
|
||||
if (schedule_work(&qcom_host->ice_cfg_work))
|
||||
ufshcd_scsi_block_requests(
|
||||
qcom_host->hba);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -337,6 +337,9 @@ struct ufs_qcom_host {
|
|||
/* Bitmask for enabling debug prints */
|
||||
u32 dbg_print_en;
|
||||
struct ufs_qcom_testbus testbus;
|
||||
|
||||
struct work_struct ice_cfg_work;
|
||||
struct request *req_pending;
|
||||
};
|
||||
|
||||
static inline u32
|
||||
|
|
|
@ -1954,14 +1954,6 @@ int ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
|
|||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = ufshcd_vops_crypto_engine_cfg_start(hba, task_tag);
|
||||
if (ret) {
|
||||
dev_err(hba->dev,
|
||||
"%s: failed to configure crypto engine %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
hba->lrb[task_tag].issue_time_stamp = ktime_get();
|
||||
hba->lrb[task_tag].complete_time_stamp = ktime_set(0, 0);
|
||||
ufshcd_clk_scaling_start_busy(hba);
|
||||
|
@ -2627,6 +2619,22 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
|
|||
goto out;
|
||||
}
|
||||
|
||||
err = ufshcd_vops_crypto_engine_cfg_start(hba, tag);
|
||||
if (err) {
|
||||
if (err != -EAGAIN)
|
||||
dev_err(hba->dev,
|
||||
"%s: failed to configure crypto engine %d\n",
|
||||
__func__, err);
|
||||
|
||||
scsi_dma_unmap(lrbp->cmd);
|
||||
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;
|
||||
}
|
||||
|
||||
/* Make sure descriptors are ready before ringing the doorbell */
|
||||
wmb();
|
||||
/* issue command to the controller */
|
||||
|
@ -2640,6 +2648,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
|
|||
clear_bit_unlock(tag, &hba->lrb_in_use);
|
||||
ufshcd_release_all(hba);
|
||||
ufshcd_vops_pm_qos_req_end(hba, cmd->request, true);
|
||||
ufshcd_vops_crypto_engine_cfg_end(hba, lrbp, cmd->request);
|
||||
dev_err(hba->dev, "%s: failed sending command, %d\n",
|
||||
__func__, err);
|
||||
err = DID_ERROR;
|
||||
|
@ -4938,7 +4947,7 @@ void ufshcd_abort_outstanding_transfer_requests(struct ufs_hba *hba, int result)
|
|||
/* Mark completed command as NULL in LRB */
|
||||
lrbp->cmd = NULL;
|
||||
ufshcd_release_all(hba);
|
||||
if (cmd->request)
|
||||
if (cmd->request) {
|
||||
/*
|
||||
* As we are accessing the "request" structure,
|
||||
* this must be called before calling
|
||||
|
@ -4946,6 +4955,9 @@ void ufshcd_abort_outstanding_transfer_requests(struct ufs_hba *hba, int result)
|
|||
*/
|
||||
ufshcd_vops_pm_qos_req_end(hba, cmd->request,
|
||||
true);
|
||||
ufshcd_vops_crypto_engine_cfg_end(hba,
|
||||
lrbp, cmd->request);
|
||||
}
|
||||
/* Do not touch lrbp after scsi done */
|
||||
cmd->scsi_done(cmd);
|
||||
} else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE) {
|
||||
|
@ -4990,7 +5002,7 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba,
|
|||
lrbp->cmd = NULL;
|
||||
__ufshcd_release(hba, false);
|
||||
__ufshcd_hibern8_release(hba, false);
|
||||
if (cmd->request)
|
||||
if (cmd->request) {
|
||||
/*
|
||||
* As we are accessing the "request" structure,
|
||||
* this must be called before calling
|
||||
|
@ -4998,6 +5010,10 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba,
|
|||
*/
|
||||
ufshcd_vops_pm_qos_req_end(hba, cmd->request,
|
||||
false);
|
||||
ufshcd_vops_crypto_engine_cfg_end(hba,
|
||||
lrbp, cmd->request);
|
||||
}
|
||||
|
||||
/* Do not touch lrbp after scsi done */
|
||||
cmd->scsi_done(cmd);
|
||||
} else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE) {
|
||||
|
|
Loading…
Add table
Reference in a new issue