Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
0002 /*
0003  * Copyright(c) 2016 - 2018 Intel Corporation.
0004  */
0005 
0006 #include "hfi.h"
0007 #include "verbs_txreq.h"
0008 #include "qp.h"
0009 #include "trace.h"
0010 
0011 #define TXREQ_LEN 24
0012 
0013 void hfi1_put_txreq(struct verbs_txreq *tx)
0014 {
0015     struct hfi1_ibdev *dev;
0016     struct rvt_qp *qp;
0017     unsigned long flags;
0018     unsigned int seq;
0019     struct hfi1_qp_priv *priv;
0020 
0021     qp = tx->qp;
0022     dev = to_idev(qp->ibqp.device);
0023 
0024     if (tx->mr)
0025         rvt_put_mr(tx->mr);
0026 
0027     sdma_txclean(dd_from_dev(dev), &tx->txreq);
0028 
0029     /* Free verbs_txreq and return to slab cache */
0030     kmem_cache_free(dev->verbs_txreq_cache, tx);
0031 
0032     do {
0033         seq = read_seqbegin(&dev->txwait_lock);
0034         if (!list_empty(&dev->txwait)) {
0035             struct iowait *wait;
0036 
0037             write_seqlock_irqsave(&dev->txwait_lock, flags);
0038             wait = list_first_entry(&dev->txwait, struct iowait,
0039                         list);
0040             qp = iowait_to_qp(wait);
0041             priv = qp->priv;
0042             list_del_init(&priv->s_iowait.list);
0043             /* refcount held until actual wake up */
0044             write_sequnlock_irqrestore(&dev->txwait_lock, flags);
0045             hfi1_qp_wakeup(qp, RVT_S_WAIT_TX);
0046             break;
0047         }
0048     } while (read_seqretry(&dev->txwait_lock, seq));
0049 }
0050 
0051 struct verbs_txreq *__get_txreq(struct hfi1_ibdev *dev,
0052                 struct rvt_qp *qp)
0053     __must_hold(&qp->s_lock)
0054 {
0055     struct verbs_txreq *tx = NULL;
0056 
0057     write_seqlock(&dev->txwait_lock);
0058     if (ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK) {
0059         struct hfi1_qp_priv *priv;
0060 
0061         tx = kmem_cache_alloc(dev->verbs_txreq_cache, VERBS_TXREQ_GFP);
0062         if (tx)
0063             goto out;
0064         priv = qp->priv;
0065         if (list_empty(&priv->s_iowait.list)) {
0066             dev->n_txwait++;
0067             qp->s_flags |= RVT_S_WAIT_TX;
0068             list_add_tail(&priv->s_iowait.list, &dev->txwait);
0069             priv->s_iowait.lock = &dev->txwait_lock;
0070             trace_hfi1_qpsleep(qp, RVT_S_WAIT_TX);
0071             rvt_get_qp(qp);
0072         }
0073         qp->s_flags &= ~RVT_S_BUSY;
0074     }
0075 out:
0076     write_sequnlock(&dev->txwait_lock);
0077     return tx;
0078 }
0079 
0080 int verbs_txreq_init(struct hfi1_ibdev *dev)
0081 {
0082     char buf[TXREQ_LEN];
0083     struct hfi1_devdata *dd = dd_from_dev(dev);
0084 
0085     snprintf(buf, sizeof(buf), "hfi1_%u_vtxreq_cache", dd->unit);
0086     dev->verbs_txreq_cache = kmem_cache_create(buf,
0087                            sizeof(struct verbs_txreq),
0088                            0, SLAB_HWCACHE_ALIGN,
0089                            NULL);
0090     if (!dev->verbs_txreq_cache)
0091         return -ENOMEM;
0092     return 0;
0093 }
0094 
0095 void verbs_txreq_exit(struct hfi1_ibdev *dev)
0096 {
0097     kmem_cache_destroy(dev->verbs_txreq_cache);
0098     dev->verbs_txreq_cache = NULL;
0099 }