All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39.
@ 2019-11-14 10:08 Deepak Ukey
  2019-11-14 10:08 ` [PATCH V2 01/13] pm80xx : Fix for SATA device discovery Deepak Ukey
                   ` (13 more replies)
  0 siblings, 14 replies; 21+ messages in thread
From: Deepak Ukey @ 2019-11-14 10:08 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, jsperbeck, auradkar, ianyar

From: Deepak Ukey <Deepak.Ukey@microchip.com>

This patch set includes some bug fixes and features for pm80xx driver.

Changes from V1:
	For "Fix for SATA device discovery" patch.
		- Spilt the patch in two different patches
		that is "Fix for SATA device discovery" and
		"Make phy enable completion as NULL"
	For "Cleanup command when a reset times out" patch.
		- Fix the typo mistake.
	For "Controller fatal error through sysfs" patch.
		- Updated the function name in comment section.
	For " Modified the logic to collect fatal dump" patch.
		- Fixed the compiler warning for mips and i386
		  architecture.

Deepak Ukey (2):
  pm80xx : Controller fatal error through sysfs.
  pm80xx : Modified the logic to collect fatal dump.

John Sperbeck (1):
  pm80xx : Initialize variable used as return status.

Vikram Auradkar (3):
  pm80xx : Convert 'long' mdelay to msleep.
  pm80xx : Fix dereferencing dangling pointer.
  pm80xx : Tie the interrupt name to the module instance.

ianyar (1):
  pm80xx : Increase timeout for pm80xx mpi_uninit_check.

peter chang (6):
  pm80xx : Fix for SATA device discovery.
  pm80xx : Make phy enable completion as NULL.
  pm80xx : Squashed logging cleanup changes.
  pm80xx : Fix command issue sizing.
  pm80xx : Cleanup command when a reset times out.
  pm80xx : Do not request 12G sas speeds.

 drivers/scsi/pm8001/pm8001_ctl.c  |  20 ++
 drivers/scsi/pm8001/pm8001_hwi.c  | 131 +++++++----
 drivers/scsi/pm8001/pm8001_init.c |  34 ++-
 drivers/scsi/pm8001/pm8001_sas.c  |  70 ++++--
 drivers/scsi/pm8001/pm8001_sas.h  |  24 +-
 drivers/scsi/pm8001/pm80xx_hwi.c  | 451 ++++++++++++++++++++++++++++----------
 drivers/scsi/pm8001/pm80xx_hwi.h  |   3 +
 7 files changed, 550 insertions(+), 183 deletions(-)

-- 
2.16.3


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

* [PATCH V2 01/13] pm80xx : Fix for SATA device discovery.
  2019-11-14 10:08 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
@ 2019-11-14 10:08 ` Deepak Ukey
  2019-11-18  9:00   ` Jinpu Wang
  2019-11-14 10:08 ` [PATCH V2 02/13] pm80xx : Make phy enable completion as NULL Deepak Ukey
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 21+ messages in thread
From: Deepak Ukey @ 2019-11-14 10:08 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, jsperbeck, auradkar, ianyar

From: peter chang <dpf@google.com>

Driver was  missing complete() call in mpi_sata_completion which
result in SATA abort error handling is timing out. That causes the
device to be left in the in_recovery state so subsequent commands
sent to the device fail and the OS removes access to it.

Signed-off-by: peter chang <dpf@google.com>
Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 73261902d75d..161bf4760eac 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -2382,6 +2382,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 			pm8001_printk("task 0x%p done with io_status 0x%x"
 			" resp 0x%x stat 0x%x but aborted by upper layer!\n",
 			t, status, ts->resp, ts->stat));
+		if (t->slow_task)
+			complete(&t->slow_task->completion);
 		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
 	} else {
 		spin_unlock_irqrestore(&t->task_state_lock, flags);
-- 
2.16.3


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

* [PATCH V2 02/13] pm80xx : Make phy enable completion as NULL.
  2019-11-14 10:08 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
  2019-11-14 10:08 ` [PATCH V2 01/13] pm80xx : Fix for SATA device discovery Deepak Ukey
@ 2019-11-14 10:08 ` Deepak Ukey
  2019-11-18  9:01   ` Jinpu Wang
  2019-11-14 10:09 ` [PATCH V2 03/13] pm80xx : Initialize variable used as return status Deepak Ukey
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 21+ messages in thread
From: Deepak Ukey @ 2019-11-14 10:08 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, jsperbeck, auradkar, ianyar

From: peter chang <dpf@google.com>

After the completing the mpi_phy_start_resp make phy enable completion
as NULL.

Signed-off-by: peter chang <dpf@google.com>
Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 161bf4760eac..ee9c187d8caa 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -3132,8 +3132,10 @@ static int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 	if (status == 0) {
 		phy->phy_state = PHY_LINK_DOWN;
 		if (pm8001_ha->flags == PM8001F_RUN_TIME &&
-				phy->enable_completion != NULL)
+				phy->enable_completion != NULL) {
 			complete(phy->enable_completion);
+			phy->enable_completion = NULL;
+		}
 	}
 	return 0;
 
-- 
2.16.3


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

* [PATCH V2 03/13] pm80xx : Initialize variable used as return status.
  2019-11-14 10:08 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
  2019-11-14 10:08 ` [PATCH V2 01/13] pm80xx : Fix for SATA device discovery Deepak Ukey
  2019-11-14 10:08 ` [PATCH V2 02/13] pm80xx : Make phy enable completion as NULL Deepak Ukey
@ 2019-11-14 10:09 ` Deepak Ukey
  2019-11-14 10:09 ` [PATCH V2 04/13] pm80xx : Convert 'long' mdelay to msleep Deepak Ukey
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 21+ messages in thread
From: Deepak Ukey @ 2019-11-14 10:09 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, jsperbeck, auradkar, ianyar

From: John Sperbeck <jsperbeck@google.com>

In pm8001_task_exec(), if the PHY is down, then we return the
current value of 'rc'. We need to make sure it's initialized.

Signed-off-by: John Sperbeck <jsperbeck@google.com>
Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
---
 drivers/scsi/pm8001/pm8001_sas.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 7e48154e11c3..81160e99c75e 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -384,7 +384,7 @@ static int pm8001_task_exec(struct sas_task *task,
 	struct pm8001_port *port = NULL;
 	struct sas_task *t = task;
 	struct pm8001_ccb_info *ccb;
-	u32 tag = 0xdeadbeef, rc, n_elem = 0;
+	u32 tag = 0xdeadbeef, rc = 0, n_elem = 0;
 	unsigned long flags = 0;
 
 	if (!dev->port) {
-- 
2.16.3


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

* [PATCH V2 04/13] pm80xx : Convert 'long' mdelay to msleep.
  2019-11-14 10:08 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (2 preceding siblings ...)
  2019-11-14 10:09 ` [PATCH V2 03/13] pm80xx : Initialize variable used as return status Deepak Ukey
@ 2019-11-14 10:09 ` Deepak Ukey
  2019-11-14 10:09 ` [PATCH V2 05/13] pm80xx : Squashed logging cleanup changes Deepak Ukey
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 21+ messages in thread
From: Deepak Ukey @ 2019-11-14 10:09 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, jsperbeck, auradkar, ianyar

From: Vikram Auradkar <auradkar@google.com>

For delays longer than 20ms [um]delay isn't recommended.
pm80xx_chip_soft_rst starts off with a 500ms delay before it even
gets around to checking for the results of the reset. As long as
it's at least 500ms it doesn't matter what the scheduler is doing.
The delay in the pm8001_exec_internal_task_abort does nothing, and
theory is this is a delay to avoid a double-free.

Signed-off-by: Vikram Auradkar <auradkar@google.com>
Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index ee9c187d8caa..1a1adda15db8 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -1241,7 +1241,7 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha)
 		pm8001_printk("reset register before write : 0x%x\n", regval));
 
 	pm8001_cw32(pm8001_ha, 0, SPC_REG_SOFT_RESET, SPCv_NORMAL_RESET_VALUE);
-	mdelay(500);
+	msleep(500);
 
 	regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET);
 	PM8001_INIT_DBG(pm8001_ha,
@@ -2986,7 +2986,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
 	pm8001_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr);
 	spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);
 	if (pm8001_ha->flags == PM8001F_RUN_TIME)
-		mdelay(200);/*delay a moment to wait disk to spinup*/
+		msleep(200);/*delay a moment to wait disk to spinup*/
 	pm8001_bytes_dmaed(pm8001_ha, phy_id);
 }
 
-- 
2.16.3


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

* [PATCH V2 05/13] pm80xx : Squashed logging cleanup changes.
  2019-11-14 10:08 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (3 preceding siblings ...)
  2019-11-14 10:09 ` [PATCH V2 04/13] pm80xx : Convert 'long' mdelay to msleep Deepak Ukey
@ 2019-11-14 10:09 ` Deepak Ukey
  2019-11-14 10:09 ` [PATCH V2 06/13] pm80xx : Increase timeout for pm80xx mpi_uninit_check Deepak Ukey
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 21+ messages in thread
From: Deepak Ukey @ 2019-11-14 10:09 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, jsperbeck, auradkar, ianyar

From: peter chang <dpf@google.com>

The default logging doesn't include the device name, so it's
difficult to determine which controller is being logged about in
error scenarios. The logging level was only settable via sysfs,
which made it inconvenient for actual debugging. This changes the
default to only cover error handling.

Signed-off-by: peter chang <dpf@google.com>
Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c  |  62 ++++++++++++++------
 drivers/scsi/pm8001/pm8001_init.c |   6 +-
 drivers/scsi/pm8001/pm8001_sas.c  |   6 +-
 drivers/scsi/pm8001/pm8001_sas.h  |  15 ++++-
 drivers/scsi/pm8001/pm80xx_hwi.c  | 118 +++++++++++++++++++++++++++++++++-----
 5 files changed, 170 insertions(+), 37 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 68a8217032d0..2c1c722eca17 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1364,7 +1364,7 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
 	/*Update the PI to the firmware*/
 	pm8001_cw32(pm8001_ha, circularQ->pi_pci_bar,
 		circularQ->pi_offset, circularQ->producer_idx);
-	PM8001_IO_DBG(pm8001_ha,
+	PM8001_DEVIO_DBG(pm8001_ha,
 		pm8001_printk("INB Q %x OPCODE:%x , UPDATED PI=%d CI=%d\n",
 			responseQueue, opCode, circularQ->producer_idx,
 			circularQ->consumer_index));
@@ -1436,6 +1436,10 @@ u32 pm8001_mpi_msg_consume(struct pm8001_hba_info *pm8001_ha,
 			/* read header */
 			header_tmp = pm8001_read_32(msgHeader);
 			msgHeader_tmp = cpu_to_le32(header_tmp);
+			PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(
+				"outbound opcode msgheader:%x ci=%d pi=%d\n",
+				msgHeader_tmp, circularQ->consumer_idx,
+				circularQ->producer_index));
 			if (0 != (le32_to_cpu(msgHeader_tmp) & 0x80000000)) {
 				if (OPC_OUB_SKIP_ENTRY !=
 					(le32_to_cpu(msgHeader_tmp) & 0xfff)) {
@@ -1604,7 +1608,8 @@ void pm8001_work_fn(struct work_struct *work)
 				break;
 
 			default:
-				pm8001_printk("...query task failed!!!\n");
+				PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(
+					"...query task failed!!!\n"));
 				break;
 			});
 
@@ -1890,6 +1895,11 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 			pm8001_printk("SAS Address of IO Failure Drive:"
 			"%016llx", SAS_ADDR(t->dev->sas_addr)));
 
+	if (status)
+		PM8001_IOERR_DBG(pm8001_ha, pm8001_printk(
+			"status:0x%x, tag:0x%x, task:0x%p\n",
+			status, tag, t));
+
 	switch (status) {
 	case IO_SUCCESS:
 		PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS"
@@ -2072,7 +2082,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
 		break;
 	default:
-		PM8001_IO_DBG(pm8001_ha,
+		PM8001_DEVIO_DBG(pm8001_ha,
 			pm8001_printk("Unknown status 0x%x\n", status));
 		/* not allowed case. Therefore, return failed status */
 		ts->resp = SAS_TASK_COMPLETE;
@@ -2125,7 +2135,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
 	if (unlikely(!t || !t->lldd_task || !t->dev))
 		return;
 	ts = &t->task_status;
-	PM8001_IO_DBG(pm8001_ha,
+	PM8001_DEVIO_DBG(pm8001_ha,
 		pm8001_printk("port_id = %x,device_id = %x\n",
 		port_id, dev_id));
 	switch (event) {
@@ -2263,7 +2273,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
 			pm8001_printk("  IO_XFER_CMD_FRAME_ISSUED\n"));
 		return;
 	default:
-		PM8001_IO_DBG(pm8001_ha,
+		PM8001_DEVIO_DBG(pm8001_ha,
 			pm8001_printk("Unknown status 0x%x\n", event));
 		/* not allowed case. Therefore, return failed status */
 		ts->resp = SAS_TASK_COMPLETE;
@@ -2352,6 +2362,12 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 			pm8001_printk("ts null\n"));
 		return;
 	}
+
+	if (status)
+		PM8001_IOERR_DBG(pm8001_ha, pm8001_printk(
+			"status:0x%x, tag:0x%x, task::0x%p\n",
+			status, tag, t));
+
 	/* Print sas address of IO failed device */
 	if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) &&
 		(status != IO_UNDERFLOW)) {
@@ -2652,7 +2668,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
 		break;
 	default:
-		PM8001_IO_DBG(pm8001_ha,
+		PM8001_DEVIO_DBG(pm8001_ha,
 			pm8001_printk("Unknown status 0x%x\n", status));
 		/* not allowed case. Therefore, return failed status */
 		ts->resp = SAS_TASK_COMPLETE;
@@ -2723,7 +2739,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
 	if (unlikely(!t || !t->lldd_task || !t->dev))
 		return;
 	ts = &t->task_status;
-	PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+	PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(
 		"port_id:0x%x, device_id:0x%x, tag:0x%x, event:0x%x\n",
 		port_id, dev_id, tag, event));
 	switch (event) {
@@ -2872,7 +2888,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->stat = SAS_OPEN_TO;
 		break;
 	default:
-		PM8001_IO_DBG(pm8001_ha,
+		PM8001_DEVIO_DBG(pm8001_ha,
 			pm8001_printk("Unknown status 0x%x\n", event));
 		/* not allowed case. Therefore, return failed status */
 		ts->resp = SAS_TASK_COMPLETE;
@@ -2917,9 +2933,13 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 	t = ccb->task;
 	ts = &t->task_status;
 	pm8001_dev = ccb->device;
-	if (status)
+	if (status) {
 		PM8001_FAIL_DBG(pm8001_ha,
 			pm8001_printk("smp IO status 0x%x\n", status));
+		PM8001_IOERR_DBG(pm8001_ha,
+			pm8001_printk("status:0x%x, tag:0x%x, task:0x%p\n",
+			status, tag, t));
+	}
 	if (unlikely(!t || !t->lldd_task || !t->dev))
 		return;
 
@@ -3070,7 +3090,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
 		break;
 	default:
-		PM8001_IO_DBG(pm8001_ha,
+		PM8001_DEVIO_DBG(pm8001_ha,
 			pm8001_printk("Unknown status 0x%x\n", status));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_DEV_NO_RESPONSE;
@@ -3416,7 +3436,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		pm8001_get_lrate_mode(phy, link_rate);
 		break;
 	default:
-		PM8001_MSG_DBG(pm8001_ha,
+		PM8001_DEVIO_DBG(pm8001_ha,
 			pm8001_printk("unknown device type(%x)\n", deviceType));
 		break;
 	}
@@ -3463,7 +3483,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
 	struct sas_ha_struct *sas_ha = pm8001_ha->sas;
 	struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
 	unsigned long flags;
-	PM8001_MSG_DBG(pm8001_ha,
+	PM8001_DEVIO_DBG(pm8001_ha,
 		pm8001_printk("HW_EVENT_SATA_PHY_UP port id = %d,"
 		" phy id = %d\n", port_id, phy_id));
 	port->port_state =  portstate;
@@ -3541,7 +3561,7 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		break;
 	default:
 		port->port_attached = 0;
-		PM8001_MSG_DBG(pm8001_ha,
+		PM8001_DEVIO_DBG(pm8001_ha,
 			pm8001_printk(" phy Down and(default) = %x\n",
 			portstate));
 		break;
@@ -3689,7 +3709,7 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha,
 			pm8001_printk(": FLASH_UPDATE_DISABLED\n"));
 		break;
 	default:
-		PM8001_MSG_DBG(pm8001_ha,
+		PM8001_DEVIO_DBG(pm8001_ha,
 			pm8001_printk("No matched status = %d\n", status));
 		break;
 	}
@@ -3805,8 +3825,9 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb)
 	struct sas_ha_struct *sas_ha = pm8001_ha->sas;
 	struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
 	struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id];
-	PM8001_MSG_DBG(pm8001_ha,
-		pm8001_printk("outbound queue HW event & event type : "));
+	PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(
+		"SPC HW event for portid:%d, phyid:%d, event:%x, status:%x\n",
+		port_id, phy_id, eventType, status));
 	switch (eventType) {
 	case HW_EVENT_PHY_START_STATUS:
 		PM8001_MSG_DBG(pm8001_ha,
@@ -3990,7 +4011,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb)
 			pm8001_printk("EVENT_BROADCAST_ASYNCH_EVENT\n"));
 		break;
 	default:
-		PM8001_MSG_DBG(pm8001_ha,
+		PM8001_DEVIO_DBG(pm8001_ha,
 			pm8001_printk("Unknown event type = %x\n", eventType));
 		break;
 	}
@@ -4161,7 +4182,7 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
 			pm8001_printk("OPC_OUB_SAS_RE_INITIALIZE\n"));
 		break;
 	default:
-		PM8001_MSG_DBG(pm8001_ha,
+		PM8001_DEVIO_DBG(pm8001_ha,
 			pm8001_printk("Unknown outbound Queue IOMB OPC = %x\n",
 			opc));
 		break;
@@ -4649,6 +4670,9 @@ static irqreturn_t
 pm8001_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec)
 {
 	pm8001_chip_interrupt_disable(pm8001_ha, vec);
+	PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(
+		"irq vec %d, ODMR:0x%x\n",
+		vec, pm8001_cr32(pm8001_ha, 0, 0x30)));
 	process_oq(pm8001_ha, vec);
 	pm8001_chip_interrupt_enable(pm8001_ha, vec);
 	return IRQ_HANDLED;
@@ -4960,6 +4984,8 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
 	if (!fw_control_context)
 		return -ENOMEM;
 	fw_control = (struct fw_control_info *)&ioctl_payload->func_specific;
+	PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(
+		"dma fw_control context input length :%x\n", fw_control->len));
 	memcpy(buffer, fw_control->buffer, fw_control->len);
 	flash_update_info.sgl.addr = cpu_to_le64(phys_addr);
 	flash_update_info.sgl.im_len.len = cpu_to_le32(fw_control->len);
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 3374f553c617..b7cc3d05a3e0 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -42,6 +42,10 @@
 #include "pm8001_sas.h"
 #include "pm8001_chips.h"
 
+static ulong logging_level = PM8001_FAIL_LOGGING | PM8001_IOERR_LOGGING;
+module_param(logging_level, ulong, 0644);
+MODULE_PARM_DESC(logging_level, " bits for enabling logging info.");
+
 static struct scsi_transport_template *pm8001_stt;
 
 /**
@@ -466,7 +470,7 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
 	pm8001_ha->sas = sha;
 	pm8001_ha->shost = shost;
 	pm8001_ha->id = pm8001_id++;
-	pm8001_ha->logging_level = 0x01;
+	pm8001_ha->logging_level = logging_level;
 	sprintf(pm8001_ha->name, "%s%d", DRV_NAME, pm8001_ha->id);
 	/* IOMB size is 128 for 8088/89 controllers */
 	if (pm8001_ha->chip_id != chip_8001)
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 81160e99c75e..447a66d60275 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -119,7 +119,7 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr,
 	mem_virt_alloc = dma_alloc_coherent(&pdev->dev, mem_size + align,
 					    &mem_dma_handle, GFP_KERNEL);
 	if (!mem_virt_alloc) {
-		pm8001_printk("memory allocation error\n");
+		pr_err("pm80xx: memory allocation error\n");
 		return -1;
 	}
 	*pphys_addr = mem_dma_handle;
@@ -249,6 +249,8 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
 		spin_unlock_irqrestore(&pm8001_ha->lock, flags);
 		return 0;
 	default:
+		PM8001_DEVIO_DBG(pm8001_ha,
+			pm8001_printk("func 0x%x\n", func));
 		rc = -EOPNOTSUPP;
 	}
 	msleep(300);
@@ -1179,7 +1181,7 @@ int pm8001_query_task(struct sas_task *task)
 			break;
 		}
 	}
-	pm8001_printk(":rc= %d\n", rc);
+	pr_err("pm80xx: rc= %d\n", rc);
 	return rc;
 }
 
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index ff17c6aff63d..9e0da7bccb45 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -66,8 +66,11 @@
 #define PM8001_EH_LOGGING	0x10 /* libsas EH function logging*/
 #define PM8001_IOCTL_LOGGING	0x20 /* IOCTL message logging */
 #define PM8001_MSG_LOGGING	0x40 /* misc message logging */
-#define pm8001_printk(format, arg...)	printk(KERN_INFO "pm80xx %s %d:" \
-			format, __func__, __LINE__, ## arg)
+#define PM8001_DEV_LOGGING	0x80 /* development message logging */
+#define PM8001_DEVIO_LOGGING	0x100 /* development io message logging */
+#define PM8001_IOERR_LOGGING	0x200 /* development io err message logging */
+#define pm8001_printk(format, arg...)	pr_info("%s:: %s  %d:" \
+			format, pm8001_ha->name, __func__, __LINE__, ## arg)
 #define PM8001_CHECK_LOGGING(HBA, LEVEL, CMD)	\
 do {						\
 	if (unlikely(HBA->logging_level & LEVEL))	\
@@ -97,6 +100,14 @@ do {						\
 #define PM8001_MSG_DBG(HBA, CMD)		\
 	PM8001_CHECK_LOGGING(HBA, PM8001_MSG_LOGGING, CMD)
 
+#define PM8001_DEV_DBG(HBA, CMD)		\
+	PM8001_CHECK_LOGGING(HBA, PM8001_DEV_LOGGING, CMD)
+
+#define PM8001_DEVIO_DBG(HBA, CMD)		\
+	PM8001_CHECK_LOGGING(HBA, PM8001_DEVIO_LOGGING, CMD)
+
+#define PM8001_IOERR_DBG(HBA, CMD)		\
+	PM8001_CHECK_LOGGING(HBA, PM8001_IOERR_LOGGING, CMD)
 
 #define PM8001_USE_TASKLET
 #define PM8001_USE_MSIX
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 1a1adda15db8..6057610263c1 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -317,6 +317,25 @@ static void read_main_config_table(struct pm8001_hba_info *pm8001_ha)
 		pm8001_mr32(address, MAIN_MPI_ILA_RELEASE_TYPE);
 	pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version =
 		pm8001_mr32(address, MAIN_MPI_INACTIVE_FW_VERSION);
+
+	PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
+		"Main cfg table: sign:%x interface rev:%x fw_rev:%x\n",
+		pm8001_ha->main_cfg_tbl.pm80xx_tbl.signature,
+		pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev,
+		pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev));
+
+	PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
+		"table offset: gst:%x iq:%x oq:%x int vec:%x phy attr:%x\n",
+		pm8001_ha->main_cfg_tbl.pm80xx_tbl.gst_offset,
+		pm8001_ha->main_cfg_tbl.pm80xx_tbl.inbound_queue_offset,
+		pm8001_ha->main_cfg_tbl.pm80xx_tbl.outbound_queue_offset,
+		pm8001_ha->main_cfg_tbl.pm80xx_tbl.int_vec_table_offset,
+		pm8001_ha->main_cfg_tbl.pm80xx_tbl.phy_attr_table_offset));
+
+	PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
+		"Main cfg table; ila rev:%x Inactive fw rev:%x\n",
+		pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version,
+		pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version));
 }
 
 /**
@@ -521,6 +540,11 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
 			pm8001_mr32(addressib, (offsetib + 0x18));
 		pm8001_ha->inbnd_q_tbl[i].producer_idx		= 0;
 		pm8001_ha->inbnd_q_tbl[i].consumer_index	= 0;
+
+		PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
+			"IQ %d pi_bar 0x%x pi_offset 0x%x\n", i,
+			pm8001_ha->inbnd_q_tbl[i].pi_pci_bar,
+			pm8001_ha->inbnd_q_tbl[i].pi_offset));
 	}
 	for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) {
 		pm8001_ha->outbnd_q_tbl[i].element_size_cnt	=
@@ -549,6 +573,11 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
 			pm8001_mr32(addressob, (offsetob + 0x18));
 		pm8001_ha->outbnd_q_tbl[i].consumer_idx		= 0;
 		pm8001_ha->outbnd_q_tbl[i].producer_index	= 0;
+
+		PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
+			"OQ %d ci_bar 0x%x ci_offset 0x%x\n", i,
+			pm8001_ha->outbnd_q_tbl[i].ci_pci_bar,
+			pm8001_ha->outbnd_q_tbl[i].ci_offset));
 	}
 }
 
@@ -582,6 +611,10 @@ static void update_main_config_table(struct pm8001_hba_info *pm8001_ha)
 					((pm8001_ha->number_of_intr - 1) << 8);
 	pm8001_mw32(address, MAIN_FATAL_ERROR_INTERRUPT,
 		pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt);
+	PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
+		"Updated Fatal error interrupt vector 0x%x\n",
+		pm8001_mr32(address, MAIN_FATAL_ERROR_INTERRUPT)));
+
 	pm8001_mw32(address, MAIN_EVENT_CRC_CHECK,
 		pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump);
 
@@ -591,6 +624,9 @@ static void update_main_config_table(struct pm8001_hba_info *pm8001_ha)
 	pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping |= 0x20000000;
 	pm8001_mw32(address, MAIN_GPIO_LED_FLAGS_OFFSET,
 		pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping);
+	PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
+		"Programming DW 0x21 in main cfg table with 0x%x\n",
+		pm8001_mr32(address, MAIN_GPIO_LED_FLAGS_OFFSET)));
 
 	pm8001_mw32(address, MAIN_PORT_RECOVERY_TIMER,
 		pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer);
@@ -629,6 +665,21 @@ static void update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha,
 		pm8001_ha->inbnd_q_tbl[number].ci_upper_base_addr);
 	pm8001_mw32(address, offset + IB_CI_BASE_ADDR_LO_OFFSET,
 		pm8001_ha->inbnd_q_tbl[number].ci_lower_base_addr);
+
+	PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
+		"IQ %d: Element pri size 0x%x\n",
+		number,
+		pm8001_ha->inbnd_q_tbl[number].element_pri_size_cnt));
+
+	PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
+		"IQ upr base addr 0x%x IQ lwr base addr 0x%x\n",
+		pm8001_ha->inbnd_q_tbl[number].upper_base_addr,
+		pm8001_ha->inbnd_q_tbl[number].lower_base_addr));
+
+	PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
+		"CI upper base addr 0x%x CI lower base addr 0x%x\n",
+		pm8001_ha->inbnd_q_tbl[number].ci_upper_base_addr,
+		pm8001_ha->inbnd_q_tbl[number].ci_lower_base_addr));
 }
 
 /**
@@ -652,6 +703,21 @@ static void update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha,
 		pm8001_ha->outbnd_q_tbl[number].pi_lower_base_addr);
 	pm8001_mw32(address, offset + OB_INTERRUPT_COALES_OFFSET,
 		pm8001_ha->outbnd_q_tbl[number].interrup_vec_cnt_delay);
+
+	PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
+		"OQ %d: Element pri size 0x%x\n",
+		number,
+		pm8001_ha->outbnd_q_tbl[number].element_size_cnt));
+
+	PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
+		"OQ upr base addr 0x%x OQ lwr base addr 0x%x\n",
+		pm8001_ha->outbnd_q_tbl[number].upper_base_addr,
+		pm8001_ha->outbnd_q_tbl[number].lower_base_addr));
+
+	PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
+		"PI upper base addr 0x%x PI lower base addr 0x%x\n",
+		pm8001_ha->outbnd_q_tbl[number].pi_upper_base_addr,
+		pm8001_ha->outbnd_q_tbl[number].pi_lower_base_addr));
 }
 
 /**
@@ -797,7 +863,7 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha)
 	value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0);
 	offset = value & 0x03FFFFFF; /* scratch pad 0 TBL address */
 
-	PM8001_INIT_DBG(pm8001_ha,
+	PM8001_DEV_DBG(pm8001_ha,
 		pm8001_printk("Scratchpad 0 Offset: 0x%x value 0x%x\n",
 				offset, value));
 	pcilogic = (value & 0xFC000000) >> 26;
@@ -885,6 +951,10 @@ pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha)
 				(THERMAL_ENABLE << 8) | page_code;
 	payload.cfg_pg[1] = (LTEMPHIL << 24) | (RTEMPHIL << 8);
 
+	PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
+		"Setting up thermal config. cfg_pg 0 0x%x cfg_pg 1 0x%x\n",
+		payload.cfg_pg[0], payload.cfg_pg[1]));
+
 	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
 	if (rc)
 		pm8001_tag_free(pm8001_ha, tag);
@@ -1090,6 +1160,10 @@ static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha)
 	payload.new_curidx_ksop = ((1 << 24) | (1 << 16) | (1 << 8) |
 					KEK_MGMT_SUBOP_KEYCARDUPDATE);
 
+	PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
+		"Saving Encryption info to flash. payload 0x%x\n",
+		payload.new_curidx_ksop));
+
 	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
 	if (rc)
 		pm8001_tag_free(pm8001_ha, tag);
@@ -1570,6 +1644,10 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 	if (unlikely(!t || !t->lldd_task || !t->dev))
 		return;
 	ts = &t->task_status;
+
+	PM8001_DEV_DBG(pm8001_ha, pm8001_printk(
+		"tag::0x%x, status::0x%x task::0x%p\n", tag, status, t));
+
 	/* Print sas address of IO failed device */
 	if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) &&
 		(status != IO_UNDERFLOW))
@@ -1772,7 +1850,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
 		break;
 	default:
-		PM8001_IO_DBG(pm8001_ha,
+		PM8001_DEVIO_DBG(pm8001_ha,
 			pm8001_printk("Unknown status 0x%x\n", status));
 		/* not allowed case. Therefore, return failed status */
 		ts->resp = SAS_TASK_COMPLETE;
@@ -1826,7 +1904,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
 	if (unlikely(!t || !t->lldd_task || !t->dev))
 		return;
 	ts = &t->task_status;
-	PM8001_IO_DBG(pm8001_ha,
+	PM8001_IOERR_DBG(pm8001_ha,
 		pm8001_printk("port_id:0x%x, tag:0x%x, event:0x%x\n",
 				port_id, tag, event));
 	switch (event) {
@@ -1963,7 +2041,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->stat = SAS_DATA_OVERRUN;
 		break;
 	case IO_XFER_ERROR_INTERNAL_CRC_ERROR:
-		PM8001_IO_DBG(pm8001_ha,
+		PM8001_IOERR_DBG(pm8001_ha,
 			pm8001_printk("IO_XFR_ERROR_INTERNAL_CRC_ERROR\n"));
 		/* TBC: used default set values */
 		ts->resp = SAS_TASK_COMPLETE;
@@ -1974,7 +2052,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
 			pm8001_printk("IO_XFER_CMD_FRAME_ISSUED\n"));
 		return;
 	default:
-		PM8001_IO_DBG(pm8001_ha,
+		PM8001_DEVIO_DBG(pm8001_ha,
 			pm8001_printk("Unknown status 0x%x\n", event));
 		/* not allowed case. Therefore, return failed status */
 		ts->resp = SAS_TASK_COMPLETE;
@@ -2062,6 +2140,12 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 			pm8001_printk("ts null\n"));
 		return;
 	}
+
+	if (unlikely(status))
+		PM8001_IOERR_DBG(pm8001_ha, pm8001_printk(
+			"status:0x%x, tag:0x%x, task::0x%p\n",
+			status, tag, t));
+
 	/* Print sas address of IO failed device */
 	if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) &&
 		(status != IO_UNDERFLOW)) {
@@ -2365,7 +2449,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
 		break;
 	default:
-		PM8001_IO_DBG(pm8001_ha,
+		PM8001_DEVIO_DBG(pm8001_ha,
 			pm8001_printk("Unknown status 0x%x\n", status));
 		/* not allowed case. Therefore, return failed status */
 		ts->resp = SAS_TASK_COMPLETE;
@@ -2437,7 +2521,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
 	}
 
 	ts = &t->task_status;
-	PM8001_IO_DBG(pm8001_ha,
+	PM8001_IOERR_DBG(pm8001_ha,
 		pm8001_printk("port_id:0x%x, tag:0x%x, event:0x%x\n",
 				port_id, tag, event));
 	switch (event) {
@@ -2657,6 +2741,9 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 	if (unlikely(!t || !t->lldd_task || !t->dev))
 		return;
 
+	PM8001_DEV_DBG(pm8001_ha,
+		pm8001_printk("tag::0x%x status::0x%x\n", tag, status));
+
 	switch (status) {
 
 	case IO_SUCCESS:
@@ -2824,7 +2911,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
 		break;
 	default:
-		PM8001_IO_DBG(pm8001_ha,
+		PM8001_DEVIO_DBG(pm8001_ha,
 			pm8001_printk("Unknown status 0x%x\n", status));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_DEV_NO_RESPONSE;
@@ -2966,7 +3053,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		pm8001_get_lrate_mode(phy, link_rate);
 		break;
 	default:
-		PM8001_MSG_DBG(pm8001_ha,
+		PM8001_DEVIO_DBG(pm8001_ha,
 			pm8001_printk("unknown device type(%x)\n", deviceType));
 		break;
 	}
@@ -3015,7 +3102,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
 	struct sas_ha_struct *sas_ha = pm8001_ha->sas;
 	struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
 	unsigned long flags;
-	PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+	PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(
 		"port id %d, phy id %d link_rate %d portstate 0x%x\n",
 				port_id, phy_id, link_rate, portstate));
 
@@ -3103,7 +3190,7 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		break;
 	default:
 		port->port_attached = 0;
-		PM8001_MSG_DBG(pm8001_ha,
+		PM8001_DEVIO_DBG(pm8001_ha,
 			pm8001_printk(" Phy Down and(default) = 0x%x\n",
 			portstate));
 		break;
@@ -3195,7 +3282,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
 	struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
 	struct pm8001_port *port = &pm8001_ha->port[port_id];
 	struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id];
-	PM8001_MSG_DBG(pm8001_ha,
+	PM8001_DEV_DBG(pm8001_ha,
 		pm8001_printk("portid:%d phyid:%d event:0x%x status:0x%x\n",
 				port_id, phy_id, eventType, status));
 
@@ -3380,7 +3467,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
 			pm8001_printk("EVENT_BROADCAST_ASYNCH_EVENT\n"));
 		break;
 	default:
-		PM8001_MSG_DBG(pm8001_ha,
+		PM8001_DEVIO_DBG(pm8001_ha,
 			pm8001_printk("Unknown event type 0x%x\n", eventType));
 		break;
 	}
@@ -3762,7 +3849,7 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ssp_coalesced_comp_resp(pm8001_ha, piomb);
 		break;
 	default:
-		PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+		PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(
 			"Unknown outbound Queue IOMB OPC = 0x%x\n", opc));
 		break;
 	}
@@ -4645,6 +4732,9 @@ static irqreturn_t
 pm80xx_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec)
 {
 	pm80xx_chip_interrupt_disable(pm8001_ha, vec);
+	PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(
+		"irq vec %d, ODMR:0x%x\n",
+		vec, pm8001_cr32(pm8001_ha, 0, 0x30)));
 	process_oq(pm8001_ha, vec);
 	pm80xx_chip_interrupt_enable(pm8001_ha, vec);
 	return IRQ_HANDLED;
-- 
2.16.3


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

* [PATCH V2 06/13] pm80xx : Increase timeout for pm80xx mpi_uninit_check.
  2019-11-14 10:08 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (4 preceding siblings ...)
  2019-11-14 10:09 ` [PATCH V2 05/13] pm80xx : Squashed logging cleanup changes Deepak Ukey
@ 2019-11-14 10:09 ` Deepak Ukey
  2019-11-14 10:09 ` [PATCH V2 07/13] pm80xx : Fix dereferencing dangling pointer Deepak Ukey
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 21+ messages in thread
From: Deepak Ukey @ 2019-11-14 10:09 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, jsperbeck, auradkar, ianyar

From: ianyar <ianyar@google.com>

The function  mpi_uninit_check takes longer for inbound doorbell
register to be cleared. Increased the timeout substantially so
that the driver does not fail to load.

Signed-off-by: ianyar <ianyar@google.com>
Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 4 ++--
 drivers/scsi/pm8001/pm80xx_hwi.h | 3 +++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 6057610263c1..9d04e5cfffb4 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -735,9 +735,9 @@ static int mpi_init_check(struct pm8001_hba_info *pm8001_ha)
 	pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_UPDATE);
 	/* wait until Inbound DoorBell Clear Register toggled */
 	if (IS_SPCV_12G(pm8001_ha->pdev)) {
-		max_wait_count = 4 * 1000 * 1000;/* 4 sec */
+		max_wait_count = SPCV_DOORBELL_CLEAR_TIMEOUT;
 	} else {
-		max_wait_count = 2 * 1000 * 1000;/* 2 sec */
+		max_wait_count = SPC_DOORBELL_CLEAR_TIMEOUT;
 	}
 	do {
 		udelay(1);
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index dc9ab7689060..701951a0f715 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -220,6 +220,9 @@
 #define SAS_DOPNRJT_RTRY_TMO            128
 #define SAS_COPNRJT_RTRY_TMO            128
 
+#define SPCV_DOORBELL_CLEAR_TIMEOUT	(30 * 1000 * 1000) /* 30 sec */
+#define SPC_DOORBELL_CLEAR_TIMEOUT	(15 * 1000 * 1000) /* 15 sec */
+
 /*
   Making ORR bigger than IT NEXUS LOSS which is 2000000us = 2 second.
   Assuming a bigger value 3 second, 3000000/128 = 23437.5 where 128
-- 
2.16.3


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

* [PATCH V2 07/13] pm80xx : Fix dereferencing dangling pointer.
  2019-11-14 10:08 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (5 preceding siblings ...)
  2019-11-14 10:09 ` [PATCH V2 06/13] pm80xx : Increase timeout for pm80xx mpi_uninit_check Deepak Ukey
@ 2019-11-14 10:09 ` Deepak Ukey
  2019-11-14 10:09 ` [PATCH V2 08/13] pm80xx : Fix command issue sizing Deepak Ukey
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 21+ messages in thread
From: Deepak Ukey @ 2019-11-14 10:09 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, jsperbeck, auradkar, ianyar

From: Vikram Auradkar <auradkar@google.com>

sas_task structure should not be used after task_done is called.
If the device is gone or not attached, we call task_done on t and
continue to use in the sas_task in rest of the function. task_done
is pointing to sas_ata_task_done, may free the memory associated
with the task before returning.

Signed-off-by: Vikram Auradkar <auradkar@google.com>
Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
---
 drivers/scsi/pm8001/pm8001_sas.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 447a66d60275..4491de8d40fc 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -388,6 +388,7 @@ static int pm8001_task_exec(struct sas_task *task,
 	struct pm8001_ccb_info *ccb;
 	u32 tag = 0xdeadbeef, rc = 0, n_elem = 0;
 	unsigned long flags = 0;
+	enum sas_protocol task_proto = t->task_proto;
 
 	if (!dev->port) {
 		struct task_status_struct *tsm = &t->task_status;
@@ -412,7 +413,7 @@ static int pm8001_task_exec(struct sas_task *task,
 		pm8001_dev = dev->lldd_dev;
 		port = &pm8001_ha->port[sas_find_local_port_id(dev)];
 		if (DEV_IS_GONE(pm8001_dev) || !port->port_attached) {
-			if (sas_protocol_ata(t->task_proto)) {
+			if (sas_protocol_ata(task_proto)) {
 				struct task_status_struct *ts = &t->task_status;
 				ts->resp = SAS_TASK_UNDELIVERED;
 				ts->stat = SAS_PHY_DOWN;
@@ -434,7 +435,7 @@ static int pm8001_task_exec(struct sas_task *task,
 			goto err_out;
 		ccb = &pm8001_ha->ccb_info[tag];
 
-		if (!sas_protocol_ata(t->task_proto)) {
+		if (!sas_protocol_ata(task_proto)) {
 			if (t->num_scatter) {
 				n_elem = dma_map_sg(pm8001_ha->dev,
 					t->scatter,
@@ -454,7 +455,7 @@ static int pm8001_task_exec(struct sas_task *task,
 		ccb->ccb_tag = tag;
 		ccb->task = t;
 		ccb->device = pm8001_dev;
-		switch (t->task_proto) {
+		switch (task_proto) {
 		case SAS_PROTOCOL_SMP:
 			rc = pm8001_task_prep_smp(pm8001_ha, ccb);
 			break;
@@ -471,8 +472,7 @@ static int pm8001_task_exec(struct sas_task *task,
 			break;
 		default:
 			dev_printk(KERN_ERR, pm8001_ha->dev,
-				"unknown sas_task proto: 0x%x\n",
-				t->task_proto);
+				"unknown sas_task proto: 0x%x\n", task_proto);
 			rc = -EINVAL;
 			break;
 		}
@@ -495,7 +495,7 @@ static int pm8001_task_exec(struct sas_task *task,
 	pm8001_tag_free(pm8001_ha, tag);
 err_out:
 	dev_printk(KERN_ERR, pm8001_ha->dev, "pm8001 exec failed[%d]!\n", rc);
-	if (!sas_protocol_ata(t->task_proto))
+	if (!sas_protocol_ata(task_proto))
 		if (n_elem)
 			dma_unmap_sg(pm8001_ha->dev, t->scatter, t->num_scatter,
 				t->data_dir);
-- 
2.16.3


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

* [PATCH V2 08/13] pm80xx : Fix command issue sizing.
  2019-11-14 10:08 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (6 preceding siblings ...)
  2019-11-14 10:09 ` [PATCH V2 07/13] pm80xx : Fix dereferencing dangling pointer Deepak Ukey
@ 2019-11-14 10:09 ` Deepak Ukey
  2019-11-14 10:09 ` [PATCH V2 09/13] pm80xx : Cleanup command when a reset times out Deepak Ukey
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 21+ messages in thread
From: Deepak Ukey @ 2019-11-14 10:09 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, jsperbeck, auradkar, ianyar

From: peter chang <dpf@google.com>

The commands to the controller are sent in fixed sized chunks which are
set per-chip-generation and stashed in iomb_size. The driver fills in
structs matching the register layout and memcpy this to memory shared
with the controller. however, there are two problem cases:
	1)Things like phy_start_req are too large because they share the
	sas_identify_frame definition with libsas, and it includes the
	crc word. this means that it's overwriting the start of the next
	command block, that's ok except if it happens at the end of the
	shared memory area.
	2)Things like set_nvm_data_req which are shared between the HAL
	layers. this means that it's sending 'random' data for things
	that are in the reserved area. so far we haven't found a case
	where the controller FW cares, but sending possible gibberish
	(for most of the structures this is in the reserved area so
	previously zeroed) is not recommended.

Signed-off-by: peter chang <dpf@google.com>
Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c | 69 ++++++++++++++++++++++++++--------------
 drivers/scsi/pm8001/pm8001_sas.h |  3 +-
 drivers/scsi/pm8001/pm80xx_hwi.c | 47 +++++++++++++++++----------
 3 files changed, 79 insertions(+), 40 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 2c1c722eca17..1cbcade747fe 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1336,10 +1336,13 @@ int pm8001_mpi_msg_free_get(struct inbound_queue_table *circularQ,
  * @circularQ: the inbound queue we want to transfer to HBA.
  * @opCode: the operation code represents commands which LLDD and fw recognized.
  * @payload: the command payload of each operation command.
+ * @nb: size in bytes of the command payload
+ * @responseQueue: queue to interrupt on w/ command response (if any)
  */
 int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
 			 struct inbound_queue_table *circularQ,
-			 u32 opCode, void *payload, u32 responseQueue)
+			 u32 opCode, void *payload, size_t nb,
+			 u32 responseQueue)
 {
 	u32 Header = 0, hpriority = 0, bc = 1, category = 0x02;
 	void *pMessage;
@@ -1350,10 +1353,13 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
 			pm8001_printk("No free mpi buffer\n"));
 		return -ENOMEM;
 	}
-	BUG_ON(!payload);
-	/*Copy to the payload*/
-	memcpy(pMessage, payload, (pm8001_ha->iomb_size -
-				sizeof(struct mpi_msg_hdr)));
+
+	if (nb > (pm8001_ha->iomb_size - sizeof(struct mpi_msg_hdr)))
+		nb = pm8001_ha->iomb_size - sizeof(struct mpi_msg_hdr);
+	memcpy(pMessage, payload, nb);
+	if (nb + sizeof(struct mpi_msg_hdr) < pm8001_ha->iomb_size)
+		memset(pMessage + nb, 0, pm8001_ha->iomb_size -
+				(nb + sizeof(struct mpi_msg_hdr)));
 
 	/*Build the header*/
 	Header = ((1 << 31) | (hpriority << 30) | ((bc & 0x1f) << 24)
@@ -1763,7 +1769,8 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
 	task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
 	task_abort.tag = cpu_to_le32(ccb_tag);
 
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
+	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort,
+			sizeof(task_abort), 0);
 	if (ret)
 		pm8001_tag_free(pm8001_ha, ccb_tag);
 
@@ -1836,7 +1843,8 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
 	sata_cmd.ncqtag_atap_dir_m |= ((0x1 << 7) | (0x5 << 9));
 	memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
 
-	res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
+	res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd,
+			sizeof(sata_cmd), 0);
 	if (res) {
 		sas_free_task(task);
 		pm8001_tag_free(pm8001_ha, ccb_tag);
@@ -3375,7 +3383,8 @@ static void pm8001_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha,
 		((phyId & 0x0F) << 4) | (port_id & 0x0F));
 	payload.param0 = cpu_to_le32(param0);
 	payload.param1 = cpu_to_le32(param1);
-	pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+			sizeof(payload), 0);
 }
 
 static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
@@ -4305,7 +4314,7 @@ static int pm8001_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
 		cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_resp)-4);
 	build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, &smp_cmd);
 	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
-					(u32 *)&smp_cmd, 0);
+			&smp_cmd, sizeof(smp_cmd), 0);
 	if (rc)
 		goto err_out_2;
 
@@ -4373,7 +4382,8 @@ static int pm8001_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
 		ssp_cmd.len = cpu_to_le32(task->total_xfer_len);
 		ssp_cmd.esgl = 0;
 	}
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd, 0);
+	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd,
+			sizeof(ssp_cmd), 0);
 	return ret;
 }
 
@@ -4482,7 +4492,8 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
 		}
 	}
 
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
+	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd,
+			sizeof(sata_cmd), 0);
 	return ret;
 }
 
@@ -4517,7 +4528,8 @@ pm8001_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
 	memcpy(payload.sas_identify.sas_addr,
 		pm8001_ha->sas_addr, SAS_ADDR_SIZE);
 	payload.sas_identify.phy_id = phy_id;
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
+	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
+			sizeof(payload), 0);
 	return ret;
 }
 
@@ -4539,7 +4551,8 @@ static int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
 	memset(&payload, 0, sizeof(payload));
 	payload.tag = cpu_to_le32(tag);
 	payload.phy_id = cpu_to_le32(phy_id);
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
+	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
+			sizeof(payload), 0);
 	return ret;
 }
 
@@ -4598,7 +4611,8 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
 		cpu_to_le32(ITNT | (firstBurstSize * 0x10000));
 	memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr,
 		SAS_ADDR_SIZE);
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+			sizeof(payload), 0);
 	return rc;
 }
 
@@ -4619,7 +4633,8 @@ int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha,
 	payload.device_id = cpu_to_le32(device_id);
 	PM8001_MSG_DBG(pm8001_ha,
 		pm8001_printk("unregister device device_id = %d\n", device_id));
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+			sizeof(payload), 0);
 	return ret;
 }
 
@@ -4642,7 +4657,8 @@ static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
 	payload.tag = cpu_to_le32(1);
 	payload.phyop_phyid =
 		cpu_to_le32(((phy_op & 0xff) << 8) | (phyId & 0x0F));
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+			sizeof(payload), 0);
 	return ret;
 }
 
@@ -4696,7 +4712,8 @@ static int send_task_abort(struct pm8001_hba_info *pm8001_ha, u32 opc,
 		task_abort.device_id = cpu_to_le32(dev_id);
 		task_abort.tag = cpu_to_le32(cmd_tag);
 	}
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
+	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort,
+			sizeof(task_abort), 0);
 	return ret;
 }
 
@@ -4753,7 +4770,8 @@ int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha,
 	if (pm8001_ha->chip_id != chip_8001)
 		sspTMCmd.ds_ads_m = 0x08;
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd, 0);
+	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd,
+			sizeof(sspTMCmd), 0);
 	return ret;
 }
 
@@ -4843,7 +4861,8 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 	default:
 		break;
 	}
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req,
+			sizeof(nvmd_req), 0);
 	if (rc) {
 		kfree(fw_control_context);
 		pm8001_tag_free(pm8001_ha, tag);
@@ -4927,7 +4946,8 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 	default:
 		break;
 	}
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req,
+			sizeof(nvmd_req), 0);
 	if (rc) {
 		kfree(fw_control_context);
 		pm8001_tag_free(pm8001_ha, tag);
@@ -4962,7 +4982,8 @@ pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha,
 		cpu_to_le32(lower_32_bits(le64_to_cpu(info->sgl.addr)));
 	payload.sgl_addr_hi =
 		cpu_to_le32(upper_32_bits(le64_to_cpu(info->sgl.addr)));
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+			sizeof(payload), 0);
 	return ret;
 }
 
@@ -5109,7 +5130,8 @@ pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha,
 	payload.tag = cpu_to_le32(tag);
 	payload.device_id = cpu_to_le32(pm8001_dev->device_id);
 	payload.nds = cpu_to_le32(state);
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+			sizeof(payload), 0);
 	return rc;
 
 }
@@ -5134,7 +5156,8 @@ pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha)
 	payload.SSAHOLT = cpu_to_le32(0xd << 25);
 	payload.sata_hol_tmo = cpu_to_le32(80);
 	payload.open_reject_cmdretries_data_retries = cpu_to_le32(0xff00ff);
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+			sizeof(payload), 0);
 	if (rc)
 		pm8001_tag_free(pm8001_ha, tag);
 	return rc;
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 9e0da7bccb45..d64883b80da9 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -674,7 +674,8 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr,
 void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha);
 int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
 			struct inbound_queue_table *circularQ,
-			u32 opCode, void *payload, u32 responseQueue);
+			u32 opCode, void *payload, size_t nb,
+			u32 responseQueue);
 int pm8001_mpi_msg_free_get(struct inbound_queue_table *circularQ,
 				u16 messageSize, void **messagePtr);
 u32 pm8001_mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg,
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 9d04e5cfffb4..09008db2efdc 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -955,7 +955,8 @@ pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha)
 		"Setting up thermal config. cfg_pg 0 0x%x cfg_pg 1 0x%x\n",
 		payload.cfg_pg[0], payload.cfg_pg[1]));
 
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+			sizeof(payload), 0);
 	if (rc)
 		pm8001_tag_free(pm8001_ha, tag);
 	return rc;
@@ -1037,7 +1038,8 @@ pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha)
 	memcpy(&payload.cfg_pg, &SASConfigPage,
 			 sizeof(SASProtocolTimerConfig_t));
 
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+			sizeof(payload), 0);
 	if (rc)
 		pm8001_tag_free(pm8001_ha, tag);
 
@@ -1164,7 +1166,8 @@ static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha)
 		"Saving Encryption info to flash. payload 0x%x\n",
 		payload.new_curidx_ksop));
 
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+			sizeof(payload), 0);
 	if (rc)
 		pm8001_tag_free(pm8001_ha, tag);
 
@@ -1517,7 +1520,10 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha,
 	task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
 	task_abort.tag = cpu_to_le32(ccb_tag);
 
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
+	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort,
+			sizeof(task_abort), 0);
+	PM8001_FAIL_DBG(pm8001_ha,
+		pm8001_printk("Executing abort task end\n"));
 	if (ret) {
 		sas_free_task(task);
 		pm8001_tag_free(pm8001_ha, ccb_tag);
@@ -1593,7 +1599,9 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
 	sata_cmd.ncqtag_atap_dir_m_dad |= ((0x1 << 7) | (0x5 << 9));
 	memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
 
-	res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
+	res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd,
+			sizeof(sata_cmd), 0);
+	PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Executing read log end\n"));
 	if (res) {
 		sas_free_task(task);
 		pm8001_tag_free(pm8001_ha, ccb_tag);
@@ -2962,7 +2970,8 @@ static void pm80xx_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha,
 		((phyId & 0xFF) << 24) | (port_id & 0xFF));
 	payload.param0 = cpu_to_le32(param0);
 	payload.param1 = cpu_to_le32(param1);
-	pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+			sizeof(payload), 0);
 }
 
 static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
@@ -4082,8 +4091,8 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
 
 	build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag,
 				&smp_cmd, pm8001_ha->smp_exp_mode, length);
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
-					(u32 *)&smp_cmd, 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &smp_cmd,
+			sizeof(smp_cmd), 0);
 	if (rc)
 		goto err_out_2;
 	return 0;
@@ -4291,7 +4300,7 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
 	}
 	q_index = (u32) (pm8001_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM;
 	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
-						&ssp_cmd, q_index);
+			&ssp_cmd, sizeof(ssp_cmd), q_index);
 	return ret;
 }
 
@@ -4532,7 +4541,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
 	}
 	q_index = (u32) (pm8001_ha_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM;
 	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
-						&sata_cmd, q_index);
+			&sata_cmd, sizeof(sata_cmd), q_index);
 	return ret;
 }
 
@@ -4587,7 +4596,8 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
 	memcpy(payload.sas_identify.sas_addr,
 	  &pm8001_ha->phy[phy_id].dev_sas_addr, SAS_ADDR_SIZE);
 	payload.sas_identify.phy_id = phy_id;
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
+	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
+			sizeof(payload), 0);
 	return ret;
 }
 
@@ -4609,7 +4619,8 @@ static int pm80xx_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
 	memset(&payload, 0, sizeof(payload));
 	payload.tag = cpu_to_le32(tag);
 	payload.phy_id = cpu_to_le32(phy_id);
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
+	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
+			sizeof(payload), 0);
 	return ret;
 }
 
@@ -4675,7 +4686,8 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
 	memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr,
 		SAS_ADDR_SIZE);
 
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+			sizeof(payload), 0);
 	if (rc)
 		pm8001_tag_free(pm8001_ha, tag);
 
@@ -4705,7 +4717,8 @@ static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
 	payload.tag = cpu_to_le32(tag);
 	payload.phyop_phyid =
 		cpu_to_le32(((phy_op & 0xFF) << 8) | (phyId & 0xFF));
-	return pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	return pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+			sizeof(payload), 0);
 }
 
 static u32 pm80xx_chip_is_our_interrupt(struct pm8001_hba_info *pm8001_ha)
@@ -4763,7 +4776,8 @@ void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha,
 		payload.reserved[j] =  cpu_to_le32(*((u32 *)buf + i));
 		j++;
 	}
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+			sizeof(payload), 0);
 	if (rc)
 		pm8001_tag_free(pm8001_ha, tag);
 }
@@ -4805,7 +4819,8 @@ void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha,
 	for (i = 0; i < length; i++)
 		payload.reserved[i] = cpu_to_le32(*(buf + i));
 
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+			sizeof(payload), 0);
 	if (rc)
 		pm8001_tag_free(pm8001_ha, tag);
 
-- 
2.16.3


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

* [PATCH V2 09/13] pm80xx : Cleanup command when a reset times out.
  2019-11-14 10:08 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (7 preceding siblings ...)
  2019-11-14 10:09 ` [PATCH V2 08/13] pm80xx : Fix command issue sizing Deepak Ukey
@ 2019-11-14 10:09 ` Deepak Ukey
  2019-11-18  9:41   ` Jinpu Wang
  2019-11-14 10:09 ` [PATCH V2 10/13] pm80xx : Do not request 12G sas speeds Deepak Ukey
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 21+ messages in thread
From: Deepak Ukey @ 2019-11-14 10:09 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, jsperbeck, auradkar, ianyar

From: peter chang <dpf@google.com>

Added the fix so the if driver properly sent the abort it try to remove
it from the firmware's list of outstanding commands regardless of the
abort status. This means that the task gets free-ed 'now' rather than
possibly getting free-ed later when the scsi layer thinks it's leaked
but still valid.

Signed-off-by: peter chang <dpf@google.com>
Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
---
 drivers/scsi/pm8001/pm8001_sas.c | 50 +++++++++++++++++++++++++++++-----------
 1 file changed, 37 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 4491de8d40fc..b7cbc312843e 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -1204,8 +1204,8 @@ int pm8001_abort_task(struct sas_task *task)
 	pm8001_dev = dev->lldd_dev;
 	pm8001_ha = pm8001_find_ha_by_dev(dev);
 	phy_id = pm8001_dev->attached_phy;
-	rc = pm8001_find_tag(task, &tag);
-	if (rc == 0) {
+	ret = pm8001_find_tag(task, &tag);
+	if (ret == 0) {
 		pm8001_printk("no tag for task:%p\n", task);
 		return TMF_RESP_FUNC_FAILED;
 	}
@@ -1243,26 +1243,50 @@ int pm8001_abort_task(struct sas_task *task)
 
 			/* 2. Send Phy Control Hard Reset */
 			reinit_completion(&completion);
+			phy->port_reset_status = PORT_RESET_TMO;
 			phy->reset_success = false;
 			phy->enable_completion = &completion;
 			phy->reset_completion = &completion_reset;
 			ret = PM8001_CHIP_DISP->phy_ctl_req(pm8001_ha, phy_id,
 				PHY_HARD_RESET);
-			if (ret)
-				goto out;
-			PM8001_MSG_DBG(pm8001_ha,
-				pm8001_printk("Waiting for local phy ctl\n"));
-			wait_for_completion(&completion);
-			if (!phy->reset_success)
+			if (ret) {
+				phy->enable_completion = NULL;
+				phy->reset_completion = NULL;
 				goto out;
+			}
 
-			/* 3. Wait for Port Reset complete / Port reset TMO */
+			/* In the case of the reset timeout/fail we still
+			 * abort the command at the firmware. The assumption
+			 * here is that the drive is off doing something so
+			 * that it's not processing requests, and we want to
+			 * avoid getting a completion for this and either
+			 * leaking the task in libsas or losing the race and
+			 * getting a double free.
+			 */
 			PM8001_MSG_DBG(pm8001_ha,
+				pm8001_printk("Waiting for local phy ctl\n"));
+			ret = wait_for_completion_timeout(&completion,
+					PM8001_TASK_TIMEOUT * HZ);
+			if (!ret || !phy->reset_success) {
+				phy->enable_completion = NULL;
+				phy->reset_completion = NULL;
+			} else {
+				/* 3. Wait for Port Reset complete or
+				 * Port reset TMO
+				 */
+				PM8001_MSG_DBG(pm8001_ha,
 				pm8001_printk("Waiting for Port reset\n"));
-			wait_for_completion(&completion_reset);
-			if (phy->port_reset_status) {
-				pm8001_dev_gone_notify(dev);
-				goto out;
+				ret = wait_for_completion_timeout(
+					&completion_reset,
+					PM8001_TASK_TIMEOUT * HZ);
+				if (!ret)
+					phy->reset_completion = NULL;
+				WARN_ON(phy->port_reset_status ==
+						PORT_RESET_TMO);
+				if (phy->port_reset_status == PORT_RESET_TMO) {
+					pm8001_dev_gone_notify(dev);
+					goto out;
+				}
 			}
 
 			/*
-- 
2.16.3


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

* [PATCH V2 10/13] pm80xx : Do not request 12G sas speeds.
  2019-11-14 10:08 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (8 preceding siblings ...)
  2019-11-14 10:09 ` [PATCH V2 09/13] pm80xx : Cleanup command when a reset times out Deepak Ukey
@ 2019-11-14 10:09 ` Deepak Ukey
  2019-11-14 10:41   ` John Garry
  2019-11-14 10:09 ` [PATCH V2 11/13] pm80xx : Controller fatal error through sysfs Deepak Ukey
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 21+ messages in thread
From: Deepak Ukey @ 2019-11-14 10:09 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, jsperbeck, auradkar, ianyar

From: peter chang <dpf@google.com>

occasionally, 6G capable drives fail to train at 6G on links that look
good from a signal-integrity perspective. PMC suggests configuring the
port to not even expect 12G.

Signed-off-by: peter chang <dpf@google.com>
Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
---
 drivers/scsi/pm8001/pm8001_init.c | 17 +++++++++++++++++
 drivers/scsi/pm8001/pm8001_sas.h  |  1 +
 drivers/scsi/pm8001/pm80xx_hwi.c  | 21 ++++-----------------
 3 files changed, 22 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index b7cc3d05a3e0..86b619d10392 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -41,11 +41,20 @@
 #include <linux/slab.h>
 #include "pm8001_sas.h"
 #include "pm8001_chips.h"
+#include "pm80xx_hwi.h"
 
 static ulong logging_level = PM8001_FAIL_LOGGING | PM8001_IOERR_LOGGING;
 module_param(logging_level, ulong, 0644);
 MODULE_PARM_DESC(logging_level, " bits for enabling logging info.");
 
+static ulong link_rate = LINKRATE_15 | LINKRATE_30 | LINKRATE_60 | LINKRATE_120;
+module_param(link_rate, ulong, 0644);
+MODULE_PARM_DESC(link_rate, "Enable link rate.\n"
+		" 1: Link rate 1.5G\n"
+		" 2: Link rate 3.0G\n"
+		" 4: Link rate 6.0G\n"
+		" 8: Link rate 12.0G\n");
+
 static struct scsi_transport_template *pm8001_stt;
 
 /**
@@ -471,6 +480,14 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
 	pm8001_ha->shost = shost;
 	pm8001_ha->id = pm8001_id++;
 	pm8001_ha->logging_level = logging_level;
+	if (link_rate >= 1 && link_rate <= 15)
+		pm8001_ha->link_rate = (link_rate << 8);
+	else {
+		pm8001_ha->link_rate = LINKRATE_15 | LINKRATE_30 |
+			LINKRATE_60 | LINKRATE_120;
+		PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+			"Setting link rate to default value\n"));
+	}
 	sprintf(pm8001_ha->name, "%s%d", DRV_NAME, pm8001_ha->id);
 	/* IOMB size is 128 for 8088/89 controllers */
 	if (pm8001_ha->chip_id != chip_8001)
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index d64883b80da9..f7be7b85624e 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -546,6 +546,7 @@ struct pm8001_hba_info {
 	struct tasklet_struct	tasklet[PM8001_MAX_MSIX_VEC];
 #endif
 	u32			logging_level;
+	u32			link_rate;
 	u32			fw_status;
 	u32			smp_exp_mode;
 	bool			controller_fatal_error;
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 09008db2efdc..5ca9732f4704 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -37,6 +37,7 @@
  * POSSIBILITY OF SUCH DAMAGES.
  *
  */
+ #include <linux/version.h>
  #include <linux/slab.h>
  #include "pm8001_sas.h"
  #include "pm80xx_hwi.h"
@@ -4565,23 +4566,9 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
 
 	PM8001_INIT_DBG(pm8001_ha,
 		pm8001_printk("PHY START REQ for phy_id %d\n", phy_id));
-	/*
-	 ** [0:7]	PHY Identifier
-	 ** [8:11]	link rate 1.5G, 3G, 6G
-	 ** [12:13] link mode 01b SAS mode; 10b SATA mode; 11b Auto mode
-	 ** [14]	0b disable spin up hold; 1b enable spin up hold
-	 ** [15] ob no change in current PHY analig setup 1b enable using SPAST
-	 */
-	if (!IS_SPCV_12G(pm8001_ha->pdev))
-		payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE |
-				LINKMODE_AUTO | LINKRATE_15 |
-				LINKRATE_30 | LINKRATE_60 | phy_id);
-	else
-		payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE |
-				LINKMODE_AUTO | LINKRATE_15 |
-				LINKRATE_30 | LINKRATE_60 | LINKRATE_120 |
-				phy_id);
 
+	payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE |
+			LINKMODE_AUTO | pm8001_ha->link_rate | phy_id);
 	/* SSC Disable and SAS Analog ST configuration */
 	/**
 	payload.ase_sh_lm_slr_phyid =
@@ -4594,7 +4581,7 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
 	payload.sas_identify.dev_type = SAS_END_DEVICE;
 	payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL;
 	memcpy(payload.sas_identify.sas_addr,
-	  &pm8001_ha->phy[phy_id].dev_sas_addr, SAS_ADDR_SIZE);
+	  &pm8001_ha->sas_addr, SAS_ADDR_SIZE);
 	payload.sas_identify.phy_id = phy_id;
 	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
 			sizeof(payload), 0);
-- 
2.16.3


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

* [PATCH V2 11/13] pm80xx : Controller fatal error through sysfs.
  2019-11-14 10:08 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (9 preceding siblings ...)
  2019-11-14 10:09 ` [PATCH V2 10/13] pm80xx : Do not request 12G sas speeds Deepak Ukey
@ 2019-11-14 10:09 ` Deepak Ukey
  2019-11-18  9:42   ` Jinpu Wang
  2019-11-14 10:09 ` [PATCH V2 12/13] pm80xx : Tie the interrupt name to the module instance Deepak Ukey
                   ` (2 subsequent siblings)
  13 siblings, 1 reply; 21+ messages in thread
From: Deepak Ukey @ 2019-11-14 10:09 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, jsperbeck, auradkar, ianyar

From: Deepak Ukey <Deepak.Ukey@microchip.com>

Added support to check controller fatal error through sysfs.

Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
---
 drivers/scsi/pm8001/pm8001_ctl.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 6b85016b4db3..7c6be2ec110d 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -69,6 +69,25 @@ static ssize_t pm8001_ctl_mpi_interface_rev_show(struct device *cdev,
 static
 DEVICE_ATTR(interface_rev, S_IRUGO, pm8001_ctl_mpi_interface_rev_show, NULL);
 
+/**
+ * controller_fatal_error_show - check controller is under fatal err
+ * @cdev: pointer to embedded class device
+ * @buf: the buffer returned
+ *
+ * A sysfs 'read only' shost attribute.
+ */
+static ssize_t controller_fatal_error_show(struct device *cdev,
+		struct device_attribute *attr, char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(cdev);
+	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+	struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			pm8001_ha->controller_fatal_error);
+}
+static DEVICE_ATTR_RO(controller_fatal_error);
+
 /**
  * pm8001_ctl_fw_version_show - firmware version
  * @cdev: pointer to embedded class device
@@ -804,6 +823,7 @@ static DEVICE_ATTR(update_fw, S_IRUGO|S_IWUSR|S_IWGRP,
 	pm8001_show_update_fw, pm8001_store_update_fw);
 struct device_attribute *pm8001_host_attrs[] = {
 	&dev_attr_interface_rev,
+	&dev_attr_controller_fatal_error,
 	&dev_attr_fw_version,
 	&dev_attr_update_fw,
 	&dev_attr_aap_log,
-- 
2.16.3


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

* [PATCH V2 12/13] pm80xx : Tie the interrupt name to the module instance.
  2019-11-14 10:08 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (10 preceding siblings ...)
  2019-11-14 10:09 ` [PATCH V2 11/13] pm80xx : Controller fatal error through sysfs Deepak Ukey
@ 2019-11-14 10:09 ` Deepak Ukey
  2019-11-14 10:09 ` [PATCH V2 13/13] pm80xx : Modified the logic to collect fatal dump Deepak Ukey
  2019-11-19  4:29 ` [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Martin K. Petersen
  13 siblings, 0 replies; 21+ messages in thread
From: Deepak Ukey @ 2019-11-14 10:09 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, jsperbeck, auradkar, ianyar

From: Vikram Auradkar <auradkar@google.com>

With msix enabled, the interrupt instances are <prefix><index> where
the prefix is fixed for all module instances, making it a little
harder to track down what's what.

Signed-off-by: Vikram Auradkar <auradkar@google.com>
Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
---
 drivers/scsi/pm8001/pm8001_init.c | 11 ++++++-----
 drivers/scsi/pm8001/pm8001_sas.h  |  2 ++
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 86b619d10392..485f0afc53f9 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -894,7 +894,6 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
 	u32 number_of_intr;
 	int flag = 0;
 	int rc;
-	static char intr_drvname[PM8001_MAX_MSIX_VEC][sizeof(DRV_NAME)+3];
 
 	/* SPCv controllers supports 64 msi-x */
 	if (pm8001_ha->chip_id == chip_8001) {
@@ -915,14 +914,16 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
 				rc, pm8001_ha->number_of_intr));
 
 	for (i = 0; i < number_of_intr; i++) {
-		snprintf(intr_drvname[i], sizeof(intr_drvname[0]),
-				DRV_NAME"%d", i);
+		snprintf(pm8001_ha->intr_drvname[i],
+			sizeof(pm8001_ha->intr_drvname[0]),
+			"%s-%d", pm8001_ha->name, i);
 		pm8001_ha->irq_vector[i].irq_id = i;
 		pm8001_ha->irq_vector[i].drv_inst = pm8001_ha;
 
 		rc = request_irq(pci_irq_vector(pm8001_ha->pdev, i),
 			pm8001_interrupt_handler_msix, flag,
-			intr_drvname[i], &(pm8001_ha->irq_vector[i]));
+			pm8001_ha->intr_drvname[i],
+			&(pm8001_ha->irq_vector[i]));
 		if (rc) {
 			for (j = 0; j < i; j++) {
 				free_irq(pci_irq_vector(pm8001_ha->pdev, i),
@@ -963,7 +964,7 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha)
 	pm8001_ha->irq_vector[0].irq_id = 0;
 	pm8001_ha->irq_vector[0].drv_inst = pm8001_ha;
 	rc = request_irq(pdev->irq, pm8001_interrupt_handler_intx, IRQF_SHARED,
-		DRV_NAME, SHOST_TO_SAS_HA(pm8001_ha->shost));
+		pm8001_ha->name, SHOST_TO_SAS_HA(pm8001_ha->shost));
 	return rc;
 }
 
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index f7be7b85624e..a55b03bca529 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -541,6 +541,8 @@ struct pm8001_hba_info {
 	struct pm8001_ccb_info	*ccb_info;
 #ifdef PM8001_USE_MSIX
 	int			number_of_intr;/*will be used in remove()*/
+	char			intr_drvname[PM8001_MAX_MSIX_VEC]
+				[PM8001_NAME_LENGTH+1+3+1];
 #endif
 #ifdef PM8001_USE_TASKLET
 	struct tasklet_struct	tasklet[PM8001_MAX_MSIX_VEC];
-- 
2.16.3


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

* [PATCH V2 13/13] pm80xx : Modified the logic to collect fatal dump.
  2019-11-14 10:08 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (11 preceding siblings ...)
  2019-11-14 10:09 ` [PATCH V2 12/13] pm80xx : Tie the interrupt name to the module instance Deepak Ukey
@ 2019-11-14 10:09 ` Deepak Ukey
  2019-11-18  9:43   ` Jinpu Wang
  2019-11-19  4:29 ` [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Martin K. Petersen
  13 siblings, 1 reply; 21+ messages in thread
From: Deepak Ukey @ 2019-11-14 10:09 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, deepak.ukey, jinpu.wang,
	martin.petersen, dpf, jsperbeck, auradkar, ianyar

From: Deepak Ukey <Deepak.Ukey@microchip.com>

Added the correct method to collect the fatal dump.

Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Reported-by: kbuild test robot <lkp@intel.com>
---
 drivers/scsi/pm8001/pm8001_sas.h |   3 +
 drivers/scsi/pm8001/pm80xx_hwi.c | 251 ++++++++++++++++++++++++++++++---------
 2 files changed, 195 insertions(+), 59 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index a55b03bca529..93438c8f67da 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -152,6 +152,8 @@ struct pm8001_ioctl_payload {
 #define MPI_FATAL_EDUMP_TABLE_HANDSHAKE            0x0C     /* FDDHSHK */
 #define MPI_FATAL_EDUMP_TABLE_STATUS               0x10     /* FDDTSTAT */
 #define MPI_FATAL_EDUMP_TABLE_ACCUM_LEN            0x14     /* ACCDDLEN */
+#define MPI_FATAL_EDUMP_TABLE_TOTAL_LEN		   0x18	    /* TOTALLEN */
+#define MPI_FATAL_EDUMP_TABLE_SIGNATURE		   0x1C     /* SIGNITURE */
 #define MPI_FATAL_EDUMP_HANDSHAKE_RDY              0x1
 #define MPI_FATAL_EDUMP_HANDSHAKE_BUSY             0x0
 #define MPI_FATAL_EDUMP_TABLE_STAT_RSVD                 0x0
@@ -507,6 +509,7 @@ struct pm8001_hba_info {
 	u32			forensic_last_offset;
 	u32			fatal_forensic_shift_offset;
 	u32			forensic_fatal_step;
+	u32			forensic_preserved_accumulated_transfer;
 	u32			evtlog_ib_offset;
 	u32			evtlog_ob_offset;
 	void __iomem	*msg_unit_tbl_addr;/*Message Unit Table Addr*/
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 5ca9732f4704..19601138e889 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -76,7 +76,7 @@ void pm80xx_pci_mem_copy(struct pm8001_hba_info  *pm8001_ha, u32 soffset,
 	destination1 = (u32 *)destination;
 
 	for (index = 0; index < dw_count; index += 4, destination1++) {
-		offset = (soffset + index / 4);
+		offset = (soffset + index);
 		if (offset < (64 * 1024)) {
 			value = pm8001_cr32(pm8001_ha, bus_base_number, offset);
 			*destination1 =  cpu_to_le32(value);
@@ -93,9 +93,12 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
 	struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
 	void __iomem *fatal_table_address = pm8001_ha->fatal_tbl_addr;
 	u32 accum_len , reg_val, index, *temp;
+	u32 status = 1;
 	unsigned long start;
 	u8 *direct_data;
 	char *fatal_error_data = buf;
+	u32 length_to_read;
+	u32 offset;
 
 	pm8001_ha->forensic_info.data_buf.direct_data = buf;
 	if (pm8001_ha->chip_id == chip_8001) {
@@ -105,16 +108,35 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
 		return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
 			(char *)buf;
 	}
+	/* initialize variables for very first call from host application */
 	if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) {
 		PM8001_IO_DBG(pm8001_ha,
 		pm8001_printk("forensic_info TYPE_NON_FATAL..............\n"));
 		direct_data = (u8 *)fatal_error_data;
 		pm8001_ha->forensic_info.data_type = TYPE_NON_FATAL;
 		pm8001_ha->forensic_info.data_buf.direct_len = SYSFS_OFFSET;
+		pm8001_ha->forensic_info.data_buf.direct_offset = 0;
 		pm8001_ha->forensic_info.data_buf.read_len = 0;
+		pm8001_ha->forensic_preserved_accumulated_transfer = 0;
 
-		pm8001_ha->forensic_info.data_buf.direct_data = direct_data;
+		/* Write signature to fatal dump table */
+		pm8001_mw32(fatal_table_address,
+				MPI_FATAL_EDUMP_TABLE_SIGNATURE, 0x1234abcd);
 
+		pm8001_ha->forensic_info.data_buf.direct_data = direct_data;
+		PM8001_IO_DBG(pm8001_ha,
+			pm8001_printk("ossaHwCB: status1 %d\n", status));
+		PM8001_IO_DBG(pm8001_ha,
+			pm8001_printk("ossaHwCB: read_len 0x%x\n",
+			pm8001_ha->forensic_info.data_buf.read_len));
+		PM8001_IO_DBG(pm8001_ha,
+			pm8001_printk("ossaHwCB: direct_len 0x%x\n",
+			pm8001_ha->forensic_info.data_buf.direct_len));
+		PM8001_IO_DBG(pm8001_ha,
+			pm8001_printk("ossaHwCB: direct_offset 0x%x\n",
+			pm8001_ha->forensic_info.data_buf.direct_offset));
+	}
+	if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) {
 		/* start to get data */
 		/* Program the MEMBASE II Shifting Register with 0x00.*/
 		pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,
@@ -127,30 +149,66 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
 	/* Read until accum_len is retrived */
 	accum_len = pm8001_mr32(fatal_table_address,
 				MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
-	PM8001_IO_DBG(pm8001_ha, pm8001_printk("accum_len 0x%x\n",
-						accum_len));
+	/* Determine length of data between previously stored transfer length
+	 * and current accumulated transfer length
+	 */
+	length_to_read =
+		accum_len - pm8001_ha->forensic_preserved_accumulated_transfer;
+	PM8001_IO_DBG(pm8001_ha,
+		pm8001_printk("get_fatal_spcv: accum_len 0x%x\n", accum_len));
+	PM8001_IO_DBG(pm8001_ha,
+		pm8001_printk("get_fatal_spcv: length_to_read 0x%x\n",
+		length_to_read));
+	PM8001_IO_DBG(pm8001_ha,
+		pm8001_printk("get_fatal_spcv: last_offset 0x%x\n",
+		pm8001_ha->forensic_last_offset));
+	PM8001_IO_DBG(pm8001_ha,
+		pm8001_printk("get_fatal_spcv: read_len 0x%x\n",
+		pm8001_ha->forensic_info.data_buf.read_len));
+	PM8001_IO_DBG(pm8001_ha,
+		pm8001_printk("get_fatal_spcv:: direct_len 0x%x\n",
+		pm8001_ha->forensic_info.data_buf.direct_len));
+	PM8001_IO_DBG(pm8001_ha,
+		pm8001_printk("get_fatal_spcv:: direct_offset 0x%x\n",
+		pm8001_ha->forensic_info.data_buf.direct_offset));
+
+	/* If accumulated length failed to read correctly fail the attempt.*/
 	if (accum_len == 0xFFFFFFFF) {
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("Possible PCI issue 0x%x not expected\n",
-				accum_len));
-		return -EIO;
+			accum_len));
+		return status;
 	}
-	if (accum_len == 0 || accum_len >= 0x100000) {
+	/* If accumulated length is zero fail the attempt */
+	if (accum_len == 0) {
 		pm8001_ha->forensic_info.data_buf.direct_data +=
 			sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
-				"%08x ", 0xFFFFFFFF);
+			"%08x ", 0xFFFFFFFF);
 		return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
 			(char *)buf;
 	}
+	/* Accumulated length is good so start capturing the first data */
 	temp = (u32 *)pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr;
 	if (pm8001_ha->forensic_fatal_step == 0) {
 moreData:
+		/* If data to read is less than SYSFS_OFFSET then reduce the
+		 * length of dataLen
+		 */
+		if (pm8001_ha->forensic_last_offset + SYSFS_OFFSET
+				> length_to_read) {
+			pm8001_ha->forensic_info.data_buf.direct_len =
+				length_to_read -
+				pm8001_ha->forensic_last_offset;
+		} else {
+			pm8001_ha->forensic_info.data_buf.direct_len =
+				SYSFS_OFFSET;
+		}
 		if (pm8001_ha->forensic_info.data_buf.direct_data) {
 			/* Data is in bar, copy to host memory */
-			pm80xx_pci_mem_copy(pm8001_ha, pm8001_ha->fatal_bar_loc,
-			 pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr,
-				pm8001_ha->forensic_info.data_buf.direct_len ,
-					1);
+			pm80xx_pci_mem_copy(pm8001_ha,
+			pm8001_ha->fatal_bar_loc,
+			pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr,
+			pm8001_ha->forensic_info.data_buf.direct_len, 1);
 		}
 		pm8001_ha->fatal_bar_loc +=
 			pm8001_ha->forensic_info.data_buf.direct_len;
@@ -161,21 +219,29 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
 		pm8001_ha->forensic_info.data_buf.read_len =
 			pm8001_ha->forensic_info.data_buf.direct_len;
 
-		if (pm8001_ha->forensic_last_offset  >= accum_len) {
+		if (pm8001_ha->forensic_last_offset  >= length_to_read) {
 			pm8001_ha->forensic_info.data_buf.direct_data +=
 			sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
 				"%08x ", 3);
-			for (index = 0; index < (SYSFS_OFFSET / 4); index++) {
+			for (index = 0; index <
+				(pm8001_ha->forensic_info.data_buf.direct_len
+				 / 4); index++) {
 				pm8001_ha->forensic_info.data_buf.direct_data +=
-					sprintf(pm8001_ha->
-					 forensic_info.data_buf.direct_data,
-						"%08x ", *(temp + index));
+				sprintf(
+				pm8001_ha->forensic_info.data_buf.direct_data,
+				"%08x ", *(temp + index));
 			}
 
 			pm8001_ha->fatal_bar_loc = 0;
 			pm8001_ha->forensic_fatal_step = 1;
 			pm8001_ha->fatal_forensic_shift_offset = 0;
 			pm8001_ha->forensic_last_offset	= 0;
+			status = 0;
+			offset = (int)
+			((char *)pm8001_ha->forensic_info.data_buf.direct_data
+			- (char *)buf);
+			PM8001_IO_DBG(pm8001_ha,
+			pm8001_printk("get_fatal_spcv:return1 0x%x\n", offset));
 			return (char *)pm8001_ha->
 				forensic_info.data_buf.direct_data -
 				(char *)buf;
@@ -185,12 +251,20 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
 				sprintf(pm8001_ha->
 					forensic_info.data_buf.direct_data,
 					"%08x ", 2);
-			for (index = 0; index < (SYSFS_OFFSET / 4); index++) {
-				pm8001_ha->forensic_info.data_buf.direct_data +=
-					sprintf(pm8001_ha->
+			for (index = 0; index <
+				(pm8001_ha->forensic_info.data_buf.direct_len
+				 / 4); index++) {
+				pm8001_ha->forensic_info.data_buf.direct_data
+					+= sprintf(pm8001_ha->
 					forensic_info.data_buf.direct_data,
 					"%08x ", *(temp + index));
 			}
+			status = 0;
+			offset = (int)
+			((char *)pm8001_ha->forensic_info.data_buf.direct_data
+			- (char *)buf);
+			PM8001_IO_DBG(pm8001_ha,
+			pm8001_printk("get_fatal_spcv:return2 0x%x\n", offset));
 			return (char *)pm8001_ha->
 				forensic_info.data_buf.direct_data -
 				(char *)buf;
@@ -200,63 +274,122 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
 		pm8001_ha->forensic_info.data_buf.direct_data +=
 			sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
 				"%08x ", 2);
-		for (index = 0; index < 256; index++) {
+		for (index = 0; index <
+			(pm8001_ha->forensic_info.data_buf.direct_len
+			 / 4) ; index++) {
 			pm8001_ha->forensic_info.data_buf.direct_data +=
 				sprintf(pm8001_ha->
-					forensic_info.data_buf.direct_data,
-						"%08x ", *(temp + index));
+				forensic_info.data_buf.direct_data,
+				"%08x ", *(temp + index));
 		}
 		pm8001_ha->fatal_forensic_shift_offset += 0x100;
 		pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,
 			pm8001_ha->fatal_forensic_shift_offset);
 		pm8001_ha->fatal_bar_loc = 0;
+		status = 0;
+		offset = (int)
+			((char *)pm8001_ha->forensic_info.data_buf.direct_data
+			- (char *)buf);
+		PM8001_IO_DBG(pm8001_ha,
+		pm8001_printk("get_fatal_spcv: return3 0x%x\n", offset));
 		return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
 			(char *)buf;
 	}
 	if (pm8001_ha->forensic_fatal_step == 1) {
-		pm8001_ha->fatal_forensic_shift_offset = 0;
-		/* Read 64K of the debug data. */
-		pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,
-			pm8001_ha->fatal_forensic_shift_offset);
-		pm8001_mw32(fatal_table_address,
-			MPI_FATAL_EDUMP_TABLE_HANDSHAKE,
+		/* store previous accumulated length before triggering next
+		 * accumulated length update
+		 */
+		pm8001_ha->forensic_preserved_accumulated_transfer =
+			pm8001_mr32(fatal_table_address,
+			MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
+
+		/* continue capturing the fatal log until Dump status is 0x3 */
+		if (pm8001_mr32(fatal_table_address,
+			MPI_FATAL_EDUMP_TABLE_STATUS) <
+			MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) {
+
+			/* reset fddstat bit by writing to zero*/
+			pm8001_mw32(fatal_table_address,
+					MPI_FATAL_EDUMP_TABLE_STATUS, 0x0);
+
+			/* set dump control value to '1' so that new data will
+			 * be transferred to shared memory
+			 */
+			pm8001_mw32(fatal_table_address,
+				MPI_FATAL_EDUMP_TABLE_HANDSHAKE,
 				MPI_FATAL_EDUMP_HANDSHAKE_RDY);
 
-		/* Poll FDDHSHK  until clear  */
-		start = jiffies + (2 * HZ); /* 2 sec */
+			/*Poll FDDHSHK  until clear */
+			start = jiffies + (2 * HZ); /* 2 sec */
 
-		do {
-			reg_val = pm8001_mr32(fatal_table_address,
+			do {
+				reg_val = pm8001_mr32(fatal_table_address,
 					MPI_FATAL_EDUMP_TABLE_HANDSHAKE);
-		} while ((reg_val) && time_before(jiffies, start));
+			} while ((reg_val) && time_before(jiffies, start));
 
-		if (reg_val != 0) {
-			PM8001_FAIL_DBG(pm8001_ha,
-			pm8001_printk("TIMEOUT:MEMBASE_II_SHIFT_REGISTER"
-			" = 0x%x\n", reg_val));
-			return -EIO;
-		}
-
-		/* Read the next 64K of the debug data. */
-		pm8001_ha->forensic_fatal_step = 0;
-		if (pm8001_mr32(fatal_table_address,
-			MPI_FATAL_EDUMP_TABLE_STATUS) !=
-				MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) {
-			pm8001_mw32(fatal_table_address,
-				MPI_FATAL_EDUMP_TABLE_HANDSHAKE, 0);
-			goto moreData;
-		} else {
-			pm8001_ha->forensic_info.data_buf.direct_data +=
-				sprintf(pm8001_ha->
-					forensic_info.data_buf.direct_data,
-						"%08x ", 4);
-			pm8001_ha->forensic_info.data_buf.read_len = 0xFFFFFFFF;
-			pm8001_ha->forensic_info.data_buf.direct_len =  0;
-			pm8001_ha->forensic_info.data_buf.direct_offset = 0;
-			pm8001_ha->forensic_info.data_buf.read_len = 0;
+			if (reg_val != 0) {
+				PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+				"TIMEOUT:MPI_FATAL_EDUMP_TABLE_HDSHAKE 0x%x\n",
+				reg_val));
+			       /* Fail the dump if a timeout occurs */
+				pm8001_ha->forensic_info.data_buf.direct_data +=
+				sprintf(
+				pm8001_ha->forensic_info.data_buf.direct_data,
+				"%08x ", 0xFFFFFFFF);
+				return((char *)
+				pm8001_ha->forensic_info.data_buf.direct_data
+				- (char *)buf);
+			}
+			/* Poll status register until set to 2 or
+			 * 3 for up to 2 seconds
+			 */
+			start = jiffies + (2 * HZ); /* 2 sec */
+
+			do {
+				reg_val = pm8001_mr32(fatal_table_address,
+					MPI_FATAL_EDUMP_TABLE_STATUS);
+			} while (((reg_val != 2) || (reg_val != 3)) &&
+					time_before(jiffies, start));
+
+			if (reg_val < 2) {
+				PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+				"TIMEOUT:MPI_FATAL_EDUMP_TABLE_STATUS = 0x%x\n",
+				reg_val));
+				/* Fail the dump if a timeout occurs */
+				pm8001_ha->forensic_info.data_buf.direct_data +=
+				sprintf(
+				pm8001_ha->forensic_info.data_buf.direct_data,
+				"%08x ", 0xFFFFFFFF);
+				pm8001_cw32(pm8001_ha, 0,
+					MEMBASE_II_SHIFT_REGISTER,
+					pm8001_ha->fatal_forensic_shift_offset);
+			}
+			/* Read the next block of the debug data.*/
+			length_to_read = pm8001_mr32(fatal_table_address,
+			MPI_FATAL_EDUMP_TABLE_ACCUM_LEN) -
+			pm8001_ha->forensic_preserved_accumulated_transfer;
+			if (length_to_read != 0x0) {
+				pm8001_ha->forensic_fatal_step = 0;
+				goto moreData;
+			} else {
+				pm8001_ha->forensic_info.data_buf.direct_data +=
+				sprintf(
+				pm8001_ha->forensic_info.data_buf.direct_data,
+				"%08x ", 4);
+				pm8001_ha->forensic_info.data_buf.read_len
+								= 0xFFFFFFFF;
+				pm8001_ha->forensic_info.data_buf.direct_len
+								=  0;
+				pm8001_ha->forensic_info.data_buf.direct_offset
+								= 0;
+				pm8001_ha->forensic_info.data_buf.read_len = 0;
+			}
 		}
 	}
-
+	offset = (int)((char *)pm8001_ha->forensic_info.data_buf.direct_data
+			- (char *)buf);
+	PM8001_IO_DBG(pm8001_ha,
+		pm8001_printk("get_fatal_spcv: return4 0x%x\n", offset));
 	return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
 		(char *)buf;
 }
-- 
2.16.3


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

* Re: [PATCH V2 10/13] pm80xx : Do not request 12G sas speeds.
  2019-11-14 10:09 ` [PATCH V2 10/13] pm80xx : Do not request 12G sas speeds Deepak Ukey
@ 2019-11-14 10:41   ` John Garry
  0 siblings, 0 replies; 21+ messages in thread
From: John Garry @ 2019-11-14 10:41 UTC (permalink / raw)
  To: Deepak Ukey, linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, jinpu.wang,
	martin.petersen, dpf, jsperbeck, auradkar, ianyar

On 14/11/2019 10:09, Deepak Ukey wrote:
> From: peter chang <dpf@google.com>
> 
> occasionally, 6G capable drives fail to train at 6G on links that look
> good from a signal-integrity perspective. PMC suggests configuring the
> port to not even expect 12G.

We can set the PHY max hw linkrate at 6Gbps via sysfs, but I assume that 
this is not good enough.

So could the driver has the intelligence to know the training failed, 
and reset the max linkrate accordingly and retry?

It just seems that adding a module parameter to set the max linkrate is 
a little heavy handed.

BTW, how is this handled in the phy control rate callback, 
pm8001_phy_control? Would 6Gbps be set as PHY hw linkrate?

Thanks,
John

> Signed-off-by: peter chang <dpf@google.com>
> Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
> Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
> ---
>   drivers/scsi/pm8001/pm8001_init.c | 17 +++++++++++++++++
>   drivers/scsi/pm8001/pm8001_sas.h  |  1 +
>   drivers/scsi/pm8001/pm80xx_hwi.c  | 21 ++++-----------------
>   3 files changed, 22 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
> index b7cc3d05a3e0..86b619d10392 100644
> --- a/drivers/scsi/pm8001/pm8001_init.c
> +++ b/drivers/scsi/pm8001/pm8001_init.c
> @@ -41,11 +41,20 @@
>   #include <linux/slab.h>
>   #include "pm8001_sas.h"
>   #include "pm8001_chips.h"
> +#include "pm80xx_hwi.h"
>   
>   static ulong logging_level = PM8001_FAIL_LOGGING | PM8001_IOERR_LOGGING;
>   module_param(logging_level, ulong, 0644);
>   MODULE_PARM_DESC(logging_level, " bits for enabling logging info.");
>   
> +static ulong link_rate = LINKRATE_15 | LINKRATE_30 | LINKRATE_60 | LINKRATE_120;
> +module_param(link_rate, ulong, 0644);
> +MODULE_PARM_DESC(link_rate, "Enable link rate.\n"
> +		" 1: Link rate 1.5G\n"
> +		" 2: Link rate 3.0G\n"
> +		" 4: Link rate 6.0G\n"
> +		" 8: Link rate 12.0G\n");
> +
>   static struct scsi_transport_template *pm8001_stt;
>   
>   /**
> @@ -471,6 +480,14 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
>   	pm8001_ha->shost = shost;
>   	pm8001_ha->id = pm8001_id++;
>   	pm8001_ha->logging_level = logging_level;
> +	if (link_rate >= 1 && link_rate <= 15)
> +		pm8001_ha->link_rate = (link_rate << 8);
> +	else {
> +		pm8001_ha->link_rate = LINKRATE_15 | LINKRATE_30 |
> +			LINKRATE_60 | LINKRATE_120;
> +		PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
> +			"Setting link rate to default value\n"));
> +	}
>   	sprintf(pm8001_ha->name, "%s%d", DRV_NAME, pm8001_ha->id);
>   	/* IOMB size is 128 for 8088/89 controllers */
>   	if (pm8001_ha->chip_id != chip_8001)
> diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
> index d64883b80da9..f7be7b85624e 100644
> --- a/drivers/scsi/pm8001/pm8001_sas.h
> +++ b/drivers/scsi/pm8001/pm8001_sas.h
> @@ -546,6 +546,7 @@ struct pm8001_hba_info {
>   	struct tasklet_struct	tasklet[PM8001_MAX_MSIX_VEC];
>   #endif
>   	u32			logging_level;
> +	u32			link_rate;
>   	u32			fw_status;
>   	u32			smp_exp_mode;
>   	bool			controller_fatal_error;
> diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
> index 09008db2efdc..5ca9732f4704 100644
> --- a/drivers/scsi/pm8001/pm80xx_hwi.c
> +++ b/drivers/scsi/pm8001/pm80xx_hwi.c
> @@ -37,6 +37,7 @@
>    * POSSIBILITY OF SUCH DAMAGES.
>    *
>    */
> + #include <linux/version.h>
>    #include <linux/slab.h>
>    #include "pm8001_sas.h"
>    #include "pm80xx_hwi.h"
> @@ -4565,23 +4566,9 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
>   
>   	PM8001_INIT_DBG(pm8001_ha,
>   		pm8001_printk("PHY START REQ for phy_id %d\n", phy_id));
> -	/*
> -	 ** [0:7]	PHY Identifier
> -	 ** [8:11]	link rate 1.5G, 3G, 6G
> -	 ** [12:13] link mode 01b SAS mode; 10b SATA mode; 11b Auto mode
> -	 ** [14]	0b disable spin up hold; 1b enable spin up hold
> -	 ** [15] ob no change in current PHY analig setup 1b enable using SPAST
> -	 */
> -	if (!IS_SPCV_12G(pm8001_ha->pdev))
> -		payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE |
> -				LINKMODE_AUTO | LINKRATE_15 |
> -				LINKRATE_30 | LINKRATE_60 | phy_id);
> -	else
> -		payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE |
> -				LINKMODE_AUTO | LINKRATE_15 |
> -				LINKRATE_30 | LINKRATE_60 | LINKRATE_120 |
> -				phy_id);
>   
> +	payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE |
> +			LINKMODE_AUTO | pm8001_ha->link_rate | phy_id);
>   	/* SSC Disable and SAS Analog ST configuration */
>   	/**
>   	payload.ase_sh_lm_slr_phyid =
> @@ -4594,7 +4581,7 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
>   	payload.sas_identify.dev_type = SAS_END_DEVICE;
>   	payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL;
>   	memcpy(payload.sas_identify.sas_addr,
> -	  &pm8001_ha->phy[phy_id].dev_sas_addr, SAS_ADDR_SIZE);
> +	  &pm8001_ha->sas_addr, SAS_ADDR_SIZE);
>   	payload.sas_identify.phy_id = phy_id;
>   	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
>   			sizeof(payload), 0);
> 


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

* Re: [PATCH V2 01/13] pm80xx : Fix for SATA device discovery.
  2019-11-14 10:08 ` [PATCH V2 01/13] pm80xx : Fix for SATA device discovery Deepak Ukey
@ 2019-11-18  9:00   ` Jinpu Wang
  0 siblings, 0 replies; 21+ messages in thread
From: Jinpu Wang @ 2019-11-18  9:00 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas.G,
	Jack Wang, Martin K. Petersen, dpf, jsperbeck, Vikram Auradkar,
	ianyar

On Thu, Nov 14, 2019 at 11:08 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: peter chang <dpf@google.com>
>
> Driver was  missing complete() call in mpi_sata_completion which
> result in SATA abort error handling is timing out. That causes the
> device to be left in the in_recovery state so subsequent commands
> sent to the device fail and the OS removes access to it.
>
> Signed-off-by: peter chang <dpf@google.com>
> Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
Thanks
> ---
>  drivers/scsi/pm8001/pm80xx_hwi.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
> index 73261902d75d..161bf4760eac 100644
> --- a/drivers/scsi/pm8001/pm80xx_hwi.c
> +++ b/drivers/scsi/pm8001/pm80xx_hwi.c
> @@ -2382,6 +2382,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                         pm8001_printk("task 0x%p done with io_status 0x%x"
>                         " resp 0x%x stat 0x%x but aborted by upper layer!\n",
>                         t, status, ts->resp, ts->stat));
> +               if (t->slow_task)
> +                       complete(&t->slow_task->completion);
>                 pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
>         } else {
>                 spin_unlock_irqrestore(&t->task_state_lock, flags);
> --
> 2.16.3
>

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

* Re: [PATCH V2 02/13] pm80xx : Make phy enable completion as NULL.
  2019-11-14 10:08 ` [PATCH V2 02/13] pm80xx : Make phy enable completion as NULL Deepak Ukey
@ 2019-11-18  9:01   ` Jinpu Wang
  0 siblings, 0 replies; 21+ messages in thread
From: Jinpu Wang @ 2019-11-18  9:01 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas.G,
	Jack Wang, Martin K. Petersen, dpf, jsperbeck, Vikram Auradkar,
	ianyar

On Thu, Nov 14, 2019 at 11:08 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: peter chang <dpf@google.com>
>
> After the completing the mpi_phy_start_resp make phy enable completion
> as NULL.
>
> Signed-off-by: peter chang <dpf@google.com>
> Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
Thanks

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

* Re: [PATCH V2 09/13] pm80xx : Cleanup command when a reset times out.
  2019-11-14 10:09 ` [PATCH V2 09/13] pm80xx : Cleanup command when a reset times out Deepak Ukey
@ 2019-11-18  9:41   ` Jinpu Wang
  0 siblings, 0 replies; 21+ messages in thread
From: Jinpu Wang @ 2019-11-18  9:41 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas.G,
	Jack Wang, Martin K. Petersen, dpf, jsperbeck, Vikram Auradkar,
	ianyar

On Thu, Nov 14, 2019 at 11:08 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: peter chang <dpf@google.com>
>
> Added the fix so the if driver properly sent the abort it try to remove
> it from the firmware's list of outstanding commands regardless of the
> abort status. This means that the task gets free-ed 'now' rather than
> possibly getting free-ed later when the scsi layer thinks it's leaked
> but still valid.
>
> Signed-off-by: peter chang <dpf@google.com>
> Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
Thanks
> ---
>  drivers/scsi/pm8001/pm8001_sas.c | 50 +++++++++++++++++++++++++++++-----------
>  1 file changed, 37 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
> index 4491de8d40fc..b7cbc312843e 100644
> --- a/drivers/scsi/pm8001/pm8001_sas.c
> +++ b/drivers/scsi/pm8001/pm8001_sas.c
> @@ -1204,8 +1204,8 @@ int pm8001_abort_task(struct sas_task *task)
>         pm8001_dev = dev->lldd_dev;
>         pm8001_ha = pm8001_find_ha_by_dev(dev);
>         phy_id = pm8001_dev->attached_phy;
> -       rc = pm8001_find_tag(task, &tag);
> -       if (rc == 0) {
> +       ret = pm8001_find_tag(task, &tag);
> +       if (ret == 0) {
>                 pm8001_printk("no tag for task:%p\n", task);
>                 return TMF_RESP_FUNC_FAILED;
>         }
> @@ -1243,26 +1243,50 @@ int pm8001_abort_task(struct sas_task *task)
>
>                         /* 2. Send Phy Control Hard Reset */
>                         reinit_completion(&completion);
> +                       phy->port_reset_status = PORT_RESET_TMO;
>                         phy->reset_success = false;
>                         phy->enable_completion = &completion;
>                         phy->reset_completion = &completion_reset;
>                         ret = PM8001_CHIP_DISP->phy_ctl_req(pm8001_ha, phy_id,
>                                 PHY_HARD_RESET);
> -                       if (ret)
> -                               goto out;
> -                       PM8001_MSG_DBG(pm8001_ha,
> -                               pm8001_printk("Waiting for local phy ctl\n"));
> -                       wait_for_completion(&completion);
> -                       if (!phy->reset_success)
> +                       if (ret) {
> +                               phy->enable_completion = NULL;
> +                               phy->reset_completion = NULL;
>                                 goto out;
> +                       }
>
> -                       /* 3. Wait for Port Reset complete / Port reset TMO */
> +                       /* In the case of the reset timeout/fail we still
> +                        * abort the command at the firmware. The assumption
> +                        * here is that the drive is off doing something so
> +                        * that it's not processing requests, and we want to
> +                        * avoid getting a completion for this and either
> +                        * leaking the task in libsas or losing the race and
> +                        * getting a double free.
> +                        */
>                         PM8001_MSG_DBG(pm8001_ha,
> +                               pm8001_printk("Waiting for local phy ctl\n"));
> +                       ret = wait_for_completion_timeout(&completion,
> +                                       PM8001_TASK_TIMEOUT * HZ);
> +                       if (!ret || !phy->reset_success) {
> +                               phy->enable_completion = NULL;
> +                               phy->reset_completion = NULL;
> +                       } else {
> +                               /* 3. Wait for Port Reset complete or
> +                                * Port reset TMO
> +                                */
> +                               PM8001_MSG_DBG(pm8001_ha,
>                                 pm8001_printk("Waiting for Port reset\n"));
> -                       wait_for_completion(&completion_reset);
> -                       if (phy->port_reset_status) {
> -                               pm8001_dev_gone_notify(dev);
> -                               goto out;
> +                               ret = wait_for_completion_timeout(
> +                                       &completion_reset,
> +                                       PM8001_TASK_TIMEOUT * HZ);
> +                               if (!ret)
> +                                       phy->reset_completion = NULL;
> +                               WARN_ON(phy->port_reset_status ==
> +                                               PORT_RESET_TMO);
> +                               if (phy->port_reset_status == PORT_RESET_TMO) {
> +                                       pm8001_dev_gone_notify(dev);
> +                                       goto out;
> +                               }
>                         }
>
>                         /*
> --
> 2.16.3
>

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

* Re: [PATCH V2 11/13] pm80xx : Controller fatal error through sysfs.
  2019-11-14 10:09 ` [PATCH V2 11/13] pm80xx : Controller fatal error through sysfs Deepak Ukey
@ 2019-11-18  9:42   ` Jinpu Wang
  0 siblings, 0 replies; 21+ messages in thread
From: Jinpu Wang @ 2019-11-18  9:42 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas.G,
	Jack Wang, Martin K. Petersen, dpf, jsperbeck, Vikram Auradkar,
	ianyar

On Thu, Nov 14, 2019 at 11:08 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: Deepak Ukey <Deepak.Ukey@microchip.com>
>
> Added support to check controller fatal error through sysfs.
>
> Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
> ---
>  drivers/scsi/pm8001/pm8001_ctl.c | 20 ++++++++++++++++++++
>  1 file changed, 20 insertions(+)
>
> diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
> index 6b85016b4db3..7c6be2ec110d 100644
> --- a/drivers/scsi/pm8001/pm8001_ctl.c
> +++ b/drivers/scsi/pm8001/pm8001_ctl.c
> @@ -69,6 +69,25 @@ static ssize_t pm8001_ctl_mpi_interface_rev_show(struct device *cdev,
>  static
>  DEVICE_ATTR(interface_rev, S_IRUGO, pm8001_ctl_mpi_interface_rev_show, NULL);
>
> +/**
> + * controller_fatal_error_show - check controller is under fatal err
> + * @cdev: pointer to embedded class device
> + * @buf: the buffer returned
> + *
> + * A sysfs 'read only' shost attribute.
> + */
> +static ssize_t controller_fatal_error_show(struct device *cdev,
> +               struct device_attribute *attr, char *buf)
> +{
> +       struct Scsi_Host *shost = class_to_shost(cdev);
> +       struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
> +       struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
> +
> +       return snprintf(buf, PAGE_SIZE, "%d\n",
> +                       pm8001_ha->controller_fatal_error);
> +}
> +static DEVICE_ATTR_RO(controller_fatal_error);
> +
>  /**
>   * pm8001_ctl_fw_version_show - firmware version
>   * @cdev: pointer to embedded class device
> @@ -804,6 +823,7 @@ static DEVICE_ATTR(update_fw, S_IRUGO|S_IWUSR|S_IWGRP,
>         pm8001_show_update_fw, pm8001_store_update_fw);
>  struct device_attribute *pm8001_host_attrs[] = {
>         &dev_attr_interface_rev,
> +       &dev_attr_controller_fatal_error,
>         &dev_attr_fw_version,
>         &dev_attr_update_fw,
>         &dev_attr_aap_log,
> --
> 2.16.3
>

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

* Re: [PATCH V2 13/13] pm80xx : Modified the logic to collect fatal dump.
  2019-11-14 10:09 ` [PATCH V2 13/13] pm80xx : Modified the logic to collect fatal dump Deepak Ukey
@ 2019-11-18  9:43   ` Jinpu Wang
  0 siblings, 0 replies; 21+ messages in thread
From: Jinpu Wang @ 2019-11-18  9:43 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas.G,
	Jack Wang, Martin K. Petersen, dpf, jsperbeck, Vikram Auradkar,
	ianyar

On Thu, Nov 14, 2019 at 11:08 AM Deepak Ukey <deepak.ukey@microchip.com> wrote:
>
> From: Deepak Ukey <Deepak.Ukey@microchip.com>
>
> Added the correct method to collect the fatal dump.
>
> Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
> Reported-by: kbuild test robot <lkp@intel.com>
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
> ---
>  drivers/scsi/pm8001/pm8001_sas.h |   3 +
>  drivers/scsi/pm8001/pm80xx_hwi.c | 251 ++++++++++++++++++++++++++++++---------
>  2 files changed, 195 insertions(+), 59 deletions(-)
>
> diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
> index a55b03bca529..93438c8f67da 100644
> --- a/drivers/scsi/pm8001/pm8001_sas.h
> +++ b/drivers/scsi/pm8001/pm8001_sas.h
> @@ -152,6 +152,8 @@ struct pm8001_ioctl_payload {
>  #define MPI_FATAL_EDUMP_TABLE_HANDSHAKE            0x0C     /* FDDHSHK */
>  #define MPI_FATAL_EDUMP_TABLE_STATUS               0x10     /* FDDTSTAT */
>  #define MPI_FATAL_EDUMP_TABLE_ACCUM_LEN            0x14     /* ACCDDLEN */
> +#define MPI_FATAL_EDUMP_TABLE_TOTAL_LEN                   0x18     /* TOTALLEN */
> +#define MPI_FATAL_EDUMP_TABLE_SIGNATURE                   0x1C     /* SIGNITURE */
>  #define MPI_FATAL_EDUMP_HANDSHAKE_RDY              0x1
>  #define MPI_FATAL_EDUMP_HANDSHAKE_BUSY             0x0
>  #define MPI_FATAL_EDUMP_TABLE_STAT_RSVD                 0x0
> @@ -507,6 +509,7 @@ struct pm8001_hba_info {
>         u32                     forensic_last_offset;
>         u32                     fatal_forensic_shift_offset;
>         u32                     forensic_fatal_step;
> +       u32                     forensic_preserved_accumulated_transfer;
>         u32                     evtlog_ib_offset;
>         u32                     evtlog_ob_offset;
>         void __iomem    *msg_unit_tbl_addr;/*Message Unit Table Addr*/
> diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
> index 5ca9732f4704..19601138e889 100644
> --- a/drivers/scsi/pm8001/pm80xx_hwi.c
> +++ b/drivers/scsi/pm8001/pm80xx_hwi.c
> @@ -76,7 +76,7 @@ void pm80xx_pci_mem_copy(struct pm8001_hba_info  *pm8001_ha, u32 soffset,
>         destination1 = (u32 *)destination;
>
>         for (index = 0; index < dw_count; index += 4, destination1++) {
> -               offset = (soffset + index / 4);
> +               offset = (soffset + index);
>                 if (offset < (64 * 1024)) {
>                         value = pm8001_cr32(pm8001_ha, bus_base_number, offset);
>                         *destination1 =  cpu_to_le32(value);
> @@ -93,9 +93,12 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
>         struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
>         void __iomem *fatal_table_address = pm8001_ha->fatal_tbl_addr;
>         u32 accum_len , reg_val, index, *temp;
> +       u32 status = 1;
>         unsigned long start;
>         u8 *direct_data;
>         char *fatal_error_data = buf;
> +       u32 length_to_read;
> +       u32 offset;
>
>         pm8001_ha->forensic_info.data_buf.direct_data = buf;
>         if (pm8001_ha->chip_id == chip_8001) {
> @@ -105,16 +108,35 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
>                 return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
>                         (char *)buf;
>         }
> +       /* initialize variables for very first call from host application */
>         if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) {
>                 PM8001_IO_DBG(pm8001_ha,
>                 pm8001_printk("forensic_info TYPE_NON_FATAL..............\n"));
>                 direct_data = (u8 *)fatal_error_data;
>                 pm8001_ha->forensic_info.data_type = TYPE_NON_FATAL;
>                 pm8001_ha->forensic_info.data_buf.direct_len = SYSFS_OFFSET;
> +               pm8001_ha->forensic_info.data_buf.direct_offset = 0;
>                 pm8001_ha->forensic_info.data_buf.read_len = 0;
> +               pm8001_ha->forensic_preserved_accumulated_transfer = 0;
>
> -               pm8001_ha->forensic_info.data_buf.direct_data = direct_data;
> +               /* Write signature to fatal dump table */
> +               pm8001_mw32(fatal_table_address,
> +                               MPI_FATAL_EDUMP_TABLE_SIGNATURE, 0x1234abcd);
>
> +               pm8001_ha->forensic_info.data_buf.direct_data = direct_data;
> +               PM8001_IO_DBG(pm8001_ha,
> +                       pm8001_printk("ossaHwCB: status1 %d\n", status));
> +               PM8001_IO_DBG(pm8001_ha,
> +                       pm8001_printk("ossaHwCB: read_len 0x%x\n",
> +                       pm8001_ha->forensic_info.data_buf.read_len));
> +               PM8001_IO_DBG(pm8001_ha,
> +                       pm8001_printk("ossaHwCB: direct_len 0x%x\n",
> +                       pm8001_ha->forensic_info.data_buf.direct_len));
> +               PM8001_IO_DBG(pm8001_ha,
> +                       pm8001_printk("ossaHwCB: direct_offset 0x%x\n",
> +                       pm8001_ha->forensic_info.data_buf.direct_offset));
> +       }
> +       if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) {
>                 /* start to get data */
>                 /* Program the MEMBASE II Shifting Register with 0x00.*/
>                 pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,
> @@ -127,30 +149,66 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
>         /* Read until accum_len is retrived */
>         accum_len = pm8001_mr32(fatal_table_address,
>                                 MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
> -       PM8001_IO_DBG(pm8001_ha, pm8001_printk("accum_len 0x%x\n",
> -                                               accum_len));
> +       /* Determine length of data between previously stored transfer length
> +        * and current accumulated transfer length
> +        */
> +       length_to_read =
> +               accum_len - pm8001_ha->forensic_preserved_accumulated_transfer;
> +       PM8001_IO_DBG(pm8001_ha,
> +               pm8001_printk("get_fatal_spcv: accum_len 0x%x\n", accum_len));
> +       PM8001_IO_DBG(pm8001_ha,
> +               pm8001_printk("get_fatal_spcv: length_to_read 0x%x\n",
> +               length_to_read));
> +       PM8001_IO_DBG(pm8001_ha,
> +               pm8001_printk("get_fatal_spcv: last_offset 0x%x\n",
> +               pm8001_ha->forensic_last_offset));
> +       PM8001_IO_DBG(pm8001_ha,
> +               pm8001_printk("get_fatal_spcv: read_len 0x%x\n",
> +               pm8001_ha->forensic_info.data_buf.read_len));
> +       PM8001_IO_DBG(pm8001_ha,
> +               pm8001_printk("get_fatal_spcv:: direct_len 0x%x\n",
> +               pm8001_ha->forensic_info.data_buf.direct_len));
> +       PM8001_IO_DBG(pm8001_ha,
> +               pm8001_printk("get_fatal_spcv:: direct_offset 0x%x\n",
> +               pm8001_ha->forensic_info.data_buf.direct_offset));
> +
> +       /* If accumulated length failed to read correctly fail the attempt.*/
>         if (accum_len == 0xFFFFFFFF) {
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("Possible PCI issue 0x%x not expected\n",
> -                               accum_len));
> -               return -EIO;
> +                       accum_len));
> +               return status;
>         }
> -       if (accum_len == 0 || accum_len >= 0x100000) {
> +       /* If accumulated length is zero fail the attempt */
> +       if (accum_len == 0) {
>                 pm8001_ha->forensic_info.data_buf.direct_data +=
>                         sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
> -                               "%08x ", 0xFFFFFFFF);
> +                       "%08x ", 0xFFFFFFFF);
>                 return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
>                         (char *)buf;
>         }
> +       /* Accumulated length is good so start capturing the first data */
>         temp = (u32 *)pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr;
>         if (pm8001_ha->forensic_fatal_step == 0) {
>  moreData:
> +               /* If data to read is less than SYSFS_OFFSET then reduce the
> +                * length of dataLen
> +                */
> +               if (pm8001_ha->forensic_last_offset + SYSFS_OFFSET
> +                               > length_to_read) {
> +                       pm8001_ha->forensic_info.data_buf.direct_len =
> +                               length_to_read -
> +                               pm8001_ha->forensic_last_offset;
> +               } else {
> +                       pm8001_ha->forensic_info.data_buf.direct_len =
> +                               SYSFS_OFFSET;
> +               }
>                 if (pm8001_ha->forensic_info.data_buf.direct_data) {
>                         /* Data is in bar, copy to host memory */
> -                       pm80xx_pci_mem_copy(pm8001_ha, pm8001_ha->fatal_bar_loc,
> -                        pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr,
> -                               pm8001_ha->forensic_info.data_buf.direct_len ,
> -                                       1);
> +                       pm80xx_pci_mem_copy(pm8001_ha,
> +                       pm8001_ha->fatal_bar_loc,
> +                       pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr,
> +                       pm8001_ha->forensic_info.data_buf.direct_len, 1);
>                 }
>                 pm8001_ha->fatal_bar_loc +=
>                         pm8001_ha->forensic_info.data_buf.direct_len;
> @@ -161,21 +219,29 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
>                 pm8001_ha->forensic_info.data_buf.read_len =
>                         pm8001_ha->forensic_info.data_buf.direct_len;
>
> -               if (pm8001_ha->forensic_last_offset  >= accum_len) {
> +               if (pm8001_ha->forensic_last_offset  >= length_to_read) {
>                         pm8001_ha->forensic_info.data_buf.direct_data +=
>                         sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
>                                 "%08x ", 3);
> -                       for (index = 0; index < (SYSFS_OFFSET / 4); index++) {
> +                       for (index = 0; index <
> +                               (pm8001_ha->forensic_info.data_buf.direct_len
> +                                / 4); index++) {
>                                 pm8001_ha->forensic_info.data_buf.direct_data +=
> -                                       sprintf(pm8001_ha->
> -                                        forensic_info.data_buf.direct_data,
> -                                               "%08x ", *(temp + index));
> +                               sprintf(
> +                               pm8001_ha->forensic_info.data_buf.direct_data,
> +                               "%08x ", *(temp + index));
>                         }
>
>                         pm8001_ha->fatal_bar_loc = 0;
>                         pm8001_ha->forensic_fatal_step = 1;
>                         pm8001_ha->fatal_forensic_shift_offset = 0;
>                         pm8001_ha->forensic_last_offset = 0;
> +                       status = 0;
> +                       offset = (int)
> +                       ((char *)pm8001_ha->forensic_info.data_buf.direct_data
> +                       - (char *)buf);
> +                       PM8001_IO_DBG(pm8001_ha,
> +                       pm8001_printk("get_fatal_spcv:return1 0x%x\n", offset));
>                         return (char *)pm8001_ha->
>                                 forensic_info.data_buf.direct_data -
>                                 (char *)buf;
> @@ -185,12 +251,20 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
>                                 sprintf(pm8001_ha->
>                                         forensic_info.data_buf.direct_data,
>                                         "%08x ", 2);
> -                       for (index = 0; index < (SYSFS_OFFSET / 4); index++) {
> -                               pm8001_ha->forensic_info.data_buf.direct_data +=
> -                                       sprintf(pm8001_ha->
> +                       for (index = 0; index <
> +                               (pm8001_ha->forensic_info.data_buf.direct_len
> +                                / 4); index++) {
> +                               pm8001_ha->forensic_info.data_buf.direct_data
> +                                       += sprintf(pm8001_ha->
>                                         forensic_info.data_buf.direct_data,
>                                         "%08x ", *(temp + index));
>                         }
> +                       status = 0;
> +                       offset = (int)
> +                       ((char *)pm8001_ha->forensic_info.data_buf.direct_data
> +                       - (char *)buf);
> +                       PM8001_IO_DBG(pm8001_ha,
> +                       pm8001_printk("get_fatal_spcv:return2 0x%x\n", offset));
>                         return (char *)pm8001_ha->
>                                 forensic_info.data_buf.direct_data -
>                                 (char *)buf;
> @@ -200,63 +274,122 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
>                 pm8001_ha->forensic_info.data_buf.direct_data +=
>                         sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
>                                 "%08x ", 2);
> -               for (index = 0; index < 256; index++) {
> +               for (index = 0; index <
> +                       (pm8001_ha->forensic_info.data_buf.direct_len
> +                        / 4) ; index++) {
>                         pm8001_ha->forensic_info.data_buf.direct_data +=
>                                 sprintf(pm8001_ha->
> -                                       forensic_info.data_buf.direct_data,
> -                                               "%08x ", *(temp + index));
> +                               forensic_info.data_buf.direct_data,
> +                               "%08x ", *(temp + index));
>                 }
>                 pm8001_ha->fatal_forensic_shift_offset += 0x100;
>                 pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,
>                         pm8001_ha->fatal_forensic_shift_offset);
>                 pm8001_ha->fatal_bar_loc = 0;
> +               status = 0;
> +               offset = (int)
> +                       ((char *)pm8001_ha->forensic_info.data_buf.direct_data
> +                       - (char *)buf);
> +               PM8001_IO_DBG(pm8001_ha,
> +               pm8001_printk("get_fatal_spcv: return3 0x%x\n", offset));
>                 return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
>                         (char *)buf;
>         }
>         if (pm8001_ha->forensic_fatal_step == 1) {
> -               pm8001_ha->fatal_forensic_shift_offset = 0;
> -               /* Read 64K of the debug data. */
> -               pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,
> -                       pm8001_ha->fatal_forensic_shift_offset);
> -               pm8001_mw32(fatal_table_address,
> -                       MPI_FATAL_EDUMP_TABLE_HANDSHAKE,
> +               /* store previous accumulated length before triggering next
> +                * accumulated length update
> +                */
> +               pm8001_ha->forensic_preserved_accumulated_transfer =
> +                       pm8001_mr32(fatal_table_address,
> +                       MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
> +
> +               /* continue capturing the fatal log until Dump status is 0x3 */
> +               if (pm8001_mr32(fatal_table_address,
> +                       MPI_FATAL_EDUMP_TABLE_STATUS) <
> +                       MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) {
> +
> +                       /* reset fddstat bit by writing to zero*/
> +                       pm8001_mw32(fatal_table_address,
> +                                       MPI_FATAL_EDUMP_TABLE_STATUS, 0x0);
> +
> +                       /* set dump control value to '1' so that new data will
> +                        * be transferred to shared memory
> +                        */
> +                       pm8001_mw32(fatal_table_address,
> +                               MPI_FATAL_EDUMP_TABLE_HANDSHAKE,
>                                 MPI_FATAL_EDUMP_HANDSHAKE_RDY);
>
> -               /* Poll FDDHSHK  until clear  */
> -               start = jiffies + (2 * HZ); /* 2 sec */
> +                       /*Poll FDDHSHK  until clear */
> +                       start = jiffies + (2 * HZ); /* 2 sec */
>
> -               do {
> -                       reg_val = pm8001_mr32(fatal_table_address,
> +                       do {
> +                               reg_val = pm8001_mr32(fatal_table_address,
>                                         MPI_FATAL_EDUMP_TABLE_HANDSHAKE);
> -               } while ((reg_val) && time_before(jiffies, start));
> +                       } while ((reg_val) && time_before(jiffies, start));
>
> -               if (reg_val != 0) {
> -                       PM8001_FAIL_DBG(pm8001_ha,
> -                       pm8001_printk("TIMEOUT:MEMBASE_II_SHIFT_REGISTER"
> -                       " = 0x%x\n", reg_val));
> -                       return -EIO;
> -               }
> -
> -               /* Read the next 64K of the debug data. */
> -               pm8001_ha->forensic_fatal_step = 0;
> -               if (pm8001_mr32(fatal_table_address,
> -                       MPI_FATAL_EDUMP_TABLE_STATUS) !=
> -                               MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) {
> -                       pm8001_mw32(fatal_table_address,
> -                               MPI_FATAL_EDUMP_TABLE_HANDSHAKE, 0);
> -                       goto moreData;
> -               } else {
> -                       pm8001_ha->forensic_info.data_buf.direct_data +=
> -                               sprintf(pm8001_ha->
> -                                       forensic_info.data_buf.direct_data,
> -                                               "%08x ", 4);
> -                       pm8001_ha->forensic_info.data_buf.read_len = 0xFFFFFFFF;
> -                       pm8001_ha->forensic_info.data_buf.direct_len =  0;
> -                       pm8001_ha->forensic_info.data_buf.direct_offset = 0;
> -                       pm8001_ha->forensic_info.data_buf.read_len = 0;
> +                       if (reg_val != 0) {
> +                               PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
> +                               "TIMEOUT:MPI_FATAL_EDUMP_TABLE_HDSHAKE 0x%x\n",
> +                               reg_val));
> +                              /* Fail the dump if a timeout occurs */
> +                               pm8001_ha->forensic_info.data_buf.direct_data +=
> +                               sprintf(
> +                               pm8001_ha->forensic_info.data_buf.direct_data,
> +                               "%08x ", 0xFFFFFFFF);
> +                               return((char *)
> +                               pm8001_ha->forensic_info.data_buf.direct_data
> +                               - (char *)buf);
> +                       }
> +                       /* Poll status register until set to 2 or
> +                        * 3 for up to 2 seconds
> +                        */
> +                       start = jiffies + (2 * HZ); /* 2 sec */
> +
> +                       do {
> +                               reg_val = pm8001_mr32(fatal_table_address,
> +                                       MPI_FATAL_EDUMP_TABLE_STATUS);
> +                       } while (((reg_val != 2) || (reg_val != 3)) &&
> +                                       time_before(jiffies, start));
> +
> +                       if (reg_val < 2) {
> +                               PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
> +                               "TIMEOUT:MPI_FATAL_EDUMP_TABLE_STATUS = 0x%x\n",
> +                               reg_val));
> +                               /* Fail the dump if a timeout occurs */
> +                               pm8001_ha->forensic_info.data_buf.direct_data +=
> +                               sprintf(
> +                               pm8001_ha->forensic_info.data_buf.direct_data,
> +                               "%08x ", 0xFFFFFFFF);
> +                               pm8001_cw32(pm8001_ha, 0,
> +                                       MEMBASE_II_SHIFT_REGISTER,
> +                                       pm8001_ha->fatal_forensic_shift_offset);
> +                       }
> +                       /* Read the next block of the debug data.*/
> +                       length_to_read = pm8001_mr32(fatal_table_address,
> +                       MPI_FATAL_EDUMP_TABLE_ACCUM_LEN) -
> +                       pm8001_ha->forensic_preserved_accumulated_transfer;
> +                       if (length_to_read != 0x0) {
> +                               pm8001_ha->forensic_fatal_step = 0;
> +                               goto moreData;
> +                       } else {
> +                               pm8001_ha->forensic_info.data_buf.direct_data +=
> +                               sprintf(
> +                               pm8001_ha->forensic_info.data_buf.direct_data,
> +                               "%08x ", 4);
> +                               pm8001_ha->forensic_info.data_buf.read_len
> +                                                               = 0xFFFFFFFF;
> +                               pm8001_ha->forensic_info.data_buf.direct_len
> +                                                               =  0;
> +                               pm8001_ha->forensic_info.data_buf.direct_offset
> +                                                               = 0;
> +                               pm8001_ha->forensic_info.data_buf.read_len = 0;
> +                       }
>                 }
>         }
> -
> +       offset = (int)((char *)pm8001_ha->forensic_info.data_buf.direct_data
> +                       - (char *)buf);
> +       PM8001_IO_DBG(pm8001_ha,
> +               pm8001_printk("get_fatal_spcv: return4 0x%x\n", offset));
>         return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
>                 (char *)buf;
>  }
> --
> 2.16.3
>

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

* Re: [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39.
  2019-11-14 10:08 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
                   ` (12 preceding siblings ...)
  2019-11-14 10:09 ` [PATCH V2 13/13] pm80xx : Modified the logic to collect fatal dump Deepak Ukey
@ 2019-11-19  4:29 ` Martin K. Petersen
  13 siblings, 0 replies; 21+ messages in thread
From: Martin K. Petersen @ 2019-11-19  4:29 UTC (permalink / raw)
  To: Deepak Ukey
  Cc: linux-scsi, Vasanthalakshmi.Tharmarajan, Viswas.G, jinpu.wang,
	martin.petersen, dpf, jsperbeck, auradkar, ianyar


Deepak,

> This patch set includes some bug fixes and features for pm80xx driver.

Applied to 5.5/scsi-queue, thanks!

-- 
Martin K. Petersen	Oracle Linux Engineering

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

end of thread, other threads:[~2019-11-19  4:29 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-14 10:08 [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Deepak Ukey
2019-11-14 10:08 ` [PATCH V2 01/13] pm80xx : Fix for SATA device discovery Deepak Ukey
2019-11-18  9:00   ` Jinpu Wang
2019-11-14 10:08 ` [PATCH V2 02/13] pm80xx : Make phy enable completion as NULL Deepak Ukey
2019-11-18  9:01   ` Jinpu Wang
2019-11-14 10:09 ` [PATCH V2 03/13] pm80xx : Initialize variable used as return status Deepak Ukey
2019-11-14 10:09 ` [PATCH V2 04/13] pm80xx : Convert 'long' mdelay to msleep Deepak Ukey
2019-11-14 10:09 ` [PATCH V2 05/13] pm80xx : Squashed logging cleanup changes Deepak Ukey
2019-11-14 10:09 ` [PATCH V2 06/13] pm80xx : Increase timeout for pm80xx mpi_uninit_check Deepak Ukey
2019-11-14 10:09 ` [PATCH V2 07/13] pm80xx : Fix dereferencing dangling pointer Deepak Ukey
2019-11-14 10:09 ` [PATCH V2 08/13] pm80xx : Fix command issue sizing Deepak Ukey
2019-11-14 10:09 ` [PATCH V2 09/13] pm80xx : Cleanup command when a reset times out Deepak Ukey
2019-11-18  9:41   ` Jinpu Wang
2019-11-14 10:09 ` [PATCH V2 10/13] pm80xx : Do not request 12G sas speeds Deepak Ukey
2019-11-14 10:41   ` John Garry
2019-11-14 10:09 ` [PATCH V2 11/13] pm80xx : Controller fatal error through sysfs Deepak Ukey
2019-11-18  9:42   ` Jinpu Wang
2019-11-14 10:09 ` [PATCH V2 12/13] pm80xx : Tie the interrupt name to the module instance Deepak Ukey
2019-11-14 10:09 ` [PATCH V2 13/13] pm80xx : Modified the logic to collect fatal dump Deepak Ukey
2019-11-18  9:43   ` Jinpu Wang
2019-11-19  4:29 ` [PATCH V2 00/13] pm80xx : Updates for the driver version 0.1.39 Martin K. Petersen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.