Skip to content

Commit 88c5d0a

Browse files
committed
Merge branch 'fixes' into next
Signed-off-by: Vinod Koul <[email protected]>
2 parents 49c4959 + 6b4b87f commit 88c5d0a

File tree

3 files changed

+99
-17
lines changed

3 files changed

+99
-17
lines changed

drivers/dma/idxd/idxd.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,14 @@ struct idxd_desc {
292292
struct idxd_wq *wq;
293293
};
294294

295+
/*
296+
* This is software defined error for the completion status. We overload the error code
297+
* that will never appear in completion status and only SWERR register.
298+
*/
299+
enum idxd_completion_status {
300+
IDXD_COMP_DESC_ABORT = 0xff,
301+
};
302+
295303
#define confdev_to_idxd(dev) container_of(dev, struct idxd_device, conf_dev)
296304
#define confdev_to_wq(dev) container_of(dev, struct idxd_wq, conf_dev)
297305

@@ -478,4 +486,10 @@ static inline void perfmon_init(void) {}
478486
static inline void perfmon_exit(void) {}
479487
#endif
480488

489+
static inline void complete_desc(struct idxd_desc *desc, enum idxd_complete_type reason)
490+
{
491+
idxd_dma_complete_txd(desc, reason);
492+
idxd_free_desc(desc->wq, desc);
493+
}
494+
481495
#endif

drivers/dma/idxd/irq.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -245,12 +245,6 @@ static inline bool match_fault(struct idxd_desc *desc, u64 fault_addr)
245245
return false;
246246
}
247247

248-
static inline void complete_desc(struct idxd_desc *desc, enum idxd_complete_type reason)
249-
{
250-
idxd_dma_complete_txd(desc, reason);
251-
idxd_free_desc(desc->wq, desc);
252-
}
253-
254248
static int irq_process_pending_llist(struct idxd_irq_entry *irq_entry,
255249
enum irq_work_type wtype,
256250
int *processed, u64 data)
@@ -272,8 +266,16 @@ static int irq_process_pending_llist(struct idxd_irq_entry *irq_entry,
272266
reason = IDXD_COMPLETE_DEV_FAIL;
273267

274268
llist_for_each_entry_safe(desc, t, head, llnode) {
275-
if (desc->completion->status) {
276-
if ((desc->completion->status & DSA_COMP_STATUS_MASK) != DSA_COMP_SUCCESS)
269+
u8 status = desc->completion->status & DSA_COMP_STATUS_MASK;
270+
271+
if (status) {
272+
if (unlikely(status == IDXD_COMP_DESC_ABORT)) {
273+
complete_desc(desc, IDXD_COMPLETE_ABORT);
274+
(*processed)++;
275+
continue;
276+
}
277+
278+
if (unlikely(status != DSA_COMP_SUCCESS))
277279
match_fault(desc, data);
278280
complete_desc(desc, reason);
279281
(*processed)++;
@@ -329,7 +331,14 @@ static int irq_process_work_list(struct idxd_irq_entry *irq_entry,
329331
spin_unlock_irqrestore(&irq_entry->list_lock, flags);
330332

331333
list_for_each_entry(desc, &flist, list) {
332-
if ((desc->completion->status & DSA_COMP_STATUS_MASK) != DSA_COMP_SUCCESS)
334+
u8 status = desc->completion->status & DSA_COMP_STATUS_MASK;
335+
336+
if (unlikely(status == IDXD_COMP_DESC_ABORT)) {
337+
complete_desc(desc, IDXD_COMPLETE_ABORT);
338+
continue;
339+
}
340+
341+
if (unlikely(status != DSA_COMP_SUCCESS))
333342
match_fault(desc, data);
334343
complete_desc(desc, reason);
335344
}

drivers/dma/idxd/submit.c

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,64 @@ void idxd_free_desc(struct idxd_wq *wq, struct idxd_desc *desc)
7979
sbitmap_queue_clear(&wq->sbq, desc->id, cpu);
8080
}
8181

82+
static struct idxd_desc *list_abort_desc(struct idxd_wq *wq, struct idxd_irq_entry *ie,
83+
struct idxd_desc *desc)
84+
{
85+
struct idxd_desc *d, *n;
86+
87+
lockdep_assert_held(&ie->list_lock);
88+
list_for_each_entry_safe(d, n, &ie->work_list, list) {
89+
if (d == desc) {
90+
list_del(&d->list);
91+
return d;
92+
}
93+
}
94+
95+
/*
96+
* At this point, the desc needs to be aborted is held by the completion
97+
* handler where it has taken it off the pending list but has not added to the
98+
* work list. It will be cleaned up by the interrupt handler when it sees the
99+
* IDXD_COMP_DESC_ABORT for completion status.
100+
*/
101+
return NULL;
102+
}
103+
104+
static void llist_abort_desc(struct idxd_wq *wq, struct idxd_irq_entry *ie,
105+
struct idxd_desc *desc)
106+
{
107+
struct idxd_desc *d, *t, *found = NULL;
108+
struct llist_node *head;
109+
unsigned long flags;
110+
111+
desc->completion->status = IDXD_COMP_DESC_ABORT;
112+
/*
113+
* Grab the list lock so it will block the irq thread handler. This allows the
114+
* abort code to locate the descriptor need to be aborted.
115+
*/
116+
spin_lock_irqsave(&ie->list_lock, flags);
117+
head = llist_del_all(&ie->pending_llist);
118+
if (head) {
119+
llist_for_each_entry_safe(d, t, head, llnode) {
120+
if (d == desc) {
121+
found = desc;
122+
continue;
123+
}
124+
list_add_tail(&desc->list, &ie->work_list);
125+
}
126+
}
127+
128+
if (!found)
129+
found = list_abort_desc(wq, ie, desc);
130+
spin_unlock_irqrestore(&ie->list_lock, flags);
131+
132+
if (found)
133+
complete_desc(found, IDXD_COMPLETE_ABORT);
134+
}
135+
82136
int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc)
83137
{
84138
struct idxd_device *idxd = wq->idxd;
139+
struct idxd_irq_entry *ie = NULL;
85140
void __iomem *portal;
86141
int rc;
87142

@@ -99,6 +154,16 @@ int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc)
99154
* even on UP because the recipient is a device.
100155
*/
101156
wmb();
157+
158+
/*
159+
* Pending the descriptor to the lockless list for the irq_entry
160+
* that we designated the descriptor to.
161+
*/
162+
if (desc->hw->flags & IDXD_OP_FLAG_RCI) {
163+
ie = &idxd->irq_entries[wq->id + 1];
164+
llist_add(&desc->llnode, &ie->pending_llist);
165+
}
166+
102167
if (wq_dedicated(wq)) {
103168
iosubmit_cmds512(portal, desc->hw, 1);
104169
} else {
@@ -111,18 +176,12 @@ int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc)
111176
rc = enqcmds(portal, desc->hw);
112177
if (rc < 0) {
113178
percpu_ref_put(&wq->wq_active);
179+
if (ie)
180+
llist_abort_desc(wq, ie, desc);
114181
return rc;
115182
}
116183
}
117184

118185
percpu_ref_put(&wq->wq_active);
119-
120-
/*
121-
* Pending the descriptor to the lockless list for the irq_entry
122-
* that we designated the descriptor to.
123-
*/
124-
if (desc->hw->flags & IDXD_OP_FLAG_RCI)
125-
llist_add(&desc->llnode, &idxd->irq_entries[wq->id + 1].pending_llist);
126-
127186
return 0;
128187
}

0 commit comments

Comments
 (0)