All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/31] libsas and pm8001 fixes
@ 2022-02-14  2:17 Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 01/31] scsi: libsas: Fix sas_ata_qc_issue() handling of NCQ NON DATA commands Damien Le Moal
                   ` (32 more replies)
  0 siblings, 33 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

This first part of this series (patches 1 to 24) fixes handling of NCQ
NON DATA commands in libsas and many bugs in the pm8001 driver.

The fixes for the pm8001 driver include:
* Suppression of all sparse warnings, fixing along the way many le32
  handling bugs for big-endian architectures
* Fix handling of NCQ NON DATA commands
* Fix of tag values handling (0 *is* a valid tag value)
* Fix many tag iand memory leaks in error path
* Fix NCQ error recovery (abort all task execution) that was causing a
  crash

The second part of the series (patches 25 to 31) iadd a small cleanup of
libsas code and many simplifications of the pm8001 driver code.

With these fixes, libzbc test suite passes all test case. This test
suite was used with an SMR drive for testing because it generates many
NCQ NON DATA commands (for zone management commands) and also generates
many NCQ command errors to check ASC/ASCQ returned by the device. With
the test suite, the error recovery path was extensively exercised. The
same tests were also executed with a SAS SMR drives to exercise the
error path.

The patches are based on the 5.18/scsi-staging tree.

Changes from v2:
* Reorganized the series: fixes first, cleanups second.
* Added more bug/leaks fix patches
* Addressed Gary's comment for the ccb alloc helper (patch 28)
* Rebased (and tested) all patches on 5.18/scsi-staging

Changes from v1:
* Added reviewed-by tags
* Addressed Christoph's comments on patch 4 and 8
* Added patches 21 and 22 to fix 2 additional problems found while
  preparing this v2 series
* Added patch 23 and 24 to cleanup the code further.

Damien Le Moal (31):
  scsi: libsas: Fix sas_ata_qc_issue() handling of NCQ NON DATA commands
  scsi: pm8001: Fix __iomem pointer use in pm8001_phy_control()
  scsi: pm8001: Fix pm8001_update_flash() local variable type
  scsi: pm8001: Fix command initialization in pm80XX_send_read_log()
  scsi: pm8001: Fix pm80xx_pci_mem_copy() interface
  scsi: pm8001: Fix command initialization in pm8001_chip_ssp_tm_req()
  scsi: pm8001: Fix payload initialization in pm80xx_set_thermal_config()
  scsi: pm8001: Fix le32 values handling in pm80xx_set_sas_protocol_timer_config()
  scsi: pm8001: Fix payload initialization in pm80xx_encrypt_update()
  scsi: pm8001: Fix le32 values handling in pm80xx_chip_ssp_io_req()
  scsi: pm8001: Fix le32 values handling in pm80xx_chip_sata_req()
  scsi: pm8001: Fix use of struct set_phy_profile_req fields
  scsi: pm8001: Remove local variable in pm8001_pci_resume()
  scsi: pm8001: Fix NCQ NON DATA command task initialization
  scsi: pm8001: Fix NCQ NON DATA command completion handling
  scsi: pm8001: Fix abort all task initialization
  scsi: pm8001: Fix pm8001_tag_alloc() failures handling
  scsi: pm8001: Fix pm80xx_chip_phy_ctl_req()
  scsi: pm8001: Fix pm8001_mpi_task_abort_resp()
  scsi: pm8001: Fix tag values handling
  scsi: pm8001: Fix task leak in pm8001_send_abort_all()
  scsi: pm8001: Fix tag leaks on error
  scsi: pm8001: fix memory leak in pm8001_chip_fw_flash_update_req()
  scsi: pm8001: Fix process_one_iomb() kdoc comment
  scsi: libsas: Simplify sas_ata_qc_issue() detection of NCQ commands
  scsi: pm8001: Simplify pm8001_get_ncq_tag()
  scsi: pm8001: Cleanup pm8001_queue_command()
  scsi: pm8001: Introduce ccb alloc/free helpers
  scsi: pm8001: Simplify pm8001_mpi_build_cmd() interface
  scsi: pm8001: Simplify pm8001_task_exec()
  scsi: pm8001: Simplify pm8001_ccb_task_free()

 drivers/scsi/libsas/sas_ata.c     |  11 +-
 drivers/scsi/pm8001/pm8001_ctl.c  |   5 +-
 drivers/scsi/pm8001/pm8001_hwi.c  | 450 ++++++++++++-----------------
 drivers/scsi/pm8001/pm8001_init.c |  11 +-
 drivers/scsi/pm8001/pm8001_sas.c  | 297 +++++++++----------
 drivers/scsi/pm8001/pm8001_sas.h  |  64 ++++-
 drivers/scsi/pm8001/pm80xx_hwi.c  | 458 ++++++++++++++----------------
 drivers/scsi/pm8001/pm80xx_hwi.h  |   2 +-
 8 files changed, 605 insertions(+), 693 deletions(-)

-- 
2.34.1


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

* [PATCH v3 01/31] scsi: libsas: Fix sas_ata_qc_issue() handling of NCQ NON DATA commands
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14 17:56   ` John Garry
  2022-02-14  2:17 ` [PATCH v3 02/31] scsi: pm8001: Fix __iomem pointer use in pm8001_phy_control() Damien Le Moal
                   ` (31 subsequent siblings)
  32 siblings, 1 reply; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

To detect for the DMA_NONE (no data transfer) DMA direction,
sas_ata_qc_issue() tests if the command protocol is ATA_PROT_NODATA.
This test does not include the ATA_CMD_NCQ_NON_DATA command as this
command protocol is defined as ATA_PROT_NCQ_NODATA (equal to
ATA_PROT_FLAG_NCQ) and not as ATA_PROT_NODATA.

To include both NCQ and non-NCQ commands when testing for the DMA_NONE
DMA direction, use "!ata_is_data()".

Fixes: 176ddd89171d ("scsi: libsas: Reset num_scatter if libata marks qc as NODATA")
Cc: stable@vger.kernel.org
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/libsas/sas_ata.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index e0030a093994..50f779088b6e 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -197,7 +197,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
 		task->total_xfer_len = qc->nbytes;
 		task->num_scatter = qc->n_elem;
 		task->data_dir = qc->dma_dir;
-	} else if (qc->tf.protocol == ATA_PROT_NODATA) {
+	} else if (!ata_is_data(qc->tf.protocol)) {
 		task->data_dir = DMA_NONE;
 	} else {
 		for_each_sg(qc->sg, sg, qc->n_elem, si)
-- 
2.34.1


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

* [PATCH v3 02/31] scsi: pm8001: Fix __iomem pointer use in pm8001_phy_control()
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 01/31] scsi: libsas: Fix sas_ata_qc_issue() handling of NCQ NON DATA commands Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 03/31] scsi: pm8001: Fix pm8001_update_flash() local variable type Damien Le Moal
                   ` (30 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

Avoid the sparse warning "warning: cast removes address space '__iomem'
of expression" by declaring the qp pointer as "u32 __iomem *".
Accordingly, change the accesses to the qp array to use readl().

Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm8001_sas.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index b3530f53df25..6062664e8698 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -234,14 +234,13 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
 		}
 		{
 			struct sas_phy *phy = sas_phy->phy;
-			uint32_t *qp = (uint32_t *)(((char *)
-				pm8001_ha->io_mem[2].memvirtaddr)
-				+ 0x1034 + (0x4000 * (phy_id & 3)));
-
-			phy->invalid_dword_count = qp[0];
-			phy->running_disparity_error_count = qp[1];
-			phy->loss_of_dword_sync_count = qp[3];
-			phy->phy_reset_problem_count = qp[4];
+			u32 __iomem *qp = pm8001_ha->io_mem[2].memvirtaddr
+				+ 0x1034 + (0x4000 * (phy_id & 3));
+
+			phy->invalid_dword_count = readl(qp);
+			phy->running_disparity_error_count = readl(&qp[1]);
+			phy->loss_of_dword_sync_count = readl(&qp[3]);
+			phy->phy_reset_problem_count = readl(&qp[4]);
 		}
 		if (pm8001_ha->chip_id == chip_8001)
 			pm8001_bar4_shift(pm8001_ha, 0);
-- 
2.34.1


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

* [PATCH v3 03/31] scsi: pm8001: Fix pm8001_update_flash() local variable type
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 01/31] scsi: libsas: Fix sas_ata_qc_issue() handling of NCQ NON DATA commands Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 02/31] scsi: pm8001: Fix __iomem pointer use in pm8001_phy_control() Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 04/31] scsi: pm8001: Fix command initialization in pm80XX_send_read_log() Damien Le Moal
                   ` (29 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

Change the type of partitionSizeTmp from u32 to __be32 to suppress the
sparse warning:

warning: cast to restricted __be32

Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm8001_ctl.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 66307783c73c..73f036bed128 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -721,7 +721,8 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha)
 	DECLARE_COMPLETION_ONSTACK(completion);
 	u8		*ioctlbuffer;
 	struct fw_control_info	*fwControl;
-	u32		partitionSize, partitionSizeTmp;
+	__be32		partitionSizeTmp;
+	u32		partitionSize;
 	u32		loopNumber, loopcount;
 	struct pm8001_fw_image_header *image_hdr;
 	u32		sizeRead = 0;
@@ -742,7 +743,7 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha)
 	image_hdr = (struct pm8001_fw_image_header *)pm8001_ha->fw_image->data;
 	while (sizeRead < pm8001_ha->fw_image->size) {
 		partitionSizeTmp =
-			*(u32 *)((u8 *)&image_hdr->image_length + sizeRead);
+			*(__be32 *)((u8 *)&image_hdr->image_length + sizeRead);
 		partitionSize = be32_to_cpu(partitionSizeTmp);
 		loopcount = DIV_ROUND_UP(partitionSize + HEADER_LEN,
 					IOCTL_BUF_SIZE);
-- 
2.34.1


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

* [PATCH v3 04/31] scsi: pm8001: Fix command initialization in pm80XX_send_read_log()
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (2 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 03/31] scsi: pm8001: Fix pm8001_update_flash() local variable type Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 05/31] scsi: pm8001: Fix pm80xx_pci_mem_copy() interface Damien Le Moal
                   ` (28 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

Since the sata_cmd struct is zeroed out before its fields are
initialized, there is no need for using "|=" to initialize the
ncqtag_atap_dir_m field. Using a standard assignment removes the sparse
warning:

warning: invalid assignment: |=

Also, since the ncqtag_atap_dir_m field has type __le32, use
cpu_to_le32() to generate the assigned value.

Fixes: c6b9ef5779c3 ("[SCSI] pm80xx: NCQ error handling changes")
Reviewed-by: John Garry <john.garry@huawei.com>
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c | 2 +-
 drivers/scsi/pm8001/pm80xx_hwi.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index a9decac0b5cc..dff859bc5501 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1864,7 +1864,7 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
 
 	sata_cmd.tag = cpu_to_le32(ccb_tag);
 	sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
-	sata_cmd.ncqtag_atap_dir_m |= ((0x1 << 7) | (0x5 << 9));
+	sata_cmd.ncqtag_atap_dir_m = cpu_to_le32((0x1 << 7) | (0x5 << 9));
 	memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
 
 	res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd,
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 26b64524e327..aa0c4566db4f 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -1882,7 +1882,7 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
 
 	sata_cmd.tag = cpu_to_le32(ccb_tag);
 	sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
-	sata_cmd.ncqtag_atap_dir_m_dad |= ((0x1 << 7) | (0x5 << 9));
+	sata_cmd.ncqtag_atap_dir_m_dad = cpu_to_le32(((0x1 << 7) | (0x5 << 9)));
 	memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
 
 	res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd,
-- 
2.34.1


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

* [PATCH v3 05/31] scsi: pm8001: Fix pm80xx_pci_mem_copy() interface
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (3 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 04/31] scsi: pm8001: Fix command initialization in pm80XX_send_read_log() Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 06/31] scsi: pm8001: Fix command initialization in pm8001_chip_ssp_tm_req() Damien Le Moal
                   ` (27 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

The declaration of the local variable destination1 in
pm80xx_pci_mem_copy() as a pointer to a u32 results in the sparse
warning:

warning: incorrect type in assignment (different base types)
    expected unsigned int [usertype]
    got restricted __le32 [usertype]

Furthermore, the destination" argument of pm80xx_pci_mem_copy() is
wrongly declared with the const attribute.

Fix both problems by changing the type of the "destination" argument
to "__le32 *" and use this argument directly inside the
pm80xx_pci_mem_copy() function, thus removing the need for the
destination1 local variable.

Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index aa0c4566db4f..8a2d4087d405 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -67,18 +67,16 @@ int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shift_value)
 }
 
 static void pm80xx_pci_mem_copy(struct pm8001_hba_info  *pm8001_ha, u32 soffset,
-				const void *destination,
+				__le32 *destination,
 				u32 dw_count, u32 bus_base_number)
 {
 	u32 index, value, offset;
-	u32 *destination1;
-	destination1 = (u32 *)destination;
 
-	for (index = 0; index < dw_count; index += 4, destination1++) {
+	for (index = 0; index < dw_count; index += 4, destination++) {
 		offset = (soffset + index);
 		if (offset < (64 * 1024)) {
 			value = pm8001_cr32(pm8001_ha, bus_base_number, offset);
-			*destination1 =  cpu_to_le32(value);
+			*destination = cpu_to_le32(value);
 		}
 	}
 	return;
-- 
2.34.1


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

* [PATCH v3 06/31] scsi: pm8001: Fix command initialization in pm8001_chip_ssp_tm_req()
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (4 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 05/31] scsi: pm8001: Fix pm80xx_pci_mem_copy() interface Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 07/31] scsi: pm8001: Fix payload initialization in pm80xx_set_thermal_config() Damien Le Moal
                   ` (26 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

The ds_ads_m field of struct ssp_ini_tm_start_req has the type __le32.
Assigning a value to it should thus use cpu_to_le32(). This fixes the
sparse warning:

warning: incorrect type in assignment (different base types)
   expected restricted __le32 [addressable] [assigned] [usertype] ds_ads_m
   got int

Fixes: dbf9bfe61571 ("[SCSI] pm8001: add SAS/SATA HBA driver")
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index dff859bc5501..3893bd470bcc 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -4636,7 +4636,7 @@ int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha,
 	memcpy(sspTMCmd.lun, task->ssp_task.LUN, 8);
 	sspTMCmd.tag = cpu_to_le32(ccb->ccb_tag);
 	if (pm8001_ha->chip_id != chip_8001)
-		sspTMCmd.ds_ads_m = 0x08;
+		sspTMCmd.ds_ads_m = cpu_to_le32(0x08);
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd,
 			sizeof(sspTMCmd), 0);
-- 
2.34.1


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

* [PATCH v3 07/31] scsi: pm8001: Fix payload initialization in pm80xx_set_thermal_config()
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (5 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 06/31] scsi: pm8001: Fix command initialization in pm8001_chip_ssp_tm_req() Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 08/31] scsi: pm8001: Fix le32 values handling in pm80xx_set_sas_protocol_timer_config() Damien Le Moal
                   ` (25 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

The fields of the set_ctrl_cfg_req structure have the __le32 type, so
use cpu_to_le32() to assign them. This removes the sparse warnings:

warning: incorrect type in assignment (different base types)
    expected restricted __le32
    got unsigned int

Fixes: 842784e0d15b ("pm80xx: Update For Thermal Page Code")
Fixes: f5860992db55 ("[SCSI] pm80xx: Added SPCv/ve specific hardware functionalities and relevant changes in common files")
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
Reviewed-by: John Garry <john.garry@huawei.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 8a2d4087d405..f9c4cec514fb 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -1201,9 +1201,11 @@ pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha)
 	else
 		page_code = THERMAL_PAGE_CODE_8H;
 
-	payload.cfg_pg[0] = (THERMAL_LOG_ENABLE << 9) |
-				(THERMAL_ENABLE << 8) | page_code;
-	payload.cfg_pg[1] = (LTEMPHIL << 24) | (RTEMPHIL << 8);
+	payload.cfg_pg[0] =
+		cpu_to_le32((THERMAL_LOG_ENABLE << 9) |
+			    (THERMAL_ENABLE << 8) | page_code);
+	payload.cfg_pg[1] =
+		cpu_to_le32((LTEMPHIL << 24) | (RTEMPHIL << 8));
 
 	pm8001_dbg(pm8001_ha, DEV,
 		   "Setting up thermal config. cfg_pg 0 0x%x cfg_pg 1 0x%x\n",
-- 
2.34.1


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

* [PATCH v3 08/31] scsi: pm8001: Fix le32 values handling in pm80xx_set_sas_protocol_timer_config()
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (6 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 07/31] scsi: pm8001: Fix payload initialization in pm80xx_set_thermal_config() Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 09/31] scsi: pm8001: Fix payload initialization in pm80xx_encrypt_update() Damien Le Moal
                   ` (24 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

All fields of the SASProtocolTimerConfig structure have the __le32 type.
As such, use cpu_to_le32() to initialize them. This change suppresses
many sparse warnings:

warning: incorrect type in assignment (different base types)
   expected restricted __le32 [addressable] [usertype] pageCode
   got int

Note that the check to limit the value of the STP_IDLE_TMO field is
removed as this field is initialized using the fixed (and small) value
defined by the STP_IDLE_TIME macro.

The pm8001_dbg() calls printing the values of the SASProtocolTimerConfig
structure fileds are changed to use le32_to_cpu() to present the values
in human readable form.

Fixes: a6cb3d012b98 ("[SCSI] pm80xx: thermal, sas controller config and error handling update")
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 52 +++++++++++++++-----------------
 1 file changed, 25 insertions(+), 27 deletions(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index f9c4cec514fb..108e4743fe81 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -1245,43 +1245,41 @@ pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha)
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	payload.tag = cpu_to_le32(tag);
 
-	SASConfigPage.pageCode        =  SAS_PROTOCOL_TIMER_CONFIG_PAGE;
-	SASConfigPage.MST_MSI         =  3 << 15;
-	SASConfigPage.STP_SSP_MCT_TMO =  (STP_MCT_TMO << 16) | SSP_MCT_TMO;
-	SASConfigPage.STP_FRM_TMO     = (SAS_MAX_OPEN_TIME << 24) |
-				(SMP_MAX_CONN_TIMER << 16) | STP_FRM_TIMER;
-	SASConfigPage.STP_IDLE_TMO    =  STP_IDLE_TIME;
-
-	if (SASConfigPage.STP_IDLE_TMO > 0x3FFFFFF)
-		SASConfigPage.STP_IDLE_TMO = 0x3FFFFFF;
-
-
-	SASConfigPage.OPNRJT_RTRY_INTVL =         (SAS_MFD << 16) |
-						SAS_OPNRJT_RTRY_INTVL;
-	SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO =  (SAS_DOPNRJT_RTRY_TMO << 16)
-						| SAS_COPNRJT_RTRY_TMO;
-	SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR =  (SAS_DOPNRJT_RTRY_THR << 16)
-						| SAS_COPNRJT_RTRY_THR;
-	SASConfigPage.MAX_AIP =  SAS_MAX_AIP;
+	SASConfigPage.pageCode = cpu_to_le32(SAS_PROTOCOL_TIMER_CONFIG_PAGE);
+	SASConfigPage.MST_MSI = cpu_to_le32(3 << 15);
+	SASConfigPage.STP_SSP_MCT_TMO =
+		cpu_to_le32((STP_MCT_TMO << 16) | SSP_MCT_TMO);
+	SASConfigPage.STP_FRM_TMO =
+		cpu_to_le32((SAS_MAX_OPEN_TIME << 24) |
+			    (SMP_MAX_CONN_TIMER << 16) | STP_FRM_TIMER);
+	SASConfigPage.STP_IDLE_TMO = cpu_to_le32(STP_IDLE_TIME);
+
+	SASConfigPage.OPNRJT_RTRY_INTVL =
+		cpu_to_le32((SAS_MFD << 16) | SAS_OPNRJT_RTRY_INTVL);
+	SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO =
+		cpu_to_le32((SAS_DOPNRJT_RTRY_TMO << 16) | SAS_COPNRJT_RTRY_TMO);
+	SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR =
+		cpu_to_le32((SAS_DOPNRJT_RTRY_THR << 16) | SAS_COPNRJT_RTRY_THR);
+	SASConfigPage.MAX_AIP = cpu_to_le32(SAS_MAX_AIP);
 
 	pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.pageCode 0x%08x\n",
-		   SASConfigPage.pageCode);
+		   le32_to_cpu(SASConfigPage.pageCode));
 	pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.MST_MSI  0x%08x\n",
-		   SASConfigPage.MST_MSI);
+		   le32_to_cpu(SASConfigPage.MST_MSI));
 	pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.STP_SSP_MCT_TMO  0x%08x\n",
-		   SASConfigPage.STP_SSP_MCT_TMO);
+		   le32_to_cpu(SASConfigPage.STP_SSP_MCT_TMO));
 	pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.STP_FRM_TMO  0x%08x\n",
-		   SASConfigPage.STP_FRM_TMO);
+		   le32_to_cpu(SASConfigPage.STP_FRM_TMO));
 	pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.STP_IDLE_TMO  0x%08x\n",
-		   SASConfigPage.STP_IDLE_TMO);
+		   le32_to_cpu(SASConfigPage.STP_IDLE_TMO));
 	pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.OPNRJT_RTRY_INTVL  0x%08x\n",
-		   SASConfigPage.OPNRJT_RTRY_INTVL);
+		   le32_to_cpu(SASConfigPage.OPNRJT_RTRY_INTVL));
 	pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO  0x%08x\n",
-		   SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO);
+		   le32_to_cpu(SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO));
 	pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR  0x%08x\n",
-		   SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR);
+		   le32_to_cpu(SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR));
 	pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.MAX_AIP  0x%08x\n",
-		   SASConfigPage.MAX_AIP);
+		   le32_to_cpu(SASConfigPage.MAX_AIP));
 
 	memcpy(&payload.cfg_pg, &SASConfigPage,
 			 sizeof(SASProtocolTimerConfig_t));
-- 
2.34.1


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

* [PATCH v3 09/31] scsi: pm8001: Fix payload initialization in pm80xx_encrypt_update()
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (7 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 08/31] scsi: pm8001: Fix le32 values handling in pm80xx_set_sas_protocol_timer_config() Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 10/31] scsi: pm8001: Fix le32 values handling in pm80xx_chip_ssp_io_req() Damien Le Moal
                   ` (23 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

All fields of the kek_mgmt_req structure have the type __le32. So make
sure to use cpu_to_le32() to initialize them. This suppresses the sparse
warning:

warning: incorrect type in assignment (different base types)
   expected restricted __le32 [addressable] [assigned] [usertype] new_curidx_ksop
   got int

Fixes: 5860992db55c ("[SCSI] pm80xx: Added SPCv/ve specific hardware functionalities and relevant changes in common files")
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 108e4743fe81..8e4c515f54f4 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -1405,12 +1405,13 @@ static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha)
 	/* Currently only one key is used. New KEK index is 1.
 	 * Current KEK index is 1. Store KEK to NVRAM is 1.
 	 */
-	payload.new_curidx_ksop = ((1 << 24) | (1 << 16) | (1 << 8) |
-					KEK_MGMT_SUBOP_KEYCARDUPDATE);
+	payload.new_curidx_ksop =
+		cpu_to_le32(((1 << 24) | (1 << 16) | (1 << 8) |
+			     KEK_MGMT_SUBOP_KEYCARDUPDATE));
 
 	pm8001_dbg(pm8001_ha, DEV,
 		   "Saving Encryption info to flash. payload 0x%x\n",
-		   payload.new_curidx_ksop);
+		   le32_to_cpu(payload.new_curidx_ksop));
 
 	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
 			sizeof(payload), 0);
-- 
2.34.1


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

* [PATCH v3 10/31] scsi: pm8001: Fix le32 values handling in pm80xx_chip_ssp_io_req()
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (8 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 09/31] scsi: pm8001: Fix payload initialization in pm80xx_encrypt_update() Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 11/31] scsi: pm8001: Fix le32 values handling in pm80xx_chip_sata_req() Damien Le Moal
                   ` (22 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

Make sure that the __le32 fields of struct ssp_ini_io_start_req are
manipulated after applying the correct endian conversion. That is, use
cpu_to_le32() for assigning values and le32_to_cpu() for consulting a
field value. In particular, make sure that the calculations for the 4G
boundary check are done using CPU endianness and *not* little endian
values. With these fixes, many sparse warnings are removed.

While at it, add blank lines after variable declarations and in some
other places to make this code more readable.

Fixes: 0ecdf00ba6e5 ("[SCSI] pm80xx: 4G boundary fix.")
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 41 +++++++++++++++++++-------------
 1 file changed, 25 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 8e4c515f54f4..0ed4bc114e5e 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -4386,13 +4386,15 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
 	struct ssp_ini_io_start_req ssp_cmd;
 	u32 tag = ccb->ccb_tag;
 	int ret;
-	u64 phys_addr, start_addr, end_addr;
+	u64 phys_addr, end_addr;
 	u32 end_addr_high, end_addr_low;
 	struct inbound_queue_table *circularQ;
 	u32 q_index, cpu_id;
 	u32 opc = OPC_INB_SSPINIIOSTART;
+
 	memset(&ssp_cmd, 0, sizeof(ssp_cmd));
 	memcpy(ssp_cmd.ssp_iu.lun, task->ssp_task.LUN, 8);
+
 	/* data address domain added for spcv; set to 0 by host,
 	 * used internally by controller
 	 * 0 for SAS 1.1 and SAS 2.0 compatible TLR
@@ -4403,7 +4405,7 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
 	ssp_cmd.device_id = cpu_to_le32(pm8001_dev->device_id);
 	ssp_cmd.tag = cpu_to_le32(tag);
 	if (task->ssp_task.enable_first_burst)
-		ssp_cmd.ssp_iu.efb_prio_attr |= 0x80;
+		ssp_cmd.ssp_iu.efb_prio_attr = 0x80;
 	ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_prio << 3);
 	ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7);
 	memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cmd->cmnd,
@@ -4435,21 +4437,24 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
 			ssp_cmd.enc_esgl = cpu_to_le32(1<<31);
 		} else if (task->num_scatter == 1) {
 			u64 dma_addr = sg_dma_address(task->scatter);
+
 			ssp_cmd.enc_addr_low =
 				cpu_to_le32(lower_32_bits(dma_addr));
 			ssp_cmd.enc_addr_high =
 				cpu_to_le32(upper_32_bits(dma_addr));
 			ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
 			ssp_cmd.enc_esgl = 0;
+
 			/* Check 4G Boundary */
-			start_addr = cpu_to_le64(dma_addr);
-			end_addr = (start_addr + ssp_cmd.enc_len) - 1;
-			end_addr_low = cpu_to_le32(lower_32_bits(end_addr));
-			end_addr_high = cpu_to_le32(upper_32_bits(end_addr));
-			if (end_addr_high != ssp_cmd.enc_addr_high) {
+			end_addr = dma_addr + le32_to_cpu(ssp_cmd.enc_len) - 1;
+			end_addr_low = lower_32_bits(end_addr);
+			end_addr_high = upper_32_bits(end_addr);
+
+			if (end_addr_high != le32_to_cpu(ssp_cmd.enc_addr_high)) {
 				pm8001_dbg(pm8001_ha, FAIL,
 					   "The sg list address start_addr=0x%016llx data_len=0x%x end_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n",
-					   start_addr, ssp_cmd.enc_len,
+					   dma_addr,
+					   le32_to_cpu(ssp_cmd.enc_len),
 					   end_addr_high, end_addr_low);
 				pm8001_chip_make_sg(task->scatter, 1,
 					ccb->buf_prd);
@@ -4458,7 +4463,7 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
 					cpu_to_le32(lower_32_bits(phys_addr));
 				ssp_cmd.enc_addr_high =
 					cpu_to_le32(upper_32_bits(phys_addr));
-				ssp_cmd.enc_esgl = cpu_to_le32(1<<31);
+				ssp_cmd.enc_esgl = cpu_to_le32(1U<<31);
 			}
 		} else if (task->num_scatter == 0) {
 			ssp_cmd.enc_addr_low = 0;
@@ -4466,8 +4471,10 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
 			ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
 			ssp_cmd.enc_esgl = 0;
 		}
+
 		/* XTS mode. All other fields are 0 */
-		ssp_cmd.key_cmode = 0x6 << 4;
+		ssp_cmd.key_cmode = cpu_to_le32(0x6 << 4);
+
 		/* set tweak values. Should be the start lba */
 		ssp_cmd.twk_val0 = cpu_to_le32((task->ssp_task.cmd->cmnd[2] << 24) |
 						(task->ssp_task.cmd->cmnd[3] << 16) |
@@ -4489,20 +4496,22 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
 			ssp_cmd.esgl = cpu_to_le32(1<<31);
 		} else if (task->num_scatter == 1) {
 			u64 dma_addr = sg_dma_address(task->scatter);
+
 			ssp_cmd.addr_low = cpu_to_le32(lower_32_bits(dma_addr));
 			ssp_cmd.addr_high =
 				cpu_to_le32(upper_32_bits(dma_addr));
 			ssp_cmd.len = cpu_to_le32(task->total_xfer_len);
 			ssp_cmd.esgl = 0;
+
 			/* Check 4G Boundary */
-			start_addr = cpu_to_le64(dma_addr);
-			end_addr = (start_addr + ssp_cmd.len) - 1;
-			end_addr_low = cpu_to_le32(lower_32_bits(end_addr));
-			end_addr_high = cpu_to_le32(upper_32_bits(end_addr));
-			if (end_addr_high != ssp_cmd.addr_high) {
+			end_addr = dma_addr + le32_to_cpu(ssp_cmd.len) - 1;
+			end_addr_low = lower_32_bits(end_addr);
+			end_addr_high = upper_32_bits(end_addr);
+			if (end_addr_high != le32_to_cpu(ssp_cmd.addr_high)) {
 				pm8001_dbg(pm8001_ha, FAIL,
 					   "The sg list address start_addr=0x%016llx data_len=0x%x end_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n",
-					   start_addr, ssp_cmd.len,
+					   dma_addr,
+					   le32_to_cpu(ssp_cmd.len),
 					   end_addr_high, end_addr_low);
 				pm8001_chip_make_sg(task->scatter, 1,
 					ccb->buf_prd);
-- 
2.34.1


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

* [PATCH v3 11/31] scsi: pm8001: Fix le32 values handling in pm80xx_chip_sata_req()
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (9 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 10/31] scsi: pm8001: Fix le32 values handling in pm80xx_chip_ssp_io_req() Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 12/31] scsi: pm8001: Fix use of struct set_phy_profile_req fields Damien Le Moal
                   ` (21 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

Make sure that the __le32 fields of struct sata_cmd are manipulated
after applying the correct endian conversion. That is, use cpu_to_le32()
for assigning values and le32_to_cpu() for consulting a field value.
In particular, make sure that the calculations for the 4G boundary check
are done using CPU endianness and *not* little endian values. With these
fixes, many sparse warnings are removed.

While at it, fix some code identation and add blank lines after
variable declarations and in some other places to make this code more
readable.

Fixes: 0ecdf00ba6e5 ("[SCSI] pm80xx: 4G boundary fix.")
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 82 ++++++++++++++++++--------------
 1 file changed, 45 insertions(+), 37 deletions(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 0ed4bc114e5e..8ebefdb18c85 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -4546,7 +4546,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
 	u32 q_index, cpu_id;
 	struct sata_start_req sata_cmd;
 	u32 hdr_tag, ncg_tag = 0;
-	u64 phys_addr, start_addr, end_addr;
+	u64 phys_addr, end_addr;
 	u32 end_addr_high, end_addr_low;
 	u32 ATAP = 0x0;
 	u32 dir;
@@ -4607,32 +4607,38 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
 			pm8001_chip_make_sg(task->scatter,
 						ccb->n_elem, ccb->buf_prd);
 			phys_addr = ccb->ccb_dma_handle;
-			sata_cmd.enc_addr_low = lower_32_bits(phys_addr);
-			sata_cmd.enc_addr_high = upper_32_bits(phys_addr);
+			sata_cmd.enc_addr_low =
+				cpu_to_le32(lower_32_bits(phys_addr));
+			sata_cmd.enc_addr_high =
+				cpu_to_le32(upper_32_bits(phys_addr));
 			sata_cmd.enc_esgl = cpu_to_le32(1 << 31);
 		} else if (task->num_scatter == 1) {
 			u64 dma_addr = sg_dma_address(task->scatter);
-			sata_cmd.enc_addr_low = lower_32_bits(dma_addr);
-			sata_cmd.enc_addr_high = upper_32_bits(dma_addr);
+
+			sata_cmd.enc_addr_low =
+				cpu_to_le32(lower_32_bits(dma_addr));
+			sata_cmd.enc_addr_high =
+				cpu_to_le32(upper_32_bits(dma_addr));
 			sata_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
 			sata_cmd.enc_esgl = 0;
+
 			/* Check 4G Boundary */
-			start_addr = cpu_to_le64(dma_addr);
-			end_addr = (start_addr + sata_cmd.enc_len) - 1;
-			end_addr_low = cpu_to_le32(lower_32_bits(end_addr));
-			end_addr_high = cpu_to_le32(upper_32_bits(end_addr));
-			if (end_addr_high != sata_cmd.enc_addr_high) {
+			end_addr = dma_addr + le32_to_cpu(sata_cmd.enc_len) - 1;
+			end_addr_low = lower_32_bits(end_addr);
+			end_addr_high = upper_32_bits(end_addr);
+			if (end_addr_high != le32_to_cpu(sata_cmd.enc_addr_high)) {
 				pm8001_dbg(pm8001_ha, FAIL,
 					   "The sg list address start_addr=0x%016llx data_len=0x%x end_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n",
-					   start_addr, sata_cmd.enc_len,
+					   dma_addr,
+					   le32_to_cpu(sata_cmd.enc_len),
 					   end_addr_high, end_addr_low);
 				pm8001_chip_make_sg(task->scatter, 1,
 					ccb->buf_prd);
 				phys_addr = ccb->ccb_dma_handle;
 				sata_cmd.enc_addr_low =
-					lower_32_bits(phys_addr);
+					cpu_to_le32(lower_32_bits(phys_addr));
 				sata_cmd.enc_addr_high =
-					upper_32_bits(phys_addr);
+					cpu_to_le32(upper_32_bits(phys_addr));
 				sata_cmd.enc_esgl =
 					cpu_to_le32(1 << 31);
 			}
@@ -4643,7 +4649,8 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
 			sata_cmd.enc_esgl = 0;
 		}
 		/* XTS mode. All other fields are 0 */
-		sata_cmd.key_index_mode = 0x6 << 4;
+		sata_cmd.key_index_mode = cpu_to_le32(0x6 << 4);
+
 		/* set tweak values. Should be the start lba */
 		sata_cmd.twk_val0 =
 			cpu_to_le32((sata_cmd.sata_fis.lbal_exp << 24) |
@@ -4669,31 +4676,31 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
 			phys_addr = ccb->ccb_dma_handle;
 			sata_cmd.addr_low = lower_32_bits(phys_addr);
 			sata_cmd.addr_high = upper_32_bits(phys_addr);
-			sata_cmd.esgl = cpu_to_le32(1 << 31);
+			sata_cmd.esgl = cpu_to_le32(1U << 31);
 		} else if (task->num_scatter == 1) {
 			u64 dma_addr = sg_dma_address(task->scatter);
+
 			sata_cmd.addr_low = lower_32_bits(dma_addr);
 			sata_cmd.addr_high = upper_32_bits(dma_addr);
 			sata_cmd.len = cpu_to_le32(task->total_xfer_len);
 			sata_cmd.esgl = 0;
+
 			/* Check 4G Boundary */
-			start_addr = cpu_to_le64(dma_addr);
-			end_addr = (start_addr + sata_cmd.len) - 1;
-			end_addr_low = cpu_to_le32(lower_32_bits(end_addr));
-			end_addr_high = cpu_to_le32(upper_32_bits(end_addr));
+			end_addr = dma_addr + le32_to_cpu(sata_cmd.len) - 1;
+			end_addr_low = lower_32_bits(end_addr);
+			end_addr_high = upper_32_bits(end_addr);
 			if (end_addr_high != sata_cmd.addr_high) {
 				pm8001_dbg(pm8001_ha, FAIL,
 					   "The sg list address start_addr=0x%016llx data_len=0x%xend_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n",
-					   start_addr, sata_cmd.len,
+					   dma_addr,
+					   le32_to_cpu(sata_cmd.len),
 					   end_addr_high, end_addr_low);
 				pm8001_chip_make_sg(task->scatter, 1,
 					ccb->buf_prd);
 				phys_addr = ccb->ccb_dma_handle;
-				sata_cmd.addr_low =
-					lower_32_bits(phys_addr);
-				sata_cmd.addr_high =
-					upper_32_bits(phys_addr);
-				sata_cmd.esgl = cpu_to_le32(1 << 31);
+				sata_cmd.addr_low = lower_32_bits(phys_addr);
+				sata_cmd.addr_high = upper_32_bits(phys_addr);
+				sata_cmd.esgl = cpu_to_le32(1U << 31);
 			}
 		} else if (task->num_scatter == 0) {
 			sata_cmd.addr_low = 0;
@@ -4701,27 +4708,28 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
 			sata_cmd.len = cpu_to_le32(task->total_xfer_len);
 			sata_cmd.esgl = 0;
 		}
+
 		/* scsi cdb */
 		sata_cmd.atapi_scsi_cdb[0] =
 			cpu_to_le32(((task->ata_task.atapi_packet[0]) |
-			(task->ata_task.atapi_packet[1] << 8) |
-			(task->ata_task.atapi_packet[2] << 16) |
-			(task->ata_task.atapi_packet[3] << 24)));
+				     (task->ata_task.atapi_packet[1] << 8) |
+				     (task->ata_task.atapi_packet[2] << 16) |
+				     (task->ata_task.atapi_packet[3] << 24)));
 		sata_cmd.atapi_scsi_cdb[1] =
 			cpu_to_le32(((task->ata_task.atapi_packet[4]) |
-			(task->ata_task.atapi_packet[5] << 8) |
-			(task->ata_task.atapi_packet[6] << 16) |
-			(task->ata_task.atapi_packet[7] << 24)));
+				     (task->ata_task.atapi_packet[5] << 8) |
+				     (task->ata_task.atapi_packet[6] << 16) |
+				     (task->ata_task.atapi_packet[7] << 24)));
 		sata_cmd.atapi_scsi_cdb[2] =
 			cpu_to_le32(((task->ata_task.atapi_packet[8]) |
-			(task->ata_task.atapi_packet[9] << 8) |
-			(task->ata_task.atapi_packet[10] << 16) |
-			(task->ata_task.atapi_packet[11] << 24)));
+				     (task->ata_task.atapi_packet[9] << 8) |
+				     (task->ata_task.atapi_packet[10] << 16) |
+				     (task->ata_task.atapi_packet[11] << 24)));
 		sata_cmd.atapi_scsi_cdb[3] =
 			cpu_to_le32(((task->ata_task.atapi_packet[12]) |
-			(task->ata_task.atapi_packet[13] << 8) |
-			(task->ata_task.atapi_packet[14] << 16) |
-			(task->ata_task.atapi_packet[15] << 24)));
+				     (task->ata_task.atapi_packet[13] << 8) |
+				     (task->ata_task.atapi_packet[14] << 16) |
+				     (task->ata_task.atapi_packet[15] << 24)));
 	}
 
 	/* Check for read log for failed drive and return */
-- 
2.34.1


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

* [PATCH v3 12/31] scsi: pm8001: Fix use of struct set_phy_profile_req fields
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (10 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 11/31] scsi: pm8001: Fix le32 values handling in pm80xx_chip_sata_req() Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 13/31] scsi: pm8001: Remove local variable in pm8001_pci_resume() Damien Le Moal
                   ` (20 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

In mpi_set_phy_profile_req() and pm8001_set_phy_profile_single(), use
cpu_to_le32() to initialize the ppc_phyid field of struct
set_phy_profile_req. Furthermore, fix the definition of the reserved
field of this structure to be an array of __le32, to match the use of
cpu_to_le32() when assigning values. These changes remove several sparse
type warnings.

Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 12 +++++++-----
 drivers/scsi/pm8001/pm80xx_hwi.h |  2 +-
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 8ebefdb18c85..ad2e40425fbf 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -4982,12 +4982,13 @@ static void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha,
 		pm8001_dbg(pm8001_ha, FAIL, "Invalid tag\n");
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	payload.tag = cpu_to_le32(tag);
-	payload.ppc_phyid = (((operation & 0xF) << 8) | (phyid  & 0xFF));
+	payload.ppc_phyid =
+		cpu_to_le32(((operation & 0xF) << 8) | (phyid  & 0xFF));
 	pm8001_dbg(pm8001_ha, INIT,
 		   " phy profile command for phy %x ,length is %d\n",
-		   payload.ppc_phyid, length);
+		   le32_to_cpu(payload.ppc_phyid), length);
 	for (i = length; i < (length + PHY_DWORD_LENGTH - 1); i++) {
-		payload.reserved[j] =  cpu_to_le32(*((u32 *)buf + i));
+		payload.reserved[j] = cpu_to_le32(*((u32 *)buf + i));
 		j++;
 	}
 	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
@@ -5027,8 +5028,9 @@ void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha,
 	opc = OPC_INB_SET_PHY_PROFILE;
 
 	payload.tag = cpu_to_le32(tag);
-	payload.ppc_phyid = (((SAS_PHY_ANALOG_SETTINGS_PAGE & 0xF) << 8)
-				| (phy & 0xFF));
+	payload.ppc_phyid =
+		cpu_to_le32(((SAS_PHY_ANALOG_SETTINGS_PAGE & 0xF) << 8)
+			    | (phy & 0xFF));
 
 	for (i = 0; i < length; i++)
 		payload.reserved[i] = cpu_to_le32(*(buf + i));
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index c7e5d93bea92..7cb59e38e67a 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -972,7 +972,7 @@ struct dek_mgmt_req {
 struct set_phy_profile_req {
 	__le32	tag;
 	__le32	ppc_phyid;
-	u32	reserved[29];
+	__le32	reserved[29];
 } __attribute__((packed, aligned(4)));
 
 /**
-- 
2.34.1


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

* [PATCH v3 13/31] scsi: pm8001: Remove local variable in pm8001_pci_resume()
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (11 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 12/31] scsi: pm8001: Fix use of struct set_phy_profile_req fields Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 14/31] scsi: pm8001: Fix NCQ NON DATA command task initialization Damien Le Moal
                   ` (19 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

In pm8001_pci_resume(), the use of the u32 type for the local variable
device_state causes a sparse warning:

warning: incorrect type in assignment (different base types)
    expected unsigned int [usertype] device_state
    got restricted pci_power_t [usertype] current_state

Since this variable is used only once in the function, remove it and
use pdev->current_state directly. While at it, also add a blank line
after the last local variable declaration.

Reviewed-by: John Garry <john.garry@huawei.com>
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm8001_init.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index d8a2121cb8d9..4b9a26f008a9 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -1335,13 +1335,13 @@ static int __maybe_unused pm8001_pci_resume(struct device *dev)
 	struct pm8001_hba_info *pm8001_ha;
 	int rc;
 	u8 i = 0, j;
-	u32 device_state;
 	DECLARE_COMPLETION_ONSTACK(completion);
+
 	pm8001_ha = sha->lldd_ha;
-	device_state = pdev->current_state;
 
-	pm8001_info(pm8001_ha, "pdev=0x%p, slot=%s, resuming from previous operating state [D%d]\n",
-		      pdev, pm8001_ha->name, device_state);
+	pm8001_info(pm8001_ha,
+		    "pdev=0x%p, slot=%s, resuming from previous operating state [D%d]\n",
+		    pdev, pm8001_ha->name, pdev->current_state);
 
 	rc = pci_go_44(pdev);
 	if (rc)
-- 
2.34.1


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

* [PATCH v3 14/31] scsi: pm8001: Fix NCQ NON DATA command task initialization
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (12 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 13/31] scsi: pm8001: Remove local variable in pm8001_pci_resume() Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 15/31] scsi: pm8001: Fix NCQ NON DATA command completion handling Damien Le Moal
                   ` (18 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

In the pm8001_chip_sata_req() and pm80xx_chip_sata_req() functions, all
tasks with a DMA direction of DMA_NONE (no data transfer) are
initialized using the ATAP value 0x04. However, NCQ NON DATA commands,
while being DMA_NONE commands are NCQ commands and need to be
initialized using the value 0x07 for ATAP, similarly to other NCQ
commands.

Make sure that NCQ NON DATA command tasks are initialized similarly to
other NCQ commands by also testing the task "use_ncq" field in addition
to the DMA direction. While at it, reorganize the code into a chain of
if - else if - else to avoid useless affectations and debug messages.

Fixes: dbf9bfe61571 ("[SCSI] pm8001: add SAS/SATA HBA driver")
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c | 14 +++++++-------
 drivers/scsi/pm8001/pm80xx_hwi.c | 13 ++++++-------
 2 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 3893bd470bcc..3c667e67cd2e 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -4282,22 +4282,22 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
 	u32  opc = OPC_INB_SATA_HOST_OPSTART;
 	memset(&sata_cmd, 0, sizeof(sata_cmd));
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
-	if (task->data_dir == DMA_NONE) {
+
+	if (task->data_dir == DMA_NONE && !task->ata_task.use_ncq) {
 		ATAP = 0x04;  /* no data*/
 		pm8001_dbg(pm8001_ha, IO, "no data\n");
 	} else if (likely(!task->ata_task.device_control_reg_update)) {
-		if (task->ata_task.dma_xfer) {
+		if (task->ata_task.use_ncq &&
+		    dev->sata_dev.class != ATA_DEV_ATAPI) {
+			ATAP = 0x07; /* FPDMA */
+			pm8001_dbg(pm8001_ha, IO, "FPDMA\n");
+		} else if (task->ata_task.dma_xfer) {
 			ATAP = 0x06; /* DMA */
 			pm8001_dbg(pm8001_ha, IO, "DMA\n");
 		} else {
 			ATAP = 0x05; /* PIO*/
 			pm8001_dbg(pm8001_ha, IO, "PIO\n");
 		}
-		if (task->ata_task.use_ncq &&
-			dev->sata_dev.class != ATA_DEV_ATAPI) {
-			ATAP = 0x07; /* FPDMA */
-			pm8001_dbg(pm8001_ha, IO, "FPDMA\n");
-		}
 	}
 	if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) {
 		task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index ad2e40425fbf..e3b03ddc26f8 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -4558,22 +4558,21 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
 	q_index = (u32) (cpu_id) % (pm8001_ha->max_q_num);
 	circularQ = &pm8001_ha->inbnd_q_tbl[q_index];
 
-	if (task->data_dir == DMA_NONE) {
+	if (task->data_dir == DMA_NONE && !task->ata_task.use_ncq) {
 		ATAP = 0x04; /* no data*/
 		pm8001_dbg(pm8001_ha, IO, "no data\n");
 	} else if (likely(!task->ata_task.device_control_reg_update)) {
-		if (task->ata_task.dma_xfer) {
+		if (task->ata_task.use_ncq &&
+		    dev->sata_dev.class != ATA_DEV_ATAPI) {
+			ATAP = 0x07; /* FPDMA */
+			pm8001_dbg(pm8001_ha, IO, "FPDMA\n");
+		} else if (task->ata_task.dma_xfer) {
 			ATAP = 0x06; /* DMA */
 			pm8001_dbg(pm8001_ha, IO, "DMA\n");
 		} else {
 			ATAP = 0x05; /* PIO*/
 			pm8001_dbg(pm8001_ha, IO, "PIO\n");
 		}
-		if (task->ata_task.use_ncq &&
-		    dev->sata_dev.class != ATA_DEV_ATAPI) {
-			ATAP = 0x07; /* FPDMA */
-			pm8001_dbg(pm8001_ha, IO, "FPDMA\n");
-		}
 	}
 	if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) {
 		task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
-- 
2.34.1


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

* [PATCH v3 15/31] scsi: pm8001: Fix NCQ NON DATA command completion handling
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (13 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 14/31] scsi: pm8001: Fix NCQ NON DATA command task initialization Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 16/31] scsi: pm8001: Fix abort all task initialization Damien Le Moal
                   ` (17 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

NCQ NON DATA is an NCQ command with the DMA_NONE DMA direction and so a
register-device-to-host-FIS response is expected for it.

However, for an IO_SUCCESS case, mpi_sata_completion() expects a
set-device-bits-FIS for any ata task with an use_ncq field true, which
includes NCQ NON DATA commands.

Fix this to correctly treat NCQ NON DATA commands as non-data by also
testing for the DMA_NONE DMA direction.

Fixes: dbf9bfe61571 ("[SCSI] pm8001: add SAS/SATA HBA driver")
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c | 3 ++-
 drivers/scsi/pm8001/pm80xx_hwi.c | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 3c667e67cd2e..10a78312fbaf 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -2415,7 +2415,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 				len = sizeof(struct pio_setup_fis);
 				pm8001_dbg(pm8001_ha, IO,
 					   "PIO read len = %d\n", len);
-			} else if (t->ata_task.use_ncq) {
+			} else if (t->ata_task.use_ncq &&
+				   t->data_dir != DMA_NONE) {
 				len = sizeof(struct set_dev_bits_fis);
 				pm8001_dbg(pm8001_ha, IO, "FPDMA len = %d\n",
 					   len);
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index e3b03ddc26f8..082b6353d3fb 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -2507,7 +2507,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha,
 				len = sizeof(struct pio_setup_fis);
 				pm8001_dbg(pm8001_ha, IO,
 					   "PIO read len = %d\n", len);
-			} else if (t->ata_task.use_ncq) {
+			} else if (t->ata_task.use_ncq &&
+				   t->data_dir != DMA_NONE) {
 				len = sizeof(struct set_dev_bits_fis);
 				pm8001_dbg(pm8001_ha, IO, "FPDMA len = %d\n",
 					   len);
-- 
2.34.1


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

* [PATCH v3 16/31] scsi: pm8001: Fix abort all task initialization
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (14 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 15/31] scsi: pm8001: Fix NCQ NON DATA command completion handling Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 17/31] scsi: pm8001: Fix pm8001_tag_alloc() failures handling Damien Le Moal
                   ` (16 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

In pm80xx_send_abort_all(), the n_elem field of the ccb used is not
initialized to 0. This missing initialization sometimes lead to the
task completion path seeing the ccb with a non-zero n_elem resulting in
the execution of invalid dma_unmap_sg() calls in pm8001_ccb_task_free(),
causing a crash such as:

[  197.676341] RIP: 0010:iommu_dma_unmap_sg+0x6d/0x280
[  197.700204] RSP: 0018:ffff889bbcf89c88 EFLAGS: 00010012
[  197.705485] RAX: dffffc0000000000 RBX: 0000000000000000 RCX: ffffffff83d0bda0
[  197.712687] RDX: 0000000000000002 RSI: 0000000000000000 RDI: ffff88810dffc0d0
[  197.719887] RBP: 0000000000000000 R08: 0000000000000000 R09: ffff8881c790098b
[  197.727089] R10: ffffed1038f20131 R11: 0000000000000001 R12: 0000000000000000
[  197.734296] R13: ffff88810dffc0d0 R14: 0000000000000010 R15: 0000000000000000
[  197.741493] FS:  0000000000000000(0000) GS:ffff889bbcf80000(0000) knlGS:0000000000000000
[  197.749659] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  197.755459] CR2: 00007f16c1b42734 CR3: 0000000004814000 CR4: 0000000000350ee0
[  197.762656] Call Trace:
[  197.765127]  <IRQ>
[  197.767162]  pm8001_ccb_task_free+0x5f1/0x820 [pm80xx]
[  197.772364]  ? do_raw_spin_unlock+0x54/0x220
[  197.776680]  pm8001_mpi_task_abort_resp+0x2ce/0x4f0 [pm80xx]
[  197.782406]  process_oq+0xe85/0x7890 [pm80xx]
[  197.786817]  ? lock_acquire+0x194/0x490
[  197.790697]  ? handle_irq_event+0x10e/0x1b0
[  197.794920]  ? mpi_sata_completion+0x2d70/0x2d70 [pm80xx]
[  197.800378]  ? __wake_up_bit+0x100/0x100
[  197.804340]  ? lock_is_held_type+0x98/0x110
[  197.808565]  pm80xx_chip_isr+0x94/0x130 [pm80xx]
[  197.813243]  tasklet_action_common.constprop.0+0x24b/0x2f0
[  197.818785]  __do_softirq+0x1b5/0x82d
[  197.822485]  ? do_raw_spin_unlock+0x54/0x220
[  197.826799]  __irq_exit_rcu+0x17e/0x1e0
[  197.830678]  irq_exit_rcu+0xa/0x20
[  197.834114]  common_interrupt+0x78/0x90
[  197.840051]  </IRQ>
[  197.844236]  <TASK>
[  197.848397]  asm_common_interrupt+0x1e/0x40

Avoid this issue by always initializing the ccb n_elem field to 0 in
pm8001_send_abort_all(), pm8001_send_read_log() and
pm80xx_send_abort_all().

Fixes: c6b9ef5779c3 ("[SCSI] pm80xx: NCQ error handling changes")
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c | 2 ++
 drivers/scsi/pm8001/pm80xx_hwi.c | 1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 10a78312fbaf..e801d4b64d09 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1787,6 +1787,7 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
 	ccb->device = pm8001_ha_dev;
 	ccb->ccb_tag = ccb_tag;
 	ccb->task = task;
+	ccb->n_elem = 0;
 
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 
@@ -1848,6 +1849,7 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
 	ccb->device = pm8001_ha_dev;
 	ccb->ccb_tag = ccb_tag;
 	ccb->task = task;
+	ccb->n_elem = 0;
 	pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG;
 	pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG;
 
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 082b6353d3fb..413b01cc2a84 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -1800,6 +1800,7 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha,
 	ccb->device = pm8001_ha_dev;
 	ccb->ccb_tag = ccb_tag;
 	ccb->task = task;
+	ccb->n_elem = 0;
 
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 
-- 
2.34.1


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

* [PATCH v3 17/31] scsi: pm8001: Fix pm8001_tag_alloc() failures handling
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (15 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 16/31] scsi: pm8001: Fix abort all task initialization Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14 18:02   ` John Garry
  2022-02-14  2:17 ` [PATCH v3 18/31] scsi: pm8001: Fix pm80xx_chip_phy_ctl_req() Damien Le Moal
                   ` (15 subsequent siblings)
  32 siblings, 1 reply; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

In mpi_set_phy_profile_req() and in pm8001_set_phy_profile_single(), if
pm8001_tag_alloc() fails to allocate a new tag, a warning message is
issued but the uninitialized tag variable is still used to build a
command. Avoid this by returning early in case of tag allocation
failure.

Also make sure to always return the error code returned by
pm8001_tag_alloc() when this function fails instead of an arbitrary
value.

Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 413b01cc2a84..b0b6dc643916 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -1191,7 +1191,7 @@ pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha)
 	memset(&payload, 0, sizeof(struct set_ctrl_cfg_req));
 	rc = pm8001_tag_alloc(pm8001_ha, &tag);
 	if (rc)
-		return -1;
+		return rc;
 
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	payload.tag = cpu_to_le32(tag);
@@ -1240,7 +1240,7 @@ pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha)
 	rc = pm8001_tag_alloc(pm8001_ha, &tag);
 
 	if (rc)
-		return -1;
+		return rc;
 
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	payload.tag = cpu_to_le32(tag);
@@ -1398,7 +1398,7 @@ static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha)
 	memset(&payload, 0, sizeof(struct kek_mgmt_req));
 	rc = pm8001_tag_alloc(pm8001_ha, &tag);
 	if (rc)
-		return -1;
+		return rc;
 
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	payload.tag = cpu_to_le32(tag);
@@ -4979,8 +4979,11 @@ static void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha,
 
 	memset(&payload, 0, sizeof(payload));
 	rc = pm8001_tag_alloc(pm8001_ha, &tag);
-	if (rc)
+	if (rc) {
 		pm8001_dbg(pm8001_ha, FAIL, "Invalid tag\n");
+		return;
+	}
+
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	payload.tag = cpu_to_le32(tag);
 	payload.ppc_phyid =
@@ -5022,8 +5025,10 @@ void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha,
 	memset(&payload, 0, sizeof(payload));
 
 	rc = pm8001_tag_alloc(pm8001_ha, &tag);
-	if (rc)
+	if (rc) {
 		pm8001_dbg(pm8001_ha, INIT, "Invalid tag\n");
+		return;
+	}
 
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	opc = OPC_INB_SET_PHY_PROFILE;
-- 
2.34.1


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

* [PATCH v3 18/31] scsi: pm8001: Fix pm80xx_chip_phy_ctl_req()
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (16 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 17/31] scsi: pm8001: Fix pm8001_tag_alloc() failures handling Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 19/31] scsi: pm8001: Fix pm8001_mpi_task_abort_resp() Damien Le Moal
                   ` (14 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

If pm8001_mpi_build_cmd() fails, the allocated tag should be freed.

Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index b0b6dc643916..73e9379ab09a 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -4932,8 +4932,13 @@ static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
 	payload.tag = cpu_to_le32(tag);
 	payload.phyop_phyid =
 		cpu_to_le32(((phy_op & 0xFF) << 8) | (phyId & 0xFF));
-	return pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
-			sizeof(payload), 0);
+
+	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+				  sizeof(payload), 0);
+	if (rc)
+		pm8001_tag_free(pm8001_ha, tag);
+
+	return rc;
 }
 
 static u32 pm80xx_chip_is_our_interrupt(struct pm8001_hba_info *pm8001_ha)
-- 
2.34.1


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

* [PATCH v3 19/31] scsi: pm8001: Fix pm8001_mpi_task_abort_resp()
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (17 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 18/31] scsi: pm8001: Fix pm80xx_chip_phy_ctl_req() Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 20/31] scsi: pm8001: Fix tag values handling Damien Le Moal
                   ` (13 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

The call to pm8001_ccb_task_free() at the end of
pm8001_mpi_task_abort_resp() already frees the ccb tag. So when the
device NCQ_ABORT_ALL_FLAG is set, the tag should not be freed again.
Also change the hardcoded 0xBFFFFFFF value to ~NCQ_ABORT_ALL_FLAG as it
ought to be.

Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index e801d4b64d09..64a87c5bd66b 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3717,12 +3717,11 @@ int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 	mb();
 
 	if (pm8001_dev->id & NCQ_ABORT_ALL_FLAG) {
-		pm8001_tag_free(pm8001_ha, tag);
 		sas_free_task(t);
-		/* clear the flag */
-		pm8001_dev->id &= 0xBFFFFFFF;
-	} else
+		pm8001_dev->id &= ~NCQ_ABORT_ALL_FLAG;
+	} else {
 		t->task_done(t);
+	}
 
 	return 0;
 }
-- 
2.34.1


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

* [PATCH v3 20/31] scsi: pm8001: Fix tag values handling
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (18 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 19/31] scsi: pm8001: Fix pm8001_mpi_task_abort_resp() Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-15 11:09   ` John Garry
  2022-02-14  2:17 ` [PATCH v3 21/31] scsi: pm8001: Fix task leak in pm8001_send_abort_all() Damien Le Moal
                   ` (12 subsequent siblings)
  32 siblings, 1 reply; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

The function pm8001_tag_alloc() determines free tags using the function
find_first_zero_bit() which can return 0 when the first bit of the
bitmap being inspected is 0. As such, tag 0 is a valid tag value that
should not be dismissed as invalid. Fix the functions pm8001_work_fn(),
mpi_sata_completion(), pm8001_mpi_task_abort_resp() and
pm8001_open_reject_retry() to not dismiss 0 tags as invalid.

The value 0xffffffff is used for invalid tags for unused ccb
information structures. Add the macro definition PM8001_INVALID_TAG to
define this value.

Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c  | 52 +++++++++++--------------------
 drivers/scsi/pm8001/pm8001_init.c |  3 +-
 drivers/scsi/pm8001/pm8001_sas.c  | 13 ++++----
 drivers/scsi/pm8001/pm8001_sas.h  |  2 ++
 drivers/scsi/pm8001/pm80xx_hwi.c  |  5 ---
 5 files changed, 28 insertions(+), 47 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 64a87c5bd66b..640e8473ce06 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1522,7 +1522,6 @@ void pm8001_work_fn(struct work_struct *work)
 	case IO_XFER_ERROR_BREAK:
 	{	/* This one stashes the sas_task instead */
 		struct sas_task *t = (struct sas_task *)pm8001_dev;
-		u32 tag;
 		struct pm8001_ccb_info *ccb;
 		struct pm8001_hba_info *pm8001_ha = pw->pm8001_ha;
 		unsigned long flags, flags1;
@@ -1544,8 +1543,8 @@ void pm8001_work_fn(struct work_struct *work)
 		/* Search for a possible ccb that matches the task */
 		for (i = 0; ccb = NULL, i < PM8001_MAX_CCB; i++) {
 			ccb = &pm8001_ha->ccb_info[i];
-			tag = ccb->ccb_tag;
-			if ((tag != 0xFFFFFFFF) && (ccb->task == t))
+			if ((ccb->ccb_tag != PM8001_INVALID_TAG) &&
+			    (ccb->task == t))
 				break;
 		}
 		if (!ccb) {
@@ -1566,11 +1565,11 @@ void pm8001_work_fn(struct work_struct *work)
 			spin_unlock_irqrestore(&t->task_state_lock, flags1);
 			pm8001_dbg(pm8001_ha, FAIL, "task 0x%p done with event 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
 				   t, pw->handler, ts->resp, ts->stat);
-			pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+			pm8001_ccb_task_free(pm8001_ha, t, ccb, ccb->ccb_tag);
 			spin_unlock_irqrestore(&pm8001_ha->lock, flags);
 		} else {
 			spin_unlock_irqrestore(&t->task_state_lock, flags1);
-			pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+			pm8001_ccb_task_free(pm8001_ha, t, ccb, ccb->ccb_tag);
 			mb();/* in order to force CPU ordering */
 			spin_unlock_irqrestore(&pm8001_ha->lock, flags);
 			t->task_done(t);
@@ -1579,7 +1578,6 @@ void pm8001_work_fn(struct work_struct *work)
 	case IO_XFER_OPEN_RETRY_TIMEOUT:
 	{	/* This one stashes the sas_task instead */
 		struct sas_task *t = (struct sas_task *)pm8001_dev;
-		u32 tag;
 		struct pm8001_ccb_info *ccb;
 		struct pm8001_hba_info *pm8001_ha = pw->pm8001_ha;
 		unsigned long flags, flags1;
@@ -1613,8 +1611,8 @@ void pm8001_work_fn(struct work_struct *work)
 		/* Search for a possible ccb that matches the task */
 		for (i = 0; ccb = NULL, i < PM8001_MAX_CCB; i++) {
 			ccb = &pm8001_ha->ccb_info[i];
-			tag = ccb->ccb_tag;
-			if ((tag != 0xFFFFFFFF) && (ccb->task == t))
+			if ((ccb->ccb_tag != PM8001_INVALID_TAG) &&
+			    (ccb->task == t))
 				break;
 		}
 		if (!ccb) {
@@ -1685,19 +1683,13 @@ void pm8001_work_fn(struct work_struct *work)
 		struct task_status_struct *ts;
 		struct sas_task *task;
 		int i;
-		u32 tag, device_id;
+		u32 device_id;
 
 		for (i = 0; ccb = NULL, i < PM8001_MAX_CCB; i++) {
 			ccb = &pm8001_ha->ccb_info[i];
 			task = ccb->task;
 			ts = &task->task_status;
-			tag = ccb->ccb_tag;
-			/* check if tag is NULL */
-			if (!tag) {
-				pm8001_dbg(pm8001_ha, FAIL,
-					"tag Null\n");
-				continue;
-			}
+
 			if (task != NULL) {
 				dev = task->dev;
 				if (!dev) {
@@ -1706,10 +1698,11 @@ void pm8001_work_fn(struct work_struct *work)
 					continue;
 				}
 				/*complete sas task and update to top layer */
-				pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
+				pm8001_ccb_task_free(pm8001_ha, task, ccb,
+						     ccb->ccb_tag);
 				ts->resp = SAS_TASK_COMPLETE;
 				task->task_done(task);
-			} else if (tag != 0xFFFFFFFF) {
+			} else if (ccb->ccb_tag != PM8001_INVALID_TAG) {
 				/* complete the internal commands/non-sas task */
 				pm8001_dev = ccb->device;
 				if (pm8001_dev->dcompletion) {
@@ -1717,7 +1710,7 @@ void pm8001_work_fn(struct work_struct *work)
 					pm8001_dev->dcompletion = NULL;
 				}
 				complete(pm8001_ha->nvmd_completion);
-				pm8001_tag_free(pm8001_ha, tag);
+				pm8001_tag_free(pm8001_ha, ccb->ccb_tag);
 			}
 		}
 		/* Deregister all the device ids  */
@@ -2313,11 +2306,6 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 	param = le32_to_cpu(psataPayload->param);
 	tag = le32_to_cpu(psataPayload->tag);
 
-	if (!tag) {
-		pm8001_dbg(pm8001_ha, FAIL, "tag null\n");
-		return;
-	}
-
 	ccb = &pm8001_ha->ccb_info[tag];
 	t = ccb->task;
 	pm8001_dev = ccb->device;
@@ -3068,7 +3056,7 @@ void pm8001_mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha,
 		   device_id, pds, nds, status);
 	complete(pm8001_dev->setds_completion);
 	ccb->task = NULL;
-	ccb->ccb_tag = 0xFFFFFFFF;
+	ccb->ccb_tag = PM8001_INVALID_TAG;
 	pm8001_tag_free(pm8001_ha, tag);
 }
 
@@ -3086,7 +3074,7 @@ void pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 				dlen_status);
 	}
 	ccb->task = NULL;
-	ccb->ccb_tag = 0xFFFFFFFF;
+	ccb->ccb_tag = PM8001_INVALID_TAG;
 	pm8001_tag_free(pm8001_ha, tag);
 }
 
@@ -3113,7 +3101,7 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		 * freed by requesting path anywhere.
 		 */
 		ccb->task = NULL;
-		ccb->ccb_tag = 0xFFFFFFFF;
+		ccb->ccb_tag = PM8001_INVALID_TAG;
 		pm8001_tag_free(pm8001_ha, tag);
 		return;
 	}
@@ -3159,7 +3147,7 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 	complete(pm8001_ha->nvmd_completion);
 	pm8001_dbg(pm8001_ha, MSG, "Get nvmd data complete!\n");
 	ccb->task = NULL;
-	ccb->ccb_tag = 0xFFFFFFFF;
+	ccb->ccb_tag = PM8001_INVALID_TAG;
 	pm8001_tag_free(pm8001_ha, tag);
 }
 
@@ -3572,7 +3560,7 @@ int pm8001_mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 	}
 	complete(pm8001_dev->dcompletion);
 	ccb->task = NULL;
-	ccb->ccb_tag = 0xFFFFFFFF;
+	ccb->ccb_tag = PM8001_INVALID_TAG;
 	pm8001_tag_free(pm8001_ha, htag);
 	return 0;
 }
@@ -3644,7 +3632,7 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha,
 	}
 	kfree(ccb->fw_control_context);
 	ccb->task = NULL;
-	ccb->ccb_tag = 0xFFFFFFFF;
+	ccb->ccb_tag = PM8001_INVALID_TAG;
 	pm8001_tag_free(pm8001_ha, tag);
 	complete(pm8001_ha->nvmd_completion);
 	return 0;
@@ -3680,10 +3668,6 @@ int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 
 	status = le32_to_cpu(pPayload->status);
 	tag = le32_to_cpu(pPayload->tag);
-	if (!tag) {
-		pm8001_dbg(pm8001_ha, FAIL, " TAG NULL. RETURNING !!!\n");
-		return -1;
-	}
 
 	scp = le32_to_cpu(pPayload->scp);
 	ccb = &pm8001_ha->ccb_info[tag];
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 4b9a26f008a9..8f44be8364dc 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -1216,10 +1216,11 @@ pm8001_init_ccb_tag(struct pm8001_hba_info *pm8001_ha, struct Scsi_Host *shost,
 			goto err_out;
 		}
 		pm8001_ha->ccb_info[i].task = NULL;
-		pm8001_ha->ccb_info[i].ccb_tag = 0xffffffff;
+		pm8001_ha->ccb_info[i].ccb_tag = PM8001_INVALID_TAG;
 		pm8001_ha->ccb_info[i].device = NULL;
 		++pm8001_ha->tags_num;
 	}
+
 	return 0;
 
 err_out_noccb:
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 6062664e8698..d9b8d61b7578 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -563,7 +563,7 @@ void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha,
 
 	task->lldd_task = NULL;
 	ccb->task = NULL;
-	ccb->ccb_tag = 0xFFFFFFFF;
+	ccb->ccb_tag = PM8001_INVALID_TAG;
 	ccb->open_retry = 0;
 	pm8001_tag_free(pm8001_ha, ccb_idx);
 }
@@ -943,9 +943,11 @@ void pm8001_open_reject_retry(
 		struct task_status_struct *ts;
 		struct pm8001_device *pm8001_dev;
 		unsigned long flags1;
-		u32 tag;
 		struct pm8001_ccb_info *ccb = &pm8001_ha->ccb_info[i];
 
+		if (ccb->ccb_tag == PM8001_INVALID_TAG)
+			continue;
+
 		pm8001_dev = ccb->device;
 		if (!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED))
 			continue;
@@ -957,9 +959,6 @@ void pm8001_open_reject_retry(
 				continue;
 		} else if (pm8001_dev != device_to_close)
 			continue;
-		tag = ccb->ccb_tag;
-		if (!tag || (tag == 0xFFFFFFFF))
-			continue;
 		task = ccb->task;
 		if (!task || !task->task_done)
 			continue;
@@ -979,11 +978,11 @@ void pm8001_open_reject_retry(
 				& SAS_TASK_STATE_ABORTED))) {
 			spin_unlock_irqrestore(&task->task_state_lock,
 				flags1);
-			pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
+			pm8001_ccb_task_free(pm8001_ha, task, ccb, ccb->ccb_tag);
 		} else {
 			spin_unlock_irqrestore(&task->task_state_lock,
 				flags1);
-			pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
+			pm8001_ccb_task_free(pm8001_ha, task, ccb, ccb->ccb_tag);
 			mb();/* in order to force CPU ordering */
 			spin_unlock_irqrestore(&pm8001_ha->lock, flags);
 			task->task_done(task);
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index a17da1cebce1..1791cdf30276 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -738,6 +738,8 @@ void pm8001_free_dev(struct pm8001_device *pm8001_dev);
 /* ctl shared API */
 extern const struct attribute_group *pm8001_host_groups[];
 
+#define PM8001_INVALID_TAG	((u32)-1)
+
 static inline void
 pm8001_ccb_task_free_done(struct pm8001_hba_info *pm8001_ha,
 			struct sas_task *task, struct pm8001_ccb_info *ccb,
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 73e9379ab09a..9cea0a27f1a1 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -2402,11 +2402,6 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha,
 	param = le32_to_cpu(psataPayload->param);
 	tag = le32_to_cpu(psataPayload->tag);
 
-	if (!tag) {
-		pm8001_dbg(pm8001_ha, FAIL, "tag null\n");
-		return;
-	}
-
 	ccb = &pm8001_ha->ccb_info[tag];
 	t = ccb->task;
 	pm8001_dev = ccb->device;
-- 
2.34.1


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

* [PATCH v3 21/31] scsi: pm8001: Fix task leak in pm8001_send_abort_all()
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (19 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 20/31] scsi: pm8001: Fix tag values handling Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 22/31] scsi: pm8001: Fix tag leaks on error Damien Le Moal
                   ` (11 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

In pm8001_send_abort_all(), make sure to free the allocated sas task
if pm8001_tag_alloc() or pm8001_mpi_build_cmd() fail.

Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 640e8473ce06..5886c7a83238 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1764,7 +1764,6 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
 	}
 
 	task = sas_alloc_slow_task(GFP_ATOMIC);
-
 	if (!task) {
 		pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task\n");
 		return;
@@ -1773,8 +1772,10 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
 	task->task_done = pm8001_task_done;
 
 	res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
-	if (res)
+	if (res) {
+		sas_free_task(task);
 		return;
+	}
 
 	ccb = &pm8001_ha->ccb_info[ccb_tag];
 	ccb->device = pm8001_ha_dev;
@@ -1791,8 +1792,10 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
 
 	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort,
 			sizeof(task_abort), 0);
-	if (ret)
+	if (ret) {
+		sas_free_task(task);
 		pm8001_tag_free(pm8001_ha, ccb_tag);
+	}
 
 }
 
-- 
2.34.1


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

* [PATCH v3 22/31] scsi: pm8001: Fix tag leaks on error
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (20 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 21/31] scsi: pm8001: Fix task leak in pm8001_send_abort_all() Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 23/31] scsi: pm8001: fix memory leak in pm8001_chip_fw_flash_update_req() Damien Le Moal
                   ` (10 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

In pm8001_chip_set_dev_state_req(), pm8001_chip_fw_flash_update_req()
and pm8001_chip_reg_dev_req() add missing calls to pm8001_tag_free() to
free the allocated tag when pm8001_mpi_build_cmd() fails.

Similarly, in pm8001_exec_internal_task_abort(), if the chip
->task_abort method fails, the tag allocated for the abort request task
must be freed. Add the missing call to pm8001_tag_free(). Also remove
the useless ex_err label and use "break" instead of "goto" statements
in the retry loop.

Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c |  9 +++++++++
 drivers/scsi/pm8001/pm8001_sas.c | 33 +++++++++++++++++---------------
 2 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 5886c7a83238..2eff6e2f6cf9 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -4475,6 +4475,9 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
 		SAS_ADDR_SIZE);
 	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
 			sizeof(payload), 0);
+	if (rc)
+		pm8001_tag_free(pm8001_ha, tag);
+
 	return rc;
 }
 
@@ -4887,6 +4890,9 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
 	ccb->ccb_tag = tag;
 	rc = pm8001_chip_fw_flash_update_build(pm8001_ha, &flash_update_info,
 		tag);
+	if (rc)
+		pm8001_tag_free(pm8001_ha, tag);
+
 	return rc;
 }
 
@@ -4991,6 +4997,9 @@ pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha,
 	payload.nds = cpu_to_le32(state);
 	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
 			sizeof(payload), 0);
+	if (rc)
+		pm8001_tag_free(pm8001_ha, tag);
+
 	return rc;
 
 }
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index d9b8d61b7578..1e7031400294 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -829,7 +829,8 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
 
 		res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
 		if (res)
-			goto ex_err;
+			break;
+
 		ccb = &pm8001_ha->ccb_info[ccb_tag];
 		ccb->device = pm8001_dev;
 		ccb->ccb_tag = ccb_tag;
@@ -838,36 +839,38 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
 
 		res = PM8001_CHIP_DISP->task_abort(pm8001_ha,
 			pm8001_dev, flag, task_tag, ccb_tag);
-
 		if (res) {
 			del_timer(&task->slow_task->timer);
-			pm8001_dbg(pm8001_ha, FAIL, "Executing internal task failed\n");
-			goto ex_err;
+			pm8001_dbg(pm8001_ha, FAIL,
+				   "Executing internal task failed\n");
+			pm8001_tag_free(pm8001_ha, ccb_tag);
+			break;
 		}
+
 		wait_for_completion(&task->slow_task->completion);
 		res = TMF_RESP_FUNC_FAILED;
+
 		/* Even TMF timed out, return direct. */
 		if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
 			pm8001_dbg(pm8001_ha, FAIL, "TMF task timeout.\n");
-			goto ex_err;
+			break;
 		}
 
 		if (task->task_status.resp == SAS_TASK_COMPLETE &&
 			task->task_status.stat == SAS_SAM_STAT_GOOD) {
 			res = TMF_RESP_FUNC_COMPLETE;
 			break;
-
-		} else {
-			pm8001_dbg(pm8001_ha, EH,
-				   " Task to dev %016llx response: 0x%x status 0x%x\n",
-				   SAS_ADDR(dev->sas_addr),
-				   task->task_status.resp,
-				   task->task_status.stat);
-			sas_free_task(task);
-			task = NULL;
 		}
+
+		pm8001_dbg(pm8001_ha, EH,
+			   " Task to dev %016llx response: 0x%x status 0x%x\n",
+			   SAS_ADDR(dev->sas_addr),
+			   task->task_status.resp,
+			   task->task_status.stat);
+		sas_free_task(task);
+		task = NULL;
 	}
-ex_err:
+
 	BUG_ON(retry == 3 && task != NULL);
 	sas_free_task(task);
 	return res;
-- 
2.34.1


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

* [PATCH v3 23/31] scsi: pm8001: fix memory leak in pm8001_chip_fw_flash_update_req()
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (21 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 22/31] scsi: pm8001: Fix tag leaks on error Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 24/31] scsi: pm8001: Fix process_one_iomb() kdoc comment Damien Le Moal
                   ` (9 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

In pm8001_chip_fw_flash_update_build(), if
pm8001_chip_fw_flash_update_build() fails, the struct fw_control_ex
allocated must be freed.

Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 2eff6e2f6cf9..978b1bd60334 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -4890,8 +4890,10 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
 	ccb->ccb_tag = tag;
 	rc = pm8001_chip_fw_flash_update_build(pm8001_ha, &flash_update_info,
 		tag);
-	if (rc)
+	if (rc) {
+		kfree(fw_control_context);
 		pm8001_tag_free(pm8001_ha, tag);
+	}
 
 	return rc;
 }
-- 
2.34.1


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

* [PATCH v3 24/31] scsi: pm8001: Fix process_one_iomb() kdoc comment
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (22 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 23/31] scsi: pm8001: fix memory leak in pm8001_chip_fw_flash_update_req() Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 25/31] scsi: libsas: Simplify sas_ata_qc_issue() detection of NCQ commands Damien Le Moal
                   ` (8 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

Add missing description of the circularQ argument.

Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 9cea0a27f1a1..e74cd02a5c08 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -3922,6 +3922,7 @@ static int ssp_coalesced_comp_resp(struct pm8001_hba_info *pm8001_ha,
 /**
  * process_one_iomb - process one outbound Queue memory block
  * @pm8001_ha: our hba card information
+ * @circularQ: the outbound queue table.
  * @piomb: IO message buffer
  */
 static void process_one_iomb(struct pm8001_hba_info *pm8001_ha,
-- 
2.34.1


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

* [PATCH v3 25/31] scsi: libsas: Simplify sas_ata_qc_issue() detection of NCQ commands
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (23 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 24/31] scsi: pm8001: Fix process_one_iomb() kdoc comment Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 26/31] scsi: pm8001: Simplify pm8001_get_ncq_tag() Damien Le Moal
                   ` (7 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

To detect if a command is NCQ, there is no need to test all possible NCQ
command codes. Instead, use ata_is_ncq() to test the command protocol.

Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/libsas/sas_ata.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 50f779088b6e..fcfc8fd4b14f 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -181,14 +181,9 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
 	task->task_proto = SAS_PROTOCOL_STP;
 	task->task_done = sas_ata_task_done;
 
-	if (qc->tf.command == ATA_CMD_FPDMA_WRITE ||
-	    qc->tf.command == ATA_CMD_FPDMA_READ ||
-	    qc->tf.command == ATA_CMD_FPDMA_RECV ||
-	    qc->tf.command == ATA_CMD_FPDMA_SEND ||
-	    qc->tf.command == ATA_CMD_NCQ_NON_DATA) {
-		/* Need to zero out the tag libata assigned us */
+	/* For NCQ commands, zero out the tag libata assigned us */
+	if (ata_is_ncq(qc->tf.protocol))
 		qc->tf.nsect = 0;
-	}
 
 	ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, (u8 *)&task->ata_task.fis);
 	task->uldd_task = qc;
-- 
2.34.1


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

* [PATCH v3 26/31] scsi: pm8001: Simplify pm8001_get_ncq_tag()
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (24 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 25/31] scsi: libsas: Simplify sas_ata_qc_issue() detection of NCQ commands Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 27/31] scsi: pm8001: Cleanup pm8001_queue_command() Damien Le Moal
                   ` (6 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

To detect if a command is NCQ, there is no need to test all possible NCQ
command codes. Instead, use ata_is_ncq() to test the command protocol.

Reviewed-by: John Garry <john.garry@huawei.com>
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm8001_sas.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 1e7031400294..cbcb56b56a2f 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -304,16 +304,12 @@ static int pm8001_task_prep_smp(struct pm8001_hba_info *pm8001_ha,
 u32 pm8001_get_ncq_tag(struct sas_task *task, u32 *tag)
 {
 	struct ata_queued_cmd *qc = task->uldd_task;
-	if (qc) {
-		if (qc->tf.command == ATA_CMD_FPDMA_WRITE ||
-		    qc->tf.command == ATA_CMD_FPDMA_READ ||
-		    qc->tf.command == ATA_CMD_FPDMA_RECV ||
-		    qc->tf.command == ATA_CMD_FPDMA_SEND ||
-		    qc->tf.command == ATA_CMD_NCQ_NON_DATA) {
-			*tag = qc->tag;
-			return 1;
-		}
+
+	if (qc && ata_is_ncq(qc->tf.protocol)) {
+		*tag = qc->tag;
+		return 1;
 	}
+
 	return 0;
 }
 
-- 
2.34.1


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

* [PATCH v3 27/31] scsi: pm8001: Cleanup pm8001_queue_command()
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (25 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 26/31] scsi: pm8001: Simplify pm8001_get_ncq_tag() Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-15 10:55   ` John Garry
  2022-02-14  2:17 ` [PATCH v3 28/31] scsi: pm8001: Introduce ccb alloc/free helpers Damien Le Moal
                   ` (5 subsequent siblings)
  32 siblings, 1 reply; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

Avoid repeatedly declaring "struct task_status_struct *ts" to handle
error cases by declaring this variable for the entire function scope.
This allows simplifying the error cases, and together with the addition
of blank lines make the code more readable.

Reviewed-by: John Garry <john.garry@huawei.com>
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm8001_sas.c | 27 +++++++++++++--------------
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index cbcb56b56a2f..d08cbf3ef879 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -381,54 +381,53 @@ static int pm8001_task_exec(struct sas_task *task,
 	struct pm8001_device *pm8001_dev;
 	struct pm8001_port *port = NULL;
 	struct sas_task *t = task;
+	struct task_status_struct *ts = &t->task_status;
 	struct pm8001_ccb_info *ccb;
 	u32 tag = 0xdeadbeef, rc = 0, n_elem = 0;
 	unsigned long flags = 0;
 	enum sas_protocol task_proto = t->task_proto;
 
 	if (!dev->port) {
-		struct task_status_struct *tsm = &t->task_status;
-		tsm->resp = SAS_TASK_UNDELIVERED;
-		tsm->stat = SAS_PHY_DOWN;
+		ts->resp = SAS_TASK_UNDELIVERED;
+		ts->stat = SAS_PHY_DOWN;
 		if (dev->dev_type != SAS_SATA_DEV)
 			t->task_done(t);
 		return 0;
 	}
+
 	pm8001_ha = pm8001_find_ha_by_dev(task->dev);
 	if (pm8001_ha->controller_fatal_error) {
-		struct task_status_struct *ts = &t->task_status;
-
 		ts->resp = SAS_TASK_UNDELIVERED;
 		t->task_done(t);
 		return 0;
 	}
+
 	pm8001_dbg(pm8001_ha, IO, "pm8001_task_exec device\n");
+
 	spin_lock_irqsave(&pm8001_ha->lock, flags);
+
 	do {
 		dev = t->dev;
 		pm8001_dev = dev->lldd_dev;
 		port = &pm8001_ha->port[sas_find_local_port_id(dev)];
+
 		if (DEV_IS_GONE(pm8001_dev) || !port->port_attached) {
+			ts->resp = SAS_TASK_UNDELIVERED;
+			ts->stat = SAS_PHY_DOWN;
 			if (sas_protocol_ata(task_proto)) {
-				struct task_status_struct *ts = &t->task_status;
-				ts->resp = SAS_TASK_UNDELIVERED;
-				ts->stat = SAS_PHY_DOWN;
-
 				spin_unlock_irqrestore(&pm8001_ha->lock, flags);
 				t->task_done(t);
 				spin_lock_irqsave(&pm8001_ha->lock, flags);
-				continue;
 			} else {
-				struct task_status_struct *ts = &t->task_status;
-				ts->resp = SAS_TASK_UNDELIVERED;
-				ts->stat = SAS_PHY_DOWN;
 				t->task_done(t);
-				continue;
 			}
+			continue;
 		}
+
 		rc = pm8001_tag_alloc(pm8001_ha, &tag);
 		if (rc)
 			goto err_out;
+
 		ccb = &pm8001_ha->ccb_info[tag];
 
 		if (!sas_protocol_ata(task_proto)) {
-- 
2.34.1


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

* [PATCH v3 28/31] scsi: pm8001: Introduce ccb alloc/free helpers
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (26 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 27/31] scsi: pm8001: Cleanup pm8001_queue_command() Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-15 11:07   ` John Garry
  2022-02-14  2:17 ` [PATCH v3 29/31] scsi: pm8001: Simplify pm8001_mpi_build_cmd() interface Damien Le Moal
                   ` (4 subsequent siblings)
  32 siblings, 1 reply; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

Introduce the pm8001_ccb_alloc() and pm8001_ccb_free() helpers to
replace the typical code patterns:

	res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
	if (res)
		...
	ccb = &pm8001_ha->ccb_info[ccb_tag];
	ccb->device = pm8001_ha_dev;
	ccb->ccb_tag = ccb_tag;
	ccb->task = task;
	ccb->n_elem = 0;A

and

	ccb->task = NULL;
	ccb->ccb_tag = PM8001_INVALID_TAG;
	pm8001_tag_free(pm8001_ha, tag);

With the simpler function calls:

	ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_ha_dev, task);
	if (!ccb)
		...

and

	pm8001_ccb_free(pm8001_ha, ccb);

The pm8001_ccb_alloc() helper ensures that all fields of the ccb info
structure for the newly allocated tag are all initialized, except the
buf_prd field. The pm8001_ccb_free() helper clears the initialized
fields and the ccb tag to ensure that iteration over the adapter
ccb_info array detects ccbs that are in use.

All call site of the pm8001_tag_alloc() function that use a ccb info
associated with an allocated tag are converted to use the new helpers.

Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c | 180 +++++++++++++------------------
 drivers/scsi/pm8001/pm8001_sas.c |  46 ++++----
 drivers/scsi/pm8001/pm8001_sas.h |  47 ++++++++
 drivers/scsi/pm8001/pm80xx_hwi.c |  64 +++++------
 4 files changed, 165 insertions(+), 172 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 978b1bd60334..9018c7140d71 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1710,7 +1710,7 @@ void pm8001_work_fn(struct work_struct *work)
 					pm8001_dev->dcompletion = NULL;
 				}
 				complete(pm8001_ha->nvmd_completion);
-				pm8001_tag_free(pm8001_ha, ccb->ccb_tag);
+				pm8001_ccb_free(pm8001_ha, ccb);
 			}
 		}
 		/* Deregister all the device ids  */
@@ -1749,8 +1749,6 @@ int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha, void *data,
 static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
 		struct pm8001_device *pm8001_ha_dev)
 {
-	int res;
-	u32 ccb_tag;
 	struct pm8001_ccb_info *ccb;
 	struct sas_task *task = NULL;
 	struct task_abort_req task_abort;
@@ -1771,32 +1769,25 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
 
 	task->task_done = pm8001_task_done;
 
-	res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
-	if (res) {
+	ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_ha_dev, task);
+	if (!ccb) {
 		sas_free_task(task);
 		return;
 	}
 
-	ccb = &pm8001_ha->ccb_info[ccb_tag];
-	ccb->device = pm8001_ha_dev;
-	ccb->ccb_tag = ccb_tag;
-	ccb->task = task;
-	ccb->n_elem = 0;
-
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 
 	memset(&task_abort, 0, sizeof(task_abort));
 	task_abort.abort_all = cpu_to_le32(1);
 	task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
-	task_abort.tag = cpu_to_le32(ccb_tag);
+	task_abort.tag = cpu_to_le32(ccb->ccb_tag);
 
 	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort,
 			sizeof(task_abort), 0);
 	if (ret) {
 		sas_free_task(task);
-		pm8001_tag_free(pm8001_ha, ccb_tag);
+		pm8001_ccb_free(pm8001_ha, ccb);
 	}
-
 }
 
 static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
@@ -1804,7 +1795,6 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
 {
 	struct sata_start_req sata_cmd;
 	int res;
-	u32 ccb_tag;
 	struct pm8001_ccb_info *ccb;
 	struct sas_task *task = NULL;
 	struct host_to_dev_fis fis;
@@ -1820,20 +1810,13 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
 	}
 	task->task_done = pm8001_task_done;
 
-	res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
-	if (res) {
-		sas_free_task(task);
-		pm8001_dbg(pm8001_ha, FAIL, "cannot allocate tag !!!\n");
-		return;
-	}
-
-	/* allocate domain device by ourselves as libsas
-	 * is not going to provide any
-	*/
+	/*
+	 * Allocate domain device by ourselves as libsas is not going to
+	 * provide any.
+	 */
 	dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC);
 	if (!dev) {
 		sas_free_task(task);
-		pm8001_tag_free(pm8001_ha, ccb_tag);
 		pm8001_dbg(pm8001_ha, FAIL,
 			   "Domain device cannot be allocated\n");
 		return;
@@ -1841,11 +1824,13 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
 	task->dev = dev;
 	task->dev->lldd_dev = pm8001_ha_dev;
 
-	ccb = &pm8001_ha->ccb_info[ccb_tag];
-	ccb->device = pm8001_ha_dev;
-	ccb->ccb_tag = ccb_tag;
-	ccb->task = task;
-	ccb->n_elem = 0;
+	ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_ha_dev, task);
+	if (!ccb) {
+		sas_free_task(task);
+		kfree(dev);
+		return;
+	}
+
 	pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG;
 	pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG;
 
@@ -1860,7 +1845,7 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
 	fis.lbal = 0x10;
 	fis.sector_count = 0x1;
 
-	sata_cmd.tag = cpu_to_le32(ccb_tag);
+	sata_cmd.tag = cpu_to_le32(ccb->ccb_tag);
 	sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
 	sata_cmd.ncqtag_atap_dir_m = cpu_to_le32((0x1 << 7) | (0x5 << 9));
 	memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
@@ -1869,7 +1854,7 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
 			sizeof(sata_cmd), 0);
 	if (res) {
 		sas_free_task(task);
-		pm8001_tag_free(pm8001_ha, ccb_tag);
+		pm8001_ccb_free(pm8001_ha, ccb);
 		kfree(dev);
 	}
 }
@@ -3055,12 +3040,12 @@ void pm8001_mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha,
 	u32 device_id = le32_to_cpu(pPayload->device_id);
 	u8 pds = le32_to_cpu(pPayload->pds_nds) & PDS_BITS;
 	u8 nds = le32_to_cpu(pPayload->pds_nds) & NDS_BITS;
-	pm8001_dbg(pm8001_ha, MSG, "Set device id = 0x%x state from 0x%x to 0x%x status = 0x%x!\n",
+
+	pm8001_dbg(pm8001_ha, MSG,
+		   "Set device id = 0x%x state from 0x%x to 0x%x status = 0x%x!\n",
 		   device_id, pds, nds, status);
 	complete(pm8001_dev->setds_completion);
-	ccb->task = NULL;
-	ccb->ccb_tag = PM8001_INVALID_TAG;
-	pm8001_tag_free(pm8001_ha, tag);
+	pm8001_ccb_free(pm8001_ha, ccb);
 }
 
 void pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
@@ -3070,15 +3055,14 @@ void pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 	u32 tag = le32_to_cpu(pPayload->tag);
 	struct pm8001_ccb_info *ccb = &pm8001_ha->ccb_info[tag];
 	u32 dlen_status = le32_to_cpu(pPayload->dlen_status);
+
 	complete(pm8001_ha->nvmd_completion);
 	pm8001_dbg(pm8001_ha, MSG, "Set nvm data complete!\n");
 	if ((dlen_status & NVMD_STAT) != 0) {
 		pm8001_dbg(pm8001_ha, FAIL, "Set nvm data error %x\n",
 				dlen_status);
 	}
-	ccb->task = NULL;
-	ccb->ccb_tag = PM8001_INVALID_TAG;
-	pm8001_tag_free(pm8001_ha, tag);
+	pm8001_ccb_free(pm8001_ha, ccb);
 }
 
 void
@@ -3103,9 +3087,7 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		/* We should free tag during failure also, the tag is not being
 		 * freed by requesting path anywhere.
 		 */
-		ccb->task = NULL;
-		ccb->ccb_tag = PM8001_INVALID_TAG;
-		pm8001_tag_free(pm8001_ha, tag);
+		pm8001_ccb_free(pm8001_ha, ccb);
 		return;
 	}
 	if (ir_tds_bn_dps_das_nvm & IPMode) {
@@ -3149,9 +3131,7 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 	 */
 	complete(pm8001_ha->nvmd_completion);
 	pm8001_dbg(pm8001_ha, MSG, "Get nvmd data complete!\n");
-	ccb->task = NULL;
-	ccb->ccb_tag = PM8001_INVALID_TAG;
-	pm8001_tag_free(pm8001_ha, tag);
+	pm8001_ccb_free(pm8001_ha, ccb);
 }
 
 int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
@@ -3562,9 +3542,7 @@ int pm8001_mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		break;
 	}
 	complete(pm8001_dev->dcompletion);
-	ccb->task = NULL;
-	ccb->ccb_tag = PM8001_INVALID_TAG;
-	pm8001_tag_free(pm8001_ha, htag);
+	pm8001_ccb_free(pm8001_ha, ccb);
 	return 0;
 }
 
@@ -3597,6 +3575,7 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha,
 		(struct fw_flash_Update_resp *)(piomb + 4);
 	u32 tag = le32_to_cpu(ppayload->tag);
 	struct pm8001_ccb_info *ccb = &pm8001_ha->ccb_info[tag];
+
 	status = le32_to_cpu(ppayload->status);
 	switch (status) {
 	case FLASH_UPDATE_COMPLETE_PENDING_REBOOT:
@@ -3634,9 +3613,7 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha,
 		break;
 	}
 	kfree(ccb->fw_control_context);
-	ccb->task = NULL;
-	ccb->ccb_tag = PM8001_INVALID_TAG;
-	pm8001_tag_free(pm8001_ha, tag);
+	pm8001_ccb_free(pm8001_ha, ccb);
 	complete(pm8001_ha->nvmd_completion);
 	return 0;
 }
@@ -4429,7 +4406,7 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
 	u32 stp_sspsmp_sata = 0x4;
 	struct inbound_queue_table *circularQ;
 	u32 linkrate, phy_id;
-	int rc, tag = 0xdeadbeef;
+	int rc;
 	struct pm8001_ccb_info *ccb;
 	u8 retryFlag = 0x1;
 	u16 firstBurstSize = 0;
@@ -4440,13 +4417,11 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 
 	memset(&payload, 0, sizeof(payload));
-	rc = pm8001_tag_alloc(pm8001_ha, &tag);
-	if (rc)
-		return rc;
-	ccb = &pm8001_ha->ccb_info[tag];
-	ccb->device = pm8001_dev;
-	ccb->ccb_tag = tag;
-	payload.tag = cpu_to_le32(tag);
+	ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_dev, NULL);
+	if (!ccb)
+		return -SAS_QUEUE_FULL;
+
+	payload.tag = cpu_to_le32(ccb->ccb_tag);
 	if (flag == 1)
 		stp_sspsmp_sata = 0x02; /*direct attached sata */
 	else {
@@ -4476,7 +4451,7 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
 	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
 			sizeof(payload), 0);
 	if (rc)
-		pm8001_tag_free(pm8001_ha, tag);
+		pm8001_ccb_free(pm8001_ha, ccb);
 
 	return rc;
 }
@@ -4641,7 +4616,6 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 	u32 opc = OPC_INB_GET_NVMD_DATA;
 	u32 nvmd_type;
 	int rc;
-	u32 tag;
 	struct pm8001_ccb_info *ccb;
 	struct inbound_queue_table *circularQ;
 	struct get_nvm_data_req nvmd_req;
@@ -4656,15 +4630,15 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 	fw_control_context->len = ioctl_payload->rd_length;
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	memset(&nvmd_req, 0, sizeof(nvmd_req));
-	rc = pm8001_tag_alloc(pm8001_ha, &tag);
-	if (rc) {
+
+	ccb = pm8001_ccb_alloc(pm8001_ha, NULL, NULL);
+	if (!ccb) {
 		kfree(fw_control_context);
-		return rc;
+		return -SAS_QUEUE_FULL;
 	}
-	ccb = &pm8001_ha->ccb_info[tag];
-	ccb->ccb_tag = tag;
 	ccb->fw_control_context = fw_control_context;
-	nvmd_req.tag = cpu_to_le32(tag);
+
+	nvmd_req.tag = cpu_to_le32(ccb->ccb_tag);
 
 	switch (nvmd_type) {
 	case TWI_DEVICE: {
@@ -4725,7 +4699,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 			sizeof(nvmd_req), 0);
 	if (rc) {
 		kfree(fw_control_context);
-		pm8001_tag_free(pm8001_ha, tag);
+		pm8001_ccb_free(pm8001_ha, ccb);
 	}
 	return rc;
 }
@@ -4736,7 +4710,6 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 	u32 opc = OPC_INB_SET_NVMD_DATA;
 	u32 nvmd_type;
 	int rc;
-	u32 tag;
 	struct pm8001_ccb_info *ccb;
 	struct inbound_queue_table *circularQ;
 	struct set_nvm_data_req nvmd_req;
@@ -4752,15 +4725,15 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 		&ioctl_payload->func_specific,
 		ioctl_payload->wr_length);
 	memset(&nvmd_req, 0, sizeof(nvmd_req));
-	rc = pm8001_tag_alloc(pm8001_ha, &tag);
-	if (rc) {
+
+	ccb = pm8001_ccb_alloc(pm8001_ha, NULL, NULL);
+	if (!ccb) {
 		kfree(fw_control_context);
-		return -EBUSY;
+		return -SAS_QUEUE_FULL;
 	}
-	ccb = &pm8001_ha->ccb_info[tag];
 	ccb->fw_control_context = fw_control_context;
-	ccb->ccb_tag = tag;
-	nvmd_req.tag = cpu_to_le32(tag);
+
+	nvmd_req.tag = cpu_to_le32(ccb->ccb_tag);
 	switch (nvmd_type) {
 	case TWI_DEVICE: {
 		u32 twi_addr, twi_page_size;
@@ -4810,7 +4783,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 			sizeof(nvmd_req), 0);
 	if (rc) {
 		kfree(fw_control_context);
-		pm8001_tag_free(pm8001_ha, tag);
+		pm8001_ccb_free(pm8001_ha, ccb);
 	}
 	return rc;
 }
@@ -4856,7 +4829,6 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
 	struct fw_control_info *fw_control;
 	struct fw_control_ex *fw_control_context;
 	int rc;
-	u32 tag;
 	struct pm8001_ccb_info *ccb;
 	void *buffer = pm8001_ha->memoryMap.region[FW_FLASH].virt_ptr;
 	dma_addr_t phys_addr = pm8001_ha->memoryMap.region[FW_FLASH].phys_addr;
@@ -4880,19 +4852,19 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
 	fw_control_context->virtAddr = buffer;
 	fw_control_context->phys_addr = phys_addr;
 	fw_control_context->len = fw_control->len;
-	rc = pm8001_tag_alloc(pm8001_ha, &tag);
-	if (rc) {
+
+	ccb = pm8001_ccb_alloc(pm8001_ha, NULL, NULL);
+	if (!ccb) {
 		kfree(fw_control_context);
-		return -EBUSY;
+		return -SAS_QUEUE_FULL;
 	}
-	ccb = &pm8001_ha->ccb_info[tag];
 	ccb->fw_control_context = fw_control_context;
-	ccb->ccb_tag = tag;
+
 	rc = pm8001_chip_fw_flash_update_build(pm8001_ha, &flash_update_info,
-		tag);
+					       ccb->ccb_tag);
 	if (rc) {
 		kfree(fw_control_context);
-		pm8001_tag_free(pm8001_ha, tag);
+		pm8001_ccb_free(pm8001_ha, ccb);
 	}
 
 	return rc;
@@ -4984,26 +4956,25 @@ pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha,
 	struct inbound_queue_table *circularQ;
 	struct pm8001_ccb_info *ccb;
 	int rc;
-	u32 tag;
 	u32 opc = OPC_INB_SET_DEVICE_STATE;
+
 	memset(&payload, 0, sizeof(payload));
-	rc = pm8001_tag_alloc(pm8001_ha, &tag);
-	if (rc)
-		return -1;
-	ccb = &pm8001_ha->ccb_info[tag];
-	ccb->ccb_tag = tag;
-	ccb->device = pm8001_dev;
+
+	ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_dev, NULL);
+	if (!ccb)
+		return -SAS_QUEUE_FULL;
+
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
-	payload.tag = cpu_to_le32(tag);
+	payload.tag = cpu_to_le32(ccb->ccb_tag);
 	payload.device_id = cpu_to_le32(pm8001_dev->device_id);
 	payload.nds = cpu_to_le32(state);
+
 	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
 			sizeof(payload), 0);
 	if (rc)
-		pm8001_tag_free(pm8001_ha, tag);
+		pm8001_ccb_free(pm8001_ha, ccb);
 
 	return rc;
-
 }
 
 static int
@@ -5013,25 +4984,26 @@ pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha)
 	struct inbound_queue_table *circularQ;
 	struct pm8001_ccb_info *ccb;
 	int rc;
-	u32 tag;
 	u32 opc = OPC_INB_SAS_RE_INITIALIZE;
+
 	memset(&payload, 0, sizeof(payload));
-	rc = pm8001_tag_alloc(pm8001_ha, &tag);
-	if (rc)
-		return -ENOMEM;
-	ccb = &pm8001_ha->ccb_info[tag];
-	ccb->ccb_tag = tag;
+
+	ccb = pm8001_ccb_alloc(pm8001_ha, NULL, NULL);
+	if (!ccb)
+		return -SAS_QUEUE_FULL;
+
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
-	payload.tag = cpu_to_le32(tag);
+	payload.tag = cpu_to_le32(ccb->ccb_tag);
 	payload.SSAHOLT = cpu_to_le32(0xd << 25);
 	payload.sata_hol_tmo = cpu_to_le32(80);
 	payload.open_reject_cmdretries_data_retries = cpu_to_le32(0xff00ff);
+
 	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
 			sizeof(payload), 0);
 	if (rc)
-		pm8001_tag_free(pm8001_ha, tag);
-	return rc;
+		pm8001_ccb_free(pm8001_ha, ccb);
 
+	return rc;
 }
 
 const struct pm8001_dispatch pm8001_8001_dispatch = {
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index d08cbf3ef879..6c4aa04c9144 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -74,7 +74,7 @@ void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag)
   * @pm8001_ha: our hba struct
   * @tag_out: the found empty tag .
   */
-inline int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out)
+int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out)
 {
 	unsigned int tag;
 	void *bitmap = pm8001_ha->tags;
@@ -383,7 +383,7 @@ static int pm8001_task_exec(struct sas_task *task,
 	struct sas_task *t = task;
 	struct task_status_struct *ts = &t->task_status;
 	struct pm8001_ccb_info *ccb;
-	u32 tag = 0xdeadbeef, rc = 0, n_elem = 0;
+	u32 rc = 0, n_elem = 0;
 	unsigned long flags = 0;
 	enum sas_protocol task_proto = t->task_proto;
 
@@ -424,11 +424,11 @@ static int pm8001_task_exec(struct sas_task *task,
 			continue;
 		}
 
-		rc = pm8001_tag_alloc(pm8001_ha, &tag);
-		if (rc)
+		ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_dev, t);
+		if (!ccb) {
+			rc = -SAS_QUEUE_FULL;
 			goto err_out;
-
-		ccb = &pm8001_ha->ccb_info[tag];
+		}
 
 		if (!sas_protocol_ata(task_proto)) {
 			if (t->num_scatter) {
@@ -438,7 +438,7 @@ static int pm8001_task_exec(struct sas_task *task,
 					t->data_dir);
 				if (!n_elem) {
 					rc = -ENOMEM;
-					goto err_out_tag;
+					goto err_out_ccb;
 				}
 			}
 		} else {
@@ -447,9 +447,7 @@ static int pm8001_task_exec(struct sas_task *task,
 
 		t->lldd_task = ccb;
 		ccb->n_elem = n_elem;
-		ccb->ccb_tag = tag;
-		ccb->task = t;
-		ccb->device = pm8001_dev;
+
 		switch (task_proto) {
 		case SAS_PROTOCOL_SMP:
 			atomic_inc(&pm8001_dev->running_req);
@@ -478,15 +476,15 @@ static int pm8001_task_exec(struct sas_task *task,
 		if (rc) {
 			pm8001_dbg(pm8001_ha, IO, "rc is %x\n", rc);
 			atomic_dec(&pm8001_dev->running_req);
-			goto err_out_tag;
+			goto err_out_ccb;
 		}
 		/* TODO: select normal or high priority */
 	} while (0);
 	rc = 0;
 	goto out_done;
 
-err_out_tag:
-	pm8001_tag_free(pm8001_ha, tag);
+err_out_ccb:
+	pm8001_ccb_free(pm8001_ha, ccb);
 err_out:
 	dev_printk(KERN_ERR, pm8001_ha->dev, "pm8001 exec failed[%d]!\n", rc);
 	if (!sas_protocol_ata(task_proto))
@@ -557,10 +555,7 @@ void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha,
 	}
 
 	task->lldd_task = NULL;
-	ccb->task = NULL;
-	ccb->ccb_tag = PM8001_INVALID_TAG;
-	ccb->open_retry = 0;
-	pm8001_tag_free(pm8001_ha, ccb_idx);
+	pm8001_ccb_free(pm8001_ha, ccb);
 }
 
 /**
@@ -806,7 +801,6 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
 	u32 task_tag)
 {
 	int res, retry;
-	u32 ccb_tag;
 	struct pm8001_ccb_info *ccb;
 	struct sas_task *task = NULL;
 
@@ -822,23 +816,19 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
 		task->slow_task->timer.expires = jiffies + PM8001_TASK_TIMEOUT * HZ;
 		add_timer(&task->slow_task->timer);
 
-		res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
-		if (res)
+		ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_dev, task);
+		if (!ccb) {
+			res = -SAS_QUEUE_FULL;
 			break;
-
-		ccb = &pm8001_ha->ccb_info[ccb_tag];
-		ccb->device = pm8001_dev;
-		ccb->ccb_tag = ccb_tag;
-		ccb->task = task;
-		ccb->n_elem = 0;
+		}
 
 		res = PM8001_CHIP_DISP->task_abort(pm8001_ha,
-			pm8001_dev, flag, task_tag, ccb_tag);
+			pm8001_dev, flag, task_tag, ccb->ccb_tag);
 		if (res) {
 			del_timer(&task->slow_task->timer);
 			pm8001_dbg(pm8001_ha, FAIL,
 				   "Executing internal task failed\n");
-			pm8001_tag_free(pm8001_ha, ccb_tag);
+			pm8001_ccb_free(pm8001_ha, ccb);
 			break;
 		}
 
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 1791cdf30276..824ada7f6a3f 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -740,6 +740,53 @@ extern const struct attribute_group *pm8001_host_groups[];
 
 #define PM8001_INVALID_TAG	((u32)-1)
 
+/*
+ * Allocate a new tag and return the corresponding ccb after initializing it.
+ */
+static inline struct pm8001_ccb_info *
+pm8001_ccb_alloc(struct pm8001_hba_info *pm8001_ha,
+		 struct pm8001_device *dev, struct sas_task *task)
+{
+	struct pm8001_ccb_info *ccb;
+	u32 tag;
+
+	if (pm8001_tag_alloc(pm8001_ha, &tag)) {
+		pm8001_dbg(pm8001_ha, FAIL, "Failed to allocate a tag\n");
+		return NULL;
+	}
+
+	ccb = &pm8001_ha->ccb_info[tag];
+	ccb->task = task;
+	ccb->n_elem = 0;
+	ccb->ccb_tag = tag;
+	ccb->device = dev;
+	ccb->fw_control_context = NULL;
+	ccb->open_retry = 0;
+
+	return ccb;
+}
+
+/*
+ * Free the tag of an initialized ccb.
+ */
+static inline void pm8001_ccb_free(struct pm8001_hba_info *pm8001_ha,
+				   struct pm8001_ccb_info *ccb)
+{
+	u32 tag = ccb->ccb_tag;
+
+	/*
+	 * Cleanup the ccb to make sure that a manual scan of the adapter
+	 * ccb_info array can detect ccb's that are in use.
+	 * C.f. pm8001_open_reject_retry()
+	 */
+	ccb->task = NULL;
+	ccb->ccb_tag = PM8001_INVALID_TAG;
+	ccb->device = NULL;
+	ccb->fw_control_context = NULL;
+
+	pm8001_tag_free(pm8001_ha, tag);
+}
+
 static inline void
 pm8001_ccb_task_free_done(struct pm8001_hba_info *pm8001_ha,
 			struct sas_task *task, struct pm8001_ccb_info *ccb,
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index e74cd02a5c08..5a65d4406c94 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -1767,8 +1767,6 @@ pm80xx_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec)
 static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha,
 		struct pm8001_device *pm8001_ha_dev)
 {
-	int res;
-	u32 ccb_tag;
 	struct pm8001_ccb_info *ccb;
 	struct sas_task *task = NULL;
 	struct task_abort_req task_abort;
@@ -1790,31 +1788,25 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha,
 
 	task->task_done = pm8001_task_done;
 
-	res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
-	if (res) {
+	ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_ha_dev, task);
+	if (!ccb) {
 		sas_free_task(task);
 		return;
 	}
 
-	ccb = &pm8001_ha->ccb_info[ccb_tag];
-	ccb->device = pm8001_ha_dev;
-	ccb->ccb_tag = ccb_tag;
-	ccb->task = task;
-	ccb->n_elem = 0;
-
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 
 	memset(&task_abort, 0, sizeof(task_abort));
 	task_abort.abort_all = cpu_to_le32(1);
 	task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
-	task_abort.tag = cpu_to_le32(ccb_tag);
+	task_abort.tag = cpu_to_le32(ccb->ccb_tag);
 
 	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort,
 			sizeof(task_abort), 0);
 	pm8001_dbg(pm8001_ha, FAIL, "Executing abort task end\n");
 	if (ret) {
 		sas_free_task(task);
-		pm8001_tag_free(pm8001_ha, ccb_tag);
+		pm8001_ccb_free(pm8001_ha, ccb);
 	}
 }
 
@@ -1823,7 +1815,6 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
 {
 	struct sata_start_req sata_cmd;
 	int res;
-	u32 ccb_tag;
 	struct pm8001_ccb_info *ccb;
 	struct sas_task *task = NULL;
 	struct host_to_dev_fis fis;
@@ -1839,20 +1830,13 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
 	}
 	task->task_done = pm8001_task_done;
 
-	res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
-	if (res) {
-		sas_free_task(task);
-		pm8001_dbg(pm8001_ha, FAIL, "cannot allocate tag !!!\n");
-		return;
-	}
-
-	/* allocate domain device by ourselves as libsas
-	 * is not going to provide any
-	*/
+	/*
+	 * Allocate domain device by ourselves as libsas is not going to
+	 * provide any.
+	 */
 	dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC);
 	if (!dev) {
 		sas_free_task(task);
-		pm8001_tag_free(pm8001_ha, ccb_tag);
 		pm8001_dbg(pm8001_ha, FAIL,
 			   "Domain device cannot be allocated\n");
 		return;
@@ -1861,11 +1845,13 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
 	task->dev = dev;
 	task->dev->lldd_dev = pm8001_ha_dev;
 
-	ccb = &pm8001_ha->ccb_info[ccb_tag];
-	ccb->device = pm8001_ha_dev;
-	ccb->ccb_tag = ccb_tag;
-	ccb->task = task;
-	ccb->n_elem = 0;
+	ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_ha_dev, task);
+	if (!ccb) {
+		sas_free_task(task);
+		kfree(dev);
+		return;
+	}
+
 	pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG;
 	pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG;
 
@@ -1880,7 +1866,7 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
 	fis.lbal = 0x10;
 	fis.sector_count = 0x1;
 
-	sata_cmd.tag = cpu_to_le32(ccb_tag);
+	sata_cmd.tag = cpu_to_le32(ccb->ccb_tag);
 	sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
 	sata_cmd.ncqtag_atap_dir_m_dad = cpu_to_le32(((0x1 << 7) | (0x5 << 9)));
 	memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
@@ -1890,7 +1876,7 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
 	pm8001_dbg(pm8001_ha, FAIL, "Executing read log end\n");
 	if (res) {
 		sas_free_task(task);
-		pm8001_tag_free(pm8001_ha, ccb_tag);
+		pm8001_ccb_free(pm8001_ha, ccb);
 		kfree(dev);
 	}
 }
@@ -4847,7 +4833,7 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
 	u32 stp_sspsmp_sata = 0x4;
 	struct inbound_queue_table *circularQ;
 	u32 linkrate, phy_id;
-	int rc, tag = 0xdeadbeef;
+	int rc;
 	struct pm8001_ccb_info *ccb;
 	u8 retryFlag = 0x1;
 	u16 firstBurstSize = 0;
@@ -4858,13 +4844,11 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 
 	memset(&payload, 0, sizeof(payload));
-	rc = pm8001_tag_alloc(pm8001_ha, &tag);
-	if (rc)
-		return rc;
-	ccb = &pm8001_ha->ccb_info[tag];
-	ccb->device = pm8001_dev;
-	ccb->ccb_tag = tag;
-	payload.tag = cpu_to_le32(tag);
+	ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_dev, NULL);
+	if (!ccb)
+		return -SAS_QUEUE_FULL;
+
+	payload.tag = cpu_to_le32(ccb->ccb_tag);
 
 	if (flag == 1) {
 		stp_sspsmp_sata = 0x02; /*direct attached sata */
@@ -4901,7 +4885,7 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
 	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
 			sizeof(payload), 0);
 	if (rc)
-		pm8001_tag_free(pm8001_ha, tag);
+		pm8001_ccb_free(pm8001_ha, ccb);
 
 	return rc;
 }
-- 
2.34.1


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

* [PATCH v3 29/31] scsi: pm8001: Simplify pm8001_mpi_build_cmd() interface
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (27 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 28/31] scsi: pm8001: Introduce ccb alloc/free helpers Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:17 ` [PATCH v3 30/31] scsi: pm8001: Simplify pm8001_task_exec() Damien Le Moal
                   ` (3 subsequent siblings)
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

There is no need to pass a pointer to a struct inbound_queue_table to
pm8001_mpi_build_cmd(). Passing the start index in the inbound queue
table of the adapter is enough. This change allows avoiding the
declaration of a struct inbound_queue_table pointer (circularQ
variables) in many functions, simplifying the code.

While at it, blank lines are added i(e.g. after local variable
declarations) to make the code more readable.

Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c | 154 +++++++++++--------------------
 drivers/scsi/pm8001/pm8001_sas.h |   3 +-
 drivers/scsi/pm8001/pm80xx_hwi.c |  98 +++++++-------------
 3 files changed, 89 insertions(+), 166 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 9018c7140d71..726421311543 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1309,21 +1309,20 @@ int pm8001_mpi_msg_free_get(struct inbound_queue_table *circularQ,
  * pm8001_mpi_build_cmd- build the message queue for transfer, update the PI to
  * FW to tell the fw to get this message from IOMB.
  * @pm8001_ha: our hba card information
- * @circularQ: the inbound queue we want to transfer to HBA.
+ * @q_index: the index in the inbound queue we want to transfer to HBA.
  * @opCode: the operation code represents commands which LLDD and fw recognized.
  * @payload: the command payload of each operation command.
  * @nb: size in bytes of the command payload
  * @responseQueue: queue to interrupt on w/ command response (if any)
  */
 int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
-			 struct inbound_queue_table *circularQ,
-			 u32 opCode, void *payload, size_t nb,
+			 u32 q_index, u32 opCode, void *payload, size_t nb,
 			 u32 responseQueue)
 {
 	u32 Header = 0, hpriority = 0, bc = 1, category = 0x02;
 	void *pMessage;
 	unsigned long flags;
-	int q_index = circularQ - pm8001_ha->inbnd_q_tbl;
+	struct inbound_queue_table *circularQ = &pm8001_ha->inbnd_q_tbl[q_index];
 	int rv;
 	u32 htag = le32_to_cpu(*(__le32 *)payload);
 
@@ -1752,7 +1751,6 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
 	struct pm8001_ccb_info *ccb;
 	struct sas_task *task = NULL;
 	struct task_abort_req task_abort;
-	struct inbound_queue_table *circularQ;
 	u32 opc = OPC_INB_SATA_ABORT;
 	int ret;
 
@@ -1775,15 +1773,13 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
 		return;
 	}
 
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
-
 	memset(&task_abort, 0, sizeof(task_abort));
 	task_abort.abort_all = cpu_to_le32(1);
 	task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
 	task_abort.tag = cpu_to_le32(ccb->ccb_tag);
 
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort,
-			sizeof(task_abort), 0);
+	ret = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &task_abort,
+				   sizeof(task_abort), 0);
 	if (ret) {
 		sas_free_task(task);
 		pm8001_ccb_free(pm8001_ha, ccb);
@@ -1799,11 +1795,9 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
 	struct sas_task *task = NULL;
 	struct host_to_dev_fis fis;
 	struct domain_device *dev;
-	struct inbound_queue_table *circularQ;
 	u32 opc = OPC_INB_SATA_HOST_OPSTART;
 
 	task = sas_alloc_slow_task(GFP_ATOMIC);
-
 	if (!task) {
 		pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task !!!\n");
 		return;
@@ -1834,9 +1828,6 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
 	pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG;
 	pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG;
 
-	memset(&sata_cmd, 0, sizeof(sata_cmd));
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
-
 	/* construct read log FIS */
 	memset(&fis, 0, sizeof(struct host_to_dev_fis));
 	fis.fis_type = 0x27;
@@ -1845,13 +1836,14 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
 	fis.lbal = 0x10;
 	fis.sector_count = 0x1;
 
+	memset(&sata_cmd, 0, sizeof(sata_cmd));
 	sata_cmd.tag = cpu_to_le32(ccb->ccb_tag);
 	sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
 	sata_cmd.ncqtag_atap_dir_m = cpu_to_le32((0x1 << 7) | (0x5 << 9));
 	memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
 
-	res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd,
-			sizeof(sata_cmd), 0);
+	res = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &sata_cmd,
+				   sizeof(sata_cmd), 0);
 	if (res) {
 		sas_free_task(task);
 		pm8001_ccb_free(pm8001_ha, ccb);
@@ -3278,17 +3270,14 @@ static void pm8001_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha,
 	struct hw_event_ack_req	 payload;
 	u32 opc = OPC_INB_SAS_HW_EVENT_ACK;
 
-	struct inbound_queue_table *circularQ;
-
 	memset((u8 *)&payload, 0, sizeof(payload));
-	circularQ = &pm8001_ha->inbnd_q_tbl[Qnum];
 	payload.tag = cpu_to_le32(1);
 	payload.sea_phyid_portid = cpu_to_le32(((SEA & 0xFFFF) << 8) |
 		((phyId & 0x0F) << 4) | (port_id & 0x0F));
 	payload.param0 = cpu_to_le32(param0);
 	payload.param1 = cpu_to_le32(param1);
-	pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
-			sizeof(payload), 0);
+
+	pm8001_mpi_build_cmd(pm8001_ha, Qnum, opc, &payload, sizeof(payload), 0);
 }
 
 static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
@@ -4120,7 +4109,6 @@ static int pm8001_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
 	u32 req_len, resp_len;
 	struct smp_req smp_cmd;
 	u32 opc;
-	struct inbound_queue_table *circularQ;
 
 	memset(&smp_cmd, 0, sizeof(smp_cmd));
 	/*
@@ -4146,7 +4134,6 @@ static int pm8001_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
 	}
 
 	opc = OPC_INB_SMP_REQUEST;
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	smp_cmd.tag = cpu_to_le32(ccb->ccb_tag);
 	smp_cmd.long_smp_req.long_req_addr =
 		cpu_to_le64((u64)sg_dma_address(&task->smp_task.smp_req));
@@ -4157,8 +4144,8 @@ static int pm8001_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
 	smp_cmd.long_smp_req.long_resp_size =
 		cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_resp)-4);
 	build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, &smp_cmd);
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
-			&smp_cmd, sizeof(smp_cmd), 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc,
+				  &smp_cmd, sizeof(smp_cmd), 0);
 	if (rc)
 		goto err_out_2;
 
@@ -4186,9 +4173,7 @@ static int pm8001_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
 	struct pm8001_device *pm8001_dev = dev->lldd_dev;
 	struct ssp_ini_io_start_req ssp_cmd;
 	u32 tag = ccb->ccb_tag;
-	int ret;
 	u64 phys_addr;
-	struct inbound_queue_table *circularQ;
 	u32 opc = OPC_INB_SSPINIIOSTART;
 	memset(&ssp_cmd, 0, sizeof(ssp_cmd));
 	memcpy(ssp_cmd.ssp_iu.lun, task->ssp_task.LUN, 8);
@@ -4204,7 +4189,6 @@ static int pm8001_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
 	ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7);
 	memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cmd->cmnd,
 	       task->ssp_task.cmd->cmd_len);
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 
 	/* fill in PRD (scatter/gather) table, if any */
 	if (task->num_scatter > 1) {
@@ -4225,9 +4209,9 @@ static int pm8001_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
 		ssp_cmd.len = cpu_to_le32(task->total_xfer_len);
 		ssp_cmd.esgl = 0;
 	}
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd,
-			sizeof(ssp_cmd), 0);
-	return ret;
+
+	return pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &ssp_cmd,
+				    sizeof(ssp_cmd), 0);
 }
 
 static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
@@ -4237,17 +4221,15 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
 	struct domain_device *dev = task->dev;
 	struct pm8001_device *pm8001_ha_dev = dev->lldd_dev;
 	u32 tag = ccb->ccb_tag;
-	int ret;
 	struct sata_start_req sata_cmd;
 	u32 hdr_tag, ncg_tag = 0;
 	u64 phys_addr;
 	u32 ATAP = 0x0;
 	u32 dir;
-	struct inbound_queue_table *circularQ;
 	unsigned long flags;
 	u32  opc = OPC_INB_SATA_HOST_OPSTART;
+
 	memset(&sata_cmd, 0, sizeof(sata_cmd));
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 
 	if (task->data_dir == DMA_NONE && !task->ata_task.use_ncq) {
 		ATAP = 0x04;  /* no data*/
@@ -4333,9 +4315,8 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
 		}
 	}
 
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd,
-			sizeof(sata_cmd), 0);
-	return ret;
+	return pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &sata_cmd,
+				    sizeof(sata_cmd), 0);
 }
 
 /**
@@ -4347,11 +4328,9 @@ static int
 pm8001_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
 {
 	struct phy_start_req payload;
-	struct inbound_queue_table *circularQ;
-	int ret;
 	u32 tag = 0x01;
 	u32 opcode = OPC_INB_PHYSTART;
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
 	memset(&payload, 0, sizeof(payload));
 	payload.tag = cpu_to_le32(tag);
 	/*
@@ -4368,9 +4347,9 @@ pm8001_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
 	memcpy(payload.sas_identify.sas_addr,
 		pm8001_ha->sas_addr, SAS_ADDR_SIZE);
 	payload.sas_identify.phy_id = phy_id;
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
-			sizeof(payload), 0);
-	return ret;
+
+	return pm8001_mpi_build_cmd(pm8001_ha, 0, opcode, &payload,
+				    sizeof(payload), 0);
 }
 
 /**
@@ -4382,17 +4361,15 @@ static int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
 				    u8 phy_id)
 {
 	struct phy_stop_req payload;
-	struct inbound_queue_table *circularQ;
-	int ret;
 	u32 tag = 0x01;
 	u32 opcode = OPC_INB_PHYSTOP;
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
 	memset(&payload, 0, sizeof(payload));
 	payload.tag = cpu_to_le32(tag);
 	payload.phy_id = cpu_to_le32(phy_id);
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
-			sizeof(payload), 0);
-	return ret;
+
+	return pm8001_mpi_build_cmd(pm8001_ha, 0, opcode, &payload,
+				    sizeof(payload), 0);
 }
 
 /*
@@ -4404,7 +4381,6 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
 	struct reg_dev_req payload;
 	u32	opc;
 	u32 stp_sspsmp_sata = 0x4;
-	struct inbound_queue_table *circularQ;
 	u32 linkrate, phy_id;
 	int rc;
 	struct pm8001_ccb_info *ccb;
@@ -4414,7 +4390,6 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
 	struct domain_device *dev = pm8001_dev->sas_device;
 	struct domain_device *parent_dev = dev->parent;
 	struct pm8001_port *port = dev->port->lldd_port;
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 
 	memset(&payload, 0, sizeof(payload));
 	ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_dev, NULL);
@@ -4448,8 +4423,9 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
 		cpu_to_le32(ITNT | (firstBurstSize * 0x10000));
 	memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr,
 		SAS_ADDR_SIZE);
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
-			sizeof(payload), 0);
+
+	rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,
+				  sizeof(payload), 0);
 	if (rc)
 		pm8001_ccb_free(pm8001_ha, ccb);
 
@@ -4464,18 +4440,15 @@ int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha,
 {
 	struct dereg_dev_req payload;
 	u32 opc = OPC_INB_DEREG_DEV_HANDLE;
-	int ret;
-	struct inbound_queue_table *circularQ;
 
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	memset(&payload, 0, sizeof(payload));
 	payload.tag = cpu_to_le32(1);
 	payload.device_id = cpu_to_le32(device_id);
 	pm8001_dbg(pm8001_ha, MSG, "unregister device device_id = %d\n",
 		   device_id);
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
-			sizeof(payload), 0);
-	return ret;
+
+	return pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,
+				    sizeof(payload), 0);
 }
 
 /**
@@ -4488,17 +4461,15 @@ static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
 	u32 phyId, u32 phy_op)
 {
 	struct local_phy_ctl_req payload;
-	struct inbound_queue_table *circularQ;
-	int ret;
 	u32 opc = OPC_INB_LOCAL_PHY_CONTROL;
+
 	memset(&payload, 0, sizeof(payload));
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	payload.tag = cpu_to_le32(1);
 	payload.phyop_phyid =
 		cpu_to_le32(((phy_op & 0xff) << 8) | (phyId & 0x0F));
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
-			sizeof(payload), 0);
-	return ret;
+
+	return pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,
+				    sizeof(payload), 0);
 }
 
 static u32 pm8001_chip_is_our_interrupt(struct pm8001_hba_info *pm8001_ha)
@@ -4536,9 +4507,7 @@ static int send_task_abort(struct pm8001_hba_info *pm8001_ha, u32 opc,
 	u32 dev_id, u8 flag, u32 task_tag, u32 cmd_tag)
 {
 	struct task_abort_req task_abort;
-	struct inbound_queue_table *circularQ;
-	int ret;
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
 	memset(&task_abort, 0, sizeof(task_abort));
 	if (ABORT_SINGLE == (flag & ABORT_MASK)) {
 		task_abort.abort_all = 0;
@@ -4550,9 +4519,9 @@ static int send_task_abort(struct pm8001_hba_info *pm8001_ha, u32 opc,
 		task_abort.device_id = cpu_to_le32(dev_id);
 		task_abort.tag = cpu_to_le32(cmd_tag);
 	}
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort,
-			sizeof(task_abort), 0);
-	return ret;
+
+	return pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &task_abort,
+				    sizeof(task_abort), 0);
 }
 
 /*
@@ -4592,9 +4561,7 @@ int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha,
 	struct domain_device *dev = task->dev;
 	struct pm8001_device *pm8001_dev = dev->lldd_dev;
 	u32 opc = OPC_INB_SSPINITMSTART;
-	struct inbound_queue_table *circularQ;
 	struct ssp_ini_tm_start_req sspTMCmd;
-	int ret;
 
 	memset(&sspTMCmd, 0, sizeof(sspTMCmd));
 	sspTMCmd.device_id = cpu_to_le32(pm8001_dev->device_id);
@@ -4604,10 +4571,9 @@ int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha,
 	sspTMCmd.tag = cpu_to_le32(ccb->ccb_tag);
 	if (pm8001_ha->chip_id != chip_8001)
 		sspTMCmd.ds_ads_m = cpu_to_le32(0x08);
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd,
-			sizeof(sspTMCmd), 0);
-	return ret;
+
+	return pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &sspTMCmd,
+				    sizeof(sspTMCmd), 0);
 }
 
 int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
@@ -4617,7 +4583,6 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 	u32 nvmd_type;
 	int rc;
 	struct pm8001_ccb_info *ccb;
-	struct inbound_queue_table *circularQ;
 	struct get_nvm_data_req nvmd_req;
 	struct fw_control_ex *fw_control_context;
 	struct pm8001_ioctl_payload *ioctl_payload = payload;
@@ -4628,7 +4593,6 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 		return -ENOMEM;
 	fw_control_context->usrAddr = (u8 *)ioctl_payload->func_specific;
 	fw_control_context->len = ioctl_payload->rd_length;
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	memset(&nvmd_req, 0, sizeof(nvmd_req));
 
 	ccb = pm8001_ccb_alloc(pm8001_ha, NULL, NULL);
@@ -4695,8 +4659,9 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 	default:
 		break;
 	}
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req,
-			sizeof(nvmd_req), 0);
+
+	rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &nvmd_req,
+				  sizeof(nvmd_req), 0);
 	if (rc) {
 		kfree(fw_control_context);
 		pm8001_ccb_free(pm8001_ha, ccb);
@@ -4711,7 +4676,6 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 	u32 nvmd_type;
 	int rc;
 	struct pm8001_ccb_info *ccb;
-	struct inbound_queue_table *circularQ;
 	struct set_nvm_data_req nvmd_req;
 	struct fw_control_ex *fw_control_context;
 	struct pm8001_ioctl_payload *ioctl_payload = payload;
@@ -4720,7 +4684,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 	fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL);
 	if (!fw_control_context)
 		return -ENOMEM;
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
 	memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr,
 		&ioctl_payload->func_specific,
 		ioctl_payload->wr_length);
@@ -4779,7 +4743,8 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 	default:
 		break;
 	}
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req,
+
+	rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &nvmd_req,
 			sizeof(nvmd_req), 0);
 	if (rc) {
 		kfree(fw_control_context);
@@ -4800,12 +4765,9 @@ pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha,
 {
 	struct fw_flash_Update_req payload;
 	struct fw_flash_updata_info *info;
-	struct inbound_queue_table *circularQ;
-	int ret;
 	u32 opc = OPC_INB_FW_FLASH_UPDATE;
 
 	memset(&payload, 0, sizeof(struct fw_flash_Update_req));
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	info = fw_flash_updata_info;
 	payload.tag = cpu_to_le32(tag);
 	payload.cur_image_len = cpu_to_le32(info->cur_image_len);
@@ -4816,9 +4778,9 @@ pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha,
 		cpu_to_le32(lower_32_bits(le64_to_cpu(info->sgl.addr)));
 	payload.sgl_addr_hi =
 		cpu_to_le32(upper_32_bits(le64_to_cpu(info->sgl.addr)));
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
-			sizeof(payload), 0);
-	return ret;
+
+	return pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,
+				    sizeof(payload), 0);
 }
 
 int
@@ -4953,7 +4915,6 @@ pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha,
 	struct pm8001_device *pm8001_dev, u32 state)
 {
 	struct set_dev_state_req payload;
-	struct inbound_queue_table *circularQ;
 	struct pm8001_ccb_info *ccb;
 	int rc;
 	u32 opc = OPC_INB_SET_DEVICE_STATE;
@@ -4964,13 +4925,12 @@ pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha,
 	if (!ccb)
 		return -SAS_QUEUE_FULL;
 
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	payload.tag = cpu_to_le32(ccb->ccb_tag);
 	payload.device_id = cpu_to_le32(pm8001_dev->device_id);
 	payload.nds = cpu_to_le32(state);
 
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
-			sizeof(payload), 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,
+				  sizeof(payload), 0);
 	if (rc)
 		pm8001_ccb_free(pm8001_ha, ccb);
 
@@ -4981,7 +4941,6 @@ static int
 pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha)
 {
 	struct sas_re_initialization_req payload;
-	struct inbound_queue_table *circularQ;
 	struct pm8001_ccb_info *ccb;
 	int rc;
 	u32 opc = OPC_INB_SAS_RE_INITIALIZE;
@@ -4992,14 +4951,13 @@ pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha)
 	if (!ccb)
 		return -SAS_QUEUE_FULL;
 
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	payload.tag = cpu_to_le32(ccb->ccb_tag);
 	payload.SSAHOLT = cpu_to_le32(0xd << 25);
 	payload.sata_hol_tmo = cpu_to_le32(80);
 	payload.open_reject_cmdretries_data_retries = cpu_to_le32(0xff00ff);
 
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
-			sizeof(payload), 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,
+				  sizeof(payload), 0);
 	if (rc)
 		pm8001_ccb_free(pm8001_ha, ccb);
 
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 824ada7f6a3f..aec4572906cf 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -668,8 +668,7 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr,
 
 void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha);
 int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
-			struct inbound_queue_table *circularQ,
-			u32 opCode, void *payload, size_t nb,
+			u32 q_index, u32 opCode, void *payload, size_t nb,
 			u32 responseQueue);
 int pm8001_mpi_msg_free_get(struct inbound_queue_table *circularQ,
 				u16 messageSize, void **messagePtr);
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 5a65d4406c94..c25d2c435f6a 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -1182,7 +1182,6 @@ int
 pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha)
 {
 	struct set_ctrl_cfg_req payload;
-	struct inbound_queue_table *circularQ;
 	int rc;
 	u32 tag;
 	u32 opc = OPC_INB_SET_CONTROLLER_CONFIG;
@@ -1193,7 +1192,6 @@ pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha)
 	if (rc)
 		return rc;
 
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	payload.tag = cpu_to_le32(tag);
 
 	if (IS_SPCV_12G(pm8001_ha->pdev))
@@ -1211,7 +1209,7 @@ pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha)
 		   "Setting up thermal config. cfg_pg 0 0x%x cfg_pg 1 0x%x\n",
 		   payload.cfg_pg[0], payload.cfg_pg[1]);
 
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+	rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,
 			sizeof(payload), 0);
 	if (rc)
 		pm8001_tag_free(pm8001_ha, tag);
@@ -1228,7 +1226,6 @@ static int
 pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha)
 {
 	struct set_ctrl_cfg_req payload;
-	struct inbound_queue_table *circularQ;
 	SASProtocolTimerConfig_t SASConfigPage;
 	int rc;
 	u32 tag;
@@ -1238,11 +1235,9 @@ pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha)
 	memset(&SASConfigPage, 0, sizeof(SASProtocolTimerConfig_t));
 
 	rc = pm8001_tag_alloc(pm8001_ha, &tag);
-
 	if (rc)
 		return rc;
 
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	payload.tag = cpu_to_le32(tag);
 
 	SASConfigPage.pageCode = cpu_to_le32(SAS_PROTOCOL_TIMER_CONFIG_PAGE);
@@ -1284,7 +1279,7 @@ pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha)
 	memcpy(&payload.cfg_pg, &SASConfigPage,
 			 sizeof(SASProtocolTimerConfig_t));
 
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+	rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,
 			sizeof(payload), 0);
 	if (rc)
 		pm8001_tag_free(pm8001_ha, tag);
@@ -1390,7 +1385,6 @@ pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha)
 static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha)
 {
 	struct kek_mgmt_req payload;
-	struct inbound_queue_table *circularQ;
 	int rc;
 	u32 tag;
 	u32 opc = OPC_INB_KEK_MANAGEMENT;
@@ -1400,7 +1394,6 @@ static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha)
 	if (rc)
 		return rc;
 
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	payload.tag = cpu_to_le32(tag);
 	/* Currently only one key is used. New KEK index is 1.
 	 * Current KEK index is 1. Store KEK to NVRAM is 1.
@@ -1413,7 +1406,7 @@ static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha)
 		   "Saving Encryption info to flash. payload 0x%x\n",
 		   le32_to_cpu(payload.new_curidx_ksop));
 
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+	rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,
 			sizeof(payload), 0);
 	if (rc)
 		pm8001_tag_free(pm8001_ha, tag);
@@ -1770,7 +1763,6 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha,
 	struct pm8001_ccb_info *ccb;
 	struct sas_task *task = NULL;
 	struct task_abort_req task_abort;
-	struct inbound_queue_table *circularQ;
 	u32 opc = OPC_INB_SATA_ABORT;
 	int ret;
 
@@ -1794,15 +1786,13 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha,
 		return;
 	}
 
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
-
 	memset(&task_abort, 0, sizeof(task_abort));
 	task_abort.abort_all = cpu_to_le32(1);
 	task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
 	task_abort.tag = cpu_to_le32(ccb->ccb_tag);
 
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort,
-			sizeof(task_abort), 0);
+	ret = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &task_abort,
+				   sizeof(task_abort), 0);
 	pm8001_dbg(pm8001_ha, FAIL, "Executing abort task end\n");
 	if (ret) {
 		sas_free_task(task);
@@ -1819,11 +1809,9 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
 	struct sas_task *task = NULL;
 	struct host_to_dev_fis fis;
 	struct domain_device *dev;
-	struct inbound_queue_table *circularQ;
 	u32 opc = OPC_INB_SATA_HOST_OPSTART;
 
 	task = sas_alloc_slow_task(GFP_ATOMIC);
-
 	if (!task) {
 		pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task !!!\n");
 		return;
@@ -1856,7 +1844,6 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
 	pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG;
 
 	memset(&sata_cmd, 0, sizeof(sata_cmd));
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 
 	/* construct read log FIS */
 	memset(&fis, 0, sizeof(struct host_to_dev_fis));
@@ -1871,8 +1858,8 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
 	sata_cmd.ncqtag_atap_dir_m_dad = cpu_to_le32(((0x1 << 7) | (0x5 << 9)));
 	memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
 
-	res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd,
-			sizeof(sata_cmd), 0);
+	res = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &sata_cmd,
+				   sizeof(sata_cmd), 0);
 	pm8001_dbg(pm8001_ha, FAIL, "Executing read log end\n");
 	if (res) {
 		sas_free_task(task);
@@ -3234,17 +3221,15 @@ static void pm80xx_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha,
 	struct hw_event_ack_req	 payload;
 	u32 opc = OPC_INB_SAS_HW_EVENT_ACK;
 
-	struct inbound_queue_table *circularQ;
-
 	memset((u8 *)&payload, 0, sizeof(payload));
-	circularQ = &pm8001_ha->inbnd_q_tbl[Qnum];
 	payload.tag = cpu_to_le32(1);
 	payload.phyid_sea_portid = cpu_to_le32(((SEA & 0xFFFF) << 8) |
 		((phyId & 0xFF) << 24) | (port_id & 0xFF));
 	payload.param0 = cpu_to_le32(param0);
 	payload.param1 = cpu_to_le32(param1);
-	pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
-			sizeof(payload), 0);
+
+	pm8001_mpi_build_cmd(pm8001_ha, Qnum, opc, &payload,
+			     sizeof(payload), 0);
 }
 
 static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
@@ -4211,7 +4196,6 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
 	u32 req_len, resp_len;
 	struct smp_req smp_cmd;
 	u32 opc;
-	struct inbound_queue_table *circularQ;
 	u32 i, length;
 	u8 *payload;
 	u8 *to;
@@ -4240,7 +4224,6 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
 	}
 
 	opc = OPC_INB_SMP_REQUEST;
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	smp_cmd.tag = cpu_to_le32(ccb->ccb_tag);
 
 	length = sg_req->length;
@@ -4308,8 +4291,8 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
 	kunmap_atomic(to);
 	build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag,
 				&smp_cmd, pm8001_ha->smp_exp_mode, length);
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &smp_cmd,
-			sizeof(smp_cmd), 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &smp_cmd,
+				  sizeof(smp_cmd), 0);
 	if (rc)
 		goto err_out_2;
 	return 0;
@@ -4369,10 +4352,8 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
 	struct pm8001_device *pm8001_dev = dev->lldd_dev;
 	struct ssp_ini_io_start_req ssp_cmd;
 	u32 tag = ccb->ccb_tag;
-	int ret;
 	u64 phys_addr, end_addr;
 	u32 end_addr_high, end_addr_low;
-	struct inbound_queue_table *circularQ;
 	u32 q_index, cpu_id;
 	u32 opc = OPC_INB_SSPINIIOSTART;
 
@@ -4396,7 +4377,6 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
 		       task->ssp_task.cmd->cmd_len);
 	cpu_id = smp_processor_id();
 	q_index = (u32) (cpu_id) % (pm8001_ha->max_q_num);
-	circularQ = &pm8001_ha->inbnd_q_tbl[q_index];
 
 	/* Check if encryption is set */
 	if (pm8001_ha->chip->encrypt &&
@@ -4513,9 +4493,9 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
 			ssp_cmd.esgl = 0;
 		}
 	}
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
-			&ssp_cmd, sizeof(ssp_cmd), q_index);
-	return ret;
+
+	return pm8001_mpi_build_cmd(pm8001_ha, q_index, opc, &ssp_cmd,
+				    sizeof(ssp_cmd), q_index);
 }
 
 static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
@@ -4526,7 +4506,6 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
 	struct pm8001_device *pm8001_ha_dev = dev->lldd_dev;
 	struct ata_queued_cmd *qc = task->uldd_task;
 	u32 tag = ccb->ccb_tag;
-	int ret;
 	u32 q_index, cpu_id;
 	struct sata_start_req sata_cmd;
 	u32 hdr_tag, ncg_tag = 0;
@@ -4534,13 +4513,11 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
 	u32 end_addr_high, end_addr_low;
 	u32 ATAP = 0x0;
 	u32 dir;
-	struct inbound_queue_table *circularQ;
 	unsigned long flags;
 	u32 opc = OPC_INB_SATA_HOST_OPSTART;
 	memset(&sata_cmd, 0, sizeof(sata_cmd));
 	cpu_id = smp_processor_id();
 	q_index = (u32) (cpu_id) % (pm8001_ha->max_q_num);
-	circularQ = &pm8001_ha->inbnd_q_tbl[q_index];
 
 	if (task->data_dir == DMA_NONE && !task->ata_task.use_ncq) {
 		ATAP = 0x04; /* no data*/
@@ -4755,9 +4732,8 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
 				ccb->ccb_tag, opc,
 				qc ? qc->tf.command : 0, // ata opcode
 				ccb->device ? atomic_read(&ccb->device->running_req) : 0);
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
-			&sata_cmd, sizeof(sata_cmd), q_index);
-	return ret;
+	return pm8001_mpi_build_cmd(pm8001_ha, q_index, opc, &sata_cmd,
+				    sizeof(sata_cmd), q_index);
 }
 
 /**
@@ -4769,11 +4745,9 @@ static int
 pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
 {
 	struct phy_start_req payload;
-	struct inbound_queue_table *circularQ;
-	int ret;
 	u32 tag = 0x01;
 	u32 opcode = OPC_INB_PHYSTART;
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
 	memset(&payload, 0, sizeof(payload));
 	payload.tag = cpu_to_le32(tag);
 
@@ -4795,9 +4769,9 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
 	memcpy(payload.sas_identify.sas_addr,
 	  &pm8001_ha->sas_addr, SAS_ADDR_SIZE);
 	payload.sas_identify.phy_id = phy_id;
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
-			sizeof(payload), 0);
-	return ret;
+
+	return pm8001_mpi_build_cmd(pm8001_ha, 0, opcode, &payload,
+				    sizeof(payload), 0);
 }
 
 /**
@@ -4809,17 +4783,15 @@ static int pm80xx_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
 	u8 phy_id)
 {
 	struct phy_stop_req payload;
-	struct inbound_queue_table *circularQ;
-	int ret;
 	u32 tag = 0x01;
 	u32 opcode = OPC_INB_PHYSTOP;
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
 	memset(&payload, 0, sizeof(payload));
 	payload.tag = cpu_to_le32(tag);
 	payload.phy_id = cpu_to_le32(phy_id);
-	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
-			sizeof(payload), 0);
-	return ret;
+
+	return pm8001_mpi_build_cmd(pm8001_ha, 0, opcode, &payload,
+				    sizeof(payload), 0);
 }
 
 /*
@@ -4831,7 +4803,6 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
 	struct reg_dev_req payload;
 	u32	opc;
 	u32 stp_sspsmp_sata = 0x4;
-	struct inbound_queue_table *circularQ;
 	u32 linkrate, phy_id;
 	int rc;
 	struct pm8001_ccb_info *ccb;
@@ -4841,7 +4812,6 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
 	struct domain_device *dev = pm8001_dev->sas_device;
 	struct domain_device *parent_dev = dev->parent;
 	struct pm8001_port *port = dev->port->lldd_port;
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 
 	memset(&payload, 0, sizeof(payload));
 	ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_dev, NULL);
@@ -4882,7 +4852,7 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
 	memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr,
 		SAS_ADDR_SIZE);
 
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+	rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,
 			sizeof(payload), 0);
 	if (rc)
 		pm8001_ccb_free(pm8001_ha, ccb);
@@ -4902,18 +4872,18 @@ static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
 	u32 tag;
 	int rc;
 	struct local_phy_ctl_req payload;
-	struct inbound_queue_table *circularQ;
 	u32 opc = OPC_INB_LOCAL_PHY_CONTROL;
+
 	memset(&payload, 0, sizeof(payload));
 	rc = pm8001_tag_alloc(pm8001_ha, &tag);
 	if (rc)
 		return rc;
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
 	payload.tag = cpu_to_le32(tag);
 	payload.phyop_phyid =
 		cpu_to_le32(((phy_op & 0xFF) << 8) | (phyId & 0xFF));
 
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+	rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,
 				  sizeof(payload), 0);
 	if (rc)
 		pm8001_tag_free(pm8001_ha, tag);
@@ -4959,7 +4929,6 @@ static void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha,
 	u32 tag, i, j = 0;
 	int rc;
 	struct set_phy_profile_req payload;
-	struct inbound_queue_table *circularQ;
 	u32 opc = OPC_INB_SET_PHY_PROFILE;
 
 	memset(&payload, 0, sizeof(payload));
@@ -4969,7 +4938,6 @@ static void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha,
 		return;
 	}
 
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	payload.tag = cpu_to_le32(tag);
 	payload.ppc_phyid =
 		cpu_to_le32(((operation & 0xF) << 8) | (phyid  & 0xFF));
@@ -4980,8 +4948,8 @@ static void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha,
 		payload.reserved[j] = cpu_to_le32(*((u32 *)buf + i));
 		j++;
 	}
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
-			sizeof(payload), 0);
+	rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,
+				  sizeof(payload), 0);
 	if (rc)
 		pm8001_tag_free(pm8001_ha, tag);
 }
@@ -5005,7 +4973,6 @@ void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha,
 	u32 tag, opc;
 	int rc, i;
 	struct set_phy_profile_req payload;
-	struct inbound_queue_table *circularQ;
 
 	memset(&payload, 0, sizeof(payload));
 
@@ -5015,7 +4982,6 @@ void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha,
 		return;
 	}
 
-	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	opc = OPC_INB_SET_PHY_PROFILE;
 
 	payload.tag = cpu_to_le32(tag);
@@ -5026,7 +4992,7 @@ void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha,
 	for (i = 0; i < length; i++)
 		payload.reserved[i] = cpu_to_le32(*(buf + i));
 
-	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+	rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,
 			sizeof(payload), 0);
 	if (rc)
 		pm8001_tag_free(pm8001_ha, tag);
-- 
2.34.1


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

* [PATCH v3 30/31] scsi: pm8001: Simplify pm8001_task_exec()
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (28 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 29/31] scsi: pm8001: Simplify pm8001_mpi_build_cmd() interface Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-15  8:57   ` John Garry
  2022-02-14  2:17 ` [PATCH v3 31/31] scsi: pm8001: Simplify pm8001_ccb_task_free() Damien Le Moal
                   ` (2 subsequent siblings)
  32 siblings, 1 reply; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

The main part of the pm8001_task_exec() function uses a do {} while(0)
loop that is useless and only makes the code harder to read. Remove this
loop. Also, the unnecessary local variable t is removed.
Additionnally, handling of the running_req counter is fixed to avoid
decrementing it without a corresponding incrementation in the case of an
invalid task protocol.

Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm8001_sas.c | 160 ++++++++++++++-----------------
 1 file changed, 73 insertions(+), 87 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 6c4aa04c9144..980afde2a0ab 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -373,32 +373,32 @@ static int sas_find_local_port_id(struct domain_device *dev)
   * @is_tmf: if it is task management task.
   * @tmf: the task management IU
   */
-static int pm8001_task_exec(struct sas_task *task,
-	gfp_t gfp_flags, int is_tmf, struct pm8001_tmf_task *tmf)
+static int pm8001_task_exec(struct sas_task *task, gfp_t gfp_flags, int is_tmf,
+			    struct pm8001_tmf_task *tmf)
 {
 	struct domain_device *dev = task->dev;
+	struct pm8001_device *pm8001_dev = dev->lldd_dev;
 	struct pm8001_hba_info *pm8001_ha;
-	struct pm8001_device *pm8001_dev;
 	struct pm8001_port *port = NULL;
-	struct sas_task *t = task;
-	struct task_status_struct *ts = &t->task_status;
+	struct task_status_struct *ts = &task->task_status;
+	enum sas_protocol task_proto = task->task_proto;
 	struct pm8001_ccb_info *ccb;
-	u32 rc = 0, n_elem = 0;
-	unsigned long flags = 0;
-	enum sas_protocol task_proto = t->task_proto;
+	unsigned long flags;
+	u32 n_elem = 0;
+	int rc = 0;
 
 	if (!dev->port) {
 		ts->resp = SAS_TASK_UNDELIVERED;
 		ts->stat = SAS_PHY_DOWN;
 		if (dev->dev_type != SAS_SATA_DEV)
-			t->task_done(t);
+			task->task_done(task);
 		return 0;
 	}
 
-	pm8001_ha = pm8001_find_ha_by_dev(task->dev);
+	pm8001_ha = pm8001_find_ha_by_dev(dev);
 	if (pm8001_ha->controller_fatal_error) {
 		ts->resp = SAS_TASK_UNDELIVERED;
-		t->task_done(t);
+		task->task_done(task);
 		return 0;
 	}
 
@@ -406,92 +406,78 @@ static int pm8001_task_exec(struct sas_task *task,
 
 	spin_lock_irqsave(&pm8001_ha->lock, flags);
 
-	do {
-		dev = t->dev;
-		pm8001_dev = dev->lldd_dev;
-		port = &pm8001_ha->port[sas_find_local_port_id(dev)];
+	pm8001_dev = dev->lldd_dev;
+	port = &pm8001_ha->port[sas_find_local_port_id(dev)];
 
-		if (DEV_IS_GONE(pm8001_dev) || !port->port_attached) {
-			ts->resp = SAS_TASK_UNDELIVERED;
-			ts->stat = SAS_PHY_DOWN;
-			if (sas_protocol_ata(task_proto)) {
-				spin_unlock_irqrestore(&pm8001_ha->lock, flags);
-				t->task_done(t);
-				spin_lock_irqsave(&pm8001_ha->lock, flags);
-			} else {
-				t->task_done(t);
-			}
-			continue;
+	if (DEV_IS_GONE(pm8001_dev) || !port->port_attached) {
+		ts->resp = SAS_TASK_UNDELIVERED;
+		ts->stat = SAS_PHY_DOWN;
+		if (sas_protocol_ata(task_proto)) {
+			spin_unlock_irqrestore(&pm8001_ha->lock, flags);
+			task->task_done(task);
+			spin_lock_irqsave(&pm8001_ha->lock, flags);
+		} else {
+			task->task_done(task);
 		}
+		goto unlock;
+	}
 
-		ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_dev, t);
-		if (!ccb) {
-			rc = -SAS_QUEUE_FULL;
-			goto err_out;
-		}
+	ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_dev, task);
+	if (!ccb) {
+		rc = -SAS_QUEUE_FULL;
+		goto unlock;
+	}
 
-		if (!sas_protocol_ata(task_proto)) {
-			if (t->num_scatter) {
-				n_elem = dma_map_sg(pm8001_ha->dev,
-					t->scatter,
-					t->num_scatter,
-					t->data_dir);
-				if (!n_elem) {
-					rc = -ENOMEM;
-					goto err_out_ccb;
-				}
+	if (!sas_protocol_ata(task_proto)) {
+		if (task->num_scatter) {
+			n_elem = dma_map_sg(pm8001_ha->dev, task->scatter,
+					    task->num_scatter, task->data_dir);
+			if (!n_elem) {
+				rc = -ENOMEM;
+				goto ccb_free;
 			}
-		} else {
-			n_elem = t->num_scatter;
 		}
+	} else {
+		n_elem = task->num_scatter;
+	}
 
-		t->lldd_task = ccb;
-		ccb->n_elem = n_elem;
+	task->lldd_task = ccb;
+	ccb->n_elem = n_elem;
 
-		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);
-			else
-				rc = pm8001_task_prep_ssp(pm8001_ha, ccb);
-			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:
-			dev_printk(KERN_ERR, pm8001_ha->dev,
-				"unknown sas_task proto: 0x%x\n", task_proto);
-			rc = -EINVAL;
-			break;
-		}
+	atomic_inc(&pm8001_dev->running_req);
 
-		if (rc) {
-			pm8001_dbg(pm8001_ha, IO, "rc is %x\n", rc);
-			atomic_dec(&pm8001_dev->running_req);
-			goto err_out_ccb;
-		}
-		/* TODO: select normal or high priority */
-	} while (0);
-	rc = 0;
-	goto out_done;
+	switch (task_proto) {
+	case SAS_PROTOCOL_SMP:
+		rc = pm8001_task_prep_smp(pm8001_ha, ccb);
+		break;
+	case SAS_PROTOCOL_SSP:
+		if (is_tmf)
+			rc = pm8001_task_prep_ssp_tm(pm8001_ha, ccb, tmf);
+		else
+			rc = pm8001_task_prep_ssp(pm8001_ha, ccb);
+		break;
+	case SAS_PROTOCOL_SATA:
+	case SAS_PROTOCOL_STP:
+		rc = pm8001_task_prep_ata(pm8001_ha, ccb);
+		break;
+	default:
+		dev_printk(KERN_ERR, pm8001_ha->dev,
+			   "unknown sas_task proto: 0x%x\n", task_proto);
+		rc = -EINVAL;
+		break;
+	}
 
-err_out_ccb:
-	pm8001_ccb_free(pm8001_ha, ccb);
-err_out:
-	dev_printk(KERN_ERR, pm8001_ha->dev, "pm8001 exec failed[%d]!\n", rc);
-	if (!sas_protocol_ata(task_proto))
-		if (n_elem)
-			dma_unmap_sg(pm8001_ha->dev, t->scatter, t->num_scatter,
-				t->data_dir);
-out_done:
+	if (rc) {
+		atomic_dec(&pm8001_dev->running_req);
+		if (!sas_protocol_ata(task_proto) && n_elem)
+			dma_unmap_sg(pm8001_ha->dev, task->scatter,
+				     task->num_scatter, task->data_dir);
+ccb_free:
+		pm8001_ccb_free(pm8001_ha, ccb);
+		dev_err(pm8001_ha->dev, "pm8001 exec failed[%d]!\n", rc);
+	}
+
+unlock:
 	spin_unlock_irqrestore(&pm8001_ha->lock, flags);
 	return rc;
 }
-- 
2.34.1


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

* [PATCH v3 31/31] scsi: pm8001: Simplify pm8001_ccb_task_free()
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (29 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 30/31] scsi: pm8001: Simplify pm8001_task_exec() Damien Le Moal
@ 2022-02-14  2:17 ` Damien Le Moal
  2022-02-14  2:23 ` [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
  2022-02-14 18:06 ` John Garry
  32 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:17 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

The task argument of the pm8001_ccb_task_free() function can be infered
from the ccb argument ccb_task field. So there is no need to have this
argument. Likewise, the ccb_index argument is always equal to the ccb
tag field and is not needed either. Remove both arguments and update all
call sites. The pm8001_ccb_task_free_done() helper is also modified to
match this change.

Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c | 48 +++++++++++++++-----------------
 drivers/scsi/pm8001/pm8001_sas.c | 25 ++++++++---------
 drivers/scsi/pm8001/pm8001_sas.h | 12 ++++----
 drivers/scsi/pm8001/pm80xx_hwi.c | 41 ++++++++++++---------------
 4 files changed, 58 insertions(+), 68 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 726421311543..d70a38c17544 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1564,11 +1564,11 @@ void pm8001_work_fn(struct work_struct *work)
 			spin_unlock_irqrestore(&t->task_state_lock, flags1);
 			pm8001_dbg(pm8001_ha, FAIL, "task 0x%p done with event 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
 				   t, pw->handler, ts->resp, ts->stat);
-			pm8001_ccb_task_free(pm8001_ha, t, ccb, ccb->ccb_tag);
+			pm8001_ccb_task_free(pm8001_ha, ccb);
 			spin_unlock_irqrestore(&pm8001_ha->lock, flags);
 		} else {
 			spin_unlock_irqrestore(&t->task_state_lock, flags1);
-			pm8001_ccb_task_free(pm8001_ha, t, ccb, ccb->ccb_tag);
+			pm8001_ccb_task_free(pm8001_ha, ccb);
 			mb();/* in order to force CPU ordering */
 			spin_unlock_irqrestore(&pm8001_ha->lock, flags);
 			t->task_done(t);
@@ -1697,8 +1697,7 @@ void pm8001_work_fn(struct work_struct *work)
 					continue;
 				}
 				/*complete sas task and update to top layer */
-				pm8001_ccb_task_free(pm8001_ha, task, ccb,
-						     ccb->ccb_tag);
+				pm8001_ccb_task_free(pm8001_ha, ccb);
 				ts->resp = SAS_TASK_COMPLETE;
 				task->task_done(task);
 			} else if (ccb->ccb_tag != PM8001_INVALID_TAG) {
@@ -2084,10 +2083,10 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		spin_unlock_irqrestore(&t->task_state_lock, flags);
 		pm8001_dbg(pm8001_ha, FAIL, "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
 			   t, status, ts->resp, ts->stat);
-		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+		pm8001_ccb_task_free(pm8001_ha, ccb);
 	} else {
 		spin_unlock_irqrestore(&t->task_state_lock, flags);
-		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+		pm8001_ccb_task_free(pm8001_ha, ccb);
 		mb();/* in order to force CPU ordering */
 		t->task_done(t);
 	}
@@ -2251,10 +2250,10 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		spin_unlock_irqrestore(&t->task_state_lock, flags);
 		pm8001_dbg(pm8001_ha, FAIL, "task 0x%p done with event 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
 			   t, event, ts->resp, ts->stat);
-		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+		pm8001_ccb_task_free(pm8001_ha, ccb);
 	} else {
 		spin_unlock_irqrestore(&t->task_state_lock, flags);
-		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+		pm8001_ccb_task_free(pm8001_ha, ccb);
 		mb();/* in order to force CPU ordering */
 		t->task_done(t);
 	}
@@ -2480,7 +2479,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 				IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
 			ts->resp = SAS_TASK_UNDELIVERED;
 			ts->stat = SAS_QUEUE_FULL;
-			pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
+			pm8001_ccb_task_free_done(pm8001_ha, ccb);
 			return;
 		}
 		break;
@@ -2496,7 +2495,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 				IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
 			ts->resp = SAS_TASK_UNDELIVERED;
 			ts->stat = SAS_QUEUE_FULL;
-			pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
+			pm8001_ccb_task_free_done(pm8001_ha, ccb);
 			return;
 		}
 		break;
@@ -2518,7 +2517,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 				IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY);
 			ts->resp = SAS_TASK_UNDELIVERED;
 			ts->stat = SAS_QUEUE_FULL;
-			pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
+			pm8001_ccb_task_free_done(pm8001_ha, ccb);
 			return;
 		}
 		break;
@@ -2589,7 +2588,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 				    IO_DS_NON_OPERATIONAL);
 			ts->resp = SAS_TASK_UNDELIVERED;
 			ts->stat = SAS_QUEUE_FULL;
-			pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
+			pm8001_ccb_task_free_done(pm8001_ha, ccb);
 			return;
 		}
 		break;
@@ -2609,7 +2608,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 				    IO_DS_IN_ERROR);
 			ts->resp = SAS_TASK_UNDELIVERED;
 			ts->stat = SAS_QUEUE_FULL;
-			pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
+			pm8001_ccb_task_free_done(pm8001_ha, ccb);
 			return;
 		}
 		break;
@@ -2639,10 +2638,10 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		pm8001_dbg(pm8001_ha, FAIL,
 			   "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
 			   t, status, ts->resp, ts->stat);
-		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+		pm8001_ccb_task_free(pm8001_ha, ccb);
 	} else {
 		spin_unlock_irqrestore(&t->task_state_lock, flags);
-		pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
+		pm8001_ccb_task_free_done(pm8001_ha, ccb);
 	}
 }
 
@@ -2734,7 +2733,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
 				IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
 			ts->resp = SAS_TASK_COMPLETE;
 			ts->stat = SAS_QUEUE_FULL;
-			pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
+			pm8001_ccb_task_free_done(pm8001_ha, ccb);
 			return;
 		}
 		break;
@@ -2828,10 +2827,10 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		pm8001_dbg(pm8001_ha, FAIL,
 			   "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
 			   t, event, ts->resp, ts->stat);
-		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+		pm8001_ccb_task_free(pm8001_ha, ccb);
 	} else {
 		spin_unlock_irqrestore(&t->task_state_lock, flags);
-		pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
+		pm8001_ccb_task_free_done(pm8001_ha, ccb);
 	}
 }
 
@@ -3011,12 +3010,10 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		spin_unlock_irqrestore(&t->task_state_lock, flags);
 		pm8001_dbg(pm8001_ha, FAIL, "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
 			   t, status, ts->resp, ts->stat);
-		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+		pm8001_ccb_task_free(pm8001_ha, ccb);
 	} else {
 		spin_unlock_irqrestore(&t->task_state_lock, flags);
-		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
-		mb();/* in order to force CPU ordering */
-		t->task_done(t);
+		pm8001_ccb_task_free_done(pm8001_ha, ccb);
 	}
 }
 
@@ -3666,7 +3663,7 @@ int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 	t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
 	t->task_state_flags |= SAS_TASK_STATE_DONE;
 	spin_unlock_irqrestore(&t->task_state_lock, flags);
-	pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+	pm8001_ccb_task_free(pm8001_ha, ccb);
 	mb();
 
 	if (pm8001_dev->id & NCQ_ABORT_ALL_FLAG) {
@@ -4304,12 +4301,11 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
 					   "task 0x%p resp 0x%x  stat 0x%x but aborted by upper layer\n",
 					   task, ts->resp,
 					   ts->stat);
-				pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
+				pm8001_ccb_task_free(pm8001_ha, ccb);
 			} else {
 				spin_unlock_irqrestore(&task->task_state_lock,
 							flags);
-				pm8001_ccb_task_free_done(pm8001_ha, task,
-								ccb, tag);
+				pm8001_ccb_task_free_done(pm8001_ha, ccb);
 				return 0;
 			}
 		}
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 980afde2a0ab..ddcd96e0fd95 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -496,22 +496,21 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
 /**
   * pm8001_ccb_task_free - free the sg for ssp and smp command, free the ccb.
   * @pm8001_ha: our hba card information
-  * @ccb: the ccb which attached to ssp task
-  * @task: the task to be free.
-  * @ccb_idx: ccb index.
+  * @ccb: the ccb which attached to ssp task to free
   */
 void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha,
-	struct sas_task *task, struct pm8001_ccb_info *ccb, u32 ccb_idx)
+			  struct pm8001_ccb_info *ccb)
 {
+	struct sas_task *task = ccb->task;
 	struct ata_queued_cmd *qc;
 	struct pm8001_device *pm8001_dev;
 
-	if (!ccb->task)
+	if (!task)
 		return;
-	if (!sas_protocol_ata(task->task_proto))
-		if (ccb->n_elem)
-			dma_unmap_sg(pm8001_ha->dev, task->scatter,
-				task->num_scatter, task->data_dir);
+
+	if (!sas_protocol_ata(task->task_proto) && ccb->n_elem)
+		dma_unmap_sg(pm8001_ha->dev, task->scatter,
+			     task->num_scatter, task->data_dir);
 
 	switch (task->task_proto) {
 	case SAS_PROTOCOL_SMP:
@@ -530,12 +529,12 @@ void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha,
 	}
 
 	if (sas_protocol_ata(task->task_proto)) {
-		// For SCSI/ATA commands uldd_task points to ata_queued_cmd
+		/* For SCSI/ATA commands uldd_task points to ata_queued_cmd */
 		qc = task->uldd_task;
 		pm8001_dev = ccb->device;
 		trace_pm80xx_request_complete(pm8001_ha->id,
 			pm8001_dev ? pm8001_dev->attached_phy : PM8001_MAX_PHYS,
-			ccb_idx, 0 /* ctlr_opcode not known */,
+			ccb->ccb_tag, 0 /* ctlr_opcode not known */,
 			qc ? qc->tf.command : 0, // ata opcode
 			pm8001_dev ? atomic_read(&pm8001_dev->running_req) : -1);
 	}
@@ -952,11 +951,11 @@ void pm8001_open_reject_retry(
 				& SAS_TASK_STATE_ABORTED))) {
 			spin_unlock_irqrestore(&task->task_state_lock,
 				flags1);
-			pm8001_ccb_task_free(pm8001_ha, task, ccb, ccb->ccb_tag);
+			pm8001_ccb_task_free(pm8001_ha, ccb);
 		} else {
 			spin_unlock_irqrestore(&task->task_state_lock,
 				flags1);
-			pm8001_ccb_task_free(pm8001_ha, task, ccb, ccb->ccb_tag);
+			pm8001_ccb_task_free(pm8001_ha, ccb);
 			mb();/* in order to force CPU ordering */
 			spin_unlock_irqrestore(&pm8001_ha->lock, flags);
 			task->task_done(task);
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index aec4572906cf..2aab357d9a23 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -641,7 +641,7 @@ int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out);
 void pm8001_tag_init(struct pm8001_hba_info *pm8001_ha);
 u32 pm8001_get_ncq_tag(struct sas_task *task, u32 *tag);
 void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha,
-	struct sas_task *task, struct pm8001_ccb_info *ccb, u32 ccb_idx);
+			  struct pm8001_ccb_info *ccb);
 int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
 	void *funcdata);
 void pm8001_scan_start(struct Scsi_Host *shost);
@@ -786,12 +786,12 @@ static inline void pm8001_ccb_free(struct pm8001_hba_info *pm8001_ha,
 	pm8001_tag_free(pm8001_ha, tag);
 }
 
-static inline void
-pm8001_ccb_task_free_done(struct pm8001_hba_info *pm8001_ha,
-			struct sas_task *task, struct pm8001_ccb_info *ccb,
-			u32 ccb_idx)
+static inline void pm8001_ccb_task_free_done(struct pm8001_hba_info *pm8001_ha,
+					     struct pm8001_ccb_info *ccb)
 {
-	pm8001_ccb_task_free(pm8001_ha, task, ccb, ccb_idx);
+	struct sas_task *task = ccb->task;
+
+	pm8001_ccb_task_free(pm8001_ha, ccb);
 	smp_mb(); /*in order to force CPU ordering*/
 	task->task_done(task);
 }
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index c25d2c435f6a..9550c586ff66 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -2159,12 +2159,10 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 			   t, status, ts->resp, ts->stat);
 		if (t->slow_task)
 			complete(&t->slow_task->completion);
-		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+		pm8001_ccb_task_free(pm8001_ha, ccb);
 	} else {
 		spin_unlock_irqrestore(&t->task_state_lock, flags);
-		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
-		mb();/* in order to force CPU ordering */
-		t->task_done(t);
+		pm8001_ccb_task_free_done(pm8001_ha, ccb);
 	}
 }
 
@@ -2340,12 +2338,10 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		pm8001_dbg(pm8001_ha, FAIL,
 			   "task 0x%p done with event 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
 			   t, event, ts->resp, ts->stat);
-		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+		pm8001_ccb_task_free(pm8001_ha, ccb);
 	} else {
 		spin_unlock_irqrestore(&t->task_state_lock, flags);
-		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
-		mb();/* in order to force CPU ordering */
-		t->task_done(t);
+		pm8001_ccb_task_free_done(pm8001_ha, ccb);
 	}
 }
 
@@ -2579,7 +2575,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha,
 			ts->stat = SAS_QUEUE_FULL;
 			spin_unlock_irqrestore(&circularQ->oq_lock,
 					circularQ->lock_flags);
-			pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
+			pm8001_ccb_task_free_done(pm8001_ha, ccb);
 			spin_lock_irqsave(&circularQ->oq_lock,
 					circularQ->lock_flags);
 			return;
@@ -2599,7 +2595,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha,
 			ts->stat = SAS_QUEUE_FULL;
 			spin_unlock_irqrestore(&circularQ->oq_lock,
 					circularQ->lock_flags);
-			pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
+			pm8001_ccb_task_free_done(pm8001_ha, ccb);
 			spin_lock_irqsave(&circularQ->oq_lock,
 					circularQ->lock_flags);
 			return;
@@ -2627,7 +2623,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha,
 			ts->stat = SAS_QUEUE_FULL;
 			spin_unlock_irqrestore(&circularQ->oq_lock,
 					circularQ->lock_flags);
-			pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
+			pm8001_ccb_task_free_done(pm8001_ha, ccb);
 			spin_lock_irqsave(&circularQ->oq_lock,
 					circularQ->lock_flags);
 			return;
@@ -2702,7 +2698,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha,
 			ts->stat = SAS_QUEUE_FULL;
 			spin_unlock_irqrestore(&circularQ->oq_lock,
 					circularQ->lock_flags);
-			pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
+			pm8001_ccb_task_free_done(pm8001_ha, ccb);
 			spin_lock_irqsave(&circularQ->oq_lock,
 					circularQ->lock_flags);
 			return;
@@ -2726,7 +2722,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha,
 			ts->stat = SAS_QUEUE_FULL;
 			spin_unlock_irqrestore(&circularQ->oq_lock,
 					circularQ->lock_flags);
-			pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
+			pm8001_ccb_task_free_done(pm8001_ha, ccb);
 			spin_lock_irqsave(&circularQ->oq_lock,
 					circularQ->lock_flags);
 			return;
@@ -2762,12 +2758,12 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha,
 			   t, status, ts->resp, ts->stat);
 		if (t->slow_task)
 			complete(&t->slow_task->completion);
-		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+		pm8001_ccb_task_free(pm8001_ha, ccb);
 	} else {
 		spin_unlock_irqrestore(&t->task_state_lock, flags);
 		spin_unlock_irqrestore(&circularQ->oq_lock,
 				circularQ->lock_flags);
-		pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
+		pm8001_ccb_task_free_done(pm8001_ha, ccb);
 		spin_lock_irqsave(&circularQ->oq_lock,
 				circularQ->lock_flags);
 	}
@@ -2872,7 +2868,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha,
 			ts->stat = SAS_QUEUE_FULL;
 			spin_unlock_irqrestore(&circularQ->oq_lock,
 					circularQ->lock_flags);
-			pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
+			pm8001_ccb_task_free_done(pm8001_ha, ccb);
 			spin_lock_irqsave(&circularQ->oq_lock,
 					circularQ->lock_flags);
 			return;
@@ -2982,12 +2978,12 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha,
 		pm8001_dbg(pm8001_ha, FAIL,
 			   "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
 			   t, event, ts->resp, ts->stat);
-		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+		pm8001_ccb_task_free(pm8001_ha, ccb);
 	} else {
 		spin_unlock_irqrestore(&t->task_state_lock, flags);
 		spin_unlock_irqrestore(&circularQ->oq_lock,
 				circularQ->lock_flags);
-		pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
+		pm8001_ccb_task_free_done(pm8001_ha, ccb);
 		spin_lock_irqsave(&circularQ->oq_lock,
 				circularQ->lock_flags);
 	}
@@ -3196,10 +3192,10 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
 		pm8001_dbg(pm8001_ha, FAIL,
 			   "task 0x%p done with io_status 0x%x resp 0x%xstat 0x%x but aborted by upper layer!\n",
 			   t, status, ts->resp, ts->stat);
-		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+		pm8001_ccb_task_free(pm8001_ha, ccb);
 	} else {
 		spin_unlock_irqrestore(&t->task_state_lock, flags);
-		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+		pm8001_ccb_task_free(pm8001_ha, ccb);
 		mb();/* in order to force CPU ordering */
 		t->task_done(t);
 	}
@@ -4715,13 +4711,12 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
 					   "task 0x%p resp 0x%x  stat 0x%x but aborted by upper layer\n",
 					   task, ts->resp,
 					   ts->stat);
-				pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
+				pm8001_ccb_task_free(pm8001_ha, ccb);
 				return 0;
 			} else {
 				spin_unlock_irqrestore(&task->task_state_lock,
 							flags);
-				pm8001_ccb_task_free_done(pm8001_ha, task,
-								ccb, tag);
+				pm8001_ccb_task_free_done(pm8001_ha, ccb);
 				atomic_dec(&pm8001_ha_dev->running_req);
 				return 0;
 			}
-- 
2.34.1


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

* Re: [PATCH v3 00/31] libsas and pm8001 fixes
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (30 preceding siblings ...)
  2022-02-14  2:17 ` [PATCH v3 31/31] scsi: pm8001: Simplify pm8001_ccb_task_free() Damien Le Moal
@ 2022-02-14  2:23 ` Damien Le Moal
  2022-02-15  3:18   ` Martin K. Petersen
  2022-02-14 18:06 ` John Garry
  32 siblings, 1 reply; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14  2:23 UTC (permalink / raw)
  To: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing

On 2022/02/14 11:17, Damien Le Moal wrote:
> This first part of this series (patches 1 to 24) fixes handling of NCQ
> NON DATA commands in libsas and many bugs in the pm8001 driver.
> 
> The fixes for the pm8001 driver include:
> * Suppression of all sparse warnings, fixing along the way many le32
>   handling bugs for big-endian architectures
> * Fix handling of NCQ NON DATA commands
> * Fix of tag values handling (0 *is* a valid tag value)
> * Fix many tag iand memory leaks in error path
> * Fix NCQ error recovery (abort all task execution) that was causing a
>   crash
> 
> The second part of the series (patches 25 to 31) iadd a small cleanup of
> libsas code and many simplifications of the pm8001 driver code.
> 
> With these fixes, libzbc test suite passes all test case. This test
> suite was used with an SMR drive for testing because it generates many
> NCQ NON DATA commands (for zone management commands) and also generates
> many NCQ command errors to check ASC/ASCQ returned by the device. With
> the test suite, the error recovery path was extensively exercised. The
> same tests were also executed with a SAS SMR drives to exercise the
> error path.
> 
> The patches are based on the 5.18/scsi-staging tree.

Martin,

Note that there is a conflict between 5.18/scsi-staging and 5.17-rc3/4 in the
pm8001 driver. And I need to touch rc3/rc4 code too. Could you rebase scsi-staging ?

Best regards.

> 
> Changes from v2:
> * Reorganized the series: fixes first, cleanups second.
> * Added more bug/leaks fix patches
> * Addressed Gary's comment for the ccb alloc helper (patch 28)
> * Rebased (and tested) all patches on 5.18/scsi-staging
> 
> Changes from v1:
> * Added reviewed-by tags
> * Addressed Christoph's comments on patch 4 and 8
> * Added patches 21 and 22 to fix 2 additional problems found while
>   preparing this v2 series
> * Added patch 23 and 24 to cleanup the code further.
> 
> Damien Le Moal (31):
>   scsi: libsas: Fix sas_ata_qc_issue() handling of NCQ NON DATA commands
>   scsi: pm8001: Fix __iomem pointer use in pm8001_phy_control()
>   scsi: pm8001: Fix pm8001_update_flash() local variable type
>   scsi: pm8001: Fix command initialization in pm80XX_send_read_log()
>   scsi: pm8001: Fix pm80xx_pci_mem_copy() interface
>   scsi: pm8001: Fix command initialization in pm8001_chip_ssp_tm_req()
>   scsi: pm8001: Fix payload initialization in pm80xx_set_thermal_config()
>   scsi: pm8001: Fix le32 values handling in pm80xx_set_sas_protocol_timer_config()
>   scsi: pm8001: Fix payload initialization in pm80xx_encrypt_update()
>   scsi: pm8001: Fix le32 values handling in pm80xx_chip_ssp_io_req()
>   scsi: pm8001: Fix le32 values handling in pm80xx_chip_sata_req()
>   scsi: pm8001: Fix use of struct set_phy_profile_req fields
>   scsi: pm8001: Remove local variable in pm8001_pci_resume()
>   scsi: pm8001: Fix NCQ NON DATA command task initialization
>   scsi: pm8001: Fix NCQ NON DATA command completion handling
>   scsi: pm8001: Fix abort all task initialization
>   scsi: pm8001: Fix pm8001_tag_alloc() failures handling
>   scsi: pm8001: Fix pm80xx_chip_phy_ctl_req()
>   scsi: pm8001: Fix pm8001_mpi_task_abort_resp()
>   scsi: pm8001: Fix tag values handling
>   scsi: pm8001: Fix task leak in pm8001_send_abort_all()
>   scsi: pm8001: Fix tag leaks on error
>   scsi: pm8001: fix memory leak in pm8001_chip_fw_flash_update_req()
>   scsi: pm8001: Fix process_one_iomb() kdoc comment
>   scsi: libsas: Simplify sas_ata_qc_issue() detection of NCQ commands
>   scsi: pm8001: Simplify pm8001_get_ncq_tag()
>   scsi: pm8001: Cleanup pm8001_queue_command()
>   scsi: pm8001: Introduce ccb alloc/free helpers
>   scsi: pm8001: Simplify pm8001_mpi_build_cmd() interface
>   scsi: pm8001: Simplify pm8001_task_exec()
>   scsi: pm8001: Simplify pm8001_ccb_task_free()
> 
>  drivers/scsi/libsas/sas_ata.c     |  11 +-
>  drivers/scsi/pm8001/pm8001_ctl.c  |   5 +-
>  drivers/scsi/pm8001/pm8001_hwi.c  | 450 ++++++++++++-----------------
>  drivers/scsi/pm8001/pm8001_init.c |  11 +-
>  drivers/scsi/pm8001/pm8001_sas.c  | 297 +++++++++----------
>  drivers/scsi/pm8001/pm8001_sas.h  |  64 ++++-
>  drivers/scsi/pm8001/pm80xx_hwi.c  | 458 ++++++++++++++----------------
>  drivers/scsi/pm8001/pm80xx_hwi.h  |   2 +-
>  8 files changed, 605 insertions(+), 693 deletions(-)
> 


-- 
Damien Le Moal
Western Digital Research

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

* Re: [PATCH v3 01/31] scsi: libsas: Fix sas_ata_qc_issue() handling of NCQ NON DATA commands
  2022-02-14  2:17 ` [PATCH v3 01/31] scsi: libsas: Fix sas_ata_qc_issue() handling of NCQ NON DATA commands Damien Le Moal
@ 2022-02-14 17:56   ` John Garry
  2022-02-14 22:23     ` Damien Le Moal
  0 siblings, 1 reply; 61+ messages in thread
From: John Garry @ 2022-02-14 17:56 UTC (permalink / raw)
  To: Damien Le Moal, linux-scsi, Martin K . Petersen, Xiang Chen,
	Jason Yan, Luo Jiaxing

On 14/02/2022 02:17, Damien Le Moal wrote:
> To detect for the DMA_NONE (no data transfer) DMA direction,
> sas_ata_qc_issue() tests if the command protocol is ATA_PROT_NODATA.
> This test does not include the ATA_CMD_NCQ_NON_DATA command as this
> command protocol is defined as ATA_PROT_NCQ_NODATA (equal to
> ATA_PROT_FLAG_NCQ) and not as ATA_PROT_NODATA.
> 
> To include both NCQ and non-NCQ commands when testing for the DMA_NONE
> DMA direction, use "!ata_is_data()".
> 
> Fixes: 176ddd89171d ("scsi: libsas: Reset num_scatter if libata marks qc as NODATA")
> Cc: stable@vger.kernel.org
> Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>

Regardless of comment below:
Reviewed-by: John Garry <john.garry@huawei.com>

> ---
>   drivers/scsi/libsas/sas_ata.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
> index e0030a093994..50f779088b6e 100644
> --- a/drivers/scsi/libsas/sas_ata.c
> +++ b/drivers/scsi/libsas/sas_ata.c
> @@ -197,7 +197,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
>   		task->total_xfer_len = qc->nbytes;
>   		task->num_scatter = qc->n_elem;
>   		task->data_dir = qc->dma_dir;
> -	} else if (qc->tf.protocol == ATA_PROT_NODATA) {
> +	} else if (!ata_is_data(qc->tf.protocol)) {

I was thinking ata_is_dma() would be more appropiate, but I suppose we 
don't have to use DMA.

>   		task->data_dir = DMA_NONE; >   	} else {
>   		for_each_sg(qc->sg, sg, qc->n_elem, si)


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

* Re: [PATCH v3 17/31] scsi: pm8001: Fix pm8001_tag_alloc() failures handling
  2022-02-14  2:17 ` [PATCH v3 17/31] scsi: pm8001: Fix pm8001_tag_alloc() failures handling Damien Le Moal
@ 2022-02-14 18:02   ` John Garry
  0 siblings, 0 replies; 61+ messages in thread
From: John Garry @ 2022-02-14 18:02 UTC (permalink / raw)
  To: Damien Le Moal, linux-scsi, Martin K . Petersen, Xiang Chen, Jason Yan

On 14/02/2022 02:17, Damien Le Moal wrote:
> In mpi_set_phy_profile_req() and in pm8001_set_phy_profile_single(), if
> pm8001_tag_alloc() fails to allocate a new tag, a warning message is
> issued but the uninitialized tag variable is still used to build a
> command. Avoid this by returning early in case of tag allocation
> failure.
> 
> Also make sure to always return the error code returned by
> pm8001_tag_alloc() when this function fails instead of an arbitrary
> value.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>

Reviewed-by: John Garry <john.garry@huawei.com>

> ---
>   drivers/scsi/pm8001/pm80xx_hwi.c | 15 ++++++++++-----
>   1 file changed, 10 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
> index 413b01cc2a84..b0b6dc643916 100644
> --- a/drivers/scsi/pm8001/pm80xx_hwi.c
> +++ b/drivers/scsi/pm8001/pm80xx_hwi.c
> @@ -1191,7 +1191,7 @@ pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha)
>   	memset(&payload, 0, sizeof(struct set_ctrl_cfg_req));
>   	rc = pm8001_tag_alloc(pm8001_ha, &tag);
>   	if (rc)
> -		return -1;
> +		return rc;
>   
>   	circularQ = &pm8001_ha->inbnd_q_tbl[0];
>   	payload.tag = cpu_to_le32(tag);
> @@ -1240,7 +1240,7 @@ pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha)

jfyi, please note this:
https://lore.kernel.org/linux-scsi/PH0PR11MB5112D8C17D9EA268C197893FEC579@PH0PR11MB5112.namprd11.prod.outlook.com/

>   	rc = pm8001_tag_alloc(pm8001_ha, &tag);
>   
>   	if (rc)
> -		return -1;
> +		return rc;
>   
>   	circularQ = &pm8001_ha->inbnd_q_tbl[0];
>   	payload.tag = cpu_to_le32(tag);
> @@ -1398,7 +1398,7 @@ static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha)
>   	memset(&payload, 0, sizeof(struct kek_mgmt_req));
>   	rc = pm8001_tag_alloc(pm8001_ha, &tag);
>   	if (rc)
> -		return -1;
> +		return rc;
>   
>   	circularQ = &pm8001_ha->inbnd_q_tbl[0];
>   	payload.tag = cpu_to_le32(tag);
> @@ -4979,8 +4979,11 @@ static void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha,
>   
>   	memset(&payload, 0, sizeof(payload));
>   	rc = pm8001_tag_alloc(pm8001_ha, &tag);
> -	if (rc)
> +	if (rc) {
>   		pm8001_dbg(pm8001_ha, FAIL, "Invalid tag\n");

ha - it was originally just continuing regardless

> +		return;
> +	}
> +
>   	circularQ = &pm8001_ha->inbnd_q_tbl[0];
>   	payload.tag = cpu_to_le32(tag);
>   	payload.ppc_phyid =
> @@ -5022,8 +5025,10 @@ void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha,
>   	memset(&payload, 0, sizeof(payload));
>   
>   	rc = pm8001_tag_alloc(pm8001_ha, &tag);
> -	if (rc)

and here

> +	if (rc) {
>   		pm8001_dbg(pm8001_ha, INIT, "Invalid tag\n");
> +		return;
> +	}
>   
>   	circularQ = &pm8001_ha->inbnd_q_tbl[0];
>   	opc = OPC_INB_SET_PHY_PROFILE;


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

* Re: [PATCH v3 00/31] libsas and pm8001 fixes
  2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
                   ` (31 preceding siblings ...)
  2022-02-14  2:23 ` [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
@ 2022-02-14 18:06 ` John Garry
  2022-02-14 22:29   ` Damien Le Moal
  32 siblings, 1 reply; 61+ messages in thread
From: John Garry @ 2022-02-14 18:06 UTC (permalink / raw)
  To: Damien Le Moal, linux-scsi, Martin K . Petersen, Xiang Chen, Jason Yan

On 14/02/2022 02:17, Damien Le Moal wrote:
> This first part of this series (patches 1 to 24) fixes handling of NCQ
> NON DATA commands in libsas and many bugs in the pm8001 driver.
> 
> The fixes for the pm8001 driver include:
> * Suppression of all sparse warnings, fixing along the way many le32
>    handling bugs for big-endian architectures
> * Fix handling of NCQ NON DATA commands
> * Fix of tag values handling (0*is*  a valid tag value)
> * Fix many tag iand memory leaks in error path
> * Fix NCQ error recovery (abort all task execution) that was causing a
>    crash
> 
> The second part of the series (patches 25 to 31) iadd a small cleanup of
> libsas code and many simplifications of the pm8001 driver code.
> 
> With these fixes, libzbc test suite passes all test case. This test
> suite was used with an SMR drive for testing because it generates many
> NCQ NON DATA commands (for zone management commands) and also generates
> many NCQ command errors to check ASC/ASCQ returned by the device. With
> the test suite, the error recovery path was extensively exercised. The
> same tests were also executed with a SAS SMR drives to exercise the
> error path.
> 
> The patches are based on the 5.18/scsi-staging tree.

Hi Damien,

jfyi, I still see the hang with this series. I don't think that the tag 
fixes were relevant unfortunately.

btw, how about add guys from get_maintainers.pl to lighten the review 
workload (and we should have the official maintainer anyway)? There are 
quite a few patches now...

Thanks,
John

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

* Re: [PATCH v3 01/31] scsi: libsas: Fix sas_ata_qc_issue() handling of NCQ NON DATA commands
  2022-02-14 17:56   ` John Garry
@ 2022-02-14 22:23     ` Damien Le Moal
  0 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14 22:23 UTC (permalink / raw)
  To: John Garry, linux-scsi, Martin K . Petersen, Xiang Chen,
	Jason Yan, Luo Jiaxing

On 2/15/22 02:56, John Garry wrote:
> On 14/02/2022 02:17, Damien Le Moal wrote:
>> To detect for the DMA_NONE (no data transfer) DMA direction,
>> sas_ata_qc_issue() tests if the command protocol is ATA_PROT_NODATA.
>> This test does not include the ATA_CMD_NCQ_NON_DATA command as this
>> command protocol is defined as ATA_PROT_NCQ_NODATA (equal to
>> ATA_PROT_FLAG_NCQ) and not as ATA_PROT_NODATA.
>>
>> To include both NCQ and non-NCQ commands when testing for the DMA_NONE
>> DMA direction, use "!ata_is_data()".
>>
>> Fixes: 176ddd89171d ("scsi: libsas: Reset num_scatter if libata marks qc as NODATA")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
> 
> Regardless of comment below:
> Reviewed-by: John Garry <john.garry@huawei.com>
> 
>> ---
>>   drivers/scsi/libsas/sas_ata.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
>> index e0030a093994..50f779088b6e 100644
>> --- a/drivers/scsi/libsas/sas_ata.c
>> +++ b/drivers/scsi/libsas/sas_ata.c
>> @@ -197,7 +197,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
>>   		task->total_xfer_len = qc->nbytes;
>>   		task->num_scatter = qc->n_elem;
>>   		task->data_dir = qc->dma_dir;
>> -	} else if (qc->tf.protocol == ATA_PROT_NODATA) {
>> +	} else if (!ata_is_data(qc->tf.protocol)) {
> 
> I was thinking ata_is_dma() would be more appropiate, but I suppose we 
> don't have to use DMA.

That was my first thought, but using ata_is_dma() would not include PIO
case, so that would not work.

> 
>>   		task->data_dir = DMA_NONE; >   	} else {
>>   		for_each_sg(qc->sg, sg, qc->n_elem, si)
> 


-- 
Damien Le Moal
Western Digital Research

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

* Re: [PATCH v3 00/31] libsas and pm8001 fixes
  2022-02-14 18:06 ` John Garry
@ 2022-02-14 22:29   ` Damien Le Moal
  2022-02-15  8:16     ` John Garry
  0 siblings, 1 reply; 61+ messages in thread
From: Damien Le Moal @ 2022-02-14 22:29 UTC (permalink / raw)
  To: John Garry, linux-scsi, Martin K . Petersen, Xiang Chen, Jason Yan

On 2/15/22 03:06, John Garry wrote:
> On 14/02/2022 02:17, Damien Le Moal wrote:
>> This first part of this series (patches 1 to 24) fixes handling of NCQ
>> NON DATA commands in libsas and many bugs in the pm8001 driver.
>>
>> The fixes for the pm8001 driver include:
>> * Suppression of all sparse warnings, fixing along the way many le32
>>    handling bugs for big-endian architectures
>> * Fix handling of NCQ NON DATA commands
>> * Fix of tag values handling (0*is*  a valid tag value)
>> * Fix many tag iand memory leaks in error path
>> * Fix NCQ error recovery (abort all task execution) that was causing a
>>    crash
>>
>> The second part of the series (patches 25 to 31) iadd a small cleanup of
>> libsas code and many simplifications of the pm8001 driver code.
>>
>> With these fixes, libzbc test suite passes all test case. This test
>> suite was used with an SMR drive for testing because it generates many
>> NCQ NON DATA commands (for zone management commands) and also generates
>> many NCQ command errors to check ASC/ASCQ returned by the device. With
>> the test suite, the error recovery path was extensively exercised. The
>> same tests were also executed with a SAS SMR drives to exercise the
>> error path.
>>
>> The patches are based on the 5.18/scsi-staging tree.
> 
> Hi Damien,
> 
> jfyi, I still see the hang with this series. I don't think that the tag 
> fixes were relevant unfortunately.

As mentioned above, I did test with a SAS drive too (an SMR one to
heavily test the error path) and it worked perfectly.
Note that using Martin's rc1 based scsi-staging tree, I did see a lot of
KASAN complaints on boot regarding MSI/PCI setup. These warnings are
gone with rc3/4. What kernel version base are you using ?

I could not find the ARM board I have in the lab yesterday. Will try
again to find it and test with it.

> 
> btw, how about add guys from get_maintainers.pl to lighten the review 
> workload (and we should have the official maintainer anyway)? There are 
> quite a few patches now...

I did that... I will check again. I may have made mistake creating the
distribution list.

> 
> Thanks,
> John


-- 
Damien Le Moal
Western Digital Research

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

* Re: [PATCH v3 00/31] libsas and pm8001 fixes
  2022-02-14  2:23 ` [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
@ 2022-02-15  3:18   ` Martin K. Petersen
  2022-02-15  7:38     ` Damien Le Moal
  0 siblings, 1 reply; 61+ messages in thread
From: Martin K. Petersen @ 2022-02-15  3:18 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: linux-scsi, Martin K . Petersen, John Garry, Xiang Chen,
	Jason Yan, Luo Jiaxing


Hi Damien!

> Note that there is a conflict between 5.18/scsi-staging and 5.17-rc3/4
> in the pm8001 driver. And I need to touch rc3/rc4 code too. Could you
> rebase scsi-staging ?

I pulled in 5.17/scsi-fixes and fixed up the conflicts.

I suggest you merge your -rc of choice when testing. That's what I do if
the baseline kernel has problems on my lab systems.

-- 
Martin K. Petersen	Oracle Linux Engineering

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

* Re: [PATCH v3 00/31] libsas and pm8001 fixes
  2022-02-15  3:18   ` Martin K. Petersen
@ 2022-02-15  7:38     ` Damien Le Moal
  0 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-15  7:38 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: linux-scsi, John Garry, Xiang Chen, Jason Yan, Luo Jiaxing

On 2/15/22 12:18, Martin K. Petersen wrote:
> 
> Hi Damien!
> 
>> Note that there is a conflict between 5.18/scsi-staging and 5.17-rc3/4
>> in the pm8001 driver. And I need to touch rc3/rc4 code too. Could you
>> rebase scsi-staging ?
> 
> I pulled in 5.17/scsi-fixes and fixed up the conflicts.

Thanks !

> I suggest you merge your -rc of choice when testing. That's what I do if
> the baseline kernel has problems on my lab systems.

That is what I normally do, but for some reason, this time, I kept
ending up with a non working kernel...
I must have done something very wrong :)



-- 
Damien Le Moal
Western Digital Research

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

* Re: [PATCH v3 00/31] libsas and pm8001 fixes
  2022-02-14 22:29   ` Damien Le Moal
@ 2022-02-15  8:16     ` John Garry
  0 siblings, 0 replies; 61+ messages in thread
From: John Garry @ 2022-02-15  8:16 UTC (permalink / raw)
  To: Damien Le Moal, linux-scsi, Martin K . Petersen, Xiang Chen, Jason Yan

On 14/02/2022 22:29, Damien Le Moal wrote:
> On 2/15/22 03:06, John Garry wrote:
>> On 14/02/2022 02:17, Damien Le Moal wrote:
>>> This first part of this series (patches 1 to 24) fixes handling of NCQ
>>> NON DATA commands in libsas and many bugs in the pm8001 driver.
>>>
>>> The fixes for the pm8001 driver include:
>>> * Suppression of all sparse warnings, fixing along the way many le32
>>>     handling bugs for big-endian architectures
>>> * Fix handling of NCQ NON DATA commands
>>> * Fix of tag values handling (0*is*  a valid tag value)
>>> * Fix many tag iand memory leaks in error path
>>> * Fix NCQ error recovery (abort all task execution) that was causing a
>>>     crash
>>>
>>> The second part of the series (patches 25 to 31) iadd a small cleanup of
>>> libsas code and many simplifications of the pm8001 driver code.
>>>
>>> With these fixes, libzbc test suite passes all test case. This test
>>> suite was used with an SMR drive for testing because it generates many
>>> NCQ NON DATA commands (for zone management commands) and also generates
>>> many NCQ command errors to check ASC/ASCQ returned by the device. With
>>> the test suite, the error recovery path was extensively exercised. The
>>> same tests were also executed with a SAS SMR drives to exercise the
>>> error path.
>>>
>>> The patches are based on the 5.18/scsi-staging tree.
>>
>> Hi Damien,
>>
>> jfyi, I still see the hang with this series. I don't think that the tag
>> fixes were relevant unfortunately.
> 
> As mentioned above, I did test with a SAS drive too (an SMR one to
> heavily test the error path) and it worked perfectly.
> Note that using Martin's rc1 based scsi-staging tree, I did see a lot of
> KASAN complaints on boot regarding MSI/PCI setup. These warnings are
> gone with rc3/4. What kernel version base are you using ?

I was using mkp 5.18 staging tree from yesterday as baseline:
https://github.com/hisilicon/kernel-dev/commits/private-topic-sas-5.17-damien-pm8001-v3

If I start using rc4 then I would get conflicts (which obviously would 
be resolvable easily enough), but I doubt it is an issue (in using rc1).

> 
> I could not find the ARM board I have in the lab yesterday. Will try
> again to find it and test with it.

That would be brilliant if you could. This problem could even be down to 
defconfig differences (between arm64 and x86_64).

Thanks,
John

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

* Re: [PATCH v3 30/31] scsi: pm8001: Simplify pm8001_task_exec()
  2022-02-14  2:17 ` [PATCH v3 30/31] scsi: pm8001: Simplify pm8001_task_exec() Damien Le Moal
@ 2022-02-15  8:57   ` John Garry
  0 siblings, 0 replies; 61+ messages in thread
From: John Garry @ 2022-02-15  8:57 UTC (permalink / raw)
  To: Damien Le Moal, linux-scsi, Martin K . Petersen, Xiang Chen,
	Jason Yan, Ajish Koshy, Viswas G, jinpu.wang

On 14/02/2022 02:17, Damien Le Moal wrote:
> The main part of the pm8001_task_exec() function uses a do {} while(0)
> loop that is useless and only makes the code harder to read. Remove this
> loop. Also, the unnecessary local variable t is removed.
> Additionnally, handling of the running_req counter is fixed to avoid
> decrementing it without a corresponding incrementation in the case of an
> invalid task protocol.
> 

Hi Damien,

I think that this is much improved, but there are still issues with the 
code but they are outside the scope of your change.

Just some minor comments below.

Regardless,

Reviewed-by: John Garry <john.garry@huawei.com>

> Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
> ---
>   drivers/scsi/pm8001/pm8001_sas.c | 160 ++++++++++++++-----------------
>   1 file changed, 73 insertions(+), 87 deletions(-)
> 
> diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
> index 6c4aa04c9144..980afde2a0ab 100644
> --- a/drivers/scsi/pm8001/pm8001_sas.c
> +++ b/drivers/scsi/pm8001/pm8001_sas.c
> @@ -373,32 +373,32 @@ static int sas_find_local_port_id(struct domain_device *dev)
>     * @is_tmf: if it is task management task.
>     * @tmf: the task management IU
>     */
> -static int pm8001_task_exec(struct sas_task *task,
> -	gfp_t gfp_flags, int is_tmf, struct pm8001_tmf_task *tmf)
> +static int pm8001_task_exec(struct sas_task *task, gfp_t gfp_flags, int is_tmf,
> +			    struct pm8001_tmf_task *tmf)
>   {
>   	struct domain_device *dev = task->dev;
> +	struct pm8001_device *pm8001_dev = dev->lldd_dev;
>   	struct pm8001_hba_info *pm8001_ha;
> -	struct pm8001_device *pm8001_dev;
>   	struct pm8001_port *port = NULL;
> -	struct sas_task *t = task;
> -	struct task_status_struct *ts = &t->task_status;
> +	struct task_status_struct *ts = &task->task_status;
> +	enum sas_protocol task_proto = task->task_proto;

nit: I think that these can be better arranged in reverse fir-tree 
style, but no big deal

>   	struct pm8001_ccb_info *ccb;
> -	u32 rc = 0, n_elem = 0;
> -	unsigned long flags = 0;
> -	enum sas_protocol task_proto = t->task_proto;
> +	unsigned long flags;
> +	u32 n_elem = 0;
> +	int rc = 0;
>   
>   	if (!dev->port) {
>   		ts->resp = SAS_TASK_UNDELIVERED;
>   		ts->stat = SAS_PHY_DOWN;
>   		if (dev->dev_type != SAS_SATA_DEV)
> -			t->task_done(t);
> +			task->task_done(task);
>   		return 0;
>   	}
>   
> -	pm8001_ha = pm8001_find_ha_by_dev(task->dev);
> +	pm8001_ha = pm8001_find_ha_by_dev(dev);
>   	if (pm8001_ha->controller_fatal_error) {
>   		ts->resp = SAS_TASK_UNDELIVERED;
> -		t->task_done(t);
> +		task->task_done(task);
>   		return 0;
>   	}
>   
> @@ -406,92 +406,78 @@ static int pm8001_task_exec(struct sas_task *task,
>   
>   	spin_lock_irqsave(&pm8001_ha->lock, flags);
>   
> -	do {
> -		dev = t->dev;
> -		pm8001_dev = dev->lldd_dev;
> -		port = &pm8001_ha->port[sas_find_local_port_id(dev)];
> +	pm8001_dev = dev->lldd_dev;
> +	port = &pm8001_ha->port[sas_find_local_port_id(dev)];
>   
> -		if (DEV_IS_GONE(pm8001_dev) || !port->port_attached) {
> -			ts->resp = SAS_TASK_UNDELIVERED;
> -			ts->stat = SAS_PHY_DOWN;
> -			if (sas_protocol_ata(task_proto)) {
> -				spin_unlock_irqrestore(&pm8001_ha->lock, flags);
> -				t->task_done(t);
> -				spin_lock_irqsave(&pm8001_ha->lock, flags);
> -			} else {
> -				t->task_done(t);
> -			}
> -			continue;
> +	if (DEV_IS_GONE(pm8001_dev) || !port->port_attached) {
> +		ts->resp = SAS_TASK_UNDELIVERED;
> +		ts->stat = SAS_PHY_DOWN;
> +		if (sas_protocol_ata(task_proto)) {
> +			spin_unlock_irqrestore(&pm8001_ha->lock, flags);
> +			task->task_done(task);
> +			spin_lock_irqsave(&pm8001_ha->lock, flags);
> +		} else {
> +			task->task_done(task);
>   		}
> +		goto unlock;
> +	}
>   
> -		ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_dev, t);
> -		if (!ccb) {
> -			rc = -SAS_QUEUE_FULL;
> -			goto err_out;
> -		}
> +	ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_dev, task);
> +	if (!ccb) {
> +		rc = -SAS_QUEUE_FULL;
> +		goto unlock;
> +	}
>   
> -		if (!sas_protocol_ata(task_proto)) {
> -			if (t->num_scatter) {
> -				n_elem = dma_map_sg(pm8001_ha->dev,
> -					t->scatter,
> -					t->num_scatter,
> -					t->data_dir);
> -				if (!n_elem) {
> -					rc = -ENOMEM;
> -					goto err_out_ccb;
> -				}
> +	if (!sas_protocol_ata(task_proto)) {
> +		if (task->num_scatter) {
> +			n_elem = dma_map_sg(pm8001_ha->dev, task->scatter,
> +					    task->num_scatter, task->data_dir);
> +			if (!n_elem) {
> +				rc = -ENOMEM;
> +				goto ccb_free;
>   			}
> -		} else {
> -			n_elem = t->num_scatter;
>   		}
> +	} else {
> +		n_elem = task->num_scatter;
> +	}
>   
> -		t->lldd_task = ccb;
> -		ccb->n_elem = n_elem;
> +	task->lldd_task = ccb;
> +	ccb->n_elem = n_elem;
>   
> -		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);
> -			else
> -				rc = pm8001_task_prep_ssp(pm8001_ha, ccb);
> -			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:
> -			dev_printk(KERN_ERR, pm8001_ha->dev,
> -				"unknown sas_task proto: 0x%x\n", task_proto);
> -			rc = -EINVAL;
> -			break;
> -		}
> +	atomic_inc(&pm8001_dev->running_req);
>   
> -		if (rc) {
> -			pm8001_dbg(pm8001_ha, IO, "rc is %x\n", rc);
> -			atomic_dec(&pm8001_dev->running_req);
> -			goto err_out_ccb;
> -		}
> -		/* TODO: select normal or high priority */
> -	} while (0);
> -	rc = 0;
> -	goto out_done;
> +	switch (task_proto) {
> +	case SAS_PROTOCOL_SMP:
> +		rc = pm8001_task_prep_smp(pm8001_ha, ccb);
> +		break;
> +	case SAS_PROTOCOL_SSP:
> +		if (is_tmf)
> +			rc = pm8001_task_prep_ssp_tm(pm8001_ha, ccb, tmf);
> +		else
> +			rc = pm8001_task_prep_ssp(pm8001_ha, ccb);
> +		break;
> +	case SAS_PROTOCOL_SATA:
> +	case SAS_PROTOCOL_STP:
> +		rc = pm8001_task_prep_ata(pm8001_ha, ccb);
> +		break;
> +	default:
> +		dev_printk(KERN_ERR, pm8001_ha->dev,
> +			   "unknown sas_task proto: 0x%x\n", task_proto);
> +		rc = -EINVAL;
> +		break;
> +	}
>   
> -err_out_ccb:
> -	pm8001_ccb_free(pm8001_ha, ccb);
> -err_out:
> -	dev_printk(KERN_ERR, pm8001_ha->dev, "pm8001 exec failed[%d]!\n", rc);
> -	if (!sas_protocol_ata(task_proto))
> -		if (n_elem)
> -			dma_unmap_sg(pm8001_ha->dev, t->scatter, t->num_scatter,
> -				t->data_dir);
> -out_done:

I know it's a personal preference, but I preferred the old labels; 
however I did not like the goto out_done. I think that the old code 
should just have had 2x spin_unlock_irqrestore + return statements.

> +	if (rc) {
> +		atomic_dec(&pm8001_dev->running_req);
> +		if (!sas_protocol_ata(task_proto) && n_elem)
> +			dma_unmap_sg(pm8001_ha->dev, task->scatter,
> +				     task->num_scatter, task->data_dir);
> +ccb_free:
> +		pm8001_ccb_free(pm8001_ha, ccb);
> +		dev_err(pm8001_ha->dev, "pm8001 exec failed[%d]!\n", rc);

Comment on current code, so feel free to ignore: pm8001_dbg should be 
used always (and improved to be able to do so)

> +	}
> +
> +unlock:
>   	spin_unlock_irqrestore(&pm8001_ha->lock, flags);
>   	return rc;
>   }


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

* Re: [PATCH v3 27/31] scsi: pm8001: Cleanup pm8001_queue_command()
  2022-02-14  2:17 ` [PATCH v3 27/31] scsi: pm8001: Cleanup pm8001_queue_command() Damien Le Moal
@ 2022-02-15 10:55   ` John Garry
  2022-02-16 11:36     ` Damien Le Moal
  0 siblings, 1 reply; 61+ messages in thread
From: John Garry @ 2022-02-15 10:55 UTC (permalink / raw)
  To: Damien Le Moal, linux-scsi, Martin K . Petersen, Xiang Chen,
	Jason Yan, Luo Jiaxing

On 14/02/2022 02:17, Damien Le Moal wrote:
> Avoid repeatedly declaring "struct task_status_struct *ts" to handle
> error cases by declaring this variable for the entire function scope.
> This allows simplifying the error cases, and together with the addition
> of blank lines make the code more readable.
> 
> Reviewed-by: John Garry<john.garry@huawei.com>
> Signed-off-by: Damien Le Moal<damien.lemoal@opensource.wdc.com>
> ---

I assume that this can now just be merged with 30/31

Thanks,
John

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

* Re: [PATCH v3 28/31] scsi: pm8001: Introduce ccb alloc/free helpers
  2022-02-14  2:17 ` [PATCH v3 28/31] scsi: pm8001: Introduce ccb alloc/free helpers Damien Le Moal
@ 2022-02-15 11:07   ` John Garry
  2022-02-15 23:41     ` Damien Le Moal
  2022-02-16 11:43     ` Damien Le Moal
  0 siblings, 2 replies; 61+ messages in thread
From: John Garry @ 2022-02-15 11:07 UTC (permalink / raw)
  To: Damien Le Moal, linux-scsi, Martin K . Petersen, Xiang Chen,
	Jason Yan, Luo Jiaxing

On 14/02/2022 02:17, Damien Le Moal wrote:
> Introduce the pm8001_ccb_alloc() and pm8001_ccb_free() helpers to
> replace the typical code patterns:
> 
> 	res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
> 	if (res)
> 		...
> 	ccb = &pm8001_ha->ccb_info[ccb_tag];
> 	ccb->device = pm8001_ha_dev;
> 	ccb->ccb_tag = ccb_tag;
> 	ccb->task = task;
> 	ccb->n_elem = 0;A

nit: stray 'A' character

> 
> and
> 
> 	ccb->task = NULL;
> 	ccb->ccb_tag = PM8001_INVALID_TAG;
> 	pm8001_tag_free(pm8001_ha, tag);

Isn't it possible to do a "memset struct members", such that we order 
the members specifically that we can memset(0) a known region? The 
advantage is that adding/removing a member does not require much code to 
be touched and possibly missed.

> 
> With the simpler function calls:
> 
> 	ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_ha_dev, task);
> 	if (!ccb)
> 		...
> 
> and
> 
> 	pm8001_ccb_free(pm8001_ha, ccb);
> 
> The pm8001_ccb_alloc() helper ensures that all fields of the ccb info
> structure for the newly allocated tag are all initialized, except the
> buf_prd field. The pm8001_ccb_free() helper clears the initialized
> fields and the ccb tag to ensure that iteration over the adapter
> ccb_info array detects ccbs that are in use.


> 
> All call site of the pm8001_tag_alloc() function that use a ccb info
> associated with an allocated tag are converted to use the new helpers.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
> ---

The comments are not a show stopper, so:
Reviewed-by: John Garry <john.garry@huawei.com>


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

* Re: [PATCH v3 20/31] scsi: pm8001: Fix tag values handling
  2022-02-14  2:17 ` [PATCH v3 20/31] scsi: pm8001: Fix tag values handling Damien Le Moal
@ 2022-02-15 11:09   ` John Garry
  2022-02-15 23:44     ` Damien Le Moal
  0 siblings, 1 reply; 61+ messages in thread
From: John Garry @ 2022-02-15 11:09 UTC (permalink / raw)
  To: Damien Le Moal, linux-scsi, Martin K . Petersen, Xiang Chen,
	Jason Yan, jinpu.wang, Ajish Koshy

On 14/02/2022 02:17, Damien Le Moal wrote:
> @@ -1685,19 +1683,13 @@ void pm8001_work_fn(struct work_struct *work)
>   		struct task_status_struct *ts;
>   		struct sas_task *task;
>   		int i;
> -		u32 tag, device_id;
> +		u32 device_id;
>   
>   		for (i = 0; ccb = NULL, i < PM8001_MAX_CCB; i++) {
>   			ccb = &pm8001_ha->ccb_info[i];
>   			task = ccb->task;
>   			ts = &task->task_status;
> -			tag = ccb->ccb_tag;
> -			/* check if tag is NULL */
> -			if (!tag) {
> -				pm8001_dbg(pm8001_ha, FAIL,
> -					"tag Null\n");
> -				continue;
> -			}
> +

This looks so dodgy that maybe it is intentional. I think experts on 
this HW/driver need to check this further.

Thanks,
John

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

* Re: [PATCH v3 28/31] scsi: pm8001: Introduce ccb alloc/free helpers
  2022-02-15 11:07   ` John Garry
@ 2022-02-15 23:41     ` Damien Le Moal
  2022-02-16 11:43     ` Damien Le Moal
  1 sibling, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-15 23:41 UTC (permalink / raw)
  To: John Garry, linux-scsi, Martin K . Petersen, Xiang Chen,
	Jason Yan, Luo Jiaxing

On 2/15/22 20:07, John Garry wrote:
> On 14/02/2022 02:17, Damien Le Moal wrote:
>> Introduce the pm8001_ccb_alloc() and pm8001_ccb_free() helpers to
>> replace the typical code patterns:
>>
>> 	res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
>> 	if (res)
>> 		...
>> 	ccb = &pm8001_ha->ccb_info[ccb_tag];
>> 	ccb->device = pm8001_ha_dev;
>> 	ccb->ccb_tag = ccb_tag;
>> 	ccb->task = task;
>> 	ccb->n_elem = 0;A
> 
> nit: stray 'A' character

Weird... How did this pass compile & test ? Will fix that in v4.

> 
>>
>> and
>>
>> 	ccb->task = NULL;
>> 	ccb->ccb_tag = PM8001_INVALID_TAG;
>> 	pm8001_tag_free(pm8001_ha, tag);
> 
> Isn't it possible to do a "memset struct members", such that we order 
> the members specifically that we can memset(0) a known region? The 
> advantage is that adding/removing a member does not require much code to 
> be touched and possibly missed.

Hmmm. I guess we can by moving the buf_prd field at the end of the
struct. We would still need the ccb_tag initialization though, so I am
not entirely sure if this is worse it... Will try to see how it looks.

> 
>>
>> With the simpler function calls:
>>
>> 	ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_ha_dev, task);
>> 	if (!ccb)
>> 		...
>>
>> and
>>
>> 	pm8001_ccb_free(pm8001_ha, ccb);
>>
>> The pm8001_ccb_alloc() helper ensures that all fields of the ccb info
>> structure for the newly allocated tag are all initialized, except the
>> buf_prd field. The pm8001_ccb_free() helper clears the initialized
>> fields and the ccb tag to ensure that iteration over the adapter
>> ccb_info array detects ccbs that are in use.
> 
> 
>>
>> All call site of the pm8001_tag_alloc() function that use a ccb info
>> associated with an allocated tag are converted to use the new helpers.
>>
>> Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
>> ---
> 
> The comments are not a show stopper, so:
> Reviewed-by: John Garry <john.garry@huawei.com>
> 


-- 
Damien Le Moal
Western Digital Research

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

* Re: [PATCH v3 20/31] scsi: pm8001: Fix tag values handling
  2022-02-15 11:09   ` John Garry
@ 2022-02-15 23:44     ` Damien Le Moal
  0 siblings, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-15 23:44 UTC (permalink / raw)
  To: John Garry, linux-scsi, Martin K . Petersen, Xiang Chen,
	Jason Yan, jinpu.wang, Ajish Koshy, Jack Wang

On 2/15/22 20:09, John Garry wrote:
> On 14/02/2022 02:17, Damien Le Moal wrote:
>> @@ -1685,19 +1683,13 @@ void pm8001_work_fn(struct work_struct *work)
>>   		struct task_status_struct *ts;
>>   		struct sas_task *task;
>>   		int i;
>> -		u32 tag, device_id;
>> +		u32 device_id;
>>   
>>   		for (i = 0; ccb = NULL, i < PM8001_MAX_CCB; i++) {
>>   			ccb = &pm8001_ha->ccb_info[i];
>>   			task = ccb->task;
>>   			ts = &task->task_status;
>> -			tag = ccb->ccb_tag;
>> -			/* check if tag is NULL */
>> -			if (!tag) {
>> -				pm8001_dbg(pm8001_ha, FAIL,
>> -					"tag Null\n");
>> -				continue;
>> -			}
>> +
> 
> This looks so dodgy that maybe it is intentional. I think experts on 
> this HW/driver need to check this further.

Well, the tag that was allocated for this task may have been the
perfectly valid tag 0, so this really looks completely bogus to me, like
all other tag == 0 checks.

Will update the distribution list for v4 to add Jack Wang
<jinpu.wang@cloud.ionos.com> who is missing.


> 
> Thanks,
> John


-- 
Damien Le Moal
Western Digital Research

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

* Re: [PATCH v3 27/31] scsi: pm8001: Cleanup pm8001_queue_command()
  2022-02-15 10:55   ` John Garry
@ 2022-02-16 11:36     ` Damien Le Moal
  2022-02-16 11:38       ` John Garry
  0 siblings, 1 reply; 61+ messages in thread
From: Damien Le Moal @ 2022-02-16 11:36 UTC (permalink / raw)
  To: John Garry, linux-scsi, Martin K . Petersen, Xiang Chen,
	Jason Yan, Luo Jiaxing

On 2/15/22 19:55, John Garry wrote:
> On 14/02/2022 02:17, Damien Le Moal wrote:
>> Avoid repeatedly declaring "struct task_status_struct *ts" to handle
>> error cases by declaring this variable for the entire function scope.
>> This allows simplifying the error cases, and together with the addition
>> of blank lines make the code more readable.
>>
>> Reviewed-by: John Garry<john.garry@huawei.com>
>> Signed-off-by: Damien Le Moal<damien.lemoal@opensource.wdc.com>
>> ---
> 
> I assume that this can now just be merged with 30/31

patch 30 cleans up pm8001_task_exec(). This patch is for
pm8001_queue_command(). I preferred to separate to facilitate review.
But if you insist, I can merge these into a much bigger "code cleanup"
patch...

> 
> Thanks,
> John


-- 
Damien Le Moal
Western Digital Research

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

* Re: [PATCH v3 27/31] scsi: pm8001: Cleanup pm8001_queue_command()
  2022-02-16 11:36     ` Damien Le Moal
@ 2022-02-16 11:38       ` John Garry
  2022-02-16 11:42         ` Damien Le Moal
  0 siblings, 1 reply; 61+ messages in thread
From: John Garry @ 2022-02-16 11:38 UTC (permalink / raw)
  To: Damien Le Moal, linux-scsi, Martin K . Petersen, Xiang Chen, Jason Yan

On 16/02/2022 11:36, Damien Le Moal wrote:
> On 2/15/22 19:55, John Garry wrote:
>> On 14/02/2022 02:17, Damien Le Moal wrote:
>>> Avoid repeatedly declaring "struct task_status_struct *ts" to handle
>>> error cases by declaring this variable for the entire function scope.
>>> This allows simplifying the error cases, and together with the addition
>>> of blank lines make the code more readable.
>>>
>>> Reviewed-by: John Garry<john.garry@huawei.com>
>>> Signed-off-by: Damien Le Moal<damien.lemoal@opensource.wdc.com>
>>> ---
>>
>> I assume that this can now just be merged with 30/31
> 

Hi Damien,

> patch 30 cleans up pm8001_task_exec(). This patch is for
> pm8001_queue_command(). I preferred to separate to facilitate review.
> But if you insist, I can merge these into a much bigger "code cleanup"
> patch...
> 
I don't mind really.

BTW, on a separate topic, IIRC you said that rmmod hangs for this driver 
- if so, did you investigate why?

Thanks,
John

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

* Re: [PATCH v3 27/31] scsi: pm8001: Cleanup pm8001_queue_command()
  2022-02-16 11:38       ` John Garry
@ 2022-02-16 11:42         ` Damien Le Moal
  2022-02-16 11:50           ` John Garry
  0 siblings, 1 reply; 61+ messages in thread
From: Damien Le Moal @ 2022-02-16 11:42 UTC (permalink / raw)
  To: John Garry, linux-scsi, Martin K . Petersen, Xiang Chen, Jason Yan

On 2/16/22 20:38, John Garry wrote:
> On 16/02/2022 11:36, Damien Le Moal wrote:
>> On 2/15/22 19:55, John Garry wrote:
>>> On 14/02/2022 02:17, Damien Le Moal wrote:
>>>> Avoid repeatedly declaring "struct task_status_struct *ts" to handle
>>>> error cases by declaring this variable for the entire function scope.
>>>> This allows simplifying the error cases, and together with the addition
>>>> of blank lines make the code more readable.
>>>>
>>>> Reviewed-by: John Garry<john.garry@huawei.com>
>>>> Signed-off-by: Damien Le Moal<damien.lemoal@opensource.wdc.com>
>>>> ---
>>>
>>> I assume that this can now just be merged with 30/31
>>
> 
> Hi Damien,
> 
>> patch 30 cleans up pm8001_task_exec(). This patch is for
>> pm8001_queue_command(). I preferred to separate to facilitate review.
>> But if you insist, I can merge these into a much bigger "code cleanup"
>> patch...
>>
> I don't mind really.
> 
> BTW, on a separate topic, IIRC you said that rmmod hangs for this driver 
> - if so, did you investigate why?

The problem is gone with the fixes. I suspect it was due to the buggy
non-data command handling (likely, the flush issued when stopping the
device on rmmod).

I have not tackled/tried again the QD change failure though.

Preparing v4 now. Will check the QD change.

> 
> Thanks,
> John


-- 
Damien Le Moal
Western Digital Research

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

* Re: [PATCH v3 28/31] scsi: pm8001: Introduce ccb alloc/free helpers
  2022-02-15 11:07   ` John Garry
  2022-02-15 23:41     ` Damien Le Moal
@ 2022-02-16 11:43     ` Damien Le Moal
  1 sibling, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-16 11:43 UTC (permalink / raw)
  To: John Garry, linux-scsi, Martin K . Petersen, Xiang Chen,
	Jason Yan, Luo Jiaxing

On 2/15/22 20:07, John Garry wrote:
> On 14/02/2022 02:17, Damien Le Moal wrote:
>> Introduce the pm8001_ccb_alloc() and pm8001_ccb_free() helpers to
>> replace the typical code patterns:
>>
>> 	res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
>> 	if (res)
>> 		...
>> 	ccb = &pm8001_ha->ccb_info[ccb_tag];
>> 	ccb->device = pm8001_ha_dev;
>> 	ccb->ccb_tag = ccb_tag;
>> 	ccb->task = task;
>> 	ccb->n_elem = 0;A
> 
> nit: stray 'A' character
> 
>>
>> and
>>
>> 	ccb->task = NULL;
>> 	ccb->ccb_tag = PM8001_INVALID_TAG;
>> 	pm8001_tag_free(pm8001_ha, tag);
> 
> Isn't it possible to do a "memset struct members", such that we order 
> the members specifically that we can memset(0) a known region? The 
> advantage is that adding/removing a member does not require much code to 
> be touched and possibly missed.
> 
>>
>> With the simpler function calls:
>>
>> 	ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_ha_dev, task);
>> 	if (!ccb)
>> 		...
>>
>> and
>>
>> 	pm8001_ccb_free(pm8001_ha, ccb);
>>
>> The pm8001_ccb_alloc() helper ensures that all fields of the ccb info
>> structure for the newly allocated tag are all initialized, except the
>> buf_prd field. The pm8001_ccb_free() helper clears the initialized
>> fields and the ccb tag to ensure that iteration over the adapter
>> ccb_info array detects ccbs that are in use.
> 
> 
>>
>> All call site of the pm8001_tag_alloc() function that use a ccb info
>> associated with an allocated tag are converted to use the new helpers.
>>
>> Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
>> ---
> 
> The comments are not a show stopper, so:
> Reviewed-by: John Garry <john.garry@huawei.com>

Thanks. I left the patch as-is and did not try the memset() thing. Let's
do that later.

> 


-- 
Damien Le Moal
Western Digital Research

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

* Re: [PATCH v3 27/31] scsi: pm8001: Cleanup pm8001_queue_command()
  2022-02-16 11:42         ` Damien Le Moal
@ 2022-02-16 11:50           ` John Garry
  2022-02-16 12:05             ` Damien Le Moal
  0 siblings, 1 reply; 61+ messages in thread
From: John Garry @ 2022-02-16 11:50 UTC (permalink / raw)
  To: Damien Le Moal, linux-scsi, Martin K . Petersen, Xiang Chen, Jason Yan

On 16/02/2022 11:42, Damien Le Moal wrote:
>> Hi Damien,
>>
>>> patch 30 cleans up pm8001_task_exec(). This patch is for
>>> pm8001_queue_command(). I preferred to separate to facilitate review.
>>> But if you insist, I can merge these into a much bigger "code cleanup"
>>> patch...
>>>
>> I don't mind really.
>>
>> BTW, on a separate topic, IIRC you said that rmmod hangs for this driver
>> - if so, did you investigate why?
> The problem is gone with the fixes. I suspect it was due to the buggy
> non-data command handling (likely, the flush issued when stopping the
> device on rmmod).
> 
> I have not tackled/tried again the QD change failure though.
> 
> Preparing v4 now. Will check the QD change.
> 

ok, great.

JFYI, turning on DMA debug sometimes gives this even after fdisk -l:

[   45.080945] sas: sas_scsi_find_task: querying task 0x(____ptrval____)
[   45.087582] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
[   45.093681] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO 
Failure Drive:5000c50085ff5559
[   45.102641] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
[   45.108739] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO 
Failure Drive:5000c50085ff5559
[   45.117694] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
[   45.123792] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO 
Failure Drive:5000c50085ff5559
[   45.132652] pm80xx: rc= -5
[   45.135370] sas: sas_scsi_find_task: task 0x(____ptrval____) result 
code -5 not handled
[   45.143466] sas: task 0x(____ptrval____) is not at LU: I_T recover
[   45.149741] sas: I_T nexus reset for dev 5000c50085ff5559
[   47.183916] sas: I_T 5000c50085ff5559 recovered
[   47.189034] sas: --- Exit sas_scsi_recover_host: busy: 0 failed: 1 
tries: 1
[   47.204168] ------------[ cut here ]------------
[   47.208829] DMA-API: pm80xx 0000:04:00.0: cacheline tracking EEXIST, 
overlapping mappings aren't supported
[   47.218502] WARNING: CPU: 3 PID: 641 at kernel/dma/debug.c:570 
add_dma_entry+0x308/0x3f0
[   47.226607] Modules linked in:
[   47.229678] CPU: 3 PID: 641 Comm: kworker/3:1H Not tainted 
5.17.0-rc1-11918-gd9d909a8c666 #407
[   47.238298] Hardware name: Huawei D06 /D06, BIOS Hisilicon D06 UEFI 
RC0 - V1.16.01 03/15/2019
[   47.246829] Workqueue: kblockd blk_mq_run_work_fn
[   47.251552] pstate: 604000c9 (nZCv daIF +PAN -UAO -TCO -DIT -SSBS 
BTYPE=--)
[   47.258522] pc : add_dma_entry+0x308/0x3f0
[   47.262626] lr : add_dma_entry+0x308/0x3f0
[   47.266730] sp : ffff80002e5c75f0
[   47.270049] x29: ffff80002e5c75f0 x28: 0000002880a908c0 x27: 
ffff80000cc95440
[   47.277216] x26: ffff80000cc94000 x25: ffff80000cc94e20 x24: 
ffff00208e4660c8
[   47.284382] x23: ffff800009d16b40 x22: ffff80000a5b8700 x21: 
1ffff00005cb8eca
[   47.291548] x20: ffff80000caf4c90 x19: ffff0a2009726100 x18: 
0000000000000000
[   47.298713] x17: 70616c7265766f20 x16: 2c54534958454520 x15: 
676e696b63617274
[   47.305879] x14: 1ffff00005cb8df4 x13: 0000000041b58ab3 x12: 
ffff700005cb8e27
[   47.313044] x11: 1ffff00005cb8e26 x10: ffff700005cb8e26 x9 : 
dfff800000000000
[   47.320210] x8 : ffff80002e5c7137 x7 : 0000000000000001 x6 : 
00008ffffa3471da
[   47.327375] x5 : ffff80002e5c7130 x4 : dfff800000000000 x3 : 
ffff8000083a1f48
[   47.334540] x2 : 0000000000000000 x1 : 0000000000000000 x0 : 
ffff00208f7ab200
[   47.341706] Call trace:
[   47.344157]  add_dma_entry+0x308/0x3f0
[   47.347914]  debug_dma_map_sg+0x3ac/0x500
[   47.351931]  __dma_map_sg_attrs+0xac/0x130
[   47.356037]  dma_map_sg_attrs+0x14/0x2c
[   47.359883]  pm8001_task_exec.constprop.0+0x5e0/0x800
[   47.364945]  pm8001_queue_command+0x1c/0x2c
[   47.369136]  sas_queuecommand+0x2c4/0x360
[   47.373153]  scsi_queue_rq+0x810/0x1334
[   47.377000]  blk_mq_dispatch_rq_list+0x340/0xda0
[   47.381625]  __blk_mq_sched_dispatch_requests+0x14c/0x22c
[   47.387034]  blk_mq_sched_dispatch_requests+0x60/0x9c
[   47.392095]  __blk_mq_run_hw_queue+0xc8/0x274
[   47.396460]  blk_mq_run_work_fn+0x30/0x40
[   47.400476]  process_one_work+0x494/0xbac
[   47.404494]  worker_thread+0xac/0x6d0
[   47.408164]  kthread+0x174/0x184
[   47.411401]  ret_from_fork+0x10/0x2[   45.080945] sas: 
sas_scsi_find_task: querying task 0x(____ptrval____)
[   45.087582] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
[   45.093681] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO 
Failure Drive:5000c50085ff5559
[   45.102641] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
[   45.108739] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO 
Failure Drive:5000c50085ff5559
[   45.117694] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
[   45.123792] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO 
Failure Drive:5000c50085ff5559
[   45.132652] pm80xx: rc= -5
[   45.135370] sas: sas_scsi_find_task: task 0x(____ptrval____) result 
code -5 not handled
[   45.143466] sas: task 0x(____ptrval____) is not at LU: I_T recover
[   45.149741] sas: I_T nexus reset for dev 5000c50085ff5559
[   47.183916] sas: I_T 5000c50085ff5559 recovered
[   47.189034] sas: --- Exit sas_scsi_recover_host: busy: 0 failed: 1 
tries: 1
[   47.204168] ------------[ cut here ]------------
[   47.208829] DMA-API: pm80xx 0000:04:00.0: cacheline tracking EEXIST, 
overlapping mappings aren't supported
[   47.218502] WARNING: CPU: 3 PID: 641 at kernel/dma/debug.c:570 
add_dma_entry+0x308/0x3f0
[   47.226607] Modules linked in:
[   47.229678] CPU: 3 PID: 641 Comm: kworker/3:1H Not tainted 
5.17.0-rc1-11918-gd9d909a8c666 #407
[   47.238298] Hardware name: Huawei D06 /D06, BIOS Hisilicon D06 UEFI 
RC0 - V1.16.01 03/15/2019
[   47.246829] Workqueue: kblockd blk_mq_run_work_fn
[   47.251552] pstate: 604000c9 (nZCv daIF +PAN -UAO -TCO -DIT -SSBS 
BTYPE=--)
[   47.258522] pc : add_dma_entry+0x308/0x3f0
[   47.262626] lr : add_dma_entry+0x308/0x3f0
[   47.266730] sp : ffff80002e5c75f0
[   47.270049] x29: ffff80002e5c75f0 x28: 0000002880a908c0 x27: 
ffff80000cc95440
[   47.277216] x26: ffff80000cc94000 x25: ffff80000cc94e20 x24: 
ffff00208e4660c8
[   47.284382] x23: ffff800009d16b40 x22: ffff80000a5b8700 x21: 
1ffff00005cb8eca
[   47.291548] x20: ffff80000caf4c90 x19: ffff0a2009726100 x18: 
0000000000000000
[   47.298713] x17: 70616c7265766f20 x16: 2c54534958454520 x15: 
676e696b63617274
[   47.305879] x14: 1ffff00005cb8df4 x13: 0000000041b58ab3 x12: 
ffff700005cb8e27
[   47.313044] x11: 1ffff00005cb8e26 x10: ffff700005cb8e26 x9 : 
dfff800000000000
[   47.320210] x8 : ffff80002e5c7137 x7 : 0000000000000001 x6 : 
00008ffffa3471da
[   47.327375] x5 : ffff80002e5c7130 x4 : dfff800000000000 x3 : 
ffff8000083a1f48
[   47.334540] x2 : 0000000000000000 x1 : 0000000000000000 x0 : 
ffff00208f7ab200
[   47.341706] Call trace:
[   47.344157]  add_dma_entry+0x308/0x3f0
[   47.347914]  debug_dma_map_sg+0x3ac/0x500
[   47.351931]  __dma_map_sg_attrs+0xac/0x130
[   47.356037]  dma_map_sg_attrs+0x14/0x2c
[   47.359883]  pm8001_task_exec.constprop.0+0x5e0/0x800
[   47.364945]  pm8001_queue_command+0x1c/0x2c
[   47.369136]  sas_queuecommand+0x2c4/0x360
[   47.373153]  scsi_queue_rq+0x810/0x1334
[   47.377000]  blk_mq_dispatch_rq_list+0x340/0xda0
[   47.381625]  __blk_mq_sched_dispatch_requests+0x14c/0x22c
[   47.387034]  blk_mq_sched_dispatch_requests+0x60/0x9c
[   47.392095]  __blk_mq_run_hw_queue+0xc8/0x274
[   47.396460]  blk_mq_run_work_fn+0x30/0x40
[   47.400476]  process_one_work+0x494/0xbac
[   47.404494]  worker_thread+0xac/0x6d0
[   47.408164]  kthread+0x174/0x184
[   47.411401]  ret_from_fork+0x10/0x2

I'll have a look at it. And that is on mainline or mkp-scsi staging, and 
not your patchset.

Thanks,
John

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

* Re: [PATCH v3 27/31] scsi: pm8001: Cleanup pm8001_queue_command()
  2022-02-16 11:50           ` John Garry
@ 2022-02-16 12:05             ` Damien Le Moal
  2022-02-16 12:21               ` John Garry
  0 siblings, 1 reply; 61+ messages in thread
From: Damien Le Moal @ 2022-02-16 12:05 UTC (permalink / raw)
  To: John Garry, linux-scsi, Martin K . Petersen, Xiang Chen, Jason Yan

On 2/16/22 20:50, John Garry wrote:
> On 16/02/2022 11:42, Damien Le Moal wrote:
>>> Hi Damien,
>>>
>>>> patch 30 cleans up pm8001_task_exec(). This patch is for
>>>> pm8001_queue_command(). I preferred to separate to facilitate review.
>>>> But if you insist, I can merge these into a much bigger "code cleanup"
>>>> patch...
>>>>
>>> I don't mind really.
>>>
>>> BTW, on a separate topic, IIRC you said that rmmod hangs for this driver
>>> - if so, did you investigate why?
>> The problem is gone with the fixes. I suspect it was due to the buggy
>> non-data command handling (likely, the flush issued when stopping the
>> device on rmmod).
>>
>> I have not tackled/tried again the QD change failure though.
>>
>> Preparing v4 now. Will check the QD change.
>>
> 
> ok, great.
> 
> JFYI, turning on DMA debug sometimes gives this even after fdisk -l:
> 
> [   45.080945] sas: sas_scsi_find_task: querying task 0x(____ptrval____)
> [   45.087582] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b

What is status 0x3b ? Is this a driver thing or sas thing ? Have not
checked.

> [   45.093681] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO 
> Failure Drive:5000c50085ff5559
> [   45.102641] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
> [   45.108739] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO 
> Failure Drive:5000c50085ff5559
> [   45.117694] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
> [   45.123792] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO 
> Failure Drive:5000c50085ff5559
> [   45.132652] pm80xx: rc= -5

This comes from pm8001_query_task(), pm8001_abort_task() or
pm8001_chip_abort_task()...

> [   45.135370] sas: sas_scsi_find_task: task 0x(____ptrval____) result 
> code -5 not handled

Missing error handling ?

> [   45.143466] sas: task 0x(____ptrval____) is not at LU: I_T recover
> [   45.149741] sas: I_T nexus reset for dev 5000c50085ff5559
> [   47.183916] sas: I_T 5000c50085ff5559 recovered

Weird... Losing your drive ? Bad cable ?

> [   47.189034] sas: --- Exit sas_scsi_recover_host: busy: 0 failed: 1 
> tries: 1
> [   47.204168] ------------[ cut here ]------------
> [   47.208829] DMA-API: pm80xx 0000:04:00.0: cacheline tracking EEXIST, 
> overlapping mappings aren't supported
> [   47.218502] WARNING: CPU: 3 PID: 641 at kernel/dma/debug.c:570 
> add_dma_entry+0x308/0x3f0
> [   47.226607] Modules linked in:
> [   47.229678] CPU: 3 PID: 641 Comm: kworker/3:1H Not tainted 
> 5.17.0-rc1-11918-gd9d909a8c666 #407
> [   47.238298] Hardware name: Huawei D06 /D06, BIOS Hisilicon D06 UEFI 
> RC0 - V1.16.01 03/15/2019
> [   47.246829] Workqueue: kblockd blk_mq_run_work_fn
> [   47.251552] pstate: 604000c9 (nZCv daIF +PAN -UAO -TCO -DIT -SSBS 
> BTYPE=--)
> [   47.258522] pc : add_dma_entry+0x308/0x3f0
> [   47.262626] lr : add_dma_entry+0x308/0x3f0
> [   47.266730] sp : ffff80002e5c75f0
> [   47.270049] x29: ffff80002e5c75f0 x28: 0000002880a908c0 x27: 
> ffff80000cc95440
> [   47.277216] x26: ffff80000cc94000 x25: ffff80000cc94e20 x24: 
> ffff00208e4660c8
> [   47.284382] x23: ffff800009d16b40 x22: ffff80000a5b8700 x21: 
> 1ffff00005cb8eca
> [   47.291548] x20: ffff80000caf4c90 x19: ffff0a2009726100 x18: 
> 0000000000000000
> [   47.298713] x17: 70616c7265766f20 x16: 2c54534958454520 x15: 
> 676e696b63617274
> [   47.305879] x14: 1ffff00005cb8df4 x13: 0000000041b58ab3 x12: 
> ffff700005cb8e27
> [   47.313044] x11: 1ffff00005cb8e26 x10: ffff700005cb8e26 x9 : 
> dfff800000000000
> [   47.320210] x8 : ffff80002e5c7137 x7 : 0000000000000001 x6 : 
> 00008ffffa3471da
> [   47.327375] x5 : ffff80002e5c7130 x4 : dfff800000000000 x3 : 
> ffff8000083a1f48
> [   47.334540] x2 : 0000000000000000 x1 : 0000000000000000 x0 : 
> ffff00208f7ab200
> [   47.341706] Call trace:
> [   47.344157]  add_dma_entry+0x308/0x3f0
> [   47.347914]  debug_dma_map_sg+0x3ac/0x500
> [   47.351931]  __dma_map_sg_attrs+0xac/0x130
> [   47.356037]  dma_map_sg_attrs+0x14/0x2c
> [   47.359883]  pm8001_task_exec.constprop.0+0x5e0/0x800
> [   47.364945]  pm8001_queue_command+0x1c/0x2c
> [   47.369136]  sas_queuecommand+0x2c4/0x360
> [   47.373153]  scsi_queue_rq+0x810/0x1334
> [   47.377000]  blk_mq_dispatch_rq_list+0x340/0xda0
> [   47.381625]  __blk_mq_sched_dispatch_requests+0x14c/0x22c
> [   47.387034]  blk_mq_sched_dispatch_requests+0x60/0x9c
> [   47.392095]  __blk_mq_run_hw_queue+0xc8/0x274
> [   47.396460]  blk_mq_run_work_fn+0x30/0x40
> [   47.400476]  process_one_work+0x494/0xbac
> [   47.404494]  worker_thread+0xac/0x6d0
> [   47.408164]  kthread+0x174/0x184
> [   47.411401]  ret_from_fork+0x10/0x2[   45.080945] sas: 
> sas_scsi_find_task: querying task 0x(____ptrval____)
> [   45.087582] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
> [   45.093681] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO 
> Failure Drive:5000c50085ff5559
> [   45.102641] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
> [   45.108739] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO 
> Failure Drive:5000c50085ff5559
> [   45.117694] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
> [   45.123792] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO 
> Failure Drive:5000c50085ff5559
> [   45.132652] pm80xx: rc= -5
> [   45.135370] sas: sas_scsi_find_task: task 0x(____ptrval____) result 
> code -5 not handled
> [   45.143466] sas: task 0x(____ptrval____) is not at LU: I_T recover
> [   45.149741] sas: I_T nexus reset for dev 5000c50085ff5559
> [   47.183916] sas: I_T 5000c50085ff5559 recovered
> [   47.189034] sas: --- Exit sas_scsi_recover_host: busy: 0 failed: 1 
> tries: 1
> [   47.204168] ------------[ cut here ]------------
> [   47.208829] DMA-API: pm80xx 0000:04:00.0: cacheline tracking EEXIST, 
> overlapping mappings aren't supported
> [   47.218502] WARNING: CPU: 3 PID: 641 at kernel/dma/debug.c:570 
> add_dma_entry+0x308/0x3f0
> [   47.226607] Modules linked in:
> [   47.229678] CPU: 3 PID: 641 Comm: kworker/3:1H Not tainted 
> 5.17.0-rc1-11918-gd9d909a8c666 #407
> [   47.238298] Hardware name: Huawei D06 /D06, BIOS Hisilicon D06 UEFI 
> RC0 - V1.16.01 03/15/2019
> [   47.246829] Workqueue: kblockd blk_mq_run_work_fn
> [   47.251552] pstate: 604000c9 (nZCv daIF +PAN -UAO -TCO -DIT -SSBS 
> BTYPE=--)
> [   47.258522] pc : add_dma_entry+0x308/0x3f0
> [   47.262626] lr : add_dma_entry+0x308/0x3f0
> [   47.266730] sp : ffff80002e5c75f0
> [   47.270049] x29: ffff80002e5c75f0 x28: 0000002880a908c0 x27: 
> ffff80000cc95440
> [   47.277216] x26: ffff80000cc94000 x25: ffff80000cc94e20 x24: 
> ffff00208e4660c8
> [   47.284382] x23: ffff800009d16b40 x22: ffff80000a5b8700 x21: 
> 1ffff00005cb8eca
> [   47.291548] x20: ffff80000caf4c90 x19: ffff0a2009726100 x18: 
> 0000000000000000
> [   47.298713] x17: 70616c7265766f20 x16: 2c54534958454520 x15: 
> 676e696b63617274
> [   47.305879] x14: 1ffff00005cb8df4 x13: 0000000041b58ab3 x12: 
> ffff700005cb8e27
> [   47.313044] x11: 1ffff00005cb8e26 x10: ffff700005cb8e26 x9 : 
> dfff800000000000
> [   47.320210] x8 : ffff80002e5c7137 x7 : 0000000000000001 x6 : 
> 00008ffffa3471da
> [   47.327375] x5 : ffff80002e5c7130 x4 : dfff800000000000 x3 : 
> ffff8000083a1f48
> [   47.334540] x2 : 0000000000000000 x1 : 0000000000000000 x0 : 
> ffff00208f7ab200
> [   47.341706] Call trace:
> [   47.344157]  add_dma_entry+0x308/0x3f0
> [   47.347914]  debug_dma_map_sg+0x3ac/0x500
> [   47.351931]  __dma_map_sg_attrs+0xac/0x130
> [   47.356037]  dma_map_sg_attrs+0x14/0x2c
> [   47.359883]  pm8001_task_exec.constprop.0+0x5e0/0x800
> [   47.364945]  pm8001_queue_command+0x1c/0x2c
> [   47.369136]  sas_queuecommand+0x2c4/0x360
> [   47.373153]  scsi_queue_rq+0x810/0x1334
> [   47.377000]  blk_mq_dispatch_rq_list+0x340/0xda0
> [   47.381625]  __blk_mq_sched_dispatch_requests+0x14c/0x22c
> [   47.387034]  blk_mq_sched_dispatch_requests+0x60/0x9c
> [   47.392095]  __blk_mq_run_hw_queue+0xc8/0x274
> [   47.396460]  blk_mq_run_work_fn+0x30/0x40
> [   47.400476]  process_one_work+0x494/0xbac
> [   47.404494]  worker_thread+0xac/0x6d0
> [   47.408164]  kthread+0x174/0x184
> [   47.411401]  ret_from_fork+0x10/0x2
> 
> I'll have a look at it. And that is on mainline or mkp-scsi staging, and 
> not your patchset.

Are you saying that my patches suppresses the above ? This is submission
path and the dma code seems to complain about alignment... So bad buffer
addresses ?

> 
> Thanks,
> John


-- 
Damien Le Moal
Western Digital Research

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

* Re: [PATCH v3 27/31] scsi: pm8001: Cleanup pm8001_queue_command()
  2022-02-16 12:05             ` Damien Le Moal
@ 2022-02-16 12:21               ` John Garry
  2022-02-17  0:12                 ` Damien Le Moal
  0 siblings, 1 reply; 61+ messages in thread
From: John Garry @ 2022-02-16 12:21 UTC (permalink / raw)
  To: Damien Le Moal, linux-scsi, Martin K . Petersen, Xiang Chen, Jason Yan


>> JFYI, turning on DMA debug sometimes gives this even after fdisk -l:
>>
>> [   45.080945] sas: sas_scsi_find_task: querying task 0x(____ptrval____)
>> [   45.087582] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
> 
> What is status 0x3b ? Is this a driver thing or sas thing ? Have not
> checked.

This is a driver thing. I'd need the manual to check.

> 
>> [   45.093681] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO
>> Failure Drive:5000c50085ff5559
>> [   45.102641] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
>> [   45.108739] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO
>> Failure Drive:5000c50085ff5559
>> [   45.117694] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
>> [   45.123792] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO
>> Failure Drive:5000c50085ff5559
>> [   45.132652] pm80xx: rc= -5
> 
> This comes from pm8001_query_task(), pm8001_abort_task() or
> pm8001_chip_abort_task()...
> 
>> [   45.135370] sas: sas_scsi_find_task: task 0x(____ptrval____) result
>> code -5 not handled
> 
> Missing error handling ?

This is something I added. So the driver does not return a valid TMF 
code - it returns -5, which I think comes from pm8001_query_task() -> 
pm8001_exec_internal_tmf_task(). And sas_scsi_find_task() does not 
recognise -5 and just assumes that the TMF failed, so ...

> 
>> [   45.143466] sas: task 0x(____ptrval____) is not at LU: I_T recover
>> [   45.149741] sas: I_T nexus reset for dev 5000c50085ff5559
>> [   47.183916] sas: I_T 5000c50085ff5559 recovered
> 
> Weird... Losing your drive ? Bad cable ?

.. we escalate the error handling and call sas_eh_handle_sas_errors() -> 
sas_recover_I_T(), which resets the PHY - see pm8001_I_T_nexus_reset().

> 
>> [   47.189034] sas: --- Exit sas_scsi_recover_host: busy: 0 failed: 1
>> tries: 1
>> [   47.204168] ------------[ cut here ]------------
>> [   47.208829] DMA-API: pm80xx 0000:04:00.0: cacheline tracking EEXIST,
>> overlapping mappings aren't supported
>> [   47.218502] WARNING: CPU: 3 PID: 641 at kernel/dma/debug.c:570
>> add_dma_entry+0x308/0x3f0
>> [   47.226607] Modules linked in:
>> [   47.229678] CPU: 3 PID: 641 Comm: kworker/3:1H Not tainted
>> 5.17.0-rc1-11918-gd9d909a8c666 #407
>> [   47.238298] Hardware name: Huawei D06 /D06, BIOS Hisilicon D06 UEFI
>> RC0 - V1.16.01 03/15/2019
>> [   47.246829] Workqueue: kblockd blk_mq_run_work_fn
>> [   47.251552] pstate: 604000c9 (nZCv daIF +PAN -UAO -TCO -DIT -SSBS
>> BTYPE=--)
>> [   47.258522] pc : add_dma_entry+0x308/0x3f0
>> [   47.262626] lr : add_dma_entry+0x308/0x3f0
>> [   47.266730] sp : ffff80002e5c75f0
>> [   47.270049] x29: ffff80002e5c75f0 x28: 0000002880a908c0 x27:
>> ffff80000cc95440
>> [   47.277216] x26: ffff80000cc94000 x25: ffff80000cc94e20 x24:
>> ffff00208e4660c8
>> [   47.284382] x23: ffff800009d16b40 x22: ffff80000a5b8700 x21:
>> 1ffff00005cb8eca
>> [   47.291548] x20: ffff80000caf4c90 x19: ffff0a2009726100 x18:
>> 0000000000000000
>> [   47.298713] x17: 70616c7265766f20 x16: 2c54534958454520 x15:
>> 676e696b63617274
>> [   47.305879] x14: 1ffff00005cb8df4 x13: 0000000041b58ab3 x12:
>> ffff700005cb8e27
>> [   47.313044] x11: 1ffff00005cb8e26 x10: ffff700005cb8e26 x9 :
>> dfff800000000000
>> [   47.320210] x8 : ffff80002e5c7137 x7 : 0000000000000001 x6 :
>> 00008ffffa3471da
>> [   47.327375] x5 : ffff80002e5c7130 x4 : dfff800000000000 x3 :
>> ffff8000083a1f48
>> [   47.334540] x2 : 0000000000000000 x1 : 0000000000000000 x0 :
>> ffff00208f7ab200
>> [   47.341706] Call trace:
>> [   47.344157]  add_dma_entry+0x308/0x3f0
>> [   47.347914]  debug_dma_map_sg+0x3ac/0x500
>> [   47.351931]  __dma_map_sg_attrs+0xac/0x130
>> [   47.356037]  dma_map_sg_attrs+0x14/0x2c
>> [   47.359883]  pm8001_task_exec.constprop.0+0x5e0/0x800
>> [   47.364945]  pm8001_queue_command+0x1c/0x2c
>> [   47.369136]  sas_queuecommand+0x2c4/0x360
>> [   47.373153]  scsi_queue_rq+0x810/0x1334
>> [   47.377000]  blk_mq_dispatch_rq_list+0x340/0xda0
>> [   47.381625]  __blk_mq_sched_dispatch_requests+0x14c/0x22c
>> [   47.387034]  blk_mq_sched_dispatch_requests+0x60/0x9c
>> [   47.392095]  __blk_mq_run_hw_queue+0xc8/0x274
>> [   47.396460]  blk_mq_run_work_fn+0x30/0x40
>> [   47.400476]  process_one_work+0x494/0xbac
>> [   47.404494]  worker_thread+0xac/0x6d0
>> [   47.408164]  kthread+0x174/0x184
>> [   47.411401]  ret_from_fork+0x10/0x2[   45.080945] sas:
>> sas_scsi_find_task: querying task 0x(____ptrval____)
>> [   45.087582] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
>> [   45.093681] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO
>> Failure Drive:5000c50085ff5559
>> [   45.102641] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
>> [   45.108739] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO
>> Failure Drive:5000c50085ff5559
>> [   45.117694] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
>> [   45.123792] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO
>> Failure Drive:5000c50085ff5559
>> [   45.132652] pm80xx: rc= -5
>> [   45.135370] sas: sas_scsi_find_task: task 0x(____ptrval____) result
>> code -5 not handled
>> [   45.143466] sas: task 0x(____ptrval____) is not at LU: I_T recover
>> [   45.149741] sas: I_T nexus reset for dev 5000c50085ff5559
>> [   47.183916] sas: I_T 5000c50085ff5559 recovered
>> [   47.189034] sas: --- Exit sas_scsi_recover_host: busy: 0 failed: 1
>> tries: 1
>> [   47.204168] ------------[ cut here ]------------
>> [   47.208829] DMA-API: pm80xx 0000:04:00.0: cacheline tracking EEXIST,
>> overlapping mappings aren't supported
>> [   47.218502] WARNING: CPU: 3 PID: 641 at kernel/dma/debug.c:570
>> add_dma_entry+0x308/0x3f0
>> [   47.226607] Modules linked in:
>> [   47.229678] CPU: 3 PID: 641 Comm: kworker/3:1H Not tainted
>> 5.17.0-rc1-11918-gd9d909a8c666 #407
>> [   47.238298] Hardware name: Huawei D06 /D06, BIOS Hisilicon D06 UEFI
>> RC0 - V1.16.01 03/15/2019
>> [   47.246829] Workqueue: kblockd blk_mq_run_work_fn
>> [   47.251552] pstate: 604000c9 (nZCv daIF +PAN -UAO -TCO -DIT -SSBS
>> BTYPE=--)
>> [   47.258522] pc : add_dma_entry+0x308/0x3f0
>> [   47.262626] lr : add_dma_entry+0x308/0x3f0
>> [   47.266730] sp : ffff80002e5c75f0
>> [   47.270049] x29: ffff80002e5c75f0 x28: 0000002880a908c0 x27:
>> ffff80000cc95440
>> [   47.277216] x26: ffff80000cc94000 x25: ffff80000cc94e20 x24:
>> ffff00208e4660c8
>> [   47.284382] x23: ffff800009d16b40 x22: ffff80000a5b8700 x21:
>> 1ffff00005cb8eca
>> [   47.291548] x20: ffff80000caf4c90 x19: ffff0a2009726100 x18:
>> 0000000000000000
>> [   47.298713] x17: 70616c7265766f20 x16: 2c54534958454520 x15:
>> 676e696b63617274
>> [   47.305879] x14: 1ffff00005cb8df4 x13: 0000000041b58ab3 x12:
>> ffff700005cb8e27
>> [   47.313044] x11: 1ffff00005cb8e26 x10: ffff700005cb8e26 x9 :
>> dfff800000000000
>> [   47.320210] x8 : ffff80002e5c7137 x7 : 0000000000000001 x6 :
>> 00008ffffa3471da
>> [   47.327375] x5 : ffff80002e5c7130 x4 : dfff800000000000 x3 :
>> ffff8000083a1f48
>> [   47.334540] x2 : 0000000000000000 x1 : 0000000000000000 x0 :
>> ffff00208f7ab200
>> [   47.341706] Call trace:
>> [   47.344157]  add_dma_entry+0x308/0x3f0
>> [   47.347914]  debug_dma_map_sg+0x3ac/0x500
>> [   47.351931]  __dma_map_sg_attrs+0xac/0x130
>> [   47.356037]  dma_map_sg_attrs+0x14/0x2c
>> [   47.359883]  pm8001_task_exec.constprop.0+0x5e0/0x800
>> [   47.364945]  pm8001_queue_command+0x1c/0x2c
>> [   47.369136]  sas_queuecommand+0x2c4/0x360
>> [   47.373153]  scsi_queue_rq+0x810/0x1334
>> [   47.377000]  blk_mq_dispatch_rq_list+0x340/0xda0
>> [   47.381625]  __blk_mq_sched_dispatch_requests+0x14c/0x22c
>> [   47.387034]  blk_mq_sched_dispatch_requests+0x60/0x9c
>> [   47.392095]  __blk_mq_run_hw_queue+0xc8/0x274
>> [   47.396460]  blk_mq_run_work_fn+0x30/0x40
>> [   47.400476]  process_one_work+0x494/0xbac
>> [   47.404494]  worker_thread+0xac/0x6d0
>> [   47.408164]  kthread+0x174/0x184
>> [   47.411401]  ret_from_fork+0x10/0x2
>>
>> I'll have a look at it. And that is on mainline or mkp-scsi staging, and
>> not your patchset.
> 
> Are you saying that my patches suppresses the above ? This is submission
> path and the dma code seems to complain about alignment... So bad buffer
> addresses ?

Your series does not suppress it. It doesn't occur often, so I need to 
check more.

I think the issue is that we call dma_map_sg() twice, i.e. ccb never 
unmapped.

Thanks,
John


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

* Re: [PATCH v3 27/31] scsi: pm8001: Cleanup pm8001_queue_command()
  2022-02-16 12:21               ` John Garry
@ 2022-02-17  0:12                 ` Damien Le Moal
  2022-02-17  9:23                   ` John Garry
  0 siblings, 1 reply; 61+ messages in thread
From: Damien Le Moal @ 2022-02-17  0:12 UTC (permalink / raw)
  To: John Garry, linux-scsi, Martin K . Petersen, Xiang Chen, Jason Yan

On 2/16/22 21:21, John Garry wrote:
> 
>>> JFYI, turning on DMA debug sometimes gives this even after fdisk -l:
>>>
>>> [   45.080945] sas: sas_scsi_find_task: querying task 0x(____ptrval____)
>>> [   45.087582] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
>>
>> What is status 0x3b ? Is this a driver thing or sas thing ? Have not
>> checked.
> 
> This is a driver thing. I'd need the manual to check.
> 
>>
>>> [   45.093681] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO
>>> Failure Drive:5000c50085ff5559
>>> [   45.102641] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
>>> [   45.108739] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO
>>> Failure Drive:5000c50085ff5559
>>> [   45.117694] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
>>> [   45.123792] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO
>>> Failure Drive:5000c50085ff5559
>>> [   45.132652] pm80xx: rc= -5
>>
>> This comes from pm8001_query_task(), pm8001_abort_task() or
>> pm8001_chip_abort_task()...
>>
>>> [   45.135370] sas: sas_scsi_find_task: task 0x(____ptrval____) result
>>> code -5 not handled
>>
>> Missing error handling ?
> 
> This is something I added. So the driver does not return a valid TMF 
> code - it returns -5, which I think comes from pm8001_query_task() -> 
> pm8001_exec_internal_tmf_task(). And sas_scsi_find_task() does not 
> recognise -5 and just assumes that the TMF failed, so ...
> 
>>
>>> [   45.143466] sas: task 0x(____ptrval____) is not at LU: I_T recover
>>> [   45.149741] sas: I_T nexus reset for dev 5000c50085ff5559
>>> [   47.183916] sas: I_T 5000c50085ff5559 recovered
>>
>> Weird... Losing your drive ? Bad cable ?
> 
> .. we escalate the error handling and call sas_eh_handle_sas_errors() -> 
> sas_recover_I_T(), which resets the PHY - see pm8001_I_T_nexus_reset().
> 
>>
>>> [   47.189034] sas: --- Exit sas_scsi_recover_host: busy: 0 failed: 1
>>> tries: 1
>>> [   47.204168] ------------[ cut here ]------------
>>> [   47.208829] DMA-API: pm80xx 0000:04:00.0: cacheline tracking EEXIST,
>>> overlapping mappings aren't supported
>>> [   47.218502] WARNING: CPU: 3 PID: 641 at kernel/dma/debug.c:570
>>> add_dma_entry+0x308/0x3f0
>>> [   47.226607] Modules linked in:
>>> [   47.229678] CPU: 3 PID: 641 Comm: kworker/3:1H Not tainted
>>> 5.17.0-rc1-11918-gd9d909a8c666 #407
>>> [   47.238298] Hardware name: Huawei D06 /D06, BIOS Hisilicon D06 UEFI
>>> RC0 - V1.16.01 03/15/2019
>>> [   47.246829] Workqueue: kblockd blk_mq_run_work_fn
>>> [   47.251552] pstate: 604000c9 (nZCv daIF +PAN -UAO -TCO -DIT -SSBS
>>> BTYPE=--)
>>> [   47.258522] pc : add_dma_entry+0x308/0x3f0
>>> [   47.262626] lr : add_dma_entry+0x308/0x3f0
>>> [   47.266730] sp : ffff80002e5c75f0
>>> [   47.270049] x29: ffff80002e5c75f0 x28: 0000002880a908c0 x27:
>>> ffff80000cc95440
>>> [   47.277216] x26: ffff80000cc94000 x25: ffff80000cc94e20 x24:
>>> ffff00208e4660c8
>>> [   47.284382] x23: ffff800009d16b40 x22: ffff80000a5b8700 x21:
>>> 1ffff00005cb8eca
>>> [   47.291548] x20: ffff80000caf4c90 x19: ffff0a2009726100 x18:
>>> 0000000000000000
>>> [   47.298713] x17: 70616c7265766f20 x16: 2c54534958454520 x15:
>>> 676e696b63617274
>>> [   47.305879] x14: 1ffff00005cb8df4 x13: 0000000041b58ab3 x12:
>>> ffff700005cb8e27
>>> [   47.313044] x11: 1ffff00005cb8e26 x10: ffff700005cb8e26 x9 :
>>> dfff800000000000
>>> [   47.320210] x8 : ffff80002e5c7137 x7 : 0000000000000001 x6 :
>>> 00008ffffa3471da
>>> [   47.327375] x5 : ffff80002e5c7130 x4 : dfff800000000000 x3 :
>>> ffff8000083a1f48
>>> [   47.334540] x2 : 0000000000000000 x1 : 0000000000000000 x0 :
>>> ffff00208f7ab200
>>> [   47.341706] Call trace:
>>> [   47.344157]  add_dma_entry+0x308/0x3f0
>>> [   47.347914]  debug_dma_map_sg+0x3ac/0x500
>>> [   47.351931]  __dma_map_sg_attrs+0xac/0x130
>>> [   47.356037]  dma_map_sg_attrs+0x14/0x2c
>>> [   47.359883]  pm8001_task_exec.constprop.0+0x5e0/0x800
>>> [   47.364945]  pm8001_queue_command+0x1c/0x2c
>>> [   47.369136]  sas_queuecommand+0x2c4/0x360
>>> [   47.373153]  scsi_queue_rq+0x810/0x1334
>>> [   47.377000]  blk_mq_dispatch_rq_list+0x340/0xda0
>>> [   47.381625]  __blk_mq_sched_dispatch_requests+0x14c/0x22c
>>> [   47.387034]  blk_mq_sched_dispatch_requests+0x60/0x9c
>>> [   47.392095]  __blk_mq_run_hw_queue+0xc8/0x274
>>> [   47.396460]  blk_mq_run_work_fn+0x30/0x40
>>> [   47.400476]  process_one_work+0x494/0xbac
>>> [   47.404494]  worker_thread+0xac/0x6d0
>>> [   47.408164]  kthread+0x174/0x184
>>> [   47.411401]  ret_from_fork+0x10/0x2[   45.080945] sas:
>>> sas_scsi_find_task: querying task 0x(____ptrval____)
>>> [   45.087582] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
>>> [   45.093681] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO
>>> Failure Drive:5000c50085ff5559
>>> [   45.102641] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
>>> [   45.108739] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO
>>> Failure Drive:5000c50085ff5559
>>> [   45.117694] pm80xx0:: mpi_ssp_completion  1936:sas IO status 0x3b
>>> [   45.123792] pm80xx0:: mpi_ssp_completion  1947:SAS Address of IO
>>> Failure Drive:5000c50085ff5559
>>> [   45.132652] pm80xx: rc= -5
>>> [   45.135370] sas: sas_scsi_find_task: task 0x(____ptrval____) result
>>> code -5 not handled
>>> [   45.143466] sas: task 0x(____ptrval____) is not at LU: I_T recover
>>> [   45.149741] sas: I_T nexus reset for dev 5000c50085ff5559
>>> [   47.183916] sas: I_T 5000c50085ff5559 recovered
>>> [   47.189034] sas: --- Exit sas_scsi_recover_host: busy: 0 failed: 1
>>> tries: 1
>>> [   47.204168] ------------[ cut here ]------------
>>> [   47.208829] DMA-API: pm80xx 0000:04:00.0: cacheline tracking EEXIST,
>>> overlapping mappings aren't supported
>>> [   47.218502] WARNING: CPU: 3 PID: 641 at kernel/dma/debug.c:570
>>> add_dma_entry+0x308/0x3f0
>>> [   47.226607] Modules linked in:
>>> [   47.229678] CPU: 3 PID: 641 Comm: kworker/3:1H Not tainted
>>> 5.17.0-rc1-11918-gd9d909a8c666 #407
>>> [   47.238298] Hardware name: Huawei D06 /D06, BIOS Hisilicon D06 UEFI
>>> RC0 - V1.16.01 03/15/2019
>>> [   47.246829] Workqueue: kblockd blk_mq_run_work_fn
>>> [   47.251552] pstate: 604000c9 (nZCv daIF +PAN -UAO -TCO -DIT -SSBS
>>> BTYPE=--)
>>> [   47.258522] pc : add_dma_entry+0x308/0x3f0
>>> [   47.262626] lr : add_dma_entry+0x308/0x3f0
>>> [   47.266730] sp : ffff80002e5c75f0
>>> [   47.270049] x29: ffff80002e5c75f0 x28: 0000002880a908c0 x27:
>>> ffff80000cc95440
>>> [   47.277216] x26: ffff80000cc94000 x25: ffff80000cc94e20 x24:
>>> ffff00208e4660c8
>>> [   47.284382] x23: ffff800009d16b40 x22: ffff80000a5b8700 x21:
>>> 1ffff00005cb8eca
>>> [   47.291548] x20: ffff80000caf4c90 x19: ffff0a2009726100 x18:
>>> 0000000000000000
>>> [   47.298713] x17: 70616c7265766f20 x16: 2c54534958454520 x15:
>>> 676e696b63617274
>>> [   47.305879] x14: 1ffff00005cb8df4 x13: 0000000041b58ab3 x12:
>>> ffff700005cb8e27
>>> [   47.313044] x11: 1ffff00005cb8e26 x10: ffff700005cb8e26 x9 :
>>> dfff800000000000
>>> [   47.320210] x8 : ffff80002e5c7137 x7 : 0000000000000001 x6 :
>>> 00008ffffa3471da
>>> [   47.327375] x5 : ffff80002e5c7130 x4 : dfff800000000000 x3 :
>>> ffff8000083a1f48
>>> [   47.334540] x2 : 0000000000000000 x1 : 0000000000000000 x0 :
>>> ffff00208f7ab200
>>> [   47.341706] Call trace:
>>> [   47.344157]  add_dma_entry+0x308/0x3f0
>>> [   47.347914]  debug_dma_map_sg+0x3ac/0x500
>>> [   47.351931]  __dma_map_sg_attrs+0xac/0x130
>>> [   47.356037]  dma_map_sg_attrs+0x14/0x2c
>>> [   47.359883]  pm8001_task_exec.constprop.0+0x5e0/0x800
>>> [   47.364945]  pm8001_queue_command+0x1c/0x2c
>>> [   47.369136]  sas_queuecommand+0x2c4/0x360
>>> [   47.373153]  scsi_queue_rq+0x810/0x1334
>>> [   47.377000]  blk_mq_dispatch_rq_list+0x340/0xda0
>>> [   47.381625]  __blk_mq_sched_dispatch_requests+0x14c/0x22c
>>> [   47.387034]  blk_mq_sched_dispatch_requests+0x60/0x9c
>>> [   47.392095]  __blk_mq_run_hw_queue+0xc8/0x274
>>> [   47.396460]  blk_mq_run_work_fn+0x30/0x40
>>> [   47.400476]  process_one_work+0x494/0xbac
>>> [   47.404494]  worker_thread+0xac/0x6d0
>>> [   47.408164]  kthread+0x174/0x184
>>> [   47.411401]  ret_from_fork+0x10/0x2
>>>
>>> I'll have a look at it. And that is on mainline or mkp-scsi staging, and
>>> not your patchset.
>>
>> Are you saying that my patches suppresses the above ? This is submission
>> path and the dma code seems to complain about alignment... So bad buffer
>> addresses ?
> 
> Your series does not suppress it. It doesn't occur often, so I need to 
> check more.
> 
> I think the issue is that we call dma_map_sg() twice, i.e. ccb never 
> unmapped.

That would be a big issue indeed. We could add a flag to CCBs to track
the buf_prd DMA mapping state and BUG_ON() when ccb free function is
called with the buffer still mapped. That should allow catching this
infrequent problem ?

> 
> Thanks,
> John
> 


-- 
Damien Le Moal
Western Digital Research

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

* Re: [PATCH v3 27/31] scsi: pm8001: Cleanup pm8001_queue_command()
  2022-02-17  0:12                 ` Damien Le Moal
@ 2022-02-17  9:23                   ` John Garry
  2022-02-17 10:47                     ` Damien Le Moal
  2022-02-17 11:47                     ` Damien Le Moal
  0 siblings, 2 replies; 61+ messages in thread
From: John Garry @ 2022-02-17  9:23 UTC (permalink / raw)
  To: Damien Le Moal, linux-scsi, Martin K . Petersen, Xiang Chen, Jason Yan

On 17/02/2022 00:12, Damien Le Moal wrote:
>>>> I'll have a look at it. And that is on mainline or mkp-scsi staging, and
>>>> not your patchset.
>>> Are you saying that my patches suppresses the above ? This is submission
>>> path and the dma code seems to complain about alignment... So bad buffer
>>> addresses ?
>> Your series does not suppress it. It doesn't occur often, so I need to
>> check more.
>>
>> I think the issue is that we call dma_map_sg() twice, i.e. ccb never
>> unmapped.
> That would be a big issue indeed. We could add a flag to CCBs to track
> the buf_prd DMA mapping state and BUG_ON() when ccb free function is
> called with the buffer still mapped. That should allow catching this
> infrequent problem ?
> 

I figured out what is happening here and it does not help solve the 
mystery of my hang.

Here's the steps:
a. scsi_cmnd times out
b. scsi error handling kicks in
c. libsas attempts to abort the task, which fails
d. libsas then tries IT nexus reset, which passes
  - libsas assumes the scsi_cmnd has completed with failure
e. error handling concludes
f. scsi midlayer then retries the same scsi_cmnd
g. since we did not "free" associated ccb earlier or dma unmap at d., 
the dma unmap on the same scsi_cmnd causes the warn

So the LLD should really free resources and dma unmap at point IT nexus 
reset completes, but it doesn't. I think in certain conditions dma map 
should not be done twice.

Anyway, that can be fixed, but I still have the hang :(

Thanks,
John

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

* Re: [PATCH v3 27/31] scsi: pm8001: Cleanup pm8001_queue_command()
  2022-02-17  9:23                   ` John Garry
@ 2022-02-17 10:47                     ` Damien Le Moal
  2022-02-17 12:49                       ` John Garry
  2022-02-17 11:47                     ` Damien Le Moal
  1 sibling, 1 reply; 61+ messages in thread
From: Damien Le Moal @ 2022-02-17 10:47 UTC (permalink / raw)
  To: John Garry, linux-scsi, Martin K . Petersen, Xiang Chen, Jason Yan

On 2/17/22 18:23, John Garry wrote:
> On 17/02/2022 00:12, Damien Le Moal wrote:
>>>>> I'll have a look at it. And that is on mainline or mkp-scsi staging, and
>>>>> not your patchset.
>>>> Are you saying that my patches suppresses the above ? This is submission
>>>> path and the dma code seems to complain about alignment... So bad buffer
>>>> addresses ?
>>> Your series does not suppress it. It doesn't occur often, so I need to
>>> check more.
>>>
>>> I think the issue is that we call dma_map_sg() twice, i.e. ccb never
>>> unmapped.
>> That would be a big issue indeed. We could add a flag to CCBs to track
>> the buf_prd DMA mapping state and BUG_ON() when ccb free function is
>> called with the buffer still mapped. That should allow catching this
>> infrequent problem ?
>>
> 
> I figured out what is happening here and it does not help solve the 
> mystery of my hang.
> 
> Here's the steps:
> a. scsi_cmnd times out
> b. scsi error handling kicks in
> c. libsas attempts to abort the task, which fails
> d. libsas then tries IT nexus reset, which passes
>   - libsas assumes the scsi_cmnd has completed with failure
> e. error handling concludes
> f. scsi midlayer then retries the same scsi_cmnd
> g. since we did not "free" associated ccb earlier or dma unmap at d., 
> the dma unmap on the same scsi_cmnd causes the warn
> 
> So the LLD should really free resources and dma unmap at point IT nexus 
> reset completes, but it doesn't. I think in certain conditions dma map 
> should not be done twice.
> 
> Anyway, that can be fixed, but I still have the hang :(

I guess (a) (cmd timeout) is only the symptom of the hang ? That is, the
hang is causing the timeout ?
It may be good to turn on scsi trace to see if the command was only
partially done, or not at all, or if it is a non-data command.

And speaking of errors, I am currently testing v4 of my series and
noticed some weird things in the error handling. E.g., with one of the
test executing a report zones command with an LBA out of range, I see this:

[23962.027105] pm80xx0:: mpi_sata_event  2788:SATA EVENT 0x23
[23962.036099] pm80xx0:: pm80xx_send_read_log  1863:Executing read log end

All good: this is IO_XFER_ERROR_ABORTED_NCQ_MODE. And the read log is to
get the drive queue out of error state.

[23962.046101] pm80xx0:: mpi_sata_event  2788:SATA EVENT 0x26

This is IO_XFER_ERROR_UNEXPECTED_PHASE. No clue what this is doing.

[23962.054947] pm80xx0:: mpi_sata_event  2805:task or dev null

Why ?

[23962.063865] pm80xx0:: pm80xx_send_abort_all  1796:Executing abort
task end

All queued commands are aborted when the read log completes. Again, per
ATA NCQ specs, all good. After that, normal (some useless) messages.

[23962.063964] pm80xx0:: mpi_sata_completion  2395:IO failed device_id
16388 status 0x1 tag 1
[23962.084587] pm80xx0:: mpi_sata_completion  2430:SAS Address of IO
Failure Drive:50010860002f5657
[23962.095526] sas: sas_ata_task_done: SAS error 0x8d
[23962.139470] sas: Enter sas_scsi_recover_host busy: 1 failed: 1
[23962.147897] ata24.00: exception Emask 0x0 SAct 0x800 SErr 0x0 action 0x0
[23962.156253] ata24.00: failed command: RECEIVE FPDMA QUEUED
[23962.163307] ata24.00: cmd 65/01:00:00:00:0c/00:02:23:01:00/40 tag 11
ncq dma 512 in
[23962.163307]          res 43/10:00:00:00:00/00:00:00:00:00/00 Emask
0x480 (invalid argument) <F>

Good here, correct error...

[23962.182879] ata24.00: status: { DRDY SENSE ERR }
[23962.189100] ata24.00: error: { IDNF }

... but I need to look at this in libata. Getting the same with AHCI.

[23962.215456] ata24.00: configured for UDMA/133
[23962.221469] ata24: EH complete
[23962.226056] sas: --- Exit sas_scsi_recover_host: busy: 0 failed: 1
tries: 1

That event 0x26 and the "task or dev null" are obscure. No clue, but
they look wrong.

Overall, this driver is by default way too verbose I think. I would
prefer to reduce the above to something like:

[23962.095526] sas: sas_ata_task_done: SAS error 0x8d
[23962.139470] sas: Enter sas_scsi_recover_host busy: 1 failed: 1
[23962.147897] ata24.00: exception Emask 0x0 SAct 0x800 SErr 0x0 action 0x0
[23962.156253] ata24.00: failed command: RECEIVE FPDMA QUEUED
[23962.163307] ata24.00: cmd 65/01:00:00:00:0c/00:02:23:01:00/40 tag 11
ncq dma 512 in
[23962.163307]          res 43/10:00:00:00:00/00:00:00:00:00/00 Emask
0x480 (invalid argument) <F>
[23962.182879] ata24.00: status: { DRDY SENSE ERR }
[23962.189100] ata24.00: error: { IDNF }
[23962.215456] ata24.00: configured for UDMA/133
[23962.221469] ata24: EH complete
[23962.226056] sas: --- Exit sas_scsi_recover_host: busy: 0 failed: 1
tries: 1

That is, by default, remove most FAIL messages, changing them to DEV
level. The same test with a SAS drive is totally silent, as it should
be, since the command error is not a fatal one.

But not touching this for now. I first want the series to be queued.




-- 
Damien Le Moal
Western Digital Research

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

* Re: [PATCH v3 27/31] scsi: pm8001: Cleanup pm8001_queue_command()
  2022-02-17  9:23                   ` John Garry
  2022-02-17 10:47                     ` Damien Le Moal
@ 2022-02-17 11:47                     ` Damien Le Moal
  1 sibling, 0 replies; 61+ messages in thread
From: Damien Le Moal @ 2022-02-17 11:47 UTC (permalink / raw)
  To: John Garry, linux-scsi, Martin K . Petersen, Xiang Chen, Jason Yan

On 2/17/22 18:23, John Garry wrote:
> On 17/02/2022 00:12, Damien Le Moal wrote:
>>>>> I'll have a look at it. And that is on mainline or mkp-scsi staging, and
>>>>> not your patchset.
>>>> Are you saying that my patches suppresses the above ? This is submission
>>>> path and the dma code seems to complain about alignment... So bad buffer
>>>> addresses ?
>>> Your series does not suppress it. It doesn't occur often, so I need to
>>> check more.
>>>
>>> I think the issue is that we call dma_map_sg() twice, i.e. ccb never
>>> unmapped.
>> That would be a big issue indeed. We could add a flag to CCBs to track
>> the buf_prd DMA mapping state and BUG_ON() when ccb free function is
>> called with the buffer still mapped. That should allow catching this
>> infrequent problem ?
>>
> 
> I figured out what is happening here and it does not help solve the 
> mystery of my hang.
> 
> Here's the steps:
> a. scsi_cmnd times out
> b. scsi error handling kicks in
> c. libsas attempts to abort the task, which fails
> d. libsas then tries IT nexus reset, which passes
>   - libsas assumes the scsi_cmnd has completed with failure
> e. error handling concludes
> f. scsi midlayer then retries the same scsi_cmnd
> g. since we did not "free" associated ccb earlier or dma unmap at d., 
> the dma unmap on the same scsi_cmnd causes the warn
> 
> So the LLD should really free resources and dma unmap at point IT nexus 
> reset completes, but it doesn't. I think in certain conditions dma map 
> should not be done twice.
> 
> Anyway, that can be fixed, but I still have the hang :(

One thought: could it be bug with the DMA engine of your platform ?
What if you simply run an fio workload on the disk directly (no FS),
hang happens too ?

For the bugs I fixed with my series, it was the reverse: fio worked
great but everything broke down when I ran libzbc tests...

> 
> Thanks,
> John


-- 
Damien Le Moal
Western Digital Research

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

* Re: [PATCH v3 27/31] scsi: pm8001: Cleanup pm8001_queue_command()
  2022-02-17 10:47                     ` Damien Le Moal
@ 2022-02-17 12:49                       ` John Garry
  2022-02-18  3:12                         ` Damien Le Moal
  0 siblings, 1 reply; 61+ messages in thread
From: John Garry @ 2022-02-17 12:49 UTC (permalink / raw)
  To: Damien Le Moal, linux-scsi, Martin K . Petersen, Xiang Chen, Jason Yan

>>>
>>
>> I figured out what is happening here and it does not help solve the
>> mystery of my hang.
>>
>> Here's the steps:
>> a. scsi_cmnd times out
>> b. scsi error handling kicks in
>> c. libsas attempts to abort the task, which fails
>> d. libsas then tries IT nexus reset, which passes
>>    - libsas assumes the scsi_cmnd has completed with failure
>> e. error handling concludes
>> f. scsi midlayer then retries the same scsi_cmnd
>> g. since we did not "free" associated ccb earlier or dma unmap at d.,
>> the dma unmap on the same scsi_cmnd causes the warn
>>
>> So the LLD should really free resources and dma unmap at point IT nexus
>> reset completes, but it doesn't. I think in certain conditions dma map
>> should not be done twice.
>>
>> Anyway, that can be fixed, but I still have the hang :(
> 
> I guess (a) (cmd timeout) is only the symptom of the hang ? That is, the
> hang is causing the timeout ?

Right

> It may be good to turn on scsi trace to see if the command was only
> partially done, or not at all, or if it is a non-data command.
> 

I could do that. But I think that the command just does not complete. Or 
maybe it is missed.

> And speaking of errors, I am currently testing v4 of my series and
> noticed some weird things in the error handling. E.g., with one of the
> test executing a report zones command with an LBA out of range, I see this:
> 
> [23962.027105] pm80xx0:: mpi_sata_event  2788:SATA EVENT 0x23
> [23962.036099] pm80xx0:: pm80xx_send_read_log  1863:Executing read log end
> 

I don't know why the driver even does this, but the implementation of 
pm80xx_send_read_log() is questionable. It would be nice to not see ATA 
code in the driver like this.

> All good: this is IO_XFER_ERROR_ABORTED_NCQ_MODE. And the read log is to
> get the drive queue out of error state.
> 
> [23962.046101] pm80xx0:: mpi_sata_event  2788:SATA EVENT 0x26
> 
> This is IO_XFER_ERROR_UNEXPECTED_PHASE. No clue what this is doing.
> 
> [23962.054947] pm80xx0:: mpi_sata_event  2805:task or dev null
> 
> Why ?
> 
> [23962.063865] pm80xx0:: pm80xx_send_abort_all  1796:Executing abort
> task end
> 
> All queued commands are aborted when the read log completes. Again, per
> ATA NCQ specs, all good. After that, normal (some useless) messages.
> 
> [23962.063964] pm80xx0:: mpi_sata_completion  2395:IO failed device_id
> 16388 status 0x1 tag 1
> [23962.084587] pm80xx0:: mpi_sata_completion  2430:SAS Address of IO
> Failure Drive:50010860002f5657
> [23962.095526] sas: sas_ata_task_done: SAS error 0x8d
> [23962.139470] sas: Enter sas_scsi_recover_host busy: 1 failed: 1
> [23962.147897] ata24.00: exception Emask 0x0 SAct 0x800 SErr 0x0 action 0x0
> [23962.156253] ata24.00: failed command: RECEIVE FPDMA QUEUED
> [23962.163307] ata24.00: cmd 65/01:00:00:00:0c/00:02:23:01:00/40 tag 11
> ncq dma 512 in
> [23962.163307]          res 43/10:00:00:00:00/00:00:00:00:00/00 Emask
> 0x480 (invalid argument) <F>
> 
> Good here, correct error...
> 
> [23962.182879] ata24.00: status: { DRDY SENSE ERR }
> [23962.189100] ata24.00: error: { IDNF }
> 
> ... but I need to look at this in libata. Getting the same with AHCI.

ok, in a way that is a relief.

> 
> [23962.215456] ata24.00: configured for UDMA/133
> [23962.221469] ata24: EH complete
> [23962.226056] sas: --- Exit sas_scsi_recover_host: busy: 0 failed: 1
> tries: 1
> 
> That event 0x26 and the "task or dev null" are obscure. No clue, but
> they look wrong.

As above, I doubt the implemenation of that code. It alloc's a domain 
device itself, which is not how things should be done.

> 
> Overall, this driver is by default way too verbose I think. I would
> prefer to reduce the above to something like:
> 
> [23962.095526] sas: sas_ata_task_done: SAS error 0x8d
> [23962.139470] sas: Enter sas_scsi_recover_host busy: 1 failed: 1
> [23962.147897] ata24.00: exception Emask 0x0 SAct 0x800 SErr 0x0 action 0x0
> [23962.156253] ata24.00: failed command: RECEIVE FPDMA QUEUED
> [23962.163307] ata24.00: cmd 65/01:00:00:00:0c/00:02:23:01:00/40 tag 11
> ncq dma 512 in
> [23962.163307]          res 43/10:00:00:00:00/00:00:00:00:00/00 Emask
> 0x480 (invalid argument) <F>
> [23962.182879] ata24.00: status: { DRDY SENSE ERR }
> [23962.189100] ata24.00: error: { IDNF }
> [23962.215456] ata24.00: configured for UDMA/133
> [23962.221469] ata24: EH complete
> [23962.226056] sas: --- Exit sas_scsi_recover_host: busy: 0 failed: 1
> tries: 1
> 
> That is, by default, remove most FAIL messages, changing them to DEV
> level. The same test with a SAS drive is totally silent, as it should
> be, since the command error is not a fatal one.
> 
> But not touching this for now. I first want the series to be queued.
> 

In response to later message:

On 17/02/2022 11:47, Damien Le Moal wrote:
 >> Anyway, that can be fixed, but I still have the hang:(
 > One thought: could it be bug with the DMA engine of your platform ?
 > What if you simply run an fio workload on the disk directly (no FS),
 > hang happens too ?

I did try fio a while ago and it worked ok. Strange.

 > For the bugs I fixed with my series, it was the reverse: fio worked
 > great but everything broke down when I ran libzbc tests...
 >

I got a few more things to try but need to make progress on my libsas 
series now ...

Thanks,
John





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

* Re: [PATCH v3 27/31] scsi: pm8001: Cleanup pm8001_queue_command()
  2022-02-17 12:49                       ` John Garry
@ 2022-02-18  3:12                         ` Damien Le Moal
  2022-02-18 11:21                           ` John Garry
  0 siblings, 1 reply; 61+ messages in thread
From: Damien Le Moal @ 2022-02-18  3:12 UTC (permalink / raw)
  To: John Garry, linux-scsi, Martin K . Petersen, Xiang Chen, Jason Yan

On 2/17/22 21:49, John Garry wrote:
>>>>
>>>
>>> I figured out what is happening here and it does not help solve the
>>> mystery of my hang.
>>>
>>> Here's the steps:
>>> a. scsi_cmnd times out
>>> b. scsi error handling kicks in
>>> c. libsas attempts to abort the task, which fails
>>> d. libsas then tries IT nexus reset, which passes
>>>    - libsas assumes the scsi_cmnd has completed with failure
>>> e. error handling concludes
>>> f. scsi midlayer then retries the same scsi_cmnd
>>> g. since we did not "free" associated ccb earlier or dma unmap at d.,
>>> the dma unmap on the same scsi_cmnd causes the warn
>>>
>>> So the LLD should really free resources and dma unmap at point IT nexus
>>> reset completes, but it doesn't. I think in certain conditions dma map
>>> should not be done twice.
>>>
>>> Anyway, that can be fixed, but I still have the hang :(
>>
>> I guess (a) (cmd timeout) is only the symptom of the hang ? That is, the
>> hang is causing the timeout ?
> 
> Right
> 
>> It may be good to turn on scsi trace to see if the command was only
>> partially done, or not at all, or if it is a non-data command.
>>
> 
> I could do that. But I think that the command just does not complete. Or 
> maybe it is missed.
> 
>> And speaking of errors, I am currently testing v4 of my series and
>> noticed some weird things in the error handling. E.g., with one of the
>> test executing a report zones command with an LBA out of range, I see this:
>>
>> [23962.027105] pm80xx0:: mpi_sata_event  2788:SATA EVENT 0x23
>> [23962.036099] pm80xx0:: pm80xx_send_read_log  1863:Executing read log end
>>
> 
> I don't know why the driver even does this, but the implementation of 
> pm80xx_send_read_log() is questionable. It would be nice to not see ATA 
> code in the driver like this.

I have been thinking about this one. We should be able to avoid this
read log and rely on libata-eh to do it. All we should need to do is an
internal abort all without completing the commands. libata will do the
read log and resend the retry for the failed command (if appropriate)
and all the other aborted NCQ commands.

Need to look at how other libsas drivers are handling this. But the
above should work, I think.

Not adding this to the current series though :) That will be for another
patch series.

-- 
Damien Le Moal
Western Digital Research

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

* Re: [PATCH v3 27/31] scsi: pm8001: Cleanup pm8001_queue_command()
  2022-02-18  3:12                         ` Damien Le Moal
@ 2022-02-18 11:21                           ` John Garry
  0 siblings, 0 replies; 61+ messages in thread
From: John Garry @ 2022-02-18 11:21 UTC (permalink / raw)
  To: Damien Le Moal, linux-scsi, Martin K . Petersen, Xiang Chen, Jason Yan

On 18/02/2022 03:12, Damien Le Moal wrote:
>> I don't know why the driver even does this, but the implementation of
>> pm80xx_send_read_log() is questionable. It would be nice to not see ATA
>> code in the driver like this.
> I have been thinking about this one. We should be able to avoid this
> read log and rely on libata-eh to do it. All we should need to do is an
> internal abort all without completing the commands. libata will do the
> read log and resend the retry for the failed command (if appropriate)
> and all the other aborted NCQ commands.
> 
> Need to look at how other libsas drivers are handling this. But the
> above should work, I think.

I just assumed that this was something specific to that HW as no other 
libsas driver does this manually.

> 
> Not adding this to the current series though:)  That will be for another
> patch series.
Please note that the Hisi SAS driver also issues an ATA softreset as 
part of the disk reset procedure - it would be nice to have that sort of 
code in libata also; I see softreset code in libahci which maybe could 
be refactored. I can check further when I get a chance.

Thanks,
John



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

end of thread, other threads:[~2022-02-18 11:21 UTC | newest]

Thread overview: 61+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-14  2:17 [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 01/31] scsi: libsas: Fix sas_ata_qc_issue() handling of NCQ NON DATA commands Damien Le Moal
2022-02-14 17:56   ` John Garry
2022-02-14 22:23     ` Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 02/31] scsi: pm8001: Fix __iomem pointer use in pm8001_phy_control() Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 03/31] scsi: pm8001: Fix pm8001_update_flash() local variable type Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 04/31] scsi: pm8001: Fix command initialization in pm80XX_send_read_log() Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 05/31] scsi: pm8001: Fix pm80xx_pci_mem_copy() interface Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 06/31] scsi: pm8001: Fix command initialization in pm8001_chip_ssp_tm_req() Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 07/31] scsi: pm8001: Fix payload initialization in pm80xx_set_thermal_config() Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 08/31] scsi: pm8001: Fix le32 values handling in pm80xx_set_sas_protocol_timer_config() Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 09/31] scsi: pm8001: Fix payload initialization in pm80xx_encrypt_update() Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 10/31] scsi: pm8001: Fix le32 values handling in pm80xx_chip_ssp_io_req() Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 11/31] scsi: pm8001: Fix le32 values handling in pm80xx_chip_sata_req() Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 12/31] scsi: pm8001: Fix use of struct set_phy_profile_req fields Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 13/31] scsi: pm8001: Remove local variable in pm8001_pci_resume() Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 14/31] scsi: pm8001: Fix NCQ NON DATA command task initialization Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 15/31] scsi: pm8001: Fix NCQ NON DATA command completion handling Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 16/31] scsi: pm8001: Fix abort all task initialization Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 17/31] scsi: pm8001: Fix pm8001_tag_alloc() failures handling Damien Le Moal
2022-02-14 18:02   ` John Garry
2022-02-14  2:17 ` [PATCH v3 18/31] scsi: pm8001: Fix pm80xx_chip_phy_ctl_req() Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 19/31] scsi: pm8001: Fix pm8001_mpi_task_abort_resp() Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 20/31] scsi: pm8001: Fix tag values handling Damien Le Moal
2022-02-15 11:09   ` John Garry
2022-02-15 23:44     ` Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 21/31] scsi: pm8001: Fix task leak in pm8001_send_abort_all() Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 22/31] scsi: pm8001: Fix tag leaks on error Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 23/31] scsi: pm8001: fix memory leak in pm8001_chip_fw_flash_update_req() Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 24/31] scsi: pm8001: Fix process_one_iomb() kdoc comment Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 25/31] scsi: libsas: Simplify sas_ata_qc_issue() detection of NCQ commands Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 26/31] scsi: pm8001: Simplify pm8001_get_ncq_tag() Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 27/31] scsi: pm8001: Cleanup pm8001_queue_command() Damien Le Moal
2022-02-15 10:55   ` John Garry
2022-02-16 11:36     ` Damien Le Moal
2022-02-16 11:38       ` John Garry
2022-02-16 11:42         ` Damien Le Moal
2022-02-16 11:50           ` John Garry
2022-02-16 12:05             ` Damien Le Moal
2022-02-16 12:21               ` John Garry
2022-02-17  0:12                 ` Damien Le Moal
2022-02-17  9:23                   ` John Garry
2022-02-17 10:47                     ` Damien Le Moal
2022-02-17 12:49                       ` John Garry
2022-02-18  3:12                         ` Damien Le Moal
2022-02-18 11:21                           ` John Garry
2022-02-17 11:47                     ` Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 28/31] scsi: pm8001: Introduce ccb alloc/free helpers Damien Le Moal
2022-02-15 11:07   ` John Garry
2022-02-15 23:41     ` Damien Le Moal
2022-02-16 11:43     ` Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 29/31] scsi: pm8001: Simplify pm8001_mpi_build_cmd() interface Damien Le Moal
2022-02-14  2:17 ` [PATCH v3 30/31] scsi: pm8001: Simplify pm8001_task_exec() Damien Le Moal
2022-02-15  8:57   ` John Garry
2022-02-14  2:17 ` [PATCH v3 31/31] scsi: pm8001: Simplify pm8001_ccb_task_free() Damien Le Moal
2022-02-14  2:23 ` [PATCH v3 00/31] libsas and pm8001 fixes Damien Le Moal
2022-02-15  3:18   ` Martin K. Petersen
2022-02-15  7:38     ` Damien Le Moal
2022-02-14 18:06 ` John Garry
2022-02-14 22:29   ` Damien Le Moal
2022-02-15  8:16     ` John Garry

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.