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