[PATCH v2.1] sd: Micro-optimize READ / WRITE CDB encoding

2017-10-24 Thread Douglas Gilbert
The sd_setup_read_write_cmnd() function is on the "fast path" for
block system access to SCSI devices (logical units). Rewrite this
function to improve speed and readability:
 - use put_unaligned_be family of functions to save lots of shifts
 - improve the scaling code when sector_size > 512 bytes
 - use variable names containing "sect" for block system quantities
   which have implicit 512 byte sector size. Use "lba" and
   "num_blks" after optional scaling to match the logical block
   address and number of logical blocks of the SCSI device being
   accessed
 - use local variables to hold values that were previously calculated
   more than once

Signed-off-by: Douglas Gilbert 
---
 drivers/scsi/sd.c | 216 --
 1 file changed, 94 insertions(+), 122 deletions(-)

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index d175c5c5ccf8..618cb5d0f75a 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1004,11 +1004,18 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd 
*SCpnt)
struct scsi_device *sdp = SCpnt->device;
struct gendisk *disk = rq->rq_disk;
struct scsi_disk *sdkp = scsi_disk(disk);
-   sector_t block = blk_rq_pos(rq);
-   sector_t threshold;
-   unsigned int this_count = blk_rq_sectors(rq);
+   unsigned int num_sects = blk_rq_sectors(rq);
+   unsigned int num_blks;
unsigned int dif, dix;
-   bool zoned_write = sd_is_zoned(sdkp) && rq_data_dir(rq) == WRITE;
+   unsigned int sect_sz;
+   sector_t sect_addr = blk_rq_pos(rq);
+   sector_t sect_after = sect_addr + num_sects;
+   sector_t total_sects = get_capacity(disk);
+   sector_t threshold_sect;
+   sector_t lba;
+   bool is_write = (rq_data_dir(rq) == WRITE);
+   bool have_fua = !!(rq->cmd_flags & REQ_FUA);
+   bool zoned_write = sd_is_zoned(sdkp) && is_write;
int ret;
unsigned char protect;
 
@@ -1029,20 +1036,23 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd 
*SCpnt)
 
SCSI_LOG_HLQUEUE(1,
scmd_printk(KERN_INFO, SCpnt,
-   "%s: block=%llu, count=%d\n",
-   __func__, (unsigned long long)block, this_count));
+   "%s: sector=%llu, num_sects=%d\n",
+   __func__, (unsigned long long)sect_addr, num_sects));
 
-   if (!sdp || !scsi_device_online(sdp) ||
-   block + blk_rq_sectors(rq) > get_capacity(disk)) {
+   if (likely(sdp && scsi_device_online(sdp) &&
+  (sect_after <= total_sects)))
+   ; /* ok: have device, its online and access fits on medium */
+   else {
SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
"Finishing %u sectors\n",
-   blk_rq_sectors(rq)));
+   num_sects));
SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
"Retry with 0x%p\n", SCpnt));
goto out;
}
+   sect_sz = sdp->sector_size;
 
-   if (sdp->changed) {
+   if (unlikely(sdp->changed)) {
/*
 * quietly refuse to do anything to a changed disc until 
 * the changed bit has been reset
@@ -1055,21 +1065,22 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd 
*SCpnt)
 * Some SD card readers can't handle multi-sector accesses which touch
 * the last one or two hardware sectors.  Split accesses as needed.
 */
-   threshold = get_capacity(disk) - SD_LAST_BUGGY_SECTORS *
-   (sdp->sector_size / 512);
-
-   if (unlikely(sdp->last_sector_bug && block + this_count > threshold)) {
-   if (block < threshold) {
-   /* Access up to the threshold but not beyond */
-   this_count = threshold - block;
-   } else {
-   /* Access only a single hardware sector */
-   this_count = sdp->sector_size / 512;
-   }
+   if (unlikely(sdp->last_sector_bug)) {
+   threshold_sect = total_sects -
+   (SD_LAST_BUGGY_SECTORS * (sect_sz / 512));
+
+   if (unlikely(sect_after > threshold_sect))
+   num_sects = (sect_addr < threshold_sect) ?
+   (threshold_sect - sect_addr) :
+   (sect_sz / 512);
+   /* If LBA less than threshold then access up to the
+* threshold but not beyond; otherwise access only
+* a single hardware sector.
+*/
}
 
-   SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n",
-   (unsigned 

Re: [PATCH] sd: Micro-optimize READ / WRITE CDB encoding

2017-10-24 Thread Douglas Gilbert

On 2017-10-17 06:41 PM, Bart Van Assche wrote:

On Tue, 2017-10-17 at 18:17 -0400, Douglas Gilbert wrote:

On 2017-10-17 05:03 PM, Bart Van Assche wrote:

@@ -1025,7 +1025,6 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd 
*SCpnt)
struct gendisk *disk = rq->rq_disk;
struct scsi_disk *sdkp = scsi_disk(disk);
sector_t block = blk_rq_pos(rq);


s/block/lba/# use the well understood SCSI abbreviation


Since blk_rq_pos() returns the offset in units of 512 bytes, how about renaming
'block' into 'sector' and using the name 'lba' for the number obtained after the
shift operation?




-   sector_t threshold;
unsigned int this_count = blk_rq_sectors(rq);
unsigned int dif, dix;
bool zoned_write = sd_is_zoned(sdkp) && rq_data_dir(rq) == WRITE;
@@ -1071,20 +1070,22 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd 
*SCpnt)
goto out;
}
   
-	/*

-* Some SD card readers can't handle multi-sector accesses which touch
-* the last one or two hardware sectors.  Split accesses as needed.
-*/
-   threshold = get_capacity(disk) - SD_LAST_BUGGY_SECTORS *
-   (sdp->sector_size / 512);
+   if (unlikely(sdp->last_sector_bug)) {
+   sector_t threshold;


s/threshold/threshold_lba/  # a bit long but more precise


A similar comment applies here - shouldn't this be called 'threshold_sector'?


}
}
if (rq_data_dir(rq) == WRITE) {
@@ -1173,56 +1157,26 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd 
*SCpnt)
SCpnt->cmnd[7] = 0x18;
SCpnt->cmnd[9] = (rq_data_dir(rq) == READ) ? READ_32 : WRITE_32;


Perhaps rq_data_dir(rq) could be placed in a local variable


I will keep that for a separate patch.


Hi,
This thread is going a bit cold so I have attached my rewrite of
sd_setup_read_write_cmnd(). It incorporates Bart's speed improvements
(e.g. using put_unaligned_be*() and improving the scaling algorithm)
plus the naming improvements discussed above. I plan to send it as
a freestanding post shortly.

One thing that caught my eye in the rewrite was this line near the end:
SCpnt->underflow = num_blks << 9;

The underflow field is defined in scsi_cmnd.h as:
unsigned underflow; /* Return error if less than
   this amount is transferred */

IMO the calculation (i.e. multiplying by 512) is the correct number
of bytes only if sector_size is 512. To make it more generally
correct it should read:
SCpnt->underflow = num_sects << 9;

Comments, anyone ...

Doug Gilbert

static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
{
	struct request *rq = SCpnt->request;
	struct scsi_device *sdp = SCpnt->device;
	struct gendisk *disk = rq->rq_disk;
	struct scsi_disk *sdkp = scsi_disk(disk);
	unsigned int num_sects = blk_rq_sectors(rq);
	unsigned int num_blks;
	unsigned int dif, dix;
	unsigned int sect_sz;
	sector_t sect_addr = blk_rq_pos(rq);
	sector_t sect_after = sect_addr + num_sects;
	sector_t total_sects = get_capacity(disk);
	sector_t threshold_sect;
	sector_t lba;
	bool is_write = (rq_data_dir(rq) == WRITE);
	bool have_fua = !!(rq->cmd_flags & REQ_FUA);
	bool zoned_write = sd_is_zoned(sdkp) && is_write;
	int ret;
	unsigned char protect;

	if (zoned_write) {
		ret = sd_zbc_write_lock_zone(SCpnt);
		if (ret != BLKPREP_OK)
			return ret;
	}

	ret = scsi_init_io(SCpnt);
	if (ret != BLKPREP_OK)
		goto out;
	WARN_ON_ONCE(SCpnt != rq->special);

	/* from here on until we're complete, any goto out
	 * is used for a killable error condition */
	ret = BLKPREP_KILL;

	SCSI_LOG_HLQUEUE(1,
		scmd_printk(KERN_INFO, SCpnt,
			"%s: sector=%llu, num_sects=%d\n",
			__func__, (unsigned long long)sect_addr, num_sects));

	if (likely(sdp && scsi_device_online(sdp) &&
		   (sect_after <= total_sects)))
		; /* ok: have device, its online and access fits on medium */
	else {
		SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
		"Finishing %u sectors\n",
		num_sects));
		SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
		"Retry with 0x%p\n", SCpnt));
		goto out;
	}
	sect_sz = sdp->sector_size;

	if (unlikely(sdp->changed)) {
		/*
		 * quietly refuse to do anything to a changed disc until 
		 * the changed bit has been reset
		 */
		/* printk("SCSI disk has been changed or is not present. Prohibiting further I/O.\n"); */
		goto out;
	}

	/*
	 * Some SD card readers can't handle multi-sector accesses which touch
	 * the last one or two hardware sectors.  Split accesses as needed.
	 */
	if (unlikely(sdp->last_sector_bug)) {
		threshold_sect = total_sects -
			(SD_LAST_BUGGY_SECTORS * (sect_sz / 512));

		if (unlikely(sect_after > threshold_sect))
			num_sects = (sect_addr < threshold_sect) ?
		(threshold_sect - sect_addr) :
		(sect_sz / 512);
			/* If LBA less than threshold then access up to the
			 * threshold but not beyond; otherwise access only
			 * a 

Re: [PATCHv6,2/5] scsi: Export blacklist flags to sysfs

2017-10-24 Thread jeffy

Hi guys,

maybe we need to add the generated scsi_devinfo_tbl.c into 
drivers/scsi/.gitignore :)


On 10/02/2017 10:26 PM, Hannes Reinecke wrote:

Each scsi device is scanned according to the found blacklist flags,
but this information is never presented to sysfs.
This makes it quite hard to figure out if blacklisting worked as
expected.
With this patch we're exporting an additional attribute 'blacklist'
containing the blacklist flags for this device.

Signed-off-by: Hannes Reinecke 
Reviewed-by: Bart Van Assche 
Reviewed-by: Johannes Thumshirn 
---
  drivers/scsi/Makefile |  8 
  drivers/scsi/scsi_scan.c  |  1 +
  drivers/scsi/scsi_sysfs.c | 37 +
  3 files changed, 46 insertions(+)

diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 93dbe58..c4298c7 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -191,6 +191,14 @@ clean-files := 53c700_d.h 53c700_u.h

  $(obj)/53c700.o $(MODVERDIR)/$(obj)/53c700.ver: $(obj)/53c700_d.h

+$(obj)/scsi_sysfs.o: $(obj)/scsi_devinfo_tbl.c
+
+quiet_cmd_bflags = GEN $@
+   cmd_bflags = sed -n 's/.*BLIST_\([A-Z0-9_]*\) *.*/BLIST_FLAG_NAME(\1),/p' 
$< > $@
+
+$(obj)/scsi_devinfo_tbl.c: include/scsi/scsi_devinfo.h
+   $(call if_changed,bflags)
+
  # If you want to play with the firmware, uncomment
  # GENERATE_FIRMWARE := 1

diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index e7818af..26edd61 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -984,6 +984,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned 
char *inq_result,
scsi_attach_vpd(sdev);

sdev->max_queue_depth = sdev->queue_depth;
+   sdev->sdev_bflags = *bflags;

/*
 * Ok, the device is now all set up, we can
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index bf53356..fde3f44 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -20,6 +20,7 @@
  #include 
  #include 
  #include 
+#include 

  #include "scsi_priv.h"
  #include "scsi_logging.h"
@@ -966,6 +967,41 @@ static DEVICE_ATTR(queue_depth, S_IRUGO | S_IWUSR, 
sdev_show_queue_depth,
  }
  static DEVICE_ATTR(wwid, S_IRUGO, sdev_show_wwid, NULL);

+#define BLIST_FLAG_NAME(name) [ilog2(BLIST_##name)] = #name
+static const char *const sdev_bflags_name[] = {
+#include "scsi_devinfo_tbl.c"
+};
+#undef BLIST_FLAG_NAME
+
+static ssize_t
+sdev_show_blacklist(struct device *dev, struct device_attribute *attr,
+   char *buf)
+{
+   struct scsi_device *sdev = to_scsi_device(dev);
+   int i;
+   ssize_t len = 0;
+
+   for (i = 0; i < sizeof(sdev->sdev_bflags) * BITS_PER_BYTE; i++) {
+   const char *name = NULL;
+
+   if (!(sdev->sdev_bflags & BIT(i)))
+   continue;
+   if (i < ARRAY_SIZE(sdev_bflags_name) && sdev_bflags_name[i])
+   name = sdev_bflags_name[i];
+
+   if (name)
+   len += snprintf(buf + len, PAGE_SIZE - len,
+   "%s%s", len ? " " : "", name);
+   else
+   len += snprintf(buf + len, PAGE_SIZE - len,
+   "%sINVALID_BIT(%d)", len ? " " : "", i);
+   }
+   if (len)
+   len += snprintf(buf + len, PAGE_SIZE - len, "\n");
+   return len;
+}
+static DEVICE_ATTR(blacklist, S_IRUGO, sdev_show_blacklist, NULL);
+
  #ifdef CONFIG_SCSI_DH
  static ssize_t
  sdev_show_dh_state(struct device *dev, struct device_attribute *attr,
@@ -1151,6 +1187,7 @@ static umode_t scsi_sdev_bin_attr_is_visible(struct 
kobject *kobj,
_attr_queue_depth.attr,
_attr_queue_type.attr,
_attr_wwid.attr,
+   _attr_blacklist.attr,
  #ifdef CONFIG_SCSI_DH
_attr_dh_state.attr,
_attr_access_state.attr,







Re: [PATCH V9 1/4] dma-mapping: Rework dma_get_cache_alignment()

2017-10-24 Thread 陈华才
Hi, Marek

Patch3 is needed for stable, but Patch3 depend on Patch1 and Patch2.

Huacai
 
 
-- Original --
From:  "Marek Szyprowski";
Date:  Tue, Oct 24, 2017 09:30 PM
To:  "Huacai Chen"; "Christoph Hellwig"; 
Cc:  "Robin Murphy"; "Andrew 
Morton"; "Fuxin Zhang"; 
"linux-kernel"; "Ralf 
Baechle"; "JamesHogan"; 
"linux-mips"; "James E . J 
.Bottomley"; "Martin K . 
Petersen"; 
"linux-scsi"; "stable"; 
"Michael S . Tsirkin"; "Pawel Osciak"; 
"Kyungmin Park"; "Michael 
Chan"; "Benjamin 
Herrenschmidt"; "Ivan Mikhaylov"; 
"Tariq Toukan"; "Andy Gross"; "Mark 
A . Greer"; "Robert Baldyga"; 
Subject:  Re: [PATCH V9 1/4] dma-mapping: Rework dma_get_cache_alignment()

 
Hi Huacai,

On 2017-10-23 09:12, Huacai Chen wrote:
> Make dma_get_cache_alignment() to accept a 'dev' argument. As a result,
> it can return different alignments due to different devices' I/O cache
> coherency.
>
> Currently, ARM/ARM64 and MIPS support coherent & noncoherent devices
> co-exist. This may be extended in the future, so add a new function
> pointer (i.e, get_cache_alignment) in 'struct dma_map_ops' as a generic
> solution.
>
> Cc: sta...@vger.kernel.org

I don't think this change should go to stable.

> Cc: Michael S. Tsirkin 
> Cc: Pawel Osciak 
> Cc: Marek Szyprowski 
> Cc: Kyungmin Park 
> Cc: Michael Chan 
> Cc: Benjamin Herrenschmidt 
> Cc: Ivan Mikhaylov 
> Cc: Tariq Toukan 
> Cc: Andy Gross 
> Cc: Mark A. Greer 
> Cc: Robert Baldyga 
> Cc: Marek Szyprowski 
> Signed-off-by: Huacai Chen 
> ---
>   drivers/infiniband/hw/mthca/mthca_main.c   |   2 +-
>   drivers/media/v4l2-core/videobuf2-dma-contig.c |   2 +-
>   drivers/net/ethernet/broadcom/b44.c|   8 +-
>   drivers/net/ethernet/ibm/emac/core.c   |  32 +++--
>   drivers/net/ethernet/ibm/emac/core.h   |  14 +-
>   drivers/net/ethernet/mellanox/mlx4/main.c  |   2 +-
>   drivers/spi/spi-qup.c  |   4 +-
>   drivers/tty/serial/mpsc.c  | 179 
> +
>   drivers/tty/serial/samsung.c   |  14 +-
>   include/linux/dma-mapping.h|  17 ++-

For videobuf2-dma-contig, serial/samsung and dma-mapping.h:

Acked-by: Marek Szyprowski 


>   10 files changed, 150 insertions(+), 124 deletions(-)
>
> diff --git a/drivers/infiniband/hw/mthca/mthca_main.c 
> b/drivers/infiniband/hw/mthca/mthca_main.c
> index e36a9bc..078fe8d 100644
> --- a/drivers/infiniband/hw/mthca/mthca_main.c
> +++ b/drivers/infiniband/hw/mthca/mthca_main.c
> @@ -416,7 +416,7 @@ static int mthca_init_icm(struct mthca_dev *mdev,
>   
>   /* CPU writes to non-reserved MTTs, while HCA might DMA to reserved 
> mtts */
>   mdev->limits.reserved_mtts = ALIGN(mdev->limits.reserved_mtts * 
> mdev->limits.mtt_seg_size,
> -dma_get_cache_alignment()) / 
> mdev->limits.mtt_seg_size;
> +
> dma_get_cache_alignment(>pdev->dev)) / mdev->limits.mtt_seg_size;
>   
>   mdev->mr_table.mtt_table = mthca_alloc_icm_table(mdev, 
> init_hca->mtt_base,
>
> mdev->limits.mtt_seg_size,
> diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
> b/drivers/media/v4l2-core/videobuf2-dma-contig.c
> index 9f389f3..1f6a9b7 100644
> --- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
> +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
> @@ -484,7 +484,7 @@ static void *vb2_dc_get_userptr(struct device *dev, 
> unsigned long vaddr,
>   int ret = 0;
>   struct sg_table *sgt;
>   unsigned long contig_size;
> - unsigned long dma_align = dma_get_cache_alignment();
> + unsigned long dma_align = dma_get_cache_alignment(dev);
>   
>   /* Only cache aligned DMA transfers are reliable */
>   if (!IS_ALIGNED(vaddr | size, dma_align)) {
> diff --git a/drivers/net/ethernet/broadcom/b44.c 
> b/drivers/net/ethernet/broadcom/b44.c
> index a1125d1..2f6ffe5 100644
> --- a/drivers/net/ethernet/broadcom/b44.c
> +++ b/drivers/net/ethernet/broadcom/b44.c
> @@ -2344,6 +2344,10 @@ 

Re: [PATCH V9 1/4] dma-mapping: Rework dma_get_cache_alignment()

2017-10-24 Thread Mark Greer
On Mon, Oct 23, 2017 at 03:12:44PM +0800, Huacai Chen wrote:
> Make dma_get_cache_alignment() to accept a 'dev' argument. As a result,
> it can return different alignments due to different devices' I/O cache
> coherency.
> 
> Currently, ARM/ARM64 and MIPS support coherent & noncoherent devices
> co-exist. This may be extended in the future, so add a new function
> pointer (i.e, get_cache_alignment) in 'struct dma_map_ops' as a generic
> solution.
> 
> Cc: sta...@vger.kernel.org
> Cc: Michael S. Tsirkin 
> Cc: Pawel Osciak 
> Cc: Marek Szyprowski 
> Cc: Kyungmin Park 
> Cc: Michael Chan 
> Cc: Benjamin Herrenschmidt 
> Cc: Ivan Mikhaylov 
> Cc: Tariq Toukan 
> Cc: Andy Gross 
> Cc: Mark A. Greer 
> Cc: Robert Baldyga 
> Cc: Marek Szyprowski 
> Signed-off-by: Huacai Chen 
> ---

For the mpsc stuff:

Acked-by: Mark Greer 


Re: [PATCH 9/9] bsg: split handling of SCSI CDBs vs transport requeues

2017-10-24 Thread Jens Axboe
On 10/23/2017 01:17 AM, Martin K. Petersen wrote:
> 
> Christoph,
> 
>>> Yes, I expected the bsg bits to go through Jens' tree.
>>
>> Ok, then I misremembered it, and we'll have to delay the remaining
>> patches until the next merge window, as they depend on the previous
>> ones.
> 
> I don't mind taking them through SCSI if Jens agrees.

I'm fine with that, as long as the last issue Benjamin brought up has
been fixed up.

-- 
Jens Axboe



[PATCH] usb: storage: uas: mark expected switch fall-through

2017-10-24 Thread Gustavo A. R. Silva
In preparation to enabling -Wimplicit-fallthrough, mark switch cases
where we are expecting to fall through.

Addresses-Coverity-ID: 115016
Signed-off-by: Gustavo A. R. Silva 
---
 drivers/usb/storage/uas.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 63cf981..bd4671d 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -668,6 +668,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
break;
case DMA_BIDIRECTIONAL:
cmdinfo->state |= ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB;
+   /* fall through */
case DMA_TO_DEVICE:
cmdinfo->state |= ALLOC_DATA_OUT_URB | SUBMIT_DATA_OUT_URB;
case DMA_NONE:
-- 
2.7.4



Re: [PATCH 9/9] bsg: split handling of SCSI CDBs vs transport requeues

2017-10-24 Thread Benjamin Block
> +static int bsg_transport_complete_rq(struct request *rq, struct sg_io_v4 
> *hdr)
> +{
> + struct bsg_job *job = blk_mq_rq_to_pdu(rq);
> + int ret = 0;
> +
> + /*
> +  * The assignments below don't make much sense, but are kept for
> +  * bug by bug backwards compatibility:
> +  */
> + hdr->device_status = job->result & 0xff;
> + hdr->transport_status = host_byte(job->result);
> + hdr->driver_status = driver_byte(job->result);
> + hdr->info = 0;
> + if (hdr->device_status || hdr->transport_status || hdr->driver_status)
> + hdr->info |= SG_INFO_CHECK;
> + hdr->response_len = 0;
> +
> + if (job->result < 0) {
> + /* we're only returning the result field in the reply */
> + job->reply_len = sizeof(u32);
> + ret = job->result;
> + }
> +
> + if (job->reply_len && hdr->response) {
> + int len = min(hdr->max_response_len, job->reply_len);
> +
> + if (copy_to_user(ptr64(hdr->response), job->reply, len))
> + ret = -EFAULT;
> + else
> + hdr->response_len = len;
> + }
> +
> + /* we assume all request payload was transferred, residual == 0 */
> + hdr->dout_resid = 0;
> +
> + if (rq->next_rq) {
> + unsigned int rsp_len = blk_rq_bytes(rq->next_rq);
> +
> + if (WARN_ON(job->reply_payload_rcv_len > rsp_len))

This gives my a lot of new Warnings when running my tests on zFCP, non
of which happen when I run on 4.13.

After browsing the source some, I figured this is because in comparison
to the old code, blk_rq_bytes() is now called after we finished the
blk-request already and blk_update_bidi_request()+blk_update_request()
was already called. This will update rq->__data_len, and thus the call
here to get rsp_len will get a wrong value. Thus the warnings, and the
following calculation is actually wrong.

I figure you can just replace this call for blk_rq_bytes() with
'job->reply_payload.payload_len'. Its essentially the same value, but
the later is not changed after the job is committed as far as I could see
in the source. Driver makes use of it, but only reading as far as I
could make out after browsing the code for a bit.

I did a quick test with that change in place and that seems to work fine
now. As far as my tests go, they behave as they did before.


Beste Grüße / Best regards,
  - Benjamin Block

> + hdr->din_resid = 0;
> + else
> + hdr->din_resid = rsp_len - job->reply_payload_rcv_len;
> + } else {
> + hdr->din_resid = 0;
> + }
> +
> + return ret;
> +}
> +

--
Linux on z Systems Development / IBM Systems & Technology Group
  IBM Deutschland Research & Development GmbH
Vorsitz. AufsR.: Martina Koederitz /Geschäftsführung: Dirk Wittkopp
Sitz der Gesellschaft: Böblingen / Registergericht: AmtsG Stuttgart, HRB 243294



Re: [PATCH 02/12] hpsa: cleanup sas_phy structures in sysfs when unloading

2017-10-24 Thread Martin K. Petersen

Don,

> Unsure. I do not see the mangled e-mail anywhere in the e-mail
> chain. I did not type the e-mail in like that. But it originated from
> me.  I may have pulled the patch from an archive that mangled it.
>
> Do you want me to re-post the two patches?

I'll fix them up. But it's a bad time to have to rebase...

-- 
Martin K. Petersen  Oracle Linux Engineering


[PATCH 18/19] scsi: hisi_sas: add v3 hw support for AXI fatal error

2017-10-24 Thread John Garry
From: Xiaofei Tan 

Add support for processing AXI bus fatal errors.

If AXI bus fatal error happen, do controller reset to
recover.

Signed-off-by: Xiaofei Tan 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 125 +
 1 file changed, 125 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 18cc3b4..f700482 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -53,6 +53,11 @@
 #define HGC_IOMB_PROC1_STATUS  0x104
 #define CFG_1US_TIMER_TRSH 0xcc
 #define CHNL_INT_STATUS0x148
+#define HGC_AXI_FIFO_ERR_INFO  0x154
+#define AXI_ERR_INFO_OFF   0
+#define AXI_ERR_INFO_MSK   (0xff << AXI_ERR_INFO_OFF)
+#define FIFO_ERR_INFO_OFF  8
+#define FIFO_ERR_INFO_MSK  (0xff << FIFO_ERR_INFO_OFF)
 #define INT_COAL_EN0x19c
 #define OQ_INT_COAL_TIME   0x1a0
 #define OQ_INT_COAL_CNT0x1a4
@@ -1315,6 +1320,114 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void 
*p)
return IRQ_HANDLED;
 }
 
+static const struct hisi_sas_hw_error axi_error[] = {
+   { .msk = BIT(0), .msg = "IOST_AXI_W_ERR" },
+   { .msk = BIT(1), .msg = "IOST_AXI_R_ERR" },
+   { .msk = BIT(2), .msg = "ITCT_AXI_W_ERR" },
+   { .msk = BIT(3), .msg = "ITCT_AXI_R_ERR" },
+   { .msk = BIT(4), .msg = "SATA_AXI_W_ERR" },
+   { .msk = BIT(5), .msg = "SATA_AXI_R_ERR" },
+   { .msk = BIT(6), .msg = "DQE_AXI_R_ERR" },
+   { .msk = BIT(7), .msg = "CQE_AXI_W_ERR" },
+   {},
+};
+
+static const struct hisi_sas_hw_error fifo_error[] = {
+   { .msk = BIT(8),  .msg = "CQE_WINFO_FIFO" },
+   { .msk = BIT(9),  .msg = "CQE_MSG_FIFIO" },
+   { .msk = BIT(10), .msg = "GETDQE_FIFO" },
+   { .msk = BIT(11), .msg = "CMDP_FIFO" },
+   { .msk = BIT(12), .msg = "AWTCTRL_FIFO" },
+   {},
+};
+
+static const struct hisi_sas_hw_error fatal_axi_error[] = {
+   {
+   .irq_msk = BIT(ENT_INT_SRC3_WP_DEPTH_OFF),
+   .msg = "write pointer and depth",
+   },
+   {
+   .irq_msk = BIT(ENT_INT_SRC3_IPTT_SLOT_NOMATCH_OFF),
+   .msg = "iptt no match slot",
+   },
+   {
+   .irq_msk = BIT(ENT_INT_SRC3_RP_DEPTH_OFF),
+   .msg = "read pointer and depth",
+   },
+   {
+   .irq_msk = BIT(ENT_INT_SRC3_AXI_OFF),
+   .reg = HGC_AXI_FIFO_ERR_INFO,
+   .sub = axi_error,
+   },
+   {
+   .irq_msk = BIT(ENT_INT_SRC3_FIFO_OFF),
+   .reg = HGC_AXI_FIFO_ERR_INFO,
+   .sub = fifo_error,
+   },
+   {
+   .irq_msk = BIT(ENT_INT_SRC3_LM_OFF),
+   .msg = "LM add/fetch list",
+   },
+   {
+   .irq_msk = BIT(ENT_INT_SRC3_ABT_OFF),
+   .msg = "SAS_HGC_ABT fetch LM list",
+   },
+};
+
+static irqreturn_t fatal_axi_int_v3_hw(int irq_no, void *p)
+{
+   u32 irq_value, irq_msk;
+   struct hisi_hba *hisi_hba = p;
+   struct device *dev = hisi_hba->dev;
+   int i;
+
+   irq_msk = hisi_sas_read32(hisi_hba, ENT_INT_SRC_MSK3);
+   hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, irq_msk | 0x1df00);
+
+   irq_value = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
+
+   for (i = 0; i < ARRAY_SIZE(fatal_axi_error); i++) {
+   const struct hisi_sas_hw_error *error = _axi_error[i];
+
+   if (!(irq_value & error->irq_msk))
+   continue;
+
+   if (error->sub) {
+   const struct hisi_sas_hw_error *sub = error->sub;
+   u32 err_value = hisi_sas_read32(hisi_hba, error->reg);
+
+   for (; sub->msk || sub->msg; sub++) {
+   if (!(err_value & sub->msk))
+   continue;
+
+   dev_warn(dev, "%s error (0x%x) found!\n",
+   sub->msg, irq_value);
+   queue_work(hisi_hba->wq, _hba->rst_work);
+   }
+   } else {
+   dev_warn(dev, "%s error (0x%x) found!\n",
+   error->msg, irq_value);
+   queue_work(hisi_hba->wq, _hba->rst_work);
+   }
+   }
+
+   if (irq_value & BIT(ENT_INT_SRC3_ITC_INT_OFF)) {
+   u32 reg_val = hisi_sas_read32(hisi_hba, ITCT_CLR);
+   u32 dev_id = reg_val & ITCT_DEV_MSK;
+   struct hisi_sas_device *sas_dev =
+   _hba->devices[dev_id];
+
+   hisi_sas_write32(hisi_hba, ITCT_CLR, 0);
+   dev_dbg(dev, "clear ITCT ok\n");
+   complete(sas_dev->completion);
+ 

[PATCH 12/19] scsi: hisi_sas: check PHY state in get_wideport_bitmap_v3_hw()

2017-10-24 Thread John Garry
From: Xiaofei Tan 

We should check register PHY_STATE when getting the bitmap
of a wideport, as, if the PHY is not ready, the value of
register PHY_PORT_NUM_MA is not valid.

V2 hw has done this check, and v3 hw should do this check too.

Signed-off-by: Xiaofei Tan 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 67ebd8f..c88e787 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -755,10 +755,12 @@ static int get_wideport_bitmap_v3_hw(struct hisi_hba 
*hisi_hba, int port_id)
 {
int i, bitmap = 0;
u32 phy_port_num_ma = hisi_sas_read32(hisi_hba, PHY_PORT_NUM_MA);
+   u32 phy_state = hisi_sas_read32(hisi_hba, PHY_STATE);
 
for (i = 0; i < hisi_hba->n_phy; i++)
-   if (((phy_port_num_ma >> (i * 4)) & 0xf) == port_id)
-   bitmap |= 1 << i;
+   if (phy_state & BIT(i))
+   if (((phy_port_num_ma >> (i * 4)) & 0xf) == port_id)
+   bitmap |= BIT(i);
 
return bitmap;
 }
-- 
1.9.1



[PATCH 13/19] scsi: hisi_sas: init connect cfg register for v3 hw

2017-10-24 Thread John Garry
From: Xiaofei Tan 

Add initialization of register CON_CFG_DRIVER for v3 hw,
to limit number of the times of setup connection.

Signed-off-by: Xiaofei Tan 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index c88e787..5fbd121 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -135,6 +135,7 @@
 #define RX_IDAF_DWORD0 (PORT_BASE + 0xc4)
 #define RXOP_CHECK_CFG_H   (PORT_BASE + 0xfc)
 #define STP_LINK_TIMER (PORT_BASE + 0x120)
+#define CON_CFG_DRIVER (PORT_BASE + 0x130)
 #define SAS_SSP_CON_TIMER_CFG  (PORT_BASE + 0x134)
 #define SAS_SMP_CON_TIMER_CFG  (PORT_BASE + 0x138)
 #define SAS_STP_CON_TIMER_CFG  (PORT_BASE + 0x13c)
@@ -422,6 +423,8 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
 0xa03e8);
hisi_sas_phy_write32(hisi_hba, i, STP_LINK_TIMER,
 0x7f7a120);
+   hisi_sas_phy_write32(hisi_hba, i, CON_CFG_DRIVER,
+0x2a0a80);
}
for (i = 0; i < hisi_hba->queue_count; i++) {
/* Delivery queue */
-- 
1.9.1



[PATCH 11/19] scsi: hisi_sas: report v2 hw AXI errors to userspace

2017-10-24 Thread John Garry
From: Shiju Jose 

This patch adds reporting of AXI errors in the SAS v2 hw
driver to userspace as non-standard trace events.

rasdaemon can be used to read and log these AXI errors
in userspace.

Signed-off-by: Shiju Jose 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 54 +++---
 1 file changed, 50 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 0cf8244..8626d9f 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -389,6 +389,13 @@
 #define HISI_SAS_ECC_ERR_HGC_RXM_MEM1  BIT(7)
 #define HISI_SAS_ECC_ERR_HGC_RXM_MEM2  BIT(8)
 #define HISI_SAS_ECC_ERR_HGC_RXM_MEM3  BIT(9)
+#define HISI_SAS_ERR_WP_DEPTH  BIT(10)
+#define HISI_SAS_ERR_IPTT_SLOT_NOMATCH BIT(11)
+#define HISI_SAS_ERR_RP_DEPTH  BIT(12)
+#define HISI_SAS_ERR_AXI   BIT(13)
+#define HISI_SAS_ERR_FIFO  BIT(14)
+#define HISI_SAS_ERR_LM_ADD_FETCH_LIST BIT(15)
+#define HISI_SAS_ERR_HGC_ABT_FETCH_LM  BIT(16)
 
 struct hisi_sas_complete_v2_hdr {
__le32 dw0;
@@ -417,6 +424,7 @@ struct hisi_sas_hw_err_info {
u64   physical_addr;
u32   mb_err;
u32   type;
+   u32   axi_err_info;
 };
 
 static const struct hisi_sas_hw_error one_bit_ecc_errors[] = {
@@ -748,6 +756,7 @@ enum {
 #define HISI_SAS_VALID_PA  BIT(0)
 #define HISI_SAS_VALID_MB_ERR  BIT(1)
 #define HISI_SAS_VALID_ERR_TYPEBIT(2)
+#define HISI_SAS_VALID_AXI_ERR_INFOBIT(3)
 
 #define ERR_ON_TX_PHASE(err_phase) (err_phase == 0x2 || \
err_phase == 0x4 || err_phase == 0x8 ||\
@@ -3052,32 +3061,39 @@ static irqreturn_t fatal_ecc_int_v2_hw(int irq_no, void 
*p)
{
.irq_msk = BIT(ENT_INT_SRC3_WP_DEPTH_OFF),
.msg = "write pointer and depth",
+   .type = HISI_SAS_ERR_WP_DEPTH,
},
{
.irq_msk = BIT(ENT_INT_SRC3_IPTT_SLOT_NOMATCH_OFF),
.msg = "iptt no match slot",
+   .type = HISI_SAS_ERR_IPTT_SLOT_NOMATCH,
},
{
.irq_msk = BIT(ENT_INT_SRC3_RP_DEPTH_OFF),
.msg = "read pointer and depth",
+   .type = HISI_SAS_ERR_RP_DEPTH,
},
{
.irq_msk = BIT(ENT_INT_SRC3_AXI_OFF),
.reg = HGC_AXI_FIFO_ERR_INFO,
+   .type = HISI_SAS_ERR_AXI,
.sub = axi_error,
},
{
.irq_msk = BIT(ENT_INT_SRC3_FIFO_OFF),
.reg = HGC_AXI_FIFO_ERR_INFO,
+   .type = HISI_SAS_ERR_FIFO,
.sub = fifo_error,
},
{
.irq_msk = BIT(ENT_INT_SRC3_LM_OFF),
.msg = "LM add/fetch list",
+   .type = HISI_SAS_ERR_LM_ADD_FETCH_LIST,
},
{
.irq_msk = BIT(ENT_INT_SRC3_ABT_OFF),
.msg = "SAS_HGC_ABT fetch LM list",
+   .type = HISI_SAS_ERR_HGC_ABT_FETCH_LM,
},
 };
 
@@ -3088,12 +3104,17 @@ static irqreturn_t fatal_axi_int_v2_hw(int irq_no, void 
*p)
struct device *dev = hisi_hba->dev;
const struct hisi_sas_hw_error *axi_error;
int i;
+   struct hisi_sas_hw_err_info err_data;
+   bool trace_ns_event_enabled = trace_non_standard_event_enabled();
 
irq_msk = hisi_sas_read32(hisi_hba, ENT_INT_SRC_MSK3);
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, irq_msk | 0xfffe);
 
irq_value = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
 
+   if (trace_ns_event_enabled)
+   memset(_data, 0, sizeof(err_data));
+
for (i = 0; i < ARRAY_SIZE(fatal_axi_errors); i++) {
axi_error = _axi_errors[i];
if (!(irq_value & axi_error->irq_msk))
@@ -3108,13 +3129,38 @@ static irqreturn_t fatal_axi_int_v2_hw(int irq_no, void 
*p)
for (; sub->msk || sub->msg; sub++) {
if (!(err_value & sub->msk))
continue;
-   dev_warn(dev, "%s (0x%x) found!\n",
-sub->msg, irq_value);
+   if (trace_ns_event_enabled) {
+   err_data.validation_bits =
+   HISI_SAS_VALID_ERR_TYPE |
+   HISI_SAS_VALID_AXI_ERR_INFO;
+   err_data.type = axi_error->type;
+   err_data.axi_err_info = sub->msk;
+   log_non_standard_event(
+   _SEC_TYPE_HISI_SAS,
+   _UUID_LE,
+  

[PATCH 14/19] scsi: hisi_sas: add v3 hw DFX feature

2017-10-24 Thread John Garry
From: Xiaofei Tan 

Realise get_events() to add DFX feature for v3 hw. Just
like v2 hw, We support the following errors:
- loss_of_dword_sync_count
- invalid_dword_count
- phy_reset_problem_count
- running_disparity_error_count

Signed-off-by: Xiaofei Tan 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 5fbd121..818bd575 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -172,6 +172,10 @@
 #define DMA_RX_STATUS  (PORT_BASE + 0x2e8)
 #define DMA_RX_STATUS_BUSY_OFF 0
 #define DMA_RX_STATUS_BUSY_MSK (0x1 << DMA_RX_STATUS_BUSY_OFF)
+#define ERR_CNT_DWS_LOST   (PORT_BASE + 0x380)
+#define ERR_CNT_RESET_PROB (PORT_BASE + 0x384)
+#define ERR_CNT_INVLD_DW   (PORT_BASE + 0x390)
+#define ERR_CNT_DISP_ERR   (PORT_BASE + 0x398)
 
 #define DEFAULT_ITCT_HW2048 /* reset value, not reprogrammed */
 #if (HISI_SAS_MAX_DEVICES > DEFAULT_ITCT_HW)
@@ -1742,6 +1746,31 @@ static u32 get_phys_state_v3_hw(struct hisi_hba 
*hisi_hba)
return hisi_sas_read32(hisi_hba, PHY_STATE);
 }
 
+static void phy_get_events_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+   struct hisi_sas_phy *phy = _hba->phy[phy_no];
+   struct asd_sas_phy *sas_phy = >sas_phy;
+   struct sas_phy *sphy = sas_phy->phy;
+   u32 reg_value;
+
+   /* loss dword sync */
+   reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_DWS_LOST);
+   sphy->loss_of_dword_sync_count += reg_value;
+
+   /* phy reset problem */
+   reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_RESET_PROB);
+   sphy->phy_reset_problem_count += reg_value;
+
+   /* invalid dword */
+   reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_INVLD_DW);
+   sphy->invalid_dword_count += reg_value;
+
+   /* disparity err */
+   reg_value = hisi_sas_phy_read32(hisi_hba, phy_no, ERR_CNT_DISP_ERR);
+   sphy->running_disparity_error_count += reg_value;
+
+}
+
 static int soft_reset_v3_hw(struct hisi_hba *hisi_hba)
 {
struct device *dev = hisi_hba->dev;
@@ -1794,6 +1823,7 @@ static int soft_reset_v3_hw(struct hisi_hba *hisi_hba)
.dereg_device = dereg_device_v3_hw,
.soft_reset = soft_reset_v3_hw,
.get_phys_state = get_phys_state_v3_hw,
+   .get_events = phy_get_events_v3_hw,
 };
 
 static struct Scsi_Host *
-- 
1.9.1



[PATCH 17/19] scsi: hisi_sas: complete all tasklets prior to host reset

2017-10-24 Thread John Garry
From: Xiaofei Tan 

The CQ event is handled in tasklet context, and it could
be delayed if the system loading is high.

It is possible to run into some problems when executing
a host reset when cq_tasklet_vx_hw() is being executed.

So, prior to host reset, execute tasklet_kill() to ensure
that all CQ tasklets are complete.

Besides, as the function hisi_sas_wait_tasklets_done()
is added to do tasklet_kill(), this patch refactors some
code where tasklet_kill() is used.

Signed-off-by: Xiaofei Tan 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  1 +
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 11 +++
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  8 ++--
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c |  3 ++-
 4 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 00fefea..636cdf8 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -435,4 +435,5 @@ extern void hisi_sas_slot_task_free(struct hisi_hba 
*hisi_hba,
struct hisi_sas_slot *slot);
 extern void hisi_sas_init_mem(struct hisi_hba *hisi_hba);
 extern void hisi_sas_rst_work_handler(struct work_struct *work);
+extern void hisi_sas_kill_tasklets(struct hisi_hba *hisi_hba);
 #endif
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 1d417a4..4cbb999 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1548,6 +1548,17 @@ void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int 
phy_no, int rdy)
 }
 EXPORT_SYMBOL_GPL(hisi_sas_phy_down);
 
+void hisi_sas_kill_tasklets(struct hisi_hba *hisi_hba)
+{
+   int i;
+
+   for (i = 0; i < hisi_hba->queue_count; i++) {
+   struct hisi_sas_cq *cq = _hba->cq[i];
+
+   tasklet_kill(>tasklet);
+   }
+}
+EXPORT_SYMBOL_GPL(hisi_sas_kill_tasklets);
 
 struct scsi_transport_template *hisi_sas_stt;
 EXPORT_SYMBOL_GPL(hisi_sas_stt);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 8626d9f..433412a 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -3512,6 +3512,7 @@ static int soft_reset_v2_hw(struct hisi_hba *hisi_hba)
 
interrupt_disable_v2_hw(hisi_hba);
hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0);
+   hisi_sas_kill_tasklets(hisi_hba);
 
hisi_sas_stop_phys(hisi_hba);
 
@@ -3595,16 +3596,11 @@ static int hisi_sas_v2_remove(struct platform_device 
*pdev)
 {
struct sas_ha_struct *sha = platform_get_drvdata(pdev);
struct hisi_hba *hisi_hba = sha->lldd_ha;
-   int i;
 
if (timer_pending(_hba->timer))
del_timer(_hba->timer);
 
-   for (i = 0; i < hisi_hba->queue_count; i++) {
-   struct hisi_sas_cq *cq = _hba->cq[i];
-
-   tasklet_kill(>tasklet);
-   }
+   hisi_sas_kill_tasklets(hisi_hba);
 
return hisi_sas_remove(pdev);
 }
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 243fa1d..18cc3b4 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -1768,6 +1768,7 @@ static int soft_reset_v3_hw(struct hisi_hba *hisi_hba)
 
interrupt_disable_v3_hw(hisi_hba);
hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0);
+   hisi_sas_kill_tasklets(hisi_hba);
 
hisi_sas_stop_phys(hisi_hba);
 
@@ -1977,7 +1978,6 @@ static int soft_reset_v3_hw(struct hisi_hba *hisi_hba)
struct hisi_sas_cq *cq = _hba->cq[i];
 
free_irq(pci_irq_vector(pdev, i+16), cq);
-   tasklet_kill(>tasklet);
}
pci_free_irq_vectors(pdev);
 }
@@ -1993,6 +1993,7 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev)
sas_remove_host(sha->core.shost);
 
hisi_sas_v3_destroy_irqs(pdev, hisi_hba);
+   hisi_sas_kill_tasklets(hisi_hba);
pci_release_regions(pdev);
pci_disable_device(pdev);
hisi_sas_free(hisi_hba);
-- 
1.9.1



[PATCH 16/19] scsi: hisi_sas: fix a bug when free device for v3 hw

2017-10-24 Thread John Garry
From: Xiang Chen 

Use completion to wait on ITCT CLR interrupt finishing before
processing other things when freeing a device.

This is safer than the pre-existing process of polling the
register.

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 25 +++--
 1 file changed, 7 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 1f8995b..243fa1d 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -393,7 +393,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
hisi_sas_write32(hisi_hba, ENT_INT_SRC3, 0x);
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, 0xfefefefe);
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK2, 0xfefefefe);
-   hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0x);
+   hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xfffe20ff);
hisi_sas_write32(hisi_hba, CHNL_PHYUPDOWN_INT_MSK, 0x0);
hisi_sas_write32(hisi_hba, CHNL_ENT_INT_MSK, 0x0);
hisi_sas_write32(hisi_hba, HGC_COM_INT_MSK, 0x0);
@@ -582,35 +582,24 @@ static void setup_itct_v3_hw(struct hisi_hba *hisi_hba,
 static void free_device_v3_hw(struct hisi_hba *hisi_hba,
  struct hisi_sas_device *sas_dev)
 {
+   DECLARE_COMPLETION_ONSTACK(completion);
u64 dev_id = sas_dev->device_id;
-   struct device *dev = hisi_hba->dev;
struct hisi_sas_itct *itct = _hba->itct[dev_id];
u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
 
+   sas_dev->completion = 
+
/* clear the itct interrupt state */
if (ENT_INT_SRC3_ITC_INT_MSK & reg_val)
hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
 ENT_INT_SRC3_ITC_INT_MSK);
 
/* clear the itct table*/
-   reg_val = hisi_sas_read32(hisi_hba, ITCT_CLR);
-   reg_val |= ITCT_CLR_EN_MSK | (dev_id & ITCT_DEV_MSK);
+   reg_val = ITCT_CLR_EN_MSK | (dev_id & ITCT_DEV_MSK);
hisi_sas_write32(hisi_hba, ITCT_CLR, reg_val);
 
-   udelay(10);
-   reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
-   if (ENT_INT_SRC3_ITC_INT_MSK & reg_val) {
-   dev_dbg(dev, "got clear ITCT done interrupt\n");
-
-   /* invalid the itct state*/
-   memset(itct, 0, sizeof(struct hisi_sas_itct));
-   hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
-ENT_INT_SRC3_ITC_INT_MSK);
-
-   /* clear the itct */
-   hisi_sas_write32(hisi_hba, ITCT_CLR, 0);
-   dev_dbg(dev, "clear ITCT ok\n");
-   }
+   wait_for_completion(sas_dev->completion);
+   memset(itct, 0, sizeof(struct hisi_sas_itct));
 }
 
 static void dereg_device_v3_hw(struct hisi_hba *hisi_hba,
-- 
1.9.1



[PATCH 19/19] scsi: hisi_sas: add v3 hw port AXI error handling

2017-10-24 Thread John Garry
From: Xiaofei Tan 

Add support for servicing AXI errors handling. We do host
a controller reset for such errors.

Signed-off-by: Xiaofei Tan 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 42 ++
 1 file changed, 37 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index f700482..d1bf5af 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -160,6 +160,10 @@
 #define CHL_INT1_DMAC_TX_ECC_ERR_MSK   (0x1 << CHL_INT1_DMAC_TX_ECC_ERR_OFF)
 #define CHL_INT1_DMAC_RX_ECC_ERR_OFF   17
 #define CHL_INT1_DMAC_RX_ECC_ERR_MSK   (0x1 << CHL_INT1_DMAC_RX_ECC_ERR_OFF)
+#define CHL_INT1_DMAC_TX_AXI_WR_ERR_OFF19
+#define CHL_INT1_DMAC_TX_AXI_RD_ERR_OFF20
+#define CHL_INT1_DMAC_RX_AXI_WR_ERR_OFF21
+#define CHL_INT1_DMAC_RX_AXI_RD_ERR_OFF22
 #define CHL_INT2   (PORT_BASE + 0x1bc)
 #define CHL_INT0_MSK   (PORT_BASE + 0x1c0)
 #define CHL_INT1_MSK   (PORT_BASE + 0x1c4)
@@ -417,7 +421,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0x);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT2, 0x);
hisi_sas_phy_write32(hisi_hba, i, RXOP_CHECK_CFG_H, 0x1000);
-   hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0x);
+   hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0xff87);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0x8bff);
hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL_RDY_MSK, 0x0);
hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_NOT_RDY_MSK, 0x0);
@@ -1265,6 +1269,25 @@ static irqreturn_t int_phy_up_down_bcast_v3_hw(int 
irq_no, void *p)
return res;
 }
 
+static const struct hisi_sas_hw_error port_axi_error[] = {
+   {
+   .irq_msk = BIT(CHL_INT1_DMAC_TX_AXI_WR_ERR_OFF),
+   .msg = "dma_tx_axi_wr_err",
+   },
+   {
+   .irq_msk = BIT(CHL_INT1_DMAC_TX_AXI_RD_ERR_OFF),
+   .msg = "dma_tx_axi_rd_err",
+   },
+   {
+   .irq_msk = BIT(CHL_INT1_DMAC_RX_AXI_WR_ERR_OFF),
+   .msg = "dma_rx_axi_wr_err",
+   },
+   {
+   .irq_msk = BIT(CHL_INT1_DMAC_RX_AXI_RD_ERR_OFF),
+   .msg = "dma_rx_axi_rd_err",
+   },
+};
+
 static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p)
 {
struct hisi_hba *hisi_hba = p;
@@ -1290,10 +1313,19 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void 
*p)
 
if ((irq_msk & (4 << (phy_no * 4))) &&
irq_value1) {
-   if (irq_value1 & (CHL_INT1_DMAC_RX_ECC_ERR_MSK |
- CHL_INT1_DMAC_TX_ECC_ERR_MSK))
-   panic("%s: DMAC RX/TX ecc bad error! (0x%x)",
-   dev_name(dev), irq_value1);
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(port_axi_error); i++) {
+   const struct hisi_sas_hw_error *error =
+   _axi_error[i];
+
+   if (!(irq_value1 & error->irq_msk))
+   continue;
+
+   dev_warn(dev, "%s error (phy%d 0x%x) found!\n",
+   error->msg, phy_no, irq_value1);
+   queue_work(hisi_hba->wq, _hba->rst_work);
+   }
 
hisi_sas_phy_write32(hisi_hba, phy_no,
 CHL_INT1, irq_value1);
-- 
1.9.1



[PATCH 15/19] scsi: hisi_sas: add hisi_hba.rst_work init for v3 hw

2017-10-24 Thread John Garry
From: Xiaofei Tan 

Add init code of hisi_hba->rst_work for v3 hw. Because v3
hw also need it to recover controller when some hw errors
occurs.

Signed-off-by: Xiaofei Tan 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   | 1 +
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 3 ++-
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 1 +
 3 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 58bc69e..00fefea 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -434,4 +434,5 @@ extern void hisi_sas_slot_task_free(struct hisi_hba 
*hisi_hba,
struct sas_task *task,
struct hisi_sas_slot *slot);
 extern void hisi_sas_init_mem(struct hisi_hba *hisi_hba);
+extern void hisi_sas_rst_work_handler(struct work_struct *work);
 #endif
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 6b4dabde..1d417a4 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1785,13 +1785,14 @@ void hisi_sas_free(struct hisi_hba *hisi_hba)
 }
 EXPORT_SYMBOL_GPL(hisi_sas_free);
 
-static void hisi_sas_rst_work_handler(struct work_struct *work)
+void hisi_sas_rst_work_handler(struct work_struct *work)
 {
struct hisi_hba *hisi_hba =
container_of(work, struct hisi_hba, rst_work);
 
hisi_sas_controller_reset(hisi_hba);
 }
+EXPORT_SYMBOL_GPL(hisi_sas_rst_work_handler);
 
 int hisi_sas_get_fw_info(struct hisi_hba *hisi_hba)
 {
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 818bd575..1f8995b 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -1840,6 +1840,7 @@ static int soft_reset_v3_hw(struct hisi_hba *hisi_hba)
}
hisi_hba = shost_priv(shost);
 
+   INIT_WORK(_hba->rst_work, hisi_sas_rst_work_handler);
hisi_hba->hw = _sas_v3_hw;
hisi_hba->pci_dev = pdev;
hisi_hba->dev = dev;
-- 
1.9.1



RE: [PATCH 02/12] hpsa: cleanup sas_phy structures in sysfs when unloading

2017-10-24 Thread Don Brace
> -Original Message-
> On Fri, 2017-10-20 at 16:51 -0500, Don Brace wrote:
> > From: Martin Wilck 
> >
> > I am resubmitting this patch on behalf of Martin Wilck
> > with his permission.
> >
> > The original patch can be found here:
> > https://www.spinics.net/lists/linux-scsi/msg102083.html
> >
> > This patch did not help until Hannes's
> > commit 9441284fbc39 ("scsi-fixup-kernel-warning-during-rmmod")
> > was applied to the kernel.
> >
> > --
> > Original patch description from Martin:
> > --
> >
> > When the hpsa module is unloaded using rmmod, dangling
> > symlinks remain under /sys/class/sas_phy. Fix this by
> > calling sas_phy_delete() rather than sas_phy_free (which,
> > according to comments, should not be called for PHYs that
> > have been set up successfully, anyway).
> >
> > Tested-by: Don Brace 
> > Reviewed-by: Don Brace 
> > Signed-off-by: Martin Wilck 
> 
> Hey, what's this for a signoff?  The original patch had the correct
> email address; how did it get mangled like this?
> 
> James

Unsure. I do not see the mangled e-mail anywhere in the e-mail
chain. I did not type the e-mail in like that. But it originated from me.
I may have pulled the patch from an archive that mangled it.

Do you want me to re-post the two patches? 

Thanks,
Don Brace
ESC - Smart Storage
Microsemi Corporation





[PATCH 05/19] scsi: hisi_sas: fix SATA breakpoint memory size

2017-10-24 Thread John Garry
From: Xiang Chen 

Currently the size of memory we allocate for SATA
breakpoint buffer is incorrect.

The breakpoint memory size should be as follows:
32 (NCQ tags) * 128 * 2048 (max #devs) = 8MB

Currently we only allocate 0.5MB, but get away with it
as we never have SATA device index > 128 typically.

To conserve precious DMA memory (8MB may not be even
available), limit the number of devices per HBA to 1024,
which means 4MB of memory required for SATA breakpoint.

The 1024 device limit applied to all HW versions. For v3
hw, we need to configure this value.

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   | 8 ++--
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 6 +++---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 +-
 3 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 07f4a4c..07538cf 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -29,7 +29,7 @@
 #define HISI_SAS_MAX_PHYS  9
 #define HISI_SAS_MAX_QUEUES32
 #define HISI_SAS_QUEUE_SLOTS 512
-#define HISI_SAS_MAX_ITCT_ENTRIES 2048
+#define HISI_SAS_MAX_ITCT_ENTRIES 1024
 #define HISI_SAS_MAX_DEVICES HISI_SAS_MAX_ITCT_ENTRIES
 #define HISI_SAS_RESET_BIT 0
 #define HISI_SAS_REJECT_CMD_BIT1
@@ -342,7 +342,11 @@ struct hisi_sas_initial_fis {
 };
 
 struct hisi_sas_breakpoint {
-   u8  data[128];  /*io128 byte*/
+   u8  data[128];
+};
+
+struct hisi_sas_sata_breakpoint {
+   struct hisi_sas_breakpoint tag[32];
 };
 
 struct hisi_sas_sge {
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 254af67..f49a131 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1613,7 +1613,7 @@ void hisi_sas_init_mem(struct hisi_hba *hisi_hba)
s = max_command_entries * sizeof(struct hisi_sas_breakpoint);
memset(hisi_hba->breakpoint, 0, s);
 
-   s = max_command_entries * sizeof(struct hisi_sas_breakpoint) * 2;
+   s = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_sata_breakpoint);
memset(hisi_hba->sata_breakpoint, 0, s);
 }
 EXPORT_SYMBOL_GPL(hisi_sas_init_mem);
@@ -1706,7 +1706,7 @@ int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct 
Scsi_Host *shost)
if (!hisi_hba->initial_fis)
goto err_out;
 
-   s = max_command_entries * sizeof(struct hisi_sas_breakpoint) * 2;
+   s = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_sata_breakpoint);
hisi_hba->sata_breakpoint = dma_alloc_coherent(dev, s,
_hba->sata_breakpoint_dma, GFP_KERNEL);
if (!hisi_hba->sata_breakpoint)
@@ -1771,7 +1771,7 @@ void hisi_sas_free(struct hisi_hba *hisi_hba)
  hisi_hba->initial_fis,
  hisi_hba->initial_fis_dma);
 
-   s = max_command_entries * sizeof(struct hisi_sas_breakpoint) * 2;
+   s = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_sata_breakpoint);
if (hisi_hba->sata_breakpoint)
dma_free_coherent(dev, s,
  hisi_hba->sata_breakpoint,
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 38eeba9..ac499e9 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -172,7 +172,6 @@
 #define DMA_RX_STATUS_BUSY_OFF 0
 #define DMA_RX_STATUS_BUSY_MSK (0x1 << DMA_RX_STATUS_BUSY_OFF)
 
-#define MAX_ITCT_HW4096 /* max the hw can support */
 #define DEFAULT_ITCT_HW2048 /* reset value, not reprogrammed */
 #if (HISI_SAS_MAX_DEVICES > DEFAULT_ITCT_HW)
 #error Max ITCT exceeded
@@ -377,6 +376,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
/* Global registers init */
hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE,
 (u32)((1ULL << hisi_hba->queue_count) - 1));
+   hisi_sas_write32(hisi_hba, CFG_MAX_TAG, 0xfff0400);
hisi_sas_write32(hisi_hba, HGC_SAS_TXFAIL_RETRY_CTRL, 0x108);
hisi_sas_write32(hisi_hba, CFG_1US_TIMER_TRSH, 0xd);
hisi_sas_write32(hisi_hba, INT_COAL_EN, 0x1);
-- 
1.9.1



[PATCH 04/19] scsi: hisi_sas: grab hisi_hba.lock when processing slots

2017-10-24 Thread John Garry
From: Xiang Chen 

When adding/removing slots from device list, we need to
lock this operation with hisi_hba lock for safety.

This patch adds missing instances of this.

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 5 -
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 ++
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 ++
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index e038bdf..254af67 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -401,7 +401,9 @@ static int hisi_sas_task_prep(struct sas_task *task, struct 
hisi_sas_dq
goto err_out_buf;
}
 
+   spin_lock_irqsave(_hba->lock, flags);
list_add_tail(>entry, _dev->list);
+   spin_unlock_irqrestore(_hba->lock, flags);
spin_lock_irqsave(>task_state_lock, flags);
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
spin_unlock_irqrestore(>task_state_lock, flags);
@@ -1387,8 +1389,9 @@ static int hisi_sas_query_task(struct sas_task *task)
if (rc)
goto err_out_buf;
 
-
+   spin_lock_irqsave(_hba->lock, flags);
list_add_tail(>entry, _dev->list);
+   spin_unlock_irqrestore(_hba->lock, flags);
spin_lock_irqsave(>task_state_lock, flags);
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
spin_unlock_irqrestore(>task_state_lock, flags);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 73d12ff..3b2e5b5 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -2378,7 +2378,9 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
 
if (unlikely(aborted)) {
ts->stat = SAS_ABORTED_TASK;
+   spin_lock_irqsave(_hba->lock, flags);
hisi_sas_slot_task_free(hisi_hba, task, slot);
+   spin_unlock_irqrestore(_hba->lock, flags);
return -1;
}
 
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index d60501f..38eeba9 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -1400,7 +1400,9 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p)
ts->resp = SAS_TASK_COMPLETE;
if (unlikely(aborted)) {
ts->stat = SAS_ABORTED_TASK;
+   spin_lock_irqsave(_hba->lock, flags);
hisi_sas_slot_task_free(hisi_hba, task, slot);
+   spin_unlock_irqrestore(_hba->lock, flags);
return -1;
}
 
-- 
1.9.1



[PATCH 01/19] scsi: hisi_sas: delete get_ncq_tag_v3_hw()

2017-10-24 Thread John Garry
From: Xiang Chen 

We already relocated hisi_sas_get_ncq_tag() into common
file main.c, so delete get_ncq_tag_v3_hw() and use
hisi_sas_get_ncq_tag() instead.

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 16 +---
 1 file changed, 1 insertion(+), 15 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 2e5fa97..d60501f 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -988,20 +988,6 @@ static int prep_smp_v3_hw(struct hisi_hba *hisi_hba,
return rc;
 }
 
-static int get_ncq_tag_v3_hw(struct sas_task *task, u32 *tag)
-{
-   struct ata_queued_cmd *qc = task->uldd_task;
-
-   if (qc) {
-   if (qc->tf.command == ATA_CMD_FPDMA_WRITE ||
-   qc->tf.command == ATA_CMD_FPDMA_READ) {
-   *tag = qc->tag;
-   return 1;
-   }
-   }
-   return 0;
-}
-
 static int prep_ata_v3_hw(struct hisi_hba *hisi_hba,
  struct hisi_sas_slot *slot)
 {
@@ -1050,7 +1036,7 @@ static int prep_ata_v3_hw(struct hisi_hba *hisi_hba,
hdr->dw1 = cpu_to_le32(dw1);
 
/* dw2 */
-   if (task->ata_task.use_ncq && get_ncq_tag_v3_hw(task, _tag)) {
+   if (task->ata_task.use_ncq && hisi_sas_get_ncq_tag(task, _tag)) {
task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
dw2 |= hdr_tag << CMD_HDR_NCQ_TAG_OFF;
}
-- 
1.9.1



[PATCH 08/19] scsi: hisi_sas: fix the risk of freeing slot twice

2017-10-24 Thread John Garry
From: Xiaofei Tan 

The function hisi_sas_slot_task_free() is used to free
the slot and do tidy-up of LLDD resources. The LLDD
generally should know the state of a slot and decide when
to free it, and it should only be done once.

For some scenarios, we really don't know the state, like
when TMF timeout. In this case, we check task->lldd_task
before calling hisi_sas_slot_task_free().

However, we may miss some scenarios when we should also
check task->lldd_task, and it is not SMP safe to check
task->lldd_task as we don't protect it within spin lock.

This patch is to fix this risk of freeing slot twice, as
follows:
1. Check task->lldd_task in the hisi_sas_slot_task_free(),
and give up freeing of this time if task->lldd_task is NULL.
2. Set slot->buf to NULL after it is freed.

Signed-off-by: Xiaofei Tan 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 2a209e1..6b4dabde 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -185,13 +185,16 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, 
struct sas_task *task,
struct domain_device *device = task->dev;
struct hisi_sas_device *sas_dev = device->lldd_dev;
 
+   if (!task->lldd_task)
+   return;
+
+   task->lldd_task = NULL;
+
if (!sas_protocol_ata(task->task_proto))
if (slot->n_elem)
dma_unmap_sg(dev, task->scatter, slot->n_elem,
 task->data_dir);
 
-   task->lldd_task = NULL;
-
if (sas_dev)
atomic64_dec(_dev->running_req);
}
@@ -199,8 +202,8 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, 
struct sas_task *task,
if (slot->buf)
dma_pool_free(hisi_hba->buffer_pool, slot->buf, slot->buf_dma);
 
-
list_del_init(>entry);
+   slot->buf = NULL;
slot->task = NULL;
slot->port = NULL;
hisi_sas_slot_index_free(hisi_hba, slot->idx);
-- 
1.9.1



[PATCH 03/19] scsi: hisi_sas: use spin_lock_irqsave() for hisi_hba.lock

2017-10-24 Thread John Garry
From: Xiaofei Tan 

We used spin_lock() to grab hisi_hba.lock in two places
where spin_lock_irqsave() should be used, as
hisi_hba.lock can be taken in interrupt context.

This patch is to fix this.

Signed-off-by: Xiaofei Tan 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 5 +++--
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 5 +++--
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 0eb9174..e038bdf 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -505,9 +505,10 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct 
domain_device *device)
 {
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct hisi_sas_device *sas_dev = NULL;
+   unsigned long flags;
int i;
 
-   spin_lock(_hba->lock);
+   spin_lock_irqsave(_hba->lock, flags);
for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
if (hisi_hba->devices[i].dev_type == SAS_PHY_UNUSED) {
int queue = i % hisi_hba->queue_count;
@@ -524,7 +525,7 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct 
domain_device *device)
break;
}
}
-   spin_unlock(_hba->lock);
+   spin_unlock_irqrestore(_hba->lock, flags);
 
return sas_dev;
 }
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 779af97..73d12ff 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -843,8 +843,9 @@ hisi_sas_device *alloc_dev_quirk_v2_hw(struct domain_device 
*device)
struct hisi_sas_device *sas_dev = NULL;
int i, sata_dev = dev_is_sata(device);
int sata_idx = -1;
+   unsigned long flags;
 
-   spin_lock(_hba->lock);
+   spin_lock_irqsave(_hba->lock, flags);
 
if (sata_dev)
if (!sata_index_alloc_v2_hw(hisi_hba, _idx))
@@ -874,7 +875,7 @@ hisi_sas_device *alloc_dev_quirk_v2_hw(struct domain_device 
*device)
}
 
 out:
-   spin_unlock(_hba->lock);
+   spin_unlock_irqrestore(_hba->lock, flags);
 
return sas_dev;
 }
-- 
1.9.1



[PATCH 10/19] scsi: hisi_sas: report ECC errors in v2 hw to userspace

2017-10-24 Thread John Garry
From: Shiju Jose 

This patch adds reporting ECC errors in the SAS V2 driver to
userspace as non-standard trace events.

rasdaemon can be used to read and log these ECC errors in
userspace.

Rasdaemon log for the SAS errors with the decoding sample:
cpu 00:[   70.025830] hisi_sas_v2_hw HISI0162:01: phy7, wait tx fifo need send 
break
  -0 [4204528] 0.07: non_standard_event:   2017-09-06 
11:14:49 +
 Recoverable
 section type: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 fru text: HISI0162:01 fru 
id: ----
 length: 24
 error:
  : 0007  013c 
  0010:  0001
HISI HIP07: SAS error: [phy addr = 0x0x13c: single-bit ecc: error type = 
hgc_dqe ecc]

cpu 00:  -0 [4204552] 0.07: non_standard_event:   
2017-09-06 11:14:49 +
 Fatal
 section type: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 fru text: HISI0162:01 fru 
id: ----
 length: 24
 error:
  : 0007  013c 
  0010: 0001 0001
HISI HIP07: SAS error: [phy addr = 0x0x13c: multi-bit ecc: error type = hgc_dqe 
ecc]

Signed-off-by: Shiju Jose 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  9 
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 95 +-
 2 files changed, 102 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index d2d384b..58bc69e 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -12,6 +12,7 @@
 #ifndef _HISI_SAS_H_
 #define _HISI_SAS_H_
 
+#include 
 #include 
 #include 
 #include 
@@ -22,7 +23,9 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 
@@ -96,9 +99,15 @@ struct hisi_sas_hw_error {
int shift;
const char *msg;
int reg;
+   u32 type;
const struct hisi_sas_hw_error *sub;
 };
 
+enum hisi_sas_bit_err_type {
+   HISI_SAS_ERR_SINGLE_BIT_ECC = 0x0,
+   HISI_SAS_ERR_MULTI_BIT_ECC = 0x1,
+};
+
 struct hisi_sas_phy {
struct hisi_hba *hisi_hba;
struct hisi_sas_port*port;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index ee34f2e..0cf8244 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -379,6 +379,17 @@
 
 #define HISI_SAS_FATAL_INT_NR  2
 
+#define HISI_SAS_ECC_ERR_HGC_DQE   BIT(0)
+#define HISI_SAS_ECC_ERR_HGC_IOST  BIT(1)
+#define HISI_SAS_ECC_ERR_HGC_ITCT  BIT(2)
+#define HISI_SAS_ECC_ERR_HGC_IOSTLIST  BIT(3)
+#define HISI_SAS_ECC_ERR_HGC_ITCTLIST  BIT(4)
+#define HISI_SAS_ECC_ERR_HGC_CQE   BIT(5)
+#define HISI_SAS_ECC_ERR_HGC_RXM_MEM0  BIT(6)
+#define HISI_SAS_ECC_ERR_HGC_RXM_MEM1  BIT(7)
+#define HISI_SAS_ECC_ERR_HGC_RXM_MEM2  BIT(8)
+#define HISI_SAS_ECC_ERR_HGC_RXM_MEM3  BIT(9)
+
 struct hisi_sas_complete_v2_hdr {
__le32 dw0;
__le32 dw1;
@@ -401,6 +412,13 @@ struct hisi_sas_err_record_v2 {
__le32 dma_rx_err_type;
 };
 
+struct hisi_sas_hw_err_info {
+   u64   validation_bits;
+   u64   physical_addr;
+   u32   mb_err;
+   u32   type;
+};
+
 static const struct hisi_sas_hw_error one_bit_ecc_errors[] = {
{
.irq_msk = BIT(SAS_ECC_INTR_DQE_ECC_1B_OFF),
@@ -408,6 +426,7 @@ struct hisi_sas_err_record_v2 {
.shift = HGC_DQE_ECC_1B_ADDR_OFF,
.msg = "hgc_dqe_acc1b_intr found: Ram address is 0x%08X\n",
.reg = HGC_DQE_ECC_ADDR,
+   .type = HISI_SAS_ECC_ERR_HGC_DQE,
},
{
.irq_msk = BIT(SAS_ECC_INTR_IOST_ECC_1B_OFF),
@@ -415,6 +434,7 @@ struct hisi_sas_err_record_v2 {
.shift = HGC_IOST_ECC_1B_ADDR_OFF,
.msg = "hgc_iost_acc1b_intr found: Ram address is 0x%08X\n",
.reg = HGC_IOST_ECC_ADDR,
+   .type = HISI_SAS_ECC_ERR_HGC_IOST,
},
{
.irq_msk = BIT(SAS_ECC_INTR_ITCT_ECC_1B_OFF),
@@ -422,6 +442,7 @@ struct hisi_sas_err_record_v2 {
.shift = HGC_ITCT_ECC_1B_ADDR_OFF,
.msg = "hgc_itct_acc1b_intr found: am address is 0x%08X\n",
.reg = HGC_ITCT_ECC_ADDR,
+   .type = HISI_SAS_ECC_ERR_HGC_ITCT,
},
{
.irq_msk = BIT(SAS_ECC_INTR_IOSTLIST_ECC_1B_OFF),
@@ -429,6 +450,7 @@ struct hisi_sas_err_record_v2 {
.shift = HGC_LM_DFX_STATUS2_IOSTLIST_OFF,
.msg = "hgc_iostl_acc1b_intr found: memory address is 0x%08X\n",
.reg = HGC_LM_DFX_STATUS2,
+   .type = HISI_SAS_ECC_ERR_HGC_IOSTLIST,
},
{
.irq_msk = BIT(SAS_ECC_INTR_ITCTLIST_ECC_1B_OFF),
@@ -436,6 +458,7 @@ struct hisi_sas_err_record_v2 {
.shift = 

[PATCH 06/19] scsi: hisi_sas: us start_phy in PHY_FUNC_LINK_RESET

2017-10-24 Thread John Garry
From: Xiang Chen 

When a PHY_FUNC_LINK_RESET is issued, we need to fill the
transport identify_frame to SAS controller before the
PHYs are enabled.

Without this, we may find that if a PHY which belonged to
a wideport before the reset may generate a new port id.

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   | 2 +-
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 2 +-
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 2 +-
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 +-
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 07538cf..ea4b5d6 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -198,7 +198,7 @@ struct hisi_sas_hw {
int (*slot_complete)(struct hisi_hba *hisi_hba,
 struct hisi_sas_slot *slot);
void (*phys_init)(struct hisi_hba *hisi_hba);
-   void (*phy_enable)(struct hisi_hba *hisi_hba, int phy_no);
+   void (*phy_start)(struct hisi_hba *hisi_hba, int phy_no);
void (*phy_disable)(struct hisi_hba *hisi_hba, int phy_no);
void (*phy_hard_reset)(struct hisi_hba *hisi_hba, int phy_no);
void (*get_events)(struct hisi_hba *hisi_hba, int phy_no);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index f49a131..88d90dc 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -765,7 +765,7 @@ static int hisi_sas_control_phy(struct asd_sas_phy 
*sas_phy, enum phy_func func,
case PHY_FUNC_LINK_RESET:
hisi_hba->hw->phy_disable(hisi_hba, phy_no);
msleep(100);
-   hisi_hba->hw->phy_enable(hisi_hba, phy_no);
+   hisi_hba->hw->phy_start(hisi_hba, phy_no);
break;
 
case PHY_FUNC_DISABLE:
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 08eca20..00b5ee4 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -1857,7 +1857,7 @@ static int hisi_sas_v1_init(struct hisi_hba *hisi_hba)
.start_delivery = start_delivery_v1_hw,
.slot_complete = slot_complete_v1_hw,
.phys_init = phys_init_v1_hw,
-   .phy_enable = enable_phy_v1_hw,
+   .phy_start = start_phy_v1_hw,
.phy_disable = disable_phy_v1_hw,
.phy_hard_reset = phy_hard_reset_v1_hw,
.phy_set_linkrate = phy_set_linkrate_v1_hw,
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 3b2e5b5..50a0fc8 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -3463,7 +3463,7 @@ static int soft_reset_v2_hw(struct hisi_hba *hisi_hba)
.start_delivery = start_delivery_v2_hw,
.slot_complete = slot_complete_v2_hw,
.phys_init = phys_init_v2_hw,
-   .phy_enable = enable_phy_v2_hw,
+   .phy_start = start_phy_v2_hw,
.phy_disable = disable_phy_v2_hw,
.phy_hard_reset = phy_hard_reset_v2_hw,
.get_events = phy_get_events_v2_hw,
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index ac499e9..67ebd8f 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -1781,7 +1781,7 @@ static int soft_reset_v3_hw(struct hisi_hba *hisi_hba)
.start_delivery = start_delivery_v3_hw,
.slot_complete = slot_complete_v3_hw,
.phys_init = phys_init_v3_hw,
-   .phy_enable = enable_phy_v3_hw,
+   .phy_start = start_phy_v3_hw,
.phy_disable = disable_phy_v3_hw,
.phy_hard_reset = phy_hard_reset_v3_hw,
.phy_get_max_linkrate = phy_get_max_linkrate_v3_hw,
-- 
1.9.1



[PATCH 09/19] scsi: hisi_sas: use array for v2 hw AXI errors

2017-10-24 Thread John Garry
From: Shiju Jose 

The code to print AXI errors in v2 hw driver is
repetitive.

This patch condenses the code by looping an array of
errors.

Also, a formatting error in one_bit_ecc_errors[] and
multi_bit_ecc_errors[] is fixed.

Signed-off-by: Shiju Jose 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |   1 +
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 236 ++---
 2 files changed, 100 insertions(+), 137 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index ea4b5d6..d2d384b 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -96,6 +96,7 @@ struct hisi_sas_hw_error {
int shift;
const char *msg;
int reg;
+   const struct hisi_sas_hw_error *sub;
 };
 
 struct hisi_sas_phy {
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 50a0fc8..ee34f2e 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -406,80 +406,70 @@ struct hisi_sas_err_record_v2 {
.irq_msk = BIT(SAS_ECC_INTR_DQE_ECC_1B_OFF),
.msk = HGC_DQE_ECC_1B_ADDR_MSK,
.shift = HGC_DQE_ECC_1B_ADDR_OFF,
-   .msg = "hgc_dqe_acc1b_intr found: \
-   Ram address is 0x%08X\n",
+   .msg = "hgc_dqe_acc1b_intr found: Ram address is 0x%08X\n",
.reg = HGC_DQE_ECC_ADDR,
},
{
.irq_msk = BIT(SAS_ECC_INTR_IOST_ECC_1B_OFF),
.msk = HGC_IOST_ECC_1B_ADDR_MSK,
.shift = HGC_IOST_ECC_1B_ADDR_OFF,
-   .msg = "hgc_iost_acc1b_intr found: \
-   Ram address is 0x%08X\n",
+   .msg = "hgc_iost_acc1b_intr found: Ram address is 0x%08X\n",
.reg = HGC_IOST_ECC_ADDR,
},
{
.irq_msk = BIT(SAS_ECC_INTR_ITCT_ECC_1B_OFF),
.msk = HGC_ITCT_ECC_1B_ADDR_MSK,
.shift = HGC_ITCT_ECC_1B_ADDR_OFF,
-   .msg = "hgc_itct_acc1b_intr found: \
-   Ram address is 0x%08X\n",
+   .msg = "hgc_itct_acc1b_intr found: am address is 0x%08X\n",
.reg = HGC_ITCT_ECC_ADDR,
},
{
.irq_msk = BIT(SAS_ECC_INTR_IOSTLIST_ECC_1B_OFF),
.msk = HGC_LM_DFX_STATUS2_IOSTLIST_MSK,
.shift = HGC_LM_DFX_STATUS2_IOSTLIST_OFF,
-   .msg = "hgc_iostl_acc1b_intr found:  \
-   memory address is 0x%08X\n",
+   .msg = "hgc_iostl_acc1b_intr found: memory address is 0x%08X\n",
.reg = HGC_LM_DFX_STATUS2,
},
{
.irq_msk = BIT(SAS_ECC_INTR_ITCTLIST_ECC_1B_OFF),
.msk = HGC_LM_DFX_STATUS2_ITCTLIST_MSK,
.shift = HGC_LM_DFX_STATUS2_ITCTLIST_OFF,
-   .msg = "hgc_itctl_acc1b_intr found: \
-   memory address is 0x%08X\n",
+   .msg = "hgc_itctl_acc1b_intr found: memory address is 0x%08X\n",
.reg = HGC_LM_DFX_STATUS2,
},
{
.irq_msk = BIT(SAS_ECC_INTR_CQE_ECC_1B_OFF),
.msk = HGC_CQE_ECC_1B_ADDR_MSK,
.shift = HGC_CQE_ECC_1B_ADDR_OFF,
-   .msg = "hgc_cqe_acc1b_intr found: \
-   Ram address is 0x%08X\n",
+   .msg = "hgc_cqe_acc1b_intr found: Ram address is 0x%08X\n",
.reg = HGC_CQE_ECC_ADDR,
},
{
.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM0_ECC_1B_OFF),
.msk = HGC_RXM_DFX_STATUS14_MEM0_MSK,
.shift = HGC_RXM_DFX_STATUS14_MEM0_OFF,
-   .msg = "rxm_mem0_acc1b_intr found: \
-   memory address is 0x%08X\n",
+   .msg = "rxm_mem0_acc1b_intr found: memory address is 0x%08X\n",
.reg = HGC_RXM_DFX_STATUS14,
},
{
.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM1_ECC_1B_OFF),
.msk = HGC_RXM_DFX_STATUS14_MEM1_MSK,
.shift = HGC_RXM_DFX_STATUS14_MEM1_OFF,
-   .msg = "rxm_mem1_acc1b_intr found: \
-   memory address is 0x%08X\n",
+   .msg = "rxm_mem1_acc1b_intr found: memory address is 0x%08X\n",
.reg = HGC_RXM_DFX_STATUS14,
},
{
.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM2_ECC_1B_OFF),
.msk = HGC_RXM_DFX_STATUS14_MEM2_MSK,
.shift = HGC_RXM_DFX_STATUS14_MEM2_OFF,
-   .msg = "rxm_mem2_acc1b_intr found: \
-   memory address is 0x%08X\n",
+   .msg = "rxm_mem2_acc1b_intr found: memory address is 0x%08X\n",
.reg = HGC_RXM_DFX_STATUS14,
},
 

[PATCH 07/19] scsi: hisi_sas: fix NULL check in SMP abort task path

2017-10-24 Thread John Garry
From: Xiaofei Tan 

This patch adds a NULL check of task->lldd_task before
freeing the slot in SMP path.

This is to guard against the scenario of the slot being
freed during the from the preceding internal abort.

Signed-off-by: Xiaofei Tan 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 88d90dc..2a209e1 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1161,7 +1161,7 @@ static int hisi_sas_abort_task(struct sas_task *task)
 
rc = hisi_sas_internal_task_abort(hisi_hba, device,
 HISI_SAS_INT_ABT_CMD, tag);
-   if (rc == TMF_RESP_FUNC_FAILED) {
+   if (rc == TMF_RESP_FUNC_FAILED && task->lldd_task) {
spin_lock_irqsave(_hba->lock, flags);
hisi_sas_do_release_task(hisi_hba, task, slot);
spin_unlock_irqrestore(_hba->lock, flags);
-- 
1.9.1



[PATCH 02/19] scsi: hisi_sas: fix internal abort slot timeout bug

2017-10-24 Thread John Garry
From: Xiang Chen 

When an internal abort times out in
hisi_sas_internal_task_abort(), goto the exit label in
and not go through the other task status checks.

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 9e29902..0eb9174 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1469,6 +1469,7 @@ static int hisi_sas_query_task(struct sas_task *task)
if (slot)
slot->task = NULL;
dev_err(dev, "internal task abort: timeout.\n");
+   goto exit;
}
}
 
-- 
1.9.1



[PATCH 00/19] hisi_sas: misc fixes, improvements, and new features

2017-10-24 Thread John Garry
This patchset contains many misc fixes, improvements,
and a few new features.

Here is a list of the significant changes:
- more fixes for hisi_hba.locking
- v3 hw DFX feature
- random error handling bugfixes
- reporting v2 hw errors to userspace

Shiju Jose (3):
  scsi: hisi_sas: use array for v2 hw AXI errors
  scsi: hisi_sas: report ECC errors in v2 hw to userspace
  scsi: hisi_sas: report v2 hw AXI errors to userspace

Xiang Chen (6):
  scsi: hisi_sas: delete get_ncq_tag_v3_hw()
  scsi: hisi_sas: fix internal abort slot timeout bug
  scsi: hisi_sas: grab hisi_hba.lock when processing slots
  scsi: hisi_sas: fix SATA breakpoint memory size
  scsi: hisi_sas: us start_phy in PHY_FUNC_LINK_RESET
  scsi: hisi_sas: fix a bug when free device for v3 hw

Xiaofei Tan (10):
  scsi: hisi_sas: use spin_lock_irqsave() for hisi_hba.lock
  scsi: hisi_sas: fix NULL check in SMP abort task path
  scsi: hisi_sas: fix the risk of freeing slot twice
  scsi: hisi_sas: check PHY state in get_wideport_bitmap_v3_hw()
  scsi: hisi_sas: init connect cfg register for v3 hw
  scsi: hisi_sas: add v3 hw DFX feature
  scsi: hisi_sas: add hisi_hba.rst_work init for v3 hw
  scsi: hisi_sas: complete all tasklets prior to host reset
  scsi: hisi_sas: add v3 hw support for AXI fatal error
  scsi: hisi_sas: add v3 hw port AXI error handling

 drivers/scsi/hisi_sas/hisi_sas.h   |  22 +-
 drivers/scsi/hisi_sas/hisi_sas_main.c  |  44 +++-
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |   2 +-
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 390 +
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 257 ++
 5 files changed, 510 insertions(+), 205 deletions(-)

-- 
1.9.1



Re: [PATCH V9 1/4] dma-mapping: Rework dma_get_cache_alignment()

2017-10-24 Thread Marek Szyprowski

Hi Huacai,

On 2017-10-23 09:12, Huacai Chen wrote:

Make dma_get_cache_alignment() to accept a 'dev' argument. As a result,
it can return different alignments due to different devices' I/O cache
coherency.

Currently, ARM/ARM64 and MIPS support coherent & noncoherent devices
co-exist. This may be extended in the future, so add a new function
pointer (i.e, get_cache_alignment) in 'struct dma_map_ops' as a generic
solution.

Cc: sta...@vger.kernel.org


I don't think this change should go to stable.


Cc: Michael S. Tsirkin 
Cc: Pawel Osciak 
Cc: Marek Szyprowski 
Cc: Kyungmin Park 
Cc: Michael Chan 
Cc: Benjamin Herrenschmidt 
Cc: Ivan Mikhaylov 
Cc: Tariq Toukan 
Cc: Andy Gross 
Cc: Mark A. Greer 
Cc: Robert Baldyga 
Cc: Marek Szyprowski 
Signed-off-by: Huacai Chen 
---
  drivers/infiniband/hw/mthca/mthca_main.c   |   2 +-
  drivers/media/v4l2-core/videobuf2-dma-contig.c |   2 +-
  drivers/net/ethernet/broadcom/b44.c|   8 +-
  drivers/net/ethernet/ibm/emac/core.c   |  32 +++--
  drivers/net/ethernet/ibm/emac/core.h   |  14 +-
  drivers/net/ethernet/mellanox/mlx4/main.c  |   2 +-
  drivers/spi/spi-qup.c  |   4 +-
  drivers/tty/serial/mpsc.c  | 179 +
  drivers/tty/serial/samsung.c   |  14 +-
  include/linux/dma-mapping.h|  17 ++-


For videobuf2-dma-contig, serial/samsung and dma-mapping.h:

Acked-by: Marek Szyprowski 



  10 files changed, 150 insertions(+), 124 deletions(-)

diff --git a/drivers/infiniband/hw/mthca/mthca_main.c 
b/drivers/infiniband/hw/mthca/mthca_main.c
index e36a9bc..078fe8d 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -416,7 +416,7 @@ static int mthca_init_icm(struct mthca_dev *mdev,
  
  	/* CPU writes to non-reserved MTTs, while HCA might DMA to reserved mtts */

mdev->limits.reserved_mtts = ALIGN(mdev->limits.reserved_mtts * 
mdev->limits.mtt_seg_size,
-  dma_get_cache_alignment()) / 
mdev->limits.mtt_seg_size;
+  
dma_get_cache_alignment(>pdev->dev)) / mdev->limits.mtt_seg_size;
  
  	mdev->mr_table.mtt_table = mthca_alloc_icm_table(mdev, init_hca->mtt_base,

 
mdev->limits.mtt_seg_size,
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 9f389f3..1f6a9b7 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -484,7 +484,7 @@ static void *vb2_dc_get_userptr(struct device *dev, 
unsigned long vaddr,
int ret = 0;
struct sg_table *sgt;
unsigned long contig_size;
-   unsigned long dma_align = dma_get_cache_alignment();
+   unsigned long dma_align = dma_get_cache_alignment(dev);
  
  	/* Only cache aligned DMA transfers are reliable */

if (!IS_ALIGNED(vaddr | size, dma_align)) {
diff --git a/drivers/net/ethernet/broadcom/b44.c 
b/drivers/net/ethernet/broadcom/b44.c
index a1125d1..2f6ffe5 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -2344,6 +2344,10 @@ static int b44_init_one(struct ssb_device *sdev,
struct net_device *dev;
struct b44 *bp;
int err;
+   unsigned int dma_desc_align_size = 
dma_get_cache_alignment(sdev->dma_dev);
+
+   /* Setup paramaters for syncing RX/TX DMA descriptors */
+   dma_desc_sync_size = max_t(unsigned int, dma_desc_align_size, 
sizeof(struct dma_desc));
  
  	instance++;
  
@@ -2587,12 +2591,8 @@ static inline void b44_pci_exit(void)
  
  static int __init b44_init(void)

  {
-   unsigned int dma_desc_align_size = dma_get_cache_alignment();
int err;
  
-	/* Setup paramaters for syncing RX/TX DMA descriptors */

-   dma_desc_sync_size = max_t(unsigned int, dma_desc_align_size, 
sizeof(struct dma_desc));
-
err = b44_pci_init();
if (err)
return err;
diff --git a/drivers/net/ethernet/ibm/emac/core.c 
b/drivers/net/ethernet/ibm/emac/core.c
index 7feff24..8dcebb2 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -1030,8 +1030,9 @@ static int emac_set_mac_address(struct net_device *ndev, 
void *sa)
  
  static int emac_resize_rx_ring(struct emac_instance *dev, int new_mtu)

  {
-   int rx_sync_size = emac_rx_sync_size(new_mtu);
-   int rx_skb_size = emac_rx_skb_size(new_mtu);
+   struct device *dma_dev = >ofdev->dev;
+   int rx_skb_size = 

答复: [PATCH v5 2/5] dt-bindings: scsi: ufs: add document for hisi-ufs

2017-10-24 Thread liwei (CM)
Hi, Arnd
Sorry to bother you, what's your opinion about my explanation and revision 
method?
I am looking forward to your reply, thanks!


-邮件原件-
发件人: liwei (CM) 
发送时间: 2017年10月21日 17:59
收件人: 'Arnd Bergmann'
抄送: Rob Herring; Mark Rutland; xuwei (O); Catalin Marinas; Will Deacon; Vinayak 
Holikatti; James E.J. Bottomley; Martin K. Petersen; Kevin Hilman; Gregory 
CLEMENT; Thomas Petazzoni; Masahiro Yamada; Riku Voipio; Thierry Reding; 
Krzysztof Kozlowski; Eric Anholt; DTML; Linux Kernel Mailing List; Linux ARM; 
linux-scsi; Guodong Xu; Fengbaopeng (kevin, Kirin Solution Dept); lihuan (Z); 
wangyupeng (A)
主题: 答复: [PATCH v5 2/5] dt-bindings: scsi: ufs: add document for hisi-ufs

Hi, Bergmann
Sorry late for the reply,and thank you very much for your patience.
My reply is as follows. I look forward to your further reply.


-邮件原件-
发件人: arndbergm...@gmail.com [mailto:arndbergm...@gmail.com] 代表 Arnd Bergmann
发送时间: 2017年10月20日 17:16
收件人: liwei (CM)
抄送: Rob Herring; Mark Rutland; xuwei (O); Catalin Marinas; Will Deacon; Vinayak 
Holikatti; James E.J. Bottomley; Martin K. Petersen; Kevin Hilman; Gregory 
CLEMENT; Thomas Petazzoni; Masahiro Yamada; Riku Voipio; Thierry Reding; 
Krzysztof Kozlowski; Eric Anholt; DTML; Linux Kernel Mailing List; Linux ARM; 
linux-scsi; Guodong Xu; Fengbaopeng (kevin, Kirin Solution Dept); lihuan (Z); 
wangyupeng (A)
主题: Re: [PATCH v5 2/5] dt-bindings: scsi: ufs: add document for hisi-ufs

On Fri, Oct 20, 2017 at 10:52 AM, Li Wei  wrote:
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/ufs/ufs-hisi.txt
> @@ -0,0 +1,46 @@
> +* Hisilicon Universal Flash Storage (UFS) Host Controller
> +
> +UFS nodes are defined to describe on-chip UFS hardware macro.
> +Each UFS Host Controller should have its own node.
> +
> +Required properties:
> +- compatible: compatible list, contains one of the following -
> +   "hisilicon,hi3660-ufs" for hisi ufs host controller
> +present on Hi3660 chipset.
> +- reg   : should contain UFS register address space & UFS SYS 
> CTRL register address,
> +- interrupt-parent  : interrupt device
> +- interrupts: interrupt number
> +- clocks   : List of phandle and clock specifier pairs
> +- clock-names   : List of clock input name strings sorted in the same
> + order as the clocks property. "clk_ref", "clk_phy" is 
> optional
> +- resets: reset node register, one reset the clk and the other 
> reset the controller
> +- reset-names   : describe reset node register

I think I've asked about this before, but I think this should be done more 
consistently with the other UFS bindings.

In particular, I wonder if what you describe as the "UFS SYS CTRL"
area corresponds to what Qualcomm have described as their PHY implementation. 
It certainly seems to driver some of the properties that would normally be 
associated with a PHY.

Liwei:Yes, a part of "UFS SYS CTRL" is associated with a PHY, but from our chip 
colleague that we assure "UFS SYS CTRL" is associated with clk/reset/power 
on/power off and so on. 
In fact, in addition to the controller itself, the controller related periphery 
are all in this area. So it's not appropriate to put this into a separate phy 
node.

For the "clock-names" property, you specify "clk_ref", which I assume is the 
same as what Qualcomm call "ref_clk". I'd suggest you use the existing name and 
add that as the default name in the ufshcd-pltfrm.txt binding document.

Liwei:" ref_clk " is already in the ufshcd-pltfrm.txt binding document, and 
parse in ufshcd.c, so we will replace "clk_ref" with "ref_clk". I will fix it 
in patch v6;

The "clk_phy" property appears to be related to the PHY, so it might be better 
to have a separate phy node with either just the clk, or with the clk plus the 
"UFS SYS CTRL" register area, whichever matches your hardware better, and then 
use teh "phys/phy-names" property to refer to that.

Liwei: OK, I will add a separate phy node and fix it in patch v6;

The reset handling you describe here (both resets and reset-gpios) appears to 
be completely generic, so I'd suggest adding those to ufshcd-pltfrm.txt instead 
of your own binding, to ensure that future drivers use the same identifiers.

Liwei: From our soc chip colleague, reset include "rst", "assert" is not 
generic and related with our soc implementation, you can see 
ufs_hisi_soc_init() in drivers/scsi/ufs/ufs-hisi.c, the position of rst and 
assert is very special, it's hard to put it in a generic process; reset-gpios 
is used to solve a defect of the SOC chip reset function and it is not generic 
, but our chip has been updated, so this is no longer needed, and I will remove 
it in the patch v6;

Thanks!

  Arnd