1256694Snp/* 2256694Snp * Copyright (c) 2009-2013 Chelsio, Inc. All rights reserved. 3256694Snp * 4256694Snp * This software is available to you under a choice of one of two 5256694Snp * licenses. You may choose to be licensed under the terms of the GNU 6256694Snp * General Public License (GPL) Version 2, available from the file 7256694Snp * COPYING in the main directory of this source tree, or the 8256694Snp * OpenIB.org BSD license below: 9256694Snp * 10256694Snp * Redistribution and use in source and binary forms, with or 11256694Snp * without modification, are permitted provided that the following 12256694Snp * conditions are met: 13256694Snp * 14256694Snp * - Redistributions of source code must retain the above 15256694Snp * copyright notice, this list of conditions and the following 16256694Snp * disclaimer. 17256694Snp * 18256694Snp * - Redistributions in binary form must reproduce the above 19256694Snp * copyright notice, this list of conditions and the following 20256694Snp * disclaimer in the documentation and/or other materials 21256694Snp * provided with the distribution. 22256694Snp * 23256694Snp * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24256694Snp * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25256694Snp * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26256694Snp * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27256694Snp * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28256694Snp * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29256694Snp * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30256694Snp * SOFTWARE. 31256694Snp */ 32256694Snp#include <sys/cdefs.h> 33256694Snp__FBSDID("$FreeBSD$"); 34256694Snp 35256694Snp#include "opt_inet.h" 36256694Snp 37256694Snp#ifdef TCP_OFFLOAD 38256694Snp#include <sys/types.h> 39256694Snp#include <sys/malloc.h> 40256694Snp#include <sys/socket.h> 41256694Snp#include <sys/socketvar.h> 42256694Snp#include <sys/sockio.h> 43256694Snp#include <sys/taskqueue.h> 44256694Snp#include <netinet/in.h> 45256694Snp#include <net/neighbour.h> 46256694Snp#include <net/route.h> 47256694Snp 48256694Snp#include <netinet/in_systm.h> 49256694Snp#include <netinet/in_pcb.h> 50256694Snp#include <netinet/ip.h> 51256694Snp#include <netinet/ip_var.h> 52256694Snp#include <netinet/tcp_var.h> 53256694Snp#include <netinet/tcp.h> 54256694Snp#include <netinet/tcpip.h> 55256694Snp 56256694Snp#include <netinet/toecore.h> 57256694Snp 58256694Snpstruct sge_iq; 59256694Snpstruct rss_header; 60256694Snp#include <linux/types.h> 61256694Snp#include "offload.h" 62256694Snp#include "tom/t4_tom.h" 63256694Snp 64256694Snp#define TOEPCB(so) ((struct toepcb *)(so_sototcpcb((so))->t_toe)) 65256694Snp 66256694Snp#include "iw_cxgbe.h" 67256694Snp#include <linux/module.h> 68256694Snp#include <linux/workqueue.h> 69256694Snp#include <linux/notifier.h> 70256694Snp#include <linux/inetdevice.h> 71256694Snp#include <linux/if_vlan.h> 72256694Snp#include <net/netevent.h> 73256694Snp 74256694Snpstatic spinlock_t req_lock; 75256694Snpstatic TAILQ_HEAD(c4iw_ep_list, c4iw_ep_common) req_list; 76256694Snpstatic struct work_struct c4iw_task; 77256694Snpstatic struct workqueue_struct *c4iw_taskq; 78256694Snpstatic LIST_HEAD(timeout_list); 79256694Snpstatic spinlock_t timeout_lock; 80256694Snp 81256694Snpstatic void process_req(struct work_struct *ctx); 82256694Snpstatic void start_ep_timer(struct c4iw_ep *ep); 83256694Snpstatic void stop_ep_timer(struct c4iw_ep *ep); 84256694Snpstatic int set_tcpinfo(struct c4iw_ep *ep); 85256694Snpstatic enum c4iw_ep_state state_read(struct c4iw_ep_common *epc); 86256694Snpstatic void __state_set(struct c4iw_ep_common *epc, enum c4iw_ep_state tostate); 87256694Snpstatic void state_set(struct c4iw_ep_common *epc, enum c4iw_ep_state tostate); 88256694Snpstatic void *alloc_ep(int size, gfp_t flags); 89256694Snpvoid __free_ep(struct c4iw_ep_common *epc); 90256694Snpstatic struct rtentry * find_route(__be32 local_ip, __be32 peer_ip, __be16 local_port, 91256694Snp __be16 peer_port, u8 tos); 92256694Snpstatic int close_socket(struct c4iw_ep_common *epc, int close); 93256694Snpstatic int shutdown_socket(struct c4iw_ep_common *epc); 94256694Snpstatic void abort_socket(struct c4iw_ep *ep); 95256694Snpstatic void send_mpa_req(struct c4iw_ep *ep); 96256694Snpstatic int send_mpa_reject(struct c4iw_ep *ep, const void *pdata, u8 plen); 97256694Snpstatic int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen); 98256694Snpstatic void close_complete_upcall(struct c4iw_ep *ep); 99256694Snpstatic int abort_connection(struct c4iw_ep *ep); 100256694Snpstatic void peer_close_upcall(struct c4iw_ep *ep); 101256694Snpstatic void peer_abort_upcall(struct c4iw_ep *ep); 102256694Snpstatic void connect_reply_upcall(struct c4iw_ep *ep, int status); 103256694Snpstatic void connect_request_upcall(struct c4iw_ep *ep); 104256694Snpstatic void established_upcall(struct c4iw_ep *ep); 105256694Snpstatic void process_mpa_reply(struct c4iw_ep *ep); 106256694Snpstatic void process_mpa_request(struct c4iw_ep *ep); 107256694Snpstatic void process_peer_close(struct c4iw_ep *ep); 108256694Snpstatic void process_conn_error(struct c4iw_ep *ep); 109256694Snpstatic void process_close_complete(struct c4iw_ep *ep); 110256694Snpstatic void ep_timeout(unsigned long arg); 111256694Snpstatic void init_sock(struct c4iw_ep_common *epc); 112256694Snpstatic void process_data(struct c4iw_ep *ep); 113256694Snpstatic void process_connected(struct c4iw_ep *ep); 114256694Snpstatic struct socket * dequeue_socket(struct socket *head, struct sockaddr_in **remote, struct c4iw_ep *child_ep); 115256694Snpstatic void process_newconn(struct c4iw_ep *parent_ep); 116256694Snpstatic int c4iw_so_upcall(struct socket *so, void *arg, int waitflag); 117256694Snpstatic void process_socket_event(struct c4iw_ep *ep); 118256694Snpstatic void release_ep_resources(struct c4iw_ep *ep); 119256694Snp 120256694Snp#define START_EP_TIMER(ep) \ 121256694Snp do { \ 122256694Snp CTR3(KTR_IW_CXGBE, "start_ep_timer (%s:%d) ep %p", \ 123256694Snp __func__, __LINE__, (ep)); \ 124256694Snp start_ep_timer(ep); \ 125256694Snp } while (0) 126256694Snp 127256694Snp#define STOP_EP_TIMER(ep) \ 128256694Snp do { \ 129256694Snp CTR3(KTR_IW_CXGBE, "stop_ep_timer (%s:%d) ep %p", \ 130256694Snp __func__, __LINE__, (ep)); \ 131256694Snp stop_ep_timer(ep); \ 132256694Snp } while (0) 133256694Snp 134256694Snp#ifdef KTR 135256694Snpstatic char *states[] = { 136256694Snp "idle", 137256694Snp "listen", 138256694Snp "connecting", 139256694Snp "mpa_wait_req", 140256694Snp "mpa_req_sent", 141256694Snp "mpa_req_rcvd", 142256694Snp "mpa_rep_sent", 143256694Snp "fpdu_mode", 144256694Snp "aborting", 145256694Snp "closing", 146256694Snp "moribund", 147256694Snp "dead", 148256694Snp NULL, 149256694Snp}; 150256694Snp#endif 151256694Snp 152256694Snpstatic void 153256694Snpprocess_req(struct work_struct *ctx) 154256694Snp{ 155256694Snp struct c4iw_ep_common *epc; 156256694Snp 157256694Snp spin_lock(&req_lock); 158256694Snp while (!TAILQ_EMPTY(&req_list)) { 159256694Snp epc = TAILQ_FIRST(&req_list); 160256694Snp TAILQ_REMOVE(&req_list, epc, entry); 161256694Snp epc->entry.tqe_prev = NULL; 162256694Snp spin_unlock(&req_lock); 163256694Snp if (epc->so) 164256694Snp process_socket_event((struct c4iw_ep *)epc); 165256694Snp c4iw_put_ep(epc); 166256694Snp spin_lock(&req_lock); 167256694Snp } 168256694Snp spin_unlock(&req_lock); 169256694Snp} 170256694Snp 171256694Snp/* 172256694Snp * XXX: doesn't belong here in the iWARP driver. 173256694Snp * XXX: assumes that the connection was offloaded by cxgbe/t4_tom if TF_TOE is 174256694Snp * set. Is this a valid assumption for active open? 175256694Snp */ 176256694Snpstatic int 177256694Snpset_tcpinfo(struct c4iw_ep *ep) 178256694Snp{ 179256694Snp struct socket *so = ep->com.so; 180256694Snp struct inpcb *inp = sotoinpcb(so); 181256694Snp struct tcpcb *tp; 182256694Snp struct toepcb *toep; 183256694Snp int rc = 0; 184256694Snp 185256694Snp INP_WLOCK(inp); 186256694Snp tp = intotcpcb(inp); 187256694Snp if ((tp->t_flags & TF_TOE) == 0) { 188256694Snp rc = EINVAL; 189256694Snp log(LOG_ERR, "%s: connection not offloaded (so %p, ep %p)\n", 190256694Snp __func__, so, ep); 191256694Snp goto done; 192256694Snp } 193256694Snp toep = TOEPCB(so); 194256694Snp 195256694Snp ep->hwtid = toep->tid; 196256694Snp ep->snd_seq = tp->snd_nxt; 197256694Snp ep->rcv_seq = tp->rcv_nxt; 198256694Snp ep->emss = max(tp->t_maxseg, 128); 199256694Snpdone: 200256694Snp INP_WUNLOCK(inp); 201256694Snp return (rc); 202256694Snp 203256694Snp} 204256694Snp 205256694Snpstatic struct rtentry * 206256694Snpfind_route(__be32 local_ip, __be32 peer_ip, __be16 local_port, 207256694Snp __be16 peer_port, u8 tos) 208256694Snp{ 209256694Snp struct route iproute; 210256694Snp struct sockaddr_in *dst = (struct sockaddr_in *)&iproute.ro_dst; 211256694Snp 212256694Snp CTR5(KTR_IW_CXGBE, "%s:frtB %x, %x, %d, %d", __func__, local_ip, 213256694Snp peer_ip, ntohs(local_port), ntohs(peer_port)); 214256694Snp bzero(&iproute, sizeof iproute); 215256694Snp dst->sin_family = AF_INET; 216256694Snp dst->sin_len = sizeof *dst; 217256694Snp dst->sin_addr.s_addr = peer_ip; 218256694Snp 219256694Snp rtalloc(&iproute); 220256694Snp CTR2(KTR_IW_CXGBE, "%s:frtE %p", __func__, (uint64_t)iproute.ro_rt); 221256694Snp return iproute.ro_rt; 222256694Snp} 223256694Snp 224256694Snpstatic int 225256694Snpclose_socket(struct c4iw_ep_common *epc, int close) 226256694Snp{ 227256694Snp struct socket *so = epc->so; 228256694Snp int rc; 229256694Snp 230256694Snp CTR4(KTR_IW_CXGBE, "%s: so %p, ep %p, state %s", __func__, epc, so, 231256694Snp states[epc->state]); 232256694Snp 233256694Snp SOCK_LOCK(so); 234256694Snp soupcall_clear(so, SO_RCV); 235256694Snp SOCK_UNLOCK(so); 236256694Snp 237256694Snp if (close) 238256694Snp rc = soclose(so); 239256694Snp else 240256694Snp rc = soshutdown(so, SHUT_WR | SHUT_RD); 241256694Snp epc->so = NULL; 242256694Snp 243256694Snp return (rc); 244256694Snp} 245256694Snp 246256694Snpstatic int 247256694Snpshutdown_socket(struct c4iw_ep_common *epc) 248256694Snp{ 249256694Snp 250256694Snp CTR4(KTR_IW_CXGBE, "%s: so %p, ep %p, state %s", __func__, epc->so, epc, 251256694Snp states[epc->state]); 252256694Snp 253256694Snp return (soshutdown(epc->so, SHUT_WR)); 254256694Snp} 255256694Snp 256256694Snpstatic void 257256694Snpabort_socket(struct c4iw_ep *ep) 258256694Snp{ 259256694Snp struct sockopt sopt; 260256694Snp int rc; 261256694Snp struct linger l; 262256694Snp 263256694Snp CTR4(KTR_IW_CXGBE, "%s ep %p so %p state %s", __func__, ep, ep->com.so, 264256694Snp states[ep->com.state]); 265256694Snp 266256694Snp l.l_onoff = 1; 267256694Snp l.l_linger = 0; 268256694Snp 269256694Snp /* linger_time of 0 forces RST to be sent */ 270256694Snp sopt.sopt_dir = SOPT_SET; 271256694Snp sopt.sopt_level = SOL_SOCKET; 272256694Snp sopt.sopt_name = SO_LINGER; 273256694Snp sopt.sopt_val = (caddr_t)&l; 274256694Snp sopt.sopt_valsize = sizeof l; 275256694Snp sopt.sopt_td = NULL; 276256694Snp rc = sosetopt(ep->com.so, &sopt); 277256694Snp if (rc) { 278256694Snp log(LOG_ERR, "%s: can't set linger to 0, no RST! err %d\n", 279256694Snp __func__, rc); 280256694Snp } 281256694Snp} 282256694Snp 283256694Snpstatic void 284256694Snpprocess_peer_close(struct c4iw_ep *ep) 285256694Snp{ 286256694Snp struct c4iw_qp_attributes attrs; 287256694Snp int disconnect = 1; 288256694Snp int release = 0; 289256694Snp 290256694Snp CTR4(KTR_IW_CXGBE, "%s:ppcB ep %p so %p state %s", __func__, ep, 291256694Snp ep->com.so, states[ep->com.state]); 292256694Snp 293256694Snp mutex_lock(&ep->com.mutex); 294256694Snp switch (ep->com.state) { 295256694Snp 296256694Snp case MPA_REQ_WAIT: 297256694Snp CTR2(KTR_IW_CXGBE, "%s:ppc1 %p MPA_REQ_WAIT CLOSING", 298256694Snp __func__, ep); 299256694Snp __state_set(&ep->com, CLOSING); 300256694Snp break; 301256694Snp 302256694Snp case MPA_REQ_SENT: 303256694Snp CTR2(KTR_IW_CXGBE, "%s:ppc2 %p MPA_REQ_SENT CLOSING", 304256694Snp __func__, ep); 305256694Snp __state_set(&ep->com, DEAD); 306256694Snp connect_reply_upcall(ep, -ECONNABORTED); 307256694Snp 308256694Snp disconnect = 0; 309256694Snp STOP_EP_TIMER(ep); 310256694Snp close_socket(&ep->com, 0); 311256694Snp ep->com.cm_id->rem_ref(ep->com.cm_id); 312256694Snp ep->com.cm_id = NULL; 313256694Snp ep->com.qp = NULL; 314256694Snp release = 1; 315256694Snp break; 316256694Snp 317256694Snp case MPA_REQ_RCVD: 318256694Snp 319256694Snp /* 320256694Snp * We're gonna mark this puppy DEAD, but keep 321256694Snp * the reference on it until the ULP accepts or 322256694Snp * rejects the CR. 323256694Snp */ 324256694Snp CTR2(KTR_IW_CXGBE, "%s:ppc3 %p MPA_REQ_RCVD CLOSING", 325256694Snp __func__, ep); 326256694Snp __state_set(&ep->com, CLOSING); 327256694Snp c4iw_get_ep(&ep->com); 328256694Snp break; 329256694Snp 330256694Snp case MPA_REP_SENT: 331256694Snp CTR2(KTR_IW_CXGBE, "%s:ppc4 %p MPA_REP_SENT CLOSING", 332256694Snp __func__, ep); 333256694Snp __state_set(&ep->com, CLOSING); 334256694Snp break; 335256694Snp 336256694Snp case FPDU_MODE: 337256694Snp CTR2(KTR_IW_CXGBE, "%s:ppc5 %p FPDU_MODE CLOSING", 338256694Snp __func__, ep); 339256694Snp START_EP_TIMER(ep); 340256694Snp __state_set(&ep->com, CLOSING); 341256694Snp attrs.next_state = C4IW_QP_STATE_CLOSING; 342256694Snp c4iw_modify_qp(ep->com.dev, ep->com.qp, 343256694Snp C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 344256694Snp peer_close_upcall(ep); 345256694Snp break; 346256694Snp 347256694Snp case ABORTING: 348256694Snp CTR2(KTR_IW_CXGBE, "%s:ppc6 %p ABORTING (disconn)", 349256694Snp __func__, ep); 350256694Snp disconnect = 0; 351256694Snp break; 352256694Snp 353256694Snp case CLOSING: 354256694Snp CTR2(KTR_IW_CXGBE, "%s:ppc7 %p CLOSING MORIBUND", 355256694Snp __func__, ep); 356256694Snp __state_set(&ep->com, MORIBUND); 357256694Snp disconnect = 0; 358256694Snp break; 359256694Snp 360256694Snp case MORIBUND: 361256694Snp CTR2(KTR_IW_CXGBE, "%s:ppc8 %p MORIBUND DEAD", __func__, 362256694Snp ep); 363256694Snp STOP_EP_TIMER(ep); 364256694Snp if (ep->com.cm_id && ep->com.qp) { 365256694Snp attrs.next_state = C4IW_QP_STATE_IDLE; 366256694Snp c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 367256694Snp C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 368256694Snp } 369256694Snp close_socket(&ep->com, 0); 370256694Snp close_complete_upcall(ep); 371256694Snp __state_set(&ep->com, DEAD); 372256694Snp release = 1; 373256694Snp disconnect = 0; 374256694Snp break; 375256694Snp 376256694Snp case DEAD: 377256694Snp CTR2(KTR_IW_CXGBE, "%s:ppc9 %p DEAD (disconn)", 378256694Snp __func__, ep); 379256694Snp disconnect = 0; 380256694Snp break; 381256694Snp 382256694Snp default: 383256694Snp panic("%s: ep %p state %d", __func__, ep, 384256694Snp ep->com.state); 385256694Snp break; 386256694Snp } 387256694Snp 388256694Snp mutex_unlock(&ep->com.mutex); 389256694Snp 390256694Snp if (disconnect) { 391256694Snp 392256694Snp CTR2(KTR_IW_CXGBE, "%s:ppca %p", __func__, ep); 393256694Snp c4iw_ep_disconnect(ep, 0, M_NOWAIT); 394256694Snp } 395256694Snp if (release) { 396256694Snp 397256694Snp CTR2(KTR_IW_CXGBE, "%s:ppcb %p", __func__, ep); 398256694Snp c4iw_put_ep(&ep->com); 399256694Snp } 400256694Snp CTR2(KTR_IW_CXGBE, "%s:ppcE %p", __func__, ep); 401256694Snp return; 402256694Snp} 403256694Snp 404256694Snpstatic void 405256694Snpprocess_conn_error(struct c4iw_ep *ep) 406256694Snp{ 407256694Snp struct c4iw_qp_attributes attrs; 408256694Snp int ret; 409256694Snp int state; 410256694Snp 411256694Snp state = state_read(&ep->com); 412256694Snp CTR5(KTR_IW_CXGBE, "%s:pceB ep %p so %p so->so_error %u state %s", 413256694Snp __func__, ep, ep->com.so, ep->com.so->so_error, 414256694Snp states[ep->com.state]); 415256694Snp 416256694Snp switch (state) { 417256694Snp 418256694Snp case MPA_REQ_WAIT: 419256694Snp STOP_EP_TIMER(ep); 420256694Snp break; 421256694Snp 422256694Snp case MPA_REQ_SENT: 423256694Snp STOP_EP_TIMER(ep); 424256694Snp connect_reply_upcall(ep, -ECONNRESET); 425256694Snp break; 426256694Snp 427256694Snp case MPA_REP_SENT: 428256694Snp ep->com.rpl_err = ECONNRESET; 429256694Snp CTR1(KTR_IW_CXGBE, "waking up ep %p", ep); 430256694Snp break; 431256694Snp 432256694Snp case MPA_REQ_RCVD: 433256694Snp 434256694Snp /* 435256694Snp * We're gonna mark this puppy DEAD, but keep 436256694Snp * the reference on it until the ULP accepts or 437256694Snp * rejects the CR. 438256694Snp */ 439256694Snp c4iw_get_ep(&ep->com); 440256694Snp break; 441256694Snp 442256694Snp case MORIBUND: 443256694Snp case CLOSING: 444256694Snp STOP_EP_TIMER(ep); 445256694Snp /*FALLTHROUGH*/ 446256694Snp case FPDU_MODE: 447256694Snp 448256694Snp if (ep->com.cm_id && ep->com.qp) { 449256694Snp 450256694Snp attrs.next_state = C4IW_QP_STATE_ERROR; 451256694Snp ret = c4iw_modify_qp(ep->com.qp->rhp, 452256694Snp ep->com.qp, C4IW_QP_ATTR_NEXT_STATE, 453256694Snp &attrs, 1); 454256694Snp if (ret) 455256694Snp log(LOG_ERR, 456256694Snp "%s - qp <- error failed!\n", 457256694Snp __func__); 458256694Snp } 459256694Snp peer_abort_upcall(ep); 460256694Snp break; 461256694Snp 462256694Snp case ABORTING: 463256694Snp break; 464256694Snp 465256694Snp case DEAD: 466256694Snp CTR2(KTR_IW_CXGBE, "%s so_error %d IN DEAD STATE!!!!", 467256694Snp __func__, ep->com.so->so_error); 468256694Snp return; 469256694Snp 470256694Snp default: 471256694Snp panic("%s: ep %p state %d", __func__, ep, state); 472256694Snp break; 473256694Snp } 474256694Snp 475256694Snp if (state != ABORTING) { 476256694Snp 477256694Snp CTR2(KTR_IW_CXGBE, "%s:pce1 %p", __func__, ep); 478256694Snp close_socket(&ep->com, 0); 479256694Snp state_set(&ep->com, DEAD); 480256694Snp c4iw_put_ep(&ep->com); 481256694Snp } 482256694Snp CTR2(KTR_IW_CXGBE, "%s:pceE %p", __func__, ep); 483256694Snp return; 484256694Snp} 485256694Snp 486256694Snpstatic void 487256694Snpprocess_close_complete(struct c4iw_ep *ep) 488256694Snp{ 489256694Snp struct c4iw_qp_attributes attrs; 490256694Snp int release = 0; 491256694Snp 492256694Snp CTR4(KTR_IW_CXGBE, "%s:pccB ep %p so %p state %s", __func__, ep, 493256694Snp ep->com.so, states[ep->com.state]); 494256694Snp 495256694Snp /* The cm_id may be null if we failed to connect */ 496256694Snp mutex_lock(&ep->com.mutex); 497256694Snp 498256694Snp switch (ep->com.state) { 499256694Snp 500256694Snp case CLOSING: 501256694Snp CTR2(KTR_IW_CXGBE, "%s:pcc1 %p CLOSING MORIBUND", 502256694Snp __func__, ep); 503256694Snp __state_set(&ep->com, MORIBUND); 504256694Snp break; 505256694Snp 506256694Snp case MORIBUND: 507256694Snp CTR2(KTR_IW_CXGBE, "%s:pcc1 %p MORIBUND DEAD", __func__, 508256694Snp ep); 509256694Snp STOP_EP_TIMER(ep); 510256694Snp 511256694Snp if ((ep->com.cm_id) && (ep->com.qp)) { 512256694Snp 513256694Snp CTR2(KTR_IW_CXGBE, "%s:pcc2 %p QP_STATE_IDLE", 514256694Snp __func__, ep); 515256694Snp attrs.next_state = C4IW_QP_STATE_IDLE; 516256694Snp c4iw_modify_qp(ep->com.dev, 517256694Snp ep->com.qp, 518256694Snp C4IW_QP_ATTR_NEXT_STATE, 519256694Snp &attrs, 1); 520256694Snp } 521256694Snp 522256694Snp if (ep->parent_ep) { 523256694Snp 524256694Snp CTR2(KTR_IW_CXGBE, "%s:pcc3 %p", __func__, ep); 525256694Snp close_socket(&ep->com, 1); 526256694Snp } 527256694Snp else { 528256694Snp 529256694Snp CTR2(KTR_IW_CXGBE, "%s:pcc4 %p", __func__, ep); 530256694Snp close_socket(&ep->com, 0); 531256694Snp } 532256694Snp close_complete_upcall(ep); 533256694Snp __state_set(&ep->com, DEAD); 534256694Snp release = 1; 535256694Snp break; 536256694Snp 537256694Snp case ABORTING: 538256694Snp CTR2(KTR_IW_CXGBE, "%s:pcc5 %p ABORTING", __func__, ep); 539256694Snp break; 540256694Snp 541256694Snp case DEAD: 542256694Snp default: 543256694Snp CTR2(KTR_IW_CXGBE, "%s:pcc6 %p DEAD", __func__, ep); 544256694Snp panic("%s:pcc6 %p DEAD", __func__, ep); 545256694Snp break; 546256694Snp } 547256694Snp mutex_unlock(&ep->com.mutex); 548256694Snp 549256694Snp if (release) { 550256694Snp 551256694Snp CTR2(KTR_IW_CXGBE, "%s:pcc7 %p", __func__, ep); 552256694Snp c4iw_put_ep(&ep->com); 553256694Snp } 554256694Snp CTR2(KTR_IW_CXGBE, "%s:pccE %p", __func__, ep); 555256694Snp return; 556256694Snp} 557256694Snp 558256694Snpstatic void 559256694Snpinit_sock(struct c4iw_ep_common *epc) 560256694Snp{ 561256694Snp int rc; 562256694Snp struct sockopt sopt; 563256694Snp struct socket *so = epc->so; 564256694Snp int on = 1; 565256694Snp 566256694Snp SOCK_LOCK(so); 567256694Snp soupcall_set(so, SO_RCV, c4iw_so_upcall, epc); 568256694Snp so->so_state |= SS_NBIO; 569256694Snp SOCK_UNLOCK(so); 570256694Snp sopt.sopt_dir = SOPT_SET; 571256694Snp sopt.sopt_level = IPPROTO_TCP; 572256694Snp sopt.sopt_name = TCP_NODELAY; 573256694Snp sopt.sopt_val = (caddr_t)&on; 574256694Snp sopt.sopt_valsize = sizeof on; 575256694Snp sopt.sopt_td = NULL; 576256694Snp rc = sosetopt(so, &sopt); 577256694Snp if (rc) { 578256694Snp log(LOG_ERR, "%s: can't set TCP_NODELAY on so %p (%d)\n", 579256694Snp __func__, so, rc); 580256694Snp } 581256694Snp} 582256694Snp 583256694Snpstatic void 584256694Snpprocess_data(struct c4iw_ep *ep) 585256694Snp{ 586256694Snp struct sockaddr_in *local, *remote; 587256694Snp 588256694Snp CTR5(KTR_IW_CXGBE, "%s: so %p, ep %p, state %s, sb_cc %d", __func__, 589256694Snp ep->com.so, ep, states[ep->com.state], ep->com.so->so_rcv.sb_cc); 590256694Snp 591256694Snp switch (state_read(&ep->com)) { 592256694Snp case MPA_REQ_SENT: 593256694Snp process_mpa_reply(ep); 594256694Snp break; 595256694Snp case MPA_REQ_WAIT: 596256694Snp in_getsockaddr(ep->com.so, (struct sockaddr **)&local); 597256694Snp in_getpeeraddr(ep->com.so, (struct sockaddr **)&remote); 598256694Snp ep->com.local_addr = *local; 599256694Snp ep->com.remote_addr = *remote; 600256694Snp free(local, M_SONAME); 601256694Snp free(remote, M_SONAME); 602256694Snp process_mpa_request(ep); 603256694Snp break; 604256694Snp default: 605256694Snp if (ep->com.so->so_rcv.sb_cc) 606256694Snp log(LOG_ERR, "%s: Unexpected streaming data. " 607256694Snp "ep %p, state %d, so %p, so_state 0x%x, sb_cc %u\n", 608256694Snp __func__, ep, state_read(&ep->com), ep->com.so, 609256694Snp ep->com.so->so_state, ep->com.so->so_rcv.sb_cc); 610256694Snp break; 611256694Snp } 612256694Snp} 613256694Snp 614256694Snpstatic void 615256694Snpprocess_connected(struct c4iw_ep *ep) 616256694Snp{ 617256694Snp 618256694Snp if ((ep->com.so->so_state & SS_ISCONNECTED) && !ep->com.so->so_error) 619256694Snp send_mpa_req(ep); 620256694Snp else { 621256694Snp connect_reply_upcall(ep, -ep->com.so->so_error); 622256694Snp close_socket(&ep->com, 0); 623256694Snp state_set(&ep->com, DEAD); 624256694Snp c4iw_put_ep(&ep->com); 625256694Snp } 626256694Snp} 627256694Snp 628256694Snpstatic struct socket * 629256694Snpdequeue_socket(struct socket *head, struct sockaddr_in **remote, 630256694Snp struct c4iw_ep *child_ep) 631256694Snp{ 632256694Snp struct socket *so; 633256694Snp 634256694Snp ACCEPT_LOCK(); 635256694Snp so = TAILQ_FIRST(&head->so_comp); 636256694Snp if (!so) { 637256694Snp ACCEPT_UNLOCK(); 638256694Snp return (NULL); 639256694Snp } 640256694Snp TAILQ_REMOVE(&head->so_comp, so, so_list); 641256694Snp head->so_qlen--; 642256694Snp SOCK_LOCK(so); 643256694Snp so->so_qstate &= ~SQ_COMP; 644256694Snp so->so_head = NULL; 645256694Snp soref(so); 646256694Snp soupcall_set(so, SO_RCV, c4iw_so_upcall, child_ep); 647256694Snp so->so_state |= SS_NBIO; 648256694Snp SOCK_UNLOCK(so); 649256694Snp ACCEPT_UNLOCK(); 650256694Snp soaccept(so, (struct sockaddr **)remote); 651256694Snp 652256694Snp return (so); 653256694Snp} 654256694Snp 655256694Snpstatic void 656256694Snpprocess_newconn(struct c4iw_ep *parent_ep) 657256694Snp{ 658256694Snp struct socket *child_so; 659256694Snp struct c4iw_ep *child_ep; 660256694Snp struct sockaddr_in *remote; 661256694Snp 662256694Snp child_ep = alloc_ep(sizeof(*child_ep), M_NOWAIT); 663256694Snp if (!child_ep) { 664256694Snp CTR3(KTR_IW_CXGBE, "%s: parent so %p, parent ep %p, ENOMEM", 665256694Snp __func__, parent_ep->com.so, parent_ep); 666256694Snp log(LOG_ERR, "%s: failed to allocate ep entry\n", __func__); 667256694Snp return; 668256694Snp } 669256694Snp 670256694Snp child_so = dequeue_socket(parent_ep->com.so, &remote, child_ep); 671256694Snp if (!child_so) { 672256694Snp CTR4(KTR_IW_CXGBE, 673256694Snp "%s: parent so %p, parent ep %p, child ep %p, dequeue err", 674256694Snp __func__, parent_ep->com.so, parent_ep, child_ep); 675256694Snp log(LOG_ERR, "%s: failed to dequeue child socket\n", __func__); 676256694Snp __free_ep(&child_ep->com); 677256694Snp return; 678256694Snp 679256694Snp } 680256694Snp 681256694Snp CTR5(KTR_IW_CXGBE, 682256694Snp "%s: parent so %p, parent ep %p, child so %p, child ep %p", 683256694Snp __func__, parent_ep->com.so, parent_ep, child_so, child_ep); 684256694Snp 685256694Snp child_ep->com.local_addr = parent_ep->com.local_addr; 686256694Snp child_ep->com.remote_addr = *remote; 687256694Snp child_ep->com.dev = parent_ep->com.dev; 688256694Snp child_ep->com.so = child_so; 689256694Snp child_ep->com.cm_id = NULL; 690256694Snp child_ep->com.thread = parent_ep->com.thread; 691256694Snp child_ep->parent_ep = parent_ep; 692256694Snp 693256694Snp free(remote, M_SONAME); 694256694Snp c4iw_get_ep(&parent_ep->com); 695256694Snp child_ep->parent_ep = parent_ep; 696256694Snp init_timer(&child_ep->timer); 697256694Snp state_set(&child_ep->com, MPA_REQ_WAIT); 698256694Snp START_EP_TIMER(child_ep); 699256694Snp 700256694Snp /* maybe the request has already been queued up on the socket... */ 701256694Snp process_mpa_request(child_ep); 702256694Snp} 703256694Snp 704256694Snpstatic int 705256694Snpc4iw_so_upcall(struct socket *so, void *arg, int waitflag) 706256694Snp{ 707256694Snp struct c4iw_ep *ep = arg; 708256694Snp 709256694Snp spin_lock(&req_lock); 710256694Snp 711256694Snp CTR6(KTR_IW_CXGBE, 712256694Snp "%s: so %p, so_state 0x%x, ep %p, ep_state %s, tqe_prev %p", 713256694Snp __func__, so, so->so_state, ep, states[ep->com.state], 714256694Snp ep->com.entry.tqe_prev); 715256694Snp 716256694Snp if (ep && ep->com.so && !ep->com.entry.tqe_prev) { 717256694Snp KASSERT(ep->com.so == so, ("%s: XXX review.", __func__)); 718256694Snp c4iw_get_ep(&ep->com); 719256694Snp TAILQ_INSERT_TAIL(&req_list, &ep->com, entry); 720256694Snp queue_work(c4iw_taskq, &c4iw_task); 721256694Snp } 722256694Snp 723256694Snp spin_unlock(&req_lock); 724256694Snp return (SU_OK); 725256694Snp} 726256694Snp 727256694Snpstatic void 728256694Snpprocess_socket_event(struct c4iw_ep *ep) 729256694Snp{ 730256694Snp int state = state_read(&ep->com); 731256694Snp struct socket *so = ep->com.so; 732256694Snp 733256694Snp CTR6(KTR_IW_CXGBE, "process_socket_event: so %p, so_state 0x%x, " 734256694Snp "so_err %d, sb_state 0x%x, ep %p, ep_state %s", so, so->so_state, 735256694Snp so->so_error, so->so_rcv.sb_state, ep, states[state]); 736256694Snp 737256694Snp if (state == CONNECTING) { 738256694Snp process_connected(ep); 739256694Snp return; 740256694Snp } 741256694Snp 742256694Snp if (state == LISTEN) { 743256694Snp process_newconn(ep); 744256694Snp return; 745256694Snp } 746256694Snp 747256694Snp /* connection error */ 748256694Snp if (so->so_error) { 749256694Snp process_conn_error(ep); 750256694Snp return; 751256694Snp } 752256694Snp 753256694Snp /* peer close */ 754256694Snp if ((so->so_rcv.sb_state & SBS_CANTRCVMORE) && state < CLOSING) { 755256694Snp process_peer_close(ep); 756256694Snp return; 757256694Snp } 758256694Snp 759256694Snp /* close complete */ 760256694Snp if (so->so_state & SS_ISDISCONNECTED) { 761256694Snp process_close_complete(ep); 762256694Snp return; 763256694Snp } 764256694Snp 765256694Snp /* rx data */ 766256694Snp process_data(ep); 767256694Snp} 768256694Snp 769256694SnpSYSCTL_NODE(_hw, OID_AUTO, iw_cxgbe, CTLFLAG_RD, 0, "iw_cxgbe driver parameters"); 770256694Snp 771256694Snpint db_delay_usecs = 1; 772256694SnpTUNABLE_INT("hw.iw_cxgbe.db_delay_usecs", &db_delay_usecs); 773256694SnpSYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, db_delay_usecs, CTLFLAG_RW, &db_delay_usecs, 0, 774256694Snp "Usecs to delay awaiting db fifo to drain"); 775256694Snp 776256694Snpstatic int dack_mode = 1; 777256694SnpTUNABLE_INT("hw.iw_cxgbe.dack_mode", &dack_mode); 778256694SnpSYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, dack_mode, CTLFLAG_RW, &dack_mode, 0, 779256694Snp "Delayed ack mode (default = 1)"); 780256694Snp 781256694Snpint c4iw_max_read_depth = 8; 782256694SnpTUNABLE_INT("hw.iw_cxgbe.c4iw_max_read_depth", &c4iw_max_read_depth); 783256694SnpSYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, c4iw_max_read_depth, CTLFLAG_RW, &c4iw_max_read_depth, 0, 784256694Snp "Per-connection max ORD/IRD (default = 8)"); 785256694Snp 786256694Snpstatic int enable_tcp_timestamps; 787256694SnpTUNABLE_INT("hw.iw_cxgbe.enable_tcp_timestamps", &enable_tcp_timestamps); 788256694SnpSYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, enable_tcp_timestamps, CTLFLAG_RW, &enable_tcp_timestamps, 0, 789256694Snp "Enable tcp timestamps (default = 0)"); 790256694Snp 791256694Snpstatic int enable_tcp_sack; 792256694SnpTUNABLE_INT("hw.iw_cxgbe.enable_tcp_sack", &enable_tcp_sack); 793256694SnpSYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, enable_tcp_sack, CTLFLAG_RW, &enable_tcp_sack, 0, 794256694Snp "Enable tcp SACK (default = 0)"); 795256694Snp 796256694Snpstatic int enable_tcp_window_scaling = 1; 797256694SnpTUNABLE_INT("hw.iw_cxgbe.enable_tcp_window_scaling", &enable_tcp_window_scaling); 798256694SnpSYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, enable_tcp_window_scaling, CTLFLAG_RW, &enable_tcp_window_scaling, 0, 799256694Snp "Enable tcp window scaling (default = 1)"); 800256694Snp 801256694Snpint c4iw_debug = 1; 802256694SnpTUNABLE_INT("hw.iw_cxgbe.c4iw_debug", &c4iw_debug); 803256694SnpSYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, c4iw_debug, CTLFLAG_RW, &c4iw_debug, 0, 804256694Snp "Enable debug logging (default = 0)"); 805256694Snp 806256694Snpstatic int peer2peer; 807256694SnpTUNABLE_INT("hw.iw_cxgbe.peer2peer", &peer2peer); 808256694SnpSYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, peer2peer, CTLFLAG_RW, &peer2peer, 0, 809256694Snp "Support peer2peer ULPs (default = 0)"); 810256694Snp 811256694Snpstatic int p2p_type = FW_RI_INIT_P2PTYPE_READ_REQ; 812256694SnpTUNABLE_INT("hw.iw_cxgbe.p2p_type", &p2p_type); 813256694SnpSYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, p2p_type, CTLFLAG_RW, &p2p_type, 0, 814256694Snp "RDMAP opcode to use for the RTR message: 1 = RDMA_READ 0 = RDMA_WRITE (default 1)"); 815256694Snp 816256694Snpstatic int ep_timeout_secs = 60; 817256694SnpTUNABLE_INT("hw.iw_cxgbe.ep_timeout_secs", &ep_timeout_secs); 818256694SnpSYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, ep_timeout_secs, CTLFLAG_RW, &ep_timeout_secs, 0, 819256694Snp "CM Endpoint operation timeout in seconds (default = 60)"); 820256694Snp 821256694Snpstatic int mpa_rev = 1; 822256694SnpTUNABLE_INT("hw.iw_cxgbe.mpa_rev", &mpa_rev); 823256694Snp#ifdef IW_CM_MPAV2 824256694SnpSYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, mpa_rev, CTLFLAG_RW, &mpa_rev, 0, 825256694Snp "MPA Revision, 0 supports amso1100, 1 is RFC0544 spec compliant, 2 is IETF MPA Peer Connect Draft compliant (default = 1)"); 826256694Snp#else 827256694SnpSYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, mpa_rev, CTLFLAG_RW, &mpa_rev, 0, 828256694Snp "MPA Revision, 0 supports amso1100, 1 is RFC0544 spec compliant (default = 1)"); 829256694Snp#endif 830256694Snp 831256694Snpstatic int markers_enabled; 832256694SnpTUNABLE_INT("hw.iw_cxgbe.markers_enabled", &markers_enabled); 833256694SnpSYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, markers_enabled, CTLFLAG_RW, &markers_enabled, 0, 834256694Snp "Enable MPA MARKERS (default(0) = disabled)"); 835256694Snp 836256694Snpstatic int crc_enabled = 1; 837256694SnpTUNABLE_INT("hw.iw_cxgbe.crc_enabled", &crc_enabled); 838256694SnpSYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, crc_enabled, CTLFLAG_RW, &crc_enabled, 0, 839256694Snp "Enable MPA CRC (default(1) = enabled)"); 840256694Snp 841256694Snpstatic int rcv_win = 256 * 1024; 842256694SnpTUNABLE_INT("hw.iw_cxgbe.rcv_win", &rcv_win); 843256694SnpSYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, rcv_win, CTLFLAG_RW, &rcv_win, 0, 844256694Snp "TCP receive window in bytes (default = 256KB)"); 845256694Snp 846256694Snpstatic int snd_win = 128 * 1024; 847256694SnpTUNABLE_INT("hw.iw_cxgbe.snd_win", &snd_win); 848256694SnpSYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, snd_win, CTLFLAG_RW, &snd_win, 0, 849256694Snp "TCP send window in bytes (default = 128KB)"); 850256694Snp 851256694Snpint db_fc_threshold = 2000; 852256694SnpTUNABLE_INT("hw.iw_cxgbe.db_fc_threshold", &db_fc_threshold); 853256694SnpSYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, db_fc_threshold, CTLFLAG_RW, &db_fc_threshold, 0, 854256694Snp "QP count/threshold that triggers automatic"); 855256694Snp 856256694Snpstatic void 857256694Snpstart_ep_timer(struct c4iw_ep *ep) 858256694Snp{ 859256694Snp 860256694Snp if (timer_pending(&ep->timer)) { 861256694Snp CTR2(KTR_IW_CXGBE, "%s: ep %p, already started", __func__, ep); 862256694Snp printk(KERN_ERR "%s timer already started! ep %p\n", __func__, 863256694Snp ep); 864256694Snp return; 865256694Snp } 866256694Snp clear_bit(TIMEOUT, &ep->com.flags); 867256694Snp c4iw_get_ep(&ep->com); 868256694Snp ep->timer.expires = jiffies + ep_timeout_secs * HZ; 869256694Snp ep->timer.data = (unsigned long)ep; 870256694Snp ep->timer.function = ep_timeout; 871256694Snp add_timer(&ep->timer); 872256694Snp} 873256694Snp 874256694Snpstatic void 875256694Snpstop_ep_timer(struct c4iw_ep *ep) 876256694Snp{ 877256694Snp 878256694Snp del_timer_sync(&ep->timer); 879256694Snp if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) { 880256694Snp c4iw_put_ep(&ep->com); 881256694Snp } 882256694Snp} 883256694Snp 884256694Snpstatic enum 885256694Snpc4iw_ep_state state_read(struct c4iw_ep_common *epc) 886256694Snp{ 887256694Snp enum c4iw_ep_state state; 888256694Snp 889256694Snp mutex_lock(&epc->mutex); 890256694Snp state = epc->state; 891256694Snp mutex_unlock(&epc->mutex); 892256694Snp 893256694Snp return (state); 894256694Snp} 895256694Snp 896256694Snpstatic void 897256694Snp__state_set(struct c4iw_ep_common *epc, enum c4iw_ep_state new) 898256694Snp{ 899256694Snp 900256694Snp epc->state = new; 901256694Snp} 902256694Snp 903256694Snpstatic void 904256694Snpstate_set(struct c4iw_ep_common *epc, enum c4iw_ep_state new) 905256694Snp{ 906256694Snp 907256694Snp mutex_lock(&epc->mutex); 908256694Snp __state_set(epc, new); 909256694Snp mutex_unlock(&epc->mutex); 910256694Snp} 911256694Snp 912256694Snpstatic void * 913256694Snpalloc_ep(int size, gfp_t gfp) 914256694Snp{ 915256694Snp struct c4iw_ep_common *epc; 916256694Snp 917256694Snp epc = kzalloc(size, gfp); 918256694Snp if (epc == NULL) 919256694Snp return (NULL); 920256694Snp 921256694Snp kref_init(&epc->kref); 922256694Snp mutex_init(&epc->mutex); 923256694Snp c4iw_init_wr_wait(&epc->wr_wait); 924256694Snp 925256694Snp return (epc); 926256694Snp} 927256694Snp 928256694Snpvoid 929256694Snp__free_ep(struct c4iw_ep_common *epc) 930256694Snp{ 931256694Snp CTR2(KTR_IW_CXGBE, "%s:feB %p", __func__, epc); 932256694Snp KASSERT(!epc->so, ("%s warning ep->so %p \n", __func__, epc->so)); 933256694Snp KASSERT(!epc->entry.tqe_prev, ("%s epc %p still on req list!\n", __func__, epc)); 934256694Snp free(epc, M_DEVBUF); 935256694Snp CTR2(KTR_IW_CXGBE, "%s:feE %p", __func__, epc); 936256694Snp} 937256694Snp 938256694Snpvoid _c4iw_free_ep(struct kref *kref) 939256694Snp{ 940256694Snp struct c4iw_ep *ep; 941256694Snp struct c4iw_ep_common *epc; 942256694Snp 943256694Snp ep = container_of(kref, struct c4iw_ep, com.kref); 944256694Snp epc = &ep->com; 945256694Snp KASSERT(!epc->so, ("%s ep->so %p", __func__, epc->so)); 946256694Snp KASSERT(!epc->entry.tqe_prev, ("%s epc %p still on req list", 947256694Snp __func__, epc)); 948256694Snp kfree(ep); 949256694Snp} 950256694Snp 951256694Snpstatic void release_ep_resources(struct c4iw_ep *ep) 952256694Snp{ 953256694Snp CTR2(KTR_IW_CXGBE, "%s:rerB %p", __func__, ep); 954256694Snp set_bit(RELEASE_RESOURCES, &ep->com.flags); 955256694Snp c4iw_put_ep(&ep->com); 956256694Snp CTR2(KTR_IW_CXGBE, "%s:rerE %p", __func__, ep); 957256694Snp} 958256694Snp 959256694Snpstatic void 960256694Snpsend_mpa_req(struct c4iw_ep *ep) 961256694Snp{ 962256694Snp int mpalen; 963256694Snp struct mpa_message *mpa; 964256694Snp struct mpa_v2_conn_params mpa_v2_params; 965256694Snp struct mbuf *m; 966256694Snp char mpa_rev_to_use = mpa_rev; 967256694Snp int err; 968256694Snp 969256694Snp if (ep->retry_with_mpa_v1) 970256694Snp mpa_rev_to_use = 1; 971256694Snp mpalen = sizeof(*mpa) + ep->plen; 972256694Snp if (mpa_rev_to_use == 2) 973256694Snp mpalen += sizeof(struct mpa_v2_conn_params); 974256694Snp 975256694Snp if (mpalen > MHLEN) 976256694Snp CXGBE_UNIMPLEMENTED(__func__); 977256694Snp 978256694Snp m = m_gethdr(M_NOWAIT, MT_DATA); 979256694Snp if (m == NULL) { 980256694Snp connect_reply_upcall(ep, -ENOMEM); 981256694Snp return; 982256694Snp } 983256694Snp 984256694Snp mpa = mtod(m, struct mpa_message *); 985256694Snp m->m_len = mpalen; 986256694Snp m->m_pkthdr.len = mpalen; 987256694Snp memcpy(mpa->key, MPA_KEY_REQ, sizeof(mpa->key)); 988256694Snp mpa->flags = (crc_enabled ? MPA_CRC : 0) | 989256694Snp (markers_enabled ? MPA_MARKERS : 0) | 990256694Snp (mpa_rev_to_use == 2 ? MPA_ENHANCED_RDMA_CONN : 0); 991256694Snp mpa->private_data_size = htons(ep->plen); 992256694Snp mpa->revision = mpa_rev_to_use; 993256694Snp 994256694Snp if (mpa_rev_to_use == 1) { 995256694Snp ep->tried_with_mpa_v1 = 1; 996256694Snp ep->retry_with_mpa_v1 = 0; 997256694Snp } 998256694Snp 999256694Snp if (mpa_rev_to_use == 2) { 1000256694Snp mpa->private_data_size += 1001256694Snp htons(sizeof(struct mpa_v2_conn_params)); 1002256694Snp mpa_v2_params.ird = htons((u16)ep->ird); 1003256694Snp mpa_v2_params.ord = htons((u16)ep->ord); 1004256694Snp 1005256694Snp if (peer2peer) { 1006256694Snp mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL); 1007256694Snp 1008256694Snp if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE) { 1009256694Snp mpa_v2_params.ord |= 1010256694Snp htons(MPA_V2_RDMA_WRITE_RTR); 1011256694Snp } else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) { 1012256694Snp mpa_v2_params.ord |= 1013256694Snp htons(MPA_V2_RDMA_READ_RTR); 1014256694Snp } 1015256694Snp } 1016256694Snp memcpy(mpa->private_data, &mpa_v2_params, 1017256694Snp sizeof(struct mpa_v2_conn_params)); 1018256694Snp 1019256694Snp if (ep->plen) { 1020256694Snp 1021256694Snp memcpy(mpa->private_data + 1022256694Snp sizeof(struct mpa_v2_conn_params), 1023256694Snp ep->mpa_pkt + sizeof(*mpa), ep->plen); 1024256694Snp } 1025256694Snp } else { 1026256694Snp 1027256694Snp if (ep->plen) 1028256694Snp memcpy(mpa->private_data, 1029256694Snp ep->mpa_pkt + sizeof(*mpa), ep->plen); 1030256694Snp CTR2(KTR_IW_CXGBE, "%s:smr7 %p", __func__, ep); 1031256694Snp } 1032256694Snp 1033256694Snp err = sosend(ep->com.so, NULL, NULL, m, NULL, MSG_DONTWAIT, ep->com.thread); 1034256694Snp if (err) { 1035256694Snp connect_reply_upcall(ep, -ENOMEM); 1036256694Snp return; 1037256694Snp } 1038256694Snp 1039256694Snp START_EP_TIMER(ep); 1040256694Snp state_set(&ep->com, MPA_REQ_SENT); 1041256694Snp ep->mpa_attr.initiator = 1; 1042256694Snp} 1043256694Snp 1044256694Snpstatic int send_mpa_reject(struct c4iw_ep *ep, const void *pdata, u8 plen) 1045256694Snp{ 1046256694Snp int mpalen ; 1047256694Snp struct mpa_message *mpa; 1048256694Snp struct mpa_v2_conn_params mpa_v2_params; 1049256694Snp struct mbuf *m; 1050256694Snp int err; 1051256694Snp 1052256694Snp CTR4(KTR_IW_CXGBE, "%s:smrejB %p %u %d", __func__, ep, ep->hwtid, 1053256694Snp ep->plen); 1054256694Snp 1055256694Snp mpalen = sizeof(*mpa) + plen; 1056256694Snp 1057256694Snp if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 1058256694Snp 1059256694Snp mpalen += sizeof(struct mpa_v2_conn_params); 1060256694Snp CTR4(KTR_IW_CXGBE, "%s:smrej1 %p %u %d", __func__, ep, 1061256694Snp ep->mpa_attr.version, mpalen); 1062256694Snp } 1063256694Snp 1064256694Snp if (mpalen > MHLEN) 1065256694Snp CXGBE_UNIMPLEMENTED(__func__); 1066256694Snp 1067256694Snp m = m_gethdr(M_NOWAIT, MT_DATA); 1068256694Snp if (m == NULL) { 1069256694Snp 1070256694Snp printf("%s - cannot alloc mbuf!\n", __func__); 1071256694Snp CTR2(KTR_IW_CXGBE, "%s:smrej2 %p", __func__, ep); 1072256694Snp return (-ENOMEM); 1073256694Snp } 1074256694Snp 1075256694Snp 1076256694Snp mpa = mtod(m, struct mpa_message *); 1077256694Snp m->m_len = mpalen; 1078256694Snp m->m_pkthdr.len = mpalen; 1079256694Snp memset(mpa, 0, sizeof(*mpa)); 1080256694Snp memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key)); 1081256694Snp mpa->flags = MPA_REJECT; 1082256694Snp mpa->revision = mpa_rev; 1083256694Snp mpa->private_data_size = htons(plen); 1084256694Snp 1085256694Snp if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 1086256694Snp 1087256694Snp mpa->flags |= MPA_ENHANCED_RDMA_CONN; 1088256694Snp mpa->private_data_size += 1089256694Snp htons(sizeof(struct mpa_v2_conn_params)); 1090256694Snp mpa_v2_params.ird = htons(((u16)ep->ird) | 1091256694Snp (peer2peer ? MPA_V2_PEER2PEER_MODEL : 1092256694Snp 0)); 1093256694Snp mpa_v2_params.ord = htons(((u16)ep->ord) | (peer2peer ? 1094256694Snp (p2p_type == 1095256694Snp FW_RI_INIT_P2PTYPE_RDMA_WRITE ? 1096256694Snp MPA_V2_RDMA_WRITE_RTR : p2p_type == 1097256694Snp FW_RI_INIT_P2PTYPE_READ_REQ ? 1098256694Snp MPA_V2_RDMA_READ_RTR : 0) : 0)); 1099256694Snp memcpy(mpa->private_data, &mpa_v2_params, 1100256694Snp sizeof(struct mpa_v2_conn_params)); 1101256694Snp 1102256694Snp if (ep->plen) 1103256694Snp memcpy(mpa->private_data + 1104256694Snp sizeof(struct mpa_v2_conn_params), pdata, plen); 1105256694Snp CTR5(KTR_IW_CXGBE, "%s:smrej3 %p %d %d %d", __func__, ep, 1106256694Snp mpa_v2_params.ird, mpa_v2_params.ord, ep->plen); 1107256694Snp } else 1108256694Snp if (plen) 1109256694Snp memcpy(mpa->private_data, pdata, plen); 1110256694Snp 1111256694Snp err = sosend(ep->com.so, NULL, NULL, m, NULL, MSG_DONTWAIT, ep->com.thread); 1112256694Snp if (!err) 1113256694Snp ep->snd_seq += mpalen; 1114256694Snp CTR4(KTR_IW_CXGBE, "%s:smrejE %p %u %d", __func__, ep, ep->hwtid, err); 1115256694Snp return err; 1116256694Snp} 1117256694Snp 1118256694Snpstatic int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen) 1119256694Snp{ 1120256694Snp int mpalen; 1121256694Snp struct mpa_message *mpa; 1122256694Snp struct mbuf *m; 1123256694Snp struct mpa_v2_conn_params mpa_v2_params; 1124256694Snp int err; 1125256694Snp 1126256694Snp CTR2(KTR_IW_CXGBE, "%s:smrepB %p", __func__, ep); 1127256694Snp 1128256694Snp mpalen = sizeof(*mpa) + plen; 1129256694Snp 1130256694Snp if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 1131256694Snp 1132256694Snp CTR3(KTR_IW_CXGBE, "%s:smrep1 %p %d", __func__, ep, 1133256694Snp ep->mpa_attr.version); 1134256694Snp mpalen += sizeof(struct mpa_v2_conn_params); 1135256694Snp } 1136256694Snp 1137256694Snp if (mpalen > MHLEN) 1138256694Snp CXGBE_UNIMPLEMENTED(__func__); 1139256694Snp 1140256694Snp m = m_gethdr(M_NOWAIT, MT_DATA); 1141256694Snp if (m == NULL) { 1142256694Snp 1143256694Snp CTR2(KTR_IW_CXGBE, "%s:smrep2 %p", __func__, ep); 1144256694Snp printf("%s - cannot alloc mbuf!\n", __func__); 1145256694Snp return (-ENOMEM); 1146256694Snp } 1147256694Snp 1148256694Snp 1149256694Snp mpa = mtod(m, struct mpa_message *); 1150256694Snp m->m_len = mpalen; 1151256694Snp m->m_pkthdr.len = mpalen; 1152256694Snp memset(mpa, 0, sizeof(*mpa)); 1153256694Snp memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key)); 1154256694Snp mpa->flags = (ep->mpa_attr.crc_enabled ? MPA_CRC : 0) | 1155256694Snp (markers_enabled ? MPA_MARKERS : 0); 1156256694Snp mpa->revision = ep->mpa_attr.version; 1157256694Snp mpa->private_data_size = htons(plen); 1158256694Snp 1159256694Snp if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 1160256694Snp 1161256694Snp mpa->flags |= MPA_ENHANCED_RDMA_CONN; 1162256694Snp mpa->private_data_size += 1163256694Snp htons(sizeof(struct mpa_v2_conn_params)); 1164256694Snp mpa_v2_params.ird = htons((u16)ep->ird); 1165256694Snp mpa_v2_params.ord = htons((u16)ep->ord); 1166256694Snp CTR5(KTR_IW_CXGBE, "%s:smrep3 %p %d %d %d", __func__, ep, 1167256694Snp ep->mpa_attr.version, mpa_v2_params.ird, mpa_v2_params.ord); 1168256694Snp 1169256694Snp if (peer2peer && (ep->mpa_attr.p2p_type != 1170256694Snp FW_RI_INIT_P2PTYPE_DISABLED)) { 1171256694Snp 1172256694Snp mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL); 1173256694Snp 1174256694Snp if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE) { 1175256694Snp 1176256694Snp mpa_v2_params.ord |= 1177256694Snp htons(MPA_V2_RDMA_WRITE_RTR); 1178256694Snp CTR5(KTR_IW_CXGBE, "%s:smrep4 %p %d %d %d", 1179256694Snp __func__, ep, p2p_type, mpa_v2_params.ird, 1180256694Snp mpa_v2_params.ord); 1181256694Snp } 1182256694Snp else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) { 1183256694Snp 1184256694Snp mpa_v2_params.ord |= 1185256694Snp htons(MPA_V2_RDMA_READ_RTR); 1186256694Snp CTR5(KTR_IW_CXGBE, "%s:smrep5 %p %d %d %d", 1187256694Snp __func__, ep, p2p_type, mpa_v2_params.ird, 1188256694Snp mpa_v2_params.ord); 1189256694Snp } 1190256694Snp } 1191256694Snp 1192256694Snp memcpy(mpa->private_data, &mpa_v2_params, 1193256694Snp sizeof(struct mpa_v2_conn_params)); 1194256694Snp 1195256694Snp if (ep->plen) 1196256694Snp memcpy(mpa->private_data + 1197256694Snp sizeof(struct mpa_v2_conn_params), pdata, plen); 1198256694Snp } else 1199256694Snp if (plen) 1200256694Snp memcpy(mpa->private_data, pdata, plen); 1201256694Snp 1202256694Snp state_set(&ep->com, MPA_REP_SENT); 1203256694Snp ep->snd_seq += mpalen; 1204256694Snp err = sosend(ep->com.so, NULL, NULL, m, NULL, MSG_DONTWAIT, 1205256694Snp ep->com.thread); 1206256694Snp CTR3(KTR_IW_CXGBE, "%s:smrepE %p %d", __func__, ep, err); 1207256694Snp return err; 1208256694Snp} 1209256694Snp 1210256694Snp 1211256694Snp 1212256694Snpstatic void close_complete_upcall(struct c4iw_ep *ep) 1213256694Snp{ 1214256694Snp struct iw_cm_event event; 1215256694Snp 1216256694Snp CTR2(KTR_IW_CXGBE, "%s:ccuB %p", __func__, ep); 1217256694Snp memset(&event, 0, sizeof(event)); 1218256694Snp event.event = IW_CM_EVENT_CLOSE; 1219256694Snp 1220256694Snp if (ep->com.cm_id) { 1221256694Snp 1222256694Snp CTR2(KTR_IW_CXGBE, "%s:ccu1 %1", __func__, ep); 1223256694Snp ep->com.cm_id->event_handler(ep->com.cm_id, &event); 1224256694Snp ep->com.cm_id->rem_ref(ep->com.cm_id); 1225256694Snp ep->com.cm_id = NULL; 1226256694Snp ep->com.qp = NULL; 1227256694Snp set_bit(CLOSE_UPCALL, &ep->com.history); 1228256694Snp } 1229256694Snp CTR2(KTR_IW_CXGBE, "%s:ccuE %p", __func__, ep); 1230256694Snp} 1231256694Snp 1232256694Snpstatic int abort_connection(struct c4iw_ep *ep) 1233256694Snp{ 1234256694Snp int err; 1235256694Snp 1236256694Snp CTR2(KTR_IW_CXGBE, "%s:abB %p", __func__, ep); 1237256694Snp close_complete_upcall(ep); 1238256694Snp state_set(&ep->com, ABORTING); 1239256694Snp abort_socket(ep); 1240256694Snp err = close_socket(&ep->com, 0); 1241256694Snp set_bit(ABORT_CONN, &ep->com.history); 1242256694Snp CTR2(KTR_IW_CXGBE, "%s:abE %p", __func__, ep); 1243256694Snp return err; 1244256694Snp} 1245256694Snp 1246256694Snpstatic void peer_close_upcall(struct c4iw_ep *ep) 1247256694Snp{ 1248256694Snp struct iw_cm_event event; 1249256694Snp 1250256694Snp CTR2(KTR_IW_CXGBE, "%s:pcuB %p", __func__, ep); 1251256694Snp memset(&event, 0, sizeof(event)); 1252256694Snp event.event = IW_CM_EVENT_DISCONNECT; 1253256694Snp 1254256694Snp if (ep->com.cm_id) { 1255256694Snp 1256256694Snp CTR2(KTR_IW_CXGBE, "%s:pcu1 %p", __func__, ep); 1257256694Snp ep->com.cm_id->event_handler(ep->com.cm_id, &event); 1258256694Snp set_bit(DISCONN_UPCALL, &ep->com.history); 1259256694Snp } 1260256694Snp CTR2(KTR_IW_CXGBE, "%s:pcuE %p", __func__, ep); 1261256694Snp} 1262256694Snp 1263256694Snpstatic void peer_abort_upcall(struct c4iw_ep *ep) 1264256694Snp{ 1265256694Snp struct iw_cm_event event; 1266256694Snp 1267256694Snp CTR2(KTR_IW_CXGBE, "%s:pauB %p", __func__, ep); 1268256694Snp memset(&event, 0, sizeof(event)); 1269256694Snp event.event = IW_CM_EVENT_CLOSE; 1270256694Snp event.status = -ECONNRESET; 1271256694Snp 1272256694Snp if (ep->com.cm_id) { 1273256694Snp 1274256694Snp CTR2(KTR_IW_CXGBE, "%s:pau1 %p", __func__, ep); 1275256694Snp ep->com.cm_id->event_handler(ep->com.cm_id, &event); 1276256694Snp ep->com.cm_id->rem_ref(ep->com.cm_id); 1277256694Snp ep->com.cm_id = NULL; 1278256694Snp ep->com.qp = NULL; 1279256694Snp set_bit(ABORT_UPCALL, &ep->com.history); 1280256694Snp } 1281256694Snp CTR2(KTR_IW_CXGBE, "%s:pauE %p", __func__, ep); 1282256694Snp} 1283256694Snp 1284256694Snpstatic void connect_reply_upcall(struct c4iw_ep *ep, int status) 1285256694Snp{ 1286256694Snp struct iw_cm_event event; 1287256694Snp 1288256694Snp CTR3(KTR_IW_CXGBE, "%s:cruB %p", __func__, ep, status); 1289256694Snp memset(&event, 0, sizeof(event)); 1290256694Snp event.event = IW_CM_EVENT_CONNECT_REPLY; 1291256694Snp event.status = (status ==-ECONNABORTED)?-ECONNRESET: status; 1292256694Snp event.local_addr = ep->com.local_addr; 1293256694Snp event.remote_addr = ep->com.remote_addr; 1294256694Snp 1295256694Snp if ((status == 0) || (status == -ECONNREFUSED)) { 1296256694Snp 1297256694Snp if (!ep->tried_with_mpa_v1) { 1298256694Snp 1299256694Snp CTR2(KTR_IW_CXGBE, "%s:cru1 %p", __func__, ep); 1300256694Snp /* this means MPA_v2 is used */ 1301256694Snp event.private_data_len = ep->plen - 1302256694Snp sizeof(struct mpa_v2_conn_params); 1303256694Snp event.private_data = ep->mpa_pkt + 1304256694Snp sizeof(struct mpa_message) + 1305256694Snp sizeof(struct mpa_v2_conn_params); 1306256694Snp } else { 1307256694Snp 1308256694Snp CTR2(KTR_IW_CXGBE, "%s:cru2 %p", __func__, ep); 1309256694Snp /* this means MPA_v1 is used */ 1310256694Snp event.private_data_len = ep->plen; 1311256694Snp event.private_data = ep->mpa_pkt + 1312256694Snp sizeof(struct mpa_message); 1313256694Snp } 1314256694Snp } 1315256694Snp 1316256694Snp if (ep->com.cm_id) { 1317256694Snp 1318256694Snp CTR2(KTR_IW_CXGBE, "%s:cru3 %p", __func__, ep); 1319256694Snp set_bit(CONN_RPL_UPCALL, &ep->com.history); 1320256694Snp ep->com.cm_id->event_handler(ep->com.cm_id, &event); 1321256694Snp } 1322256694Snp 1323256694Snp if(status == -ECONNABORTED) { 1324256694Snp 1325256694Snp CTR3(KTR_IW_CXGBE, "%s:cruE %p %d", __func__, ep, status); 1326256694Snp return; 1327256694Snp } 1328256694Snp 1329256694Snp if (status < 0) { 1330256694Snp 1331256694Snp CTR3(KTR_IW_CXGBE, "%s:cru4 %p %d", __func__, ep, status); 1332256694Snp ep->com.cm_id->rem_ref(ep->com.cm_id); 1333256694Snp ep->com.cm_id = NULL; 1334256694Snp ep->com.qp = NULL; 1335256694Snp } 1336256694Snp 1337256694Snp CTR2(KTR_IW_CXGBE, "%s:cruE %p", __func__, ep); 1338256694Snp} 1339256694Snp 1340256694Snpstatic void connect_request_upcall(struct c4iw_ep *ep) 1341256694Snp{ 1342256694Snp struct iw_cm_event event; 1343256694Snp 1344256694Snp CTR3(KTR_IW_CXGBE, "%s: ep %p, mpa_v1 %d", __func__, ep, 1345256694Snp ep->tried_with_mpa_v1); 1346256694Snp 1347256694Snp memset(&event, 0, sizeof(event)); 1348256694Snp event.event = IW_CM_EVENT_CONNECT_REQUEST; 1349256694Snp event.local_addr = ep->com.local_addr; 1350256694Snp event.remote_addr = ep->com.remote_addr; 1351256694Snp event.provider_data = ep; 1352256694Snp event.so = ep->com.so; 1353256694Snp 1354256694Snp if (!ep->tried_with_mpa_v1) { 1355256694Snp /* this means MPA_v2 is used */ 1356256694Snp#ifdef IW_CM_MPAV2 1357256694Snp event.ord = ep->ord; 1358256694Snp event.ird = ep->ird; 1359256694Snp#endif 1360256694Snp event.private_data_len = ep->plen - 1361256694Snp sizeof(struct mpa_v2_conn_params); 1362256694Snp event.private_data = ep->mpa_pkt + sizeof(struct mpa_message) + 1363256694Snp sizeof(struct mpa_v2_conn_params); 1364256694Snp } else { 1365256694Snp 1366256694Snp /* this means MPA_v1 is used. Send max supported */ 1367256694Snp#ifdef IW_CM_MPAV2 1368256694Snp event.ord = c4iw_max_read_depth; 1369256694Snp event.ird = c4iw_max_read_depth; 1370256694Snp#endif 1371256694Snp event.private_data_len = ep->plen; 1372256694Snp event.private_data = ep->mpa_pkt + sizeof(struct mpa_message); 1373256694Snp } 1374256694Snp 1375256694Snp c4iw_get_ep(&ep->com); 1376256694Snp ep->parent_ep->com.cm_id->event_handler(ep->parent_ep->com.cm_id, 1377256694Snp &event); 1378256694Snp set_bit(CONNREQ_UPCALL, &ep->com.history); 1379256694Snp c4iw_put_ep(&ep->parent_ep->com); 1380256694Snp} 1381256694Snp 1382256694Snpstatic void established_upcall(struct c4iw_ep *ep) 1383256694Snp{ 1384256694Snp struct iw_cm_event event; 1385256694Snp 1386256694Snp CTR2(KTR_IW_CXGBE, "%s:euB %p", __func__, ep); 1387256694Snp memset(&event, 0, sizeof(event)); 1388256694Snp event.event = IW_CM_EVENT_ESTABLISHED; 1389256694Snp#ifdef IW_CM_MPAV2 1390256694Snp event.ird = ep->ird; 1391256694Snp event.ord = ep->ord; 1392256694Snp#endif 1393256694Snp if (ep->com.cm_id) { 1394256694Snp 1395256694Snp CTR2(KTR_IW_CXGBE, "%s:eu1 %p", __func__, ep); 1396256694Snp ep->com.cm_id->event_handler(ep->com.cm_id, &event); 1397256694Snp set_bit(ESTAB_UPCALL, &ep->com.history); 1398256694Snp } 1399256694Snp CTR2(KTR_IW_CXGBE, "%s:euE %p", __func__, ep); 1400256694Snp} 1401256694Snp 1402256694Snp 1403256694Snp 1404256694Snpstatic void process_mpa_reply(struct c4iw_ep *ep) 1405256694Snp{ 1406256694Snp struct mpa_message *mpa; 1407256694Snp struct mpa_v2_conn_params *mpa_v2_params; 1408256694Snp u16 plen; 1409256694Snp u16 resp_ird, resp_ord; 1410256694Snp u8 rtr_mismatch = 0, insuff_ird = 0; 1411256694Snp struct c4iw_qp_attributes attrs; 1412256694Snp enum c4iw_qp_attr_mask mask; 1413256694Snp int err; 1414256694Snp struct mbuf *top, *m; 1415256694Snp int flags = MSG_DONTWAIT; 1416256694Snp struct uio uio; 1417256694Snp 1418256694Snp CTR2(KTR_IW_CXGBE, "%s:pmrB %p", __func__, ep); 1419256694Snp 1420256694Snp /* 1421256694Snp * Stop mpa timer. If it expired, then the state has 1422256694Snp * changed and we bail since ep_timeout already aborted 1423256694Snp * the connection. 1424256694Snp */ 1425256694Snp STOP_EP_TIMER(ep); 1426256694Snp if (state_read(&ep->com) != MPA_REQ_SENT) 1427256694Snp return; 1428256694Snp 1429256694Snp uio.uio_resid = 1000000; 1430256694Snp uio.uio_td = ep->com.thread; 1431256694Snp err = soreceive(ep->com.so, NULL, &uio, &top, NULL, &flags); 1432256694Snp 1433256694Snp if (err) { 1434256694Snp 1435256694Snp if (err == EWOULDBLOCK) { 1436256694Snp 1437256694Snp CTR2(KTR_IW_CXGBE, "%s:pmr1 %p", __func__, ep); 1438256694Snp START_EP_TIMER(ep); 1439256694Snp return; 1440256694Snp } 1441256694Snp err = -err; 1442256694Snp CTR2(KTR_IW_CXGBE, "%s:pmr2 %p", __func__, ep); 1443256694Snp goto err; 1444256694Snp } 1445256694Snp 1446256694Snp if (ep->com.so->so_rcv.sb_mb) { 1447256694Snp 1448256694Snp CTR2(KTR_IW_CXGBE, "%s:pmr3 %p", __func__, ep); 1449256694Snp printf("%s data after soreceive called! so %p sb_mb %p top %p\n", 1450256694Snp __func__, ep->com.so, ep->com.so->so_rcv.sb_mb, top); 1451256694Snp } 1452256694Snp 1453256694Snp m = top; 1454256694Snp 1455256694Snp do { 1456256694Snp 1457256694Snp CTR2(KTR_IW_CXGBE, "%s:pmr4 %p", __func__, ep); 1458256694Snp /* 1459256694Snp * If we get more than the supported amount of private data 1460256694Snp * then we must fail this connection. 1461256694Snp */ 1462256694Snp if (ep->mpa_pkt_len + m->m_len > sizeof(ep->mpa_pkt)) { 1463256694Snp 1464256694Snp CTR3(KTR_IW_CXGBE, "%s:pmr5 %p %d", __func__, ep, 1465256694Snp ep->mpa_pkt_len + m->m_len); 1466256694Snp err = (-EINVAL); 1467256694Snp goto err; 1468256694Snp } 1469256694Snp 1470256694Snp /* 1471256694Snp * copy the new data into our accumulation buffer. 1472256694Snp */ 1473256694Snp m_copydata(m, 0, m->m_len, &(ep->mpa_pkt[ep->mpa_pkt_len])); 1474256694Snp ep->mpa_pkt_len += m->m_len; 1475256694Snp if (!m->m_next) 1476256694Snp m = m->m_nextpkt; 1477256694Snp else 1478256694Snp m = m->m_next; 1479256694Snp } while (m); 1480256694Snp 1481256694Snp m_freem(top); 1482256694Snp /* 1483256694Snp * if we don't even have the mpa message, then bail. 1484256694Snp */ 1485256694Snp if (ep->mpa_pkt_len < sizeof(*mpa)) 1486256694Snp return; 1487256694Snp mpa = (struct mpa_message *) ep->mpa_pkt; 1488256694Snp 1489256694Snp /* Validate MPA header. */ 1490256694Snp if (mpa->revision > mpa_rev) { 1491256694Snp 1492256694Snp CTR4(KTR_IW_CXGBE, "%s:pmr6 %p %d %d", __func__, ep, 1493256694Snp mpa->revision, mpa_rev); 1494256694Snp printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d, " 1495256694Snp " Received = %d\n", __func__, mpa_rev, mpa->revision); 1496256694Snp err = -EPROTO; 1497256694Snp goto err; 1498256694Snp } 1499256694Snp 1500256694Snp if (memcmp(mpa->key, MPA_KEY_REP, sizeof(mpa->key))) { 1501256694Snp 1502256694Snp CTR2(KTR_IW_CXGBE, "%s:pmr7 %p", __func__, ep); 1503256694Snp err = -EPROTO; 1504256694Snp goto err; 1505256694Snp } 1506256694Snp 1507256694Snp plen = ntohs(mpa->private_data_size); 1508256694Snp 1509256694Snp /* 1510256694Snp * Fail if there's too much private data. 1511256694Snp */ 1512256694Snp if (plen > MPA_MAX_PRIVATE_DATA) { 1513256694Snp 1514256694Snp CTR2(KTR_IW_CXGBE, "%s:pmr8 %p", __func__, ep); 1515256694Snp err = -EPROTO; 1516256694Snp goto err; 1517256694Snp } 1518256694Snp 1519256694Snp /* 1520256694Snp * If plen does not account for pkt size 1521256694Snp */ 1522256694Snp if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) { 1523256694Snp 1524256694Snp CTR2(KTR_IW_CXGBE, "%s:pmr9 %p", __func__, ep); 1525256694Snp err = -EPROTO; 1526256694Snp goto err; 1527256694Snp } 1528256694Snp 1529256694Snp ep->plen = (u8) plen; 1530256694Snp 1531256694Snp /* 1532256694Snp * If we don't have all the pdata yet, then bail. 1533256694Snp * We'll continue process when more data arrives. 1534256694Snp */ 1535256694Snp if (ep->mpa_pkt_len < (sizeof(*mpa) + plen)) { 1536256694Snp 1537256694Snp CTR2(KTR_IW_CXGBE, "%s:pmra %p", __func__, ep); 1538256694Snp return; 1539256694Snp } 1540256694Snp 1541256694Snp if (mpa->flags & MPA_REJECT) { 1542256694Snp 1543256694Snp CTR2(KTR_IW_CXGBE, "%s:pmrb %p", __func__, ep); 1544256694Snp err = -ECONNREFUSED; 1545256694Snp goto err; 1546256694Snp } 1547256694Snp 1548256694Snp /* 1549256694Snp * If we get here we have accumulated the entire mpa 1550256694Snp * start reply message including private data. And 1551256694Snp * the MPA header is valid. 1552256694Snp */ 1553256694Snp state_set(&ep->com, FPDU_MODE); 1554256694Snp ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0; 1555256694Snp ep->mpa_attr.recv_marker_enabled = markers_enabled; 1556256694Snp ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0; 1557256694Snp ep->mpa_attr.version = mpa->revision; 1558256694Snp ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED; 1559256694Snp 1560256694Snp if (mpa->revision == 2) { 1561256694Snp 1562256694Snp CTR2(KTR_IW_CXGBE, "%s:pmrc %p", __func__, ep); 1563256694Snp ep->mpa_attr.enhanced_rdma_conn = 1564256694Snp mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0; 1565256694Snp 1566256694Snp if (ep->mpa_attr.enhanced_rdma_conn) { 1567256694Snp 1568256694Snp CTR2(KTR_IW_CXGBE, "%s:pmrd %p", __func__, ep); 1569256694Snp mpa_v2_params = (struct mpa_v2_conn_params *) 1570256694Snp (ep->mpa_pkt + sizeof(*mpa)); 1571256694Snp resp_ird = ntohs(mpa_v2_params->ird) & 1572256694Snp MPA_V2_IRD_ORD_MASK; 1573256694Snp resp_ord = ntohs(mpa_v2_params->ord) & 1574256694Snp MPA_V2_IRD_ORD_MASK; 1575256694Snp 1576256694Snp /* 1577256694Snp * This is a double-check. Ideally, below checks are 1578256694Snp * not required since ird/ord stuff has been taken 1579256694Snp * care of in c4iw_accept_cr 1580256694Snp */ 1581256694Snp if ((ep->ird < resp_ord) || (ep->ord > resp_ird)) { 1582256694Snp 1583256694Snp CTR2(KTR_IW_CXGBE, "%s:pmre %p", __func__, ep); 1584256694Snp err = -ENOMEM; 1585256694Snp ep->ird = resp_ord; 1586256694Snp ep->ord = resp_ird; 1587256694Snp insuff_ird = 1; 1588256694Snp } 1589256694Snp 1590256694Snp if (ntohs(mpa_v2_params->ird) & 1591256694Snp MPA_V2_PEER2PEER_MODEL) { 1592256694Snp 1593256694Snp CTR2(KTR_IW_CXGBE, "%s:pmrf %p", __func__, ep); 1594256694Snp if (ntohs(mpa_v2_params->ord) & 1595256694Snp MPA_V2_RDMA_WRITE_RTR) { 1596256694Snp 1597256694Snp CTR2(KTR_IW_CXGBE, "%s:pmrg %p", __func__, ep); 1598256694Snp ep->mpa_attr.p2p_type = 1599256694Snp FW_RI_INIT_P2PTYPE_RDMA_WRITE; 1600256694Snp } 1601256694Snp else if (ntohs(mpa_v2_params->ord) & 1602256694Snp MPA_V2_RDMA_READ_RTR) { 1603256694Snp 1604256694Snp CTR2(KTR_IW_CXGBE, "%s:pmrh %p", __func__, ep); 1605256694Snp ep->mpa_attr.p2p_type = 1606256694Snp FW_RI_INIT_P2PTYPE_READ_REQ; 1607256694Snp } 1608256694Snp } 1609256694Snp } 1610256694Snp } else { 1611256694Snp 1612256694Snp CTR2(KTR_IW_CXGBE, "%s:pmri %p", __func__, ep); 1613256694Snp 1614256694Snp if (mpa->revision == 1) { 1615256694Snp 1616256694Snp CTR2(KTR_IW_CXGBE, "%s:pmrj %p", __func__, ep); 1617256694Snp 1618256694Snp if (peer2peer) { 1619256694Snp 1620256694Snp CTR2(KTR_IW_CXGBE, "%s:pmrk %p", __func__, ep); 1621256694Snp ep->mpa_attr.p2p_type = p2p_type; 1622256694Snp } 1623256694Snp } 1624256694Snp } 1625256694Snp 1626256694Snp if (set_tcpinfo(ep)) { 1627256694Snp 1628256694Snp CTR2(KTR_IW_CXGBE, "%s:pmrl %p", __func__, ep); 1629256694Snp printf("%s set_tcpinfo error\n", __func__); 1630256694Snp goto err; 1631256694Snp } 1632256694Snp 1633256694Snp CTR6(KTR_IW_CXGBE, "%s - crc_enabled = %d, recv_marker_enabled = %d, " 1634256694Snp "xmit_marker_enabled = %d, version = %d p2p_type = %d", __func__, 1635256694Snp ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled, 1636256694Snp ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version, 1637256694Snp ep->mpa_attr.p2p_type); 1638256694Snp 1639256694Snp /* 1640256694Snp * If responder's RTR does not match with that of initiator, assign 1641256694Snp * FW_RI_INIT_P2PTYPE_DISABLED in mpa attributes so that RTR is not 1642256694Snp * generated when moving QP to RTS state. 1643256694Snp * A TERM message will be sent after QP has moved to RTS state 1644256694Snp */ 1645256694Snp if ((ep->mpa_attr.version == 2) && peer2peer && 1646256694Snp (ep->mpa_attr.p2p_type != p2p_type)) { 1647256694Snp 1648256694Snp CTR2(KTR_IW_CXGBE, "%s:pmrm %p", __func__, ep); 1649256694Snp ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED; 1650256694Snp rtr_mismatch = 1; 1651256694Snp } 1652256694Snp 1653256694Snp 1654256694Snp //ep->ofld_txq = TOEPCB(ep->com.so)->ofld_txq; 1655256694Snp attrs.mpa_attr = ep->mpa_attr; 1656256694Snp attrs.max_ird = ep->ird; 1657256694Snp attrs.max_ord = ep->ord; 1658256694Snp attrs.llp_stream_handle = ep; 1659256694Snp attrs.next_state = C4IW_QP_STATE_RTS; 1660256694Snp 1661256694Snp mask = C4IW_QP_ATTR_NEXT_STATE | 1662256694Snp C4IW_QP_ATTR_LLP_STREAM_HANDLE | C4IW_QP_ATTR_MPA_ATTR | 1663256694Snp C4IW_QP_ATTR_MAX_IRD | C4IW_QP_ATTR_MAX_ORD; 1664256694Snp 1665256694Snp /* bind QP and TID with INIT_WR */ 1666256694Snp err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, mask, &attrs, 1); 1667256694Snp 1668256694Snp if (err) { 1669256694Snp 1670256694Snp CTR2(KTR_IW_CXGBE, "%s:pmrn %p", __func__, ep); 1671256694Snp goto err; 1672256694Snp } 1673256694Snp 1674256694Snp /* 1675256694Snp * If responder's RTR requirement did not match with what initiator 1676256694Snp * supports, generate TERM message 1677256694Snp */ 1678256694Snp if (rtr_mismatch) { 1679256694Snp 1680256694Snp CTR2(KTR_IW_CXGBE, "%s:pmro %p", __func__, ep); 1681256694Snp printk(KERN_ERR "%s: RTR mismatch, sending TERM\n", __func__); 1682256694Snp attrs.layer_etype = LAYER_MPA | DDP_LLP; 1683256694Snp attrs.ecode = MPA_NOMATCH_RTR; 1684256694Snp attrs.next_state = C4IW_QP_STATE_TERMINATE; 1685256694Snp err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 1686256694Snp C4IW_QP_ATTR_NEXT_STATE, &attrs, 0); 1687256694Snp err = -ENOMEM; 1688256694Snp goto out; 1689256694Snp } 1690256694Snp 1691256694Snp /* 1692256694Snp * Generate TERM if initiator IRD is not sufficient for responder 1693256694Snp * provided ORD. Currently, we do the same behaviour even when 1694256694Snp * responder provided IRD is also not sufficient as regards to 1695256694Snp * initiator ORD. 1696256694Snp */ 1697256694Snp if (insuff_ird) { 1698256694Snp 1699256694Snp CTR2(KTR_IW_CXGBE, "%s:pmrp %p", __func__, ep); 1700256694Snp printk(KERN_ERR "%s: Insufficient IRD, sending TERM\n", 1701256694Snp __func__); 1702256694Snp attrs.layer_etype = LAYER_MPA | DDP_LLP; 1703256694Snp attrs.ecode = MPA_INSUFF_IRD; 1704256694Snp attrs.next_state = C4IW_QP_STATE_TERMINATE; 1705256694Snp err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 1706256694Snp C4IW_QP_ATTR_NEXT_STATE, &attrs, 0); 1707256694Snp err = -ENOMEM; 1708256694Snp goto out; 1709256694Snp } 1710256694Snp goto out; 1711256694Snperr: 1712256694Snp state_set(&ep->com, ABORTING); 1713256694Snp abort_connection(ep); 1714256694Snpout: 1715256694Snp connect_reply_upcall(ep, err); 1716256694Snp CTR2(KTR_IW_CXGBE, "%s:pmrE %p", __func__, ep); 1717256694Snp return; 1718256694Snp} 1719256694Snp 1720256694Snpstatic void 1721256694Snpprocess_mpa_request(struct c4iw_ep *ep) 1722256694Snp{ 1723256694Snp struct mpa_message *mpa; 1724256694Snp u16 plen; 1725256694Snp int flags = MSG_DONTWAIT; 1726256694Snp int rc; 1727256694Snp struct iovec iov; 1728256694Snp struct uio uio; 1729256694Snp enum c4iw_ep_state state = state_read(&ep->com); 1730256694Snp 1731256694Snp CTR3(KTR_IW_CXGBE, "%s: ep %p, state %s", __func__, ep, states[state]); 1732256694Snp 1733256694Snp if (state != MPA_REQ_WAIT) 1734256694Snp return; 1735256694Snp 1736256694Snp iov.iov_base = &ep->mpa_pkt[ep->mpa_pkt_len]; 1737256694Snp iov.iov_len = sizeof(ep->mpa_pkt) - ep->mpa_pkt_len; 1738256694Snp uio.uio_iov = &iov; 1739256694Snp uio.uio_iovcnt = 1; 1740256694Snp uio.uio_offset = 0; 1741256694Snp uio.uio_resid = sizeof(ep->mpa_pkt) - ep->mpa_pkt_len; 1742256694Snp uio.uio_segflg = UIO_SYSSPACE; 1743256694Snp uio.uio_rw = UIO_READ; 1744256694Snp uio.uio_td = NULL; /* uio.uio_td = ep->com.thread; */ 1745256694Snp 1746256694Snp rc = soreceive(ep->com.so, NULL, &uio, NULL, NULL, &flags); 1747256694Snp if (rc == EAGAIN) 1748256694Snp return; 1749256694Snp else if (rc) { 1750256694Snpabort: 1751256694Snp STOP_EP_TIMER(ep); 1752256694Snp abort_connection(ep); 1753256694Snp return; 1754256694Snp } 1755256694Snp KASSERT(uio.uio_offset > 0, ("%s: sorecieve on so %p read no data", 1756256694Snp __func__, ep->com.so)); 1757256694Snp ep->mpa_pkt_len += uio.uio_offset; 1758256694Snp 1759256694Snp /* 1760256694Snp * If we get more than the supported amount of private data then we must 1761256694Snp * fail this connection. XXX: check so_rcv->sb_cc, or peek with another 1762256694Snp * soreceive, or increase the size of mpa_pkt by 1 and abort if the last 1763256694Snp * byte is filled by the soreceive above. 1764256694Snp */ 1765256694Snp 1766256694Snp /* Don't even have the MPA message. Wait for more data to arrive. */ 1767256694Snp if (ep->mpa_pkt_len < sizeof(*mpa)) 1768256694Snp return; 1769256694Snp mpa = (struct mpa_message *) ep->mpa_pkt; 1770256694Snp 1771256694Snp /* 1772256694Snp * Validate MPA Header. 1773256694Snp */ 1774256694Snp if (mpa->revision > mpa_rev) { 1775256694Snp log(LOG_ERR, "%s: MPA version mismatch. Local = %d," 1776256694Snp " Received = %d\n", __func__, mpa_rev, mpa->revision); 1777256694Snp goto abort; 1778256694Snp } 1779256694Snp 1780256694Snp if (memcmp(mpa->key, MPA_KEY_REQ, sizeof(mpa->key))) 1781256694Snp goto abort; 1782256694Snp 1783256694Snp /* 1784256694Snp * Fail if there's too much private data. 1785256694Snp */ 1786256694Snp plen = ntohs(mpa->private_data_size); 1787256694Snp if (plen > MPA_MAX_PRIVATE_DATA) 1788256694Snp goto abort; 1789256694Snp 1790256694Snp /* 1791256694Snp * If plen does not account for pkt size 1792256694Snp */ 1793256694Snp if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) 1794256694Snp goto abort; 1795256694Snp 1796256694Snp ep->plen = (u8) plen; 1797256694Snp 1798256694Snp /* 1799256694Snp * If we don't have all the pdata yet, then bail. 1800256694Snp */ 1801256694Snp if (ep->mpa_pkt_len < (sizeof(*mpa) + plen)) 1802256694Snp return; 1803256694Snp 1804256694Snp /* 1805256694Snp * If we get here we have accumulated the entire mpa 1806256694Snp * start reply message including private data. 1807256694Snp */ 1808256694Snp ep->mpa_attr.initiator = 0; 1809256694Snp ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0; 1810256694Snp ep->mpa_attr.recv_marker_enabled = markers_enabled; 1811256694Snp ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0; 1812256694Snp ep->mpa_attr.version = mpa->revision; 1813256694Snp if (mpa->revision == 1) 1814256694Snp ep->tried_with_mpa_v1 = 1; 1815256694Snp ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED; 1816256694Snp 1817256694Snp if (mpa->revision == 2) { 1818256694Snp ep->mpa_attr.enhanced_rdma_conn = 1819256694Snp mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0; 1820256694Snp if (ep->mpa_attr.enhanced_rdma_conn) { 1821256694Snp struct mpa_v2_conn_params *mpa_v2_params; 1822256694Snp u16 ird, ord; 1823256694Snp 1824256694Snp mpa_v2_params = (void *)&ep->mpa_pkt[sizeof(*mpa)]; 1825256694Snp ird = ntohs(mpa_v2_params->ird); 1826256694Snp ord = ntohs(mpa_v2_params->ord); 1827256694Snp 1828256694Snp ep->ird = ird & MPA_V2_IRD_ORD_MASK; 1829256694Snp ep->ord = ord & MPA_V2_IRD_ORD_MASK; 1830256694Snp if (ird & MPA_V2_PEER2PEER_MODEL && peer2peer) { 1831256694Snp if (ord & MPA_V2_RDMA_WRITE_RTR) { 1832256694Snp ep->mpa_attr.p2p_type = 1833256694Snp FW_RI_INIT_P2PTYPE_RDMA_WRITE; 1834256694Snp } else if (ord & MPA_V2_RDMA_READ_RTR) { 1835256694Snp ep->mpa_attr.p2p_type = 1836256694Snp FW_RI_INIT_P2PTYPE_READ_REQ; 1837256694Snp } 1838256694Snp } 1839256694Snp } 1840256694Snp } else if (mpa->revision == 1 && peer2peer) 1841256694Snp ep->mpa_attr.p2p_type = p2p_type; 1842256694Snp 1843256694Snp if (set_tcpinfo(ep)) 1844256694Snp goto abort; 1845256694Snp 1846256694Snp CTR5(KTR_IW_CXGBE, "%s: crc_enabled = %d, recv_marker_enabled = %d, " 1847256694Snp "xmit_marker_enabled = %d, version = %d", __func__, 1848256694Snp ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled, 1849256694Snp ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version); 1850256694Snp 1851256694Snp state_set(&ep->com, MPA_REQ_RCVD); 1852256694Snp STOP_EP_TIMER(ep); 1853256694Snp 1854256694Snp /* drive upcall */ 1855256694Snp mutex_lock(&ep->parent_ep->com.mutex); 1856256694Snp if (ep->parent_ep->com.state != DEAD) 1857256694Snp connect_request_upcall(ep); 1858256694Snp else 1859256694Snp abort_connection(ep); 1860256694Snp mutex_unlock(&ep->parent_ep->com.mutex); 1861256694Snp} 1862256694Snp 1863256694Snp/* 1864256694Snp * Upcall from the adapter indicating data has been transmitted. 1865256694Snp * For us its just the single MPA request or reply. We can now free 1866256694Snp * the skb holding the mpa message. 1867256694Snp */ 1868256694Snpint c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) 1869256694Snp{ 1870256694Snp int err; 1871256694Snp struct c4iw_ep *ep = to_ep(cm_id); 1872256694Snp CTR2(KTR_IW_CXGBE, "%s:crcB %p", __func__, ep); 1873256694Snp 1874256694Snp if (state_read(&ep->com) == DEAD) { 1875256694Snp 1876256694Snp CTR2(KTR_IW_CXGBE, "%s:crc1 %p", __func__, ep); 1877256694Snp c4iw_put_ep(&ep->com); 1878256694Snp return -ECONNRESET; 1879256694Snp } 1880256694Snp set_bit(ULP_REJECT, &ep->com.history); 1881256694Snp BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD); 1882256694Snp 1883256694Snp if (mpa_rev == 0) { 1884256694Snp 1885256694Snp CTR2(KTR_IW_CXGBE, "%s:crc2 %p", __func__, ep); 1886256694Snp abort_connection(ep); 1887256694Snp } 1888256694Snp else { 1889256694Snp 1890256694Snp CTR2(KTR_IW_CXGBE, "%s:crc3 %p", __func__, ep); 1891256694Snp err = send_mpa_reject(ep, pdata, pdata_len); 1892256694Snp err = soshutdown(ep->com.so, 3); 1893256694Snp } 1894256694Snp c4iw_put_ep(&ep->com); 1895256694Snp CTR2(KTR_IW_CXGBE, "%s:crc4 %p", __func__, ep); 1896256694Snp return 0; 1897256694Snp} 1898256694Snp 1899256694Snpint c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) 1900256694Snp{ 1901256694Snp int err; 1902256694Snp struct c4iw_qp_attributes attrs; 1903256694Snp enum c4iw_qp_attr_mask mask; 1904256694Snp struct c4iw_ep *ep = to_ep(cm_id); 1905256694Snp struct c4iw_dev *h = to_c4iw_dev(cm_id->device); 1906256694Snp struct c4iw_qp *qp = get_qhp(h, conn_param->qpn); 1907256694Snp 1908256694Snp CTR2(KTR_IW_CXGBE, "%s:cacB %p", __func__, ep); 1909256694Snp 1910256694Snp if (state_read(&ep->com) == DEAD) { 1911256694Snp 1912256694Snp CTR2(KTR_IW_CXGBE, "%s:cac1 %p", __func__, ep); 1913256694Snp err = -ECONNRESET; 1914256694Snp goto err; 1915256694Snp } 1916256694Snp 1917256694Snp BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD); 1918256694Snp BUG_ON(!qp); 1919256694Snp 1920256694Snp set_bit(ULP_ACCEPT, &ep->com.history); 1921256694Snp 1922256694Snp if ((conn_param->ord > c4iw_max_read_depth) || 1923256694Snp (conn_param->ird > c4iw_max_read_depth)) { 1924256694Snp 1925256694Snp CTR2(KTR_IW_CXGBE, "%s:cac2 %p", __func__, ep); 1926256694Snp abort_connection(ep); 1927256694Snp err = -EINVAL; 1928256694Snp goto err; 1929256694Snp } 1930256694Snp 1931256694Snp if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 1932256694Snp 1933256694Snp CTR2(KTR_IW_CXGBE, "%s:cac3 %p", __func__, ep); 1934256694Snp 1935256694Snp if (conn_param->ord > ep->ird) { 1936256694Snp 1937256694Snp CTR2(KTR_IW_CXGBE, "%s:cac4 %p", __func__, ep); 1938256694Snp ep->ird = conn_param->ird; 1939256694Snp ep->ord = conn_param->ord; 1940256694Snp send_mpa_reject(ep, conn_param->private_data, 1941256694Snp conn_param->private_data_len); 1942256694Snp abort_connection(ep); 1943256694Snp err = -ENOMEM; 1944256694Snp goto err; 1945256694Snp } 1946256694Snp 1947256694Snp if (conn_param->ird > ep->ord) { 1948256694Snp 1949256694Snp CTR2(KTR_IW_CXGBE, "%s:cac5 %p", __func__, ep); 1950256694Snp 1951256694Snp if (!ep->ord) { 1952256694Snp 1953256694Snp CTR2(KTR_IW_CXGBE, "%s:cac6 %p", __func__, ep); 1954256694Snp conn_param->ird = 1; 1955256694Snp } 1956256694Snp else { 1957256694Snp CTR2(KTR_IW_CXGBE, "%s:cac7 %p", __func__, ep); 1958256694Snp abort_connection(ep); 1959256694Snp err = -ENOMEM; 1960256694Snp goto err; 1961256694Snp } 1962256694Snp } 1963256694Snp 1964256694Snp } 1965256694Snp ep->ird = conn_param->ird; 1966256694Snp ep->ord = conn_param->ord; 1967256694Snp 1968256694Snp if (ep->mpa_attr.version != 2) { 1969256694Snp 1970256694Snp CTR2(KTR_IW_CXGBE, "%s:cac8 %p", __func__, ep); 1971256694Snp 1972256694Snp if (peer2peer && ep->ird == 0) { 1973256694Snp 1974256694Snp CTR2(KTR_IW_CXGBE, "%s:cac9 %p", __func__, ep); 1975256694Snp ep->ird = 1; 1976256694Snp } 1977256694Snp } 1978256694Snp 1979256694Snp 1980256694Snp cm_id->add_ref(cm_id); 1981256694Snp ep->com.cm_id = cm_id; 1982256694Snp ep->com.qp = qp; 1983256694Snp //ep->ofld_txq = TOEPCB(ep->com.so)->ofld_txq; 1984256694Snp 1985256694Snp /* bind QP to EP and move to RTS */ 1986256694Snp attrs.mpa_attr = ep->mpa_attr; 1987256694Snp attrs.max_ird = ep->ird; 1988256694Snp attrs.max_ord = ep->ord; 1989256694Snp attrs.llp_stream_handle = ep; 1990256694Snp attrs.next_state = C4IW_QP_STATE_RTS; 1991256694Snp 1992256694Snp /* bind QP and TID with INIT_WR */ 1993256694Snp mask = C4IW_QP_ATTR_NEXT_STATE | 1994256694Snp C4IW_QP_ATTR_LLP_STREAM_HANDLE | 1995256694Snp C4IW_QP_ATTR_MPA_ATTR | 1996256694Snp C4IW_QP_ATTR_MAX_IRD | 1997256694Snp C4IW_QP_ATTR_MAX_ORD; 1998256694Snp 1999256694Snp err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, mask, &attrs, 1); 2000256694Snp 2001256694Snp if (err) { 2002256694Snp 2003256694Snp CTR2(KTR_IW_CXGBE, "%s:caca %p", __func__, ep); 2004256694Snp goto err1; 2005256694Snp } 2006256694Snp err = send_mpa_reply(ep, conn_param->private_data, 2007256694Snp conn_param->private_data_len); 2008256694Snp 2009256694Snp if (err) { 2010256694Snp 2011256694Snp CTR2(KTR_IW_CXGBE, "%s:caca %p", __func__, ep); 2012256694Snp goto err1; 2013256694Snp } 2014256694Snp 2015256694Snp state_set(&ep->com, FPDU_MODE); 2016256694Snp established_upcall(ep); 2017256694Snp c4iw_put_ep(&ep->com); 2018256694Snp CTR2(KTR_IW_CXGBE, "%s:cacE %p", __func__, ep); 2019256694Snp return 0; 2020256694Snperr1: 2021256694Snp ep->com.cm_id = NULL; 2022256694Snp ep->com.qp = NULL; 2023256694Snp cm_id->rem_ref(cm_id); 2024256694Snperr: 2025256694Snp c4iw_put_ep(&ep->com); 2026256694Snp CTR2(KTR_IW_CXGBE, "%s:cacE err %p", __func__, ep); 2027256694Snp return err; 2028256694Snp} 2029256694Snp 2030256694Snp 2031256694Snp 2032256694Snpint c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) 2033256694Snp{ 2034256694Snp int err = 0; 2035256694Snp struct c4iw_dev *dev = to_c4iw_dev(cm_id->device); 2036256694Snp struct c4iw_ep *ep = NULL; 2037256694Snp struct rtentry *rt; 2038256694Snp struct toedev *tdev; 2039256694Snp 2040256694Snp CTR2(KTR_IW_CXGBE, "%s:ccB %p", __func__, cm_id); 2041256694Snp 2042256694Snp if ((conn_param->ord > c4iw_max_read_depth) || 2043256694Snp (conn_param->ird > c4iw_max_read_depth)) { 2044256694Snp 2045256694Snp CTR2(KTR_IW_CXGBE, "%s:cc1 %p", __func__, cm_id); 2046256694Snp err = -EINVAL; 2047256694Snp goto out; 2048256694Snp } 2049256694Snp ep = alloc_ep(sizeof(*ep), M_NOWAIT); 2050256694Snp 2051256694Snp if (!ep) { 2052256694Snp 2053256694Snp CTR2(KTR_IW_CXGBE, "%s:cc2 %p", __func__, cm_id); 2054256694Snp printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __func__); 2055256694Snp err = -ENOMEM; 2056256694Snp goto out; 2057256694Snp } 2058256694Snp init_timer(&ep->timer); 2059256694Snp ep->plen = conn_param->private_data_len; 2060256694Snp 2061256694Snp if (ep->plen) { 2062256694Snp 2063256694Snp CTR2(KTR_IW_CXGBE, "%s:cc3 %p", __func__, ep); 2064256694Snp memcpy(ep->mpa_pkt + sizeof(struct mpa_message), 2065256694Snp conn_param->private_data, ep->plen); 2066256694Snp } 2067256694Snp ep->ird = conn_param->ird; 2068256694Snp ep->ord = conn_param->ord; 2069256694Snp 2070256694Snp if (peer2peer && ep->ord == 0) { 2071256694Snp 2072256694Snp CTR2(KTR_IW_CXGBE, "%s:cc4 %p", __func__, ep); 2073256694Snp ep->ord = 1; 2074256694Snp } 2075256694Snp 2076256694Snp cm_id->add_ref(cm_id); 2077256694Snp ep->com.dev = dev; 2078256694Snp ep->com.cm_id = cm_id; 2079256694Snp ep->com.qp = get_qhp(dev, conn_param->qpn); 2080256694Snp 2081256694Snp if (!ep->com.qp) { 2082256694Snp 2083256694Snp CTR2(KTR_IW_CXGBE, "%s:cc5 %p", __func__, ep); 2084256694Snp err = -EINVAL; 2085256694Snp goto fail2; 2086256694Snp } 2087256694Snp ep->com.thread = curthread; 2088256694Snp ep->com.so = cm_id->so; 2089256694Snp 2090256694Snp init_sock(&ep->com); 2091256694Snp 2092256694Snp /* find a route */ 2093256694Snp rt = find_route( 2094256694Snp cm_id->local_addr.sin_addr.s_addr, 2095256694Snp cm_id->remote_addr.sin_addr.s_addr, 2096256694Snp cm_id->local_addr.sin_port, 2097256694Snp cm_id->remote_addr.sin_port, 0); 2098256694Snp 2099256694Snp if (!rt) { 2100256694Snp 2101256694Snp CTR2(KTR_IW_CXGBE, "%s:cc7 %p", __func__, ep); 2102256694Snp printk(KERN_ERR MOD "%s - cannot find route.\n", __func__); 2103256694Snp err = -EHOSTUNREACH; 2104256694Snp goto fail3; 2105256694Snp } 2106256694Snp 2107256694Snp 2108256694Snp if (!(rt->rt_ifp->if_flags & IFCAP_TOE)) { 2109256694Snp 2110256694Snp CTR2(KTR_IW_CXGBE, "%s:cc8 %p", __func__, ep); 2111256694Snp printf("%s - interface not TOE capable.\n", __func__); 2112256694Snp goto fail3; 2113256694Snp } 2114256694Snp tdev = TOEDEV(rt->rt_ifp); 2115256694Snp 2116256694Snp if (tdev == NULL) { 2117256694Snp 2118256694Snp CTR2(KTR_IW_CXGBE, "%s:cc9 %p", __func__, ep); 2119256694Snp printf("%s - No toedev for interface.\n", __func__); 2120256694Snp goto fail3; 2121256694Snp } 2122256694Snp RTFREE(rt); 2123256694Snp 2124256694Snp state_set(&ep->com, CONNECTING); 2125256694Snp ep->tos = 0; 2126256694Snp ep->com.local_addr = cm_id->local_addr; 2127256694Snp ep->com.remote_addr = cm_id->remote_addr; 2128256694Snp err = soconnect(ep->com.so, (struct sockaddr *)&ep->com.remote_addr, 2129256694Snp ep->com.thread); 2130256694Snp 2131256694Snp if (!err) { 2132256694Snp 2133256694Snp CTR2(KTR_IW_CXGBE, "%s:cca %p", __func__, ep); 2134256694Snp goto out; 2135256694Snp } 2136256694Snp 2137256694Snpfail3: 2138256694Snp CTR2(KTR_IW_CXGBE, "%s:ccb %p", __func__, ep); 2139256694Snp RTFREE(rt); 2140256694Snpfail2: 2141256694Snp cm_id->rem_ref(cm_id); 2142256694Snp c4iw_put_ep(&ep->com); 2143256694Snpout: 2144256694Snp CTR2(KTR_IW_CXGBE, "%s:ccE %p", __func__, ep); 2145256694Snp return err; 2146256694Snp} 2147256694Snp 2148256694Snp/* 2149256694Snp * iwcm->create_listen. Returns -errno on failure. 2150256694Snp */ 2151256694Snpint 2152256694Snpc4iw_create_listen(struct iw_cm_id *cm_id, int backlog) 2153256694Snp{ 2154256694Snp int rc; 2155256694Snp struct c4iw_dev *dev = to_c4iw_dev(cm_id->device); 2156256694Snp struct c4iw_listen_ep *ep; 2157256694Snp struct socket *so = cm_id->so; 2158256694Snp 2159256694Snp ep = alloc_ep(sizeof(*ep), GFP_KERNEL); 2160256694Snp CTR5(KTR_IW_CXGBE, "%s: cm_id %p, lso %p, ep %p, inp %p", __func__, 2161256694Snp cm_id, so, ep, so->so_pcb); 2162256694Snp if (ep == NULL) { 2163256694Snp log(LOG_ERR, "%s: failed to alloc memory for endpoint\n", 2164256694Snp __func__); 2165256694Snp rc = ENOMEM; 2166256694Snp goto failed; 2167256694Snp } 2168256694Snp 2169256694Snp cm_id->add_ref(cm_id); 2170256694Snp ep->com.cm_id = cm_id; 2171256694Snp ep->com.dev = dev; 2172256694Snp ep->backlog = backlog; 2173256694Snp ep->com.local_addr = cm_id->local_addr; 2174256694Snp ep->com.thread = curthread; 2175256694Snp state_set(&ep->com, LISTEN); 2176256694Snp ep->com.so = so; 2177256694Snp init_sock(&ep->com); 2178256694Snp 2179256694Snp rc = solisten(so, ep->backlog, ep->com.thread); 2180256694Snp if (rc != 0) { 2181256694Snp log(LOG_ERR, "%s: failed to start listener: %d\n", __func__, 2182256694Snp rc); 2183256694Snp close_socket(&ep->com, 0); 2184256694Snp cm_id->rem_ref(cm_id); 2185256694Snp c4iw_put_ep(&ep->com); 2186256694Snp goto failed; 2187256694Snp } 2188256694Snp 2189256694Snp cm_id->provider_data = ep; 2190256694Snp return (0); 2191256694Snp 2192256694Snpfailed: 2193256694Snp CTR3(KTR_IW_CXGBE, "%s: cm_id %p, FAILED (%d)", __func__, cm_id, rc); 2194256694Snp return (-rc); 2195256694Snp} 2196256694Snp 2197256694Snpint 2198256694Snpc4iw_destroy_listen(struct iw_cm_id *cm_id) 2199256694Snp{ 2200256694Snp int rc; 2201256694Snp struct c4iw_listen_ep *ep = to_listen_ep(cm_id); 2202256694Snp 2203256694Snp CTR4(KTR_IW_CXGBE, "%s: cm_id %p, so %p, inp %p", __func__, cm_id, 2204256694Snp cm_id->so, cm_id->so->so_pcb); 2205256694Snp 2206256694Snp state_set(&ep->com, DEAD); 2207256694Snp rc = close_socket(&ep->com, 0); 2208256694Snp cm_id->rem_ref(cm_id); 2209256694Snp c4iw_put_ep(&ep->com); 2210256694Snp 2211256694Snp return (rc); 2212256694Snp} 2213256694Snp 2214256694Snpint c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) 2215256694Snp{ 2216256694Snp int ret = 0; 2217256694Snp int close = 0; 2218256694Snp int fatal = 0; 2219256694Snp struct c4iw_rdev *rdev; 2220256694Snp 2221256694Snp mutex_lock(&ep->com.mutex); 2222256694Snp 2223256694Snp CTR2(KTR_IW_CXGBE, "%s:cedB %p", __func__, ep); 2224256694Snp 2225256694Snp rdev = &ep->com.dev->rdev; 2226256694Snp 2227256694Snp if (c4iw_fatal_error(rdev)) { 2228256694Snp 2229256694Snp CTR2(KTR_IW_CXGBE, "%s:ced1 %p", __func__, ep); 2230256694Snp fatal = 1; 2231256694Snp close_complete_upcall(ep); 2232256694Snp ep->com.state = DEAD; 2233256694Snp } 2234256694Snp CTR3(KTR_IW_CXGBE, "%s:ced2 %p %s", __func__, ep, 2235256694Snp states[ep->com.state]); 2236256694Snp 2237256694Snp switch (ep->com.state) { 2238256694Snp 2239256694Snp case MPA_REQ_WAIT: 2240256694Snp case MPA_REQ_SENT: 2241256694Snp case MPA_REQ_RCVD: 2242256694Snp case MPA_REP_SENT: 2243256694Snp case FPDU_MODE: 2244256694Snp close = 1; 2245256694Snp if (abrupt) 2246256694Snp ep->com.state = ABORTING; 2247256694Snp else { 2248256694Snp ep->com.state = CLOSING; 2249256694Snp START_EP_TIMER(ep); 2250256694Snp } 2251256694Snp set_bit(CLOSE_SENT, &ep->com.flags); 2252256694Snp break; 2253256694Snp 2254256694Snp case CLOSING: 2255256694Snp 2256256694Snp if (!test_and_set_bit(CLOSE_SENT, &ep->com.flags)) { 2257256694Snp 2258256694Snp close = 1; 2259256694Snp if (abrupt) { 2260256694Snp STOP_EP_TIMER(ep); 2261256694Snp ep->com.state = ABORTING; 2262256694Snp } else 2263256694Snp ep->com.state = MORIBUND; 2264256694Snp } 2265256694Snp break; 2266256694Snp 2267256694Snp case MORIBUND: 2268256694Snp case ABORTING: 2269256694Snp case DEAD: 2270256694Snp CTR3(KTR_IW_CXGBE, 2271256694Snp "%s ignoring disconnect ep %p state %u", __func__, 2272256694Snp ep, ep->com.state); 2273256694Snp break; 2274256694Snp 2275256694Snp default: 2276256694Snp BUG(); 2277256694Snp break; 2278256694Snp } 2279256694Snp 2280256694Snp mutex_unlock(&ep->com.mutex); 2281256694Snp 2282256694Snp if (close) { 2283256694Snp 2284256694Snp CTR2(KTR_IW_CXGBE, "%s:ced3 %p", __func__, ep); 2285256694Snp 2286256694Snp if (abrupt) { 2287256694Snp 2288256694Snp CTR2(KTR_IW_CXGBE, "%s:ced4 %p", __func__, ep); 2289256694Snp set_bit(EP_DISC_ABORT, &ep->com.history); 2290256694Snp ret = abort_connection(ep); 2291256694Snp } else { 2292256694Snp 2293256694Snp CTR2(KTR_IW_CXGBE, "%s:ced5 %p", __func__, ep); 2294256694Snp set_bit(EP_DISC_CLOSE, &ep->com.history); 2295256694Snp 2296256694Snp if (!ep->parent_ep) 2297256694Snp __state_set(&ep->com, MORIBUND); 2298256694Snp ret = shutdown_socket(&ep->com); 2299256694Snp } 2300256694Snp 2301256694Snp if (ret) { 2302256694Snp 2303256694Snp fatal = 1; 2304256694Snp } 2305256694Snp } 2306256694Snp 2307256694Snp if (fatal) { 2308256694Snp 2309256694Snp release_ep_resources(ep); 2310256694Snp CTR2(KTR_IW_CXGBE, "%s:ced6 %p", __func__, ep); 2311256694Snp } 2312256694Snp CTR2(KTR_IW_CXGBE, "%s:cedE %p", __func__, ep); 2313256694Snp return ret; 2314256694Snp} 2315256694Snp 2316256694Snp#ifdef C4IW_EP_REDIRECT 2317256694Snpint c4iw_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new, 2318256694Snp struct l2t_entry *l2t) 2319256694Snp{ 2320256694Snp struct c4iw_ep *ep = ctx; 2321256694Snp 2322256694Snp if (ep->dst != old) 2323256694Snp return 0; 2324256694Snp 2325256694Snp PDBG("%s ep %p redirect to dst %p l2t %p\n", __func__, ep, new, 2326256694Snp l2t); 2327256694Snp dst_hold(new); 2328256694Snp cxgb4_l2t_release(ep->l2t); 2329256694Snp ep->l2t = l2t; 2330256694Snp dst_release(old); 2331256694Snp ep->dst = new; 2332256694Snp return 1; 2333256694Snp} 2334256694Snp#endif 2335256694Snp 2336256694Snp 2337256694Snp 2338256694Snpstatic void ep_timeout(unsigned long arg) 2339256694Snp{ 2340256694Snp struct c4iw_ep *ep = (struct c4iw_ep *)arg; 2341256694Snp int kickit = 0; 2342256694Snp 2343256694Snp CTR2(KTR_IW_CXGBE, "%s:etB %p", __func__, ep); 2344256694Snp spin_lock(&timeout_lock); 2345256694Snp 2346256694Snp if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) { 2347256694Snp 2348256694Snp list_add_tail(&ep->entry, &timeout_list); 2349256694Snp kickit = 1; 2350256694Snp } 2351256694Snp spin_unlock(&timeout_lock); 2352256694Snp 2353256694Snp if (kickit) { 2354256694Snp 2355256694Snp CTR2(KTR_IW_CXGBE, "%s:et1 %p", __func__, ep); 2356256694Snp queue_work(c4iw_taskq, &c4iw_task); 2357256694Snp } 2358256694Snp CTR2(KTR_IW_CXGBE, "%s:etE %p", __func__, ep); 2359256694Snp} 2360256694Snp 2361256694Snpstatic int fw6_wr_rpl(struct adapter *sc, const __be64 *rpl) 2362256694Snp{ 2363256694Snp uint64_t val = be64toh(*rpl); 2364256694Snp int ret; 2365256694Snp struct c4iw_wr_wait *wr_waitp; 2366256694Snp 2367256694Snp ret = (int)((val >> 8) & 0xff); 2368256694Snp wr_waitp = (struct c4iw_wr_wait *)rpl[1]; 2369256694Snp CTR3(KTR_IW_CXGBE, "%s wr_waitp %p ret %u", __func__, wr_waitp, ret); 2370256694Snp if (wr_waitp) 2371256694Snp c4iw_wake_up(wr_waitp, ret ? -ret : 0); 2372256694Snp 2373256694Snp return (0); 2374256694Snp} 2375256694Snp 2376256694Snpstatic int fw6_cqe_handler(struct adapter *sc, const __be64 *rpl) 2377256694Snp{ 2378256694Snp struct t4_cqe cqe =*(const struct t4_cqe *)(&rpl[0]); 2379256694Snp 2380256694Snp CTR2(KTR_IW_CXGBE, "%s rpl %p", __func__, rpl); 2381256694Snp c4iw_ev_dispatch(sc->iwarp_softc, &cqe); 2382256694Snp 2383256694Snp return (0); 2384256694Snp} 2385256694Snp 2386256694Snpstatic int terminate(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) 2387256694Snp{ 2388256694Snp 2389256694Snp struct adapter *sc = iq->adapter; 2390256694Snp 2391256694Snp const struct cpl_rdma_terminate *rpl = (const void *)(rss + 1); 2392256694Snp unsigned int tid = GET_TID(rpl); 2393256694Snp struct c4iw_qp_attributes attrs; 2394256694Snp struct toepcb *toep = lookup_tid(sc, tid); 2395256694Snp struct socket *so = inp_inpcbtosocket(toep->inp); 2396256694Snp struct c4iw_ep *ep = so->so_rcv.sb_upcallarg; 2397256694Snp 2398256694Snp CTR2(KTR_IW_CXGBE, "%s:tB %p %d", __func__, ep); 2399256694Snp 2400256694Snp if (ep && ep->com.qp) { 2401256694Snp 2402256694Snp printk(KERN_WARNING MOD "TERM received tid %u qpid %u\n", tid, 2403256694Snp ep->com.qp->wq.sq.qid); 2404256694Snp attrs.next_state = C4IW_QP_STATE_TERMINATE; 2405256694Snp c4iw_modify_qp(ep->com.dev, ep->com.qp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 2406256694Snp 1); 2407256694Snp } else 2408256694Snp printk(KERN_WARNING MOD "TERM received tid %u no ep/qp\n", tid); 2409256694Snp CTR2(KTR_IW_CXGBE, "%s:tE %p %d", __func__, ep); 2410256694Snp 2411256694Snp return 0; 2412256694Snp} 2413256694Snp 2414256694Snp void 2415256694Snpc4iw_cm_init_cpl(struct adapter *sc) 2416256694Snp{ 2417256694Snp 2418256694Snp t4_register_cpl_handler(sc, CPL_RDMA_TERMINATE, terminate); 2419256694Snp t4_register_fw_msg_handler(sc, FW6_TYPE_WR_RPL, fw6_wr_rpl); 2420256694Snp t4_register_fw_msg_handler(sc, FW6_TYPE_CQE, fw6_cqe_handler); 2421256694Snp t4_register_an_handler(sc, c4iw_ev_handler); 2422256694Snp} 2423256694Snp 2424256694Snp void 2425256694Snpc4iw_cm_term_cpl(struct adapter *sc) 2426256694Snp{ 2427256694Snp 2428256694Snp t4_register_cpl_handler(sc, CPL_RDMA_TERMINATE, NULL); 2429256694Snp t4_register_fw_msg_handler(sc, FW6_TYPE_WR_RPL, NULL); 2430256694Snp t4_register_fw_msg_handler(sc, FW6_TYPE_CQE, NULL); 2431256694Snp} 2432256694Snp 2433256694Snpint __init c4iw_cm_init(void) 2434256694Snp{ 2435256694Snp 2436256694Snp TAILQ_INIT(&req_list); 2437256694Snp spin_lock_init(&req_lock); 2438256694Snp INIT_LIST_HEAD(&timeout_list); 2439256694Snp spin_lock_init(&timeout_lock); 2440256694Snp 2441256694Snp INIT_WORK(&c4iw_task, process_req); 2442256694Snp 2443256694Snp c4iw_taskq = create_singlethread_workqueue("iw_cxgbe"); 2444256694Snp if (!c4iw_taskq) 2445256694Snp return -ENOMEM; 2446256694Snp 2447256694Snp 2448256694Snp return 0; 2449256694Snp} 2450256694Snp 2451256694Snpvoid __exit c4iw_cm_term(void) 2452256694Snp{ 2453256694Snp WARN_ON(!TAILQ_EMPTY(&req_list)); 2454256694Snp WARN_ON(!list_empty(&timeout_list)); 2455256694Snp flush_workqueue(c4iw_taskq); 2456256694Snp destroy_workqueue(c4iw_taskq); 2457256694Snp} 2458256694Snp#endif 2459