RE: [PATCH v4] cxlflash: Base support for IBM CXL Flash Adapter

2015-06-08 Thread Stephen Bates
Hi

I just wanted to add support for this patchset. There are others considering 
implementing block IO devices that use the CAPI (CXL) interface and having this 
patch-set upstream will be very useful in the future.

Supported-by: Stephen Bates 

Cheers

Stephen 

-Original Message-
From: linux-scsi-ow...@vger.kernel.org 
[mailto:linux-scsi-ow...@vger.kernel.org] On Behalf Of Matthew R. Ochs
Sent: Friday, June 5, 2015 3:46 PM
To: linux-scsi@vger.kernel.org; james.bottom...@hansenpartnership.com; 
n...@linux-iscsi.org; brk...@linux.vnet.ibm.com; h...@infradead.org
Cc: mi...@neuling.org; imun...@au1.ibm.com; Manoj N. Kumar
Subject: [PATCH v4] cxlflash: Base support for IBM CXL Flash Adapter

SCSI device driver to support filesystem access on the IBM CXL Flash adapter.

Signed-off-by: Matthew R. Ochs 
Signed-off-by: Manoj N. Kumar 
---
 drivers/scsi/Kconfig|1 +
 drivers/scsi/Makefile   |1 +
 drivers/scsi/cxlflash/Kconfig   |   11 +
 drivers/scsi/cxlflash/Makefile  |2 +
 drivers/scsi/cxlflash/common.h  |  180 
 drivers/scsi/cxlflash/main.c| 2263 +++
 drivers/scsi/cxlflash/main.h|  104 ++
 drivers/scsi/cxlflash/sislite.h |  465 
 8 files changed, 3027 insertions(+)
 create mode 100644 drivers/scsi/cxlflash/Kconfig
 create mode 100644 drivers/scsi/cxlflash/Makefile
 create mode 100644 drivers/scsi/cxlflash/common.h
 create mode 100644 drivers/scsi/cxlflash/main.c
 create mode 100644 drivers/scsi/cxlflash/main.h
 create mode 100755 drivers/scsi/cxlflash/sislite.h

diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index b021bcb..ebb12a7 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -345,6 +345,7 @@ source "drivers/scsi/cxgbi/Kconfig"
 source "drivers/scsi/bnx2i/Kconfig"
 source "drivers/scsi/bnx2fc/Kconfig"
 source "drivers/scsi/be2iscsi/Kconfig"
+source "drivers/scsi/cxlflash/Kconfig"
 
 config SGIWD93_SCSI
tristate "SGI WD93C93 SCSI Driver"
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index dee160a..619f8fb 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -101,6 +101,7 @@ obj-$(CONFIG_SCSI_7000FASST)+= wd7000.o
 obj-$(CONFIG_SCSI_EATA)+= eata.o
 obj-$(CONFIG_SCSI_DC395x)  += dc395x.o
 obj-$(CONFIG_SCSI_AM53C974)+= esp_scsi.o   am53c974.o
+obj-$(CONFIG_CXLFLASH) += cxlflash/
 obj-$(CONFIG_MEGARAID_LEGACY)  += megaraid.o
 obj-$(CONFIG_MEGARAID_NEWGEN)  += megaraid/
 obj-$(CONFIG_MEGARAID_SAS) += megaraid/
diff --git a/drivers/scsi/cxlflash/Kconfig b/drivers/scsi/cxlflash/Kconfig
new file mode 100644
index 000..e98c3f6
--- /dev/null
+++ b/drivers/scsi/cxlflash/Kconfig
@@ -0,0 +1,11 @@
+#
+# IBM CXL-attached Flash Accelerator SCSI Driver
+#
+
+config CXLFLASH
+   tristate "Support for IBM CAPI Flash"
+   depends on CXL
+   default m
+   help
+ Allows CAPI Accelerated IO to Flash
+ If unsure, say N.
diff --git a/drivers/scsi/cxlflash/Makefile b/drivers/scsi/cxlflash/Makefile
new file mode 100644
index 000..dc95e20
--- /dev/null
+++ b/drivers/scsi/cxlflash/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_CXLFLASH) += cxlflash.o
+cxlflash-y += main.o
diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
new file mode 100644
index 000..2bd842b
--- /dev/null
+++ b/drivers/scsi/cxlflash/common.h
@@ -0,0 +1,180 @@
+/*
+ * CXL Flash Device Driver
+ *
+ * Written by: Manoj N. Kumar , IBM Corporation
+ * Matthew R. Ochs , IBM Corporation
+ *
+ * Copyright (C) 2015 IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _CXLFLASH_COMMON_H
+#define _CXLFLASH_COMMON_H
+
+#include 
+#include 
+#include 
+#include 
+
+
+#define MAX_CONTEXT  CXLFLASH_MAX_CONTEXT   /* num contexts per afu */
+
+#define CXLFLASH_BLOCK_SIZE4096/* 4K blocks */
+#define CXLFLASH_MAX_XFER_SIZE 16777216/* 16MB transfer */
+#define CXLFLASH_MAX_SECTORS   (CXLFLASH_MAX_XFER_SIZE/512)/* SCSI wants
+  max_sectors
+  in units of
+  512 byte
+  sectors
+   */
+
+#define NUM_RRQ_ENTRY16 /* for master issued cmds */
+#define MAX_RHT_PER_CONTEXT (PAGE_SIZE / sizeof(struct sisl_rht_entry))
+
+/* AFU command retry limit */
+#define MC_RETRY_CNT 5 /* sufficient for SCSI check and
+  certain AFU errors */
+
+/* Command management definitions */
+#define CXLFLASH_NUM_CMDS  (2 * CXLFLA

Re: [PATCH v4] cxlflash: Base support for IBM CXL Flash Adapter

2015-06-08 Thread Brian King
On 06/08/2015 04:41 PM, Manoj Kumar wrote:
> On 6/8/2015 12:54 PM, Brian King wrote:
> 
>>> +
>>> +rcr = send_tmf(afu, scp, TMF_LUN_RESET);
>>> +if (unlikely(rcr))
>>> +rc = FAILED;
>>
>> Do you need to wait for all commands to the LUN to be returned before 
>> returning from
>> here? You could put a simple loop here, polling until there are no ops 
>> outstanding
>> to this LUN, if needed...
> 
> Brian:
> 
> Good suggestion. Would it be acceptable to add this capability in a future 
> patch?

That's fine with me. 

Thanks,

Brian

-- 
Brian King
Power Linux I/O
IBM Linux Technology Center


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4] cxlflash: Base support for IBM CXL Flash Adapter

2015-06-08 Thread Manoj Kumar

On 6/8/2015 12:54 PM, Brian King wrote:


+
+   rcr = send_tmf(afu, scp, TMF_LUN_RESET);
+   if (unlikely(rcr))
+   rc = FAILED;


Do you need to wait for all commands to the LUN to be returned before returning 
from
here? You could put a simple loop here, polling until there are no ops 
outstanding
to this LUN, if needed...


Brian:

Good suggestion. Would it be acceptable to add this capability in a 
future patch?


- Manoj

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4] cxlflash: Base support for IBM CXL Flash Adapter

2015-06-08 Thread Manoj Kumar

Brian:

Thank you for your review. Comments are inline.

- Manoj

On 6/8/2015 12:54 PM, Brian King wrote:

Looking pretty good. A few more comments.

Thanks,

Brian


+   spin_lock_irqsave(&cfg->tmf_waitq.lock, lock_flags);
+   if (cfg->tmf_active)
+   wait_event_interruptible_locked_irq(cfg->tmf_waitq,
+   !cfg->tmf_active);
+   spin_unlock_irqrestore(&cfg->tmf_waitq.lock, lock_flags);


This needs to return SCSI_MLQUEUE_HOST_BUSY instead of sleeping. You can't sleep
in queuecommand.



Okay, will revise in v5 to return an error instead of sleeping.


+   if (atomic64_dec_and_test(&afu->room)) {


If you have two threads executing this code concurrently you could have a 
problem.
If afu->room = 1 and thread 1 decrements it and the return value is 0, we go 
into this
leg. If a second thread then comes in right after afu->room goes to zero, 
afu->room
will then get decremented to -1, and you'll send the command, regardless of 
whether
the AFU has room or not. Either the AFU will have room and afu->room will then
end up being off by one, or it won't have room and you'll send a command when it
does not have room.

I think if you use atomic_dec_if_positive instead, you can get rid of this race 
condition.
You'd then need to check the return value. If its positive, there is room, if 
it zero,
you are out of room and you are the thread that will reset afu->room from the 
AFU. If
it is negative, then you have to either return host busy, or wait for the other 
thread to
reset afu->room and simply try the atomic_dec_if_positive again in the loop here
instead of reading from the adapter and trying to set it from two threads.



Good catch. Will switch to atomic_dec_if_positive() in v5 to avoid the race.



--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4] cxlflash: Base support for IBM CXL Flash Adapter

2015-06-08 Thread Matthew R. Ochs
On Jun 8, 2015, at 5:05 AM, Michael Neuling wrote:
> 
> Reviewed-by: Michael Neuling 

Thanks again for helping us to review the code.

> 
> The core cxl changes needed for this are in mpe's powerpc next branch queued 
> up
> for 4.2.  They are in linux next-20150605.  To compile this you'll need to 
> pull
> in mpe's powerpc tree from:
> 
>  git://git.kernel.org/pub/scm/linux/kernel/git/mpe/linux.git next

I went ahead and did a test build against this tree, everything worked.

>> +config CXLFLASH
>> +tristate "Support for IBM CAPI Flash"
>> +depends on CXL
> 
> This should be depends on SCSI too?

Yep, and PCI. Will fix in v5.

> 
>> +struct afu {
> < snip>
>> +u64 interface_version;
> 
> This doesn't seem to be used anywhere except for in init_afu where it's
> only used local to that function.

True, the intention here is to save it off in case it is needed in a debug 
scenario. We may
even make it retrievable via a sysfs attribute at some point. 

>> +
>> +static inline u64 lun_to_lunid(u64 lun)
>> +{
>> +u64 lun_id;
>> +
>> +int_to_scsilun(lun, (struct scsi_lun *)&lun_id);
>> +return swab64(lun_id);
>> +}
> 
> This is only used in main.c.  Why is it not just in there?

We use it in other places within the driver that have not been submitted. 
Rather than
migrating it around we decided to keep it defined in the common header.

> 
>> +/**
>> + * cxlflash_probe() - PCI entry point to add host
>> + * @pdev:   PCI device associated with the host.
>> + * @dev_id: PCI device id associated with device.
>> + *
>> + * Return: 0 on success / non-zero on failure
>> + */
>> +static int cxlflash_probe(struct pci_dev *pdev,
>> +  const struct pci_device_id *dev_id)
>> +{
> 
>> +phys_dev = cxl_get_phys_dev(pdev);
>> +if (!dev_is_pci(phys_dev)) {
>> +pr_err("%s: not a pci dev\n", __func__);
>> +rc = ENODEV;
> 
> -ENODEV;

Good catch! Will fix in v5.

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4] cxlflash: Base support for IBM CXL Flash Adapter

2015-06-08 Thread Brian King
Looking pretty good. A few more comments.

Thanks,

Brian


On 06/05/2015 04:46 PM, Matthew R. Ochs wrote:
> +/**
> + * cxlflash_queuecommand() - sends a mid-layer request
> + * @host:SCSI host associated with device.
> + * @scp: SCSI command to send.
> + *
> + * Return:
> + *   0 on success
> + *   SCSI_MLQUEUE_HOST_BUSY when host is busy
> + */
> +static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd 
> *scp)
> +{
> + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata;
> + struct afu *afu = cfg->afu;
> + struct pci_dev *pdev = cfg->dev;
> + struct afu_cmd *cmd;
> + u32 port_sel = scp->device->channel + 1;
> + int nseg, i, ncount;
> + struct scatterlist *sg;
> + ulong lock_flags;
> + short lflag = 0;
> + int rc = 0;
> +
> + pr_debug("%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]));
> +
> + /* If a Task Management Function is active, wait for it to complete
> +  * before continuing with regular commands.
> +  */
> + spin_lock_irqsave(&cfg->tmf_waitq.lock, lock_flags);
> + if (cfg->tmf_active)
> + wait_event_interruptible_locked_irq(cfg->tmf_waitq,
> + !cfg->tmf_active);
> + spin_unlock_irqrestore(&cfg->tmf_waitq.lock, lock_flags);

This needs to return SCSI_MLQUEUE_HOST_BUSY instead of sleeping. You can't sleep
in queuecommand.

> +
> + cmd = cxlflash_cmd_checkout(afu);
> + if (unlikely(!cmd)) {
> + pr_err("%s: could not get a free command\n", __func__);
> + rc = SCSI_MLQUEUE_HOST_BUSY;
> + goto out;
> + }
> +
> + cmd->rcb.ctx_id = afu->ctx_hndl;
> + cmd->rcb.port_sel = port_sel;
> + cmd->rcb.lun_id = lun_to_lunid(scp->device->lun);
> +
> + if (scp->sc_data_direction == DMA_TO_DEVICE)
> + lflag = SISL_REQ_FLAGS_HOST_WRITE;
> + else
> + lflag = SISL_REQ_FLAGS_HOST_READ;
> +
> + cmd->rcb.req_flags = (SISL_REQ_FLAGS_PORT_LUN_ID |
> +   SISL_REQ_FLAGS_SUP_UNDERRUN | lflag);
> +
> + /* Stash the scp in the reserved field, for reuse during interrupt */
> + cmd->rcb.scp = scp;
> +
> + nseg = scsi_dma_map(scp);
> + if (unlikely(nseg < 0)) {
> + dev_err(&pdev->dev, "%s: Fail DMA map! nseg=%d\n",
> + __func__, nseg);
> + rc = SCSI_MLQUEUE_HOST_BUSY;
> + goto out;
> + }
> +
> + ncount = scsi_sg_count(scp);
> + scsi_for_each_sg(scp, sg, ncount, i) {
> + cmd->rcb.data_len = sg_dma_len(sg);
> + cmd->rcb.data_ea = sg_dma_address(sg);
> + }
> +
> + /* Copy the CDB from the scsi_cmnd passed in */
> + memcpy(cmd->rcb.cdb, scp->cmnd, sizeof(cmd->rcb.cdb));
> +
> + /* Send the command */
> + rc = cxlflash_send_cmd(afu, cmd);
> + if (unlikely(rc)) {
> + cxlflash_cmd_checkin(cmd);
> + scsi_dma_unmap(scp);
> + }
> +
> +out:
> + return rc;
> +}
> +
> +/**
> + * cxlflash_eh_device_reset_handler() - reset a single LUN
> + * @scp: SCSI command to send.
> + *
> + * Return:
> + *   SUCCESS as defined in scsi/scsi.h
> + *   FAILED as defined in scsi/scsi.h
> + */
> +static int cxlflash_eh_device_reset_handler(struct scsi_cmnd *scp)
> +{
> + int rc = SUCCESS;
> + struct Scsi_Host *host = scp->device->host;
> + struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)host->hostdata;
> + struct afu *afu = cfg->afu;
> + int rcr = 0;
> +
> + pr_debug("%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]));
> +
> + rcr = send_tmf(afu, scp, TMF_LUN_RESET);
> + if (unlikely(rcr))
> + rc = FAILED;

Do you need to wait for all commands to the LUN to be returned before returning 
from
here? You could put a simple loop here, polling until there are no ops 
outstanding
to this LUN, if needed...


> +
> + pr_debug("%s: returning rc=%d\n", __func__, rc);
> + return rc;
> +}
> +

> +
> +/**
> + * cxlflash_send_cmd() - sends an AFU command
> + * @afu: AFU associated with the host.
> + * @cmd: AFU command to send.
> + *
> + * Return:
> + *   0 on success
> + *   -1 on failure
> + */
> +int cxlflash_send_cm

Re: [PATCH v4] cxlflash: Base support for IBM CXL Flash Adapter

2015-06-08 Thread Michael Neuling
On Fri, 2015-06-05 at 16:46 -0500, Matthew R. Ochs wrote:
> SCSI device driver to support filesystem access on the IBM CXL Flash adapter.

Few minor nits below but other than that it looks good to me.  The CXL parts
are good and the rest of the driver is looking decent.  FWIW:

Reviewed-by: Michael Neuling 

The core cxl changes needed for this are in mpe's powerpc next branch queued up
for 4.2.  They are in linux next-20150605.  To compile this you'll need to pull
in mpe's powerpc tree from:

  git://git.kernel.org/pub/scm/linux/kernel/git/mpe/linux.git next


> diff --git a/drivers/scsi/cxlflash/Kconfig b/drivers/scsi/cxlflash/Kconfig
> new file mode 100644
> index 000..e98c3f6
> --- /dev/null
> +++ b/drivers/scsi/cxlflash/Kconfig
> @@ -0,0 +1,11 @@
> +#
> +# IBM CXL-attached Flash Accelerator SCSI Driver
> +#
> +
> +config CXLFLASH
> + tristate "Support for IBM CAPI Flash"
> + depends on CXL

This should be depends on SCSI too?  

> +struct afu {
< snip>
> + u64 interface_version;

This doesn't seem to be used anywhere except for in init_afu where it's
only used local to that function.

> + struct cxlflash_cfg *parent; /* Pointer back to parent cxlflash_cfg */
> +
> +};
> +
> +static inline u64 lun_to_lunid(u64 lun)
> +{
> + u64 lun_id;
> +
> + int_to_scsilun(lun, (struct scsi_lun *)&lun_id);
> + return swab64(lun_id);
> +}

This is only used in main.c.  Why is it not just in there?

> +/**
> + * cxlflash_probe() - PCI entry point to add host
> + * @pdev:PCI device associated with the host.
> + * @dev_id:  PCI device id associated with device.
> + *
> + * Return: 0 on success / non-zero on failure
> + */
> +static int cxlflash_probe(struct pci_dev *pdev,
> +   const struct pci_device_id *dev_id)
> +{

> + phys_dev = cxl_get_phys_dev(pdev);
> + if (!dev_is_pci(phys_dev)) {
> + pr_err("%s: not a pci dev\n", __func__);
> + rc = ENODEV;

-ENODEV;

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html