Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: pm80xx: Fix pm8001_abort_task() for chip_8006 when using an expander

For a direct attached device, attached_phy contains the local phy id.
For a device behind an expander, attached_phy contains the remote phy
id, not the local phy id.

The pm8001_ha->phy array only contains the phys of the HBA. It does not
contain the phys of the expander.

Thus, you cannot use attached_phy to index the pm8001_ha->phy array,
without first verifying that the device is directly attached.

Use the pm80xx_get_local_phy_id() helper to make sure that we use the
local phy id to index the array, regardless if the device is directly
attached or not.

Fixes: 869ddbdcae3b ("scsi: pm80xx: corrected SATA abort handling sequence.")
Reviewed-by: Igor Pylypiv <ipylypiv@google.com>
Signed-off-by: Niklas Cassel <cassel@kernel.org>
Link: https://lore.kernel.org/r/20250814173215.1765055-21-cassel@kernel.org
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Niklas Cassel and committed by
Martin K. Petersen
ad70c6bc b4ec9830

+3 -3
+3 -3
drivers/scsi/pm8001/pm8001_sas.c
··· 1063 1063 struct pm8001_hba_info *pm8001_ha; 1064 1064 struct pm8001_device *pm8001_dev; 1065 1065 int rc = TMF_RESP_FUNC_FAILED, ret; 1066 - u32 phy_id, port_id; 1066 + u32 port_id; 1067 1067 struct sas_task_slow slow_task; 1068 1068 1069 1069 if (!task->lldd_task || !task->dev) ··· 1072 1072 dev = task->dev; 1073 1073 pm8001_dev = dev->lldd_dev; 1074 1074 pm8001_ha = pm8001_find_ha_by_dev(dev); 1075 - phy_id = pm8001_dev->attached_phy; 1076 1075 1077 1076 if (PM8001_CHIP_DISP->fatal_errors(pm8001_ha)) { 1078 1077 // If the controller is seeing fatal errors ··· 1103 1104 if (pm8001_ha->chip_id == chip_8006) { 1104 1105 DECLARE_COMPLETION_ONSTACK(completion_reset); 1105 1106 DECLARE_COMPLETION_ONSTACK(completion); 1106 - struct pm8001_phy *phy = pm8001_ha->phy + phy_id; 1107 + u32 phy_id = pm80xx_get_local_phy_id(dev); 1108 + struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; 1107 1109 port_id = phy->port->port_id; 1108 1110 1109 1111 /* 1. Set Device state as Recovery */