1 /**************************************************************************
3 Copyright (c) 2007, Chelsio Inc.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
9 1. Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
12 2. Neither the name of the Chelsio Corporation nor the names of its
13 contributors may be used to endorse or promote products derived from
14 this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 POSSIBILITY OF SUCH DAMAGE.
28 ***************************************************************************/
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
36 #include <sys/module.h>
37 #include <sys/pciio.h>
39 #include <machine/bus.h>
40 #include <machine/resource.h>
41 #include <sys/bus_dma.h>
43 #include <sys/ioccom.h>
45 #include <sys/mutex.h>
46 #include <sys/rwlock.h>
47 #include <sys/linker.h>
48 #include <sys/firmware.h>
49 #include <sys/socket.h>
50 #include <sys/sockio.h>
52 #include <sys/sysctl.h>
53 #include <sys/syslog.h>
54 #include <sys/queue.h>
55 #include <sys/taskqueue.h>
57 #include <sys/queue.h>
58 #include <sys/libkern.h>
60 #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 post_qp_event(struct iwch_dev *rnicp, struct iwch_qp *qhp, struct iwch_cq *chp,
77 struct respQ_msg_t *rsp_msg,
78 enum ib_event_type ib_event,
81 struct ib_event event;
82 struct iwch_qp_attributes attrs;
84 if ((qhp->attr.state == IWCH_QP_STATE_ERROR) ||
85 (qhp->attr.state == IWCH_QP_STATE_TERMINATE)) {
86 CTR4(KTR_IW_CXGB, "%s AE received after RTS - "
87 "qp state %d qpid 0x%x status 0x%x", __FUNCTION__,
88 qhp->attr.state, qhp->wq.qpid, CQE_STATUS(rsp_msg->cqe));
92 log(LOG_ERR, "%s - AE qpid 0x%x opcode %d status 0x%x "
93 "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __FUNCTION__,
94 CQE_QPID(rsp_msg->cqe), CQE_OPCODE(rsp_msg->cqe),
95 CQE_STATUS(rsp_msg->cqe), CQE_TYPE(rsp_msg->cqe),
96 CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe));
99 event.event = ib_event;
100 event.device = chp->ibcq.device;
101 if (ib_event == IB_EVENT_CQ_ERR)
102 event.element.cq = &chp->ibcq;
104 event.element.qp = &qhp->ibqp;
106 if (qhp->ibqp.event_handler)
107 (*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context);
109 if (qhp->attr.state == IWCH_QP_STATE_RTS) {
110 attrs.next_state = IWCH_QP_STATE_TERMINATE;
111 iwch_modify_qp(qhp->rhp, qhp, IWCH_QP_ATTR_NEXT_STATE,
114 iwch_post_terminate(qhp, rsp_msg);
119 iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct mbuf *m)
121 struct iwch_dev *rnicp;
122 struct respQ_msg_t *rsp_msg = (struct respQ_msg_t *) m->m_data;
125 u32 cqid = RSPQ_CQID(rsp_msg);
127 rnicp = (struct iwch_dev *) rdev_p->ulp;
128 mtx_lock(&rnicp->lock);
129 chp = get_chp(rnicp, cqid);
130 qhp = get_qhp(rnicp, CQE_QPID(rsp_msg->cqe));
132 log(LOG_ERR,"BAD AE cqid 0x%x qpid 0x%x opcode %d "
133 "status 0x%x type %d wrid.hi 0x%x wrid.lo 0x%x \n",
134 cqid, CQE_QPID(rsp_msg->cqe),
135 CQE_OPCODE(rsp_msg->cqe), CQE_STATUS(rsp_msg->cqe),
136 CQE_TYPE(rsp_msg->cqe), CQE_WRID_HI(rsp_msg->cqe),
137 CQE_WRID_LOW(rsp_msg->cqe));
138 mtx_unlock(&rnicp->lock);
141 iwch_qp_add_ref(&qhp->ibqp);
142 mtx_lock(&chp->lock);
144 mtx_unlock(&chp->lock);
145 mtx_unlock(&rnicp->lock);
148 * 1) completion of our sending a TERMINATE.
149 * 2) incoming TERMINATE message.
151 if ((CQE_OPCODE(rsp_msg->cqe) == T3_TERMINATE) &&
152 (CQE_STATUS(rsp_msg->cqe) == 0)) {
153 if (SQ_TYPE(rsp_msg->cqe)) {
154 CTR3(KTR_IW_CXGB, "%s QPID 0x%x ep %p disconnecting",
155 __FUNCTION__, qhp->wq.qpid, qhp->ep);
156 iwch_ep_disconnect(qhp->ep, 0, M_NOWAIT);
158 CTR2(KTR_IW_CXGB, "%s post REQ_ERR AE QPID 0x%x", __FUNCTION__,
160 post_qp_event(rnicp, qhp, chp, rsp_msg,
161 IB_EVENT_QP_REQ_ERR, 0);
162 iwch_ep_disconnect(qhp->ep, 0, M_NOWAIT);
167 /* Bad incoming Read request */
168 if (SQ_TYPE(rsp_msg->cqe) &&
169 (CQE_OPCODE(rsp_msg->cqe) == T3_READ_RESP)) {
170 post_qp_event(rnicp, qhp, chp, rsp_msg, IB_EVENT_QP_REQ_ERR, 1);
174 /* Bad incoming write */
175 if (RQ_TYPE(rsp_msg->cqe) &&
176 (CQE_OPCODE(rsp_msg->cqe) == T3_RDMA_WRITE)) {
177 post_qp_event(rnicp, qhp, chp, rsp_msg, IB_EVENT_QP_REQ_ERR, 1);
181 switch (CQE_STATUS(rsp_msg->cqe)) {
183 /* Completion Events */
184 case TPT_ERR_SUCCESS:
187 * Confirm the destination entry if this is a RECV completion.
189 if (qhp->ep && SQ_TYPE(rsp_msg->cqe))
190 dst_confirm(qhp->ep->dst);
192 (*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
201 case TPT_ERR_INVALIDATE_SHARED_MR:
202 case TPT_ERR_INVALIDATE_MR_WITH_MW_BOUND:
203 log(LOG_ERR, "%s - CQE Err qpid 0x%x opcode %d status 0x%x "
204 "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __FUNCTION__,
205 CQE_QPID(rsp_msg->cqe), CQE_OPCODE(rsp_msg->cqe),
206 CQE_STATUS(rsp_msg->cqe), CQE_TYPE(rsp_msg->cqe),
207 CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe));
208 (*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
209 post_qp_event(rnicp, qhp, chp, rsp_msg, IB_EVENT_QP_ACCESS_ERR, 1);
212 /* Device Fatal Errors */
214 case TPT_ERR_ECC_PSTAG:
215 case TPT_ERR_INTERNAL_ERR:
216 post_qp_event(rnicp, qhp, chp, rsp_msg, IB_EVENT_DEVICE_FATAL, 1);
219 /* QP Fatal Errors */
220 case TPT_ERR_OUT_OF_RQE:
221 case TPT_ERR_PBL_ADDR_BOUND:
224 case TPT_ERR_PDU_LEN_ERR:
225 case TPT_ERR_DDP_VERSION:
226 case TPT_ERR_RDMA_VERSION:
228 case TPT_ERR_DDP_QUEUE_NUM:
232 case TPT_ERR_MSN_GAP:
233 case TPT_ERR_MSN_RANGE:
234 case TPT_ERR_RQE_ADDR_BOUND:
235 case TPT_ERR_IRD_OVERFLOW:
236 post_qp_event(rnicp, qhp, chp, rsp_msg, IB_EVENT_QP_FATAL, 1);
240 log(LOG_ERR,"Unknown T3 status 0x%x QPID 0x%x\n",
241 CQE_STATUS(rsp_msg->cqe), qhp->wq.qpid);
242 post_qp_event(rnicp, qhp, chp, rsp_msg, IB_EVENT_QP_FATAL, 1);
246 mtx_lock(&chp->lock);
247 if (--chp->refcnt == 0)
249 mtx_unlock(&chp->lock);
250 iwch_qp_rem_ref(&qhp->ibqp);