Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

IB/hfi1: Reduce lock contention on iowait_lock for sdma and pio

Commit 4e045572e2c2 ("IB/hfi1: Add unique txwait_lock for txreq events")
laid the ground work to support per resource waiting locking.

This patch adds that with a lock unique to each sdma engine and pio
sendcontext and makes necessary changes for verbs, PSM, and vnic to use
the new locks.

This is particularly beneficial for smaller messages that will exhaust
resources at a faster rate.

Fixes: 7724105686e7 ("IB/hfi1: add driver files")
Reviewed-by: Gary Leshner <Gary.S.Leshner@intel.com>
Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>

authored by

Mike Marciniszyn and committed by
Jason Gunthorpe
9aefcabe 18912c45

+27 -31
+3 -3
drivers/infiniband/hw/hfi1/pio.c
··· 742 742 spin_lock_init(&sc->alloc_lock); 743 743 spin_lock_init(&sc->release_lock); 744 744 spin_lock_init(&sc->credit_ctrl_lock); 745 + seqlock_init(&sc->waitlock); 745 746 INIT_LIST_HEAD(&sc->piowait); 746 747 INIT_WORK(&sc->halt_work, sc_halted); 747 748 init_waitqueue_head(&sc->halt_wait); ··· 1594 1593 static void sc_piobufavail(struct send_context *sc) 1595 1594 { 1596 1595 struct hfi1_devdata *dd = sc->dd; 1597 - struct hfi1_ibdev *dev = &dd->verbs_dev; 1598 1596 struct list_head *list; 1599 1597 struct rvt_qp *qps[PIO_WAIT_BATCH_SIZE]; 1600 1598 struct rvt_qp *qp; ··· 1612 1612 * could end up with QPs on the wait list with the interrupt 1613 1613 * disabled. 1614 1614 */ 1615 - write_seqlock_irqsave(&dev->iowait_lock, flags); 1615 + write_seqlock_irqsave(&sc->waitlock, flags); 1616 1616 while (!list_empty(list)) { 1617 1617 struct iowait *wait; 1618 1618 ··· 1636 1636 if (!list_empty(list)) 1637 1637 hfi1_sc_wantpiobuf_intr(sc, 1); 1638 1638 } 1639 - write_sequnlock_irqrestore(&dev->iowait_lock, flags); 1639 + write_sequnlock_irqrestore(&sc->waitlock, flags); 1640 1640 1641 1641 /* Wake up the most starved one first */ 1642 1642 if (n)
+2
drivers/infiniband/hw/hfi1/pio.h
··· 127 127 volatile __le64 *hw_free; /* HW free counter */ 128 128 /* list for PIO waiters */ 129 129 struct list_head piowait ____cacheline_aligned_in_smp; 130 + seqlock_t waitlock; 131 + 130 132 spinlock_t credit_ctrl_lock ____cacheline_aligned_in_smp; 131 133 u32 credit_intr_count; /* count of credit intr users */ 132 134 u64 credit_ctrl; /* cache for credit control */
+8 -12
drivers/infiniband/hw/hfi1/qp.c
··· 368 368 369 369 static void qp_pio_drain(struct rvt_qp *qp) 370 370 { 371 - struct hfi1_ibdev *dev; 372 371 struct hfi1_qp_priv *priv = qp->priv; 373 372 374 373 if (!priv->s_sendcontext) 375 374 return; 376 - dev = to_idev(qp->ibqp.device); 377 375 while (iowait_pio_pending(&priv->s_iowait)) { 378 - write_seqlock_irq(&dev->iowait_lock); 376 + write_seqlock_irq(&priv->s_sendcontext->waitlock); 379 377 hfi1_sc_wantpiobuf_intr(priv->s_sendcontext, 1); 380 - write_sequnlock_irq(&dev->iowait_lock); 378 + write_sequnlock_irq(&priv->s_sendcontext->waitlock); 381 379 iowait_pio_drain(&priv->s_iowait); 382 - write_seqlock_irq(&dev->iowait_lock); 380 + write_seqlock_irq(&priv->s_sendcontext->waitlock); 383 381 hfi1_sc_wantpiobuf_intr(priv->s_sendcontext, 0); 384 - write_sequnlock_irq(&dev->iowait_lock); 382 + write_sequnlock_irq(&priv->s_sendcontext->waitlock); 385 383 } 386 384 } 387 385 ··· 450 452 struct hfi1_qp_priv *priv; 451 453 unsigned long flags; 452 454 int ret = 0; 453 - struct hfi1_ibdev *dev; 454 455 455 456 qp = tx->qp; 456 457 priv = qp->priv; ··· 462 465 * buffer and undoing the side effects of the copy. 463 466 */ 464 467 /* Make a common routine? */ 465 - dev = &sde->dd->verbs_dev; 466 468 list_add_tail(&stx->list, &wait->tx_head); 467 - write_seqlock(&dev->iowait_lock); 469 + write_seqlock(&sde->waitlock); 468 470 if (sdma_progress(sde, seq, stx)) 469 471 goto eagain; 470 472 if (list_empty(&priv->s_iowait.list)) { ··· 474 478 qp->s_flags |= RVT_S_WAIT_DMA_DESC; 475 479 iowait_queue(pkts_sent, &priv->s_iowait, 476 480 &sde->dmawait); 477 - priv->s_iowait.lock = &dev->iowait_lock; 481 + priv->s_iowait.lock = &sde->waitlock; 478 482 trace_hfi1_qpsleep(qp, RVT_S_WAIT_DMA_DESC); 479 483 rvt_get_qp(qp); 480 484 } 481 - write_sequnlock(&dev->iowait_lock); 485 + write_sequnlock(&sde->waitlock); 482 486 hfi1_qp_unbusy(qp, wait); 483 487 spin_unlock_irqrestore(&qp->s_lock, flags); 484 488 ret = -EBUSY; ··· 488 492 } 489 493 return ret; 490 494 eagain: 491 - write_sequnlock(&dev->iowait_lock); 495 + write_sequnlock(&sde->waitlock); 492 496 spin_unlock_irqrestore(&qp->s_lock, flags); 493 497 list_del_init(&stx->list); 494 498 return -EAGAIN;
+5 -5
drivers/infiniband/hw/hfi1/sdma.c
··· 1424 1424 seqlock_init(&sde->head_lock); 1425 1425 spin_lock_init(&sde->senddmactrl_lock); 1426 1426 spin_lock_init(&sde->flushlist_lock); 1427 + seqlock_init(&sde->waitlock); 1427 1428 /* insure there is always a zero bit */ 1428 1429 sde->ahg_bits = 0xfffffffe00000000ULL; 1429 1430 ··· 1759 1758 struct iowait *wait, *nw; 1760 1759 struct iowait *waits[SDMA_WAIT_BATCH_SIZE]; 1761 1760 uint i, n = 0, seq, max_idx = 0; 1762 - struct hfi1_ibdev *dev = &sde->dd->verbs_dev; 1763 1761 u8 max_starved_cnt = 0; 1764 1762 1765 1763 #ifdef CONFIG_SDMA_VERBOSITY ··· 1768 1768 #endif 1769 1769 1770 1770 do { 1771 - seq = read_seqbegin(&dev->iowait_lock); 1771 + seq = read_seqbegin(&sde->waitlock); 1772 1772 if (!list_empty(&sde->dmawait)) { 1773 1773 /* at least one item */ 1774 - write_seqlock(&dev->iowait_lock); 1774 + write_seqlock(&sde->waitlock); 1775 1775 /* Harvest waiters wanting DMA descriptors */ 1776 1776 list_for_each_entry_safe( 1777 1777 wait, ··· 1794 1794 list_del_init(&wait->list); 1795 1795 waits[n++] = wait; 1796 1796 } 1797 - write_sequnlock(&dev->iowait_lock); 1797 + write_sequnlock(&sde->waitlock); 1798 1798 break; 1799 1799 } 1800 - } while (read_seqretry(&dev->iowait_lock, seq)); 1800 + } while (read_seqretry(&sde->waitlock, seq)); 1801 1801 1802 1802 /* Schedule the most starved one first */ 1803 1803 if (n)
+1
drivers/infiniband/hw/hfi1/sdma.h
··· 382 382 u64 progress_int_cnt; 383 383 384 384 /* private: */ 385 + seqlock_t waitlock; 385 386 struct list_head dmawait; 386 387 387 388 /* CONFIG SDMA for now, just blindly duplicate */
+2 -3
drivers/infiniband/hw/hfi1/user_sdma.c
··· 130 130 { 131 131 struct hfi1_user_sdma_pkt_q *pq = 132 132 container_of(wait->iow, struct hfi1_user_sdma_pkt_q, busy); 133 - struct hfi1_ibdev *dev = &pq->dd->verbs_dev; 134 133 struct user_sdma_txreq *tx = 135 134 container_of(txreq, struct user_sdma_txreq, txreq); 136 135 ··· 143 144 * it is supposed to be enqueued. 144 145 */ 145 146 xchg(&pq->state, SDMA_PKT_Q_DEFERRED); 146 - write_seqlock(&dev->iowait_lock); 147 + write_seqlock(&sde->waitlock); 147 148 if (list_empty(&pq->busy.list)) 148 149 iowait_queue(pkts_sent, &pq->busy, &sde->dmawait); 149 - write_sequnlock(&dev->iowait_lock); 150 + write_sequnlock(&sde->waitlock); 150 151 return -EBUSY; 151 152 eagain: 152 153 return -EAGAIN;
+3 -4
drivers/infiniband/hw/hfi1/verbs.c
··· 765 765 { 766 766 struct hfi1_qp_priv *priv = qp->priv; 767 767 struct hfi1_devdata *dd = sc->dd; 768 - struct hfi1_ibdev *dev = &dd->verbs_dev; 769 768 unsigned long flags; 770 769 int ret = 0; 771 770 ··· 776 777 */ 777 778 spin_lock_irqsave(&qp->s_lock, flags); 778 779 if (ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK) { 779 - write_seqlock(&dev->iowait_lock); 780 + write_seqlock(&sc->waitlock); 780 781 list_add_tail(&ps->s_txreq->txreq.list, 781 782 &ps->wait->tx_head); 782 783 if (list_empty(&priv->s_iowait.list)) { ··· 789 790 was_empty = list_empty(&sc->piowait); 790 791 iowait_queue(ps->pkts_sent, &priv->s_iowait, 791 792 &sc->piowait); 792 - priv->s_iowait.lock = &dev->iowait_lock; 793 + priv->s_iowait.lock = &sc->waitlock; 793 794 trace_hfi1_qpsleep(qp, RVT_S_WAIT_PIO); 794 795 rvt_get_qp(qp); 795 796 /* counting: only call wantpiobuf_intr if first user */ 796 797 if (was_empty) 797 798 hfi1_sc_wantpiobuf_intr(sc, 1); 798 799 } 799 - write_sequnlock(&dev->iowait_lock); 800 + write_sequnlock(&sc->waitlock); 800 801 hfi1_qp_unbusy(qp, ps->wait); 801 802 ret = -EBUSY; 802 803 }
+3 -4
drivers/infiniband/hw/hfi1/vnic_sdma.c
··· 232 232 { 233 233 struct hfi1_vnic_sdma *vnic_sdma = 234 234 container_of(wait->iow, struct hfi1_vnic_sdma, wait); 235 - struct hfi1_ibdev *dev = &vnic_sdma->dd->verbs_dev; 236 235 237 - write_seqlock(&dev->iowait_lock); 236 + write_seqlock(&sde->waitlock); 238 237 if (sdma_progress(sde, seq, txreq)) { 239 - write_sequnlock(&dev->iowait_lock); 238 + write_sequnlock(&sde->waitlock); 240 239 return -EAGAIN; 241 240 } 242 241 243 242 vnic_sdma->state = HFI1_VNIC_SDMA_Q_DEFERRED; 244 243 if (list_empty(&vnic_sdma->wait.list)) 245 244 iowait_queue(pkts_sent, wait->iow, &sde->dmawait); 246 - write_sequnlock(&dev->iowait_lock); 245 + write_sequnlock(&sde->waitlock); 247 246 return -EBUSY; 248 247 } 249 248