summaryrefslogtreecommitdiff
path: root/drivers/scsi
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-01-30 07:05:31 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2017-01-30 07:05:31 -0800
commitba93fbf5f094c5bd57b23410cf60759f6c8a5a0b (patch)
tree1f6a969d8740602aaa00519fb483a6c0a6012fef /drivers/scsi
parentd9f73b621eedcb036539a80f9039d7dd204751c7 (diff)
parentd6bbd448c783a92e425f928e32ec470a9ebe2cb2 (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.c46
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];