/* called by the create qp verb */ int rxe_qp_from_init(struct rxe_dev *rxe, struct rxe_qp *qp, struct rxe_pd *pd, struct ib_qp_init_attr *init, struct ib_udata *udata, struct ib_pd *ibpd) { int err; struct rxe_cq *rcq = to_rcq(init->recv_cq); struct rxe_cq *scq = to_rcq(init->send_cq); struct rxe_srq *srq = init->srq ? to_rsrq(init->srq) : NULL; struct ib_ucontext *context = udata ? ibpd->uobject->context : NULL; rxe_add_ref(pd); rxe_add_ref(rcq); rxe_add_ref(scq); if (srq) rxe_add_ref(srq); qp->pd = pd; qp->rcq = rcq; qp->scq = scq; qp->srq = srq; qp->udata = udata; rxe_qp_init_misc(rxe, qp, init); err = rxe_qp_init_req(rxe, qp, init, context, udata); if (err) goto err1; err = rxe_qp_init_resp(rxe, qp, init, context, udata); if (err) goto err2; qp->attr.qp_state = IB_QPS_RESET; qp->valid = 1; return 0; err2: rxe_queue_cleanup(qp->sq.queue); err1: if (srq) rxe_drop_ref(srq); rxe_drop_ref(scq); rxe_drop_ref(rcq); rxe_drop_ref(pd); return err; }
static int rxe_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata) { int err; struct rxe_cq *cq = to_rcq(ibcq); struct rxe_dev *rxe = to_rdev(ibcq->device); struct rxe_resize_cq_resp __user *uresp = NULL; if (udata) { if (udata->outlen < sizeof(*uresp)) return -EINVAL; uresp = udata->outbuf; } err = rxe_cq_chk_attr(rxe, cq, cqe, 0); if (err) goto err1; err = rxe_cq_resize_queue(cq, cqe, uresp, udata); if (err) goto err1; return 0; err1: return err; }
static int rxe_peek_cq(struct ib_cq *ibcq, int wc_cnt) { struct rxe_cq *cq = to_rcq(ibcq); int count = queue_count(cq->queue); return (count > wc_cnt) ? wc_cnt : count; }
static int rxe_destroy_cq(struct ib_cq *ibcq) { struct rxe_cq *cq = to_rcq(ibcq); rxe_drop_ref(cq); return 0; }
static int rxe_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata) { struct rxe_cq *cq = to_rcq(ibcq); rxe_cq_disable(cq); rxe_drop_ref(cq); return 0; }
static int rxe_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags) { struct rxe_cq *cq = to_rcq(ibcq); if (cq->notify != IB_CQ_NEXT_COMP) cq->notify = flags & IB_CQ_SOLICITED_MASK; return 0; }
static int rxe_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags) { struct rxe_cq *cq = to_rcq(ibcq); unsigned long irq_flags; int ret = 0; spin_lock_irqsave(&cq->cq_lock, irq_flags); if (cq->notify != IB_CQ_NEXT_COMP) cq->notify = flags & IB_CQ_SOLICITED_MASK; if ((flags & IB_CQ_REPORT_MISSED_EVENTS) && !queue_empty(cq->queue)) ret = 1; spin_unlock_irqrestore(&cq->cq_lock, irq_flags); return ret; }
static int rxe_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata) { int err; struct rxe_cq *cq = to_rcq(ibcq); struct rxe_dev *rxe = to_rdev(ibcq->device); err = rxe_cq_chk_attr(rxe, cq, cqe, 0, udata); if (err) goto err1; err = rxe_cq_resize_queue(cq, cqe, udata); if (err) goto err1; return 0; err1: return err; }
static int rxe_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc) { int i; struct rxe_cq *cq = to_rcq(ibcq); struct rxe_cqe *cqe; unsigned long flags; spin_lock_irqsave(&cq->cq_lock, flags); for (i = 0; i < num_entries; i++) { cqe = queue_head(cq->queue); if (!cqe) break; memcpy(wc++, &cqe->ibwc, sizeof(*wc)); advance_consumer(cq->queue); } spin_unlock_irqrestore(&cq->cq_lock, flags); return i; }