Skip to content

Commit 23a50c8

Browse files
davejiangvinodkoul
authored andcommitted
dmaengine: idxd: fix descriptor flushing locking
The descriptor flushing for shutdown is not holding the irq_entry list lock. If there's ongoing interrupt completion handling, this can corrupt the list. Add locking to protect list walking. Also refactor the code so it's more compact. Fixes: 8f47d1a ("dmaengine: idxd: connect idxd to dmaengine subsystem") Signed-off-by: Dave Jiang <[email protected]> Link: https://lore.kernel.org/r/163942148935.2412839.18282664745572777280.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Vinod Koul <[email protected]>
1 parent ec0d642 commit 23a50c8

File tree

1 file changed

+15
-14
lines changed

1 file changed

+15
-14
lines changed

drivers/dma/idxd/init.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -689,26 +689,28 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
689689
return rc;
690690
}
691691

692-
static void idxd_flush_pending_llist(struct idxd_irq_entry *ie)
692+
static void idxd_flush_pending_descs(struct idxd_irq_entry *ie)
693693
{
694694
struct idxd_desc *desc, *itr;
695695
struct llist_node *head;
696+
LIST_HEAD(flist);
697+
enum idxd_complete_type ctype;
696698

699+
spin_lock(&ie->list_lock);
697700
head = llist_del_all(&ie->pending_llist);
698-
if (!head)
699-
return;
700-
701-
llist_for_each_entry_safe(desc, itr, head, llnode)
702-
idxd_dma_complete_txd(desc, IDXD_COMPLETE_ABORT, true);
703-
}
701+
if (head) {
702+
llist_for_each_entry_safe(desc, itr, head, llnode)
703+
list_add_tail(&desc->list, &ie->work_list);
704+
}
704705

705-
static void idxd_flush_work_list(struct idxd_irq_entry *ie)
706-
{
707-
struct idxd_desc *desc, *iter;
706+
list_for_each_entry_safe(desc, itr, &ie->work_list, list)
707+
list_move_tail(&desc->list, &flist);
708+
spin_unlock(&ie->list_lock);
708709

709-
list_for_each_entry_safe(desc, iter, &ie->work_list, list) {
710+
list_for_each_entry_safe(desc, itr, &flist, list) {
710711
list_del(&desc->list);
711-
idxd_dma_complete_txd(desc, IDXD_COMPLETE_ABORT, true);
712+
ctype = desc->completion->status ? IDXD_COMPLETE_NORMAL : IDXD_COMPLETE_ABORT;
713+
idxd_dma_complete_txd(desc, ctype, true);
712714
}
713715
}
714716

@@ -762,8 +764,7 @@ static void idxd_shutdown(struct pci_dev *pdev)
762764
synchronize_irq(irq_entry->vector);
763765
if (i == 0)
764766
continue;
765-
idxd_flush_pending_llist(irq_entry);
766-
idxd_flush_work_list(irq_entry);
767+
idxd_flush_pending_descs(irq_entry);
767768
}
768769
flush_workqueue(idxd->wq);
769770
}

0 commit comments

Comments
 (0)