]> CyberLeo.Net >> Repos - FreeBSD/releng/9.1.git/blob - sys/dev/cxgbe/tom/t4_cpl_io.c
Copy stable/9 to releng/9.1 as part of the 9.1-RELEASE release process.
[FreeBSD/releng/9.1.git] / sys / dev / cxgbe / tom / t4_cpl_io.c
1 /*-
2  * Copyright (c) 2012 Chelsio Communications, Inc.
3  * All rights reserved.
4  * Written by: Navdeep Parhar <np@FreeBSD.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include "opt_inet.h"
32
33 #ifdef TCP_OFFLOAD
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <sys/kernel.h>
37 #include <sys/ktr.h>
38 #include <sys/module.h>
39 #include <sys/protosw.h>
40 #include <sys/domain.h>
41 #include <sys/socket.h>
42 #include <sys/socketvar.h>
43 #include <sys/sglist.h>
44 #include <netinet/in.h>
45 #include <netinet/in_pcb.h>
46 #include <netinet/ip.h>
47 #include <netinet/tcp_var.h>
48 #define TCPSTATES
49 #include <netinet/tcp_fsm.h>
50 #include <netinet/tcp_seq.h>
51 #include <netinet/toecore.h>
52
53 #include "common/common.h"
54 #include "common/t4_msg.h"
55 #include "common/t4_regs.h"
56 #include "tom/t4_tom_l2t.h"
57 #include "tom/t4_tom.h"
58
59 VNET_DECLARE(int, tcp_do_autosndbuf);
60 #define V_tcp_do_autosndbuf VNET(tcp_do_autosndbuf)
61 VNET_DECLARE(int, tcp_autosndbuf_inc);
62 #define V_tcp_autosndbuf_inc VNET(tcp_autosndbuf_inc)
63 VNET_DECLARE(int, tcp_autosndbuf_max);
64 #define V_tcp_autosndbuf_max VNET(tcp_autosndbuf_max)
65 VNET_DECLARE(int, tcp_do_autorcvbuf);
66 #define V_tcp_do_autorcvbuf VNET(tcp_do_autorcvbuf)
67 VNET_DECLARE(int, tcp_autorcvbuf_inc);
68 #define V_tcp_autorcvbuf_inc VNET(tcp_autorcvbuf_inc)
69 VNET_DECLARE(int, tcp_autorcvbuf_max);
70 #define V_tcp_autorcvbuf_max VNET(tcp_autorcvbuf_max)
71
72 void
73 send_flowc_wr(struct toepcb *toep, struct flowc_tx_params *ftxp)
74 {
75         struct wrqe *wr;
76         struct fw_flowc_wr *flowc;
77         unsigned int nparams = ftxp ? 8 : 4, flowclen;
78         struct port_info *pi = toep->port;
79         struct adapter *sc = pi->adapter;
80         unsigned int pfvf = G_FW_VIID_PFN(pi->viid) << S_FW_VIID_PFN;
81         struct ofld_tx_sdesc *txsd = &toep->txsd[toep->txsd_pidx];
82
83         KASSERT(!toepcb_flag(toep, TPF_FLOWC_WR_SENT),
84             ("%s: flowc for tid %u sent already", __func__, toep->tid));
85
86         CTR2(KTR_CXGBE, "%s: tid %u", __func__, toep->tid);
87
88         flowclen = sizeof(*flowc) + nparams * sizeof(struct fw_flowc_mnemval);
89
90         wr = alloc_wrqe(roundup(flowclen, 16), toep->ofld_txq);
91         if (wr == NULL) {
92                 /* XXX */
93                 panic("%s: allocation failure.", __func__);
94         }
95         flowc = wrtod(wr);
96         memset(flowc, 0, wr->wr_len);
97
98         flowc->op_to_nparams = htobe32(V_FW_WR_OP(FW_FLOWC_WR) |
99             V_FW_FLOWC_WR_NPARAMS(nparams));
100         flowc->flowid_len16 = htonl(V_FW_WR_LEN16(howmany(flowclen, 16)) |
101             V_FW_WR_FLOWID(toep->tid));
102
103         flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN;
104         flowc->mnemval[0].val = htobe32(pfvf);
105         flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH;
106         flowc->mnemval[1].val = htobe32(pi->tx_chan);
107         flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT;
108         flowc->mnemval[2].val = htobe32(pi->tx_chan);
109         flowc->mnemval[3].mnemonic = FW_FLOWC_MNEM_IQID;
110         flowc->mnemval[3].val = htobe32(toep->ofld_rxq->iq.abs_id);
111         if (ftxp) {
112                 uint32_t sndbuf = min(ftxp->snd_space, sc->tt.sndbuf);
113
114                 flowc->mnemval[4].mnemonic = FW_FLOWC_MNEM_SNDNXT;
115                 flowc->mnemval[4].val = htobe32(ftxp->snd_nxt);
116                 flowc->mnemval[5].mnemonic = FW_FLOWC_MNEM_RCVNXT;
117                 flowc->mnemval[5].val = htobe32(ftxp->rcv_nxt);
118                 flowc->mnemval[6].mnemonic = FW_FLOWC_MNEM_SNDBUF;
119                 flowc->mnemval[6].val = htobe32(sndbuf);
120                 flowc->mnemval[7].mnemonic = FW_FLOWC_MNEM_MSS;
121                 flowc->mnemval[7].val = htobe32(ftxp->mss);
122         }
123
124         txsd->tx_credits = howmany(flowclen, 16);
125         txsd->plen = 0;
126         KASSERT(toep->tx_credits >= txsd->tx_credits && toep->txsd_avail > 0,
127             ("%s: not enough credits (%d)", __func__, toep->tx_credits));
128         toep->tx_credits -= txsd->tx_credits;
129         if (__predict_false(++toep->txsd_pidx == toep->txsd_total))
130                 toep->txsd_pidx = 0;
131         toep->txsd_avail--;
132
133         toepcb_set_flag(toep, TPF_FLOWC_WR_SENT);
134         t4_wrq_tx(sc, wr);
135 }
136
137 void
138 send_reset(struct adapter *sc, struct toepcb *toep, uint32_t snd_nxt)
139 {
140         struct wrqe *wr;
141         struct cpl_abort_req *req;
142         int tid = toep->tid;
143         struct inpcb *inp = toep->inp;
144         struct tcpcb *tp = intotcpcb(inp);      /* don't use if INP_DROPPED */
145
146         INP_WLOCK_ASSERT(inp);
147
148         CTR6(KTR_CXGBE, "%s: tid %d (%s), toep_flags 0x%x, inp_flags 0x%x%s",
149             __func__, toep->tid,
150             inp->inp_flags & INP_DROPPED ? "inp dropped" :
151             tcpstates[tp->t_state],
152             toep->flags, inp->inp_flags,
153             toepcb_flag(toep, TPF_ABORT_SHUTDOWN) ?
154             " (abort already in progress)" : "");
155
156         if (toepcb_flag(toep, TPF_ABORT_SHUTDOWN))
157                 return; /* abort already in progress */
158
159         toepcb_set_flag(toep, TPF_ABORT_SHUTDOWN);
160
161         KASSERT(toepcb_flag(toep, TPF_FLOWC_WR_SENT),
162             ("%s: flowc_wr not sent for tid %d.", __func__, tid));
163
164         wr = alloc_wrqe(sizeof(*req), toep->ofld_txq);
165         if (wr == NULL) {
166                 /* XXX */
167                 panic("%s: allocation failure.", __func__);
168         }
169         req = wrtod(wr);
170
171         INIT_TP_WR_MIT_CPL(req, CPL_ABORT_REQ, tid);
172         if (inp->inp_flags & INP_DROPPED)
173                 req->rsvd0 = htobe32(snd_nxt);
174         else
175                 req->rsvd0 = htobe32(tp->snd_nxt);
176         req->rsvd1 = !toepcb_flag(toep, TPF_TX_DATA_SENT);
177         req->cmd = CPL_ABORT_SEND_RST;
178
179         /*
180          * XXX: What's the correct way to tell that the inp hasn't been detached
181          * from its socket?  Should I even be flushing the snd buffer here?
182          */
183         if ((inp->inp_flags & (INP_DROPPED | INP_TIMEWAIT)) == 0) {
184                 struct socket *so = inp->inp_socket;
185
186                 if (so != NULL) /* because I'm not sure.  See comment above */
187                         sbflush(&so->so_snd);
188         }
189
190         t4_l2t_send(sc, wr, toep->l2te);
191 }
192
193 /*
194  * Called when a connection is established to translate the TCP options
195  * reported by HW to FreeBSD's native format.
196  */
197 static void
198 assign_rxopt(struct tcpcb *tp, unsigned int opt)
199 {
200         struct toepcb *toep = tp->t_toe;
201         struct adapter *sc = td_adapter(toep->td);
202
203         INP_LOCK_ASSERT(tp->t_inpcb);
204
205         tp->t_maxseg = tp->t_maxopd = sc->params.mtus[G_TCPOPT_MSS(opt)] - 40;
206
207         if (G_TCPOPT_TSTAMP(opt)) {
208                 tp->t_flags |= TF_RCVD_TSTMP;   /* timestamps ok */
209                 tp->ts_recent = 0;              /* hmmm */
210                 tp->ts_recent_age = tcp_ts_getticks();
211                 tp->t_maxseg -= TCPOLEN_TSTAMP_APPA;
212         }
213
214         if (G_TCPOPT_SACK(opt))
215                 tp->t_flags |= TF_SACK_PERMIT;  /* should already be set */
216         else
217                 tp->t_flags &= ~TF_SACK_PERMIT; /* sack disallowed by peer */
218
219         if (G_TCPOPT_WSCALE_OK(opt))
220                 tp->t_flags |= TF_RCVD_SCALE;
221
222         /* Doing window scaling? */
223         if ((tp->t_flags & (TF_RCVD_SCALE | TF_REQ_SCALE)) ==
224             (TF_RCVD_SCALE | TF_REQ_SCALE)) {
225                 tp->rcv_scale = tp->request_r_scale;
226                 tp->snd_scale = G_TCPOPT_SND_WSCALE(opt);
227         }
228 }
229
230 /*
231  * Completes some final bits of initialization for just established connections
232  * and changes their state to TCPS_ESTABLISHED.
233  *
234  * The ISNs are from after the exchange of SYNs.  i.e., the true ISN + 1.
235  */
236 void
237 make_established(struct toepcb *toep, uint32_t snd_isn, uint32_t rcv_isn,
238     uint16_t opt)
239 {
240         struct inpcb *inp = toep->inp;
241         struct socket *so = inp->inp_socket;
242         struct tcpcb *tp = intotcpcb(inp);
243         long bufsize;
244         uint32_t iss = be32toh(snd_isn) - 1;    /* true ISS */
245         uint32_t irs = be32toh(rcv_isn) - 1;    /* true IRS */
246         uint16_t tcpopt = be16toh(opt);
247         struct flowc_tx_params ftxp;
248
249         INP_WLOCK_ASSERT(inp);
250         KASSERT(tp->t_state == TCPS_SYN_SENT ||
251             tp->t_state == TCPS_SYN_RECEIVED,
252             ("%s: TCP state %s", __func__, tcpstates[tp->t_state]));
253
254         CTR4(KTR_CXGBE, "%s: tid %d, toep %p, inp %p",
255             __func__, toep->tid, toep, inp);
256
257         tp->t_state = TCPS_ESTABLISHED;
258         tp->t_starttime = ticks;
259         TCPSTAT_INC(tcps_connects);
260
261         tp->irs = irs;
262         tcp_rcvseqinit(tp);
263         tp->rcv_wnd = toep->rx_credits << 10;
264         tp->rcv_adv += tp->rcv_wnd;
265         tp->last_ack_sent = tp->rcv_nxt;
266
267         /*
268          * If we were unable to send all rx credits via opt0, save the remainder
269          * in rx_credits so that they can be handed over with the next credit
270          * update.
271          */
272         SOCKBUF_LOCK(&so->so_rcv);
273         bufsize = select_rcv_wnd(so);
274         SOCKBUF_UNLOCK(&so->so_rcv);
275         toep->rx_credits = bufsize - tp->rcv_wnd;
276
277         tp->iss = iss;
278         tcp_sendseqinit(tp);
279         tp->snd_una = iss + 1;
280         tp->snd_nxt = iss + 1;
281         tp->snd_max = iss + 1;
282
283         assign_rxopt(tp, tcpopt);
284
285         SOCKBUF_LOCK(&so->so_snd);
286         if (so->so_snd.sb_flags & SB_AUTOSIZE && V_tcp_do_autosndbuf)
287                 bufsize = V_tcp_autosndbuf_max;
288         else
289                 bufsize = sbspace(&so->so_snd);
290         SOCKBUF_UNLOCK(&so->so_snd);
291
292         ftxp.snd_nxt = tp->snd_nxt;
293         ftxp.rcv_nxt = tp->rcv_nxt;
294         ftxp.snd_space = bufsize;
295         ftxp.mss = tp->t_maxseg;
296         send_flowc_wr(toep, &ftxp);
297
298         soisconnected(so);
299 }
300
301 static int
302 send_rx_credits(struct adapter *sc, struct toepcb *toep, uint32_t credits)
303 {
304         struct wrqe *wr;
305         struct cpl_rx_data_ack *req;
306         uint32_t dack = F_RX_DACK_CHANGE | V_RX_DACK_MODE(1);
307
308         wr = alloc_wrqe(sizeof(*req), toep->ctrlq);
309         if (wr == NULL)
310                 return (0);
311         req = wrtod(wr);
312
313         INIT_TP_WR_MIT_CPL(req, CPL_RX_DATA_ACK, toep->tid);
314         req->credit_dack = htobe32(dack | V_RX_CREDITS(credits));
315
316         t4_wrq_tx(sc, wr);
317         return (credits);
318 }
319
320 void
321 t4_rcvd(struct toedev *tod, struct tcpcb *tp)
322 {
323         struct adapter *sc = tod->tod_softc;
324         struct inpcb *inp = tp->t_inpcb;
325         struct socket *so = inp->inp_socket;
326         struct sockbuf *so_rcv = &so->so_rcv;
327         struct toepcb *toep = tp->t_toe;
328         int must_send;
329
330         INP_WLOCK_ASSERT(inp);
331
332         SOCKBUF_LOCK(so_rcv);
333         KASSERT(toep->enqueued >= so_rcv->sb_cc,
334             ("%s: so_rcv->sb_cc > enqueued", __func__));
335         toep->rx_credits += toep->enqueued - so_rcv->sb_cc;
336         toep->enqueued = so_rcv->sb_cc;
337         SOCKBUF_UNLOCK(so_rcv);
338
339         must_send = toep->rx_credits + 16384 >= tp->rcv_wnd;
340         if (must_send || toep->rx_credits >= 15 * 1024) {
341                 int credits;
342
343                 credits = send_rx_credits(sc, toep, toep->rx_credits);
344                 toep->rx_credits -= credits;
345                 tp->rcv_wnd += credits;
346                 tp->rcv_adv += credits;
347         }
348 }
349
350 /*
351  * Close a connection by sending a CPL_CLOSE_CON_REQ message.
352  */
353 static int
354 close_conn(struct adapter *sc, struct toepcb *toep)
355 {
356         struct wrqe *wr;
357         struct cpl_close_con_req *req;
358         unsigned int tid = toep->tid;
359
360         CTR3(KTR_CXGBE, "%s: tid %u%s", __func__, toep->tid,
361             toepcb_flag(toep, TPF_FIN_SENT) ? ", IGNORED" : "");
362
363         if (toepcb_flag(toep, TPF_FIN_SENT))
364                 return (0);
365
366         KASSERT(toepcb_flag(toep, TPF_FLOWC_WR_SENT),
367             ("%s: flowc_wr not sent for tid %u.", __func__, tid));
368
369         wr = alloc_wrqe(sizeof(*req), toep->ofld_txq);
370         if (wr == NULL) {
371                 /* XXX */
372                 panic("%s: allocation failure.", __func__);
373         }
374         req = wrtod(wr);
375
376         req->wr.wr_hi = htonl(V_FW_WR_OP(FW_TP_WR) |
377             V_FW_WR_IMMDLEN(sizeof(*req) - sizeof(req->wr)));
378         req->wr.wr_mid = htonl(V_FW_WR_LEN16(howmany(sizeof(*req), 16)) |
379             V_FW_WR_FLOWID(tid));
380         req->wr.wr_lo = cpu_to_be64(0);
381         OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, tid));
382         req->rsvd = 0;
383
384         toepcb_set_flag(toep, TPF_FIN_SENT);
385         toepcb_clr_flag(toep, TPF_SEND_FIN);
386         t4_l2t_send(sc, wr, toep->l2te);
387
388         return (0);
389 }
390
391 #define MAX_OFLD_TX_CREDITS (SGE_MAX_WR_LEN / 16)
392 #define MIN_OFLD_TX_CREDITS (howmany(sizeof(struct fw_ofld_tx_data_wr) + 1, 16))
393
394 /* Maximum amount of immediate data we could stuff in a WR */
395 static inline int
396 max_imm_payload(int tx_credits)
397 {
398         const int n = 2;        /* Use only up to 2 desc for imm. data WR */
399
400         KASSERT(tx_credits >= 0 &&
401                 tx_credits <= MAX_OFLD_TX_CREDITS,
402                 ("%s: %d credits", __func__, tx_credits));
403
404         if (tx_credits < MIN_OFLD_TX_CREDITS)
405                 return (0);
406
407         if (tx_credits >= (n * EQ_ESIZE) / 16)
408                 return ((n * EQ_ESIZE) - sizeof(struct fw_ofld_tx_data_wr));
409         else
410                 return (tx_credits * 16 - sizeof(struct fw_ofld_tx_data_wr));
411 }
412
413 /* Maximum number of SGL entries we could stuff in a WR */
414 static inline int
415 max_dsgl_nsegs(int tx_credits)
416 {
417         int nseg = 1;   /* ulptx_sgl has room for 1, rest ulp_tx_sge_pair */
418         int sge_pair_credits = tx_credits - MIN_OFLD_TX_CREDITS;
419
420         KASSERT(tx_credits >= 0 &&
421                 tx_credits <= MAX_OFLD_TX_CREDITS,
422                 ("%s: %d credits", __func__, tx_credits));
423
424         if (tx_credits < MIN_OFLD_TX_CREDITS)
425                 return (0);
426
427         nseg += 2 * (sge_pair_credits * 16 / 24);
428         if ((sge_pair_credits * 16) % 24 == 16)
429                 nseg++;
430
431         return (nseg);
432 }
433
434 static inline void
435 write_tx_wr(void *dst, struct toepcb *toep, unsigned int immdlen,
436     unsigned int plen, uint8_t credits, int more_to_come)
437 {
438         struct fw_ofld_tx_data_wr *txwr = dst;
439         int shove = !more_to_come;
440         int compl = 1;
441
442         /*
443          * We always request completion notifications from the firmware.  The
444          * only exception is when we know we'll get more data to send shortly
445          * and that we'll have some tx credits remaining to transmit that data.
446          */
447         if (more_to_come && toep->tx_credits - credits >= MIN_OFLD_TX_CREDITS)
448                 compl = 0;
449
450         txwr->op_to_immdlen = htobe32(V_WR_OP(FW_OFLD_TX_DATA_WR) |
451             V_FW_WR_COMPL(compl) | V_FW_WR_IMMDLEN(immdlen));
452         txwr->flowid_len16 = htobe32(V_FW_WR_FLOWID(toep->tid) |
453             V_FW_WR_LEN16(credits));
454         txwr->tunnel_to_proxy =
455             htobe32(V_FW_OFLD_TX_DATA_WR_ULPMODE(toep->ulp_mode) |
456                 V_FW_OFLD_TX_DATA_WR_URGENT(0) |        /* XXX */
457                 V_FW_OFLD_TX_DATA_WR_SHOVE(shove));
458         txwr->plen = htobe32(plen);
459 }
460
461 /*
462  * Generate a DSGL from a starting mbuf.  The total number of segments and the
463  * maximum segments in any one mbuf are provided.
464  */
465 static void
466 write_tx_sgl(void *dst, struct mbuf *start, struct mbuf *stop, int nsegs, int n)
467 {
468         struct mbuf *m;
469         struct ulptx_sgl *usgl = dst;
470         int i, j, rc;
471         struct sglist sg;
472         struct sglist_seg segs[n];
473
474         KASSERT(nsegs > 0, ("%s: nsegs 0", __func__));
475
476         sglist_init(&sg, n, segs);
477         usgl->cmd_nsge = htobe32(V_ULPTX_CMD(ULP_TX_SC_DSGL) |
478             V_ULPTX_NSGE(nsegs));
479
480         i = -1;
481         for (m = start; m != stop; m = m->m_next) {
482                 rc = sglist_append(&sg, mtod(m, void *), m->m_len);
483                 if (__predict_false(rc != 0))
484                         panic("%s: sglist_append %d", __func__, rc);
485
486                 for (j = 0; j < sg.sg_nseg; i++, j++) {
487                         if (i < 0) {
488                                 usgl->len0 = htobe32(segs[j].ss_len);
489                                 usgl->addr0 = htobe64(segs[j].ss_paddr);
490                         } else {
491                                 usgl->sge[i / 2].len[i & 1] =
492                                     htobe32(segs[j].ss_len);
493                                 usgl->sge[i / 2].addr[i & 1] =
494                                     htobe64(segs[j].ss_paddr);
495                         }
496 #ifdef INVARIANTS
497                         nsegs--;
498 #endif
499                 }
500                 sglist_reset(&sg);
501         }
502         if (i & 1)
503                 usgl->sge[i / 2].len[1] = htobe32(0);
504         KASSERT(nsegs == 0, ("%s: nsegs %d, start %p, stop %p",
505             __func__, nsegs, start, stop));
506 }
507
508 /*
509  * Max number of SGL entries an offload tx work request can have.  This is 41
510  * (1 + 40) for a full 512B work request.
511  * fw_ofld_tx_data_wr(16B) + ulptx_sgl(16B, 1) + ulptx_sge_pair(480B, 40)
512  */
513 #define OFLD_SGL_LEN (41)
514
515 /*
516  * Send data and/or a FIN to the peer.
517  *
518  * The socket's so_snd buffer consists of a stream of data starting with sb_mb
519  * and linked together with m_next.  sb_sndptr, if set, is the last mbuf that
520  * was transmitted.
521  */
522 static void
523 t4_push_frames(struct adapter *sc, struct toepcb *toep)
524 {
525         struct mbuf *sndptr, *m, *sb_sndptr;
526         struct fw_ofld_tx_data_wr *txwr;
527         struct wrqe *wr;
528         unsigned int plen, nsegs, credits, max_imm, max_nsegs, max_nsegs_1mbuf;
529         struct inpcb *inp = toep->inp;
530         struct tcpcb *tp = intotcpcb(inp);
531         struct socket *so = inp->inp_socket;
532         struct sockbuf *sb = &so->so_snd;
533         int tx_credits;
534         struct ofld_tx_sdesc *txsd = &toep->txsd[toep->txsd_pidx];
535
536         INP_WLOCK_ASSERT(inp);
537         KASSERT(toepcb_flag(toep, TPF_FLOWC_WR_SENT),
538             ("%s: flowc_wr not sent for tid %u.", __func__, toep->tid));
539
540         if (toep->ulp_mode != ULP_MODE_NONE)
541                 CXGBE_UNIMPLEMENTED("ulp_mode");
542
543         /*
544          * This function doesn't resume by itself.  Someone else must clear the
545          * flag and call this function.
546          */
547         if (__predict_false(toepcb_flag(toep, TPF_TX_SUSPENDED)))
548                 return;
549
550         do {
551                 tx_credits = min(toep->tx_credits, MAX_OFLD_TX_CREDITS);
552                 max_imm = max_imm_payload(tx_credits);
553                 max_nsegs = max_dsgl_nsegs(tx_credits);
554
555                 SOCKBUF_LOCK(sb);
556                 sb_sndptr = sb->sb_sndptr;
557                 sndptr = sb_sndptr ? sb_sndptr->m_next : sb->sb_mb;
558                 plen = 0;
559                 nsegs = 0;
560                 max_nsegs_1mbuf = 0; /* max # of SGL segments in any one mbuf */
561                 for (m = sndptr; m != NULL; m = m->m_next) {
562                         int n = sglist_count(mtod(m, void *), m->m_len);
563
564                         nsegs += n;
565                         plen += m->m_len;
566
567                         /* This mbuf sent us _over_ the nsegs limit, back out */
568                         if (plen > max_imm && nsegs > max_nsegs) {
569                                 nsegs -= n;
570                                 plen -= m->m_len;
571                                 if (plen == 0) {
572                                         /* Too few credits */
573                                         toepcb_set_flag(toep, TPF_TX_SUSPENDED);
574                                         SOCKBUF_UNLOCK(sb);
575                                         return;
576                                 }
577                                 break;
578                         }
579
580                         if (max_nsegs_1mbuf < n)
581                                 max_nsegs_1mbuf = n;
582                         sb_sndptr = m;  /* new sb->sb_sndptr if all goes well */
583
584                         /* This mbuf put us right at the max_nsegs limit */
585                         if (plen > max_imm && nsegs == max_nsegs) {
586                                 m = m->m_next;
587                                 break;
588                         }
589                 }
590
591                 if (sb->sb_flags & SB_AUTOSIZE &&
592                     V_tcp_do_autosndbuf &&
593                     sb->sb_hiwat < V_tcp_autosndbuf_max &&
594                     sbspace(sb) < sb->sb_hiwat / 8 * 7) {
595                         int newsize = min(sb->sb_hiwat + V_tcp_autosndbuf_inc,
596                             V_tcp_autosndbuf_max);
597
598                         if (!sbreserve_locked(sb, newsize, so, NULL))
599                                 sb->sb_flags &= ~SB_AUTOSIZE;
600                         else {
601                                 sowwakeup_locked(so);   /* room available */
602                                 SOCKBUF_UNLOCK_ASSERT(sb);
603                                 goto unlocked;
604                         }
605                 }
606                 SOCKBUF_UNLOCK(sb);
607 unlocked:
608
609                 /* nothing to send */
610                 if (plen == 0) {
611                         KASSERT(m == NULL,
612                             ("%s: nothing to send, but m != NULL", __func__));
613                         break;
614                 }
615
616                 if (__predict_false(toepcb_flag(toep, TPF_FIN_SENT)))
617                         panic("%s: excess tx.", __func__);
618
619                 if (plen <= max_imm) {
620
621                         /* Immediate data tx */
622
623                         wr = alloc_wrqe(roundup(sizeof(*txwr) + plen, 16),
624                                         toep->ofld_txq);
625                         if (wr == NULL) {
626                                 /* XXX: how will we recover from this? */
627                                 toepcb_set_flag(toep, TPF_TX_SUSPENDED);
628                                 return;
629                         }
630                         txwr = wrtod(wr);
631                         credits = howmany(wr->wr_len, 16);
632                         write_tx_wr(txwr, toep, plen, plen, credits,
633                             tp->t_flags & TF_MORETOCOME);
634                         m_copydata(sndptr, 0, plen, (void *)(txwr + 1));
635                 } else {
636                         int wr_len;
637
638                         /* DSGL tx */
639
640                         wr_len = sizeof(*txwr) + sizeof(struct ulptx_sgl) +
641                             ((3 * (nsegs - 1)) / 2 + ((nsegs - 1) & 1)) * 8;
642                         wr = alloc_wrqe(roundup(wr_len, 16), toep->ofld_txq);
643                         if (wr == NULL) {
644                                 /* XXX: how will we recover from this? */
645                                 toepcb_set_flag(toep, TPF_TX_SUSPENDED);
646                                 return;
647                         }
648                         txwr = wrtod(wr);
649                         credits = howmany(wr_len, 16);
650                         write_tx_wr(txwr, toep, 0, plen, credits,
651                             tp->t_flags & TF_MORETOCOME);
652                         write_tx_sgl(txwr + 1, sndptr, m, nsegs,
653                             max_nsegs_1mbuf);
654                         if (wr_len & 0xf) {
655                                 uint64_t *pad = (uint64_t *)
656                                     ((uintptr_t)txwr + wr_len);
657                                 *pad = 0;
658                         }
659                 }
660
661                 KASSERT(toep->tx_credits >= credits,
662                         ("%s: not enough credits", __func__));
663
664                 toep->tx_credits -= credits;
665
666                 tp->snd_nxt += plen;
667                 tp->snd_max += plen;
668
669                 SOCKBUF_LOCK(sb);
670                 KASSERT(sb_sndptr, ("%s: sb_sndptr is NULL", __func__));
671                 sb->sb_sndptr = sb_sndptr;
672                 SOCKBUF_UNLOCK(sb);
673
674                 toepcb_set_flag(toep, TPF_TX_DATA_SENT);
675
676                 KASSERT(toep->txsd_avail > 0, ("%s: no txsd", __func__));
677                 txsd->plen = plen;
678                 txsd->tx_credits = credits;
679                 txsd++;
680                 if (__predict_false(++toep->txsd_pidx == toep->txsd_total)) {
681                         toep->txsd_pidx = 0;
682                         txsd = &toep->txsd[0];
683                 }
684                 toep->txsd_avail--;
685
686                 t4_l2t_send(sc, wr, toep->l2te);
687         } while (m != NULL);
688
689         /* Send a FIN if requested, but only if there's no more data to send */
690         if (m == NULL && toepcb_flag(toep, TPF_SEND_FIN))
691                 close_conn(sc, toep);
692 }
693
694 int
695 t4_tod_output(struct toedev *tod, struct tcpcb *tp)
696 {
697         struct adapter *sc = tod->tod_softc;
698 #ifdef INVARIANTS
699         struct inpcb *inp = tp->t_inpcb;
700 #endif
701         struct toepcb *toep = tp->t_toe;
702
703         INP_WLOCK_ASSERT(inp);
704         KASSERT((inp->inp_flags & INP_DROPPED) == 0,
705             ("%s: inp %p dropped.", __func__, inp));
706         KASSERT(toep != NULL, ("%s: toep is NULL", __func__));
707
708         t4_push_frames(sc, toep);
709
710         return (0);
711 }
712
713 int
714 t4_send_fin(struct toedev *tod, struct tcpcb *tp)
715 {
716         struct adapter *sc = tod->tod_softc;
717 #ifdef INVARIANTS
718         struct inpcb *inp = tp->t_inpcb;
719 #endif
720         struct toepcb *toep = tp->t_toe;
721
722         INP_WLOCK_ASSERT(inp);
723         KASSERT((inp->inp_flags & INP_DROPPED) == 0,
724             ("%s: inp %p dropped.", __func__, inp));
725         KASSERT(toep != NULL, ("%s: toep is NULL", __func__));
726
727         toepcb_set_flag(toep, TPF_SEND_FIN);
728         t4_push_frames(sc, toep);
729
730         return (0);
731 }
732
733 int
734 t4_send_rst(struct toedev *tod, struct tcpcb *tp)
735 {
736         struct adapter *sc = tod->tod_softc;
737 #if defined(INVARIANTS)
738         struct inpcb *inp = tp->t_inpcb;
739 #endif
740         struct toepcb *toep = tp->t_toe;
741
742         INP_WLOCK_ASSERT(inp);
743         KASSERT((inp->inp_flags & INP_DROPPED) == 0,
744             ("%s: inp %p dropped.", __func__, inp));
745         KASSERT(toep != NULL, ("%s: toep is NULL", __func__));
746
747         /* hmmmm */
748         KASSERT(toepcb_flag(toep, TPF_FLOWC_WR_SENT),
749             ("%s: flowc for tid %u [%s] not sent already",
750             __func__, toep->tid, tcpstates[tp->t_state]));
751
752         send_reset(sc, toep, 0);
753         return (0);
754 }
755
756 /*
757  * Peer has sent us a FIN.
758  */
759 static int
760 do_peer_close(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
761 {
762         struct adapter *sc = iq->adapter;
763         const struct cpl_peer_close *cpl = (const void *)(rss + 1);
764         unsigned int tid = GET_TID(cpl);
765         struct toepcb *toep = lookup_tid(sc, tid);
766         struct inpcb *inp = toep->inp;
767         struct tcpcb *tp = NULL;
768         struct socket *so = NULL;
769 #ifdef INVARIANTS
770         unsigned int opcode = G_CPL_OPCODE(be32toh(OPCODE_TID(cpl)));
771 #endif
772
773         KASSERT(opcode == CPL_PEER_CLOSE,
774             ("%s: unexpected opcode 0x%x", __func__, opcode));
775         KASSERT(m == NULL, ("%s: wasn't expecting payload", __func__));
776         KASSERT(toep->tid == tid, ("%s: toep tid mismatch", __func__));
777
778         INP_INFO_WLOCK(&V_tcbinfo);
779         INP_WLOCK(inp);
780         tp = intotcpcb(inp);
781
782         CTR5(KTR_CXGBE, "%s: tid %u (%s), toep_flags 0x%x, inp %p", __func__,
783             tid, tp ? tcpstates[tp->t_state] : "no tp", toep->flags, inp);
784
785         if (toepcb_flag(toep, TPF_ABORT_SHUTDOWN))
786                 goto done;
787
788         so = inp->inp_socket;
789
790         socantrcvmore(so);
791         tp->rcv_nxt++;  /* FIN */
792         KASSERT(tp->rcv_nxt == be32toh(cpl->rcv_nxt),
793             ("%s: rcv_nxt mismatch: %u %u", __func__, tp->rcv_nxt,
794             be32toh(cpl->rcv_nxt)));
795
796         switch (tp->t_state) {
797         case TCPS_SYN_RECEIVED:
798                 tp->t_starttime = ticks;
799                 /* FALLTHROUGH */ 
800
801         case TCPS_ESTABLISHED:
802                 tp->t_state = TCPS_CLOSE_WAIT;
803                 break;
804
805         case TCPS_FIN_WAIT_1:
806                 tp->t_state = TCPS_CLOSING;
807                 break;
808
809         case TCPS_FIN_WAIT_2:
810                 tcp_twstart(tp);
811                 INP_UNLOCK_ASSERT(inp);  /* safe, we have a ref on the inp */
812                 INP_INFO_WUNLOCK(&V_tcbinfo);
813
814                 INP_WLOCK(inp);
815                 final_cpl_received(toep);
816                 return (0);
817
818         default:
819                 log(LOG_ERR, "%s: TID %u received CPL_PEER_CLOSE in state %d\n",
820                     __func__, tid, tp->t_state);
821         }
822 done:
823         INP_WUNLOCK(inp);
824         INP_INFO_WUNLOCK(&V_tcbinfo);
825         return (0);
826 }
827
828 /*
829  * Peer has ACK'd our FIN.
830  */
831 static int
832 do_close_con_rpl(struct sge_iq *iq, const struct rss_header *rss,
833     struct mbuf *m)
834 {
835         struct adapter *sc = iq->adapter;
836         const struct cpl_close_con_rpl *cpl = (const void *)(rss + 1);
837         unsigned int tid = GET_TID(cpl);
838         struct toepcb *toep = lookup_tid(sc, tid);
839         struct inpcb *inp = toep->inp;
840         struct tcpcb *tp = NULL;
841         struct socket *so = NULL;
842 #ifdef INVARIANTS
843         unsigned int opcode = G_CPL_OPCODE(be32toh(OPCODE_TID(cpl)));
844 #endif
845
846         KASSERT(opcode == CPL_CLOSE_CON_RPL,
847             ("%s: unexpected opcode 0x%x", __func__, opcode));
848         KASSERT(m == NULL, ("%s: wasn't expecting payload", __func__));
849         KASSERT(toep->tid == tid, ("%s: toep tid mismatch", __func__));
850
851         INP_INFO_WLOCK(&V_tcbinfo);
852         INP_WLOCK(inp);
853         tp = intotcpcb(inp);
854
855         CTR4(KTR_CXGBE, "%s: tid %u (%s), toep_flags 0x%x",
856             __func__, tid, tp ? tcpstates[tp->t_state] : "no tp", toep->flags);
857
858         if (toepcb_flag(toep, TPF_ABORT_SHUTDOWN))
859                 goto done;
860
861         so = inp->inp_socket;
862         tp->snd_una = be32toh(cpl->snd_nxt) - 1;        /* exclude FIN */
863
864         switch (tp->t_state) {
865         case TCPS_CLOSING:      /* see TCPS_FIN_WAIT_2 in do_peer_close too */
866                 tcp_twstart(tp);
867 release:
868                 INP_UNLOCK_ASSERT(inp); /* safe, we have a ref on the  inp */
869                 INP_INFO_WUNLOCK(&V_tcbinfo);
870
871                 INP_WLOCK(inp);
872                 final_cpl_received(toep);       /* no more CPLs expected */
873
874                 return (0);
875         case TCPS_LAST_ACK:
876                 if (tcp_close(tp))
877                         INP_WUNLOCK(inp);
878                 goto release;
879
880         case TCPS_FIN_WAIT_1:
881                 if (so->so_rcv.sb_state & SBS_CANTRCVMORE)
882                         soisdisconnected(so);
883                 tp->t_state = TCPS_FIN_WAIT_2;
884                 break;
885
886         default:
887                 log(LOG_ERR,
888                     "%s: TID %u received CPL_CLOSE_CON_RPL in state %s\n",
889                     __func__, tid, tcpstates[tp->t_state]);
890         }
891 done:
892         INP_WUNLOCK(inp);
893         INP_INFO_WUNLOCK(&V_tcbinfo);
894         return (0);
895 }
896
897 void
898 send_abort_rpl(struct adapter *sc, struct sge_wrq *ofld_txq, int tid,
899     int rst_status)
900 {
901         struct wrqe *wr;
902         struct cpl_abort_rpl *cpl;
903
904         wr = alloc_wrqe(sizeof(*cpl), ofld_txq);
905         if (wr == NULL) {
906                 /* XXX */
907                 panic("%s: allocation failure.", __func__);
908         }
909         cpl = wrtod(wr);
910
911         INIT_TP_WR_MIT_CPL(cpl, CPL_ABORT_RPL, tid);
912         cpl->cmd = rst_status;
913
914         t4_wrq_tx(sc, wr);
915 }
916
917 static int
918 abort_status_to_errno(struct tcpcb *tp, unsigned int abort_reason)
919 {
920         switch (abort_reason) {
921         case CPL_ERR_BAD_SYN:
922         case CPL_ERR_CONN_RESET:
923                 return (tp->t_state == TCPS_CLOSE_WAIT ? EPIPE : ECONNRESET);
924         case CPL_ERR_XMIT_TIMEDOUT:
925         case CPL_ERR_PERSIST_TIMEDOUT:
926         case CPL_ERR_FINWAIT2_TIMEDOUT:
927         case CPL_ERR_KEEPALIVE_TIMEDOUT:
928                 return (ETIMEDOUT);
929         default:
930                 return (EIO);
931         }
932 }
933
934 /*
935  * TCP RST from the peer, timeout, or some other such critical error.
936  */
937 static int
938 do_abort_req(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
939 {
940         struct adapter *sc = iq->adapter;
941         const struct cpl_abort_req_rss *cpl = (const void *)(rss + 1);
942         unsigned int tid = GET_TID(cpl);
943         struct toepcb *toep = lookup_tid(sc, tid);
944         struct sge_wrq *ofld_txq = toep->ofld_txq;
945         struct inpcb *inp;
946         struct tcpcb *tp;
947         struct socket *so;
948 #ifdef INVARIANTS
949         unsigned int opcode = G_CPL_OPCODE(be32toh(OPCODE_TID(cpl)));
950 #endif
951
952         KASSERT(opcode == CPL_ABORT_REQ_RSS,
953             ("%s: unexpected opcode 0x%x", __func__, opcode));
954         KASSERT(m == NULL, ("%s: wasn't expecting payload", __func__));
955
956         if (toepcb_flag(toep, TPF_SYNQE))
957                 return (do_abort_req_synqe(iq, rss, m));
958
959         KASSERT(toep->tid == tid, ("%s: toep tid mismatch", __func__));
960
961         if (cpl->status == CPL_ERR_RTX_NEG_ADVICE ||
962             cpl->status == CPL_ERR_PERSIST_NEG_ADVICE) {
963                 CTR4(KTR_CXGBE, "%s: negative advice %d for tid %d (0x%x)",
964                     __func__, cpl->status, tid, toep->flags);
965                 return (0);     /* Ignore negative advice */
966         }
967
968         inp = toep->inp;
969         INP_INFO_WLOCK(&V_tcbinfo);     /* for tcp_close */
970         INP_WLOCK(inp);
971
972         tp = intotcpcb(inp);
973         so = inp->inp_socket;
974
975         CTR6(KTR_CXGBE,
976             "%s: tid %d (%s), toep_flags 0x%x, inp_flags 0x%x, status %d",
977             __func__, tid, tcpstates[tp->t_state], toep->flags, inp->inp_flags,
978             cpl->status);
979
980         /*
981          * If we'd initiated an abort earlier the reply to it is responsible for
982          * cleaning up resources.  Otherwise we tear everything down right here
983          * right now.  We owe the T4 a CPL_ABORT_RPL no matter what.
984          */
985         if (toepcb_flag(toep, TPF_ABORT_SHUTDOWN)) {
986                 INP_WUNLOCK(inp);
987                 goto done;
988         }
989         toepcb_set_flag(toep, TPF_ABORT_SHUTDOWN);
990
991         so_error_set(so, abort_status_to_errno(tp, cpl->status));
992         tp = tcp_close(tp);
993         if (tp == NULL)
994                 INP_WLOCK(inp); /* re-acquire */
995
996         final_cpl_received(toep);
997 done:
998         INP_INFO_WUNLOCK(&V_tcbinfo);
999         send_abort_rpl(sc, ofld_txq, tid, CPL_ABORT_NO_RST);
1000         return (0);
1001 }
1002
1003 /*
1004  * Reply to the CPL_ABORT_REQ (send_reset)
1005  */
1006 static int
1007 do_abort_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
1008 {
1009         struct adapter *sc = iq->adapter;
1010         const struct cpl_abort_rpl_rss *cpl = (const void *)(rss + 1);
1011         unsigned int tid = GET_TID(cpl);
1012         struct toepcb *toep = lookup_tid(sc, tid);
1013         struct inpcb *inp = toep->inp;
1014 #ifdef INVARIANTS
1015         unsigned int opcode = G_CPL_OPCODE(be32toh(OPCODE_TID(cpl)));
1016 #endif
1017
1018         KASSERT(opcode == CPL_ABORT_RPL_RSS,
1019             ("%s: unexpected opcode 0x%x", __func__, opcode));
1020         KASSERT(m == NULL, ("%s: wasn't expecting payload", __func__));
1021
1022         if (toepcb_flag(toep, TPF_SYNQE))
1023                 return (do_abort_rpl_synqe(iq, rss, m));
1024
1025         KASSERT(toep->tid == tid, ("%s: toep tid mismatch", __func__));
1026
1027         CTR5(KTR_CXGBE, "%s: tid %u, toep %p, inp %p, status %d",
1028             __func__, tid, toep, inp, cpl->status);
1029
1030         KASSERT(toepcb_flag(toep, TPF_ABORT_SHUTDOWN),
1031             ("%s: wasn't expecting abort reply", __func__));
1032
1033         INP_WLOCK(inp);
1034         final_cpl_received(toep);
1035
1036         return (0);
1037 }
1038
1039 static int
1040 do_rx_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
1041 {
1042         struct adapter *sc = iq->adapter;
1043         const struct cpl_rx_data *cpl = mtod(m, const void *);
1044         unsigned int tid = GET_TID(cpl);
1045         struct toepcb *toep = lookup_tid(sc, tid);
1046         struct inpcb *inp = toep->inp;
1047         struct tcpcb *tp;
1048         struct socket *so;
1049         struct sockbuf *so_rcv;
1050
1051         if (__predict_false(toepcb_flag(toep, TPF_SYNQE))) {
1052                 /*
1053                  * do_pass_establish failed and must be attempting to abort the
1054                  * synqe's tid.  Meanwhile, the T4 has sent us data for such a
1055                  * connection.
1056                  */
1057                 KASSERT(toepcb_flag(toep, TPF_ABORT_SHUTDOWN),
1058                     ("%s: synqe and tid isn't being aborted.", __func__));
1059                 m_freem(m);
1060                 return (0);
1061         }
1062
1063         KASSERT(toep->tid == tid, ("%s: toep tid mismatch", __func__));
1064
1065         /* strip off CPL header */
1066         m_adj(m, sizeof(*cpl));
1067
1068         INP_WLOCK(inp);
1069         if (inp->inp_flags & (INP_DROPPED | INP_TIMEWAIT)) {
1070                 CTR4(KTR_CXGBE, "%s: tid %u, rx (%d bytes), inp_flags 0x%x",
1071                     __func__, tid, m->m_pkthdr.len, inp->inp_flags);
1072                 INP_WUNLOCK(inp);
1073                 m_freem(m);
1074                 return (0);
1075         }
1076
1077         tp = intotcpcb(inp);
1078
1079 #ifdef INVARIANTS
1080         if (__predict_false(tp->rcv_nxt != be32toh(cpl->seq))) {
1081                 log(LOG_ERR,
1082                     "%s: unexpected seq# %x for TID %u, rcv_nxt %x\n",
1083                     __func__, be32toh(cpl->seq), toep->tid, tp->rcv_nxt);
1084         }
1085 #endif
1086
1087         tp->rcv_nxt += m->m_pkthdr.len;
1088         KASSERT(tp->rcv_wnd >= m->m_pkthdr.len,
1089             ("%s: negative window size", __func__));
1090         tp->rcv_wnd -= m->m_pkthdr.len;
1091         tp->t_rcvtime = ticks;
1092
1093         so = inp_inpcbtosocket(inp);
1094         so_rcv = &so->so_rcv;
1095         SOCKBUF_LOCK(so_rcv);
1096
1097         if (__predict_false(so_rcv->sb_state & SBS_CANTRCVMORE)) {
1098                 CTR3(KTR_CXGBE, "%s: tid %u, excess rx (%d bytes)",
1099                     __func__, tid, m->m_pkthdr.len);
1100                 m_freem(m);
1101                 SOCKBUF_UNLOCK(so_rcv);
1102                 INP_WUNLOCK(inp);
1103
1104                 INP_INFO_WLOCK(&V_tcbinfo);
1105                 INP_WLOCK(inp);
1106                 tp = tcp_drop(tp, ECONNRESET);
1107                 if (tp)
1108                         INP_WUNLOCK(inp);
1109                 INP_INFO_WUNLOCK(&V_tcbinfo);
1110
1111                 return (0);
1112         }
1113
1114         /* receive buffer autosize */
1115         if (so_rcv->sb_flags & SB_AUTOSIZE &&
1116             V_tcp_do_autorcvbuf &&
1117             so_rcv->sb_hiwat < V_tcp_autorcvbuf_max &&
1118             m->m_pkthdr.len > (sbspace(so_rcv) / 8 * 7)) {
1119                 unsigned int hiwat = so_rcv->sb_hiwat;
1120                 unsigned int newsize = min(hiwat + V_tcp_autorcvbuf_inc,
1121                     V_tcp_autorcvbuf_max);
1122
1123                 if (!sbreserve_locked(so_rcv, newsize, so, NULL))
1124                         so_rcv->sb_flags &= ~SB_AUTOSIZE;
1125                 else
1126                         toep->rx_credits += newsize - hiwat;
1127         }
1128         toep->enqueued += m->m_pkthdr.len;
1129         sbappendstream_locked(so_rcv, m);
1130         sorwakeup_locked(so);
1131         SOCKBUF_UNLOCK_ASSERT(so_rcv);
1132
1133         INP_WUNLOCK(inp);
1134         return (0);
1135 }
1136
1137 #define S_CPL_FW4_ACK_OPCODE    24
1138 #define M_CPL_FW4_ACK_OPCODE    0xff
1139 #define V_CPL_FW4_ACK_OPCODE(x) ((x) << S_CPL_FW4_ACK_OPCODE)
1140 #define G_CPL_FW4_ACK_OPCODE(x) \
1141     (((x) >> S_CPL_FW4_ACK_OPCODE) & M_CPL_FW4_ACK_OPCODE)
1142  
1143 #define S_CPL_FW4_ACK_FLOWID    0
1144 #define M_CPL_FW4_ACK_FLOWID    0xffffff
1145 #define V_CPL_FW4_ACK_FLOWID(x) ((x) << S_CPL_FW4_ACK_FLOWID)
1146 #define G_CPL_FW4_ACK_FLOWID(x) \
1147     (((x) >> S_CPL_FW4_ACK_FLOWID) & M_CPL_FW4_ACK_FLOWID)
1148  
1149 #define S_CPL_FW4_ACK_CR        24
1150 #define M_CPL_FW4_ACK_CR        0xff
1151 #define V_CPL_FW4_ACK_CR(x)     ((x) << S_CPL_FW4_ACK_CR)
1152 #define G_CPL_FW4_ACK_CR(x)     (((x) >> S_CPL_FW4_ACK_CR) & M_CPL_FW4_ACK_CR)
1153  
1154 #define S_CPL_FW4_ACK_SEQVAL    0
1155 #define M_CPL_FW4_ACK_SEQVAL    0x1
1156 #define V_CPL_FW4_ACK_SEQVAL(x) ((x) << S_CPL_FW4_ACK_SEQVAL)
1157 #define G_CPL_FW4_ACK_SEQVAL(x) \
1158     (((x) >> S_CPL_FW4_ACK_SEQVAL) & M_CPL_FW4_ACK_SEQVAL)
1159 #define F_CPL_FW4_ACK_SEQVAL    V_CPL_FW4_ACK_SEQVAL(1U)
1160
1161 static int
1162 do_fw4_ack(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
1163 {
1164         struct adapter *sc = iq->adapter;
1165         const struct cpl_fw4_ack *cpl = (const void *)(rss + 1);
1166         unsigned int tid = G_CPL_FW4_ACK_FLOWID(be32toh(OPCODE_TID(cpl)));
1167         struct toepcb *toep = lookup_tid(sc, tid);
1168         struct inpcb *inp;
1169         struct tcpcb *tp;
1170         struct socket *so;
1171         uint8_t credits = cpl->credits;
1172         struct ofld_tx_sdesc *txsd;
1173         int plen;
1174 #ifdef INVARIANTS
1175         unsigned int opcode = G_CPL_FW4_ACK_OPCODE(be32toh(OPCODE_TID(cpl)));
1176 #endif
1177
1178         /*
1179          * Very unusual case: we'd sent a flowc + abort_req for a synq entry and
1180          * now this comes back carrying the credits for the flowc.
1181          */
1182         if (__predict_false(toepcb_flag(toep, TPF_SYNQE))) {
1183                 KASSERT(toepcb_flag(toep, TPF_ABORT_SHUTDOWN),
1184                     ("%s: credits for a synq entry %p", __func__, toep));
1185                 return (0);
1186         }
1187
1188         inp = toep->inp;
1189
1190         KASSERT(opcode == CPL_FW4_ACK,
1191             ("%s: unexpected opcode 0x%x", __func__, opcode));
1192         KASSERT(m == NULL, ("%s: wasn't expecting payload", __func__));
1193         KASSERT(toep->tid == tid, ("%s: toep tid mismatch", __func__));
1194
1195         INP_WLOCK(inp);
1196
1197         if (__predict_false(toepcb_flag(toep, TPF_ABORT_SHUTDOWN))) {
1198                 INP_WUNLOCK(inp);
1199                 return (0);
1200         }
1201
1202         KASSERT((inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) == 0,
1203             ("%s: inp_flags 0x%x", __func__, inp->inp_flags));
1204
1205         tp = intotcpcb(inp);
1206
1207         if (cpl->flags & CPL_FW4_ACK_FLAGS_SEQVAL) {
1208                 tcp_seq snd_una = be32toh(cpl->snd_una);
1209
1210 #ifdef INVARIANTS
1211                 if (__predict_false(SEQ_LT(snd_una, tp->snd_una))) {
1212                         log(LOG_ERR,
1213                             "%s: unexpected seq# %x for TID %u, snd_una %x\n",
1214                             __func__, snd_una, toep->tid, tp->snd_una);
1215                 }
1216 #endif
1217
1218                 if (tp->snd_una != snd_una) {
1219                         tp->snd_una = snd_una;
1220                         tp->ts_recent_age = tcp_ts_getticks();
1221                 }
1222         }
1223
1224         so = inp->inp_socket;
1225         txsd = &toep->txsd[toep->txsd_cidx];
1226         plen = 0;
1227         while (credits) {
1228                 KASSERT(credits >= txsd->tx_credits,
1229                     ("%s: too many (or partial) credits", __func__));
1230                 credits -= txsd->tx_credits;
1231                 toep->tx_credits += txsd->tx_credits;
1232                 plen += txsd->plen;
1233                 txsd++;
1234                 toep->txsd_avail++;
1235                 KASSERT(toep->txsd_avail <= toep->txsd_total,
1236                     ("%s: txsd avail > total", __func__));
1237                 if (__predict_false(++toep->txsd_cidx == toep->txsd_total)) {
1238                         txsd = &toep->txsd[0];
1239                         toep->txsd_cidx = 0;
1240                 }
1241         }
1242
1243         if (plen > 0) {
1244                 struct sockbuf *sb = &so->so_snd;
1245
1246                 SOCKBUF_LOCK(sb);
1247                 sbdrop_locked(sb, plen);
1248                 sowwakeup_locked(so);
1249                 SOCKBUF_UNLOCK_ASSERT(sb);
1250         }
1251
1252         /* XXX */
1253         if ((toepcb_flag(toep, TPF_TX_SUSPENDED) &&
1254             toep->tx_credits >= MIN_OFLD_TX_CREDITS) ||
1255             toep->tx_credits == toep->txsd_total *
1256             howmany((sizeof(struct fw_ofld_tx_data_wr) + 1), 16)) {
1257                 toepcb_clr_flag(toep, TPF_TX_SUSPENDED);
1258                 t4_push_frames(sc, toep);
1259         }
1260         INP_WUNLOCK(inp);
1261
1262         return (0);
1263 }
1264
1265 void
1266 t4_init_cpl_io_handlers(struct adapter *sc)
1267 {
1268
1269         t4_register_cpl_handler(sc, CPL_PEER_CLOSE, do_peer_close);
1270         t4_register_cpl_handler(sc, CPL_CLOSE_CON_RPL, do_close_con_rpl);
1271         t4_register_cpl_handler(sc, CPL_ABORT_REQ_RSS, do_abort_req);
1272         t4_register_cpl_handler(sc, CPL_ABORT_RPL_RSS, do_abort_rpl);
1273         t4_register_cpl_handler(sc, CPL_RX_DATA, do_rx_data);
1274         t4_register_cpl_handler(sc, CPL_FW4_ACK, do_fw4_ack);
1275 }
1276 #endif