summaryrefslogtreecommitdiff
path: root/drivers/dma/idxd
diff options
context:
space:
mode:
authorVinod Koul <vkoul@kernel.org>2022-01-05 12:48:05 +0530
committerVinod Koul <vkoul@kernel.org>2022-01-05 12:48:05 +0530
commit5cb664fbeba0a11592c1d2774833a4cc49d1ca19 (patch)
treef5eb47d25d0b90cebbe46d0cbe33bf39bc339eef /drivers/dma/idxd
parent105a8c525675bb7d4d64871f9b2edf39460de881 (diff)
parent822c9f2b833c53fc67e8adf6f63ecc3ea24d502c (diff)
Merge branch 'fixes' into next
We have a conflict in idxd driver between 'fixes' and 'next' and there are patches dependent on this so, merge the 'fixes' branch into next
Diffstat (limited to 'drivers/dma/idxd')
-rw-r--r--drivers/dma/idxd/irq.c2
-rw-r--r--drivers/dma/idxd/submit.c18
2 files changed, 18 insertions, 2 deletions
diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c
index 0b0055a0ad2a..925171e9738c 100644
--- a/drivers/dma/idxd/irq.c
+++ b/drivers/dma/idxd/irq.c
@@ -318,10 +318,10 @@ halt:
INIT_WORK(&idxd->work, idxd_device_reinit);
queue_work(idxd->wq, &idxd->work);
} else {
- spin_lock(&idxd->dev_lock);
idxd->state = IDXD_DEV_HALTED;
idxd_wqs_quiesce(idxd);
idxd_wqs_unmap_portal(idxd);
+ spin_lock(&idxd->dev_lock);
idxd_device_clear_state(idxd);
dev_err(&idxd->pdev->dev,
"idxd halted, need %s.\n",
diff --git a/drivers/dma/idxd/submit.c b/drivers/dma/idxd/submit.c
index 569815a84e95..11ac06be1f0a 100644
--- a/drivers/dma/idxd/submit.c
+++ b/drivers/dma/idxd/submit.c
@@ -97,6 +97,7 @@ static void llist_abort_desc(struct idxd_wq *wq, struct idxd_irq_entry *ie,
{
struct idxd_desc *d, *t, *found = NULL;
struct llist_node *head;
+ LIST_HEAD(flist);
desc->completion->status = IDXD_COMP_DESC_ABORT;
/*
@@ -111,7 +112,11 @@ static void llist_abort_desc(struct idxd_wq *wq, struct idxd_irq_entry *ie,
found = desc;
continue;
}
- list_add_tail(&desc->list, &ie->work_list);
+
+ if (d->completion->status)
+ list_add_tail(&d->list, &flist);
+ else
+ list_add_tail(&d->list, &ie->work_list);
}
}
@@ -121,6 +126,17 @@ static void llist_abort_desc(struct idxd_wq *wq, struct idxd_irq_entry *ie,
if (found)
idxd_dma_complete_txd(found, IDXD_COMPLETE_ABORT, false);
+
+ /*
+ * completing the descriptor will return desc to allocator and
+ * the desc can be acquired by a different process and the
+ * desc->list can be modified. Delete desc from list so the
+ * list trasversing does not get corrupted by the other process.
+ */
+ list_for_each_entry_safe(d, t, &flist, list) {
+ list_del_init(&d->list);
+ idxd_dma_complete_txd(found, IDXD_COMPLETE_ABORT, true);
+ }
}
/*