1331722Seadler/* 2256694Snp * Copyright (c) 2009-2013 Chelsio, Inc. All rights reserved. 3256694Snp * 4256694Snp * This software is available to you under a choice of one of two 5256694Snp * licenses. You may choose to be licensed under the terms of the GNU 6256694Snp * General Public License (GPL) Version 2, available from the file 7256694Snp * COPYING in the main directory of this source tree, or the 8256694Snp * OpenIB.org BSD license below: 9256694Snp * 10256694Snp * Redistribution and use in source and binary forms, with or 11256694Snp * without modification, are permitted provided that the following 12256694Snp * conditions are met: 13256694Snp * 14256694Snp * - Redistributions of source code must retain the above 15256694Snp * copyright notice, this list of conditions and the following 16256694Snp * disclaimer. 17256694Snp * 18256694Snp * - Redistributions in binary form must reproduce the above 19256694Snp * copyright notice, this list of conditions and the following 20256694Snp * disclaimer in the documentation and/or other materials 21256694Snp * provided with the distribution. 22256694Snp * 23256694Snp * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24256694Snp * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25256694Snp * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26256694Snp * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27256694Snp * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28256694Snp * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29256694Snp * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30256694Snp * SOFTWARE. 31256694Snp */ 32256694Snp#include <sys/cdefs.h> 33256694Snp__FBSDID("$FreeBSD$"); 34256694Snp 35256694Snp#include "opt_inet.h" 36256694Snp 37256694Snp#ifdef TCP_OFFLOAD 38256694Snp#include <linux/slab.h> 39256694Snp 40256694Snp#include "iw_cxgbe.h" 41256694Snp 42256694Snpstatic void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp, 43256694Snp struct c4iw_qp *qhp, 44256694Snp struct t4_cqe *err_cqe, 45256694Snp enum ib_event_type ib_event) 46256694Snp{ 47256694Snp struct ib_event event; 48256694Snp struct c4iw_qp_attributes attrs; 49256694Snp unsigned long flag; 50256694Snp 51256694Snp if ((qhp->attr.state == C4IW_QP_STATE_ERROR) || 52256694Snp (qhp->attr.state == C4IW_QP_STATE_TERMINATE)) { 53256694Snp CTR4(KTR_IW_CXGBE, "%s AE received after RTS - " 54256694Snp "qp state %d qpid 0x%x status 0x%x", __func__, 55256694Snp qhp->attr.state, qhp->wq.sq.qid, CQE_STATUS(err_cqe)); 56256694Snp return; 57256694Snp } 58256694Snp 59256694Snp printf("AE qpid 0x%x opcode %d status 0x%x " 60256694Snp "type %d wrid.hi 0x%x wrid.lo 0x%x\n", 61256694Snp CQE_QPID(err_cqe), CQE_OPCODE(err_cqe), 62256694Snp CQE_STATUS(err_cqe), CQE_TYPE(err_cqe), 63256694Snp CQE_WRID_HI(err_cqe), CQE_WRID_LOW(err_cqe)); 64256694Snp 65256694Snp if (qhp->attr.state == C4IW_QP_STATE_RTS) { 66256694Snp attrs.next_state = C4IW_QP_STATE_TERMINATE; 67256694Snp c4iw_modify_qp(qhp->rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, 68256694Snp &attrs, 0); 69256694Snp } 70256694Snp 71256694Snp event.event = ib_event; 72256694Snp event.device = chp->ibcq.device; 73256694Snp if (ib_event == IB_EVENT_CQ_ERR) 74256694Snp event.element.cq = &chp->ibcq; 75256694Snp else 76256694Snp event.element.qp = &qhp->ibqp; 77256694Snp if (qhp->ibqp.event_handler) 78256694Snp (*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context); 79256694Snp 80256694Snp spin_lock_irqsave(&chp->comp_handler_lock, flag); 81256694Snp (*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context); 82256694Snp spin_unlock_irqrestore(&chp->comp_handler_lock, flag); 83256694Snp} 84256694Snp 85256694Snpvoid c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe) 86256694Snp{ 87256694Snp struct c4iw_cq *chp; 88256694Snp struct c4iw_qp *qhp; 89256694Snp u32 cqid; 90256694Snp 91256694Snp spin_lock_irq(&dev->lock); 92256694Snp qhp = get_qhp(dev, CQE_QPID(err_cqe)); 93256694Snp if (!qhp) { 94256694Snp printf("BAD AE qpid 0x%x opcode %d " 95256694Snp "status 0x%x type %d wrid.hi 0x%x wrid.lo 0x%x\n", 96256694Snp CQE_QPID(err_cqe), 97256694Snp CQE_OPCODE(err_cqe), CQE_STATUS(err_cqe), 98256694Snp CQE_TYPE(err_cqe), CQE_WRID_HI(err_cqe), 99256694Snp CQE_WRID_LOW(err_cqe)); 100256694Snp spin_unlock_irq(&dev->lock); 101256694Snp goto out; 102256694Snp } 103256694Snp 104256694Snp if (SQ_TYPE(err_cqe)) 105256694Snp cqid = qhp->attr.scq; 106256694Snp else 107256694Snp cqid = qhp->attr.rcq; 108256694Snp chp = get_chp(dev, cqid); 109256694Snp if (!chp) { 110256694Snp printf("BAD AE cqid 0x%x qpid 0x%x opcode %d " 111256694Snp "status 0x%x type %d wrid.hi 0x%x wrid.lo 0x%x\n", 112256694Snp cqid, CQE_QPID(err_cqe), 113256694Snp CQE_OPCODE(err_cqe), CQE_STATUS(err_cqe), 114256694Snp CQE_TYPE(err_cqe), CQE_WRID_HI(err_cqe), 115256694Snp CQE_WRID_LOW(err_cqe)); 116256694Snp spin_unlock_irq(&dev->lock); 117256694Snp goto out; 118256694Snp } 119256694Snp 120256694Snp c4iw_qp_add_ref(&qhp->ibqp); 121256694Snp atomic_inc(&chp->refcnt); 122256694Snp spin_unlock_irq(&dev->lock); 123256694Snp 124256694Snp /* Bad incoming write */ 125256694Snp if (RQ_TYPE(err_cqe) && 126256694Snp (CQE_OPCODE(err_cqe) == FW_RI_RDMA_WRITE)) { 127256694Snp post_qp_event(dev, chp, qhp, err_cqe, IB_EVENT_QP_REQ_ERR); 128256694Snp goto done; 129256694Snp } 130256694Snp 131256694Snp switch (CQE_STATUS(err_cqe)) { 132256694Snp 133256694Snp /* Completion Events */ 134256694Snp case T4_ERR_SUCCESS: 135256694Snp printf(KERN_ERR MOD "AE with status 0!\n"); 136256694Snp break; 137256694Snp 138256694Snp case T4_ERR_STAG: 139256694Snp case T4_ERR_PDID: 140256694Snp case T4_ERR_QPID: 141256694Snp case T4_ERR_ACCESS: 142256694Snp case T4_ERR_WRAP: 143256694Snp case T4_ERR_BOUND: 144256694Snp case T4_ERR_INVALIDATE_SHARED_MR: 145256694Snp case T4_ERR_INVALIDATE_MR_WITH_MW_BOUND: 146256694Snp post_qp_event(dev, chp, qhp, err_cqe, IB_EVENT_QP_ACCESS_ERR); 147256694Snp break; 148256694Snp 149256694Snp /* Device Fatal Errors */ 150256694Snp case T4_ERR_ECC: 151256694Snp case T4_ERR_ECC_PSTAG: 152256694Snp case T4_ERR_INTERNAL_ERR: 153256694Snp post_qp_event(dev, chp, qhp, err_cqe, IB_EVENT_DEVICE_FATAL); 154256694Snp break; 155256694Snp 156256694Snp /* QP Fatal Errors */ 157256694Snp case T4_ERR_OUT_OF_RQE: 158256694Snp case T4_ERR_PBL_ADDR_BOUND: 159256694Snp case T4_ERR_CRC: 160256694Snp case T4_ERR_MARKER: 161256694Snp case T4_ERR_PDU_LEN_ERR: 162256694Snp case T4_ERR_DDP_VERSION: 163256694Snp case T4_ERR_RDMA_VERSION: 164256694Snp case T4_ERR_OPCODE: 165256694Snp case T4_ERR_DDP_QUEUE_NUM: 166256694Snp case T4_ERR_MSN: 167256694Snp case T4_ERR_TBIT: 168256694Snp case T4_ERR_MO: 169256694Snp case T4_ERR_MSN_GAP: 170256694Snp case T4_ERR_MSN_RANGE: 171256694Snp case T4_ERR_RQE_ADDR_BOUND: 172256694Snp case T4_ERR_IRD_OVERFLOW: 173256694Snp post_qp_event(dev, chp, qhp, err_cqe, IB_EVENT_QP_FATAL); 174256694Snp break; 175256694Snp 176256694Snp default: 177256694Snp printf("Unknown T4 status 0x%x QPID 0x%x\n", 178256694Snp CQE_STATUS(err_cqe), qhp->wq.sq.qid); 179256694Snp post_qp_event(dev, chp, qhp, err_cqe, IB_EVENT_QP_FATAL); 180256694Snp break; 181256694Snp } 182256694Snpdone: 183256694Snp if (atomic_dec_and_test(&chp->refcnt)) 184256694Snp wake_up(&chp->wait); 185256694Snp c4iw_qp_rem_ref(&qhp->ibqp); 186256694Snpout: 187256694Snp return; 188256694Snp} 189256694Snp 190256694Snpint c4iw_ev_handler(struct sge_iq *iq, const struct rsp_ctrl *rc) 191256694Snp{ 192256694Snp struct c4iw_dev *dev = iq->adapter->iwarp_softc; 193256694Snp u32 qid = be32_to_cpu(rc->pldbuflen_qid); 194256694Snp struct c4iw_cq *chp; 195256694Snp unsigned long flag; 196256694Snp 197301158Snp spin_lock_irqsave(&dev->lock, flag); 198256694Snp chp = get_chp(dev, qid); 199256694Snp if (chp) { 200301158Snp atomic_inc(&chp->refcnt); 201301158Snp spin_unlock_irqrestore(&dev->lock, flag); 202301158Snp 203256694Snp spin_lock_irqsave(&chp->comp_handler_lock, flag); 204256694Snp (*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context); 205256694Snp spin_unlock_irqrestore(&chp->comp_handler_lock, flag); 206301158Snp if (atomic_dec_and_test(&chp->refcnt)) 207301158Snp wake_up(&chp->wait); 208301158Snp } else { 209256694Snp CTR2(KTR_IW_CXGBE, "%s unknown cqid 0x%x", __func__, qid); 210301158Snp spin_unlock_irqrestore(&dev->lock, flag); 211301158Snp } 212301158Snp 213256694Snp return 0; 214256694Snp} 215256694Snp#endif 216