Commit 750d4fbe authored by Xingui Yang's avatar Xingui Yang Committed by Martin K. Petersen
Browse files

scsi: hisi_sas: Fixed failure to issue vendor specific commands



At present, we determine the protocol through the cmd type, but other cmd
types, such as vendor-specific commands, default to the PIO protocol.  This
strategy often causes the execution of different vendor-specific commands
to fail. In fact, for these commands, a better way is to use the protocol
configured by the command's tf to determine its protocol.

Fixes: 6f2ff1a1 ("hisi_sas: add v2 path to send ATA command")
Signed-off-by: default avatarXingui Yang <yangxingui@huawei.com>
Link: https://lore.kernel.org/r/20250220090011.313848-1-liyihang9@huawei.com


Reviewed-by: default avatarYihang Li <liyihang9@huawei.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent bd067766
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -633,8 +633,7 @@ extern struct dentry *hisi_sas_debugfs_dir;
extern void hisi_sas_stop_phys(struct hisi_hba *hisi_hba);
extern int hisi_sas_alloc(struct hisi_hba *hisi_hba);
extern void hisi_sas_free(struct hisi_hba *hisi_hba);
extern u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis,
				int direction);
extern u8 hisi_sas_get_ata_protocol(struct sas_task *task);
extern struct hisi_sas_port *to_hisi_sas_port(struct asd_sas_port *sas_port);
extern void hisi_sas_sata_done(struct sas_task *task,
			    struct hisi_sas_slot *slot);
+26 −2
Original line number Diff line number Diff line
@@ -21,8 +21,32 @@ struct hisi_sas_internal_abort_data {
	bool rst_ha_timeout; /* reset the HA for timeout */
};

u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction)
static u8 hisi_sas_get_ata_protocol_from_tf(struct ata_queued_cmd *qc)
{
	if (!qc)
		return HISI_SAS_SATA_PROTOCOL_PIO;

	switch (qc->tf.protocol) {
	case ATA_PROT_NODATA:
		return HISI_SAS_SATA_PROTOCOL_NONDATA;
	case ATA_PROT_PIO:
		return HISI_SAS_SATA_PROTOCOL_PIO;
	case ATA_PROT_DMA:
		return HISI_SAS_SATA_PROTOCOL_DMA;
	case ATA_PROT_NCQ_NODATA:
	case ATA_PROT_NCQ:
		return HISI_SAS_SATA_PROTOCOL_FPDMA;
	default:
		return HISI_SAS_SATA_PROTOCOL_PIO;
	}
}

u8 hisi_sas_get_ata_protocol(struct sas_task *task)
{
	struct host_to_dev_fis *fis = &task->ata_task.fis;
	struct ata_queued_cmd *qc = task->uldd_task;
	int direction = task->data_dir;

	switch (fis->command) {
	case ATA_CMD_FPDMA_WRITE:
	case ATA_CMD_FPDMA_READ:
@@ -93,7 +117,7 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction)
	{
		if (direction == DMA_NONE)
			return HISI_SAS_SATA_PROTOCOL_NONDATA;
		return HISI_SAS_SATA_PROTOCOL_PIO;
		return hisi_sas_get_ata_protocol_from_tf(qc);
	}
	}
}
+1 −3
Original line number Diff line number Diff line
@@ -2538,9 +2538,7 @@ static void prep_ata_v2_hw(struct hisi_hba *hisi_hba,
			(task->ata_task.fis.control & ATA_SRST))
		dw1 |= 1 << CMD_HDR_RESET_OFF;

	dw1 |= (hisi_sas_get_ata_protocol(
		&task->ata_task.fis, task->data_dir))
		<< CMD_HDR_FRAME_TYPE_OFF;
	dw1 |= (hisi_sas_get_ata_protocol(task)) << CMD_HDR_FRAME_TYPE_OFF;
	dw1 |= sas_dev->device_id << CMD_HDR_DEV_ID_OFF;
	hdr->dw1 = cpu_to_le32(dw1);

+1 −3
Original line number Diff line number Diff line
@@ -1456,9 +1456,7 @@ static void prep_ata_v3_hw(struct hisi_hba *hisi_hba,
			(task->ata_task.fis.control & ATA_SRST))
		dw1 |= 1 << CMD_HDR_RESET_OFF;

	dw1 |= (hisi_sas_get_ata_protocol(
		&task->ata_task.fis, task->data_dir))
		<< CMD_HDR_FRAME_TYPE_OFF;
	dw1 |= (hisi_sas_get_ata_protocol(task)) << CMD_HDR_FRAME_TYPE_OFF;
	dw1 |= sas_dev->device_id << CMD_HDR_DEV_ID_OFF;

	if (FIS_CMD_IS_UNCONSTRAINED(task->ata_task.fis))