linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features
@ 2017-10-24 15:51 John Garry
  2017-10-24 15:51 ` [PATCH 01/19] scsi: hisi_sas: delete get_ncq_tag_v3_hw() John Garry
                   ` (19 more replies)
  0 siblings, 20 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, 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

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

* [PATCH 01/19] scsi: hisi_sas: delete get_ncq_tag_v3_hw()
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
@ 2017-10-24 15:51 ` John Garry
  2017-10-24 15:51 ` [PATCH 02/19] scsi: hisi_sas: fix internal abort slot timeout bug John Garry
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, Xiang Chen, John Garry

From: Xiang Chen <chenxiang66@hisilicon.com>

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 <chenxiang66@hisilicon.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 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, &hdr_tag)) {
+	if (task->ata_task.use_ncq && hisi_sas_get_ncq_tag(task, &hdr_tag)) {
 		task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
 		dw2 |= hdr_tag << CMD_HDR_NCQ_TAG_OFF;
 	}
-- 
1.9.1

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

* [PATCH 02/19] scsi: hisi_sas: fix internal abort slot timeout bug
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
  2017-10-24 15:51 ` [PATCH 01/19] scsi: hisi_sas: delete get_ncq_tag_v3_hw() John Garry
@ 2017-10-24 15:51 ` John Garry
  2017-10-24 15:51 ` [PATCH 03/19] scsi: hisi_sas: use spin_lock_irqsave() for hisi_hba.lock John Garry
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, Xiang Chen, John Garry

From: Xiang Chen <chenxiang66@hisilicon.com>

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 <chenxiang66@hisilicon.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 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

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

* [PATCH 03/19] scsi: hisi_sas: use spin_lock_irqsave() for hisi_hba.lock
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
  2017-10-24 15:51 ` [PATCH 01/19] scsi: hisi_sas: delete get_ncq_tag_v3_hw() John Garry
  2017-10-24 15:51 ` [PATCH 02/19] scsi: hisi_sas: fix internal abort slot timeout bug John Garry
@ 2017-10-24 15:51 ` John Garry
  2017-10-24 15:51 ` [PATCH 04/19] scsi: hisi_sas: grab hisi_hba.lock when processing slots John Garry
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, Xiaofei Tan,
	John Garry

From: Xiaofei Tan <tanxiaofei@huawei.com>

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 <tanxiaofei@huawei.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 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(&hisi_hba->lock);
+	spin_lock_irqsave(&hisi_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(&hisi_hba->lock);
+	spin_unlock_irqrestore(&hisi_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(&hisi_hba->lock);
+	spin_lock_irqsave(&hisi_hba->lock, flags);
 
 	if (sata_dev)
 		if (!sata_index_alloc_v2_hw(hisi_hba, &sata_idx))
@@ -874,7 +875,7 @@ hisi_sas_device *alloc_dev_quirk_v2_hw(struct domain_device *device)
 	}
 
 out:
-	spin_unlock(&hisi_hba->lock);
+	spin_unlock_irqrestore(&hisi_hba->lock, flags);
 
 	return sas_dev;
 }
-- 
1.9.1

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

* [PATCH 04/19] scsi: hisi_sas: grab hisi_hba.lock when processing slots
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
                   ` (2 preceding siblings ...)
  2017-10-24 15:51 ` [PATCH 03/19] scsi: hisi_sas: use spin_lock_irqsave() for hisi_hba.lock John Garry
@ 2017-10-24 15:51 ` John Garry
  2017-10-24 15:51 ` [PATCH 05/19] scsi: hisi_sas: fix SATA breakpoint memory size John Garry
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, Xiang Chen, John Garry

From: Xiang Chen <chenxiang66@hisilicon.com>

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 <chenxiang66@hisilicon.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 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(&hisi_hba->lock, flags);
 	list_add_tail(&slot->entry, &sas_dev->list);
+	spin_unlock_irqrestore(&hisi_hba->lock, flags);
 	spin_lock_irqsave(&task->task_state_lock, flags);
 	task->task_state_flags |= SAS_TASK_AT_INITIATOR;
 	spin_unlock_irqrestore(&task->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(&hisi_hba->lock, flags);
 	list_add_tail(&slot->entry, &sas_dev->list);
+	spin_unlock_irqrestore(&hisi_hba->lock, flags);
 	spin_lock_irqsave(&task->task_state_lock, flags);
 	task->task_state_flags |= SAS_TASK_AT_INITIATOR;
 	spin_unlock_irqrestore(&task->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(&hisi_hba->lock, flags);
 		hisi_sas_slot_task_free(hisi_hba, task, slot);
+		spin_unlock_irqrestore(&hisi_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(&hisi_hba->lock, flags);
 		hisi_sas_slot_task_free(hisi_hba, task, slot);
+		spin_unlock_irqrestore(&hisi_hba->lock, flags);
 		return -1;
 	}
 
-- 
1.9.1

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

* [PATCH 05/19] scsi: hisi_sas: fix SATA breakpoint memory size
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
                   ` (3 preceding siblings ...)
  2017-10-24 15:51 ` [PATCH 04/19] scsi: hisi_sas: grab hisi_hba.lock when processing slots John Garry
@ 2017-10-24 15:51 ` John Garry
  2017-10-24 15:51 ` [PATCH 06/19] scsi: hisi_sas: us start_phy in PHY_FUNC_LINK_RESET John Garry
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, Xiang Chen, John Garry

From: Xiang Chen <chenxiang66@hisilicon.com>

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 <chenxiang66@hisilicon.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 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_QUEUES	32
 #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_BIT	1
@@ -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,
 				&hisi_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_HW			4096 /* max the hw can support */
 #define DEFAULT_ITCT_HW		2048 /* 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

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

* [PATCH 06/19] scsi: hisi_sas: us start_phy in PHY_FUNC_LINK_RESET
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
                   ` (4 preceding siblings ...)
  2017-10-24 15:51 ` [PATCH 05/19] scsi: hisi_sas: fix SATA breakpoint memory size John Garry
@ 2017-10-24 15:51 ` John Garry
  2017-10-24 15:51 ` [PATCH 07/19] scsi: hisi_sas: fix NULL check in SMP abort task path John Garry
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, Xiang Chen, John Garry

From: Xiang Chen <chenxiang66@hisilicon.com>

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 <chenxiang66@hisilicon.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 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

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

* [PATCH 07/19] scsi: hisi_sas: fix NULL check in SMP abort task path
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
                   ` (5 preceding siblings ...)
  2017-10-24 15:51 ` [PATCH 06/19] scsi: hisi_sas: us start_phy in PHY_FUNC_LINK_RESET John Garry
@ 2017-10-24 15:51 ` John Garry
  2017-10-24 15:51 ` [PATCH 08/19] scsi: hisi_sas: fix the risk of freeing slot twice John Garry
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, Xiaofei Tan,
	John Garry

From: Xiaofei Tan <tanxiaofei@huawei.com>

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 <tanxiaofei@huawei.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 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(&hisi_hba->lock, flags);
 			hisi_sas_do_release_task(hisi_hba, task, slot);
 			spin_unlock_irqrestore(&hisi_hba->lock, flags);
-- 
1.9.1

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

* [PATCH 08/19] scsi: hisi_sas: fix the risk of freeing slot twice
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
                   ` (6 preceding siblings ...)
  2017-10-24 15:51 ` [PATCH 07/19] scsi: hisi_sas: fix NULL check in SMP abort task path John Garry
@ 2017-10-24 15:51 ` John Garry
  2017-10-24 15:51 ` [PATCH 09/19] scsi: hisi_sas: use array for v2 hw AXI errors John Garry
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, Xiaofei Tan,
	John Garry

From: Xiaofei Tan <tanxiaofei@huawei.com>

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 <tanxiaofei@huawei.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 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(&sas_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(&slot->entry);
+	slot->buf = NULL;
 	slot->task = NULL;
 	slot->port = NULL;
 	hisi_sas_slot_index_free(hisi_hba, slot->idx);
-- 
1.9.1

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

* [PATCH 09/19] scsi: hisi_sas: use array for v2 hw AXI errors
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
                   ` (7 preceding siblings ...)
  2017-10-24 15:51 ` [PATCH 08/19] scsi: hisi_sas: fix the risk of freeing slot twice John Garry
@ 2017-10-24 15:51 ` John Garry
  2017-10-24 15:51 ` [PATCH 10/19] scsi: hisi_sas: report ECC errors in v2 hw to userspace John Garry
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, Shiju Jose, John Garry

From: Shiju Jose <shiju.jose@huawei.com>

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 <shiju.jose@huawei.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 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,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM3_ECC_1B_OFF),
 		.msk = HGC_RXM_DFX_STATUS15_MEM3_MSK,
 		.shift = HGC_RXM_DFX_STATUS15_MEM3_OFF,
-		.msg = "rxm_mem3_acc1b_intr found: \
-				memory address is 0x%08X\n",
+		.msg = "rxm_mem3_acc1b_intr found: memory address is 0x%08X\n",
 		.reg = HGC_RXM_DFX_STATUS15,
 	},
 };
@@ -489,80 +479,70 @@ struct hisi_sas_err_record_v2 {
 		.irq_msk = BIT(SAS_ECC_INTR_DQE_ECC_MB_OFF),
 		.msk = HGC_DQE_ECC_MB_ADDR_MSK,
 		.shift = HGC_DQE_ECC_MB_ADDR_OFF,
-		.msg = "hgc_dqe_accbad_intr (0x%x) found: \
-				Ram address is 0x%08X\n",
+		.msg = "hgc_dqe_accbad_intr (0x%x) found: Ram address is 0x%08X\n",
 		.reg = HGC_DQE_ECC_ADDR,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_IOST_ECC_MB_OFF),
 		.msk = HGC_IOST_ECC_MB_ADDR_MSK,
 		.shift = HGC_IOST_ECC_MB_ADDR_OFF,
-		.msg = "hgc_iost_accbad_intr (0x%x) found: \
-				Ram address is 0x%08X\n",
+		.msg = "hgc_iost_accbad_intr (0x%x) found: Ram address is 0x%08X\n",
 		.reg = HGC_IOST_ECC_ADDR,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_ITCT_ECC_MB_OFF),
 		.msk = HGC_ITCT_ECC_MB_ADDR_MSK,
 		.shift = HGC_ITCT_ECC_MB_ADDR_OFF,
-		.msg = "hgc_itct_accbad_intr (0x%x) found: \
-				Ram address is 0x%08X\n",
+		.msg = "hgc_itct_accbad_intr (0x%x) found: Ram address is 0x%08X\n",
 		.reg = HGC_ITCT_ECC_ADDR,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_IOSTLIST_ECC_MB_OFF),
 		.msk = HGC_LM_DFX_STATUS2_IOSTLIST_MSK,
 		.shift = HGC_LM_DFX_STATUS2_IOSTLIST_OFF,
-		.msg = "hgc_iostl_accbad_intr (0x%x) found: \
-				memory address is 0x%08X\n",
+		.msg = "hgc_iostl_accbad_intr (0x%x) found: memory address is 0x%08X\n",
 		.reg = HGC_LM_DFX_STATUS2,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_ITCTLIST_ECC_MB_OFF),
 		.msk = HGC_LM_DFX_STATUS2_ITCTLIST_MSK,
 		.shift = HGC_LM_DFX_STATUS2_ITCTLIST_OFF,
-		.msg = "hgc_itctl_accbad_intr (0x%x) found: \
-				memory address is 0x%08X\n",
+		.msg = "hgc_itctl_accbad_intr (0x%x) found: memory address is 0x%08X\n",
 		.reg = HGC_LM_DFX_STATUS2,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_CQE_ECC_MB_OFF),
 		.msk = HGC_CQE_ECC_MB_ADDR_MSK,
 		.shift = HGC_CQE_ECC_MB_ADDR_OFF,
-		.msg = "hgc_cqe_accbad_intr (0x%x) found: \
-				Ram address is 0x%08X\n",
+		.msg = "hgc_cqe_accbad_intr (0x%x) found: Ram address is 0x%08X\n",
 		.reg = HGC_CQE_ECC_ADDR,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM0_ECC_MB_OFF),
 		.msk = HGC_RXM_DFX_STATUS14_MEM0_MSK,
 		.shift = HGC_RXM_DFX_STATUS14_MEM0_OFF,
-		.msg = "rxm_mem0_accbad_intr (0x%x) found: \
-			memory address is 0x%08X\n",
+		.msg = "rxm_mem0_accbad_intr (0x%x) found: memory address is 0x%08X\n",
 		.reg = HGC_RXM_DFX_STATUS14,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM1_ECC_MB_OFF),
 		.msk = HGC_RXM_DFX_STATUS14_MEM1_MSK,
 		.shift = HGC_RXM_DFX_STATUS14_MEM1_OFF,
-		.msg = "rxm_mem1_accbad_intr (0x%x) found: \
-			memory address is 0x%08X\n",
+		.msg = "rxm_mem1_accbad_intr (0x%x) found: memory address is 0x%08X\n",
 		.reg = HGC_RXM_DFX_STATUS14,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM2_ECC_MB_OFF),
 		.msk = HGC_RXM_DFX_STATUS14_MEM2_MSK,
 		.shift = HGC_RXM_DFX_STATUS14_MEM2_OFF,
-		.msg = "rxm_mem2_accbad_intr (0x%x) found: \
-				memory address is 0x%08X\n",
+		.msg = "rxm_mem2_accbad_intr (0x%x) found: memory address is 0x%08X\n",
 		.reg = HGC_RXM_DFX_STATUS14,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM3_ECC_MB_OFF),
 		.msk = HGC_RXM_DFX_STATUS15_MEM3_MSK,
 		.shift = HGC_RXM_DFX_STATUS15_MEM3_OFF,
-		.msg = "rxm_mem3_accbad_intr (0x%x) found: \
-				memory address is 0x%08X\n",
+		.msg = "rxm_mem3_accbad_intr (0x%x) found: memory address is 0x%08X\n",
 		.reg = HGC_RXM_DFX_STATUS15,
 	},
 };
@@ -2956,25 +2936,58 @@ static irqreturn_t fatal_ecc_int_v2_hw(int irq_no, void *p)
 	return IRQ_HANDLED;
 }
 
-#define AXI_ERR_NR	8
-static const char axi_err_info[AXI_ERR_NR][32] = {
-	"IOST_AXI_W_ERR",
-	"IOST_AXI_R_ERR",
-	"ITCT_AXI_W_ERR",
-	"ITCT_AXI_R_ERR",
-	"SATA_AXI_W_ERR",
-	"SATA_AXI_R_ERR",
-	"DQE_AXI_R_ERR",
-	"CQE_AXI_W_ERR"
+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" },
+	{},
 };
 
-#define FIFO_ERR_NR	5
-static const char fifo_err_info[FIFO_ERR_NR][32] = {
-	"CQE_WINFO_FIFO",
-	"CQE_MSG_FIFIO",
-	"GETDQE_FIFO",
-	"CMDP_FIFO",
-	"AWTCTRL_FIFO"
+static const struct hisi_sas_hw_error fatal_axi_errors[] = {
+	{
+		.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_v2_hw(int irq_no, void *p)
@@ -2982,98 +2995,47 @@ static irqreturn_t fatal_axi_int_v2_hw(int irq_no, void *p)
 	struct hisi_hba *hisi_hba = p;
 	u32 irq_value, irq_msk, err_value;
 	struct device *dev = hisi_hba->dev;
+	const struct hisi_sas_hw_error *axi_error;
+	int i;
 
 	irq_msk = hisi_sas_read32(hisi_hba, ENT_INT_SRC_MSK3);
 	hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, irq_msk | 0xfffffffe);
 
 	irq_value = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
-	if (irq_value) {
-		if (irq_value & BIT(ENT_INT_SRC3_WP_DEPTH_OFF)) {
-			hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
-					1 << ENT_INT_SRC3_WP_DEPTH_OFF);
-			dev_warn(dev, "write pointer and depth error (0x%x) \
-			       found!\n",
-			       irq_value);
-			queue_work(hisi_hba->wq, &hisi_hba->rst_work);
-		}
 
-		if (irq_value & BIT(ENT_INT_SRC3_IPTT_SLOT_NOMATCH_OFF)) {
-			hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
-					 1 <<
-					 ENT_INT_SRC3_IPTT_SLOT_NOMATCH_OFF);
-			dev_warn(dev, "iptt no match slot error (0x%x) found!\n",
-			      irq_value);
-			queue_work(hisi_hba->wq, &hisi_hba->rst_work);
-		}
-
-		if (irq_value & BIT(ENT_INT_SRC3_RP_DEPTH_OFF)) {
-			dev_warn(dev, "read pointer and depth error (0x%x) \
-			       found!\n",
-			       irq_value);
-			queue_work(hisi_hba->wq, &hisi_hba->rst_work);
-		}
-
-		if (irq_value & BIT(ENT_INT_SRC3_AXI_OFF)) {
-			int i;
-
-			hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
-					1 << ENT_INT_SRC3_AXI_OFF);
-			err_value = hisi_sas_read32(hisi_hba,
-						    HGC_AXI_FIFO_ERR_INFO);
-
-			for (i = 0; i < AXI_ERR_NR; i++) {
-				if (err_value & BIT(i)) {
-					dev_warn(dev, "%s (0x%x) found!\n",
-					      axi_err_info[i], irq_value);
-					queue_work(hisi_hba->wq, &hisi_hba->rst_work);
-				}
-			}
-		}
-
-		if (irq_value & BIT(ENT_INT_SRC3_FIFO_OFF)) {
-			int i;
-
-			hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
-					1 << ENT_INT_SRC3_FIFO_OFF);
-			err_value = hisi_sas_read32(hisi_hba,
-						    HGC_AXI_FIFO_ERR_INFO);
+	for (i = 0; i < ARRAY_SIZE(fatal_axi_errors); i++) {
+		axi_error = &fatal_axi_errors[i];
+		if (!(irq_value & axi_error->irq_msk))
+			continue;
 
-			for (i = 0; i < FIFO_ERR_NR; i++) {
-				if (err_value & BIT(AXI_ERR_NR + i)) {
-					dev_warn(dev, "%s (0x%x) found!\n",
-					      fifo_err_info[i], irq_value);
-					queue_work(hisi_hba->wq, &hisi_hba->rst_work);
-				}
+		hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
+				 1 << axi_error->shift);
+		if (axi_error->sub) {
+			const struct hisi_sas_hw_error *sub = axi_error->sub;
+
+			err_value = hisi_sas_read32(hisi_hba, axi_error->reg);
+			for (; sub->msk || sub->msg; sub++) {
+				if (!(err_value & sub->msk))
+					continue;
+				dev_warn(dev, "%s (0x%x) found!\n",
+					 sub->msg, irq_value);
+				queue_work(hisi_hba->wq, &hisi_hba->rst_work);
 			}
-
-		}
-
-		if (irq_value & BIT(ENT_INT_SRC3_LM_OFF)) {
-			hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
-					1 << ENT_INT_SRC3_LM_OFF);
-			dev_warn(dev, "LM add/fetch list error (0x%x) found!\n",
-			      irq_value);
-			queue_work(hisi_hba->wq, &hisi_hba->rst_work);
-		}
-
-		if (irq_value & BIT(ENT_INT_SRC3_ABT_OFF)) {
-			hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
-					1 << ENT_INT_SRC3_ABT_OFF);
-			dev_warn(dev, "SAS_HGC_ABT fetch LM list error (0x%x) found!\n",
-			      irq_value);
+		} else {
+			dev_warn(dev, "%s (0x%x) found!\n",
+				 axi_error->msg, irq_value);
 			queue_work(hisi_hba->wq, &hisi_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 =
-					&hisi_hba->devices[dev_id];
+	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 = &hisi_hba->devices[dev_id];
 
-			hisi_sas_write32(hisi_hba, ITCT_CLR, 0);
-			dev_dbg(dev, "clear ITCT ok\n");
-			complete(sas_dev->completion);
-		}
+		hisi_sas_write32(hisi_hba, ITCT_CLR, 0);
+		dev_dbg(dev, "clear ITCT ok\n");
+		complete(sas_dev->completion);
 	}
 
 	hisi_sas_write32(hisi_hba, ENT_INT_SRC3, irq_value);
-- 
1.9.1

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

* [PATCH 10/19] scsi: hisi_sas: report ECC errors in v2 hw to userspace
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
                   ` (8 preceding siblings ...)
  2017-10-24 15:51 ` [PATCH 09/19] scsi: hisi_sas: use array for v2 hw AXI errors John Garry
@ 2017-10-24 15:51 ` John Garry
  2017-10-24 15:51 ` [PATCH 11/19] scsi: hisi_sas: report v2 hw AXI errors " John Garry
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, Shiju Jose, John Garry

From: Shiju Jose <shiju.jose@huawei.com>

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
          <idle>-0     [4204528]     0.000007: non_standard_event:   2017-09-06 11:14:49 +0000
 Recoverable
 section type: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 fru text: HISI0162:01 fru id: 00000000-0000-0000-0000-000000000000
 length: 24
 error:
  00000000: 00000007 00000000 0000013c 00000000
  00000010: 00000000 00000001
HISI HIP07: SAS error: [phy addr = 0x0x13c: single-bit ecc: error type = hgc_dqe ecc]

cpu 00:          <idle>-0     [4204552]     0.000007: non_standard_event:   2017-09-06 11:14:49 +0000
 Fatal
 section type: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 fru text: HISI0162:01 fru id: 00000000-0000-0000-0000-000000000000
 length: 24
 error:
  00000000: 00000007 00000000 0000013c 00000000
  00000010: 00000001 00000001
HISI HIP07: SAS error: [phy addr = 0x0x13c: multi-bit ecc: error type = hgc_dqe ecc]

Signed-off-by: Shiju Jose <shiju.jose@huawei.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 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 <acpi/ghes.h>
 #include <linux/acpi.h>
 #include <linux/clk.h>
 #include <linux/dmapool.h>
@@ -22,7 +23,9 @@
 #include <linux/pci.h>
 #include <linux/platform_device.h>
 #include <linux/property.h>
+#include <linux/ras.h>
 #include <linux/regmap.h>
+#include <ras/ras_event.h>
 #include <scsi/sas_ata.h>
 #include <scsi/libsas.h>
 
@@ -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 = HGC_LM_DFX_STATUS2_ITCTLIST_OFF,
 		.msg = "hgc_itctl_acc1b_intr found: memory address is 0x%08X\n",
 		.reg = HGC_LM_DFX_STATUS2,
+		.type = HISI_SAS_ECC_ERR_HGC_ITCTLIST,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_CQE_ECC_1B_OFF),
@@ -443,6 +466,7 @@ struct hisi_sas_err_record_v2 {
 		.shift = HGC_CQE_ECC_1B_ADDR_OFF,
 		.msg = "hgc_cqe_acc1b_intr found: Ram address is 0x%08X\n",
 		.reg = HGC_CQE_ECC_ADDR,
+		.type = HISI_SAS_ECC_ERR_HGC_CQE,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM0_ECC_1B_OFF),
@@ -450,6 +474,7 @@ struct hisi_sas_err_record_v2 {
 		.shift = HGC_RXM_DFX_STATUS14_MEM0_OFF,
 		.msg = "rxm_mem0_acc1b_intr found: memory address is 0x%08X\n",
 		.reg = HGC_RXM_DFX_STATUS14,
+		.type = HISI_SAS_ECC_ERR_HGC_RXM_MEM0,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM1_ECC_1B_OFF),
@@ -457,6 +482,7 @@ struct hisi_sas_err_record_v2 {
 		.shift = HGC_RXM_DFX_STATUS14_MEM1_OFF,
 		.msg = "rxm_mem1_acc1b_intr found: memory address is 0x%08X\n",
 		.reg = HGC_RXM_DFX_STATUS14,
+		.type = HISI_SAS_ECC_ERR_HGC_RXM_MEM1,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM2_ECC_1B_OFF),
@@ -464,6 +490,7 @@ struct hisi_sas_err_record_v2 {
 		.shift = HGC_RXM_DFX_STATUS14_MEM2_OFF,
 		.msg = "rxm_mem2_acc1b_intr found: memory address is 0x%08X\n",
 		.reg = HGC_RXM_DFX_STATUS14,
+		.type = HISI_SAS_ECC_ERR_HGC_RXM_MEM2,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM3_ECC_1B_OFF),
@@ -471,6 +498,7 @@ struct hisi_sas_err_record_v2 {
 		.shift = HGC_RXM_DFX_STATUS15_MEM3_OFF,
 		.msg = "rxm_mem3_acc1b_intr found: memory address is 0x%08X\n",
 		.reg = HGC_RXM_DFX_STATUS15,
+		.type = HISI_SAS_ECC_ERR_HGC_RXM_MEM3,
 	},
 };
 
@@ -481,6 +509,7 @@ struct hisi_sas_err_record_v2 {
 		.shift = HGC_DQE_ECC_MB_ADDR_OFF,
 		.msg = "hgc_dqe_accbad_intr (0x%x) 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_MB_OFF),
@@ -488,6 +517,7 @@ struct hisi_sas_err_record_v2 {
 		.shift = HGC_IOST_ECC_MB_ADDR_OFF,
 		.msg = "hgc_iost_accbad_intr (0x%x) 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_MB_OFF),
@@ -495,6 +525,7 @@ struct hisi_sas_err_record_v2 {
 		.shift = HGC_ITCT_ECC_MB_ADDR_OFF,
 		.msg = "hgc_itct_accbad_intr (0x%x) found: Ram 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_MB_OFF),
@@ -502,6 +533,7 @@ struct hisi_sas_err_record_v2 {
 		.shift = HGC_LM_DFX_STATUS2_IOSTLIST_OFF,
 		.msg = "hgc_iostl_accbad_intr (0x%x) 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_MB_OFF),
@@ -509,6 +541,7 @@ struct hisi_sas_err_record_v2 {
 		.shift = HGC_LM_DFX_STATUS2_ITCTLIST_OFF,
 		.msg = "hgc_itctl_accbad_intr (0x%x) found: memory address is 0x%08X\n",
 		.reg = HGC_LM_DFX_STATUS2,
+		.type = HISI_SAS_ECC_ERR_HGC_ITCTLIST,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_CQE_ECC_MB_OFF),
@@ -516,6 +549,7 @@ struct hisi_sas_err_record_v2 {
 		.shift = HGC_CQE_ECC_MB_ADDR_OFF,
 		.msg = "hgc_cqe_accbad_intr (0x%x) found: Ram address is 0x%08X\n",
 		.reg = HGC_CQE_ECC_ADDR,
+		.type = HISI_SAS_ECC_ERR_HGC_CQE,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM0_ECC_MB_OFF),
@@ -523,6 +557,7 @@ struct hisi_sas_err_record_v2 {
 		.shift = HGC_RXM_DFX_STATUS14_MEM0_OFF,
 		.msg = "rxm_mem0_accbad_intr (0x%x) found: memory address is 0x%08X\n",
 		.reg = HGC_RXM_DFX_STATUS14,
+		.type = HISI_SAS_ECC_ERR_HGC_RXM_MEM0,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM1_ECC_MB_OFF),
@@ -530,6 +565,7 @@ struct hisi_sas_err_record_v2 {
 		.shift = HGC_RXM_DFX_STATUS14_MEM1_OFF,
 		.msg = "rxm_mem1_accbad_intr (0x%x) found: memory address is 0x%08X\n",
 		.reg = HGC_RXM_DFX_STATUS14,
+		.type = HISI_SAS_ECC_ERR_HGC_RXM_MEM1,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM2_ECC_MB_OFF),
@@ -537,6 +573,7 @@ struct hisi_sas_err_record_v2 {
 		.shift = HGC_RXM_DFX_STATUS14_MEM2_OFF,
 		.msg = "rxm_mem2_accbad_intr (0x%x) found: memory address is 0x%08X\n",
 		.reg = HGC_RXM_DFX_STATUS14,
+		.type = HISI_SAS_ECC_ERR_HGC_RXM_MEM2,
 	},
 	{
 		.irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM3_ECC_MB_OFF),
@@ -544,6 +581,7 @@ struct hisi_sas_err_record_v2 {
 		.shift = HGC_RXM_DFX_STATUS15_MEM3_OFF,
 		.msg = "rxm_mem3_accbad_intr (0x%x) found: memory address is 0x%08X\n",
 		.reg = HGC_RXM_DFX_STATUS15,
+		.type = HISI_SAS_ECC_ERR_HGC_RXM_MEM3,
 	},
 };
 
@@ -702,6 +740,15 @@ enum {
 #define DIR_TO_DEVICE 2
 #define DIR_RESERVED 3
 
+/* Vendor specific CPER SEC TYPE for HISI SAS Memory errors */
+#define CPER_SEC_TYPE_HISI_SAS                                           \
+	UUID_LE(0xDAFFD814, 0x6EBA, 0x4D8C, 0x8A, 0x91, 0xBC, 0x9B,     \
+	0xBF, 0x4A, 0xA3, 0x01)
+
+#define HISI_SAS_VALID_PA		BIT(0)
+#define HISI_SAS_VALID_MB_ERR		BIT(1)
+#define HISI_SAS_VALID_ERR_TYPE		BIT(2)
+
 #define ERR_ON_TX_PHASE(err_phase) (err_phase == 0x2 || \
 		err_phase == 0x4 || err_phase == 0x8 ||\
 		err_phase == 0x6 || err_phase == 0xa)
@@ -2882,6 +2929,17 @@ static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p)
 	const struct hisi_sas_hw_error *ecc_error;
 	u32 val;
 	int i;
+	struct hisi_sas_hw_err_info err_data;
+	bool trace_ns_event_enabled = trace_non_standard_event_enabled();
+
+	if (trace_ns_event_enabled) {
+		memset(&err_data, 0, sizeof(err_data));
+		err_data.validation_bits =
+					HISI_SAS_VALID_PA |
+					HISI_SAS_VALID_MB_ERR |
+					HISI_SAS_VALID_ERR_TYPE;
+		err_data.mb_err = HISI_SAS_ERR_SINGLE_BIT_ECC;
+	}
 
 	for (i = 0; i < ARRAY_SIZE(one_bit_ecc_errors); i++) {
 		ecc_error = &one_bit_ecc_errors[i];
@@ -2889,7 +2947,18 @@ static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p)
 			val = hisi_sas_read32(hisi_hba, ecc_error->reg);
 			val &= ecc_error->msk;
 			val >>= ecc_error->shift;
-			dev_warn(dev, ecc_error->msg, val);
+			if (trace_ns_event_enabled) {
+				err_data.physical_addr = val;
+				err_data.type = ecc_error->type;
+				log_non_standard_event(&CPER_SEC_TYPE_HISI_SAS,
+						       &NULL_UUID_LE,
+						       dev_name(dev),
+						       GHES_SEV_RECOVERABLE,
+						       (const u8 *)&err_data,
+						       sizeof(err_data));
+			} else {
+				dev_warn(dev, ecc_error->msg, val);
+			}
 		}
 	}
 }
@@ -2901,6 +2970,17 @@ static void multi_bit_ecc_error_process_v2_hw(struct hisi_hba *hisi_hba,
 	const struct hisi_sas_hw_error *ecc_error;
 	u32 val;
 	int i;
+	struct hisi_sas_hw_err_info err_data;
+	bool trace_ns_event_enabled = trace_non_standard_event_enabled();
+
+	if (trace_ns_event_enabled) {
+		memset(&err_data, 0, sizeof(err_data));
+		err_data.validation_bits =
+					HISI_SAS_VALID_PA |
+					HISI_SAS_VALID_MB_ERR |
+					HISI_SAS_VALID_ERR_TYPE;
+		err_data.mb_err = HISI_SAS_ERR_MULTI_BIT_ECC;
+	}
 
 	for (i = 0; i < ARRAY_SIZE(multi_bit_ecc_errors); i++) {
 		ecc_error = &multi_bit_ecc_errors[i];
@@ -2908,7 +2988,18 @@ static void multi_bit_ecc_error_process_v2_hw(struct hisi_hba *hisi_hba,
 			val = hisi_sas_read32(hisi_hba, ecc_error->reg);
 			val &= ecc_error->msk;
 			val >>= ecc_error->shift;
-			dev_warn(dev, ecc_error->msg, irq_value, val);
+			if (trace_ns_event_enabled) {
+				err_data.physical_addr = val;
+				err_data.type = ecc_error->type;
+				log_non_standard_event(&CPER_SEC_TYPE_HISI_SAS,
+						       &NULL_UUID_LE,
+						       dev_name(dev),
+						       GHES_SEV_PANIC,
+						       (const u8 *)&err_data,
+						       sizeof(err_data));
+			} else {
+				dev_warn(dev, ecc_error->msg, irq_value, val);
+			}
 			queue_work(hisi_hba->wq, &hisi_hba->rst_work);
 		}
 	}
-- 
1.9.1

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

* [PATCH 11/19] scsi: hisi_sas: report v2 hw AXI errors to userspace
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
                   ` (9 preceding siblings ...)
  2017-10-24 15:51 ` [PATCH 10/19] scsi: hisi_sas: report ECC errors in v2 hw to userspace John Garry
@ 2017-10-24 15:51 ` John Garry
  2017-10-24 15:51 ` [PATCH 12/19] scsi: hisi_sas: check PHY state in get_wideport_bitmap_v3_hw() John Garry
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, Shiju Jose, John Garry

From: Shiju Jose <shiju.jose@huawei.com>

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 <shiju.jose@huawei.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 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_TYPE		BIT(2)
+#define HISI_SAS_VALID_AXI_ERR_INFO	BIT(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 | 0xfffffffe);
 
 	irq_value = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
 
+	if (trace_ns_event_enabled)
+		memset(&err_data, 0, sizeof(err_data));
+
 	for (i = 0; i < ARRAY_SIZE(fatal_axi_errors); i++) {
 		axi_error = &fatal_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(
+							&CPER_SEC_TYPE_HISI_SAS,
+							&NULL_UUID_LE,
+							dev_name(dev),
+							GHES_SEV_PANIC,
+							(const u8 *)&err_data,
+							sizeof(err_data));
+				} else
+					dev_warn(dev, "%s (0x%x) found!\n",
+						 sub->msg, irq_value);
 				queue_work(hisi_hba->wq, &hisi_hba->rst_work);
 			}
 		} else {
-			dev_warn(dev, "%s (0x%x) found!\n",
-				 axi_error->msg, irq_value);
+			if (trace_ns_event_enabled) {
+				err_data.validation_bits =
+						HISI_SAS_VALID_ERR_TYPE;
+				err_data.type = axi_error->type;
+				log_non_standard_event(&CPER_SEC_TYPE_HISI_SAS,
+						       &NULL_UUID_LE,
+						       dev_name(dev),
+						       GHES_SEV_PANIC,
+						       (const u8 *)&err_data,
+						       sizeof(err_data));
+			} else
+				dev_warn(dev, "%s (0x%x) found!\n",
+					 axi_error->msg, irq_value);
 			queue_work(hisi_hba->wq, &hisi_hba->rst_work);
 		}
 	}
-- 
1.9.1

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

* [PATCH 12/19] scsi: hisi_sas: check PHY state in get_wideport_bitmap_v3_hw()
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
                   ` (10 preceding siblings ...)
  2017-10-24 15:51 ` [PATCH 11/19] scsi: hisi_sas: report v2 hw AXI errors " John Garry
@ 2017-10-24 15:51 ` John Garry
  2017-10-24 15:51 ` [PATCH 13/19] scsi: hisi_sas: init connect cfg register for v3 hw John Garry
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, Xiaofei Tan,
	John Garry

From: Xiaofei Tan <tanxiaofei@huawei.com>

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 <tanxiaofei@huawei.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 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

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

* [PATCH 13/19] scsi: hisi_sas: init connect cfg register for v3 hw
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
                   ` (11 preceding siblings ...)
  2017-10-24 15:51 ` [PATCH 12/19] scsi: hisi_sas: check PHY state in get_wideport_bitmap_v3_hw() John Garry
@ 2017-10-24 15:51 ` John Garry
  2017-10-24 15:51 ` [PATCH 14/19] scsi: hisi_sas: add v3 hw DFX feature John Garry
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, Xiaofei Tan,
	John Garry

From: Xiaofei Tan <tanxiaofei@huawei.com>

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

Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 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

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

* [PATCH 14/19] scsi: hisi_sas: add v3 hw DFX feature
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
                   ` (12 preceding siblings ...)
  2017-10-24 15:51 ` [PATCH 13/19] scsi: hisi_sas: init connect cfg register for v3 hw John Garry
@ 2017-10-24 15:51 ` John Garry
  2017-10-24 15:51 ` [PATCH 15/19] scsi: hisi_sas: add hisi_hba.rst_work init for v3 hw John Garry
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, Xiaofei Tan,
	John Garry

From: Xiaofei Tan <tanxiaofei@huawei.com>

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 <tanxiaofei@huawei.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 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_HW		2048 /* 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 = &hisi_hba->phy[phy_no];
+	struct asd_sas_phy *sas_phy = &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

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

* [PATCH 15/19] scsi: hisi_sas: add hisi_hba.rst_work init for v3 hw
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
                   ` (13 preceding siblings ...)
  2017-10-24 15:51 ` [PATCH 14/19] scsi: hisi_sas: add v3 hw DFX feature John Garry
@ 2017-10-24 15:51 ` John Garry
  2017-10-24 15:51 ` [PATCH 16/19] scsi: hisi_sas: fix a bug when free device " John Garry
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, Xiaofei Tan,
	John Garry

From: Xiaofei Tan <tanxiaofei@huawei.com>

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 <tanxiaofei@huawei.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 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(&hisi_hba->rst_work, hisi_sas_rst_work_handler);
 	hisi_hba->hw = &hisi_sas_v3_hw;
 	hisi_hba->pci_dev = pdev;
 	hisi_hba->dev = dev;
-- 
1.9.1

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

* [PATCH 16/19] scsi: hisi_sas: fix a bug when free device for v3 hw
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
                   ` (14 preceding siblings ...)
  2017-10-24 15:51 ` [PATCH 15/19] scsi: hisi_sas: add hisi_hba.rst_work init for v3 hw John Garry
@ 2017-10-24 15:51 ` John Garry
  2017-10-24 15:51 ` [PATCH 17/19] scsi: hisi_sas: complete all tasklets prior to host reset John Garry
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, Xiang Chen, John Garry

From: Xiang Chen <chenxiang66@hisilicon.com>

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 <chenxiang66@hisilicon.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 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, 0xffffffff);
 	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, 0xffffffff);
+	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 = &hisi_hba->itct[dev_id];
 	u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
 
+	sas_dev->completion = &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

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

* [PATCH 17/19] scsi: hisi_sas: complete all tasklets prior to host reset
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
                   ` (15 preceding siblings ...)
  2017-10-24 15:51 ` [PATCH 16/19] scsi: hisi_sas: fix a bug when free device " John Garry
@ 2017-10-24 15:51 ` John Garry
  2017-10-24 15:51 ` [PATCH 18/19] scsi: hisi_sas: add v3 hw support for AXI fatal error John Garry
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, Xiaofei Tan,
	John Garry

From: Xiaofei Tan <tanxiaofei@huawei.com>

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 <tanxiaofei@huawei.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 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 = &hisi_hba->cq[i];
+
+		tasklet_kill(&cq->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(&hisi_hba->timer))
 		del_timer(&hisi_hba->timer);
 
-	for (i = 0; i < hisi_hba->queue_count; i++) {
-		struct hisi_sas_cq *cq = &hisi_hba->cq[i];
-
-		tasklet_kill(&cq->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 = &hisi_hba->cq[i];
 
 		free_irq(pci_irq_vector(pdev, i+16), cq);
-		tasklet_kill(&cq->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

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

* [PATCH 18/19] scsi: hisi_sas: add v3 hw support for AXI fatal error
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
                   ` (16 preceding siblings ...)
  2017-10-24 15:51 ` [PATCH 17/19] scsi: hisi_sas: complete all tasklets prior to host reset John Garry
@ 2017-10-24 15:51 ` John Garry
  2017-10-24 15:51 ` [PATCH 19/19] scsi: hisi_sas: add v3 hw port AXI error handling John Garry
  2017-10-25 12:29 ` [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features Martin K. Petersen
  19 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, Xiaofei Tan,
	John Garry

From: Xiaofei Tan <tanxiaofei@huawei.com>

Add support for processing AXI bus fatal errors.

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

Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 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_STATUS			0x148
+#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_EN			0x19c
 #define OQ_INT_COAL_TIME		0x1a0
 #define OQ_INT_COAL_CNT			0x1a4
@@ -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 = &fatal_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, &hisi_hba->rst_work);
+			}
+		} else {
+			dev_warn(dev, "%s error (0x%x) found!\n",
+				error->msg, irq_value);
+			queue_work(hisi_hba->wq, &hisi_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 =
+				&hisi_hba->devices[dev_id];
+
+		hisi_sas_write32(hisi_hba, ITCT_CLR, 0);
+		dev_dbg(dev, "clear ITCT ok\n");
+		complete(sas_dev->completion);
+	}
+
+	hisi_sas_write32(hisi_hba, ENT_INT_SRC3, irq_value & 0x1df00);
+	hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, irq_msk);
+
+	return IRQ_HANDLED;
+}
+
 static void
 slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
 	       struct hisi_sas_slot *slot)
@@ -1615,6 +1728,15 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba)
 		goto free_phy_irq;
 	}
 
+	rc = devm_request_irq(dev, pci_irq_vector(pdev, 11),
+			      fatal_axi_int_v3_hw, 0,
+			      DRV_NAME " fatal", hisi_hba);
+	if (rc) {
+		dev_err(dev, "could not request fatal interrupt, rc=%d\n", rc);
+		rc = -ENOENT;
+		goto free_chnl_interrupt;
+	}
+
 	/* Init tasklets for cq only */
 	for (i = 0; i < hisi_hba->queue_count; i++) {
 		struct hisi_sas_cq *cq = &hisi_hba->cq[i];
@@ -1642,6 +1764,8 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba)
 
 		free_irq(pci_irq_vector(pdev, k+16), cq);
 	}
+	free_irq(pci_irq_vector(pdev, 11), hisi_hba);
+free_chnl_interrupt:
 	free_irq(pci_irq_vector(pdev, 2), hisi_hba);
 free_phy_irq:
 	free_irq(pci_irq_vector(pdev, 1), hisi_hba);
@@ -1974,6 +2098,7 @@ static int soft_reset_v3_hw(struct hisi_hba *hisi_hba)
 
 	free_irq(pci_irq_vector(pdev, 1), hisi_hba);
 	free_irq(pci_irq_vector(pdev, 2), hisi_hba);
+	free_irq(pci_irq_vector(pdev, 11), hisi_hba);
 	for (i = 0; i < hisi_hba->queue_count; i++) {
 		struct hisi_sas_cq *cq = &hisi_hba->cq[i];
 
-- 
1.9.1

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

* [PATCH 19/19] scsi: hisi_sas: add v3 hw port AXI error handling
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
                   ` (17 preceding siblings ...)
  2017-10-24 15:51 ` [PATCH 18/19] scsi: hisi_sas: add v3 hw support for AXI fatal error John Garry
@ 2017-10-24 15:51 ` John Garry
  2017-10-25 12:29 ` [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features Martin K. Petersen
  19 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2017-10-24 15:51 UTC (permalink / raw)
  To: jejb, martin.petersen
  Cc: linuxarm, linux-scsi, linux-kernel, zhangfei.gao, Xiaofei Tan,
	John Garry

From: Xiaofei Tan <tanxiaofei@huawei.com>

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

Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
Signed-off-by: John Garry <john.garry@huawei.com>
---
 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_OFF	19
+#define CHL_INT1_DMAC_TX_AXI_RD_ERR_OFF	20
+#define CHL_INT1_DMAC_RX_AXI_WR_ERR_OFF	21
+#define CHL_INT1_DMAC_RX_AXI_RD_ERR_OFF	22
 #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, 0xffffffff);
 		hisi_sas_phy_write32(hisi_hba, i, CHL_INT2, 0xffffffff);
 		hisi_sas_phy_write32(hisi_hba, i, RXOP_CHECK_CFG_H, 0x1000);
-		hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0xffffffff);
+		hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0xff87ffff);
 		hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0x8ffffbff);
 		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 =
+						&port_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, &hisi_hba->rst_work);
+			}
 
 			hisi_sas_phy_write32(hisi_hba, phy_no,
 					     CHL_INT1, irq_value1);
-- 
1.9.1

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

* Re: [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features
  2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
                   ` (18 preceding siblings ...)
  2017-10-24 15:51 ` [PATCH 19/19] scsi: hisi_sas: add v3 hw port AXI error handling John Garry
@ 2017-10-25 12:29 ` Martin K. Petersen
  19 siblings, 0 replies; 21+ messages in thread
From: Martin K. Petersen @ 2017-10-25 12:29 UTC (permalink / raw)
  To: John Garry
  Cc: jejb, martin.petersen, linuxarm, linux-scsi, linux-kernel, zhangfei.gao


John,

> 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

Applied to 4.15/scsi-queue. Thanks!

-- 
Martin K. Petersen	Oracle Linux Engineering

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

end of thread, other threads:[~2017-10-25 12:30 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-24 15:51 [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features John Garry
2017-10-24 15:51 ` [PATCH 01/19] scsi: hisi_sas: delete get_ncq_tag_v3_hw() John Garry
2017-10-24 15:51 ` [PATCH 02/19] scsi: hisi_sas: fix internal abort slot timeout bug John Garry
2017-10-24 15:51 ` [PATCH 03/19] scsi: hisi_sas: use spin_lock_irqsave() for hisi_hba.lock John Garry
2017-10-24 15:51 ` [PATCH 04/19] scsi: hisi_sas: grab hisi_hba.lock when processing slots John Garry
2017-10-24 15:51 ` [PATCH 05/19] scsi: hisi_sas: fix SATA breakpoint memory size John Garry
2017-10-24 15:51 ` [PATCH 06/19] scsi: hisi_sas: us start_phy in PHY_FUNC_LINK_RESET John Garry
2017-10-24 15:51 ` [PATCH 07/19] scsi: hisi_sas: fix NULL check in SMP abort task path John Garry
2017-10-24 15:51 ` [PATCH 08/19] scsi: hisi_sas: fix the risk of freeing slot twice John Garry
2017-10-24 15:51 ` [PATCH 09/19] scsi: hisi_sas: use array for v2 hw AXI errors John Garry
2017-10-24 15:51 ` [PATCH 10/19] scsi: hisi_sas: report ECC errors in v2 hw to userspace John Garry
2017-10-24 15:51 ` [PATCH 11/19] scsi: hisi_sas: report v2 hw AXI errors " John Garry
2017-10-24 15:51 ` [PATCH 12/19] scsi: hisi_sas: check PHY state in get_wideport_bitmap_v3_hw() John Garry
2017-10-24 15:51 ` [PATCH 13/19] scsi: hisi_sas: init connect cfg register for v3 hw John Garry
2017-10-24 15:51 ` [PATCH 14/19] scsi: hisi_sas: add v3 hw DFX feature John Garry
2017-10-24 15:51 ` [PATCH 15/19] scsi: hisi_sas: add hisi_hba.rst_work init for v3 hw John Garry
2017-10-24 15:51 ` [PATCH 16/19] scsi: hisi_sas: fix a bug when free device " John Garry
2017-10-24 15:51 ` [PATCH 17/19] scsi: hisi_sas: complete all tasklets prior to host reset John Garry
2017-10-24 15:51 ` [PATCH 18/19] scsi: hisi_sas: add v3 hw support for AXI fatal error John Garry
2017-10-24 15:51 ` [PATCH 19/19] scsi: hisi_sas: add v3 hw port AXI error handling John Garry
2017-10-25 12:29 ` [PATCH 00/19] hisi_sas: misc fixes, improvements, and new features Martin K. Petersen

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