]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/dev/cxgb/ulp/iw_cxgb/iw_cxgb_ev.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / dev / cxgb / ulp / iw_cxgb / iw_cxgb_ev.c
1 /**************************************************************************
2
3 Copyright (c) 2007, Chelsio Inc.
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8
9  1. Redistributions of source code must retain the above copyright notice,
10     this list of conditions and the following disclaimer.
11
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.
15
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.
27
28 ***************************************************************************/
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/bus.h>
36 #include <sys/module.h>
37 #include <sys/pciio.h>
38 #include <sys/conf.h>
39 #include <machine/bus.h>
40 #include <machine/resource.h>
41 #include <sys/bus_dma.h>
42 #include <sys/rman.h>
43 #include <sys/ioccom.h>
44 #include <sys/mbuf.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>
51 #include <sys/smp.h>
52 #include <sys/sysctl.h>
53 #include <sys/syslog.h>
54 #include <sys/queue.h>
55 #include <sys/taskqueue.h>
56 #include <sys/proc.h>
57 #include <sys/queue.h>
58 #include <sys/libkern.h>
59
60 #include <netinet/in.h>
61
62 #include <contrib/rdma/ib_verbs.h>
63 #include <contrib/rdma/ib_umem.h>
64 #include <contrib/rdma/ib_user_verbs.h>
65
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>
74
75 static void
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,
79                 int send_term)
80 {
81         struct ib_event event;
82         struct iwch_qp_attributes attrs;
83
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));
89                 return;
90         }
91
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));
97
98
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;
103         else
104                 event.element.qp = &qhp->ibqp;
105
106         if (qhp->ibqp.event_handler)
107                 (*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context);
108
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,
112                                &attrs, 1);
113                 if (send_term)
114                         iwch_post_terminate(qhp, rsp_msg);
115         }
116 }
117
118 void
119 iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct mbuf *m)
120 {
121         struct iwch_dev *rnicp;
122         struct respQ_msg_t *rsp_msg = (struct respQ_msg_t *) m->m_data;
123         struct iwch_cq *chp;
124         struct iwch_qp *qhp;
125         u32 cqid = RSPQ_CQID(rsp_msg);
126
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));
131         if (!chp || !qhp) {
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);
139                 goto out;
140         }
141         iwch_qp_add_ref(&qhp->ibqp);
142         mtx_lock(&chp->lock);
143         ++chp->refcnt;
144         mtx_unlock(&chp->lock);
145         mtx_unlock(&rnicp->lock);
146
147         /*
148          * 1) completion of our sending a TERMINATE.
149          * 2) incoming TERMINATE message.
150          */
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);
157                 } else {
158                         CTR2(KTR_IW_CXGB, "%s post REQ_ERR AE QPID 0x%x", __FUNCTION__,
159                              qhp->wq.qpid);
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);
163                 }
164                 goto done;
165         }
166
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);
171                 goto done;
172         }
173
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);
178                 goto done;
179         }
180
181         switch (CQE_STATUS(rsp_msg->cqe)) {
182
183         /* Completion Events */
184         case TPT_ERR_SUCCESS:
185 #if 0
186                 /*
187                  * Confirm the destination entry if this is a RECV completion.
188                  */
189                 if (qhp->ep && SQ_TYPE(rsp_msg->cqe))
190                         dst_confirm(qhp->ep->dst);
191 #endif          
192                 (*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
193                 break;
194
195         case TPT_ERR_STAG:
196         case TPT_ERR_PDID:
197         case TPT_ERR_QPID:
198         case TPT_ERR_ACCESS:
199         case TPT_ERR_WRAP:
200         case TPT_ERR_BOUND:
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);
210                 break;
211
212         /* Device Fatal Errors */
213         case TPT_ERR_ECC:
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);
217                 break;
218
219         /* QP Fatal Errors */
220         case TPT_ERR_OUT_OF_RQE:
221         case TPT_ERR_PBL_ADDR_BOUND:
222         case TPT_ERR_CRC:
223         case TPT_ERR_MARKER:
224         case TPT_ERR_PDU_LEN_ERR:
225         case TPT_ERR_DDP_VERSION:
226         case TPT_ERR_RDMA_VERSION:
227         case TPT_ERR_OPCODE:
228         case TPT_ERR_DDP_QUEUE_NUM:
229         case TPT_ERR_MSN:
230         case TPT_ERR_TBIT:
231         case TPT_ERR_MO:
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);
237                 break;
238
239         default:
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);
243                 break;
244         }
245 done:
246         mtx_lock(&chp->lock);
247         if (--chp->refcnt == 0)
248                 wakeup(chp);
249         mtx_unlock(&chp->lock);
250         iwch_qp_rem_ref(&qhp->ibqp);
251 out:
252         m_free(m);
253 }