All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 0/4] pm80xx updates
@ 2020-10-30  6:09 Viswas G
  2020-10-30  6:09 ` [PATCH V2 1/4] pm80xx: make mpi_build_cmd locking consistent Viswas G
                   ` (3 more replies)
  0 siblings, 4 replies; 18+ messages in thread
From: Viswas G @ 2020-10-30  6:09 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, Ruksar.devadi,
	martin.petersen, yuuzheng, vishakhavc, radha, akshatzen,
	jinpu.wang

From: Viswas G <Viswas.G@microchip.com>

This patch set include some bug fixes for pm80xx driver.

Changes from v1:
	- Improved commit message for "make mpi_build_cmd locking
	  consistent.patch"

Viswas G (1):
  pm80xx: make running_req atomic.

akshatzen (1):
  pm80xx: Avoid busywait in FW ready check

peter chang (1):
  pm80xx: make mpi_build_cmd locking consistent

yuuzheng (1):
  pm80xx: make pm8001_mpi_set_nvmd_resp free of race condition

 drivers/scsi/pm8001/pm8001_hwi.c  |  86 +++++++++++++++++++------
 drivers/scsi/pm8001/pm8001_init.c |   2 +-
 drivers/scsi/pm8001/pm8001_sas.c  |  11 ++--
 drivers/scsi/pm8001/pm8001_sas.h  |   2 +-
 drivers/scsi/pm8001/pm80xx_hwi.c  | 130 ++++++++++++++++++++++++++++++--------
 drivers/scsi/pm8001/pm80xx_hwi.h  |   6 ++
 6 files changed, 185 insertions(+), 52 deletions(-)

-- 
2.16.3


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

* [PATCH V2 1/4] pm80xx: make mpi_build_cmd locking consistent
  2020-10-30  6:09 [PATCH V2 0/4] pm80xx updates Viswas G
@ 2020-10-30  6:09 ` Viswas G
  2020-10-30  6:51   ` Jinpu Wang
  2020-10-30  6:09 ` [PATCH V2 2/4] pm80xx: make running_req atomic Viswas G
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 18+ messages in thread
From: Viswas G @ 2020-10-30  6:09 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, Ruksar.devadi,
	martin.petersen, yuuzheng, vishakhavc, radha, akshatzen,
	jinpu.wang

From: peter chang <dpf@google.com>

Driver submit all internal requests (like abort_task, event
acknowledgment etc.) through inbound queue 0. While submitting those,
driver does not acquire any lock and it may lead to a race when there 
is an IO request coming in CPU0 and submitted through inbound queue 0. 
To avoid this, lock acquisition has been moved to pm8001_mpi_build_cmd().
All command submission will go through this path.

Signed-off-by: peter chang <dpf@google.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Ruksar Devadi <Ruksar.devadi@microchip.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c | 21 +++++++++++++++------
 drivers/scsi/pm8001/pm80xx_hwi.c |  8 --------
 2 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 2b7b2954ec31..597d7a096a97 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1356,12 +1356,19 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
 {
 	u32 Header = 0, hpriority = 0, bc = 1, category = 0x02;
 	void *pMessage;
-
-	if (pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size,
-		&pMessage) < 0) {
+	unsigned long flags;
+	int q_index = circularQ - pm8001_ha->inbnd_q_tbl;
+	int rv = -1;
+
+	WARN_ON(q_index >= PM8001_MAX_INB_NUM);
+	spin_lock_irqsave(&circularQ->iq_lock, flags);
+	rv = pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size,
+			&pMessage);
+	if (rv < 0) {
 		PM8001_IO_DBG(pm8001_ha,
-			pm8001_printk("No free mpi buffer\n"));
-		return -ENOMEM;
+			      pm8001_printk("No free mpi buffer\n"));
+		rv = -ENOMEM;
+		goto done;
 	}
 
 	if (nb > (pm8001_ha->iomb_size - sizeof(struct mpi_msg_hdr)))
@@ -1384,7 +1391,9 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
 		pm8001_printk("INB Q %x OPCODE:%x , UPDATED PI=%d CI=%d\n",
 			responseQueue, opCode, circularQ->producer_idx,
 			circularQ->consumer_index));
-	return 0;
+done:
+	spin_unlock_irqrestore(&circularQ->iq_lock, flags);
+	return rv;
 }
 
 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 7593f248afb2..5fe50e0effcd 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -4281,7 +4281,6 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
 	char *preq_dma_addr = NULL;
 	__le64 tmp_addr;
 	u32 i, length;
-	unsigned long flags;
 
 	memset(&smp_cmd, 0, sizeof(smp_cmd));
 	/*
@@ -4377,10 +4376,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);
-	spin_lock_irqsave(&circularQ->iq_lock, flags);
 	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &smp_cmd,
 			sizeof(smp_cmd), 0);
-	spin_unlock_irqrestore(&circularQ->iq_lock, flags);
 	if (rc)
 		goto err_out_2;
 	return 0;
@@ -4444,7 +4441,6 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
 	u64 phys_addr, start_addr, end_addr;
 	u32 end_addr_high, end_addr_low;
 	struct inbound_queue_table *circularQ;
-	unsigned long flags;
 	u32 q_index, cpu_id;
 	u32 opc = OPC_INB_SSPINIIOSTART;
 	memset(&ssp_cmd, 0, sizeof(ssp_cmd));
@@ -4582,10 +4578,8 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
 			ssp_cmd.esgl = 0;
 		}
 	}
-	spin_lock_irqsave(&circularQ->iq_lock, flags);
 	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
 			&ssp_cmd, sizeof(ssp_cmd), q_index);
-	spin_unlock_irqrestore(&circularQ->iq_lock, flags);
 	return ret;
 }
 
@@ -4819,10 +4813,8 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
 			}
 		}
 	}
-	spin_lock_irqsave(&circularQ->iq_lock, flags);
 	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
 			&sata_cmd, sizeof(sata_cmd), q_index);
-	spin_unlock_irqrestore(&circularQ->iq_lock, flags);
 	return ret;
 }
 
-- 
2.16.3


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

* [PATCH V2 2/4] pm80xx: make running_req atomic.
  2020-10-30  6:09 [PATCH V2 0/4] pm80xx updates Viswas G
  2020-10-30  6:09 ` [PATCH V2 1/4] pm80xx: make mpi_build_cmd locking consistent Viswas G
@ 2020-10-30  6:09 ` Viswas G
  2020-10-30  7:34   ` Jinpu Wang
  2020-10-30  6:09 ` [PATCH V2 3/4] pm80xx: Avoid busywait in FW ready check Viswas G
  2020-10-30  6:09 ` [PATCH V2 4/4] pm80xx: make pm8001_mpi_set_nvmd_resp free of race condition Viswas G
  3 siblings, 1 reply; 18+ messages in thread
From: Viswas G @ 2020-10-30  6:09 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, Ruksar.devadi,
	martin.petersen, yuuzheng, vishakhavc, radha, akshatzen,
	jinpu.wang

From: Viswas G <Viswas.G@microchip.com>

Incorrect value of the running_req was causing the driver unload
to be stuck during the sas lldd_dev_gone notification handling.
During sata IO completion, for some of the error status, driver
is scheduling event handler and running_req is decremented from that.
But there are some other error status (like IO_DS_IN_RECOVERY,
IO_XFER_ERR_LAST_PIO_DATAIN_CRC_ERR) where the IO have been completed
by fw/driver, but running_req is not decremented.

Also During NCQ error handling, driver itself will initiate
READ_LOG_EXT and ABORT_ALL. When libsas/libata initiate READ_LOG_EXT
(0x2F), driver increments the running_req. But this will be completed
by the driver in pm80xx_chip_sata_req(), but running_req was not
decremented.

Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Ruksar Devadi <Ruksar.devadi@microchip.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c  |  58 +++++++++++++++++-----
 drivers/scsi/pm8001/pm8001_init.c |   2 +-
 drivers/scsi/pm8001/pm8001_sas.c  |  11 +++--
 drivers/scsi/pm8001/pm8001_sas.h  |   2 +-
 drivers/scsi/pm8001/pm80xx_hwi.c  | 101 ++++++++++++++++++++++++++++++++++----
 5 files changed, 147 insertions(+), 27 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 597d7a096a97..9e9a546da959 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1587,7 +1587,7 @@ void pm8001_work_fn(struct work_struct *work)
 		ts->stat = SAS_QUEUE_FULL;
 		pm8001_dev = ccb->device;
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		spin_lock_irqsave(&t->task_state_lock, flags1);
 		t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
 		t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
@@ -1942,7 +1942,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 			sas_ssp_task_response(pm8001_ha->dev, t, iu);
 		}
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_ABORTED:
 		PM8001_IO_DBG(pm8001_ha,
@@ -1958,7 +1958,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->stat = SAS_DATA_UNDERRUN;
 		ts->residual = param;
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_NO_DEVICE:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2172,7 +2172,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->stat = SAS_DATA_OVERRUN;
 		ts->residual = 0;
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_BREAK:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2487,7 +2487,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 					pm8001_printk("response to large\n"));
 		}
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_ABORTED:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2495,7 +2495,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_ABORTED_TASK;
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 		/* following cases are to do cases */
 	case IO_UNDERFLOW:
@@ -2506,19 +2506,23 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->stat = SAS_DATA_UNDERRUN;
 		ts->residual =  param;
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_NO_DEVICE:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_NO_DEVICE\n"));
 		ts->resp = SAS_TASK_UNDELIVERED;
 		ts->stat = SAS_PHY_DOWN;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_BREAK:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_XFER_ERROR_BREAK\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_INTERRUPTED;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_PHY_NOT_READY:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2526,6 +2530,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2534,6 +2540,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_EPROTO;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2541,6 +2549,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_OPEN_CNX_ERROR_BREAK:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2548,6 +2558,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2587,6 +2599,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_CONN_RATE;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2610,48 +2624,64 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_NAK_RECEIVED:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_NAK_R_ERR;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_NAK_R_ERR;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_DMA:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_XFER_ERROR_DMA\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_ABORTED_TASK;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_SATA_LINK_TIMEOUT:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_XFER_ERROR_SATA_LINK_TIMEOUT\n"));
 		ts->resp = SAS_TASK_UNDELIVERED;
 		ts->stat = SAS_DEV_NO_RESPONSE;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_REJECTED_NCQ_MODE:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_DATA_UNDERRUN;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_OPEN_RETRY_TIMEOUT:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_TO;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_PORT_IN_RESET:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_PORT_IN_RESET\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_DEV_NO_RESPONSE;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_DS_NON_OPERATIONAL:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2672,6 +2702,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 			pm8001_printk("  IO_DS_IN_RECOVERY\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_DEV_NO_RESPONSE;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_DS_IN_ERROR:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2693,6 +2725,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	default:
 		PM8001_DEVIO_DBG(pm8001_ha,
@@ -2700,6 +2734,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		/* not allowed case. Therefore, return failed status */
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_DEV_NO_RESPONSE;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	}
 	spin_lock_irqsave(&t->task_state_lock, flags);
@@ -2776,7 +2812,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->stat = SAS_DATA_OVERRUN;
 		ts->residual = 0;
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_BREAK:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2976,7 +3012,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAM_STAT_GOOD;
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_ABORTED:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2984,7 +3020,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_ABORTED_TASK;
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_OVERFLOW:
 		PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n"));
@@ -2992,7 +3028,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->stat = SAS_DATA_OVERRUN;
 		ts->residual = 0;
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_NO_DEVICE:
 		PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_NO_DEVICE\n"));
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 3cf3e58b6979..fb471ad3720a 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -412,7 +412,7 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha,
 		pm8001_ha->devices[i].dev_type = SAS_PHY_UNUSED;
 		pm8001_ha->devices[i].id = i;
 		pm8001_ha->devices[i].device_id = PM8001_MAX_DEVICES;
-		pm8001_ha->devices[i].running_req = 0;
+		atomic_set(&pm8001_ha->devices[i].running_req, 0);
 	}
 	pm8001_ha->flags = PM8001F_INIT_TIME;
 	/* Initialize tags */
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 9889bab7d31c..d6e0bc588698 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -456,9 +456,11 @@ static int pm8001_task_exec(struct sas_task *task,
 		ccb->device = pm8001_dev;
 		switch (task_proto) {
 		case SAS_PROTOCOL_SMP:
+			atomic_inc(&pm8001_dev->running_req);
 			rc = pm8001_task_prep_smp(pm8001_ha, ccb);
 			break;
 		case SAS_PROTOCOL_SSP:
+			atomic_inc(&pm8001_dev->running_req);
 			if (is_tmf)
 				rc = pm8001_task_prep_ssp_tm(pm8001_ha,
 					ccb, tmf);
@@ -467,6 +469,7 @@ static int pm8001_task_exec(struct sas_task *task,
 			break;
 		case SAS_PROTOCOL_SATA:
 		case SAS_PROTOCOL_STP:
+			atomic_inc(&pm8001_dev->running_req);
 			rc = pm8001_task_prep_ata(pm8001_ha, ccb);
 			break;
 		default:
@@ -479,13 +482,13 @@ static int pm8001_task_exec(struct sas_task *task,
 		if (rc) {
 			PM8001_IO_DBG(pm8001_ha,
 				pm8001_printk("rc is %x\n", rc));
+			atomic_dec(&pm8001_dev->running_req);
 			goto err_out_tag;
 		}
 		/* TODO: select normal or high priority */
 		spin_lock(&t->task_state_lock);
 		t->task_state_flags |= SAS_TASK_AT_INITIATOR;
 		spin_unlock(&t->task_state_lock);
-		pm8001_dev->running_req++;
 	} while (0);
 	rc = 0;
 	goto out_done;
@@ -886,11 +889,11 @@ static void pm8001_dev_gone_notify(struct domain_device *dev)
 		PM8001_DISC_DBG(pm8001_ha,
 			pm8001_printk("found dev[%d:%x] is gone.\n",
 			pm8001_dev->device_id, pm8001_dev->dev_type));
-		if (pm8001_dev->running_req) {
+		if (atomic_read(&pm8001_dev->running_req)) {
 			spin_unlock_irqrestore(&pm8001_ha->lock, flags);
 			pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
 				dev, 1, 0);
-			while (pm8001_dev->running_req)
+			while (atomic_read(&pm8001_dev->running_req))
 				msleep(20);
 			spin_lock_irqsave(&pm8001_ha->lock, flags);
 		}
@@ -968,7 +971,7 @@ void pm8001_open_reject_retry(
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		spin_lock_irqsave(&task->task_state_lock, flags1);
 		task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
 		task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 95663e138083..091574721ea1 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -293,7 +293,7 @@ struct pm8001_device {
 	struct completion	*dcompletion;
 	struct completion	*setds_completion;
 	u32			device_id;
-	u32			running_req;
+	atomic_t		running_req;
 };
 
 struct pm8001_prd_imt {
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 5fe50e0effcd..1ba93fb76093 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -1960,13 +1960,15 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 			sas_ssp_task_response(pm8001_ha->dev, t, iu);
 		}
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_ABORTED:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_ABORTED IOMB Tag\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_ABORTED_TASK;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_UNDERFLOW:
 		/* SSP Completion with error */
@@ -1977,13 +1979,15 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->stat = SAS_DATA_UNDERRUN;
 		ts->residual = param;
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_NO_DEVICE:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_NO_DEVICE\n"));
 		ts->resp = SAS_TASK_UNDELIVERED;
 		ts->stat = SAS_PHY_DOWN;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_BREAK:
 		PM8001_IO_DBG(pm8001_ha,
@@ -1992,6 +1996,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->stat = SAS_OPEN_REJECT;
 		/* Force the midlayer to retry */
 		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_PHY_NOT_READY:
 		PM8001_IO_DBG(pm8001_ha,
@@ -1999,6 +2005,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_INVALID_SSP_RSP_FRAME:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2006,6 +2014,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2013,6 +2023,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_EPROTO;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2020,6 +2032,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_OPEN_CNX_ERROR_BREAK:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2027,6 +2041,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
 	case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
@@ -2050,6 +2066,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_BAD_DEST;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
 		PM8001_IO_DBG(pm8001_ha, pm8001_printk(
@@ -2057,6 +2075,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_CONN_RATE;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2064,6 +2084,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->resp = SAS_TASK_UNDELIVERED;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_NAK_RECEIVED:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2071,18 +2093,24 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_NAK_R_ERR;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_DMA:
 		PM8001_IO_DBG(pm8001_ha,
 		pm8001_printk("IO_XFER_ERROR_DMA\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_OPEN_RETRY_TIMEOUT:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2090,18 +2118,24 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_OFFSET_MISMATCH:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_PORT_IN_RESET:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_PORT_IN_RESET\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_DS_NON_OPERATIONAL:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2118,18 +2152,24 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 			pm8001_printk("IO_DS_IN_RECOVERY\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_TM_TAG_NOT_FOUND:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_TM_TAG_NOT_FOUND\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_SSP_EXT_IU_ZERO_LEN_ERROR:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_SSP_EXT_IU_ZERO_LEN_ERROR\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2137,6 +2177,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	default:
 		PM8001_DEVIO_DBG(pm8001_ha,
@@ -2144,6 +2186,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		/* not allowed case. Therefore, return failed status */
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	}
 	PM8001_IO_DBG(pm8001_ha,
@@ -2203,7 +2247,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->stat = SAS_DATA_OVERRUN;
 		ts->residual = 0;
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_BREAK:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2528,7 +2572,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 					pm8001_printk("response too large\n"));
 		}
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_ABORTED:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2536,7 +2580,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_ABORTED_TASK;
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 		/* following cases are to do cases */
 	case IO_UNDERFLOW:
@@ -2547,19 +2591,23 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->stat = SAS_DATA_UNDERRUN;
 		ts->residual = param;
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_NO_DEVICE:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_NO_DEVICE\n"));
 		ts->resp = SAS_TASK_UNDELIVERED;
 		ts->stat = SAS_PHY_DOWN;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_BREAK:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_XFER_ERROR_BREAK\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_INTERRUPTED;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_PHY_NOT_READY:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2567,6 +2615,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
 		PM8001_IO_DBG(pm8001_ha, pm8001_printk(
@@ -2574,6 +2624,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_EPROTO;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2581,6 +2633,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_OPEN_CNX_ERROR_BREAK:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2588,6 +2642,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
 	case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
@@ -2631,6 +2687,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_CONN_RATE;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
 		PM8001_IO_DBG(pm8001_ha, pm8001_printk(
@@ -2653,48 +2711,64 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_NAK_RECEIVED:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_NAK_R_ERR;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_NAK_R_ERR;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_DMA:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_XFER_ERROR_DMA\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_ABORTED_TASK;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_SATA_LINK_TIMEOUT:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_XFER_ERROR_SATA_LINK_TIMEOUT\n"));
 		ts->resp = SAS_TASK_UNDELIVERED;
 		ts->stat = SAS_DEV_NO_RESPONSE;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_REJECTED_NCQ_MODE:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_DATA_UNDERRUN;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_OPEN_RETRY_TIMEOUT:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_TO;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_PORT_IN_RESET:
 		PM8001_IO_DBG(pm8001_ha,
 			pm8001_printk("IO_PORT_IN_RESET\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_DEV_NO_RESPONSE;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_DS_NON_OPERATIONAL:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2715,6 +2789,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 			pm8001_printk("IO_DS_IN_RECOVERY\n"));
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_DEV_NO_RESPONSE;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_DS_IN_ERROR:
 		PM8001_IO_DBG(pm8001_ha,
@@ -2736,6 +2812,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_OPEN_REJECT;
 		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	default:
 		PM8001_DEVIO_DBG(pm8001_ha,
@@ -2743,6 +2821,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		/* not allowed case. Therefore, return failed status */
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_DEV_NO_RESPONSE;
+		if (pm8001_dev)
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	}
 	spin_lock_irqsave(&t->task_state_lock, flags);
@@ -2820,7 +2900,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
 		ts->stat = SAS_DATA_OVERRUN;
 		ts->residual = 0;
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_XFER_ERROR_BREAK:
 		PM8001_IO_DBG(pm8001_ha,
@@ -3040,7 +3120,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAM_STAT_GOOD;
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		if (pm8001_ha->smp_exp_mode == SMP_DIRECT) {
 			PM8001_IO_DBG(pm8001_ha,
 				pm8001_printk("DIRECT RESPONSE Length:%d\n",
@@ -3063,7 +3143,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->resp = SAS_TASK_COMPLETE;
 		ts->stat = SAS_ABORTED_TASK;
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_OVERFLOW:
 		PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n"));
@@ -3071,7 +3151,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		ts->stat = SAS_DATA_OVERRUN;
 		ts->residual = 0;
 		if (pm8001_dev)
-			pm8001_dev->running_req--;
+			atomic_dec(&pm8001_dev->running_req);
 		break;
 	case IO_NO_DEVICE:
 		PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_NO_DEVICE\n"));
@@ -4809,6 +4889,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
 							flags);
 				pm8001_ccb_task_free_done(pm8001_ha, task,
 								ccb, tag);
+				atomic_dec(&pm8001_ha_dev->running_req);
 				return 0;
 			}
 		}
-- 
2.16.3


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

* [PATCH V2 3/4] pm80xx: Avoid busywait in FW ready check
  2020-10-30  6:09 [PATCH V2 0/4] pm80xx updates Viswas G
  2020-10-30  6:09 ` [PATCH V2 1/4] pm80xx: make mpi_build_cmd locking consistent Viswas G
  2020-10-30  6:09 ` [PATCH V2 2/4] pm80xx: make running_req atomic Viswas G
@ 2020-10-30  6:09 ` Viswas G
  2020-10-30  7:35   ` Jinpu Wang
  2020-10-30  6:09 ` [PATCH V2 4/4] pm80xx: make pm8001_mpi_set_nvmd_resp free of race condition Viswas G
  3 siblings, 1 reply; 18+ messages in thread
From: Viswas G @ 2020-10-30  6:09 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, Ruksar.devadi,
	martin.petersen, yuuzheng, vishakhavc, radha, akshatzen,
	jinpu.wang

From: akshatzen <akshatzen@google.com>

Today in function check_fw_ready we do busy wait using udelay. Due to
which CPU is not released and we see CPU need_resched failures.

Here busy waiting is not necessary since we are in process context and
we should sleep instead. So to avoid busy waiting we are replacing
udelay with msleep of 20 ms intervals to check for FW to become ready.

It's verified that check_fw_ready today is not being used in interrupt
context anywhere, hence it is safe to make this change.

Tested:
Installed the kernel and looked at dmesg for failures pertaining to
need_resched and did not find them.

Signed-off-by: akshatzen <akshatzen@google.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Ruksar Devadi <Ruksar.devadi@microchip.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 21 +++++++++++----------
 drivers/scsi/pm8001/pm80xx_hwi.h |  6 ++++++
 2 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 1ba93fb76093..24a4f6b9e79d 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -1042,6 +1042,7 @@ static int mpi_init_check(struct pm8001_hba_info *pm8001_ha)
 
 /**
  * check_fw_ready - The LLDD check if the FW is ready, if not, return error.
+ * This function sleeps hence it must not be used in atomic context.
  * @pm8001_ha: our hba card information
  */
 static int check_fw_ready(struct pm8001_hba_info *pm8001_ha)
@@ -1052,16 +1053,16 @@ static int check_fw_ready(struct pm8001_hba_info *pm8001_ha)
 	int ret = 0;
 
 	/* reset / PCIe ready */
-	max_wait_time = max_wait_count = 100 * 1000;	/* 100 milli sec */
+	max_wait_time = max_wait_count = 5;	/* 100 milli sec */
 	do {
-		udelay(1);
+		msleep(FW_READY_INTERVAL);
 		value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
 	} while ((value == 0xFFFFFFFF) && (--max_wait_count));
 
 	/* check ila status */
-	max_wait_time = max_wait_count = 1000 * 1000;	/* 1000 milli sec */
+	max_wait_time = max_wait_count = 50;	/* 1000 milli sec */
 	do {
-		udelay(1);
+		msleep(FW_READY_INTERVAL);
 		value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
 	} while (((value & SCRATCH_PAD_ILA_READY) !=
 			SCRATCH_PAD_ILA_READY) && (--max_wait_count));
@@ -1074,9 +1075,9 @@ static int check_fw_ready(struct pm8001_hba_info *pm8001_ha)
 	}
 
 	/* check RAAE status */
-	max_wait_time = max_wait_count = 1800 * 1000;	/* 1800 milli sec */
+	max_wait_time = max_wait_count = 90;	/* 1800 milli sec */
 	do {
-		udelay(1);
+		msleep(FW_READY_INTERVAL);
 		value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
 	} while (((value & SCRATCH_PAD_RAAE_READY) !=
 				SCRATCH_PAD_RAAE_READY) && (--max_wait_count));
@@ -1089,9 +1090,9 @@ static int check_fw_ready(struct pm8001_hba_info *pm8001_ha)
 	}
 
 	/* check iop0 status */
-	max_wait_time = max_wait_count = 600 * 1000;	/* 600 milli sec */
+	max_wait_time = max_wait_count = 30;	/* 600 milli sec */
 	do {
-		udelay(1);
+		msleep(FW_READY_INTERVAL);
 		value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
 	} while (((value & SCRATCH_PAD_IOP0_READY) != SCRATCH_PAD_IOP0_READY) &&
 			(--max_wait_count));
@@ -1107,9 +1108,9 @@ static int check_fw_ready(struct pm8001_hba_info *pm8001_ha)
 	if ((pm8001_ha->chip_id != chip_8008) &&
 			(pm8001_ha->chip_id != chip_8009)) {
 		/* 200 milli sec */
-		max_wait_time = max_wait_count = 200 * 1000;
+		max_wait_time = max_wait_count = 10;
 		do {
-			udelay(1);
+			msleep(FW_READY_INTERVAL);
 			value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
 		} while (((value & SCRATCH_PAD_IOP1_READY) !=
 				SCRATCH_PAD_IOP1_READY) && (--max_wait_count));
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index 701951a0f715..ec48bc276de6 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -1639,3 +1639,9 @@ typedef struct SASProtocolTimerConfig SASProtocolTimerConfig_t;
 
 #define MEMBASE_II_SHIFT_REGISTER       0x1010
 #endif
+
+/**
+ * As we know sleep (1~20) ms may result in sleep longer than ~20 ms, hence we
+ * choose 20 ms interval.
+ */
+#define FW_READY_INTERVAL	20
-- 
2.16.3


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

* [PATCH V2 4/4] pm80xx: make pm8001_mpi_set_nvmd_resp free of race condition
  2020-10-30  6:09 [PATCH V2 0/4] pm80xx updates Viswas G
                   ` (2 preceding siblings ...)
  2020-10-30  6:09 ` [PATCH V2 3/4] pm80xx: Avoid busywait in FW ready check Viswas G
@ 2020-10-30  6:09 ` Viswas G
  2020-10-30  7:44   ` Jinpu Wang
  3 siblings, 1 reply; 18+ messages in thread
From: Viswas G @ 2020-10-30  6:09 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, Ruksar.devadi,
	martin.petersen, yuuzheng, vishakhavc, radha, akshatzen,
	jinpu.wang

From: yuuzheng <yuuzheng@google.com>

The use-after-free or null-pointer error occurs when the 251-byte
response data are copied from IOMB buffer to response message
buffer in function mp8001_mpi_set_nvmd_resp. pm8001_mpi_set_nvmd_resp
is a function to process the response of command set_nvmd_data_resp.
After sending the command set_nvmd_data, the caller begins to sleep by
calling wait_for_complete() and wait for the wake-up from calling
complete() in pm8001_mpi_set_nvmd_resp. In the current code,
the memcpy for response message buffer occurs after calling complete().
So, it is not protected by the use of wait_for_completion() and
complete().

Due to unexpected events (e.g., interrupt), if response buffer gets
freed before memcpy, the use-after-free error will occur.
To fix it, the complete() should be called after memcpy.

Signed-off-by: yuuzheng <yuuzheng@google.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Ruksar Devadi <Ruksar.devadi@microchip.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 9e9a546da959..2054c2b03d92 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3279,10 +3279,15 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		pm8001_ha->memoryMap.region[NVMD].virt_ptr,
 		fw_control_context->len);
 	kfree(ccb->fw_control_context);
+	/* To avoid race condition, complete should be
+	 * called after the message is copied to
+	 * fw_control_context->usrAddr
+	 */
+	complete(pm8001_ha->nvmd_completion);
+	PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Set nvm data complete!\n"));
 	ccb->task = NULL;
 	ccb->ccb_tag = 0xFFFFFFFF;
 	pm8001_tag_free(pm8001_ha, tag);
-	complete(pm8001_ha->nvmd_completion);
 }
 
 int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
-- 
2.16.3


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

* Re: [PATCH V2 1/4] pm80xx: make mpi_build_cmd locking consistent
  2020-10-30  6:09 ` [PATCH V2 1/4] pm80xx: make mpi_build_cmd locking consistent Viswas G
@ 2020-10-30  6:51   ` Jinpu Wang
  0 siblings, 0 replies; 18+ messages in thread
From: Jinpu Wang @ 2020-10-30  6:51 UTC (permalink / raw)
  To: Viswas G
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Ruksar.devadi, Martin K. Petersen, yuuzheng, vishakhavc,
	Radha Ramachandran, akshatzen

On Fri, Oct 30, 2020 at 6:59 AM Viswas G <Viswas.G@microchip.com.com> wrote:
>
> From: peter chang <dpf@google.com>
>
> Driver submit all internal requests (like abort_task, event
> acknowledgment etc.) through inbound queue 0. While submitting those,
> driver does not acquire any lock and it may lead to a race when there
> is an IO request coming in CPU0 and submitted through inbound queue 0.
> To avoid this, lock acquisition has been moved to pm8001_mpi_build_cmd().
> All command submission will go through this path.
>
> Signed-off-by: peter chang <dpf@google.com>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
> Signed-off-by: Ruksar Devadi <Ruksar.devadi@microchip.com>
> Signed-off-by: Radha Ramachandran <radha@google.com>
This commit message is easy to follow.
Thanks.
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
> ---
>  drivers/scsi/pm8001/pm8001_hwi.c | 21 +++++++++++++++------
>  drivers/scsi/pm8001/pm80xx_hwi.c |  8 --------
>  2 files changed, 15 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
> index 2b7b2954ec31..597d7a096a97 100644
> --- a/drivers/scsi/pm8001/pm8001_hwi.c
> +++ b/drivers/scsi/pm8001/pm8001_hwi.c
> @@ -1356,12 +1356,19 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
>  {
>         u32 Header = 0, hpriority = 0, bc = 1, category = 0x02;
>         void *pMessage;
> -
> -       if (pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size,
> -               &pMessage) < 0) {
> +       unsigned long flags;
> +       int q_index = circularQ - pm8001_ha->inbnd_q_tbl;
> +       int rv = -1;
> +
> +       WARN_ON(q_index >= PM8001_MAX_INB_NUM);
> +       spin_lock_irqsave(&circularQ->iq_lock, flags);
> +       rv = pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size,
> +                       &pMessage);
> +       if (rv < 0) {
>                 PM8001_IO_DBG(pm8001_ha,
> -                       pm8001_printk("No free mpi buffer\n"));
> -               return -ENOMEM;
> +                             pm8001_printk("No free mpi buffer\n"));
> +               rv = -ENOMEM;
> +               goto done;
>         }
>
>         if (nb > (pm8001_ha->iomb_size - sizeof(struct mpi_msg_hdr)))
> @@ -1384,7 +1391,9 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
>                 pm8001_printk("INB Q %x OPCODE:%x , UPDATED PI=%d CI=%d\n",
>                         responseQueue, opCode, circularQ->producer_idx,
>                         circularQ->consumer_index));
> -       return 0;
> +done:
> +       spin_unlock_irqrestore(&circularQ->iq_lock, flags);
> +       return rv;
>  }
>
>  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 7593f248afb2..5fe50e0effcd 100644
> --- a/drivers/scsi/pm8001/pm80xx_hwi.c
> +++ b/drivers/scsi/pm8001/pm80xx_hwi.c
> @@ -4281,7 +4281,6 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
>         char *preq_dma_addr = NULL;
>         __le64 tmp_addr;
>         u32 i, length;
> -       unsigned long flags;
>
>         memset(&smp_cmd, 0, sizeof(smp_cmd));
>         /*
> @@ -4377,10 +4376,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);
> -       spin_lock_irqsave(&circularQ->iq_lock, flags);
>         rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &smp_cmd,
>                         sizeof(smp_cmd), 0);
> -       spin_unlock_irqrestore(&circularQ->iq_lock, flags);
>         if (rc)
>                 goto err_out_2;
>         return 0;
> @@ -4444,7 +4441,6 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
>         u64 phys_addr, start_addr, end_addr;
>         u32 end_addr_high, end_addr_low;
>         struct inbound_queue_table *circularQ;
> -       unsigned long flags;
>         u32 q_index, cpu_id;
>         u32 opc = OPC_INB_SSPINIIOSTART;
>         memset(&ssp_cmd, 0, sizeof(ssp_cmd));
> @@ -4582,10 +4578,8 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
>                         ssp_cmd.esgl = 0;
>                 }
>         }
> -       spin_lock_irqsave(&circularQ->iq_lock, flags);
>         ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
>                         &ssp_cmd, sizeof(ssp_cmd), q_index);
> -       spin_unlock_irqrestore(&circularQ->iq_lock, flags);
>         return ret;
>  }
>
> @@ -4819,10 +4813,8 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
>                         }
>                 }
>         }
> -       spin_lock_irqsave(&circularQ->iq_lock, flags);
>         ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
>                         &sata_cmd, sizeof(sata_cmd), q_index);
> -       spin_unlock_irqrestore(&circularQ->iq_lock, flags);
>         return ret;
>  }
>
> --
> 2.16.3
>

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

* Re: [PATCH V2 2/4] pm80xx: make running_req atomic.
  2020-10-30  6:09 ` [PATCH V2 2/4] pm80xx: make running_req atomic Viswas G
@ 2020-10-30  7:34   ` Jinpu Wang
  0 siblings, 0 replies; 18+ messages in thread
From: Jinpu Wang @ 2020-10-30  7:34 UTC (permalink / raw)
  To: Viswas G
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Ruksar.devadi, Martin K. Petersen, yuuzheng, vishakhavc,
	Radha Ramachandran, akshatzen

On Fri, Oct 30, 2020 at 6:59 AM Viswas G <Viswas.G@microchip.com.com> wrote:
>
> From: Viswas G <Viswas.G@microchip.com>
>
> Incorrect value of the running_req was causing the driver unload
> to be stuck during the sas lldd_dev_gone notification handling.
> During sata IO completion, for some of the error status, driver
> is scheduling event handler and running_req is decremented from that.
> But there are some other error status (like IO_DS_IN_RECOVERY,
> IO_XFER_ERR_LAST_PIO_DATAIN_CRC_ERR) where the IO have been completed
> by fw/driver, but running_req is not decremented.
>
> Also During NCQ error handling, driver itself will initiate
> READ_LOG_EXT and ABORT_ALL. When libsas/libata initiate READ_LOG_EXT
> (0x2F), driver increments the running_req. But this will be completed
> by the driver in pm80xx_chip_sata_req(), but running_req was not
> decremented.
>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
> Signed-off-by: Ruksar Devadi <Ruksar.devadi@microchip.com>
Looks good to me!
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
> ---
>  drivers/scsi/pm8001/pm8001_hwi.c  |  58 +++++++++++++++++-----
>  drivers/scsi/pm8001/pm8001_init.c |   2 +-
>  drivers/scsi/pm8001/pm8001_sas.c  |  11 +++--
>  drivers/scsi/pm8001/pm8001_sas.h  |   2 +-
>  drivers/scsi/pm8001/pm80xx_hwi.c  | 101 ++++++++++++++++++++++++++++++++++----
>  5 files changed, 147 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
> index 597d7a096a97..9e9a546da959 100644
> --- a/drivers/scsi/pm8001/pm8001_hwi.c
> +++ b/drivers/scsi/pm8001/pm8001_hwi.c
> @@ -1587,7 +1587,7 @@ void pm8001_work_fn(struct work_struct *work)
>                 ts->stat = SAS_QUEUE_FULL;
>                 pm8001_dev = ccb->device;
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 spin_lock_irqsave(&t->task_state_lock, flags1);
>                 t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
>                 t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
> @@ -1942,7 +1942,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                         sas_ssp_task_response(pm8001_ha->dev, t, iu);
>                 }
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_ABORTED:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -1958,7 +1958,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                 ts->stat = SAS_DATA_UNDERRUN;
>                 ts->residual = param;
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_NO_DEVICE:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2172,7 +2172,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                 ts->stat = SAS_DATA_OVERRUN;
>                 ts->residual = 0;
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_BREAK:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2487,7 +2487,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                                         pm8001_printk("response to large\n"));
>                 }
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_ABORTED:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2495,7 +2495,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_ABORTED_TASK;
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>                 /* following cases are to do cases */
>         case IO_UNDERFLOW:
> @@ -2506,19 +2506,23 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->stat = SAS_DATA_UNDERRUN;
>                 ts->residual =  param;
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_NO_DEVICE:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_NO_DEVICE\n"));
>                 ts->resp = SAS_TASK_UNDELIVERED;
>                 ts->stat = SAS_PHY_DOWN;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_BREAK:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_XFER_ERROR_BREAK\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_INTERRUPTED;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_PHY_NOT_READY:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2526,6 +2530,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2534,6 +2540,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_EPROTO;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2541,6 +2549,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_UNKNOWN;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_OPEN_CNX_ERROR_BREAK:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2548,6 +2558,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2587,6 +2599,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_CONN_RATE;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2610,48 +2624,64 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_NAK_RECEIVED:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_NAK_R_ERR;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_NAK_R_ERR;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_DMA:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_XFER_ERROR_DMA\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_ABORTED_TASK;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_SATA_LINK_TIMEOUT:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_XFER_ERROR_SATA_LINK_TIMEOUT\n"));
>                 ts->resp = SAS_TASK_UNDELIVERED;
>                 ts->stat = SAS_DEV_NO_RESPONSE;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_REJECTED_NCQ_MODE:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_DATA_UNDERRUN;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_OPEN_RETRY_TIMEOUT:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_TO;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_PORT_IN_RESET:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_PORT_IN_RESET\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_DEV_NO_RESPONSE;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_DS_NON_OPERATIONAL:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2672,6 +2702,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                         pm8001_printk("  IO_DS_IN_RECOVERY\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_DEV_NO_RESPONSE;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_DS_IN_ERROR:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2693,6 +2725,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         default:
>                 PM8001_DEVIO_DBG(pm8001_ha,
> @@ -2700,6 +2734,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 /* not allowed case. Therefore, return failed status */
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_DEV_NO_RESPONSE;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         }
>         spin_lock_irqsave(&t->task_state_lock, flags);
> @@ -2776,7 +2812,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                 ts->stat = SAS_DATA_OVERRUN;
>                 ts->residual = 0;
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_BREAK:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2976,7 +3012,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAM_STAT_GOOD;
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_ABORTED:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2984,7 +3020,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_ABORTED_TASK;
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_OVERFLOW:
>                 PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n"));
> @@ -2992,7 +3028,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->stat = SAS_DATA_OVERRUN;
>                 ts->residual = 0;
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_NO_DEVICE:
>                 PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_NO_DEVICE\n"));
> diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
> index 3cf3e58b6979..fb471ad3720a 100644
> --- a/drivers/scsi/pm8001/pm8001_init.c
> +++ b/drivers/scsi/pm8001/pm8001_init.c
> @@ -412,7 +412,7 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha,
>                 pm8001_ha->devices[i].dev_type = SAS_PHY_UNUSED;
>                 pm8001_ha->devices[i].id = i;
>                 pm8001_ha->devices[i].device_id = PM8001_MAX_DEVICES;
> -               pm8001_ha->devices[i].running_req = 0;
> +               atomic_set(&pm8001_ha->devices[i].running_req, 0);
>         }
>         pm8001_ha->flags = PM8001F_INIT_TIME;
>         /* Initialize tags */
> diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
> index 9889bab7d31c..d6e0bc588698 100644
> --- a/drivers/scsi/pm8001/pm8001_sas.c
> +++ b/drivers/scsi/pm8001/pm8001_sas.c
> @@ -456,9 +456,11 @@ static int pm8001_task_exec(struct sas_task *task,
>                 ccb->device = pm8001_dev;
>                 switch (task_proto) {
>                 case SAS_PROTOCOL_SMP:
> +                       atomic_inc(&pm8001_dev->running_req);
>                         rc = pm8001_task_prep_smp(pm8001_ha, ccb);
>                         break;
>                 case SAS_PROTOCOL_SSP:
> +                       atomic_inc(&pm8001_dev->running_req);
>                         if (is_tmf)
>                                 rc = pm8001_task_prep_ssp_tm(pm8001_ha,
>                                         ccb, tmf);
> @@ -467,6 +469,7 @@ static int pm8001_task_exec(struct sas_task *task,
>                         break;
>                 case SAS_PROTOCOL_SATA:
>                 case SAS_PROTOCOL_STP:
> +                       atomic_inc(&pm8001_dev->running_req);
>                         rc = pm8001_task_prep_ata(pm8001_ha, ccb);
>                         break;
>                 default:
> @@ -479,13 +482,13 @@ static int pm8001_task_exec(struct sas_task *task,
>                 if (rc) {
>                         PM8001_IO_DBG(pm8001_ha,
>                                 pm8001_printk("rc is %x\n", rc));
> +                       atomic_dec(&pm8001_dev->running_req);
>                         goto err_out_tag;
>                 }
>                 /* TODO: select normal or high priority */
>                 spin_lock(&t->task_state_lock);
>                 t->task_state_flags |= SAS_TASK_AT_INITIATOR;
>                 spin_unlock(&t->task_state_lock);
> -               pm8001_dev->running_req++;
>         } while (0);
>         rc = 0;
>         goto out_done;
> @@ -886,11 +889,11 @@ static void pm8001_dev_gone_notify(struct domain_device *dev)
>                 PM8001_DISC_DBG(pm8001_ha,
>                         pm8001_printk("found dev[%d:%x] is gone.\n",
>                         pm8001_dev->device_id, pm8001_dev->dev_type));
> -               if (pm8001_dev->running_req) {
> +               if (atomic_read(&pm8001_dev->running_req)) {
>                         spin_unlock_irqrestore(&pm8001_ha->lock, flags);
>                         pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
>                                 dev, 1, 0);
> -                       while (pm8001_dev->running_req)
> +                       while (atomic_read(&pm8001_dev->running_req))
>                                 msleep(20);
>                         spin_lock_irqsave(&pm8001_ha->lock, flags);
>                 }
> @@ -968,7 +971,7 @@ void pm8001_open_reject_retry(
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 spin_lock_irqsave(&task->task_state_lock, flags1);
>                 task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
>                 task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
> diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
> index 95663e138083..091574721ea1 100644
> --- a/drivers/scsi/pm8001/pm8001_sas.h
> +++ b/drivers/scsi/pm8001/pm8001_sas.h
> @@ -293,7 +293,7 @@ struct pm8001_device {
>         struct completion       *dcompletion;
>         struct completion       *setds_completion;
>         u32                     device_id;
> -       u32                     running_req;
> +       atomic_t                running_req;
>  };
>
>  struct pm8001_prd_imt {
> diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
> index 5fe50e0effcd..1ba93fb76093 100644
> --- a/drivers/scsi/pm8001/pm80xx_hwi.c
> +++ b/drivers/scsi/pm8001/pm80xx_hwi.c
> @@ -1960,13 +1960,15 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                         sas_ssp_task_response(pm8001_ha->dev, t, iu);
>                 }
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_ABORTED:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_ABORTED IOMB Tag\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_ABORTED_TASK;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_UNDERFLOW:
>                 /* SSP Completion with error */
> @@ -1977,13 +1979,15 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                 ts->stat = SAS_DATA_UNDERRUN;
>                 ts->residual = param;
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_NO_DEVICE:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_NO_DEVICE\n"));
>                 ts->resp = SAS_TASK_UNDELIVERED;
>                 ts->stat = SAS_PHY_DOWN;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_BREAK:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -1992,6 +1996,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                 ts->stat = SAS_OPEN_REJECT;
>                 /* Force the midlayer to retry */
>                 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_PHY_NOT_READY:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -1999,6 +2005,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_INVALID_SSP_RSP_FRAME:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2006,6 +2014,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2013,6 +2023,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_EPROTO;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2020,6 +2032,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_UNKNOWN;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_OPEN_CNX_ERROR_BREAK:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2027,6 +2041,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
>         case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
> @@ -2050,6 +2066,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_BAD_DEST;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
>                 PM8001_IO_DBG(pm8001_ha, pm8001_printk(
> @@ -2057,6 +2075,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_CONN_RATE;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2064,6 +2084,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                 ts->resp = SAS_TASK_UNDELIVERED;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_NAK_RECEIVED:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2071,18 +2093,24 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_NAK_R_ERR;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_DMA:
>                 PM8001_IO_DBG(pm8001_ha,
>                 pm8001_printk("IO_XFER_ERROR_DMA\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_OPEN_RETRY_TIMEOUT:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2090,18 +2118,24 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_OFFSET_MISMATCH:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_PORT_IN_RESET:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_PORT_IN_RESET\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_DS_NON_OPERATIONAL:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2118,18 +2152,24 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                         pm8001_printk("IO_DS_IN_RECOVERY\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_TM_TAG_NOT_FOUND:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_TM_TAG_NOT_FOUND\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_SSP_EXT_IU_ZERO_LEN_ERROR:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_SSP_EXT_IU_ZERO_LEN_ERROR\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2137,6 +2177,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         default:
>                 PM8001_DEVIO_DBG(pm8001_ha,
> @@ -2144,6 +2186,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                 /* not allowed case. Therefore, return failed status */
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         }
>         PM8001_IO_DBG(pm8001_ha,
> @@ -2203,7 +2247,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                 ts->stat = SAS_DATA_OVERRUN;
>                 ts->residual = 0;
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_BREAK:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2528,7 +2572,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                                         pm8001_printk("response too large\n"));
>                 }
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_ABORTED:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2536,7 +2580,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_ABORTED_TASK;
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>                 /* following cases are to do cases */
>         case IO_UNDERFLOW:
> @@ -2547,19 +2591,23 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->stat = SAS_DATA_UNDERRUN;
>                 ts->residual = param;
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_NO_DEVICE:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_NO_DEVICE\n"));
>                 ts->resp = SAS_TASK_UNDELIVERED;
>                 ts->stat = SAS_PHY_DOWN;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_BREAK:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_XFER_ERROR_BREAK\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_INTERRUPTED;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_PHY_NOT_READY:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2567,6 +2615,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
>                 PM8001_IO_DBG(pm8001_ha, pm8001_printk(
> @@ -2574,6 +2624,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_EPROTO;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2581,6 +2633,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_UNKNOWN;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_OPEN_CNX_ERROR_BREAK:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2588,6 +2642,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
>         case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
> @@ -2631,6 +2687,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_CONN_RATE;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
>                 PM8001_IO_DBG(pm8001_ha, pm8001_printk(
> @@ -2653,48 +2711,64 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_NAK_RECEIVED:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_NAK_R_ERR;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_NAK_R_ERR;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_DMA:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_XFER_ERROR_DMA\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_ABORTED_TASK;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_SATA_LINK_TIMEOUT:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_XFER_ERROR_SATA_LINK_TIMEOUT\n"));
>                 ts->resp = SAS_TASK_UNDELIVERED;
>                 ts->stat = SAS_DEV_NO_RESPONSE;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_REJECTED_NCQ_MODE:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_DATA_UNDERRUN;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_OPEN_RETRY_TIMEOUT:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_TO;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_PORT_IN_RESET:
>                 PM8001_IO_DBG(pm8001_ha,
>                         pm8001_printk("IO_PORT_IN_RESET\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_DEV_NO_RESPONSE;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_DS_NON_OPERATIONAL:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2715,6 +2789,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                         pm8001_printk("IO_DS_IN_RECOVERY\n"));
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_DEV_NO_RESPONSE;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_DS_IN_ERROR:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -2736,6 +2812,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_OPEN_REJECT;
>                 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         default:
>                 PM8001_DEVIO_DBG(pm8001_ha,
> @@ -2743,6 +2821,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 /* not allowed case. Therefore, return failed status */
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_DEV_NO_RESPONSE;
> +               if (pm8001_dev)
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         }
>         spin_lock_irqsave(&t->task_state_lock, flags);
> @@ -2820,7 +2900,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
>                 ts->stat = SAS_DATA_OVERRUN;
>                 ts->residual = 0;
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_XFER_ERROR_BREAK:
>                 PM8001_IO_DBG(pm8001_ha,
> @@ -3040,7 +3120,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAM_STAT_GOOD;
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 if (pm8001_ha->smp_exp_mode == SMP_DIRECT) {
>                         PM8001_IO_DBG(pm8001_ha,
>                                 pm8001_printk("DIRECT RESPONSE Length:%d\n",
> @@ -3063,7 +3143,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->resp = SAS_TASK_COMPLETE;
>                 ts->stat = SAS_ABORTED_TASK;
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_OVERFLOW:
>                 PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n"));
> @@ -3071,7 +3151,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 ts->stat = SAS_DATA_OVERRUN;
>                 ts->residual = 0;
>                 if (pm8001_dev)
> -                       pm8001_dev->running_req--;
> +                       atomic_dec(&pm8001_dev->running_req);
>                 break;
>         case IO_NO_DEVICE:
>                 PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_NO_DEVICE\n"));
> @@ -4809,6 +4889,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
>                                                         flags);
>                                 pm8001_ccb_task_free_done(pm8001_ha, task,
>                                                                 ccb, tag);
> +                               atomic_dec(&pm8001_ha_dev->running_req);
>                                 return 0;
>                         }
>                 }
> --
> 2.16.3
>

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

* Re: [PATCH V2 3/4] pm80xx: Avoid busywait in FW ready check
  2020-10-30  6:09 ` [PATCH V2 3/4] pm80xx: Avoid busywait in FW ready check Viswas G
@ 2020-10-30  7:35   ` Jinpu Wang
  0 siblings, 0 replies; 18+ messages in thread
From: Jinpu Wang @ 2020-10-30  7:35 UTC (permalink / raw)
  To: Viswas G
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Ruksar.devadi, Martin K. Petersen, yuuzheng, vishakhavc,
	Radha Ramachandran, akshatzen

On Fri, Oct 30, 2020 at 6:59 AM Viswas G <Viswas.G@microchip.com.com> wrote:
>
> From: akshatzen <akshatzen@google.com>
>
> Today in function check_fw_ready we do busy wait using udelay. Due to
> which CPU is not released and we see CPU need_resched failures.
>
> Here busy waiting is not necessary since we are in process context and
> we should sleep instead. So to avoid busy waiting we are replacing
> udelay with msleep of 20 ms intervals to check for FW to become ready.
>
> It's verified that check_fw_ready today is not being used in interrupt
> context anywhere, hence it is safe to make this change.
>
> Tested:
> Installed the kernel and looked at dmesg for failures pertaining to
> need_resched and did not find them.
>
> Signed-off-by: akshatzen <akshatzen@google.com>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
> Signed-off-by: Ruksar Devadi <Ruksar.devadi@microchip.com>
> Signed-off-by: Radha Ramachandran <radha@google.com>
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
> ---
>  drivers/scsi/pm8001/pm80xx_hwi.c | 21 +++++++++++----------
>  drivers/scsi/pm8001/pm80xx_hwi.h |  6 ++++++
>  2 files changed, 17 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
> index 1ba93fb76093..24a4f6b9e79d 100644
> --- a/drivers/scsi/pm8001/pm80xx_hwi.c
> +++ b/drivers/scsi/pm8001/pm80xx_hwi.c
> @@ -1042,6 +1042,7 @@ static int mpi_init_check(struct pm8001_hba_info *pm8001_ha)
>
>  /**
>   * check_fw_ready - The LLDD check if the FW is ready, if not, return error.
> + * This function sleeps hence it must not be used in atomic context.
>   * @pm8001_ha: our hba card information
>   */
>  static int check_fw_ready(struct pm8001_hba_info *pm8001_ha)
> @@ -1052,16 +1053,16 @@ static int check_fw_ready(struct pm8001_hba_info *pm8001_ha)
>         int ret = 0;
>
>         /* reset / PCIe ready */
> -       max_wait_time = max_wait_count = 100 * 1000;    /* 100 milli sec */
> +       max_wait_time = max_wait_count = 5;     /* 100 milli sec */
>         do {
> -               udelay(1);
> +               msleep(FW_READY_INTERVAL);
>                 value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
>         } while ((value == 0xFFFFFFFF) && (--max_wait_count));
>
>         /* check ila status */
> -       max_wait_time = max_wait_count = 1000 * 1000;   /* 1000 milli sec */
> +       max_wait_time = max_wait_count = 50;    /* 1000 milli sec */
>         do {
> -               udelay(1);
> +               msleep(FW_READY_INTERVAL);
>                 value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
>         } while (((value & SCRATCH_PAD_ILA_READY) !=
>                         SCRATCH_PAD_ILA_READY) && (--max_wait_count));
> @@ -1074,9 +1075,9 @@ static int check_fw_ready(struct pm8001_hba_info *pm8001_ha)
>         }
>
>         /* check RAAE status */
> -       max_wait_time = max_wait_count = 1800 * 1000;   /* 1800 milli sec */
> +       max_wait_time = max_wait_count = 90;    /* 1800 milli sec */
>         do {
> -               udelay(1);
> +               msleep(FW_READY_INTERVAL);
>                 value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
>         } while (((value & SCRATCH_PAD_RAAE_READY) !=
>                                 SCRATCH_PAD_RAAE_READY) && (--max_wait_count));
> @@ -1089,9 +1090,9 @@ static int check_fw_ready(struct pm8001_hba_info *pm8001_ha)
>         }
>
>         /* check iop0 status */
> -       max_wait_time = max_wait_count = 600 * 1000;    /* 600 milli sec */
> +       max_wait_time = max_wait_count = 30;    /* 600 milli sec */
>         do {
> -               udelay(1);
> +               msleep(FW_READY_INTERVAL);
>                 value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
>         } while (((value & SCRATCH_PAD_IOP0_READY) != SCRATCH_PAD_IOP0_READY) &&
>                         (--max_wait_count));
> @@ -1107,9 +1108,9 @@ static int check_fw_ready(struct pm8001_hba_info *pm8001_ha)
>         if ((pm8001_ha->chip_id != chip_8008) &&
>                         (pm8001_ha->chip_id != chip_8009)) {
>                 /* 200 milli sec */
> -               max_wait_time = max_wait_count = 200 * 1000;
> +               max_wait_time = max_wait_count = 10;
>                 do {
> -                       udelay(1);
> +                       msleep(FW_READY_INTERVAL);
>                         value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
>                 } while (((value & SCRATCH_PAD_IOP1_READY) !=
>                                 SCRATCH_PAD_IOP1_READY) && (--max_wait_count));
> diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
> index 701951a0f715..ec48bc276de6 100644
> --- a/drivers/scsi/pm8001/pm80xx_hwi.h
> +++ b/drivers/scsi/pm8001/pm80xx_hwi.h
> @@ -1639,3 +1639,9 @@ typedef struct SASProtocolTimerConfig SASProtocolTimerConfig_t;
>
>  #define MEMBASE_II_SHIFT_REGISTER       0x1010
>  #endif
> +
> +/**
> + * As we know sleep (1~20) ms may result in sleep longer than ~20 ms, hence we
> + * choose 20 ms interval.
> + */
> +#define FW_READY_INTERVAL      20
> --
> 2.16.3
>

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

* Re: [PATCH V2 4/4] pm80xx: make pm8001_mpi_set_nvmd_resp free of race condition
  2020-10-30  6:09 ` [PATCH V2 4/4] pm80xx: make pm8001_mpi_set_nvmd_resp free of race condition Viswas G
@ 2020-10-30  7:44   ` Jinpu Wang
  0 siblings, 0 replies; 18+ messages in thread
From: Jinpu Wang @ 2020-10-30  7:44 UTC (permalink / raw)
  To: Viswas G
  Cc: Linux SCSI Mailinglist, Vasanthalakshmi.Tharmarajan, Viswas G,
	Ruksar.devadi, Martin K. Petersen, yuuzheng, vishakhavc,
	Radha Ramachandran, akshatzen

On Fri, Oct 30, 2020 at 6:59 AM Viswas G <Viswas.G@microchip.com.com> wrote:
>
> From: yuuzheng <yuuzheng@google.com>
>
> The use-after-free or null-pointer error occurs when the 251-byte
> response data are copied from IOMB buffer to response message
> buffer in function mp8001_mpi_set_nvmd_resp. pm8001_mpi_set_nvmd_resp
typo mp8001_mpi_set_nvmd_resp.
> is a function to process the response of command set_nvmd_data_resp.
> After sending the command set_nvmd_data, the caller begins to sleep by
> calling wait_for_complete() and wait for the wake-up from calling
> complete() in pm8001_mpi_set_nvmd_resp. In the current code,
> the memcpy for response message buffer occurs after calling complete().
> So, it is not protected by the use of wait_for_completion() and
> complete().
>
> Due to unexpected events (e.g., interrupt), if response buffer gets
> freed before memcpy, the use-after-free error will occur.
> To fix it, the complete() should be called after memcpy.
>
> Signed-off-by: yuuzheng <yuuzheng@google.com>
> Signed-off-by: Viswas G <Viswas.G@microchip.com>
> Signed-off-by: Ruksar Devadi <Ruksar.devadi@microchip.com>
> Signed-off-by: Radha Ramachandran <radha@google.com>
The code and the commit message doesn't match, the commit message is
talking about pm8001_mpi_set_nvmd_resp,
but the code change is in pm8001_mpi_get_nvmd_resp

The fix itself looks correct, please fix the commit message, with that
you can add my
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
> ---
>  drivers/scsi/pm8001/pm8001_hwi.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
> index 9e9a546da959..2054c2b03d92 100644
> --- a/drivers/scsi/pm8001/pm8001_hwi.c
> +++ b/drivers/scsi/pm8001/pm8001_hwi.c
> @@ -3279,10 +3279,15 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                 pm8001_ha->memoryMap.region[NVMD].virt_ptr,
>                 fw_control_context->len);
>         kfree(ccb->fw_control_context);
> +       /* To avoid race condition, complete should be
> +        * called after the message is copied to
> +        * fw_control_context->usrAddr
> +        */
> +       complete(pm8001_ha->nvmd_completion);
> +       PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Set nvm data complete!\n"));
>         ccb->task = NULL;
>         ccb->ccb_tag = 0xFFFFFFFF;
>         pm8001_tag_free(pm8001_ha, tag);
> -       complete(pm8001_ha->nvmd_completion);
>  }
>
>  int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
> --
> 2.16.3
>

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

* Re: [PATCH v2 0/4] pm80xx updates
  2021-09-06 17:04 [PATCH v2 0/4] pm80xx updates Ajish Koshy
  2021-09-15  2:29 ` Martin K. Petersen
@ 2021-09-22  4:45 ` Martin K. Petersen
  1 sibling, 0 replies; 18+ messages in thread
From: Martin K. Petersen @ 2021-09-22  4:45 UTC (permalink / raw)
  To: Ajish Koshy, linux-scsi
  Cc: Martin K . Petersen, Vasanthalakshmi.Tharmarajan, Jinpu Wang,
	Ruksar.devadi, Viswas.G, Ashokkumar.N

On Mon, 6 Sep 2021 22:34:00 +0530, Ajish Koshy wrote:

> This patchset includes bugfixes for pm80xx driver
> 
> Changes from v1 to v2:
> 	- For fix incorrect port value patch
> 		- More detailed commit message now
> 		  mentioning problem and fix.
> 	- For fix lockup due to commit patch
> 		- Commit message includes little detail
> 		  of previous commit.
> 		- Added 'Fixes' tag.
> 
> [...]

Applied to 5.16/scsi-queue, thanks!

[1/4] scsi: pm80xx: fix incorrect port value when registering a device
      https://git.kernel.org/mkp/scsi/c/08d0a992131a
[2/4] scsi: pm80xx: fix lockup due to commit <1f02beff224e>
      https://git.kernel.org/mkp/scsi/c/b27a40534ef7
[3/4] scsi: pm80xx: Corrected Inbound and Outbound queue logging
      https://git.kernel.org/mkp/scsi/c/c29737d03c74
[4/4] scsi: pm80xx: fix memory leak during rmmod
      https://git.kernel.org/mkp/scsi/c/51e6ed83bb4a

-- 
Martin K. Petersen	Oracle Linux Engineering

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

* Re: [PATCH v2 0/4] pm80xx updates
  2021-09-06 17:04 [PATCH v2 0/4] pm80xx updates Ajish Koshy
@ 2021-09-15  2:29 ` Martin K. Petersen
  2021-09-22  4:45 ` Martin K. Petersen
  1 sibling, 0 replies; 18+ messages in thread
From: Martin K. Petersen @ 2021-09-15  2:29 UTC (permalink / raw)
  To: Ajish Koshy
  Cc: linux-scsi, Vasanthalakshmi.Tharmarajan, Viswas.G, Ruksar.devadi,
	Ashokkumar.N, Jinpu Wang


Ajish,

> This patchset includes bugfixes for pm80xx driver
>
> Ajish Koshy (3):
>   scsi: pm80xx: fix incorrect port value when registering a device
>   scsi: pm80xx: fix lockup due to commit <1f02beff224e>
>   scsi: pm80xx: fix memory leak during rmmod
>
> Viswas G (1):
>   scsi: pm80xx: Corrected Inbound and Outbound queue logging

Applied to 5.16/scsi-staging, thanks!

-- 
Martin K. Petersen	Oracle Linux Engineering

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

* [PATCH v2 0/4] pm80xx updates
@ 2021-09-06 17:04 Ajish Koshy
  2021-09-15  2:29 ` Martin K. Petersen
  2021-09-22  4:45 ` Martin K. Petersen
  0 siblings, 2 replies; 18+ messages in thread
From: Ajish Koshy @ 2021-09-06 17:04 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, Ruksar.devadi,
	Ashokkumar.N, Jinpu Wang

This patchset includes bugfixes for pm80xx driver

Changes from v1 to v2:
	- For fix incorrect port value patch
		- More detailed commit message now
		  mentioning problem and fix.
	- For fix lockup due to commit patch
		- Commit message includes little detail
		  of previous commit.
		- Added 'Fixes' tag.
		  

Ajish Koshy (3):
  scsi: pm80xx: fix incorrect port value when registering a device
  scsi: pm80xx: fix lockup due to commit <1f02beff224e>
  scsi: pm80xx: fix memory leak during rmmod

Viswas G (1):
  scsi: pm80xx: Corrected Inbound and Outbound queue logging

 drivers/scsi/pm8001/pm8001_ctl.c  |  6 ++--
 drivers/scsi/pm8001/pm8001_hwi.c  |  7 +++-
 drivers/scsi/pm8001/pm8001_init.c | 12 +++++++
 drivers/scsi/pm8001/pm8001_sas.c  | 15 ++++++++
 drivers/scsi/pm8001/pm8001_sas.h  |  6 ++--
 drivers/scsi/pm8001/pm80xx_hwi.c  | 60 +++++++++++++++++++++++++------
 6 files changed, 91 insertions(+), 15 deletions(-)

-- 
2.27.0


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

* Re: [PATCH V2 0/4] pm80xx updates.
  2020-10-05 14:50 [PATCH V2 " Viswas G
  2020-10-07  2:06 ` Martin K. Petersen
@ 2020-10-13 22:43 ` Martin K. Petersen
  1 sibling, 0 replies; 18+ messages in thread
From: Martin K. Petersen @ 2020-10-13 22:43 UTC (permalink / raw)
  To: Viswas G, linux-scsi
  Cc: Martin K . Petersen, Vasanthalakshmi.Tharmarajan, Jinpu Wang,
	Viswas.G, Ruksar.devadi

On Mon, 5 Oct 2020 20:20:07 +0530, Viswas G wrote:

> Changes from v1:
> 	- Improved commit messages.
> 	- Fixed compiler warning for
> 		 "Increase the number of outstanding IO supported" patch
> 
> Viswas G (4):
>   pm80xx: Increase number of supported queues.
>   pm80xx: Remove DMA memory allocation for ccb and device structures.
>   pm80xx: Increase the number of outstanding IO supported to 1024.
>   pm80xx: Driver version update
> 
> [...]

Applied to 5.10/scsi-queue, thanks!

[1/4] scsi: pm80xx: Increase number of supported queues
      https://git.kernel.org/mkp/scsi/c/05c6c029a44d
[2/4] scsi: pm80xx: Remove DMA memory allocation for ccb and device structures
      https://git.kernel.org/mkp/scsi/c/27bc43bd7c42
[3/4] scsi: pm80xx: Increase the number of outstanding I/O supported to 1024
      https://git.kernel.org/mkp/scsi/c/5a141315ed7c
[4/4] scsi: pm80xx: Driver version update
      https://git.kernel.org/mkp/scsi/c/39a45d538dba

-- 
Martin K. Petersen	Oracle Linux Engineering

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

* Re: [PATCH V2 0/4] pm80xx updates.
  2020-10-07  3:03   ` Douglas Gilbert
  2020-10-07  3:28     ` Bart Van Assche
@ 2020-10-07  3:43     ` Martin K. Petersen
  1 sibling, 0 replies; 18+ messages in thread
From: Martin K. Petersen @ 2020-10-07  3:43 UTC (permalink / raw)
  To: Douglas Gilbert
  Cc: Martin K. Petersen, Viswas G, linux-scsi,
	Vasanthalakshmi.Tharmarajan, Viswas.G, Ruksar.devadi, Jinpu Wang


Hello Doug,

> As for "imperative mood", I believe there is no such thing in English
> grammar.

"Imperative mood" is how it is described in submitting-patches.rst. I
deliberately use the same term in my feedback emails to make it easy for
the recipient to locate the relevant section in that file.

If you believe that the official process document should be amended,
feel free to reach out to linux-doc.

-- 
Martin K. Petersen	Oracle Linux Engineering

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

* Re: [PATCH V2 0/4] pm80xx updates.
  2020-10-07  3:03   ` Douglas Gilbert
@ 2020-10-07  3:28     ` Bart Van Assche
  2020-10-07  3:43     ` Martin K. Petersen
  1 sibling, 0 replies; 18+ messages in thread
From: Bart Van Assche @ 2020-10-07  3:28 UTC (permalink / raw)
  To: dgilbert, Martin K. Petersen, Viswas G
  Cc: linux-scsi, Vasanthalakshmi.Tharmarajan, Viswas.G, Ruksar.devadi,
	Jinpu Wang

On 2020-10-06 20:03, Douglas Gilbert wrote:
> Is the "imperative mood" something in Danish or German grammar?

Have you already encountered this?
https://en.wikipedia.org/wiki/Imperative_mood#English

Thanks,

Bart.

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

* Re: [PATCH V2 0/4] pm80xx updates.
  2020-10-07  2:06 ` Martin K. Petersen
@ 2020-10-07  3:03   ` Douglas Gilbert
  2020-10-07  3:28     ` Bart Van Assche
  2020-10-07  3:43     ` Martin K. Petersen
  0 siblings, 2 replies; 18+ messages in thread
From: Douglas Gilbert @ 2020-10-07  3:03 UTC (permalink / raw)
  To: Martin K. Petersen, Viswas G
  Cc: linux-scsi, Vasanthalakshmi.Tharmarajan, Viswas.G, Ruksar.devadi,
	Jinpu Wang

On 2020-10-06 10:06 p.m., Martin K. Petersen wrote:
> 
> Viswas,
> 
>> Changes from v1:
>> 	- Improved commit messages.
>> 	- Fixed compiler warning for
>> 		 "Increase the number of outstanding IO supported" patch
> 
> Applied to 5.10/scsi-staging.
> 
> In the future please run checkpatch and make sure that the commit
> messages are using imperative mood (see
> Documentation/process/submitting-patches.rst, section 2).

Get thee to a nunnery! [W. Shakespeare; translation: "fuck off"]
Now that is imperative.

As for "imperative mood", I believe there is no such thing in English
grammar. My mother taught grammar and I studied French and Latin at
school. Markus Elfring objected to my:
     [PATCH] lib/scatterlist: Fix memory leak in sgl_alloc_order()  ***

with the same "imperative mood" line. In English, including British
(i.e. "international") English taught in south Asia, that is the
_imperative_ . Basically if you can stick "You" in front of the
verb at the start of the sentence and the sense is the same, then
it is the imperative.

Is the "imperative mood" something in Danish or German grammar?

Doug Gilbert


*** That patch was ack-ed by Bart (the culprit) and as far as I
     know hasn't gone any further. My sgl-to-sgl copy, compare
     and sgl_memset await that bug being sorted.


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

* Re: [PATCH V2 0/4] pm80xx updates.
  2020-10-05 14:50 [PATCH V2 " Viswas G
@ 2020-10-07  2:06 ` Martin K. Petersen
  2020-10-07  3:03   ` Douglas Gilbert
  2020-10-13 22:43 ` Martin K. Petersen
  1 sibling, 1 reply; 18+ messages in thread
From: Martin K. Petersen @ 2020-10-07  2:06 UTC (permalink / raw)
  To: Viswas G
  Cc: linux-scsi, Vasanthalakshmi.Tharmarajan, Viswas.G, Ruksar.devadi,
	Jinpu Wang


Viswas,

> Changes from v1:
> 	- Improved commit messages.
> 	- Fixed compiler warning for 
> 		 "Increase the number of outstanding IO supported" patch 

Applied to 5.10/scsi-staging.

In the future please run checkpatch and make sure that the commit
messages are using imperative mood (see
Documentation/process/submitting-patches.rst, section 2).

Thanks!

-- 
Martin K. Petersen	Oracle Linux Engineering

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

* [PATCH V2 0/4] pm80xx updates.
@ 2020-10-05 14:50 Viswas G
  2020-10-07  2:06 ` Martin K. Petersen
  2020-10-13 22:43 ` Martin K. Petersen
  0 siblings, 2 replies; 18+ messages in thread
From: Viswas G @ 2020-10-05 14:50 UTC (permalink / raw)
  To: linux-scsi
  Cc: Vasanthalakshmi.Tharmarajan, Viswas.G, Ruksar.devadi, Jinpu Wang

From: Viswas G <Viswas.G@microchip.com>

Changes from v1:
	- Improved commit messages.
	- Fixed compiler warning for 
		 "Increase the number of outstanding IO supported" patch 

Viswas G (4):
  pm80xx: Increase number of supported queues.
  pm80xx: Remove DMA memory allocation for ccb and device structures.
  pm80xx: Increase the number of outstanding IO supported to 1024.
  pm80xx: Driver version update

 drivers/scsi/pm8001/pm8001_ctl.c  |   6 +-
 drivers/scsi/pm8001/pm8001_defs.h |  27 +++--
 drivers/scsi/pm8001/pm8001_hwi.c  |  38 +++----
 drivers/scsi/pm8001/pm8001_init.c | 221 ++++++++++++++++++++++++++------------
 drivers/scsi/pm8001/pm8001_sas.h  |  15 ++-
 drivers/scsi/pm8001/pm80xx_hwi.c  | 109 ++++++++++---------
 6 files changed, 254 insertions(+), 162 deletions(-)

-- 
2.16.3


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

end of thread, other threads:[~2021-09-22  4:45 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-30  6:09 [PATCH V2 0/4] pm80xx updates Viswas G
2020-10-30  6:09 ` [PATCH V2 1/4] pm80xx: make mpi_build_cmd locking consistent Viswas G
2020-10-30  6:51   ` Jinpu Wang
2020-10-30  6:09 ` [PATCH V2 2/4] pm80xx: make running_req atomic Viswas G
2020-10-30  7:34   ` Jinpu Wang
2020-10-30  6:09 ` [PATCH V2 3/4] pm80xx: Avoid busywait in FW ready check Viswas G
2020-10-30  7:35   ` Jinpu Wang
2020-10-30  6:09 ` [PATCH V2 4/4] pm80xx: make pm8001_mpi_set_nvmd_resp free of race condition Viswas G
2020-10-30  7:44   ` Jinpu Wang
  -- strict thread matches above, loose matches on Subject: below --
2021-09-06 17:04 [PATCH v2 0/4] pm80xx updates Ajish Koshy
2021-09-15  2:29 ` Martin K. Petersen
2021-09-22  4:45 ` Martin K. Petersen
2020-10-05 14:50 [PATCH V2 " Viswas G
2020-10-07  2:06 ` Martin K. Petersen
2020-10-07  3:03   ` Douglas Gilbert
2020-10-07  3:28     ` Bart Van Assche
2020-10-07  3:43     ` Martin K. Petersen
2020-10-13 22:43 ` 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.