summaryrefslogtreecommitdiffstats
path: root/sys/dev/cxgbe/tom/t4_cpl_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/cxgbe/tom/t4_cpl_io.c')
-rw-r--r--sys/dev/cxgbe/tom/t4_cpl_io.c76
1 files changed, 57 insertions, 19 deletions
diff --git a/sys/dev/cxgbe/tom/t4_cpl_io.c b/sys/dev/cxgbe/tom/t4_cpl_io.c
index e3f0296..6ae1ec4 100644
--- a/sys/dev/cxgbe/tom/t4_cpl_io.c
+++ b/sys/dev/cxgbe/tom/t4_cpl_io.c
@@ -786,6 +786,29 @@ do_peer_close(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
KASSERT(opcode == CPL_PEER_CLOSE,
("%s: unexpected opcode 0x%x", __func__, opcode));
KASSERT(m == NULL, ("%s: wasn't expecting payload", __func__));
+
+ if (__predict_false(toep->flags & TPF_SYNQE)) {
+#ifdef INVARIANTS
+ struct synq_entry *synqe = (void *)toep;
+
+ INP_WLOCK(synqe->lctx->inp);
+ if (synqe->flags & TPF_SYNQE_HAS_L2TE) {
+ KASSERT(synqe->flags & TPF_ABORT_SHUTDOWN,
+ ("%s: listen socket closed but tid %u not aborted.",
+ __func__, tid));
+ } else {
+ /*
+ * do_pass_accept_req is still running and will
+ * eventually take care of this tid.
+ */
+ }
+ INP_WUNLOCK(synqe->lctx->inp);
+#endif
+ CTR4(KTR_CXGBE, "%s: tid %u, synqe %p (0x%x)", __func__, tid,
+ toep, toep->flags);
+ return (0);
+ }
+
KASSERT(toep->tid == tid, ("%s: toep tid mismatch", __func__));
INP_INFO_WLOCK(&V_tcbinfo);
@@ -1090,15 +1113,27 @@ do_rx_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
struct socket *so;
struct sockbuf *sb;
int len;
+ uint32_t ddp_placed = 0;
if (__predict_false(toep->flags & TPF_SYNQE)) {
- /*
- * do_pass_establish failed and must be attempting to abort the
- * synqe's tid. Meanwhile, the T4 has sent us data for such a
- * connection.
- */
- KASSERT(toep->flags & TPF_ABORT_SHUTDOWN,
- ("%s: synqe and tid isn't being aborted.", __func__));
+#ifdef INVARIANTS
+ struct synq_entry *synqe = (void *)toep;
+
+ INP_WLOCK(synqe->lctx->inp);
+ if (synqe->flags & TPF_SYNQE_HAS_L2TE) {
+ KASSERT(synqe->flags & TPF_ABORT_SHUTDOWN,
+ ("%s: listen socket closed but tid %u not aborted.",
+ __func__, tid));
+ } else {
+ /*
+ * do_pass_accept_req is still running and will
+ * eventually take care of this tid.
+ */
+ }
+ INP_WUNLOCK(synqe->lctx->inp);
+#endif
+ CTR4(KTR_CXGBE, "%s: tid %u, synqe %p (0x%x)", __func__, tid,
+ toep, toep->flags);
m_freem(m);
return (0);
}
@@ -1120,13 +1155,8 @@ do_rx_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
tp = intotcpcb(inp);
-#ifdef INVARIANTS
- if (__predict_false(tp->rcv_nxt != be32toh(cpl->seq))) {
- log(LOG_ERR,
- "%s: unexpected seq# %x for TID %u, rcv_nxt %x\n",
- __func__, be32toh(cpl->seq), toep->tid, tp->rcv_nxt);
- }
-#endif
+ if (__predict_false(tp->rcv_nxt != be32toh(cpl->seq)))
+ ddp_placed = be32toh(cpl->seq) - tp->rcv_nxt;
tp->rcv_nxt += len;
KASSERT(tp->rcv_wnd >= len, ("%s: negative window size", __func__));
@@ -1173,12 +1203,20 @@ do_rx_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
int changed = !(toep->ddp_flags & DDP_ON) ^ cpl->ddp_off;
if (changed) {
- if (__predict_false(!(toep->ddp_flags & DDP_SC_REQ))) {
- /* XXX: handle this if legitimate */
- panic("%s: unexpected DDP state change %d",
- __func__, cpl->ddp_off);
+ if (toep->ddp_flags & DDP_SC_REQ)
+ toep->ddp_flags ^= DDP_ON | DDP_SC_REQ;
+ else {
+ KASSERT(cpl->ddp_off == 1,
+ ("%s: DDP switched on by itself.",
+ __func__));
+
+ /* Fell out of DDP mode */
+ toep->ddp_flags &= ~(DDP_ON | DDP_BUF0_ACTIVE |
+ DDP_BUF1_ACTIVE);
+
+ if (ddp_placed)
+ insert_ddp_data(toep, ddp_placed);
}
- toep->ddp_flags ^= DDP_ON | DDP_SC_REQ;
}
if ((toep->ddp_flags & DDP_OK) == 0 &&
OpenPOWER on IntegriCloud