From b711ef5e176bf47c10c0d24e21c1486b5331d33f Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Tue, 7 Mar 2023 14:09:14 +0800 Subject: 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 Link: https://lore.kernel.org/r/1678169355-76215-4-git-send-email-chenxiang66@hisilicon.com Reviewed-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 77 ++++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 20 deletions(-) (limited to 'drivers/scsi/hisi_sas/hisi_sas_main.c') diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 628cfbe4053b..325d6d6a21c3 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -683,6 +683,55 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device) 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) { 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 = &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 */ - synchronize_irq(cq->irq_no); + hisi_sas_sync_cq(cq); slot->task = NULL; } } @@ -1551,11 +1600,11 @@ static int hisi_sas_abort_task(struct sas_task *task) 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 */ 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); 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)) && 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 */ - synchronize_irq(cq->irq_no); + hisi_sas_sync_cq(cq); slot->task = NULL; } } @@ -1896,10 +1945,10 @@ static bool hisi_sas_internal_abort_timeout(struct sas_task *task, struct hisi_sas_cq *cq = &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 */ - synchronize_irq(cq->irq_no); + hisi_sas_sync_cq(cq); slot->task = NULL; } @@ -2003,18 +2052,6 @@ void hisi_sas_phy_bcast(struct hisi_sas_phy *phy) } 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) { struct hisi_hba *hisi_hba = shost_priv(shost); -- cgit v1.2.3