Linux SCSI subsystem development
 help / color / mirror / Atom feed
* [RFC PATCH v2 0/3] ufs: core: mcq: Add ufshcd_abort() support in MCQ mode
@ 2023-03-09  5:28 Bao D. Nguyen
  2023-03-09  5:28 ` [RFC PATCH v2 1/3] ufs: mcq: Add supporting functions for mcq abort Bao D. Nguyen
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Bao D. Nguyen @ 2023-03-09  5:28 UTC (permalink / raw)
  To: quic_asutoshd, quic_cang, bvanassche, mani, stanley.chu,
	adrian.hunter, beanhuo, avri.altman, martin.petersen
  Cc: linux-scsi, Bao D. Nguyen

This patch series enable support for ufshcd_abort() in MCQ mode.
The first patch is to prepare synchronization for ufshcd_abort() and interrupt contexts.
The second patch contains the supporting functions for ufshcd_abort().
The third and fourth patches add support for MCQ abort as discussed in the UFS
host controller spec.

Bao D. Nguyen (3):
  ufs: mcq: Add supporting functions for mcq abort
  ufs: mcq: Add support for clean up mcq resources
  ufs: mcq: Added ufshcd_mcq_abort()
---
v1->v2:
patch #1
  - Removed ufshcd_mcq_cqe_search()
  - Removed mcq_poll_ms from the hba. Replaced with MCQ_POLL_MS
patch #2
  - Changed the type of mask argument from u32 to unsigned long in function ufshcd_clear_cmds()
patch #3
  - Removed the ufshcd_mcq_cqe_search error case
---

 drivers/ufs/core/ufs-mcq.c     | 243 +++++++++++++++++++++++++++++++++++++++++
 drivers/ufs/core/ufshcd-priv.h |  17 +++
 drivers/ufs/core/ufshcd.c      |  55 ++++++++--
 include/ufs/ufshcd.h           |   1 +
 include/ufs/ufshci.h           |  16 +++
 5 files changed, 324 insertions(+), 8 deletions(-)

-- 
2.7.4


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

* [RFC PATCH v2 1/3] ufs: mcq: Add supporting functions for mcq abort
  2023-03-09  5:28 [RFC PATCH v2 0/3] ufs: core: mcq: Add ufshcd_abort() support in MCQ mode Bao D. Nguyen
@ 2023-03-09  5:28 ` Bao D. Nguyen
  2023-03-09  5:58   ` Adrian Hunter
  2023-03-09 18:15   ` Bart Van Assche
  2023-03-09  5:28 ` [RFC PATCH v2 2/3] ufs: mcq: Add support for clean up mcq resources Bao D. Nguyen
  2023-03-09  5:28 ` [RFC PATCH v2 3/3] ufs: mcq: Added ufshcd_mcq_abort() Bao D. Nguyen
  2 siblings, 2 replies; 9+ messages in thread
From: Bao D. Nguyen @ 2023-03-09  5:28 UTC (permalink / raw)
  To: quic_asutoshd, quic_cang, bvanassche, mani, stanley.chu,
	adrian.hunter, beanhuo, avri.altman, martin.petersen
  Cc: linux-scsi, Bao D. Nguyen, Alim Akhtar, James E.J. Bottomley,
	Arthur Simchaev, open list

Add supporting functions to handle ufs abort in mcq mode.

Signed-off-by: Bao D. Nguyen <quic_nguyenb@quicinc.com>
---
 drivers/ufs/core/ufs-mcq.c     | 181 +++++++++++++++++++++++++++++++++++++++++
 drivers/ufs/core/ufshcd-priv.h |  14 ++++
 drivers/ufs/core/ufshcd.c      |   3 +-
 include/ufs/ufshcd.h           |   1 +
 include/ufs/ufshci.h           |  16 ++++
 5 files changed, 214 insertions(+), 1 deletion(-)

diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c
index 31df052..4c33c1a 100644
--- a/drivers/ufs/core/ufs-mcq.c
+++ b/drivers/ufs/core/ufs-mcq.c
@@ -12,6 +12,9 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include "ufshcd-priv.h"
+#include <linux/delay.h>
+#include <scsi/scsi_cmnd.h>
+#include <linux/bitfield.h>
 
 #define MAX_QUEUE_SUP GENMASK(7, 0)
 #define UFS_MCQ_MIN_RW_QUEUES 2
@@ -27,6 +30,9 @@
 #define MCQ_ENTRY_SIZE_IN_DWORD	8
 #define CQE_UCD_BA GENMASK_ULL(63, 7)
 
+/* Max mcq register polling time in millisecond unit */
+#define MCQ_POLL_MS 500
+
 static int rw_queue_count_set(const char *val, const struct kernel_param *kp)
 {
 	return param_set_uint_minmax(val, kp, UFS_MCQ_MIN_RW_QUEUES,
@@ -429,3 +435,178 @@ int ufshcd_mcq_init(struct ufs_hba *hba)
 	host->host_tagset = 1;
 	return 0;
 }
+
+static int ufshcd_mcq_poll_register(void __iomem *reg, u32 mask,
+			u32 val, unsigned long timeout_ms)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
+	int err = 0;
+
+	/* ignore bits that we don't intend to wait on */
+	val = val & mask;
+
+	while ((readl(reg) & mask) != val) {
+		usleep_range(10, 50);
+		if (time_after(jiffies, timeout)) {
+			err = -ETIMEDOUT;
+			break;
+		}
+	}
+
+	return err;
+}
+
+static int ufshcd_mcq_sq_stop(struct ufs_hba *hba, struct ufs_hw_queue *hwq)
+{
+	void __iomem *reg;
+	u32 i = hwq->id;
+	int err;
+
+	writel(SQ_STOP, mcq_opr_base(hba, OPR_SQD, i) + REG_SQRTC);
+	reg = mcq_opr_base(hba, OPR_SQD, i) + REG_SQRTS;
+	err = ufshcd_mcq_poll_register(reg, SQ_STS, SQ_STS, MCQ_POLL_MS);
+	if (err)
+		dev_err(hba->dev, "%s: failed. hwq-id=%d, err=%d\n",
+			__func__, i, err);
+	return err;
+}
+
+static int ufshcd_mcq_sq_start(struct ufs_hba *hba, struct ufs_hw_queue *hwq)
+{
+	void __iomem *reg;
+	u32 i = hwq->id;
+	int err;
+
+	writel(SQ_START, mcq_opr_base(hba, OPR_SQD, i) + REG_SQRTC);
+	reg = mcq_opr_base(hba, OPR_SQD, i) + REG_SQRTS;
+	err = ufshcd_mcq_poll_register(reg, SQ_STS, 0, MCQ_POLL_MS);
+	if (err)
+		dev_err(hba->dev, "%s: failed. hwq-id=%d, err=%d\n",
+			__func__, i, err);
+	return err;
+}
+
+/**
+ * ufshcd_mcq_sq_cleanup - Clean up Submission Queue resources
+ * associated with the pending command.
+ * @hba - per adapter instance.
+ * @task_tag - The command's task tag.
+ * @result - Result of the Clean up operation.
+ *
+ * Returns 0 and result on completion. Returns error code if
+ * the operation fails.
+ */
+int ufshcd_mcq_sq_cleanup(struct ufs_hba *hba, int task_tag, int *result)
+{
+	struct ufshcd_lrb *lrbp = &hba->lrb[task_tag];
+	struct scsi_cmnd *cmd = lrbp->cmd;
+	struct ufs_hw_queue *hwq;
+	void __iomem *reg, *opr_sqd_base;
+	u32 nexus, i;
+	int err;
+
+	hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(cmd));
+	i = hwq->id;
+
+	spin_lock(&hwq->sq_lock);
+
+	/* stop the SQ fetching before working on it */
+	err = ufshcd_mcq_sq_stop(hba, hwq);
+	if (err)
+		goto unlock;
+
+	/* SQCTI = EXT_IID, IID, LUN, Task Tag */
+	nexus = lrbp->lun << 8 | task_tag;
+	opr_sqd_base = mcq_opr_base(hba, OPR_SQD, i);
+	writel(nexus, opr_sqd_base + REG_SQCTI);
+
+	/* SQRTCy.ICU = 1 */
+	writel(SQ_ICU, opr_sqd_base + REG_SQRTC);
+
+	/* Poll SQRTSy.CUS = 1. Return result from SQRTSy.RTC */
+	reg = opr_sqd_base + REG_SQRTS;
+	err = ufshcd_mcq_poll_register(reg, SQ_CUS, SQ_CUS, MCQ_POLL_MS);
+	if (err) {
+		dev_err(hba->dev, "%s: failed. hwq=%d, lun=0x%x, tag=%d\n",
+			__func__, i, lrbp->lun, task_tag);
+		*result = FIELD_GET(SQ_ICU_ERR_CODE_MASK, readl(reg));
+	}
+
+	err = ufshcd_mcq_sq_start(hba, hwq);
+
+unlock:
+	spin_unlock(&hwq->sq_lock);
+	return err;
+}
+
+static u64 ufshcd_mcq_get_cmd_desc_addr(struct ufs_hba *hba,
+					int task_tag)
+{
+	struct ufshcd_lrb *lrbp = &hba->lrb[task_tag];
+	__le32 hi = lrbp->utr_descriptor_ptr->command_desc_base_addr_hi;
+	__le32 lo = lrbp->utr_descriptor_ptr->command_desc_base_addr_lo;
+
+	return le64_to_cpu((__le64)hi << 32 | lo);
+}
+
+/**
+ * ufshcd_mcq_nullify_cmd - Nullify utrd. Host controller does not fetch
+ * transfer with Command Type = 0xF. post the Completion Queue with OCS=ABORTED.
+ * @hba - per adapter instance.
+ * @hwq - Hardware Queue of the nullified utrd.
+ */
+static void ufshcd_mcq_nullify_cmd(struct ufs_hba *hba, struct ufs_hw_queue *hwq)
+{
+	struct utp_transfer_req_desc *utrd;
+	u32 dword_0;
+
+	utrd = (struct utp_transfer_req_desc *)(hwq->sqe_base_addr +
+			hwq->id * sizeof(struct utp_transfer_req_desc));
+	dword_0 = le32_to_cpu(utrd->header.dword_0);
+	dword_0 &= ~UPIU_COMMAND_TYPE_MASK;
+	dword_0 |= FIELD_PREP(UPIU_COMMAND_TYPE_MASK, 0xF);
+	utrd->header.dword_0 = cpu_to_le32(dword_0);
+}
+
+/**
+ * ufshcd_mcq_sqe_search - Search for the cmd in the Submission Queue (SQ)
+ * @hba - per adapter instance.
+ * @hwq - Hardware Queue to be searched.
+ * @task_tag - The command's task tag.
+ *
+ * Returns true if the SQE containing the command is present in the SQ
+ * (not fetched by the controller); returns false if the SQE is not in the SQ.
+ */
+static bool ufshcd_mcq_sqe_search(struct ufs_hba *hba,
+		struct ufs_hw_queue *hwq, int task_tag)
+{
+	struct utp_transfer_req_desc *utrd;
+	u32 mask = hwq->max_entries - 1;
+	bool ret = false;
+	u64 addr, match;
+	u32 i;
+
+	spin_lock(&hwq->sq_lock);
+
+	ufshcd_mcq_update_sq_head_slot(hwq);
+	if (ufshcd_mcq_is_sq_empty(hwq))
+		goto out;
+
+	addr = ufshcd_mcq_get_cmd_desc_addr(hba, task_tag);
+	i = hwq->sq_head_slot;
+	while (i != hwq->sq_tail_slot) {
+		utrd = (struct utp_transfer_req_desc *)(hwq->sqe_base_addr +
+				i * sizeof(struct utp_transfer_req_desc));
+		match = le64_to_cpu((__le64)utrd->command_desc_base_addr_hi << 32 |
+				utrd->command_desc_base_addr_lo) & CQE_UCD_BA;
+		if (addr == match) {
+			ret = true;
+			goto out;
+		}
+		i = (i + 1) & mask;
+	}
+
+out:
+	spin_unlock(&hwq->sq_lock);
+	return ret;
+}
diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h
index 529f850..e25a852 100644
--- a/drivers/ufs/core/ufshcd-priv.h
+++ b/drivers/ufs/core/ufshcd-priv.h
@@ -78,6 +78,8 @@ struct ufs_hw_queue *ufshcd_mcq_req_to_hwq(struct ufs_hba *hba,
 unsigned long ufshcd_mcq_poll_cqe_lock(struct ufs_hba *hba,
 				       struct ufs_hw_queue *hwq);
 
+int ufshcd_mcq_sq_cleanup(struct ufs_hba *hba, int task_tag, int *result);
+
 #define UFSHCD_MCQ_IO_QUEUE_OFFSET	1
 #define SD_ASCII_STD true
 #define SD_RAW false
@@ -403,4 +405,16 @@ static inline struct cq_entry *ufshcd_mcq_cur_cqe(struct ufs_hw_queue *q)
 
 	return cqe + q->cq_head_slot;
 }
+
+static inline void ufshcd_mcq_update_sq_head_slot(struct ufs_hw_queue *q)
+{
+	u32 val = readl(q->mcq_sq_head);
+
+	q->sq_head_slot = val / sizeof(struct utp_transfer_req_desc);
+}
+
+static inline bool ufshcd_mcq_is_sq_empty(struct ufs_hw_queue *q)
+{
+	return q->sq_head_slot == q->sq_tail_slot;
+}
 #endif /* _UFSHCD_PRIV_H_ */
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 629442c..49a05909 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -56,7 +56,8 @@
 #define NOP_OUT_RETRIES    10
 /* Timeout after 50 msecs if NOP OUT hangs without response */
 #define NOP_OUT_TIMEOUT    50 /* msecs */
-
+/* Maximum MCQ registers polling time */
+#define MCQ_POLL_TIMEOUT   500
 /* Query request retries */
 #define QUERY_REQ_RETRIES 3
 /* Query request timeout */
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index 05e4164..6ee532e0 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -1105,6 +1105,7 @@ struct ufs_hw_queue {
 	u32 max_entries;
 	u32 id;
 	u32 sq_tail_slot;
+	u32 sq_head_slot;
 	spinlock_t sq_lock;
 	u32 cq_tail_slot;
 	u32 cq_head_slot;
diff --git a/include/ufs/ufshci.h b/include/ufs/ufshci.h
index 11424bb..252e731 100644
--- a/include/ufs/ufshci.h
+++ b/include/ufs/ufshci.h
@@ -99,6 +99,9 @@ enum {
 enum {
 	REG_SQHP		= 0x0,
 	REG_SQTP		= 0x4,
+	REG_SQRTC		= 0x8,
+	REG_SQCTI		= 0xC,
+	REG_SQRTS		= 0x10,
 };
 
 enum {
@@ -111,6 +114,19 @@ enum {
 	REG_CQIE		= 0x4,
 };
 
+enum {
+	SQ_START		= 0x0,
+	SQ_STOP			= 0x1,
+	SQ_ICU			= 0x2,
+};
+
+enum {
+	SQ_STS			= 0x1,
+	SQ_CUS			= 0x2,
+};
+
+#define SQ_ICU_ERR_CODE_MASK		GENMASK(7, 4)
+#define UPIU_COMMAND_TYPE_MASK		GENMASK(31, 28)
 #define UFS_MASK(mask, offset)		((mask) << (offset))
 
 /* UFS Version 08h */
-- 
2.7.4


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

* [RFC PATCH v2 2/3] ufs: mcq: Add support for clean up mcq resources
  2023-03-09  5:28 [RFC PATCH v2 0/3] ufs: core: mcq: Add ufshcd_abort() support in MCQ mode Bao D. Nguyen
  2023-03-09  5:28 ` [RFC PATCH v2 1/3] ufs: mcq: Add supporting functions for mcq abort Bao D. Nguyen
@ 2023-03-09  5:28 ` Bao D. Nguyen
  2023-03-09  5:28 ` [RFC PATCH v2 3/3] ufs: mcq: Added ufshcd_mcq_abort() Bao D. Nguyen
  2 siblings, 0 replies; 9+ messages in thread
From: Bao D. Nguyen @ 2023-03-09  5:28 UTC (permalink / raw)
  To: quic_asutoshd, quic_cang, bvanassche, mani, stanley.chu,
	adrian.hunter, beanhuo, avri.altman, martin.petersen
  Cc: linux-scsi, Bao D. Nguyen, Alim Akhtar, James E.J. Bottomley,
	open list

Update ufshcd_clear_cmds() to clean up the mcq resources similar
to the function ufshcd_utrl_clear() does for sdb mode.

Update ufshcd_try_to_abort_task() to support mcq mode so that
this function can be invoked in either mcq or sdb mode.

Signed-off-by: Bao D. Nguyen <quic_nguyenb@quicinc.com>
---
 drivers/ufs/core/ufshcd.c | 41 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 37 insertions(+), 4 deletions(-)

diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 49a05909..d29c096 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -2985,10 +2985,28 @@ static int ufshcd_compose_dev_cmd(struct ufs_hba *hba,
  * @mask and wait until the controller confirms that these requests have been
  * cleared.
  */
-static int ufshcd_clear_cmds(struct ufs_hba *hba, u32 mask)
+static int ufshcd_clear_cmds(struct ufs_hba *hba, unsigned long mask)
 {
 	unsigned long flags;
+	int err, result, tag;
 
+	if (is_mcq_enabled(hba)) {
+		/*
+		 * MCQ mode. Clean up the MCQ resources similar to
+		 * what the ufshcd_utrl_clear() does for SDB mode.
+		 */
+		for_each_set_bit(tag, &mask, hba->nutrs) {
+			err = ufshcd_mcq_sq_cleanup(hba, tag, &result);
+			if (err || result) {
+				dev_err(hba->dev, "%s: failed tag=%d. err=%d, result=%d\n",
+					__func__, tag, err, result);
+				return FAILED;
+			}
+		}
+		return 0;
+	}
+
+	/* Single Doorbell Mode */
 	/* clear outstanding transaction before retry */
 	spin_lock_irqsave(hba->host->host_lock, flags);
 	ufshcd_utrl_clear(hba, mask);
@@ -7344,6 +7362,20 @@ static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag)
 			 */
 			dev_err(hba->dev, "%s: cmd at tag %d not pending in the device.\n",
 				__func__, tag);
+			if (is_mcq_enabled(hba)) {
+				/* mcq mode */
+				if (!lrbp->cmd) {
+					/* command completed already */
+					dev_err(hba->dev, "%s: cmd at tag=%d is cleared.\n",
+						__func__, tag);
+					goto out;
+				}
+				/* sleep for max. 200us to stabilize */
+				usleep_range(100, 200);
+				continue;
+			}
+
+			/* single door bell mode */
 			reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
 			if (reg & (1 << tag)) {
 				/* sleep for max. 200us to stabilize */
@@ -7410,8 +7442,8 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
 
 	ufshcd_hold(hba, false);
 	reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
-	/* If command is already aborted/completed, return FAILED. */
-	if (!(test_bit(tag, &hba->outstanding_reqs))) {
+	if (!is_mcq_enabled(hba) && !(test_bit(tag, &hba->outstanding_reqs))) {
+		/* If command is already aborted/completed, return FAILED. */
 		dev_err(hba->dev,
 			"%s: cmd at tag %d already completed, outstanding=0x%lx, doorbell=0x%x\n",
 			__func__, tag, hba->outstanding_reqs, reg);
@@ -7440,7 +7472,8 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
 	}
 	hba->req_abort_count++;
 
-	if (!(reg & (1 << tag))) {
+	if (!is_mcq_enabled(hba) && !(reg & (1 << tag))) {
+		/* only execute this code in single doorbell mode */
 		dev_err(hba->dev,
 		"%s: cmd was completed, but without a notifying intr, tag = %d",
 		__func__, tag);
-- 
2.7.4


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

* [RFC PATCH v2 3/3] ufs: mcq: Added ufshcd_mcq_abort()
  2023-03-09  5:28 [RFC PATCH v2 0/3] ufs: core: mcq: Add ufshcd_abort() support in MCQ mode Bao D. Nguyen
  2023-03-09  5:28 ` [RFC PATCH v2 1/3] ufs: mcq: Add supporting functions for mcq abort Bao D. Nguyen
  2023-03-09  5:28 ` [RFC PATCH v2 2/3] ufs: mcq: Add support for clean up mcq resources Bao D. Nguyen
@ 2023-03-09  5:28 ` Bao D. Nguyen
  2 siblings, 0 replies; 9+ messages in thread
From: Bao D. Nguyen @ 2023-03-09  5:28 UTC (permalink / raw)
  To: quic_asutoshd, quic_cang, bvanassche, mani, stanley.chu,
	adrian.hunter, beanhuo, avri.altman, martin.petersen
  Cc: linux-scsi, Bao D. Nguyen, Alim Akhtar, James E.J. Bottomley,
	Arthur Simchaev, open list

Add ufshcd_mcq_abort() to support ufs abort in mcq mode.

Signed-off-by: Bao D. Nguyen <quic_nguyenb@quicinc.com>
---
 drivers/ufs/core/ufs-mcq.c     | 62 ++++++++++++++++++++++++++++++++++++++++++
 drivers/ufs/core/ufshcd-priv.h |  5 +++-
 drivers/ufs/core/ufshcd.c      | 11 ++++++--
 3 files changed, 74 insertions(+), 4 deletions(-)

diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c
index 4c33c1a..8d0019e 100644
--- a/drivers/ufs/core/ufs-mcq.c
+++ b/drivers/ufs/core/ufs-mcq.c
@@ -610,3 +610,65 @@ static bool ufshcd_mcq_sqe_search(struct ufs_hba *hba,
 	spin_unlock(&hwq->sq_lock);
 	return ret;
 }
+
+/**
+ * ufshcd_mcq_abort - Abort the command in MCQ.
+ * @cmd - The command to be aborted.
+ *
+ * Returns SUCCESS or FAILED error codes
+ */
+int ufshcd_mcq_abort(struct scsi_cmnd *cmd)
+{
+	struct Scsi_Host *host = cmd->device->host;
+	struct ufs_hba *hba = shost_priv(host);
+	int tag = scsi_cmd_to_rq(cmd)->tag;
+	struct ufshcd_lrb *lrbp = &hba->lrb[tag];
+	struct ufs_hw_queue *hwq;
+	int err = FAILED;
+
+	if (!lrbp->cmd) {
+		dev_err(hba->dev,
+			"%s: skip abort. cmd at tag %d already completed.\n",
+			__func__, tag);
+		goto out;
+	}
+
+	/* Skip task abort in case previous aborts failed and report failure */
+	if (lrbp->req_abort_skip) {
+		dev_err(hba->dev, "%s: skip abort. tag %d failed earlier\n",
+			__func__, tag);
+		goto out;
+	}
+
+	hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(cmd));
+
+	if (ufshcd_mcq_sqe_search(hba, hwq, tag)) {
+		/*
+		 * Failure. The command should not be "stuck" in SQ for
+		 * a long time which resulted in command being aborted.
+		 */
+		dev_err(hba->dev, "%s: cmd found in sq. hwq=%d, tag=%d\n",
+				__func__, hwq->id, tag);
+		/* Set the Command Type to 0xF per the spec */
+		ufshcd_mcq_nullify_cmd(hba, hwq);
+		goto out;
+	}
+
+	/*
+	 * The command is not in the Submission Queue, and it is not
+	 * in the Completion Queue either. Query the device to see if
+	 * the command is being processed in the device.
+	 */
+	if (ufshcd_try_to_abort_task(hba, tag)) {
+		dev_err(hba->dev, "%s: device abort failed %d\n", __func__, err);
+		lrbp->req_abort_skip = true;
+		goto out;
+	}
+
+	err = SUCCESS;
+	if (lrbp->cmd)
+		ufshcd_release_scsi_cmd(hba, lrbp);
+
+out:
+	return err;
+}
diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h
index e25a852..8b38568 100644
--- a/drivers/ufs/core/ufshcd-priv.h
+++ b/drivers/ufs/core/ufshcd-priv.h
@@ -79,7 +79,10 @@ unsigned long ufshcd_mcq_poll_cqe_lock(struct ufs_hba *hba,
 				       struct ufs_hw_queue *hwq);
 
 int ufshcd_mcq_sq_cleanup(struct ufs_hba *hba, int task_tag, int *result);
-
+int ufshcd_mcq_abort(struct scsi_cmnd *cmd);
+int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag);
+void ufshcd_release_scsi_cmd(struct ufs_hba *hba,
+				struct ufshcd_lrb *lrbp);
 #define UFSHCD_MCQ_IO_QUEUE_OFFSET	1
 #define SD_ASCII_STD true
 #define SD_RAW false
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index d29c096..f71a03d 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -302,7 +302,6 @@ static int ufshcd_setup_hba_vreg(struct ufs_hba *hba, bool on);
 static int ufshcd_setup_vreg(struct ufs_hba *hba, bool on);
 static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba,
 					 struct ufs_vreg *vreg);
-static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag);
 static void ufshcd_wb_toggle_buf_flush_during_h8(struct ufs_hba *hba,
 						 bool enable);
 static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba);
@@ -5413,7 +5412,7 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
 }
 
 /* Release the resources allocated for processing a SCSI command. */
-static void ufshcd_release_scsi_cmd(struct ufs_hba *hba,
+void ufshcd_release_scsi_cmd(struct ufs_hba *hba,
 				    struct ufshcd_lrb *lrbp)
 {
 	struct scsi_cmnd *cmd = lrbp->cmd;
@@ -7339,7 +7338,7 @@ static void ufshcd_set_req_abort_skip(struct ufs_hba *hba, unsigned long bitmap)
  *
  * Returns zero on success, non-zero on failure
  */
-static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag)
+int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag)
 {
 	struct ufshcd_lrb *lrbp = &hba->lrb[tag];
 	int err = 0;
@@ -7499,6 +7498,12 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
 		goto release;
 	}
 
+	if (is_mcq_enabled(hba)) {
+		/* MCQ mode. Branch off to handle abort for mcq mode */
+		err = ufshcd_mcq_abort(cmd);
+		goto release;
+	}
+
 	/* Skip task abort in case previous aborts failed and report failure */
 	if (lrbp->req_abort_skip) {
 		dev_err(hba->dev, "%s: skipping abort\n", __func__);
-- 
2.7.4


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

* Re: [RFC PATCH v2 1/3] ufs: mcq: Add supporting functions for mcq abort
  2023-03-09  5:28 ` [RFC PATCH v2 1/3] ufs: mcq: Add supporting functions for mcq abort Bao D. Nguyen
@ 2023-03-09  5:58   ` Adrian Hunter
  2023-03-09 18:15   ` Bart Van Assche
  1 sibling, 0 replies; 9+ messages in thread
From: Adrian Hunter @ 2023-03-09  5:58 UTC (permalink / raw)
  To: Bao D. Nguyen, quic_asutoshd, quic_cang, bvanassche, mani,
	stanley.chu, beanhuo, avri.altman, martin.petersen
  Cc: linux-scsi, Alim Akhtar, James E.J. Bottomley, Arthur Simchaev,
	open list

On 9/03/23 07:28, Bao D. Nguyen wrote:
> Add supporting functions to handle ufs abort in mcq mode.
> 
> Signed-off-by: Bao D. Nguyen <quic_nguyenb@quicinc.com>
> ---
>  drivers/ufs/core/ufs-mcq.c     | 181 +++++++++++++++++++++++++++++++++++++++++
>  drivers/ufs/core/ufshcd-priv.h |  14 ++++
>  drivers/ufs/core/ufshcd.c      |   3 +-
>  include/ufs/ufshcd.h           |   1 +
>  include/ufs/ufshci.h           |  16 ++++
>  5 files changed, 214 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c
> index 31df052..4c33c1a 100644
> --- a/drivers/ufs/core/ufs-mcq.c
> +++ b/drivers/ufs/core/ufs-mcq.c
> @@ -12,6 +12,9 @@
>  #include <linux/module.h>
>  #include <linux/platform_device.h>
>  #include "ufshcd-priv.h"
> +#include <linux/delay.h>
> +#include <scsi/scsi_cmnd.h>
> +#include <linux/bitfield.h>
>  
>  #define MAX_QUEUE_SUP GENMASK(7, 0)
>  #define UFS_MCQ_MIN_RW_QUEUES 2
> @@ -27,6 +30,9 @@
>  #define MCQ_ENTRY_SIZE_IN_DWORD	8
>  #define CQE_UCD_BA GENMASK_ULL(63, 7)
>  
> +/* Max mcq register polling time in millisecond unit */
> +#define MCQ_POLL_MS 500
> +
>  static int rw_queue_count_set(const char *val, const struct kernel_param *kp)
>  {
>  	return param_set_uint_minmax(val, kp, UFS_MCQ_MIN_RW_QUEUES,
> @@ -429,3 +435,178 @@ int ufshcd_mcq_init(struct ufs_hba *hba)
>  	host->host_tagset = 1;
>  	return 0;
>  }
> +
> +static int ufshcd_mcq_poll_register(void __iomem *reg, u32 mask,
> +			u32 val, unsigned long timeout_ms)
> +{
> +	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
> +	int err = 0;
> +
> +	/* ignore bits that we don't intend to wait on */
> +	val = val & mask;
> +
> +	while ((readl(reg) & mask) != val) {
> +		usleep_range(10, 50);
> +		if (time_after(jiffies, timeout)) {
> +			err = -ETIMEDOUT;
> +			break;
> +		}
> +	}

Should be able to use a macro from include/linux/iopoll.h
here

> +
> +	return err;
> +}



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

* Re: [RFC PATCH v2 1/3] ufs: mcq: Add supporting functions for mcq abort
  2023-03-09  5:28 ` [RFC PATCH v2 1/3] ufs: mcq: Add supporting functions for mcq abort Bao D. Nguyen
  2023-03-09  5:58   ` Adrian Hunter
@ 2023-03-09 18:15   ` Bart Van Assche
  2023-03-09 22:47     ` Bao D. Nguyen
  1 sibling, 1 reply; 9+ messages in thread
From: Bart Van Assche @ 2023-03-09 18:15 UTC (permalink / raw)
  To: Bao D. Nguyen, quic_asutoshd, quic_cang, mani, stanley.chu,
	adrian.hunter, beanhuo, avri.altman, martin.petersen
  Cc: linux-scsi, Alim Akhtar, James E.J. Bottomley, Arthur Simchaev,
	open list

On 3/8/23 21:28, Bao D. Nguyen wrote:
> +static bool ufshcd_mcq_sqe_search(struct ufs_hba *hba,
> +		struct ufs_hw_queue *hwq, int task_tag)
> +{
> +	struct utp_transfer_req_desc *utrd;
> +	u32 mask = hwq->max_entries - 1;
> +	bool ret = false;
> +	u64 addr, match;
> +	u32 i;

The variable name "i" is usually used for a loop index. In this case it 
represents a slot in the submission queue. How about renaming "i" into 
"slot"?

> +static inline void ufshcd_mcq_update_sq_head_slot(struct ufs_hw_queue *q)
> +{
> +	u32 val = readl(q->mcq_sq_head);
> +
> +	q->sq_head_slot = val / sizeof(struct utp_transfer_req_desc);
> +}

Please modify this function such that it returns the head slot value 
instead of storing it in a member variable and remove the sq_head_slot 
member variable. Storing the sq_head_slot value in a member variable 
seems wrong to me since the value of that variable will be outdated as 
soon as the submission queue is restarted.

> +static inline bool ufshcd_mcq_is_sq_empty(struct ufs_hw_queue *q)
> +{
> +	return q->sq_head_slot == q->sq_tail_slot;
> +}

Please remove this function and inline this function into its callers.

Thanks,

Bart.

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

* Re: [RFC PATCH v2 1/3] ufs: mcq: Add supporting functions for mcq abort
  2023-03-09 18:15   ` Bart Van Assche
@ 2023-03-09 22:47     ` Bao D. Nguyen
  2023-03-09 22:54       ` Bart Van Assche
  0 siblings, 1 reply; 9+ messages in thread
From: Bao D. Nguyen @ 2023-03-09 22:47 UTC (permalink / raw)
  To: Bart Van Assche, quic_asutoshd, quic_cang, mani, stanley.chu,
	adrian.hunter, beanhuo, avri.altman, martin.petersen
  Cc: linux-scsi, Alim Akhtar, James E.J. Bottomley, Arthur Simchaev,
	open list

On 3/9/2023 10:15 AM, Bart Van Assche wrote:
> On 3/8/23 21:28, Bao D. Nguyen wrote:
>> +static bool ufshcd_mcq_sqe_search(struct ufs_hba *hba,
>> +        struct ufs_hw_queue *hwq, int task_tag)
>> +{
>> +    struct utp_transfer_req_desc *utrd;
>> +    u32 mask = hwq->max_entries - 1;
>> +    bool ret = false;
>> +    u64 addr, match;
>> +    u32 i;
>
> The variable name "i" is usually used for a loop index. In this case 
> it represents a slot in the submission queue. How about renaming "i" 
> into "slot"?
I will make the change.
>
>> +static inline void ufshcd_mcq_update_sq_head_slot(struct 
>> ufs_hw_queue *q)
>> +{
>> +    u32 val = readl(q->mcq_sq_head);
>> +
>> +    q->sq_head_slot = val / sizeof(struct utp_transfer_req_desc);
>> +}
>
> Please modify this function such that it returns the head slot value 
> instead of storing it in a member variable and remove the sq_head_slot 
> member variable. Storing the sq_head_slot value in a member variable 
> seems wrong to me since the value of that variable will be outdated as 
> soon as the submission queue is restarted.
>
I can modify the function that I am introducing in this patch namely 
ufshcd_mcq_update_sq_head_slot() according to your suggestion.
However, to keep the original mcq code consistent with this change, 
should I make the same modifications to these existing functions 
ufshcd_mcq_update_cq_tail_slot(), ufshcd_mcq_update_cq_head() in a 
separate patch and include in this series?

>> +static inline bool ufshcd_mcq_is_sq_empty(struct ufs_hw_queue *q)
>> +{
>> +    return q->sq_head_slot == q->sq_tail_slot;
>> +}
>
> Please remove this function and inline this function into its callers.

Same comment. Should I also update the existing ufshcd_mcq_is_cq_empty() 
in a separate patch together with ufshcd_mcq_update_cq_tail_slot(), 
ufshcd_mcq_update_cq_head() mentioned above?

Thanks,

Bao

>
> Thanks,
>
> Bart.



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

* Re: [RFC PATCH v2 1/3] ufs: mcq: Add supporting functions for mcq abort
  2023-03-09 22:47     ` Bao D. Nguyen
@ 2023-03-09 22:54       ` Bart Van Assche
  2023-03-09 22:56         ` Bao D. Nguyen
  0 siblings, 1 reply; 9+ messages in thread
From: Bart Van Assche @ 2023-03-09 22:54 UTC (permalink / raw)
  To: Bao D. Nguyen, quic_asutoshd, quic_cang, mani, stanley.chu,
	adrian.hunter, beanhuo, avri.altman, martin.petersen
  Cc: linux-scsi, Alim Akhtar, James E.J. Bottomley, Arthur Simchaev,
	open list

On 3/9/23 14:47, Bao D. Nguyen wrote:
> On 3/9/2023 10:15 AM, Bart Van Assche wrote:
>> On 3/8/23 21:28, Bao D. Nguyen wrote:
>>> +static inline bool ufshcd_mcq_is_sq_empty(struct ufs_hw_queue *q)
>>> +{
>>> +    return q->sq_head_slot == q->sq_tail_slot;
>>> +}
>>
>> Please remove this function and inline this function into its callers.
> 
> Same comment. Should I also update the existing ufshcd_mcq_is_cq_empty() 
> in a separate patch together with ufshcd_mcq_update_cq_tail_slot(), 
> ufshcd_mcq_update_cq_head() mentioned above?

Hi Bao,

Modifying the existing code may improve uniformity of the UFS host 
controller driver. If any existing code is refactored, please do that 
via a separate patch.

Thanks,

Bart.


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

* Re: [RFC PATCH v2 1/3] ufs: mcq: Add supporting functions for mcq abort
  2023-03-09 22:54       ` Bart Van Assche
@ 2023-03-09 22:56         ` Bao D. Nguyen
  0 siblings, 0 replies; 9+ messages in thread
From: Bao D. Nguyen @ 2023-03-09 22:56 UTC (permalink / raw)
  To: Bart Van Assche, quic_asutoshd, quic_cang, mani, stanley.chu,
	adrian.hunter, beanhuo, avri.altman, martin.petersen
  Cc: linux-scsi, Alim Akhtar, James E.J. Bottomley, Arthur Simchaev,
	open list

On 3/9/2023 2:54 PM, Bart Van Assche wrote:
> On 3/9/23 14:47, Bao D. Nguyen wrote:
>> On 3/9/2023 10:15 AM, Bart Van Assche wrote:
>>> On 3/8/23 21:28, Bao D. Nguyen wrote:
>>>> +static inline bool ufshcd_mcq_is_sq_empty(struct ufs_hw_queue *q)
>>>> +{
>>>> +    return q->sq_head_slot == q->sq_tail_slot;
>>>> +}
>>>
>>> Please remove this function and inline this function into its callers.
>>
>> Same comment. Should I also update the existing 
>> ufshcd_mcq_is_cq_empty() in a separate patch together with 
>> ufshcd_mcq_update_cq_tail_slot(), ufshcd_mcq_update_cq_head() 
>> mentioned above?
>
> Hi Bao,
>
> Modifying the existing code may improve uniformity of the UFS host 
> controller driver. If any existing code is refactored, please do that 
> via a separate patch.
Thanks Bart. I will make that change in a separate patch.
>
> Thanks,
>
> Bart.
>


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

end of thread, other threads:[~2023-03-09 22:56 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-03-09  5:28 [RFC PATCH v2 0/3] ufs: core: mcq: Add ufshcd_abort() support in MCQ mode Bao D. Nguyen
2023-03-09  5:28 ` [RFC PATCH v2 1/3] ufs: mcq: Add supporting functions for mcq abort Bao D. Nguyen
2023-03-09  5:58   ` Adrian Hunter
2023-03-09 18:15   ` Bart Van Assche
2023-03-09 22:47     ` Bao D. Nguyen
2023-03-09 22:54       ` Bart Van Assche
2023-03-09 22:56         ` Bao D. Nguyen
2023-03-09  5:28 ` [RFC PATCH v2 2/3] ufs: mcq: Add support for clean up mcq resources Bao D. Nguyen
2023-03-09  5:28 ` [RFC PATCH v2 3/3] ufs: mcq: Added ufshcd_mcq_abort() Bao D. Nguyen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox