linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 00/15] Big fixes, retries, handle a race condition
@ 2015-10-27 10:44 Yaniv Gardi
  2015-10-27 10:44 ` [PATCH v5 01/15] scsi: ufs: clear UTRD, UPIU req and rsp before new transfers Yaniv Gardi
                   ` (15 more replies)
  0 siblings, 16 replies; 27+ messages in thread
From: Yaniv Gardi @ 2015-10-27 10:44 UTC (permalink / raw)
  To: robherring2, James.Bottomley, pebolle, hch
  Cc: linux-kernel, linux-scsi, linux-arm-msm, santoshsy,
	linux-scsi-owner, subhashj, ygardi, gbroner, draviv

Important:
This serie of 15 small patches should be pushed after the series of 8 patches
"Fix error message and present UFS variant probe"

V5:
removed un-necessary wmb()

V4:
fixing a few comments from reviewers

V3:
removed specific calls to wmb() since they are redundant.

V2:
a few minor changes

V1:
This serie of 15 small patches should be pushed after the series of 8 patches
I have uploaded to the upstream a week ago:
"Fix error message and present UFS variant probe"

Yaniv Gardi (15):
  scsi: ufs: clear UTRD, UPIU req and rsp before new transfers
  scsi: ufs: clear fields UTRD, UPIU req and rsp before new transfers
  scsi: ufs: verify command tag validity
  scsi: ufs: clear outstanding_request bit in case query timeout
  scsi: ufs: increase fDeviceInit query response timeout
  scsi: ufs: avoid exception event handler racing with PM callbacks
  scsi: ufs: set REQUEST_SENSE command size to 18 bytes
  scsi: ufs: add retries to dme_peer get and set attribute
  scsi: ufs: add retries for hibern8 enter
  scsi: ufs: fix error recovery after the hibern8 exit failure
  scsi: ufs: retry failed query flag requests
  scsi: ufs: reduce the interrupts for power mode change requests
  scsi: ufs: add missing memory barriers
  scsi: ufs: commit descriptors before setting the doorbell
  scsi: ufs: add wrapper for retrying sending query attribute

 drivers/scsi/ufs/ufshcd.c | 408 ++++++++++++++++++++++++++++++++++++----------
 drivers/scsi/ufs/ufshcd.h |   4 +
 2 files changed, 327 insertions(+), 85 deletions(-)

-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v5 01/15] scsi: ufs: clear UTRD, UPIU req and rsp before new transfers
  2015-10-27 10:44 [PATCH v5 00/15] Big fixes, retries, handle a race condition Yaniv Gardi
@ 2015-10-27 10:44 ` Yaniv Gardi
  2015-10-27 14:53   ` Gilad Broner
  2015-10-27 10:44 ` [PATCH v5 02/15] scsi: ufs: clear fields " Yaniv Gardi
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 27+ messages in thread
From: Yaniv Gardi @ 2015-10-27 10:44 UTC (permalink / raw)
  To: robherring2, James.Bottomley, pebolle, hch
  Cc: linux-kernel, linux-scsi, linux-arm-msm, santoshsy,
	linux-scsi-owner, subhashj, ygardi, gbroner, draviv, Maya Erez,
	Vinayak Holikatti, James E.J. Bottomley

Clear the UFS data structures before sending new request.

The SCSI command is sent to the device within the UFS UPIU request.
As part of the transfer UPIU preparation, the SCSI command is copied
to the UPIU structure according to the SCSI command size.
As different SCSI commands differ in size from each other, we need
to clear the whole SCSI command field to prevent sending uninitialized
data to the device.

The UPIU response doesn't always include the sense data and can differ
in size.
Hence, the UPIU response should also be cleared before the transfer.

Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
Signed-off-by: Maya Erez <merez@codeaurora.org>
Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>

---
 drivers/scsi/ufs/ufshcd.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 131c720..3428f72 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3,7 +3,7 @@
  *
  * This code is based on drivers/scsi/ufs/ufshcd.c
  * Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *
  * Authors:
  *	Santosh Yaraganavi <santosh.sy@samsung.com>
@@ -1035,6 +1035,7 @@ static int ufshcd_map_sg(struct ufshcd_lrb *lrbp)
 				cpu_to_le32(lower_32_bits(sg->dma_address));
 			prd_table[i].upper_addr =
 				cpu_to_le32(upper_32_bits(sg->dma_address));
+			prd_table[i].reserved = 0;
 		}
 	} else {
 		lrbp->utr_descriptor_ptr->prd_table_length = 0;
@@ -1117,7 +1118,8 @@ static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp,
 
 	/* Transfer request descriptor header fields */
 	req_desc->header.dword_0 = cpu_to_le32(dword_0);
-
+	/* dword_1 is reserved, hence it is set to 0 */
+	req_desc->header.dword_1 = 0;
 	/*
 	 * assigning invalid value for command status. Controller
 	 * updates OCS on command completion, with the command
@@ -1125,6 +1127,8 @@ static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp,
 	 */
 	req_desc->header.dword_2 =
 		cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
+	/* dword_3 is reserved, hence it is set to 0 */
+	req_desc->header.dword_3 = 0;
 }
 
 /**
@@ -1137,6 +1141,7 @@ static
 void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb *lrbp, u32 upiu_flags)
 {
 	struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr;
+	unsigned short cdb_len;
 
 	/* command descriptor fields */
 	ucd_req_ptr->header.dword_0 = UPIU_HEADER_DWORD(
@@ -1151,8 +1156,12 @@ void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb *lrbp, u32 upiu_flags)
 	ucd_req_ptr->sc.exp_data_transfer_len =
 		cpu_to_be32(lrbp->cmd->sdb.length);
 
-	memcpy(ucd_req_ptr->sc.cdb, lrbp->cmd->cmnd,
-		(min_t(unsigned short, lrbp->cmd->cmd_len, MAX_CDB_SIZE)));
+	cdb_len = min_t(unsigned short, lrbp->cmd->cmd_len, MAX_CDB_SIZE);
+	memcpy(ucd_req_ptr->sc.cdb, lrbp->cmd->cmnd, cdb_len);
+	if (cdb_len < MAX_CDB_SIZE)
+		memset(ucd_req_ptr->sc.cdb + cdb_len, 0,
+		       (MAX_CDB_SIZE - cdb_len));
+	memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
 }
 
 /**
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 02/15] scsi: ufs: clear fields UTRD, UPIU req and rsp before new transfers
  2015-10-27 10:44 [PATCH v5 00/15] Big fixes, retries, handle a race condition Yaniv Gardi
  2015-10-27 10:44 ` [PATCH v5 01/15] scsi: ufs: clear UTRD, UPIU req and rsp before new transfers Yaniv Gardi
@ 2015-10-27 10:44 ` Yaniv Gardi
  2015-10-27 14:55   ` Gilad Broner
  2015-10-27 10:44 ` [PATCH v5 03/15] scsi: ufs: verify command tag validity Yaniv Gardi
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 27+ messages in thread
From: Yaniv Gardi @ 2015-10-27 10:44 UTC (permalink / raw)
  To: robherring2, James.Bottomley, pebolle, hch
  Cc: linux-kernel, linux-scsi, linux-arm-msm, santoshsy,
	linux-scsi-owner, subhashj, ygardi, gbroner, draviv,
	Vinayak Holikatti, James E.J. Bottomley

Some of the data structures (like response UPIU) and/or its elements
(unused fields) should be cleared before sending out the respective
command to UFS device.

This change clears the UPIU response data structure for query commands
and NOP command before sending out the command. We also initialize the
PRDT table length to zero which should take care of commands which doesn't
have any data associated with it. We are also clearing the unused fields in
request UPIU for NOP command.

Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>

---
 drivers/scsi/ufs/ufshcd.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 3428f72..2d3ebca 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1129,6 +1129,8 @@ static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp,
 		cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
 	/* dword_3 is reserved, hence it is set to 0 */
 	req_desc->header.dword_3 = 0;
+
+	req_desc->prd_table_length = 0;
 }
 
 /**
@@ -1198,6 +1200,7 @@ static void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba,
 	if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC)
 		memcpy(descp, query->descriptor, len);
 
+	memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
 }
 
 static inline void ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp)
@@ -1210,6 +1213,11 @@ static inline void ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp)
 	ucd_req_ptr->header.dword_0 =
 		UPIU_HEADER_DWORD(
 			UPIU_TRANSACTION_NOP_OUT, 0, 0, lrbp->task_tag);
+	/* clear rest of the fields of basic header */
+	ucd_req_ptr->header.dword_1 = 0;
+	ucd_req_ptr->header.dword_2 = 0;
+
+	memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
 }
 
 /**
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 03/15] scsi: ufs: verify command tag validity
  2015-10-27 10:44 [PATCH v5 00/15] Big fixes, retries, handle a race condition Yaniv Gardi
  2015-10-27 10:44 ` [PATCH v5 01/15] scsi: ufs: clear UTRD, UPIU req and rsp before new transfers Yaniv Gardi
  2015-10-27 10:44 ` [PATCH v5 02/15] scsi: ufs: clear fields " Yaniv Gardi
@ 2015-10-27 10:44 ` Yaniv Gardi
  2015-10-27 10:44 ` [PATCH v5 04/15] scsi: ufs: clear outstanding_request bit in case query timeout Yaniv Gardi
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 27+ messages in thread
From: Yaniv Gardi @ 2015-10-27 10:44 UTC (permalink / raw)
  To: robherring2, James.Bottomley, pebolle, hch
  Cc: linux-kernel, linux-scsi, linux-arm-msm, santoshsy,
	linux-scsi-owner, subhashj, ygardi, gbroner, draviv,
	Vinayak Holikatti, James E.J. Bottomley

A race condition appear to exist between request completion when
scsi_done() is called to end the request and set the tag back to
-1 (at blk_queue_end_tag() scsi_end_request), and scsi layer error
handling which aborts the command and reuses it to request sense
data. Sending the request sense is done with tag which was set to -1
and so it is invalid.
Assert command tag passed from scsi layer is valid.

Signed-off-by: Gilad Broner <gbroner@codeaurora.org>
Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>

---
 drivers/scsi/ufs/ufshcd.c | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 2d3ebca..8860a57 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -190,6 +190,10 @@ static int ufshcd_config_pwr_mode(struct ufs_hba *hba,
 		struct ufs_pa_layer_attr *desired_pwr_mode);
 static int ufshcd_change_power_mode(struct ufs_hba *hba,
 			     struct ufs_pa_layer_attr *pwr_mode);
+static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag)
+{
+	return tag >= 0 && tag < hba->nutrs;
+}
 
 static inline int ufshcd_enable_irq(struct ufs_hba *hba)
 {
@@ -1310,6 +1314,12 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
 	hba = shost_priv(host);
 
 	tag = cmd->request->tag;
+	if (!ufshcd_valid_tag(hba, tag)) {
+		dev_err(hba->dev,
+			"%s: invalid command tag %d: cmd=0x%p, cmd->request=0x%p",
+			__func__, tag, cmd, cmd->request);
+		BUG();
+	}
 
 	spin_lock_irqsave(hba->host->host_lock, flags);
 	switch (hba->ufshcd_state) {
@@ -3862,13 +3872,23 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
 	host = cmd->device->host;
 	hba = shost_priv(host);
 	tag = cmd->request->tag;
+	if (!ufshcd_valid_tag(hba, tag)) {
+		dev_err(hba->dev,
+			"%s: invalid command tag %d: cmd=0x%p, cmd->request=0x%p",
+			__func__, tag, cmd, cmd->request);
+		BUG();
+	}
 
 	ufshcd_hold(hba, false);
+	reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
 	/* If command is already aborted/completed, return SUCCESS */
-	if (!(test_bit(tag, &hba->outstanding_reqs)))
+	if (!(test_bit(tag, &hba->outstanding_reqs))) {
+		dev_err(hba->dev,
+			"%s: cmd at tag %d already completed, outstanding=0x%lx, doorbell=0x%x\n",
+			__func__, tag, hba->outstanding_reqs, reg);
 		goto out;
+	}
 
-	reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
 	if (!(reg & (1 << tag))) {
 		dev_err(hba->dev,
 		"%s: cmd was completed, but without a notifying intr, tag = %d",
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 04/15] scsi: ufs: clear outstanding_request bit in case query timeout
  2015-10-27 10:44 [PATCH v5 00/15] Big fixes, retries, handle a race condition Yaniv Gardi
                   ` (2 preceding siblings ...)
  2015-10-27 10:44 ` [PATCH v5 03/15] scsi: ufs: verify command tag validity Yaniv Gardi
@ 2015-10-27 10:44 ` Yaniv Gardi
  2015-10-27 14:56   ` Gilad Broner
  2015-10-27 10:44 ` [PATCH v5 05/15] scsi: ufs: increase fDeviceInit query response timeout Yaniv Gardi
                   ` (11 subsequent siblings)
  15 siblings, 1 reply; 27+ messages in thread
From: Yaniv Gardi @ 2015-10-27 10:44 UTC (permalink / raw)
  To: robherring2, James.Bottomley, pebolle, hch
  Cc: linux-kernel, linux-scsi, linux-arm-msm, santoshsy,
	linux-scsi-owner, subhashj, ygardi, gbroner, draviv,
	Vinayak Holikatti, James E.J. Bottomley

When sending a query to the device returns with a timeout error,
we clear the corresponding bit in the DOORBELL register but
we don't clear the outstanding_request field as we should.
This patch fixes this bug.

Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>

---
 drivers/scsi/ufs/ufshcd.c | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 8860a57..e0b8755 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -364,6 +364,16 @@ static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos)
 }
 
 /**
+ * ufshcd_outstanding_req_clear - Clear a bit in outstanding request field
+ * @hba: per adapter instance
+ * @tag: position of the bit to be cleared
+ */
+static inline void ufshcd_outstanding_req_clear(struct ufs_hba *hba, int tag)
+{
+	__clear_bit(tag, &hba->outstanding_reqs);
+}
+
+/**
  * ufshcd_get_lists_status - Check UCRDY, UTRLRDY and UTMRLRDY
  * @reg: Register value of host controller status
  *
@@ -1502,9 +1512,17 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
 
 	if (!time_left) {
 		err = -ETIMEDOUT;
+		dev_dbg(hba->dev, "%s: dev_cmd request timedout, tag %d\n",
+			__func__, lrbp->task_tag);
 		if (!ufshcd_clear_cmd(hba, lrbp->task_tag))
-			/* sucessfully cleared the command, retry if needed */
+			/* successfully cleared the command, retry if needed */
 			err = -EAGAIN;
+		/*
+		 * in case of an error, after clearing the doorbell,
+		 * we also need to clear the outstanding_request
+		 * field in hba
+		 */
+		ufshcd_outstanding_req_clear(hba, lrbp->task_tag);
 	}
 
 	return err;
@@ -3942,7 +3960,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
 	scsi_dma_unmap(cmd);
 
 	spin_lock_irqsave(host->host_lock, flags);
-	__clear_bit(tag, &hba->outstanding_reqs);
+	ufshcd_outstanding_req_clear(hba, tag);
 	hba->lrb[tag].cmd = NULL;
 	spin_unlock_irqrestore(host->host_lock, flags);
 
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 05/15] scsi: ufs: increase fDeviceInit query response timeout
  2015-10-27 10:44 [PATCH v5 00/15] Big fixes, retries, handle a race condition Yaniv Gardi
                   ` (3 preceding siblings ...)
  2015-10-27 10:44 ` [PATCH v5 04/15] scsi: ufs: clear outstanding_request bit in case query timeout Yaniv Gardi
@ 2015-10-27 10:44 ` Yaniv Gardi
  2015-10-27 14:56   ` Gilad Broner
  2015-10-27 10:44 ` [PATCH v5 06/15] scsi: ufs: avoid exception event handler racing with PM callbacks Yaniv Gardi
                   ` (10 subsequent siblings)
  15 siblings, 1 reply; 27+ messages in thread
From: Yaniv Gardi @ 2015-10-27 10:44 UTC (permalink / raw)
  To: robherring2, James.Bottomley, pebolle, hch
  Cc: linux-kernel, linux-scsi, linux-arm-msm, santoshsy,
	linux-scsi-owner, subhashj, ygardi, gbroner, draviv,
	Vinayak Holikatti, James E.J. Bottomley

fDeviceInit query response time for some devices is too long that default
query request timeout of 100ms may not be enough. Experiments show that
fDeviceInit response sometimes takes 500ms so to be on safer side this
change sets the timeout to 600ms. Without this change, we might
unnecessarily have to retry fDeviceInit query requests multiple times and
each query request timeout prints one error message.

Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>

---
 drivers/scsi/ufs/ufshcd.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index e0b8755..573a8cb 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -58,6 +58,12 @@
 #define QUERY_REQ_RETRIES 10
 /* Query request timeout */
 #define QUERY_REQ_TIMEOUT 30 /* msec */
+/*
+ * Query request timeout for fDeviceInit flag
+ * fDeviceInit query response time for some devices is too large that default
+ * QUERY_REQ_TIMEOUT may not be enough for such devices.
+ */
+#define QUERY_FDEVICEINIT_REQ_TIMEOUT 600 /* msec */
 
 /* Task management command timeout */
 #define TM_CMD_TIMEOUT	100 /* msecs */
@@ -1651,6 +1657,7 @@ static int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
 	struct ufs_query_req *request = NULL;
 	struct ufs_query_res *response = NULL;
 	int err, index = 0, selector = 0;
+	int timeout = QUERY_REQ_TIMEOUT;
 
 	BUG_ON(!hba);
 
@@ -1683,7 +1690,10 @@ static int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
 		goto out_unlock;
 	}
 
-	err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT);
+	if (idn == QUERY_FLAG_IDN_FDEVICEINIT)
+		timeout = QUERY_FDEVICEINIT_REQ_TIMEOUT;
+
+	err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, timeout);
 
 	if (err) {
 		dev_err(hba->dev,
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 06/15] scsi: ufs: avoid exception event handler racing with PM callbacks
  2015-10-27 10:44 [PATCH v5 00/15] Big fixes, retries, handle a race condition Yaniv Gardi
                   ` (4 preceding siblings ...)
  2015-10-27 10:44 ` [PATCH v5 05/15] scsi: ufs: increase fDeviceInit query response timeout Yaniv Gardi
@ 2015-10-27 10:44 ` Yaniv Gardi
  2015-10-27 14:57   ` Gilad Broner
  2015-10-27 10:44 ` [PATCH v5 07/15] scsi: ufs: set REQUEST_SENSE command size to 18 bytes Yaniv Gardi
                   ` (9 subsequent siblings)
  15 siblings, 1 reply; 27+ messages in thread
From: Yaniv Gardi @ 2015-10-27 10:44 UTC (permalink / raw)
  To: robherring2, James.Bottomley, pebolle, hch
  Cc: linux-kernel, linux-scsi, linux-arm-msm, santoshsy,
	linux-scsi-owner, subhashj, ygardi, gbroner, draviv,
	Vinayak Holikatti, James E.J. Bottomley

If device raises the exception event in the response to the commands
sent during the runtime/system PM callbacks, exception event handler
might run in parallel with PM callbacks and may see unclocked register
accesses. This change fixes this issue by not scheduling the exception
event handler while PM callbacks are running.

Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>

---
 drivers/scsi/ufs/ufshcd.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 573a8cb..0e54183 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3145,7 +3145,20 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
 			scsi_status = result & MASK_SCSI_STATUS;
 			result = ufshcd_scsi_cmd_status(lrbp, scsi_status);
 
-			if (ufshcd_is_exception_event(lrbp->ucd_rsp_ptr))
+			/*
+			 * Currently we are only supporting BKOPs exception
+			 * events hence we can ignore BKOPs exception event
+			 * during power management callbacks. BKOPs exception
+			 * event is not expected to be raised in runtime suspend
+			 * callback as it allows the urgent bkops.
+			 * During system suspend, we are anyway forcefully
+			 * disabling the bkops and if urgent bkops is needed
+			 * it will be enabled on system resume. Long term
+			 * solution could be to abort the system suspend if
+			 * UFS device needs urgent BKOPs.
+			 */
+			if (!hba->pm_op_in_progress &&
+			    ufshcd_is_exception_event(lrbp->ucd_rsp_ptr))
 				schedule_work(&hba->eeh_work);
 			break;
 		case UPIU_TRANSACTION_REJECT_UPIU:
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 07/15] scsi: ufs: set REQUEST_SENSE command size to 18 bytes
  2015-10-27 10:44 [PATCH v5 00/15] Big fixes, retries, handle a race condition Yaniv Gardi
                   ` (5 preceding siblings ...)
  2015-10-27 10:44 ` [PATCH v5 06/15] scsi: ufs: avoid exception event handler racing with PM callbacks Yaniv Gardi
@ 2015-10-27 10:44 ` Yaniv Gardi
  2015-10-27 10:44 ` [PATCH v5 08/15] scsi: ufs: add retries to dme_peer get and set attribute Yaniv Gardi
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 27+ messages in thread
From: Yaniv Gardi @ 2015-10-27 10:44 UTC (permalink / raw)
  To: robherring2, James.Bottomley, pebolle, hch
  Cc: linux-kernel, linux-scsi, linux-arm-msm, santoshsy,
	linux-scsi-owner, subhashj, ygardi, gbroner, draviv,
	Vinayak Holikatti, James E.J. Bottomley

According to UFS device specification REQUEST_SENSE command can
only report back up to 18 bytes of data.

Signed-off-by: Gilad Broner <gbroner@codeaurora.org>
Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>

---
 drivers/scsi/ufs/ufshcd.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 0e54183..8a04691 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -43,6 +43,8 @@
 #include "ufshcd.h"
 #include "unipro.h"
 
+#define UFSHCD_REQ_SENSE_SIZE	18
+
 #define UFSHCD_ENABLE_INTRS	(UTP_TRANSFER_REQ_COMPL |\
 				 UTP_TASK_REQ_COMPL |\
 				 UFSHCD_ERROR_MASK)
@@ -836,7 +838,7 @@ static inline void ufshcd_copy_sense_data(struct ufshcd_lrb *lrbp)
 		len = be16_to_cpu(lrbp->ucd_rsp_ptr->sr.sense_data_len);
 		memcpy(lrbp->sense_buffer,
 			lrbp->ucd_rsp_ptr->sr.sense_data,
-			min_t(int, len, SCSI_SENSE_BUFFERSIZE));
+			min_t(int, len, UFSHCD_REQ_SENSE_SIZE));
 	}
 }
 
@@ -1381,7 +1383,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
 
 	WARN_ON(lrbp->cmd);
 	lrbp->cmd = cmd;
-	lrbp->sense_bufflen = SCSI_SENSE_BUFFERSIZE;
+	lrbp->sense_bufflen = UFSHCD_REQ_SENSE_SIZE;
 	lrbp->sense_buffer = cmd->sense_buffer;
 	lrbp->task_tag = tag;
 	lrbp->lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun);
@@ -4817,19 +4819,19 @@ ufshcd_send_request_sense(struct ufs_hba *hba, struct scsi_device *sdp)
 				0,
 				0,
 				0,
-				SCSI_SENSE_BUFFERSIZE,
+				UFSHCD_REQ_SENSE_SIZE,
 				0};
 	char *buffer;
 	int ret;
 
-	buffer = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
+	buffer = kzalloc(UFSHCD_REQ_SENSE_SIZE, GFP_KERNEL);
 	if (!buffer) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
 	ret = scsi_execute_req_flags(sdp, cmd, DMA_FROM_DEVICE, buffer,
-				SCSI_SENSE_BUFFERSIZE, NULL,
+				UFSHCD_REQ_SENSE_SIZE, NULL,
 				msecs_to_jiffies(1000), 3, NULL, REQ_PM);
 	if (ret)
 		pr_err("%s: failed with err %d\n", __func__, ret);
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 08/15] scsi: ufs: add retries to dme_peer get and set attribute
  2015-10-27 10:44 [PATCH v5 00/15] Big fixes, retries, handle a race condition Yaniv Gardi
                   ` (6 preceding siblings ...)
  2015-10-27 10:44 ` [PATCH v5 07/15] scsi: ufs: set REQUEST_SENSE command size to 18 bytes Yaniv Gardi
@ 2015-10-27 10:44 ` Yaniv Gardi
  2015-10-27 14:58   ` Gilad Broner
  2015-10-27 10:44 ` [PATCH v5 09/15] scsi: ufs: add retries for hibern8 enter Yaniv Gardi
                   ` (7 subsequent siblings)
  15 siblings, 1 reply; 27+ messages in thread
From: Yaniv Gardi @ 2015-10-27 10:44 UTC (permalink / raw)
  To: robherring2, James.Bottomley, pebolle, hch
  Cc: linux-kernel, linux-scsi, linux-arm-msm, santoshsy,
	linux-scsi-owner, subhashj, ygardi, gbroner, draviv, Lee Susman,
	Vinayak Holikatti, James E.J. Bottomley

The dme_peer get/set attribute commands are prone to errors, therefore
we add three retries for the UIC command sending.
Error code returned from ufshcd_send_uic_cmd() is checked, and unless
it was successful or the retries have finished, another command will be
sent.

Signed-off-by: Lee Susman <lsusman@codeaurora.org>
Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>

---
 drivers/scsi/ufs/ufshcd.c | 40 +++++++++++++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 8a04691..5005d12 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -70,6 +70,9 @@
 /* Task management command timeout */
 #define TM_CMD_TIMEOUT	100 /* msecs */
 
+/* maximum number of retries for a general UIC command  */
+#define UFS_UIC_COMMAND_RETRIES 3
+
 /* maximum number of link-startup retries */
 #define DME_LINKSTARTUP_RETRIES 3
 
@@ -2185,6 +2188,7 @@ int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
 	};
 	const char *set = action[!!peer];
 	int ret;
+	int retries = UFS_UIC_COMMAND_RETRIES;
 
 	uic_cmd.command = peer ?
 		UIC_CMD_DME_PEER_SET : UIC_CMD_DME_SET;
@@ -2192,10 +2196,18 @@ int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
 	uic_cmd.argument2 = UIC_ARG_ATTR_TYPE(attr_set);
 	uic_cmd.argument3 = mib_val;
 
-	ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
-	if (ret)
-		dev_err(hba->dev, "%s: attr-id 0x%x val 0x%x error code %d\n",
-			set, UIC_GET_ATTR_ID(attr_sel), mib_val, ret);
+	do {
+		/* for peer attributes we retry upon failure */
+		ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
+		if (ret)
+			dev_dbg(hba->dev, "%s: attr-id 0x%x val 0x%x error code %d\n",
+				set, UIC_GET_ATTR_ID(attr_sel), mib_val, ret);
+	} while (ret && peer && --retries);
+
+	if (!retries)
+		dev_err(hba->dev, "%s: attr-id 0x%x val 0x%x failed %d retries\n",
+				set, UIC_GET_ATTR_ID(attr_sel), mib_val,
+				retries);
 
 	return ret;
 }
@@ -2220,6 +2232,7 @@ int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
 	};
 	const char *get = action[!!peer];
 	int ret;
+	int retries = UFS_UIC_COMMAND_RETRIES;
 	struct ufs_pa_layer_attr orig_pwr_info;
 	struct ufs_pa_layer_attr temp_pwr_info;
 	bool pwr_mode_change = false;
@@ -2250,14 +2263,19 @@ int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
 		UIC_CMD_DME_PEER_GET : UIC_CMD_DME_GET;
 	uic_cmd.argument1 = attr_sel;
 
-	ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
-	if (ret) {
-		dev_err(hba->dev, "%s: attr-id 0x%x error code %d\n",
-			get, UIC_GET_ATTR_ID(attr_sel), ret);
-		goto out;
-	}
+	do {
+		/* for peer attributes we retry upon failure */
+		ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
+		if (ret)
+			dev_dbg(hba->dev, "%s: attr-id 0x%x error code %d\n",
+				get, UIC_GET_ATTR_ID(attr_sel), ret);
+	} while (ret && peer && --retries);
+
+	if (!retries)
+		dev_err(hba->dev, "%s: attr-id 0x%x failed %d retries\n",
+				get, UIC_GET_ATTR_ID(attr_sel), retries);
 
-	if (mib_val)
+	if (mib_val && !ret)
 		*mib_val = uic_cmd.argument3;
 
 	if (peer && (hba->quirks & UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE)
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 09/15] scsi: ufs: add retries for hibern8 enter
  2015-10-27 10:44 [PATCH v5 00/15] Big fixes, retries, handle a race condition Yaniv Gardi
                   ` (7 preceding siblings ...)
  2015-10-27 10:44 ` [PATCH v5 08/15] scsi: ufs: add retries to dme_peer get and set attribute Yaniv Gardi
@ 2015-10-27 10:44 ` Yaniv Gardi
  2015-10-27 14:59   ` Gilad Broner
  2015-10-27 10:44 ` [PATCH v5 10/15] scsi: ufs: fix error recovery after the hibern8 exit failure Yaniv Gardi
                   ` (6 subsequent siblings)
  15 siblings, 1 reply; 27+ messages in thread
From: Yaniv Gardi @ 2015-10-27 10:44 UTC (permalink / raw)
  To: robherring2, James.Bottomley, pebolle, hch
  Cc: linux-kernel, linux-scsi, linux-arm-msm, santoshsy,
	linux-scsi-owner, subhashj, ygardi, gbroner, draviv,
	Vinayak Holikatti, James E.J. Bottomley

If hibern8 enter command fails then UFS link state may be unknown which
may result into timeout of all the commands issued after failure.

This change does 2 things (for pre-defined number of retry counts) after
hibern8 enter failure:
1. Recovers the UFS link to active state
2. If link is recovered to active state, tries to put the UFS link in
   hibern8 enter again until retry count expires.

Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>

---
 drivers/scsi/ufs/ufshcd.c | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 5005d12..ed134d6 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -76,6 +76,9 @@
 /* maximum number of link-startup retries */
 #define DME_LINKSTARTUP_RETRIES 3
 
+/* Maximum retries for Hibern8 enter */
+#define UIC_HIBERN8_ENTER_RETRIES 3
+
 /* maximum number of reset retries before giving up */
 #define MAX_HOST_RESET_RETRIES 5
 
@@ -2390,13 +2393,32 @@ out:
 	return ret;
 }
 
-static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
+static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
 {
+	int ret;
 	struct uic_command uic_cmd = {0};
 
 	uic_cmd.command = UIC_CMD_DME_HIBER_ENTER;
+	ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
+
+	if (ret)
+		dev_err(hba->dev, "%s: hibern8 enter failed. ret = %d\n",
+			__func__, ret);
+
+	return ret;
+}
+
+static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
+{
+	int ret = 0, retries;
 
-	return ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
+	for (retries = UIC_HIBERN8_ENTER_RETRIES; retries > 0; retries--) {
+		ret = __ufshcd_uic_hibern8_enter(hba);
+		if (!ret || ret == -ENOLINK)
+			goto out;
+	}
+out:
+	return ret;
 }
 
 static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba)
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 10/15] scsi: ufs: fix error recovery after the hibern8 exit failure
  2015-10-27 10:44 [PATCH v5 00/15] Big fixes, retries, handle a race condition Yaniv Gardi
                   ` (8 preceding siblings ...)
  2015-10-27 10:44 ` [PATCH v5 09/15] scsi: ufs: add retries for hibern8 enter Yaniv Gardi
@ 2015-10-27 10:44 ` Yaniv Gardi
  2015-10-27 14:59   ` Gilad Broner
  2015-10-27 10:44 ` [PATCH v5 11/15] scsi: ufs: retry failed query flag requests Yaniv Gardi
                   ` (5 subsequent siblings)
  15 siblings, 1 reply; 27+ messages in thread
From: Yaniv Gardi @ 2015-10-27 10:44 UTC (permalink / raw)
  To: robherring2, James.Bottomley, pebolle, hch
  Cc: linux-kernel, linux-scsi, linux-arm-msm, santoshsy,
	linux-scsi-owner, subhashj, ygardi, gbroner, draviv,
	Vinayak Holikatti, James E.J. Bottomley

Hibern8 exit can be called from 3 different context:
    - ufshcd_hibern8_exit_work
    - ufshcd_ungate_work
    - runtime/system resume

If hibern8 exit fails for some reason then we try to bring the link to
active state by link startup but this recovery mechanism results into
deadlock or errors from first 2 context listed above. This change fixes
the recovery by adding proper error handling mechanism.

Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>

---
 drivers/scsi/ufs/ufshcd.c | 58 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 53 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index ed134d6..60ba729 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -610,6 +610,11 @@ int ufshcd_hold(struct ufs_hba *hba, bool async)
 	spin_lock_irqsave(hba->host->host_lock, flags);
 	hba->clk_gating.active_reqs++;
 
+	if (ufshcd_eh_in_progress(hba)) {
+		spin_unlock_irqrestore(hba->host->host_lock, flags);
+		return 0;
+	}
+
 start:
 	switch (hba->clk_gating.state) {
 	case CLKS_ON:
@@ -725,7 +730,8 @@ static void __ufshcd_release(struct ufs_hba *hba)
 	if (hba->clk_gating.active_reqs || hba->clk_gating.is_suspended
 		|| hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL
 		|| hba->lrb_in_use || hba->outstanding_tasks
-		|| hba->active_uic_cmd || hba->uic_async_done)
+		|| hba->active_uic_cmd || hba->uic_async_done
+		|| ufshcd_eh_in_progress(hba))
 		return;
 
 	hba->clk_gating.state = REQ_CLKS_OFF;
@@ -1363,6 +1369,13 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
 		cmd->scsi_done(cmd);
 		goto out_unlock;
 	}
+
+	/* if error handling is in progress, don't issue commands */
+	if (ufshcd_eh_in_progress(hba)) {
+		set_host_byte(cmd, DID_ERROR);
+		cmd->scsi_done(cmd);
+		goto out_unlock;
+	}
 	spin_unlock_irqrestore(hba->host->host_lock, flags);
 
 	/* acquire the tag to make sure device cmds don't use it */
@@ -2393,6 +2406,31 @@ out:
 	return ret;
 }
 
+static int ufshcd_link_recovery(struct ufs_hba *hba)
+{
+	int ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(hba->host->host_lock, flags);
+	hba->ufshcd_state = UFSHCD_STATE_RESET;
+	ufshcd_set_eh_in_progress(hba);
+	spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+	ret = ufshcd_host_reset_and_restore(hba);
+
+	spin_lock_irqsave(hba->host->host_lock, flags);
+	if (ret)
+		hba->ufshcd_state = UFSHCD_STATE_ERROR;
+	ufshcd_clear_eh_in_progress(hba);
+	spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+	if (ret)
+		dev_err(hba->dev, "%s: link recovery failed, err %d",
+			__func__, ret);
+
+	return ret;
+}
+
 static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
 {
 	int ret;
@@ -2401,10 +2439,18 @@ static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
 	uic_cmd.command = UIC_CMD_DME_HIBER_ENTER;
 	ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
 
-	if (ret)
+	if (ret) {
 		dev_err(hba->dev, "%s: hibern8 enter failed. ret = %d\n",
 			__func__, ret);
 
+		/*
+		 * If link recovery fails then return error so that caller
+		 * don't retry the hibern8 enter again.
+		 */
+		if (ufshcd_link_recovery(hba))
+			ret = -ENOLINK;
+	}
+
 	return ret;
 }
 
@@ -2429,8 +2475,9 @@ static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba)
 	uic_cmd.command = UIC_CMD_DME_HIBER_EXIT;
 	ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
 	if (ret) {
-		ufshcd_set_link_off(hba);
-		ret = ufshcd_host_reset_and_restore(hba);
+		dev_err(hba->dev, "%s: hibern8 exit failed. ret = %d\n",
+			__func__, ret);
+		ret = ufshcd_link_recovery(hba);
 	}
 
 	return ret;
@@ -4382,7 +4429,6 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
 	/* UFS device is also active now */
 	ufshcd_set_ufs_dev_active(hba);
 	ufshcd_force_reset_auto_bkops(hba);
-	hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
 	hba->wlun_dev_clr_ua = true;
 
 	if (ufshcd_get_max_pwr_mode(hba)) {
@@ -4396,6 +4442,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
 					__func__, ret);
 	}
 
+	/* set the state as operational after switching to desired gear */
+	hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
 	/*
 	 * If we are in error handling context or in power management callbacks
 	 * context, no need to scan the host
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 11/15] scsi: ufs: retry failed query flag requests
  2015-10-27 10:44 [PATCH v5 00/15] Big fixes, retries, handle a race condition Yaniv Gardi
                   ` (9 preceding siblings ...)
  2015-10-27 10:44 ` [PATCH v5 10/15] scsi: ufs: fix error recovery after the hibern8 exit failure Yaniv Gardi
@ 2015-10-27 10:44 ` Yaniv Gardi
  2015-10-27 10:44 ` [PATCH v5 12/15] scsi: ufs: reduce the interrupts for power mode change requests Yaniv Gardi
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 27+ messages in thread
From: Yaniv Gardi @ 2015-10-27 10:44 UTC (permalink / raw)
  To: robherring2, James.Bottomley, pebolle, hch
  Cc: linux-kernel, linux-scsi, linux-arm-msm, santoshsy,
	linux-scsi-owner, subhashj, ygardi, gbroner, draviv,
	Vinayak Holikatti, James E.J. Bottomley

UFS flag query requests may fail sometimes due to timeouts etc.
Add a wrapper function to retry up to 10 times in case of such
failure, similar to retries being made for attribute queries.

Signed-off-by: Gilad Broner <gbroner@codeaurora.org>
Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>

---
 drivers/scsi/ufs/ufshcd.c | 63 ++++++++++++++++++++++++++++-------------------
 drivers/scsi/ufs/ufshcd.h |  4 +++
 2 files changed, 41 insertions(+), 26 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 60ba729..889a7be 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1663,6 +1663,29 @@ static inline void ufshcd_init_query(struct ufs_hba *hba,
 	(*request)->upiu_req.selector = selector;
 }
 
+static int ufshcd_query_flag_retry(struct ufs_hba *hba,
+	enum query_opcode opcode, enum flag_idn idn, bool *flag_res)
+{
+	int ret;
+	int retries;
+
+	for (retries = 0; retries < QUERY_REQ_RETRIES; retries++) {
+		ret = ufshcd_query_flag(hba, opcode, idn, flag_res);
+		if (ret)
+			dev_dbg(hba->dev,
+				"%s: failed with error %d, retries %d\n",
+				__func__, ret, retries);
+		else
+			break;
+	}
+
+	if (ret)
+		dev_err(hba->dev,
+			"%s: query attribute, opcode %d, idn %d, failed with error %d after %d retires\n",
+			__func__, opcode, idn, ret, retries);
+	return ret;
+}
+
 /**
  * ufshcd_query_flag() - API function for sending flag query requests
  * hba: per-adapter instance
@@ -1672,7 +1695,7 @@ static inline void ufshcd_init_query(struct ufs_hba *hba,
  *
  * Returns 0 for success, non-zero in case of failure
  */
-static int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
+int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
 			enum flag_idn idn, bool *flag_res)
 {
 	struct ufs_query_req *request = NULL;
@@ -2657,17 +2680,12 @@ static int ufshcd_config_pwr_mode(struct ufs_hba *hba,
  */
 static int ufshcd_complete_dev_init(struct ufs_hba *hba)
 {
-	int i, retries, err = 0;
+	int i;
+	int err;
 	bool flag_res = 1;
 
-	for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) {
-		/* Set the fDeviceInit flag */
-		err = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_SET_FLAG,
-					QUERY_FLAG_IDN_FDEVICEINIT, NULL);
-		if (!err || err == -ETIMEDOUT)
-			break;
-		dev_dbg(hba->dev, "%s: error %d retrying\n", __func__, err);
-	}
+	err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG,
+		QUERY_FLAG_IDN_FDEVICEINIT, NULL);
 	if (err) {
 		dev_err(hba->dev,
 			"%s setting fDeviceInit flag failed with error %d\n",
@@ -2675,18 +2693,11 @@ static int ufshcd_complete_dev_init(struct ufs_hba *hba)
 		goto out;
 	}
 
-	/* poll for max. 100 iterations for fDeviceInit flag to clear */
-	for (i = 0; i < 100 && !err && flag_res; i++) {
-		for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) {
-			err = ufshcd_query_flag(hba,
-					UPIU_QUERY_OPCODE_READ_FLAG,
-					QUERY_FLAG_IDN_FDEVICEINIT, &flag_res);
-			if (!err || err == -ETIMEDOUT)
-				break;
-			dev_dbg(hba->dev, "%s: error %d retrying\n", __func__,
-					err);
-		}
-	}
+	/* poll for max. 1000 iterations for fDeviceInit flag to clear */
+	for (i = 0; i < 1000 && !err && flag_res; i++)
+		err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG,
+			QUERY_FLAG_IDN_FDEVICEINIT, &flag_res);
+
 	if (err)
 		dev_err(hba->dev,
 			"%s reading fDeviceInit flag failed with error %d\n",
@@ -3433,7 +3444,7 @@ static int ufshcd_enable_auto_bkops(struct ufs_hba *hba)
 	if (hba->auto_bkops_enabled)
 		goto out;
 
-	err = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_SET_FLAG,
+	err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG,
 			QUERY_FLAG_IDN_BKOPS_EN, NULL);
 	if (err) {
 		dev_err(hba->dev, "%s: failed to enable bkops %d\n",
@@ -3482,7 +3493,7 @@ static int ufshcd_disable_auto_bkops(struct ufs_hba *hba)
 		goto out;
 	}
 
-	err = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_CLEAR_FLAG,
+	err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_CLEAR_FLAG,
 			QUERY_FLAG_IDN_BKOPS_EN, NULL);
 	if (err) {
 		dev_err(hba->dev, "%s: failed to disable bkops %d\n",
@@ -4453,8 +4464,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
 
 		/* clear any previous UFS device information */
 		memset(&hba->dev_info, 0, sizeof(hba->dev_info));
-		if (!ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG,
-				       QUERY_FLAG_IDN_PWR_ON_WPE, &flag))
+		if (!ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG,
+				QUERY_FLAG_IDN_PWR_ON_WPE, &flag))
 			hba->dev_info.f_power_on_wp_en = flag;
 
 		if (!hba->is_init_prefetch)
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 2570d94..f8ce680 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -3,6 +3,7 @@
  *
  * This code is based on drivers/scsi/ufs/ufshcd.h
  * Copyright (C) 2011-2013 Samsung India Software Operations
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *
  * Authors:
  *	Santosh Yaraganavi <santosh.sy@samsung.com>
@@ -681,6 +682,9 @@ static inline int ufshcd_dme_peer_get(struct ufs_hba *hba,
 	return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_PEER);
 }
 
+/* Expose Query-Request API */
+int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
+	enum flag_idn idn, bool *flag_res);
 int ufshcd_hold(struct ufs_hba *hba, bool async);
 void ufshcd_release(struct ufs_hba *hba);
 
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 12/15] scsi: ufs: reduce the interrupts for power mode change requests
  2015-10-27 10:44 [PATCH v5 00/15] Big fixes, retries, handle a race condition Yaniv Gardi
                   ` (10 preceding siblings ...)
  2015-10-27 10:44 ` [PATCH v5 11/15] scsi: ufs: retry failed query flag requests Yaniv Gardi
@ 2015-10-27 10:44 ` Yaniv Gardi
  2015-10-27 14:59   ` Gilad Broner
  2015-10-27 10:44 ` [PATCH v5 13/15] scsi: ufs: add missing memory barriers Yaniv Gardi
                   ` (3 subsequent siblings)
  15 siblings, 1 reply; 27+ messages in thread
From: Yaniv Gardi @ 2015-10-27 10:44 UTC (permalink / raw)
  To: robherring2, James.Bottomley, pebolle, hch
  Cc: linux-kernel, linux-scsi, linux-arm-msm, santoshsy,
	linux-scsi-owner, subhashj, ygardi, gbroner, draviv,
	Vinayak Holikatti, James E.J. Bottomley

DME commands such as Hibern8 enter/exit and gear switch generate 2
completion interrupts, one for confirmation that command is received
by local UniPro and 2nd one is the final confirmation after communication
with remote UniPro. Currently both of these completions are registered
as interrupt events which is not quite necessary and instead we can
just wait for the interrupt of 2nd completion, this should reduce
the number of interrupts and could reduce the unnecessary CPU wakeups
to handle extra interrupts.

Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>

---
 drivers/scsi/ufs/ufshcd.c | 41 +++++++++++++++++++++++++++--------------
 1 file changed, 27 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 889a7be..24a879d 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -987,13 +987,15 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
  * __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
  * @hba: per adapter instance
  * @uic_cmd: UIC command
+ * @completion: initialize the completion only if this is set to true
  *
  * Identical to ufshcd_send_uic_cmd() expect mutex. Must be called
  * with mutex held and host_lock locked.
  * Returns 0 only if success.
  */
 static int
-__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd,
+		      bool completion)
 {
 	if (!ufshcd_ready_for_uic_cmd(hba)) {
 		dev_err(hba->dev,
@@ -1001,7 +1003,8 @@ __ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
 		return -EIO;
 	}
 
-	init_completion(&uic_cmd->done);
+	if (completion)
+		init_completion(&uic_cmd->done);
 
 	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
 
@@ -1026,7 +1029,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
 	ufshcd_add_delay_before_dme_cmd(hba);
 
 	spin_lock_irqsave(hba->host->host_lock, flags);
-	ret = __ufshcd_send_uic_cmd(hba, uic_cmd);
+	ret = __ufshcd_send_uic_cmd(hba, uic_cmd, true);
 	spin_unlock_irqrestore(hba->host->host_lock, flags);
 	if (!ret)
 		ret = ufshcd_wait_for_uic_cmd(hba, uic_cmd);
@@ -2347,6 +2350,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd)
 	unsigned long flags;
 	u8 status;
 	int ret;
+	bool reenable_intr = false;
 
 	mutex_lock(&hba->uic_cmd_mutex);
 	init_completion(&uic_async_done);
@@ -2354,15 +2358,17 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd)
 
 	spin_lock_irqsave(hba->host->host_lock, flags);
 	hba->uic_async_done = &uic_async_done;
-	ret = __ufshcd_send_uic_cmd(hba, cmd);
-	spin_unlock_irqrestore(hba->host->host_lock, flags);
-	if (ret) {
-		dev_err(hba->dev,
-			"pwr ctrl cmd 0x%x with mode 0x%x uic error %d\n",
-			cmd->command, cmd->argument3, ret);
-		goto out;
+	if (ufshcd_readl(hba, REG_INTERRUPT_ENABLE) & UIC_COMMAND_COMPL) {
+		ufshcd_disable_intr(hba, UIC_COMMAND_COMPL);
+		/*
+		 * Make sure UIC command completion interrupt is disabled before
+		 * issuing UIC command.
+		 */
+		wmb();
+		reenable_intr = true;
 	}
-	ret = ufshcd_wait_for_uic_cmd(hba, cmd);
+	ret = __ufshcd_send_uic_cmd(hba, cmd, false);
+	spin_unlock_irqrestore(hba->host->host_lock, flags);
 	if (ret) {
 		dev_err(hba->dev,
 			"pwr ctrl cmd 0x%x with mode 0x%x uic error %d\n",
@@ -2388,7 +2394,10 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd)
 	}
 out:
 	spin_lock_irqsave(hba->host->host_lock, flags);
+	hba->active_uic_cmd = NULL;
 	hba->uic_async_done = NULL;
+	if (reenable_intr)
+		ufshcd_enable_intr(hba, UIC_COMMAND_COMPL);
 	spin_unlock_irqrestore(hba->host->host_lock, flags);
 	mutex_unlock(&hba->uic_cmd_mutex);
 
@@ -3813,16 +3822,20 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)
  */
 static irqreturn_t ufshcd_intr(int irq, void *__hba)
 {
-	u32 intr_status;
+	u32 intr_status, enabled_intr_status;
 	irqreturn_t retval = IRQ_NONE;
 	struct ufs_hba *hba = __hba;
 
 	spin_lock(hba->host->host_lock);
 	intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
+	enabled_intr_status =
+		intr_status & ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
 
-	if (intr_status) {
+	if (intr_status)
 		ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS);
-		ufshcd_sl_intr(hba, intr_status);
+
+	if (enabled_intr_status) {
+		ufshcd_sl_intr(hba, enabled_intr_status);
 		retval = IRQ_HANDLED;
 	}
 	spin_unlock(hba->host->host_lock);
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 13/15] scsi: ufs: add missing memory barriers
  2015-10-27 10:44 [PATCH v5 00/15] Big fixes, retries, handle a race condition Yaniv Gardi
                   ` (11 preceding siblings ...)
  2015-10-27 10:44 ` [PATCH v5 12/15] scsi: ufs: reduce the interrupts for power mode change requests Yaniv Gardi
@ 2015-10-27 10:44 ` Yaniv Gardi
  2015-10-27 10:44 ` [PATCH v5 14/15] scsi: ufs: commit descriptors before setting the doorbell Yaniv Gardi
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 27+ messages in thread
From: Yaniv Gardi @ 2015-10-27 10:44 UTC (permalink / raw)
  To: robherring2, James.Bottomley, pebolle, hch
  Cc: linux-kernel, linux-scsi, linux-arm-msm, santoshsy,
	linux-scsi-owner, subhashj, ygardi, gbroner, draviv,
	Vinayak Holikatti, James E.J. Bottomley

Performing several writes to UFS host controller registers has
no guarantee of ordering, so we must make sure register writes
to setup request list base address etc. are performed before the
run/stop register is enabled.
In addition, when setting up a task request, we must make sure
the updating of descriptors takes places before ringing the
doorbell, similarly to setting up a transfer request.

Signed-off-by: Gilad Broner <gbroner@codeaurora.org>
Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>

---
 drivers/scsi/ufs/ufshcd.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 24a879d..dfc4ac1 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -402,11 +402,9 @@ static inline int ufshcd_get_lists_status(u32 reg)
 	 *  1		UTRLRDY
 	 *  2		UTMRLRDY
 	 *  3		UCRDY
-	 *  4		HEI
-	 *  5		DEI
-	 * 6-7		reserved
+	 * 4-7		reserved
 	 */
-	return (((reg) & (0xFF)) >> 1) ^ (0x07);
+	return ((reg & 0xFF) >> 1) ^ 0x07;
 }
 
 /**
@@ -2727,7 +2725,7 @@ out:
  * To bring UFS host controller to operational state,
  * 1. Enable required interrupts
  * 2. Configure interrupt aggregation
- * 3. Program UTRL and UTMRL base addres
+ * 3. Program UTRL and UTMRL base address
  * 4. Configure run-stop-registers
  *
  * Returns 0 on success, non-zero value on failure
@@ -2757,8 +2755,13 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
 			REG_UTP_TASK_REQ_LIST_BASE_H);
 
 	/*
+	 * Make sure base address and interrupt setup are updated before
+	 * enabling the run/stop registers below.
+	 */
+	wmb();
+
+	/*
 	 * UCRDY, UTMRLDY and UTRLRDY bits must be 1
-	 * DEI, HEI bits must be 0
 	 */
 	reg = ufshcd_readl(hba, REG_CONTROLLER_STATUS);
 	if (!(ufshcd_get_lists_status(reg))) {
@@ -3921,6 +3924,10 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
 
 	/* send command to the controller */
 	__set_bit(free_slot, &hba->outstanding_tasks);
+
+	/* Make sure descriptors are ready before ringing the task doorbell */
+	wmb();
+
 	ufshcd_writel(hba, 1 << free_slot, REG_UTP_TASK_REQ_DOOR_BELL);
 
 	spin_unlock_irqrestore(host->host_lock, flags);
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 14/15] scsi: ufs: commit descriptors before setting the doorbell
  2015-10-27 10:44 [PATCH v5 00/15] Big fixes, retries, handle a race condition Yaniv Gardi
                   ` (12 preceding siblings ...)
  2015-10-27 10:44 ` [PATCH v5 13/15] scsi: ufs: add missing memory barriers Yaniv Gardi
@ 2015-10-27 10:44 ` Yaniv Gardi
  2015-10-27 10:44 ` [PATCH v5 15/15] scsi: ufs: add wrapper for retrying sending query attribute Yaniv Gardi
  2015-10-28 12:05 ` [PATCH v5 00/15] Big fixes, retries, handle a race condition Dolev Raviv
  15 siblings, 0 replies; 27+ messages in thread
From: Yaniv Gardi @ 2015-10-27 10:44 UTC (permalink / raw)
  To: robherring2, James.Bottomley, pebolle, hch
  Cc: linux-kernel, linux-scsi, linux-arm-msm, santoshsy,
	linux-scsi-owner, subhashj, ygardi, gbroner, draviv,
	Vinayak Holikatti, James E.J. Bottomley

Add a write memory barrier to make sure descriptors prepared are actually
written to memory before ringing the doorbell. We have also added the
write memory barrier after ringing the doorbell register so that
controller sees the new request immediately.

Signed-off-by: Gilad Broner <gbroner@codeaurora.org>
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>

---
 drivers/scsi/ufs/ufshcd.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index dfc4ac1..ec90504 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1628,6 +1628,8 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
 
 	hba->dev_cmd.complete = &wait;
 
+	/* Make sure descriptors are ready before ringing the doorbell */
+	wmb();
 	spin_lock_irqsave(hba->host->host_lock, flags);
 	ufshcd_send_command(hba, tag);
 	spin_unlock_irqrestore(hba->host->host_lock, flags);
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v5 15/15] scsi: ufs: add wrapper for retrying sending query attribute
  2015-10-27 10:44 [PATCH v5 00/15] Big fixes, retries, handle a race condition Yaniv Gardi
                   ` (13 preceding siblings ...)
  2015-10-27 10:44 ` [PATCH v5 14/15] scsi: ufs: commit descriptors before setting the doorbell Yaniv Gardi
@ 2015-10-27 10:44 ` Yaniv Gardi
  2015-10-27 15:00   ` Gilad Broner
  2015-10-28 12:05 ` [PATCH v5 00/15] Big fixes, retries, handle a race condition Dolev Raviv
  15 siblings, 1 reply; 27+ messages in thread
From: Yaniv Gardi @ 2015-10-27 10:44 UTC (permalink / raw)
  To: robherring2, James.Bottomley, pebolle, hch
  Cc: linux-kernel, linux-scsi, linux-arm-msm, santoshsy,
	linux-scsi-owner, subhashj, ygardi, gbroner, draviv,
	Vinayak Holikatti, James E.J. Bottomley

Sometimes queries from the device might return a failure so it is
recommended to retry sending the query, before giving up.
This change adds a wrapper to retry sending a query attribute,
in cases where we need to wait longer, before we continue,
or before reporting a failure.

Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>

---
 drivers/scsi/ufs/ufshcd.c | 51 ++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 44 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index ec90504..1d1e681 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1824,6 +1824,43 @@ out:
 }
 
 /**
+ * ufshcd_query_attr_retry() - API function for sending query
+ * attribute with retries
+ * @hba: per-adapter instance
+ * @opcode: attribute opcode
+ * @idn: attribute idn to access
+ * @index: index field
+ * @selector: selector field
+ * @attr_val: the attribute value after the query request
+ * completes
+ *
+ * Returns 0 for success, non-zero in case of failure
+*/
+static int ufshcd_query_attr_retry(struct ufs_hba *hba,
+	enum query_opcode opcode, enum attr_idn idn, u8 index, u8 selector,
+	u32 *attr_val)
+{
+	int ret = 0;
+	u32 retries;
+
+	 for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) {
+		ret = ufshcd_query_attr(hba, opcode, idn, index,
+						selector, attr_val);
+		if (ret)
+			dev_dbg(hba->dev, "%s: failed with error %d, retries %d\n",
+				__func__, ret, retries);
+		else
+			break;
+	}
+
+	if (ret)
+		dev_err(hba->dev,
+			"%s: query attribute, idn %d, failed with error %d after %d retires\n",
+			__func__, idn, ret, QUERY_REQ_RETRIES);
+	return ret;
+}
+
+/**
  * ufshcd_query_descriptor - API function for sending descriptor requests
  * hba: per-adapter instance
  * opcode: attribute opcode
@@ -3404,7 +3441,7 @@ static int ufshcd_disable_ee(struct ufs_hba *hba, u16 mask)
 
 	val = hba->ee_ctrl_mask & ~mask;
 	val &= 0xFFFF; /* 2 bytes */
-	err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
+	err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
 			QUERY_ATTR_IDN_EE_CONTROL, 0, 0, &val);
 	if (!err)
 		hba->ee_ctrl_mask &= ~mask;
@@ -3432,7 +3469,7 @@ static int ufshcd_enable_ee(struct ufs_hba *hba, u16 mask)
 
 	val = hba->ee_ctrl_mask | mask;
 	val &= 0xFFFF; /* 2 bytes */
-	err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
+	err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
 			QUERY_ATTR_IDN_EE_CONTROL, 0, 0, &val);
 	if (!err)
 		hba->ee_ctrl_mask |= mask;
@@ -3538,7 +3575,7 @@ static void  ufshcd_force_reset_auto_bkops(struct ufs_hba *hba)
 
 static inline int ufshcd_get_bkops_status(struct ufs_hba *hba, u32 *status)
 {
-	return ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
+	return ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
 			QUERY_ATTR_IDN_BKOPS_STATUS, 0, 0, status);
 }
 
@@ -3601,7 +3638,7 @@ static int ufshcd_urgent_bkops(struct ufs_hba *hba)
 
 static inline int ufshcd_get_ee_status(struct ufs_hba *hba, u32 *status)
 {
-	return ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
+	return ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
 			QUERY_ATTR_IDN_EE_STATUS, 0, 0, status);
 }
 
@@ -4355,9 +4392,9 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba)
 	dev_dbg(hba->dev, "%s: setting icc_level 0x%x",
 			__func__, hba->init_prefetch_data.icc_level);
 
-	ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
-			QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0,
-			&hba->init_prefetch_data.icc_level);
+	ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
+		QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0,
+		&hba->init_prefetch_data.icc_level);
 
 	if (ret)
 		dev_err(hba->dev,
-- 
1.8.5.2

-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 01/15] scsi: ufs: clear UTRD, UPIU req and rsp before new transfers
  2015-10-27 10:44 ` [PATCH v5 01/15] scsi: ufs: clear UTRD, UPIU req and rsp before new transfers Yaniv Gardi
@ 2015-10-27 14:53   ` Gilad Broner
  0 siblings, 0 replies; 27+ messages in thread
From: Gilad Broner @ 2015-10-27 14:53 UTC (permalink / raw)
  To: Yaniv Gardi
  Cc: robherring2, james.bottomley, pebolle, hch, linux-kernel,
	linux-scsi, linux-arm-msm, santoshsy, linux-scsi-owner, subhashj,
	ygardi, gbroner, draviv, Maya Erez, Vinayak Holikatti,
	James E.J. Bottomley

Looks OK.
Reviewed-by: Gilad Broner <gbroner@codeaurora.org>

> Clear the UFS data structures before sending new request.
>
> The SCSI command is sent to the device within the UFS UPIU request.
> As part of the transfer UPIU preparation, the SCSI command is copied
> to the UPIU structure according to the SCSI command size.
> As different SCSI commands differ in size from each other, we need
> to clear the whole SCSI command field to prevent sending uninitialized
> data to the device.
>
> The UPIU response doesn't always include the sense data and can differ
> in size.
> Hence, the UPIU response should also be cleared before the transfer.
>
> Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
> Signed-off-by: Maya Erez <merez@codeaurora.org>
> Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 17 +++++++++++++----
>  1 file changed, 13 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 131c720..3428f72 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -3,7 +3,7 @@
>   *
>   * This code is based on drivers/scsi/ufs/ufshcd.c
>   * Copyright (C) 2011-2013 Samsung India Software Operations
> - * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
>   *
>   * Authors:
>   *	Santosh Yaraganavi <santosh.sy@samsung.com>
> @@ -1035,6 +1035,7 @@ static int ufshcd_map_sg(struct ufshcd_lrb *lrbp)
>  				cpu_to_le32(lower_32_bits(sg->dma_address));
>  			prd_table[i].upper_addr =
>  				cpu_to_le32(upper_32_bits(sg->dma_address));
> +			prd_table[i].reserved = 0;
>  		}
>  	} else {
>  		lrbp->utr_descriptor_ptr->prd_table_length = 0;
> @@ -1117,7 +1118,8 @@ static void ufshcd_prepare_req_desc_hdr(struct
> ufshcd_lrb *lrbp,
>
>  	/* Transfer request descriptor header fields */
>  	req_desc->header.dword_0 = cpu_to_le32(dword_0);
> -
> +	/* dword_1 is reserved, hence it is set to 0 */
> +	req_desc->header.dword_1 = 0;
>  	/*
>  	 * assigning invalid value for command status. Controller
>  	 * updates OCS on command completion, with the command
> @@ -1125,6 +1127,8 @@ static void ufshcd_prepare_req_desc_hdr(struct
> ufshcd_lrb *lrbp,
>  	 */
>  	req_desc->header.dword_2 =
>  		cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
> +	/* dword_3 is reserved, hence it is set to 0 */
> +	req_desc->header.dword_3 = 0;
>  }
>
>  /**
> @@ -1137,6 +1141,7 @@ static
>  void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb *lrbp, u32
> upiu_flags)
>  {
>  	struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr;
> +	unsigned short cdb_len;
>
>  	/* command descriptor fields */
>  	ucd_req_ptr->header.dword_0 = UPIU_HEADER_DWORD(
> @@ -1151,8 +1156,12 @@ void ufshcd_prepare_utp_scsi_cmd_upiu(struct
> ufshcd_lrb *lrbp, u32 upiu_flags)
>  	ucd_req_ptr->sc.exp_data_transfer_len =
>  		cpu_to_be32(lrbp->cmd->sdb.length);
>
> -	memcpy(ucd_req_ptr->sc.cdb, lrbp->cmd->cmnd,
> -		(min_t(unsigned short, lrbp->cmd->cmd_len, MAX_CDB_SIZE)));
> +	cdb_len = min_t(unsigned short, lrbp->cmd->cmd_len, MAX_CDB_SIZE);
> +	memcpy(ucd_req_ptr->sc.cdb, lrbp->cmd->cmnd, cdb_len);
> +	if (cdb_len < MAX_CDB_SIZE)
> +		memset(ucd_req_ptr->sc.cdb + cdb_len, 0,
> +		       (MAX_CDB_SIZE - cdb_len));
> +	memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
>  }
>
>  /**
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 02/15] scsi: ufs: clear fields UTRD, UPIU req and rsp before new transfers
  2015-10-27 10:44 ` [PATCH v5 02/15] scsi: ufs: clear fields " Yaniv Gardi
@ 2015-10-27 14:55   ` Gilad Broner
  0 siblings, 0 replies; 27+ messages in thread
From: Gilad Broner @ 2015-10-27 14:55 UTC (permalink / raw)
  To: Yaniv Gardi
  Cc: robherring2, james.bottomley, pebolle, hch, linux-kernel,
	linux-scsi, linux-arm-msm, santoshsy, linux-scsi-owner, subhashj,
	ygardi, gbroner, draviv, Vinayak Holikatti, James E.J. Bottomley

Looks OK.
Reviewed-by: Gilad Broner <gbroner@codeaurora.org>

> Some of the data structures (like response UPIU) and/or its elements
> (unused fields) should be cleared before sending out the respective
> command to UFS device.
>
> This change clears the UPIU response data structure for query commands
> and NOP command before sending out the command. We also initialize the
> PRDT table length to zero which should take care of commands which doesn't
> have any data associated with it. We are also clearing the unused fields
> in
> request UPIU for NOP command.
>
> Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
> Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 3428f72..2d3ebca 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -1129,6 +1129,8 @@ static void ufshcd_prepare_req_desc_hdr(struct
> ufshcd_lrb *lrbp,
>  		cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
>  	/* dword_3 is reserved, hence it is set to 0 */
>  	req_desc->header.dword_3 = 0;
> +
> +	req_desc->prd_table_length = 0;
>  }
>
>  /**
> @@ -1198,6 +1200,7 @@ static void ufshcd_prepare_utp_query_req_upiu(struct
> ufs_hba *hba,
>  	if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC)
>  		memcpy(descp, query->descriptor, len);
>
> +	memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
>  }
>
>  static inline void ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp)
> @@ -1210,6 +1213,11 @@ static inline void
> ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp)
>  	ucd_req_ptr->header.dword_0 =
>  		UPIU_HEADER_DWORD(
>  			UPIU_TRANSACTION_NOP_OUT, 0, 0, lrbp->task_tag);
> +	/* clear rest of the fields of basic header */
> +	ucd_req_ptr->header.dword_1 = 0;
> +	ucd_req_ptr->header.dword_2 = 0;
> +
> +	memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
>  }
>
>  /**
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 04/15] scsi: ufs: clear outstanding_request bit in case query timeout
  2015-10-27 10:44 ` [PATCH v5 04/15] scsi: ufs: clear outstanding_request bit in case query timeout Yaniv Gardi
@ 2015-10-27 14:56   ` Gilad Broner
  0 siblings, 0 replies; 27+ messages in thread
From: Gilad Broner @ 2015-10-27 14:56 UTC (permalink / raw)
  To: Yaniv Gardi
  Cc: robherring2, james.bottomley, pebolle, hch, linux-kernel,
	linux-scsi, linux-arm-msm, santoshsy, linux-scsi-owner, subhashj,
	ygardi, gbroner, draviv, Vinayak Holikatti, James E.J. Bottomley

Reviewed-by: Gilad Broner <gbroner@codeaurora.org>

> When sending a query to the device returns with a timeout error,
> we clear the corresponding bit in the DOORBELL register but
> we don't clear the outstanding_request field as we should.
> This patch fixes this bug.
>
> Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 22 ++++++++++++++++++++--
>  1 file changed, 20 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 8860a57..e0b8755 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -364,6 +364,16 @@ static inline void ufshcd_utrl_clear(struct ufs_hba
> *hba, u32 pos)
>  }
>
>  /**
> + * ufshcd_outstanding_req_clear - Clear a bit in outstanding request
> field
> + * @hba: per adapter instance
> + * @tag: position of the bit to be cleared
> + */
> +static inline void ufshcd_outstanding_req_clear(struct ufs_hba *hba, int
> tag)
> +{
> +	__clear_bit(tag, &hba->outstanding_reqs);
> +}
> +
> +/**
>   * ufshcd_get_lists_status - Check UCRDY, UTRLRDY and UTMRLRDY
>   * @reg: Register value of host controller status
>   *
> @@ -1502,9 +1512,17 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba
> *hba,
>
>  	if (!time_left) {
>  		err = -ETIMEDOUT;
> +		dev_dbg(hba->dev, "%s: dev_cmd request timedout, tag %d\n",
> +			__func__, lrbp->task_tag);
>  		if (!ufshcd_clear_cmd(hba, lrbp->task_tag))
> -			/* sucessfully cleared the command, retry if needed */
> +			/* successfully cleared the command, retry if needed */
>  			err = -EAGAIN;
> +		/*
> +		 * in case of an error, after clearing the doorbell,
> +		 * we also need to clear the outstanding_request
> +		 * field in hba
> +		 */
> +		ufshcd_outstanding_req_clear(hba, lrbp->task_tag);
>  	}
>
>  	return err;
> @@ -3942,7 +3960,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
>  	scsi_dma_unmap(cmd);
>
>  	spin_lock_irqsave(host->host_lock, flags);
> -	__clear_bit(tag, &hba->outstanding_reqs);
> +	ufshcd_outstanding_req_clear(hba, tag);
>  	hba->lrb[tag].cmd = NULL;
>  	spin_unlock_irqrestore(host->host_lock, flags);
>
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 05/15] scsi: ufs: increase fDeviceInit query response timeout
  2015-10-27 10:44 ` [PATCH v5 05/15] scsi: ufs: increase fDeviceInit query response timeout Yaniv Gardi
@ 2015-10-27 14:56   ` Gilad Broner
  0 siblings, 0 replies; 27+ messages in thread
From: Gilad Broner @ 2015-10-27 14:56 UTC (permalink / raw)
  To: Yaniv Gardi
  Cc: robherring2, james.bottomley, pebolle, hch, linux-kernel,
	linux-scsi, linux-arm-msm, santoshsy, linux-scsi-owner, subhashj,
	ygardi, gbroner, draviv, Vinayak Holikatti, James E.J. Bottomley

Reviewed-by: Gilad Broner <gbroner@codeaurora.org>

> fDeviceInit query response time for some devices is too long that default
> query request timeout of 100ms may not be enough. Experiments show that
> fDeviceInit response sometimes takes 500ms so to be on safer side this
> change sets the timeout to 600ms. Without this change, we might
> unnecessarily have to retry fDeviceInit query requests multiple times and
> each query request timeout prints one error message.
>
> Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
> Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 12 +++++++++++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index e0b8755..573a8cb 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -58,6 +58,12 @@
>  #define QUERY_REQ_RETRIES 10
>  /* Query request timeout */
>  #define QUERY_REQ_TIMEOUT 30 /* msec */
> +/*
> + * Query request timeout for fDeviceInit flag
> + * fDeviceInit query response time for some devices is too large that
> default
> + * QUERY_REQ_TIMEOUT may not be enough for such devices.
> + */
> +#define QUERY_FDEVICEINIT_REQ_TIMEOUT 600 /* msec */
>
>  /* Task management command timeout */
>  #define TM_CMD_TIMEOUT	100 /* msecs */
> @@ -1651,6 +1657,7 @@ static int ufshcd_query_flag(struct ufs_hba *hba,
> enum query_opcode opcode,
>  	struct ufs_query_req *request = NULL;
>  	struct ufs_query_res *response = NULL;
>  	int err, index = 0, selector = 0;
> +	int timeout = QUERY_REQ_TIMEOUT;
>
>  	BUG_ON(!hba);
>
> @@ -1683,7 +1690,10 @@ static int ufshcd_query_flag(struct ufs_hba *hba,
> enum query_opcode opcode,
>  		goto out_unlock;
>  	}
>
> -	err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT);
> +	if (idn == QUERY_FLAG_IDN_FDEVICEINIT)
> +		timeout = QUERY_FDEVICEINIT_REQ_TIMEOUT;
> +
> +	err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, timeout);
>
>  	if (err) {
>  		dev_err(hba->dev,
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 06/15] scsi: ufs: avoid exception event handler racing with PM callbacks
  2015-10-27 10:44 ` [PATCH v5 06/15] scsi: ufs: avoid exception event handler racing with PM callbacks Yaniv Gardi
@ 2015-10-27 14:57   ` Gilad Broner
  0 siblings, 0 replies; 27+ messages in thread
From: Gilad Broner @ 2015-10-27 14:57 UTC (permalink / raw)
  To: Yaniv Gardi
  Cc: robherring2, james.bottomley, pebolle, hch, linux-kernel,
	linux-scsi, linux-arm-msm, santoshsy, linux-scsi-owner, subhashj,
	ygardi, gbroner, draviv, Vinayak Holikatti, James E.J. Bottomley

Reviewed-by: Gilad Broner <gbroner@codeaurora.org>

> If device raises the exception event in the response to the commands
> sent during the runtime/system PM callbacks, exception event handler
> might run in parallel with PM callbacks and may see unclocked register
> accesses. This change fixes this issue by not scheduling the exception
> event handler while PM callbacks are running.
>
> Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
> Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 15 ++++++++++++++-
>  1 file changed, 14 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 573a8cb..0e54183 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -3145,7 +3145,20 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,
> struct ufshcd_lrb *lrbp)
>  			scsi_status = result & MASK_SCSI_STATUS;
>  			result = ufshcd_scsi_cmd_status(lrbp, scsi_status);
>
> -			if (ufshcd_is_exception_event(lrbp->ucd_rsp_ptr))
> +			/*
> +			 * Currently we are only supporting BKOPs exception
> +			 * events hence we can ignore BKOPs exception event
> +			 * during power management callbacks. BKOPs exception
> +			 * event is not expected to be raised in runtime suspend
> +			 * callback as it allows the urgent bkops.
> +			 * During system suspend, we are anyway forcefully
> +			 * disabling the bkops and if urgent bkops is needed
> +			 * it will be enabled on system resume. Long term
> +			 * solution could be to abort the system suspend if
> +			 * UFS device needs urgent BKOPs.
> +			 */
> +			if (!hba->pm_op_in_progress &&
> +			    ufshcd_is_exception_event(lrbp->ucd_rsp_ptr))
>  				schedule_work(&hba->eeh_work);
>  			break;
>  		case UPIU_TRANSACTION_REJECT_UPIU:
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 08/15] scsi: ufs: add retries to dme_peer get and set attribute
  2015-10-27 10:44 ` [PATCH v5 08/15] scsi: ufs: add retries to dme_peer get and set attribute Yaniv Gardi
@ 2015-10-27 14:58   ` Gilad Broner
  0 siblings, 0 replies; 27+ messages in thread
From: Gilad Broner @ 2015-10-27 14:58 UTC (permalink / raw)
  To: Yaniv Gardi
  Cc: robherring2, james.bottomley, pebolle, hch, linux-kernel,
	linux-scsi, linux-arm-msm, santoshsy, linux-scsi-owner, subhashj,
	ygardi, gbroner, draviv, Lee Susman, Vinayak Holikatti,
	James E.J. Bottomley

Reviewed-by: Gilad Broner <gbroner@codeaurora.org>

> The dme_peer get/set attribute commands are prone to errors, therefore
> we add three retries for the UIC command sending.
> Error code returned from ufshcd_send_uic_cmd() is checked, and unless
> it was successful or the retries have finished, another command will be
> sent.
>
> Signed-off-by: Lee Susman <lsusman@codeaurora.org>
> Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 40 +++++++++++++++++++++++++++++-----------
>  1 file changed, 29 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 8a04691..5005d12 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -70,6 +70,9 @@
>  /* Task management command timeout */
>  #define TM_CMD_TIMEOUT	100 /* msecs */
>
> +/* maximum number of retries for a general UIC command  */
> +#define UFS_UIC_COMMAND_RETRIES 3
> +
>  /* maximum number of link-startup retries */
>  #define DME_LINKSTARTUP_RETRIES 3
>
> @@ -2185,6 +2188,7 @@ int ufshcd_dme_set_attr(struct ufs_hba *hba, u32
> attr_sel,
>  	};
>  	const char *set = action[!!peer];
>  	int ret;
> +	int retries = UFS_UIC_COMMAND_RETRIES;
>
>  	uic_cmd.command = peer ?
>  		UIC_CMD_DME_PEER_SET : UIC_CMD_DME_SET;
> @@ -2192,10 +2196,18 @@ int ufshcd_dme_set_attr(struct ufs_hba *hba, u32
> attr_sel,
>  	uic_cmd.argument2 = UIC_ARG_ATTR_TYPE(attr_set);
>  	uic_cmd.argument3 = mib_val;
>
> -	ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
> -	if (ret)
> -		dev_err(hba->dev, "%s: attr-id 0x%x val 0x%x error code %d\n",
> -			set, UIC_GET_ATTR_ID(attr_sel), mib_val, ret);
> +	do {
> +		/* for peer attributes we retry upon failure */
> +		ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
> +		if (ret)
> +			dev_dbg(hba->dev, "%s: attr-id 0x%x val 0x%x error code %d\n",
> +				set, UIC_GET_ATTR_ID(attr_sel), mib_val, ret);
> +	} while (ret && peer && --retries);
> +
> +	if (!retries)
> +		dev_err(hba->dev, "%s: attr-id 0x%x val 0x%x failed %d retries\n",
> +				set, UIC_GET_ATTR_ID(attr_sel), mib_val,
> +				retries);
>
>  	return ret;
>  }
> @@ -2220,6 +2232,7 @@ int ufshcd_dme_get_attr(struct ufs_hba *hba, u32
> attr_sel,
>  	};
>  	const char *get = action[!!peer];
>  	int ret;
> +	int retries = UFS_UIC_COMMAND_RETRIES;
>  	struct ufs_pa_layer_attr orig_pwr_info;
>  	struct ufs_pa_layer_attr temp_pwr_info;
>  	bool pwr_mode_change = false;
> @@ -2250,14 +2263,19 @@ int ufshcd_dme_get_attr(struct ufs_hba *hba, u32
> attr_sel,
>  		UIC_CMD_DME_PEER_GET : UIC_CMD_DME_GET;
>  	uic_cmd.argument1 = attr_sel;
>
> -	ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
> -	if (ret) {
> -		dev_err(hba->dev, "%s: attr-id 0x%x error code %d\n",
> -			get, UIC_GET_ATTR_ID(attr_sel), ret);
> -		goto out;
> -	}
> +	do {
> +		/* for peer attributes we retry upon failure */
> +		ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
> +		if (ret)
> +			dev_dbg(hba->dev, "%s: attr-id 0x%x error code %d\n",
> +				get, UIC_GET_ATTR_ID(attr_sel), ret);
> +	} while (ret && peer && --retries);
> +
> +	if (!retries)
> +		dev_err(hba->dev, "%s: attr-id 0x%x failed %d retries\n",
> +				get, UIC_GET_ATTR_ID(attr_sel), retries);
>
> -	if (mib_val)
> +	if (mib_val && !ret)
>  		*mib_val = uic_cmd.argument3;
>
>  	if (peer && (hba->quirks & UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE)
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 09/15] scsi: ufs: add retries for hibern8 enter
  2015-10-27 10:44 ` [PATCH v5 09/15] scsi: ufs: add retries for hibern8 enter Yaniv Gardi
@ 2015-10-27 14:59   ` Gilad Broner
  0 siblings, 0 replies; 27+ messages in thread
From: Gilad Broner @ 2015-10-27 14:59 UTC (permalink / raw)
  To: Yaniv Gardi
  Cc: robherring2, james.bottomley, pebolle, hch, linux-kernel,
	linux-scsi, linux-arm-msm, santoshsy, linux-scsi-owner, subhashj,
	ygardi, gbroner, draviv, Vinayak Holikatti, James E.J. Bottomley

Reviewed-by: Gilad Broner <gbroner@codeaurora.org>

> If hibern8 enter command fails then UFS link state may be unknown which
> may result into timeout of all the commands issued after failure.
>
> This change does 2 things (for pre-defined number of retry counts) after
> hibern8 enter failure:
> 1. Recovers the UFS link to active state
> 2. If link is recovered to active state, tries to put the UFS link in
>    hibern8 enter again until retry count expires.
>
> Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
> Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 26 ++++++++++++++++++++++++--
>  1 file changed, 24 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 5005d12..ed134d6 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -76,6 +76,9 @@
>  /* maximum number of link-startup retries */
>  #define DME_LINKSTARTUP_RETRIES 3
>
> +/* Maximum retries for Hibern8 enter */
> +#define UIC_HIBERN8_ENTER_RETRIES 3
> +
>  /* maximum number of reset retries before giving up */
>  #define MAX_HOST_RESET_RETRIES 5
>
> @@ -2390,13 +2393,32 @@ out:
>  	return ret;
>  }
>
> -static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
> +static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
>  {
> +	int ret;
>  	struct uic_command uic_cmd = {0};
>
>  	uic_cmd.command = UIC_CMD_DME_HIBER_ENTER;
> +	ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
> +
> +	if (ret)
> +		dev_err(hba->dev, "%s: hibern8 enter failed. ret = %d\n",
> +			__func__, ret);
> +
> +	return ret;
> +}
> +
> +static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
> +{
> +	int ret = 0, retries;
>
> -	return ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
> +	for (retries = UIC_HIBERN8_ENTER_RETRIES; retries > 0; retries--) {
> +		ret = __ufshcd_uic_hibern8_enter(hba);
> +		if (!ret || ret == -ENOLINK)
> +			goto out;
> +	}
> +out:
> +	return ret;
>  }
>
>  static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba)
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 10/15] scsi: ufs: fix error recovery after the hibern8 exit failure
  2015-10-27 10:44 ` [PATCH v5 10/15] scsi: ufs: fix error recovery after the hibern8 exit failure Yaniv Gardi
@ 2015-10-27 14:59   ` Gilad Broner
  0 siblings, 0 replies; 27+ messages in thread
From: Gilad Broner @ 2015-10-27 14:59 UTC (permalink / raw)
  To: Yaniv Gardi
  Cc: robherring2, james.bottomley, pebolle, hch, linux-kernel,
	linux-scsi, linux-arm-msm, santoshsy, linux-scsi-owner, subhashj,
	ygardi, gbroner, draviv, Vinayak Holikatti, James E.J. Bottomley

Reviewed-by: Gilad Broner <gbroner@codeaurora.org>

> Hibern8 exit can be called from 3 different context:
>     - ufshcd_hibern8_exit_work
>     - ufshcd_ungate_work
>     - runtime/system resume
>
> If hibern8 exit fails for some reason then we try to bring the link to
> active state by link startup but this recovery mechanism results into
> deadlock or errors from first 2 context listed above. This change fixes
> the recovery by adding proper error handling mechanism.
>
> Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
> Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 58
> +++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 53 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index ed134d6..60ba729 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -610,6 +610,11 @@ int ufshcd_hold(struct ufs_hba *hba, bool async)
>  	spin_lock_irqsave(hba->host->host_lock, flags);
>  	hba->clk_gating.active_reqs++;
>
> +	if (ufshcd_eh_in_progress(hba)) {
> +		spin_unlock_irqrestore(hba->host->host_lock, flags);
> +		return 0;
> +	}
> +
>  start:
>  	switch (hba->clk_gating.state) {
>  	case CLKS_ON:
> @@ -725,7 +730,8 @@ static void __ufshcd_release(struct ufs_hba *hba)
>  	if (hba->clk_gating.active_reqs || hba->clk_gating.is_suspended
>  		|| hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL
>  		|| hba->lrb_in_use || hba->outstanding_tasks
> -		|| hba->active_uic_cmd || hba->uic_async_done)
> +		|| hba->active_uic_cmd || hba->uic_async_done
> +		|| ufshcd_eh_in_progress(hba))
>  		return;
>
>  	hba->clk_gating.state = REQ_CLKS_OFF;
> @@ -1363,6 +1369,13 @@ static int ufshcd_queuecommand(struct Scsi_Host
> *host, struct scsi_cmnd *cmd)
>  		cmd->scsi_done(cmd);
>  		goto out_unlock;
>  	}
> +
> +	/* if error handling is in progress, don't issue commands */
> +	if (ufshcd_eh_in_progress(hba)) {
> +		set_host_byte(cmd, DID_ERROR);
> +		cmd->scsi_done(cmd);
> +		goto out_unlock;
> +	}
>  	spin_unlock_irqrestore(hba->host->host_lock, flags);
>
>  	/* acquire the tag to make sure device cmds don't use it */
> @@ -2393,6 +2406,31 @@ out:
>  	return ret;
>  }
>
> +static int ufshcd_link_recovery(struct ufs_hba *hba)
> +{
> +	int ret;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(hba->host->host_lock, flags);
> +	hba->ufshcd_state = UFSHCD_STATE_RESET;
> +	ufshcd_set_eh_in_progress(hba);
> +	spin_unlock_irqrestore(hba->host->host_lock, flags);
> +
> +	ret = ufshcd_host_reset_and_restore(hba);
> +
> +	spin_lock_irqsave(hba->host->host_lock, flags);
> +	if (ret)
> +		hba->ufshcd_state = UFSHCD_STATE_ERROR;
> +	ufshcd_clear_eh_in_progress(hba);
> +	spin_unlock_irqrestore(hba->host->host_lock, flags);
> +
> +	if (ret)
> +		dev_err(hba->dev, "%s: link recovery failed, err %d",
> +			__func__, ret);
> +
> +	return ret;
> +}
> +
>  static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
>  {
>  	int ret;
> @@ -2401,10 +2439,18 @@ static int __ufshcd_uic_hibern8_enter(struct
> ufs_hba *hba)
>  	uic_cmd.command = UIC_CMD_DME_HIBER_ENTER;
>  	ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
>
> -	if (ret)
> +	if (ret) {
>  		dev_err(hba->dev, "%s: hibern8 enter failed. ret = %d\n",
>  			__func__, ret);
>
> +		/*
> +		 * If link recovery fails then return error so that caller
> +		 * don't retry the hibern8 enter again.
> +		 */
> +		if (ufshcd_link_recovery(hba))
> +			ret = -ENOLINK;
> +	}
> +
>  	return ret;
>  }
>
> @@ -2429,8 +2475,9 @@ static int ufshcd_uic_hibern8_exit(struct ufs_hba
> *hba)
>  	uic_cmd.command = UIC_CMD_DME_HIBER_EXIT;
>  	ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
>  	if (ret) {
> -		ufshcd_set_link_off(hba);
> -		ret = ufshcd_host_reset_and_restore(hba);
> +		dev_err(hba->dev, "%s: hibern8 exit failed. ret = %d\n",
> +			__func__, ret);
> +		ret = ufshcd_link_recovery(hba);
>  	}
>
>  	return ret;
> @@ -4382,7 +4429,6 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
>  	/* UFS device is also active now */
>  	ufshcd_set_ufs_dev_active(hba);
>  	ufshcd_force_reset_auto_bkops(hba);
> -	hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
>  	hba->wlun_dev_clr_ua = true;
>
>  	if (ufshcd_get_max_pwr_mode(hba)) {
> @@ -4396,6 +4442,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
>  					__func__, ret);
>  	}
>
> +	/* set the state as operational after switching to desired gear */
> +	hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
>  	/*
>  	 * If we are in error handling context or in power management callbacks
>  	 * context, no need to scan the host
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 12/15] scsi: ufs: reduce the interrupts for power mode change requests
  2015-10-27 10:44 ` [PATCH v5 12/15] scsi: ufs: reduce the interrupts for power mode change requests Yaniv Gardi
@ 2015-10-27 14:59   ` Gilad Broner
  0 siblings, 0 replies; 27+ messages in thread
From: Gilad Broner @ 2015-10-27 14:59 UTC (permalink / raw)
  To: Yaniv Gardi
  Cc: robherring2, james.bottomley, pebolle, hch, linux-kernel,
	linux-scsi, linux-arm-msm, santoshsy, linux-scsi-owner, subhashj,
	ygardi, gbroner, draviv, Vinayak Holikatti, James E.J. Bottomley

Reviewed-by: Gilad Broner <gbroner@codeaurora.org>

> DME commands such as Hibern8 enter/exit and gear switch generate 2
> completion interrupts, one for confirmation that command is received
> by local UniPro and 2nd one is the final confirmation after communication
> with remote UniPro. Currently both of these completions are registered
> as interrupt events which is not quite necessary and instead we can
> just wait for the interrupt of 2nd completion, this should reduce
> the number of interrupts and could reduce the unnecessary CPU wakeups
> to handle extra interrupts.
>
> Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
> Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 41 +++++++++++++++++++++++++++--------------
>  1 file changed, 27 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 889a7be..24a879d 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -987,13 +987,15 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct
> uic_command *uic_cmd)
>   * __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
>   * @hba: per adapter instance
>   * @uic_cmd: UIC command
> + * @completion: initialize the completion only if this is set to true
>   *
>   * Identical to ufshcd_send_uic_cmd() expect mutex. Must be called
>   * with mutex held and host_lock locked.
>   * Returns 0 only if success.
>   */
>  static int
> -__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
> +__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd,
> +		      bool completion)
>  {
>  	if (!ufshcd_ready_for_uic_cmd(hba)) {
>  		dev_err(hba->dev,
> @@ -1001,7 +1003,8 @@ __ufshcd_send_uic_cmd(struct ufs_hba *hba, struct
> uic_command *uic_cmd)
>  		return -EIO;
>  	}
>
> -	init_completion(&uic_cmd->done);
> +	if (completion)
> +		init_completion(&uic_cmd->done);
>
>  	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
>
> @@ -1026,7 +1029,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct
> uic_command *uic_cmd)
>  	ufshcd_add_delay_before_dme_cmd(hba);
>
>  	spin_lock_irqsave(hba->host->host_lock, flags);
> -	ret = __ufshcd_send_uic_cmd(hba, uic_cmd);
> +	ret = __ufshcd_send_uic_cmd(hba, uic_cmd, true);
>  	spin_unlock_irqrestore(hba->host->host_lock, flags);
>  	if (!ret)
>  		ret = ufshcd_wait_for_uic_cmd(hba, uic_cmd);
> @@ -2347,6 +2350,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba,
> struct uic_command *cmd)
>  	unsigned long flags;
>  	u8 status;
>  	int ret;
> +	bool reenable_intr = false;
>
>  	mutex_lock(&hba->uic_cmd_mutex);
>  	init_completion(&uic_async_done);
> @@ -2354,15 +2358,17 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba
> *hba, struct uic_command *cmd)
>
>  	spin_lock_irqsave(hba->host->host_lock, flags);
>  	hba->uic_async_done = &uic_async_done;
> -	ret = __ufshcd_send_uic_cmd(hba, cmd);
> -	spin_unlock_irqrestore(hba->host->host_lock, flags);
> -	if (ret) {
> -		dev_err(hba->dev,
> -			"pwr ctrl cmd 0x%x with mode 0x%x uic error %d\n",
> -			cmd->command, cmd->argument3, ret);
> -		goto out;
> +	if (ufshcd_readl(hba, REG_INTERRUPT_ENABLE) & UIC_COMMAND_COMPL) {
> +		ufshcd_disable_intr(hba, UIC_COMMAND_COMPL);
> +		/*
> +		 * Make sure UIC command completion interrupt is disabled before
> +		 * issuing UIC command.
> +		 */
> +		wmb();
> +		reenable_intr = true;
>  	}
> -	ret = ufshcd_wait_for_uic_cmd(hba, cmd);
> +	ret = __ufshcd_send_uic_cmd(hba, cmd, false);
> +	spin_unlock_irqrestore(hba->host->host_lock, flags);
>  	if (ret) {
>  		dev_err(hba->dev,
>  			"pwr ctrl cmd 0x%x with mode 0x%x uic error %d\n",
> @@ -2388,7 +2394,10 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba,
> struct uic_command *cmd)
>  	}
>  out:
>  	spin_lock_irqsave(hba->host->host_lock, flags);
> +	hba->active_uic_cmd = NULL;
>  	hba->uic_async_done = NULL;
> +	if (reenable_intr)
> +		ufshcd_enable_intr(hba, UIC_COMMAND_COMPL);
>  	spin_unlock_irqrestore(hba->host->host_lock, flags);
>  	mutex_unlock(&hba->uic_cmd_mutex);
>
> @@ -3813,16 +3822,20 @@ static void ufshcd_sl_intr(struct ufs_hba *hba,
> u32 intr_status)
>   */
>  static irqreturn_t ufshcd_intr(int irq, void *__hba)
>  {
> -	u32 intr_status;
> +	u32 intr_status, enabled_intr_status;
>  	irqreturn_t retval = IRQ_NONE;
>  	struct ufs_hba *hba = __hba;
>
>  	spin_lock(hba->host->host_lock);
>  	intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
> +	enabled_intr_status =
> +		intr_status & ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
>
> -	if (intr_status) {
> +	if (intr_status)
>  		ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS);
> -		ufshcd_sl_intr(hba, intr_status);
> +
> +	if (enabled_intr_status) {
> +		ufshcd_sl_intr(hba, enabled_intr_status);
>  		retval = IRQ_HANDLED;
>  	}
>  	spin_unlock(hba->host->host_lock);
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v5 15/15] scsi: ufs: add wrapper for retrying sending query attribute
  2015-10-27 10:44 ` [PATCH v5 15/15] scsi: ufs: add wrapper for retrying sending query attribute Yaniv Gardi
@ 2015-10-27 15:00   ` Gilad Broner
  0 siblings, 0 replies; 27+ messages in thread
From: Gilad Broner @ 2015-10-27 15:00 UTC (permalink / raw)
  To: Yaniv Gardi
  Cc: robherring2, james.bottomley, pebolle, hch, linux-kernel,
	linux-scsi, linux-arm-msm, santoshsy, linux-scsi-owner, subhashj,
	ygardi, gbroner, draviv, Vinayak Holikatti, James E.J. Bottomley

Reviewed-by: Gilad Broner <gbroner@codeaurora.org>

> Sometimes queries from the device might return a failure so it is
> recommended to retry sending the query, before giving up.
> This change adds a wrapper to retry sending a query attribute,
> in cases where we need to wait longer, before we continue,
> or before reporting a failure.
>
> Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 51
> ++++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 44 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index ec90504..1d1e681 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -1824,6 +1824,43 @@ out:
>  }
>
>  /**
> + * ufshcd_query_attr_retry() - API function for sending query
> + * attribute with retries
> + * @hba: per-adapter instance
> + * @opcode: attribute opcode
> + * @idn: attribute idn to access
> + * @index: index field
> + * @selector: selector field
> + * @attr_val: the attribute value after the query request
> + * completes
> + *
> + * Returns 0 for success, non-zero in case of failure
> +*/
> +static int ufshcd_query_attr_retry(struct ufs_hba *hba,
> +	enum query_opcode opcode, enum attr_idn idn, u8 index, u8 selector,
> +	u32 *attr_val)
> +{
> +	int ret = 0;
> +	u32 retries;
> +
> +	 for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) {
> +		ret = ufshcd_query_attr(hba, opcode, idn, index,
> +						selector, attr_val);
> +		if (ret)
> +			dev_dbg(hba->dev, "%s: failed with error %d, retries %d\n",
> +				__func__, ret, retries);
> +		else
> +			break;
> +	}
> +
> +	if (ret)
> +		dev_err(hba->dev,
> +			"%s: query attribute, idn %d, failed with error %d after %d
> retires\n",
> +			__func__, idn, ret, QUERY_REQ_RETRIES);
> +	return ret;
> +}
> +
> +/**
>   * ufshcd_query_descriptor - API function for sending descriptor requests
>   * hba: per-adapter instance
>   * opcode: attribute opcode
> @@ -3404,7 +3441,7 @@ static int ufshcd_disable_ee(struct ufs_hba *hba,
> u16 mask)
>
>  	val = hba->ee_ctrl_mask & ~mask;
>  	val &= 0xFFFF; /* 2 bytes */
> -	err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
> +	err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
>  			QUERY_ATTR_IDN_EE_CONTROL, 0, 0, &val);
>  	if (!err)
>  		hba->ee_ctrl_mask &= ~mask;
> @@ -3432,7 +3469,7 @@ static int ufshcd_enable_ee(struct ufs_hba *hba, u16
> mask)
>
>  	val = hba->ee_ctrl_mask | mask;
>  	val &= 0xFFFF; /* 2 bytes */
> -	err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
> +	err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
>  			QUERY_ATTR_IDN_EE_CONTROL, 0, 0, &val);
>  	if (!err)
>  		hba->ee_ctrl_mask |= mask;
> @@ -3538,7 +3575,7 @@ static void  ufshcd_force_reset_auto_bkops(struct
> ufs_hba *hba)
>
>  static inline int ufshcd_get_bkops_status(struct ufs_hba *hba, u32
> *status)
>  {
> -	return ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
> +	return ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
>  			QUERY_ATTR_IDN_BKOPS_STATUS, 0, 0, status);
>  }
>
> @@ -3601,7 +3638,7 @@ static int ufshcd_urgent_bkops(struct ufs_hba *hba)
>
>  static inline int ufshcd_get_ee_status(struct ufs_hba *hba, u32 *status)
>  {
> -	return ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
> +	return ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
>  			QUERY_ATTR_IDN_EE_STATUS, 0, 0, status);
>  }
>
> @@ -4355,9 +4392,9 @@ static void ufshcd_init_icc_levels(struct ufs_hba
> *hba)
>  	dev_dbg(hba->dev, "%s: setting icc_level 0x%x",
>  			__func__, hba->init_prefetch_data.icc_level);
>
> -	ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
> -			QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0,
> -			&hba->init_prefetch_data.icc_level);
> +	ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
> +		QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0,
> +		&hba->init_prefetch_data.icc_level);
>
>  	if (ret)
>  		dev_err(hba->dev,
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


^ permalink raw reply	[flat|nested] 27+ messages in thread

* RE: [PATCH v5 00/15] Big fixes, retries, handle a race condition
  2015-10-27 10:44 [PATCH v5 00/15] Big fixes, retries, handle a race condition Yaniv Gardi
                   ` (14 preceding siblings ...)
  2015-10-27 10:44 ` [PATCH v5 15/15] scsi: ufs: add wrapper for retrying sending query attribute Yaniv Gardi
@ 2015-10-28 12:05 ` Dolev Raviv
  15 siblings, 0 replies; 27+ messages in thread
From: Dolev Raviv @ 2015-10-28 12:05 UTC (permalink / raw)
  To: 'Yaniv Gardi', robherring2, James.Bottomley, pebolle, hch
  Cc: linux-kernel, linux-scsi, linux-arm-msm, santoshsy,
	linux-scsi-owner, subhashj, gbroner

Reviewed-by: Dolev Raviv <draviv@codeaurora.org>

Thanks,
Dolev
-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux
Foundation Collaborative Project

-----Original Message-----
From: Yaniv Gardi [mailto:ygardi@codeaurora.org] 
Sent: Tuesday, October 27, 2015 12:44 PM
To: robherring2@gmail.com; James.Bottomley@HansenPartnership.com;
pebolle@tiscali.nl; hch@infradead.org
Cc: linux-kernel@vger.kernel.org; linux-scsi@vger.kernel.org;
linux-arm-msm@vger.kernel.org; santoshsy@gmail.com;
linux-scsi-owner@vger.kernel.org; subhashj@codeaurora.org;
ygardi@codeaurora.org; gbroner@codeaurora.org; draviv@codeaurora.org
Subject: [PATCH v5 00/15] Big fixes, retries, handle a race condition

Important:
This serie of 15 small patches should be pushed after the series of 8
patches "Fix error message and present UFS variant probe"

V5:
removed un-necessary wmb()

V4:
fixing a few comments from reviewers

V3:
removed specific calls to wmb() since they are redundant.

V2:
a few minor changes

V1:
This serie of 15 small patches should be pushed after the series of 8
patches I have uploaded to the upstream a week ago:
"Fix error message and present UFS variant probe"

Yaniv Gardi (15):
  scsi: ufs: clear UTRD, UPIU req and rsp before new transfers
  scsi: ufs: clear fields UTRD, UPIU req and rsp before new transfers
  scsi: ufs: verify command tag validity
  scsi: ufs: clear outstanding_request bit in case query timeout
  scsi: ufs: increase fDeviceInit query response timeout
  scsi: ufs: avoid exception event handler racing with PM callbacks
  scsi: ufs: set REQUEST_SENSE command size to 18 bytes
  scsi: ufs: add retries to dme_peer get and set attribute
  scsi: ufs: add retries for hibern8 enter
  scsi: ufs: fix error recovery after the hibern8 exit failure
  scsi: ufs: retry failed query flag requests
  scsi: ufs: reduce the interrupts for power mode change requests
  scsi: ufs: add missing memory barriers
  scsi: ufs: commit descriptors before setting the doorbell
  scsi: ufs: add wrapper for retrying sending query attribute

 drivers/scsi/ufs/ufshcd.c | 408
++++++++++++++++++++++++++++++++++++----------
 drivers/scsi/ufs/ufshcd.h |   4 +
 2 files changed, 327 insertions(+), 85 deletions(-)

--
1.8.5.2

--
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2015-10-28 12:06 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-27 10:44 [PATCH v5 00/15] Big fixes, retries, handle a race condition Yaniv Gardi
2015-10-27 10:44 ` [PATCH v5 01/15] scsi: ufs: clear UTRD, UPIU req and rsp before new transfers Yaniv Gardi
2015-10-27 14:53   ` Gilad Broner
2015-10-27 10:44 ` [PATCH v5 02/15] scsi: ufs: clear fields " Yaniv Gardi
2015-10-27 14:55   ` Gilad Broner
2015-10-27 10:44 ` [PATCH v5 03/15] scsi: ufs: verify command tag validity Yaniv Gardi
2015-10-27 10:44 ` [PATCH v5 04/15] scsi: ufs: clear outstanding_request bit in case query timeout Yaniv Gardi
2015-10-27 14:56   ` Gilad Broner
2015-10-27 10:44 ` [PATCH v5 05/15] scsi: ufs: increase fDeviceInit query response timeout Yaniv Gardi
2015-10-27 14:56   ` Gilad Broner
2015-10-27 10:44 ` [PATCH v5 06/15] scsi: ufs: avoid exception event handler racing with PM callbacks Yaniv Gardi
2015-10-27 14:57   ` Gilad Broner
2015-10-27 10:44 ` [PATCH v5 07/15] scsi: ufs: set REQUEST_SENSE command size to 18 bytes Yaniv Gardi
2015-10-27 10:44 ` [PATCH v5 08/15] scsi: ufs: add retries to dme_peer get and set attribute Yaniv Gardi
2015-10-27 14:58   ` Gilad Broner
2015-10-27 10:44 ` [PATCH v5 09/15] scsi: ufs: add retries for hibern8 enter Yaniv Gardi
2015-10-27 14:59   ` Gilad Broner
2015-10-27 10:44 ` [PATCH v5 10/15] scsi: ufs: fix error recovery after the hibern8 exit failure Yaniv Gardi
2015-10-27 14:59   ` Gilad Broner
2015-10-27 10:44 ` [PATCH v5 11/15] scsi: ufs: retry failed query flag requests Yaniv Gardi
2015-10-27 10:44 ` [PATCH v5 12/15] scsi: ufs: reduce the interrupts for power mode change requests Yaniv Gardi
2015-10-27 14:59   ` Gilad Broner
2015-10-27 10:44 ` [PATCH v5 13/15] scsi: ufs: add missing memory barriers Yaniv Gardi
2015-10-27 10:44 ` [PATCH v5 14/15] scsi: ufs: commit descriptors before setting the doorbell Yaniv Gardi
2015-10-27 10:44 ` [PATCH v5 15/15] scsi: ufs: add wrapper for retrying sending query attribute Yaniv Gardi
2015-10-27 15:00   ` Gilad Broner
2015-10-28 12:05 ` [PATCH v5 00/15] Big fixes, retries, handle a race condition Dolev Raviv

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).