scsi: hisi_sas: Sync complete queue for poll queue
Currently we sync irq to avoid freeing task before using task in I/O completion. After adding io_uring support, we need to do something similar for poll queues. As the process of CQ entries on poll queue are protected by spinlock cq->lock, we can use spin_lock() + spin_unlock() on cq->lock to make sure that CQ entries are processed to completion and then the complete queue is synced. Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> Link: https://lore.kernel.org/r/1678169355-76215-4-git-send-email-chenxiang66@hisilicon.com Reviewed-by: John Garry <john.garry@huawei.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
0e47effa77
commit
b711ef5e17
@ -660,12 +660,13 @@ extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba,
|
|||||||
extern void hisi_sas_init_mem(struct hisi_hba *hisi_hba);
|
extern void hisi_sas_init_mem(struct hisi_hba *hisi_hba);
|
||||||
extern void hisi_sas_rst_work_handler(struct work_struct *work);
|
extern void hisi_sas_rst_work_handler(struct work_struct *work);
|
||||||
extern void hisi_sas_sync_rst_work_handler(struct work_struct *work);
|
extern void hisi_sas_sync_rst_work_handler(struct work_struct *work);
|
||||||
extern void hisi_sas_sync_irqs(struct hisi_hba *hisi_hba);
|
|
||||||
extern void hisi_sas_phy_oob_ready(struct hisi_hba *hisi_hba, int phy_no);
|
extern void hisi_sas_phy_oob_ready(struct hisi_hba *hisi_hba, int phy_no);
|
||||||
extern bool hisi_sas_notify_phy_event(struct hisi_sas_phy *phy,
|
extern bool hisi_sas_notify_phy_event(struct hisi_sas_phy *phy,
|
||||||
enum hisi_sas_phy_event event);
|
enum hisi_sas_phy_event event);
|
||||||
extern void hisi_sas_release_tasks(struct hisi_hba *hisi_hba);
|
extern void hisi_sas_release_tasks(struct hisi_hba *hisi_hba);
|
||||||
extern u8 hisi_sas_get_prog_phy_linkrate_mask(enum sas_linkrate max);
|
extern u8 hisi_sas_get_prog_phy_linkrate_mask(enum sas_linkrate max);
|
||||||
|
extern void hisi_sas_sync_cqs(struct hisi_hba *hisi_hba);
|
||||||
|
extern void hisi_sas_sync_poll_cqs(struct hisi_hba *hisi_hba);
|
||||||
extern void hisi_sas_controller_reset_prepare(struct hisi_hba *hisi_hba);
|
extern void hisi_sas_controller_reset_prepare(struct hisi_hba *hisi_hba);
|
||||||
extern void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba);
|
extern void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba);
|
||||||
#endif
|
#endif
|
||||||
|
@ -683,6 +683,55 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
|
|||||||
return sas_dev;
|
return sas_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hisi_sas_sync_poll_cq(struct hisi_sas_cq *cq)
|
||||||
|
{
|
||||||
|
/* make sure CQ entries being processed are processed to completion */
|
||||||
|
spin_lock(&cq->poll_lock);
|
||||||
|
spin_unlock(&cq->poll_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool hisi_sas_queue_is_poll(struct hisi_sas_cq *cq)
|
||||||
|
{
|
||||||
|
struct hisi_hba *hisi_hba = cq->hisi_hba;
|
||||||
|
|
||||||
|
if (cq->id < hisi_hba->queue_count - hisi_hba->iopoll_q_cnt)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hisi_sas_sync_cq(struct hisi_sas_cq *cq)
|
||||||
|
{
|
||||||
|
if (hisi_sas_queue_is_poll(cq))
|
||||||
|
hisi_sas_sync_poll_cq(cq);
|
||||||
|
else
|
||||||
|
synchronize_irq(cq->irq_no);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hisi_sas_sync_poll_cqs(struct hisi_hba *hisi_hba)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < hisi_hba->queue_count; i++) {
|
||||||
|
struct hisi_sas_cq *cq = &hisi_hba->cq[i];
|
||||||
|
|
||||||
|
if (hisi_sas_queue_is_poll(cq))
|
||||||
|
hisi_sas_sync_poll_cq(cq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(hisi_sas_sync_poll_cqs);
|
||||||
|
|
||||||
|
void hisi_sas_sync_cqs(struct hisi_hba *hisi_hba)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < hisi_hba->queue_count; i++) {
|
||||||
|
struct hisi_sas_cq *cq = &hisi_hba->cq[i];
|
||||||
|
|
||||||
|
hisi_sas_sync_cq(cq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(hisi_sas_sync_cqs);
|
||||||
|
|
||||||
static void hisi_sas_tmf_aborted(struct sas_task *task)
|
static void hisi_sas_tmf_aborted(struct sas_task *task)
|
||||||
{
|
{
|
||||||
struct hisi_sas_slot *slot = task->lldd_task;
|
struct hisi_sas_slot *slot = task->lldd_task;
|
||||||
@ -694,10 +743,10 @@ static void hisi_sas_tmf_aborted(struct sas_task *task)
|
|||||||
struct hisi_sas_cq *cq =
|
struct hisi_sas_cq *cq =
|
||||||
&hisi_hba->cq[slot->dlvry_queue];
|
&hisi_hba->cq[slot->dlvry_queue];
|
||||||
/*
|
/*
|
||||||
* sync irq to avoid free'ing task
|
* sync irq or poll queue to avoid free'ing task
|
||||||
* before using task in IO completion
|
* before using task in IO completion
|
||||||
*/
|
*/
|
||||||
synchronize_irq(cq->irq_no);
|
hisi_sas_sync_cq(cq);
|
||||||
slot->task = NULL;
|
slot->task = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1551,11 +1600,11 @@ static int hisi_sas_abort_task(struct sas_task *task)
|
|||||||
|
|
||||||
if (slot) {
|
if (slot) {
|
||||||
/*
|
/*
|
||||||
* sync irq to avoid free'ing task
|
* sync irq or poll queue to avoid free'ing task
|
||||||
* before using task in IO completion
|
* before using task in IO completion
|
||||||
*/
|
*/
|
||||||
cq = &hisi_hba->cq[slot->dlvry_queue];
|
cq = &hisi_hba->cq[slot->dlvry_queue];
|
||||||
synchronize_irq(cq->irq_no);
|
hisi_sas_sync_cq(cq);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||||
rc = TMF_RESP_FUNC_COMPLETE;
|
rc = TMF_RESP_FUNC_COMPLETE;
|
||||||
@ -1622,10 +1671,10 @@ static int hisi_sas_abort_task(struct sas_task *task)
|
|||||||
if (((rc < 0) || (rc == TMF_RESP_FUNC_FAILED)) &&
|
if (((rc < 0) || (rc == TMF_RESP_FUNC_FAILED)) &&
|
||||||
task->lldd_task) {
|
task->lldd_task) {
|
||||||
/*
|
/*
|
||||||
* sync irq to avoid free'ing task
|
* sync irq or poll queue to avoid free'ing task
|
||||||
* before using task in IO completion
|
* before using task in IO completion
|
||||||
*/
|
*/
|
||||||
synchronize_irq(cq->irq_no);
|
hisi_sas_sync_cq(cq);
|
||||||
slot->task = NULL;
|
slot->task = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1896,10 +1945,10 @@ static bool hisi_sas_internal_abort_timeout(struct sas_task *task,
|
|||||||
struct hisi_sas_cq *cq =
|
struct hisi_sas_cq *cq =
|
||||||
&hisi_hba->cq[slot->dlvry_queue];
|
&hisi_hba->cq[slot->dlvry_queue];
|
||||||
/*
|
/*
|
||||||
* sync irq to avoid free'ing task
|
* sync irq or poll queue to avoid free'ing task
|
||||||
* before using task in IO completion
|
* before using task in IO completion
|
||||||
*/
|
*/
|
||||||
synchronize_irq(cq->irq_no);
|
hisi_sas_sync_cq(cq);
|
||||||
slot->task = NULL;
|
slot->task = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2003,18 +2052,6 @@ void hisi_sas_phy_bcast(struct hisi_sas_phy *phy)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(hisi_sas_phy_bcast);
|
EXPORT_SYMBOL_GPL(hisi_sas_phy_bcast);
|
||||||
|
|
||||||
void hisi_sas_sync_irqs(struct hisi_hba *hisi_hba)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < hisi_hba->cq_nvecs; i++) {
|
|
||||||
struct hisi_sas_cq *cq = &hisi_hba->cq[i];
|
|
||||||
|
|
||||||
synchronize_irq(cq->irq_no);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(hisi_sas_sync_irqs);
|
|
||||||
|
|
||||||
int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type)
|
int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type)
|
||||||
{
|
{
|
||||||
struct hisi_hba *hisi_hba = shost_priv(shost);
|
struct hisi_hba *hisi_hba = shost_priv(shost);
|
||||||
|
@ -2657,6 +2657,7 @@ static int disable_host_v3_hw(struct hisi_hba *hisi_hba)
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
interrupt_disable_v3_hw(hisi_hba);
|
interrupt_disable_v3_hw(hisi_hba);
|
||||||
|
hisi_sas_sync_poll_cqs(hisi_hba);
|
||||||
hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0);
|
hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0);
|
||||||
|
|
||||||
hisi_sas_stop_phys(hisi_hba);
|
hisi_sas_stop_phys(hisi_hba);
|
||||||
@ -3069,7 +3070,7 @@ static void debugfs_snapshot_prepare_v3_hw(struct hisi_hba *hisi_hba)
|
|||||||
|
|
||||||
wait_cmds_complete_timeout_v3_hw(hisi_hba, 100, 5000);
|
wait_cmds_complete_timeout_v3_hw(hisi_hba, 100, 5000);
|
||||||
|
|
||||||
hisi_sas_sync_irqs(hisi_hba);
|
hisi_sas_sync_cqs(hisi_hba);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debugfs_snapshot_restore_v3_hw(struct hisi_hba *hisi_hba)
|
static void debugfs_snapshot_restore_v3_hw(struct hisi_hba *hisi_hba)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user