cxgb_cpl_io.c (174712) | cxgb_cpl_io.c (176472) |
---|---|
1/************************************************************************** 2 3Copyright (c) 2007, Chelsio Inc. 4All rights reserved. 5 6Redistribution and use in source and binary forms, with or without 7modification, are permitted provided that the following conditions are met: 8 --- 14 unchanged lines hidden (view full) --- 23INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26POSSIBILITY OF SUCH DAMAGE. 27 28***************************************************************************/ 29 30#include <sys/cdefs.h> | 1/************************************************************************** 2 3Copyright (c) 2007, Chelsio Inc. 4All rights reserved. 5 6Redistribution and use in source and binary forms, with or without 7modification, are permitted provided that the following conditions are met: 8 --- 14 unchanged lines hidden (view full) --- 23INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26POSSIBILITY OF SUCH DAMAGE. 27 28***************************************************************************/ 29 30#include <sys/cdefs.h> |
31__FBSDID("$FreeBSD: head/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c 174712 2007-12-17 10:02:29Z kmacy $"); | 31__FBSDID("$FreeBSD: head/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c 176472 2008-02-23 01:06:17Z kmacy $"); |
32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/fcntl.h> 36#include <sys/kernel.h> 37#include <sys/limits.h> | 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/fcntl.h> 36#include <sys/kernel.h> 37#include <sys/limits.h> |
38#include <sys/ktr.h> |
|
38#include <sys/lock.h> 39#include <sys/mbuf.h> 40#include <sys/mutex.h> 41#include <sys/socket.h> 42#include <sys/sysctl.h> 43#include <sys/syslog.h> 44#include <sys/socketvar.h> 45#include <sys/protosw.h> --- 12 unchanged lines hidden (view full) --- 58#include <dev/cxgb/sys/mbufq.h> 59 60#include <netinet/ip.h> 61#include <netinet/tcp_var.h> 62#include <netinet/tcp_fsm.h> 63#include <netinet/tcp_offload.h> 64#include <netinet/tcp_seq.h> 65#include <netinet/tcp_syncache.h> | 39#include <sys/lock.h> 40#include <sys/mbuf.h> 41#include <sys/mutex.h> 42#include <sys/socket.h> 43#include <sys/sysctl.h> 44#include <sys/syslog.h> 45#include <sys/socketvar.h> 46#include <sys/protosw.h> --- 12 unchanged lines hidden (view full) --- 59#include <dev/cxgb/sys/mbufq.h> 60 61#include <netinet/ip.h> 62#include <netinet/tcp_var.h> 63#include <netinet/tcp_fsm.h> 64#include <netinet/tcp_offload.h> 65#include <netinet/tcp_seq.h> 66#include <netinet/tcp_syncache.h> |
67#include <netinet/tcp_timer.h> |
|
66#include <net/route.h> 67 | 68#include <net/route.h> 69 |
68 | |
69#include <dev/cxgb/t3cdev.h> 70#include <dev/cxgb/common/cxgb_firmware_exports.h> 71#include <dev/cxgb/common/cxgb_t3_cpl.h> 72#include <dev/cxgb/common/cxgb_tcb.h> 73#include <dev/cxgb/common/cxgb_ctl_defs.h> 74#include <dev/cxgb/cxgb_l2t.h> 75#include <dev/cxgb/cxgb_offload.h> 76#include <vm/vm.h> 77#include <vm/pmap.h> 78#include <machine/bus.h> 79#include <dev/cxgb/sys/mvec.h> 80#include <dev/cxgb/ulp/toecore/cxgb_toedev.h> 81#include <dev/cxgb/ulp/tom/cxgb_defs.h> 82#include <dev/cxgb/ulp/tom/cxgb_tom.h> 83#include <dev/cxgb/ulp/tom/cxgb_t3_ddp.h> 84#include <dev/cxgb/ulp/tom/cxgb_toepcb.h> 85#include <dev/cxgb/ulp/tom/cxgb_tcp.h> 86 | 70#include <dev/cxgb/t3cdev.h> 71#include <dev/cxgb/common/cxgb_firmware_exports.h> 72#include <dev/cxgb/common/cxgb_t3_cpl.h> 73#include <dev/cxgb/common/cxgb_tcb.h> 74#include <dev/cxgb/common/cxgb_ctl_defs.h> 75#include <dev/cxgb/cxgb_l2t.h> 76#include <dev/cxgb/cxgb_offload.h> 77#include <vm/vm.h> 78#include <vm/pmap.h> 79#include <machine/bus.h> 80#include <dev/cxgb/sys/mvec.h> 81#include <dev/cxgb/ulp/toecore/cxgb_toedev.h> 82#include <dev/cxgb/ulp/tom/cxgb_defs.h> 83#include <dev/cxgb/ulp/tom/cxgb_tom.h> 84#include <dev/cxgb/ulp/tom/cxgb_t3_ddp.h> 85#include <dev/cxgb/ulp/tom/cxgb_toepcb.h> 86#include <dev/cxgb/ulp/tom/cxgb_tcp.h> 87 |
87 88 | |
89/* 90 * For ULP connections HW may add headers, e.g., for digests, that aren't part 91 * of the messages sent by the host but that are part of the TCP payload and 92 * therefore consume TCP sequence space. Tx connection parameters that 93 * operate in TCP sequence space are affected by the HW additions and need to 94 * compensate for them to accurately track TCP sequence numbers. This array 95 * contains the compensating extra lengths for ULP packets. It is indexed by 96 * a packet's ULP submode. --- 16 unchanged lines hidden (view full) --- 113 */ 114static unsigned int wrlen __read_mostly; 115 116/* 117 * The number of WRs needed for an skb depends on the number of page fragments 118 * in the skb and whether it has any payload in its main body. This maps the 119 * length of the gather list represented by an skb into the # of necessary WRs. 120 */ | 88/* 89 * For ULP connections HW may add headers, e.g., for digests, that aren't part 90 * of the messages sent by the host but that are part of the TCP payload and 91 * therefore consume TCP sequence space. Tx connection parameters that 92 * operate in TCP sequence space are affected by the HW additions and need to 93 * compensate for them to accurately track TCP sequence numbers. This array 94 * contains the compensating extra lengths for ULP packets. It is indexed by 95 * a packet's ULP submode. --- 16 unchanged lines hidden (view full) --- 112 */ 113static unsigned int wrlen __read_mostly; 114 115/* 116 * The number of WRs needed for an skb depends on the number of page fragments 117 * in the skb and whether it has any payload in its main body. This maps the 118 * length of the gather list represented by an skb into the # of necessary WRs. 119 */ |
121static unsigned int mbuf_wrs[TX_MAX_SEGS] __read_mostly; | 120static unsigned int mbuf_wrs[TX_MAX_SEGS + 1] __read_mostly; |
122 123/* 124 * Max receive window supported by HW in bytes. Only a small part of it can 125 * be set through option0, the rest needs to be set through RX_DATA_ACK. 126 */ 127#define MAX_RCV_WND ((1U << 27) - 1) 128 129/* --- 12 unchanged lines hidden (view full) --- 142extern int tcp_autorcvbuf_max; 143extern int tcp_autosndbuf_max; 144 145static void t3_send_reset(struct toepcb *toep); 146static void send_abort_rpl(struct mbuf *m, struct toedev *tdev, int rst_status); 147static inline void free_atid(struct t3cdev *cdev, unsigned int tid); 148static void handle_syncache_event(int event, void *arg); 149 | 121 122/* 123 * Max receive window supported by HW in bytes. Only a small part of it can 124 * be set through option0, the rest needs to be set through RX_DATA_ACK. 125 */ 126#define MAX_RCV_WND ((1U << 27) - 1) 127 128/* --- 12 unchanged lines hidden (view full) --- 141extern int tcp_autorcvbuf_max; 142extern int tcp_autosndbuf_max; 143 144static void t3_send_reset(struct toepcb *toep); 145static void send_abort_rpl(struct mbuf *m, struct toedev *tdev, int rst_status); 146static inline void free_atid(struct t3cdev *cdev, unsigned int tid); 147static void handle_syncache_event(int event, void *arg); 148 |
149static inline void 150SBAPPEND(struct sockbuf *sb, struct mbuf *n) 151{ 152 struct mbuf * m; |
|
150 | 153 |
154 m = sb->sb_mb; 155 while (m) { 156 KASSERT(((m->m_flags & M_EXT) && (m->m_ext.ext_type == EXT_EXTREF)) || 157 !(m->m_flags & M_EXT), ("unexpected type M_EXT=%d ext_type=%d m_len=%d\n", 158 !!(m->m_flags & M_EXT), m->m_ext.ext_type, m->m_len)); 159 KASSERT(m->m_next != (struct mbuf *)0xffffffff, ("bad next value m_next=%p m_nextpkt=%p m_flags=0x%x", 160 m->m_next, m->m_nextpkt, m->m_flags)); 161 m = m->m_next; 162 } 163 m = n; 164 while (m) { 165 KASSERT(((m->m_flags & M_EXT) && (m->m_ext.ext_type == EXT_EXTREF)) || 166 !(m->m_flags & M_EXT), ("unexpected type M_EXT=%d ext_type=%d m_len=%d\n", 167 !!(m->m_flags & M_EXT), m->m_ext.ext_type, m->m_len)); 168 KASSERT(m->m_next != (struct mbuf *)0xffffffff, ("bad next value m_next=%p m_nextpkt=%p m_flags=0x%x", 169 m->m_next, m->m_nextpkt, m->m_flags)); 170 m = m->m_next; 171 } 172 sbappend_locked(sb, n); 173 m = sb->sb_mb; 174 while (m) { 175 KASSERT(m->m_next != (struct mbuf *)0xffffffff, ("bad next value m_next=%p m_nextpkt=%p m_flags=0x%x", 176 m->m_next, m->m_nextpkt, m->m_flags)); 177 m = m->m_next; 178 } 179} 180 |
|
151static inline int 152is_t3a(const struct toedev *dev) 153{ 154 return (dev->tod_ttid == TOE_ID_CHELSIO_T3); 155} 156 157static void 158dump_toepcb(struct toepcb *toep) 159{ 160 DPRINTF("qset_idx=%d qset=%d ulp_mode=%d mtu_idx=%d tid=%d\n", 161 toep->tp_qset_idx, toep->tp_qset, toep->tp_ulp_mode, 162 toep->tp_mtu_idx, toep->tp_tid); 163 164 DPRINTF("wr_max=%d wr_avail=%d wr_unacked=%d mss_clamp=%d flags=0x%x\n", 165 toep->tp_wr_max, toep->tp_wr_avail, toep->tp_wr_unacked, 166 toep->tp_mss_clamp, toep->tp_flags); 167} 168 | 181static inline int 182is_t3a(const struct toedev *dev) 183{ 184 return (dev->tod_ttid == TOE_ID_CHELSIO_T3); 185} 186 187static void 188dump_toepcb(struct toepcb *toep) 189{ 190 DPRINTF("qset_idx=%d qset=%d ulp_mode=%d mtu_idx=%d tid=%d\n", 191 toep->tp_qset_idx, toep->tp_qset, toep->tp_ulp_mode, 192 toep->tp_mtu_idx, toep->tp_tid); 193 194 DPRINTF("wr_max=%d wr_avail=%d wr_unacked=%d mss_clamp=%d flags=0x%x\n", 195 toep->tp_wr_max, toep->tp_wr_avail, toep->tp_wr_unacked, 196 toep->tp_mss_clamp, toep->tp_flags); 197} 198 |
199#ifndef RTALLOC2_DEFINED |
|
169static struct rtentry * 170rtalloc2(struct sockaddr *dst, int report, u_long ignflags) 171{ 172 struct rtentry *rt = NULL; 173 174 if ((rt = rtalloc1(dst, report, ignflags)) != NULL) 175 RT_UNLOCK(rt); 176 177 return (rt); 178} | 200static struct rtentry * 201rtalloc2(struct sockaddr *dst, int report, u_long ignflags) 202{ 203 struct rtentry *rt = NULL; 204 205 if ((rt = rtalloc1(dst, report, ignflags)) != NULL) 206 RT_UNLOCK(rt); 207 208 return (rt); 209} |
179 | 210#endif |
180/* 181 * Determine whether to send a CPL message now or defer it. A message is 182 * deferred if the connection is in SYN_SENT since we don't know the TID yet. 183 * For connections in other states the message is sent immediately. 184 * If through_l2t is set the message is subject to ARP processing, otherwise 185 * it is sent directly. 186 */ 187static inline void | 211/* 212 * Determine whether to send a CPL message now or defer it. A message is 213 * deferred if the connection is in SYN_SENT since we don't know the TID yet. 214 * For connections in other states the message is sent immediately. 215 * If through_l2t is set the message is subject to ARP processing, otherwise 216 * it is sent directly. 217 */ 218static inline void |
188send_or_defer(struct socket *so, struct tcpcb *tp, struct mbuf *m, int through_l2t) | 219send_or_defer(struct toepcb *toep, struct mbuf *m, int through_l2t) |
189{ | 220{ |
190 struct toepcb *toep = tp->t_toe; | 221 struct tcpcb *tp = toep->tp_tp; |
191 | 222 |
192 | |
193 if (__predict_false(tp->t_state == TCPS_SYN_SENT)) { 194 INP_LOCK(tp->t_inpcb); 195 mbufq_tail(&toep->out_of_order_queue, m); // defer 196 INP_UNLOCK(tp->t_inpcb); 197 } else if (through_l2t) | 223 if (__predict_false(tp->t_state == TCPS_SYN_SENT)) { 224 INP_LOCK(tp->t_inpcb); 225 mbufq_tail(&toep->out_of_order_queue, m); // defer 226 INP_UNLOCK(tp->t_inpcb); 227 } else if (through_l2t) |
198 l2t_send(T3C_DEV(so), m, toep->tp_l2t); // send through L2T | 228 l2t_send(TOEP_T3C_DEV(toep), m, toep->tp_l2t); // send through L2T |
199 else | 229 else |
200 cxgb_ofld_send(T3C_DEV(so), m); // send directly | 230 cxgb_ofld_send(TOEP_T3C_DEV(toep), m); // send directly |
201} 202 203static inline unsigned int | 231} 232 233static inline unsigned int |
204mkprio(unsigned int cntrl, const struct socket *so) | 234mkprio(unsigned int cntrl, const struct toepcb *toep) |
205{ | 235{ |
206 return cntrl; | 236 return (cntrl); |
207} 208 209/* 210 * Populate a TID_RELEASE WR. The skb must be already propely sized. 211 */ 212static inline void | 237} 238 239/* 240 * Populate a TID_RELEASE WR. The skb must be already propely sized. 241 */ 242static inline void |
213mk_tid_release(struct mbuf *m, const struct socket *so, unsigned int tid) | 243mk_tid_release(struct mbuf *m, const struct toepcb *toep, unsigned int tid) |
214{ 215 struct cpl_tid_release *req; 216 | 244{ 245 struct cpl_tid_release *req; 246 |
217 m_set_priority(m, mkprio(CPL_PRIORITY_SETUP, so)); | 247 m_set_priority(m, mkprio(CPL_PRIORITY_SETUP, toep)); |
218 m->m_pkthdr.len = m->m_len = sizeof(*req); 219 req = mtod(m, struct cpl_tid_release *); 220 req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); | 248 m->m_pkthdr.len = m->m_len = sizeof(*req); 249 req = mtod(m, struct cpl_tid_release *); 250 req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); |
251 req->wr.wr_lo = 0; |
|
221 OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_TID_RELEASE, tid)); 222} 223 224static inline void 225make_tx_data_wr(struct socket *so, struct mbuf *m, int len, struct mbuf *tail) 226{ 227 struct tcpcb *tp = sototcpcb(so); 228 struct toepcb *toep = tp->t_toe; --- 23 unchanged lines hidden (view full) --- 252 if (tcp_do_autosndbuf && so->so_snd.sb_flags & SB_AUTOSIZE) 253 req->param |= htonl(V_TX_SNDBUF(tcp_autosndbuf_max >> 15)); 254 else 255 req->param |= htonl(V_TX_SNDBUF(so->so_snd.sb_hiwat >> 15)); 256 toep->tp_flags |= TP_DATASENT; 257 } 258} 259 | 252 OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_TID_RELEASE, tid)); 253} 254 255static inline void 256make_tx_data_wr(struct socket *so, struct mbuf *m, int len, struct mbuf *tail) 257{ 258 struct tcpcb *tp = sototcpcb(so); 259 struct toepcb *toep = tp->t_toe; --- 23 unchanged lines hidden (view full) --- 283 if (tcp_do_autosndbuf && so->so_snd.sb_flags & SB_AUTOSIZE) 284 req->param |= htonl(V_TX_SNDBUF(tcp_autosndbuf_max >> 15)); 285 else 286 req->param |= htonl(V_TX_SNDBUF(so->so_snd.sb_hiwat >> 15)); 287 toep->tp_flags |= TP_DATASENT; 288 } 289} 290 |
291#define IMM_LEN 64 /* XXX - see WR_LEN in the cxgb driver */ 292 |
|
260int 261t3_push_frames(struct socket *so, int req_completion) 262{ 263 struct tcpcb *tp = sototcpcb(so); 264 struct toepcb *toep = tp->t_toe; 265 266 struct mbuf *tail, *m0, *last; 267 struct t3cdev *cdev; 268 struct tom_data *d; | 293int 294t3_push_frames(struct socket *so, int req_completion) 295{ 296 struct tcpcb *tp = sototcpcb(so); 297 struct toepcb *toep = tp->t_toe; 298 299 struct mbuf *tail, *m0, *last; 300 struct t3cdev *cdev; 301 struct tom_data *d; |
269 int bytes, count, total_bytes; | 302 int i, bytes, count, total_bytes; |
270 bus_dma_segment_t segs[TX_MAX_SEGS], *segp; | 303 bus_dma_segment_t segs[TX_MAX_SEGS], *segp; |
271 segp = segs; | |
272 273 if (tp->t_state == TCPS_SYN_SENT || tp->t_state == TCPS_CLOSED) { 274 DPRINTF("tcp state=%d\n", tp->t_state); 275 return (0); 276 } 277 278 if (so->so_state & (SS_ISDISCONNECTING|SS_ISDISCONNECTED)) { 279 DPRINTF("disconnecting\n"); 280 281 return (0); 282 } 283 | 304 305 if (tp->t_state == TCPS_SYN_SENT || tp->t_state == TCPS_CLOSED) { 306 DPRINTF("tcp state=%d\n", tp->t_state); 307 return (0); 308 } 309 310 if (so->so_state & (SS_ISDISCONNECTING|SS_ISDISCONNECTED)) { 311 DPRINTF("disconnecting\n"); 312 313 return (0); 314 } 315 |
284 INP_LOCK_ASSERT(tp->t_inpcb); | |
285 | 316 |
317 INP_LOCK_ASSERT(tp->t_inpcb); |
|
286 SOCKBUF_LOCK(&so->so_snd); | 318 SOCKBUF_LOCK(&so->so_snd); |
287 | |
288 d = TOM_DATA(TOE_DEV(so)); 289 cdev = d->cdev; 290 last = tail = so->so_snd.sb_sndptr ? so->so_snd.sb_sndptr : so->so_snd.sb_mb; 291 total_bytes = 0; 292 DPRINTF("wr_avail=%d tail=%p snd.cc=%d tp_last=%p\n", 293 toep->tp_wr_avail, tail, so->so_snd.sb_cc, toep->tp_m_last); 294 295 if (last && toep->tp_m_last == last && so->so_snd.sb_sndptroff != 0) { --- 5 unchanged lines hidden (view full) --- 301 DPRINTF("wr_avail=%d tail=%p\n", toep->tp_wr_avail, tail); 302 SOCKBUF_UNLOCK(&so->so_snd); 303 return (0); 304 } 305 306 toep->tp_m_last = NULL; 307 while (toep->tp_wr_avail && (tail != NULL)) { 308 count = bytes = 0; | 319 d = TOM_DATA(TOE_DEV(so)); 320 cdev = d->cdev; 321 last = tail = so->so_snd.sb_sndptr ? so->so_snd.sb_sndptr : so->so_snd.sb_mb; 322 total_bytes = 0; 323 DPRINTF("wr_avail=%d tail=%p snd.cc=%d tp_last=%p\n", 324 toep->tp_wr_avail, tail, so->so_snd.sb_cc, toep->tp_m_last); 325 326 if (last && toep->tp_m_last == last && so->so_snd.sb_sndptroff != 0) { --- 5 unchanged lines hidden (view full) --- 332 DPRINTF("wr_avail=%d tail=%p\n", toep->tp_wr_avail, tail); 333 SOCKBUF_UNLOCK(&so->so_snd); 334 return (0); 335 } 336 337 toep->tp_m_last = NULL; 338 while (toep->tp_wr_avail && (tail != NULL)) { 339 count = bytes = 0; |
340 segp = segs; |
|
309 if ((m0 = m_gethdr(M_NOWAIT, MT_DATA)) == NULL) { 310 SOCKBUF_UNLOCK(&so->so_snd); 311 return (0); 312 } | 341 if ((m0 = m_gethdr(M_NOWAIT, MT_DATA)) == NULL) { 342 SOCKBUF_UNLOCK(&so->so_snd); 343 return (0); 344 } |
313 while ((mbuf_wrs[count + 1] <= toep->tp_wr_avail) 314 && (tail != NULL) && (count < TX_MAX_SEGS)) { 315 bytes += tail->m_len; 316 count++; | 345 /* 346 * If the data in tail fits as in-line, then 347 * make an immediate data wr. 348 */ 349 if (tail->m_len <= IMM_LEN) { 350 count = 1; 351 bytes = tail->m_len; |
317 last = tail; | 352 last = tail; |
318 /* 319 * technically an abuse to be using this for a VA 320 * but less gross than defining my own structure 321 * or calling pmap_kextract from here :-| 322 */ 323 segp->ds_addr = (bus_addr_t)tail->m_data; 324 segp->ds_len = tail->m_len; 325 DPRINTF("count=%d wr_needed=%d ds_addr=%p ds_len=%d\n", 326 count, mbuf_wrs[count], tail->m_data, tail->m_len); 327 328 segp++; | |
329 tail = tail->m_next; | 353 tail = tail->m_next; |
354 m_set_sgl(m0, NULL); 355 m_set_sgllen(m0, 0); 356 make_tx_data_wr(so, m0, bytes, tail); 357 m_append(m0, bytes, mtod(last, caddr_t)); 358 KASSERT(!m0->m_next, ("bad append")); 359 } else { 360 while ((mbuf_wrs[count + 1] <= toep->tp_wr_avail) 361 && (tail != NULL) && (count < TX_MAX_SEGS-1)) { 362 bytes += tail->m_len; 363 last = tail; 364 count++; 365 /* 366 * technically an abuse to be using this for a VA 367 * but less gross than defining my own structure 368 * or calling pmap_kextract from here :-| 369 */ 370 segp->ds_addr = (bus_addr_t)tail->m_data; 371 segp->ds_len = tail->m_len; 372 DPRINTF("count=%d wr_needed=%d ds_addr=%p ds_len=%d\n", 373 count, mbuf_wrs[count], tail->m_data, tail->m_len); 374 segp++; 375 tail = tail->m_next; 376 } 377 DPRINTF("wr_avail=%d mbuf_wrs[%d]=%d tail=%p\n", 378 toep->tp_wr_avail, count, mbuf_wrs[count], tail); 379 380 m_set_sgl(m0, segs); 381 m_set_sgllen(m0, count); 382 make_tx_data_wr(so, m0, bytes, tail); |
|
330 } | 383 } |
331 DPRINTF("wr_avail=%d mbuf_wrs[%d]=%d tail=%p\n", 332 toep->tp_wr_avail, count, mbuf_wrs[count], tail); | 384 m_set_priority(m0, mkprio(CPL_PRIORITY_DATA, toep)); 385 |
333 if (tail) { 334 so->so_snd.sb_sndptr = tail; 335 toep->tp_m_last = NULL; 336 } else 337 toep->tp_m_last = so->so_snd.sb_sndptr = last; 338 | 386 if (tail) { 387 so->so_snd.sb_sndptr = tail; 388 toep->tp_m_last = NULL; 389 } else 390 toep->tp_m_last = so->so_snd.sb_sndptr = last; 391 |
392 |
|
339 DPRINTF("toep->tp_m_last=%p\n", toep->tp_m_last); 340 341 so->so_snd.sb_sndptroff += bytes; 342 total_bytes += bytes; 343 toep->tp_write_seq += bytes; | 393 DPRINTF("toep->tp_m_last=%p\n", toep->tp_m_last); 394 395 so->so_snd.sb_sndptroff += bytes; 396 total_bytes += bytes; 397 toep->tp_write_seq += bytes; |
398 CTR6(KTR_TOM, "t3_push_frames: wr_avail=%d mbuf_wrs[%d]=%d tail=%p sndptr=%p sndptroff=%d", 399 toep->tp_wr_avail, count, mbuf_wrs[count], tail, so->so_snd.sb_sndptr, so->so_snd.sb_sndptroff); 400 if (tail) 401 CTR4(KTR_TOM, "t3_push_frames: total_bytes=%d tp_m_last=%p tailbuf=%p snd_una=0x%08x", 402 total_bytes, toep->tp_m_last, tail->m_data, tp->snd_una); 403 else 404 CTR3(KTR_TOM, "t3_push_frames: total_bytes=%d tp_m_last=%p snd_una=0x%08x", 405 total_bytes, toep->tp_m_last, tp->snd_una); |
|
344 345 | 406 407 |
346 SOCKBUF_UNLOCK(&so->so_snd); 347 348 /* 349 * XXX can drop socket buffer lock here 350 */ | 408 i = 0; 409 while (i < count && m_get_sgllen(m0)) { 410 if ((count - i) >= 3) { 411 CTR6(KTR_TOM, 412 "t3_push_frames: pa=0x%zx len=%d pa=0x%zx len=%d pa=0x%zx len=%d", 413 segs[i].ds_addr, segs[i].ds_len, segs[i + 1].ds_addr, segs[i + 1].ds_len, 414 segs[i + 2].ds_addr, segs[i + 2].ds_len); 415 i += 3; 416 } else if ((count - i) == 2) { 417 CTR4(KTR_TOM, 418 "t3_push_frames: pa=0x%zx len=%d pa=0x%zx len=%d", 419 segs[i].ds_addr, segs[i].ds_len, segs[i + 1].ds_addr, segs[i + 1].ds_len); 420 i += 2; 421 } else { 422 CTR2(KTR_TOM, "t3_push_frames: pa=0x%zx len=%d", 423 segs[i].ds_addr, segs[i].ds_len); 424 i++; 425 } |
351 | 426 |
352 toep->tp_wr_avail -= mbuf_wrs[count]; 353 toep->tp_wr_unacked += mbuf_wrs[count]; | 427 } |
354 | 428 |
355 make_tx_data_wr(so, m0, bytes, tail); 356 m_set_priority(m0, mkprio(CPL_PRIORITY_DATA, so)); 357 m_set_sgl(m0, segs); 358 m_set_sgllen(m0, count); 359 /* | 429 /* |
360 * remember credits used 361 */ 362 m0->m_pkthdr.csum_data = mbuf_wrs[count]; 363 m0->m_pkthdr.len = bytes; | 430 * remember credits used 431 */ 432 m0->m_pkthdr.csum_data = mbuf_wrs[count]; 433 m0->m_pkthdr.len = bytes; |
434 toep->tp_wr_avail -= mbuf_wrs[count]; 435 toep->tp_wr_unacked += mbuf_wrs[count]; 436 |
|
364 if ((req_completion && toep->tp_wr_unacked == mbuf_wrs[count]) || 365 toep->tp_wr_unacked >= toep->tp_wr_max / 2) { 366 struct work_request_hdr *wr = cplhdr(m0); 367 368 wr->wr_hi |= htonl(F_WR_COMPL); 369 toep->tp_wr_unacked = 0; 370 } | 437 if ((req_completion && toep->tp_wr_unacked == mbuf_wrs[count]) || 438 toep->tp_wr_unacked >= toep->tp_wr_max / 2) { 439 struct work_request_hdr *wr = cplhdr(m0); 440 441 wr->wr_hi |= htonl(F_WR_COMPL); 442 toep->tp_wr_unacked = 0; 443 } |
371 | 444 KASSERT((m0->m_pkthdr.csum_data > 0) && 445 (m0->m_pkthdr.csum_data <= 4), ("bad credit count %d", 446 m0->m_pkthdr.csum_data)); |
372 m0->m_type = MT_DONTFREE; 373 enqueue_wr(toep, m0); 374 DPRINTF("sending offload tx with %d bytes in %d segments\n", 375 bytes, count); | 447 m0->m_type = MT_DONTFREE; 448 enqueue_wr(toep, m0); 449 DPRINTF("sending offload tx with %d bytes in %d segments\n", 450 bytes, count); |
376 | |
377 l2t_send(cdev, m0, toep->tp_l2t); | 451 l2t_send(cdev, m0, toep->tp_l2t); |
378 if (toep->tp_wr_avail && (tail != NULL)) 379 SOCKBUF_LOCK(&so->so_snd); | |
380 } | 452 } |
381 382 SOCKBUF_UNLOCK_ASSERT(&so->so_snd); | 453 SOCKBUF_UNLOCK(&so->so_snd); |
383 return (total_bytes); 384} 385 386/* 387 * Close a connection by sending a CPL_CLOSE_CON_REQ message. Cannot fail 388 * under any circumstances. We take the easy way out and always queue the 389 * message to the write_queue. We can optimize the case where the queue is 390 * already empty though the optimization is probably not worth it. --- 71 unchanged lines hidden (view full) --- 462 struct toedev *tdev = toep->tp_toedev; 463 464 m = m_gethdr_nofail(sizeof(*req)); 465 466 DPRINTF("returning %u credits to HW\n", credits); 467 468 req = mtod(m, struct cpl_rx_data_ack *); 469 req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); | 454 return (total_bytes); 455} 456 457/* 458 * Close a connection by sending a CPL_CLOSE_CON_REQ message. Cannot fail 459 * under any circumstances. We take the easy way out and always queue the 460 * message to the write_queue. We can optimize the case where the queue is 461 * already empty though the optimization is probably not worth it. --- 71 unchanged lines hidden (view full) --- 533 struct toedev *tdev = toep->tp_toedev; 534 535 m = m_gethdr_nofail(sizeof(*req)); 536 537 DPRINTF("returning %u credits to HW\n", credits); 538 539 req = mtod(m, struct cpl_rx_data_ack *); 540 req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); |
541 req->wr.wr_lo = 0; |
|
470 OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_RX_DATA_ACK, toep->tp_tid)); 471 req->credit_dack = htonl(dack | V_RX_CREDITS(credits)); | 542 OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_RX_DATA_ACK, toep->tp_tid)); 543 req->credit_dack = htonl(dack | V_RX_CREDITS(credits)); |
472 m_set_priority(m, mkprio(CPL_PRIORITY_ACK, toeptoso(toep))); | 544 m_set_priority(m, mkprio(CPL_PRIORITY_ACK, toep)); |
473 cxgb_ofld_send(TOM_DATA(tdev)->cdev, m); 474 return (credits); 475} 476 | 545 cxgb_ofld_send(TOM_DATA(tdev)->cdev, m); 546 return (credits); 547} 548 |
549/* 550 * Send RX_DATA_ACK CPL message to request a modulation timer to be scheduled. 551 * This is only used in DDP mode, so we take the opportunity to also set the 552 * DACK mode and flush any Rx credits. 553 */ 554void 555t3_send_rx_modulate(struct toepcb *toep) 556{ 557 struct mbuf *m; 558 struct cpl_rx_data_ack *req; |
|
477 | 559 |
560 m = m_gethdr_nofail(sizeof(*req)); 561 562 req = mtod(m, struct cpl_rx_data_ack *); 563 req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); 564 req->wr.wr_lo = 0; 565 m->m_pkthdr.len = m->m_len = sizeof(*req); 566 567 OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_RX_DATA_ACK, toep->tp_tid)); 568 req->credit_dack = htonl(F_RX_MODULATE | F_RX_DACK_CHANGE | 569 V_RX_DACK_MODE(1) | 570 V_RX_CREDITS(toep->tp_copied_seq - toep->tp_rcv_wup)); 571 m_set_priority(m, mkprio(CPL_PRIORITY_CONTROL, toep)); 572 cxgb_ofld_send(TOEP_T3C_DEV(toep), m); 573 toep->tp_rcv_wup = toep->tp_copied_seq; 574} 575 |
|
478/* | 576/* |
577 * Handle receipt of an urgent pointer. 578 */ 579static void 580handle_urg_ptr(struct socket *so, uint32_t urg_seq) 581{ 582#ifdef URGENT_DATA_SUPPORTED 583 struct tcpcb *tp = sototcpcb(so); 584 585 urg_seq--; /* initially points past the urgent data, per BSD */ 586 587 if (tp->urg_data && !after(urg_seq, tp->urg_seq)) 588 return; /* duplicate pointer */ 589 sk_send_sigurg(sk); 590 if (tp->urg_seq == tp->copied_seq && tp->urg_data && 591 !sock_flag(sk, SOCK_URGINLINE) && tp->copied_seq != tp->rcv_nxt) { 592 struct sk_buff *skb = skb_peek(&sk->sk_receive_queue); 593 594 tp->copied_seq++; 595 if (skb && tp->copied_seq - TCP_SKB_CB(skb)->seq >= skb->len) 596 tom_eat_skb(sk, skb, 0); 597 } 598 tp->urg_data = TCP_URG_NOTYET; 599 tp->urg_seq = urg_seq; 600#endif 601} 602 603/* 604 * Returns true if a socket cannot accept new Rx data. 605 */ 606static inline int 607so_no_receive(const struct socket *so) 608{ 609 return (so->so_state & (SS_ISDISCONNECTED|SS_ISDISCONNECTING)); 610} 611 612/* 613 * Process an urgent data notification. 614 */ 615static void 616rx_urg_notify(struct toepcb *toep, struct mbuf *m) 617{ 618 struct cpl_rx_urg_notify *hdr = cplhdr(m); 619 struct socket *so = toeptoso(toep); 620 621 VALIDATE_SOCK(so); 622 623 if (!so_no_receive(so)) 624 handle_urg_ptr(so, ntohl(hdr->seq)); 625 626 m_freem(m); 627} 628 629/* 630 * Handler for RX_URG_NOTIFY CPL messages. 631 */ 632static int 633do_rx_urg_notify(struct t3cdev *cdev, struct mbuf *m, void *ctx) 634{ 635 struct toepcb *toep = (struct toepcb *)ctx; 636 637 rx_urg_notify(toep, m); 638 return (0); 639} 640 641/* |
|
479 * Set of states for which we should return RX credits. 480 */ 481#define CREDIT_RETURN_STATE (TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | TCPF_FIN_WAIT2) 482 483/* 484 * Called after some received data has been read. It returns RX credits 485 * to the HW for the amount of data processed. 486 */ 487void | 642 * Set of states for which we should return RX credits. 643 */ 644#define CREDIT_RETURN_STATE (TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | TCPF_FIN_WAIT2) 645 646/* 647 * Called after some received data has been read. It returns RX credits 648 * to the HW for the amount of data processed. 649 */ 650void |
488t3_cleanup_rbuf(struct tcpcb *tp) | 651t3_cleanup_rbuf(struct tcpcb *tp, int copied) |
489{ 490 struct toepcb *toep = tp->t_toe; 491 struct socket *so; 492 struct toedev *dev; 493 int dack_mode, must_send, read; 494 u32 thres, credits, dack = 0; 495 | 652{ 653 struct toepcb *toep = tp->t_toe; 654 struct socket *so; 655 struct toedev *dev; 656 int dack_mode, must_send, read; 657 u32 thres, credits, dack = 0; 658 |
659 so = tp->t_inpcb->inp_socket; |
|
496 if (!((tp->t_state == TCPS_ESTABLISHED) || (tp->t_state == TCPS_FIN_WAIT_1) || | 660 if (!((tp->t_state == TCPS_ESTABLISHED) || (tp->t_state == TCPS_FIN_WAIT_1) || |
497 (tp->t_state == TCPS_FIN_WAIT_2))) | 661 (tp->t_state == TCPS_FIN_WAIT_2))) { 662 if (copied) { 663 SOCKBUF_LOCK(&so->so_rcv); 664 toep->tp_copied_seq += copied; 665 SOCKBUF_UNLOCK(&so->so_rcv); 666 } 667 |
498 return; | 668 return; |
499 INP_LOCK_ASSERT(tp->t_inpcb); | 669 } |
500 | 670 |
501 so = tp->t_inpcb->inp_socket; | 671 INP_LOCK_ASSERT(tp->t_inpcb); |
502 SOCKBUF_LOCK(&so->so_rcv); | 672 SOCKBUF_LOCK(&so->so_rcv); |
503 read = toep->tp_enqueued_bytes - so->so_rcv.sb_cc; 504 toep->tp_copied_seq += read; 505 toep->tp_enqueued_bytes -= read; | 673 if (copied) 674 toep->tp_copied_seq += copied; 675 else { 676 read = toep->tp_enqueued_bytes - so->so_rcv.sb_cc; 677 toep->tp_copied_seq += read; 678 } |
506 credits = toep->tp_copied_seq - toep->tp_rcv_wup; | 679 credits = toep->tp_copied_seq - toep->tp_rcv_wup; |
680 toep->tp_enqueued_bytes = so->so_rcv.sb_cc; |
|
507 SOCKBUF_UNLOCK(&so->so_rcv); 508 | 681 SOCKBUF_UNLOCK(&so->so_rcv); 682 |
509 if (credits > so->so_rcv.sb_mbmax) | 683 if (credits > so->so_rcv.sb_mbmax) { |
510 printf("copied_seq=%u rcv_wup=%u credits=%u\n", 511 toep->tp_copied_seq, toep->tp_rcv_wup, credits); | 684 printf("copied_seq=%u rcv_wup=%u credits=%u\n", 685 toep->tp_copied_seq, toep->tp_rcv_wup, credits); |
512 /* | 686 credits = so->so_rcv.sb_mbmax; 687 } 688 689 690 /* |
513 * XXX this won't accurately reflect credit return - we need 514 * to look at the difference between the amount that has been 515 * put in the recv sockbuf and what is there now 516 */ 517 518 if (__predict_false(!credits)) 519 return; 520 --- 67 unchanged lines hidden (view full) --- 588 t3_push_frames(so, 1); 589 return (0); 590} 591 592static int 593cxgb_toe_rcvd(struct tcpcb *tp) 594{ 595 INP_LOCK_ASSERT(tp->t_inpcb); | 691 * XXX this won't accurately reflect credit return - we need 692 * to look at the difference between the amount that has been 693 * put in the recv sockbuf and what is there now 694 */ 695 696 if (__predict_false(!credits)) 697 return; 698 --- 67 unchanged lines hidden (view full) --- 766 t3_push_frames(so, 1); 767 return (0); 768} 769 770static int 771cxgb_toe_rcvd(struct tcpcb *tp) 772{ 773 INP_LOCK_ASSERT(tp->t_inpcb); |
596 t3_cleanup_rbuf(tp); | 774 t3_cleanup_rbuf(tp, 0); |
597 598 return (0); 599} 600 601static void 602cxgb_toe_detach(struct tcpcb *tp) 603{ 604 struct toepcb *toep; --- 21 unchanged lines hidden (view full) --- 626 .tu_rcvd = cxgb_toe_rcvd, 627 .tu_detach = cxgb_toe_detach, 628 .tu_detach = cxgb_toe_detach, 629 .tu_syncache_event = handle_syncache_event, 630}; 631 632 633static void | 775 776 return (0); 777} 778 779static void 780cxgb_toe_detach(struct tcpcb *tp) 781{ 782 struct toepcb *toep; --- 21 unchanged lines hidden (view full) --- 804 .tu_rcvd = cxgb_toe_rcvd, 805 .tu_detach = cxgb_toe_detach, 806 .tu_detach = cxgb_toe_detach, 807 .tu_syncache_event = handle_syncache_event, 808}; 809 810 811static void |
634__set_tcb_field(struct socket *so, struct mbuf *m, uint16_t word, | 812__set_tcb_field(struct toepcb *toep, struct mbuf *m, uint16_t word, |
635 uint64_t mask, uint64_t val, int no_reply) 636{ 637 struct cpl_set_tcb_field *req; | 813 uint64_t mask, uint64_t val, int no_reply) 814{ 815 struct cpl_set_tcb_field *req; |
638 struct tcpcb *tp = sototcpcb(so); 639 struct toepcb *toep = tp->t_toe; | |
640 | 816 |
817 CTR4(KTR_TCB, "__set_tcb_field_ulp(tid=%u word=0x%x mask=%jx val=%jx", 818 toep->tp_tid, word, mask, val); 819 |
|
641 req = mtod(m, struct cpl_set_tcb_field *); 642 m->m_pkthdr.len = m->m_len = sizeof(*req); 643 req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); | 820 req = mtod(m, struct cpl_set_tcb_field *); 821 m->m_pkthdr.len = m->m_len = sizeof(*req); 822 req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); |
823 req->wr.wr_lo = 0; |
|
644 OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, toep->tp_tid)); 645 req->reply = V_NO_REPLY(no_reply); 646 req->cpu_idx = 0; 647 req->word = htons(word); 648 req->mask = htobe64(mask); 649 req->val = htobe64(val); 650 | 824 OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, toep->tp_tid)); 825 req->reply = V_NO_REPLY(no_reply); 826 req->cpu_idx = 0; 827 req->word = htons(word); 828 req->mask = htobe64(mask); 829 req->val = htobe64(val); 830 |
651 m_set_priority(m, mkprio(CPL_PRIORITY_CONTROL, so)); 652 send_or_defer(so, tp, m, 0); | 831 m_set_priority(m, mkprio(CPL_PRIORITY_CONTROL, toep)); 832 send_or_defer(toep, m, 0); |
653} 654 655static void 656t3_set_tcb_field(struct socket *so, uint16_t word, uint64_t mask, uint64_t val) 657{ 658 struct mbuf *m; 659 struct tcpcb *tp = sototcpcb(so); 660 struct toepcb *toep = tp->t_toe; 661 662 if (toep == NULL) 663 return; | 833} 834 835static void 836t3_set_tcb_field(struct socket *so, uint16_t word, uint64_t mask, uint64_t val) 837{ 838 struct mbuf *m; 839 struct tcpcb *tp = sototcpcb(so); 840 struct toepcb *toep = tp->t_toe; 841 842 if (toep == NULL) 843 return; |
664 665 if (tp->t_state == TCPS_CLOSED || (toep->tp_flags & TP_ABORT_SHUTDOWN)) | 844 845 if (tp->t_state == TCPS_CLOSED || (toep->tp_flags & TP_ABORT_SHUTDOWN)) { 846 printf("not seting field\n"); |
666 return; | 847 return; |
667 | 848 } 849 |
668 m = m_gethdr_nofail(sizeof(struct cpl_set_tcb_field)); 669 | 850 m = m_gethdr_nofail(sizeof(struct cpl_set_tcb_field)); 851 |
670 __set_tcb_field(so, m, word, mask, val, 1); | 852 __set_tcb_field(toep, m, word, mask, val, 1); |
671} 672 673/* 674 * Set one of the t_flags bits in the TCB. 675 */ 676static void 677set_tcb_tflag(struct socket *so, unsigned int bit_pos, int val) 678{ --- 51 unchanged lines hidden (view full) --- 730#define TP_DDP_TIMER_WORKAROUND_VAL\ 731 (V_TF_DDP_BUF0_VALID(1) | V_TF_DDP_ACTIVE_BUF(0) |\ 732 ((V_TCB_RX_DDP_BUF0_OFFSET((uint64_t)1) | V_TCB_RX_DDP_BUF0_LEN((uint64_t)2)) <<\ 733 32)) 734 735static void 736t3_enable_ddp(struct socket *so, int on) 737{ | 853} 854 855/* 856 * Set one of the t_flags bits in the TCB. 857 */ 858static void 859set_tcb_tflag(struct socket *so, unsigned int bit_pos, int val) 860{ --- 51 unchanged lines hidden (view full) --- 912#define TP_DDP_TIMER_WORKAROUND_VAL\ 913 (V_TF_DDP_BUF0_VALID(1) | V_TF_DDP_ACTIVE_BUF(0) |\ 914 ((V_TCB_RX_DDP_BUF0_OFFSET((uint64_t)1) | V_TCB_RX_DDP_BUF0_LEN((uint64_t)2)) <<\ 915 32)) 916 917static void 918t3_enable_ddp(struct socket *so, int on) 919{ |
738 if (on) | 920 if (on) { 921 |
739 t3_set_tcb_field(so, W_TCB_RX_DDP_FLAGS, V_TF_DDP_OFF(1), 740 V_TF_DDP_OFF(0)); | 922 t3_set_tcb_field(so, W_TCB_RX_DDP_FLAGS, V_TF_DDP_OFF(1), 923 V_TF_DDP_OFF(0)); |
741 else | 924 } else |
742 t3_set_tcb_field(so, W_TCB_RX_DDP_FLAGS, 743 V_TF_DDP_OFF(1) | 744 TP_DDP_TIMER_WORKAROUND_MASK, 745 V_TF_DDP_OFF(1) | 746 TP_DDP_TIMER_WORKAROUND_VAL); 747 748} 749 | 925 t3_set_tcb_field(so, W_TCB_RX_DDP_FLAGS, 926 V_TF_DDP_OFF(1) | 927 TP_DDP_TIMER_WORKAROUND_MASK, 928 V_TF_DDP_OFF(1) | 929 TP_DDP_TIMER_WORKAROUND_VAL); 930 931} 932 |
750 | |
751void 752t3_set_ddp_tag(struct socket *so, int buf_idx, unsigned int tag_color) 753{ 754 t3_set_tcb_field(so, W_TCB_RX_DDP_BUF0_TAG + buf_idx, 755 V_TCB_RX_DDP_BUF0_TAG(M_TCB_RX_DDP_BUF0_TAG), 756 tag_color); 757} 758 --- 13 unchanged lines hidden (view full) --- 772 V_TCB_RX_DDP_BUF1_LEN(M_TCB_RX_DDP_BUF1_LEN << 32), 773 V_TCB_RX_DDP_BUF1_OFFSET((uint64_t)offset) | 774 V_TCB_RX_DDP_BUF1_LEN(((uint64_t)len) << 32)); 775} 776 777static int 778t3_set_cong_control(struct socket *so, const char *name) 779{ | 933void 934t3_set_ddp_tag(struct socket *so, int buf_idx, unsigned int tag_color) 935{ 936 t3_set_tcb_field(so, W_TCB_RX_DDP_BUF0_TAG + buf_idx, 937 V_TCB_RX_DDP_BUF0_TAG(M_TCB_RX_DDP_BUF0_TAG), 938 tag_color); 939} 940 --- 13 unchanged lines hidden (view full) --- 954 V_TCB_RX_DDP_BUF1_LEN(M_TCB_RX_DDP_BUF1_LEN << 32), 955 V_TCB_RX_DDP_BUF1_OFFSET((uint64_t)offset) | 956 V_TCB_RX_DDP_BUF1_LEN(((uint64_t)len) << 32)); 957} 958 959static int 960t3_set_cong_control(struct socket *so, const char *name) 961{ |
780#ifdef notyet | 962#ifdef CONGESTION_CONTROL_SUPPORTED |
781 int cong_algo; 782 783 for (cong_algo = 0; cong_algo < ARRAY_SIZE(t3_cong_ops); cong_algo++) 784 if (!strcmp(name, t3_cong_ops[cong_algo].name)) 785 break; 786 787 if (cong_algo >= ARRAY_SIZE(t3_cong_ops)) 788 return -EINVAL; --- 8 unchanged lines hidden (view full) --- 797 struct tcpcb *tp = sototcpcb(so); 798 struct toepcb *toep = tp->t_toe; 799 struct mbuf *m = m_gethdr(M_NOWAIT, MT_DATA); 800 801 if (!m) 802 return (ENOMEM); 803 804 INP_LOCK_ASSERT(tp->t_inpcb); | 963 int cong_algo; 964 965 for (cong_algo = 0; cong_algo < ARRAY_SIZE(t3_cong_ops); cong_algo++) 966 if (!strcmp(name, t3_cong_ops[cong_algo].name)) 967 break; 968 969 if (cong_algo >= ARRAY_SIZE(t3_cong_ops)) 970 return -EINVAL; --- 8 unchanged lines hidden (view full) --- 979 struct tcpcb *tp = sototcpcb(so); 980 struct toepcb *toep = tp->t_toe; 981 struct mbuf *m = m_gethdr(M_NOWAIT, MT_DATA); 982 983 if (!m) 984 return (ENOMEM); 985 986 INP_LOCK_ASSERT(tp->t_inpcb); |
805 m_set_priority(m, mkprio(CPL_PRIORITY_CONTROL, so)); | 987 m_set_priority(m, mkprio(CPL_PRIORITY_CONTROL, toep)); |
806 req = mtod(m, struct cpl_get_tcb *); 807 m->m_pkthdr.len = m->m_len = sizeof(*req); 808 req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); | 988 req = mtod(m, struct cpl_get_tcb *); 989 m->m_pkthdr.len = m->m_len = sizeof(*req); 990 req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); |
991 req->wr.wr_lo = 0; |
|
809 OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_GET_TCB, toep->tp_tid)); 810 req->cpuno = htons(toep->tp_qset); | 992 OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_GET_TCB, toep->tp_tid)); 993 req->cpuno = htons(toep->tp_qset); |
994 req->rsvd = 0; |
|
811 if (sototcpcb(so)->t_state == TCPS_SYN_SENT) 812 mbufq_tail(&toep->out_of_order_queue, m); // defer 813 else 814 cxgb_ofld_send(T3C_DEV(so), m); 815 return 0; 816} 817 818static inline void --- 39 unchanged lines hidden (view full) --- 858 859 tp->t_maxseg = td->mtus[idx] - 40; 860 } else 861 idx = find_best_mtu(td, pmtu); 862 863 return (idx); 864} 865 | 995 if (sototcpcb(so)->t_state == TCPS_SYN_SENT) 996 mbufq_tail(&toep->out_of_order_queue, m); // defer 997 else 998 cxgb_ofld_send(T3C_DEV(so), m); 999 return 0; 1000} 1001 1002static inline void --- 39 unchanged lines hidden (view full) --- 1042 1043 tp->t_maxseg = td->mtus[idx] - 40; 1044 } else 1045 idx = find_best_mtu(td, pmtu); 1046 1047 return (idx); 1048} 1049 |
866void 867t3_release_ddp_resources(struct toepcb *toep) 868{ 869 /* 870 * This is a no-op until we have DDP support 871 */ 872} 873 | |
874static inline void 875free_atid(struct t3cdev *cdev, unsigned int tid) 876{ 877 struct toepcb *toep = cxgb_free_atid(cdev, tid); 878 879 if (toep) 880 toepcb_release(toep); 881} --- 28 unchanged lines hidden (view full) --- 910 purge_wr_queue(toep); 911 reset_wr_list(toep); 912 } 913 914 if (toep->tp_l2t) { 915 l2t_release(L2DATA(cdev), toep->tp_l2t); 916 toep->tp_l2t = NULL; 917 } | 1050static inline void 1051free_atid(struct t3cdev *cdev, unsigned int tid) 1052{ 1053 struct toepcb *toep = cxgb_free_atid(cdev, tid); 1054 1055 if (toep) 1056 toepcb_release(toep); 1057} --- 28 unchanged lines hidden (view full) --- 1086 purge_wr_queue(toep); 1087 reset_wr_list(toep); 1088 } 1089 1090 if (toep->tp_l2t) { 1091 l2t_release(L2DATA(cdev), toep->tp_l2t); 1092 toep->tp_l2t = NULL; 1093 } |
918 printf("setting toep->tp_tp to NULL\n"); 919 | |
920 toep->tp_tp = NULL; 921 if (tp) { 922 INP_LOCK_ASSERT(tp->t_inpcb); 923 tp->t_toe = NULL; 924 tp->t_flags &= ~TF_TOE; 925 } 926 927 if (toep->tp_state == TCPS_SYN_SENT) { --- 31 unchanged lines hidden (view full) --- 959{ 960 int wscale = 0; 961 962 if (space > MAX_RCV_WND) 963 space = MAX_RCV_WND; 964 965 if (tcp_do_rfc1323) 966 for (; space > 65535 && wscale < 14; space >>= 1, ++wscale) ; | 1094 toep->tp_tp = NULL; 1095 if (tp) { 1096 INP_LOCK_ASSERT(tp->t_inpcb); 1097 tp->t_toe = NULL; 1098 tp->t_flags &= ~TF_TOE; 1099 } 1100 1101 if (toep->tp_state == TCPS_SYN_SENT) { --- 31 unchanged lines hidden (view full) --- 1133{ 1134 int wscale = 0; 1135 1136 if (space > MAX_RCV_WND) 1137 space = MAX_RCV_WND; 1138 1139 if (tcp_do_rfc1323) 1140 for (; space > 65535 && wscale < 14; space >>= 1, ++wscale) ; |
967 return wscale; | 1141 1142 return (wscale); |
968} 969 970/* 971 * Determine the receive window size for a socket. 972 */ | 1143} 1144 1145/* 1146 * Determine the receive window size for a socket. 1147 */ |
973static unsigned int 974select_rcv_wnd(struct socket *so) | 1148static unsigned long 1149select_rcv_wnd(struct toedev *dev, struct socket *so) |
975{ | 1150{ |
976 struct toedev *dev = TOE_DEV(so); | |
977 struct tom_data *d = TOM_DATA(dev); 978 unsigned int wnd; 979 unsigned int max_rcv_wnd; 980 981 if (tcp_do_autorcvbuf) 982 wnd = tcp_autorcvbuf_max; 983 else | 1151 struct tom_data *d = TOM_DATA(dev); 1152 unsigned int wnd; 1153 unsigned int max_rcv_wnd; 1154 1155 if (tcp_do_autorcvbuf) 1156 wnd = tcp_autorcvbuf_max; 1157 else |
984 wnd = sbspace(&so->so_rcv); | 1158 wnd = so->so_rcv.sb_hiwat; 1159 |
985 | 1160 |
1161 |
|
986 /* XXX 987 * For receive coalescing to work effectively we need a receive window 988 * that can accomodate a coalesced segment. 989 */ 990 if (wnd < MIN_RCV_WND) 991 wnd = MIN_RCV_WND; 992 993 /* PR 5138 */ | 1162 /* XXX 1163 * For receive coalescing to work effectively we need a receive window 1164 * that can accomodate a coalesced segment. 1165 */ 1166 if (wnd < MIN_RCV_WND) 1167 wnd = MIN_RCV_WND; 1168 1169 /* PR 5138 */ |
994 max_rcv_wnd = (dev->tod_ttid == TOE_ID_CHELSIO_T3B ? | 1170 max_rcv_wnd = (dev->tod_ttid < TOE_ID_CHELSIO_T3C ? |
995 (uint32_t)d->rx_page_size * 23 : 996 MAX_RCV_WND); 997 998 return min(wnd, max_rcv_wnd); 999} 1000 1001/* 1002 * Assign offload parameters to some socket fields. This code is used by --- 9 unchanged lines hidden (view full) --- 1012 SOCK_LOCK_ASSERT(so); 1013 1014 printf("initializing offload socket\n"); 1015 /* 1016 * We either need to fix push frames to work with sbcompress 1017 * or we need to add this 1018 */ 1019 so->so_snd.sb_flags |= SB_NOCOALESCE; | 1171 (uint32_t)d->rx_page_size * 23 : 1172 MAX_RCV_WND); 1173 1174 return min(wnd, max_rcv_wnd); 1175} 1176 1177/* 1178 * Assign offload parameters to some socket fields. This code is used by --- 9 unchanged lines hidden (view full) --- 1188 SOCK_LOCK_ASSERT(so); 1189 1190 printf("initializing offload socket\n"); 1191 /* 1192 * We either need to fix push frames to work with sbcompress 1193 * or we need to add this 1194 */ 1195 so->so_snd.sb_flags |= SB_NOCOALESCE; |
1020 | 1196 so->so_rcv.sb_flags |= SB_NOCOALESCE; 1197 |
1021 tp->t_toe = toep; 1022 toep->tp_tp = tp; 1023 toep->tp_toedev = dev; 1024 1025 toep->tp_tid = tid; 1026 toep->tp_l2t = e; 1027 toep->tp_wr_max = toep->tp_wr_avail = TOM_TUNABLE(dev, max_wrs); 1028 toep->tp_wr_unacked = 0; 1029 toep->tp_delack_mode = 0; 1030 1031 toep->tp_mtu_idx = select_mss(td, tp, dst->rt_ifp->if_mtu); 1032 /* 1033 * XXX broken 1034 * 1035 */ | 1198 tp->t_toe = toep; 1199 toep->tp_tp = tp; 1200 toep->tp_toedev = dev; 1201 1202 toep->tp_tid = tid; 1203 toep->tp_l2t = e; 1204 toep->tp_wr_max = toep->tp_wr_avail = TOM_TUNABLE(dev, max_wrs); 1205 toep->tp_wr_unacked = 0; 1206 toep->tp_delack_mode = 0; 1207 1208 toep->tp_mtu_idx = select_mss(td, tp, dst->rt_ifp->if_mtu); 1209 /* 1210 * XXX broken 1211 * 1212 */ |
1036 tp->rcv_wnd = select_rcv_wnd(so); | 1213 tp->rcv_wnd = select_rcv_wnd(dev, so); 1214 |
1037 toep->tp_ulp_mode = TOM_TUNABLE(dev, ddp) && !(so->so_options & SO_NO_DDP) && 1038 tp->rcv_wnd >= MIN_DDP_RCV_WIN ? ULP_MODE_TCPDDP : 0; 1039 toep->tp_qset_idx = 0; 1040 1041 reset_wr_list(toep); 1042 DPRINTF("initialization done\n"); 1043} 1044 --- 26 unchanged lines hidden (view full) --- 1071 1072static inline unsigned int 1073calc_opt2(const struct socket *so, struct toedev *dev) 1074{ 1075 int flv_valid; 1076 1077 flv_valid = (TOM_TUNABLE(dev, cong_alg) != -1); 1078 | 1215 toep->tp_ulp_mode = TOM_TUNABLE(dev, ddp) && !(so->so_options & SO_NO_DDP) && 1216 tp->rcv_wnd >= MIN_DDP_RCV_WIN ? ULP_MODE_TCPDDP : 0; 1217 toep->tp_qset_idx = 0; 1218 1219 reset_wr_list(toep); 1220 DPRINTF("initialization done\n"); 1221} 1222 --- 26 unchanged lines hidden (view full) --- 1249 1250static inline unsigned int 1251calc_opt2(const struct socket *so, struct toedev *dev) 1252{ 1253 int flv_valid; 1254 1255 flv_valid = (TOM_TUNABLE(dev, cong_alg) != -1); 1256 |
1079 return V_FLAVORS_VALID(flv_valid) | 1080 V_CONG_CONTROL_FLAVOR(flv_valid ? TOM_TUNABLE(dev, cong_alg) : 0); | 1257 return (V_FLAVORS_VALID(flv_valid) | 1258 V_CONG_CONTROL_FLAVOR(flv_valid ? TOM_TUNABLE(dev, cong_alg) : 0)); |
1081} | 1259} |
1260 1261#if DEBUG_WR > 1 1262static int 1263count_pending_wrs(const struct toepcb *toep) 1264{ 1265 const struct mbuf *m; 1266 int n = 0; 1267 1268 wr_queue_walk(toep, m) 1269 n += m->m_pkthdr.csum_data; 1270 return (n); 1271} 1272#endif 1273 |
|
1082#if 0 1083(((*(struct tom_data **)&(dev)->l4opt)->conf.cong_alg) != -1) 1084#endif 1085 1086static void 1087mk_act_open_req(struct socket *so, struct mbuf *m, 1088 unsigned int atid, const struct l2t_entry *e) 1089{ 1090 struct cpl_act_open_req *req; 1091 struct inpcb *inp = sotoinpcb(so); 1092 struct tcpcb *tp = intotcpcb(inp); 1093 struct toepcb *toep = tp->t_toe; 1094 struct toedev *tdev = TOE_DEV(so); 1095 | 1274#if 0 1275(((*(struct tom_data **)&(dev)->l4opt)->conf.cong_alg) != -1) 1276#endif 1277 1278static void 1279mk_act_open_req(struct socket *so, struct mbuf *m, 1280 unsigned int atid, const struct l2t_entry *e) 1281{ 1282 struct cpl_act_open_req *req; 1283 struct inpcb *inp = sotoinpcb(so); 1284 struct tcpcb *tp = intotcpcb(inp); 1285 struct toepcb *toep = tp->t_toe; 1286 struct toedev *tdev = TOE_DEV(so); 1287 |
1096 m_set_priority((struct mbuf *)m, mkprio(CPL_PRIORITY_SETUP, so)); | 1288 m_set_priority((struct mbuf *)m, mkprio(CPL_PRIORITY_SETUP, toep)); |
1097 1098 req = mtod(m, struct cpl_act_open_req *); 1099 m->m_pkthdr.len = m->m_len = sizeof(*req); | 1289 1290 req = mtod(m, struct cpl_act_open_req *); 1291 m->m_pkthdr.len = m->m_len = sizeof(*req); |
1100 | 1292 |
1101 req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); | 1293 req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); |
1294 req->wr.wr_lo = 0; |
|
1102 OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, atid)); 1103 req->local_port = inp->inp_lport; 1104 req->peer_port = inp->inp_fport; 1105 memcpy(&req->local_ip, &inp->inp_laddr, 4); 1106 memcpy(&req->peer_ip, &inp->inp_faddr, 4); | 1295 OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, atid)); 1296 req->local_port = inp->inp_lport; 1297 req->peer_port = inp->inp_fport; 1298 memcpy(&req->local_ip, &inp->inp_laddr, 4); 1299 memcpy(&req->peer_ip, &inp->inp_faddr, 4); |
1107 DPRINTF("connect smt_idx=%d\n", e->smt_idx); | |
1108 req->opt0h = htonl(calc_opt0h(so, toep->tp_mtu_idx) | V_L2T_IDX(e->idx) | 1109 V_TX_CHANNEL(e->smt_idx)); 1110 req->opt0l = htonl(calc_opt0l(so, toep->tp_ulp_mode)); 1111 req->params = 0; 1112 req->opt2 = htonl(calc_opt2(so, tdev)); 1113} 1114 1115 --- 23 unchanged lines hidden (view full) --- 1139static void 1140fail_act_open(struct toepcb *toep, int errno) 1141{ 1142 struct tcpcb *tp = toep->tp_tp; 1143 1144 t3_release_offload_resources(toep); 1145 if (tp) { 1146 INP_LOCK_ASSERT(tp->t_inpcb); | 1300 req->opt0h = htonl(calc_opt0h(so, toep->tp_mtu_idx) | V_L2T_IDX(e->idx) | 1301 V_TX_CHANNEL(e->smt_idx)); 1302 req->opt0l = htonl(calc_opt0l(so, toep->tp_ulp_mode)); 1303 req->params = 0; 1304 req->opt2 = htonl(calc_opt2(so, tdev)); 1305} 1306 1307 --- 23 unchanged lines hidden (view full) --- 1331static void 1332fail_act_open(struct toepcb *toep, int errno) 1333{ 1334 struct tcpcb *tp = toep->tp_tp; 1335 1336 t3_release_offload_resources(toep); 1337 if (tp) { 1338 INP_LOCK_ASSERT(tp->t_inpcb); |
1147 cxgb_tcp_drop(tp, errno); | 1339 tcp_drop(tp, errno); |
1148 } 1149 1150#ifdef notyet 1151 TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS); 1152#endif 1153} 1154 1155/* --- 128 unchanged lines hidden (view full) --- 1284 1285 mk_act_open_req(so, m, atid, e); 1286 SOCK_UNLOCK(so); 1287 1288 soisconnecting(so); 1289 toep = tp->t_toe; 1290 m_set_toep(m, tp->t_toe); 1291 | 1340 } 1341 1342#ifdef notyet 1343 TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS); 1344#endif 1345} 1346 1347/* --- 128 unchanged lines hidden (view full) --- 1476 1477 mk_act_open_req(so, m, atid, e); 1478 SOCK_UNLOCK(so); 1479 1480 soisconnecting(so); 1481 toep = tp->t_toe; 1482 m_set_toep(m, tp->t_toe); 1483 |
1292 printf("sending off request\n"); 1293 | |
1294 toep->tp_state = TCPS_SYN_SENT; 1295 l2t_send(d->cdev, (struct mbuf *)m, e); 1296 1297 if (toep->tp_ulp_mode) 1298 t3_enable_ddp(so, 0); 1299 return (0); 1300 1301free_tid: --- 35 unchanged lines hidden (view full) --- 1337 1338 /* Purge the send queue so we don't send anything after an abort. */ 1339 if (so) 1340 sbflush(&so->so_snd); 1341 if ((toep->tp_flags & TP_CLOSE_CON_REQUESTED) && is_t3a(tdev)) 1342 mode |= CPL_ABORT_POST_CLOSE_REQ; 1343 1344 m = m_gethdr_nofail(sizeof(*req)); | 1484 toep->tp_state = TCPS_SYN_SENT; 1485 l2t_send(d->cdev, (struct mbuf *)m, e); 1486 1487 if (toep->tp_ulp_mode) 1488 t3_enable_ddp(so, 0); 1489 return (0); 1490 1491free_tid: --- 35 unchanged lines hidden (view full) --- 1527 1528 /* Purge the send queue so we don't send anything after an abort. */ 1529 if (so) 1530 sbflush(&so->so_snd); 1531 if ((toep->tp_flags & TP_CLOSE_CON_REQUESTED) && is_t3a(tdev)) 1532 mode |= CPL_ABORT_POST_CLOSE_REQ; 1533 1534 m = m_gethdr_nofail(sizeof(*req)); |
1345 m_set_priority(m, mkprio(CPL_PRIORITY_DATA, so)); | 1535 m_set_priority(m, mkprio(CPL_PRIORITY_DATA, toep)); |
1346 set_arp_failure_handler(m, abort_arp_failure); 1347 1348 req = mtod(m, struct cpl_abort_req *); 1349 req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_REQ)); 1350 req->wr.wr_lo = htonl(V_WR_TID(tid)); 1351 OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ABORT_REQ, tid)); 1352 req->rsvd0 = tp ? htonl(tp->snd_nxt) : 0; 1353 req->rsvd1 = !(toep->tp_flags & TP_DATASENT); --- 57 unchanged lines hidden (view full) --- 1411 if (copied < 1) 1412 return (EINVAL); 1413 1414 tp = sototcpcb(so); 1415 /* 1416 * XXX I need to revisit this 1417 */ 1418 if ((err = t3_set_cong_control(so, name)) == 0) { | 1536 set_arp_failure_handler(m, abort_arp_failure); 1537 1538 req = mtod(m, struct cpl_abort_req *); 1539 req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_REQ)); 1540 req->wr.wr_lo = htonl(V_WR_TID(tid)); 1541 OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ABORT_REQ, tid)); 1542 req->rsvd0 = tp ? htonl(tp->snd_nxt) : 0; 1543 req->rsvd1 = !(toep->tp_flags & TP_DATASENT); --- 57 unchanged lines hidden (view full) --- 1601 if (copied < 1) 1602 return (EINVAL); 1603 1604 tp = sototcpcb(so); 1605 /* 1606 * XXX I need to revisit this 1607 */ 1608 if ((err = t3_set_cong_control(so, name)) == 0) { |
1419#ifdef notyet | 1609#ifdef CONGESTION_CONTROL_SUPPORTED |
1420 tp->t_cong_control = strdup(name, M_CXGB); 1421#endif 1422 } else 1423 return (err); 1424 } else { 1425 int optval, oldval; 1426 struct inpcb *inp; 1427 struct tcpcb *tp; --- 32 unchanged lines hidden (view full) --- 1460 if (sopt->sopt_level != IPPROTO_TCP) 1461 err = t3_ip_ctloutput(so, sopt); 1462 else 1463 err = t3_tcp_ctloutput(so, sopt); 1464 1465 if (err != EOPNOTSUPP) 1466 return (err); 1467 | 1610 tp->t_cong_control = strdup(name, M_CXGB); 1611#endif 1612 } else 1613 return (err); 1614 } else { 1615 int optval, oldval; 1616 struct inpcb *inp; 1617 struct tcpcb *tp; --- 32 unchanged lines hidden (view full) --- 1650 if (sopt->sopt_level != IPPROTO_TCP) 1651 err = t3_ip_ctloutput(so, sopt); 1652 else 1653 err = t3_tcp_ctloutput(so, sopt); 1654 1655 if (err != EOPNOTSUPP) 1656 return (err); 1657 |
1468 return tcp_ctloutput(so, sopt); | 1658 return (tcp_ctloutput(so, sopt)); |
1469} 1470 1471/* | 1659} 1660 1661/* |
1662 * Returns true if we need to explicitly request RST when we receive new data 1663 * on an RX-closed connection. 1664 */ 1665static inline int 1666need_rst_on_excess_rx(const struct toepcb *toep) 1667{ 1668 return (1); 1669} 1670 1671/* 1672 * Handles Rx data that arrives in a state where the socket isn't accepting 1673 * new data. 1674 */ 1675static void 1676handle_excess_rx(struct toepcb *toep, struct mbuf *m) 1677{ 1678 1679 if (need_rst_on_excess_rx(toep) && !(toep->tp_flags & TP_ABORT_SHUTDOWN)) 1680 t3_send_reset(toep); 1681 m_freem(m); 1682} 1683 1684/* 1685 * Process a get_tcb_rpl as a DDP completion (similar to RX_DDP_COMPLETE) 1686 * by getting the DDP offset from the TCB. 1687 */ 1688static void 1689tcb_rpl_as_ddp_complete(struct toepcb *toep, struct mbuf *m) 1690{ 1691 struct ddp_state *q = &toep->tp_ddp_state; 1692 struct ddp_buf_state *bsp; 1693 struct cpl_get_tcb_rpl *hdr; 1694 unsigned int ddp_offset; 1695 struct socket *so; 1696 struct tcpcb *tp; 1697 1698 uint64_t t; 1699 __be64 *tcb; 1700 1701 so = toeptoso(toep); 1702 tp = toep->tp_tp; 1703 1704 INP_LOCK_ASSERT(tp->t_inpcb); 1705 SOCKBUF_LOCK(&so->so_rcv); 1706 1707 /* Note that we only accout for CPL_GET_TCB issued by the DDP code. We 1708 * really need a cookie in order to dispatch the RPLs. 1709 */ 1710 q->get_tcb_count--; 1711 1712 /* It is a possible that a previous CPL already invalidated UBUF DDP 1713 * and moved the cur_buf idx and hence no further processing of this 1714 * skb is required. However, the app might be sleeping on 1715 * !q->get_tcb_count and we need to wake it up. 1716 */ 1717 if (q->cancel_ubuf && !t3_ddp_ubuf_pending(toep)) { 1718 struct socket *so = toeptoso(toep); 1719 1720 m_freem(m); 1721 if (__predict_true((so->so_state & SS_NOFDREF) == 0)) 1722 sorwakeup_locked(so); 1723 else 1724 SOCKBUF_UNLOCK(&so->so_rcv); 1725 return; 1726 } 1727 1728 bsp = &q->buf_state[q->cur_buf]; 1729 hdr = cplhdr(m); 1730 tcb = (__be64 *)(hdr + 1); 1731 if (q->cur_buf == 0) { 1732 t = be64toh(tcb[(31 - W_TCB_RX_DDP_BUF0_OFFSET) / 2]); 1733 ddp_offset = t >> (32 + S_TCB_RX_DDP_BUF0_OFFSET); 1734 } else { 1735 t = be64toh(tcb[(31 - W_TCB_RX_DDP_BUF1_OFFSET) / 2]); 1736 ddp_offset = t >> S_TCB_RX_DDP_BUF1_OFFSET; 1737 } 1738 ddp_offset &= M_TCB_RX_DDP_BUF0_OFFSET; 1739 m->m_cur_offset = bsp->cur_offset; 1740 bsp->cur_offset = ddp_offset; 1741 m->m_len = m->m_pkthdr.len = ddp_offset - m->m_cur_offset; 1742 1743 CTR5(KTR_TOM, 1744 "tcb_rpl_as_ddp_complete: idx=%d seq=0x%x hwbuf=%u ddp_offset=%u cur_offset=%u", 1745 q->cur_buf, tp->rcv_nxt, q->cur_buf, ddp_offset, m->m_cur_offset); 1746 KASSERT(ddp_offset >= m->m_cur_offset, ("ddp_offset=%u less than cur_offset=%u", 1747 ddp_offset, m->m_cur_offset)); 1748 1749#ifdef T3_TRACE 1750 T3_TRACE3(TIDTB(so), 1751 "tcb_rpl_as_ddp_complete: seq 0x%x hwbuf %u ddp_offset %u", 1752 tp->rcv_nxt, q->cur_buf, ddp_offset); 1753#endif 1754 1755#if 0 1756{ 1757 unsigned int ddp_flags, rcv_nxt, rx_hdr_offset, buf_idx; 1758 1759 t = be64toh(tcb[(31 - W_TCB_RX_DDP_FLAGS) / 2]); 1760 ddp_flags = (t >> S_TCB_RX_DDP_FLAGS) & M_TCB_RX_DDP_FLAGS; 1761 1762 t = be64toh(tcb[(31 - W_TCB_RCV_NXT) / 2]); 1763 rcv_nxt = t >> S_TCB_RCV_NXT; 1764 rcv_nxt &= M_TCB_RCV_NXT; 1765 1766 t = be64toh(tcb[(31 - W_TCB_RX_HDR_OFFSET) / 2]); 1767 rx_hdr_offset = t >> (32 + S_TCB_RX_HDR_OFFSET); 1768 rx_hdr_offset &= M_TCB_RX_HDR_OFFSET; 1769 1770 T3_TRACE2(TIDTB(sk), 1771 "tcb_rpl_as_ddp_complete: DDP FLAGS 0x%x dma up to 0x%x", 1772 ddp_flags, rcv_nxt - rx_hdr_offset); 1773 T3_TRACE4(TB(q), 1774 "tcb_rpl_as_ddp_complete: rcvnxt 0x%x hwbuf %u cur_offset %u cancel %u", 1775 tp->rcv_nxt, q->cur_buf, bsp->cur_offset, q->cancel_ubuf); 1776 T3_TRACE3(TB(q), 1777 "tcb_rpl_as_ddp_complete: TCB rcvnxt 0x%x hwbuf 0x%x ddp_offset %u", 1778 rcv_nxt - rx_hdr_offset, ddp_flags, ddp_offset); 1779 T3_TRACE2(TB(q), 1780 "tcb_rpl_as_ddp_complete: flags0 0x%x flags1 0x%x", 1781 q->buf_state[0].flags, q->buf_state[1].flags); 1782 1783} 1784#endif 1785 if (__predict_false(so_no_receive(so) && m->m_pkthdr.len)) { 1786 handle_excess_rx(toep, m); 1787 return; 1788 } 1789 1790#ifdef T3_TRACE 1791 if ((int)m->m_pkthdr.len < 0) { 1792 t3_ddp_error(so, "tcb_rpl_as_ddp_complete: neg len"); 1793 } 1794#endif 1795 if (bsp->flags & DDP_BF_NOCOPY) { 1796#ifdef T3_TRACE 1797 T3_TRACE0(TB(q), 1798 "tcb_rpl_as_ddp_complete: CANCEL UBUF"); 1799 1800 if (!q->cancel_ubuf && !(sk->sk_shutdown & RCV_SHUTDOWN)) { 1801 printk("!cancel_ubuf"); 1802 t3_ddp_error(sk, "tcb_rpl_as_ddp_complete: !cancel_ubuf"); 1803 } 1804#endif 1805 m->m_ddp_flags = DDP_BF_PSH | DDP_BF_NOCOPY | 1; 1806 bsp->flags &= ~(DDP_BF_NOCOPY|DDP_BF_NODATA); 1807 q->cur_buf ^= 1; 1808 } else if (bsp->flags & DDP_BF_NOFLIP) { 1809 1810 m->m_ddp_flags = 1; /* always a kernel buffer */ 1811 1812 /* now HW buffer carries a user buffer */ 1813 bsp->flags &= ~DDP_BF_NOFLIP; 1814 bsp->flags |= DDP_BF_NOCOPY; 1815 1816 /* It is possible that the CPL_GET_TCB_RPL doesn't indicate 1817 * any new data in which case we're done. If in addition the 1818 * offset is 0, then there wasn't a completion for the kbuf 1819 * and we need to decrement the posted count. 1820 */ 1821 if (m->m_pkthdr.len == 0) { 1822 if (ddp_offset == 0) { 1823 q->kbuf_posted--; 1824 bsp->flags |= DDP_BF_NODATA; 1825 } 1826 SOCKBUF_UNLOCK(&so->so_rcv); 1827 1828 m_free(m); 1829 return; 1830 } 1831 } else { 1832 SOCKBUF_UNLOCK(&so->so_rcv); 1833 /* This reply is for a CPL_GET_TCB_RPL to cancel the UBUF DDP, 1834 * but it got here way late and nobody cares anymore. 1835 */ 1836 m_free(m); 1837 return; 1838 } 1839 1840 m->m_ddp_gl = (unsigned char *)bsp->gl; 1841 m->m_flags |= M_DDP; 1842 m->m_seq = tp->rcv_nxt; 1843 tp->rcv_nxt += m->m_pkthdr.len; 1844 tp->t_rcvtime = ticks; 1845#ifdef T3_TRACE 1846 T3_TRACE3(TB(q), 1847 "tcb_rpl_as_ddp_complete: seq 0x%x hwbuf %u lskb->len %u", 1848 m->m_seq, q->cur_buf, m->m_pkthdr.len); 1849#endif 1850 CTR3(KTR_TOM, "tcb_rpl_as_ddp_complete: seq 0x%x hwbuf %u m->m_pktlen %u", 1851 m->m_seq, q->cur_buf, m->m_pkthdr.len); 1852 if (m->m_pkthdr.len == 0) 1853 q->user_ddp_pending = 0; 1854 else 1855 SBAPPEND(&so->so_rcv, m); 1856 if (__predict_true((so->so_state & SS_NOFDREF) == 0)) 1857 sorwakeup_locked(so); 1858 else 1859 SOCKBUF_UNLOCK(&so->so_rcv); 1860} 1861 1862/* 1863 * Process a CPL_GET_TCB_RPL. These can also be generated by the DDP code, 1864 * in that case they are similar to DDP completions. 1865 */ 1866static int 1867do_get_tcb_rpl(struct t3cdev *cdev, struct mbuf *m, void *ctx) 1868{ 1869 struct toepcb *toep = (struct toepcb *)ctx; 1870 1871 /* OK if socket doesn't exist */ 1872 if (toep == NULL) { 1873 printf("null toep in do_get_tcb_rpl\n"); 1874 return (CPL_RET_BUF_DONE); 1875 } 1876 1877 INP_LOCK(toep->tp_tp->t_inpcb); 1878 tcb_rpl_as_ddp_complete(toep, m); 1879 INP_UNLOCK(toep->tp_tp->t_inpcb); 1880 1881 return (0); 1882} 1883 1884static void 1885handle_ddp_data(struct toepcb *toep, struct mbuf *m) 1886{ 1887 struct tcpcb *tp = toep->tp_tp; 1888 struct socket *so = toeptoso(toep); 1889 struct ddp_state *q; 1890 struct ddp_buf_state *bsp; 1891 struct cpl_rx_data *hdr = cplhdr(m); 1892 unsigned int rcv_nxt = ntohl(hdr->seq); 1893 1894 if (tp->rcv_nxt == rcv_nxt) 1895 return; 1896 1897 INP_LOCK_ASSERT(tp->t_inpcb); 1898 SOCKBUF_LOCK(&so->so_rcv); 1899 q = &toep->tp_ddp_state; 1900 bsp = &q->buf_state[q->cur_buf]; 1901 KASSERT(SEQ_GT(rcv_nxt, tp->rcv_nxt), ("tp->rcv_nxt=0x%08x decreased rcv_nxt=0x08%x", 1902 rcv_nxt, tp->rcv_nxt)); 1903 m->m_len = m->m_pkthdr.len = rcv_nxt - tp->rcv_nxt; 1904 KASSERT(m->m_len > 0, ("%s m_len=%d", __FUNCTION__, m->m_len)); 1905 CTR3(KTR_TOM, "rcv_nxt=0x%x tp->rcv_nxt=0x%x len=%d", 1906 rcv_nxt, tp->rcv_nxt, m->m_pkthdr.len); 1907 1908#ifdef T3_TRACE 1909 if ((int)m->m_pkthdr.len < 0) { 1910 t3_ddp_error(so, "handle_ddp_data: neg len"); 1911 } 1912#endif 1913 1914 m->m_ddp_gl = (unsigned char *)bsp->gl; 1915 m->m_flags |= M_DDP; 1916 m->m_cur_offset = bsp->cur_offset; 1917 m->m_ddp_flags = DDP_BF_PSH | (bsp->flags & DDP_BF_NOCOPY) | 1; 1918 if (bsp->flags & DDP_BF_NOCOPY) 1919 bsp->flags &= ~DDP_BF_NOCOPY; 1920 1921 m->m_seq = tp->rcv_nxt; 1922 tp->rcv_nxt = rcv_nxt; 1923 bsp->cur_offset += m->m_pkthdr.len; 1924 if (!(bsp->flags & DDP_BF_NOFLIP)) 1925 q->cur_buf ^= 1; 1926 /* 1927 * For now, don't re-enable DDP after a connection fell out of DDP 1928 * mode. 1929 */ 1930 q->ubuf_ddp_ready = 0; 1931 SOCKBUF_UNLOCK(&so->so_rcv); 1932} 1933 1934/* |
|
1472 * Process new data received for a connection. 1473 */ 1474static void 1475new_rx_data(struct toepcb *toep, struct mbuf *m) 1476{ 1477 struct cpl_rx_data *hdr = cplhdr(m); 1478 struct tcpcb *tp = toep->tp_tp; 1479 struct socket *so = toeptoso(toep); 1480 int len = be16toh(hdr->len); 1481 1482 INP_LOCK(tp->t_inpcb); 1483 | 1935 * Process new data received for a connection. 1936 */ 1937static void 1938new_rx_data(struct toepcb *toep, struct mbuf *m) 1939{ 1940 struct cpl_rx_data *hdr = cplhdr(m); 1941 struct tcpcb *tp = toep->tp_tp; 1942 struct socket *so = toeptoso(toep); 1943 int len = be16toh(hdr->len); 1944 1945 INP_LOCK(tp->t_inpcb); 1946 |
1484#ifdef notyet 1485 if (__predict_false(sk_no_receive(sk))) { 1486 handle_excess_rx(so, skb); | 1947 if (__predict_false(so_no_receive(so))) { 1948 handle_excess_rx(toep, m); 1949 INP_UNLOCK(tp->t_inpcb); 1950 TRACE_EXIT; |
1487 return; 1488 } 1489 | 1951 return; 1952 } 1953 |
1490 if (ULP_MODE(tp) == ULP_MODE_TCPDDP) 1491 handle_ddp_data(so, skb); | 1954 if (toep->tp_ulp_mode == ULP_MODE_TCPDDP) 1955 handle_ddp_data(toep, m); 1956 1957 m->m_seq = ntohl(hdr->seq); 1958 m->m_ulp_mode = 0; /* for iSCSI */ |
1492 | 1959 |
1493 TCP_SKB_CB(skb)->seq = ntohl(hdr->seq); 1494 TCP_SKB_CB(skb)->flags = 0; 1495 skb_ulp_mode(skb) = 0; /* for iSCSI */ 1496#endif | |
1497#if VALIDATE_SEQ | 1960#if VALIDATE_SEQ |
1498 if (__predict_false(TCP_SKB_CB(skb)->seq != tp->rcv_nxt)) { 1499 printk(KERN_ERR | 1961 if (__predict_false(m->m_seq != tp->rcv_nxt)) { 1962 log(LOG_ERR, |
1500 "%s: TID %u: Bad sequence number %u, expected %u\n", | 1963 "%s: TID %u: Bad sequence number %u, expected %u\n", |
1501 TOE_DEV(sk)->name, TID(tp), TCP_SKB_CB(skb)->seq, | 1964 TOE_DEV(toeptoso(toep))->name, toep->tp_tid, m->m_seq, |
1502 tp->rcv_nxt); | 1965 tp->rcv_nxt); |
1503 __kfree_skb(skb); | 1966 m_freem(m); 1967 INP_UNLOCK(tp->t_inpcb); |
1504 return; 1505 } 1506#endif 1507 m_adj(m, sizeof(*hdr)); 1508 | 1968 return; 1969 } 1970#endif 1971 m_adj(m, sizeof(*hdr)); 1972 |
1509#ifdef notyet | 1973#ifdef URGENT_DATA_SUPPORTED |
1510 /* 1511 * We don't handle urgent data yet 1512 */ 1513 if (__predict_false(hdr->urg)) 1514 handle_urg_ptr(so, tp->rcv_nxt + ntohs(hdr->urg)); 1515 if (__predict_false(tp->urg_data == TCP_URG_NOTYET && 1516 tp->urg_seq - tp->rcv_nxt < skb->len)) 1517 tp->urg_data = TCP_URG_VALID | skb->data[tp->urg_seq - 1518 tp->rcv_nxt]; 1519#endif 1520 if (__predict_false(hdr->dack_mode != toep->tp_delack_mode)) { 1521 toep->tp_delack_mode = hdr->dack_mode; 1522 toep->tp_delack_seq = tp->rcv_nxt; 1523 } | 1974 /* 1975 * We don't handle urgent data yet 1976 */ 1977 if (__predict_false(hdr->urg)) 1978 handle_urg_ptr(so, tp->rcv_nxt + ntohs(hdr->urg)); 1979 if (__predict_false(tp->urg_data == TCP_URG_NOTYET && 1980 tp->urg_seq - tp->rcv_nxt < skb->len)) 1981 tp->urg_data = TCP_URG_VALID | skb->data[tp->urg_seq - 1982 tp->rcv_nxt]; 1983#endif 1984 if (__predict_false(hdr->dack_mode != toep->tp_delack_mode)) { 1985 toep->tp_delack_mode = hdr->dack_mode; 1986 toep->tp_delack_seq = tp->rcv_nxt; 1987 } |
1524 1525 DPRINTF("appending mbuf=%p pktlen=%d m_len=%d len=%d\n", m, m->m_pkthdr.len, m->m_len, len); | 1988 CTR6(KTR_TOM, "appending mbuf=%p pktlen=%d m_len=%d len=%d rcv_nxt=0x%x enqueued_bytes=%d", 1989 m, m->m_pkthdr.len, m->m_len, len, tp->rcv_nxt, toep->tp_enqueued_bytes); |
1526 1527 if (len < m->m_pkthdr.len) 1528 m->m_pkthdr.len = m->m_len = len; 1529 1530 tp->rcv_nxt += m->m_pkthdr.len; 1531 tp->t_rcvtime = ticks; 1532 toep->tp_enqueued_bytes += m->m_pkthdr.len; 1533#ifdef T3_TRACE 1534 T3_TRACE2(TIDTB(sk), | 1990 1991 if (len < m->m_pkthdr.len) 1992 m->m_pkthdr.len = m->m_len = len; 1993 1994 tp->rcv_nxt += m->m_pkthdr.len; 1995 tp->t_rcvtime = ticks; 1996 toep->tp_enqueued_bytes += m->m_pkthdr.len; 1997#ifdef T3_TRACE 1998 T3_TRACE2(TIDTB(sk), |
1535 "new_rx_data: seq 0x%x len %u", 1536 TCP_SKB_CB(skb)->seq, skb->len); | 1999 "new_rx_data: seq 0x%x len %u", 2000 m->m_seq, m->m_pkthdr.len); |
1537#endif | 2001#endif |
2002 INP_UNLOCK(tp->t_inpcb); |
|
1538 SOCKBUF_LOCK(&so->so_rcv); 1539 if (sb_notify(&so->so_rcv)) 1540 DPRINTF("rx_data so=%p flags=0x%x len=%d\n", so, so->so_rcv.sb_flags, m->m_pkthdr.len); 1541 | 2003 SOCKBUF_LOCK(&so->so_rcv); 2004 if (sb_notify(&so->so_rcv)) 2005 DPRINTF("rx_data so=%p flags=0x%x len=%d\n", so, so->so_rcv.sb_flags, m->m_pkthdr.len); 2006 |
1542 sbappend_locked(&so->so_rcv, m); 1543 KASSERT(so->so_rcv.sb_cc < so->so_rcv.sb_mbmax, | 2007 SBAPPEND(&so->so_rcv, m); |
1544 | 2008 |
2009#ifdef notyet 2010 /* 2011 * We're giving too many credits to the card - but disable this check so we can keep on moving :-| 2012 * 2013 */ 2014 KASSERT(so->so_rcv.sb_cc < (so->so_rcv.sb_mbmax << 1), 2015 |
|
1545 ("so=%p, data contents exceed mbmax, sb_cc=%d sb_mbmax=%d", 1546 so, so->so_rcv.sb_cc, so->so_rcv.sb_mbmax)); | 2016 ("so=%p, data contents exceed mbmax, sb_cc=%d sb_mbmax=%d", 2017 so, so->so_rcv.sb_cc, so->so_rcv.sb_mbmax)); |
2018#endif |
|
1547 | 2019 |
1548 INP_UNLOCK(tp->t_inpcb); 1549 DPRINTF("sb_cc=%d sb_mbcnt=%d\n", | 2020 2021 CTR2(KTR_TOM, "sb_cc=%d sb_mbcnt=%d", |
1550 so->so_rcv.sb_cc, so->so_rcv.sb_mbcnt); 1551 1552 if (__predict_true((so->so_state & SS_NOFDREF) == 0)) 1553 sorwakeup_locked(so); 1554 else 1555 SOCKBUF_UNLOCK(&so->so_rcv); 1556} 1557 --- 8 unchanged lines hidden (view full) --- 1566 DPRINTF("rx_data len=%d\n", m->m_pkthdr.len); 1567 1568 new_rx_data(toep, m); 1569 1570 return (0); 1571} 1572 1573static void | 2022 so->so_rcv.sb_cc, so->so_rcv.sb_mbcnt); 2023 2024 if (__predict_true((so->so_state & SS_NOFDREF) == 0)) 2025 sorwakeup_locked(so); 2026 else 2027 SOCKBUF_UNLOCK(&so->so_rcv); 2028} 2029 --- 8 unchanged lines hidden (view full) --- 2038 DPRINTF("rx_data len=%d\n", m->m_pkthdr.len); 2039 2040 new_rx_data(toep, m); 2041 2042 return (0); 2043} 2044 2045static void |
1574new_rx_data_ddp(struct socket *so, struct mbuf *m) | 2046new_rx_data_ddp(struct toepcb *toep, struct mbuf *m) |
1575{ | 2047{ |
1576 struct tcpcb *tp = sototcpcb(so); 1577 struct toepcb *toep = tp->t_toe; | 2048 struct tcpcb *tp; |
1578 struct ddp_state *q; 1579 struct ddp_buf_state *bsp; 1580 struct cpl_rx_data_ddp *hdr; 1581 unsigned int ddp_len, rcv_nxt, ddp_report, end_offset, buf_idx; | 2049 struct ddp_state *q; 2050 struct ddp_buf_state *bsp; 2051 struct cpl_rx_data_ddp *hdr; 2052 unsigned int ddp_len, rcv_nxt, ddp_report, end_offset, buf_idx; |
2053 struct socket *so = toeptoso(toep); 2054 int nomoredata = 0; |
|
1582 | 2055 |
1583#ifdef notyet 1584 if (unlikely(sk_no_receive(sk))) { 1585 handle_excess_rx(so, m); | 2056 tp = sototcpcb(so); 2057 2058 INP_LOCK(tp->t_inpcb); 2059 if (__predict_false(so_no_receive(so))) { 2060 2061 handle_excess_rx(toep, m); 2062 INP_UNLOCK(tp->t_inpcb); |
1586 return; 1587 } | 2063 return; 2064 } |
1588#endif 1589 tp = sototcpcb(so); | 2065 |
1590 q = &toep->tp_ddp_state; 1591 hdr = cplhdr(m); 1592 ddp_report = ntohl(hdr->u.ddp_report); 1593 buf_idx = (ddp_report >> S_DDP_BUF_IDX) & 1; 1594 bsp = &q->buf_state[buf_idx]; 1595 1596#ifdef T3_TRACE 1597 T3_TRACE5(TIDTB(sk), 1598 "new_rx_data_ddp: tp->rcv_nxt 0x%x cur_offset %u " 1599 "hdr seq 0x%x len %u offset %u", 1600 tp->rcv_nxt, bsp->cur_offset, ntohl(hdr->seq), 1601 ntohs(hdr->len), G_DDP_OFFSET(ddp_report)); 1602 T3_TRACE1(TIDTB(sk), 1603 "new_rx_data_ddp: ddp_report 0x%x", 1604 ddp_report); 1605#endif | 2066 q = &toep->tp_ddp_state; 2067 hdr = cplhdr(m); 2068 ddp_report = ntohl(hdr->u.ddp_report); 2069 buf_idx = (ddp_report >> S_DDP_BUF_IDX) & 1; 2070 bsp = &q->buf_state[buf_idx]; 2071 2072#ifdef T3_TRACE 2073 T3_TRACE5(TIDTB(sk), 2074 "new_rx_data_ddp: tp->rcv_nxt 0x%x cur_offset %u " 2075 "hdr seq 0x%x len %u offset %u", 2076 tp->rcv_nxt, bsp->cur_offset, ntohl(hdr->seq), 2077 ntohs(hdr->len), G_DDP_OFFSET(ddp_report)); 2078 T3_TRACE1(TIDTB(sk), 2079 "new_rx_data_ddp: ddp_report 0x%x", 2080 ddp_report); 2081#endif |
1606 | 2082 CTR4(KTR_TOM, 2083 "new_rx_data_ddp: tp->rcv_nxt 0x%x cur_offset %u " 2084 "hdr seq 0x%x len %u", 2085 tp->rcv_nxt, bsp->cur_offset, ntohl(hdr->seq), 2086 ntohs(hdr->len)); 2087 CTR3(KTR_TOM, 2088 "new_rx_data_ddp: offset %u ddp_report 0x%x buf_idx=%d", 2089 G_DDP_OFFSET(ddp_report), ddp_report, buf_idx); 2090 |
1607 ddp_len = ntohs(hdr->len); 1608 rcv_nxt = ntohl(hdr->seq) + ddp_len; 1609 | 2091 ddp_len = ntohs(hdr->len); 2092 rcv_nxt = ntohl(hdr->seq) + ddp_len; 2093 |
1610 /* 1611 * Overload to store old rcv_next 1612 */ 1613 m->m_pkthdr.csum_data = tp->rcv_nxt; | 2094 m->m_seq = tp->rcv_nxt; |
1614 tp->rcv_nxt = rcv_nxt; 1615 | 2095 tp->rcv_nxt = rcv_nxt; 2096 |
2097 tp->t_rcvtime = ticks; |
|
1616 /* 1617 * Store the length in m->m_len. We are changing the meaning of 1618 * m->m_len here, we need to be very careful that nothing from now on 1619 * interprets ->len of this packet the usual way. 1620 */ | 2098 /* 2099 * Store the length in m->m_len. We are changing the meaning of 2100 * m->m_len here, we need to be very careful that nothing from now on 2101 * interprets ->len of this packet the usual way. 2102 */ |
1621 m->m_len = tp->rcv_nxt - m->m_pkthdr.csum_data; 1622 | 2103 m->m_len = m->m_pkthdr.len = rcv_nxt - m->m_seq; 2104 INP_UNLOCK(tp->t_inpcb); 2105 CTR3(KTR_TOM, 2106 "new_rx_data_ddp: m_len=%u rcv_next 0x%08x rcv_nxt_prev=0x%08x ", 2107 m->m_len, rcv_nxt, m->m_seq); |
1623 /* 1624 * Figure out where the new data was placed in the buffer and store it 1625 * in when. Assumes the buffer offset starts at 0, consumer needs to 1626 * account for page pod's pg_offset. 1627 */ 1628 end_offset = G_DDP_OFFSET(ddp_report) + ddp_len; | 2108 /* 2109 * Figure out where the new data was placed in the buffer and store it 2110 * in when. Assumes the buffer offset starts at 0, consumer needs to 2111 * account for page pod's pg_offset. 2112 */ 2113 end_offset = G_DDP_OFFSET(ddp_report) + ddp_len; |
1629#ifdef notyet 1630 TCP_SKB_CB(skb)->when = end_offset - skb->len; | 2114 m->m_cur_offset = end_offset - m->m_pkthdr.len; |
1631 | 2115 |
1632 /* 1633 * We store in mac.raw the address of the gather list where the 1634 * placement happened. 1635 */ 1636 skb->mac.raw = (unsigned char *)bsp->gl; 1637#endif | 2116 SOCKBUF_LOCK(&so->so_rcv); 2117 m->m_ddp_gl = (unsigned char *)bsp->gl; 2118 m->m_flags |= M_DDP; |
1638 bsp->cur_offset = end_offset; | 2119 bsp->cur_offset = end_offset; |
2120 toep->tp_enqueued_bytes += m->m_pkthdr.len; |
|
1639 1640 /* | 2121 2122 /* |
2123 * Length is only meaningful for kbuf 2124 */ 2125 if (!(bsp->flags & DDP_BF_NOCOPY)) 2126 KASSERT(m->m_len <= bsp->gl->dgl_length, 2127 ("length received exceeds ddp pages: len=%d dgl_length=%d", 2128 m->m_len, bsp->gl->dgl_length)); 2129 2130 KASSERT(m->m_len > 0, ("%s m_len=%d", __FUNCTION__, m->m_len)); 2131 KASSERT(m->m_next == NULL, ("m_len=%p", m->m_next)); 2132 2133 2134 /* |
|
1641 * Bit 0 of flags stores whether the DDP buffer is completed. 1642 * Note that other parts of the code depend on this being in bit 0. 1643 */ 1644 if ((bsp->flags & DDP_BF_NOINVAL) && end_offset != bsp->gl->dgl_length) { | 2135 * Bit 0 of flags stores whether the DDP buffer is completed. 2136 * Note that other parts of the code depend on this being in bit 0. 2137 */ 2138 if ((bsp->flags & DDP_BF_NOINVAL) && end_offset != bsp->gl->dgl_length) { |
1645#if 0 1646 TCP_SKB_CB(skb)->flags = 0; /* potential spurious completion */ 1647#endif | |
1648 panic("spurious ddp completion"); 1649 } else { | 2139 panic("spurious ddp completion"); 2140 } else { |
1650 m->m_pkthdr.csum_flags = !!(ddp_report & F_DDP_BUF_COMPLETE); 1651 if (m->m_pkthdr.csum_flags && !(bsp->flags & DDP_BF_NOFLIP)) | 2141 m->m_ddp_flags = !!(ddp_report & F_DDP_BUF_COMPLETE); 2142 if (m->m_ddp_flags && !(bsp->flags & DDP_BF_NOFLIP)) |
1652 q->cur_buf ^= 1; /* flip buffers */ 1653 } 1654 1655 if (bsp->flags & DDP_BF_NOCOPY) { | 2143 q->cur_buf ^= 1; /* flip buffers */ 2144 } 2145 2146 if (bsp->flags & DDP_BF_NOCOPY) { |
1656 m->m_pkthdr.csum_flags |= (bsp->flags & DDP_BF_NOCOPY); | 2147 m->m_ddp_flags |= (bsp->flags & DDP_BF_NOCOPY); |
1657 bsp->flags &= ~DDP_BF_NOCOPY; 1658 } 1659 1660 if (ddp_report & F_DDP_PSH) | 2148 bsp->flags &= ~DDP_BF_NOCOPY; 2149 } 2150 2151 if (ddp_report & F_DDP_PSH) |
1661 m->m_pkthdr.csum_flags |= DDP_BF_PSH; | 2152 m->m_ddp_flags |= DDP_BF_PSH; 2153 if (nomoredata) 2154 m->m_ddp_flags |= DDP_BF_NODATA; 2155 2156 if (__predict_false(G_DDP_DACK_MODE(ddp_report) != toep->tp_delack_mode)) { 2157 toep->tp_delack_mode = G_DDP_DACK_MODE(ddp_report); 2158 toep->tp_delack_seq = tp->rcv_nxt; 2159 } 2160 2161 SBAPPEND(&so->so_rcv, m); |
1662 | 2162 |
1663 tp->t_rcvtime = ticks; 1664 sbappendstream_locked(&so->so_rcv, m); 1665#ifdef notyet 1666 if (!sock_flag(sk, SOCK_DEAD)) 1667 sk->sk_data_ready(sk, 0); 1668#endif | 2163 if ((so->so_state & SS_NOFDREF) == 0) 2164 sorwakeup_locked(so); 2165 else 2166 SOCKBUF_UNLOCK(&so->so_rcv); |
1669} 1670 1671#define DDP_ERR (F_DDP_PPOD_MISMATCH | F_DDP_LLIMIT_ERR | F_DDP_ULIMIT_ERR |\ 1672 F_DDP_PPOD_PARITY_ERR | F_DDP_PADDING_ERR | F_DDP_OFFSET_ERR |\ 1673 F_DDP_INVALID_TAG | F_DDP_COLOR_ERR | F_DDP_TID_MISMATCH |\ 1674 F_DDP_INVALID_PPOD) 1675 1676/* 1677 * Handler for RX_DATA_DDP CPL messages. 1678 */ 1679static int 1680do_rx_data_ddp(struct t3cdev *cdev, struct mbuf *m, void *ctx) 1681{ 1682 struct toepcb *toep = ctx; | 2167} 2168 2169#define DDP_ERR (F_DDP_PPOD_MISMATCH | F_DDP_LLIMIT_ERR | F_DDP_ULIMIT_ERR |\ 2170 F_DDP_PPOD_PARITY_ERR | F_DDP_PADDING_ERR | F_DDP_OFFSET_ERR |\ 2171 F_DDP_INVALID_TAG | F_DDP_COLOR_ERR | F_DDP_TID_MISMATCH |\ 2172 F_DDP_INVALID_PPOD) 2173 2174/* 2175 * Handler for RX_DATA_DDP CPL messages. 2176 */ 2177static int 2178do_rx_data_ddp(struct t3cdev *cdev, struct mbuf *m, void *ctx) 2179{ 2180 struct toepcb *toep = ctx; |
1683 struct socket *so = toeptoso(toep); | |
1684 const struct cpl_rx_data_ddp *hdr = cplhdr(m); 1685 1686 VALIDATE_SOCK(so); 1687 1688 if (__predict_false(ntohl(hdr->ddpvld_status) & DDP_ERR)) { 1689 log(LOG_ERR, "RX_DATA_DDP for TID %u reported error 0x%x\n", 1690 GET_TID(hdr), G_DDP_VALID(ntohl(hdr->ddpvld_status))); | 2181 const struct cpl_rx_data_ddp *hdr = cplhdr(m); 2182 2183 VALIDATE_SOCK(so); 2184 2185 if (__predict_false(ntohl(hdr->ddpvld_status) & DDP_ERR)) { 2186 log(LOG_ERR, "RX_DATA_DDP for TID %u reported error 0x%x\n", 2187 GET_TID(hdr), G_DDP_VALID(ntohl(hdr->ddpvld_status))); |
1691 return CPL_RET_BUF_DONE; | 2188 return (CPL_RET_BUF_DONE); |
1692 } 1693#if 0 1694 skb->h.th = tcphdr_skb->h.th; 1695#endif | 2189 } 2190#if 0 2191 skb->h.th = tcphdr_skb->h.th; 2192#endif |
1696 new_rx_data_ddp(so, m); | 2193 new_rx_data_ddp(toep, m); |
1697 return (0); 1698} 1699 1700static void | 2194 return (0); 2195} 2196 2197static void |
1701process_ddp_complete(struct socket *so, struct mbuf *m) | 2198process_ddp_complete(struct toepcb *toep, struct mbuf *m) |
1702{ | 2199{ |
1703 struct tcpcb *tp = sototcpcb(so); 1704 struct toepcb *toep = tp->t_toe; | 2200 struct tcpcb *tp = toep->tp_tp; 2201 struct socket *so = toeptoso(toep); |
1705 struct ddp_state *q; 1706 struct ddp_buf_state *bsp; 1707 struct cpl_rx_ddp_complete *hdr; 1708 unsigned int ddp_report, buf_idx, when; | 2202 struct ddp_state *q; 2203 struct ddp_buf_state *bsp; 2204 struct cpl_rx_ddp_complete *hdr; 2205 unsigned int ddp_report, buf_idx, when; |
2206 int nomoredata = 0; |
|
1709 | 2207 |
1710#ifdef notyet 1711 if (unlikely(sk_no_receive(sk))) { 1712 handle_excess_rx(sk, skb); | 2208 INP_LOCK(tp->t_inpcb); 2209 if (__predict_false(so_no_receive(so))) { 2210 struct inpcb *inp = sotoinpcb(so); 2211 2212 handle_excess_rx(toep, m); 2213 INP_UNLOCK(inp); |
1713 return; 1714 } | 2214 return; 2215 } |
1715#endif | |
1716 q = &toep->tp_ddp_state; 1717 hdr = cplhdr(m); 1718 ddp_report = ntohl(hdr->ddp_report); 1719 buf_idx = (ddp_report >> S_DDP_BUF_IDX) & 1; | 2216 q = &toep->tp_ddp_state; 2217 hdr = cplhdr(m); 2218 ddp_report = ntohl(hdr->ddp_report); 2219 buf_idx = (ddp_report >> S_DDP_BUF_IDX) & 1; |
1720 bsp = &q->buf_state[buf_idx]; | 2220 m->m_pkthdr.csum_data = tp->rcv_nxt; |
1721 | 2221 |
2222 2223 SOCKBUF_LOCK(&so->so_rcv); 2224 bsp = &q->buf_state[buf_idx]; |
|
1722 when = bsp->cur_offset; | 2225 when = bsp->cur_offset; |
1723 m->m_len = G_DDP_OFFSET(ddp_report) - when; | 2226 m->m_len = m->m_pkthdr.len = G_DDP_OFFSET(ddp_report) - when; 2227 tp->rcv_nxt += m->m_len; 2228 tp->t_rcvtime = ticks; 2229 INP_UNLOCK(tp->t_inpcb); |
1724 | 2230 |
2231 KASSERT(m->m_len > 0, ("%s m_len=%d", __FUNCTION__, m->m_len)); |
|
1725#ifdef T3_TRACE 1726 T3_TRACE5(TIDTB(sk), 1727 "process_ddp_complete: tp->rcv_nxt 0x%x cur_offset %u " 1728 "ddp_report 0x%x offset %u, len %u", 1729 tp->rcv_nxt, bsp->cur_offset, ddp_report, 1730 G_DDP_OFFSET(ddp_report), skb->len); 1731#endif | 2232#ifdef T3_TRACE 2233 T3_TRACE5(TIDTB(sk), 2234 "process_ddp_complete: tp->rcv_nxt 0x%x cur_offset %u " 2235 "ddp_report 0x%x offset %u, len %u", 2236 tp->rcv_nxt, bsp->cur_offset, ddp_report, 2237 G_DDP_OFFSET(ddp_report), skb->len); 2238#endif |
1732 | 2239 CTR5(KTR_TOM, 2240 "process_ddp_complete: tp->rcv_nxt 0x%x cur_offset %u " 2241 "ddp_report 0x%x offset %u, len %u", 2242 tp->rcv_nxt, bsp->cur_offset, ddp_report, 2243 G_DDP_OFFSET(ddp_report), m->m_len); 2244 |
1733 bsp->cur_offset += m->m_len; 1734 | 2245 bsp->cur_offset += m->m_len; 2246 |
1735 if (!(bsp->flags & DDP_BF_NOFLIP)) | 2247 if (!(bsp->flags & DDP_BF_NOFLIP)) { |
1736 q->cur_buf ^= 1; /* flip buffers */ | 2248 q->cur_buf ^= 1; /* flip buffers */ |
1737 | 2249 if (G_DDP_OFFSET(ddp_report) < q->kbuf[0]->dgl_length) 2250 nomoredata=1; 2251 } 2252 |
1738#ifdef T3_TRACE 1739 T3_TRACE4(TIDTB(sk), 1740 "process_ddp_complete: tp->rcv_nxt 0x%x cur_offset %u " 1741 "ddp_report %u offset %u", 1742 tp->rcv_nxt, bsp->cur_offset, ddp_report, 1743 G_DDP_OFFSET(ddp_report)); 1744#endif | 2253#ifdef T3_TRACE 2254 T3_TRACE4(TIDTB(sk), 2255 "process_ddp_complete: tp->rcv_nxt 0x%x cur_offset %u " 2256 "ddp_report %u offset %u", 2257 tp->rcv_nxt, bsp->cur_offset, ddp_report, 2258 G_DDP_OFFSET(ddp_report)); 2259#endif |
1745#if 0 1746 skb->mac.raw = (unsigned char *)bsp->gl; 1747#endif 1748 m->m_pkthdr.csum_flags = (bsp->flags & DDP_BF_NOCOPY) | 1; | 2260 CTR4(KTR_TOM, 2261 "process_ddp_complete: tp->rcv_nxt 0x%x cur_offset %u " 2262 "ddp_report %u offset %u", 2263 tp->rcv_nxt, bsp->cur_offset, ddp_report, 2264 G_DDP_OFFSET(ddp_report)); 2265 2266 m->m_ddp_gl = (unsigned char *)bsp->gl; 2267 m->m_flags |= M_DDP; 2268 m->m_ddp_flags = (bsp->flags & DDP_BF_NOCOPY) | 1; |
1749 if (bsp->flags & DDP_BF_NOCOPY) 1750 bsp->flags &= ~DDP_BF_NOCOPY; | 2269 if (bsp->flags & DDP_BF_NOCOPY) 2270 bsp->flags &= ~DDP_BF_NOCOPY; |
1751 m->m_pkthdr.csum_data = tp->rcv_nxt; 1752 tp->rcv_nxt += m->m_len; | 2271 if (nomoredata) 2272 m->m_ddp_flags |= DDP_BF_NODATA; |
1753 | 2273 |
1754 tp->t_rcvtime = ticks; 1755 sbappendstream_locked(&so->so_rcv, m); 1756#ifdef notyet 1757 if (!sock_flag(sk, SOCK_DEAD)) 1758 sk->sk_data_ready(sk, 0); 1759#endif | 2274 SBAPPEND(&so->so_rcv, m); 2275 2276 if ((so->so_state & SS_NOFDREF) == 0) 2277 sorwakeup_locked(so); 2278 else 2279 SOCKBUF_UNLOCK(&so->so_rcv); |
1760} 1761 1762/* 1763 * Handler for RX_DDP_COMPLETE CPL messages. 1764 */ 1765static int 1766do_rx_ddp_complete(struct t3cdev *cdev, struct mbuf *m, void *ctx) 1767{ 1768 struct toepcb *toep = ctx; | 2280} 2281 2282/* 2283 * Handler for RX_DDP_COMPLETE CPL messages. 2284 */ 2285static int 2286do_rx_ddp_complete(struct t3cdev *cdev, struct mbuf *m, void *ctx) 2287{ 2288 struct toepcb *toep = ctx; |
1769 struct socket *so = toeptoso(toep); | |
1770 1771 VALIDATE_SOCK(so); 1772#if 0 1773 skb->h.th = tcphdr_skb->h.th; 1774#endif | 2289 2290 VALIDATE_SOCK(so); 2291#if 0 2292 skb->h.th = tcphdr_skb->h.th; 2293#endif |
1775 process_ddp_complete(so, m); | 2294 process_ddp_complete(toep, m); |
1776 return (0); 1777} 1778 1779/* 1780 * Move a socket to TIME_WAIT state. We need to make some adjustments to the 1781 * socket state before calling tcp_time_wait to comply with its expectations. 1782 */ 1783static void --- 12 unchanged lines hidden (view full) --- 1796 tp->rcv_nxt++; 1797 1798 tp->ts_recent_age = 0; /* defeat recycling */ 1799 tp->t_srtt = 0; /* defeat tcp_update_metrics */ 1800 tcp_twstart(tp); 1801} 1802 1803/* | 2295 return (0); 2296} 2297 2298/* 2299 * Move a socket to TIME_WAIT state. We need to make some adjustments to the 2300 * socket state before calling tcp_time_wait to comply with its expectations. 2301 */ 2302static void --- 12 unchanged lines hidden (view full) --- 2315 tp->rcv_nxt++; 2316 2317 tp->ts_recent_age = 0; /* defeat recycling */ 2318 tp->t_srtt = 0; /* defeat tcp_update_metrics */ 2319 tcp_twstart(tp); 2320} 2321 2322/* |
2323 * For TCP DDP a PEER_CLOSE may also be an implicit RX_DDP_COMPLETE. This 2324 * function deals with the data that may be reported along with the FIN. 2325 * Returns -1 if no further processing of the PEER_CLOSE is needed, >= 0 to 2326 * perform normal FIN-related processing. In the latter case 1 indicates that 2327 * there was an implicit RX_DDP_COMPLETE and the skb should not be freed, 0 the 2328 * skb can be freed. 2329 */ 2330static int 2331handle_peer_close_data(struct socket *so, struct mbuf *m) 2332{ 2333 struct tcpcb *tp = sototcpcb(so); 2334 struct toepcb *toep = tp->t_toe; 2335 struct ddp_state *q; 2336 struct ddp_buf_state *bsp; 2337 struct cpl_peer_close *req = cplhdr(m); 2338 unsigned int rcv_nxt = ntohl(req->rcv_nxt) - 1; /* exclude FIN */ 2339 2340 if (tp->rcv_nxt == rcv_nxt) /* no data */ 2341 return (0); 2342 2343 if (__predict_false(so_no_receive(so))) { 2344 handle_excess_rx(toep, m); 2345 2346 /* 2347 * Although we discard the data we want to process the FIN so 2348 * that PEER_CLOSE + data behaves the same as RX_DATA_DDP + 2349 * PEER_CLOSE without data. In particular this PEER_CLOSE 2350 * may be what will close the connection. We return 1 because 2351 * handle_excess_rx() already freed the packet. 2352 */ 2353 return (1); 2354 } 2355 2356 INP_LOCK_ASSERT(tp->t_inpcb); 2357 q = &toep->tp_ddp_state; 2358 SOCKBUF_LOCK(&so->so_rcv); 2359 bsp = &q->buf_state[q->cur_buf]; 2360 m->m_len = m->m_pkthdr.len = rcv_nxt - tp->rcv_nxt; 2361 KASSERT(m->m_len > 0, ("%s m_len=%d", __FUNCTION__, m->m_len)); 2362 m->m_ddp_gl = (unsigned char *)bsp->gl; 2363 m->m_flags |= M_DDP; 2364 m->m_cur_offset = bsp->cur_offset; 2365 m->m_ddp_flags = 2366 DDP_BF_PSH | (bsp->flags & DDP_BF_NOCOPY) | 1; 2367 m->m_seq = tp->rcv_nxt; 2368 tp->rcv_nxt = rcv_nxt; 2369 bsp->cur_offset += m->m_pkthdr.len; 2370 if (!(bsp->flags & DDP_BF_NOFLIP)) 2371 q->cur_buf ^= 1; 2372 tp->t_rcvtime = ticks; 2373 SBAPPEND(&so->so_rcv, m); 2374 if (__predict_true((so->so_state & SS_NOFDREF) == 0)) 2375 sorwakeup_locked(so); 2376 else 2377 SOCKBUF_UNLOCK(&so->so_rcv); 2378 return (1); 2379} 2380 2381/* |
|
1804 * Handle a peer FIN. 1805 */ 1806static void 1807do_peer_fin(struct socket *so, struct mbuf *m) 1808{ 1809 struct tcpcb *tp = sototcpcb(so); 1810 struct toepcb *toep = tp->t_toe; | 2382 * Handle a peer FIN. 2383 */ 2384static void 2385do_peer_fin(struct socket *so, struct mbuf *m) 2386{ 2387 struct tcpcb *tp = sototcpcb(so); 2388 struct toepcb *toep = tp->t_toe; |
1811 int keep = 0, dead = (so->so_state & SS_NOFDREF); 1812 1813 DPRINTF("do_peer_fin state=%d dead=%d\n", tp->t_state, !!dead); | 2389 int keep = 0; 2390 DPRINTF("do_peer_fin state=%d\n", tp->t_state); |
1814 1815#ifdef T3_TRACE 1816 T3_TRACE0(TIDTB(sk),"do_peer_fin:"); 1817#endif 1818 1819 if (!is_t3a(TOE_DEV(so)) && (toep->tp_flags & TP_ABORT_RPL_PENDING)) { 1820 printf("abort_pending set\n"); 1821 1822 goto out; 1823 } | 2391 2392#ifdef T3_TRACE 2393 T3_TRACE0(TIDTB(sk),"do_peer_fin:"); 2394#endif 2395 2396 if (!is_t3a(TOE_DEV(so)) && (toep->tp_flags & TP_ABORT_RPL_PENDING)) { 2397 printf("abort_pending set\n"); 2398 2399 goto out; 2400 } |
1824 1825#ifdef notyet 1826 if (ULP_MODE(tp) == ULP_MODE_TCPDDP) { 1827 keep = handle_peer_close_data(so, skb); 1828 if (keep < 0) 1829 return; 1830 } 1831 sk->sk_shutdown |= RCV_SHUTDOWN; 1832 sock_set_flag(so, SOCK_DONE); 1833#endif | |
1834 INP_INFO_WLOCK(&tcbinfo); 1835 INP_LOCK(tp->t_inpcb); | 2401 INP_INFO_WLOCK(&tcbinfo); 2402 INP_LOCK(tp->t_inpcb); |
1836 if (TCPS_HAVERCVDFIN(tp->t_state) == 0) | 2403 if (toep->tp_ulp_mode == ULP_MODE_TCPDDP) { 2404 keep = handle_peer_close_data(so, m); 2405 if (keep < 0) { 2406 INP_INFO_WUNLOCK(&tcbinfo); 2407 INP_UNLOCK(tp->t_inpcb); 2408 return; 2409 } 2410 } 2411 if (TCPS_HAVERCVDFIN(tp->t_state) == 0) { |
1837 socantrcvmore(so); | 2412 socantrcvmore(so); |
2413 /* 2414 * If connection is half-synchronized 2415 * (ie NEEDSYN flag on) then delay ACK, 2416 * so it may be piggybacked when SYN is sent. 2417 * Otherwise, since we received a FIN then no 2418 * more input can be expected, send ACK now. 2419 */ 2420 if (tp->t_flags & TF_NEEDSYN) 2421 tp->t_flags |= TF_DELACK; 2422 else 2423 tp->t_flags |= TF_ACKNOW; 2424 tp->rcv_nxt++; 2425 } 2426 |
|
1838 switch (tp->t_state) { 1839 case TCPS_SYN_RECEIVED: 1840 tp->t_starttime = ticks; 1841 /* FALLTHROUGH */ 1842 case TCPS_ESTABLISHED: 1843 tp->t_state = TCPS_CLOSE_WAIT; 1844 break; 1845 case TCPS_FIN_WAIT_1: --- 7 unchanged lines hidden (view full) --- 1853 * be treated as an abort_rpl, i.e., transition the connection 1854 * to TCP_CLOSE (note that the host stack does this at the 1855 * time of generating the RST but we must wait for HW). 1856 * Otherwise we enter TIME_WAIT. 1857 */ 1858 t3_release_offload_resources(toep); 1859 if (toep->tp_flags & TP_ABORT_RPL_PENDING) { 1860 tp = tcp_close(tp); | 2427 switch (tp->t_state) { 2428 case TCPS_SYN_RECEIVED: 2429 tp->t_starttime = ticks; 2430 /* FALLTHROUGH */ 2431 case TCPS_ESTABLISHED: 2432 tp->t_state = TCPS_CLOSE_WAIT; 2433 break; 2434 case TCPS_FIN_WAIT_1: --- 7 unchanged lines hidden (view full) --- 2442 * be treated as an abort_rpl, i.e., transition the connection 2443 * to TCP_CLOSE (note that the host stack does this at the 2444 * time of generating the RST but we must wait for HW). 2445 * Otherwise we enter TIME_WAIT. 2446 */ 2447 t3_release_offload_resources(toep); 2448 if (toep->tp_flags & TP_ABORT_RPL_PENDING) { 2449 tp = tcp_close(tp); |
1861 } else | 2450 } else { |
1862 enter_timewait(so); | 2451 enter_timewait(so); |
2452 } |
|
1863 break; 1864 default: 1865 log(LOG_ERR, 1866 "%s: TID %u received PEER_CLOSE in bad state %d\n", 1867 TOE_DEV(so)->tod_name, toep->tp_tid, tp->t_state); 1868 } 1869 INP_INFO_WUNLOCK(&tcbinfo); 1870 if (tp) 1871 INP_UNLOCK(tp->t_inpcb); 1872 | 2453 break; 2454 default: 2455 log(LOG_ERR, 2456 "%s: TID %u received PEER_CLOSE in bad state %d\n", 2457 TOE_DEV(so)->tod_name, toep->tp_tid, tp->t_state); 2458 } 2459 INP_INFO_WUNLOCK(&tcbinfo); 2460 if (tp) 2461 INP_UNLOCK(tp->t_inpcb); 2462 |
1873 if (!dead) { 1874 DPRINTF("waking up waiters on %p rcv_notify=%d flags=0x%x\n", so, sb_notify(&so->so_rcv), so->so_rcv.sb_flags); 1875 1876 sorwakeup(so); 1877 sowwakeup(so); 1878 wakeup(&so->so_timeo); 1879#ifdef notyet 1880 sk->sk_state_change(sk); | 2463 DPRINTF("waking up waiters on %p rcv_notify=%d flags=0x%x\n", so, sb_notify(&so->so_rcv), so->so_rcv.sb_flags); |
1881 | 2464 |
1882 /* Do not send POLL_HUP for half duplex close. */ 1883 if ((sk->sk_shutdown & SEND_SHUTDOWN) || 1884 sk->sk_state == TCP_CLOSE) 1885 sk_wake_async(so, 1, POLL_HUP); 1886 else 1887 sk_wake_async(so, 1, POLL_IN); | 2465#ifdef notyet 2466 /* Do not send POLL_HUP for half duplex close. */ 2467 if ((sk->sk_shutdown & SEND_SHUTDOWN) || 2468 sk->sk_state == TCP_CLOSE) 2469 sk_wake_async(so, 1, POLL_HUP); 2470 else 2471 sk_wake_async(so, 1, POLL_IN); |
1888#endif | 2472#endif |
1889 } | 2473 |
1890out: 1891 if (!keep) 1892 m_free(m); 1893} 1894 1895/* 1896 * Handler for PEER_CLOSE CPL messages. 1897 */ --- 26 unchanged lines hidden (view full) --- 1924 INP_INFO_WLOCK(&tcbinfo); 1925 INP_LOCK(tp->t_inpcb); 1926 switch (tp->t_state) { 1927 case TCPS_CLOSING: /* see FIN_WAIT2 case in do_peer_fin */ 1928 t3_release_offload_resources(toep); 1929 if (toep->tp_flags & TP_ABORT_RPL_PENDING) { 1930 tp = tcp_close(tp); 1931 | 2474out: 2475 if (!keep) 2476 m_free(m); 2477} 2478 2479/* 2480 * Handler for PEER_CLOSE CPL messages. 2481 */ --- 26 unchanged lines hidden (view full) --- 2508 INP_INFO_WLOCK(&tcbinfo); 2509 INP_LOCK(tp->t_inpcb); 2510 switch (tp->t_state) { 2511 case TCPS_CLOSING: /* see FIN_WAIT2 case in do_peer_fin */ 2512 t3_release_offload_resources(toep); 2513 if (toep->tp_flags & TP_ABORT_RPL_PENDING) { 2514 tp = tcp_close(tp); 2515 |
1932 } else | 2516 } else { |
1933 enter_timewait(so); | 2517 enter_timewait(so); |
2518 soisdisconnected(so); 2519 } |
|
1934 break; 1935 case TCPS_LAST_ACK: 1936 /* 1937 * In this state we don't care about pending abort_rpl. 1938 * If we've sent abort_req it was post-close and was sent too 1939 * late, this close_con_rpl is the actual last message. 1940 */ 1941 t3_release_offload_resources(toep); 1942 tp = tcp_close(tp); 1943 break; 1944 case TCPS_FIN_WAIT_1: | 2520 break; 2521 case TCPS_LAST_ACK: 2522 /* 2523 * In this state we don't care about pending abort_rpl. 2524 * If we've sent abort_req it was post-close and was sent too 2525 * late, this close_con_rpl is the actual last message. 2526 */ 2527 t3_release_offload_resources(toep); 2528 tp = tcp_close(tp); 2529 break; 2530 case TCPS_FIN_WAIT_1: |
1945#ifdef notyet 1946 dst_confirm(sk->sk_dst_cache); 1947#endif 1948 soisdisconnecting(so); 1949 1950 if ((so->so_state & SS_NOFDREF) == 0) { 1951 /* 1952 * Wake up lingering close 1953 */ 1954 sowwakeup(so); 1955 sorwakeup(so); 1956 wakeup(&so->so_timeo); 1957 } else if ((so->so_options & SO_LINGER) && so->so_linger == 0 && | 2531 /* 2532 * If we can't receive any more 2533 * data, then closing user can proceed. 2534 * Starting the timer is contrary to the 2535 * specification, but if we don't get a FIN 2536 * we'll hang forever. 2537 * 2538 * XXXjl: 2539 * we should release the tp also, and use a 2540 * compressed state. 2541 */ 2542 if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { 2543 int timeout; 2544 2545 soisdisconnected(so); 2546 timeout = (tcp_fast_finwait2_recycle) ? 2547 tcp_finwait2_timeout : tcp_maxidle; 2548 tcp_timer_activate(tp, TT_2MSL, timeout); 2549 } 2550 tp->t_state = TCPS_FIN_WAIT_2; 2551 if ((so->so_options & SO_LINGER) && so->so_linger == 0 && |
1958 (toep->tp_flags & TP_ABORT_SHUTDOWN) == 0) { | 2552 (toep->tp_flags & TP_ABORT_SHUTDOWN) == 0) { |
1959 tp = cxgb_tcp_drop(tp, 0); | 2553 tp = tcp_drop(tp, 0); |
1960 } 1961 1962 break; 1963 default: 1964 log(LOG_ERR, 1965 "%s: TID %u received CLOSE_CON_RPL in bad state %d\n", 1966 TOE_DEV(so)->tod_name, toep->tp_tid, 1967 tp->t_state); 1968 } 1969 INP_INFO_WUNLOCK(&tcbinfo); 1970 if (tp) 1971 INP_UNLOCK(tp->t_inpcb); 1972out: | 2554 } 2555 2556 break; 2557 default: 2558 log(LOG_ERR, 2559 "%s: TID %u received CLOSE_CON_RPL in bad state %d\n", 2560 TOE_DEV(so)->tod_name, toep->tp_tid, 2561 tp->t_state); 2562 } 2563 INP_INFO_WUNLOCK(&tcbinfo); 2564 if (tp) 2565 INP_UNLOCK(tp->t_inpcb); 2566out: |
1973 m_free(m); | 2567 m_freem(m); |
1974} 1975 1976/* 1977 * Handler for CLOSE_CON_RPL CPL messages. 1978 */ 1979static int 1980do_close_con_rpl(struct t3cdev *cdev, struct mbuf *m, 1981 void *ctx) --- 19 unchanged lines hidden (view full) --- 2001 struct tcpcb *tp = sototcpcb(so); 2002 struct toepcb *toep = tp->t_toe; 2003 2004#ifdef T3_TRACE 2005 T3_TRACE1(TIDTB(sk), 2006 "process_abort_rpl: GTS rpl pending %d", 2007 sock_flag(sk, ABORT_RPL_PENDING)); 2008#endif | 2568} 2569 2570/* 2571 * Handler for CLOSE_CON_RPL CPL messages. 2572 */ 2573static int 2574do_close_con_rpl(struct t3cdev *cdev, struct mbuf *m, 2575 void *ctx) --- 19 unchanged lines hidden (view full) --- 2595 struct tcpcb *tp = sototcpcb(so); 2596 struct toepcb *toep = tp->t_toe; 2597 2598#ifdef T3_TRACE 2599 T3_TRACE1(TIDTB(sk), 2600 "process_abort_rpl: GTS rpl pending %d", 2601 sock_flag(sk, ABORT_RPL_PENDING)); 2602#endif |
2603 2604 INP_INFO_WLOCK(&tcbinfo); |
|
2009 INP_LOCK(tp->t_inpcb); 2010 2011 if (toep->tp_flags & TP_ABORT_RPL_PENDING) { 2012 /* 2013 * XXX panic on tcpdrop 2014 */ 2015 if (!(toep->tp_flags & TP_ABORT_RPL_RCVD) && !is_t3a(TOE_DEV(so))) 2016 toep->tp_flags |= TP_ABORT_RPL_RCVD; 2017 else { 2018 toep->tp_flags &= ~(TP_ABORT_RPL_RCVD|TP_ABORT_RPL_PENDING); 2019 if (!(toep->tp_flags & TP_ABORT_REQ_RCVD) || 2020 !is_t3a(TOE_DEV(so))) { 2021 if (toep->tp_flags & TP_ABORT_REQ_RCVD) 2022 panic("TP_ABORT_REQ_RCVD set"); | 2605 INP_LOCK(tp->t_inpcb); 2606 2607 if (toep->tp_flags & TP_ABORT_RPL_PENDING) { 2608 /* 2609 * XXX panic on tcpdrop 2610 */ 2611 if (!(toep->tp_flags & TP_ABORT_RPL_RCVD) && !is_t3a(TOE_DEV(so))) 2612 toep->tp_flags |= TP_ABORT_RPL_RCVD; 2613 else { 2614 toep->tp_flags &= ~(TP_ABORT_RPL_RCVD|TP_ABORT_RPL_PENDING); 2615 if (!(toep->tp_flags & TP_ABORT_REQ_RCVD) || 2616 !is_t3a(TOE_DEV(so))) { 2617 if (toep->tp_flags & TP_ABORT_REQ_RCVD) 2618 panic("TP_ABORT_REQ_RCVD set"); |
2023 INP_INFO_WLOCK(&tcbinfo); 2024 INP_LOCK(tp->t_inpcb); | |
2025 t3_release_offload_resources(toep); 2026 tp = tcp_close(tp); | 2619 t3_release_offload_resources(toep); 2620 tp = tcp_close(tp); |
2027 INP_INFO_WUNLOCK(&tcbinfo); | |
2028 } 2029 } 2030 } 2031 if (tp) 2032 INP_UNLOCK(tp->t_inpcb); | 2621 } 2622 } 2623 } 2624 if (tp) 2625 INP_UNLOCK(tp->t_inpcb); |
2626 INP_INFO_WUNLOCK(&tcbinfo); |
|
2033 2034 m_free(m); 2035} 2036 2037/* 2038 * Handle an ABORT_RPL_RSS CPL message. 2039 */ 2040static int --- 43 unchanged lines hidden (view full) --- 2084 so = toeptoso(toep); /* <- XXX panic */ 2085 toepcb_hold(toep); 2086 process_abort_rpl(so, m); 2087 toepcb_release(toep); 2088 return (0); 2089} 2090 2091/* | 2627 2628 m_free(m); 2629} 2630 2631/* 2632 * Handle an ABORT_RPL_RSS CPL message. 2633 */ 2634static int --- 43 unchanged lines hidden (view full) --- 2678 so = toeptoso(toep); /* <- XXX panic */ 2679 toepcb_hold(toep); 2680 process_abort_rpl(so, m); 2681 toepcb_release(toep); 2682 return (0); 2683} 2684 2685/* |
2092 * Convert the status code of an ABORT_REQ into a Linux error code. Also | 2686 * Convert the status code of an ABORT_REQ into a FreeBSD error code. Also |
2093 * indicate whether RST should be sent in response. 2094 */ 2095static int 2096abort_status_to_errno(struct socket *so, int abort_reason, int *need_rst) 2097{ 2098 struct tcpcb *tp = sototcpcb(so); 2099 2100 switch (abort_reason) { --- 183 unchanged lines hidden (view full) --- 2284 * be ignored and the connection should be closed now. 2285 * c) We have sent a regular abort_req that will get to TP too late. 2286 * That will generate an abort_rpl with status 0, wait for it. 2287 */ 2288 if (((toep->tp_flags & TP_ABORT_RPL_PENDING) == 0) || 2289 (is_t3a(TOE_DEV(so)) && (toep->tp_flags & TP_CLOSE_CON_REQUESTED))) { 2290 so->so_error = abort_status_to_errno(so, req->status, 2291 &rst_status); | 2687 * indicate whether RST should be sent in response. 2688 */ 2689static int 2690abort_status_to_errno(struct socket *so, int abort_reason, int *need_rst) 2691{ 2692 struct tcpcb *tp = sototcpcb(so); 2693 2694 switch (abort_reason) { --- 183 unchanged lines hidden (view full) --- 2878 * be ignored and the connection should be closed now. 2879 * c) We have sent a regular abort_req that will get to TP too late. 2880 * That will generate an abort_rpl with status 0, wait for it. 2881 */ 2882 if (((toep->tp_flags & TP_ABORT_RPL_PENDING) == 0) || 2883 (is_t3a(TOE_DEV(so)) && (toep->tp_flags & TP_CLOSE_CON_REQUESTED))) { 2884 so->so_error = abort_status_to_errno(so, req->status, 2885 &rst_status); |
2292#if 0 2293 if (!sock_flag(sk, SOCK_DEAD)) 2294 sk->sk_error_report(sk); 2295#endif | 2886 if (__predict_true((so->so_state & SS_NOFDREF) == 0)) 2887 sorwakeup(so); |
2296 /* 2297 * SYN_RECV needs special processing. If abort_syn_rcv() 2298 * returns 0 is has taken care of the abort. 2299 */ 2300 if ((tp->t_state == TCPS_SYN_RECEIVED) && !abort_syn_rcv(so, m)) 2301 goto skip; 2302 2303 t3_release_offload_resources(toep); --- 204 unchanged lines hidden (view full) --- 2508static void 2509syncache_add_accept_req(struct cpl_pass_accept_req *req, struct socket *lso, struct toepcb *toep) 2510{ 2511 struct in_conninfo inc; 2512 struct tcpopt to; 2513 struct tcphdr th; 2514 struct inpcb *inp; 2515 int mss, wsf, sack, ts; | 2888 /* 2889 * SYN_RECV needs special processing. If abort_syn_rcv() 2890 * returns 0 is has taken care of the abort. 2891 */ 2892 if ((tp->t_state == TCPS_SYN_RECEIVED) && !abort_syn_rcv(so, m)) 2893 goto skip; 2894 2895 t3_release_offload_resources(toep); --- 204 unchanged lines hidden (view full) --- 3100static void 3101syncache_add_accept_req(struct cpl_pass_accept_req *req, struct socket *lso, struct toepcb *toep) 3102{ 3103 struct in_conninfo inc; 3104 struct tcpopt to; 3105 struct tcphdr th; 3106 struct inpcb *inp; 3107 int mss, wsf, sack, ts; |
2516 | 3108 uint32_t rcv_isn = ntohl(req->rcv_isn); 3109 |
2517 bzero(&to, sizeof(struct tcpopt)); 2518 inp = sotoinpcb(lso); 2519 2520 /* 2521 * Fill out information for entering us into the syncache 2522 */ 2523 inc.inc_fport = th.th_sport = req->peer_port; 2524 inc.inc_lport = th.th_dport = req->local_port; | 3110 bzero(&to, sizeof(struct tcpopt)); 3111 inp = sotoinpcb(lso); 3112 3113 /* 3114 * Fill out information for entering us into the syncache 3115 */ 3116 inc.inc_fport = th.th_sport = req->peer_port; 3117 inc.inc_lport = th.th_dport = req->local_port; |
2525 toep->tp_iss = th.th_seq = req->rcv_isn; | 3118 th.th_seq = req->rcv_isn; |
2526 th.th_flags = TH_SYN; 2527 | 3119 th.th_flags = TH_SYN; 3120 |
2528 toep->tp_delack_seq = toep->tp_rcv_wup = toep->tp_copied_seq = ntohl(req->rcv_isn); | 3121 toep->tp_iss = toep->tp_delack_seq = toep->tp_rcv_wup = toep->tp_copied_seq = rcv_isn + 1; 3122 |
2529 2530 inc.inc_isipv6 = 0; 2531 inc.inc_len = 0; 2532 inc.inc_faddr.s_addr = req->peer_ip; 2533 inc.inc_laddr.s_addr = req->local_ip; 2534 2535 DPRINTF("syncache add of %d:%d %d:%d\n", 2536 ntohl(req->local_ip), ntohs(req->local_port), 2537 ntohl(req->peer_ip), ntohs(req->peer_port)); 2538 2539 mss = req->tcp_options.mss; 2540 wsf = req->tcp_options.wsf; 2541 ts = req->tcp_options.tstamp; 2542 sack = req->tcp_options.sack; 2543 to.to_mss = mss; 2544 to.to_wscale = wsf; 2545 to.to_flags = (mss ? TOF_MSS : 0) | (wsf ? TOF_SCALE : 0) | (ts ? TOF_TS : 0) | (sack ? TOF_SACKPERM : 0); | 3123 3124 inc.inc_isipv6 = 0; 3125 inc.inc_len = 0; 3126 inc.inc_faddr.s_addr = req->peer_ip; 3127 inc.inc_laddr.s_addr = req->local_ip; 3128 3129 DPRINTF("syncache add of %d:%d %d:%d\n", 3130 ntohl(req->local_ip), ntohs(req->local_port), 3131 ntohl(req->peer_ip), ntohs(req->peer_port)); 3132 3133 mss = req->tcp_options.mss; 3134 wsf = req->tcp_options.wsf; 3135 ts = req->tcp_options.tstamp; 3136 sack = req->tcp_options.sack; 3137 to.to_mss = mss; 3138 to.to_wscale = wsf; 3139 to.to_flags = (mss ? TOF_MSS : 0) | (wsf ? TOF_SCALE : 0) | (ts ? TOF_TS : 0) | (sack ? TOF_SACKPERM : 0); |
2546 | |
2547 INP_INFO_WLOCK(&tcbinfo); 2548 INP_LOCK(inp); 2549 syncache_offload_add(&inc, &to, &th, inp, &lso, &cxgb_toe_usrreqs, toep); 2550} 2551 2552 2553/* 2554 * Process a CPL_PASS_ACCEPT_REQ message. Does the part that needs the socket --- 94 unchanged lines hidden (view full) --- 2649 } 2650 /* 2651 * Point to our listen socket until accept 2652 */ 2653 newtoep->tp_tp = tp; 2654 newtoep->tp_flags = TP_SYN_RCVD; 2655 newtoep->tp_tid = tid; 2656 newtoep->tp_toedev = tdev; | 3140 INP_INFO_WLOCK(&tcbinfo); 3141 INP_LOCK(inp); 3142 syncache_offload_add(&inc, &to, &th, inp, &lso, &cxgb_toe_usrreqs, toep); 3143} 3144 3145 3146/* 3147 * Process a CPL_PASS_ACCEPT_REQ message. Does the part that needs the socket --- 94 unchanged lines hidden (view full) --- 3242 } 3243 /* 3244 * Point to our listen socket until accept 3245 */ 3246 newtoep->tp_tp = tp; 3247 newtoep->tp_flags = TP_SYN_RCVD; 3248 newtoep->tp_tid = tid; 3249 newtoep->tp_toedev = tdev; |
3250 tp->rcv_wnd = select_rcv_wnd(tdev, so); |
|
2657 | 3251 |
2658 printf("inserting tid=%d\n", tid); | |
2659 cxgb_insert_tid(cdev, d->client, newtoep, tid); 2660 SOCK_LOCK(so); 2661 LIST_INSERT_HEAD(&lctx->synq_head, newtoep, synq_entry); 2662 SOCK_UNLOCK(so); 2663 | 3252 cxgb_insert_tid(cdev, d->client, newtoep, tid); 3253 SOCK_LOCK(so); 3254 LIST_INSERT_HEAD(&lctx->synq_head, newtoep, synq_entry); 3255 SOCK_UNLOCK(so); 3256 |
2664 2665 if (lctx->ulp_mode) { | 3257 newtoep->tp_ulp_mode = TOM_TUNABLE(tdev, ddp) && !(so->so_options & SO_NO_DDP) && 3258 tp->rcv_wnd >= MIN_DDP_RCV_WIN ? ULP_MODE_TCPDDP : 0; 3259 3260 if (newtoep->tp_ulp_mode) { |
2666 ddp_mbuf = m_gethdr(M_NOWAIT, MT_DATA); 2667 | 3261 ddp_mbuf = m_gethdr(M_NOWAIT, MT_DATA); 3262 |
2668 if (!ddp_mbuf) | 3263 if (ddp_mbuf == NULL) |
2669 newtoep->tp_ulp_mode = 0; | 3264 newtoep->tp_ulp_mode = 0; |
2670 else 2671 newtoep->tp_ulp_mode = lctx->ulp_mode; | |
2672 } | 3265 } |
2673 | 3266 3267 CTR4(KTR_TOM, "ddp=%d rcv_wnd=%ld min_win=%d ulp_mode=%d", 3268 TOM_TUNABLE(tdev, ddp), tp->rcv_wnd, MIN_DDP_RCV_WIN, newtoep->tp_ulp_mode); |
2674 set_arp_failure_handler(reply_mbuf, pass_accept_rpl_arp_failure); | 3269 set_arp_failure_handler(reply_mbuf, pass_accept_rpl_arp_failure); |
2675 2676 DPRINTF("adding request to syn cache\n"); 2677 | |
2678 /* 2679 * XXX workaround for lack of syncache drop 2680 */ 2681 toepcb_hold(newtoep); 2682 syncache_add_accept_req(req, so, newtoep); | 3270 /* 3271 * XXX workaround for lack of syncache drop 3272 */ 3273 toepcb_hold(newtoep); 3274 syncache_add_accept_req(req, so, newtoep); |
2683 | |
2684 | 3275 |
2685 | |
2686 rpl = cplhdr(reply_mbuf); 2687 reply_mbuf->m_pkthdr.len = reply_mbuf->m_len = sizeof(*rpl); 2688 rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); 2689 rpl->wr.wr_lo = 0; 2690 OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_RPL, tid)); 2691 rpl->opt2 = htonl(calc_opt2(so, tdev)); 2692 rpl->rsvd = rpl->opt2; /* workaround for HW bug */ 2693 rpl->peer_ip = req->peer_ip; // req->peer_ip is not overwritten 2694 | 3276 rpl = cplhdr(reply_mbuf); 3277 reply_mbuf->m_pkthdr.len = reply_mbuf->m_len = sizeof(*rpl); 3278 rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); 3279 rpl->wr.wr_lo = 0; 3280 OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_RPL, tid)); 3281 rpl->opt2 = htonl(calc_opt2(so, tdev)); 3282 rpl->rsvd = rpl->opt2; /* workaround for HW bug */ 3283 rpl->peer_ip = req->peer_ip; // req->peer_ip is not overwritten 3284 |
2695 DPRINTF("accept smt_idx=%d\n", e->smt_idx); 2696 | |
2697 rpl->opt0h = htonl(calc_opt0h(so, select_mss(td, NULL, dst->rt_ifp->if_mtu)) | 2698 V_L2T_IDX(e->idx) | V_TX_CHANNEL(e->smt_idx)); | 3285 rpl->opt0h = htonl(calc_opt0h(so, select_mss(td, NULL, dst->rt_ifp->if_mtu)) | 3286 V_L2T_IDX(e->idx) | V_TX_CHANNEL(e->smt_idx)); |
2699 rpl->opt0l_status = htonl(calc_opt0l(so, lctx->ulp_mode) | | 3287 rpl->opt0l_status = htonl(calc_opt0l(so, newtoep->tp_ulp_mode) | |
2700 CPL_PASS_OPEN_ACCEPT); 2701 2702 DPRINTF("opt0l_status=%08x\n", rpl->opt0l_status); 2703 | 3288 CPL_PASS_OPEN_ACCEPT); 3289 3290 DPRINTF("opt0l_status=%08x\n", rpl->opt0l_status); 3291 |
2704 m_set_priority(reply_mbuf, mkprio(CPL_PRIORITY_SETUP, so)); 2705 2706#ifdef DEBUG_PRINT 2707 { 2708 int i; 2709 2710 DPRINTF("rpl:\n"); 2711 uint32_t *rplbuf = mtod(reply_mbuf, uint32_t *); | 3292 m_set_priority(reply_mbuf, mkprio(CPL_PRIORITY_SETUP, newtoep)); |
2712 | 3293 |
2713 for (i = 0; i < sizeof(*rpl)/sizeof(uint32_t); i++) 2714 DPRINTF("[%d] %08x\n", i, rplbuf[i]); 2715 } 2716#endif 2717 2718 | |
2719 l2t_send(cdev, reply_mbuf, e); 2720 m_free(m); | 3294 l2t_send(cdev, reply_mbuf, e); 3295 m_free(m); |
2721#ifdef notyet 2722 /* 2723 * XXX this call path has to be converted to not depend on sockets 2724 */ 2725 if (newtoep->tp_ulp_mode) 2726 __set_tcb_field(newso, ddp_mbuf, W_TCB_RX_DDP_FLAGS, | 3296 if (newtoep->tp_ulp_mode) { 3297 __set_tcb_field(newtoep, ddp_mbuf, W_TCB_RX_DDP_FLAGS, |
2727 V_TF_DDP_OFF(1) | 2728 TP_DDP_TIMER_WORKAROUND_MASK, 2729 V_TF_DDP_OFF(1) | | 3298 V_TF_DDP_OFF(1) | 3299 TP_DDP_TIMER_WORKAROUND_MASK, 3300 V_TF_DDP_OFF(1) | |
2730 TP_DDP_TIMER_WORKAROUND_VAL, 1); | 3301 TP_DDP_TIMER_WORKAROUND_VAL, 1); 3302 } else 3303 printf("not offloading\n"); 3304 3305 |
2731 | 3306 |
2732#endif | |
2733 return; 2734reject: 2735 if (tdev->tod_ttid == TOE_ID_CHELSIO_T3) 2736 mk_pass_accept_rpl(reply_mbuf, m); 2737 else | 3307 return; 3308reject: 3309 if (tdev->tod_ttid == TOE_ID_CHELSIO_T3) 3310 mk_pass_accept_rpl(reply_mbuf, m); 3311 else |
2738 mk_tid_release(reply_mbuf, NULL, tid); | 3312 mk_tid_release(reply_mbuf, newtoep, tid); |
2739 cxgb_ofld_send(cdev, reply_mbuf); 2740 m_free(m); 2741out: 2742#if 0 2743 TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS); 2744#else 2745 return; 2746#endif --- 41 unchanged lines hidden (view full) --- 2788#endif 2789 2790 process_pass_accept_req(lso, m, &d->tdev, listen_ctx); 2791 return (0); 2792} 2793 2794/* 2795 * Called when a connection is established to translate the TCP options | 3313 cxgb_ofld_send(cdev, reply_mbuf); 3314 m_free(m); 3315out: 3316#if 0 3317 TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS); 3318#else 3319 return; 3320#endif --- 41 unchanged lines hidden (view full) --- 3362#endif 3363 3364 process_pass_accept_req(lso, m, &d->tdev, listen_ctx); 3365 return (0); 3366} 3367 3368/* 3369 * Called when a connection is established to translate the TCP options |
2796 * reported by HW to Linux's native format. | 3370 * reported by HW to FreeBSD's native format. |
2797 */ 2798static void 2799assign_rxopt(struct socket *so, unsigned int opt) 2800{ 2801 const struct t3c_data *td = T3C_DATA(T3C_DEV(so)); 2802 struct tcpcb *tp = sototcpcb(so); 2803 struct toepcb *toep = tp->t_toe; 2804 2805 INP_LOCK_ASSERT(tp->t_inpcb); 2806 2807 toep->tp_mss_clamp = td->mtus[G_TCPOPT_MSS(opt)] - 40; 2808 tp->t_flags |= G_TCPOPT_TSTAMP(opt) ? TF_RCVD_TSTMP : 0; 2809 tp->t_flags |= G_TCPOPT_SACK(opt) ? TF_SACK_PERMIT : 0; 2810 tp->t_flags |= G_TCPOPT_WSCALE_OK(opt) ? TF_RCVD_SCALE : 0; | 3371 */ 3372static void 3373assign_rxopt(struct socket *so, unsigned int opt) 3374{ 3375 const struct t3c_data *td = T3C_DATA(T3C_DEV(so)); 3376 struct tcpcb *tp = sototcpcb(so); 3377 struct toepcb *toep = tp->t_toe; 3378 3379 INP_LOCK_ASSERT(tp->t_inpcb); 3380 3381 toep->tp_mss_clamp = td->mtus[G_TCPOPT_MSS(opt)] - 40; 3382 tp->t_flags |= G_TCPOPT_TSTAMP(opt) ? TF_RCVD_TSTMP : 0; 3383 tp->t_flags |= G_TCPOPT_SACK(opt) ? TF_SACK_PERMIT : 0; 3384 tp->t_flags |= G_TCPOPT_WSCALE_OK(opt) ? TF_RCVD_SCALE : 0; |
2811 if (tp->t_flags & TF_RCVD_SCALE) 2812 tp->rcv_scale = 0; | 3385 if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == 3386 (TF_RCVD_SCALE|TF_REQ_SCALE)) 3387 tp->rcv_scale = tp->request_r_scale; |
2813} 2814 2815/* 2816 * Completes some final bits of initialization for just established connections 2817 * and changes their state to TCP_ESTABLISHED. 2818 * 2819 * snd_isn here is the ISN after the SYN, i.e., the true ISN + 1. 2820 */ --- 5 unchanged lines hidden (view full) --- 2826 2827 toep->tp_write_seq = tp->iss = tp->snd_max = tp->snd_nxt = tp->snd_una = snd_isn; 2828 assign_rxopt(so, opt); 2829 so->so_proto->pr_ctloutput = t3_ctloutput; 2830 2831#if 0 2832 inet_sk(sk)->id = tp->write_seq ^ jiffies; 2833#endif | 3388} 3389 3390/* 3391 * Completes some final bits of initialization for just established connections 3392 * and changes their state to TCP_ESTABLISHED. 3393 * 3394 * snd_isn here is the ISN after the SYN, i.e., the true ISN + 1. 3395 */ --- 5 unchanged lines hidden (view full) --- 3401 3402 toep->tp_write_seq = tp->iss = tp->snd_max = tp->snd_nxt = tp->snd_una = snd_isn; 3403 assign_rxopt(so, opt); 3404 so->so_proto->pr_ctloutput = t3_ctloutput; 3405 3406#if 0 3407 inet_sk(sk)->id = tp->write_seq ^ jiffies; 3408#endif |
2834 2835 | |
2836 /* 2837 * XXX not clear what rcv_wup maps to 2838 */ 2839 /* 2840 * Causes the first RX_DATA_ACK to supply any Rx credits we couldn't 2841 * pass through opt0. 2842 */ 2843 if (tp->rcv_wnd > (M_RCV_BUFSIZ << 10)) 2844 toep->tp_rcv_wup -= tp->rcv_wnd - (M_RCV_BUFSIZ << 10); 2845 2846 dump_toepcb(toep); 2847 2848#ifdef notyet 2849/* 2850 * no clean interface for marking ARP up to date 2851 */ 2852 dst_confirm(sk->sk_dst_cache); 2853#endif | 3409 /* 3410 * XXX not clear what rcv_wup maps to 3411 */ 3412 /* 3413 * Causes the first RX_DATA_ACK to supply any Rx credits we couldn't 3414 * pass through opt0. 3415 */ 3416 if (tp->rcv_wnd > (M_RCV_BUFSIZ << 10)) 3417 toep->tp_rcv_wup -= tp->rcv_wnd - (M_RCV_BUFSIZ << 10); 3418 3419 dump_toepcb(toep); 3420 3421#ifdef notyet 3422/* 3423 * no clean interface for marking ARP up to date 3424 */ 3425 dst_confirm(sk->sk_dst_cache); 3426#endif |
3427 tp->t_starttime = ticks; |
|
2854 tp->t_state = TCPS_ESTABLISHED; | 3428 tp->t_state = TCPS_ESTABLISHED; |
3429 soisconnected(so); |
|
2855} 2856 2857static int 2858syncache_expand_establish_req(struct cpl_pass_establish *req, struct socket **so, struct toepcb *toep) 2859{ 2860 2861 struct in_conninfo inc; 2862 struct tcpopt to; --- 80 unchanged lines hidden (view full) --- 2943 2944 /* 2945 * XXX workaround for lack of syncache drop 2946 */ 2947 toepcb_release(toep); 2948 2949 tp = sototcpcb(so); 2950 INP_LOCK(tp->t_inpcb); | 3430} 3431 3432static int 3433syncache_expand_establish_req(struct cpl_pass_establish *req, struct socket **so, struct toepcb *toep) 3434{ 3435 3436 struct in_conninfo inc; 3437 struct tcpopt to; --- 80 unchanged lines hidden (view full) --- 3518 3519 /* 3520 * XXX workaround for lack of syncache drop 3521 */ 3522 toepcb_release(toep); 3523 3524 tp = sototcpcb(so); 3525 INP_LOCK(tp->t_inpcb); |
2951#ifdef notyet 2952 so->so_snd.sb_flags |= SB_TOE; 2953 so->so_rcv.sb_flags |= SB_TOE; 2954#endif | 3526 3527 so->so_snd.sb_flags |= SB_NOCOALESCE; 3528 so->so_rcv.sb_flags |= SB_NOCOALESCE; 3529 |
2955 toep->tp_tp = tp; 2956 toep->tp_flags = 0; 2957 tp->t_toe = toep; 2958 reset_wr_list(toep); | 3530 toep->tp_tp = tp; 3531 toep->tp_flags = 0; 3532 tp->t_toe = toep; 3533 reset_wr_list(toep); |
2959 tp->rcv_wnd = select_rcv_wnd(so); 2960 DPRINTF("rcv_wnd=%ld\n", tp->rcv_wnd); | 3534 tp->rcv_wnd = select_rcv_wnd(tdev, so); 3535 tp->rcv_nxt = toep->tp_copied_seq; |
2961 install_offload_ops(so); 2962 2963 toep->tp_wr_max = toep->tp_wr_avail = TOM_TUNABLE(tdev, max_wrs); 2964 toep->tp_wr_unacked = 0; 2965 toep->tp_qset = G_QNUM(ntohl(m->m_pkthdr.csum_data)); | 3536 install_offload_ops(so); 3537 3538 toep->tp_wr_max = toep->tp_wr_avail = TOM_TUNABLE(tdev, max_wrs); 3539 toep->tp_wr_unacked = 0; 3540 toep->tp_qset = G_QNUM(ntohl(m->m_pkthdr.csum_data)); |
2966 toep->tp_ulp_mode = TOM_TUNABLE(tdev, ddp) && !(so->so_options & SO_NO_DDP) && 2967 tp->rcv_wnd >= MIN_DDP_RCV_WIN ? ULP_MODE_TCPDDP : 0; | |
2968 toep->tp_qset_idx = 0; 2969 toep->tp_mtu_idx = select_mss(td, tp, toep->tp_l2t->neigh->rt_ifp->if_mtu); 2970 2971 /* 2972 * XXX Cancel any keep alive timer 2973 */ 2974 2975 make_established(so, ntohl(req->snd_isn), ntohs(req->tcp_opt)); 2976 INP_INFO_WUNLOCK(&tcbinfo); 2977 INP_UNLOCK(tp->t_inpcb); | 3541 toep->tp_qset_idx = 0; 3542 toep->tp_mtu_idx = select_mss(td, tp, toep->tp_l2t->neigh->rt_ifp->if_mtu); 3543 3544 /* 3545 * XXX Cancel any keep alive timer 3546 */ 3547 3548 make_established(so, ntohl(req->snd_isn), ntohs(req->tcp_opt)); 3549 INP_INFO_WUNLOCK(&tcbinfo); 3550 INP_UNLOCK(tp->t_inpcb); |
2978 soisconnected(so); | |
2979 | 3551 |
3552 CTR1(KTR_TOM, "do_pass_establish tid=%u", toep->tp_tid); 3553 cxgb_log_tcb(cdev->adapter, toep->tp_tid); |
|
2980#ifdef notyet 2981 /* 2982 * XXX not sure how these checks map to us 2983 */ 2984 if (unlikely(sk->sk_socket)) { // simultaneous opens only 2985 sk->sk_state_change(sk); 2986 sk_wake_async(so, 0, POLL_OUT); 2987 } --- 73 unchanged lines hidden (view full) --- 3061 /* 3062 * Now that we finally have a TID send any CPL messages that we had to 3063 * defer for lack of a TID. 3064 */ 3065 if (mbufq_len(&toep->out_of_order_queue)) 3066 fixup_and_send_ofo(so); 3067 3068 if (__predict_false(so->so_state & SS_NOFDREF)) { | 3554#ifdef notyet 3555 /* 3556 * XXX not sure how these checks map to us 3557 */ 3558 if (unlikely(sk->sk_socket)) { // simultaneous opens only 3559 sk->sk_state_change(sk); 3560 sk_wake_async(so, 0, POLL_OUT); 3561 } --- 73 unchanged lines hidden (view full) --- 3635 /* 3636 * Now that we finally have a TID send any CPL messages that we had to 3637 * defer for lack of a TID. 3638 */ 3639 if (mbufq_len(&toep->out_of_order_queue)) 3640 fixup_and_send_ofo(so); 3641 3642 if (__predict_false(so->so_state & SS_NOFDREF)) { |
3069#ifdef notyet 3070 /* 3071 * XXX not clear what should be done here 3072 * appears to correspond to sorwakeup_locked | 3643 /* 3644 * XXX does this even make sense? |
3073 */ | 3645 */ |
3074 sk->sk_state_change(sk); 3075 sk_wake_async(so, 0, POLL_OUT); 3076#endif | 3646 sorwakeup(so); |
3077 } 3078 m_free(m); 3079#ifdef notyet 3080/* 3081 * XXX assume no write requests permitted while socket connection is 3082 * incomplete 3083 */ 3084 /* --- 5 unchanged lines hidden (view full) --- 3090 * buffers according to the just learned write_seq, and then we send 3091 * them on their way. 3092 */ 3093 fixup_pending_writeq_buffers(sk); 3094 if (t3_push_frames(so, 1)) 3095 sk->sk_write_space(sk); 3096#endif 3097 | 3647 } 3648 m_free(m); 3649#ifdef notyet 3650/* 3651 * XXX assume no write requests permitted while socket connection is 3652 * incomplete 3653 */ 3654 /* --- 5 unchanged lines hidden (view full) --- 3660 * buffers according to the just learned write_seq, and then we send 3661 * them on their way. 3662 */ 3663 fixup_pending_writeq_buffers(sk); 3664 if (t3_push_frames(so, 1)) 3665 sk->sk_write_space(sk); 3666#endif 3667 |
3098 soisconnected(so); 3099 toep->tp_state = tp->t_state = TCPS_ESTABLISHED; | 3668 toep->tp_state = tp->t_state; |
3100 tcpstat.tcps_connects++; 3101 3102} 3103 3104/* 3105 * Process a CPL_ACT_ESTABLISH message. 3106 */ 3107static int --- 26 unchanged lines hidden (view full) --- 3134 toep->tp_tid = tid; 3135 toep->tp_tp = tp; 3136 so_insert_tid(d, so, tid); 3137 free_atid(cdev, atid); 3138 toep->tp_qset = G_QNUM(ntohl(m->m_pkthdr.csum_data)); 3139 3140 socket_act_establish(so, m); 3141 INP_UNLOCK(tp->t_inpcb); | 3669 tcpstat.tcps_connects++; 3670 3671} 3672 3673/* 3674 * Process a CPL_ACT_ESTABLISH message. 3675 */ 3676static int --- 26 unchanged lines hidden (view full) --- 3703 toep->tp_tid = tid; 3704 toep->tp_tp = tp; 3705 so_insert_tid(d, so, tid); 3706 free_atid(cdev, atid); 3707 toep->tp_qset = G_QNUM(ntohl(m->m_pkthdr.csum_data)); 3708 3709 socket_act_establish(so, m); 3710 INP_UNLOCK(tp->t_inpcb); |
3711 CTR1(KTR_TOM, "do_act_establish tid=%u", toep->tp_tid); 3712 cxgb_log_tcb(cdev->adapter, toep->tp_tid); 3713 |
|
3142 return (0); 3143} 3144 3145/* 3146 * Process an acknowledgment of WR completion. Advance snd_una and send the 3147 * next batch of work requests from the write queue. 3148 */ 3149static void 3150wr_ack(struct toepcb *toep, struct mbuf *m) 3151{ 3152 struct tcpcb *tp = toep->tp_tp; 3153 struct cpl_wr_ack *hdr = cplhdr(m); 3154 struct socket *so = toeptoso(toep); 3155 unsigned int credits = ntohs(hdr->credits); 3156 u32 snd_una = ntohl(hdr->snd_una); 3157 int bytes = 0; 3158 | 3714 return (0); 3715} 3716 3717/* 3718 * Process an acknowledgment of WR completion. Advance snd_una and send the 3719 * next batch of work requests from the write queue. 3720 */ 3721static void 3722wr_ack(struct toepcb *toep, struct mbuf *m) 3723{ 3724 struct tcpcb *tp = toep->tp_tp; 3725 struct cpl_wr_ack *hdr = cplhdr(m); 3726 struct socket *so = toeptoso(toep); 3727 unsigned int credits = ntohs(hdr->credits); 3728 u32 snd_una = ntohl(hdr->snd_una); 3729 int bytes = 0; 3730 |
3159 DPRINTF("wr_ack: snd_una=%u credits=%d\n", snd_una, credits); | 3731 CTR2(KTR_SPARE2, "wr_ack: snd_una=%u credits=%d", snd_una, credits); |
3160 3161 INP_LOCK(tp->t_inpcb); 3162 3163 toep->tp_wr_avail += credits; 3164 if (toep->tp_wr_unacked > toep->tp_wr_max - toep->tp_wr_avail) 3165 toep->tp_wr_unacked = toep->tp_wr_max - toep->tp_wr_avail; 3166 3167 while (credits) { 3168 struct mbuf *p = peek_wr(toep); | 3732 3733 INP_LOCK(tp->t_inpcb); 3734 3735 toep->tp_wr_avail += credits; 3736 if (toep->tp_wr_unacked > toep->tp_wr_max - toep->tp_wr_avail) 3737 toep->tp_wr_unacked = toep->tp_wr_max - toep->tp_wr_avail; 3738 3739 while (credits) { 3740 struct mbuf *p = peek_wr(toep); |
3169 DPRINTF("p->credits=%d p->bytes=%d\n", p->m_pkthdr.csum_data, p->m_pkthdr.len) ; | |
3170 3171 if (__predict_false(!p)) { 3172 log(LOG_ERR, "%u WR_ACK credits for TID %u with " | 3741 3742 if (__predict_false(!p)) { 3743 log(LOG_ERR, "%u WR_ACK credits for TID %u with " |
3173 "nothing pending, state %u\n", 3174 credits, toep->tp_tid, tp->t_state); | 3744 "nothing pending, state %u wr_avail=%u\n", 3745 credits, toep->tp_tid, tp->t_state, toep->tp_wr_avail); |
3175 break; 3176 } | 3746 break; 3747 } |
3748 CTR2(KTR_TOM, 3749 "wr_ack: p->credits=%d p->bytes=%d", p->m_pkthdr.csum_data, p->m_pkthdr.len); 3750 3751 KASSERT(p->m_pkthdr.csum_data != 0, ("empty request still on list")); |
|
3177 if (__predict_false(credits < p->m_pkthdr.csum_data)) { | 3752 if (__predict_false(credits < p->m_pkthdr.csum_data)) { |
3753 |
|
3178#if DEBUG_WR > 1 3179 struct tx_data_wr *w = cplhdr(p); | 3754#if DEBUG_WR > 1 3755 struct tx_data_wr *w = cplhdr(p); |
3180#ifdef notyet | |
3181 log(LOG_ERR, 3182 "TID %u got %u WR credits, need %u, len %u, " 3183 "main body %u, frags %u, seq # %u, ACK una %u," 3184 " ACK nxt %u, WR_AVAIL %u, WRs pending %u\n", 3185 toep->tp_tid, credits, p->csum, p->len, 3186 p->len - p->data_len, skb_shinfo(p)->nr_frags, 3187 ntohl(w->sndseq), snd_una, ntohl(hdr->snd_nxt), | 3756 log(LOG_ERR, 3757 "TID %u got %u WR credits, need %u, len %u, " 3758 "main body %u, frags %u, seq # %u, ACK una %u," 3759 " ACK nxt %u, WR_AVAIL %u, WRs pending %u\n", 3760 toep->tp_tid, credits, p->csum, p->len, 3761 p->len - p->data_len, skb_shinfo(p)->nr_frags, 3762 ntohl(w->sndseq), snd_una, ntohl(hdr->snd_nxt), |
3188 WR_AVAIL(tp), count_pending_wrs(tp) - credits); 3189#endif | 3763 toep->tp_wr_avail, count_pending_wrs(tp) - credits); |
3190#endif 3191 p->m_pkthdr.csum_data -= credits; 3192 break; 3193 } else { 3194 dequeue_wr(toep); 3195 credits -= p->m_pkthdr.csum_data; 3196 bytes += p->m_pkthdr.len; | 3764#endif 3765 p->m_pkthdr.csum_data -= credits; 3766 break; 3767 } else { 3768 dequeue_wr(toep); 3769 credits -= p->m_pkthdr.csum_data; 3770 bytes += p->m_pkthdr.len; |
3197 DPRINTF("done with wr of %d bytes\n", p->m_pkthdr.len); | 3771 CTR3(KTR_TOM, 3772 "wr_ack: done with wr of %d bytes remain credits=%d wr credits=%d", 3773 p->m_pkthdr.len, credits, p->m_pkthdr.csum_data); |
3198 3199 m_free(p); 3200 } 3201 } 3202 3203#if DEBUG_WR 3204 check_wr_invariants(tp); 3205#endif --- 17 unchanged lines hidden (view full) --- 3223 * Keep ARP entry "minty fresh" 3224 */ 3225 dst_confirm(sk->sk_dst_cache); 3226#endif 3227 if (tp->snd_una == tp->snd_nxt) 3228 toep->tp_flags &= ~TP_TX_WAIT_IDLE; 3229 } 3230 if (bytes) { | 3774 3775 m_free(p); 3776 } 3777 } 3778 3779#if DEBUG_WR 3780 check_wr_invariants(tp); 3781#endif --- 17 unchanged lines hidden (view full) --- 3799 * Keep ARP entry "minty fresh" 3800 */ 3801 dst_confirm(sk->sk_dst_cache); 3802#endif 3803 if (tp->snd_una == tp->snd_nxt) 3804 toep->tp_flags &= ~TP_TX_WAIT_IDLE; 3805 } 3806 if (bytes) { |
3231 DPRINTF("sbdrop(%d)\n", bytes); | 3807 CTR1(KTR_SPARE2, "wr_ack: sbdrop(%d)", bytes); |
3232 SOCKBUF_LOCK(&so->so_snd); 3233 sbdrop_locked(&so->so_snd, bytes); 3234 sowwakeup_locked(so); 3235 } 3236 3237 if (so->so_snd.sb_sndptroff < so->so_snd.sb_cc) 3238 t3_push_frames(so, 0); 3239 --- 5 unchanged lines hidden (view full) --- 3245/* 3246 * Handler for TX_DATA_ACK CPL messages. 3247 */ 3248static int 3249do_wr_ack(struct t3cdev *dev, struct mbuf *m, void *ctx) 3250{ 3251 struct toepcb *toep = (struct toepcb *)ctx; 3252 | 3808 SOCKBUF_LOCK(&so->so_snd); 3809 sbdrop_locked(&so->so_snd, bytes); 3810 sowwakeup_locked(so); 3811 } 3812 3813 if (so->so_snd.sb_sndptroff < so->so_snd.sb_cc) 3814 t3_push_frames(so, 0); 3815 --- 5 unchanged lines hidden (view full) --- 3821/* 3822 * Handler for TX_DATA_ACK CPL messages. 3823 */ 3824static int 3825do_wr_ack(struct t3cdev *dev, struct mbuf *m, void *ctx) 3826{ 3827 struct toepcb *toep = (struct toepcb *)ctx; 3828 |
3253 DPRINTF("do_wr_ack\n"); 3254 dump_toepcb(toep); 3255 | |
3256 VALIDATE_SOCK(so); 3257 3258 wr_ack(toep, m); 3259 return 0; 3260} 3261 | 3829 VALIDATE_SOCK(so); 3830 3831 wr_ack(toep, m); 3832 return 0; 3833} 3834 |
3835/* 3836 * Handler for TRACE_PKT CPL messages. Just sink these packets. 3837 */ 3838static int 3839do_trace_pkt(struct t3cdev *dev, struct mbuf *m, void *ctx) 3840{ 3841 m_freem(m); 3842 return 0; 3843} |
|
3262 3263/* 3264 * Reset a connection that is on a listener's SYN queue or accept queue, 3265 * i.e., one that has not had a struct socket associated with it. 3266 * Must be called from process context. 3267 * 3268 * Modeled after code in inet_csk_listen_stop(). 3269 */ --- 45 unchanged lines hidden (view full) --- 3315 toep->tp_tp = NULL; 3316 t3_send_reset(toep); 3317 cxgb_remove_tid(TOEP_T3C_DEV(toep), toep, toep->tp_tid); 3318 toepcb_release(toep); 3319 } 3320 SOCK_UNLOCK(lctx->lso); 3321} 3322 | 3844 3845/* 3846 * Reset a connection that is on a listener's SYN queue or accept queue, 3847 * i.e., one that has not had a struct socket associated with it. 3848 * Must be called from process context. 3849 * 3850 * Modeled after code in inet_csk_listen_stop(). 3851 */ --- 45 unchanged lines hidden (view full) --- 3897 toep->tp_tp = NULL; 3898 t3_send_reset(toep); 3899 cxgb_remove_tid(TOEP_T3C_DEV(toep), toep, toep->tp_tid); 3900 toepcb_release(toep); 3901 } 3902 SOCK_UNLOCK(lctx->lso); 3903} 3904 |
3905 3906int 3907t3_setup_ppods(struct socket *so, const struct ddp_gather_list *gl, 3908 unsigned int nppods, unsigned int tag, unsigned int maxoff, 3909 unsigned int pg_off, unsigned int color) 3910{ 3911 unsigned int i, j, pidx; 3912 struct pagepod *p; 3913 struct mbuf *m; 3914 struct ulp_mem_io *req; 3915 struct tcpcb *tp = sototcpcb(so); 3916 struct toepcb *toep = tp->t_toe; 3917 unsigned int tid = toep->tp_tid; 3918 const struct tom_data *td = TOM_DATA(TOE_DEV(so)); 3919 unsigned int ppod_addr = tag * PPOD_SIZE + td->ddp_llimit; 3920 3921 CTR6(KTR_TOM, "t3_setup_ppods(gl=%p nppods=%u tag=%u maxoff=%u pg_off=%u color=%u)", 3922 gl, nppods, tag, maxoff, pg_off, color); 3923 3924 for (i = 0; i < nppods; ++i) { 3925 m = m_gethdr_nofail(sizeof(*req) + PPOD_SIZE); 3926 m_set_priority(m, mkprio(CPL_PRIORITY_CONTROL, toep)); 3927 req = mtod(m, struct ulp_mem_io *); 3928 m->m_pkthdr.len = m->m_len = sizeof(*req) + PPOD_SIZE; 3929 req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_BYPASS)); 3930 req->wr.wr_lo = 0; 3931 req->cmd_lock_addr = htonl(V_ULP_MEMIO_ADDR(ppod_addr >> 5) | 3932 V_ULPTX_CMD(ULP_MEM_WRITE)); 3933 req->len = htonl(V_ULP_MEMIO_DATA_LEN(PPOD_SIZE / 32) | 3934 V_ULPTX_NFLITS(PPOD_SIZE / 8 + 1)); 3935 3936 p = (struct pagepod *)(req + 1); 3937 if (__predict_false(i < nppods - NUM_SENTINEL_PPODS)) { 3938 p->pp_vld_tid = htonl(F_PPOD_VALID | V_PPOD_TID(tid)); 3939 p->pp_pgsz_tag_color = htonl(V_PPOD_TAG(tag) | 3940 V_PPOD_COLOR(color)); 3941 p->pp_max_offset = htonl(maxoff); 3942 p->pp_page_offset = htonl(pg_off); 3943 p->pp_rsvd = 0; 3944 for (pidx = 4 * i, j = 0; j < 5; ++j, ++pidx) 3945 p->pp_addr[j] = pidx < gl->dgl_nelem ? 3946 htobe64(VM_PAGE_TO_PHYS(gl->dgl_pages[pidx])) : 0; 3947 } else 3948 p->pp_vld_tid = 0; /* mark sentinel page pods invalid */ 3949 send_or_defer(toep, m, 0); 3950 ppod_addr += PPOD_SIZE; 3951 } 3952 return (0); 3953} 3954 3955/* 3956 * Build a CPL_BARRIER message as payload of a ULP_TX_PKT command. 3957 */ 3958static inline void 3959mk_cpl_barrier_ulp(struct cpl_barrier *b) 3960{ 3961 struct ulp_txpkt *txpkt = (struct ulp_txpkt *)b; 3962 3963 txpkt->cmd_dest = htonl(V_ULPTX_CMD(ULP_TXPKT)); 3964 txpkt->len = htonl(V_ULPTX_NFLITS(sizeof(*b) / 8)); 3965 b->opcode = CPL_BARRIER; 3966} 3967 3968/* 3969 * Build a CPL_GET_TCB message as payload of a ULP_TX_PKT command. 3970 */ 3971static inline void 3972mk_get_tcb_ulp(struct cpl_get_tcb *req, unsigned int tid, unsigned int cpuno) 3973{ 3974 struct ulp_txpkt *txpkt = (struct ulp_txpkt *)req; 3975 3976 txpkt = (struct ulp_txpkt *)req; 3977 txpkt->cmd_dest = htonl(V_ULPTX_CMD(ULP_TXPKT)); 3978 txpkt->len = htonl(V_ULPTX_NFLITS(sizeof(*req) / 8)); 3979 OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_GET_TCB, tid)); 3980 req->cpuno = htons(cpuno); 3981} 3982 3983/* 3984 * Build a CPL_SET_TCB_FIELD message as payload of a ULP_TX_PKT command. 3985 */ 3986static inline void 3987mk_set_tcb_field_ulp(struct cpl_set_tcb_field *req, unsigned int tid, 3988 unsigned int word, uint64_t mask, uint64_t val) 3989{ 3990 struct ulp_txpkt *txpkt = (struct ulp_txpkt *)req; 3991 3992 CTR4(KTR_TCB, "mk_set_tcb_field_ulp(tid=%u word=0x%x mask=%jx val=%jx", 3993 tid, word, mask, val); 3994 3995 txpkt->cmd_dest = htonl(V_ULPTX_CMD(ULP_TXPKT)); 3996 txpkt->len = htonl(V_ULPTX_NFLITS(sizeof(*req) / 8)); 3997 OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid)); 3998 req->reply = V_NO_REPLY(1); 3999 req->cpu_idx = 0; 4000 req->word = htons(word); 4001 req->mask = htobe64(mask); 4002 req->val = htobe64(val); 4003} 4004 4005/* 4006 * Build a CPL_RX_DATA_ACK message as payload of a ULP_TX_PKT command. 4007 */ 4008static void 4009mk_rx_data_ack_ulp(struct cpl_rx_data_ack *ack, unsigned int tid, unsigned int credits) 4010{ 4011 struct ulp_txpkt *txpkt = (struct ulp_txpkt *)ack; 4012 4013 txpkt->cmd_dest = htonl(V_ULPTX_CMD(ULP_TXPKT)); 4014 txpkt->len = htonl(V_ULPTX_NFLITS(sizeof(*ack) / 8)); 4015 OPCODE_TID(ack) = htonl(MK_OPCODE_TID(CPL_RX_DATA_ACK, tid)); 4016 ack->credit_dack = htonl(F_RX_MODULATE | F_RX_DACK_CHANGE | 4017 V_RX_DACK_MODE(1) | V_RX_CREDITS(credits)); 4018} 4019 |
|
3323void | 4020void |
4021t3_cancel_ddpbuf(struct toepcb *toep, unsigned int bufidx) 4022{ 4023 unsigned int wrlen; 4024 struct mbuf *m; 4025 struct work_request_hdr *wr; 4026 struct cpl_barrier *lock; 4027 struct cpl_set_tcb_field *req; 4028 struct cpl_get_tcb *getreq; 4029 struct ddp_state *p = &toep->tp_ddp_state; 4030 4031 SOCKBUF_LOCK_ASSERT(&toeptoso(toep)->so_rcv); 4032 wrlen = sizeof(*wr) + sizeof(*req) + 2 * sizeof(*lock) + 4033 sizeof(*getreq); 4034 m = m_gethdr_nofail(wrlen); 4035 m_set_priority(m, mkprio(CPL_PRIORITY_CONTROL, toep)); 4036 wr = mtod(m, struct work_request_hdr *); 4037 bzero(wr, wrlen); 4038 4039 wr->wr_hi = htonl(V_WR_OP(FW_WROPCODE_BYPASS)); 4040 m->m_pkthdr.len = m->m_len = wrlen; 4041 4042 lock = (struct cpl_barrier *)(wr + 1); 4043 mk_cpl_barrier_ulp(lock); 4044 4045 req = (struct cpl_set_tcb_field *)(lock + 1); 4046 4047 CTR1(KTR_TCB, "t3_cancel_ddpbuf(bufidx=%u)", bufidx); 4048 4049 /* Hmmm, not sure if this actually a good thing: reactivating 4050 * the other buffer might be an issue if it has been completed 4051 * already. However, that is unlikely, since the fact that the UBUF 4052 * is not completed indicates that there is no oustanding data. 4053 */ 4054 if (bufidx == 0) 4055 mk_set_tcb_field_ulp(req, toep->tp_tid, W_TCB_RX_DDP_FLAGS, 4056 V_TF_DDP_ACTIVE_BUF(1) | 4057 V_TF_DDP_BUF0_VALID(1), 4058 V_TF_DDP_ACTIVE_BUF(1)); 4059 else 4060 mk_set_tcb_field_ulp(req, toep->tp_tid, W_TCB_RX_DDP_FLAGS, 4061 V_TF_DDP_ACTIVE_BUF(1) | 4062 V_TF_DDP_BUF1_VALID(1), 0); 4063 4064 getreq = (struct cpl_get_tcb *)(req + 1); 4065 mk_get_tcb_ulp(getreq, toep->tp_tid, toep->tp_qset); 4066 4067 mk_cpl_barrier_ulp((struct cpl_barrier *)(getreq + 1)); 4068 4069 /* Keep track of the number of oustanding CPL_GET_TCB requests 4070 */ 4071 p->get_tcb_count++; 4072 4073#ifdef T3_TRACE 4074 T3_TRACE1(TIDTB(so), 4075 "t3_cancel_ddpbuf: bufidx %u", bufidx); 4076#endif 4077 cxgb_ofld_send(TOEP_T3C_DEV(toep), m); 4078} 4079 4080/** 4081 * t3_overlay_ddpbuf - overlay an existing DDP buffer with a new one 4082 * @sk: the socket associated with the buffers 4083 * @bufidx: index of HW DDP buffer (0 or 1) 4084 * @tag0: new tag for HW buffer 0 4085 * @tag1: new tag for HW buffer 1 4086 * @len: new length for HW buf @bufidx 4087 * 4088 * Sends a compound WR to overlay a new DDP buffer on top of an existing 4089 * buffer by changing the buffer tag and length and setting the valid and 4090 * active flag accordingly. The caller must ensure the new buffer is at 4091 * least as big as the existing one. Since we typically reprogram both HW 4092 * buffers this function sets both tags for convenience. Read the TCB to 4093 * determine how made data was written into the buffer before the overlay 4094 * took place. 4095 */ 4096void 4097t3_overlay_ddpbuf(struct toepcb *toep, unsigned int bufidx, unsigned int tag0, 4098 unsigned int tag1, unsigned int len) 4099{ 4100 unsigned int wrlen; 4101 struct mbuf *m; 4102 struct work_request_hdr *wr; 4103 struct cpl_get_tcb *getreq; 4104 struct cpl_set_tcb_field *req; 4105 struct ddp_state *p = &toep->tp_ddp_state; 4106 4107 CTR4(KTR_TCB, "t3_setup_ppods(bufidx=%u tag0=%u tag1=%u len=%u)", 4108 bufidx, tag0, tag1, len); 4109 SOCKBUF_LOCK_ASSERT(&toeptoso(toep)->so_rcv); 4110 wrlen = sizeof(*wr) + 3 * sizeof(*req) + sizeof(*getreq); 4111 m = m_gethdr_nofail(wrlen); 4112 m_set_priority(m, mkprio(CPL_PRIORITY_CONTROL, toep)); 4113 wr = mtod(m, struct work_request_hdr *); 4114 m->m_pkthdr.len = m->m_len = wrlen; 4115 bzero(wr, wrlen); 4116 4117 4118 /* Set the ATOMIC flag to make sure that TP processes the following 4119 * CPLs in an atomic manner and no wire segments can be interleaved. 4120 */ 4121 wr->wr_hi = htonl(V_WR_OP(FW_WROPCODE_BYPASS) | F_WR_ATOMIC); 4122 req = (struct cpl_set_tcb_field *)(wr + 1); 4123 mk_set_tcb_field_ulp(req, toep->tp_tid, W_TCB_RX_DDP_BUF0_TAG, 4124 V_TCB_RX_DDP_BUF0_TAG(M_TCB_RX_DDP_BUF0_TAG) | 4125 V_TCB_RX_DDP_BUF1_TAG(M_TCB_RX_DDP_BUF1_TAG) << 32, 4126 V_TCB_RX_DDP_BUF0_TAG(tag0) | 4127 V_TCB_RX_DDP_BUF1_TAG((uint64_t)tag1) << 32); 4128 req++; 4129 if (bufidx == 0) { 4130 mk_set_tcb_field_ulp(req, toep->tp_tid, W_TCB_RX_DDP_BUF0_LEN, 4131 V_TCB_RX_DDP_BUF0_LEN(M_TCB_RX_DDP_BUF0_LEN), 4132 V_TCB_RX_DDP_BUF0_LEN((uint64_t)len)); 4133 req++; 4134 mk_set_tcb_field_ulp(req, toep->tp_tid, W_TCB_RX_DDP_FLAGS, 4135 V_TF_DDP_PUSH_DISABLE_0(1) | 4136 V_TF_DDP_BUF0_VALID(1) | V_TF_DDP_ACTIVE_BUF(1), 4137 V_TF_DDP_PUSH_DISABLE_0(0) | 4138 V_TF_DDP_BUF0_VALID(1)); 4139 } else { 4140 mk_set_tcb_field_ulp(req, toep->tp_tid, W_TCB_RX_DDP_BUF1_LEN, 4141 V_TCB_RX_DDP_BUF1_LEN(M_TCB_RX_DDP_BUF1_LEN), 4142 V_TCB_RX_DDP_BUF1_LEN((uint64_t)len)); 4143 req++; 4144 mk_set_tcb_field_ulp(req, toep->tp_tid, W_TCB_RX_DDP_FLAGS, 4145 V_TF_DDP_PUSH_DISABLE_1(1) | 4146 V_TF_DDP_BUF1_VALID(1) | V_TF_DDP_ACTIVE_BUF(1), 4147 V_TF_DDP_PUSH_DISABLE_1(0) | 4148 V_TF_DDP_BUF1_VALID(1) | V_TF_DDP_ACTIVE_BUF(1)); 4149 } 4150 4151 getreq = (struct cpl_get_tcb *)(req + 1); 4152 mk_get_tcb_ulp(getreq, toep->tp_tid, toep->tp_qset); 4153 4154 /* Keep track of the number of oustanding CPL_GET_TCB requests 4155 */ 4156 p->get_tcb_count++; 4157 4158#ifdef T3_TRACE 4159 T3_TRACE4(TIDTB(sk), 4160 "t3_overlay_ddpbuf: bufidx %u tag0 %u tag1 %u " 4161 "len %d", 4162 bufidx, tag0, tag1, len); 4163#endif 4164 cxgb_ofld_send(TOEP_T3C_DEV(toep), m); 4165} 4166 4167/* 4168 * Sends a compound WR containing all the CPL messages needed to program the 4169 * two HW DDP buffers, namely optionally setting up the length and offset of 4170 * each buffer, programming the DDP flags, and optionally sending RX_DATA_ACK. 4171 */ 4172void 4173t3_setup_ddpbufs(struct toepcb *toep, unsigned int len0, unsigned int offset0, 4174 unsigned int len1, unsigned int offset1, 4175 uint64_t ddp_flags, uint64_t flag_mask, int modulate) 4176{ 4177 unsigned int wrlen; 4178 struct mbuf *m; 4179 struct work_request_hdr *wr; 4180 struct cpl_set_tcb_field *req; 4181 4182 CTR6(KTR_TCB, "t3_setup_ddpbufs(len0=%u offset0=%u len1=%u offset1=%u ddp_flags=0x%08x%08x ", 4183 len0, offset0, len1, offset1, ddp_flags >> 32, ddp_flags & 0xffffffff); 4184 4185 SOCKBUF_LOCK_ASSERT(&toeptoso(toep)->so_rcv); 4186 wrlen = sizeof(*wr) + sizeof(*req) + (len0 ? sizeof(*req) : 0) + 4187 (len1 ? sizeof(*req) : 0) + 4188 (modulate ? sizeof(struct cpl_rx_data_ack) : 0); 4189 m = m_gethdr_nofail(wrlen); 4190 m_set_priority(m, mkprio(CPL_PRIORITY_CONTROL, toep)); 4191 wr = mtod(m, struct work_request_hdr *); 4192 bzero(wr, wrlen); 4193 4194 wr->wr_hi = htonl(V_WR_OP(FW_WROPCODE_BYPASS)); 4195 m->m_pkthdr.len = m->m_len = wrlen; 4196 4197 req = (struct cpl_set_tcb_field *)(wr + 1); 4198 if (len0) { /* program buffer 0 offset and length */ 4199 mk_set_tcb_field_ulp(req, toep->tp_tid, W_TCB_RX_DDP_BUF0_OFFSET, 4200 V_TCB_RX_DDP_BUF0_OFFSET(M_TCB_RX_DDP_BUF0_OFFSET) | 4201 V_TCB_RX_DDP_BUF0_LEN(M_TCB_RX_DDP_BUF0_LEN), 4202 V_TCB_RX_DDP_BUF0_OFFSET((uint64_t)offset0) | 4203 V_TCB_RX_DDP_BUF0_LEN((uint64_t)len0)); 4204 req++; 4205 } 4206 if (len1) { /* program buffer 1 offset and length */ 4207 mk_set_tcb_field_ulp(req, toep->tp_tid, W_TCB_RX_DDP_BUF1_OFFSET, 4208 V_TCB_RX_DDP_BUF1_OFFSET(M_TCB_RX_DDP_BUF1_OFFSET) | 4209 V_TCB_RX_DDP_BUF1_LEN(M_TCB_RX_DDP_BUF1_LEN) << 32, 4210 V_TCB_RX_DDP_BUF1_OFFSET((uint64_t)offset1) | 4211 V_TCB_RX_DDP_BUF1_LEN((uint64_t)len1) << 32); 4212 req++; 4213 } 4214 4215 mk_set_tcb_field_ulp(req, toep->tp_tid, W_TCB_RX_DDP_FLAGS, flag_mask, 4216 ddp_flags); 4217 4218 if (modulate) { 4219 mk_rx_data_ack_ulp((struct cpl_rx_data_ack *)(req + 1), toep->tp_tid, 4220 toep->tp_copied_seq - toep->tp_rcv_wup); 4221 toep->tp_rcv_wup = toep->tp_copied_seq; 4222 } 4223 4224#ifdef T3_TRACE 4225 T3_TRACE5(TIDTB(sk), 4226 "t3_setup_ddpbufs: len0 %u len1 %u ddp_flags 0x%08x%08x " 4227 "modulate %d", 4228 len0, len1, ddp_flags >> 32, ddp_flags & 0xffffffff, 4229 modulate); 4230#endif 4231 4232 cxgb_ofld_send(TOEP_T3C_DEV(toep), m); 4233} 4234 4235void |
|
3324t3_init_wr_tab(unsigned int wr_len) 3325{ 3326 int i; 3327 3328 if (mbuf_wrs[1]) /* already initialized */ 3329 return; 3330 3331 for (i = 1; i < ARRAY_SIZE(mbuf_wrs); i++) { --- 16 unchanged lines hidden (view full) --- 3348 log(LOG_ERR, 3349 "Chelsio TCP offload: can't allocate sk_buff\n"); 3350 return -1; 3351 } 3352 skb_put(tcphdr_skb, sizeof(struct tcphdr)); 3353 tcphdr_skb->h.raw = tcphdr_skb->data; 3354 memset(tcphdr_skb->data, 0, tcphdr_skb->len); 3355#endif | 4236t3_init_wr_tab(unsigned int wr_len) 4237{ 4238 int i; 4239 4240 if (mbuf_wrs[1]) /* already initialized */ 4241 return; 4242 4243 for (i = 1; i < ARRAY_SIZE(mbuf_wrs); i++) { --- 16 unchanged lines hidden (view full) --- 4260 log(LOG_ERR, 4261 "Chelsio TCP offload: can't allocate sk_buff\n"); 4262 return -1; 4263 } 4264 skb_put(tcphdr_skb, sizeof(struct tcphdr)); 4265 tcphdr_skb->h.raw = tcphdr_skb->data; 4266 memset(tcphdr_skb->data, 0, tcphdr_skb->len); 4267#endif |
3356 | |
3357 3358 t3tom_register_cpl_handler(CPL_ACT_ESTABLISH, do_act_establish); 3359 t3tom_register_cpl_handler(CPL_ACT_OPEN_RPL, do_act_open_rpl); 3360 t3tom_register_cpl_handler(CPL_TX_DMA_ACK, do_wr_ack); 3361 t3tom_register_cpl_handler(CPL_RX_DATA, do_rx_data); 3362 t3tom_register_cpl_handler(CPL_CLOSE_CON_RPL, do_close_con_rpl); 3363 t3tom_register_cpl_handler(CPL_PEER_CLOSE, do_peer_close); 3364 t3tom_register_cpl_handler(CPL_PASS_ESTABLISH, do_pass_establish); 3365 t3tom_register_cpl_handler(CPL_PASS_ACCEPT_REQ, do_pass_accept_req); 3366 t3tom_register_cpl_handler(CPL_ABORT_REQ_RSS, do_abort_req); 3367 t3tom_register_cpl_handler(CPL_ABORT_RPL_RSS, do_abort_rpl); 3368 t3tom_register_cpl_handler(CPL_RX_DATA_DDP, do_rx_data_ddp); 3369 t3tom_register_cpl_handler(CPL_RX_DDP_COMPLETE, do_rx_ddp_complete); | 4268 4269 t3tom_register_cpl_handler(CPL_ACT_ESTABLISH, do_act_establish); 4270 t3tom_register_cpl_handler(CPL_ACT_OPEN_RPL, do_act_open_rpl); 4271 t3tom_register_cpl_handler(CPL_TX_DMA_ACK, do_wr_ack); 4272 t3tom_register_cpl_handler(CPL_RX_DATA, do_rx_data); 4273 t3tom_register_cpl_handler(CPL_CLOSE_CON_RPL, do_close_con_rpl); 4274 t3tom_register_cpl_handler(CPL_PEER_CLOSE, do_peer_close); 4275 t3tom_register_cpl_handler(CPL_PASS_ESTABLISH, do_pass_establish); 4276 t3tom_register_cpl_handler(CPL_PASS_ACCEPT_REQ, do_pass_accept_req); 4277 t3tom_register_cpl_handler(CPL_ABORT_REQ_RSS, do_abort_req); 4278 t3tom_register_cpl_handler(CPL_ABORT_RPL_RSS, do_abort_rpl); 4279 t3tom_register_cpl_handler(CPL_RX_DATA_DDP, do_rx_data_ddp); 4280 t3tom_register_cpl_handler(CPL_RX_DDP_COMPLETE, do_rx_ddp_complete); |
3370#ifdef notyet | |
3371 t3tom_register_cpl_handler(CPL_RX_URG_NOTIFY, do_rx_urg_notify); 3372 t3tom_register_cpl_handler(CPL_TRACE_PKT, do_trace_pkt); 3373 t3tom_register_cpl_handler(CPL_GET_TCB_RPL, do_get_tcb_rpl); | 4281 t3tom_register_cpl_handler(CPL_RX_URG_NOTIFY, do_rx_urg_notify); 4282 t3tom_register_cpl_handler(CPL_TRACE_PKT, do_trace_pkt); 4283 t3tom_register_cpl_handler(CPL_GET_TCB_RPL, do_get_tcb_rpl); |
3374#endif | |
3375 return (0); 3376} 3377 | 4284 return (0); 4285} 4286 |