Commit e85d93b2 authored by Xiang Chen's avatar Xiang Chen Committed by Martin K. Petersen

scsi: hisi_sas: Use device lock to protect slot alloc/free

The IPTT of a slot is unique, and we currently use hisi_hba lock to
protect it.

Now slot is managed on hisi_sas_device.list, so use DQ lock to protect
for allocating and freeing the slot.
Signed-off-by: default avatarXiang Chen <chenxiang66@hisilicon.com>
Signed-off-by: default avatarJohn Garry <john.garry@huawei.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent fa222db0
...@@ -214,6 +214,8 @@ static void hisi_sas_slot_index_init(struct hisi_hba *hisi_hba) ...@@ -214,6 +214,8 @@ static void hisi_sas_slot_index_init(struct hisi_hba *hisi_hba)
void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task, void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
struct hisi_sas_slot *slot) struct hisi_sas_slot *slot)
{ {
struct hisi_sas_dq *dq = &hisi_hba->dq[slot->dlvry_queue];
unsigned long flags;
if (task) { if (task) {
struct device *dev = hisi_hba->dev; struct device *dev = hisi_hba->dev;
...@@ -233,11 +235,15 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task, ...@@ -233,11 +235,15 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
if (slot->buf) if (slot->buf)
dma_pool_free(hisi_hba->buffer_pool, slot->buf, slot->buf_dma); dma_pool_free(hisi_hba->buffer_pool, slot->buf, slot->buf_dma);
spin_lock_irqsave(&dq->lock, flags);
list_del_init(&slot->entry); list_del_init(&slot->entry);
spin_unlock_irqrestore(&dq->lock, flags);
slot->buf = NULL; slot->buf = NULL;
slot->task = NULL; slot->task = NULL;
slot->port = NULL; slot->port = NULL;
spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_slot_index_free(hisi_hba, slot->idx); hisi_sas_slot_index_free(hisi_hba, slot->idx);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
/* slot memory is fully zeroed when it is reused */ /* slot memory is fully zeroed when it is reused */
} }
...@@ -286,7 +292,6 @@ static void hisi_sas_slot_abort(struct work_struct *work) ...@@ -286,7 +292,6 @@ static void hisi_sas_slot_abort(struct work_struct *work)
struct scsi_lun lun; struct scsi_lun lun;
struct device *dev = hisi_hba->dev; struct device *dev = hisi_hba->dev;
int tag = abort_slot->idx; int tag = abort_slot->idx;
unsigned long flags;
if (!(task->task_proto & SAS_PROTOCOL_SSP)) { if (!(task->task_proto & SAS_PROTOCOL_SSP)) {
dev_err(dev, "cannot abort slot for non-ssp task\n"); dev_err(dev, "cannot abort slot for non-ssp task\n");
...@@ -300,9 +305,7 @@ static void hisi_sas_slot_abort(struct work_struct *work) ...@@ -300,9 +305,7 @@ static void hisi_sas_slot_abort(struct work_struct *work)
hisi_sas_debug_issue_ssp_tmf(task->dev, lun.scsi_lun, &tmf_task); hisi_sas_debug_issue_ssp_tmf(task->dev, lun.scsi_lun, &tmf_task);
out: out:
/* Do cleanup for this task */ /* Do cleanup for this task */
spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_slot_task_free(hisi_hba, task, abort_slot); hisi_sas_slot_task_free(hisi_hba, task, abort_slot);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
if (task->task_done) if (task->task_done)
task->task_done(task); task->task_done(task);
} }
...@@ -471,9 +474,9 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq *dq, ...@@ -471,9 +474,9 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq *dq,
break; break;
} }
spin_lock_irqsave(&hisi_hba->lock, flags); spin_lock_irqsave(&dq->lock, flags);
list_add_tail(&slot->entry, &sas_dev->list); list_add_tail(&slot->entry, &sas_dev->list);
spin_unlock_irqrestore(&hisi_hba->lock, flags); spin_unlock_irqrestore(&dq->lock, flags);
spin_lock_irqsave(&task->task_state_lock, flags); spin_lock_irqsave(&task->task_state_lock, flags);
task->task_state_flags |= SAS_TASK_AT_INITIATOR; task->task_state_flags |= SAS_TASK_AT_INITIATOR;
spin_unlock_irqrestore(&task->task_state_lock, flags); spin_unlock_irqrestore(&task->task_state_lock, flags);
...@@ -1047,7 +1050,6 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device) ...@@ -1047,7 +1050,6 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device)
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct device *dev = hisi_hba->dev; struct device *dev = hisi_hba->dev;
int s = sizeof(struct host_to_dev_fis); int s = sizeof(struct host_to_dev_fis);
unsigned long flags;
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);
...@@ -1072,11 +1074,8 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device) ...@@ -1072,11 +1074,8 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device)
dev_err(dev, "ata disk reset failed\n"); dev_err(dev, "ata disk reset failed\n");
} }
if (rc == TMF_RESP_FUNC_COMPLETE) { if (rc == TMF_RESP_FUNC_COMPLETE)
spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_release_task(hisi_hba, device); hisi_sas_release_task(hisi_hba, device);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
}
return rc; return rc;
} }
...@@ -1173,7 +1172,6 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba) ...@@ -1173,7 +1172,6 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
struct device *dev = hisi_hba->dev; struct device *dev = hisi_hba->dev;
struct Scsi_Host *shost = hisi_hba->shost; struct Scsi_Host *shost = hisi_hba->shost;
u32 old_state, state; u32 old_state, state;
unsigned long flags;
int rc; int rc;
if (!hisi_hba->hw->soft_reset) if (!hisi_hba->hw->soft_reset)
...@@ -1197,9 +1195,7 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba) ...@@ -1197,9 +1195,7 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
scsi_unblock_requests(shost); scsi_unblock_requests(shost);
goto out; goto out;
} }
spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_release_tasks(hisi_hba); hisi_sas_release_tasks(hisi_hba);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
...@@ -1274,11 +1270,8 @@ static int hisi_sas_abort_task(struct sas_task *task) ...@@ -1274,11 +1270,8 @@ static int hisi_sas_abort_task(struct sas_task *task)
* will have already been completed * will have already been completed
*/ */
if (rc == TMF_RESP_FUNC_COMPLETE && rc2 != TMF_RESP_FUNC_SUCC) { if (rc == TMF_RESP_FUNC_COMPLETE && rc2 != TMF_RESP_FUNC_SUCC) {
if (task->lldd_task) { if (task->lldd_task)
spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_do_release_task(hisi_hba, task, slot); hisi_sas_do_release_task(hisi_hba, task, slot);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
}
} }
} else if (task->task_proto & SAS_PROTOCOL_SATA || } else if (task->task_proto & SAS_PROTOCOL_SATA ||
task->task_proto & SAS_PROTOCOL_STP) { task->task_proto & SAS_PROTOCOL_STP) {
...@@ -1300,11 +1293,8 @@ static int hisi_sas_abort_task(struct sas_task *task) ...@@ -1300,11 +1293,8 @@ static int hisi_sas_abort_task(struct sas_task *task)
rc = hisi_sas_internal_task_abort(hisi_hba, device, rc = hisi_sas_internal_task_abort(hisi_hba, device,
HISI_SAS_INT_ABT_CMD, tag); HISI_SAS_INT_ABT_CMD, tag);
if (((rc < 0) || (rc == TMF_RESP_FUNC_FAILED)) && if (((rc < 0) || (rc == TMF_RESP_FUNC_FAILED)) &&
task->lldd_task) { task->lldd_task)
spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_do_release_task(hisi_hba, task, slot); hisi_sas_do_release_task(hisi_hba, task, slot);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
}
} }
out: out:
...@@ -1319,7 +1309,6 @@ static int hisi_sas_abort_task_set(struct domain_device *device, u8 *lun) ...@@ -1319,7 +1309,6 @@ static int hisi_sas_abort_task_set(struct domain_device *device, u8 *lun)
struct device *dev = hisi_hba->dev; struct device *dev = hisi_hba->dev;
struct hisi_sas_tmf_task tmf_task; struct hisi_sas_tmf_task tmf_task;
int rc = TMF_RESP_FUNC_FAILED; int rc = TMF_RESP_FUNC_FAILED;
unsigned long flags;
rc = hisi_sas_internal_task_abort(hisi_hba, device, rc = hisi_sas_internal_task_abort(hisi_hba, device,
HISI_SAS_INT_ABT_DEV, 0); HISI_SAS_INT_ABT_DEV, 0);
...@@ -1332,11 +1321,8 @@ static int hisi_sas_abort_task_set(struct domain_device *device, u8 *lun) ...@@ -1332,11 +1321,8 @@ static int hisi_sas_abort_task_set(struct domain_device *device, u8 *lun)
tmf_task.tmf = TMF_ABORT_TASK_SET; tmf_task.tmf = TMF_ABORT_TASK_SET;
rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task); rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task);
if (rc == TMF_RESP_FUNC_COMPLETE) { if (rc == TMF_RESP_FUNC_COMPLETE)
spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_release_task(hisi_hba, device); hisi_sas_release_task(hisi_hba, device);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
}
return rc; return rc;
} }
...@@ -1369,7 +1355,6 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device) ...@@ -1369,7 +1355,6 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device)
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct device *dev = hisi_hba->dev; struct device *dev = hisi_hba->dev;
int rc = TMF_RESP_FUNC_FAILED; int rc = TMF_RESP_FUNC_FAILED;
unsigned long flags;
if (sas_dev->dev_status != HISI_SAS_DEV_EH) if (sas_dev->dev_status != HISI_SAS_DEV_EH)
return TMF_RESP_FUNC_FAILED; return TMF_RESP_FUNC_FAILED;
...@@ -1385,11 +1370,9 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device) ...@@ -1385,11 +1370,9 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device)
rc = hisi_sas_debug_I_T_nexus_reset(device); rc = hisi_sas_debug_I_T_nexus_reset(device);
if ((rc == TMF_RESP_FUNC_COMPLETE) || (rc == -ENODEV)) { if ((rc == TMF_RESP_FUNC_COMPLETE) || (rc == -ENODEV))
spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_release_task(hisi_hba, device); hisi_sas_release_task(hisi_hba, device);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
}
return rc; return rc;
} }
...@@ -1398,7 +1381,6 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun) ...@@ -1398,7 +1381,6 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun)
struct hisi_sas_device *sas_dev = device->lldd_dev; struct hisi_sas_device *sas_dev = device->lldd_dev;
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct device *dev = hisi_hba->dev; struct device *dev = hisi_hba->dev;
unsigned long flags;
int rc = TMF_RESP_FUNC_FAILED; int rc = TMF_RESP_FUNC_FAILED;
sas_dev->dev_status = HISI_SAS_DEV_EH; sas_dev->dev_status = HISI_SAS_DEV_EH;
...@@ -1418,11 +1400,8 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun) ...@@ -1418,11 +1400,8 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun)
rc = sas_phy_reset(phy, 1); rc = sas_phy_reset(phy, 1);
if (rc == 0) { if (rc == 0)
spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_release_task(hisi_hba, device); hisi_sas_release_task(hisi_hba, device);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
}
sas_put_local_phy(phy); sas_put_local_phy(phy);
} else { } else {
struct hisi_sas_tmf_task tmf_task = { .tmf = TMF_LU_RESET }; struct hisi_sas_tmf_task tmf_task = { .tmf = TMF_LU_RESET };
...@@ -1436,11 +1415,8 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun) ...@@ -1436,11 +1415,8 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun)
hisi_sas_dereg_device(hisi_hba, device); hisi_sas_dereg_device(hisi_hba, device);
rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task); rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task);
if (rc == TMF_RESP_FUNC_COMPLETE) { if (rc == TMF_RESP_FUNC_COMPLETE)
spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_release_task(hisi_hba, device); hisi_sas_release_task(hisi_hba, device);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
}
} }
out: out:
if (rc != TMF_RESP_FUNC_COMPLETE) if (rc != TMF_RESP_FUNC_COMPLETE)
......
...@@ -2373,7 +2373,6 @@ static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -2373,7 +2373,6 @@ static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state)
u32 device_state, status; u32 device_state, status;
int rc; int rc;
u32 reg_val; u32 reg_val;
unsigned long flags;
if (!pdev->pm_cap) { if (!pdev->pm_cap) {
dev_err(dev, "PCI PM not supported\n"); dev_err(dev, "PCI PM not supported\n");
...@@ -2418,9 +2417,7 @@ static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -2418,9 +2417,7 @@ static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state)
pci_disable_device(pdev); pci_disable_device(pdev);
pci_set_power_state(pdev, device_state); pci_set_power_state(pdev, device_state);
spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_release_tasks(hisi_hba); hisi_sas_release_tasks(hisi_hba);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
sas_suspend_ha(sha); sas_suspend_ha(sha);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment