linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes
@ 2017-06-22  2:12 Uma Krishnan
  2017-06-22  2:13 ` [PATCH 01/17] cxlflash: Combine the send queue locks Uma Krishnan
                   ` (17 more replies)
  0 siblings, 18 replies; 28+ messages in thread
From: Uma Krishnan @ 2017-06-22  2:12 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

This patch series contains miscellaneous fixes and several enhancements
such as LUN provisioning support, WS16 unmap and AFU debug capabilities.

This series is intended for 4.13 and is bisectable.

Matthew R. Ochs (8):
  cxlflash: Separate AFU internal command handling from AFU sync
    specifics
  cxlflash: Introduce host ioctl support
  cxlflash: Refactor AFU capability checking
  cxlflash: Support LUN provisioning
  cxlflash: Support AFU debug
  cxlflash: Support WS16 unmap
  cxlflash: Remove zeroing of private command data
  cxlflash: Update TMF command processing

Uma Krishnan (9):
  cxlflash: Combine the send queue locks
  cxlflash: Update cxlflash_afu_sync() to return errno
  cxlflash: Reset hardware queue context via specified register
  cxlflash: Schedule asynchronous reset of the host
  cxlflash: Handle AFU sync failures
  cxlflash: Track pending scsi commands in each hardware queue
  cxlflash: Flush pending commands in cleanup path
  cxlflash: Add scsi command abort handler
  cxlflash: Create character device to provide host management interface

 Documentation/ioctl/ioctl-number.txt |    2 +-
 Documentation/powerpc/cxlflash.txt   |   76 ++-
 drivers/scsi/cxlflash/common.h       |   48 +-
 drivers/scsi/cxlflash/main.c         | 1008 ++++++++++++++++++++++++++++++----
 drivers/scsi/cxlflash/main.h         |    7 +
 drivers/scsi/cxlflash/sislite.h      |   27 +-
 drivers/scsi/cxlflash/superpipe.c    |   34 +-
 drivers/scsi/cxlflash/vlun.c         |   89 ++-
 include/uapi/scsi/cxlflash_ioctl.h   |   85 ++-
 9 files changed, 1217 insertions(+), 159 deletions(-)

-- 
2.1.0

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

* [PATCH 01/17] cxlflash: Combine the send queue locks
  2017-06-22  2:12 [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Uma Krishnan
@ 2017-06-22  2:13 ` Uma Krishnan
  2017-06-22 19:53   ` Matthew R. Ochs
  2017-06-22  2:13 ` [PATCH 02/17] cxlflash: Update cxlflash_afu_sync() to return errno Uma Krishnan
                   ` (16 subsequent siblings)
  17 siblings, 1 reply; 28+ messages in thread
From: Uma Krishnan @ 2017-06-22  2:13 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

Currently there are separate spin locks for the two supported I/O queueing
models. This makes it difficult to serialize with paths outside the enqueue
path.

As a design simplification and to support serialization with enqueue
operations, move to only a single lock that is used for enqueueing
regardless of the queueing model.

Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
---
 drivers/scsi/cxlflash/common.h | 3 +--
 drivers/scsi/cxlflash/main.c   | 9 +++++----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
index 256af81..6fc32cfc 100644
--- a/drivers/scsi/cxlflash/common.h
+++ b/drivers/scsi/cxlflash/common.h
@@ -193,7 +193,7 @@ struct hwq {
 	u32 index;		/* Index of this hwq */
 
 	atomic_t hsq_credits;
-	spinlock_t hsq_slock;
+	spinlock_t hsq_slock;	/* Hardware send queue lock */
 	struct sisl_ioarcb *hsq_start;
 	struct sisl_ioarcb *hsq_end;
 	struct sisl_ioarcb *hsq_curr;
@@ -204,7 +204,6 @@ struct hwq {
 	bool toggle;
 
 	s64 room;
-	spinlock_t rrin_slock; /* Lock to rrin queuing and cmd_room updates */
 
 	struct irq_poll irqpoll;
 } __aligned(cache_line_size());
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index a7d57c3..64ea597ca 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -261,7 +261,7 @@ static int send_cmd_ioarrin(struct afu *afu, struct afu_cmd *cmd)
 	 * To avoid the performance penalty of MMIO, spread the update of
 	 * 'room' over multiple commands.
 	 */
-	spin_lock_irqsave(&hwq->rrin_slock, lock_flags);
+	spin_lock_irqsave(&hwq->hsq_slock, lock_flags);
 	if (--hwq->room < 0) {
 		room = readq_be(&hwq->host_map->cmd_room);
 		if (room <= 0) {
@@ -277,7 +277,7 @@ static int send_cmd_ioarrin(struct afu *afu, struct afu_cmd *cmd)
 
 	writeq_be((u64)&cmd->rcb, &hwq->host_map->ioarrin);
 out:
-	spin_unlock_irqrestore(&hwq->rrin_slock, lock_flags);
+	spin_unlock_irqrestore(&hwq->hsq_slock, lock_flags);
 	dev_dbg(dev, "%s: cmd=%p len=%u ea=%016llx rc=%d\n", __func__,
 		cmd, cmd->rcb.data_len, cmd->rcb.data_ea, rc);
 	return rc;
@@ -1722,7 +1722,10 @@ static int start_afu(struct cxlflash_cfg *cfg)
 		hwq->hrrq_end = &hwq->rrq_entry[NUM_RRQ_ENTRY - 1];
 		hwq->hrrq_curr = hwq->hrrq_start;
 		hwq->toggle = 1;
+
+		/* Initialize spin locks */
 		spin_lock_init(&hwq->hrrq_slock);
+		spin_lock_init(&hwq->hsq_slock);
 
 		/* Initialize SQ */
 		if (afu_is_sq_cmd_mode(afu)) {
@@ -1731,7 +1734,6 @@ static int start_afu(struct cxlflash_cfg *cfg)
 			hwq->hsq_end = &hwq->sq[NUM_SQ_ENTRY - 1];
 			hwq->hsq_curr = hwq->hsq_start;
 
-			spin_lock_init(&hwq->hsq_slock);
 			atomic_set(&hwq->hsq_credits, NUM_SQ_ENTRY - 1);
 		}
 
@@ -1984,7 +1986,6 @@ static int init_afu(struct cxlflash_cfg *cfg)
 	for (i = 0; i < afu->num_hwqs; i++) {
 		hwq = get_hwq(afu, i);
 
-		spin_lock_init(&hwq->rrin_slock);
 		hwq->room = readq_be(&hwq->host_map->cmd_room);
 	}
 
-- 
2.1.0

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

* [PATCH 02/17] cxlflash: Update cxlflash_afu_sync() to return errno
  2017-06-22  2:12 [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Uma Krishnan
  2017-06-22  2:13 ` [PATCH 01/17] cxlflash: Combine the send queue locks Uma Krishnan
@ 2017-06-22  2:13 ` Uma Krishnan
  2017-06-22 19:54   ` Matthew R. Ochs
  2017-06-22  2:14 ` [PATCH 03/17] cxlflash: Reset hardware queue context via specified register Uma Krishnan
                   ` (15 subsequent siblings)
  17 siblings, 1 reply; 28+ messages in thread
From: Uma Krishnan @ 2017-06-22  2:13 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

The cxlflash_afu_sync() routine returns a negative one to indicate any kind
of failure. This makes it impossible to establish why the error occurred.

Update the return codes to clearly indicate the failure cause to the
caller.

Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
---
 drivers/scsi/cxlflash/main.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 64ea597ca..815d04b 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -2022,8 +2022,7 @@ static int init_afu(struct cxlflash_cfg *cfg)
  * going away).
  *
  * Return:
- *	0 on success
- *	-1 on failure
+ *	0 on success, -errno on failure
  */
 int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
 		      res_hndl_t res_hndl_u, u8 mode)
@@ -2047,7 +2046,7 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
 	buf = kzalloc(sizeof(*cmd) + __alignof__(*cmd) - 1, GFP_KERNEL);
 	if (unlikely(!buf)) {
 		dev_err(dev, "%s: no memory for command\n", __func__);
-		rc = -1;
+		rc = -ENOMEM;
 		goto out;
 	}
 
@@ -2071,12 +2070,14 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
 	*((__be32 *)&cmd->rcb.cdb[4]) = cpu_to_be32(res_hndl_u);
 
 	rc = afu->send_cmd(afu, cmd);
-	if (unlikely(rc))
+	if (unlikely(rc)) {
+		rc = -ENOBUFS;
 		goto out;
+	}
 
 	rc = wait_resp(afu, cmd);
 	if (unlikely(rc))
-		rc = -1;
+		rc = -EIO;
 out:
 	atomic_dec(&afu->cmds_active);
 	mutex_unlock(&sync_active);
-- 
2.1.0

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

* [PATCH 03/17] cxlflash: Reset hardware queue context via specified register
  2017-06-22  2:12 [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Uma Krishnan
  2017-06-22  2:13 ` [PATCH 01/17] cxlflash: Combine the send queue locks Uma Krishnan
  2017-06-22  2:13 ` [PATCH 02/17] cxlflash: Update cxlflash_afu_sync() to return errno Uma Krishnan
@ 2017-06-22  2:14 ` Uma Krishnan
  2017-06-22 19:54   ` Matthew R. Ochs
  2017-06-22  2:14 ` [PATCH 04/17] cxlflash: Schedule asynchronous reset of the host Uma Krishnan
                   ` (14 subsequent siblings)
  17 siblings, 1 reply; 28+ messages in thread
From: Uma Krishnan @ 2017-06-22  2:14 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

Per the SISLite specification, context_reset() writes 0x1 to the LSB of the
reset register. When the AFU processes this reset request, it is expected
to clear the bit after reset is complete. The current implementation simply
checks that the entire value read back is not 1, instead of masking off the
LSB and evaluating it for a change to 0. Should the AFU manipulate other
bits during the reset (reading back a value of 0xF for example), successful
completion will be prematurely indicated given the existing logic.

Additionally, in the event that the context reset operation fails, there
does not currently exist a way to provide feedback to the initiator of the
reset. This poses a problem for the rare case that a context reset fails as
the caller will proceed on the assumption that all is well.

To remedy these issues, refactor the context reset routine to only mask off
the LSB when evaluating for success and return status to the caller. Also
update the context reset handler parameters to pass a hardware queue
reference instead of a single command to better reflect that the entire
queue associated with the context is impacted by the reset.

Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
---
 drivers/scsi/cxlflash/common.h |  2 +-
 drivers/scsi/cxlflash/main.c   | 83 +++++++++++++++++++++++-------------------
 2 files changed, 47 insertions(+), 38 deletions(-)

diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
index 6fc32cfc..75decf6 100644
--- a/drivers/scsi/cxlflash/common.h
+++ b/drivers/scsi/cxlflash/common.h
@@ -211,7 +211,7 @@ struct hwq {
 struct afu {
 	struct hwq hwqs[CXLFLASH_MAX_HWQS];
 	int (*send_cmd)(struct afu *, struct afu_cmd *);
-	void (*context_reset)(struct afu_cmd *);
+	int (*context_reset)(struct hwq *);
 
 	/* AFU HW */
 	struct cxlflash_afu_map __iomem *afu_map;	/* entire MMIO map */
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 815d04b..b8dc379 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -189,55 +189,59 @@ static void cmd_complete(struct afu_cmd *cmd)
 }
 
 /**
- * context_reset() - reset command owner context via specified register
- * @cmd:	AFU command that timed out.
+ * context_reset() - reset context via specified register
+ * @hwq:	Hardware queue owning the context to be reset.
  * @reset_reg:	MMIO register to perform reset.
+ *
+ * Return: 0 on success, -errno on failure
  */
-static void context_reset(struct afu_cmd *cmd, __be64 __iomem *reset_reg)
+static int context_reset(struct hwq *hwq, __be64 __iomem *reset_reg)
 {
-	int nretry = 0;
-	u64 rrin = 0x1;
-	struct afu *afu = cmd->parent;
-	struct cxlflash_cfg *cfg = afu->parent;
+	struct cxlflash_cfg *cfg = hwq->afu->parent;
 	struct device *dev = &cfg->dev->dev;
+	int rc = -ETIMEDOUT;
+	int nretry = 0;
+	u64 val = 0x1;
 
-	dev_dbg(dev, "%s: cmd=%p\n", __func__, cmd);
+	dev_dbg(dev, "%s: hwq=%p\n", __func__, hwq);
 
-	writeq_be(rrin, reset_reg);
+	writeq_be(val, reset_reg);
 	do {
-		rrin = readq_be(reset_reg);
-		if (rrin != 0x1)
+		val = readq_be(reset_reg);
+		if ((val & 0x1) == 0x0) {
+			rc = 0;
 			break;
+		}
+
 		/* Double delay each time */
 		udelay(1 << nretry);
 	} while (nretry++ < MC_ROOM_RETRY_CNT);
 
-	dev_dbg(dev, "%s: returning rrin=%016llx nretry=%d\n",
-		__func__, rrin, nretry);
+	dev_dbg(dev, "%s: returning rc=%d, val=%016llx nretry=%d\n",
+		__func__, rc, val, nretry);
+	return rc;
 }
 
 /**
- * context_reset_ioarrin() - reset command owner context via IOARRIN register
- * @cmd:	AFU command that timed out.
+ * context_reset_ioarrin() - reset context via IOARRIN register
+ * @hwq:	Hardware queue owning the context to be reset.
+ *
+ * Return: 0 on success, -errno on failure
  */
-static void context_reset_ioarrin(struct afu_cmd *cmd)
+static int context_reset_ioarrin(struct hwq *hwq)
 {
-	struct afu *afu = cmd->parent;
-	struct hwq *hwq = get_hwq(afu, cmd->hwq_index);
-
-	context_reset(cmd, &hwq->host_map->ioarrin);
+	return context_reset(hwq, &hwq->host_map->ioarrin);
 }
 
 /**
- * context_reset_sq() - reset command owner context w/ SQ Context Reset register
- * @cmd:	AFU command that timed out.
+ * context_reset_sq() - reset context via SQ_CONTEXT_RESET register
+ * @hwq:	Hardware queue owning the context to be reset.
+ *
+ * Return: 0 on success, -errno on failure
  */
-static void context_reset_sq(struct afu_cmd *cmd)
+static int context_reset_sq(struct hwq *hwq)
 {
-	struct afu *afu = cmd->parent;
-	struct hwq *hwq = get_hwq(afu, cmd->hwq_index);
-
-	context_reset(cmd, &hwq->host_map->sq_ctx_reset);
+	return context_reset(hwq, &hwq->host_map->sq_ctx_reset);
 }
 
 /**
@@ -332,8 +336,7 @@ static int send_cmd_sq(struct afu *afu, struct afu_cmd *cmd)
  * @afu:	AFU associated with the host.
  * @cmd:	AFU command that was sent.
  *
- * Return:
- *	0 on success, -1 on timeout/error
+ * Return: 0 on success, -errno on failure
  */
 static int wait_resp(struct afu *afu, struct afu_cmd *cmd)
 {
@@ -343,15 +346,13 @@ static int wait_resp(struct afu *afu, struct afu_cmd *cmd)
 	ulong timeout = msecs_to_jiffies(cmd->rcb.timeout * 2 * 1000);
 
 	timeout = wait_for_completion_timeout(&cmd->cevent, timeout);
-	if (!timeout) {
-		afu->context_reset(cmd);
-		rc = -1;
-	}
+	if (!timeout)
+		rc = -ETIMEDOUT;
 
 	if (unlikely(cmd->sa.ioasc != 0)) {
 		dev_err(dev, "%s: cmd %02x failed, ioasc=%08x\n",
 			__func__, cmd->rcb.cdb[0], cmd->sa.ioasc);
-		rc = -1;
+		rc = -EIO;
 	}
 
 	return rc;
@@ -2033,6 +2034,7 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
 	struct hwq *hwq = get_hwq(afu, PRIMARY_HWQ);
 	char *buf = NULL;
 	int rc = 0;
+	int nretry = 0;
 	static DEFINE_MUTEX(sync_active);
 
 	if (cfg->state != STATE_NORMAL) {
@@ -2051,11 +2053,14 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
 	}
 
 	cmd = (struct afu_cmd *)PTR_ALIGN(buf, __alignof__(*cmd));
+
+retry:
 	init_completion(&cmd->cevent);
 	cmd->parent = afu;
 	cmd->hwq_index = hwq->index;
 
-	dev_dbg(dev, "%s: afu=%p cmd=%p %d\n", __func__, afu, cmd, ctx_hndl_u);
+	dev_dbg(dev, "%s: afu=%p cmd=%p ctx=%d nretry=%d\n",
+		__func__, afu, cmd, ctx_hndl_u, nretry);
 
 	cmd->rcb.req_flags = SISL_REQ_FLAGS_AFU_CMD;
 	cmd->rcb.ctx_id = hwq->ctx_hndl;
@@ -2076,8 +2081,12 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
 	}
 
 	rc = wait_resp(afu, cmd);
-	if (unlikely(rc))
-		rc = -EIO;
+	if (rc == -ETIMEDOUT) {
+		rc = afu->context_reset(hwq);
+		if (!rc && ++nretry < 2)
+			goto retry;
+	}
+
 out:
 	atomic_dec(&afu->cmds_active);
 	mutex_unlock(&sync_active);
-- 
2.1.0

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

* [PATCH 04/17] cxlflash: Schedule asynchronous reset of the host
  2017-06-22  2:12 [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Uma Krishnan
                   ` (2 preceding siblings ...)
  2017-06-22  2:14 ` [PATCH 03/17] cxlflash: Reset hardware queue context via specified register Uma Krishnan
@ 2017-06-22  2:14 ` Uma Krishnan
  2017-06-22 19:55   ` Matthew R. Ochs
  2017-06-22  2:14 ` [PATCH 05/17] cxlflash: Handle AFU sync failures Uma Krishnan
                   ` (13 subsequent siblings)
  17 siblings, 1 reply; 28+ messages in thread
From: Uma Krishnan @ 2017-06-22  2:14 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

A context reset failure indicates the AFU is in a bad state. At present,
when such a situation occurs, no further action is taken. This leaves the
adapter in an unusable state with no recoverable actions.

To avoid this situation, context reset failures will be escalated to a host
reset operation. This will be done asynchronously to allow the acting
thread to return to the user with a failure.

Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
---
 drivers/scsi/cxlflash/common.h |   2 +
 drivers/scsi/cxlflash/main.c   | 137 ++++++++++++++++++++++++++++++-----------
 2 files changed, 104 insertions(+), 35 deletions(-)

diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
index 75decf6..e9b6108 100644
--- a/drivers/scsi/cxlflash/common.h
+++ b/drivers/scsi/cxlflash/common.h
@@ -15,6 +15,7 @@
 #ifndef _CXLFLASH_COMMON_H
 #define _CXLFLASH_COMMON_H
 
+#include <linux/async.h>
 #include <linux/irq_poll.h>
 #include <linux/list.h>
 #include <linux/rwsem.h>
@@ -144,6 +145,7 @@ struct cxlflash_cfg {
 	bool tmf_active;
 	wait_queue_head_t reset_waitq;
 	enum cxlflash_state state;
+	async_cookie_t async_reset_cookie;
 };
 
 struct afu_cmd {
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index b8dc379..20c2c5e 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -586,6 +586,20 @@ static void free_mem(struct cxlflash_cfg *cfg)
 }
 
 /**
+ * cxlflash_reset_sync() - synchronizing point for asynchronous resets
+ * @cfg:	Internal structure associated with the host.
+ */
+static void cxlflash_reset_sync(struct cxlflash_cfg *cfg)
+{
+	if (cfg->async_reset_cookie == 0)
+		return;
+
+	/* Wait until all async calls prior to this cookie have completed */
+	async_synchronize_cookie(cfg->async_reset_cookie + 1);
+	cfg->async_reset_cookie = 0;
+}
+
+/**
  * stop_afu() - stops the AFU command timers and unmaps the MMIO space
  * @cfg:	Internal structure associated with the host.
  *
@@ -601,6 +615,8 @@ static void stop_afu(struct cxlflash_cfg *cfg)
 	int i;
 
 	cancel_work_sync(&cfg->work_q);
+	if (!current_is_async())
+		cxlflash_reset_sync(cfg);
 
 	if (likely(afu)) {
 		while (atomic_read(&afu->cmds_active))
@@ -2005,6 +2021,91 @@ static int init_afu(struct cxlflash_cfg *cfg)
 }
 
 /**
+ * afu_reset() - resets the AFU
+ * @cfg:	Internal structure associated with the host.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int afu_reset(struct cxlflash_cfg *cfg)
+{
+	struct device *dev = &cfg->dev->dev;
+	int rc = 0;
+
+	/* Stop the context before the reset. Since the context is
+	 * no longer available restart it after the reset is complete
+	 */
+	term_afu(cfg);
+
+	rc = init_afu(cfg);
+
+	dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc);
+	return rc;
+}
+
+/**
+ * drain_ioctls() - wait until all currently executing ioctls have completed
+ * @cfg:	Internal structure associated with the host.
+ *
+ * Obtain write access to read/write semaphore that wraps ioctl
+ * handling to 'drain' ioctls currently executing.
+ */
+static void drain_ioctls(struct cxlflash_cfg *cfg)
+{
+	down_write(&cfg->ioctl_rwsem);
+	up_write(&cfg->ioctl_rwsem);
+}
+
+/**
+ * cxlflash_async_reset_host() - asynchronous host reset handler
+ * @data:	Private data provided while scheduling reset.
+ * @cookie:	Cookie that can be used for checkpointing.
+ */
+static void cxlflash_async_reset_host(void *data, async_cookie_t cookie)
+{
+	struct cxlflash_cfg *cfg = data;
+	struct device *dev = &cfg->dev->dev;
+	int rc = 0;
+
+	if (cfg->state != STATE_RESET) {
+		dev_dbg(dev, "%s: Not performing a reset, state=%d\n",
+			__func__, cfg->state);
+		goto out;
+	}
+
+	drain_ioctls(cfg);
+	cxlflash_mark_contexts_error(cfg);
+	rc = afu_reset(cfg);
+	if (rc)
+		cfg->state = STATE_FAILTERM;
+	else
+		cfg->state = STATE_NORMAL;
+	wake_up_all(&cfg->reset_waitq);
+
+out:
+	scsi_unblock_requests(cfg->host);
+}
+
+/**
+ * cxlflash_schedule_async_reset() - schedule an asynchronous host reset
+ * @cfg:	Internal structure associated with the host.
+ */
+static void cxlflash_schedule_async_reset(struct cxlflash_cfg *cfg)
+{
+	struct device *dev = &cfg->dev->dev;
+
+	if (cfg->state != STATE_NORMAL) {
+		dev_dbg(dev, "%s: Not performing reset state=%d\n",
+			__func__, cfg->state);
+		return;
+	}
+
+	cfg->state = STATE_RESET;
+	scsi_block_requests(cfg->host);
+	cfg->async_reset_cookie = async_schedule(cxlflash_async_reset_host,
+						 cfg);
+}
+
+/**
  * cxlflash_afu_sync() - builds and sends an AFU sync command
  * @afu:	AFU associated with the host.
  * @ctx_hndl_u:	Identifies context requesting sync.
@@ -2085,6 +2186,7 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
 		rc = afu->context_reset(hwq);
 		if (!rc && ++nretry < 2)
 			goto retry;
+		cxlflash_schedule_async_reset(cfg);
 	}
 
 out:
@@ -2096,41 +2198,6 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
 }
 
 /**
- * afu_reset() - resets the AFU
- * @cfg:	Internal structure associated with the host.
- *
- * Return: 0 on success, -errno on failure
- */
-static int afu_reset(struct cxlflash_cfg *cfg)
-{
-	struct device *dev = &cfg->dev->dev;
-	int rc = 0;
-
-	/* Stop the context before the reset. Since the context is
-	 * no longer available restart it after the reset is complete
-	 */
-	term_afu(cfg);
-
-	rc = init_afu(cfg);
-
-	dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc);
-	return rc;
-}
-
-/**
- * drain_ioctls() - wait until all currently executing ioctls have completed
- * @cfg:	Internal structure associated with the host.
- *
- * Obtain write access to read/write semaphore that wraps ioctl
- * handling to 'drain' ioctls currently executing.
- */
-static void drain_ioctls(struct cxlflash_cfg *cfg)
-{
-	down_write(&cfg->ioctl_rwsem);
-	up_write(&cfg->ioctl_rwsem);
-}
-
-/**
  * cxlflash_eh_device_reset_handler() - reset a single LUN
  * @scp:	SCSI command to send.
  *
-- 
2.1.0

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

* [PATCH 05/17] cxlflash: Handle AFU sync failures
  2017-06-22  2:12 [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Uma Krishnan
                   ` (3 preceding siblings ...)
  2017-06-22  2:14 ` [PATCH 04/17] cxlflash: Schedule asynchronous reset of the host Uma Krishnan
@ 2017-06-22  2:14 ` Uma Krishnan
  2017-06-22 19:55   ` Matthew R. Ochs
  2017-06-22  2:14 ` [PATCH 06/17] cxlflash: Track pending scsi commands in each hardware queue Uma Krishnan
                   ` (12 subsequent siblings)
  17 siblings, 1 reply; 28+ messages in thread
From: Uma Krishnan @ 2017-06-22  2:14 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

AFU sync operations are not currently evaluated for failure. This is
acceptable for paths where there is not a dependency on the AFU being
consistent with the host. Examples include link reset events and LUN
cleanup operations. On paths where there is a dependency, such as a LUN
open, a sync failure should be acted upon.

In the event of AFU sync failures, either log or cleanup as appropriate for
operations that are dependent on a successful sync completion.

Update documentation to reflect behavior in the event of an AFU sync
failure.

Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
---
 Documentation/powerpc/cxlflash.txt | 12 ++++++
 drivers/scsi/cxlflash/superpipe.c  | 34 +++++++++++++--
 drivers/scsi/cxlflash/vlun.c       | 88 +++++++++++++++++++++++++++-----------
 3 files changed, 107 insertions(+), 27 deletions(-)

diff --git a/Documentation/powerpc/cxlflash.txt b/Documentation/powerpc/cxlflash.txt
index 66b4496..f9036cb 100644
--- a/Documentation/powerpc/cxlflash.txt
+++ b/Documentation/powerpc/cxlflash.txt
@@ -257,6 +257,12 @@ DK_CXLFLASH_VLUN_RESIZE
     operating in the virtual mode and used to program a LUN translation
     table that the AFU references when provided with a resource handle.
 
+    This ioctl can return -EAGAIN if an AFU sync operation takes too long.
+    In addition to returning a failure to user, cxlflash will also schedule
+    an asynchronous AFU reset. Should the user choose to retry the operation,
+    it is expected to succeed. If this ioctl fails with -EAGAIN, the user
+    can either retry the operation or treat it as a failure.
+
 DK_CXLFLASH_RELEASE
 -------------------
     This ioctl is responsible for releasing a previously obtained
@@ -309,6 +315,12 @@ DK_CXLFLASH_VLUN_CLONE
     clone. This is to avoid a stale entry in the file descriptor table of the
     child process.
 
+    This ioctl can return -EAGAIN if an AFU sync operation takes too long.
+    In addition to returning a failure to user, cxlflash will also schedule
+    an asynchronous AFU reset. Should the user choose to retry the operation,
+    it is expected to succeed. If this ioctl fails with -EAGAIN, the user
+    can either retry the operation or treat it as a failure.
+
 DK_CXLFLASH_VERIFY
 ------------------
     This ioctl is used to detect various changes such as the capacity of
diff --git a/drivers/scsi/cxlflash/superpipe.c b/drivers/scsi/cxlflash/superpipe.c
index fe9f17a..ad0f996 100644
--- a/drivers/scsi/cxlflash/superpipe.c
+++ b/drivers/scsi/cxlflash/superpipe.c
@@ -57,6 +57,19 @@ static void marshal_det_to_rele(struct dk_cxlflash_detach *detach,
 }
 
 /**
+ * marshal_udir_to_rele() - translate udirect to release structure
+ * @udirect:	Source structure from which to translate/copy.
+ * @release:	Destination structure for the translate/copy.
+ */
+static void marshal_udir_to_rele(struct dk_cxlflash_udirect *udirect,
+				 struct dk_cxlflash_release *release)
+{
+	release->hdr = udirect->hdr;
+	release->context_id = udirect->context_id;
+	release->rsrc_handle = udirect->rsrc_handle;
+}
+
+/**
  * cxlflash_free_errpage() - frees resources associated with global error page
  */
 void cxlflash_free_errpage(void)
@@ -622,6 +635,7 @@ int _cxlflash_disk_release(struct scsi_device *sdev,
 	res_hndl_t rhndl = release->rsrc_handle;
 
 	int rc = 0;
+	int rcr = 0;
 	u64 ctxid = DECODE_CTXID(release->context_id),
 	    rctxid = release->context_id;
 
@@ -686,8 +700,12 @@ int _cxlflash_disk_release(struct scsi_device *sdev,
 		rhte_f1->dw = 0;
 		dma_wmb(); /* Make RHT entry bottom-half clearing visible */
 
-		if (!ctxi->err_recovery_active)
-			cxlflash_afu_sync(afu, ctxid, rhndl, AFU_HW_SYNC);
+		if (!ctxi->err_recovery_active) {
+			rcr = cxlflash_afu_sync(afu, ctxid, rhndl, AFU_HW_SYNC);
+			if (unlikely(rcr))
+				dev_dbg(dev, "%s: AFU sync failed rc=%d\n",
+					__func__, rcr);
+		}
 		break;
 	default:
 		WARN(1, "Unsupported LUN mode!");
@@ -1929,6 +1947,7 @@ static int cxlflash_disk_direct_open(struct scsi_device *sdev, void *arg)
 	struct afu *afu = cfg->afu;
 	struct llun_info *lli = sdev->hostdata;
 	struct glun_info *gli = lli->parent;
+	struct dk_cxlflash_release rel = { { 0 }, 0 };
 
 	struct dk_cxlflash_udirect *pphys = (struct dk_cxlflash_udirect *)arg;
 
@@ -1970,13 +1989,18 @@ static int cxlflash_disk_direct_open(struct scsi_device *sdev, void *arg)
 	rsrc_handle = (rhte - ctxi->rht_start);
 
 	rht_format1(rhte, lli->lun_id[sdev->channel], ctxi->rht_perms, port);
-	cxlflash_afu_sync(afu, ctxid, rsrc_handle, AFU_LW_SYNC);
 
 	last_lba = gli->max_lba;
 	pphys->hdr.return_flags = 0;
 	pphys->last_lba = last_lba;
 	pphys->rsrc_handle = rsrc_handle;
 
+	rc = cxlflash_afu_sync(afu, ctxid, rsrc_handle, AFU_LW_SYNC);
+	if (unlikely(rc)) {
+		dev_dbg(dev, "%s: AFU sync failed rc=%d\n", __func__, rc);
+		goto err2;
+	}
+
 out:
 	if (likely(ctxi))
 		put_context(ctxi);
@@ -1984,6 +2008,10 @@ static int cxlflash_disk_direct_open(struct scsi_device *sdev, void *arg)
 		__func__, rsrc_handle, rc, last_lba);
 	return rc;
 
+err2:
+	marshal_udir_to_rele(pphys, &rel);
+	_cxlflash_disk_release(sdev, ctxi, &rel);
+	goto out;
 err1:
 	cxlflash_lun_detach(gli);
 	goto out;
diff --git a/drivers/scsi/cxlflash/vlun.c b/drivers/scsi/cxlflash/vlun.c
index 90b5c19..0800bcb 100644
--- a/drivers/scsi/cxlflash/vlun.c
+++ b/drivers/scsi/cxlflash/vlun.c
@@ -594,7 +594,9 @@ static int grow_lxt(struct afu *afu,
 	rhte->lxt_cnt = my_new_size;
 	dma_wmb(); /* Make RHT entry's LXT table size update visible */
 
-	cxlflash_afu_sync(afu, ctxid, rhndl, AFU_LW_SYNC);
+	rc = cxlflash_afu_sync(afu, ctxid, rhndl, AFU_LW_SYNC);
+	if (unlikely(rc))
+		rc = -EAGAIN;
 
 	/* free old lxt if reallocated */
 	if (lxt != lxt_old)
@@ -673,8 +675,11 @@ static int shrink_lxt(struct afu *afu,
 	rhte->lxt_start = lxt;
 	dma_wmb(); /* Make RHT entry's LXT table update visible */
 
-	if (needs_sync)
-		cxlflash_afu_sync(afu, ctxid, rhndl, AFU_HW_SYNC);
+	if (needs_sync) {
+		rc = cxlflash_afu_sync(afu, ctxid, rhndl, AFU_HW_SYNC);
+		if (unlikely(rc))
+			rc = -EAGAIN;
+	}
 
 	if (needs_ws) {
 		/*
@@ -792,6 +797,21 @@ int _cxlflash_vlun_resize(struct scsi_device *sdev,
 		rc = grow_lxt(afu, sdev, ctxid, rhndl, rhte, &new_size);
 	else if (new_size < rhte->lxt_cnt)
 		rc = shrink_lxt(afu, sdev, rhndl, rhte, ctxi, &new_size);
+	else {
+		/*
+		 * Rare case where there is already sufficient space, just
+		 * need to perform a translation sync with the AFU. This
+		 * scenario likely follows a previous sync failure during
+		 * a resize operation. Accordingly, perform the heavyweight
+		 * form of translation sync as it is unknown which type of
+		 * resize failed previously.
+		 */
+		rc = cxlflash_afu_sync(afu, ctxid, rhndl, AFU_HW_SYNC);
+		if (unlikely(rc)) {
+			rc = -EAGAIN;
+			goto out;
+		}
+	}
 
 	resize->hdr.return_flags = 0;
 	resize->last_lba = (new_size * MC_CHUNK_SIZE * gli->blk_len);
@@ -1084,10 +1104,13 @@ static int clone_lxt(struct afu *afu,
 {
 	struct cxlflash_cfg *cfg = afu->parent;
 	struct device *dev = &cfg->dev->dev;
-	struct sisl_lxt_entry *lxt;
+	struct sisl_lxt_entry *lxt = NULL;
+	bool locked = false;
 	u32 ngrps;
 	u64 aun;		/* chunk# allocated by block allocator */
-	int i, j;
+	int j;
+	int i = 0;
+	int rc = 0;
 
 	ngrps = LXT_NUM_GROUPS(rhte_src->lxt_cnt);
 
@@ -1095,33 +1118,29 @@ static int clone_lxt(struct afu *afu,
 		/* allocate new LXTs for clone */
 		lxt = kzalloc((sizeof(*lxt) * LXT_GROUP_SIZE * ngrps),
 				GFP_KERNEL);
-		if (unlikely(!lxt))
-			return -ENOMEM;
+		if (unlikely(!lxt)) {
+			rc = -ENOMEM;
+			goto out;
+		}
 
 		/* copy over */
 		memcpy(lxt, rhte_src->lxt_start,
 		       (sizeof(*lxt) * rhte_src->lxt_cnt));
 
-		/* clone the LBAs in block allocator via ref_cnt */
+		/* clone the LBAs in block allocator via ref_cnt, note that the
+		 * block allocator mutex must be held until it is established
+		 * that this routine will complete without the need for a
+		 * cleanup.
+		 */
 		mutex_lock(&blka->mutex);
+		locked = true;
 		for (i = 0; i < rhte_src->lxt_cnt; i++) {
 			aun = (lxt[i].rlba_base >> MC_CHUNK_SHIFT);
 			if (ba_clone(&blka->ba_lun, aun) == -1ULL) {
-				/* free the clones already made */
-				for (j = 0; j < i; j++) {
-					aun = (lxt[j].rlba_base >>
-					       MC_CHUNK_SHIFT);
-					ba_free(&blka->ba_lun, aun);
-				}
-
-				mutex_unlock(&blka->mutex);
-				kfree(lxt);
-				return -EIO;
+				rc = -EIO;
+				goto err;
 			}
 		}
-		mutex_unlock(&blka->mutex);
-	} else {
-		lxt = NULL;
 	}
 
 	/*
@@ -1136,10 +1155,31 @@ static int clone_lxt(struct afu *afu,
 	rhte->lxt_cnt = rhte_src->lxt_cnt;
 	dma_wmb(); /* Make RHT entry's LXT table size update visible */
 
-	cxlflash_afu_sync(afu, ctxid, rhndl, AFU_LW_SYNC);
+	rc = cxlflash_afu_sync(afu, ctxid, rhndl, AFU_LW_SYNC);
+	if (unlikely(rc)) {
+		rc = -EAGAIN;
+		goto err2;
+	}
 
-	dev_dbg(dev, "%s: returning\n", __func__);
-	return 0;
+out:
+	if (locked)
+		mutex_unlock(&blka->mutex);
+	dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc);
+	return rc;
+err2:
+	/* Reset the RHTE */
+	rhte->lxt_cnt = 0;
+	dma_wmb();
+	rhte->lxt_start = NULL;
+	dma_wmb();
+err:
+	/* free the clones already made */
+	for (j = 0; j < i; j++) {
+		aun = (lxt[j].rlba_base >> MC_CHUNK_SHIFT);
+		ba_free(&blka->ba_lun, aun);
+	}
+	kfree(lxt);
+	goto out;
 }
 
 /**
-- 
2.1.0

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

* [PATCH 06/17] cxlflash: Track pending scsi commands in each hardware queue
  2017-06-22  2:12 [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Uma Krishnan
                   ` (4 preceding siblings ...)
  2017-06-22  2:14 ` [PATCH 05/17] cxlflash: Handle AFU sync failures Uma Krishnan
@ 2017-06-22  2:14 ` Uma Krishnan
  2017-06-22 19:56   ` Matthew R. Ochs
  2017-06-22  2:14 ` [PATCH 07/17] cxlflash: Flush pending commands in cleanup path Uma Krishnan
                   ` (11 subsequent siblings)
  17 siblings, 1 reply; 28+ messages in thread
From: Uma Krishnan @ 2017-06-22  2:14 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

Currently, there is no book keeping of the pending scsi commands in the
cxlflash driver. This lack of tracking in-flight requests is too
restrictive and requires a heavy-hammer reset each time an adapter error is
encountered. Additionally, it does not allow for commands to be properly
retried.

In order to avoid this problem and to better handle error path command
cleanup, introduce a linked list for each hardware queue that tracks
pending commands.

Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
---
 drivers/scsi/cxlflash/common.h | 2 ++
 drivers/scsi/cxlflash/main.c   | 9 +++++++++
 2 files changed, 11 insertions(+)

diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
index e9b6108..3eaa3be 100644
--- a/drivers/scsi/cxlflash/common.h
+++ b/drivers/scsi/cxlflash/common.h
@@ -158,6 +158,7 @@ struct afu_cmd {
 	u32 hwq_index;
 
 	u8 cmd_tmf:1;
+	struct list_head list;	/* Pending commands link */
 
 	/* As per the SISLITE spec the IOARCB EA has to be 16-byte aligned.
 	 * However for performance reasons the IOARCB/IOASA should be
@@ -193,6 +194,7 @@ struct hwq {
 	struct sisl_ctrl_map __iomem *ctrl_map;		/* MC control map */
 	ctx_hndl_t ctx_hndl;	/* master's context handle */
 	u32 index;		/* Index of this hwq */
+	struct list_head pending_cmds;	/* Commands pending completion */
 
 	atomic_t hsq_credits;
 	spinlock_t hsq_slock;	/* Hardware send queue lock */
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 20c2c5e..1446fab 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -162,8 +162,13 @@ static void cmd_complete(struct afu_cmd *cmd)
 	struct afu *afu = cmd->parent;
 	struct cxlflash_cfg *cfg = afu->parent;
 	struct device *dev = &cfg->dev->dev;
+	struct hwq *hwq = get_hwq(afu, cmd->hwq_index);
 	bool cmd_is_tmf;
 
+	spin_lock_irqsave(&hwq->hsq_slock, lock_flags);
+	list_del(&cmd->list);
+	spin_unlock_irqrestore(&hwq->hsq_slock, lock_flags);
+
 	if (cmd->scp) {
 		scp = cmd->scp;
 		if (unlikely(cmd->sa.ioasc))
@@ -279,6 +284,7 @@ static int send_cmd_ioarrin(struct afu *afu, struct afu_cmd *cmd)
 		hwq->room = room - 1;
 	}
 
+	list_add(&cmd->list, &hwq->pending_cmds);
 	writeq_be((u64)&cmd->rcb, &hwq->host_map->ioarrin);
 out:
 	spin_unlock_irqrestore(&hwq->hsq_slock, lock_flags);
@@ -319,6 +325,8 @@ static int send_cmd_sq(struct afu *afu, struct afu_cmd *cmd)
 		hwq->hsq_curr++;
 	else
 		hwq->hsq_curr = hwq->hsq_start;
+
+	list_add(&cmd->list, &hwq->pending_cmds);
 	writeq_be((u64)hwq->hsq_curr, &hwq->host_map->sq_tail);
 
 	spin_unlock_irqrestore(&hwq->hsq_slock, lock_flags);
@@ -1840,6 +1848,7 @@ static int init_mc(struct cxlflash_cfg *cfg, u32 index)
 
 	hwq->afu = cfg->afu;
 	hwq->index = index;
+	INIT_LIST_HEAD(&hwq->pending_cmds);
 
 	if (index == PRIMARY_HWQ)
 		ctx = cxl_get_context(cfg->dev);
-- 
2.1.0

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

* [PATCH 07/17] cxlflash: Flush pending commands in cleanup path
  2017-06-22  2:12 [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Uma Krishnan
                   ` (5 preceding siblings ...)
  2017-06-22  2:14 ` [PATCH 06/17] cxlflash: Track pending scsi commands in each hardware queue Uma Krishnan
@ 2017-06-22  2:14 ` Uma Krishnan
  2017-06-22 19:56   ` Matthew R. Ochs
  2017-06-22  2:15 ` [PATCH 08/17] cxlflash: Add scsi command abort handler Uma Krishnan
                   ` (10 subsequent siblings)
  17 siblings, 1 reply; 28+ messages in thread
From: Uma Krishnan @ 2017-06-22  2:14 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

When the AFU is reset in an error path, pending scsi commands can be
silently dropped without completion or a formal abort. This puts the onus
on the cxlflash driver to notify mid-layer and indicating that the command
can be retried.

Once the card has been quiesced, the hardware send queue lock is acquired
to prevent any data movement while the pending commands are processed.

Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
---
 drivers/scsi/cxlflash/common.h |  5 +++-
 drivers/scsi/cxlflash/main.c   | 57 +++++++++++++++++++++++++++++++++++++++---
 2 files changed, 57 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
index 3eaa3be..11a5b0a 100644
--- a/drivers/scsi/cxlflash/common.h
+++ b/drivers/scsi/cxlflash/common.h
@@ -157,7 +157,9 @@ struct afu_cmd {
 	struct list_head queue;
 	u32 hwq_index;
 
-	u8 cmd_tmf:1;
+	u8 cmd_tmf:1,
+	   cmd_aborted:1;
+
 	struct list_head list;	/* Pending commands link */
 
 	/* As per the SISLITE spec the IOARCB EA has to be 16-byte aligned.
@@ -176,6 +178,7 @@ static inline struct afu_cmd *sc_to_afucz(struct scsi_cmnd *sc)
 	struct afu_cmd *afuc = sc_to_afuc(sc);
 
 	memset(afuc, 0, sizeof(*afuc));
+	INIT_LIST_HEAD(&afuc->queue);
 	return afuc;
 }
 
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 1446fab..0a3de42 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -194,6 +194,36 @@ static void cmd_complete(struct afu_cmd *cmd)
 }
 
 /**
+ * flush_pending_cmds() - flush all pending commands on this hardware queue
+ * @hwq:	Hardware queue to flush.
+ *
+ * The hardware send queue lock associated with this hardware queue must be
+ * held when calling this routine.
+ */
+static void flush_pending_cmds(struct hwq *hwq)
+{
+	struct afu_cmd *cmd, *tmp;
+	struct scsi_cmnd *scp;
+
+	list_for_each_entry_safe(cmd, tmp, &hwq->pending_cmds, list) {
+		/* Bypass command when on a doneq, cmd_complete() will handle */
+		if (!list_empty(&cmd->queue))
+			continue;
+
+		list_del(&cmd->list);
+
+		if (cmd->scp) {
+			scp = cmd->scp;
+			scp->result = (DID_IMM_RETRY << 16);
+			scp->scsi_done(scp);
+		} else {
+			cmd->cmd_aborted = true;
+			complete(&cmd->cevent);
+		}
+	}
+}
+
+/**
  * context_reset() - reset context via specified register
  * @hwq:	Hardware queue owning the context to be reset.
  * @reset_reg:	MMIO register to perform reset.
@@ -357,6 +387,9 @@ static int wait_resp(struct afu *afu, struct afu_cmd *cmd)
 	if (!timeout)
 		rc = -ETIMEDOUT;
 
+	if (cmd->cmd_aborted)
+		rc = -EAGAIN;
+
 	if (unlikely(cmd->sa.ioasc != 0)) {
 		dev_err(dev, "%s: cmd %02x failed, ioasc=%08x\n",
 			__func__, cmd->rcb.cdb[0], cmd->sa.ioasc);
@@ -702,6 +735,7 @@ static void term_mc(struct cxlflash_cfg *cfg, u32 index)
 	struct afu *afu = cfg->afu;
 	struct device *dev = &cfg->dev->dev;
 	struct hwq *hwq;
+	ulong lock_flags;
 
 	if (!afu) {
 		dev_err(dev, "%s: returning with NULL afu\n", __func__);
@@ -719,6 +753,10 @@ static void term_mc(struct cxlflash_cfg *cfg, u32 index)
 	if (index != PRIMARY_HWQ)
 		WARN_ON(cxl_release_context(hwq->ctx));
 	hwq->ctx = NULL;
+
+	spin_lock_irqsave(&hwq->hsq_slock, lock_flags);
+	flush_pending_cmds(hwq);
+	spin_unlock_irqrestore(&hwq->hsq_slock, lock_flags);
 }
 
 /**
@@ -2155,7 +2193,7 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
 
 	mutex_lock(&sync_active);
 	atomic_inc(&afu->cmds_active);
-	buf = kzalloc(sizeof(*cmd) + __alignof__(*cmd) - 1, GFP_KERNEL);
+	buf = kmalloc(sizeof(*cmd) + __alignof__(*cmd) - 1, GFP_KERNEL);
 	if (unlikely(!buf)) {
 		dev_err(dev, "%s: no memory for command\n", __func__);
 		rc = -ENOMEM;
@@ -2165,6 +2203,8 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
 	cmd = (struct afu_cmd *)PTR_ALIGN(buf, __alignof__(*cmd));
 
 retry:
+	memset(cmd, 0, sizeof(*cmd));
+	INIT_LIST_HEAD(&cmd->queue);
 	init_completion(&cmd->cevent);
 	cmd->parent = afu;
 	cmd->hwq_index = hwq->index;
@@ -2191,11 +2231,20 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
 	}
 
 	rc = wait_resp(afu, cmd);
-	if (rc == -ETIMEDOUT) {
+	switch (rc) {
+	case -ETIMEDOUT:
 		rc = afu->context_reset(hwq);
-		if (!rc && ++nretry < 2)
+		if (rc) {
+			cxlflash_schedule_async_reset(cfg);
+			break;
+		}
+		/* fall through to retry */
+	case -EAGAIN:
+		if (++nretry < 2)
 			goto retry;
-		cxlflash_schedule_async_reset(cfg);
+		/* fall through to exit */
+	default:
+		break;
 	}
 
 out:
-- 
2.1.0

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

* [PATCH 08/17] cxlflash: Add scsi command abort handler
  2017-06-22  2:12 [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Uma Krishnan
                   ` (6 preceding siblings ...)
  2017-06-22  2:14 ` [PATCH 07/17] cxlflash: Flush pending commands in cleanup path Uma Krishnan
@ 2017-06-22  2:15 ` Uma Krishnan
  2017-06-22 19:56   ` Matthew R. Ochs
  2017-06-22  2:15 ` [PATCH 09/17] cxlflash: Create character device to provide host management interface Uma Krishnan
                   ` (9 subsequent siblings)
  17 siblings, 1 reply; 28+ messages in thread
From: Uma Krishnan @ 2017-06-22  2:15 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

To date, CXL flash devices do not support a single command abort operation.
Instead, the SISLite specification provides a context reset operation to
cleanup all pending commands for a given context.

When a context reset is successful, it is guaranteed that the AFU has
aborted all currently pending I/O. This sequence is less invasive than a
device or host reset and can be executed to support scsi command abort
requests. Add eh_abort_handler callback support to process command timeouts
and abort requests.

Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
---
 drivers/scsi/cxlflash/main.c | 61 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 0a3de42..ceb247b 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -228,6 +228,10 @@ static void flush_pending_cmds(struct hwq *hwq)
  * @hwq:	Hardware queue owning the context to be reset.
  * @reset_reg:	MMIO register to perform reset.
  *
+ * When the reset is successful, the SISLite specification guarantees that
+ * the AFU has aborted all currently pending I/O. Accordingly, these commands
+ * must be flushed.
+ *
  * Return: 0 on success, -errno on failure
  */
 static int context_reset(struct hwq *hwq, __be64 __iomem *reset_reg)
@@ -237,9 +241,12 @@ static int context_reset(struct hwq *hwq, __be64 __iomem *reset_reg)
 	int rc = -ETIMEDOUT;
 	int nretry = 0;
 	u64 val = 0x1;
+	ulong lock_flags;
 
 	dev_dbg(dev, "%s: hwq=%p\n", __func__, hwq);
 
+	spin_lock_irqsave(&hwq->hsq_slock, lock_flags);
+
 	writeq_be(val, reset_reg);
 	do {
 		val = readq_be(reset_reg);
@@ -252,6 +259,11 @@ static int context_reset(struct hwq *hwq, __be64 __iomem *reset_reg)
 		udelay(1 << nretry);
 	} while (nretry++ < MC_ROOM_RETRY_CNT);
 
+	if (!rc)
+		flush_pending_cmds(hwq);
+
+	spin_unlock_irqrestore(&hwq->hsq_slock, lock_flags);
+
 	dev_dbg(dev, "%s: returning rc=%d, val=%016llx nretry=%d\n",
 		__func__, rc, val, nretry);
 	return rc;
@@ -2256,6 +2268,54 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
 }
 
 /**
+ * cxlflash_eh_abort_handler() - abort a SCSI command
+ * @scp:	SCSI command to abort.
+ *
+ * CXL Flash devices do not support a single command abort. Reset the context
+ * as per SISLite specification. Flush any pending commands in the hardware
+ * queue before the reset.
+ *
+ * Return: SUCCESS/FAILED as defined in scsi/scsi.h
+ */
+static int cxlflash_eh_abort_handler(struct scsi_cmnd *scp)
+{
+	int rc = FAILED;
+	struct Scsi_Host *host = scp->device->host;
+	struct cxlflash_cfg *cfg = shost_priv(host);
+	struct afu_cmd *cmd = sc_to_afuc(scp);
+	struct device *dev = &cfg->dev->dev;
+	struct afu *afu = cfg->afu;
+	struct hwq *hwq = get_hwq(afu, cmd->hwq_index);
+
+	dev_dbg(dev, "%s: (scp=%p) %d/%d/%d/%llu "
+		"cdb=(%08x-%08x-%08x-%08x)\n", __func__, scp, host->host_no,
+		scp->device->channel, scp->device->id, scp->device->lun,
+		get_unaligned_be32(&((u32 *)scp->cmnd)[0]),
+		get_unaligned_be32(&((u32 *)scp->cmnd)[1]),
+		get_unaligned_be32(&((u32 *)scp->cmnd)[2]),
+		get_unaligned_be32(&((u32 *)scp->cmnd)[3]));
+
+	/* When the state is not normal, another reset/reload is in progress.
+	 * Return failed and the mid-layer will invoke host reset handler.
+	 */
+	if (cfg->state != STATE_NORMAL) {
+		dev_dbg(dev, "%s: Invalid state for abort, state=%d\n",
+			__func__, cfg->state);
+		goto out;
+	}
+
+	rc = afu->context_reset(hwq);
+	if (unlikely(rc))
+		goto out;
+
+	rc = SUCCESS;
+
+out:
+	dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc);
+	return rc;
+}
+
+/**
  * cxlflash_eh_device_reset_handler() - reset a single LUN
  * @scp:	SCSI command to send.
  *
@@ -2969,6 +3029,7 @@ static struct scsi_host_template driver_template = {
 	.ioctl = cxlflash_ioctl,
 	.proc_name = CXLFLASH_NAME,
 	.queuecommand = cxlflash_queuecommand,
+	.eh_abort_handler = cxlflash_eh_abort_handler,
 	.eh_device_reset_handler = cxlflash_eh_device_reset_handler,
 	.eh_host_reset_handler = cxlflash_eh_host_reset_handler,
 	.change_queue_depth = cxlflash_change_queue_depth,
-- 
2.1.0

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

* [PATCH 09/17] cxlflash: Create character device to provide host management interface
  2017-06-22  2:12 [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Uma Krishnan
                   ` (7 preceding siblings ...)
  2017-06-22  2:15 ` [PATCH 08/17] cxlflash: Add scsi command abort handler Uma Krishnan
@ 2017-06-22  2:15 ` Uma Krishnan
  2017-06-22 19:56   ` Matthew R. Ochs
  2017-06-22  2:15 ` [PATCH 10/17] cxlflash: Separate AFU internal command handling from AFU sync specifics Uma Krishnan
                   ` (8 subsequent siblings)
  17 siblings, 1 reply; 28+ messages in thread
From: Uma Krishnan @ 2017-06-22  2:15 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

The cxlflash driver currently lacks host management interface. Future
devices supported by cxlflash will provide a variety of host-wide
management functions. Examples include LUN provisioning, hardware debug
support, and firmware download.

In order to provide a way to manage the device, a character device will
be created during probe of each adapter. This device will support a set of
ioctls defined in the SISLite specification from which administrators can
manage the adapter.

Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
---
 drivers/scsi/cxlflash/common.h |   6 +-
 drivers/scsi/cxlflash/main.c   | 207 ++++++++++++++++++++++++++++++++++++++++-
 drivers/scsi/cxlflash/main.h   |   1 +
 3 files changed, 212 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
index 11a5b0a..cbc0eb7 100644
--- a/drivers/scsi/cxlflash/common.h
+++ b/drivers/scsi/cxlflash/common.h
@@ -16,6 +16,7 @@
 #define _CXLFLASH_COMMON_H
 
 #include <linux/async.h>
+#include <linux/cdev.h>
 #include <linux/irq_poll.h>
 #include <linux/list.h>
 #include <linux/rwsem.h>
@@ -86,7 +87,8 @@ enum cxlflash_init_state {
 	INIT_STATE_NONE,
 	INIT_STATE_PCI,
 	INIT_STATE_AFU,
-	INIT_STATE_SCSI
+	INIT_STATE_SCSI,
+	INIT_STATE_CDEV
 };
 
 enum cxlflash_state {
@@ -116,6 +118,8 @@ struct cxlflash_cfg {
 	struct pci_device_id *dev_id;
 	struct Scsi_Host *host;
 	int num_fc_ports;
+	struct cdev cdev;
+	struct device *chardev;
 
 	ulong cxlflash_regs_pci;
 
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index ceb247b..0656dd2 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -34,6 +34,10 @@ MODULE_AUTHOR("Manoj N. Kumar <manoj@linux.vnet.ibm.com>");
 MODULE_AUTHOR("Matthew R. Ochs <mrochs@linux.vnet.ibm.com>");
 MODULE_LICENSE("GPL");
 
+static struct class *cxlflash_class;
+static u32 cxlflash_major;
+static DECLARE_BITMAP(cxlflash_minor, CXLFLASH_MAX_ADAPTERS);
+
 /**
  * process_cmd_err() - command error handler
  * @cmd:	AFU command that experienced the error.
@@ -863,6 +867,47 @@ static void notify_shutdown(struct cxlflash_cfg *cfg, bool wait)
 }
 
 /**
+ * cxlflash_get_minor() - gets the first available minor number
+ *
+ * Return: Unique minor number that can be used to create the character device.
+ */
+static int cxlflash_get_minor(void)
+{
+	int minor;
+	long bit;
+
+	bit = find_first_zero_bit(cxlflash_minor, CXLFLASH_MAX_ADAPTERS);
+	if (bit >= CXLFLASH_MAX_ADAPTERS)
+		return -1;
+
+	minor = bit & MINORMASK;
+	set_bit(minor, cxlflash_minor);
+	return minor;
+}
+
+/**
+ * cxlflash_put_minor() - releases the minor number
+ * @minor:	Minor number that is no longer needed.
+ */
+static void cxlflash_put_minor(int minor)
+{
+	clear_bit(minor, cxlflash_minor);
+}
+
+/**
+ * cxlflash_release_chrdev() - release the character device for the host
+ * @cfg:	Internal structure associated with the host.
+ */
+static void cxlflash_release_chrdev(struct cxlflash_cfg *cfg)
+{
+	put_device(cfg->chardev);
+	device_unregister(cfg->chardev);
+	cfg->chardev = NULL;
+	cdev_del(&cfg->cdev);
+	cxlflash_put_minor(MINOR(cfg->cdev.dev));
+}
+
+/**
  * cxlflash_remove() - PCI entry point to tear down host
  * @pdev:	PCI device associated with the host.
  *
@@ -897,6 +942,8 @@ static void cxlflash_remove(struct pci_dev *pdev)
 	cxlflash_stop_term_user_contexts(cfg);
 
 	switch (cfg->init_state) {
+	case INIT_STATE_CDEV:
+		cxlflash_release_chrdev(cfg);
 	case INIT_STATE_SCSI:
 		cxlflash_term_local_luns(cfg);
 		scsi_remove_host(cfg->host);
@@ -3120,6 +3167,86 @@ static void cxlflash_worker_thread(struct work_struct *work)
 }
 
 /**
+ * cxlflash_chr_open() - character device open handler
+ * @inode:	Device inode associated with this character device.
+ * @file:	File pointer for this device.
+ *
+ * Only users with admin privileges are allowed to open the character device.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int cxlflash_chr_open(struct inode *inode, struct file *file)
+{
+	struct cxlflash_cfg *cfg;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	cfg = container_of(inode->i_cdev, struct cxlflash_cfg, cdev);
+	file->private_data = cfg;
+
+	return 0;
+}
+
+/*
+ * Character device file operations
+ */
+static const struct file_operations cxlflash_chr_fops = {
+	.owner          = THIS_MODULE,
+	.open           = cxlflash_chr_open,
+};
+
+/**
+ * init_chrdev() - initialize the character device for the host
+ * @cfg:	Internal structure associated with the host.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int init_chrdev(struct cxlflash_cfg *cfg)
+{
+	struct device *dev = &cfg->dev->dev;
+	struct device *char_dev;
+	dev_t devno;
+	int minor;
+	int rc = 0;
+
+	minor = cxlflash_get_minor();
+	if (unlikely(minor < 0)) {
+		dev_err(dev, "%s: Exhausted allowed adapters\n", __func__);
+		rc = -ENOSPC;
+		goto out;
+	}
+
+	devno = MKDEV(cxlflash_major, minor);
+	cdev_init(&cfg->cdev, &cxlflash_chr_fops);
+
+	rc = cdev_add(&cfg->cdev, devno, 1);
+	if (rc) {
+		dev_err(dev, "%s: cdev_add failed rc=%d\n", __func__, rc);
+		goto err1;
+	}
+
+	char_dev = device_create(cxlflash_class, NULL, devno,
+				 NULL, "cxlflash%d", minor);
+	if (IS_ERR(char_dev)) {
+		rc = PTR_ERR(char_dev);
+		dev_err(dev, "%s: device_create failed rc=%d\n",
+			__func__, rc);
+		goto err2;
+	}
+
+	cfg->chardev = char_dev;
+out:
+	dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc);
+	return rc;
+err2:
+	cdev_del(&cfg->cdev);
+err1:
+	cxlflash_put_minor(minor);
+	goto out;
+}
+
+/**
  * cxlflash_probe() - PCI entry point to add host
  * @pdev:	PCI device associated with the host.
  * @dev_id:	PCI device id associated with device.
@@ -3229,6 +3356,13 @@ static int cxlflash_probe(struct pci_dev *pdev,
 	}
 	cfg->init_state = INIT_STATE_SCSI;
 
+	rc = init_chrdev(cfg);
+	if (rc) {
+		dev_err(dev, "%s: init_chrdev failed rc=%d\n", __func__, rc);
+		goto out_remove;
+	}
+	cfg->init_state = INIT_STATE_CDEV;
+
 	if (wq_has_sleeper(&cfg->reset_waitq)) {
 		cfg->state = STATE_PROBED;
 		wake_up_all(&cfg->reset_waitq);
@@ -3331,6 +3465,63 @@ static void cxlflash_pci_resume(struct pci_dev *pdev)
 	scsi_unblock_requests(cfg->host);
 }
 
+/**
+ * cxlflash_devnode() - provides devtmpfs for devices in the cxlflash class
+ * @dev:	Character device.
+ * @mode:	Mode that can be used to verify access.
+ *
+ * Return: Allocated string describing the devtmpfs structure.
+ */
+static char *cxlflash_devnode(struct device *dev, umode_t *mode)
+{
+	return kasprintf(GFP_KERNEL, "cxlflash/%s", dev_name(dev));
+}
+
+/**
+ * cxlflash_class_init() - create character device class
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int cxlflash_class_init(void)
+{
+	dev_t devno;
+	int rc = 0;
+
+	rc = alloc_chrdev_region(&devno, 0, CXLFLASH_MAX_ADAPTERS, "cxlflash");
+	if (unlikely(rc)) {
+		pr_err("%s: alloc_chrdev_region failed rc=%d\n", __func__, rc);
+		goto out;
+	}
+
+	cxlflash_major = MAJOR(devno);
+
+	cxlflash_class = class_create(THIS_MODULE, "cxlflash");
+	if (IS_ERR(cxlflash_class)) {
+		rc = PTR_ERR(cxlflash_class);
+		pr_err("%s: class_create failed rc=%d\n", __func__, rc);
+		goto err;
+	}
+
+	cxlflash_class->devnode = cxlflash_devnode;
+out:
+	pr_debug("%s: returning rc=%d\n", __func__, rc);
+	return rc;
+err:
+	unregister_chrdev_region(devno, CXLFLASH_MAX_ADAPTERS);
+	goto out;
+}
+
+/**
+ * cxlflash_class_exit() - destroy character device class
+ */
+static void cxlflash_class_exit(void)
+{
+	dev_t devno = MKDEV(cxlflash_major, 0);
+
+	class_destroy(cxlflash_class);
+	unregister_chrdev_region(devno, CXLFLASH_MAX_ADAPTERS);
+}
+
 static const struct pci_error_handlers cxlflash_err_handler = {
 	.error_detected = cxlflash_pci_error_detected,
 	.slot_reset = cxlflash_pci_slot_reset,
@@ -3356,10 +3547,23 @@ static struct pci_driver cxlflash_driver = {
  */
 static int __init init_cxlflash(void)
 {
+	int rc;
+
 	check_sizes();
 	cxlflash_list_init();
+	rc = cxlflash_class_init();
+	if (unlikely(rc))
+		goto out;
 
-	return pci_register_driver(&cxlflash_driver);
+	rc = pci_register_driver(&cxlflash_driver);
+	if (unlikely(rc))
+		goto err;
+out:
+	pr_debug("%s: returning rc=%d\n", __func__, rc);
+	return rc;
+err:
+	cxlflash_class_exit();
+	goto out;
 }
 
 /**
@@ -3371,6 +3575,7 @@ static void __exit exit_cxlflash(void)
 	cxlflash_free_errpage();
 
 	pci_unregister_driver(&cxlflash_driver);
+	cxlflash_class_exit();
 }
 
 module_init(init_cxlflash);
diff --git a/drivers/scsi/cxlflash/main.h b/drivers/scsi/cxlflash/main.h
index 49657f1..44c86c2 100644
--- a/drivers/scsi/cxlflash/main.h
+++ b/drivers/scsi/cxlflash/main.h
@@ -22,6 +22,7 @@
 
 #define CXLFLASH_NAME		"cxlflash"
 #define CXLFLASH_ADAPTER_NAME	"IBM POWER CXL Flash Adapter"
+#define CXLFLASH_MAX_ADAPTERS	32
 
 #define PCI_DEVICE_ID_IBM_CORSA		0x04F0
 #define PCI_DEVICE_ID_IBM_FLASH_GT	0x0600
-- 
2.1.0

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

* [PATCH 10/17] cxlflash: Separate AFU internal command handling from AFU sync specifics
  2017-06-22  2:12 [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Uma Krishnan
                   ` (8 preceding siblings ...)
  2017-06-22  2:15 ` [PATCH 09/17] cxlflash: Create character device to provide host management interface Uma Krishnan
@ 2017-06-22  2:15 ` Uma Krishnan
  2017-06-22  2:15 ` [PATCH 11/17] cxlflash: Introduce host ioctl support Uma Krishnan
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: Uma Krishnan @ 2017-06-22  2:15 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

From: "Matthew R. Ochs" <mrochs@linux.vnet.ibm.com>

To date the only supported internal AFU command is AFU sync. The logic
to send an internal AFU command is embedded in the specific AFU sync
handler and would need to be duplicated for new internal AFU commands.

In order to support new internal AFU commands, separate code that is
common for AFU internal commands into a generic transmission routine
and support passing back command status through an IOASA structure.
The first user of this new routine is the existing AFU sync command.
As a cleanup, use a descriptive name for the AFU sync command instead
of a magic number.

Signed-off-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
---
 drivers/scsi/cxlflash/main.c    | 79 ++++++++++++++++++++++++++---------------
 drivers/scsi/cxlflash/sislite.h |  2 ++
 2 files changed, 53 insertions(+), 28 deletions(-)

diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 0656dd2..7732dfc 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -2212,28 +2212,22 @@ static void cxlflash_schedule_async_reset(struct cxlflash_cfg *cfg)
 }
 
 /**
- * cxlflash_afu_sync() - builds and sends an AFU sync command
+ * send_afu_cmd() - builds and sends an internal AFU command
  * @afu:	AFU associated with the host.
- * @ctx_hndl_u:	Identifies context requesting sync.
- * @res_hndl_u:	Identifies resource requesting sync.
- * @mode:	Type of sync to issue (lightweight, heavyweight, global).
+ * @rcb:	Pre-populated IOARCB describing command to send.
  *
- * The AFU can only take 1 sync command at a time. This routine enforces this
- * limitation by using a mutex to provide exclusive access to the AFU during
- * the sync. This design point requires calling threads to not be on interrupt
- * context due to the possibility of sleeping during concurrent sync operations.
+ * The AFU can only take one internal AFU command at a time. This limitation is
+ * enforced by using a mutex to provide exclusive access to the AFU during the
+ * operation. This design point requires calling threads to not be on interrupt
+ * context due to the possibility of sleeping during concurrent AFU operations.
  *
- * AFU sync operations are only necessary and allowed when the device is
- * operating normally. When not operating normally, sync requests can occur as
- * part of cleaning up resources associated with an adapter prior to removal.
- * In this scenario, these requests are simply ignored (safe due to the AFU
- * going away).
+ * The command status is optionally passed back to the caller when the caller
+ * populates the IOASA field of the IOARCB with a pointer to an IOASA structure.
  *
  * Return:
  *	0 on success, -errno on failure
  */
-int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
-		      res_hndl_t res_hndl_u, u8 mode)
+static int send_afu_cmd(struct afu *afu, struct sisl_ioarcb *rcb)
 {
 	struct cxlflash_cfg *cfg = afu->parent;
 	struct device *dev = &cfg->dev->dev;
@@ -2263,25 +2257,15 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
 
 retry:
 	memset(cmd, 0, sizeof(*cmd));
+	memcpy(&cmd->rcb, rcb, sizeof(*rcb));
 	INIT_LIST_HEAD(&cmd->queue);
 	init_completion(&cmd->cevent);
 	cmd->parent = afu;
 	cmd->hwq_index = hwq->index;
-
-	dev_dbg(dev, "%s: afu=%p cmd=%p ctx=%d nretry=%d\n",
-		__func__, afu, cmd, ctx_hndl_u, nretry);
-
-	cmd->rcb.req_flags = SISL_REQ_FLAGS_AFU_CMD;
 	cmd->rcb.ctx_id = hwq->ctx_hndl;
-	cmd->rcb.msi = SISL_MSI_RRQ_UPDATED;
-	cmd->rcb.timeout = MC_AFU_SYNC_TIMEOUT;
-
-	cmd->rcb.cdb[0] = 0xC0;	/* AFU Sync */
-	cmd->rcb.cdb[1] = mode;
 
-	/* The cdb is aligned, no unaligned accessors required */
-	*((__be16 *)&cmd->rcb.cdb[2]) = cpu_to_be16(ctx_hndl_u);
-	*((__be32 *)&cmd->rcb.cdb[4]) = cpu_to_be32(res_hndl_u);
+	dev_dbg(dev, "%s: afu=%p cmd=%p type=%02x nretry=%d\n",
+		__func__, afu, cmd, cmd->rcb.cdb[0], nretry);
 
 	rc = afu->send_cmd(afu, cmd);
 	if (unlikely(rc)) {
@@ -2306,6 +2290,8 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
 		break;
 	}
 
+	if (rcb->ioasa)
+		*rcb->ioasa = cmd->sa;
 out:
 	atomic_dec(&afu->cmds_active);
 	mutex_unlock(&sync_active);
@@ -2315,6 +2301,43 @@ int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx_hndl_u,
 }
 
 /**
+ * cxlflash_afu_sync() - builds and sends an AFU sync command
+ * @afu:	AFU associated with the host.
+ * @ctx:	Identifies context requesting sync.
+ * @res:	Identifies resource requesting sync.
+ * @mode:	Type of sync to issue (lightweight, heavyweight, global).
+ *
+ * AFU sync operations are only necessary and allowed when the device is
+ * operating normally. When not operating normally, sync requests can occur as
+ * part of cleaning up resources associated with an adapter prior to removal.
+ * In this scenario, these requests are simply ignored (safe due to the AFU
+ * going away).
+ *
+ * Return:
+ *	0 on success, -errno on failure
+ */
+int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t ctx, res_hndl_t res, u8 mode)
+{
+	struct cxlflash_cfg *cfg = afu->parent;
+	struct device *dev = &cfg->dev->dev;
+	struct sisl_ioarcb rcb = { 0 };
+
+	dev_dbg(dev, "%s: afu=%p ctx=%u res=%u mode=%u\n",
+		__func__, afu, ctx, res, mode);
+
+	rcb.req_flags = SISL_REQ_FLAGS_AFU_CMD;
+	rcb.msi = SISL_MSI_RRQ_UPDATED;
+	rcb.timeout = MC_AFU_SYNC_TIMEOUT;
+
+	rcb.cdb[0] = SISL_AFU_CMD_SYNC;
+	rcb.cdb[1] = mode;
+	put_unaligned_be16(ctx, &rcb.cdb[2]);
+	put_unaligned_be32(res, &rcb.cdb[4]);
+
+	return send_afu_cmd(afu, &rcb);
+}
+
+/**
  * cxlflash_eh_abort_handler() - abort a SCSI command
  * @scp:	SCSI command to abort.
  *
diff --git a/drivers/scsi/cxlflash/sislite.h b/drivers/scsi/cxlflash/sislite.h
index a768360..483710a 100644
--- a/drivers/scsi/cxlflash/sislite.h
+++ b/drivers/scsi/cxlflash/sislite.h
@@ -72,6 +72,8 @@ struct sisl_ioarcb {
 	u16 timeout;		/* in units specified by req_flags */
 	u32 rsvd1;
 	u8 cdb[16];		/* must be in big endian */
+#define SISL_AFU_CMD_SYNC		0xC0	/* AFU sync command */
+
 	union {
 		u64 reserved;			/* Reserved for IOARRIN mode */
 		struct sisl_ioasa *ioasa;	/* IOASA EA for SQ Mode */
-- 
2.1.0

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

* [PATCH 11/17] cxlflash: Introduce host ioctl support
  2017-06-22  2:12 [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Uma Krishnan
                   ` (9 preceding siblings ...)
  2017-06-22  2:15 ` [PATCH 10/17] cxlflash: Separate AFU internal command handling from AFU sync specifics Uma Krishnan
@ 2017-06-22  2:15 ` Uma Krishnan
  2017-06-22  2:16 ` [PATCH 12/17] cxlflash: Refactor AFU capability checking Uma Krishnan
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: Uma Krishnan @ 2017-06-22  2:15 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

From: "Matthew R. Ochs" <mrochs@linux.vnet.ibm.com>

As staging for supporting various host management functions, add a host
ioctl infrastructure to filter ioctl commands and perform operations that
are common for all host ioctls. Also update the cxlflash documentation to
create a new section for documenting host ioctls.

Signed-off-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
---
 Documentation/ioctl/ioctl-number.txt |   2 +-
 Documentation/powerpc/cxlflash.txt   |  19 +++++-
 drivers/scsi/cxlflash/main.c         | 121 ++++++++++++++++++++++++++++++++++-
 include/uapi/scsi/cxlflash_ioctl.h   |  31 ++++++++-
 4 files changed, 168 insertions(+), 5 deletions(-)

diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index 08244be..6b6cc4c 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -324,7 +324,7 @@ Code  Seq#(hex)	Include File		Comments
 0xB5	00-0F	uapi/linux/rpmsg.h	<mailto:linux-remoteproc@vger.kernel.org>
 0xC0	00-0F	linux/usb/iowarrior.h
 0xCA	00-0F	uapi/misc/cxl.h
-0xCA	80-8F	uapi/scsi/cxlflash_ioctl.h
+0xCA	80-BF	uapi/scsi/cxlflash_ioctl.h
 0xCB	00-1F	CBM serial IEC bus	in development:
 					<mailto:michael.klein@puffin.lb.shuttle.de>
 0xCD	01	linux/reiserfs_fs.h
diff --git a/Documentation/powerpc/cxlflash.txt b/Documentation/powerpc/cxlflash.txt
index f9036cb..ee67021 100644
--- a/Documentation/powerpc/cxlflash.txt
+++ b/Documentation/powerpc/cxlflash.txt
@@ -124,8 +124,8 @@ Block library API
     http://github.com/open-power/capiflash
 
 
-CXL Flash Driver IOCTLs
-=======================
+CXL Flash Driver LUN IOCTLs
+===========================
 
     Users, such as the block library, that wish to interface with a flash
     device (LUN) via user space access need to use the services provided
@@ -367,3 +367,18 @@ DK_CXLFLASH_MANAGE_LUN
     exclusive user space access (superpipe). In case a LUN is visible
     across multiple ports and adapters, this ioctl is used to uniquely
     identify each LUN by its World Wide Node Name (WWNN).
+
+
+CXL Flash Driver Host IOCTLs
+============================
+
+    Each host adapter instance that is supported by the cxlflash driver
+    has a special character device associated with it to enable a set of
+    host management function. These character devices are hosted in a
+    class dedicated for cxlflash and can be accessed via /dev/cxlflash/*.
+
+    Applications can be written to perform various functions using the
+    host ioctl APIs below.
+
+    The structure definitions for these IOCTLs are available in:
+    uapi/scsi/cxlflash_ioctl.h
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 7732dfc..be468ed1 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -2693,7 +2693,14 @@ static ssize_t lun_mode_store(struct device *dev,
 static ssize_t ioctl_version_show(struct device *dev,
 				  struct device_attribute *attr, char *buf)
 {
-	return scnprintf(buf, PAGE_SIZE, "%u\n", DK_CXLFLASH_VERSION_0);
+	ssize_t bytes = 0;
+
+	bytes = scnprintf(buf, PAGE_SIZE,
+			  "disk: %u\n", DK_CXLFLASH_VERSION_0);
+	bytes += scnprintf(buf + bytes, PAGE_SIZE - bytes,
+			   "host: %u\n", HT_CXLFLASH_VERSION_0);
+
+	return bytes;
 }
 
 /**
@@ -3211,12 +3218,124 @@ static int cxlflash_chr_open(struct inode *inode, struct file *file)
 	return 0;
 }
 
+/**
+ * decode_hioctl() - translates encoded host ioctl to easily identifiable string
+ * @cmd:        The host ioctl command to decode.
+ *
+ * Return: A string identifying the decoded host ioctl.
+ */
+static char *decode_hioctl(int cmd)
+{
+	switch (cmd) {
+	default:
+		return "UNKNOWN";
+	}
+
+	return "UNKNOWN";
+}
+
+/**
+ * cxlflash_chr_ioctl() - character device IOCTL handler
+ * @file:	File pointer for this device.
+ * @cmd:	IOCTL command.
+ * @arg:	Userspace ioctl data structure.
+ *
+ * A read/write semaphore is used to implement a 'drain' of currently
+ * running ioctls. The read semaphore is taken at the beginning of each
+ * ioctl thread and released upon concluding execution. Additionally the
+ * semaphore should be released and then reacquired in any ioctl execution
+ * path which will wait for an event to occur that is outside the scope of
+ * the ioctl (i.e. an adapter reset). To drain the ioctls currently running,
+ * a thread simply needs to acquire the write semaphore.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static long cxlflash_chr_ioctl(struct file *file, unsigned int cmd,
+			       unsigned long arg)
+{
+	typedef int (*hioctl) (struct cxlflash_cfg *, void *);
+
+	struct cxlflash_cfg *cfg = file->private_data;
+	struct device *dev = &cfg->dev->dev;
+	char buf[sizeof(union cxlflash_ht_ioctls)];
+	void __user *uarg = (void __user *)arg;
+	struct ht_cxlflash_hdr *hdr;
+	size_t size = 0;
+	bool known_ioctl = false;
+	int idx = 0;
+	int rc = 0;
+	hioctl do_ioctl = NULL;
+
+	static const struct {
+		size_t size;
+		hioctl ioctl;
+	} ioctl_tbl[] = {	/* NOTE: order matters here */
+	};
+
+	/* Hold read semaphore so we can drain if needed */
+	down_read(&cfg->ioctl_rwsem);
+
+	dev_dbg(dev, "%s: cmd=%u idx=%d tbl_size=%lu\n",
+		__func__, cmd, idx, sizeof(ioctl_tbl));
+
+	switch (cmd) {
+	default:
+		rc = -EINVAL;
+		goto out;
+	}
+
+	if (unlikely(copy_from_user(&buf, uarg, size))) {
+		dev_err(dev, "%s: copy_from_user() fail "
+			"size=%lu cmd=%d (%s) uarg=%p\n",
+			__func__, size, cmd, decode_hioctl(cmd), uarg);
+		rc = -EFAULT;
+		goto out;
+	}
+
+	hdr = (struct ht_cxlflash_hdr *)&buf;
+	if (hdr->version != HT_CXLFLASH_VERSION_0) {
+		dev_dbg(dev, "%s: Version %u not supported for %s\n",
+			__func__, hdr->version, decode_hioctl(cmd));
+		rc = -EINVAL;
+		goto out;
+	}
+
+	if (hdr->rsvd[0] || hdr->rsvd[1] || hdr->return_flags) {
+		dev_dbg(dev, "%s: Reserved/rflags populated\n", __func__);
+		rc = -EINVAL;
+		goto out;
+	}
+
+	rc = do_ioctl(cfg, (void *)&buf);
+	if (likely(!rc))
+		if (unlikely(copy_to_user(uarg, &buf, size))) {
+			dev_err(dev, "%s: copy_to_user() fail "
+				"size=%lu cmd=%d (%s) uarg=%p\n",
+				__func__, size, cmd, decode_hioctl(cmd), uarg);
+			rc = -EFAULT;
+		}
+
+	/* fall through to exit */
+
+out:
+	up_read(&cfg->ioctl_rwsem);
+	if (unlikely(rc && known_ioctl))
+		dev_err(dev, "%s: ioctl %s (%08X) returned rc=%d\n",
+			__func__, decode_hioctl(cmd), cmd, rc);
+	else
+		dev_dbg(dev, "%s: ioctl %s (%08X) returned rc=%d\n",
+			__func__, decode_hioctl(cmd), cmd, rc);
+	return rc;
+}
+
 /*
  * Character device file operations
  */
 static const struct file_operations cxlflash_chr_fops = {
 	.owner          = THIS_MODULE,
 	.open           = cxlflash_chr_open,
+	.unlocked_ioctl	= cxlflash_chr_ioctl,
+	.compat_ioctl	= cxlflash_chr_ioctl,
 };
 
 /**
diff --git a/include/uapi/scsi/cxlflash_ioctl.h b/include/uapi/scsi/cxlflash_ioctl.h
index e9fdc12..87e1f63 100644
--- a/include/uapi/scsi/cxlflash_ioctl.h
+++ b/include/uapi/scsi/cxlflash_ioctl.h
@@ -31,7 +31,7 @@ struct dk_cxlflash_hdr {
 };
 
 /*
- * Return flag definitions available to all ioctls
+ * Return flag definitions available to all superpipe ioctls
  *
  * Similar to the input flags, these are grown from the bottom-up with the
  * intention that ioctl-specific return flag definitions would grow from the
@@ -180,6 +180,10 @@ union cxlflash_ioctls {
 #define CXL_MAGIC 0xCA
 #define CXL_IOWR(_n, _s)	_IOWR(CXL_MAGIC, _n, struct _s)
 
+/*
+ * CXL Flash superpipe ioctls start at base of the reserved CXL_MAGIC
+ * region (0x80) and grow upwards.
+ */
 #define DK_CXLFLASH_ATTACH		CXL_IOWR(0x80, dk_cxlflash_attach)
 #define DK_CXLFLASH_USER_DIRECT		CXL_IOWR(0x81, dk_cxlflash_udirect)
 #define DK_CXLFLASH_RELEASE		CXL_IOWR(0x82, dk_cxlflash_release)
@@ -191,4 +195,29 @@ union cxlflash_ioctls {
 #define DK_CXLFLASH_VLUN_RESIZE		CXL_IOWR(0x88, dk_cxlflash_resize)
 #define DK_CXLFLASH_VLUN_CLONE		CXL_IOWR(0x89, dk_cxlflash_clone)
 
+/*
+ * Structure and flag definitions CXL Flash host ioctls
+ */
+
+#define HT_CXLFLASH_VERSION_0  0
+
+struct ht_cxlflash_hdr {
+	__u16 version;                  /* Version data */
+	__u16 subcmd;                   /* Sub-command */
+	__u16 rsvd[2];                  /* Reserved for future use */
+	__u64 flags;                    /* Input flags */
+	__u64 return_flags;             /* Returned flags */
+};
+
+union cxlflash_ht_ioctls {
+};
+
+#define MAX_HT_CXLFLASH_IOCTL_SZ	(sizeof(union cxlflash_ht_ioctls))
+
+/*
+ * CXL Flash host ioctls start at the top of the reserved CXL_MAGIC
+ * region (0xBF) and grow downwards.
+ */
+
+
 #endif /* ifndef _CXLFLASH_IOCTL_H */
-- 
2.1.0

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

* [PATCH 12/17] cxlflash: Refactor AFU capability checking
  2017-06-22  2:12 [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Uma Krishnan
                   ` (10 preceding siblings ...)
  2017-06-22  2:15 ` [PATCH 11/17] cxlflash: Introduce host ioctl support Uma Krishnan
@ 2017-06-22  2:16 ` Uma Krishnan
  2017-06-22  2:16 ` [PATCH 13/17] cxlflash: Support LUN provisioning Uma Krishnan
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: Uma Krishnan @ 2017-06-22  2:16 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

From: "Matthew R. Ochs" <mrochs@linux.vnet.ibm.com>

The existing AFU capability checking infrastructure is closely tied to
the command mode capability bits. In order to support new capabilities,
refactor the existing infrastructure to be more generic.

Signed-off-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
---
 drivers/scsi/cxlflash/common.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
index cbc0eb7..c96526e 100644
--- a/drivers/scsi/cxlflash/common.h
+++ b/drivers/scsi/cxlflash/common.h
@@ -255,21 +255,21 @@ static inline bool afu_is_irqpoll_enabled(struct afu *afu)
 	return !!afu->irqpoll_weight;
 }
 
-static inline bool afu_is_cmd_mode(struct afu *afu, u64 cmd_mode)
+static inline bool afu_has_cap(struct afu *afu, u64 cap)
 {
 	u64 afu_cap = afu->interface_version >> SISL_INTVER_CAP_SHIFT;
 
-	return afu_cap & cmd_mode;
+	return afu_cap & cap;
 }
 
 static inline bool afu_is_sq_cmd_mode(struct afu *afu)
 {
-	return afu_is_cmd_mode(afu, SISL_INTVER_CAP_SQ_CMD_MODE);
+	return afu_has_cap(afu, SISL_INTVER_CAP_SQ_CMD_MODE);
 }
 
 static inline bool afu_is_ioarrin_cmd_mode(struct afu *afu)
 {
-	return afu_is_cmd_mode(afu, SISL_INTVER_CAP_IOARRIN_CMD_MODE);
+	return afu_has_cap(afu, SISL_INTVER_CAP_IOARRIN_CMD_MODE);
 }
 
 static inline u64 lun_to_lunid(u64 lun)
-- 
2.1.0

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

* [PATCH 13/17] cxlflash: Support LUN provisioning
  2017-06-22  2:12 [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Uma Krishnan
                   ` (11 preceding siblings ...)
  2017-06-22  2:16 ` [PATCH 12/17] cxlflash: Refactor AFU capability checking Uma Krishnan
@ 2017-06-22  2:16 ` Uma Krishnan
  2017-06-22  2:16 ` [PATCH 14/17] cxlflash: Support AFU debug Uma Krishnan
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: Uma Krishnan @ 2017-06-22  2:16 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

From: "Matthew R. Ochs" <mrochs@linux.vnet.ibm.com>

Adopt the SISLite AFU LUN provisioning capability to allow future CXL
Flash adapters the ability to better manage storage. Update the SISLite
header with the changes necessary to support LUN provision operations
and create a host ioctl interface for user LUN management software. Also
update the cxlflash documentation to describe this new host ioctl.

Signed-off-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
---
 Documentation/powerpc/cxlflash.txt |  31 +++++++++++
 drivers/scsi/cxlflash/common.h     |   5 ++
 drivers/scsi/cxlflash/main.c       | 107 ++++++++++++++++++++++++++++++++++++-
 drivers/scsi/cxlflash/main.h       |   5 ++
 drivers/scsi/cxlflash/sislite.h    |  22 +++++++-
 include/uapi/scsi/cxlflash_ioctl.h |  31 +++++++++--
 6 files changed, 192 insertions(+), 9 deletions(-)

diff --git a/Documentation/powerpc/cxlflash.txt b/Documentation/powerpc/cxlflash.txt
index ee67021..2d6297b 100644
--- a/Documentation/powerpc/cxlflash.txt
+++ b/Documentation/powerpc/cxlflash.txt
@@ -382,3 +382,34 @@ CXL Flash Driver Host IOCTLs
 
     The structure definitions for these IOCTLs are available in:
     uapi/scsi/cxlflash_ioctl.h
+
+HT_CXLFLASH_LUN_PROVISION
+-------------------------
+    This ioctl is used to create and delete persistent LUNs on cxlflash
+    devices that lack an external LUN management interface. It is only
+    valid when used with AFUs that support the LUN provision capability.
+
+    When sufficient space is available, LUNs can be created by specifying
+    the target port to host the LUN and a desired size in 4K blocks. Upon
+    success, the LUN ID and WWID of the created LUN will be returned and
+    the SCSI bus can be scanned to detect the change in LUN topology. Note
+    that partial allocations are not supported. Should a creation fail due
+    to a space issue, the target port can be queried for its current LUN
+    geometry.
+
+    To remove a LUN, the device must first be disassociated from the Linux
+    SCSI subsystem. The LUN deletion can then be initiated by specifying a
+    target port and LUN ID. Upon success, the LUN geometry associated with
+    the port will be updated to reflect new number of provisioned LUNs and
+    available capacity.
+
+    To query the LUN geometry of a port, the target port is specified and
+    upon success, the following information is presented:
+
+        - Maximum number of provisioned LUNs allowed for the port
+        - Current number of provisioned LUNs for the port
+        - Maximum total capacity of provisioned LUNs for the port (4K blocks)
+        - Current total capacity of provisioned LUNs for the port (4K blocks)
+
+    With this information, the number of available LUNs and capacity can be
+    can be calculated.
diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
index c96526e..5810724 100644
--- a/drivers/scsi/cxlflash/common.h
+++ b/drivers/scsi/cxlflash/common.h
@@ -262,6 +262,11 @@ static inline bool afu_has_cap(struct afu *afu, u64 cap)
 	return afu_cap & cap;
 }
 
+static inline bool afu_is_lun_provision(struct afu *afu)
+{
+	return afu_has_cap(afu, SISL_INTVER_CAP_LUN_PROVISION);
+}
+
 static inline bool afu_is_sq_cmd_mode(struct afu *afu)
 {
 	return afu_has_cap(afu, SISL_INTVER_CAP_SQ_CMD_MODE);
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index be468ed1..1279293 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -3227,14 +3227,105 @@ static int cxlflash_chr_open(struct inode *inode, struct file *file)
 static char *decode_hioctl(int cmd)
 {
 	switch (cmd) {
-	default:
-		return "UNKNOWN";
+	case HT_CXLFLASH_LUN_PROVISION:
+		return __stringify_1(HT_CXLFLASH_LUN_PROVISION);
 	}
 
 	return "UNKNOWN";
 }
 
 /**
+ * cxlflash_lun_provision() - host LUN provisioning handler
+ * @cfg:	Internal structure associated with the host.
+ * @arg:	Kernel copy of userspace ioctl data structure.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int cxlflash_lun_provision(struct cxlflash_cfg *cfg,
+				  struct ht_cxlflash_lun_provision *lunprov)
+{
+	struct afu *afu = cfg->afu;
+	struct device *dev = &cfg->dev->dev;
+	struct sisl_ioarcb rcb;
+	struct sisl_ioasa asa;
+	__be64 __iomem *fc_port_regs;
+	u16 port = lunprov->port;
+	u16 scmd = lunprov->hdr.subcmd;
+	u16 type;
+	u64 reg;
+	u64 size;
+	u64 lun_id;
+	int rc = 0;
+
+	if (!afu_is_lun_provision(afu)) {
+		rc = -ENOTSUPP;
+		goto out;
+	}
+
+	if (port >= cfg->num_fc_ports) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	switch (scmd) {
+	case HT_CXLFLASH_LUN_PROVISION_SUBCMD_CREATE_LUN:
+		type = SISL_AFU_LUN_PROVISION_CREATE;
+		size = lunprov->size;
+		lun_id = 0;
+		break;
+	case HT_CXLFLASH_LUN_PROVISION_SUBCMD_DELETE_LUN:
+		type = SISL_AFU_LUN_PROVISION_DELETE;
+		size = 0;
+		lun_id = lunprov->lun_id;
+		break;
+	case HT_CXLFLASH_LUN_PROVISION_SUBCMD_QUERY_PORT:
+		fc_port_regs = get_fc_port_regs(cfg, port);
+
+		reg = readq_be(&fc_port_regs[FC_MAX_NUM_LUNS / 8]);
+		lunprov->max_num_luns = reg;
+		reg = readq_be(&fc_port_regs[FC_CUR_NUM_LUNS / 8]);
+		lunprov->cur_num_luns = reg;
+		reg = readq_be(&fc_port_regs[FC_MAX_CAP_PORT / 8]);
+		lunprov->max_cap_port = reg;
+		reg = readq_be(&fc_port_regs[FC_CUR_CAP_PORT / 8]);
+		lunprov->cur_cap_port = reg;
+
+		goto out;
+	default:
+		rc = -EINVAL;
+		goto out;
+	}
+
+	memset(&rcb, 0, sizeof(rcb));
+	memset(&asa, 0, sizeof(asa));
+	rcb.req_flags = SISL_REQ_FLAGS_AFU_CMD;
+	rcb.lun_id = lun_id;
+	rcb.msi = SISL_MSI_RRQ_UPDATED;
+	rcb.timeout = MC_LUN_PROV_TIMEOUT;
+	rcb.ioasa = &asa;
+
+	rcb.cdb[0] = SISL_AFU_CMD_LUN_PROVISION;
+	rcb.cdb[1] = type;
+	rcb.cdb[2] = port;
+	put_unaligned_be64(size, &rcb.cdb[8]);
+
+	rc = send_afu_cmd(afu, &rcb);
+	if (rc) {
+		dev_err(dev, "%s: send_afu_cmd failed rc=%d asc=%08x afux=%x\n",
+			__func__, rc, asa.ioasc, asa.afu_extra);
+		goto out;
+	}
+
+	if (scmd == HT_CXLFLASH_LUN_PROVISION_SUBCMD_CREATE_LUN) {
+		lunprov->lun_id = (u64)asa.lunid_hi << 32 | asa.lunid_lo;
+		memcpy(lunprov->wwid, asa.wwid, sizeof(lunprov->wwid));
+	}
+out:
+	dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc);
+	return rc;
+}
+
+/**
  * cxlflash_chr_ioctl() - character device IOCTL handler
  * @file:	File pointer for this device.
  * @cmd:	IOCTL command.
@@ -3270,6 +3361,8 @@ static long cxlflash_chr_ioctl(struct file *file, unsigned int cmd,
 		size_t size;
 		hioctl ioctl;
 	} ioctl_tbl[] = {	/* NOTE: order matters here */
+	{ sizeof(struct ht_cxlflash_lun_provision),
+		(hioctl)cxlflash_lun_provision },
 	};
 
 	/* Hold read semaphore so we can drain if needed */
@@ -3279,6 +3372,16 @@ static long cxlflash_chr_ioctl(struct file *file, unsigned int cmd,
 		__func__, cmd, idx, sizeof(ioctl_tbl));
 
 	switch (cmd) {
+	case HT_CXLFLASH_LUN_PROVISION:
+		known_ioctl = true;
+		idx = _IOC_NR(HT_CXLFLASH_LUN_PROVISION) - _IOC_NR(cmd);
+		size = ioctl_tbl[idx].size;
+		do_ioctl = ioctl_tbl[idx].ioctl;
+
+		if (likely(do_ioctl))
+			break;
+
+		/* fall through */
 	default:
 		rc = -EINVAL;
 		goto out;
diff --git a/drivers/scsi/cxlflash/main.h b/drivers/scsi/cxlflash/main.h
index 44c86c2..6ae8a11 100644
--- a/drivers/scsi/cxlflash/main.h
+++ b/drivers/scsi/cxlflash/main.h
@@ -41,6 +41,10 @@
 /* FC defines */
 #define FC_MTIP_CMDCONFIG 0x010
 #define FC_MTIP_STATUS 0x018
+#define FC_MAX_NUM_LUNS 0x080 /* Max LUNs host can provision for port */
+#define FC_CUR_NUM_LUNS 0x088 /* Cur number LUNs provisioned for port */
+#define FC_MAX_CAP_PORT 0x090 /* Max capacity all LUNs for port (4K blocks) */
+#define FC_CUR_CAP_PORT 0x098 /* Cur capacity all LUNs for port (4K blocks) */
 
 #define FC_PNAME 0x300
 #define FC_CONFIG 0x320
@@ -63,6 +67,7 @@
 
 /* AFU command timeout values */
 #define MC_AFU_SYNC_TIMEOUT	5	/* 5 secs */
+#define MC_LUN_PROV_TIMEOUT	5	/* 5 secs */
 
 /* AFU command room retry limit */
 #define MC_ROOM_RETRY_CNT	10
diff --git a/drivers/scsi/cxlflash/sislite.h b/drivers/scsi/cxlflash/sislite.h
index 483710a..c216fee 100644
--- a/drivers/scsi/cxlflash/sislite.h
+++ b/drivers/scsi/cxlflash/sislite.h
@@ -73,6 +73,10 @@ struct sisl_ioarcb {
 	u32 rsvd1;
 	u8 cdb[16];		/* must be in big endian */
 #define SISL_AFU_CMD_SYNC		0xC0	/* AFU sync command */
+#define SISL_AFU_CMD_LUN_PROVISION	0xD0	/* AFU LUN provision command */
+
+#define SISL_AFU_LUN_PROVISION_CREATE	0x00	/* LUN provision create type */
+#define SISL_AFU_LUN_PROVISION_DELETE	0x01	/* LUN provision delete type */
 
 	union {
 		u64 reserved;			/* Reserved for IOARRIN mode */
@@ -158,6 +162,7 @@ struct sisl_rc {
 };
 
 #define SISL_SENSE_DATA_LEN     20	/* Sense data length         */
+#define SISL_WWID_DATA_LEN	16	/* WWID data length          */
 
 /*
  * IOASA: 64 bytes & must follow IOARCB, min 16 byte alignment required,
@@ -169,7 +174,12 @@ struct sisl_ioasa {
 		u32 ioasc;
 #define SISL_IOASC_GOOD_COMPLETION        0x00000000U
 	};
-	u32 resid;
+
+	union {
+		u32 resid;
+		u32 lunid_hi;
+	};
+
 	u8 port;
 	u8 afu_extra;
 	/* when afu_rc=0x04, 0x14, 0x31 (_xxx_DMA_ERR):
@@ -192,7 +202,14 @@ struct sisl_ioasa {
 
 	u8 scsi_extra;
 	u8 fc_extra;
-	u8 sense_data[SISL_SENSE_DATA_LEN];
+
+	union {
+		u8 sense_data[SISL_SENSE_DATA_LEN];
+		struct {
+			u32 lunid_lo;
+			u8 wwid[SISL_WWID_DATA_LEN];
+		};
+	};
 
 	/* These fields are defined by the SISlite architecture for the
 	 * host to use as they see fit for their implementation.
@@ -394,6 +411,7 @@ struct sisl_global_regs {
 #define SISL_INTVER_CAP_SQ_CMD_MODE		0x400000000000ULL
 #define SISL_INTVER_CAP_RESERVED_CMD_MODE_A	0x200000000000ULL
 #define SISL_INTVER_CAP_RESERVED_CMD_MODE_B	0x100000000000ULL
+#define SISL_INTVER_CAP_LUN_PROVISION		0x080000000000ULL
 };
 
 #define CXLFLASH_NUM_FC_PORTS_PER_BANK	2	/* fixed # of ports per bank */
diff --git a/include/uapi/scsi/cxlflash_ioctl.h b/include/uapi/scsi/cxlflash_ioctl.h
index 87e1f63..ad79c34 100644
--- a/include/uapi/scsi/cxlflash_ioctl.h
+++ b/include/uapi/scsi/cxlflash_ioctl.h
@@ -202,14 +202,34 @@ union cxlflash_ioctls {
 #define HT_CXLFLASH_VERSION_0  0
 
 struct ht_cxlflash_hdr {
-	__u16 version;                  /* Version data */
-	__u16 subcmd;                   /* Sub-command */
-	__u16 rsvd[2];                  /* Reserved for future use */
-	__u64 flags;                    /* Input flags */
-	__u64 return_flags;             /* Returned flags */
+	__u16 version;		/* Version data */
+	__u16 subcmd;		/* Sub-command */
+	__u16 rsvd[2];		/* Reserved for future use */
+	__u64 flags;		/* Input flags */
+	__u64 return_flags;	/* Returned flags */
+};
+
+#define HT_CXLFLASH_LUN_PROVISION_SUBCMD_CREATE_LUN	0x0001
+#define HT_CXLFLASH_LUN_PROVISION_SUBCMD_DELETE_LUN	0x0002
+#define HT_CXLFLASH_LUN_PROVISION_SUBCMD_QUERY_PORT	0x0003
+#define HT_CXLFLASH_LUN_PROVISION_WWID_LEN		16
+
+struct ht_cxlflash_lun_provision {
+	struct ht_cxlflash_hdr hdr; /* Common fields */
+	__u16 port;		    /* Target port for provision request */
+	__u16 reserved16[3];	    /* Reserved for future use */
+	__u64 size;		    /* Size of LUN (4K blocks) */
+	__u64 lun_id;		    /* SCSI LUN ID */
+	__u8 wwid[HT_CXLFLASH_LUN_PROVISION_WWID_LEN]; /* Page83 WWID, NAA-6 */
+	__u64 max_num_luns;	    /* Maximum number of LUNs provisioned */
+	__u64 cur_num_luns;	    /* Current number of LUNs provisioned */
+	__u64 max_cap_port;	    /* Total capacity for port (4K blocks) */
+	__u64 cur_cap_port;	    /* Current capacity for port (4K blocks) */
+	__u64 reserved[8];	    /* Reserved for future use */
 };
 
 union cxlflash_ht_ioctls {
+	struct ht_cxlflash_lun_provision lun_provision;
 };
 
 #define MAX_HT_CXLFLASH_IOCTL_SZ	(sizeof(union cxlflash_ht_ioctls))
@@ -218,6 +238,7 @@ union cxlflash_ht_ioctls {
  * CXL Flash host ioctls start at the top of the reserved CXL_MAGIC
  * region (0xBF) and grow downwards.
  */
+#define HT_CXLFLASH_LUN_PROVISION CXL_IOWR(0xBF, ht_cxlflash_lun_provision)
 
 
 #endif /* ifndef _CXLFLASH_IOCTL_H */
-- 
2.1.0

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

* [PATCH 14/17] cxlflash: Support AFU debug
  2017-06-22  2:12 [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Uma Krishnan
                   ` (12 preceding siblings ...)
  2017-06-22  2:16 ` [PATCH 13/17] cxlflash: Support LUN provisioning Uma Krishnan
@ 2017-06-22  2:16 ` Uma Krishnan
  2017-06-22  2:16 ` [PATCH 15/17] cxlflash: Support WS16 unmap Uma Krishnan
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: Uma Krishnan @ 2017-06-22  2:16 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

From: "Matthew R. Ochs" <mrochs@linux.vnet.ibm.com>

Adopt the SISLite AFU debug capability to allow future CXL Flash
adapters the ability to better debug AFU issues. Update the SISLite
header with the changes necessary to support AFU debug operations
and create a host ioctl interface for user debug software. Also
update the cxlflash documentation to describe this new host ioctl.

Signed-off-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
---
 Documentation/powerpc/cxlflash.txt | 14 ++++++
 drivers/scsi/cxlflash/common.h     |  5 ++
 drivers/scsi/cxlflash/main.c       | 96 ++++++++++++++++++++++++++++++++++++++
 drivers/scsi/cxlflash/main.h       |  1 +
 drivers/scsi/cxlflash/sislite.h    |  2 +
 include/uapi/scsi/cxlflash_ioctl.h | 37 +++++++++++++--
 6 files changed, 152 insertions(+), 3 deletions(-)

diff --git a/Documentation/powerpc/cxlflash.txt b/Documentation/powerpc/cxlflash.txt
index 2d6297b..a64bdaa 100644
--- a/Documentation/powerpc/cxlflash.txt
+++ b/Documentation/powerpc/cxlflash.txt
@@ -413,3 +413,17 @@ HT_CXLFLASH_LUN_PROVISION
 
     With this information, the number of available LUNs and capacity can be
     can be calculated.
+
+HT_CXLFLASH_AFU_DEBUG
+---------------------
+    This ioctl is used to debug AFUs by supporting a command pass-through
+    interface. It is only valid when used with AFUs that support the AFU
+    debug capability.
+
+    With exception of buffer management, AFU debug commands are opaque to
+    cxlflash and treated as pass-through. For debug commands that do require
+    data transfer, the user supplies an adequately sized data buffer and must
+    specify the data transfer direction with respect to the host. There is a
+    maximum transfer size of 256K imposed. Note that partial read completions
+    are not supported - when errors are experienced with a host read data
+    transfer, the data buffer is not copied back to the user.
diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
index 5810724..a91151c 100644
--- a/drivers/scsi/cxlflash/common.h
+++ b/drivers/scsi/cxlflash/common.h
@@ -262,6 +262,11 @@ static inline bool afu_has_cap(struct afu *afu, u64 cap)
 	return afu_cap & cap;
 }
 
+static inline bool afu_is_afu_debug(struct afu *afu)
+{
+	return afu_has_cap(afu, SISL_INTVER_CAP_AFU_DEBUG);
+}
+
 static inline bool afu_is_lun_provision(struct afu *afu)
 {
 	return afu_has_cap(afu, SISL_INTVER_CAP_LUN_PROVISION);
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 1279293..d3ad52e 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -3326,6 +3326,99 @@ static int cxlflash_lun_provision(struct cxlflash_cfg *cfg,
 }
 
 /**
+ * cxlflash_afu_debug() - host AFU debug handler
+ * @cfg:	Internal structure associated with the host.
+ * @arg:	Kernel copy of userspace ioctl data structure.
+ *
+ * For debug requests requiring a data buffer, always provide an aligned
+ * (cache line) buffer to the AFU to appease any alignment requirements.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int cxlflash_afu_debug(struct cxlflash_cfg *cfg,
+			      struct ht_cxlflash_afu_debug *afu_dbg)
+{
+	struct afu *afu = cfg->afu;
+	struct device *dev = &cfg->dev->dev;
+	struct sisl_ioarcb rcb;
+	struct sisl_ioasa asa;
+	char *buf = NULL;
+	char *kbuf = NULL;
+	void __user *ubuf = (__force void __user *)afu_dbg->data_ea;
+	u16 req_flags = SISL_REQ_FLAGS_AFU_CMD;
+	u32 ulen = afu_dbg->data_len;
+	bool is_write = afu_dbg->hdr.flags & HT_CXLFLASH_HOST_WRITE;
+	int rc = 0;
+
+	if (!afu_is_afu_debug(afu)) {
+		rc = -ENOTSUPP;
+		goto out;
+	}
+
+	if (ulen) {
+		req_flags |= SISL_REQ_FLAGS_SUP_UNDERRUN;
+
+		if (ulen > HT_CXLFLASH_AFU_DEBUG_MAX_DATA_LEN) {
+			rc = -EINVAL;
+			goto out;
+		}
+
+		if (unlikely(!access_ok(is_write ? VERIFY_READ : VERIFY_WRITE,
+					ubuf, ulen))) {
+			rc = -EFAULT;
+			goto out;
+		}
+
+		buf = kmalloc(ulen + cache_line_size() - 1, GFP_KERNEL);
+		if (unlikely(!buf)) {
+			rc = -ENOMEM;
+			goto out;
+		}
+
+		kbuf = PTR_ALIGN(buf, cache_line_size());
+
+		if (is_write) {
+			req_flags |= SISL_REQ_FLAGS_HOST_WRITE;
+
+			rc = copy_from_user(kbuf, ubuf, ulen);
+			if (unlikely(rc))
+				goto out;
+		}
+	}
+
+	memset(&rcb, 0, sizeof(rcb));
+	memset(&asa, 0, sizeof(asa));
+
+	rcb.req_flags = req_flags;
+	rcb.msi = SISL_MSI_RRQ_UPDATED;
+	rcb.timeout = MC_AFU_DEBUG_TIMEOUT;
+	rcb.ioasa = &asa;
+
+	if (ulen) {
+		rcb.data_len = ulen;
+		rcb.data_ea = (uintptr_t)kbuf;
+	}
+
+	rcb.cdb[0] = SISL_AFU_CMD_DEBUG;
+	memcpy(&rcb.cdb[4], afu_dbg->afu_subcmd,
+	       HT_CXLFLASH_AFU_DEBUG_SUBCMD_LEN);
+
+	rc = send_afu_cmd(afu, &rcb);
+	if (rc) {
+		dev_err(dev, "%s: send_afu_cmd failed rc=%d asc=%08x afux=%x\n",
+			__func__, rc, asa.ioasc, asa.afu_extra);
+		goto out;
+	}
+
+	if (ulen && !is_write)
+		rc = copy_to_user(ubuf, kbuf, ulen);
+out:
+	kfree(buf);
+	dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc);
+	return rc;
+}
+
+/**
  * cxlflash_chr_ioctl() - character device IOCTL handler
  * @file:	File pointer for this device.
  * @cmd:	IOCTL command.
@@ -3363,6 +3456,8 @@ static long cxlflash_chr_ioctl(struct file *file, unsigned int cmd,
 	} ioctl_tbl[] = {	/* NOTE: order matters here */
 	{ sizeof(struct ht_cxlflash_lun_provision),
 		(hioctl)cxlflash_lun_provision },
+	{ sizeof(struct ht_cxlflash_afu_debug),
+		(hioctl)cxlflash_afu_debug },
 	};
 
 	/* Hold read semaphore so we can drain if needed */
@@ -3373,6 +3468,7 @@ static long cxlflash_chr_ioctl(struct file *file, unsigned int cmd,
 
 	switch (cmd) {
 	case HT_CXLFLASH_LUN_PROVISION:
+	case HT_CXLFLASH_AFU_DEBUG:
 		known_ioctl = true;
 		idx = _IOC_NR(HT_CXLFLASH_LUN_PROVISION) - _IOC_NR(cmd);
 		size = ioctl_tbl[idx].size;
diff --git a/drivers/scsi/cxlflash/main.h b/drivers/scsi/cxlflash/main.h
index 6ae8a11..880e348 100644
--- a/drivers/scsi/cxlflash/main.h
+++ b/drivers/scsi/cxlflash/main.h
@@ -68,6 +68,7 @@
 /* AFU command timeout values */
 #define MC_AFU_SYNC_TIMEOUT	5	/* 5 secs */
 #define MC_LUN_PROV_TIMEOUT	5	/* 5 secs */
+#define MC_AFU_DEBUG_TIMEOUT	5	/* 5 secs */
 
 /* AFU command room retry limit */
 #define MC_ROOM_RETRY_CNT	10
diff --git a/drivers/scsi/cxlflash/sislite.h b/drivers/scsi/cxlflash/sislite.h
index c216fee..d671fae 100644
--- a/drivers/scsi/cxlflash/sislite.h
+++ b/drivers/scsi/cxlflash/sislite.h
@@ -74,6 +74,7 @@ struct sisl_ioarcb {
 	u8 cdb[16];		/* must be in big endian */
 #define SISL_AFU_CMD_SYNC		0xC0	/* AFU sync command */
 #define SISL_AFU_CMD_LUN_PROVISION	0xD0	/* AFU LUN provision command */
+#define SISL_AFU_CMD_DEBUG		0xE0	/* AFU debug command */
 
 #define SISL_AFU_LUN_PROVISION_CREATE	0x00	/* LUN provision create type */
 #define SISL_AFU_LUN_PROVISION_DELETE	0x01	/* LUN provision delete type */
@@ -412,6 +413,7 @@ struct sisl_global_regs {
 #define SISL_INTVER_CAP_RESERVED_CMD_MODE_A	0x200000000000ULL
 #define SISL_INTVER_CAP_RESERVED_CMD_MODE_B	0x100000000000ULL
 #define SISL_INTVER_CAP_LUN_PROVISION		0x080000000000ULL
+#define SISL_INTVER_CAP_AFU_DEBUG		0x040000000000ULL
 };
 
 #define CXLFLASH_NUM_FC_PORTS_PER_BANK	2	/* fixed # of ports per bank */
diff --git a/include/uapi/scsi/cxlflash_ioctl.h b/include/uapi/scsi/cxlflash_ioctl.h
index ad79c34..48d107e 100644
--- a/include/uapi/scsi/cxlflash_ioctl.h
+++ b/include/uapi/scsi/cxlflash_ioctl.h
@@ -18,6 +18,11 @@
 #include <linux/types.h>
 
 /*
+ * Structure and definitions for all CXL Flash ioctls
+ */
+#define CXLFLASH_WWID_LEN		16
+
+/*
  * Structure and flag definitions CXL Flash superpipe ioctls
  */
 
@@ -151,7 +156,7 @@ struct dk_cxlflash_recover_afu {
 	__u64 reserved[8];		/* Reserved for future use */
 };
 
-#define DK_CXLFLASH_MANAGE_LUN_WWID_LEN			16
+#define DK_CXLFLASH_MANAGE_LUN_WWID_LEN			CXLFLASH_WWID_LEN
 #define DK_CXLFLASH_MANAGE_LUN_ENABLE_SUPERPIPE		0x8000000000000000ULL
 #define DK_CXLFLASH_MANAGE_LUN_DISABLE_SUPERPIPE	0x4000000000000000ULL
 #define DK_CXLFLASH_MANAGE_LUN_ALL_PORTS_ACCESSIBLE	0x2000000000000000ULL
@@ -209,10 +214,20 @@ struct ht_cxlflash_hdr {
 	__u64 return_flags;	/* Returned flags */
 };
 
+/*
+ * Input flag definitions available to all host ioctls
+ *
+ * These are grown from the bottom-up with the intention that ioctl-specific
+ * input flag definitions would grow from the top-down, allowing the two sets
+ * to co-exist. While not required/enforced at this time, this provides future
+ * flexibility.
+ */
+#define HT_CXLFLASH_HOST_READ				0x0000000000000000ULL
+#define HT_CXLFLASH_HOST_WRITE				0x0000000000000001ULL
+
 #define HT_CXLFLASH_LUN_PROVISION_SUBCMD_CREATE_LUN	0x0001
 #define HT_CXLFLASH_LUN_PROVISION_SUBCMD_DELETE_LUN	0x0002
 #define HT_CXLFLASH_LUN_PROVISION_SUBCMD_QUERY_PORT	0x0003
-#define HT_CXLFLASH_LUN_PROVISION_WWID_LEN		16
 
 struct ht_cxlflash_lun_provision {
 	struct ht_cxlflash_hdr hdr; /* Common fields */
@@ -220,7 +235,7 @@ struct ht_cxlflash_lun_provision {
 	__u16 reserved16[3];	    /* Reserved for future use */
 	__u64 size;		    /* Size of LUN (4K blocks) */
 	__u64 lun_id;		    /* SCSI LUN ID */
-	__u8 wwid[HT_CXLFLASH_LUN_PROVISION_WWID_LEN]; /* Page83 WWID, NAA-6 */
+	__u8 wwid[CXLFLASH_WWID_LEN];/* Page83 WWID, NAA-6 */
 	__u64 max_num_luns;	    /* Maximum number of LUNs provisioned */
 	__u64 cur_num_luns;	    /* Current number of LUNs provisioned */
 	__u64 max_cap_port;	    /* Total capacity for port (4K blocks) */
@@ -228,8 +243,23 @@ struct ht_cxlflash_lun_provision {
 	__u64 reserved[8];	    /* Reserved for future use */
 };
 
+#define	HT_CXLFLASH_AFU_DEBUG_MAX_DATA_LEN		262144	/* 256K */
+#define HT_CXLFLASH_AFU_DEBUG_SUBCMD_LEN		12
+struct ht_cxlflash_afu_debug {
+	struct ht_cxlflash_hdr hdr; /* Common fields */
+	__u8 reserved8[4];	    /* Reserved for future use */
+	__u8 afu_subcmd[HT_CXLFLASH_AFU_DEBUG_SUBCMD_LEN]; /* AFU subcommand,
+							    * (pass through)
+							    */
+	__u64 data_ea;		    /* Data buffer effective address */
+	__u32 data_len;		    /* Data buffer length */
+	__u32 reserved32;	    /* Reserved for future use */
+	__u64 reserved[8];	    /* Reserved for future use */
+};
+
 union cxlflash_ht_ioctls {
 	struct ht_cxlflash_lun_provision lun_provision;
+	struct ht_cxlflash_afu_debug afu_debug;
 };
 
 #define MAX_HT_CXLFLASH_IOCTL_SZ	(sizeof(union cxlflash_ht_ioctls))
@@ -239,6 +269,7 @@ union cxlflash_ht_ioctls {
  * region (0xBF) and grow downwards.
  */
 #define HT_CXLFLASH_LUN_PROVISION CXL_IOWR(0xBF, ht_cxlflash_lun_provision)
+#define HT_CXLFLASH_AFU_DEBUG	  CXL_IOWR(0xBE, ht_cxlflash_afu_debug)
 
 
 #endif /* ifndef _CXLFLASH_IOCTL_H */
-- 
2.1.0

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

* [PATCH 15/17] cxlflash: Support WS16 unmap
  2017-06-22  2:12 [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Uma Krishnan
                   ` (13 preceding siblings ...)
  2017-06-22  2:16 ` [PATCH 14/17] cxlflash: Support AFU debug Uma Krishnan
@ 2017-06-22  2:16 ` Uma Krishnan
  2017-06-22  2:16 ` [PATCH 16/17] cxlflash: Remove zeroing of private command data Uma Krishnan
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: Uma Krishnan @ 2017-06-22  2:16 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

From: "Matthew R. Ochs" <mrochs@linux.vnet.ibm.com>

The cxlflash driver supports performing a write-same16 to scrub virtual
luns when they are released by a user. To date, AFUs for adapters that
are supported by cxlflash do not have the capability to unmap as part of
the WS operation. This can lead to fragmented flash devices which results
in performance degradation.

Future AFUs can optionally support unmap write-same commands and reflects
this support via the context control register. This provides userspace
applications with direct visibility such that they need not depend on a
host API.

Detect unmap support during cxlflash initialization by reading the context
control register associated with the primary hardware queue. Update the
existing write_same16() routine to set the unmap bit in the CDB when unmap
is supported by the host.

Signed-off-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
---
 drivers/scsi/cxlflash/common.h  |  1 +
 drivers/scsi/cxlflash/main.c    | 12 ++++++++++++
 drivers/scsi/cxlflash/sislite.h |  1 +
 drivers/scsi/cxlflash/vlun.c    |  1 +
 4 files changed, 15 insertions(+)

diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
index a91151c..e95e5a5 100644
--- a/drivers/scsi/cxlflash/common.h
+++ b/drivers/scsi/cxlflash/common.h
@@ -147,6 +147,7 @@ struct cxlflash_cfg {
 	wait_queue_head_t tmf_waitq;
 	spinlock_t tmf_slock;
 	bool tmf_active;
+	bool ws_unmap;		/* Write-same unmap supported */
 	wait_queue_head_t reset_waitq;
 	enum cxlflash_state state;
 	async_cookie_t async_reset_cookie;
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index d3ad52e..0cce442 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -1812,6 +1812,18 @@ static int init_global(struct cxlflash_cfg *cfg)
 			SISL_CTX_CAP_AFU_CMD | SISL_CTX_CAP_GSCSI_CMD),
 			&hwq->ctrl_map->ctx_cap);
 	}
+
+	/*
+	 * Determine write-same unmap support for host by evaluating the unmap
+	 * sector support bit of the context control register associated with
+	 * the primary hardware queue. Note that while this status is reflected
+	 * in a context register, the outcome can be assumed to be host-wide.
+	 */
+	hwq = get_hwq(afu, PRIMARY_HWQ);
+	reg = readq_be(&hwq->host_map->ctx_ctrl);
+	if (reg & SISL_CTX_CTRL_UNMAP_SECTOR)
+		cfg->ws_unmap = true;
+
 	/* Initialize heartbeat */
 	afu->hb = readq_be(&afu->afu_map->global.regs.afu_hb);
 out:
diff --git a/drivers/scsi/cxlflash/sislite.h b/drivers/scsi/cxlflash/sislite.h
index d671fae..09daa86 100644
--- a/drivers/scsi/cxlflash/sislite.h
+++ b/drivers/scsi/cxlflash/sislite.h
@@ -283,6 +283,7 @@ struct sisl_host_map {
 	__be64 rrq_end;		/* write sequence: start followed by end */
 	__be64 cmd_room;
 	__be64 ctx_ctrl;	/* least significant byte or b56:63 is LISN# */
+#define SISL_CTX_CTRL_UNMAP_SECTOR	0x8000000000000000ULL /* b0 */
 	__be64 mbox_w;		/* restricted use */
 	__be64 sq_start;	/* Submission Queue (R/W): write sequence and */
 	__be64 sq_end;		/* inclusion semantics are the same as RRQ    */
diff --git a/drivers/scsi/cxlflash/vlun.c b/drivers/scsi/cxlflash/vlun.c
index 0800bcb..bdfb930 100644
--- a/drivers/scsi/cxlflash/vlun.c
+++ b/drivers/scsi/cxlflash/vlun.c
@@ -446,6 +446,7 @@ static int write_same16(struct scsi_device *sdev,
 	while (left > 0) {
 
 		scsi_cmd[0] = WRITE_SAME_16;
+		scsi_cmd[1] = cfg->ws_unmap ? 0x8 : 0;
 		put_unaligned_be64(offset, &scsi_cmd[2]);
 		put_unaligned_be32(ws_limit < left ? ws_limit : left,
 				   &scsi_cmd[10]);
-- 
2.1.0

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

* [PATCH 16/17] cxlflash: Remove zeroing of private command data
  2017-06-22  2:12 [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Uma Krishnan
                   ` (14 preceding siblings ...)
  2017-06-22  2:16 ` [PATCH 15/17] cxlflash: Support WS16 unmap Uma Krishnan
@ 2017-06-22  2:16 ` Uma Krishnan
  2017-06-22  2:16 ` [PATCH 17/17] cxlflash: Update TMF command processing Uma Krishnan
  2017-06-26 18:43 ` [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Martin K. Petersen
  17 siblings, 0 replies; 28+ messages in thread
From: Uma Krishnan @ 2017-06-22  2:16 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

From: "Matthew R. Ochs" <mrochs@linux.vnet.ibm.com>

The SCSI core now zeroes the per-command private data area prior to
calling into the LLD. Replace the clearing operation that takes place
when the private command data reference is obtained with a routine that
performs common initializations. The zeroing that takes place in the
device reset path remains intact as the private command data associated
with the specified SCSI command is not guaranteed to be cleared.

Signed-off-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
---
 drivers/scsi/cxlflash/common.h | 11 +++++++++--
 drivers/scsi/cxlflash/main.c   |  2 +-
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
index e95e5a5..6d95e8e 100644
--- a/drivers/scsi/cxlflash/common.h
+++ b/drivers/scsi/cxlflash/common.h
@@ -178,15 +178,22 @@ static inline struct afu_cmd *sc_to_afuc(struct scsi_cmnd *sc)
 	return PTR_ALIGN(scsi_cmd_priv(sc), __alignof__(struct afu_cmd));
 }
 
-static inline struct afu_cmd *sc_to_afucz(struct scsi_cmnd *sc)
+static inline struct afu_cmd *sc_to_afuci(struct scsi_cmnd *sc)
 {
 	struct afu_cmd *afuc = sc_to_afuc(sc);
 
-	memset(afuc, 0, sizeof(*afuc));
 	INIT_LIST_HEAD(&afuc->queue);
 	return afuc;
 }
 
+static inline struct afu_cmd *sc_to_afucz(struct scsi_cmnd *sc)
+{
+	struct afu_cmd *afuc = sc_to_afuc(sc);
+
+	memset(afuc, 0, sizeof(*afuc));
+	return sc_to_afuci(sc);
+}
+
 struct hwq {
 	/* Stuff requiring alignment go first. */
 	struct sisl_ioarcb sq[NUM_SQ_ENTRY];		/* 16K SQ */
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 0cce442..4338982 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -543,7 +543,7 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp)
 	struct cxlflash_cfg *cfg = shost_priv(host);
 	struct afu *afu = cfg->afu;
 	struct device *dev = &cfg->dev->dev;
-	struct afu_cmd *cmd = sc_to_afucz(scp);
+	struct afu_cmd *cmd = sc_to_afuci(scp);
 	struct scatterlist *sg = scsi_sglist(scp);
 	int hwq_index = cmd_to_target_hwq(host, scp, afu);
 	struct hwq *hwq = get_hwq(afu, hwq_index);
-- 
2.1.0

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

* [PATCH 17/17] cxlflash: Update TMF command processing
  2017-06-22  2:12 [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Uma Krishnan
                   ` (15 preceding siblings ...)
  2017-06-22  2:16 ` [PATCH 16/17] cxlflash: Remove zeroing of private command data Uma Krishnan
@ 2017-06-22  2:16 ` Uma Krishnan
  2017-06-26 18:43 ` [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Martin K. Petersen
  17 siblings, 0 replies; 28+ messages in thread
From: Uma Krishnan @ 2017-06-22  2:16 UTC (permalink / raw)
  To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar
  Cc: linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

From: "Matthew R. Ochs" <mrochs@linux.vnet.ibm.com>

Currently, the SCSI command presented to the device reset handler is used
to send TMFs to the AFU for a device reset. This behavior is incorrect as
the command presented is an actual command and not a special notification.
As such, it should only be used for reference and not be acted upon.

Additionally, the existing TMF transmission routine does not account for
actual errors from the hardware, only reflecting failure when a timeout
occurs. This can lead to a condition where the device reset handler is
presented with a false 'success'.

Update send_tmf() to dynamically allocate a private command for sending
the TMF command and properly reflect failure when the completed command
indicates an error or was aborted. Detect TMF commands during response
processing and avoid scsi_done() for these types of commands. Lastly,
update comments in the TMF processing paths to describe the new behavior.

Signed-off-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
---
 drivers/scsi/cxlflash/main.c | 65 ++++++++++++++++++++++++++++++--------------
 1 file changed, 44 insertions(+), 21 deletions(-)

diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 4338982..7a787b6 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -155,9 +155,10 @@ static void process_cmd_err(struct afu_cmd *cmd, struct scsi_cmnd *scp)
  * cmd_complete() - command completion handler
  * @cmd:	AFU command that has completed.
  *
- * Prepares and submits command that has either completed or timed out to
- * the SCSI stack. Checks AFU command back into command pool for non-internal
- * (cmd->scp populated) commands.
+ * For SCSI commands this routine prepares and submits commands that have
+ * either completed or timed out to the SCSI stack. For internal commands
+ * (TMF or AFU), this routine simply notifies the originator that the
+ * command has completed.
  */
 static void cmd_complete(struct afu_cmd *cmd)
 {
@@ -167,7 +168,6 @@ static void cmd_complete(struct afu_cmd *cmd)
 	struct cxlflash_cfg *cfg = afu->parent;
 	struct device *dev = &cfg->dev->dev;
 	struct hwq *hwq = get_hwq(afu, cmd->hwq_index);
-	bool cmd_is_tmf;
 
 	spin_lock_irqsave(&hwq->hsq_slock, lock_flags);
 	list_del(&cmd->list);
@@ -180,19 +180,14 @@ static void cmd_complete(struct afu_cmd *cmd)
 		else
 			scp->result = (DID_OK << 16);
 
-		cmd_is_tmf = cmd->cmd_tmf;
-
 		dev_dbg_ratelimited(dev, "%s:scp=%p result=%08x ioasc=%08x\n",
 				    __func__, scp, scp->result, cmd->sa.ioasc);
-
 		scp->scsi_done(scp);
-
-		if (cmd_is_tmf) {
-			spin_lock_irqsave(&cfg->tmf_slock, lock_flags);
-			cfg->tmf_active = false;
-			wake_up_all_locked(&cfg->tmf_waitq);
-			spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags);
-		}
+	} else if (cmd->cmd_tmf) {
+		spin_lock_irqsave(&cfg->tmf_slock, lock_flags);
+		cfg->tmf_active = false;
+		wake_up_all_locked(&cfg->tmf_waitq);
+		spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags);
 	} else
 		complete(&cmd->cevent);
 }
@@ -206,8 +201,10 @@ static void cmd_complete(struct afu_cmd *cmd)
  */
 static void flush_pending_cmds(struct hwq *hwq)
 {
+	struct cxlflash_cfg *cfg = hwq->afu->parent;
 	struct afu_cmd *cmd, *tmp;
 	struct scsi_cmnd *scp;
+	ulong lock_flags;
 
 	list_for_each_entry_safe(cmd, tmp, &hwq->pending_cmds, list) {
 		/* Bypass command when on a doneq, cmd_complete() will handle */
@@ -222,7 +219,15 @@ static void flush_pending_cmds(struct hwq *hwq)
 			scp->scsi_done(scp);
 		} else {
 			cmd->cmd_aborted = true;
-			complete(&cmd->cevent);
+
+			if (cmd->cmd_tmf) {
+				spin_lock_irqsave(&cfg->tmf_slock, lock_flags);
+				cfg->tmf_active = false;
+				wake_up_all_locked(&cfg->tmf_waitq);
+				spin_unlock_irqrestore(&cfg->tmf_slock,
+						       lock_flags);
+			} else
+				complete(&cmd->cevent);
 		}
 	}
 }
@@ -455,24 +460,35 @@ static u32 cmd_to_target_hwq(struct Scsi_Host *host, struct scsi_cmnd *scp,
 /**
  * send_tmf() - sends a Task Management Function (TMF)
  * @afu:	AFU to checkout from.
- * @scp:	SCSI command from stack.
+ * @scp:	SCSI command from stack describing target.
  * @tmfcmd:	TMF command to send.
  *
  * Return:
- *	0 on success, SCSI_MLQUEUE_HOST_BUSY on failure
+ *	0 on success, SCSI_MLQUEUE_HOST_BUSY or -errno on failure
  */
 static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd)
 {
 	struct Scsi_Host *host = scp->device->host;
 	struct cxlflash_cfg *cfg = shost_priv(host);
-	struct afu_cmd *cmd = sc_to_afucz(scp);
+	struct afu_cmd *cmd = NULL;
 	struct device *dev = &cfg->dev->dev;
 	int hwq_index = cmd_to_target_hwq(host, scp, afu);
 	struct hwq *hwq = get_hwq(afu, hwq_index);
+	char *buf = NULL;
 	ulong lock_flags;
 	int rc = 0;
 	ulong to;
 
+	buf = kzalloc(sizeof(*cmd) + __alignof__(*cmd) - 1, GFP_KERNEL);
+	if (unlikely(!buf)) {
+		dev_err(dev, "%s: no memory for command\n", __func__);
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	cmd = (struct afu_cmd *)PTR_ALIGN(buf, __alignof__(*cmd));
+	INIT_LIST_HEAD(&cmd->queue);
+
 	/* When Task Management Function is active do not send another */
 	spin_lock_irqsave(&cfg->tmf_slock, lock_flags);
 	if (cfg->tmf_active)
@@ -482,7 +498,6 @@ static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd)
 	cfg->tmf_active = true;
 	spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags);
 
-	cmd->scp = scp;
 	cmd->parent = afu;
 	cmd->cmd_tmf = true;
 	cmd->hwq_index = hwq_index;
@@ -511,12 +526,20 @@ static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd)
 						       cfg->tmf_slock,
 						       to);
 	if (!to) {
-		cfg->tmf_active = false;
 		dev_err(dev, "%s: TMF timed out\n", __func__);
-		rc = -1;
+		rc = -ETIMEDOUT;
+	} else if (cmd->cmd_aborted) {
+		dev_err(dev, "%s: TMF aborted\n", __func__);
+		rc = -EAGAIN;
+	} else if (cmd->sa.ioasc) {
+		dev_err(dev, "%s: TMF failed ioasc=%08x\n",
+			__func__, cmd->sa.ioasc);
+		rc = -EIO;
 	}
+	cfg->tmf_active = false;
 	spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags);
 out:
+	kfree(buf);
 	return rc;
 }
 
-- 
2.1.0

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

* Re: [PATCH 01/17] cxlflash: Combine the send queue locks
  2017-06-22  2:13 ` [PATCH 01/17] cxlflash: Combine the send queue locks Uma Krishnan
@ 2017-06-22 19:53   ` Matthew R. Ochs
  0 siblings, 0 replies; 28+ messages in thread
From: Matthew R. Ochs @ 2017-06-22 19:53 UTC (permalink / raw)
  To: Uma Krishnan
  Cc: linux-scsi, James Bottomley, Martin K. Petersen, Manoj N. Kumar,
	Frederic Barrat, linuxppc-dev, Ian Munsie, Andrew Donnellan,
	Christophe Lombard

> On Jun 21, 2017, at 9:13 PM, Uma Krishnan <ukrishn@linux.vnet.ibm.com> =
wrote:
>=20
> Currently there are separate spin locks for the two supported I/O =
queueing
> models. This makes it difficult to serialize with paths outside the =
enqueue
> path.
>=20
> As a design simplification and to support serialization with enqueue
> operations, move to only a single lock that is used for enqueueing
> regardless of the queueing model.
>=20
> Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>

Acked-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>

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

* Re: [PATCH 02/17] cxlflash: Update cxlflash_afu_sync() to return errno
  2017-06-22  2:13 ` [PATCH 02/17] cxlflash: Update cxlflash_afu_sync() to return errno Uma Krishnan
@ 2017-06-22 19:54   ` Matthew R. Ochs
  0 siblings, 0 replies; 28+ messages in thread
From: Matthew R. Ochs @ 2017-06-22 19:54 UTC (permalink / raw)
  To: Uma Krishnan
  Cc: linux-scsi, James Bottomley, Martin K. Petersen, Manoj N. Kumar,
	Frederic Barrat, linuxppc-dev, Ian Munsie, Andrew Donnellan,
	Christophe Lombard

> On Jun 21, 2017, at 9:13 PM, Uma Krishnan <ukrishn@linux.vnet.ibm.com> =
wrote:
>=20
> The cxlflash_afu_sync() routine returns a negative one to indicate any =
kind
> of failure. This makes it impossible to establish why the error =
occurred.
>=20
> Update the return codes to clearly indicate the failure cause to the
> caller.
>=20
> Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>

Acked-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>

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

* Re: [PATCH 03/17] cxlflash: Reset hardware queue context via specified register
  2017-06-22  2:14 ` [PATCH 03/17] cxlflash: Reset hardware queue context via specified register Uma Krishnan
@ 2017-06-22 19:54   ` Matthew R. Ochs
  0 siblings, 0 replies; 28+ messages in thread
From: Matthew R. Ochs @ 2017-06-22 19:54 UTC (permalink / raw)
  To: Uma Krishnan
  Cc: linux-scsi, James Bottomley, Martin K. Petersen, Manoj N. Kumar,
	Frederic Barrat, linuxppc-dev, Ian Munsie, Andrew Donnellan,
	Christophe Lombard

> On Jun 21, 2017, at 9:14 PM, Uma Krishnan <ukrishn@linux.vnet.ibm.com> =
wrote:
>=20
> Per the SISLite specification, context_reset() writes 0x1 to the LSB =
of the
> reset register. When the AFU processes this reset request, it is =
expected
> to clear the bit after reset is complete. The current implementation =
simply
> checks that the entire value read back is not 1, instead of masking =
off the
> LSB and evaluating it for a change to 0. Should the AFU manipulate =
other
> bits during the reset (reading back a value of 0xF for example), =
successful
> completion will be prematurely indicated given the existing logic.
>=20
> Additionally, in the event that the context reset operation fails, =
there
> does not currently exist a way to provide feedback to the initiator of =
the
> reset. This poses a problem for the rare case that a context reset =
fails as
> the caller will proceed on the assumption that all is well.
>=20
> To remedy these issues, refactor the context reset routine to only =
mask off
> the LSB when evaluating for success and return status to the caller. =
Also
> update the context reset handler parameters to pass a hardware queue
> reference instead of a single command to better reflect that the =
entire
> queue associated with the context is impacted by the reset.
>=20
> Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>

Acked-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>

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

* Re: [PATCH 04/17] cxlflash: Schedule asynchronous reset of the host
  2017-06-22  2:14 ` [PATCH 04/17] cxlflash: Schedule asynchronous reset of the host Uma Krishnan
@ 2017-06-22 19:55   ` Matthew R. Ochs
  0 siblings, 0 replies; 28+ messages in thread
From: Matthew R. Ochs @ 2017-06-22 19:55 UTC (permalink / raw)
  To: Uma Krishnan
  Cc: linux-scsi, James Bottomley, Martin K. Petersen, Manoj N. Kumar,
	Frederic Barrat, linuxppc-dev, Ian Munsie, Andrew Donnellan,
	Christophe Lombard

> On Jun 21, 2017, at 9:14 PM, Uma Krishnan <ukrishn@linux.vnet.ibm.com> =
wrote:
>=20
> A context reset failure indicates the AFU is in a bad state. At =
present,
> when such a situation occurs, no further action is taken. This leaves =
the
> adapter in an unusable state with no recoverable actions.
>=20
> To avoid this situation, context reset failures will be escalated to a =
host
> reset operation. This will be done asynchronously to allow the acting
> thread to return to the user with a failure.
>=20
> Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>

Acked-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>

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

* Re: [PATCH 05/17] cxlflash: Handle AFU sync failures
  2017-06-22  2:14 ` [PATCH 05/17] cxlflash: Handle AFU sync failures Uma Krishnan
@ 2017-06-22 19:55   ` Matthew R. Ochs
  0 siblings, 0 replies; 28+ messages in thread
From: Matthew R. Ochs @ 2017-06-22 19:55 UTC (permalink / raw)
  To: Uma Krishnan
  Cc: linux-scsi, James Bottomley, Martin K. Petersen, Manoj N. Kumar,
	Frederic Barrat, linuxppc-dev, Ian Munsie, Andrew Donnellan,
	Christophe Lombard

> On Jun 21, 2017, at 9:14 PM, Uma Krishnan <ukrishn@linux.vnet.ibm.com> =
wrote:
>=20
> AFU sync operations are not currently evaluated for failure. This is
> acceptable for paths where there is not a dependency on the AFU being
> consistent with the host. Examples include link reset events and LUN
> cleanup operations. On paths where there is a dependency, such as a =
LUN
> open, a sync failure should be acted upon.
>=20
> In the event of AFU sync failures, either log or cleanup as =
appropriate for
> operations that are dependent on a successful sync completion.
>=20
> Update documentation to reflect behavior in the event of an AFU sync
> failure.
>=20
> Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>

Acked-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>

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

* Re: [PATCH 06/17] cxlflash: Track pending scsi commands in each hardware queue
  2017-06-22  2:14 ` [PATCH 06/17] cxlflash: Track pending scsi commands in each hardware queue Uma Krishnan
@ 2017-06-22 19:56   ` Matthew R. Ochs
  0 siblings, 0 replies; 28+ messages in thread
From: Matthew R. Ochs @ 2017-06-22 19:56 UTC (permalink / raw)
  To: Uma Krishnan
  Cc: linux-scsi, James Bottomley, Martin K. Petersen, Manoj N. Kumar,
	Frederic Barrat, linuxppc-dev, Ian Munsie, Andrew Donnellan,
	Christophe Lombard

> On Jun 21, 2017, at 9:14 PM, Uma Krishnan <ukrishn@linux.vnet.ibm.com> =
wrote:
>=20
> Currently, there is no book keeping of the pending scsi commands in =
the
> cxlflash driver. This lack of tracking in-flight requests is too
> restrictive and requires a heavy-hammer reset each time an adapter =
error is
> encountered. Additionally, it does not allow for commands to be =
properly
> retried.
>=20
> In order to avoid this problem and to better handle error path command
> cleanup, introduce a linked list for each hardware queue that tracks
> pending commands.
>=20
> Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>

Acked-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>

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

* Re: [PATCH 07/17] cxlflash: Flush pending commands in cleanup path
  2017-06-22  2:14 ` [PATCH 07/17] cxlflash: Flush pending commands in cleanup path Uma Krishnan
@ 2017-06-22 19:56   ` Matthew R. Ochs
  0 siblings, 0 replies; 28+ messages in thread
From: Matthew R. Ochs @ 2017-06-22 19:56 UTC (permalink / raw)
  To: Uma Krishnan
  Cc: linux-scsi, James Bottomley, Martin K. Petersen, Manoj N. Kumar,
	linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

> On Jun 21, 2017, at 9:14 PM, Uma Krishnan <ukrishn@linux.vnet.ibm.com> =
wrote:
>=20
> When the AFU is reset in an error path, pending scsi commands can be
> silently dropped without completion or a formal abort. This puts the =
onus
> on the cxlflash driver to notify mid-layer and indicating that the =
command
> can be retried.
>=20
> Once the card has been quiesced, the hardware send queue lock is =
acquired
> to prevent any data movement while the pending commands are processed.
>=20
> Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>

Acked-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>

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

* Re: [PATCH 08/17] cxlflash: Add scsi command abort handler
  2017-06-22  2:15 ` [PATCH 08/17] cxlflash: Add scsi command abort handler Uma Krishnan
@ 2017-06-22 19:56   ` Matthew R. Ochs
  0 siblings, 0 replies; 28+ messages in thread
From: Matthew R. Ochs @ 2017-06-22 19:56 UTC (permalink / raw)
  To: Uma Krishnan
  Cc: linux-scsi, James Bottomley, Martin K. Petersen, Manoj N. Kumar,
	linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

> On Jun 21, 2017, at 9:15 PM, Uma Krishnan <ukrishn@linux.vnet.ibm.com> =
wrote:
>=20
> To date, CXL flash devices do not support a single command abort =
operation.
> Instead, the SISLite specification provides a context reset operation =
to
> cleanup all pending commands for a given context.
>=20
> When a context reset is successful, it is guaranteed that the AFU has
> aborted all currently pending I/O. This sequence is less invasive than =
a
> device or host reset and can be executed to support scsi command abort
> requests. Add eh_abort_handler callback support to process command =
timeouts
> and abort requests.
>=20
> Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>

Acked-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>

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

* Re: [PATCH 09/17] cxlflash: Create character device to provide host management interface
  2017-06-22  2:15 ` [PATCH 09/17] cxlflash: Create character device to provide host management interface Uma Krishnan
@ 2017-06-22 19:56   ` Matthew R. Ochs
  0 siblings, 0 replies; 28+ messages in thread
From: Matthew R. Ochs @ 2017-06-22 19:56 UTC (permalink / raw)
  To: Uma Krishnan
  Cc: linux-scsi, James Bottomley, Martin K. Petersen, Manoj N. Kumar,
	linuxppc-dev, Ian Munsie, Andrew Donnellan, Frederic Barrat,
	Christophe Lombard

> On Jun 21, 2017, at 9:15 PM, Uma Krishnan <ukrishn@linux.vnet.ibm.com> =
wrote:
>=20
> The cxlflash driver currently lacks host management interface. Future
> devices supported by cxlflash will provide a variety of host-wide
> management functions. Examples include LUN provisioning, hardware =
debug
> support, and firmware download.
>=20
> In order to provide a way to manage the device, a character device =
will
> be created during probe of each adapter. This device will support a =
set of
> ioctls defined in the SISLite specification from which administrators =
can
> manage the adapter.
>=20
> Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>

Acked-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>

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

* Re: [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes
  2017-06-22  2:12 [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Uma Krishnan
                   ` (16 preceding siblings ...)
  2017-06-22  2:16 ` [PATCH 17/17] cxlflash: Update TMF command processing Uma Krishnan
@ 2017-06-26 18:43 ` Martin K. Petersen
  17 siblings, 0 replies; 28+ messages in thread
From: Martin K. Petersen @ 2017-06-26 18:43 UTC (permalink / raw)
  To: Uma Krishnan
  Cc: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
	Manoj N. Kumar, linuxppc-dev, Ian Munsie, Andrew Donnellan,
	Frederic Barrat, Christophe Lombard


Uma,

> This patch series contains miscellaneous fixes and several
> enhancements such as LUN provisioning support, WS16 unmap and AFU
> debug capabilities.

Applied to 4.13/scsi-queue. Thank you!

-- 
Martin K. Petersen	Oracle Linux Engineering

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

end of thread, other threads:[~2017-06-26 18:43 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-06-22  2:12 [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Uma Krishnan
2017-06-22  2:13 ` [PATCH 01/17] cxlflash: Combine the send queue locks Uma Krishnan
2017-06-22 19:53   ` Matthew R. Ochs
2017-06-22  2:13 ` [PATCH 02/17] cxlflash: Update cxlflash_afu_sync() to return errno Uma Krishnan
2017-06-22 19:54   ` Matthew R. Ochs
2017-06-22  2:14 ` [PATCH 03/17] cxlflash: Reset hardware queue context via specified register Uma Krishnan
2017-06-22 19:54   ` Matthew R. Ochs
2017-06-22  2:14 ` [PATCH 04/17] cxlflash: Schedule asynchronous reset of the host Uma Krishnan
2017-06-22 19:55   ` Matthew R. Ochs
2017-06-22  2:14 ` [PATCH 05/17] cxlflash: Handle AFU sync failures Uma Krishnan
2017-06-22 19:55   ` Matthew R. Ochs
2017-06-22  2:14 ` [PATCH 06/17] cxlflash: Track pending scsi commands in each hardware queue Uma Krishnan
2017-06-22 19:56   ` Matthew R. Ochs
2017-06-22  2:14 ` [PATCH 07/17] cxlflash: Flush pending commands in cleanup path Uma Krishnan
2017-06-22 19:56   ` Matthew R. Ochs
2017-06-22  2:15 ` [PATCH 08/17] cxlflash: Add scsi command abort handler Uma Krishnan
2017-06-22 19:56   ` Matthew R. Ochs
2017-06-22  2:15 ` [PATCH 09/17] cxlflash: Create character device to provide host management interface Uma Krishnan
2017-06-22 19:56   ` Matthew R. Ochs
2017-06-22  2:15 ` [PATCH 10/17] cxlflash: Separate AFU internal command handling from AFU sync specifics Uma Krishnan
2017-06-22  2:15 ` [PATCH 11/17] cxlflash: Introduce host ioctl support Uma Krishnan
2017-06-22  2:16 ` [PATCH 12/17] cxlflash: Refactor AFU capability checking Uma Krishnan
2017-06-22  2:16 ` [PATCH 13/17] cxlflash: Support LUN provisioning Uma Krishnan
2017-06-22  2:16 ` [PATCH 14/17] cxlflash: Support AFU debug Uma Krishnan
2017-06-22  2:16 ` [PATCH 15/17] cxlflash: Support WS16 unmap Uma Krishnan
2017-06-22  2:16 ` [PATCH 16/17] cxlflash: Remove zeroing of private command data Uma Krishnan
2017-06-22  2:16 ` [PATCH 17/17] cxlflash: Update TMF command processing Uma Krishnan
2017-06-26 18:43 ` [PATCH 00/17] cxlflash: LUN provisioning support and miscellaneous fixes Martin K. Petersen

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).