Path: blob/master/drivers/infiniband/hw/cxgb3/iwch_cq.c
15112 views
/*1* Copyright (c) 2006 Chelsio, Inc. All rights reserved.2*3* This software is available to you under a choice of one of two4* licenses. You may choose to be licensed under the terms of the GNU5* General Public License (GPL) Version 2, available from the file6* COPYING in the main directory of this source tree, or the7* OpenIB.org BSD license below:8*9* Redistribution and use in source and binary forms, with or10* without modification, are permitted provided that the following11* conditions are met:12*13* - Redistributions of source code must retain the above14* copyright notice, this list of conditions and the following15* disclaimer.16*17* - Redistributions in binary form must reproduce the above18* copyright notice, this list of conditions and the following19* disclaimer in the documentation and/or other materials20* provided with the distribution.21*22* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,23* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF24* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND25* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS26* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN27* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN28* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE29* SOFTWARE.30*/31#include "iwch_provider.h"32#include "iwch.h"3334/*35* Get one cq entry from cxio and map it to openib.36*37* Returns:38* 0 EMPTY;39* 1 cqe returned40* -EAGAIN caller must try again41* any other -errno fatal error42*/43static int iwch_poll_cq_one(struct iwch_dev *rhp, struct iwch_cq *chp,44struct ib_wc *wc)45{46struct iwch_qp *qhp = NULL;47struct t3_cqe cqe, *rd_cqe;48struct t3_wq *wq;49u32 credit = 0;50u8 cqe_flushed;51u64 cookie;52int ret = 1;5354rd_cqe = cxio_next_cqe(&chp->cq);5556if (!rd_cqe)57return 0;5859qhp = get_qhp(rhp, CQE_QPID(*rd_cqe));60if (!qhp)61wq = NULL;62else {63spin_lock(&qhp->lock);64wq = &(qhp->wq);65}66ret = cxio_poll_cq(wq, &(chp->cq), &cqe, &cqe_flushed, &cookie,67&credit);68if (t3a_device(chp->rhp) && credit) {69PDBG("%s updating %d cq credits on id %d\n", __func__,70credit, chp->cq.cqid);71cxio_hal_cq_op(&rhp->rdev, &chp->cq, CQ_CREDIT_UPDATE, credit);72}7374if (ret) {75ret = -EAGAIN;76goto out;77}78ret = 1;7980wc->wr_id = cookie;81wc->qp = &qhp->ibqp;82wc->vendor_err = CQE_STATUS(cqe);83wc->wc_flags = 0;8485PDBG("%s qpid 0x%x type %d opcode %d status 0x%x wrid hi 0x%x "86"lo 0x%x cookie 0x%llx\n", __func__,87CQE_QPID(cqe), CQE_TYPE(cqe),88CQE_OPCODE(cqe), CQE_STATUS(cqe), CQE_WRID_HI(cqe),89CQE_WRID_LOW(cqe), (unsigned long long) cookie);9091if (CQE_TYPE(cqe) == 0) {92if (!CQE_STATUS(cqe))93wc->byte_len = CQE_LEN(cqe);94else95wc->byte_len = 0;96wc->opcode = IB_WC_RECV;97if (CQE_OPCODE(cqe) == T3_SEND_WITH_INV ||98CQE_OPCODE(cqe) == T3_SEND_WITH_SE_INV) {99wc->ex.invalidate_rkey = CQE_WRID_STAG(cqe);100wc->wc_flags |= IB_WC_WITH_INVALIDATE;101}102} else {103switch (CQE_OPCODE(cqe)) {104case T3_RDMA_WRITE:105wc->opcode = IB_WC_RDMA_WRITE;106break;107case T3_READ_REQ:108wc->opcode = IB_WC_RDMA_READ;109wc->byte_len = CQE_LEN(cqe);110break;111case T3_SEND:112case T3_SEND_WITH_SE:113case T3_SEND_WITH_INV:114case T3_SEND_WITH_SE_INV:115wc->opcode = IB_WC_SEND;116break;117case T3_BIND_MW:118wc->opcode = IB_WC_BIND_MW;119break;120121case T3_LOCAL_INV:122wc->opcode = IB_WC_LOCAL_INV;123break;124case T3_FAST_REGISTER:125wc->opcode = IB_WC_FAST_REG_MR;126break;127default:128printk(KERN_ERR MOD "Unexpected opcode %d "129"in the CQE received for QPID=0x%0x\n",130CQE_OPCODE(cqe), CQE_QPID(cqe));131ret = -EINVAL;132goto out;133}134}135136if (cqe_flushed)137wc->status = IB_WC_WR_FLUSH_ERR;138else {139140switch (CQE_STATUS(cqe)) {141case TPT_ERR_SUCCESS:142wc->status = IB_WC_SUCCESS;143break;144case TPT_ERR_STAG:145wc->status = IB_WC_LOC_ACCESS_ERR;146break;147case TPT_ERR_PDID:148wc->status = IB_WC_LOC_PROT_ERR;149break;150case TPT_ERR_QPID:151case TPT_ERR_ACCESS:152wc->status = IB_WC_LOC_ACCESS_ERR;153break;154case TPT_ERR_WRAP:155wc->status = IB_WC_GENERAL_ERR;156break;157case TPT_ERR_BOUND:158wc->status = IB_WC_LOC_LEN_ERR;159break;160case TPT_ERR_INVALIDATE_SHARED_MR:161case TPT_ERR_INVALIDATE_MR_WITH_MW_BOUND:162wc->status = IB_WC_MW_BIND_ERR;163break;164case TPT_ERR_CRC:165case TPT_ERR_MARKER:166case TPT_ERR_PDU_LEN_ERR:167case TPT_ERR_OUT_OF_RQE:168case TPT_ERR_DDP_VERSION:169case TPT_ERR_RDMA_VERSION:170case TPT_ERR_DDP_QUEUE_NUM:171case TPT_ERR_MSN:172case TPT_ERR_TBIT:173case TPT_ERR_MO:174case TPT_ERR_MSN_RANGE:175case TPT_ERR_IRD_OVERFLOW:176case TPT_ERR_OPCODE:177wc->status = IB_WC_FATAL_ERR;178break;179case TPT_ERR_SWFLUSH:180wc->status = IB_WC_WR_FLUSH_ERR;181break;182default:183printk(KERN_ERR MOD "Unexpected cqe_status 0x%x for "184"QPID=0x%0x\n", CQE_STATUS(cqe), CQE_QPID(cqe));185ret = -EINVAL;186}187}188out:189if (wq)190spin_unlock(&qhp->lock);191return ret;192}193194int iwch_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)195{196struct iwch_dev *rhp;197struct iwch_cq *chp;198unsigned long flags;199int npolled;200int err = 0;201202chp = to_iwch_cq(ibcq);203rhp = chp->rhp;204205spin_lock_irqsave(&chp->lock, flags);206for (npolled = 0; npolled < num_entries; ++npolled) {207#ifdef DEBUG208int i=0;209#endif210211/*212* Because T3 can post CQEs that are _not_ associated213* with a WR, we might have to poll again after removing214* one of these.215*/216do {217err = iwch_poll_cq_one(rhp, chp, wc + npolled);218#ifdef DEBUG219BUG_ON(++i > 1000);220#endif221} while (err == -EAGAIN);222if (err <= 0)223break;224}225spin_unlock_irqrestore(&chp->lock, flags);226227if (err < 0)228return err;229else {230return npolled;231}232}233234235