/* * IBA Spec. Section 10.7.3.1 SIGNALED COMPLETIONS * ---------8<---------8<------------- * ...Note that if a completion error occurs, a Work Completion * will always be generated, even if the signaling * indicator requests an Unsignaled Completion. * ---------8<---------8<------------- */ static void do_complete(struct rxe_qp *qp, struct rxe_send_wqe *wqe) { struct rxe_cqe cqe; if ((qp->sq_sig_type == IB_SIGNAL_ALL_WR) || (wqe->wr.send_flags & IB_SEND_SIGNALED) || wqe->status != IB_WC_SUCCESS) { make_send_cqe(qp, wqe, &cqe); advance_consumer(qp->sq.queue); rxe_cq_post(qp->scq, &cqe, 0); } else { advance_consumer(qp->sq.queue); } /* * we completed something so let req run again * if it is trying to fence */ if (qp->req.wait_fence) { qp->req.wait_fence = 0; rxe_run_task(&qp->req.task, 1); } }
/* copies elements from original q to new q and then swaps the contents of the * two q headers. This is so that if anyone is holding a pointer to q it will * still work */ static int resize_finish(struct rxe_queue *q, struct rxe_queue *new_q, unsigned int num_elem) { if (!queue_empty(q) && (num_elem < queue_count(q))) return -EINVAL; while (!queue_empty(q)) { memcpy(producer_addr(new_q), consumer_addr(q), new_q->elem_size); advance_producer(new_q); advance_consumer(q); } swap(*q, *new_q); return 0; }
static void rxe_drain_resp_pkts(struct rxe_qp *qp, bool notify) { struct sk_buff *skb; struct rxe_send_wqe *wqe; while ((skb = skb_dequeue(&qp->resp_pkts))) { rxe_drop_ref(qp); kfree_skb(skb); } while ((wqe = queue_head(qp->sq.queue))) { if (notify) { wqe->status = IB_WC_WR_FLUSH_ERR; do_complete(qp, wqe); } else { advance_consumer(qp->sq.queue); } } }
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; }
static enum resp_states get_srq_wqe(struct rxe_qp *qp) { struct rxe_srq *srq = qp->srq; struct rxe_queue *q = srq->rq.queue; struct rxe_recv_wqe *wqe; struct ib_event ev; if (srq->error) return RESPST_ERR_RNR; spin_lock_bh(&srq->rq.consumer_lock); wqe = queue_head(q); if (!wqe) { spin_unlock_bh(&srq->rq.consumer_lock); return RESPST_ERR_RNR; } /* note kernel and user space recv wqes have same size */ memcpy(&qp->resp.srq_wqe, wqe, sizeof(qp->resp.srq_wqe)); qp->resp.wqe = &qp->resp.srq_wqe.wqe; advance_consumer(q); if (srq->limit && srq->ibsrq.event_handler && (queue_count(q) < srq->limit)) { srq->limit = 0; goto event; } spin_unlock_bh(&srq->rq.consumer_lock); return RESPST_CHK_LENGTH; event: spin_unlock_bh(&srq->rq.consumer_lock); ev.device = qp->ibqp.device; ev.element.srq = qp->ibqp.srq; ev.event = IB_EVENT_SRQ_LIMIT_REACHED; srq->ibsrq.event_handler(&ev, srq->ibsrq.srq_context); return RESPST_CHK_LENGTH; }