]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
scsi: hisi_sas: Fixed failure to issue vendor specific commands
authorXingui Yang <yangxingui@huawei.com>
Thu, 20 Feb 2025 09:00:11 +0000 (17:00 +0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 18 Mar 2025 02:04:21 +0000 (22:04 -0400)
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: 6f2ff1a1311e ("hisi_sas: add v2 path to send ATA command")
Signed-off-by: Xingui Yang <yangxingui@huawei.com>
Link: https://lore.kernel.org/r/20250220090011.313848-1-liyihang9@huawei.com
Reviewed-by: Yihang Li <liyihang9@huawei.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/hisi_sas/hisi_sas.h
drivers/scsi/hisi_sas/hisi_sas_main.c
drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c

index 2d438d722d0b4ff9f857baf2ce3ab67b7cb6fae9..e17f5d8226bf28b6831fce143794afaed5fcf83e 100644 (file)
@@ -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);
index da4a2ed8ee863edacbac4a6dc8becb100241a36d..3596414d970b24a07c42154454957259032dc618 100644 (file)
@@ -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);
        }
        }
 }
index 3cc4cddcb655483af61a4471f1a8ac885d30cd40..04ee02797ca3fe66ac424d60ee160ca1fa23e4d5 100644 (file)
@@ -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);
 
index 48b95d9a792753bdfdb5a2619d21627b7fc01a81..095bbf80c34efb261a183f34d8724fdc0ac4fade 100644 (file)
@@ -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))