2 /**************************************************************************
4 Copyright (c) 2007, Chelsio Inc.
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
10 1. Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
13 2. Neither the name of the Chelsio Corporation nor the names of its
14 contributors may be used to endorse or promote products derived from
15 this software without specific prior written permission.
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 POSSIBILITY OF SUCH DAMAGE.
29 ***************************************************************************/
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
37 #include <sys/module.h>
38 #include <sys/pciio.h>
40 #include <machine/bus.h>
41 #include <machine/resource.h>
42 #include <sys/bus_dma.h>
44 #include <sys/ioccom.h>
46 #include <sys/mutex.h>
47 #include <sys/rwlock.h>
48 #include <sys/linker.h>
49 #include <sys/firmware.h>
50 #include <sys/socket.h>
51 #include <sys/sockio.h>
53 #include <sys/sysctl.h>
54 #include <sys/syslog.h>
55 #include <sys/queue.h>
56 #include <sys/taskqueue.h>
58 #include <sys/queue.h>
59 #include <sys/libkern.h>
61 #include <netinet/in.h>
62 #include <contrib/rdma/ib_verbs.h>
63 #include <contrib/rdma/ib_umem.h>
64 #include <contrib/rdma/ib_user_verbs.h>
66 #include <cxgb_include.h>
67 #include <ulp/iw_cxgb/iw_cxgb_wr.h>
68 #include <ulp/iw_cxgb/iw_cxgb_hal.h>
69 #include <ulp/iw_cxgb/iw_cxgb_provider.h>
70 #include <ulp/iw_cxgb/iw_cxgb_cm.h>
71 #include <ulp/iw_cxgb/iw_cxgb.h>
72 #include <ulp/iw_cxgb/iw_cxgb_resource.h>
73 #include <ulp/iw_cxgb/iw_cxgb_user.h>
76 * Get one cq entry from cxio and map it to openib.
81 * -EAGAIN caller must try again
82 * any other neg errno fatal error
84 static int iwch_poll_cq_one(struct iwch_dev *rhp, struct iwch_cq *chp,
87 struct iwch_qp *qhp = NULL;
88 struct t3_cqe cqe, *rd_cqe;
95 rd_cqe = cxio_next_cqe(&chp->cq);
100 qhp = get_qhp(rhp, CQE_QPID(*rd_cqe));
104 mtx_lock(&qhp->lock);
107 ret = cxio_poll_cq(wq, &(chp->cq), &cqe, &cqe_flushed, &cookie,
109 if (t3a_device(chp->rhp) && credit) {
110 CTR3(KTR_IW_CXGB, "%s updating %d cq credits on id %d", __FUNCTION__,
111 credit, chp->cq.cqid);
112 cxio_hal_cq_op(&rhp->rdev, &chp->cq, CQ_CREDIT_UPDATE, credit);
123 wc->vendor_err = CQE_STATUS(cqe);
125 CTR4(KTR_IW_CXGB, "iwch_poll_cq_one qpid 0x%x type %d opcode %d status 0x%x",
126 CQE_QPID(cqe), CQE_TYPE(cqe),
127 CQE_OPCODE(cqe), CQE_STATUS(cqe));
128 CTR3(KTR_IW_CXGB, "wrid hi 0x%x lo 0x%x cookie 0x%llx",
129 CQE_WRID_HI(cqe), CQE_WRID_LOW(cqe), (unsigned long long) cookie);
131 if (CQE_TYPE(cqe) == 0) {
132 if (!CQE_STATUS(cqe))
133 wc->byte_len = CQE_LEN(cqe);
136 wc->opcode = IB_WC_RECV;
138 switch (CQE_OPCODE(cqe)) {
140 wc->opcode = IB_WC_RDMA_WRITE;
143 wc->opcode = IB_WC_RDMA_READ;
144 wc->byte_len = CQE_LEN(cqe);
147 case T3_SEND_WITH_SE:
148 wc->opcode = IB_WC_SEND;
151 wc->opcode = IB_WC_BIND_MW;
154 /* these aren't supported yet */
155 case T3_SEND_WITH_INV:
156 case T3_SEND_WITH_SE_INV:
158 case T3_FAST_REGISTER:
160 log(LOG_ERR, "Unexpected opcode %d "
161 "in the CQE received for QPID=0x%0x\n",
162 CQE_OPCODE(cqe), CQE_QPID(cqe));
169 wc->status = IB_WC_WR_FLUSH_ERR;
172 switch (CQE_STATUS(cqe)) {
173 case TPT_ERR_SUCCESS:
174 wc->status = IB_WC_SUCCESS;
177 wc->status = IB_WC_LOC_ACCESS_ERR;
180 wc->status = IB_WC_LOC_PROT_ERR;
184 wc->status = IB_WC_LOC_ACCESS_ERR;
187 wc->status = IB_WC_GENERAL_ERR;
190 wc->status = IB_WC_LOC_LEN_ERR;
192 case TPT_ERR_INVALIDATE_SHARED_MR:
193 case TPT_ERR_INVALIDATE_MR_WITH_MW_BOUND:
194 wc->status = IB_WC_MW_BIND_ERR;
198 case TPT_ERR_PDU_LEN_ERR:
199 case TPT_ERR_OUT_OF_RQE:
200 case TPT_ERR_DDP_VERSION:
201 case TPT_ERR_RDMA_VERSION:
202 case TPT_ERR_DDP_QUEUE_NUM:
206 case TPT_ERR_MSN_RANGE:
207 case TPT_ERR_IRD_OVERFLOW:
209 wc->status = IB_WC_FATAL_ERR;
211 case TPT_ERR_SWFLUSH:
212 wc->status = IB_WC_WR_FLUSH_ERR;
215 log(LOG_ERR, "Unexpected cqe_status 0x%x for "
216 "QPID=0x%0x\n", CQE_STATUS(cqe), CQE_QPID(cqe));
222 mtx_unlock(&qhp->lock);
226 int iwch_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
228 struct iwch_dev *rhp;
233 chp = to_iwch_cq(ibcq);
236 mtx_lock(&chp->lock);
237 for (npolled = 0; npolled < num_entries; ++npolled) {
243 * Because T3 can post CQEs that are _not_ associated
244 * with a WR, we might have to poll again after removing
248 err = iwch_poll_cq_one(rhp, chp, wc + npolled);
250 PANIC_IF(++i > 1000);
252 } while (err == -EAGAIN);
256 mtx_unlock(&chp->lock);