Skip to content

Commit b711ef5

Browse files
Xiang Chenmartinkpetersen
authored andcommitted
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>
1 parent 0e47eff commit b711ef5

3 files changed

Lines changed: 61 additions & 22 deletions

File tree

drivers/scsi/hisi_sas/hisi_sas.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -660,12 +660,13 @@ extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba,
660660
extern void hisi_sas_init_mem(struct hisi_hba *hisi_hba);
661661
extern void hisi_sas_rst_work_handler(struct work_struct *work);
662662
extern void hisi_sas_sync_rst_work_handler(struct work_struct *work);
663-
extern void hisi_sas_sync_irqs(struct hisi_hba *hisi_hba);
664663
extern void hisi_sas_phy_oob_ready(struct hisi_hba *hisi_hba, int phy_no);
665664
extern bool hisi_sas_notify_phy_event(struct hisi_sas_phy *phy,
666665
enum hisi_sas_phy_event event);
667666
extern void hisi_sas_release_tasks(struct hisi_hba *hisi_hba);
668667
extern u8 hisi_sas_get_prog_phy_linkrate_mask(enum sas_linkrate max);
668+
extern void hisi_sas_sync_cqs(struct hisi_hba *hisi_hba);
669+
extern void hisi_sas_sync_poll_cqs(struct hisi_hba *hisi_hba);
669670
extern void hisi_sas_controller_reset_prepare(struct hisi_hba *hisi_hba);
670671
extern void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba);
671672
#endif

drivers/scsi/hisi_sas/hisi_sas_main.c

Lines changed: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,55 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
683683
return sas_dev;
684684
}
685685

686+
static void hisi_sas_sync_poll_cq(struct hisi_sas_cq *cq)
687+
{
688+
/* make sure CQ entries being processed are processed to completion */
689+
spin_lock(&cq->poll_lock);
690+
spin_unlock(&cq->poll_lock);
691+
}
692+
693+
static bool hisi_sas_queue_is_poll(struct hisi_sas_cq *cq)
694+
{
695+
struct hisi_hba *hisi_hba = cq->hisi_hba;
696+
697+
if (cq->id < hisi_hba->queue_count - hisi_hba->iopoll_q_cnt)
698+
return false;
699+
return true;
700+
}
701+
702+
static void hisi_sas_sync_cq(struct hisi_sas_cq *cq)
703+
{
704+
if (hisi_sas_queue_is_poll(cq))
705+
hisi_sas_sync_poll_cq(cq);
706+
else
707+
synchronize_irq(cq->irq_no);
708+
}
709+
710+
void hisi_sas_sync_poll_cqs(struct hisi_hba *hisi_hba)
711+
{
712+
int i;
713+
714+
for (i = 0; i < hisi_hba->queue_count; i++) {
715+
struct hisi_sas_cq *cq = &hisi_hba->cq[i];
716+
717+
if (hisi_sas_queue_is_poll(cq))
718+
hisi_sas_sync_poll_cq(cq);
719+
}
720+
}
721+
EXPORT_SYMBOL_GPL(hisi_sas_sync_poll_cqs);
722+
723+
void hisi_sas_sync_cqs(struct hisi_hba *hisi_hba)
724+
{
725+
int i;
726+
727+
for (i = 0; i < hisi_hba->queue_count; i++) {
728+
struct hisi_sas_cq *cq = &hisi_hba->cq[i];
729+
730+
hisi_sas_sync_cq(cq);
731+
}
732+
}
733+
EXPORT_SYMBOL_GPL(hisi_sas_sync_cqs);
734+
686735
static void hisi_sas_tmf_aborted(struct sas_task *task)
687736
{
688737
struct hisi_sas_slot *slot = task->lldd_task;
@@ -694,10 +743,10 @@ static void hisi_sas_tmf_aborted(struct sas_task *task)
694743
struct hisi_sas_cq *cq =
695744
&hisi_hba->cq[slot->dlvry_queue];
696745
/*
697-
* sync irq to avoid free'ing task
746+
* sync irq or poll queue to avoid free'ing task
698747
* before using task in IO completion
699748
*/
700-
synchronize_irq(cq->irq_no);
749+
hisi_sas_sync_cq(cq);
701750
slot->task = NULL;
702751
}
703752
}
@@ -1551,11 +1600,11 @@ static int hisi_sas_abort_task(struct sas_task *task)
15511600

15521601
if (slot) {
15531602
/*
1554-
* sync irq to avoid free'ing task
1603+
* sync irq or poll queue to avoid free'ing task
15551604
* before using task in IO completion
15561605
*/
15571606
cq = &hisi_hba->cq[slot->dlvry_queue];
1558-
synchronize_irq(cq->irq_no);
1607+
hisi_sas_sync_cq(cq);
15591608
}
15601609
spin_unlock_irqrestore(&task->task_state_lock, flags);
15611610
rc = TMF_RESP_FUNC_COMPLETE;
@@ -1622,10 +1671,10 @@ static int hisi_sas_abort_task(struct sas_task *task)
16221671
if (((rc < 0) || (rc == TMF_RESP_FUNC_FAILED)) &&
16231672
task->lldd_task) {
16241673
/*
1625-
* sync irq to avoid free'ing task
1674+
* sync irq or poll queue to avoid free'ing task
16261675
* before using task in IO completion
16271676
*/
1628-
synchronize_irq(cq->irq_no);
1677+
hisi_sas_sync_cq(cq);
16291678
slot->task = NULL;
16301679
}
16311680
}
@@ -1896,10 +1945,10 @@ static bool hisi_sas_internal_abort_timeout(struct sas_task *task,
18961945
struct hisi_sas_cq *cq =
18971946
&hisi_hba->cq[slot->dlvry_queue];
18981947
/*
1899-
* sync irq to avoid free'ing task
1948+
* sync irq or poll queue to avoid free'ing task
19001949
* before using task in IO completion
19011950
*/
1902-
synchronize_irq(cq->irq_no);
1951+
hisi_sas_sync_cq(cq);
19031952
slot->task = NULL;
19041953
}
19051954

@@ -2003,18 +2052,6 @@ void hisi_sas_phy_bcast(struct hisi_sas_phy *phy)
20032052
}
20042053
EXPORT_SYMBOL_GPL(hisi_sas_phy_bcast);
20052054

2006-
void hisi_sas_sync_irqs(struct hisi_hba *hisi_hba)
2007-
{
2008-
int i;
2009-
2010-
for (i = 0; i < hisi_hba->cq_nvecs; i++) {
2011-
struct hisi_sas_cq *cq = &hisi_hba->cq[i];
2012-
2013-
synchronize_irq(cq->irq_no);
2014-
}
2015-
}
2016-
EXPORT_SYMBOL_GPL(hisi_sas_sync_irqs);
2017-
20182055
int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type)
20192056
{
20202057
struct hisi_hba *hisi_hba = shost_priv(shost);

drivers/scsi/hisi_sas/hisi_sas_v3_hw.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2657,6 +2657,7 @@ static int disable_host_v3_hw(struct hisi_hba *hisi_hba)
26572657
int rc;
26582658

26592659
interrupt_disable_v3_hw(hisi_hba);
2660+
hisi_sas_sync_poll_cqs(hisi_hba);
26602661
hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0);
26612662

26622663
hisi_sas_stop_phys(hisi_hba);
@@ -3069,7 +3070,7 @@ static void debugfs_snapshot_prepare_v3_hw(struct hisi_hba *hisi_hba)
30693070

30703071
wait_cmds_complete_timeout_v3_hw(hisi_hba, 100, 5000);
30713072

3072-
hisi_sas_sync_irqs(hisi_hba);
3073+
hisi_sas_sync_cqs(hisi_hba);
30733074
}
30743075

30753076
static void debugfs_snapshot_restore_v3_hw(struct hisi_hba *hisi_hba)

0 commit comments

Comments
 (0)