| Steve Wise | cfdda9d | 2010-04-21 15:30:06 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (c) 2009-2010 Chelsio, Inc. All rights reserved. | 
 | 3 |  * | 
 | 4 |  * This software is available to you under a choice of one of two | 
 | 5 |  * licenses.  You may choose to be licensed under the terms of the GNU | 
 | 6 |  * General Public License (GPL) Version 2, available from the file | 
 | 7 |  * COPYING in the main directory of this source tree, or the | 
 | 8 |  * OpenIB.org BSD license below: | 
 | 9 |  * | 
 | 10 |  *     Redistribution and use in source and binary forms, with or | 
 | 11 |  *     without modification, are permitted provided that the following | 
 | 12 |  *     conditions are met: | 
 | 13 |  * | 
 | 14 |  *      - Redistributions of source code must retain the above | 
 | 15 |  *        copyright notice, this list of conditions and the following | 
 | 16 |  *        disclaimer. | 
 | 17 |  * | 
 | 18 |  *      - Redistributions in binary form must reproduce the above | 
 | 19 |  *        copyright notice, this list of conditions and the following | 
 | 20 |  *        disclaimer in the documentation and/or other materials | 
 | 21 |  *        provided with the distribution. | 
 | 22 |  * | 
 | 23 |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | 
 | 24 |  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | 
 | 25 |  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 
 | 26 |  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | 
 | 27 |  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | 
 | 28 |  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | 
 | 29 |  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 
 | 30 |  * SOFTWARE. | 
 | 31 |  */ | 
 | 32 | #include <linux/slab.h> | 
 | 33 | #include <linux/mman.h> | 
 | 34 | #include <net/sock.h> | 
 | 35 |  | 
 | 36 | #include "iw_cxgb4.h" | 
 | 37 |  | 
 | 38 | static void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp, | 
 | 39 | 			  struct c4iw_qp *qhp, | 
 | 40 | 			  struct t4_cqe *err_cqe, | 
 | 41 | 			  enum ib_event_type ib_event) | 
 | 42 | { | 
 | 43 | 	struct ib_event event; | 
 | 44 | 	struct c4iw_qp_attributes attrs; | 
 | 45 |  | 
 | 46 | 	if ((qhp->attr.state == C4IW_QP_STATE_ERROR) || | 
 | 47 | 	    (qhp->attr.state == C4IW_QP_STATE_TERMINATE)) { | 
 | 48 | 		PDBG("%s AE received after RTS - " | 
 | 49 | 		     "qp state %d qpid 0x%x status 0x%x\n", __func__, | 
 | 50 | 		     qhp->attr.state, qhp->wq.sq.qid, CQE_STATUS(err_cqe)); | 
 | 51 | 		return; | 
 | 52 | 	} | 
 | 53 |  | 
| Roland Dreier | be4c9ba | 2010-05-05 14:45:40 -0700 | [diff] [blame] | 54 | 	printk(KERN_ERR MOD "AE qpid 0x%x opcode %d status 0x%x " | 
 | 55 | 	       "type %d wrid.hi 0x%x wrid.lo 0x%x\n", | 
| Steve Wise | cfdda9d | 2010-04-21 15:30:06 -0700 | [diff] [blame] | 56 | 	       CQE_QPID(err_cqe), CQE_OPCODE(err_cqe), | 
 | 57 | 	       CQE_STATUS(err_cqe), CQE_TYPE(err_cqe), | 
 | 58 | 	       CQE_WRID_HI(err_cqe), CQE_WRID_LOW(err_cqe)); | 
 | 59 |  | 
 | 60 | 	if (qhp->attr.state == C4IW_QP_STATE_RTS) { | 
 | 61 | 		attrs.next_state = C4IW_QP_STATE_TERMINATE; | 
 | 62 | 		c4iw_modify_qp(qhp->rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, | 
| Steve Wise | 0e42c1f | 2010-09-10 11:15:09 -0500 | [diff] [blame] | 63 | 			       &attrs, 0); | 
| Steve Wise | cfdda9d | 2010-04-21 15:30:06 -0700 | [diff] [blame] | 64 | 	} | 
 | 65 |  | 
 | 66 | 	event.event = ib_event; | 
 | 67 | 	event.device = chp->ibcq.device; | 
 | 68 | 	if (ib_event == IB_EVENT_CQ_ERR) | 
 | 69 | 		event.element.cq = &chp->ibcq; | 
 | 70 | 	else | 
 | 71 | 		event.element.qp = &qhp->ibqp; | 
 | 72 | 	if (qhp->ibqp.event_handler) | 
 | 73 | 		(*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context); | 
 | 74 |  | 
 | 75 | 	(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context); | 
 | 76 | } | 
 | 77 |  | 
 | 78 | void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe) | 
 | 79 | { | 
 | 80 | 	struct c4iw_cq *chp; | 
 | 81 | 	struct c4iw_qp *qhp; | 
 | 82 | 	u32 cqid; | 
 | 83 |  | 
 | 84 | 	spin_lock(&dev->lock); | 
 | 85 | 	qhp = get_qhp(dev, CQE_QPID(err_cqe)); | 
 | 86 | 	if (!qhp) { | 
 | 87 | 		printk(KERN_ERR MOD "BAD AE qpid 0x%x opcode %d " | 
 | 88 | 		       "status 0x%x type %d wrid.hi 0x%x wrid.lo 0x%x\n", | 
 | 89 | 		       CQE_QPID(err_cqe), | 
 | 90 | 		       CQE_OPCODE(err_cqe), CQE_STATUS(err_cqe), | 
 | 91 | 		       CQE_TYPE(err_cqe), CQE_WRID_HI(err_cqe), | 
 | 92 | 		       CQE_WRID_LOW(err_cqe)); | 
 | 93 | 		spin_unlock(&dev->lock); | 
 | 94 | 		goto out; | 
 | 95 | 	} | 
 | 96 |  | 
 | 97 | 	if (SQ_TYPE(err_cqe)) | 
 | 98 | 		cqid = qhp->attr.scq; | 
 | 99 | 	else | 
 | 100 | 		cqid = qhp->attr.rcq; | 
 | 101 | 	chp = get_chp(dev, cqid); | 
 | 102 | 	if (!chp) { | 
 | 103 | 		printk(KERN_ERR MOD "BAD AE cqid 0x%x qpid 0x%x opcode %d " | 
 | 104 | 		       "status 0x%x type %d wrid.hi 0x%x wrid.lo 0x%x\n", | 
 | 105 | 		       cqid, CQE_QPID(err_cqe), | 
 | 106 | 		       CQE_OPCODE(err_cqe), CQE_STATUS(err_cqe), | 
 | 107 | 		       CQE_TYPE(err_cqe), CQE_WRID_HI(err_cqe), | 
 | 108 | 		       CQE_WRID_LOW(err_cqe)); | 
 | 109 | 		spin_unlock(&dev->lock); | 
 | 110 | 		goto out; | 
 | 111 | 	} | 
 | 112 |  | 
 | 113 | 	c4iw_qp_add_ref(&qhp->ibqp); | 
 | 114 | 	atomic_inc(&chp->refcnt); | 
 | 115 | 	spin_unlock(&dev->lock); | 
 | 116 |  | 
 | 117 | 	/* Bad incoming write */ | 
 | 118 | 	if (RQ_TYPE(err_cqe) && | 
 | 119 | 	    (CQE_OPCODE(err_cqe) == FW_RI_RDMA_WRITE)) { | 
 | 120 | 		post_qp_event(dev, chp, qhp, err_cqe, IB_EVENT_QP_REQ_ERR); | 
 | 121 | 		goto done; | 
 | 122 | 	} | 
 | 123 |  | 
 | 124 | 	switch (CQE_STATUS(err_cqe)) { | 
 | 125 |  | 
 | 126 | 	/* Completion Events */ | 
 | 127 | 	case T4_ERR_SUCCESS: | 
 | 128 | 		printk(KERN_ERR MOD "AE with status 0!\n"); | 
 | 129 | 		break; | 
 | 130 |  | 
 | 131 | 	case T4_ERR_STAG: | 
 | 132 | 	case T4_ERR_PDID: | 
 | 133 | 	case T4_ERR_QPID: | 
 | 134 | 	case T4_ERR_ACCESS: | 
 | 135 | 	case T4_ERR_WRAP: | 
 | 136 | 	case T4_ERR_BOUND: | 
 | 137 | 	case T4_ERR_INVALIDATE_SHARED_MR: | 
 | 138 | 	case T4_ERR_INVALIDATE_MR_WITH_MW_BOUND: | 
 | 139 | 		post_qp_event(dev, chp, qhp, err_cqe, IB_EVENT_QP_ACCESS_ERR); | 
 | 140 | 		break; | 
 | 141 |  | 
 | 142 | 	/* Device Fatal Errors */ | 
 | 143 | 	case T4_ERR_ECC: | 
 | 144 | 	case T4_ERR_ECC_PSTAG: | 
 | 145 | 	case T4_ERR_INTERNAL_ERR: | 
 | 146 | 		post_qp_event(dev, chp, qhp, err_cqe, IB_EVENT_DEVICE_FATAL); | 
 | 147 | 		break; | 
 | 148 |  | 
 | 149 | 	/* QP Fatal Errors */ | 
 | 150 | 	case T4_ERR_OUT_OF_RQE: | 
 | 151 | 	case T4_ERR_PBL_ADDR_BOUND: | 
 | 152 | 	case T4_ERR_CRC: | 
 | 153 | 	case T4_ERR_MARKER: | 
 | 154 | 	case T4_ERR_PDU_LEN_ERR: | 
 | 155 | 	case T4_ERR_DDP_VERSION: | 
 | 156 | 	case T4_ERR_RDMA_VERSION: | 
 | 157 | 	case T4_ERR_OPCODE: | 
 | 158 | 	case T4_ERR_DDP_QUEUE_NUM: | 
 | 159 | 	case T4_ERR_MSN: | 
 | 160 | 	case T4_ERR_TBIT: | 
 | 161 | 	case T4_ERR_MO: | 
 | 162 | 	case T4_ERR_MSN_GAP: | 
 | 163 | 	case T4_ERR_MSN_RANGE: | 
 | 164 | 	case T4_ERR_RQE_ADDR_BOUND: | 
 | 165 | 	case T4_ERR_IRD_OVERFLOW: | 
 | 166 | 		post_qp_event(dev, chp, qhp, err_cqe, IB_EVENT_QP_FATAL); | 
 | 167 | 		break; | 
 | 168 |  | 
 | 169 | 	default: | 
 | 170 | 		printk(KERN_ERR MOD "Unknown T4 status 0x%x QPID 0x%x\n", | 
 | 171 | 		       CQE_STATUS(err_cqe), qhp->wq.sq.qid); | 
 | 172 | 		post_qp_event(dev, chp, qhp, err_cqe, IB_EVENT_QP_FATAL); | 
 | 173 | 		break; | 
 | 174 | 	} | 
 | 175 | done: | 
 | 176 | 	if (atomic_dec_and_test(&chp->refcnt)) | 
 | 177 | 		wake_up(&chp->wait); | 
 | 178 | 	c4iw_qp_rem_ref(&qhp->ibqp); | 
 | 179 | out: | 
 | 180 | 	return; | 
 | 181 | } | 
 | 182 |  | 
 | 183 | int c4iw_ev_handler(struct c4iw_dev *dev, u32 qid) | 
 | 184 | { | 
 | 185 | 	struct c4iw_cq *chp; | 
 | 186 |  | 
 | 187 | 	chp = get_chp(dev, qid); | 
 | 188 | 	if (chp) | 
 | 189 | 		(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context); | 
 | 190 | 	else | 
 | 191 | 		PDBG("%s unknown cqid 0x%x\n", __func__, qid); | 
 | 192 | 	return 0; | 
 | 193 | } |