cxgbe/tom: Handle the case where the chip falls out of DDP mode by

itself.  The hole in the receive sequence space corresponds to the
number of bytes placed directly up to that point.

MFC after:	1 week
This commit is contained in:
Navdeep Parhar 2012-11-29 19:39:27 +00:00
parent 000da5202e
commit d588c1f9ba
3 changed files with 53 additions and 12 deletions

View File

@ -1113,6 +1113,7 @@ 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)) {
#ifdef INVARIANTS
@ -1154,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__));
@ -1207,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 &&

View File

@ -205,6 +205,42 @@ release_ddp_resources(struct toepcb *toep)
}
}
/* XXX: handle_ddp_data code duplication */
void
insert_ddp_data(struct toepcb *toep, uint32_t n)
{
struct inpcb *inp = toep->inp;
struct tcpcb *tp = intotcpcb(inp);
struct sockbuf *sb = &inp->inp_socket->so_rcv;
struct mbuf *m;
INP_WLOCK_ASSERT(inp);
SOCKBUF_LOCK_ASSERT(sb);
m = m_get(M_NOWAIT, MT_DATA);
if (m == NULL)
CXGBE_UNIMPLEMENTED("mbuf alloc failure");
m->m_len = n;
m->m_flags |= M_DDP; /* Data is already where it should be */
m->m_data = "nothing to see here";
tp->rcv_nxt += n;
#ifndef USE_DDP_RX_FLOW_CONTROL
KASSERT(tp->rcv_wnd >= n, ("%s: negative window size", __func__));
tp->rcv_wnd -= n;
#endif
KASSERT(toep->sb_cc >= sb->sb_cc,
("%s: sb %p has more data (%d) than last time (%d).",
__func__, sb, sb->sb_cc, toep->sb_cc));
toep->rx_credits += toep->sb_cc - sb->sb_cc;
#ifdef USE_DDP_RX_FLOW_CONTROL
toep->rx_credits -= n; /* adjust for F_RX_FC_DDP */
#endif
sbappendstream_locked(sb, m);
toep->sb_cc = sb->sb_cc;
}
/* SET_TCB_FIELD sent as a ULP command looks like this */
#define LEN__SET_TCB_FIELD_ULP (sizeof(struct ulp_txpkt) + \
sizeof(struct ulptx_idata) + sizeof(struct cpl_set_tcb_field_core))

View File

@ -273,4 +273,5 @@ int t4_soreceive_ddp(struct socket *, struct sockaddr **, struct uio *,
struct mbuf **, struct mbuf **, int *);
void enable_ddp(struct adapter *, struct toepcb *toep);
void release_ddp_resources(struct toepcb *toep);
void insert_ddp_data(struct toepcb *, uint32_t);
#endif