summaryrefslogtreecommitdiff
path: root/drivers/scsi/hisi_sas
diff options
context:
space:
mode:
authorXiang Chen <chenxiang66@hisilicon.com>2023-03-07 14:09:14 +0800
committerMartin K. Petersen <martin.petersen@oracle.com>2023-03-09 21:50:02 -0500
commitb711ef5e176bf47c10c0d24e21c1486b5331d33f (patch)
treea57a16af6c773f1b58c274425a570050da478efd /drivers/scsi/hisi_sas
parent0e47effa77067d0e5fdd41871941d2b3d38a0e61 (diff)
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>
Diffstat (limited to 'drivers/scsi/hisi_sas')
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas.h3
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_main.c77
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v3_hw.c3
3 files changed, 61 insertions, 22 deletions
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index a0eed81828dc..3a5fc3658d3a 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -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_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 bool hisi_sas_notify_phy_event(struct hisi_sas_phy *phy,
enum hisi_sas_phy_event event);
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 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_done(struct hisi_hba *hisi_hba);
#endif
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);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 24282bcf33d2..1f6c02632c6a 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -2657,6 +2657,7 @@ static int disable_host_v3_hw(struct hisi_hba *hisi_hba)
int rc;
interrupt_disable_v3_hw(hisi_hba);
+ hisi_sas_sync_poll_cqs(hisi_hba);
hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0);
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);
- hisi_sas_sync_irqs(hisi_hba);
+ hisi_sas_sync_cqs(hisi_hba);
}
static void debugfs_snapshot_restore_v3_hw(struct hisi_hba *hisi_hba)