1/************************************************************************** 2 3Copyright (c) 2007, Chelsio Inc. 4All rights reserved. 5 6Redistribution and use in source and binary forms, with or without 7modification, 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 16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26POSSIBILITY OF SUCH DAMAGE. 27 28***************************************************************************/ 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD: releng/10.2/sys/dev/cxgb/ulp/iw_cxgb/iw_cxgb_ev.c 237263 2012-06-19 07:34:13Z np $"); 31 32#include "opt_inet.h" 33 34#ifdef TCP_OFFLOAD 35#include <sys/param.h> 36#include <sys/systm.h> 37#include <sys/kernel.h> 38#include <sys/bus.h> 39#include <sys/pciio.h> 40#include <sys/conf.h> 41#include <machine/bus.h> 42#include <machine/resource.h> 43#include <sys/bus_dma.h> 44#include <sys/rman.h> 45#include <sys/ioccom.h> 46#include <sys/mbuf.h> 47#include <sys/mutex.h> 48#include <sys/rwlock.h> 49#include <sys/linker.h> 50#include <sys/firmware.h> 51#include <sys/socket.h> 52#include <sys/sockio.h> 53#include <sys/smp.h> 54#include <sys/sysctl.h> 55#include <sys/syslog.h> 56#include <sys/queue.h> 57#include <sys/taskqueue.h> 58#include <sys/proc.h> 59#include <sys/queue.h> 60#include <sys/libkern.h> 61 62#include <netinet/in.h> 63 64#include <rdma/ib_verbs.h> 65#include <rdma/ib_umem.h> 66#include <rdma/ib_user_verbs.h> 67#include <linux/idr.h> 68#include <ulp/iw_cxgb/iw_cxgb_ib_intfc.h> 69 70#include <cxgb_include.h> 71#include <ulp/iw_cxgb/iw_cxgb_wr.h> 72#include <ulp/iw_cxgb/iw_cxgb_hal.h> 73#include <ulp/iw_cxgb/iw_cxgb_provider.h> 74#include <ulp/iw_cxgb/iw_cxgb_cm.h> 75#include <ulp/iw_cxgb/iw_cxgb.h> 76#include <ulp/iw_cxgb/iw_cxgb_resource.h> 77#include <ulp/iw_cxgb/iw_cxgb_user.h> 78 79static void 80post_qp_event(struct iwch_dev *rnicp, struct iwch_qp *qhp, struct iwch_cq *chp, 81 struct respQ_msg_t *rsp_msg, 82 enum ib_event_type ib_event, 83 int send_term) 84{ 85 struct ib_event event; 86 struct iwch_qp_attributes attrs; 87 88 mtx_lock(&rnicp->lock); 89 90 if (!qhp) { 91 CTR3(KTR_IW_CXGB, "%s unaffiliated error 0x%x qpid 0x%x\n", 92 __func__, CQE_STATUS(rsp_msg->cqe), 93 CQE_QPID(rsp_msg->cqe)); 94 mtx_unlock(&rnicp->lock); 95 return; 96 } 97 98 if ((qhp->attr.state == IWCH_QP_STATE_ERROR) || 99 (qhp->attr.state == IWCH_QP_STATE_TERMINATE)) { 100 CTR4(KTR_IW_CXGB, "%s AE received after RTS - " 101 "qp state %d qpid 0x%x status 0x%x", __FUNCTION__, 102 qhp->attr.state, qhp->wq.qpid, CQE_STATUS(rsp_msg->cqe)); 103 mtx_unlock(&rnicp->lock); 104 return; 105 } 106 107 log(LOG_ERR, "%s - AE qpid 0x%x opcode %d status 0x%x " 108 "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __FUNCTION__, 109 CQE_QPID(rsp_msg->cqe), CQE_OPCODE(rsp_msg->cqe), 110 CQE_STATUS(rsp_msg->cqe), CQE_TYPE(rsp_msg->cqe), 111 CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe)); 112 113 mtx_unlock(&rnicp->lock); 114 115 if (qhp->attr.state == IWCH_QP_STATE_RTS) { 116 attrs.next_state = IWCH_QP_STATE_TERMINATE; 117 iwch_modify_qp(qhp->rhp, qhp, IWCH_QP_ATTR_NEXT_STATE, 118 &attrs, 1); 119 if (send_term) 120 iwch_post_terminate(qhp, rsp_msg); 121 } 122 123 event.event = ib_event; 124 event.device = chp->ibcq.device; 125 if (ib_event == IB_EVENT_CQ_ERR) 126 event.element.cq = &chp->ibcq; 127 else 128 event.element.qp = &qhp->ibqp; 129 130 if (qhp->ibqp.event_handler) 131 (*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context); 132 133 (*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context); 134} 135 136void 137iwch_ev_dispatch(struct iwch_dev *rnicp, struct mbuf *m) 138{ 139 struct respQ_msg_t *rsp_msg = (struct respQ_msg_t *) m->m_data; 140 struct iwch_cq *chp; 141 struct iwch_qp *qhp; 142 u32 cqid = RSPQ_CQID(rsp_msg); 143 144 mtx_lock(&rnicp->lock); 145 chp = get_chp(rnicp, cqid); 146 qhp = get_qhp(rnicp, CQE_QPID(rsp_msg->cqe)); 147 if (!chp || !qhp) { 148 log(LOG_ERR,"BAD AE cqid 0x%x qpid 0x%x opcode %d " 149 "status 0x%x type %d wrid.hi 0x%x wrid.lo 0x%x \n", 150 cqid, CQE_QPID(rsp_msg->cqe), 151 CQE_OPCODE(rsp_msg->cqe), CQE_STATUS(rsp_msg->cqe), 152 CQE_TYPE(rsp_msg->cqe), CQE_WRID_HI(rsp_msg->cqe), 153 CQE_WRID_LOW(rsp_msg->cqe)); 154 mtx_unlock(&rnicp->lock); 155 return; 156 } 157 iwch_qp_add_ref(&qhp->ibqp); 158 mtx_lock(&chp->lock); 159 ++chp->refcnt; 160 mtx_unlock(&chp->lock); 161 mtx_unlock(&rnicp->lock); 162 163 /* 164 * 1) completion of our sending a TERMINATE. 165 * 2) incoming TERMINATE message. 166 */ 167 if ((CQE_OPCODE(rsp_msg->cqe) == T3_TERMINATE) && 168 (CQE_STATUS(rsp_msg->cqe) == 0)) { 169 if (SQ_TYPE(rsp_msg->cqe)) { 170 CTR3(KTR_IW_CXGB, "%s QPID 0x%x ep %p disconnecting", 171 __FUNCTION__, qhp->wq.qpid, qhp->ep); 172 iwch_ep_disconnect(qhp->ep, 0, M_NOWAIT); 173 } else { 174 CTR2(KTR_IW_CXGB, "%s post REQ_ERR AE QPID 0x%x", __FUNCTION__, 175 qhp->wq.qpid); 176 post_qp_event(rnicp, qhp, chp, rsp_msg, 177 IB_EVENT_QP_REQ_ERR, 0); 178 iwch_ep_disconnect(qhp->ep, 0, M_NOWAIT); 179 } 180 goto done; 181 } 182 183 /* Bad incoming Read request */ 184 if (SQ_TYPE(rsp_msg->cqe) && 185 (CQE_OPCODE(rsp_msg->cqe) == T3_READ_RESP)) { 186 post_qp_event(rnicp, qhp, chp, rsp_msg, IB_EVENT_QP_REQ_ERR, 1); 187 goto done; 188 } 189 190 /* Bad incoming write */ 191 if (RQ_TYPE(rsp_msg->cqe) && 192 (CQE_OPCODE(rsp_msg->cqe) == T3_RDMA_WRITE)) { 193 post_qp_event(rnicp, qhp, chp, rsp_msg, IB_EVENT_QP_REQ_ERR, 1); 194 goto done; 195 } 196 197 switch (CQE_STATUS(rsp_msg->cqe)) { 198 199 /* Completion Events */ 200 case TPT_ERR_SUCCESS: 201#if 0 202 /* 203 * Confirm the destination entry if this is a RECV completion. 204 */ 205 if (qhp->ep && SQ_TYPE(rsp_msg->cqe)) 206 dst_confirm(qhp->ep->dst); 207#endif 208 (*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context); 209 break; 210 211 case TPT_ERR_STAG: 212 case TPT_ERR_PDID: 213 case TPT_ERR_QPID: 214 case TPT_ERR_ACCESS: 215 case TPT_ERR_WRAP: 216 case TPT_ERR_BOUND: 217 case TPT_ERR_INVALIDATE_SHARED_MR: 218 case TPT_ERR_INVALIDATE_MR_WITH_MW_BOUND: 219 post_qp_event(rnicp, qhp, chp, rsp_msg, IB_EVENT_QP_ACCESS_ERR, 1); 220 break; 221 222 /* Device Fatal Errors */ 223 case TPT_ERR_ECC: 224 case TPT_ERR_ECC_PSTAG: 225 case TPT_ERR_INTERNAL_ERR: 226 post_qp_event(rnicp, qhp, chp, rsp_msg, IB_EVENT_DEVICE_FATAL, 1); 227 break; 228 229 /* QP Fatal Errors */ 230 case TPT_ERR_OUT_OF_RQE: 231 case TPT_ERR_PBL_ADDR_BOUND: 232 case TPT_ERR_CRC: 233 case TPT_ERR_MARKER: 234 case TPT_ERR_PDU_LEN_ERR: 235 case TPT_ERR_DDP_VERSION: 236 case TPT_ERR_RDMA_VERSION: 237 case TPT_ERR_OPCODE: 238 case TPT_ERR_DDP_QUEUE_NUM: 239 case TPT_ERR_MSN: 240 case TPT_ERR_TBIT: 241 case TPT_ERR_MO: 242 case TPT_ERR_MSN_GAP: 243 case TPT_ERR_MSN_RANGE: 244 case TPT_ERR_RQE_ADDR_BOUND: 245 case TPT_ERR_IRD_OVERFLOW: 246 post_qp_event(rnicp, qhp, chp, rsp_msg, IB_EVENT_QP_FATAL, 1); 247 break; 248 249 default: 250 log(LOG_ERR,"Unknown T3 status 0x%x QPID 0x%x\n", 251 CQE_STATUS(rsp_msg->cqe), qhp->wq.qpid); 252 post_qp_event(rnicp, qhp, chp, rsp_msg, IB_EVENT_QP_FATAL, 1); 253 break; 254 } 255done: 256 mtx_lock(&chp->lock); 257 if (--chp->refcnt == 0) 258 wakeup(chp); 259 mtx_unlock(&chp->lock); 260 iwch_qp_rem_ref(&qhp->ibqp); 261} 262#endif 263