if (likely(qp->attrs.state == SIW_QP_STATE_RTS)) /* * Implements data receive operation during * socket callback. TCP gracefully catches * the case where there is nothing to receive * (not calling siw_tcp_rx_data() then).
*/
tcp_read_sock(sk, &rd_desc, siw_tcp_rx_data);
up_read(&qp->state_lock);
} else {
siw_dbg_qp(qp, "unable to process RX, suspend: %d\n",
qp->rx_stream.rx_suspend);
}
done:
read_unlock(&sk->sk_callback_lock);
}
switch (qp->attrs.state) { case SIW_QP_STATE_RTS: case SIW_QP_STATE_RTR: case SIW_QP_STATE_IDLE: case SIW_QP_STATE_TERMINATE:
qp->attrs.state = SIW_QP_STATE_ERROR; break; /* * SIW_QP_STATE_CLOSING: * * This is a forced close. shall the QP be moved to * ERROR or IDLE ?
*/ case SIW_QP_STATE_CLOSING: if (tx_wqe(qp)->wr_status == SIW_WR_IDLE)
qp->attrs.state = SIW_QP_STATE_ERROR; else
qp->attrs.state = SIW_QP_STATE_IDLE; break;
default:
siw_dbg_qp(qp, "llp close: no state transition needed: %s\n",
siw_qp_state_to_string[qp->attrs.state]); break;
}
siw_sq_flush(qp);
siw_rq_flush(qp);
/* * Send a non signalled READ or WRITE to peer side as negotiated * with MPAv2 P2P setup protocol. The work request is only created * as a current active WR and does not consume Send Queue space. * * Caller must hold QP state lock.
*/ int siw_qp_mpa_rts(struct siw_qp *qp, enum mpa_v2_ctrl ctrl)
{ struct siw_wqe *wqe = tx_wqe(qp); unsignedlong flags; int rv = 0;
/* * Send a TERMINATE message, as defined in RFC's 5040/5041/5044/6581. * Sending TERMINATE messages is best effort - such messages * can only be send if the QP is still connected and it does * not have another outbound message in-progress, i.e. the * TERMINATE message must not interfer with an incomplete current * transmit operation.
*/ void siw_send_terminate(struct siw_qp *qp)
{ struct kvec iov[3]; struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_EOR }; struct iwarp_terminate *term = NULL; union iwarp_hdr *err_hdr = NULL; struct socket *s = qp->attrs.sk; struct siw_rx_stream *srx = &qp->rx_stream; union iwarp_hdr *rx_hdr = &srx->hdr;
u32 crc = 0; int num_frags, len_terminate, rv;
if (!qp->term_info.valid) return;
qp->term_info.valid = 0;
if (tx_wqe(qp)->wr_status == SIW_WR_INPROGRESS) {
siw_dbg_qp(qp, "cannot send TERMINATE: op %d in progress\n",
tx_type(tx_wqe(qp))); return;
} if (!s && qp->cep) /* QP not yet in RTS. Take socket from connection end point */
s = qp->cep->sock;
if (!s) {
siw_dbg_qp(qp, "cannot send TERMINATE: not connected\n"); return;
}
term = kzalloc(sizeof(*term), GFP_KERNEL); if (!term) return;
switch (qp->term_info.layer) { case TERM_ERROR_LAYER_RDMAP: if (qp->term_info.etype == RDMAP_ETYPE_CATASTROPHIC) /* No additional DDP/RDMAP header to be included */ break;
if (qp->term_info.etype == RDMAP_ETYPE_REMOTE_PROTECTION) { /* * Complete RDMAP frame will get attached, and * DDP segment length is valid
*/
term->flag_m = 1;
term->flag_d = 1;
term->flag_r = 1;
/* Inbound RREQ error, detected during * RRESP creation. Take state from * current TX work queue element to * reconstruct peers RREQ.
*/
rreq = (struct iwarp_rdma_rreq *)err_hdr;
switch (attrs->state) { case SIW_QP_STATE_CLOSING: /* * Verbs: move to IDLE if SQ and ORQ are empty. * Move to ERROR otherwise. But first of all we must * close the connection. So we keep CLOSING or ERROR * as a transient state, schedule connection drop work * and wait for the socket state change upcall to * come back closed.
*/ if (tx_wqe(qp)->wr_status == SIW_WR_IDLE) {
qp->attrs.state = SIW_QP_STATE_CLOSING;
} else {
qp->attrs.state = SIW_QP_STATE_ERROR;
siw_sq_flush(qp);
}
siw_rq_flush(qp);
drop_conn = 1; break;
case SIW_QP_STATE_TERMINATE:
qp->attrs.state = SIW_QP_STATE_TERMINATE;
case SIW_QP_STATE_ERROR: /* * This is an emergency close. * * Any in progress transmit operation will get * cancelled. * This will likely result in a protocol failure, * if a TX operation is in transit. The caller * could unconditional wait to give the current * operation a chance to complete. * Esp., how to handle the non-empty IRQ case? * The peer was asking for data transfer at a valid * point in time.
*/
siw_sq_flush(qp);
siw_rq_flush(qp);
qp->attrs.state = SIW_QP_STATE_ERROR;
drop_conn = 1; break;
if (unlikely(!qp->attrs.orq_size)) { /* We negotiated not to send READ req's */
rv = -EINVAL; goto out;
}
wqe->sqe.num_sge = 1;
spin_lock(&qp->orq_lock);
rreq = orq_get_free(qp); if (rreq) { /* * Make an immediate copy in ORQ to be ready * to process loopback READ reply
*/
siw_read_to_orq(rreq, &wqe->sqe);
qp->orq_put++;
} else {
qp->tx_ctx.orq_fence = 1;
rv = 0;
}
spin_unlock(&qp->orq_lock);
}
/* Clear SQE, can be re-used by application */
smp_store_mb(sqe->flags, 0);
qp->sq_get++;
out: if (unlikely(rv < 0)) {
siw_dbg_qp(qp, "error %d\n", rv);
wqe->wr_status = SIW_WR_IDLE;
} return rv;
}
/* * Must be called with SQ locked. * To avoid complete SQ starvation by constant inbound READ requests, * the active IRQ will not be served after qp->irq_burst, if the * SQ has pending work.
*/ int siw_activate_tx(struct siw_qp *qp)
{ struct siw_sqe *irqe; struct siw_wqe *wqe = tx_wqe(qp);
if (!qp->attrs.irq_size) return siw_activate_tx_from_sq(qp);
/* mark current IRQ entry free */
smp_store_mb(irqe->flags, 0);
return 1;
}
/* * Check if current CQ state qualifies for calling CQ completion * handler. Must be called with CQ lock held.
*/ staticbool siw_cq_notify_now(struct siw_cq *cq, u32 flags)
{
u32 cq_notify;
if (!cq->base_cq.comp_handler) returnfalse;
/* Read application shared notification state */
cq_notify = READ_ONCE(cq->notify->flags);
if ((cq_notify & SIW_NOTIFY_NEXT_COMPLETION) ||
((cq_notify & SIW_NOTIFY_SOLICITED) &&
(flags & SIW_WQE_SOLICITED))) { /* * CQ notification is one-shot: Since the * current CQE causes user notification, * the CQ gets dis-aremd and must be re-aremd * by the user for a new notification.
*/
WRITE_ONCE(cq->notify->flags, SIW_NOTIFY_NOT);
/* * siw_sq_flush() * * Flush SQ and ORQ entries to CQ. * * Must be called with QP state write lock held. * Therefore, SQ and ORQ lock must not be taken.
*/ void siw_sq_flush(struct siw_qp *qp)
{ struct siw_sqe *sqe; struct siw_wqe *wqe = tx_wqe(qp); int async_event = 0;
/* * Start with completing any work currently on the ORQ
*/ while (qp->attrs.orq_size) {
sqe = &qp->orq[qp->orq_get % qp->attrs.orq_size]; if (!READ_ONCE(sqe->flags)) break;
if (siw_sqe_complete(qp, sqe, 0, SIW_WC_WR_FLUSH_ERR) != 0) break;
WRITE_ONCE(sqe->flags, 0);
qp->orq_get++;
} /* * Flush an in-progress WQE if present
*/ if (wqe->wr_status != SIW_WR_IDLE) {
siw_dbg_qp(qp, "flush current SQE, type %d, status %d\n",
tx_type(wqe), wqe->wr_status);
siw_wqe_put_mem(wqe, tx_type(wqe));
if (tx_type(wqe) != SIW_OP_READ_RESPONSE &&
((tx_type(wqe) != SIW_OP_READ &&
tx_type(wqe) != SIW_OP_READ_LOCAL_INV) ||
wqe->wr_status == SIW_WR_QUEUED)) /* * An in-progress Read Request is already in * the ORQ
*/
siw_sqe_complete(qp, &wqe->sqe, wqe->bytes,
SIW_WC_WR_FLUSH_ERR);
wqe->wr_status = SIW_WR_IDLE;
} /* * Flush the Send Queue
*/ while (qp->attrs.sq_size) {
sqe = &qp->sendq[qp->sq_get % qp->attrs.sq_size]; if (!READ_ONCE(sqe->flags)) break;
async_event = 1; if (siw_sqe_complete(qp, sqe, 0, SIW_WC_WR_FLUSH_ERR) != 0) /* * Shall IB_EVENT_SQ_DRAINED be supressed if work * completion fails?
*/ break;
WRITE_ONCE(sqe->flags, 0);
qp->sq_get++;
} if (async_event)
siw_qp_event(qp, IB_EVENT_SQ_DRAINED);
}
/* * siw_rq_flush() * * Flush recv queue entries to CQ. Also * takes care of pending active tagged and untagged * inbound transfers, which have target memory * referenced. * * Must be called with QP state write lock held. * Therefore, RQ lock must not be taken.
*/ void siw_rq_flush(struct siw_qp *qp)
{ struct siw_wqe *wqe = &qp->rx_untagged.wqe_active;
/* * Flush an in-progress untagged operation if present
*/ if (wqe->wr_status != SIW_WR_IDLE) {
siw_dbg_qp(qp, "flush current rqe, type %d, status %d\n",
rx_type(wqe), wqe->wr_status);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.