1d1dfe5b8SDave Jiang // SPDX-License-Identifier: GPL-2.0 2d1dfe5b8SDave Jiang /* Copyright(c) 2019 Intel Corporation. All rights rsvd. */ 3d1dfe5b8SDave Jiang #include <linux/init.h> 4d1dfe5b8SDave Jiang #include <linux/kernel.h> 5d1dfe5b8SDave Jiang #include <linux/module.h> 6d1dfe5b8SDave Jiang #include <linux/pci.h> 7d1dfe5b8SDave Jiang #include <uapi/linux/idxd.h> 8d1dfe5b8SDave Jiang #include "idxd.h" 9d1dfe5b8SDave Jiang #include "registers.h" 10d1dfe5b8SDave Jiang 110705107fSDave Jiang static struct idxd_desc *__get_desc(struct idxd_wq *wq, int idx, int cpu) 12d1dfe5b8SDave Jiang { 13d1dfe5b8SDave Jiang struct idxd_desc *desc; 148e50d392SDave Jiang struct idxd_device *idxd = wq->idxd; 15d1dfe5b8SDave Jiang 16d1dfe5b8SDave Jiang desc = wq->descs[idx]; 17d1dfe5b8SDave Jiang memset(desc->hw, 0, sizeof(struct dsa_hw_desc)); 18435b512dSDave Jiang memset(desc->completion, 0, idxd->data->compl_size); 190705107fSDave Jiang desc->cpu = cpu; 208e50d392SDave Jiang 218e50d392SDave Jiang if (device_pasid_enabled(idxd)) 228e50d392SDave Jiang desc->hw->pasid = idxd->pasid; 238e50d392SDave Jiang 248e50d392SDave Jiang /* 25eb15e715SDave Jiang * Descriptor completion vectors are 1...N for MSIX. We will round 26eb15e715SDave Jiang * robin through the N vectors. 278e50d392SDave Jiang */ 288ba89a3cSDave Jiang wq->vec_ptr = desc->vector = (wq->vec_ptr % idxd->num_wq_irqs) + 1; 29eb15e715SDave Jiang if (!idxd->int_handles) { 308e50d392SDave Jiang desc->hw->int_handle = wq->vec_ptr; 31eb15e715SDave Jiang } else { 32eb15e715SDave Jiang /* 33eb15e715SDave Jiang * int_handles are only for descriptor completion. However for device 34eb15e715SDave Jiang * MSIX enumeration, vec 0 is used for misc interrupts. Therefore even 35eb15e715SDave Jiang * though we are rotating through 1...N for descriptor interrupts, we 36eb15e715SDave Jiang * need to acqurie the int_handles from 0..N-1. 37eb15e715SDave Jiang */ 38eb15e715SDave Jiang desc->hw->int_handle = idxd->int_handles[desc->vector - 1]; 39eb15e715SDave Jiang } 40eb15e715SDave Jiang 41d1dfe5b8SDave Jiang return desc; 42d1dfe5b8SDave Jiang } 43d1dfe5b8SDave Jiang 440705107fSDave Jiang struct idxd_desc *idxd_alloc_desc(struct idxd_wq *wq, enum idxd_op_type optype) 450705107fSDave Jiang { 460705107fSDave Jiang int cpu, idx; 470705107fSDave Jiang struct idxd_device *idxd = wq->idxd; 480705107fSDave Jiang DEFINE_SBQ_WAIT(wait); 490705107fSDave Jiang struct sbq_wait_state *ws; 500705107fSDave Jiang struct sbitmap_queue *sbq; 510705107fSDave Jiang 520705107fSDave Jiang if (idxd->state != IDXD_DEV_ENABLED) 530705107fSDave Jiang return ERR_PTR(-EIO); 540705107fSDave Jiang 550705107fSDave Jiang sbq = &wq->sbq; 560705107fSDave Jiang idx = sbitmap_queue_get(sbq, &cpu); 570705107fSDave Jiang if (idx < 0) { 580705107fSDave Jiang if (optype == IDXD_OP_NONBLOCK) 590705107fSDave Jiang return ERR_PTR(-EAGAIN); 600705107fSDave Jiang } else { 610705107fSDave Jiang return __get_desc(wq, idx, cpu); 620705107fSDave Jiang } 630705107fSDave Jiang 640705107fSDave Jiang ws = &sbq->ws[0]; 650705107fSDave Jiang for (;;) { 660705107fSDave Jiang sbitmap_prepare_to_wait(sbq, ws, &wait, TASK_INTERRUPTIBLE); 670705107fSDave Jiang if (signal_pending_state(TASK_INTERRUPTIBLE, current)) 680705107fSDave Jiang break; 690705107fSDave Jiang idx = sbitmap_queue_get(sbq, &cpu); 700705107fSDave Jiang if (idx > 0) 710705107fSDave Jiang break; 720705107fSDave Jiang schedule(); 730705107fSDave Jiang } 740705107fSDave Jiang 750705107fSDave Jiang sbitmap_finish_wait(sbq, ws, &wait); 760705107fSDave Jiang if (idx < 0) 770705107fSDave Jiang return ERR_PTR(-EAGAIN); 780705107fSDave Jiang 790705107fSDave Jiang return __get_desc(wq, idx, cpu); 800705107fSDave Jiang } 810705107fSDave Jiang 82d1dfe5b8SDave Jiang void idxd_free_desc(struct idxd_wq *wq, struct idxd_desc *desc) 83d1dfe5b8SDave Jiang { 840705107fSDave Jiang int cpu = desc->cpu; 85d1dfe5b8SDave Jiang 860705107fSDave Jiang desc->cpu = -1; 870705107fSDave Jiang sbitmap_queue_clear(&wq->sbq, desc->id, cpu); 88d1dfe5b8SDave Jiang } 89d1dfe5b8SDave Jiang 90*6b4b87f2SDave Jiang static struct idxd_desc *list_abort_desc(struct idxd_wq *wq, struct idxd_irq_entry *ie, 91*6b4b87f2SDave Jiang struct idxd_desc *desc) 92*6b4b87f2SDave Jiang { 93*6b4b87f2SDave Jiang struct idxd_desc *d, *n; 94*6b4b87f2SDave Jiang 95*6b4b87f2SDave Jiang lockdep_assert_held(&ie->list_lock); 96*6b4b87f2SDave Jiang list_for_each_entry_safe(d, n, &ie->work_list, list) { 97*6b4b87f2SDave Jiang if (d == desc) { 98*6b4b87f2SDave Jiang list_del(&d->list); 99*6b4b87f2SDave Jiang return d; 100*6b4b87f2SDave Jiang } 101*6b4b87f2SDave Jiang } 102*6b4b87f2SDave Jiang 103*6b4b87f2SDave Jiang /* 104*6b4b87f2SDave Jiang * At this point, the desc needs to be aborted is held by the completion 105*6b4b87f2SDave Jiang * handler where it has taken it off the pending list but has not added to the 106*6b4b87f2SDave Jiang * work list. It will be cleaned up by the interrupt handler when it sees the 107*6b4b87f2SDave Jiang * IDXD_COMP_DESC_ABORT for completion status. 108*6b4b87f2SDave Jiang */ 109*6b4b87f2SDave Jiang return NULL; 110*6b4b87f2SDave Jiang } 111*6b4b87f2SDave Jiang 112*6b4b87f2SDave Jiang static void llist_abort_desc(struct idxd_wq *wq, struct idxd_irq_entry *ie, 113*6b4b87f2SDave Jiang struct idxd_desc *desc) 114*6b4b87f2SDave Jiang { 115*6b4b87f2SDave Jiang struct idxd_desc *d, *t, *found = NULL; 116*6b4b87f2SDave Jiang struct llist_node *head; 117*6b4b87f2SDave Jiang unsigned long flags; 118*6b4b87f2SDave Jiang 119*6b4b87f2SDave Jiang desc->completion->status = IDXD_COMP_DESC_ABORT; 120*6b4b87f2SDave Jiang /* 121*6b4b87f2SDave Jiang * Grab the list lock so it will block the irq thread handler. This allows the 122*6b4b87f2SDave Jiang * abort code to locate the descriptor need to be aborted. 123*6b4b87f2SDave Jiang */ 124*6b4b87f2SDave Jiang spin_lock_irqsave(&ie->list_lock, flags); 125*6b4b87f2SDave Jiang head = llist_del_all(&ie->pending_llist); 126*6b4b87f2SDave Jiang if (head) { 127*6b4b87f2SDave Jiang llist_for_each_entry_safe(d, t, head, llnode) { 128*6b4b87f2SDave Jiang if (d == desc) { 129*6b4b87f2SDave Jiang found = desc; 130*6b4b87f2SDave Jiang continue; 131*6b4b87f2SDave Jiang } 132*6b4b87f2SDave Jiang list_add_tail(&desc->list, &ie->work_list); 133*6b4b87f2SDave Jiang } 134*6b4b87f2SDave Jiang } 135*6b4b87f2SDave Jiang 136*6b4b87f2SDave Jiang if (!found) 137*6b4b87f2SDave Jiang found = list_abort_desc(wq, ie, desc); 138*6b4b87f2SDave Jiang spin_unlock_irqrestore(&ie->list_lock, flags); 139*6b4b87f2SDave Jiang 140*6b4b87f2SDave Jiang if (found) 141*6b4b87f2SDave Jiang complete_desc(found, IDXD_COMPLETE_ABORT); 142*6b4b87f2SDave Jiang } 143*6b4b87f2SDave Jiang 144d1dfe5b8SDave Jiang int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc) 145d1dfe5b8SDave Jiang { 146d1dfe5b8SDave Jiang struct idxd_device *idxd = wq->idxd; 147*6b4b87f2SDave Jiang struct idxd_irq_entry *ie = NULL; 14842d279f9SDave Jiang void __iomem *portal; 1498e50d392SDave Jiang int rc; 150d1dfe5b8SDave Jiang 151d1dfe5b8SDave Jiang if (idxd->state != IDXD_DEV_ENABLED) 152d1dfe5b8SDave Jiang return -EIO; 153d1dfe5b8SDave Jiang 15493a40a6dSDave Jiang if (!percpu_ref_tryget_live(&wq->wq_active)) 15593a40a6dSDave Jiang return -ENXIO; 15693a40a6dSDave Jiang 1576daa9043SLinus Torvalds portal = wq->portal; 1588e50d392SDave Jiang 159d1dfe5b8SDave Jiang /* 1608e50d392SDave Jiang * The wmb() flushes writes to coherent DMA data before 1618e50d392SDave Jiang * possibly triggering a DMA read. The wmb() is necessary 1628e50d392SDave Jiang * even on UP because the recipient is a device. 163d1dfe5b8SDave Jiang */ 164d1dfe5b8SDave Jiang wmb(); 165*6b4b87f2SDave Jiang 166*6b4b87f2SDave Jiang /* 167*6b4b87f2SDave Jiang * Pending the descriptor to the lockless list for the irq_entry 168*6b4b87f2SDave Jiang * that we designated the descriptor to. 169*6b4b87f2SDave Jiang */ 170*6b4b87f2SDave Jiang if (desc->hw->flags & IDXD_OP_FLAG_RCI) { 171*6b4b87f2SDave Jiang ie = &idxd->irq_entries[desc->vector]; 172*6b4b87f2SDave Jiang llist_add(&desc->llnode, &ie->pending_llist); 173*6b4b87f2SDave Jiang } 174*6b4b87f2SDave Jiang 1758e50d392SDave Jiang if (wq_dedicated(wq)) { 17642d279f9SDave Jiang iosubmit_cmds512(portal, desc->hw, 1); 1778e50d392SDave Jiang } else { 1788e50d392SDave Jiang /* 1798e50d392SDave Jiang * It's not likely that we would receive queue full rejection 1808e50d392SDave Jiang * since the descriptor allocation gates at wq size. If we 1818e50d392SDave Jiang * receive a -EAGAIN, that means something went wrong such as the 1828e50d392SDave Jiang * device is not accepting descriptor at all. 1838e50d392SDave Jiang */ 1848e50d392SDave Jiang rc = enqcmds(portal, desc->hw); 185*6b4b87f2SDave Jiang if (rc < 0) { 186*6b4b87f2SDave Jiang if (ie) 187*6b4b87f2SDave Jiang llist_abort_desc(wq, ie, desc); 1888e50d392SDave Jiang return rc; 1898e50d392SDave Jiang } 190*6b4b87f2SDave Jiang } 191d1dfe5b8SDave Jiang 19293a40a6dSDave Jiang percpu_ref_put(&wq->wq_active); 193d1dfe5b8SDave Jiang return 0; 194d1dfe5b8SDave Jiang } 195