scsi: hisi_sas: Fix some issues related to asd_sas_port->phy_list
Most places that use asd_sas_port->phy_list are protected by spinlock asd_sas_port->phy_list_lock, however there are still some places which miss grabbing the lock. Add it in function hisi_sas_refresh_port_id() when accessing asd_sas_port->phy_list. This carries a risk that list mutates while at the same time dropping the lock in function hisi_sas_send_ata_reset_each_phy(). Read asd_sas_port->phy_mask instead of accessing asd_sas_port->phy_list to avoid this risk. Link: https://lore.kernel.org/r/1639999298-244569-6-git-send-email-chenxiang66@hisilicon.com Acked-by: John Garry <john.garry@huawei.com> Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
42159d3c8d
commit
29e2bac874
@ -1428,11 +1428,13 @@ static void hisi_sas_refresh_port_id(struct hisi_hba *hisi_hba)
|
|||||||
sas_port = device->port;
|
sas_port = device->port;
|
||||||
port = to_hisi_sas_port(sas_port);
|
port = to_hisi_sas_port(sas_port);
|
||||||
|
|
||||||
|
spin_lock(&sas_port->phy_list_lock);
|
||||||
list_for_each_entry(sas_phy, &sas_port->phy_list, port_phy_el)
|
list_for_each_entry(sas_phy, &sas_port->phy_list, port_phy_el)
|
||||||
if (state & BIT(sas_phy->id)) {
|
if (state & BIT(sas_phy->id)) {
|
||||||
phy = sas_phy->lldd_phy;
|
phy = sas_phy->lldd_phy;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
spin_unlock(&sas_port->phy_list_lock);
|
||||||
|
|
||||||
if (phy) {
|
if (phy) {
|
||||||
port->id = phy->port_id;
|
port->id = phy->port_id;
|
||||||
@ -1509,22 +1511,25 @@ static void hisi_sas_send_ata_reset_each_phy(struct hisi_hba *hisi_hba,
|
|||||||
struct ata_link *link;
|
struct ata_link *link;
|
||||||
u8 fis[20] = {0};
|
u8 fis[20] = {0};
|
||||||
u32 state;
|
u32 state;
|
||||||
|
int i;
|
||||||
|
|
||||||
state = hisi_hba->hw->get_phys_state(hisi_hba);
|
state = hisi_hba->hw->get_phys_state(hisi_hba);
|
||||||
list_for_each_entry(sas_phy, &sas_port->phy_list, port_phy_el) {
|
for (i = 0; i < hisi_hba->n_phy; i++) {
|
||||||
if (!(state & BIT(sas_phy->id)))
|
if (!(state & BIT(sas_phy->id)))
|
||||||
continue;
|
continue;
|
||||||
|
if (!(sas_port->phy_mask & BIT(i)))
|
||||||
|
continue;
|
||||||
|
|
||||||
ata_for_each_link(link, ap, EDGE) {
|
ata_for_each_link(link, ap, EDGE) {
|
||||||
int pmp = sata_srst_pmp(link);
|
int pmp = sata_srst_pmp(link);
|
||||||
|
|
||||||
tmf_task.phy_id = sas_phy->id;
|
tmf_task.phy_id = i;
|
||||||
hisi_sas_fill_ata_reset_cmd(link->device, 1, pmp, fis);
|
hisi_sas_fill_ata_reset_cmd(link->device, 1, pmp, fis);
|
||||||
rc = hisi_sas_exec_internal_tmf_task(device, fis, s,
|
rc = hisi_sas_exec_internal_tmf_task(device, fis, s,
|
||||||
&tmf_task);
|
&tmf_task);
|
||||||
if (rc != TMF_RESP_FUNC_COMPLETE) {
|
if (rc != TMF_RESP_FUNC_COMPLETE) {
|
||||||
dev_err(dev, "phy%d ata reset failed rc=%d\n",
|
dev_err(dev, "phy%d ata reset failed rc=%d\n",
|
||||||
sas_phy->id, rc);
|
i, rc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user