static int rxe_qp_init_req(struct rxe_dev *rxe, struct rxe_qp *qp, struct ib_qp_init_attr *init, struct ib_ucontext *context, struct ib_udata *udata) { int err; int wqe_size; err = sock_create_kern(&init_net, AF_INET, SOCK_DGRAM, 0, &qp->sk); if (err < 0) return err; qp->sk->sk->sk_user_data = qp; qp->sq.max_wr = init->cap.max_send_wr; qp->sq.max_sge = init->cap.max_send_sge; qp->sq.max_inline = init->cap.max_inline_data; wqe_size = max_t(int, sizeof(struct rxe_send_wqe) + qp->sq.max_sge * sizeof(struct ib_sge), sizeof(struct rxe_send_wqe) + qp->sq.max_inline); qp->sq.queue = rxe_queue_init(rxe, &qp->sq.max_wr, wqe_size); if (!qp->sq.queue) return -ENOMEM; err = do_mmap_info(rxe, udata, true, context, qp->sq.queue->buf, qp->sq.queue->buf_size, &qp->sq.queue->ip); if (err) { kvfree(qp->sq.queue->buf); kfree(qp->sq.queue); return err; } qp->req.wqe_index = producer_index(qp->sq.queue); qp->req.state = QP_STATE_RESET; qp->req.opcode = -1; qp->comp.opcode = -1; spin_lock_init(&qp->sq.sq_lock); skb_queue_head_init(&qp->req_pkts); rxe_init_task(rxe, &qp->req.task, qp, rxe_requester, "req"); rxe_init_task(rxe, &qp->comp.task, qp, rxe_completer, "comp"); qp->qp_timeout_jiffies = 0; /* Can't be set for UD/UC in modify_qp */ if (init->qp_type == IB_QPT_RC) { timer_setup(&qp->rnr_nak_timer, rnr_nak_timer, 0); timer_setup(&qp->retrans_timer, retransmit_timer, 0); } return 0; }
static int rxe_qp_init_req(struct rxe_dev *rxe, struct rxe_qp *qp, struct ib_qp_init_attr *init, struct ib_ucontext *context, struct ib_udata *udata) { int err; int wqe_size; qp->sq.max_wr = init->cap.max_send_wr; qp->sq.max_sge = init->cap.max_send_sge; qp->sq.max_inline = init->cap.max_inline_data; wqe_size = max_t(int, sizeof(struct rxe_send_wqe) + qp->sq.max_sge*sizeof(struct ib_sge), sizeof(struct rxe_send_wqe) + qp->sq.max_inline); qp->sq.queue = rxe_queue_init(rxe, (unsigned int *)&qp->sq.max_wr, wqe_size); if (!qp->sq.queue) return -ENOMEM; err = do_mmap_info(rxe, udata, sizeof(struct mminfo), context, qp->sq.queue->buf, qp->sq.queue->buf_size, &qp->sq.queue->ip); if (err) { vfree(qp->sq.queue->buf); kfree(qp->sq.queue); } qp->req.wqe_index = producer_index(qp->sq.queue); qp->req.state = QP_STATE_RESET; qp->req.opcode = -1; qp->comp.opcode = -1; spin_lock_init(&qp->sq.sq_lock); skb_queue_head_init(&qp->req_pkts); rxe_init_task(rxe, &qp->req.task, &rxe_fast_req, qp, rxe_requester, "req"); rxe_init_task(rxe, &qp->comp.task, &rxe_fast_comp, qp, rxe_completer, "comp"); init_timer(&qp->rnr_nak_timer); qp->rnr_nak_timer.function = rnr_nak_timer; qp->rnr_nak_timer.data = (unsigned long)qp; init_timer(&qp->retrans_timer); qp->retrans_timer.function = retransmit_timer; qp->retrans_timer.data = (unsigned long)qp; qp->qp_timeout_jiffies = 0; /* Can't be set for UD/UC in modify_qp */ return 0; }
static void req_retry(struct rxe_qp *qp) { struct rxe_send_wqe *wqe; unsigned int wqe_index; unsigned int mask; int npsn; int first = 1; wqe = queue_head(qp->sq.queue); npsn = (qp->comp.psn - wqe->first_psn) & BTH_PSN_MASK; qp->req.wqe_index = consumer_index(qp->sq.queue); qp->req.psn = qp->comp.psn; qp->req.opcode = -1; for (wqe_index = consumer_index(qp->sq.queue); wqe_index != producer_index(qp->sq.queue); wqe_index = next_index(qp->sq.queue, wqe_index)) { wqe = addr_from_index(qp->sq.queue, wqe_index); mask = wr_opcode_mask(wqe->wr.opcode, qp); if (wqe->state == wqe_state_posted) break; if (wqe->state == wqe_state_done) continue; wqe->iova = (mask & WR_ATOMIC_MASK) ? wqe->wr.wr.atomic.remote_addr : (mask & WR_READ_OR_WRITE_MASK) ? wqe->wr.wr.rdma.remote_addr : 0; if (!first || (mask & WR_READ_MASK) == 0) { wqe->dma.resid = wqe->dma.length; wqe->dma.cur_sge = 0; wqe->dma.sge_offset = 0; } if (first) { first = 0; if (mask & WR_WRITE_OR_SEND_MASK) retry_first_write_send(qp, wqe, mask, npsn); if (mask & WR_READ_MASK) wqe->iova += npsn * qp->mtu; } wqe->state = wqe_state_posted; } }
static struct rxe_send_wqe *req_next_wqe(struct rxe_qp *qp) { struct rxe_send_wqe *wqe = queue_head(qp->sq.queue); unsigned long flags; if (unlikely(qp->req.state == QP_STATE_DRAIN)) { /* check to see if we are drained; * state_lock used by requester and completer */ spin_lock_irqsave(&qp->state_lock, flags); do { if (qp->req.state != QP_STATE_DRAIN) { /* comp just finished */ spin_unlock_irqrestore(&qp->state_lock, flags); break; } if (wqe && ((qp->req.wqe_index != consumer_index(qp->sq.queue)) || (wqe->state != wqe_state_posted))) { /* comp not done yet */ spin_unlock_irqrestore(&qp->state_lock, flags); break; } qp->req.state = QP_STATE_DRAINED; spin_unlock_irqrestore(&qp->state_lock, flags); if (qp->ibqp.event_handler) { struct ib_event ev; ev.device = qp->ibqp.device; ev.element.qp = &qp->ibqp; ev.event = IB_EVENT_SQ_DRAINED; qp->ibqp.event_handler(&ev, qp->ibqp.qp_context); } } while (0); } if (qp->req.wqe_index == producer_index(qp->sq.queue)) return NULL; wqe = addr_from_index(qp->sq.queue, qp->req.wqe_index); if (unlikely((qp->req.state == QP_STATE_DRAIN || qp->req.state == QP_STATE_DRAINED) && (wqe->state != wqe_state_processing))) return NULL; if (unlikely((wqe->wr.send_flags & IB_SEND_FENCE) && (qp->req.wqe_index != consumer_index(qp->sq.queue)))) { qp->req.wait_fence = 1; return NULL; } wqe->mask = wr_opcode_mask(wqe->wr.opcode, qp); return wqe; }