diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2017-01-30 07:05:31 -0800 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-01-30 07:05:31 -0800 |
commit | ba93fbf5f094c5bd57b23410cf60759f6c8a5a0b (patch) | |
tree | 1f6a969d8740602aaa00519fb483a6c0a6012fef /drivers/scsi | |
parent | d9f73b621eedcb036539a80f9039d7dd204751c7 (diff) | |
parent | d6bbd448c783a92e425f928e32ec470a9ebe2cb2 (diff) |
Merge "ufs: add additional sync between ice work queue and pending request"
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/ufs/ufs-qcom-ice.c | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/drivers/scsi/ufs/ufs-qcom-ice.c b/drivers/scsi/ufs/ufs-qcom-ice.c index 85f82b2251c1..814d1dcfe90e 100644 --- a/drivers/scsi/ufs/ufs-qcom-ice.c +++ b/drivers/scsi/ufs/ufs-qcom-ice.c @@ -173,10 +173,19 @@ 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); + struct request *req_pending = NULL; - if (!qcom_host->ice.vops->config_start || !qcom_host->req_pending) + if (!qcom_host->ice.vops->config_start) return; + spin_lock_irqsave(&qcom_host->ice_work_lock, flags); + req_pending = qcom_host->req_pending; + if (!req_pending) { + spin_unlock_irqrestore(&qcom_host->ice_work_lock, flags); + return; + } + spin_unlock_irqrestore(&qcom_host->ice_work_lock, flags); + /* * config_start is called again as previous attempt returned -EAGAIN, * this call shall now take care of the necessary key setup. @@ -263,6 +272,10 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host, if (qcom_host->ice.vops->config_start) { memset(&ice_set, 0, sizeof(ice_set)); + + spin_lock_irqsave( + &qcom_host->ice_work_lock, flags); + err = qcom_host->ice.vops->config_start(qcom_host->ice.pdev, cmd->request, &ice_set, true); if (err) { @@ -281,13 +294,11 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host, "%s: scheduling task for ice setup\n", __func__); - spin_lock_irqsave( - &qcom_host->ice_work_lock, flags); - if (!qcom_host->req_pending) { ufshcd_scsi_block_requests( qcom_host->hba); qcom_host->req_pending = cmd->request; + if (!schedule_work( &qcom_host->ice_cfg_work)) { qcom_host->req_pending = NULL; @@ -302,9 +313,6 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host, } } - spin_unlock_irqrestore( - &qcom_host->ice_work_lock, flags); - } else { if (err != -EBUSY) dev_err(qcom_host->hba->dev, @@ -312,9 +320,14 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host, __func__, err); } + spin_unlock_irqrestore(&qcom_host->ice_work_lock, + flags); + return err; } + spin_unlock_irqrestore(&qcom_host->ice_work_lock, flags); + if (ufs_qcom_is_data_cmd(cmd_op, true)) *enable = !ice_set.encr_bypass; else if (ufs_qcom_is_data_cmd(cmd_op, false)) @@ -380,8 +393,13 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host, return -EINVAL; } - memset(&ice_set, 0, sizeof(ice_set)); + if (qcom_host->ice.vops->config_start) { + memset(&ice_set, 0, sizeof(ice_set)); + + spin_lock_irqsave( + &qcom_host->ice_work_lock, flags); + err = qcom_host->ice.vops->config_start(qcom_host->ice.pdev, req, &ice_set, true); if (err) { @@ -401,9 +419,6 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host, "%s: scheduling task for ice setup\n", __func__); - spin_lock_irqsave( - &qcom_host->ice_work_lock, flags); - if (!qcom_host->req_pending) { ufshcd_scsi_block_requests( qcom_host->hba); @@ -422,9 +437,6 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host, } } - spin_unlock_irqrestore( - &qcom_host->ice_work_lock, flags); - } else { if (err != -EBUSY) dev_err(qcom_host->hba->dev, @@ -432,8 +444,14 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host, __func__, err); } + spin_unlock_irqrestore( + &qcom_host->ice_work_lock, flags); + return err; } + + spin_unlock_irqrestore( + &qcom_host->ice_work_lock, flags); } cmd_op = cmd->cmnd[0]; |