void process_message(int s, UCRP *rm, UCRP *sm) { UCRP_PMSG((stdout, rm)); switch (rm->type) { case UCRP_COMMAND: do_command(s, rm, sm); break; case UCRP_COMPLETE: do_complete(s, rm, sm); break; case UCRP_HELP: do_help(s, rm, sm); break; case UCRP_INTERRUPT: ucrp_log(LOG_NOTICE, "%s: ignoring UCRP_INTERRUPT\n", __func__); break; case UCRP_TELL: ucrp_pmsg(stdout, rm); break; case UCRP_SUSPEND: ucrp_log(LOG_NOTICE, "%s: ignoring UCRP_SUSPEND\n", __func__); break; case UCRP_WAIT: { char *lp = UCRP_PAYLOAD(rm); fprintf(stdout, "%s: UCRP_WAIT: " "WAIT_SIGNAL=%d " "WAIT_ERROR=%d " "WAIT_STATUS=%s\n", __func__, rm->options & WAIT_SIGNAL ? 1 : 0, rm->options & WAIT_ERROR ? 1 : 0, rm->options & WAIT_STATUS ? ucrp_msg_getln(&lp) : "N/A"); break; } default: ucrp_log(LOG_NOTICE, "unknown message type=%u\n", rm->type); break; } return; }
static inline enum comp_state complete_ack(struct rxe_qp *qp, struct rxe_pkt_info *pkt, struct rxe_send_wqe *wqe) { unsigned long flags; if (wqe->has_rd_atomic) { wqe->has_rd_atomic = 0; atomic_inc(&qp->req.rd_atomic); if (qp->req.need_rd_atomic) { qp->comp.timeout_retry = 0; qp->req.need_rd_atomic = 0; rxe_run_task(&qp->req.task, 1); } } if (unlikely(qp->req.state == QP_STATE_DRAIN)) { /* state_lock used by requester & completer */ spin_lock_irqsave(&qp->state_lock, flags); if ((qp->req.state == QP_STATE_DRAIN) && (qp->comp.psn == qp->req.psn)) { 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); } } else { spin_unlock_irqrestore(&qp->state_lock, flags); } } do_complete(qp, wqe); if (psn_compare(pkt->psn, qp->comp.psn) >= 0) return COMPST_UPDATE_COMP; else return COMPST_DONE; }
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 inline enum comp_state complete_wqe(struct rxe_qp *qp, struct rxe_pkt_info *pkt, struct rxe_send_wqe *wqe) { qp->comp.opcode = -1; if (pkt) { if (psn_compare(pkt->psn, qp->comp.psn) >= 0) qp->comp.psn = (pkt->psn + 1) & BTH_PSN_MASK; if (qp->req.wait_psn) { qp->req.wait_psn = 0; rxe_run_task(&qp->req.task, 1); } } do_complete(qp, wqe); return COMPST_GET_WQE; }
int rxe_completer(void *arg) { struct rxe_qp *qp = (struct rxe_qp *)arg; struct rxe_dev *rxe = to_rdev(qp->ibqp.device); struct rxe_send_wqe *wqe = wqe; struct sk_buff *skb = NULL; struct rxe_pkt_info *pkt = NULL; enum comp_state state; rxe_add_ref(qp); if (!qp->valid || qp->req.state == QP_STATE_ERROR || qp->req.state == QP_STATE_RESET) { rxe_drain_resp_pkts(qp, qp->valid && qp->req.state == QP_STATE_ERROR); goto exit; } if (qp->comp.timeout) { qp->comp.timeout_retry = 1; qp->comp.timeout = 0; } else { qp->comp.timeout_retry = 0; } if (qp->req.need_retry) goto exit; state = COMPST_GET_ACK; while (1) { pr_debug("qp#%d state = %s\n", qp_num(qp), comp_state_name[state]); switch (state) { case COMPST_GET_ACK: skb = skb_dequeue(&qp->resp_pkts); if (skb) { pkt = SKB_TO_PKT(skb); qp->comp.timeout_retry = 0; } state = COMPST_GET_WQE; break; case COMPST_GET_WQE: state = get_wqe(qp, pkt, &wqe); break; case COMPST_CHECK_PSN: state = check_psn(qp, pkt, wqe); break; case COMPST_CHECK_ACK: state = check_ack(qp, pkt, wqe); break; case COMPST_READ: state = do_read(qp, pkt, wqe); break; case COMPST_ATOMIC: state = do_atomic(qp, pkt, wqe); break; case COMPST_WRITE_SEND: if (wqe->state == wqe_state_pending && wqe->last_psn == pkt->psn) state = COMPST_COMP_ACK; else state = COMPST_UPDATE_COMP; break; case COMPST_COMP_ACK: state = complete_ack(qp, pkt, wqe); break; case COMPST_COMP_WQE: state = complete_wqe(qp, pkt, wqe); break; case COMPST_UPDATE_COMP: if (pkt->mask & RXE_END_MASK) qp->comp.opcode = -1; else qp->comp.opcode = pkt->opcode; if (psn_compare(pkt->psn, qp->comp.psn) >= 0) qp->comp.psn = (pkt->psn + 1) & BTH_PSN_MASK; if (qp->req.wait_psn) { qp->req.wait_psn = 0; rxe_run_task(&qp->req.task, 1); } state = COMPST_DONE; break; case COMPST_DONE: if (pkt) { rxe_drop_ref(pkt->qp); kfree_skb(skb); skb = NULL; } goto done; case COMPST_EXIT: if (qp->comp.timeout_retry && wqe) { state = COMPST_ERROR_RETRY; break; } /* re reset the timeout counter if * (1) QP is type RC * (2) the QP is alive * (3) there is a packet sent by the requester that * might be acked (we still might get spurious * timeouts but try to keep them as few as possible) * (4) the timeout parameter is set */ if ((qp_type(qp) == IB_QPT_RC) && (qp->req.state == QP_STATE_READY) && (psn_compare(qp->req.psn, qp->comp.psn) > 0) && qp->qp_timeout_jiffies) mod_timer(&qp->retrans_timer, jiffies + qp->qp_timeout_jiffies); WARN_ON_ONCE(skb); goto exit; case COMPST_ERROR_RETRY: /* we come here if the retry timer fired and we did * not receive a response packet. try to retry the send * queue if that makes sense and the limits have not * been exceeded. remember that some timeouts are * spurious since we do not reset the timer but kick * it down the road or let it expire */ /* there is nothing to retry in this case */ if (!wqe || (wqe->state == wqe_state_posted)) { WARN_ON_ONCE(skb); goto exit; } if (qp->comp.retry_cnt > 0) { if (qp->comp.retry_cnt != 7) qp->comp.retry_cnt--; /* no point in retrying if we have already * seen the last ack that the requester could * have caused */ if (psn_compare(qp->req.psn, qp->comp.psn) > 0) { /* tell the requester to retry the * send queue next time around */ rxe_counter_inc(rxe, RXE_CNT_COMP_RETRY); qp->req.need_retry = 1; rxe_run_task(&qp->req.task, 1); } if (pkt) { rxe_drop_ref(pkt->qp); kfree_skb(skb); skb = NULL; } WARN_ON_ONCE(skb); goto exit; } else { rxe_counter_inc(rxe, RXE_CNT_RETRY_EXCEEDED); wqe->status = IB_WC_RETRY_EXC_ERR; state = COMPST_ERROR; } break; case COMPST_RNR_RETRY: if (qp->comp.rnr_retry > 0) { if (qp->comp.rnr_retry != 7) qp->comp.rnr_retry--; qp->req.need_retry = 1; pr_debug("qp#%d set rnr nak timer\n", qp_num(qp)); mod_timer(&qp->rnr_nak_timer, jiffies + rnrnak_jiffies(aeth_syn(pkt) & ~AETH_TYPE_MASK)); rxe_drop_ref(pkt->qp); kfree_skb(skb); skb = NULL; goto exit; } else { rxe_counter_inc(rxe, RXE_CNT_RNR_RETRY_EXCEEDED); wqe->status = IB_WC_RNR_RETRY_EXC_ERR; state = COMPST_ERROR; } break; case COMPST_ERROR: WARN_ON_ONCE(wqe->status == IB_WC_SUCCESS); do_complete(qp, wqe); rxe_qp_error(qp); if (pkt) { rxe_drop_ref(pkt->qp); kfree_skb(skb); skb = NULL; } WARN_ON_ONCE(skb); goto exit; } } exit: /* we come here if we are done with processing and want the task to * exit from the loop calling us */ WARN_ON_ONCE(skb); rxe_drop_ref(qp); return -EAGAIN; done: /* we come here if we have processed a packet we want the task to call * us again to see if there is anything else to do */ WARN_ON_ONCE(skb); rxe_drop_ref(qp); return 0; }
void node::complete() { if(!parsed_) do_complete(); }