xref: /openbmc/linux/drivers/infiniband/hw/cxgb4/cm.c (revision 6c53e938)
1cfdda9d7SSteve Wise /*
29eccfe10SSteve Wise  * Copyright (c) 2009-2014 Chelsio, Inc. All rights reserved.
3cfdda9d7SSteve Wise  *
4cfdda9d7SSteve Wise  * This software is available to you under a choice of one of two
5cfdda9d7SSteve Wise  * licenses.  You may choose to be licensed under the terms of the GNU
6cfdda9d7SSteve Wise  * General Public License (GPL) Version 2, available from the file
7cfdda9d7SSteve Wise  * COPYING in the main directory of this source tree, or the
8cfdda9d7SSteve Wise  * OpenIB.org BSD license below:
9cfdda9d7SSteve Wise  *
10cfdda9d7SSteve Wise  *     Redistribution and use in source and binary forms, with or
11cfdda9d7SSteve Wise  *     without modification, are permitted provided that the following
12cfdda9d7SSteve Wise  *     conditions are met:
13cfdda9d7SSteve Wise  *
14cfdda9d7SSteve Wise  *      - Redistributions of source code must retain the above
15cfdda9d7SSteve Wise  *	  copyright notice, this list of conditions and the following
16cfdda9d7SSteve Wise  *	  disclaimer.
17cfdda9d7SSteve Wise  *
18cfdda9d7SSteve Wise  *      - Redistributions in binary form must reproduce the above
19cfdda9d7SSteve Wise  *	  copyright notice, this list of conditions and the following
20cfdda9d7SSteve Wise  *	  disclaimer in the documentation and/or other materials
21cfdda9d7SSteve Wise  *	  provided with the distribution.
22cfdda9d7SSteve Wise  *
23cfdda9d7SSteve Wise  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24cfdda9d7SSteve Wise  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25cfdda9d7SSteve Wise  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26cfdda9d7SSteve Wise  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27cfdda9d7SSteve Wise  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28cfdda9d7SSteve Wise  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29cfdda9d7SSteve Wise  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30cfdda9d7SSteve Wise  * SOFTWARE.
31cfdda9d7SSteve Wise  */
32cfdda9d7SSteve Wise #include <linux/module.h>
33cfdda9d7SSteve Wise #include <linux/list.h>
34cfdda9d7SSteve Wise #include <linux/workqueue.h>
35cfdda9d7SSteve Wise #include <linux/skbuff.h>
36cfdda9d7SSteve Wise #include <linux/timer.h>
37cfdda9d7SSteve Wise #include <linux/notifier.h>
38cfdda9d7SSteve Wise #include <linux/inetdevice.h>
39cfdda9d7SSteve Wise #include <linux/ip.h>
40cfdda9d7SSteve Wise #include <linux/tcp.h>
411cab775cSVipul Pandya #include <linux/if_vlan.h>
42cfdda9d7SSteve Wise 
43cfdda9d7SSteve Wise #include <net/neighbour.h>
44cfdda9d7SSteve Wise #include <net/netevent.h>
45cfdda9d7SSteve Wise #include <net/route.h>
461cab775cSVipul Pandya #include <net/tcp.h>
47830662f6SVipul Pandya #include <net/ip6_route.h>
48830662f6SVipul Pandya #include <net/addrconf.h>
49cfdda9d7SSteve Wise 
5011b8e22dSSteve Wise #include <rdma/ib_addr.h>
5111b8e22dSSteve Wise 
52cfdda9d7SSteve Wise #include "iw_cxgb4.h"
53cfdda9d7SSteve Wise 
54cfdda9d7SSteve Wise static char *states[] = {
55cfdda9d7SSteve Wise 	"idle",
56cfdda9d7SSteve Wise 	"listen",
57cfdda9d7SSteve Wise 	"connecting",
58cfdda9d7SSteve Wise 	"mpa_wait_req",
59cfdda9d7SSteve Wise 	"mpa_req_sent",
60cfdda9d7SSteve Wise 	"mpa_req_rcvd",
61cfdda9d7SSteve Wise 	"mpa_rep_sent",
62cfdda9d7SSteve Wise 	"fpdu_mode",
63cfdda9d7SSteve Wise 	"aborting",
64cfdda9d7SSteve Wise 	"closing",
65cfdda9d7SSteve Wise 	"moribund",
66cfdda9d7SSteve Wise 	"dead",
67cfdda9d7SSteve Wise 	NULL,
68cfdda9d7SSteve Wise };
69cfdda9d7SSteve Wise 
705be78ee9SVipul Pandya static int nocong;
715be78ee9SVipul Pandya module_param(nocong, int, 0644);
725be78ee9SVipul Pandya MODULE_PARM_DESC(nocong, "Turn of congestion control (default=0)");
735be78ee9SVipul Pandya 
745be78ee9SVipul Pandya static int enable_ecn;
755be78ee9SVipul Pandya module_param(enable_ecn, int, 0644);
765be78ee9SVipul Pandya MODULE_PARM_DESC(enable_ecn, "Enable ECN (default=0/disabled)");
775be78ee9SVipul Pandya 
78b52fe09eSSteve Wise static int dack_mode = 1;
79ba6d3925SSteve Wise module_param(dack_mode, int, 0644);
80b52fe09eSSteve Wise MODULE_PARM_DESC(dack_mode, "Delayed ack mode (default=1)");
81ba6d3925SSteve Wise 
824c2c5763SHariprasad Shenai uint c4iw_max_read_depth = 32;
83be4c9badSRoland Dreier module_param(c4iw_max_read_depth, int, 0644);
844c2c5763SHariprasad Shenai MODULE_PARM_DESC(c4iw_max_read_depth,
854c2c5763SHariprasad Shenai 		 "Per-connection max ORD/IRD (default=32)");
86be4c9badSRoland Dreier 
87cfdda9d7SSteve Wise static int enable_tcp_timestamps;
88cfdda9d7SSteve Wise module_param(enable_tcp_timestamps, int, 0644);
89cfdda9d7SSteve Wise MODULE_PARM_DESC(enable_tcp_timestamps, "Enable tcp timestamps (default=0)");
90cfdda9d7SSteve Wise 
91cfdda9d7SSteve Wise static int enable_tcp_sack;
92cfdda9d7SSteve Wise module_param(enable_tcp_sack, int, 0644);
93cfdda9d7SSteve Wise MODULE_PARM_DESC(enable_tcp_sack, "Enable tcp SACK (default=0)");
94cfdda9d7SSteve Wise 
95cfdda9d7SSteve Wise static int enable_tcp_window_scaling = 1;
96cfdda9d7SSteve Wise module_param(enable_tcp_window_scaling, int, 0644);
97cfdda9d7SSteve Wise MODULE_PARM_DESC(enable_tcp_window_scaling,
98cfdda9d7SSteve Wise 		 "Enable tcp window scaling (default=1)");
99cfdda9d7SSteve Wise 
100cfdda9d7SSteve Wise int c4iw_debug;
101cfdda9d7SSteve Wise module_param(c4iw_debug, int, 0644);
102cfdda9d7SSteve Wise MODULE_PARM_DESC(c4iw_debug, "Enable debug logging (default=0)");
103cfdda9d7SSteve Wise 
104df2d5130SSteve Wise static int peer2peer = 1;
105cfdda9d7SSteve Wise module_param(peer2peer, int, 0644);
106df2d5130SSteve Wise MODULE_PARM_DESC(peer2peer, "Support peer2peer ULPs (default=1)");
107cfdda9d7SSteve Wise 
108cfdda9d7SSteve Wise static int p2p_type = FW_RI_INIT_P2PTYPE_READ_REQ;
109cfdda9d7SSteve Wise module_param(p2p_type, int, 0644);
110cfdda9d7SSteve Wise MODULE_PARM_DESC(p2p_type, "RDMAP opcode to use for the RTR message: "
111cfdda9d7SSteve Wise 			   "1=RDMA_READ 0=RDMA_WRITE (default 1)");
112cfdda9d7SSteve Wise 
113cfdda9d7SSteve Wise static int ep_timeout_secs = 60;
114cfdda9d7SSteve Wise module_param(ep_timeout_secs, int, 0644);
115cfdda9d7SSteve Wise MODULE_PARM_DESC(ep_timeout_secs, "CM Endpoint operation timeout "
116cfdda9d7SSteve Wise 				   "in seconds (default=60)");
117cfdda9d7SSteve Wise 
118cfdda9d7SSteve Wise static int mpa_rev = 1;
119cfdda9d7SSteve Wise module_param(mpa_rev, int, 0644);
120cfdda9d7SSteve Wise MODULE_PARM_DESC(mpa_rev, "MPA Revision, 0 supports amso1100, "
121d2fe99e8SKumar Sanghvi 		"1 is RFC0544 spec compliant, 2 is IETF MPA Peer Connect Draft"
122d2fe99e8SKumar Sanghvi 		" compliant (default=1)");
123cfdda9d7SSteve Wise 
124cfdda9d7SSteve Wise static int markers_enabled;
125cfdda9d7SSteve Wise module_param(markers_enabled, int, 0644);
126cfdda9d7SSteve Wise MODULE_PARM_DESC(markers_enabled, "Enable MPA MARKERS (default(0)=disabled)");
127cfdda9d7SSteve Wise 
128cfdda9d7SSteve Wise static int crc_enabled = 1;
129cfdda9d7SSteve Wise module_param(crc_enabled, int, 0644);
130cfdda9d7SSteve Wise MODULE_PARM_DESC(crc_enabled, "Enable MPA CRC (default(1)=enabled)");
131cfdda9d7SSteve Wise 
132cfdda9d7SSteve Wise static int rcv_win = 256 * 1024;
133cfdda9d7SSteve Wise module_param(rcv_win, int, 0644);
134cfdda9d7SSteve Wise MODULE_PARM_DESC(rcv_win, "TCP receive window in bytes (default=256KB)");
135cfdda9d7SSteve Wise 
13698ae68b7SSteve Wise static int snd_win = 128 * 1024;
137cfdda9d7SSteve Wise module_param(snd_win, int, 0644);
13898ae68b7SSteve Wise MODULE_PARM_DESC(snd_win, "TCP send window in bytes (default=128KB)");
139cfdda9d7SSteve Wise 
140cfdda9d7SSteve Wise static struct workqueue_struct *workq;
141cfdda9d7SSteve Wise 
142cfdda9d7SSteve Wise static struct sk_buff_head rxq;
143cfdda9d7SSteve Wise 
144cfdda9d7SSteve Wise static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp);
145cfdda9d7SSteve Wise static void ep_timeout(unsigned long arg);
146cfdda9d7SSteve Wise static void connect_reply_upcall(struct c4iw_ep *ep, int status);
147cfdda9d7SSteve Wise 
148be4c9badSRoland Dreier static LIST_HEAD(timeout_list);
149be4c9badSRoland Dreier static spinlock_t timeout_lock;
150be4c9badSRoland Dreier 
151325abeadSVipul Pandya static void deref_qp(struct c4iw_ep *ep)
152325abeadSVipul Pandya {
153325abeadSVipul Pandya 	c4iw_qp_rem_ref(&ep->com.qp->ibqp);
154325abeadSVipul Pandya 	clear_bit(QP_REFERENCED, &ep->com.flags);
155325abeadSVipul Pandya }
156325abeadSVipul Pandya 
157325abeadSVipul Pandya static void ref_qp(struct c4iw_ep *ep)
158325abeadSVipul Pandya {
159325abeadSVipul Pandya 	set_bit(QP_REFERENCED, &ep->com.flags);
160325abeadSVipul Pandya 	c4iw_qp_add_ref(&ep->com.qp->ibqp);
161325abeadSVipul Pandya }
162325abeadSVipul Pandya 
163cfdda9d7SSteve Wise static void start_ep_timer(struct c4iw_ep *ep)
164cfdda9d7SSteve Wise {
165cfdda9d7SSteve Wise 	PDBG("%s ep %p\n", __func__, ep);
166cfdda9d7SSteve Wise 	if (timer_pending(&ep->timer)) {
1671ec779ccSVipul Pandya 		pr_err("%s timer already started! ep %p\n",
1681ec779ccSVipul Pandya 		       __func__, ep);
1691ec779ccSVipul Pandya 		return;
1701ec779ccSVipul Pandya 	}
1711ec779ccSVipul Pandya 	clear_bit(TIMEOUT, &ep->com.flags);
172cfdda9d7SSteve Wise 	c4iw_get_ep(&ep->com);
173cfdda9d7SSteve Wise 	ep->timer.expires = jiffies + ep_timeout_secs * HZ;
174cfdda9d7SSteve Wise 	ep->timer.data = (unsigned long)ep;
175cfdda9d7SSteve Wise 	ep->timer.function = ep_timeout;
176cfdda9d7SSteve Wise 	add_timer(&ep->timer);
177cfdda9d7SSteve Wise }
178cfdda9d7SSteve Wise 
179b33bd0cbSSteve Wise static int stop_ep_timer(struct c4iw_ep *ep)
180cfdda9d7SSteve Wise {
1811ec779ccSVipul Pandya 	PDBG("%s ep %p stopping\n", __func__, ep);
182cfdda9d7SSteve Wise 	del_timer_sync(&ep->timer);
183b33bd0cbSSteve Wise 	if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) {
184cfdda9d7SSteve Wise 		c4iw_put_ep(&ep->com);
185b33bd0cbSSteve Wise 		return 0;
186b33bd0cbSSteve Wise 	}
187b33bd0cbSSteve Wise 	return 1;
188cfdda9d7SSteve Wise }
189cfdda9d7SSteve Wise 
190cfdda9d7SSteve Wise static int c4iw_l2t_send(struct c4iw_rdev *rdev, struct sk_buff *skb,
191cfdda9d7SSteve Wise 		  struct l2t_entry *l2e)
192cfdda9d7SSteve Wise {
193cfdda9d7SSteve Wise 	int	error = 0;
194cfdda9d7SSteve Wise 
195cfdda9d7SSteve Wise 	if (c4iw_fatal_error(rdev)) {
196cfdda9d7SSteve Wise 		kfree_skb(skb);
197cfdda9d7SSteve Wise 		PDBG("%s - device in error state - dropping\n", __func__);
198cfdda9d7SSteve Wise 		return -EIO;
199cfdda9d7SSteve Wise 	}
200cfdda9d7SSteve Wise 	error = cxgb4_l2t_send(rdev->lldi.ports[0], skb, l2e);
201cfdda9d7SSteve Wise 	if (error < 0)
202cfdda9d7SSteve Wise 		kfree_skb(skb);
20374594861SSteve Wise 	return error < 0 ? error : 0;
204cfdda9d7SSteve Wise }
205cfdda9d7SSteve Wise 
206cfdda9d7SSteve Wise int c4iw_ofld_send(struct c4iw_rdev *rdev, struct sk_buff *skb)
207cfdda9d7SSteve Wise {
208cfdda9d7SSteve Wise 	int	error = 0;
209cfdda9d7SSteve Wise 
210cfdda9d7SSteve Wise 	if (c4iw_fatal_error(rdev)) {
211cfdda9d7SSteve Wise 		kfree_skb(skb);
212cfdda9d7SSteve Wise 		PDBG("%s - device in error state - dropping\n", __func__);
213cfdda9d7SSteve Wise 		return -EIO;
214cfdda9d7SSteve Wise 	}
215cfdda9d7SSteve Wise 	error = cxgb4_ofld_send(rdev->lldi.ports[0], skb);
216cfdda9d7SSteve Wise 	if (error < 0)
217cfdda9d7SSteve Wise 		kfree_skb(skb);
21874594861SSteve Wise 	return error < 0 ? error : 0;
219cfdda9d7SSteve Wise }
220cfdda9d7SSteve Wise 
221cfdda9d7SSteve Wise static void release_tid(struct c4iw_rdev *rdev, u32 hwtid, struct sk_buff *skb)
222cfdda9d7SSteve Wise {
223cfdda9d7SSteve Wise 	struct cpl_tid_release *req;
224cfdda9d7SSteve Wise 
225cfdda9d7SSteve Wise 	skb = get_skb(skb, sizeof *req, GFP_KERNEL);
226cfdda9d7SSteve Wise 	if (!skb)
227cfdda9d7SSteve Wise 		return;
228cfdda9d7SSteve Wise 	req = (struct cpl_tid_release *) skb_put(skb, sizeof(*req));
229cfdda9d7SSteve Wise 	INIT_TP_WR(req, hwtid);
230cfdda9d7SSteve Wise 	OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_TID_RELEASE, hwtid));
231cfdda9d7SSteve Wise 	set_wr_txq(skb, CPL_PRIORITY_SETUP, 0);
232cfdda9d7SSteve Wise 	c4iw_ofld_send(rdev, skb);
233cfdda9d7SSteve Wise 	return;
234cfdda9d7SSteve Wise }
235cfdda9d7SSteve Wise 
236cfdda9d7SSteve Wise static void set_emss(struct c4iw_ep *ep, u16 opt)
237cfdda9d7SSteve Wise {
2386c53e938SHariprasad Shenai 	ep->emss = ep->com.dev->rdev.lldi.mtus[TCPOPT_MSS_G(opt)] -
23904524a47SHariprasad S 		   ((AF_INET == ep->com.remote_addr.ss_family) ?
24004524a47SHariprasad S 		    sizeof(struct iphdr) : sizeof(struct ipv6hdr)) -
24104524a47SHariprasad S 		   sizeof(struct tcphdr);
242cfdda9d7SSteve Wise 	ep->mss = ep->emss;
2436c53e938SHariprasad Shenai 	if (TCPOPT_TSTAMP_G(opt))
24404524a47SHariprasad S 		ep->emss -= round_up(TCPOLEN_TIMESTAMP, 4);
245cfdda9d7SSteve Wise 	if (ep->emss < 128)
246cfdda9d7SSteve Wise 		ep->emss = 128;
24792e7ae71SHariprasad Shenai 	if (ep->emss & 7)
24892e7ae71SHariprasad Shenai 		PDBG("Warning: misaligned mtu idx %u mss %u emss=%u\n",
2496c53e938SHariprasad Shenai 		     TCPOPT_MSS_G(opt), ep->mss, ep->emss);
2506c53e938SHariprasad Shenai 	PDBG("%s mss_idx %u mss %u emss=%u\n", __func__, TCPOPT_MSS_G(opt),
251cfdda9d7SSteve Wise 	     ep->mss, ep->emss);
252cfdda9d7SSteve Wise }
253cfdda9d7SSteve Wise 
254cfdda9d7SSteve Wise static enum c4iw_ep_state state_read(struct c4iw_ep_common *epc)
255cfdda9d7SSteve Wise {
256cfdda9d7SSteve Wise 	enum c4iw_ep_state state;
257cfdda9d7SSteve Wise 
2582f5b48c3SSteve Wise 	mutex_lock(&epc->mutex);
259cfdda9d7SSteve Wise 	state = epc->state;
2602f5b48c3SSteve Wise 	mutex_unlock(&epc->mutex);
261cfdda9d7SSteve Wise 	return state;
262cfdda9d7SSteve Wise }
263cfdda9d7SSteve Wise 
264cfdda9d7SSteve Wise static void __state_set(struct c4iw_ep_common *epc, enum c4iw_ep_state new)
265cfdda9d7SSteve Wise {
266cfdda9d7SSteve Wise 	epc->state = new;
267cfdda9d7SSteve Wise }
268cfdda9d7SSteve Wise 
269cfdda9d7SSteve Wise static void state_set(struct c4iw_ep_common *epc, enum c4iw_ep_state new)
270cfdda9d7SSteve Wise {
2712f5b48c3SSteve Wise 	mutex_lock(&epc->mutex);
272cfdda9d7SSteve Wise 	PDBG("%s - %s -> %s\n", __func__, states[epc->state], states[new]);
273cfdda9d7SSteve Wise 	__state_set(epc, new);
2742f5b48c3SSteve Wise 	mutex_unlock(&epc->mutex);
275cfdda9d7SSteve Wise 	return;
276cfdda9d7SSteve Wise }
277cfdda9d7SSteve Wise 
278cfdda9d7SSteve Wise static void *alloc_ep(int size, gfp_t gfp)
279cfdda9d7SSteve Wise {
280cfdda9d7SSteve Wise 	struct c4iw_ep_common *epc;
281cfdda9d7SSteve Wise 
282cfdda9d7SSteve Wise 	epc = kzalloc(size, gfp);
283cfdda9d7SSteve Wise 	if (epc) {
284cfdda9d7SSteve Wise 		kref_init(&epc->kref);
2852f5b48c3SSteve Wise 		mutex_init(&epc->mutex);
286aadc4df3SSteve Wise 		c4iw_init_wr_wait(&epc->wr_wait);
287cfdda9d7SSteve Wise 	}
288cfdda9d7SSteve Wise 	PDBG("%s alloc ep %p\n", __func__, epc);
289cfdda9d7SSteve Wise 	return epc;
290cfdda9d7SSteve Wise }
291cfdda9d7SSteve Wise 
292cfdda9d7SSteve Wise void _c4iw_free_ep(struct kref *kref)
293cfdda9d7SSteve Wise {
294cfdda9d7SSteve Wise 	struct c4iw_ep *ep;
295cfdda9d7SSteve Wise 
296cfdda9d7SSteve Wise 	ep = container_of(kref, struct c4iw_ep, com.kref);
297cfdda9d7SSteve Wise 	PDBG("%s ep %p state %s\n", __func__, ep, states[state_read(&ep->com)]);
298325abeadSVipul Pandya 	if (test_bit(QP_REFERENCED, &ep->com.flags))
299325abeadSVipul Pandya 		deref_qp(ep);
300cfdda9d7SSteve Wise 	if (test_bit(RELEASE_RESOURCES, &ep->com.flags)) {
301fe7e0a4dSVipul Pandya 		remove_handle(ep->com.dev, &ep->com.dev->hwtid_idr, ep->hwtid);
302cfdda9d7SSteve Wise 		cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid);
303cfdda9d7SSteve Wise 		dst_release(ep->dst);
304cfdda9d7SSteve Wise 		cxgb4_l2t_release(ep->l2t);
305cfdda9d7SSteve Wise 	}
3069eccfe10SSteve Wise 	if (test_bit(RELEASE_MAPINFO, &ep->com.flags)) {
3079eccfe10SSteve Wise 		print_addr(&ep->com, __func__, "remove_mapinfo/mapping");
3089eccfe10SSteve Wise 		iwpm_remove_mapinfo(&ep->com.local_addr,
3099eccfe10SSteve Wise 				    &ep->com.mapped_local_addr);
3109eccfe10SSteve Wise 		iwpm_remove_mapping(&ep->com.local_addr, RDMA_NL_C4IW);
3119eccfe10SSteve Wise 	}
312cfdda9d7SSteve Wise 	kfree(ep);
313cfdda9d7SSteve Wise }
314cfdda9d7SSteve Wise 
315cfdda9d7SSteve Wise static void release_ep_resources(struct c4iw_ep *ep)
316cfdda9d7SSteve Wise {
317cfdda9d7SSteve Wise 	set_bit(RELEASE_RESOURCES, &ep->com.flags);
318cfdda9d7SSteve Wise 	c4iw_put_ep(&ep->com);
319cfdda9d7SSteve Wise }
320cfdda9d7SSteve Wise 
321cfdda9d7SSteve Wise static int status2errno(int status)
322cfdda9d7SSteve Wise {
323cfdda9d7SSteve Wise 	switch (status) {
324cfdda9d7SSteve Wise 	case CPL_ERR_NONE:
325cfdda9d7SSteve Wise 		return 0;
326cfdda9d7SSteve Wise 	case CPL_ERR_CONN_RESET:
327cfdda9d7SSteve Wise 		return -ECONNRESET;
328cfdda9d7SSteve Wise 	case CPL_ERR_ARP_MISS:
329cfdda9d7SSteve Wise 		return -EHOSTUNREACH;
330cfdda9d7SSteve Wise 	case CPL_ERR_CONN_TIMEDOUT:
331cfdda9d7SSteve Wise 		return -ETIMEDOUT;
332cfdda9d7SSteve Wise 	case CPL_ERR_TCAM_FULL:
333cfdda9d7SSteve Wise 		return -ENOMEM;
334cfdda9d7SSteve Wise 	case CPL_ERR_CONN_EXIST:
335cfdda9d7SSteve Wise 		return -EADDRINUSE;
336cfdda9d7SSteve Wise 	default:
337cfdda9d7SSteve Wise 		return -EIO;
338cfdda9d7SSteve Wise 	}
339cfdda9d7SSteve Wise }
340cfdda9d7SSteve Wise 
341cfdda9d7SSteve Wise /*
342cfdda9d7SSteve Wise  * Try and reuse skbs already allocated...
343cfdda9d7SSteve Wise  */
344cfdda9d7SSteve Wise static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp)
345cfdda9d7SSteve Wise {
346cfdda9d7SSteve Wise 	if (skb && !skb_is_nonlinear(skb) && !skb_cloned(skb)) {
347cfdda9d7SSteve Wise 		skb_trim(skb, 0);
348cfdda9d7SSteve Wise 		skb_get(skb);
349cfdda9d7SSteve Wise 		skb_reset_transport_header(skb);
350cfdda9d7SSteve Wise 	} else {
351cfdda9d7SSteve Wise 		skb = alloc_skb(len, gfp);
352cfdda9d7SSteve Wise 	}
353b38a0ad8SSteve Wise 	t4_set_arp_err_handler(skb, NULL, NULL);
354cfdda9d7SSteve Wise 	return skb;
355cfdda9d7SSteve Wise }
356cfdda9d7SSteve Wise 
357830662f6SVipul Pandya static struct net_device *get_real_dev(struct net_device *egress_dev)
358830662f6SVipul Pandya {
35911b8e22dSSteve Wise 	return rdma_vlan_dev_real_dev(egress_dev) ? : egress_dev;
360830662f6SVipul Pandya }
361830662f6SVipul Pandya 
362830662f6SVipul Pandya static int our_interface(struct c4iw_dev *dev, struct net_device *egress_dev)
363830662f6SVipul Pandya {
364830662f6SVipul Pandya 	int i;
365830662f6SVipul Pandya 
366830662f6SVipul Pandya 	egress_dev = get_real_dev(egress_dev);
367830662f6SVipul Pandya 	for (i = 0; i < dev->rdev.lldi.nports; i++)
368830662f6SVipul Pandya 		if (dev->rdev.lldi.ports[i] == egress_dev)
369830662f6SVipul Pandya 			return 1;
370830662f6SVipul Pandya 	return 0;
371830662f6SVipul Pandya }
372830662f6SVipul Pandya 
373830662f6SVipul Pandya static struct dst_entry *find_route6(struct c4iw_dev *dev, __u8 *local_ip,
374830662f6SVipul Pandya 				     __u8 *peer_ip, __be16 local_port,
375830662f6SVipul Pandya 				     __be16 peer_port, u8 tos,
376830662f6SVipul Pandya 				     __u32 sin6_scope_id)
377830662f6SVipul Pandya {
378830662f6SVipul Pandya 	struct dst_entry *dst = NULL;
379830662f6SVipul Pandya 
380830662f6SVipul Pandya 	if (IS_ENABLED(CONFIG_IPV6)) {
381830662f6SVipul Pandya 		struct flowi6 fl6;
382830662f6SVipul Pandya 
383830662f6SVipul Pandya 		memset(&fl6, 0, sizeof(fl6));
384830662f6SVipul Pandya 		memcpy(&fl6.daddr, peer_ip, 16);
385830662f6SVipul Pandya 		memcpy(&fl6.saddr, local_ip, 16);
386830662f6SVipul Pandya 		if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL)
387830662f6SVipul Pandya 			fl6.flowi6_oif = sin6_scope_id;
388830662f6SVipul Pandya 		dst = ip6_route_output(&init_net, NULL, &fl6);
389830662f6SVipul Pandya 		if (!dst)
390830662f6SVipul Pandya 			goto out;
391830662f6SVipul Pandya 		if (!our_interface(dev, ip6_dst_idev(dst)->dev) &&
392830662f6SVipul Pandya 		    !(ip6_dst_idev(dst)->dev->flags & IFF_LOOPBACK)) {
393830662f6SVipul Pandya 			dst_release(dst);
394830662f6SVipul Pandya 			dst = NULL;
395830662f6SVipul Pandya 		}
396830662f6SVipul Pandya 	}
397830662f6SVipul Pandya 
398830662f6SVipul Pandya out:
399830662f6SVipul Pandya 	return dst;
400830662f6SVipul Pandya }
401830662f6SVipul Pandya 
402830662f6SVipul Pandya static struct dst_entry *find_route(struct c4iw_dev *dev, __be32 local_ip,
403cfdda9d7SSteve Wise 				 __be32 peer_ip, __be16 local_port,
404cfdda9d7SSteve Wise 				 __be16 peer_port, u8 tos)
405cfdda9d7SSteve Wise {
406cfdda9d7SSteve Wise 	struct rtable *rt;
40731e4543dSDavid S. Miller 	struct flowi4 fl4;
408830662f6SVipul Pandya 	struct neighbour *n;
409cfdda9d7SSteve Wise 
41031e4543dSDavid S. Miller 	rt = ip_route_output_ports(&init_net, &fl4, NULL, peer_ip, local_ip,
41178fbfd8aSDavid S. Miller 				   peer_port, local_port, IPPROTO_TCP,
41278fbfd8aSDavid S. Miller 				   tos, 0);
413b23dd4feSDavid S. Miller 	if (IS_ERR(rt))
414cfdda9d7SSteve Wise 		return NULL;
415830662f6SVipul Pandya 	n = dst_neigh_lookup(&rt->dst, &peer_ip);
416830662f6SVipul Pandya 	if (!n)
417830662f6SVipul Pandya 		return NULL;
418f8e81908SSteve Wise 	if (!our_interface(dev, n->dev) &&
419f8e81908SSteve Wise 	    !(n->dev->flags & IFF_LOOPBACK)) {
420d480201bSHariprasad S 		neigh_release(n);
421830662f6SVipul Pandya 		dst_release(&rt->dst);
422830662f6SVipul Pandya 		return NULL;
423830662f6SVipul Pandya 	}
424830662f6SVipul Pandya 	neigh_release(n);
425830662f6SVipul Pandya 	return &rt->dst;
426cfdda9d7SSteve Wise }
427cfdda9d7SSteve Wise 
428cfdda9d7SSteve Wise static void arp_failure_discard(void *handle, struct sk_buff *skb)
429cfdda9d7SSteve Wise {
430cfdda9d7SSteve Wise 	PDBG("%s c4iw_dev %p\n", __func__, handle);
431cfdda9d7SSteve Wise 	kfree_skb(skb);
432cfdda9d7SSteve Wise }
433cfdda9d7SSteve Wise 
434cfdda9d7SSteve Wise /*
435cfdda9d7SSteve Wise  * Handle an ARP failure for an active open.
436cfdda9d7SSteve Wise  */
437cfdda9d7SSteve Wise static void act_open_req_arp_failure(void *handle, struct sk_buff *skb)
438cfdda9d7SSteve Wise {
4395dab6d3aSHariprasad S 	struct c4iw_ep *ep = handle;
4405dab6d3aSHariprasad S 
441cfdda9d7SSteve Wise 	printk(KERN_ERR MOD "ARP failure duing connect\n");
442cfdda9d7SSteve Wise 	kfree_skb(skb);
4435dab6d3aSHariprasad S 	connect_reply_upcall(ep, -EHOSTUNREACH);
4445dab6d3aSHariprasad S 	state_set(&ep->com, DEAD);
4455dab6d3aSHariprasad S 	remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid);
4465dab6d3aSHariprasad S 	cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid);
4475dab6d3aSHariprasad S 	dst_release(ep->dst);
4485dab6d3aSHariprasad S 	cxgb4_l2t_release(ep->l2t);
4495dab6d3aSHariprasad S 	c4iw_put_ep(&ep->com);
450cfdda9d7SSteve Wise }
451cfdda9d7SSteve Wise 
452cfdda9d7SSteve Wise /*
453cfdda9d7SSteve Wise  * Handle an ARP failure for a CPL_ABORT_REQ.  Change it into a no RST variant
454cfdda9d7SSteve Wise  * and send it along.
455cfdda9d7SSteve Wise  */
456cfdda9d7SSteve Wise static void abort_arp_failure(void *handle, struct sk_buff *skb)
457cfdda9d7SSteve Wise {
458cfdda9d7SSteve Wise 	struct c4iw_rdev *rdev = handle;
459cfdda9d7SSteve Wise 	struct cpl_abort_req *req = cplhdr(skb);
460cfdda9d7SSteve Wise 
461cfdda9d7SSteve Wise 	PDBG("%s rdev %p\n", __func__, rdev);
462cfdda9d7SSteve Wise 	req->cmd = CPL_ABORT_NO_RST;
463cfdda9d7SSteve Wise 	c4iw_ofld_send(rdev, skb);
464cfdda9d7SSteve Wise }
465cfdda9d7SSteve Wise 
466cfdda9d7SSteve Wise static void send_flowc(struct c4iw_ep *ep, struct sk_buff *skb)
467cfdda9d7SSteve Wise {
468cfdda9d7SSteve Wise 	unsigned int flowclen = 80;
469cfdda9d7SSteve Wise 	struct fw_flowc_wr *flowc;
470cfdda9d7SSteve Wise 	int i;
471cfdda9d7SSteve Wise 
472cfdda9d7SSteve Wise 	skb = get_skb(skb, flowclen, GFP_KERNEL);
473cfdda9d7SSteve Wise 	flowc = (struct fw_flowc_wr *)__skb_put(skb, flowclen);
474cfdda9d7SSteve Wise 
475e2ac9628SHariprasad Shenai 	flowc->op_to_nparams = cpu_to_be32(FW_WR_OP_V(FW_FLOWC_WR) |
476e2ac9628SHariprasad Shenai 					   FW_FLOWC_WR_NPARAMS_V(8));
477e2ac9628SHariprasad Shenai 	flowc->flowid_len16 = cpu_to_be32(FW_WR_LEN16_V(DIV_ROUND_UP(flowclen,
478e2ac9628SHariprasad Shenai 					  16)) | FW_WR_FLOWID_V(ep->hwtid));
479cfdda9d7SSteve Wise 
480cfdda9d7SSteve Wise 	flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN;
4815167865aSHariprasad Shenai 	flowc->mnemval[0].val = cpu_to_be32(FW_PFVF_CMD_PFN_V
48235b1de55SHariprasad Shenai 					    (ep->com.dev->rdev.lldi.pf));
483cfdda9d7SSteve Wise 	flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH;
484cfdda9d7SSteve Wise 	flowc->mnemval[1].val = cpu_to_be32(ep->tx_chan);
485cfdda9d7SSteve Wise 	flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT;
486cfdda9d7SSteve Wise 	flowc->mnemval[2].val = cpu_to_be32(ep->tx_chan);
487cfdda9d7SSteve Wise 	flowc->mnemval[3].mnemonic = FW_FLOWC_MNEM_IQID;
488cfdda9d7SSteve Wise 	flowc->mnemval[3].val = cpu_to_be32(ep->rss_qid);
489cfdda9d7SSteve Wise 	flowc->mnemval[4].mnemonic = FW_FLOWC_MNEM_SNDNXT;
490cfdda9d7SSteve Wise 	flowc->mnemval[4].val = cpu_to_be32(ep->snd_seq);
491cfdda9d7SSteve Wise 	flowc->mnemval[5].mnemonic = FW_FLOWC_MNEM_RCVNXT;
492cfdda9d7SSteve Wise 	flowc->mnemval[5].val = cpu_to_be32(ep->rcv_seq);
493cfdda9d7SSteve Wise 	flowc->mnemval[6].mnemonic = FW_FLOWC_MNEM_SNDBUF;
494b408ff28SHariprasad Shenai 	flowc->mnemval[6].val = cpu_to_be32(ep->snd_win);
495cfdda9d7SSteve Wise 	flowc->mnemval[7].mnemonic = FW_FLOWC_MNEM_MSS;
496cfdda9d7SSteve Wise 	flowc->mnemval[7].val = cpu_to_be32(ep->emss);
497cfdda9d7SSteve Wise 	/* Pad WR to 16 byte boundary */
498cfdda9d7SSteve Wise 	flowc->mnemval[8].mnemonic = 0;
499cfdda9d7SSteve Wise 	flowc->mnemval[8].val = 0;
500cfdda9d7SSteve Wise 	for (i = 0; i < 9; i++) {
501cfdda9d7SSteve Wise 		flowc->mnemval[i].r4[0] = 0;
502cfdda9d7SSteve Wise 		flowc->mnemval[i].r4[1] = 0;
503cfdda9d7SSteve Wise 		flowc->mnemval[i].r4[2] = 0;
504cfdda9d7SSteve Wise 	}
505cfdda9d7SSteve Wise 
506cfdda9d7SSteve Wise 	set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
507cfdda9d7SSteve Wise 	c4iw_ofld_send(&ep->com.dev->rdev, skb);
508cfdda9d7SSteve Wise }
509cfdda9d7SSteve Wise 
510cfdda9d7SSteve Wise static int send_halfclose(struct c4iw_ep *ep, gfp_t gfp)
511cfdda9d7SSteve Wise {
512cfdda9d7SSteve Wise 	struct cpl_close_con_req *req;
513cfdda9d7SSteve Wise 	struct sk_buff *skb;
514cfdda9d7SSteve Wise 	int wrlen = roundup(sizeof *req, 16);
515cfdda9d7SSteve Wise 
516cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
517cfdda9d7SSteve Wise 	skb = get_skb(NULL, wrlen, gfp);
518cfdda9d7SSteve Wise 	if (!skb) {
519cfdda9d7SSteve Wise 		printk(KERN_ERR MOD "%s - failed to alloc skb\n", __func__);
520cfdda9d7SSteve Wise 		return -ENOMEM;
521cfdda9d7SSteve Wise 	}
522cfdda9d7SSteve Wise 	set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
523cfdda9d7SSteve Wise 	t4_set_arp_err_handler(skb, NULL, arp_failure_discard);
524cfdda9d7SSteve Wise 	req = (struct cpl_close_con_req *) skb_put(skb, wrlen);
525cfdda9d7SSteve Wise 	memset(req, 0, wrlen);
526cfdda9d7SSteve Wise 	INIT_TP_WR(req, ep->hwtid);
527cfdda9d7SSteve Wise 	OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_CLOSE_CON_REQ,
528cfdda9d7SSteve Wise 						    ep->hwtid));
529cfdda9d7SSteve Wise 	return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
530cfdda9d7SSteve Wise }
531cfdda9d7SSteve Wise 
532cfdda9d7SSteve Wise static int send_abort(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
533cfdda9d7SSteve Wise {
534cfdda9d7SSteve Wise 	struct cpl_abort_req *req;
535cfdda9d7SSteve Wise 	int wrlen = roundup(sizeof *req, 16);
536cfdda9d7SSteve Wise 
537cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
538cfdda9d7SSteve Wise 	skb = get_skb(skb, wrlen, gfp);
539cfdda9d7SSteve Wise 	if (!skb) {
540cfdda9d7SSteve Wise 		printk(KERN_ERR MOD "%s - failed to alloc skb.\n",
541cfdda9d7SSteve Wise 		       __func__);
542cfdda9d7SSteve Wise 		return -ENOMEM;
543cfdda9d7SSteve Wise 	}
544cfdda9d7SSteve Wise 	set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
545cfdda9d7SSteve Wise 	t4_set_arp_err_handler(skb, &ep->com.dev->rdev, abort_arp_failure);
546cfdda9d7SSteve Wise 	req = (struct cpl_abort_req *) skb_put(skb, wrlen);
547cfdda9d7SSteve Wise 	memset(req, 0, wrlen);
548cfdda9d7SSteve Wise 	INIT_TP_WR(req, ep->hwtid);
549cfdda9d7SSteve Wise 	OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_REQ, ep->hwtid));
550cfdda9d7SSteve Wise 	req->cmd = CPL_ABORT_SEND_RST;
551cfdda9d7SSteve Wise 	return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
552cfdda9d7SSteve Wise }
553cfdda9d7SSteve Wise 
5549eccfe10SSteve Wise /*
5559eccfe10SSteve Wise  * c4iw_form_pm_msg - Form a port mapper message with mapping info
5569eccfe10SSteve Wise  */
5579eccfe10SSteve Wise static void c4iw_form_pm_msg(struct c4iw_ep *ep,
5589eccfe10SSteve Wise 				struct iwpm_sa_data *pm_msg)
5599eccfe10SSteve Wise {
5609eccfe10SSteve Wise 	memcpy(&pm_msg->loc_addr, &ep->com.local_addr,
5619eccfe10SSteve Wise 		sizeof(ep->com.local_addr));
5629eccfe10SSteve Wise 	memcpy(&pm_msg->rem_addr, &ep->com.remote_addr,
5639eccfe10SSteve Wise 		sizeof(ep->com.remote_addr));
5649eccfe10SSteve Wise }
5659eccfe10SSteve Wise 
5669eccfe10SSteve Wise /*
5679eccfe10SSteve Wise  * c4iw_form_reg_msg - Form a port mapper message with dev info
5689eccfe10SSteve Wise  */
5699eccfe10SSteve Wise static void c4iw_form_reg_msg(struct c4iw_dev *dev,
5709eccfe10SSteve Wise 				struct iwpm_dev_data *pm_msg)
5719eccfe10SSteve Wise {
5729eccfe10SSteve Wise 	memcpy(pm_msg->dev_name, dev->ibdev.name, IWPM_DEVNAME_SIZE);
5739eccfe10SSteve Wise 	memcpy(pm_msg->if_name, dev->rdev.lldi.ports[0]->name,
5749eccfe10SSteve Wise 				IWPM_IFNAME_SIZE);
5759eccfe10SSteve Wise }
5769eccfe10SSteve Wise 
5779eccfe10SSteve Wise static void c4iw_record_pm_msg(struct c4iw_ep *ep,
5789eccfe10SSteve Wise 			struct iwpm_sa_data *pm_msg)
5799eccfe10SSteve Wise {
5809eccfe10SSteve Wise 	memcpy(&ep->com.mapped_local_addr, &pm_msg->mapped_loc_addr,
5819eccfe10SSteve Wise 		sizeof(ep->com.mapped_local_addr));
5829eccfe10SSteve Wise 	memcpy(&ep->com.mapped_remote_addr, &pm_msg->mapped_rem_addr,
5839eccfe10SSteve Wise 		sizeof(ep->com.mapped_remote_addr));
5849eccfe10SSteve Wise }
5859eccfe10SSteve Wise 
58692e7ae71SHariprasad Shenai static void best_mtu(const unsigned short *mtus, unsigned short mtu,
58704524a47SHariprasad S 		     unsigned int *idx, int use_ts, int ipv6)
58892e7ae71SHariprasad Shenai {
58904524a47SHariprasad S 	unsigned short hdr_size = (ipv6 ?
59004524a47SHariprasad S 				   sizeof(struct ipv6hdr) :
59104524a47SHariprasad S 				   sizeof(struct iphdr)) +
59292e7ae71SHariprasad Shenai 				  sizeof(struct tcphdr) +
59304524a47SHariprasad S 				  (use_ts ?
59404524a47SHariprasad S 				   round_up(TCPOLEN_TIMESTAMP, 4) : 0);
59592e7ae71SHariprasad Shenai 	unsigned short data_size = mtu - hdr_size;
59692e7ae71SHariprasad Shenai 
59792e7ae71SHariprasad Shenai 	cxgb4_best_aligned_mtu(mtus, hdr_size, data_size, 8, idx);
59892e7ae71SHariprasad Shenai }
59992e7ae71SHariprasad Shenai 
600cfdda9d7SSteve Wise static int send_connect(struct c4iw_ep *ep)
601cfdda9d7SSteve Wise {
602cfdda9d7SSteve Wise 	struct cpl_act_open_req *req;
603f079af7aSVipul Pandya 	struct cpl_t5_act_open_req *t5_req;
604830662f6SVipul Pandya 	struct cpl_act_open_req6 *req6;
605830662f6SVipul Pandya 	struct cpl_t5_act_open_req6 *t5_req6;
606cfdda9d7SSteve Wise 	struct sk_buff *skb;
607cfdda9d7SSteve Wise 	u64 opt0;
608cfdda9d7SSteve Wise 	u32 opt2;
609cfdda9d7SSteve Wise 	unsigned int mtu_idx;
610cfdda9d7SSteve Wise 	int wscale;
611830662f6SVipul Pandya 	int wrlen;
612830662f6SVipul Pandya 	int sizev4 = is_t4(ep->com.dev->rdev.lldi.adapter_type) ?
613f079af7aSVipul Pandya 				sizeof(struct cpl_act_open_req) :
614f079af7aSVipul Pandya 				sizeof(struct cpl_t5_act_open_req);
615830662f6SVipul Pandya 	int sizev6 = is_t4(ep->com.dev->rdev.lldi.adapter_type) ?
616830662f6SVipul Pandya 				sizeof(struct cpl_act_open_req6) :
617830662f6SVipul Pandya 				sizeof(struct cpl_t5_act_open_req6);
6189eccfe10SSteve Wise 	struct sockaddr_in *la = (struct sockaddr_in *)
6199eccfe10SSteve Wise 				 &ep->com.mapped_local_addr;
6209eccfe10SSteve Wise 	struct sockaddr_in *ra = (struct sockaddr_in *)
6219eccfe10SSteve Wise 				 &ep->com.mapped_remote_addr;
6229eccfe10SSteve Wise 	struct sockaddr_in6 *la6 = (struct sockaddr_in6 *)
6239eccfe10SSteve Wise 				   &ep->com.mapped_local_addr;
6249eccfe10SSteve Wise 	struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)
6259eccfe10SSteve Wise 				   &ep->com.mapped_remote_addr;
626b408ff28SHariprasad Shenai 	int win;
627830662f6SVipul Pandya 
628830662f6SVipul Pandya 	wrlen = (ep->com.remote_addr.ss_family == AF_INET) ?
629830662f6SVipul Pandya 			roundup(sizev4, 16) :
630830662f6SVipul Pandya 			roundup(sizev6, 16);
631cfdda9d7SSteve Wise 
632cfdda9d7SSteve Wise 	PDBG("%s ep %p atid %u\n", __func__, ep, ep->atid);
633cfdda9d7SSteve Wise 
634cfdda9d7SSteve Wise 	skb = get_skb(NULL, wrlen, GFP_KERNEL);
635cfdda9d7SSteve Wise 	if (!skb) {
636cfdda9d7SSteve Wise 		printk(KERN_ERR MOD "%s - failed to alloc skb.\n",
637cfdda9d7SSteve Wise 		       __func__);
638cfdda9d7SSteve Wise 		return -ENOMEM;
639cfdda9d7SSteve Wise 	}
640d4f1a5c6SSteve Wise 	set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->ctrlq_idx);
641cfdda9d7SSteve Wise 
64292e7ae71SHariprasad Shenai 	best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx,
64304524a47SHariprasad S 		 enable_tcp_timestamps,
64404524a47SHariprasad S 		 (AF_INET == ep->com.remote_addr.ss_family) ? 0 : 1);
645cfdda9d7SSteve Wise 	wscale = compute_wscale(rcv_win);
646b408ff28SHariprasad Shenai 
647b408ff28SHariprasad Shenai 	/*
648b408ff28SHariprasad Shenai 	 * Specify the largest window that will fit in opt0. The
649b408ff28SHariprasad Shenai 	 * remainder will be specified in the rx_data_ack.
650b408ff28SHariprasad Shenai 	 */
651b408ff28SHariprasad Shenai 	win = ep->rcv_win >> 10;
652d7990b0cSAnish Bhatt 	if (win > RCV_BUFSIZ_M)
653d7990b0cSAnish Bhatt 		win = RCV_BUFSIZ_M;
654b408ff28SHariprasad Shenai 
6556c53e938SHariprasad Shenai 	opt0 = (nocong ? NO_CONG_F : 0) |
656d7990b0cSAnish Bhatt 	       KEEP_ALIVE_F |
6576c53e938SHariprasad Shenai 	       DELACK_F |
658d7990b0cSAnish Bhatt 	       WND_SCALE_V(wscale) |
659d7990b0cSAnish Bhatt 	       MSS_IDX_V(mtu_idx) |
660d7990b0cSAnish Bhatt 	       L2T_IDX_V(ep->l2t->idx) |
661d7990b0cSAnish Bhatt 	       TX_CHAN_V(ep->tx_chan) |
662d7990b0cSAnish Bhatt 	       SMAC_SEL_V(ep->smac_idx) |
6636c53e938SHariprasad Shenai 	       DSCP_V(ep->tos) |
664d7990b0cSAnish Bhatt 	       ULP_MODE_V(ULP_MODE_TCPDDP) |
665d7990b0cSAnish Bhatt 	       RCV_BUFSIZ_V(win);
666d7990b0cSAnish Bhatt 	opt2 = RX_CHANNEL_V(0) |
6676c53e938SHariprasad Shenai 	       CCTRL_ECN_V(enable_ecn) |
668d7990b0cSAnish Bhatt 	       RSS_QUEUE_VALID_F | RSS_QUEUE_V(ep->rss_qid);
669cfdda9d7SSteve Wise 	if (enable_tcp_timestamps)
6706c53e938SHariprasad Shenai 		opt2 |= TSTAMPS_EN_F;
671cfdda9d7SSteve Wise 	if (enable_tcp_sack)
6726c53e938SHariprasad Shenai 		opt2 |= SACK_EN_F;
673cfdda9d7SSteve Wise 	if (wscale && enable_tcp_window_scaling)
674d7990b0cSAnish Bhatt 		opt2 |= WND_SCALE_EN_F;
67592e5011aSSteve Wise 	if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) {
676d7990b0cSAnish Bhatt 		opt2 |= T5_OPT_2_VALID_F;
67792e5011aSSteve Wise 		opt2 |= V_CONG_CNTRL(CONG_ALG_TAHOE);
678da22b896SHariprasad S 		opt2 |= CONG_CNTRL_VALID; /* OPT_2_ISS for T5 */
67992e5011aSSteve Wise 	}
6805dab6d3aSHariprasad S 	t4_set_arp_err_handler(skb, ep, act_open_req_arp_failure);
681cfdda9d7SSteve Wise 
682f079af7aSVipul Pandya 	if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) {
683830662f6SVipul Pandya 		if (ep->com.remote_addr.ss_family == AF_INET) {
684cfdda9d7SSteve Wise 			req = (struct cpl_act_open_req *) skb_put(skb, wrlen);
685cfdda9d7SSteve Wise 			INIT_TP_WR(req, 0);
686cfdda9d7SSteve Wise 			OPCODE_TID(req) = cpu_to_be32(
687f079af7aSVipul Pandya 					MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
688f079af7aSVipul Pandya 					((ep->rss_qid << 14) | ep->atid)));
689830662f6SVipul Pandya 			req->local_port = la->sin_port;
690830662f6SVipul Pandya 			req->peer_port = ra->sin_port;
691830662f6SVipul Pandya 			req->local_ip = la->sin_addr.s_addr;
692830662f6SVipul Pandya 			req->peer_ip = ra->sin_addr.s_addr;
693cfdda9d7SSteve Wise 			req->opt0 = cpu_to_be64(opt0);
69441b4f86cSKumar Sanghvi 			req->params = cpu_to_be32(cxgb4_select_ntuple(
69541b4f86cSKumar Sanghvi 						ep->com.dev->rdev.lldi.ports[0],
69641b4f86cSKumar Sanghvi 						ep->l2t));
697cfdda9d7SSteve Wise 			req->opt2 = cpu_to_be32(opt2);
698f079af7aSVipul Pandya 		} else {
699830662f6SVipul Pandya 			req6 = (struct cpl_act_open_req6 *)skb_put(skb, wrlen);
700830662f6SVipul Pandya 
701830662f6SVipul Pandya 			INIT_TP_WR(req6, 0);
702830662f6SVipul Pandya 			OPCODE_TID(req6) = cpu_to_be32(
703830662f6SVipul Pandya 					   MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,
704830662f6SVipul Pandya 					   ((ep->rss_qid<<14)|ep->atid)));
705830662f6SVipul Pandya 			req6->local_port = la6->sin6_port;
706830662f6SVipul Pandya 			req6->peer_port = ra6->sin6_port;
707830662f6SVipul Pandya 			req6->local_ip_hi = *((__be64 *)
708830662f6SVipul Pandya 						(la6->sin6_addr.s6_addr));
709830662f6SVipul Pandya 			req6->local_ip_lo = *((__be64 *)
710830662f6SVipul Pandya 						(la6->sin6_addr.s6_addr + 8));
711830662f6SVipul Pandya 			req6->peer_ip_hi = *((__be64 *)
712830662f6SVipul Pandya 						(ra6->sin6_addr.s6_addr));
713830662f6SVipul Pandya 			req6->peer_ip_lo = *((__be64 *)
714830662f6SVipul Pandya 						(ra6->sin6_addr.s6_addr + 8));
715830662f6SVipul Pandya 			req6->opt0 = cpu_to_be64(opt0);
71641b4f86cSKumar Sanghvi 			req6->params = cpu_to_be32(cxgb4_select_ntuple(
71741b4f86cSKumar Sanghvi 						ep->com.dev->rdev.lldi.ports[0],
718830662f6SVipul Pandya 						ep->l2t));
719830662f6SVipul Pandya 			req6->opt2 = cpu_to_be32(opt2);
720830662f6SVipul Pandya 		}
721830662f6SVipul Pandya 	} else {
72292e7ae71SHariprasad Shenai 		u32 isn = (prandom_u32() & ~7UL) - 1;
72392e7ae71SHariprasad Shenai 
72492e7ae71SHariprasad Shenai 		if (peer2peer)
72592e7ae71SHariprasad Shenai 			isn += 4;
72692e7ae71SHariprasad Shenai 
727830662f6SVipul Pandya 		if (ep->com.remote_addr.ss_family == AF_INET) {
728830662f6SVipul Pandya 			t5_req = (struct cpl_t5_act_open_req *)
729830662f6SVipul Pandya 				 skb_put(skb, wrlen);
730f079af7aSVipul Pandya 			INIT_TP_WR(t5_req, 0);
731f079af7aSVipul Pandya 			OPCODE_TID(t5_req) = cpu_to_be32(
732f079af7aSVipul Pandya 					MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
733f079af7aSVipul Pandya 					((ep->rss_qid << 14) | ep->atid)));
734830662f6SVipul Pandya 			t5_req->local_port = la->sin_port;
735830662f6SVipul Pandya 			t5_req->peer_port = ra->sin_port;
736830662f6SVipul Pandya 			t5_req->local_ip = la->sin_addr.s_addr;
737830662f6SVipul Pandya 			t5_req->peer_ip = ra->sin_addr.s_addr;
738f079af7aSVipul Pandya 			t5_req->opt0 = cpu_to_be64(opt0);
739d7990b0cSAnish Bhatt 			t5_req->params = cpu_to_be64(FILTER_TUPLE_V(
74041b4f86cSKumar Sanghvi 						     cxgb4_select_ntuple(
74141b4f86cSKumar Sanghvi 					     ep->com.dev->rdev.lldi.ports[0],
74241b4f86cSKumar Sanghvi 					     ep->l2t)));
74392e7ae71SHariprasad Shenai 			t5_req->rsvd = cpu_to_be32(isn);
74492e7ae71SHariprasad Shenai 			PDBG("%s snd_isn %u\n", __func__,
74592e7ae71SHariprasad Shenai 			     be32_to_cpu(t5_req->rsvd));
746f079af7aSVipul Pandya 			t5_req->opt2 = cpu_to_be32(opt2);
747830662f6SVipul Pandya 		} else {
748830662f6SVipul Pandya 			t5_req6 = (struct cpl_t5_act_open_req6 *)
749830662f6SVipul Pandya 				  skb_put(skb, wrlen);
750830662f6SVipul Pandya 			INIT_TP_WR(t5_req6, 0);
751830662f6SVipul Pandya 			OPCODE_TID(t5_req6) = cpu_to_be32(
752830662f6SVipul Pandya 					      MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,
753830662f6SVipul Pandya 					      ((ep->rss_qid<<14)|ep->atid)));
754830662f6SVipul Pandya 			t5_req6->local_port = la6->sin6_port;
755830662f6SVipul Pandya 			t5_req6->peer_port = ra6->sin6_port;
756830662f6SVipul Pandya 			t5_req6->local_ip_hi = *((__be64 *)
757830662f6SVipul Pandya 						(la6->sin6_addr.s6_addr));
758830662f6SVipul Pandya 			t5_req6->local_ip_lo = *((__be64 *)
759830662f6SVipul Pandya 						(la6->sin6_addr.s6_addr + 8));
760830662f6SVipul Pandya 			t5_req6->peer_ip_hi = *((__be64 *)
761830662f6SVipul Pandya 						(ra6->sin6_addr.s6_addr));
762830662f6SVipul Pandya 			t5_req6->peer_ip_lo = *((__be64 *)
763830662f6SVipul Pandya 						(ra6->sin6_addr.s6_addr + 8));
764830662f6SVipul Pandya 			t5_req6->opt0 = cpu_to_be64(opt0);
765d7990b0cSAnish Bhatt 			t5_req6->params = cpu_to_be64(FILTER_TUPLE_V(
76641b4f86cSKumar Sanghvi 							cxgb4_select_ntuple(
76741b4f86cSKumar Sanghvi 						ep->com.dev->rdev.lldi.ports[0],
768da22b896SHariprasad S 						ep->l2t)));
76992e7ae71SHariprasad Shenai 			t5_req6->rsvd = cpu_to_be32(isn);
77092e7ae71SHariprasad Shenai 			PDBG("%s snd_isn %u\n", __func__,
77192e7ae71SHariprasad Shenai 			     be32_to_cpu(t5_req6->rsvd));
772830662f6SVipul Pandya 			t5_req6->opt2 = cpu_to_be32(opt2);
773830662f6SVipul Pandya 		}
774f079af7aSVipul Pandya 	}
775f079af7aSVipul Pandya 
776793dad94SVipul Pandya 	set_bit(ACT_OPEN_REQ, &ep->com.history);
777cfdda9d7SSteve Wise 	return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
778cfdda9d7SSteve Wise }
779cfdda9d7SSteve Wise 
780d2fe99e8SKumar Sanghvi static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb,
781d2fe99e8SKumar Sanghvi 		u8 mpa_rev_to_use)
782cfdda9d7SSteve Wise {
783cfdda9d7SSteve Wise 	int mpalen, wrlen;
784cfdda9d7SSteve Wise 	struct fw_ofld_tx_data_wr *req;
785cfdda9d7SSteve Wise 	struct mpa_message *mpa;
786d2fe99e8SKumar Sanghvi 	struct mpa_v2_conn_params mpa_v2_params;
787cfdda9d7SSteve Wise 
788cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen);
789cfdda9d7SSteve Wise 
790cfdda9d7SSteve Wise 	BUG_ON(skb_cloned(skb));
791cfdda9d7SSteve Wise 
792cfdda9d7SSteve Wise 	mpalen = sizeof(*mpa) + ep->plen;
793d2fe99e8SKumar Sanghvi 	if (mpa_rev_to_use == 2)
794d2fe99e8SKumar Sanghvi 		mpalen += sizeof(struct mpa_v2_conn_params);
795cfdda9d7SSteve Wise 	wrlen = roundup(mpalen + sizeof *req, 16);
796cfdda9d7SSteve Wise 	skb = get_skb(skb, wrlen, GFP_KERNEL);
797cfdda9d7SSteve Wise 	if (!skb) {
798cfdda9d7SSteve Wise 		connect_reply_upcall(ep, -ENOMEM);
799cfdda9d7SSteve Wise 		return;
800cfdda9d7SSteve Wise 	}
801cfdda9d7SSteve Wise 	set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
802cfdda9d7SSteve Wise 
803cfdda9d7SSteve Wise 	req = (struct fw_ofld_tx_data_wr *)skb_put(skb, wrlen);
804cfdda9d7SSteve Wise 	memset(req, 0, wrlen);
805cfdda9d7SSteve Wise 	req->op_to_immdlen = cpu_to_be32(
806e2ac9628SHariprasad Shenai 		FW_WR_OP_V(FW_OFLD_TX_DATA_WR) |
807e2ac9628SHariprasad Shenai 		FW_WR_COMPL_F |
808e2ac9628SHariprasad Shenai 		FW_WR_IMMDLEN_V(mpalen));
809cfdda9d7SSteve Wise 	req->flowid_len16 = cpu_to_be32(
810e2ac9628SHariprasad Shenai 		FW_WR_FLOWID_V(ep->hwtid) |
811e2ac9628SHariprasad Shenai 		FW_WR_LEN16_V(wrlen >> 4));
812cfdda9d7SSteve Wise 	req->plen = cpu_to_be32(mpalen);
813cfdda9d7SSteve Wise 	req->tunnel_to_proxy = cpu_to_be32(
814e2ac9628SHariprasad Shenai 		FW_OFLD_TX_DATA_WR_FLUSH_F |
815e2ac9628SHariprasad Shenai 		FW_OFLD_TX_DATA_WR_SHOVE_F);
816cfdda9d7SSteve Wise 
817cfdda9d7SSteve Wise 	mpa = (struct mpa_message *)(req + 1);
818cfdda9d7SSteve Wise 	memcpy(mpa->key, MPA_KEY_REQ, sizeof(mpa->key));
819cfdda9d7SSteve Wise 	mpa->flags = (crc_enabled ? MPA_CRC : 0) |
820d2fe99e8SKumar Sanghvi 		     (markers_enabled ? MPA_MARKERS : 0) |
821d2fe99e8SKumar Sanghvi 		     (mpa_rev_to_use == 2 ? MPA_ENHANCED_RDMA_CONN : 0);
822cfdda9d7SSteve Wise 	mpa->private_data_size = htons(ep->plen);
823d2fe99e8SKumar Sanghvi 	mpa->revision = mpa_rev_to_use;
82401b225e1SKumar Sanghvi 	if (mpa_rev_to_use == 1) {
825d2fe99e8SKumar Sanghvi 		ep->tried_with_mpa_v1 = 1;
82601b225e1SKumar Sanghvi 		ep->retry_with_mpa_v1 = 0;
82701b225e1SKumar Sanghvi 	}
828d2fe99e8SKumar Sanghvi 
829d2fe99e8SKumar Sanghvi 	if (mpa_rev_to_use == 2) {
830f747c34aSRoland Dreier 		mpa->private_data_size = htons(ntohs(mpa->private_data_size) +
831f747c34aSRoland Dreier 					       sizeof (struct mpa_v2_conn_params));
8324c2c5763SHariprasad Shenai 		PDBG("%s initiator ird %u ord %u\n", __func__, ep->ird,
8334c2c5763SHariprasad Shenai 		     ep->ord);
834d2fe99e8SKumar Sanghvi 		mpa_v2_params.ird = htons((u16)ep->ird);
835d2fe99e8SKumar Sanghvi 		mpa_v2_params.ord = htons((u16)ep->ord);
836d2fe99e8SKumar Sanghvi 
837d2fe99e8SKumar Sanghvi 		if (peer2peer) {
838d2fe99e8SKumar Sanghvi 			mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL);
839d2fe99e8SKumar Sanghvi 			if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE)
840d2fe99e8SKumar Sanghvi 				mpa_v2_params.ord |=
841d2fe99e8SKumar Sanghvi 					htons(MPA_V2_RDMA_WRITE_RTR);
842d2fe99e8SKumar Sanghvi 			else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ)
843d2fe99e8SKumar Sanghvi 				mpa_v2_params.ord |=
844d2fe99e8SKumar Sanghvi 					htons(MPA_V2_RDMA_READ_RTR);
845d2fe99e8SKumar Sanghvi 		}
846d2fe99e8SKumar Sanghvi 		memcpy(mpa->private_data, &mpa_v2_params,
847d2fe99e8SKumar Sanghvi 		       sizeof(struct mpa_v2_conn_params));
848cfdda9d7SSteve Wise 
849cfdda9d7SSteve Wise 		if (ep->plen)
850d2fe99e8SKumar Sanghvi 			memcpy(mpa->private_data +
851d2fe99e8SKumar Sanghvi 			       sizeof(struct mpa_v2_conn_params),
852d2fe99e8SKumar Sanghvi 			       ep->mpa_pkt + sizeof(*mpa), ep->plen);
853d2fe99e8SKumar Sanghvi 	} else
854d2fe99e8SKumar Sanghvi 		if (ep->plen)
855d2fe99e8SKumar Sanghvi 			memcpy(mpa->private_data,
856d2fe99e8SKumar Sanghvi 					ep->mpa_pkt + sizeof(*mpa), ep->plen);
857cfdda9d7SSteve Wise 
858cfdda9d7SSteve Wise 	/*
859cfdda9d7SSteve Wise 	 * Reference the mpa skb.  This ensures the data area
860cfdda9d7SSteve Wise 	 * will remain in memory until the hw acks the tx.
861cfdda9d7SSteve Wise 	 * Function fw4_ack() will deref it.
862cfdda9d7SSteve Wise 	 */
863cfdda9d7SSteve Wise 	skb_get(skb);
864cfdda9d7SSteve Wise 	t4_set_arp_err_handler(skb, NULL, arp_failure_discard);
865cfdda9d7SSteve Wise 	BUG_ON(ep->mpa_skb);
866cfdda9d7SSteve Wise 	ep->mpa_skb = skb;
867cfdda9d7SSteve Wise 	c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
868cfdda9d7SSteve Wise 	start_ep_timer(ep);
869a7db89ebSSteve Wise 	__state_set(&ep->com, MPA_REQ_SENT);
870cfdda9d7SSteve Wise 	ep->mpa_attr.initiator = 1;
8719c88aa00SSteve Wise 	ep->snd_seq += mpalen;
872cfdda9d7SSteve Wise 	return;
873cfdda9d7SSteve Wise }
874cfdda9d7SSteve Wise 
875cfdda9d7SSteve Wise static int send_mpa_reject(struct c4iw_ep *ep, const void *pdata, u8 plen)
876cfdda9d7SSteve Wise {
877cfdda9d7SSteve Wise 	int mpalen, wrlen;
878cfdda9d7SSteve Wise 	struct fw_ofld_tx_data_wr *req;
879cfdda9d7SSteve Wise 	struct mpa_message *mpa;
880cfdda9d7SSteve Wise 	struct sk_buff *skb;
881d2fe99e8SKumar Sanghvi 	struct mpa_v2_conn_params mpa_v2_params;
882cfdda9d7SSteve Wise 
883cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen);
884cfdda9d7SSteve Wise 
885cfdda9d7SSteve Wise 	mpalen = sizeof(*mpa) + plen;
886d2fe99e8SKumar Sanghvi 	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn)
887d2fe99e8SKumar Sanghvi 		mpalen += sizeof(struct mpa_v2_conn_params);
888cfdda9d7SSteve Wise 	wrlen = roundup(mpalen + sizeof *req, 16);
889cfdda9d7SSteve Wise 
890cfdda9d7SSteve Wise 	skb = get_skb(NULL, wrlen, GFP_KERNEL);
891cfdda9d7SSteve Wise 	if (!skb) {
892cfdda9d7SSteve Wise 		printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __func__);
893cfdda9d7SSteve Wise 		return -ENOMEM;
894cfdda9d7SSteve Wise 	}
895cfdda9d7SSteve Wise 	set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
896cfdda9d7SSteve Wise 
897cfdda9d7SSteve Wise 	req = (struct fw_ofld_tx_data_wr *)skb_put(skb, wrlen);
898cfdda9d7SSteve Wise 	memset(req, 0, wrlen);
899cfdda9d7SSteve Wise 	req->op_to_immdlen = cpu_to_be32(
900e2ac9628SHariprasad Shenai 		FW_WR_OP_V(FW_OFLD_TX_DATA_WR) |
901e2ac9628SHariprasad Shenai 		FW_WR_COMPL_F |
902e2ac9628SHariprasad Shenai 		FW_WR_IMMDLEN_V(mpalen));
903cfdda9d7SSteve Wise 	req->flowid_len16 = cpu_to_be32(
904e2ac9628SHariprasad Shenai 		FW_WR_FLOWID_V(ep->hwtid) |
905e2ac9628SHariprasad Shenai 		FW_WR_LEN16_V(wrlen >> 4));
906cfdda9d7SSteve Wise 	req->plen = cpu_to_be32(mpalen);
907cfdda9d7SSteve Wise 	req->tunnel_to_proxy = cpu_to_be32(
908e2ac9628SHariprasad Shenai 		FW_OFLD_TX_DATA_WR_FLUSH_F |
909e2ac9628SHariprasad Shenai 		FW_OFLD_TX_DATA_WR_SHOVE_F);
910cfdda9d7SSteve Wise 
911cfdda9d7SSteve Wise 	mpa = (struct mpa_message *)(req + 1);
912cfdda9d7SSteve Wise 	memset(mpa, 0, sizeof(*mpa));
913cfdda9d7SSteve Wise 	memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key));
914cfdda9d7SSteve Wise 	mpa->flags = MPA_REJECT;
915fe7e0a4dSVipul Pandya 	mpa->revision = ep->mpa_attr.version;
916cfdda9d7SSteve Wise 	mpa->private_data_size = htons(plen);
917d2fe99e8SKumar Sanghvi 
918d2fe99e8SKumar Sanghvi 	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
919d2fe99e8SKumar Sanghvi 		mpa->flags |= MPA_ENHANCED_RDMA_CONN;
920f747c34aSRoland Dreier 		mpa->private_data_size = htons(ntohs(mpa->private_data_size) +
921f747c34aSRoland Dreier 					       sizeof (struct mpa_v2_conn_params));
922d2fe99e8SKumar Sanghvi 		mpa_v2_params.ird = htons(((u16)ep->ird) |
923d2fe99e8SKumar Sanghvi 					  (peer2peer ? MPA_V2_PEER2PEER_MODEL :
924d2fe99e8SKumar Sanghvi 					   0));
925d2fe99e8SKumar Sanghvi 		mpa_v2_params.ord = htons(((u16)ep->ord) | (peer2peer ?
926d2fe99e8SKumar Sanghvi 					  (p2p_type ==
927d2fe99e8SKumar Sanghvi 					   FW_RI_INIT_P2PTYPE_RDMA_WRITE ?
928d2fe99e8SKumar Sanghvi 					   MPA_V2_RDMA_WRITE_RTR : p2p_type ==
929d2fe99e8SKumar Sanghvi 					   FW_RI_INIT_P2PTYPE_READ_REQ ?
930d2fe99e8SKumar Sanghvi 					   MPA_V2_RDMA_READ_RTR : 0) : 0));
931d2fe99e8SKumar Sanghvi 		memcpy(mpa->private_data, &mpa_v2_params,
932d2fe99e8SKumar Sanghvi 		       sizeof(struct mpa_v2_conn_params));
933d2fe99e8SKumar Sanghvi 
934d2fe99e8SKumar Sanghvi 		if (ep->plen)
935d2fe99e8SKumar Sanghvi 			memcpy(mpa->private_data +
936d2fe99e8SKumar Sanghvi 			       sizeof(struct mpa_v2_conn_params), pdata, plen);
937d2fe99e8SKumar Sanghvi 	} else
938cfdda9d7SSteve Wise 		if (plen)
939cfdda9d7SSteve Wise 			memcpy(mpa->private_data, pdata, plen);
940cfdda9d7SSteve Wise 
941cfdda9d7SSteve Wise 	/*
942cfdda9d7SSteve Wise 	 * Reference the mpa skb again.  This ensures the data area
943cfdda9d7SSteve Wise 	 * will remain in memory until the hw acks the tx.
944cfdda9d7SSteve Wise 	 * Function fw4_ack() will deref it.
945cfdda9d7SSteve Wise 	 */
946cfdda9d7SSteve Wise 	skb_get(skb);
947cfdda9d7SSteve Wise 	set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
948cfdda9d7SSteve Wise 	t4_set_arp_err_handler(skb, NULL, arp_failure_discard);
949cfdda9d7SSteve Wise 	BUG_ON(ep->mpa_skb);
950cfdda9d7SSteve Wise 	ep->mpa_skb = skb;
9519c88aa00SSteve Wise 	ep->snd_seq += mpalen;
952cfdda9d7SSteve Wise 	return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
953cfdda9d7SSteve Wise }
954cfdda9d7SSteve Wise 
955cfdda9d7SSteve Wise static int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen)
956cfdda9d7SSteve Wise {
957cfdda9d7SSteve Wise 	int mpalen, wrlen;
958cfdda9d7SSteve Wise 	struct fw_ofld_tx_data_wr *req;
959cfdda9d7SSteve Wise 	struct mpa_message *mpa;
960cfdda9d7SSteve Wise 	struct sk_buff *skb;
961d2fe99e8SKumar Sanghvi 	struct mpa_v2_conn_params mpa_v2_params;
962cfdda9d7SSteve Wise 
963cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen);
964cfdda9d7SSteve Wise 
965cfdda9d7SSteve Wise 	mpalen = sizeof(*mpa) + plen;
966d2fe99e8SKumar Sanghvi 	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn)
967d2fe99e8SKumar Sanghvi 		mpalen += sizeof(struct mpa_v2_conn_params);
968cfdda9d7SSteve Wise 	wrlen = roundup(mpalen + sizeof *req, 16);
969cfdda9d7SSteve Wise 
970cfdda9d7SSteve Wise 	skb = get_skb(NULL, wrlen, GFP_KERNEL);
971cfdda9d7SSteve Wise 	if (!skb) {
972cfdda9d7SSteve Wise 		printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __func__);
973cfdda9d7SSteve Wise 		return -ENOMEM;
974cfdda9d7SSteve Wise 	}
975cfdda9d7SSteve Wise 	set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
976cfdda9d7SSteve Wise 
977cfdda9d7SSteve Wise 	req = (struct fw_ofld_tx_data_wr *) skb_put(skb, wrlen);
978cfdda9d7SSteve Wise 	memset(req, 0, wrlen);
979cfdda9d7SSteve Wise 	req->op_to_immdlen = cpu_to_be32(
980e2ac9628SHariprasad Shenai 		FW_WR_OP_V(FW_OFLD_TX_DATA_WR) |
981e2ac9628SHariprasad Shenai 		FW_WR_COMPL_F |
982e2ac9628SHariprasad Shenai 		FW_WR_IMMDLEN_V(mpalen));
983cfdda9d7SSteve Wise 	req->flowid_len16 = cpu_to_be32(
984e2ac9628SHariprasad Shenai 		FW_WR_FLOWID_V(ep->hwtid) |
985e2ac9628SHariprasad Shenai 		FW_WR_LEN16_V(wrlen >> 4));
986cfdda9d7SSteve Wise 	req->plen = cpu_to_be32(mpalen);
987cfdda9d7SSteve Wise 	req->tunnel_to_proxy = cpu_to_be32(
988e2ac9628SHariprasad Shenai 		FW_OFLD_TX_DATA_WR_FLUSH_F |
989e2ac9628SHariprasad Shenai 		FW_OFLD_TX_DATA_WR_SHOVE_F);
990cfdda9d7SSteve Wise 
991cfdda9d7SSteve Wise 	mpa = (struct mpa_message *)(req + 1);
992cfdda9d7SSteve Wise 	memset(mpa, 0, sizeof(*mpa));
993cfdda9d7SSteve Wise 	memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key));
994cfdda9d7SSteve Wise 	mpa->flags = (ep->mpa_attr.crc_enabled ? MPA_CRC : 0) |
995cfdda9d7SSteve Wise 		     (markers_enabled ? MPA_MARKERS : 0);
996d2fe99e8SKumar Sanghvi 	mpa->revision = ep->mpa_attr.version;
997cfdda9d7SSteve Wise 	mpa->private_data_size = htons(plen);
998d2fe99e8SKumar Sanghvi 
999d2fe99e8SKumar Sanghvi 	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
1000d2fe99e8SKumar Sanghvi 		mpa->flags |= MPA_ENHANCED_RDMA_CONN;
1001f747c34aSRoland Dreier 		mpa->private_data_size = htons(ntohs(mpa->private_data_size) +
1002f747c34aSRoland Dreier 					       sizeof (struct mpa_v2_conn_params));
1003d2fe99e8SKumar Sanghvi 		mpa_v2_params.ird = htons((u16)ep->ird);
1004d2fe99e8SKumar Sanghvi 		mpa_v2_params.ord = htons((u16)ep->ord);
1005d2fe99e8SKumar Sanghvi 		if (peer2peer && (ep->mpa_attr.p2p_type !=
1006d2fe99e8SKumar Sanghvi 					FW_RI_INIT_P2PTYPE_DISABLED)) {
1007d2fe99e8SKumar Sanghvi 			mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL);
1008d2fe99e8SKumar Sanghvi 
1009d2fe99e8SKumar Sanghvi 			if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE)
1010d2fe99e8SKumar Sanghvi 				mpa_v2_params.ord |=
1011d2fe99e8SKumar Sanghvi 					htons(MPA_V2_RDMA_WRITE_RTR);
1012d2fe99e8SKumar Sanghvi 			else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ)
1013d2fe99e8SKumar Sanghvi 				mpa_v2_params.ord |=
1014d2fe99e8SKumar Sanghvi 					htons(MPA_V2_RDMA_READ_RTR);
1015d2fe99e8SKumar Sanghvi 		}
1016d2fe99e8SKumar Sanghvi 
1017d2fe99e8SKumar Sanghvi 		memcpy(mpa->private_data, &mpa_v2_params,
1018d2fe99e8SKumar Sanghvi 		       sizeof(struct mpa_v2_conn_params));
1019d2fe99e8SKumar Sanghvi 
1020d2fe99e8SKumar Sanghvi 		if (ep->plen)
1021d2fe99e8SKumar Sanghvi 			memcpy(mpa->private_data +
1022d2fe99e8SKumar Sanghvi 			       sizeof(struct mpa_v2_conn_params), pdata, plen);
1023d2fe99e8SKumar Sanghvi 	} else
1024cfdda9d7SSteve Wise 		if (plen)
1025cfdda9d7SSteve Wise 			memcpy(mpa->private_data, pdata, plen);
1026cfdda9d7SSteve Wise 
1027cfdda9d7SSteve Wise 	/*
1028cfdda9d7SSteve Wise 	 * Reference the mpa skb.  This ensures the data area
1029cfdda9d7SSteve Wise 	 * will remain in memory until the hw acks the tx.
1030cfdda9d7SSteve Wise 	 * Function fw4_ack() will deref it.
1031cfdda9d7SSteve Wise 	 */
1032cfdda9d7SSteve Wise 	skb_get(skb);
1033cfdda9d7SSteve Wise 	t4_set_arp_err_handler(skb, NULL, arp_failure_discard);
1034cfdda9d7SSteve Wise 	ep->mpa_skb = skb;
1035a7db89ebSSteve Wise 	__state_set(&ep->com, MPA_REP_SENT);
10369c88aa00SSteve Wise 	ep->snd_seq += mpalen;
1037cfdda9d7SSteve Wise 	return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
1038cfdda9d7SSteve Wise }
1039cfdda9d7SSteve Wise 
1040cfdda9d7SSteve Wise static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb)
1041cfdda9d7SSteve Wise {
1042cfdda9d7SSteve Wise 	struct c4iw_ep *ep;
1043cfdda9d7SSteve Wise 	struct cpl_act_establish *req = cplhdr(skb);
1044cfdda9d7SSteve Wise 	unsigned int tid = GET_TID(req);
10456c53e938SHariprasad Shenai 	unsigned int atid = TID_TID_G(ntohl(req->tos_atid));
1046cfdda9d7SSteve Wise 	struct tid_info *t = dev->rdev.lldi.tids;
1047cfdda9d7SSteve Wise 
1048cfdda9d7SSteve Wise 	ep = lookup_atid(t, atid);
1049cfdda9d7SSteve Wise 
1050cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u snd_isn %u rcv_isn %u\n", __func__, ep, tid,
1051cfdda9d7SSteve Wise 	     be32_to_cpu(req->snd_isn), be32_to_cpu(req->rcv_isn));
1052cfdda9d7SSteve Wise 
1053a7db89ebSSteve Wise 	mutex_lock(&ep->com.mutex);
1054cfdda9d7SSteve Wise 	dst_confirm(ep->dst);
1055cfdda9d7SSteve Wise 
1056cfdda9d7SSteve Wise 	/* setup the hwtid for this connection */
1057cfdda9d7SSteve Wise 	ep->hwtid = tid;
1058cfdda9d7SSteve Wise 	cxgb4_insert_tid(t, ep, tid);
1059793dad94SVipul Pandya 	insert_handle(dev, &dev->hwtid_idr, ep, ep->hwtid);
1060cfdda9d7SSteve Wise 
1061cfdda9d7SSteve Wise 	ep->snd_seq = be32_to_cpu(req->snd_isn);
1062cfdda9d7SSteve Wise 	ep->rcv_seq = be32_to_cpu(req->rcv_isn);
1063cfdda9d7SSteve Wise 
1064cfdda9d7SSteve Wise 	set_emss(ep, ntohs(req->tcp_opt));
1065cfdda9d7SSteve Wise 
1066cfdda9d7SSteve Wise 	/* dealloc the atid */
1067793dad94SVipul Pandya 	remove_handle(ep->com.dev, &ep->com.dev->atid_idr, atid);
1068cfdda9d7SSteve Wise 	cxgb4_free_atid(t, atid);
1069793dad94SVipul Pandya 	set_bit(ACT_ESTAB, &ep->com.history);
1070cfdda9d7SSteve Wise 
1071cfdda9d7SSteve Wise 	/* start MPA negotiation */
1072cfdda9d7SSteve Wise 	send_flowc(ep, NULL);
1073d2fe99e8SKumar Sanghvi 	if (ep->retry_with_mpa_v1)
1074d2fe99e8SKumar Sanghvi 		send_mpa_req(ep, skb, 1);
1075d2fe99e8SKumar Sanghvi 	else
1076d2fe99e8SKumar Sanghvi 		send_mpa_req(ep, skb, mpa_rev);
1077a7db89ebSSteve Wise 	mutex_unlock(&ep->com.mutex);
1078cfdda9d7SSteve Wise 	return 0;
1079cfdda9d7SSteve Wise }
1080cfdda9d7SSteve Wise 
1081be13b2dfSSteve Wise static void close_complete_upcall(struct c4iw_ep *ep, int status)
1082cfdda9d7SSteve Wise {
1083cfdda9d7SSteve Wise 	struct iw_cm_event event;
1084cfdda9d7SSteve Wise 
1085cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
1086cfdda9d7SSteve Wise 	memset(&event, 0, sizeof(event));
1087cfdda9d7SSteve Wise 	event.event = IW_CM_EVENT_CLOSE;
1088be13b2dfSSteve Wise 	event.status = status;
1089cfdda9d7SSteve Wise 	if (ep->com.cm_id) {
1090cfdda9d7SSteve Wise 		PDBG("close complete delivered ep %p cm_id %p tid %u\n",
1091cfdda9d7SSteve Wise 		     ep, ep->com.cm_id, ep->hwtid);
1092cfdda9d7SSteve Wise 		ep->com.cm_id->event_handler(ep->com.cm_id, &event);
1093cfdda9d7SSteve Wise 		ep->com.cm_id->rem_ref(ep->com.cm_id);
1094cfdda9d7SSteve Wise 		ep->com.cm_id = NULL;
1095793dad94SVipul Pandya 		set_bit(CLOSE_UPCALL, &ep->com.history);
1096cfdda9d7SSteve Wise 	}
1097cfdda9d7SSteve Wise }
1098cfdda9d7SSteve Wise 
1099cfdda9d7SSteve Wise static int abort_connection(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
1100cfdda9d7SSteve Wise {
1101cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
1102cc18b939SSteve Wise 	__state_set(&ep->com, ABORTING);
1103793dad94SVipul Pandya 	set_bit(ABORT_CONN, &ep->com.history);
1104cfdda9d7SSteve Wise 	return send_abort(ep, skb, gfp);
1105cfdda9d7SSteve Wise }
1106cfdda9d7SSteve Wise 
1107cfdda9d7SSteve Wise static void peer_close_upcall(struct c4iw_ep *ep)
1108cfdda9d7SSteve Wise {
1109cfdda9d7SSteve Wise 	struct iw_cm_event event;
1110cfdda9d7SSteve Wise 
1111cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
1112cfdda9d7SSteve Wise 	memset(&event, 0, sizeof(event));
1113cfdda9d7SSteve Wise 	event.event = IW_CM_EVENT_DISCONNECT;
1114cfdda9d7SSteve Wise 	if (ep->com.cm_id) {
1115cfdda9d7SSteve Wise 		PDBG("peer close delivered ep %p cm_id %p tid %u\n",
1116cfdda9d7SSteve Wise 		     ep, ep->com.cm_id, ep->hwtid);
1117cfdda9d7SSteve Wise 		ep->com.cm_id->event_handler(ep->com.cm_id, &event);
1118793dad94SVipul Pandya 		set_bit(DISCONN_UPCALL, &ep->com.history);
1119cfdda9d7SSteve Wise 	}
1120cfdda9d7SSteve Wise }
1121cfdda9d7SSteve Wise 
1122cfdda9d7SSteve Wise static void peer_abort_upcall(struct c4iw_ep *ep)
1123cfdda9d7SSteve Wise {
1124cfdda9d7SSteve Wise 	struct iw_cm_event event;
1125cfdda9d7SSteve Wise 
1126cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
1127cfdda9d7SSteve Wise 	memset(&event, 0, sizeof(event));
1128cfdda9d7SSteve Wise 	event.event = IW_CM_EVENT_CLOSE;
1129cfdda9d7SSteve Wise 	event.status = -ECONNRESET;
1130cfdda9d7SSteve Wise 	if (ep->com.cm_id) {
1131cfdda9d7SSteve Wise 		PDBG("abort delivered ep %p cm_id %p tid %u\n", ep,
1132cfdda9d7SSteve Wise 		     ep->com.cm_id, ep->hwtid);
1133cfdda9d7SSteve Wise 		ep->com.cm_id->event_handler(ep->com.cm_id, &event);
1134cfdda9d7SSteve Wise 		ep->com.cm_id->rem_ref(ep->com.cm_id);
1135cfdda9d7SSteve Wise 		ep->com.cm_id = NULL;
1136793dad94SVipul Pandya 		set_bit(ABORT_UPCALL, &ep->com.history);
1137cfdda9d7SSteve Wise 	}
1138cfdda9d7SSteve Wise }
1139cfdda9d7SSteve Wise 
1140cfdda9d7SSteve Wise static void connect_reply_upcall(struct c4iw_ep *ep, int status)
1141cfdda9d7SSteve Wise {
1142cfdda9d7SSteve Wise 	struct iw_cm_event event;
1143cfdda9d7SSteve Wise 
1144cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u status %d\n", __func__, ep, ep->hwtid, status);
1145cfdda9d7SSteve Wise 	memset(&event, 0, sizeof(event));
1146cfdda9d7SSteve Wise 	event.event = IW_CM_EVENT_CONNECT_REPLY;
1147cfdda9d7SSteve Wise 	event.status = status;
114824d44a39SSteve Wise 	memcpy(&event.local_addr, &ep->com.local_addr,
114924d44a39SSteve Wise 	       sizeof(ep->com.local_addr));
115024d44a39SSteve Wise 	memcpy(&event.remote_addr, &ep->com.remote_addr,
115124d44a39SSteve Wise 	       sizeof(ep->com.remote_addr));
1152cfdda9d7SSteve Wise 
1153cfdda9d7SSteve Wise 	if ((status == 0) || (status == -ECONNREFUSED)) {
1154d2fe99e8SKumar Sanghvi 		if (!ep->tried_with_mpa_v1) {
1155d2fe99e8SKumar Sanghvi 			/* this means MPA_v2 is used */
1156d2fe99e8SKumar Sanghvi 			event.private_data_len = ep->plen -
1157d2fe99e8SKumar Sanghvi 				sizeof(struct mpa_v2_conn_params);
1158d2fe99e8SKumar Sanghvi 			event.private_data = ep->mpa_pkt +
1159d2fe99e8SKumar Sanghvi 				sizeof(struct mpa_message) +
1160d2fe99e8SKumar Sanghvi 				sizeof(struct mpa_v2_conn_params);
1161d2fe99e8SKumar Sanghvi 		} else {
1162d2fe99e8SKumar Sanghvi 			/* this means MPA_v1 is used */
1163cfdda9d7SSteve Wise 			event.private_data_len = ep->plen;
1164d2fe99e8SKumar Sanghvi 			event.private_data = ep->mpa_pkt +
1165d2fe99e8SKumar Sanghvi 				sizeof(struct mpa_message);
1166d2fe99e8SKumar Sanghvi 		}
1167cfdda9d7SSteve Wise 	}
116885963e4cSRoland Dreier 
1169cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u status %d\n", __func__, ep,
1170cfdda9d7SSteve Wise 	     ep->hwtid, status);
1171793dad94SVipul Pandya 	set_bit(CONN_RPL_UPCALL, &ep->com.history);
1172cfdda9d7SSteve Wise 	ep->com.cm_id->event_handler(ep->com.cm_id, &event);
117385963e4cSRoland Dreier 
1174cfdda9d7SSteve Wise 	if (status < 0) {
1175cfdda9d7SSteve Wise 		ep->com.cm_id->rem_ref(ep->com.cm_id);
1176cfdda9d7SSteve Wise 		ep->com.cm_id = NULL;
1177cfdda9d7SSteve Wise 	}
1178cfdda9d7SSteve Wise }
1179cfdda9d7SSteve Wise 
1180be13b2dfSSteve Wise static int connect_request_upcall(struct c4iw_ep *ep)
1181cfdda9d7SSteve Wise {
1182cfdda9d7SSteve Wise 	struct iw_cm_event event;
1183be13b2dfSSteve Wise 	int ret;
1184cfdda9d7SSteve Wise 
1185cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
1186cfdda9d7SSteve Wise 	memset(&event, 0, sizeof(event));
1187cfdda9d7SSteve Wise 	event.event = IW_CM_EVENT_CONNECT_REQUEST;
118824d44a39SSteve Wise 	memcpy(&event.local_addr, &ep->com.local_addr,
118924d44a39SSteve Wise 	       sizeof(ep->com.local_addr));
119024d44a39SSteve Wise 	memcpy(&event.remote_addr, &ep->com.remote_addr,
119124d44a39SSteve Wise 	       sizeof(ep->com.remote_addr));
1192d2fe99e8SKumar Sanghvi 	event.provider_data = ep;
1193d2fe99e8SKumar Sanghvi 	if (!ep->tried_with_mpa_v1) {
1194d2fe99e8SKumar Sanghvi 		/* this means MPA_v2 is used */
1195d2fe99e8SKumar Sanghvi 		event.ord = ep->ord;
1196d2fe99e8SKumar Sanghvi 		event.ird = ep->ird;
1197d2fe99e8SKumar Sanghvi 		event.private_data_len = ep->plen -
1198d2fe99e8SKumar Sanghvi 			sizeof(struct mpa_v2_conn_params);
1199d2fe99e8SKumar Sanghvi 		event.private_data = ep->mpa_pkt + sizeof(struct mpa_message) +
1200d2fe99e8SKumar Sanghvi 			sizeof(struct mpa_v2_conn_params);
1201d2fe99e8SKumar Sanghvi 	} else {
1202d2fe99e8SKumar Sanghvi 		/* this means MPA_v1 is used. Send max supported */
12034c2c5763SHariprasad Shenai 		event.ord = cur_max_read_depth(ep->com.dev);
12044c2c5763SHariprasad Shenai 		event.ird = cur_max_read_depth(ep->com.dev);
1205cfdda9d7SSteve Wise 		event.private_data_len = ep->plen;
1206cfdda9d7SSteve Wise 		event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
1207d2fe99e8SKumar Sanghvi 	}
1208cfdda9d7SSteve Wise 	c4iw_get_ep(&ep->com);
1209be13b2dfSSteve Wise 	ret = ep->parent_ep->com.cm_id->event_handler(ep->parent_ep->com.cm_id,
1210cfdda9d7SSteve Wise 						      &event);
1211be13b2dfSSteve Wise 	if (ret)
1212be13b2dfSSteve Wise 		c4iw_put_ep(&ep->com);
1213793dad94SVipul Pandya 	set_bit(CONNREQ_UPCALL, &ep->com.history);
1214cfdda9d7SSteve Wise 	c4iw_put_ep(&ep->parent_ep->com);
1215be13b2dfSSteve Wise 	return ret;
1216cfdda9d7SSteve Wise }
1217cfdda9d7SSteve Wise 
1218cfdda9d7SSteve Wise static void established_upcall(struct c4iw_ep *ep)
1219cfdda9d7SSteve Wise {
1220cfdda9d7SSteve Wise 	struct iw_cm_event event;
1221cfdda9d7SSteve Wise 
1222cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
1223cfdda9d7SSteve Wise 	memset(&event, 0, sizeof(event));
1224cfdda9d7SSteve Wise 	event.event = IW_CM_EVENT_ESTABLISHED;
1225d2fe99e8SKumar Sanghvi 	event.ird = ep->ird;
1226d2fe99e8SKumar Sanghvi 	event.ord = ep->ord;
1227cfdda9d7SSteve Wise 	if (ep->com.cm_id) {
1228cfdda9d7SSteve Wise 		PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
1229cfdda9d7SSteve Wise 		ep->com.cm_id->event_handler(ep->com.cm_id, &event);
1230793dad94SVipul Pandya 		set_bit(ESTAB_UPCALL, &ep->com.history);
1231cfdda9d7SSteve Wise 	}
1232cfdda9d7SSteve Wise }
1233cfdda9d7SSteve Wise 
1234cfdda9d7SSteve Wise static int update_rx_credits(struct c4iw_ep *ep, u32 credits)
1235cfdda9d7SSteve Wise {
1236cfdda9d7SSteve Wise 	struct cpl_rx_data_ack *req;
1237cfdda9d7SSteve Wise 	struct sk_buff *skb;
1238cfdda9d7SSteve Wise 	int wrlen = roundup(sizeof *req, 16);
1239cfdda9d7SSteve Wise 
1240cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u credits %u\n", __func__, ep, ep->hwtid, credits);
1241cfdda9d7SSteve Wise 	skb = get_skb(NULL, wrlen, GFP_KERNEL);
1242cfdda9d7SSteve Wise 	if (!skb) {
1243cfdda9d7SSteve Wise 		printk(KERN_ERR MOD "update_rx_credits - cannot alloc skb!\n");
1244cfdda9d7SSteve Wise 		return 0;
1245cfdda9d7SSteve Wise 	}
1246cfdda9d7SSteve Wise 
1247b408ff28SHariprasad Shenai 	/*
1248b408ff28SHariprasad Shenai 	 * If we couldn't specify the entire rcv window at connection setup
1249b408ff28SHariprasad Shenai 	 * due to the limit in the number of bits in the RCV_BUFSIZ field,
1250b408ff28SHariprasad Shenai 	 * then add the overage in to the credits returned.
1251b408ff28SHariprasad Shenai 	 */
1252d7990b0cSAnish Bhatt 	if (ep->rcv_win > RCV_BUFSIZ_M * 1024)
1253d7990b0cSAnish Bhatt 		credits += ep->rcv_win - RCV_BUFSIZ_M * 1024;
1254b408ff28SHariprasad Shenai 
1255cfdda9d7SSteve Wise 	req = (struct cpl_rx_data_ack *) skb_put(skb, wrlen);
1256cfdda9d7SSteve Wise 	memset(req, 0, wrlen);
1257cfdda9d7SSteve Wise 	INIT_TP_WR(req, ep->hwtid);
1258cfdda9d7SSteve Wise 	OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_RX_DATA_ACK,
1259cfdda9d7SSteve Wise 						    ep->hwtid));
1260d7990b0cSAnish Bhatt 	req->credit_dack = cpu_to_be32(credits | RX_FORCE_ACK_F |
1261ba6d3925SSteve Wise 				       F_RX_DACK_CHANGE |
1262ba6d3925SSteve Wise 				       V_RX_DACK_MODE(dack_mode));
1263d4f1a5c6SSteve Wise 	set_wr_txq(skb, CPL_PRIORITY_ACK, ep->ctrlq_idx);
1264cfdda9d7SSteve Wise 	c4iw_ofld_send(&ep->com.dev->rdev, skb);
1265cfdda9d7SSteve Wise 	return credits;
1266cfdda9d7SSteve Wise }
1267cfdda9d7SSteve Wise 
12684c2c5763SHariprasad Shenai #define RELAXED_IRD_NEGOTIATION 1
12694c2c5763SHariprasad Shenai 
1270cc18b939SSteve Wise static int process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
1271cfdda9d7SSteve Wise {
1272cfdda9d7SSteve Wise 	struct mpa_message *mpa;
1273d2fe99e8SKumar Sanghvi 	struct mpa_v2_conn_params *mpa_v2_params;
1274cfdda9d7SSteve Wise 	u16 plen;
1275d2fe99e8SKumar Sanghvi 	u16 resp_ird, resp_ord;
1276d2fe99e8SKumar Sanghvi 	u8 rtr_mismatch = 0, insuff_ird = 0;
1277cfdda9d7SSteve Wise 	struct c4iw_qp_attributes attrs;
1278cfdda9d7SSteve Wise 	enum c4iw_qp_attr_mask mask;
1279cfdda9d7SSteve Wise 	int err;
1280cc18b939SSteve Wise 	int disconnect = 0;
1281cfdda9d7SSteve Wise 
1282cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
1283cfdda9d7SSteve Wise 
1284cfdda9d7SSteve Wise 	/*
1285b33bd0cbSSteve Wise 	 * Stop mpa timer.  If it expired, then
1286b33bd0cbSSteve Wise 	 * we ignore the MPA reply.  process_timeout()
1287b33bd0cbSSteve Wise 	 * will abort the connection.
1288cfdda9d7SSteve Wise 	 */
1289b33bd0cbSSteve Wise 	if (stop_ep_timer(ep))
1290cc18b939SSteve Wise 		return 0;
1291cfdda9d7SSteve Wise 
1292cfdda9d7SSteve Wise 	/*
1293cfdda9d7SSteve Wise 	 * If we get more than the supported amount of private data
1294cfdda9d7SSteve Wise 	 * then we must fail this connection.
1295cfdda9d7SSteve Wise 	 */
1296cfdda9d7SSteve Wise 	if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) {
1297cfdda9d7SSteve Wise 		err = -EINVAL;
1298cfdda9d7SSteve Wise 		goto err;
1299cfdda9d7SSteve Wise 	}
1300cfdda9d7SSteve Wise 
1301cfdda9d7SSteve Wise 	/*
1302cfdda9d7SSteve Wise 	 * copy the new data into our accumulation buffer.
1303cfdda9d7SSteve Wise 	 */
1304cfdda9d7SSteve Wise 	skb_copy_from_linear_data(skb, &(ep->mpa_pkt[ep->mpa_pkt_len]),
1305cfdda9d7SSteve Wise 				  skb->len);
1306cfdda9d7SSteve Wise 	ep->mpa_pkt_len += skb->len;
1307cfdda9d7SSteve Wise 
1308cfdda9d7SSteve Wise 	/*
1309cfdda9d7SSteve Wise 	 * if we don't even have the mpa message, then bail.
1310cfdda9d7SSteve Wise 	 */
1311cfdda9d7SSteve Wise 	if (ep->mpa_pkt_len < sizeof(*mpa))
1312cc18b939SSteve Wise 		return 0;
1313cfdda9d7SSteve Wise 	mpa = (struct mpa_message *) ep->mpa_pkt;
1314cfdda9d7SSteve Wise 
1315cfdda9d7SSteve Wise 	/* Validate MPA header. */
1316d2fe99e8SKumar Sanghvi 	if (mpa->revision > mpa_rev) {
1317d2fe99e8SKumar Sanghvi 		printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d,"
1318d2fe99e8SKumar Sanghvi 		       " Received = %d\n", __func__, mpa_rev, mpa->revision);
1319cfdda9d7SSteve Wise 		err = -EPROTO;
1320cfdda9d7SSteve Wise 		goto err;
1321cfdda9d7SSteve Wise 	}
1322cfdda9d7SSteve Wise 	if (memcmp(mpa->key, MPA_KEY_REP, sizeof(mpa->key))) {
1323cfdda9d7SSteve Wise 		err = -EPROTO;
1324cfdda9d7SSteve Wise 		goto err;
1325cfdda9d7SSteve Wise 	}
1326cfdda9d7SSteve Wise 
1327cfdda9d7SSteve Wise 	plen = ntohs(mpa->private_data_size);
1328cfdda9d7SSteve Wise 
1329cfdda9d7SSteve Wise 	/*
1330cfdda9d7SSteve Wise 	 * Fail if there's too much private data.
1331cfdda9d7SSteve Wise 	 */
1332cfdda9d7SSteve Wise 	if (plen > MPA_MAX_PRIVATE_DATA) {
1333cfdda9d7SSteve Wise 		err = -EPROTO;
1334cfdda9d7SSteve Wise 		goto err;
1335cfdda9d7SSteve Wise 	}
1336cfdda9d7SSteve Wise 
1337cfdda9d7SSteve Wise 	/*
1338cfdda9d7SSteve Wise 	 * If plen does not account for pkt size
1339cfdda9d7SSteve Wise 	 */
1340cfdda9d7SSteve Wise 	if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) {
1341cfdda9d7SSteve Wise 		err = -EPROTO;
1342cfdda9d7SSteve Wise 		goto err;
1343cfdda9d7SSteve Wise 	}
1344cfdda9d7SSteve Wise 
1345cfdda9d7SSteve Wise 	ep->plen = (u8) plen;
1346cfdda9d7SSteve Wise 
1347cfdda9d7SSteve Wise 	/*
1348cfdda9d7SSteve Wise 	 * If we don't have all the pdata yet, then bail.
1349cfdda9d7SSteve Wise 	 * We'll continue process when more data arrives.
1350cfdda9d7SSteve Wise 	 */
1351cfdda9d7SSteve Wise 	if (ep->mpa_pkt_len < (sizeof(*mpa) + plen))
1352cc18b939SSteve Wise 		return 0;
1353cfdda9d7SSteve Wise 
1354cfdda9d7SSteve Wise 	if (mpa->flags & MPA_REJECT) {
1355cfdda9d7SSteve Wise 		err = -ECONNREFUSED;
1356cfdda9d7SSteve Wise 		goto err;
1357cfdda9d7SSteve Wise 	}
1358cfdda9d7SSteve Wise 
1359cfdda9d7SSteve Wise 	/*
1360cfdda9d7SSteve Wise 	 * If we get here we have accumulated the entire mpa
1361cfdda9d7SSteve Wise 	 * start reply message including private data. And
1362cfdda9d7SSteve Wise 	 * the MPA header is valid.
1363cfdda9d7SSteve Wise 	 */
1364c529fb50SSteve Wise 	__state_set(&ep->com, FPDU_MODE);
1365cfdda9d7SSteve Wise 	ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
1366cfdda9d7SSteve Wise 	ep->mpa_attr.recv_marker_enabled = markers_enabled;
1367cfdda9d7SSteve Wise 	ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
1368d2fe99e8SKumar Sanghvi 	ep->mpa_attr.version = mpa->revision;
1369d2fe99e8SKumar Sanghvi 	ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
1370d2fe99e8SKumar Sanghvi 
1371d2fe99e8SKumar Sanghvi 	if (mpa->revision == 2) {
1372d2fe99e8SKumar Sanghvi 		ep->mpa_attr.enhanced_rdma_conn =
1373d2fe99e8SKumar Sanghvi 			mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0;
1374d2fe99e8SKumar Sanghvi 		if (ep->mpa_attr.enhanced_rdma_conn) {
1375d2fe99e8SKumar Sanghvi 			mpa_v2_params = (struct mpa_v2_conn_params *)
1376d2fe99e8SKumar Sanghvi 				(ep->mpa_pkt + sizeof(*mpa));
1377d2fe99e8SKumar Sanghvi 			resp_ird = ntohs(mpa_v2_params->ird) &
1378d2fe99e8SKumar Sanghvi 				MPA_V2_IRD_ORD_MASK;
1379d2fe99e8SKumar Sanghvi 			resp_ord = ntohs(mpa_v2_params->ord) &
1380d2fe99e8SKumar Sanghvi 				MPA_V2_IRD_ORD_MASK;
13814c2c5763SHariprasad Shenai 			PDBG("%s responder ird %u ord %u ep ird %u ord %u\n",
13824c2c5763SHariprasad Shenai 			     __func__, resp_ird, resp_ord, ep->ird, ep->ord);
1383d2fe99e8SKumar Sanghvi 
1384d2fe99e8SKumar Sanghvi 			/*
1385d2fe99e8SKumar Sanghvi 			 * This is a double-check. Ideally, below checks are
1386d2fe99e8SKumar Sanghvi 			 * not required since ird/ord stuff has been taken
1387d2fe99e8SKumar Sanghvi 			 * care of in c4iw_accept_cr
1388d2fe99e8SKumar Sanghvi 			 */
13894c2c5763SHariprasad Shenai 			if (ep->ird < resp_ord) {
13904c2c5763SHariprasad Shenai 				if (RELAXED_IRD_NEGOTIATION && resp_ord <=
13914c2c5763SHariprasad Shenai 				    ep->com.dev->rdev.lldi.max_ordird_qp)
13924c2c5763SHariprasad Shenai 					ep->ird = resp_ord;
13934c2c5763SHariprasad Shenai 				else
13944c2c5763SHariprasad Shenai 					insuff_ird = 1;
13954c2c5763SHariprasad Shenai 			} else if (ep->ird > resp_ord) {
13964c2c5763SHariprasad Shenai 				ep->ird = resp_ord;
13974c2c5763SHariprasad Shenai 			}
13984c2c5763SHariprasad Shenai 			if (ep->ord > resp_ird) {
13994c2c5763SHariprasad Shenai 				if (RELAXED_IRD_NEGOTIATION)
14004c2c5763SHariprasad Shenai 					ep->ord = resp_ird;
14014c2c5763SHariprasad Shenai 				else
14024c2c5763SHariprasad Shenai 					insuff_ird = 1;
14034c2c5763SHariprasad Shenai 			}
14044c2c5763SHariprasad Shenai 			if (insuff_ird) {
1405d2fe99e8SKumar Sanghvi 				err = -ENOMEM;
1406d2fe99e8SKumar Sanghvi 				ep->ird = resp_ord;
1407d2fe99e8SKumar Sanghvi 				ep->ord = resp_ird;
1408d2fe99e8SKumar Sanghvi 			}
1409d2fe99e8SKumar Sanghvi 
1410d2fe99e8SKumar Sanghvi 			if (ntohs(mpa_v2_params->ird) &
1411d2fe99e8SKumar Sanghvi 					MPA_V2_PEER2PEER_MODEL) {
1412d2fe99e8SKumar Sanghvi 				if (ntohs(mpa_v2_params->ord) &
1413d2fe99e8SKumar Sanghvi 						MPA_V2_RDMA_WRITE_RTR)
1414d2fe99e8SKumar Sanghvi 					ep->mpa_attr.p2p_type =
1415d2fe99e8SKumar Sanghvi 						FW_RI_INIT_P2PTYPE_RDMA_WRITE;
1416d2fe99e8SKumar Sanghvi 				else if (ntohs(mpa_v2_params->ord) &
1417d2fe99e8SKumar Sanghvi 						MPA_V2_RDMA_READ_RTR)
1418d2fe99e8SKumar Sanghvi 					ep->mpa_attr.p2p_type =
1419d2fe99e8SKumar Sanghvi 						FW_RI_INIT_P2PTYPE_READ_REQ;
1420d2fe99e8SKumar Sanghvi 			}
1421d2fe99e8SKumar Sanghvi 		}
1422d2fe99e8SKumar Sanghvi 	} else if (mpa->revision == 1)
1423d2fe99e8SKumar Sanghvi 		if (peer2peer)
1424d2fe99e8SKumar Sanghvi 			ep->mpa_attr.p2p_type = p2p_type;
1425d2fe99e8SKumar Sanghvi 
1426cfdda9d7SSteve Wise 	PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, "
1427d2fe99e8SKumar Sanghvi 	     "xmit_marker_enabled=%d, version=%d p2p_type=%d local-p2p_type = "
1428d2fe99e8SKumar Sanghvi 	     "%d\n", __func__, ep->mpa_attr.crc_enabled,
1429d2fe99e8SKumar Sanghvi 	     ep->mpa_attr.recv_marker_enabled,
1430d2fe99e8SKumar Sanghvi 	     ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version,
1431d2fe99e8SKumar Sanghvi 	     ep->mpa_attr.p2p_type, p2p_type);
1432d2fe99e8SKumar Sanghvi 
1433d2fe99e8SKumar Sanghvi 	/*
1434d2fe99e8SKumar Sanghvi 	 * If responder's RTR does not match with that of initiator, assign
1435d2fe99e8SKumar Sanghvi 	 * FW_RI_INIT_P2PTYPE_DISABLED in mpa attributes so that RTR is not
1436d2fe99e8SKumar Sanghvi 	 * generated when moving QP to RTS state.
1437d2fe99e8SKumar Sanghvi 	 * A TERM message will be sent after QP has moved to RTS state
1438d2fe99e8SKumar Sanghvi 	 */
143991018f86SKumar Sanghvi 	if ((ep->mpa_attr.version == 2) && peer2peer &&
1440d2fe99e8SKumar Sanghvi 			(ep->mpa_attr.p2p_type != p2p_type)) {
1441d2fe99e8SKumar Sanghvi 		ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
1442d2fe99e8SKumar Sanghvi 		rtr_mismatch = 1;
1443d2fe99e8SKumar Sanghvi 	}
1444cfdda9d7SSteve Wise 
1445cfdda9d7SSteve Wise 	attrs.mpa_attr = ep->mpa_attr;
1446cfdda9d7SSteve Wise 	attrs.max_ird = ep->ird;
1447cfdda9d7SSteve Wise 	attrs.max_ord = ep->ord;
1448cfdda9d7SSteve Wise 	attrs.llp_stream_handle = ep;
1449cfdda9d7SSteve Wise 	attrs.next_state = C4IW_QP_STATE_RTS;
1450cfdda9d7SSteve Wise 
1451cfdda9d7SSteve Wise 	mask = C4IW_QP_ATTR_NEXT_STATE |
1452cfdda9d7SSteve Wise 	    C4IW_QP_ATTR_LLP_STREAM_HANDLE | C4IW_QP_ATTR_MPA_ATTR |
1453cfdda9d7SSteve Wise 	    C4IW_QP_ATTR_MAX_IRD | C4IW_QP_ATTR_MAX_ORD;
1454cfdda9d7SSteve Wise 
1455cfdda9d7SSteve Wise 	/* bind QP and TID with INIT_WR */
1456cfdda9d7SSteve Wise 	err = c4iw_modify_qp(ep->com.qp->rhp,
1457cfdda9d7SSteve Wise 			     ep->com.qp, mask, &attrs, 1);
1458cfdda9d7SSteve Wise 	if (err)
1459cfdda9d7SSteve Wise 		goto err;
1460d2fe99e8SKumar Sanghvi 
1461d2fe99e8SKumar Sanghvi 	/*
1462d2fe99e8SKumar Sanghvi 	 * If responder's RTR requirement did not match with what initiator
1463d2fe99e8SKumar Sanghvi 	 * supports, generate TERM message
1464d2fe99e8SKumar Sanghvi 	 */
1465d2fe99e8SKumar Sanghvi 	if (rtr_mismatch) {
1466d2fe99e8SKumar Sanghvi 		printk(KERN_ERR "%s: RTR mismatch, sending TERM\n", __func__);
1467d2fe99e8SKumar Sanghvi 		attrs.layer_etype = LAYER_MPA | DDP_LLP;
1468d2fe99e8SKumar Sanghvi 		attrs.ecode = MPA_NOMATCH_RTR;
1469d2fe99e8SKumar Sanghvi 		attrs.next_state = C4IW_QP_STATE_TERMINATE;
1470cc18b939SSteve Wise 		attrs.send_term = 1;
1471d2fe99e8SKumar Sanghvi 		err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
1472cc18b939SSteve Wise 				C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
1473d2fe99e8SKumar Sanghvi 		err = -ENOMEM;
1474cc18b939SSteve Wise 		disconnect = 1;
1475d2fe99e8SKumar Sanghvi 		goto out;
1476d2fe99e8SKumar Sanghvi 	}
1477d2fe99e8SKumar Sanghvi 
1478d2fe99e8SKumar Sanghvi 	/*
1479d2fe99e8SKumar Sanghvi 	 * Generate TERM if initiator IRD is not sufficient for responder
1480d2fe99e8SKumar Sanghvi 	 * provided ORD. Currently, we do the same behaviour even when
1481d2fe99e8SKumar Sanghvi 	 * responder provided IRD is also not sufficient as regards to
1482d2fe99e8SKumar Sanghvi 	 * initiator ORD.
1483d2fe99e8SKumar Sanghvi 	 */
1484d2fe99e8SKumar Sanghvi 	if (insuff_ird) {
1485d2fe99e8SKumar Sanghvi 		printk(KERN_ERR "%s: Insufficient IRD, sending TERM\n",
1486d2fe99e8SKumar Sanghvi 				__func__);
1487d2fe99e8SKumar Sanghvi 		attrs.layer_etype = LAYER_MPA | DDP_LLP;
1488d2fe99e8SKumar Sanghvi 		attrs.ecode = MPA_INSUFF_IRD;
1489d2fe99e8SKumar Sanghvi 		attrs.next_state = C4IW_QP_STATE_TERMINATE;
1490cc18b939SSteve Wise 		attrs.send_term = 1;
1491d2fe99e8SKumar Sanghvi 		err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
1492cc18b939SSteve Wise 				C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
1493d2fe99e8SKumar Sanghvi 		err = -ENOMEM;
1494cc18b939SSteve Wise 		disconnect = 1;
1495d2fe99e8SKumar Sanghvi 		goto out;
1496d2fe99e8SKumar Sanghvi 	}
1497cfdda9d7SSteve Wise 	goto out;
1498cfdda9d7SSteve Wise err:
1499c529fb50SSteve Wise 	__state_set(&ep->com, ABORTING);
1500b21ef16aSSteve Wise 	send_abort(ep, skb, GFP_KERNEL);
1501cfdda9d7SSteve Wise out:
1502cfdda9d7SSteve Wise 	connect_reply_upcall(ep, err);
1503cc18b939SSteve Wise 	return disconnect;
1504cfdda9d7SSteve Wise }
1505cfdda9d7SSteve Wise 
1506cfdda9d7SSteve Wise static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
1507cfdda9d7SSteve Wise {
1508cfdda9d7SSteve Wise 	struct mpa_message *mpa;
1509d2fe99e8SKumar Sanghvi 	struct mpa_v2_conn_params *mpa_v2_params;
1510cfdda9d7SSteve Wise 	u16 plen;
1511cfdda9d7SSteve Wise 
1512cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
1513cfdda9d7SSteve Wise 
1514cfdda9d7SSteve Wise 	/*
1515cfdda9d7SSteve Wise 	 * If we get more than the supported amount of private data
1516cfdda9d7SSteve Wise 	 * then we must fail this connection.
1517cfdda9d7SSteve Wise 	 */
1518cfdda9d7SSteve Wise 	if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) {
1519b33bd0cbSSteve Wise 		(void)stop_ep_timer(ep);
1520cfdda9d7SSteve Wise 		abort_connection(ep, skb, GFP_KERNEL);
1521cfdda9d7SSteve Wise 		return;
1522cfdda9d7SSteve Wise 	}
1523cfdda9d7SSteve Wise 
1524cfdda9d7SSteve Wise 	PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__);
1525cfdda9d7SSteve Wise 
1526cfdda9d7SSteve Wise 	/*
1527cfdda9d7SSteve Wise 	 * Copy the new data into our accumulation buffer.
1528cfdda9d7SSteve Wise 	 */
1529cfdda9d7SSteve Wise 	skb_copy_from_linear_data(skb, &(ep->mpa_pkt[ep->mpa_pkt_len]),
1530cfdda9d7SSteve Wise 				  skb->len);
1531cfdda9d7SSteve Wise 	ep->mpa_pkt_len += skb->len;
1532cfdda9d7SSteve Wise 
1533cfdda9d7SSteve Wise 	/*
1534cfdda9d7SSteve Wise 	 * If we don't even have the mpa message, then bail.
1535cfdda9d7SSteve Wise 	 * We'll continue process when more data arrives.
1536cfdda9d7SSteve Wise 	 */
1537cfdda9d7SSteve Wise 	if (ep->mpa_pkt_len < sizeof(*mpa))
1538cfdda9d7SSteve Wise 		return;
1539cfdda9d7SSteve Wise 
1540cfdda9d7SSteve Wise 	PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__);
1541cfdda9d7SSteve Wise 	mpa = (struct mpa_message *) ep->mpa_pkt;
1542cfdda9d7SSteve Wise 
1543cfdda9d7SSteve Wise 	/*
1544cfdda9d7SSteve Wise 	 * Validate MPA Header.
1545cfdda9d7SSteve Wise 	 */
1546d2fe99e8SKumar Sanghvi 	if (mpa->revision > mpa_rev) {
1547d2fe99e8SKumar Sanghvi 		printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d,"
1548d2fe99e8SKumar Sanghvi 		       " Received = %d\n", __func__, mpa_rev, mpa->revision);
1549b33bd0cbSSteve Wise 		(void)stop_ep_timer(ep);
1550cfdda9d7SSteve Wise 		abort_connection(ep, skb, GFP_KERNEL);
1551cfdda9d7SSteve Wise 		return;
1552cfdda9d7SSteve Wise 	}
1553cfdda9d7SSteve Wise 
1554cfdda9d7SSteve Wise 	if (memcmp(mpa->key, MPA_KEY_REQ, sizeof(mpa->key))) {
1555b33bd0cbSSteve Wise 		(void)stop_ep_timer(ep);
1556cfdda9d7SSteve Wise 		abort_connection(ep, skb, GFP_KERNEL);
1557cfdda9d7SSteve Wise 		return;
1558cfdda9d7SSteve Wise 	}
1559cfdda9d7SSteve Wise 
1560cfdda9d7SSteve Wise 	plen = ntohs(mpa->private_data_size);
1561cfdda9d7SSteve Wise 
1562cfdda9d7SSteve Wise 	/*
1563cfdda9d7SSteve Wise 	 * Fail if there's too much private data.
1564cfdda9d7SSteve Wise 	 */
1565cfdda9d7SSteve Wise 	if (plen > MPA_MAX_PRIVATE_DATA) {
1566b33bd0cbSSteve Wise 		(void)stop_ep_timer(ep);
1567cfdda9d7SSteve Wise 		abort_connection(ep, skb, GFP_KERNEL);
1568cfdda9d7SSteve Wise 		return;
1569cfdda9d7SSteve Wise 	}
1570cfdda9d7SSteve Wise 
1571cfdda9d7SSteve Wise 	/*
1572cfdda9d7SSteve Wise 	 * If plen does not account for pkt size
1573cfdda9d7SSteve Wise 	 */
1574cfdda9d7SSteve Wise 	if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) {
1575b33bd0cbSSteve Wise 		(void)stop_ep_timer(ep);
1576cfdda9d7SSteve Wise 		abort_connection(ep, skb, GFP_KERNEL);
1577cfdda9d7SSteve Wise 		return;
1578cfdda9d7SSteve Wise 	}
1579cfdda9d7SSteve Wise 	ep->plen = (u8) plen;
1580cfdda9d7SSteve Wise 
1581cfdda9d7SSteve Wise 	/*
1582cfdda9d7SSteve Wise 	 * If we don't have all the pdata yet, then bail.
1583cfdda9d7SSteve Wise 	 */
1584cfdda9d7SSteve Wise 	if (ep->mpa_pkt_len < (sizeof(*mpa) + plen))
1585cfdda9d7SSteve Wise 		return;
1586cfdda9d7SSteve Wise 
1587cfdda9d7SSteve Wise 	/*
1588cfdda9d7SSteve Wise 	 * If we get here we have accumulated the entire mpa
1589cfdda9d7SSteve Wise 	 * start reply message including private data.
1590cfdda9d7SSteve Wise 	 */
1591cfdda9d7SSteve Wise 	ep->mpa_attr.initiator = 0;
1592cfdda9d7SSteve Wise 	ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
1593cfdda9d7SSteve Wise 	ep->mpa_attr.recv_marker_enabled = markers_enabled;
1594cfdda9d7SSteve Wise 	ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
1595d2fe99e8SKumar Sanghvi 	ep->mpa_attr.version = mpa->revision;
1596d2fe99e8SKumar Sanghvi 	if (mpa->revision == 1)
1597d2fe99e8SKumar Sanghvi 		ep->tried_with_mpa_v1 = 1;
1598d2fe99e8SKumar Sanghvi 	ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
1599d2fe99e8SKumar Sanghvi 
1600d2fe99e8SKumar Sanghvi 	if (mpa->revision == 2) {
1601d2fe99e8SKumar Sanghvi 		ep->mpa_attr.enhanced_rdma_conn =
1602d2fe99e8SKumar Sanghvi 			mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0;
1603d2fe99e8SKumar Sanghvi 		if (ep->mpa_attr.enhanced_rdma_conn) {
1604d2fe99e8SKumar Sanghvi 			mpa_v2_params = (struct mpa_v2_conn_params *)
1605d2fe99e8SKumar Sanghvi 				(ep->mpa_pkt + sizeof(*mpa));
1606d2fe99e8SKumar Sanghvi 			ep->ird = ntohs(mpa_v2_params->ird) &
1607d2fe99e8SKumar Sanghvi 				MPA_V2_IRD_ORD_MASK;
1608d2fe99e8SKumar Sanghvi 			ep->ord = ntohs(mpa_v2_params->ord) &
1609d2fe99e8SKumar Sanghvi 				MPA_V2_IRD_ORD_MASK;
16104c2c5763SHariprasad Shenai 			PDBG("%s initiator ird %u ord %u\n", __func__, ep->ird,
16114c2c5763SHariprasad Shenai 			     ep->ord);
1612d2fe99e8SKumar Sanghvi 			if (ntohs(mpa_v2_params->ird) & MPA_V2_PEER2PEER_MODEL)
1613d2fe99e8SKumar Sanghvi 				if (peer2peer) {
1614d2fe99e8SKumar Sanghvi 					if (ntohs(mpa_v2_params->ord) &
1615d2fe99e8SKumar Sanghvi 							MPA_V2_RDMA_WRITE_RTR)
1616d2fe99e8SKumar Sanghvi 						ep->mpa_attr.p2p_type =
1617d2fe99e8SKumar Sanghvi 						FW_RI_INIT_P2PTYPE_RDMA_WRITE;
1618d2fe99e8SKumar Sanghvi 					else if (ntohs(mpa_v2_params->ord) &
1619d2fe99e8SKumar Sanghvi 							MPA_V2_RDMA_READ_RTR)
1620d2fe99e8SKumar Sanghvi 						ep->mpa_attr.p2p_type =
1621d2fe99e8SKumar Sanghvi 						FW_RI_INIT_P2PTYPE_READ_REQ;
1622d2fe99e8SKumar Sanghvi 				}
1623d2fe99e8SKumar Sanghvi 		}
1624d2fe99e8SKumar Sanghvi 	} else if (mpa->revision == 1)
1625d2fe99e8SKumar Sanghvi 		if (peer2peer)
1626d2fe99e8SKumar Sanghvi 			ep->mpa_attr.p2p_type = p2p_type;
1627d2fe99e8SKumar Sanghvi 
1628cfdda9d7SSteve Wise 	PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, "
1629cfdda9d7SSteve Wise 	     "xmit_marker_enabled=%d, version=%d p2p_type=%d\n", __func__,
1630cfdda9d7SSteve Wise 	     ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled,
1631cfdda9d7SSteve Wise 	     ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version,
1632cfdda9d7SSteve Wise 	     ep->mpa_attr.p2p_type);
1633cfdda9d7SSteve Wise 
1634b33bd0cbSSteve Wise 	/*
1635b33bd0cbSSteve Wise 	 * If the endpoint timer already expired, then we ignore
1636b33bd0cbSSteve Wise 	 * the start request.  process_timeout() will abort
1637b33bd0cbSSteve Wise 	 * the connection.
1638b33bd0cbSSteve Wise 	 */
1639b33bd0cbSSteve Wise 	if (!stop_ep_timer(ep)) {
1640c529fb50SSteve Wise 		__state_set(&ep->com, MPA_REQ_RCVD);
1641cfdda9d7SSteve Wise 
1642cfdda9d7SSteve Wise 		/* drive upcall */
164310be6b48SHariprasad Shenai 		mutex_lock_nested(&ep->parent_ep->com.mutex,
164410be6b48SHariprasad Shenai 				  SINGLE_DEPTH_NESTING);
1645be13b2dfSSteve Wise 		if (ep->parent_ep->com.state != DEAD) {
1646be13b2dfSSteve Wise 			if (connect_request_upcall(ep))
1647be13b2dfSSteve Wise 				abort_connection(ep, skb, GFP_KERNEL);
1648be13b2dfSSteve Wise 		} else {
1649be13b2dfSSteve Wise 			abort_connection(ep, skb, GFP_KERNEL);
1650be13b2dfSSteve Wise 		}
1651be13b2dfSSteve Wise 		mutex_unlock(&ep->parent_ep->com.mutex);
1652b33bd0cbSSteve Wise 	}
1653cfdda9d7SSteve Wise 	return;
1654cfdda9d7SSteve Wise }
1655cfdda9d7SSteve Wise 
1656cfdda9d7SSteve Wise static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb)
1657cfdda9d7SSteve Wise {
1658cfdda9d7SSteve Wise 	struct c4iw_ep *ep;
1659cfdda9d7SSteve Wise 	struct cpl_rx_data *hdr = cplhdr(skb);
1660cfdda9d7SSteve Wise 	unsigned int dlen = ntohs(hdr->len);
1661cfdda9d7SSteve Wise 	unsigned int tid = GET_TID(hdr);
1662cfdda9d7SSteve Wise 	struct tid_info *t = dev->rdev.lldi.tids;
1663793dad94SVipul Pandya 	__u8 status = hdr->status;
1664cc18b939SSteve Wise 	int disconnect = 0;
1665cfdda9d7SSteve Wise 
1666cfdda9d7SSteve Wise 	ep = lookup_tid(t, tid);
1667977116c6SSteve Wise 	if (!ep)
1668977116c6SSteve Wise 		return 0;
1669cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u dlen %u\n", __func__, ep, ep->hwtid, dlen);
1670cfdda9d7SSteve Wise 	skb_pull(skb, sizeof(*hdr));
1671cfdda9d7SSteve Wise 	skb_trim(skb, dlen);
1672c529fb50SSteve Wise 	mutex_lock(&ep->com.mutex);
1673cfdda9d7SSteve Wise 
1674cfdda9d7SSteve Wise 	/* update RX credits */
1675cfdda9d7SSteve Wise 	update_rx_credits(ep, dlen);
1676cfdda9d7SSteve Wise 
1677c529fb50SSteve Wise 	switch (ep->com.state) {
1678cfdda9d7SSteve Wise 	case MPA_REQ_SENT:
167955abf8dfSVipul Pandya 		ep->rcv_seq += dlen;
1680cc18b939SSteve Wise 		disconnect = process_mpa_reply(ep, skb);
1681cfdda9d7SSteve Wise 		break;
1682cfdda9d7SSteve Wise 	case MPA_REQ_WAIT:
168355abf8dfSVipul Pandya 		ep->rcv_seq += dlen;
1684cfdda9d7SSteve Wise 		process_mpa_request(ep, skb);
1685cfdda9d7SSteve Wise 		break;
16861557967bSVipul Pandya 	case FPDU_MODE: {
16871557967bSVipul Pandya 		struct c4iw_qp_attributes attrs;
16881557967bSVipul Pandya 		BUG_ON(!ep->com.qp);
1689e8e5b927SVipul Pandya 		if (status)
1690793dad94SVipul Pandya 			pr_err("%s Unexpected streaming data." \
169104236df2SVipul Pandya 			       " qpid %u ep %p state %d tid %u status %d\n",
169204236df2SVipul Pandya 			       __func__, ep->com.qp->wq.sq.qid, ep,
1693c529fb50SSteve Wise 			       ep->com.state, ep->hwtid, status);
169497d7ec0cSSteve Wise 		attrs.next_state = C4IW_QP_STATE_TERMINATE;
169555abf8dfSVipul Pandya 		c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
1696cc18b939SSteve Wise 			       C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
1697cc18b939SSteve Wise 		disconnect = 1;
1698cfdda9d7SSteve Wise 		break;
1699cfdda9d7SSteve Wise 	}
17001557967bSVipul Pandya 	default:
17011557967bSVipul Pandya 		break;
17021557967bSVipul Pandya 	}
1703c529fb50SSteve Wise 	mutex_unlock(&ep->com.mutex);
1704cc18b939SSteve Wise 	if (disconnect)
1705cc18b939SSteve Wise 		c4iw_ep_disconnect(ep, 0, GFP_KERNEL);
1706cfdda9d7SSteve Wise 	return 0;
1707cfdda9d7SSteve Wise }
1708cfdda9d7SSteve Wise 
1709cfdda9d7SSteve Wise static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
1710cfdda9d7SSteve Wise {
1711cfdda9d7SSteve Wise 	struct c4iw_ep *ep;
1712cfdda9d7SSteve Wise 	struct cpl_abort_rpl_rss *rpl = cplhdr(skb);
1713cfdda9d7SSteve Wise 	int release = 0;
1714cfdda9d7SSteve Wise 	unsigned int tid = GET_TID(rpl);
1715cfdda9d7SSteve Wise 	struct tid_info *t = dev->rdev.lldi.tids;
1716cfdda9d7SSteve Wise 
1717cfdda9d7SSteve Wise 	ep = lookup_tid(t, tid);
17184984037bSVipul Pandya 	if (!ep) {
17194984037bSVipul Pandya 		printk(KERN_WARNING MOD "Abort rpl to freed endpoint\n");
17204984037bSVipul Pandya 		return 0;
17214984037bSVipul Pandya 	}
172292dd6c3dSWei Yongjun 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
17232f5b48c3SSteve Wise 	mutex_lock(&ep->com.mutex);
1724cfdda9d7SSteve Wise 	switch (ep->com.state) {
1725cfdda9d7SSteve Wise 	case ABORTING:
172691e9c071SVipul Pandya 		c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
1727cfdda9d7SSteve Wise 		__state_set(&ep->com, DEAD);
1728cfdda9d7SSteve Wise 		release = 1;
1729cfdda9d7SSteve Wise 		break;
1730cfdda9d7SSteve Wise 	default:
1731cfdda9d7SSteve Wise 		printk(KERN_ERR "%s ep %p state %d\n",
1732cfdda9d7SSteve Wise 		     __func__, ep, ep->com.state);
1733cfdda9d7SSteve Wise 		break;
1734cfdda9d7SSteve Wise 	}
17352f5b48c3SSteve Wise 	mutex_unlock(&ep->com.mutex);
1736cfdda9d7SSteve Wise 
1737cfdda9d7SSteve Wise 	if (release)
1738cfdda9d7SSteve Wise 		release_ep_resources(ep);
1739cfdda9d7SSteve Wise 	return 0;
1740cfdda9d7SSteve Wise }
1741cfdda9d7SSteve Wise 
17425be78ee9SVipul Pandya static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid)
17435be78ee9SVipul Pandya {
17445be78ee9SVipul Pandya 	struct sk_buff *skb;
17455be78ee9SVipul Pandya 	struct fw_ofld_connection_wr *req;
17465be78ee9SVipul Pandya 	unsigned int mtu_idx;
17475be78ee9SVipul Pandya 	int wscale;
1748830662f6SVipul Pandya 	struct sockaddr_in *sin;
1749b408ff28SHariprasad Shenai 	int win;
17505be78ee9SVipul Pandya 
17515be78ee9SVipul Pandya 	skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
17525be78ee9SVipul Pandya 	req = (struct fw_ofld_connection_wr *)__skb_put(skb, sizeof(*req));
17535be78ee9SVipul Pandya 	memset(req, 0, sizeof(*req));
17546c53e938SHariprasad Shenai 	req->op_compl = htonl(WR_OP_V(FW_OFLD_CONNECTION_WR));
1755e2ac9628SHariprasad Shenai 	req->len16_pkd = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*req), 16)));
175641b4f86cSKumar Sanghvi 	req->le.filter = cpu_to_be32(cxgb4_select_ntuple(
175741b4f86cSKumar Sanghvi 				     ep->com.dev->rdev.lldi.ports[0],
17585be78ee9SVipul Pandya 				     ep->l2t));
17599eccfe10SSteve Wise 	sin = (struct sockaddr_in *)&ep->com.mapped_local_addr;
1760830662f6SVipul Pandya 	req->le.lport = sin->sin_port;
1761830662f6SVipul Pandya 	req->le.u.ipv4.lip = sin->sin_addr.s_addr;
17629eccfe10SSteve Wise 	sin = (struct sockaddr_in *)&ep->com.mapped_remote_addr;
1763830662f6SVipul Pandya 	req->le.pport = sin->sin_port;
1764830662f6SVipul Pandya 	req->le.u.ipv4.pip = sin->sin_addr.s_addr;
17655be78ee9SVipul Pandya 	req->tcb.t_state_to_astid =
176677a80e23SHariprasad Shenai 			htonl(FW_OFLD_CONNECTION_WR_T_STATE_V(TCP_SYN_SENT) |
176777a80e23SHariprasad Shenai 			FW_OFLD_CONNECTION_WR_ASTID_V(atid));
17685be78ee9SVipul Pandya 	req->tcb.cplrxdataack_cplpassacceptrpl =
176977a80e23SHariprasad Shenai 			htons(FW_OFLD_CONNECTION_WR_CPLRXDATAACK_F);
1770ef5d6355SVipul Pandya 	req->tcb.tx_max = (__force __be32) jiffies;
1771793dad94SVipul Pandya 	req->tcb.rcv_adv = htons(1);
177292e7ae71SHariprasad Shenai 	best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx,
177304524a47SHariprasad S 		 enable_tcp_timestamps,
177404524a47SHariprasad S 		 (AF_INET == ep->com.remote_addr.ss_family) ? 0 : 1);
17755be78ee9SVipul Pandya 	wscale = compute_wscale(rcv_win);
1776b408ff28SHariprasad Shenai 
1777b408ff28SHariprasad Shenai 	/*
1778b408ff28SHariprasad Shenai 	 * Specify the largest window that will fit in opt0. The
1779b408ff28SHariprasad Shenai 	 * remainder will be specified in the rx_data_ack.
1780b408ff28SHariprasad Shenai 	 */
1781b408ff28SHariprasad Shenai 	win = ep->rcv_win >> 10;
1782d7990b0cSAnish Bhatt 	if (win > RCV_BUFSIZ_M)
1783d7990b0cSAnish Bhatt 		win = RCV_BUFSIZ_M;
1784b408ff28SHariprasad Shenai 
17856c53e938SHariprasad Shenai 	req->tcb.opt0 = (__force __be64) (TCAM_BYPASS_F |
17866c53e938SHariprasad Shenai 		(nocong ? NO_CONG_F : 0) |
1787d7990b0cSAnish Bhatt 		KEEP_ALIVE_F |
17886c53e938SHariprasad Shenai 		DELACK_F |
1789d7990b0cSAnish Bhatt 		WND_SCALE_V(wscale) |
1790d7990b0cSAnish Bhatt 		MSS_IDX_V(mtu_idx) |
1791d7990b0cSAnish Bhatt 		L2T_IDX_V(ep->l2t->idx) |
1792d7990b0cSAnish Bhatt 		TX_CHAN_V(ep->tx_chan) |
1793d7990b0cSAnish Bhatt 		SMAC_SEL_V(ep->smac_idx) |
17946c53e938SHariprasad Shenai 		DSCP_V(ep->tos) |
1795d7990b0cSAnish Bhatt 		ULP_MODE_V(ULP_MODE_TCPDDP) |
1796d7990b0cSAnish Bhatt 		RCV_BUFSIZ_V(win));
17976c53e938SHariprasad Shenai 	req->tcb.opt2 = (__force __be32) (PACE_V(1) |
17986c53e938SHariprasad Shenai 		TX_QUEUE_V(ep->com.dev->rdev.lldi.tx_modq[ep->tx_chan]) |
1799d7990b0cSAnish Bhatt 		RX_CHANNEL_V(0) |
18006c53e938SHariprasad Shenai 		CCTRL_ECN_V(enable_ecn) |
1801d7990b0cSAnish Bhatt 		RSS_QUEUE_VALID_F | RSS_QUEUE_V(ep->rss_qid));
18025be78ee9SVipul Pandya 	if (enable_tcp_timestamps)
18036c53e938SHariprasad Shenai 		req->tcb.opt2 |= (__force __be32)TSTAMPS_EN_F;
18045be78ee9SVipul Pandya 	if (enable_tcp_sack)
18056c53e938SHariprasad Shenai 		req->tcb.opt2 |= (__force __be32)SACK_EN_F;
18065be78ee9SVipul Pandya 	if (wscale && enable_tcp_window_scaling)
1807d7990b0cSAnish Bhatt 		req->tcb.opt2 |= (__force __be32)WND_SCALE_EN_F;
1808ef5d6355SVipul Pandya 	req->tcb.opt0 = cpu_to_be64((__force u64)req->tcb.opt0);
1809ef5d6355SVipul Pandya 	req->tcb.opt2 = cpu_to_be32((__force u32)req->tcb.opt2);
1810793dad94SVipul Pandya 	set_wr_txq(skb, CPL_PRIORITY_CONTROL, ep->ctrlq_idx);
1811793dad94SVipul Pandya 	set_bit(ACT_OFLD_CONN, &ep->com.history);
18125be78ee9SVipul Pandya 	c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
18135be78ee9SVipul Pandya }
18145be78ee9SVipul Pandya 
1815cfdda9d7SSteve Wise /*
1816cfdda9d7SSteve Wise  * Return whether a failed active open has allocated a TID
1817cfdda9d7SSteve Wise  */
1818cfdda9d7SSteve Wise static inline int act_open_has_tid(int status)
1819cfdda9d7SSteve Wise {
1820cfdda9d7SSteve Wise 	return status != CPL_ERR_TCAM_FULL && status != CPL_ERR_CONN_EXIST &&
1821cfdda9d7SSteve Wise 	       status != CPL_ERR_ARP_MISS;
1822cfdda9d7SSteve Wise }
1823cfdda9d7SSteve Wise 
18247a2cea2aSSteve Wise /* Returns whether a CPL status conveys negative advice.
18257a2cea2aSSteve Wise  */
18267a2cea2aSSteve Wise static int is_neg_adv(unsigned int status)
18277a2cea2aSSteve Wise {
18287a2cea2aSSteve Wise 	return status == CPL_ERR_RTX_NEG_ADVICE ||
18297a2cea2aSSteve Wise 	       status == CPL_ERR_PERSIST_NEG_ADVICE ||
18307a2cea2aSSteve Wise 	       status == CPL_ERR_KEEPALV_NEG_ADVICE;
18317a2cea2aSSteve Wise }
18327a2cea2aSSteve Wise 
1833dd92b124SHariprasad Shenai static char *neg_adv_str(unsigned int status)
1834dd92b124SHariprasad Shenai {
1835dd92b124SHariprasad Shenai 	switch (status) {
1836dd92b124SHariprasad Shenai 	case CPL_ERR_RTX_NEG_ADVICE:
1837dd92b124SHariprasad Shenai 		return "Retransmit timeout";
1838dd92b124SHariprasad Shenai 	case CPL_ERR_PERSIST_NEG_ADVICE:
1839dd92b124SHariprasad Shenai 		return "Persist timeout";
1840dd92b124SHariprasad Shenai 	case CPL_ERR_KEEPALV_NEG_ADVICE:
1841dd92b124SHariprasad Shenai 		return "Keepalive timeout";
1842dd92b124SHariprasad Shenai 	default:
1843dd92b124SHariprasad Shenai 		return "Unknown";
1844dd92b124SHariprasad Shenai 	}
1845dd92b124SHariprasad Shenai }
1846dd92b124SHariprasad Shenai 
1847b408ff28SHariprasad Shenai static void set_tcp_window(struct c4iw_ep *ep, struct port_info *pi)
1848b408ff28SHariprasad Shenai {
1849b408ff28SHariprasad Shenai 	ep->snd_win = snd_win;
1850b408ff28SHariprasad Shenai 	ep->rcv_win = rcv_win;
1851b408ff28SHariprasad Shenai 	PDBG("%s snd_win %d rcv_win %d\n", __func__, ep->snd_win, ep->rcv_win);
1852b408ff28SHariprasad Shenai }
1853b408ff28SHariprasad Shenai 
1854793dad94SVipul Pandya #define ACT_OPEN_RETRY_COUNT 2
1855793dad94SVipul Pandya 
1856830662f6SVipul Pandya static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip,
1857830662f6SVipul Pandya 		     struct dst_entry *dst, struct c4iw_dev *cdev,
1858830662f6SVipul Pandya 		     bool clear_mpa_v1)
1859830662f6SVipul Pandya {
1860830662f6SVipul Pandya 	struct neighbour *n;
1861830662f6SVipul Pandya 	int err, step;
1862830662f6SVipul Pandya 	struct net_device *pdev;
1863830662f6SVipul Pandya 
1864830662f6SVipul Pandya 	n = dst_neigh_lookup(dst, peer_ip);
1865830662f6SVipul Pandya 	if (!n)
1866830662f6SVipul Pandya 		return -ENODEV;
1867830662f6SVipul Pandya 
1868830662f6SVipul Pandya 	rcu_read_lock();
1869830662f6SVipul Pandya 	err = -ENOMEM;
1870830662f6SVipul Pandya 	if (n->dev->flags & IFF_LOOPBACK) {
1871830662f6SVipul Pandya 		if (iptype == 4)
1872830662f6SVipul Pandya 			pdev = ip_dev_find(&init_net, *(__be32 *)peer_ip);
1873830662f6SVipul Pandya 		else if (IS_ENABLED(CONFIG_IPV6))
1874830662f6SVipul Pandya 			for_each_netdev(&init_net, pdev) {
1875830662f6SVipul Pandya 				if (ipv6_chk_addr(&init_net,
1876830662f6SVipul Pandya 						  (struct in6_addr *)peer_ip,
1877830662f6SVipul Pandya 						  pdev, 1))
1878830662f6SVipul Pandya 					break;
1879830662f6SVipul Pandya 			}
1880830662f6SVipul Pandya 		else
1881830662f6SVipul Pandya 			pdev = NULL;
1882830662f6SVipul Pandya 
1883830662f6SVipul Pandya 		if (!pdev) {
1884830662f6SVipul Pandya 			err = -ENODEV;
1885830662f6SVipul Pandya 			goto out;
1886830662f6SVipul Pandya 		}
1887830662f6SVipul Pandya 		ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t,
1888830662f6SVipul Pandya 					n, pdev, 0);
1889830662f6SVipul Pandya 		if (!ep->l2t)
1890830662f6SVipul Pandya 			goto out;
1891830662f6SVipul Pandya 		ep->mtu = pdev->mtu;
1892830662f6SVipul Pandya 		ep->tx_chan = cxgb4_port_chan(pdev);
1893830662f6SVipul Pandya 		ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
1894830662f6SVipul Pandya 		step = cdev->rdev.lldi.ntxq /
1895830662f6SVipul Pandya 			cdev->rdev.lldi.nchan;
1896830662f6SVipul Pandya 		ep->txq_idx = cxgb4_port_idx(pdev) * step;
1897830662f6SVipul Pandya 		step = cdev->rdev.lldi.nrxq /
1898830662f6SVipul Pandya 			cdev->rdev.lldi.nchan;
1899830662f6SVipul Pandya 		ep->ctrlq_idx = cxgb4_port_idx(pdev);
1900830662f6SVipul Pandya 		ep->rss_qid = cdev->rdev.lldi.rxq_ids[
1901830662f6SVipul Pandya 			cxgb4_port_idx(pdev) * step];
1902b408ff28SHariprasad Shenai 		set_tcp_window(ep, (struct port_info *)netdev_priv(pdev));
1903830662f6SVipul Pandya 		dev_put(pdev);
1904830662f6SVipul Pandya 	} else {
1905830662f6SVipul Pandya 		pdev = get_real_dev(n->dev);
1906830662f6SVipul Pandya 		ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t,
1907830662f6SVipul Pandya 					n, pdev, 0);
1908830662f6SVipul Pandya 		if (!ep->l2t)
1909830662f6SVipul Pandya 			goto out;
1910830662f6SVipul Pandya 		ep->mtu = dst_mtu(dst);
191111b8e22dSSteve Wise 		ep->tx_chan = cxgb4_port_chan(pdev);
191211b8e22dSSteve Wise 		ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
1913830662f6SVipul Pandya 		step = cdev->rdev.lldi.ntxq /
1914830662f6SVipul Pandya 			cdev->rdev.lldi.nchan;
191511b8e22dSSteve Wise 		ep->txq_idx = cxgb4_port_idx(pdev) * step;
191611b8e22dSSteve Wise 		ep->ctrlq_idx = cxgb4_port_idx(pdev);
1917830662f6SVipul Pandya 		step = cdev->rdev.lldi.nrxq /
1918830662f6SVipul Pandya 			cdev->rdev.lldi.nchan;
1919830662f6SVipul Pandya 		ep->rss_qid = cdev->rdev.lldi.rxq_ids[
192011b8e22dSSteve Wise 			cxgb4_port_idx(pdev) * step];
1921b408ff28SHariprasad Shenai 		set_tcp_window(ep, (struct port_info *)netdev_priv(pdev));
1922830662f6SVipul Pandya 
1923830662f6SVipul Pandya 		if (clear_mpa_v1) {
1924830662f6SVipul Pandya 			ep->retry_with_mpa_v1 = 0;
1925830662f6SVipul Pandya 			ep->tried_with_mpa_v1 = 0;
1926830662f6SVipul Pandya 		}
1927830662f6SVipul Pandya 	}
1928830662f6SVipul Pandya 	err = 0;
1929830662f6SVipul Pandya out:
1930830662f6SVipul Pandya 	rcu_read_unlock();
1931830662f6SVipul Pandya 
1932830662f6SVipul Pandya 	neigh_release(n);
1933830662f6SVipul Pandya 
1934830662f6SVipul Pandya 	return err;
1935830662f6SVipul Pandya }
1936830662f6SVipul Pandya 
1937793dad94SVipul Pandya static int c4iw_reconnect(struct c4iw_ep *ep)
1938793dad94SVipul Pandya {
1939793dad94SVipul Pandya 	int err = 0;
194024d44a39SSteve Wise 	struct sockaddr_in *laddr = (struct sockaddr_in *)
194124d44a39SSteve Wise 				    &ep->com.cm_id->local_addr;
194224d44a39SSteve Wise 	struct sockaddr_in *raddr = (struct sockaddr_in *)
194324d44a39SSteve Wise 				    &ep->com.cm_id->remote_addr;
1944830662f6SVipul Pandya 	struct sockaddr_in6 *laddr6 = (struct sockaddr_in6 *)
1945830662f6SVipul Pandya 				      &ep->com.cm_id->local_addr;
1946830662f6SVipul Pandya 	struct sockaddr_in6 *raddr6 = (struct sockaddr_in6 *)
1947830662f6SVipul Pandya 				      &ep->com.cm_id->remote_addr;
1948830662f6SVipul Pandya 	int iptype;
1949830662f6SVipul Pandya 	__u8 *ra;
1950793dad94SVipul Pandya 
1951793dad94SVipul Pandya 	PDBG("%s qp %p cm_id %p\n", __func__, ep->com.qp, ep->com.cm_id);
1952793dad94SVipul Pandya 	init_timer(&ep->timer);
1953793dad94SVipul Pandya 
1954793dad94SVipul Pandya 	/*
1955793dad94SVipul Pandya 	 * Allocate an active TID to initiate a TCP connection.
1956793dad94SVipul Pandya 	 */
1957793dad94SVipul Pandya 	ep->atid = cxgb4_alloc_atid(ep->com.dev->rdev.lldi.tids, ep);
1958793dad94SVipul Pandya 	if (ep->atid == -1) {
1959793dad94SVipul Pandya 		pr_err("%s - cannot alloc atid.\n", __func__);
1960793dad94SVipul Pandya 		err = -ENOMEM;
1961793dad94SVipul Pandya 		goto fail2;
1962793dad94SVipul Pandya 	}
1963793dad94SVipul Pandya 	insert_handle(ep->com.dev, &ep->com.dev->atid_idr, ep, ep->atid);
1964793dad94SVipul Pandya 
1965793dad94SVipul Pandya 	/* find a route */
1966830662f6SVipul Pandya 	if (ep->com.cm_id->local_addr.ss_family == AF_INET) {
1967830662f6SVipul Pandya 		ep->dst = find_route(ep->com.dev, laddr->sin_addr.s_addr,
1968830662f6SVipul Pandya 				     raddr->sin_addr.s_addr, laddr->sin_port,
1969830662f6SVipul Pandya 				     raddr->sin_port, 0);
1970830662f6SVipul Pandya 		iptype = 4;
1971830662f6SVipul Pandya 		ra = (__u8 *)&raddr->sin_addr;
1972830662f6SVipul Pandya 	} else {
1973830662f6SVipul Pandya 		ep->dst = find_route6(ep->com.dev, laddr6->sin6_addr.s6_addr,
1974830662f6SVipul Pandya 				      raddr6->sin6_addr.s6_addr,
1975830662f6SVipul Pandya 				      laddr6->sin6_port, raddr6->sin6_port, 0,
1976830662f6SVipul Pandya 				      raddr6->sin6_scope_id);
1977830662f6SVipul Pandya 		iptype = 6;
1978830662f6SVipul Pandya 		ra = (__u8 *)&raddr6->sin6_addr;
1979830662f6SVipul Pandya 	}
1980830662f6SVipul Pandya 	if (!ep->dst) {
1981793dad94SVipul Pandya 		pr_err("%s - cannot find route.\n", __func__);
1982793dad94SVipul Pandya 		err = -EHOSTUNREACH;
1983793dad94SVipul Pandya 		goto fail3;
1984793dad94SVipul Pandya 	}
1985830662f6SVipul Pandya 	err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, false);
1986830662f6SVipul Pandya 	if (err) {
1987793dad94SVipul Pandya 		pr_err("%s - cannot alloc l2e.\n", __func__);
1988793dad94SVipul Pandya 		goto fail4;
1989793dad94SVipul Pandya 	}
1990793dad94SVipul Pandya 
1991793dad94SVipul Pandya 	PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n",
1992793dad94SVipul Pandya 	     __func__, ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid,
1993793dad94SVipul Pandya 	     ep->l2t->idx);
1994793dad94SVipul Pandya 
1995793dad94SVipul Pandya 	state_set(&ep->com, CONNECTING);
1996793dad94SVipul Pandya 	ep->tos = 0;
1997793dad94SVipul Pandya 
1998793dad94SVipul Pandya 	/* send connect request to rnic */
1999793dad94SVipul Pandya 	err = send_connect(ep);
2000793dad94SVipul Pandya 	if (!err)
2001793dad94SVipul Pandya 		goto out;
2002793dad94SVipul Pandya 
2003793dad94SVipul Pandya 	cxgb4_l2t_release(ep->l2t);
2004793dad94SVipul Pandya fail4:
2005793dad94SVipul Pandya 	dst_release(ep->dst);
2006793dad94SVipul Pandya fail3:
2007793dad94SVipul Pandya 	remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid);
2008793dad94SVipul Pandya 	cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid);
2009793dad94SVipul Pandya fail2:
2010793dad94SVipul Pandya 	/*
2011793dad94SVipul Pandya 	 * remember to send notification to upper layer.
2012793dad94SVipul Pandya 	 * We are in here so the upper layer is not aware that this is
2013793dad94SVipul Pandya 	 * re-connect attempt and so, upper layer is still waiting for
2014793dad94SVipul Pandya 	 * response of 1st connect request.
2015793dad94SVipul Pandya 	 */
2016793dad94SVipul Pandya 	connect_reply_upcall(ep, -ECONNRESET);
2017793dad94SVipul Pandya 	c4iw_put_ep(&ep->com);
2018793dad94SVipul Pandya out:
2019793dad94SVipul Pandya 	return err;
2020793dad94SVipul Pandya }
2021793dad94SVipul Pandya 
2022cfdda9d7SSteve Wise static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
2023cfdda9d7SSteve Wise {
2024cfdda9d7SSteve Wise 	struct c4iw_ep *ep;
2025cfdda9d7SSteve Wise 	struct cpl_act_open_rpl *rpl = cplhdr(skb);
20266c53e938SHariprasad Shenai 	unsigned int atid = TID_TID_G(AOPEN_ATID_G(
2027cfdda9d7SSteve Wise 				      ntohl(rpl->atid_status)));
2028cfdda9d7SSteve Wise 	struct tid_info *t = dev->rdev.lldi.tids;
20296c53e938SHariprasad Shenai 	int status = AOPEN_STATUS_G(ntohl(rpl->atid_status));
2030830662f6SVipul Pandya 	struct sockaddr_in *la;
2031830662f6SVipul Pandya 	struct sockaddr_in *ra;
2032830662f6SVipul Pandya 	struct sockaddr_in6 *la6;
2033830662f6SVipul Pandya 	struct sockaddr_in6 *ra6;
2034cfdda9d7SSteve Wise 
2035cfdda9d7SSteve Wise 	ep = lookup_atid(t, atid);
20369eccfe10SSteve Wise 	la = (struct sockaddr_in *)&ep->com.mapped_local_addr;
20379eccfe10SSteve Wise 	ra = (struct sockaddr_in *)&ep->com.mapped_remote_addr;
20389eccfe10SSteve Wise 	la6 = (struct sockaddr_in6 *)&ep->com.mapped_local_addr;
20399eccfe10SSteve Wise 	ra6 = (struct sockaddr_in6 *)&ep->com.mapped_remote_addr;
2040cfdda9d7SSteve Wise 
2041cfdda9d7SSteve Wise 	PDBG("%s ep %p atid %u status %u errno %d\n", __func__, ep, atid,
2042cfdda9d7SSteve Wise 	     status, status2errno(status));
2043cfdda9d7SSteve Wise 
20447a2cea2aSSteve Wise 	if (is_neg_adv(status)) {
2045dd92b124SHariprasad Shenai 		dev_warn(&dev->rdev.lldi.pdev->dev,
2046dd92b124SHariprasad Shenai 			 "Connection problems for atid %u status %u (%s)\n",
2047dd92b124SHariprasad Shenai 			 atid, status, neg_adv_str(status));
2048cfdda9d7SSteve Wise 		return 0;
2049cfdda9d7SSteve Wise 	}
2050cfdda9d7SSteve Wise 
2051793dad94SVipul Pandya 	set_bit(ACT_OPEN_RPL, &ep->com.history);
2052793dad94SVipul Pandya 
2053d716a2a0SVipul Pandya 	/*
2054d716a2a0SVipul Pandya 	 * Log interesting failures.
2055d716a2a0SVipul Pandya 	 */
2056d716a2a0SVipul Pandya 	switch (status) {
2057d716a2a0SVipul Pandya 	case CPL_ERR_CONN_RESET:
2058d716a2a0SVipul Pandya 	case CPL_ERR_CONN_TIMEDOUT:
2059d716a2a0SVipul Pandya 		break;
20605be78ee9SVipul Pandya 	case CPL_ERR_TCAM_FULL:
20615be78ee9SVipul Pandya 		mutex_lock(&dev->rdev.stats.lock);
2062830662f6SVipul Pandya 		dev->rdev.stats.tcam_full++;
20635be78ee9SVipul Pandya 		mutex_unlock(&dev->rdev.stats.lock);
2064830662f6SVipul Pandya 		if (ep->com.local_addr.ss_family == AF_INET &&
2065830662f6SVipul Pandya 		    dev->rdev.lldi.enable_fw_ofld_conn) {
20665be78ee9SVipul Pandya 			send_fw_act_open_req(ep,
20676c53e938SHariprasad Shenai 					     TID_TID_G(AOPEN_ATID_G(
2068793dad94SVipul Pandya 					     ntohl(rpl->atid_status))));
20695be78ee9SVipul Pandya 			return 0;
2070793dad94SVipul Pandya 		}
2071793dad94SVipul Pandya 		break;
2072793dad94SVipul Pandya 	case CPL_ERR_CONN_EXIST:
2073793dad94SVipul Pandya 		if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) {
2074793dad94SVipul Pandya 			set_bit(ACT_RETRY_INUSE, &ep->com.history);
2075793dad94SVipul Pandya 			remove_handle(ep->com.dev, &ep->com.dev->atid_idr,
2076793dad94SVipul Pandya 					atid);
2077793dad94SVipul Pandya 			cxgb4_free_atid(t, atid);
2078793dad94SVipul Pandya 			dst_release(ep->dst);
2079793dad94SVipul Pandya 			cxgb4_l2t_release(ep->l2t);
2080793dad94SVipul Pandya 			c4iw_reconnect(ep);
2081793dad94SVipul Pandya 			return 0;
2082793dad94SVipul Pandya 		}
20835be78ee9SVipul Pandya 		break;
2084d716a2a0SVipul Pandya 	default:
2085830662f6SVipul Pandya 		if (ep->com.local_addr.ss_family == AF_INET) {
2086830662f6SVipul Pandya 			pr_info("Active open failure - atid %u status %u errno %d %pI4:%u->%pI4:%u\n",
2087d716a2a0SVipul Pandya 				atid, status, status2errno(status),
2088830662f6SVipul Pandya 				&la->sin_addr.s_addr, ntohs(la->sin_port),
2089830662f6SVipul Pandya 				&ra->sin_addr.s_addr, ntohs(ra->sin_port));
2090830662f6SVipul Pandya 		} else {
2091830662f6SVipul Pandya 			pr_info("Active open failure - atid %u status %u errno %d %pI6:%u->%pI6:%u\n",
2092830662f6SVipul Pandya 				atid, status, status2errno(status),
2093830662f6SVipul Pandya 				la6->sin6_addr.s6_addr, ntohs(la6->sin6_port),
2094830662f6SVipul Pandya 				ra6->sin6_addr.s6_addr, ntohs(ra6->sin6_port));
2095830662f6SVipul Pandya 		}
2096d716a2a0SVipul Pandya 		break;
2097d716a2a0SVipul Pandya 	}
2098d716a2a0SVipul Pandya 
2099cfdda9d7SSteve Wise 	connect_reply_upcall(ep, status2errno(status));
2100cfdda9d7SSteve Wise 	state_set(&ep->com, DEAD);
2101cfdda9d7SSteve Wise 
2102cfdda9d7SSteve Wise 	if (status && act_open_has_tid(status))
2103cfdda9d7SSteve Wise 		cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, GET_TID(rpl));
2104cfdda9d7SSteve Wise 
2105793dad94SVipul Pandya 	remove_handle(ep->com.dev, &ep->com.dev->atid_idr, atid);
2106cfdda9d7SSteve Wise 	cxgb4_free_atid(t, atid);
2107cfdda9d7SSteve Wise 	dst_release(ep->dst);
2108cfdda9d7SSteve Wise 	cxgb4_l2t_release(ep->l2t);
2109cfdda9d7SSteve Wise 	c4iw_put_ep(&ep->com);
2110cfdda9d7SSteve Wise 
2111cfdda9d7SSteve Wise 	return 0;
2112cfdda9d7SSteve Wise }
2113cfdda9d7SSteve Wise 
2114cfdda9d7SSteve Wise static int pass_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
2115cfdda9d7SSteve Wise {
2116cfdda9d7SSteve Wise 	struct cpl_pass_open_rpl *rpl = cplhdr(skb);
2117cfdda9d7SSteve Wise 	struct tid_info *t = dev->rdev.lldi.tids;
2118cfdda9d7SSteve Wise 	unsigned int stid = GET_TID(rpl);
2119cfdda9d7SSteve Wise 	struct c4iw_listen_ep *ep = lookup_stid(t, stid);
2120cfdda9d7SSteve Wise 
2121cfdda9d7SSteve Wise 	if (!ep) {
21221cab775cSVipul Pandya 		PDBG("%s stid %d lookup failure!\n", __func__, stid);
21231cab775cSVipul Pandya 		goto out;
2124cfdda9d7SSteve Wise 	}
2125cfdda9d7SSteve Wise 	PDBG("%s ep %p status %d error %d\n", __func__, ep,
2126cfdda9d7SSteve Wise 	     rpl->status, status2errno(rpl->status));
2127d9594d99SSteve Wise 	c4iw_wake_up(&ep->com.wr_wait, status2errno(rpl->status));
2128cfdda9d7SSteve Wise 
21291cab775cSVipul Pandya out:
2130cfdda9d7SSteve Wise 	return 0;
2131cfdda9d7SSteve Wise }
2132cfdda9d7SSteve Wise 
2133cfdda9d7SSteve Wise static int close_listsrv_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
2134cfdda9d7SSteve Wise {
2135cfdda9d7SSteve Wise 	struct cpl_close_listsvr_rpl *rpl = cplhdr(skb);
2136cfdda9d7SSteve Wise 	struct tid_info *t = dev->rdev.lldi.tids;
2137cfdda9d7SSteve Wise 	unsigned int stid = GET_TID(rpl);
2138cfdda9d7SSteve Wise 	struct c4iw_listen_ep *ep = lookup_stid(t, stid);
2139cfdda9d7SSteve Wise 
2140cfdda9d7SSteve Wise 	PDBG("%s ep %p\n", __func__, ep);
2141d9594d99SSteve Wise 	c4iw_wake_up(&ep->com.wr_wait, status2errno(rpl->status));
2142cfdda9d7SSteve Wise 	return 0;
2143cfdda9d7SSteve Wise }
2144cfdda9d7SSteve Wise 
2145830662f6SVipul Pandya static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb,
2146cfdda9d7SSteve Wise 		      struct cpl_pass_accept_req *req)
2147cfdda9d7SSteve Wise {
2148cfdda9d7SSteve Wise 	struct cpl_pass_accept_rpl *rpl;
2149cfdda9d7SSteve Wise 	unsigned int mtu_idx;
2150cfdda9d7SSteve Wise 	u64 opt0;
2151cfdda9d7SSteve Wise 	u32 opt2;
2152cfdda9d7SSteve Wise 	int wscale;
215392e7ae71SHariprasad Shenai 	struct cpl_t5_pass_accept_rpl *rpl5 = NULL;
2154b408ff28SHariprasad Shenai 	int win;
2155cfdda9d7SSteve Wise 
2156cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
2157cfdda9d7SSteve Wise 	BUG_ON(skb_cloned(skb));
215892e7ae71SHariprasad Shenai 
2159cfdda9d7SSteve Wise 	skb_get(skb);
216092e7ae71SHariprasad Shenai 	rpl = cplhdr(skb);
216192e7ae71SHariprasad Shenai 	if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) {
216292e7ae71SHariprasad Shenai 		skb_trim(skb, roundup(sizeof(*rpl5), 16));
216392e7ae71SHariprasad Shenai 		rpl5 = (void *)rpl;
216492e7ae71SHariprasad Shenai 		INIT_TP_WR(rpl5, ep->hwtid);
216592e7ae71SHariprasad Shenai 	} else {
216692e7ae71SHariprasad Shenai 		skb_trim(skb, sizeof(*rpl));
216792e7ae71SHariprasad Shenai 		INIT_TP_WR(rpl, ep->hwtid);
216892e7ae71SHariprasad Shenai 	}
216992e7ae71SHariprasad Shenai 	OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_PASS_ACCEPT_RPL,
217092e7ae71SHariprasad Shenai 						    ep->hwtid));
217192e7ae71SHariprasad Shenai 
217292e7ae71SHariprasad Shenai 	best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx,
217304524a47SHariprasad S 		 enable_tcp_timestamps && req->tcpopt.tstamp,
217404524a47SHariprasad S 		 (AF_INET == ep->com.remote_addr.ss_family) ? 0 : 1);
2175cfdda9d7SSteve Wise 	wscale = compute_wscale(rcv_win);
2176b408ff28SHariprasad Shenai 
2177b408ff28SHariprasad Shenai 	/*
2178b408ff28SHariprasad Shenai 	 * Specify the largest window that will fit in opt0. The
2179b408ff28SHariprasad Shenai 	 * remainder will be specified in the rx_data_ack.
2180b408ff28SHariprasad Shenai 	 */
2181b408ff28SHariprasad Shenai 	win = ep->rcv_win >> 10;
2182d7990b0cSAnish Bhatt 	if (win > RCV_BUFSIZ_M)
2183d7990b0cSAnish Bhatt 		win = RCV_BUFSIZ_M;
21846c53e938SHariprasad Shenai 	opt0 = (nocong ? NO_CONG_F : 0) |
2185d7990b0cSAnish Bhatt 	       KEEP_ALIVE_F |
21866c53e938SHariprasad Shenai 	       DELACK_F |
2187d7990b0cSAnish Bhatt 	       WND_SCALE_V(wscale) |
2188d7990b0cSAnish Bhatt 	       MSS_IDX_V(mtu_idx) |
2189d7990b0cSAnish Bhatt 	       L2T_IDX_V(ep->l2t->idx) |
2190d7990b0cSAnish Bhatt 	       TX_CHAN_V(ep->tx_chan) |
2191d7990b0cSAnish Bhatt 	       SMAC_SEL_V(ep->smac_idx) |
21926c53e938SHariprasad Shenai 	       DSCP_V(ep->tos >> 2) |
2193d7990b0cSAnish Bhatt 	       ULP_MODE_V(ULP_MODE_TCPDDP) |
2194d7990b0cSAnish Bhatt 	       RCV_BUFSIZ_V(win);
2195d7990b0cSAnish Bhatt 	opt2 = RX_CHANNEL_V(0) |
2196d7990b0cSAnish Bhatt 	       RSS_QUEUE_VALID_F | RSS_QUEUE_V(ep->rss_qid);
2197cfdda9d7SSteve Wise 
2198cfdda9d7SSteve Wise 	if (enable_tcp_timestamps && req->tcpopt.tstamp)
21996c53e938SHariprasad Shenai 		opt2 |= TSTAMPS_EN_F;
2200cfdda9d7SSteve Wise 	if (enable_tcp_sack && req->tcpopt.sack)
22016c53e938SHariprasad Shenai 		opt2 |= SACK_EN_F;
2202cfdda9d7SSteve Wise 	if (wscale && enable_tcp_window_scaling)
2203d7990b0cSAnish Bhatt 		opt2 |= WND_SCALE_EN_F;
22045be78ee9SVipul Pandya 	if (enable_ecn) {
22055be78ee9SVipul Pandya 		const struct tcphdr *tcph;
22065be78ee9SVipul Pandya 		u32 hlen = ntohl(req->hdr_len);
22075be78ee9SVipul Pandya 
22085be78ee9SVipul Pandya 		tcph = (const void *)(req + 1) + G_ETH_HDR_LEN(hlen) +
22095be78ee9SVipul Pandya 			G_IP_HDR_LEN(hlen);
22105be78ee9SVipul Pandya 		if (tcph->ece && tcph->cwr)
22116c53e938SHariprasad Shenai 			opt2 |= CCTRL_ECN_V(1);
22125be78ee9SVipul Pandya 	}
221392e5011aSSteve Wise 	if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) {
221492e7ae71SHariprasad Shenai 		u32 isn = (prandom_u32() & ~7UL) - 1;
2215d7990b0cSAnish Bhatt 		opt2 |= T5_OPT_2_VALID_F;
221692e5011aSSteve Wise 		opt2 |= V_CONG_CNTRL(CONG_ALG_TAHOE);
221792e7ae71SHariprasad Shenai 		opt2 |= CONG_CNTRL_VALID; /* OPT_2_ISS for T5 */
221892e7ae71SHariprasad Shenai 		rpl5 = (void *)rpl;
221992e7ae71SHariprasad Shenai 		memset(&rpl5->iss, 0, roundup(sizeof(*rpl5)-sizeof(*rpl), 16));
222092e7ae71SHariprasad Shenai 		if (peer2peer)
222192e7ae71SHariprasad Shenai 			isn += 4;
222292e7ae71SHariprasad Shenai 		rpl5->iss = cpu_to_be32(isn);
222392e7ae71SHariprasad Shenai 		PDBG("%s iss %u\n", __func__, be32_to_cpu(rpl5->iss));
222492e5011aSSteve Wise 	}
2225cfdda9d7SSteve Wise 
2226cfdda9d7SSteve Wise 	rpl->opt0 = cpu_to_be64(opt0);
2227cfdda9d7SSteve Wise 	rpl->opt2 = cpu_to_be32(opt2);
2228d4f1a5c6SSteve Wise 	set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->ctrlq_idx);
2229b38a0ad8SSteve Wise 	t4_set_arp_err_handler(skb, NULL, arp_failure_discard);
2230cfdda9d7SSteve Wise 	c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
2231cfdda9d7SSteve Wise 
2232cfdda9d7SSteve Wise 	return;
2233cfdda9d7SSteve Wise }
2234cfdda9d7SSteve Wise 
2235830662f6SVipul Pandya static void reject_cr(struct c4iw_dev *dev, u32 hwtid, struct sk_buff *skb)
2236cfdda9d7SSteve Wise {
2237830662f6SVipul Pandya 	PDBG("%s c4iw_dev %p tid %u\n", __func__, dev, hwtid);
2238cfdda9d7SSteve Wise 	BUG_ON(skb_cloned(skb));
2239cfdda9d7SSteve Wise 	skb_trim(skb, sizeof(struct cpl_tid_release));
2240cfdda9d7SSteve Wise 	release_tid(&dev->rdev, hwtid, skb);
2241cfdda9d7SSteve Wise 	return;
2242cfdda9d7SSteve Wise }
2243cfdda9d7SSteve Wise 
2244830662f6SVipul Pandya static void get_4tuple(struct cpl_pass_accept_req *req, int *iptype,
2245830662f6SVipul Pandya 		       __u8 *local_ip, __u8 *peer_ip,
2246cfdda9d7SSteve Wise 		       __be16 *local_port, __be16 *peer_port)
2247cfdda9d7SSteve Wise {
2248cfdda9d7SSteve Wise 	int eth_len = G_ETH_HDR_LEN(be32_to_cpu(req->hdr_len));
2249cfdda9d7SSteve Wise 	int ip_len = G_IP_HDR_LEN(be32_to_cpu(req->hdr_len));
2250cfdda9d7SSteve Wise 	struct iphdr *ip = (struct iphdr *)((u8 *)(req + 1) + eth_len);
2251830662f6SVipul Pandya 	struct ipv6hdr *ip6 = (struct ipv6hdr *)((u8 *)(req + 1) + eth_len);
2252cfdda9d7SSteve Wise 	struct tcphdr *tcp = (struct tcphdr *)
2253cfdda9d7SSteve Wise 			     ((u8 *)(req + 1) + eth_len + ip_len);
2254cfdda9d7SSteve Wise 
2255830662f6SVipul Pandya 	if (ip->version == 4) {
2256cfdda9d7SSteve Wise 		PDBG("%s saddr 0x%x daddr 0x%x sport %u dport %u\n", __func__,
2257cfdda9d7SSteve Wise 		     ntohl(ip->saddr), ntohl(ip->daddr), ntohs(tcp->source),
2258cfdda9d7SSteve Wise 		     ntohs(tcp->dest));
2259830662f6SVipul Pandya 		*iptype = 4;
2260830662f6SVipul Pandya 		memcpy(peer_ip, &ip->saddr, 4);
2261830662f6SVipul Pandya 		memcpy(local_ip, &ip->daddr, 4);
2262830662f6SVipul Pandya 	} else {
2263830662f6SVipul Pandya 		PDBG("%s saddr %pI6 daddr %pI6 sport %u dport %u\n", __func__,
2264830662f6SVipul Pandya 		     ip6->saddr.s6_addr, ip6->daddr.s6_addr, ntohs(tcp->source),
2265830662f6SVipul Pandya 		     ntohs(tcp->dest));
2266830662f6SVipul Pandya 		*iptype = 6;
2267830662f6SVipul Pandya 		memcpy(peer_ip, ip6->saddr.s6_addr, 16);
2268830662f6SVipul Pandya 		memcpy(local_ip, ip6->daddr.s6_addr, 16);
2269830662f6SVipul Pandya 	}
2270cfdda9d7SSteve Wise 	*peer_port = tcp->source;
2271cfdda9d7SSteve Wise 	*local_port = tcp->dest;
2272cfdda9d7SSteve Wise 
2273cfdda9d7SSteve Wise 	return;
2274cfdda9d7SSteve Wise }
2275cfdda9d7SSteve Wise 
2276cfdda9d7SSteve Wise static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
2277cfdda9d7SSteve Wise {
2278793dad94SVipul Pandya 	struct c4iw_ep *child_ep = NULL, *parent_ep;
2279cfdda9d7SSteve Wise 	struct cpl_pass_accept_req *req = cplhdr(skb);
22806c53e938SHariprasad Shenai 	unsigned int stid = PASS_OPEN_TID_G(ntohl(req->tos_stid));
2281cfdda9d7SSteve Wise 	struct tid_info *t = dev->rdev.lldi.tids;
2282cfdda9d7SSteve Wise 	unsigned int hwtid = GET_TID(req);
2283cfdda9d7SSteve Wise 	struct dst_entry *dst;
2284830662f6SVipul Pandya 	__u8 local_ip[16], peer_ip[16];
2285cfdda9d7SSteve Wise 	__be16 local_port, peer_port;
22863786cf18SDavid Miller 	int err;
22871cab775cSVipul Pandya 	u16 peer_mss = ntohs(req->tcpopt.mss);
2288830662f6SVipul Pandya 	int iptype;
228992e7ae71SHariprasad Shenai 	unsigned short hdrs;
2290cfdda9d7SSteve Wise 
2291cfdda9d7SSteve Wise 	parent_ep = lookup_stid(t, stid);
22921cab775cSVipul Pandya 	if (!parent_ep) {
22931cab775cSVipul Pandya 		PDBG("%s connect request on invalid stid %d\n", __func__, stid);
22941cab775cSVipul Pandya 		goto reject;
22951cab775cSVipul Pandya 	}
22961cab775cSVipul Pandya 
2297cfdda9d7SSteve Wise 	if (state_read(&parent_ep->com) != LISTEN) {
2298cfdda9d7SSteve Wise 		printk(KERN_ERR "%s - listening ep not in LISTEN\n",
2299cfdda9d7SSteve Wise 		       __func__);
2300cfdda9d7SSteve Wise 		goto reject;
2301cfdda9d7SSteve Wise 	}
2302cfdda9d7SSteve Wise 
2303830662f6SVipul Pandya 	get_4tuple(req, &iptype, local_ip, peer_ip, &local_port, &peer_port);
2304830662f6SVipul Pandya 
2305cfdda9d7SSteve Wise 	/* Find output route */
2306830662f6SVipul Pandya 	if (iptype == 4)  {
2307830662f6SVipul Pandya 		PDBG("%s parent ep %p hwtid %u laddr %pI4 raddr %pI4 lport %d rport %d peer_mss %d\n"
2308830662f6SVipul Pandya 		     , __func__, parent_ep, hwtid,
2309830662f6SVipul Pandya 		     local_ip, peer_ip, ntohs(local_port),
2310830662f6SVipul Pandya 		     ntohs(peer_port), peer_mss);
2311830662f6SVipul Pandya 		dst = find_route(dev, *(__be32 *)local_ip, *(__be32 *)peer_ip,
2312830662f6SVipul Pandya 				 local_port, peer_port,
23136c53e938SHariprasad Shenai 				 PASS_OPEN_TOS_G(ntohl(req->tos_stid)));
2314830662f6SVipul Pandya 	} else {
2315830662f6SVipul Pandya 		PDBG("%s parent ep %p hwtid %u laddr %pI6 raddr %pI6 lport %d rport %d peer_mss %d\n"
2316830662f6SVipul Pandya 		     , __func__, parent_ep, hwtid,
2317830662f6SVipul Pandya 		     local_ip, peer_ip, ntohs(local_port),
2318830662f6SVipul Pandya 		     ntohs(peer_port), peer_mss);
2319830662f6SVipul Pandya 		dst = find_route6(dev, local_ip, peer_ip, local_port, peer_port,
23206c53e938SHariprasad Shenai 				  PASS_OPEN_TOS_G(ntohl(req->tos_stid)),
2321830662f6SVipul Pandya 				  ((struct sockaddr_in6 *)
2322830662f6SVipul Pandya 				  &parent_ep->com.local_addr)->sin6_scope_id);
2323830662f6SVipul Pandya 	}
2324830662f6SVipul Pandya 	if (!dst) {
2325cfdda9d7SSteve Wise 		printk(KERN_ERR MOD "%s - failed to find dst entry!\n",
2326cfdda9d7SSteve Wise 		       __func__);
2327cfdda9d7SSteve Wise 		goto reject;
2328cfdda9d7SSteve Wise 	}
2329cfdda9d7SSteve Wise 
2330cfdda9d7SSteve Wise 	child_ep = alloc_ep(sizeof(*child_ep), GFP_KERNEL);
2331cfdda9d7SSteve Wise 	if (!child_ep) {
2332cfdda9d7SSteve Wise 		printk(KERN_ERR MOD "%s - failed to allocate ep entry!\n",
2333cfdda9d7SSteve Wise 		       __func__);
2334cfdda9d7SSteve Wise 		dst_release(dst);
2335cfdda9d7SSteve Wise 		goto reject;
2336cfdda9d7SSteve Wise 	}
23373786cf18SDavid Miller 
2338830662f6SVipul Pandya 	err = import_ep(child_ep, iptype, peer_ip, dst, dev, false);
23393786cf18SDavid Miller 	if (err) {
23403786cf18SDavid Miller 		printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
23413786cf18SDavid Miller 		       __func__);
23423786cf18SDavid Miller 		dst_release(dst);
23433786cf18SDavid Miller 		kfree(child_ep);
23443786cf18SDavid Miller 		goto reject;
23453786cf18SDavid Miller 	}
23463786cf18SDavid Miller 
234792e7ae71SHariprasad Shenai 	hdrs = sizeof(struct iphdr) + sizeof(struct tcphdr) +
234892e7ae71SHariprasad Shenai 	       ((enable_tcp_timestamps && req->tcpopt.tstamp) ? 12 : 0);
234992e7ae71SHariprasad Shenai 	if (peer_mss && child_ep->mtu > (peer_mss + hdrs))
235092e7ae71SHariprasad Shenai 		child_ep->mtu = peer_mss + hdrs;
23511cab775cSVipul Pandya 
2352cfdda9d7SSteve Wise 	state_set(&child_ep->com, CONNECTING);
2353cfdda9d7SSteve Wise 	child_ep->com.dev = dev;
2354cfdda9d7SSteve Wise 	child_ep->com.cm_id = NULL;
2355830662f6SVipul Pandya 	if (iptype == 4) {
2356830662f6SVipul Pandya 		struct sockaddr_in *sin = (struct sockaddr_in *)
2357830662f6SVipul Pandya 			&child_ep->com.local_addr;
2358830662f6SVipul Pandya 		sin->sin_family = PF_INET;
2359830662f6SVipul Pandya 		sin->sin_port = local_port;
2360830662f6SVipul Pandya 		sin->sin_addr.s_addr = *(__be32 *)local_ip;
2361830662f6SVipul Pandya 		sin = (struct sockaddr_in *)&child_ep->com.remote_addr;
2362830662f6SVipul Pandya 		sin->sin_family = PF_INET;
2363830662f6SVipul Pandya 		sin->sin_port = peer_port;
2364830662f6SVipul Pandya 		sin->sin_addr.s_addr = *(__be32 *)peer_ip;
2365830662f6SVipul Pandya 	} else {
2366830662f6SVipul Pandya 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)
2367830662f6SVipul Pandya 			&child_ep->com.local_addr;
2368830662f6SVipul Pandya 		sin6->sin6_family = PF_INET6;
2369830662f6SVipul Pandya 		sin6->sin6_port = local_port;
2370830662f6SVipul Pandya 		memcpy(sin6->sin6_addr.s6_addr, local_ip, 16);
2371830662f6SVipul Pandya 		sin6 = (struct sockaddr_in6 *)&child_ep->com.remote_addr;
2372830662f6SVipul Pandya 		sin6->sin6_family = PF_INET6;
2373830662f6SVipul Pandya 		sin6->sin6_port = peer_port;
2374830662f6SVipul Pandya 		memcpy(sin6->sin6_addr.s6_addr, peer_ip, 16);
2375830662f6SVipul Pandya 	}
2376cfdda9d7SSteve Wise 	c4iw_get_ep(&parent_ep->com);
2377cfdda9d7SSteve Wise 	child_ep->parent_ep = parent_ep;
23786c53e938SHariprasad Shenai 	child_ep->tos = PASS_OPEN_TOS_G(ntohl(req->tos_stid));
2379cfdda9d7SSteve Wise 	child_ep->dst = dst;
2380cfdda9d7SSteve Wise 	child_ep->hwtid = hwtid;
2381cfdda9d7SSteve Wise 
2382cfdda9d7SSteve Wise 	PDBG("%s tx_chan %u smac_idx %u rss_qid %u\n", __func__,
23833786cf18SDavid Miller 	     child_ep->tx_chan, child_ep->smac_idx, child_ep->rss_qid);
2384cfdda9d7SSteve Wise 
2385cfdda9d7SSteve Wise 	init_timer(&child_ep->timer);
2386cfdda9d7SSteve Wise 	cxgb4_insert_tid(t, child_ep, hwtid);
2387b3de6cfeSVipul Pandya 	insert_handle(dev, &dev->hwtid_idr, child_ep, child_ep->hwtid);
2388830662f6SVipul Pandya 	accept_cr(child_ep, skb, req);
2389793dad94SVipul Pandya 	set_bit(PASS_ACCEPT_REQ, &child_ep->com.history);
2390cfdda9d7SSteve Wise 	goto out;
2391cfdda9d7SSteve Wise reject:
2392830662f6SVipul Pandya 	reject_cr(dev, hwtid, skb);
2393cfdda9d7SSteve Wise out:
2394cfdda9d7SSteve Wise 	return 0;
2395cfdda9d7SSteve Wise }
2396cfdda9d7SSteve Wise 
2397cfdda9d7SSteve Wise static int pass_establish(struct c4iw_dev *dev, struct sk_buff *skb)
2398cfdda9d7SSteve Wise {
2399cfdda9d7SSteve Wise 	struct c4iw_ep *ep;
2400cfdda9d7SSteve Wise 	struct cpl_pass_establish *req = cplhdr(skb);
2401cfdda9d7SSteve Wise 	struct tid_info *t = dev->rdev.lldi.tids;
2402cfdda9d7SSteve Wise 	unsigned int tid = GET_TID(req);
2403cfdda9d7SSteve Wise 
2404cfdda9d7SSteve Wise 	ep = lookup_tid(t, tid);
2405cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
2406cfdda9d7SSteve Wise 	ep->snd_seq = be32_to_cpu(req->snd_isn);
2407cfdda9d7SSteve Wise 	ep->rcv_seq = be32_to_cpu(req->rcv_isn);
2408cfdda9d7SSteve Wise 
24091cab775cSVipul Pandya 	PDBG("%s ep %p hwtid %u tcp_opt 0x%02x\n", __func__, ep, tid,
24101cab775cSVipul Pandya 	     ntohs(req->tcp_opt));
24111cab775cSVipul Pandya 
2412cfdda9d7SSteve Wise 	set_emss(ep, ntohs(req->tcp_opt));
2413cfdda9d7SSteve Wise 
2414cfdda9d7SSteve Wise 	dst_confirm(ep->dst);
2415cfdda9d7SSteve Wise 	state_set(&ep->com, MPA_REQ_WAIT);
2416cfdda9d7SSteve Wise 	start_ep_timer(ep);
2417cfdda9d7SSteve Wise 	send_flowc(ep, skb);
2418793dad94SVipul Pandya 	set_bit(PASS_ESTAB, &ep->com.history);
2419cfdda9d7SSteve Wise 
2420cfdda9d7SSteve Wise 	return 0;
2421cfdda9d7SSteve Wise }
2422cfdda9d7SSteve Wise 
2423cfdda9d7SSteve Wise static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
2424cfdda9d7SSteve Wise {
2425cfdda9d7SSteve Wise 	struct cpl_peer_close *hdr = cplhdr(skb);
2426cfdda9d7SSteve Wise 	struct c4iw_ep *ep;
2427cfdda9d7SSteve Wise 	struct c4iw_qp_attributes attrs;
2428cfdda9d7SSteve Wise 	int disconnect = 1;
2429cfdda9d7SSteve Wise 	int release = 0;
2430cfdda9d7SSteve Wise 	struct tid_info *t = dev->rdev.lldi.tids;
2431cfdda9d7SSteve Wise 	unsigned int tid = GET_TID(hdr);
24328da7e7a5SSteve Wise 	int ret;
2433cfdda9d7SSteve Wise 
2434cfdda9d7SSteve Wise 	ep = lookup_tid(t, tid);
2435cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
2436cfdda9d7SSteve Wise 	dst_confirm(ep->dst);
2437cfdda9d7SSteve Wise 
2438793dad94SVipul Pandya 	set_bit(PEER_CLOSE, &ep->com.history);
24392f5b48c3SSteve Wise 	mutex_lock(&ep->com.mutex);
2440cfdda9d7SSteve Wise 	switch (ep->com.state) {
2441cfdda9d7SSteve Wise 	case MPA_REQ_WAIT:
2442cfdda9d7SSteve Wise 		__state_set(&ep->com, CLOSING);
2443cfdda9d7SSteve Wise 		break;
2444cfdda9d7SSteve Wise 	case MPA_REQ_SENT:
2445cfdda9d7SSteve Wise 		__state_set(&ep->com, CLOSING);
2446cfdda9d7SSteve Wise 		connect_reply_upcall(ep, -ECONNRESET);
2447cfdda9d7SSteve Wise 		break;
2448cfdda9d7SSteve Wise 	case MPA_REQ_RCVD:
2449cfdda9d7SSteve Wise 
2450cfdda9d7SSteve Wise 		/*
2451cfdda9d7SSteve Wise 		 * We're gonna mark this puppy DEAD, but keep
2452cfdda9d7SSteve Wise 		 * the reference on it until the ULP accepts or
2453cfdda9d7SSteve Wise 		 * rejects the CR. Also wake up anyone waiting
2454cfdda9d7SSteve Wise 		 * in rdma connection migration (see c4iw_accept_cr()).
2455cfdda9d7SSteve Wise 		 */
2456cfdda9d7SSteve Wise 		__state_set(&ep->com, CLOSING);
2457cfdda9d7SSteve Wise 		PDBG("waking up ep %p tid %u\n", ep, ep->hwtid);
2458d9594d99SSteve Wise 		c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
2459cfdda9d7SSteve Wise 		break;
2460cfdda9d7SSteve Wise 	case MPA_REP_SENT:
2461cfdda9d7SSteve Wise 		__state_set(&ep->com, CLOSING);
2462cfdda9d7SSteve Wise 		PDBG("waking up ep %p tid %u\n", ep, ep->hwtid);
2463d9594d99SSteve Wise 		c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
2464cfdda9d7SSteve Wise 		break;
2465cfdda9d7SSteve Wise 	case FPDU_MODE:
2466ca5a2202SSteve Wise 		start_ep_timer(ep);
2467cfdda9d7SSteve Wise 		__state_set(&ep->com, CLOSING);
246830c95c2dSSteve Wise 		attrs.next_state = C4IW_QP_STATE_CLOSING;
24698da7e7a5SSteve Wise 		ret = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
247030c95c2dSSteve Wise 				       C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
24718da7e7a5SSteve Wise 		if (ret != -ECONNRESET) {
2472cfdda9d7SSteve Wise 			peer_close_upcall(ep);
247330c95c2dSSteve Wise 			disconnect = 1;
24748da7e7a5SSteve Wise 		}
2475cfdda9d7SSteve Wise 		break;
2476cfdda9d7SSteve Wise 	case ABORTING:
2477cfdda9d7SSteve Wise 		disconnect = 0;
2478cfdda9d7SSteve Wise 		break;
2479cfdda9d7SSteve Wise 	case CLOSING:
2480cfdda9d7SSteve Wise 		__state_set(&ep->com, MORIBUND);
2481cfdda9d7SSteve Wise 		disconnect = 0;
2482cfdda9d7SSteve Wise 		break;
2483cfdda9d7SSteve Wise 	case MORIBUND:
2484b33bd0cbSSteve Wise 		(void)stop_ep_timer(ep);
2485cfdda9d7SSteve Wise 		if (ep->com.cm_id && ep->com.qp) {
2486cfdda9d7SSteve Wise 			attrs.next_state = C4IW_QP_STATE_IDLE;
2487cfdda9d7SSteve Wise 			c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
2488cfdda9d7SSteve Wise 				       C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
2489cfdda9d7SSteve Wise 		}
2490be13b2dfSSteve Wise 		close_complete_upcall(ep, 0);
2491cfdda9d7SSteve Wise 		__state_set(&ep->com, DEAD);
2492cfdda9d7SSteve Wise 		release = 1;
2493cfdda9d7SSteve Wise 		disconnect = 0;
2494cfdda9d7SSteve Wise 		break;
2495cfdda9d7SSteve Wise 	case DEAD:
2496cfdda9d7SSteve Wise 		disconnect = 0;
2497cfdda9d7SSteve Wise 		break;
2498cfdda9d7SSteve Wise 	default:
2499cfdda9d7SSteve Wise 		BUG_ON(1);
2500cfdda9d7SSteve Wise 	}
25012f5b48c3SSteve Wise 	mutex_unlock(&ep->com.mutex);
2502cfdda9d7SSteve Wise 	if (disconnect)
2503cfdda9d7SSteve Wise 		c4iw_ep_disconnect(ep, 0, GFP_KERNEL);
2504cfdda9d7SSteve Wise 	if (release)
2505cfdda9d7SSteve Wise 		release_ep_resources(ep);
2506cfdda9d7SSteve Wise 	return 0;
2507cfdda9d7SSteve Wise }
2508cfdda9d7SSteve Wise 
2509cfdda9d7SSteve Wise static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
2510cfdda9d7SSteve Wise {
2511cfdda9d7SSteve Wise 	struct cpl_abort_req_rss *req = cplhdr(skb);
2512cfdda9d7SSteve Wise 	struct c4iw_ep *ep;
2513cfdda9d7SSteve Wise 	struct cpl_abort_rpl *rpl;
2514cfdda9d7SSteve Wise 	struct sk_buff *rpl_skb;
2515cfdda9d7SSteve Wise 	struct c4iw_qp_attributes attrs;
2516cfdda9d7SSteve Wise 	int ret;
2517cfdda9d7SSteve Wise 	int release = 0;
2518cfdda9d7SSteve Wise 	struct tid_info *t = dev->rdev.lldi.tids;
2519cfdda9d7SSteve Wise 	unsigned int tid = GET_TID(req);
2520cfdda9d7SSteve Wise 
2521cfdda9d7SSteve Wise 	ep = lookup_tid(t, tid);
25227a2cea2aSSteve Wise 	if (is_neg_adv(req->status)) {
2523dd92b124SHariprasad Shenai 		dev_warn(&dev->rdev.lldi.pdev->dev,
2524dd92b124SHariprasad Shenai 			 "Negative advice on abort - tid %u status %d (%s)\n",
2525dd92b124SHariprasad Shenai 			 ep->hwtid, req->status, neg_adv_str(req->status));
2526cfdda9d7SSteve Wise 		return 0;
2527cfdda9d7SSteve Wise 	}
2528cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid,
2529cfdda9d7SSteve Wise 	     ep->com.state);
2530793dad94SVipul Pandya 	set_bit(PEER_ABORT, &ep->com.history);
25312f5b48c3SSteve Wise 
25322f5b48c3SSteve Wise 	/*
25332f5b48c3SSteve Wise 	 * Wake up any threads in rdma_init() or rdma_fini().
2534d2fe99e8SKumar Sanghvi 	 * However, this is not needed if com state is just
2535d2fe99e8SKumar Sanghvi 	 * MPA_REQ_SENT
25362f5b48c3SSteve Wise 	 */
2537d2fe99e8SKumar Sanghvi 	if (ep->com.state != MPA_REQ_SENT)
2538d9594d99SSteve Wise 		c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
25392f5b48c3SSteve Wise 
25402f5b48c3SSteve Wise 	mutex_lock(&ep->com.mutex);
2541cfdda9d7SSteve Wise 	switch (ep->com.state) {
2542cfdda9d7SSteve Wise 	case CONNECTING:
2543cfdda9d7SSteve Wise 		break;
2544cfdda9d7SSteve Wise 	case MPA_REQ_WAIT:
2545b33bd0cbSSteve Wise 		(void)stop_ep_timer(ep);
2546cfdda9d7SSteve Wise 		break;
2547cfdda9d7SSteve Wise 	case MPA_REQ_SENT:
2548b33bd0cbSSteve Wise 		(void)stop_ep_timer(ep);
2549fe7e0a4dSVipul Pandya 		if (mpa_rev == 1 || (mpa_rev == 2 && ep->tried_with_mpa_v1))
2550cfdda9d7SSteve Wise 			connect_reply_upcall(ep, -ECONNRESET);
2551d2fe99e8SKumar Sanghvi 		else {
2552d2fe99e8SKumar Sanghvi 			/*
2553d2fe99e8SKumar Sanghvi 			 * we just don't send notification upwards because we
2554d2fe99e8SKumar Sanghvi 			 * want to retry with mpa_v1 without upper layers even
2555d2fe99e8SKumar Sanghvi 			 * knowing it.
2556d2fe99e8SKumar Sanghvi 			 *
2557d2fe99e8SKumar Sanghvi 			 * do some housekeeping so as to re-initiate the
2558d2fe99e8SKumar Sanghvi 			 * connection
2559d2fe99e8SKumar Sanghvi 			 */
2560d2fe99e8SKumar Sanghvi 			PDBG("%s: mpa_rev=%d. Retrying with mpav1\n", __func__,
2561d2fe99e8SKumar Sanghvi 			     mpa_rev);
2562d2fe99e8SKumar Sanghvi 			ep->retry_with_mpa_v1 = 1;
2563d2fe99e8SKumar Sanghvi 		}
2564cfdda9d7SSteve Wise 		break;
2565cfdda9d7SSteve Wise 	case MPA_REP_SENT:
2566cfdda9d7SSteve Wise 		break;
2567cfdda9d7SSteve Wise 	case MPA_REQ_RCVD:
2568cfdda9d7SSteve Wise 		break;
2569cfdda9d7SSteve Wise 	case MORIBUND:
2570cfdda9d7SSteve Wise 	case CLOSING:
2571ca5a2202SSteve Wise 		stop_ep_timer(ep);
2572cfdda9d7SSteve Wise 		/*FALLTHROUGH*/
2573cfdda9d7SSteve Wise 	case FPDU_MODE:
2574cfdda9d7SSteve Wise 		if (ep->com.cm_id && ep->com.qp) {
2575cfdda9d7SSteve Wise 			attrs.next_state = C4IW_QP_STATE_ERROR;
2576cfdda9d7SSteve Wise 			ret = c4iw_modify_qp(ep->com.qp->rhp,
2577cfdda9d7SSteve Wise 				     ep->com.qp, C4IW_QP_ATTR_NEXT_STATE,
2578cfdda9d7SSteve Wise 				     &attrs, 1);
2579cfdda9d7SSteve Wise 			if (ret)
2580cfdda9d7SSteve Wise 				printk(KERN_ERR MOD
2581cfdda9d7SSteve Wise 				       "%s - qp <- error failed!\n",
2582cfdda9d7SSteve Wise 				       __func__);
2583cfdda9d7SSteve Wise 		}
2584cfdda9d7SSteve Wise 		peer_abort_upcall(ep);
2585cfdda9d7SSteve Wise 		break;
2586cfdda9d7SSteve Wise 	case ABORTING:
2587cfdda9d7SSteve Wise 		break;
2588cfdda9d7SSteve Wise 	case DEAD:
2589cfdda9d7SSteve Wise 		PDBG("%s PEER_ABORT IN DEAD STATE!!!!\n", __func__);
25902f5b48c3SSteve Wise 		mutex_unlock(&ep->com.mutex);
2591cfdda9d7SSteve Wise 		return 0;
2592cfdda9d7SSteve Wise 	default:
2593cfdda9d7SSteve Wise 		BUG_ON(1);
2594cfdda9d7SSteve Wise 		break;
2595cfdda9d7SSteve Wise 	}
2596cfdda9d7SSteve Wise 	dst_confirm(ep->dst);
2597cfdda9d7SSteve Wise 	if (ep->com.state != ABORTING) {
2598cfdda9d7SSteve Wise 		__state_set(&ep->com, DEAD);
2599d2fe99e8SKumar Sanghvi 		/* we don't release if we want to retry with mpa_v1 */
2600d2fe99e8SKumar Sanghvi 		if (!ep->retry_with_mpa_v1)
2601cfdda9d7SSteve Wise 			release = 1;
2602cfdda9d7SSteve Wise 	}
26032f5b48c3SSteve Wise 	mutex_unlock(&ep->com.mutex);
2604cfdda9d7SSteve Wise 
2605cfdda9d7SSteve Wise 	rpl_skb = get_skb(skb, sizeof(*rpl), GFP_KERNEL);
2606cfdda9d7SSteve Wise 	if (!rpl_skb) {
2607cfdda9d7SSteve Wise 		printk(KERN_ERR MOD "%s - cannot allocate skb!\n",
2608cfdda9d7SSteve Wise 		       __func__);
2609cfdda9d7SSteve Wise 		release = 1;
2610cfdda9d7SSteve Wise 		goto out;
2611cfdda9d7SSteve Wise 	}
2612cfdda9d7SSteve Wise 	set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
2613cfdda9d7SSteve Wise 	rpl = (struct cpl_abort_rpl *) skb_put(rpl_skb, sizeof(*rpl));
2614cfdda9d7SSteve Wise 	INIT_TP_WR(rpl, ep->hwtid);
2615cfdda9d7SSteve Wise 	OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_RPL, ep->hwtid));
2616cfdda9d7SSteve Wise 	rpl->cmd = CPL_ABORT_NO_RST;
2617cfdda9d7SSteve Wise 	c4iw_ofld_send(&ep->com.dev->rdev, rpl_skb);
2618cfdda9d7SSteve Wise out:
2619cfdda9d7SSteve Wise 	if (release)
2620cfdda9d7SSteve Wise 		release_ep_resources(ep);
2621fe7e0a4dSVipul Pandya 	else if (ep->retry_with_mpa_v1) {
2622fe7e0a4dSVipul Pandya 		remove_handle(ep->com.dev, &ep->com.dev->hwtid_idr, ep->hwtid);
2623d2fe99e8SKumar Sanghvi 		cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid);
2624d2fe99e8SKumar Sanghvi 		dst_release(ep->dst);
2625d2fe99e8SKumar Sanghvi 		cxgb4_l2t_release(ep->l2t);
2626d2fe99e8SKumar Sanghvi 		c4iw_reconnect(ep);
2627d2fe99e8SKumar Sanghvi 	}
2628d2fe99e8SKumar Sanghvi 
2629cfdda9d7SSteve Wise 	return 0;
2630cfdda9d7SSteve Wise }
2631cfdda9d7SSteve Wise 
2632cfdda9d7SSteve Wise static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
2633cfdda9d7SSteve Wise {
2634cfdda9d7SSteve Wise 	struct c4iw_ep *ep;
2635cfdda9d7SSteve Wise 	struct c4iw_qp_attributes attrs;
2636cfdda9d7SSteve Wise 	struct cpl_close_con_rpl *rpl = cplhdr(skb);
2637cfdda9d7SSteve Wise 	int release = 0;
2638cfdda9d7SSteve Wise 	struct tid_info *t = dev->rdev.lldi.tids;
2639cfdda9d7SSteve Wise 	unsigned int tid = GET_TID(rpl);
2640cfdda9d7SSteve Wise 
2641cfdda9d7SSteve Wise 	ep = lookup_tid(t, tid);
2642cfdda9d7SSteve Wise 
2643cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
2644cfdda9d7SSteve Wise 	BUG_ON(!ep);
2645cfdda9d7SSteve Wise 
2646cfdda9d7SSteve Wise 	/* The cm_id may be null if we failed to connect */
26472f5b48c3SSteve Wise 	mutex_lock(&ep->com.mutex);
2648cfdda9d7SSteve Wise 	switch (ep->com.state) {
2649cfdda9d7SSteve Wise 	case CLOSING:
2650cfdda9d7SSteve Wise 		__state_set(&ep->com, MORIBUND);
2651cfdda9d7SSteve Wise 		break;
2652cfdda9d7SSteve Wise 	case MORIBUND:
2653b33bd0cbSSteve Wise 		(void)stop_ep_timer(ep);
2654cfdda9d7SSteve Wise 		if ((ep->com.cm_id) && (ep->com.qp)) {
2655cfdda9d7SSteve Wise 			attrs.next_state = C4IW_QP_STATE_IDLE;
2656cfdda9d7SSteve Wise 			c4iw_modify_qp(ep->com.qp->rhp,
2657cfdda9d7SSteve Wise 					     ep->com.qp,
2658cfdda9d7SSteve Wise 					     C4IW_QP_ATTR_NEXT_STATE,
2659cfdda9d7SSteve Wise 					     &attrs, 1);
2660cfdda9d7SSteve Wise 		}
2661be13b2dfSSteve Wise 		close_complete_upcall(ep, 0);
2662cfdda9d7SSteve Wise 		__state_set(&ep->com, DEAD);
2663cfdda9d7SSteve Wise 		release = 1;
2664cfdda9d7SSteve Wise 		break;
2665cfdda9d7SSteve Wise 	case ABORTING:
2666cfdda9d7SSteve Wise 	case DEAD:
2667cfdda9d7SSteve Wise 		break;
2668cfdda9d7SSteve Wise 	default:
2669cfdda9d7SSteve Wise 		BUG_ON(1);
2670cfdda9d7SSteve Wise 		break;
2671cfdda9d7SSteve Wise 	}
26722f5b48c3SSteve Wise 	mutex_unlock(&ep->com.mutex);
2673cfdda9d7SSteve Wise 	if (release)
2674cfdda9d7SSteve Wise 		release_ep_resources(ep);
2675cfdda9d7SSteve Wise 	return 0;
2676cfdda9d7SSteve Wise }
2677cfdda9d7SSteve Wise 
2678cfdda9d7SSteve Wise static int terminate(struct c4iw_dev *dev, struct sk_buff *skb)
2679cfdda9d7SSteve Wise {
26800e42c1f4SSteve Wise 	struct cpl_rdma_terminate *rpl = cplhdr(skb);
2681cfdda9d7SSteve Wise 	struct tid_info *t = dev->rdev.lldi.tids;
26820e42c1f4SSteve Wise 	unsigned int tid = GET_TID(rpl);
26830e42c1f4SSteve Wise 	struct c4iw_ep *ep;
26840e42c1f4SSteve Wise 	struct c4iw_qp_attributes attrs;
2685cfdda9d7SSteve Wise 
2686cfdda9d7SSteve Wise 	ep = lookup_tid(t, tid);
26870e42c1f4SSteve Wise 	BUG_ON(!ep);
2688cfdda9d7SSteve Wise 
268930c95c2dSSteve Wise 	if (ep && ep->com.qp) {
26900e42c1f4SSteve Wise 		printk(KERN_WARNING MOD "TERM received tid %u qpid %u\n", tid,
26910e42c1f4SSteve Wise 		       ep->com.qp->wq.sq.qid);
26920e42c1f4SSteve Wise 		attrs.next_state = C4IW_QP_STATE_TERMINATE;
26930e42c1f4SSteve Wise 		c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
26940e42c1f4SSteve Wise 			       C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
26950e42c1f4SSteve Wise 	} else
269630c95c2dSSteve Wise 		printk(KERN_WARNING MOD "TERM received tid %u no ep/qp\n", tid);
2697cfdda9d7SSteve Wise 
2698cfdda9d7SSteve Wise 	return 0;
2699cfdda9d7SSteve Wise }
2700cfdda9d7SSteve Wise 
2701cfdda9d7SSteve Wise /*
2702cfdda9d7SSteve Wise  * Upcall from the adapter indicating data has been transmitted.
2703cfdda9d7SSteve Wise  * For us its just the single MPA request or reply.  We can now free
2704cfdda9d7SSteve Wise  * the skb holding the mpa message.
2705cfdda9d7SSteve Wise  */
2706cfdda9d7SSteve Wise static int fw4_ack(struct c4iw_dev *dev, struct sk_buff *skb)
2707cfdda9d7SSteve Wise {
2708cfdda9d7SSteve Wise 	struct c4iw_ep *ep;
2709cfdda9d7SSteve Wise 	struct cpl_fw4_ack *hdr = cplhdr(skb);
2710cfdda9d7SSteve Wise 	u8 credits = hdr->credits;
2711cfdda9d7SSteve Wise 	unsigned int tid = GET_TID(hdr);
2712cfdda9d7SSteve Wise 	struct tid_info *t = dev->rdev.lldi.tids;
2713cfdda9d7SSteve Wise 
2714cfdda9d7SSteve Wise 
2715cfdda9d7SSteve Wise 	ep = lookup_tid(t, tid);
2716cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u credits %u\n", __func__, ep, ep->hwtid, credits);
2717cfdda9d7SSteve Wise 	if (credits == 0) {
2718aa1ad260SJoe Perches 		PDBG("%s 0 credit ack ep %p tid %u state %u\n",
2719cfdda9d7SSteve Wise 		     __func__, ep, ep->hwtid, state_read(&ep->com));
2720cfdda9d7SSteve Wise 		return 0;
2721cfdda9d7SSteve Wise 	}
2722cfdda9d7SSteve Wise 
2723cfdda9d7SSteve Wise 	dst_confirm(ep->dst);
2724cfdda9d7SSteve Wise 	if (ep->mpa_skb) {
2725cfdda9d7SSteve Wise 		PDBG("%s last streaming msg ack ep %p tid %u state %u "
2726cfdda9d7SSteve Wise 		     "initiator %u freeing skb\n", __func__, ep, ep->hwtid,
2727cfdda9d7SSteve Wise 		     state_read(&ep->com), ep->mpa_attr.initiator ? 1 : 0);
2728cfdda9d7SSteve Wise 		kfree_skb(ep->mpa_skb);
2729cfdda9d7SSteve Wise 		ep->mpa_skb = NULL;
2730cfdda9d7SSteve Wise 	}
2731cfdda9d7SSteve Wise 	return 0;
2732cfdda9d7SSteve Wise }
2733cfdda9d7SSteve Wise 
2734cfdda9d7SSteve Wise int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
2735cfdda9d7SSteve Wise {
2736a7db89ebSSteve Wise 	int err = 0;
2737a7db89ebSSteve Wise 	int disconnect = 0;
2738cfdda9d7SSteve Wise 	struct c4iw_ep *ep = to_ep(cm_id);
2739cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
2740cfdda9d7SSteve Wise 
2741a7db89ebSSteve Wise 	mutex_lock(&ep->com.mutex);
2742a7db89ebSSteve Wise 	if (ep->com.state == DEAD) {
2743a7db89ebSSteve Wise 		mutex_unlock(&ep->com.mutex);
2744cfdda9d7SSteve Wise 		c4iw_put_ep(&ep->com);
2745cfdda9d7SSteve Wise 		return -ECONNRESET;
2746cfdda9d7SSteve Wise 	}
2747793dad94SVipul Pandya 	set_bit(ULP_REJECT, &ep->com.history);
2748a7db89ebSSteve Wise 	BUG_ON(ep->com.state != MPA_REQ_RCVD);
2749cfdda9d7SSteve Wise 	if (mpa_rev == 0)
2750cfdda9d7SSteve Wise 		abort_connection(ep, NULL, GFP_KERNEL);
2751cfdda9d7SSteve Wise 	else {
2752cfdda9d7SSteve Wise 		err = send_mpa_reject(ep, pdata, pdata_len);
2753a7db89ebSSteve Wise 		disconnect = 1;
2754cfdda9d7SSteve Wise 	}
2755a7db89ebSSteve Wise 	mutex_unlock(&ep->com.mutex);
2756a7db89ebSSteve Wise 	if (disconnect)
2757a7db89ebSSteve Wise 		err = c4iw_ep_disconnect(ep, 0, GFP_KERNEL);
2758cfdda9d7SSteve Wise 	c4iw_put_ep(&ep->com);
2759cfdda9d7SSteve Wise 	return 0;
2760cfdda9d7SSteve Wise }
2761cfdda9d7SSteve Wise 
2762cfdda9d7SSteve Wise int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
2763cfdda9d7SSteve Wise {
2764cfdda9d7SSteve Wise 	int err;
2765cfdda9d7SSteve Wise 	struct c4iw_qp_attributes attrs;
2766cfdda9d7SSteve Wise 	enum c4iw_qp_attr_mask mask;
2767cfdda9d7SSteve Wise 	struct c4iw_ep *ep = to_ep(cm_id);
2768cfdda9d7SSteve Wise 	struct c4iw_dev *h = to_c4iw_dev(cm_id->device);
2769cfdda9d7SSteve Wise 	struct c4iw_qp *qp = get_qhp(h, conn_param->qpn);
2770cfdda9d7SSteve Wise 
2771cfdda9d7SSteve Wise 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
2772a7db89ebSSteve Wise 
2773a7db89ebSSteve Wise 	mutex_lock(&ep->com.mutex);
2774a7db89ebSSteve Wise 	if (ep->com.state == DEAD) {
2775cfdda9d7SSteve Wise 		err = -ECONNRESET;
2776cfdda9d7SSteve Wise 		goto err;
2777cfdda9d7SSteve Wise 	}
2778cfdda9d7SSteve Wise 
2779a7db89ebSSteve Wise 	BUG_ON(ep->com.state != MPA_REQ_RCVD);
2780cfdda9d7SSteve Wise 	BUG_ON(!qp);
2781cfdda9d7SSteve Wise 
2782793dad94SVipul Pandya 	set_bit(ULP_ACCEPT, &ep->com.history);
27834c2c5763SHariprasad Shenai 	if ((conn_param->ord > cur_max_read_depth(ep->com.dev)) ||
27844c2c5763SHariprasad Shenai 	    (conn_param->ird > cur_max_read_depth(ep->com.dev))) {
2785cfdda9d7SSteve Wise 		abort_connection(ep, NULL, GFP_KERNEL);
2786cfdda9d7SSteve Wise 		err = -EINVAL;
2787cfdda9d7SSteve Wise 		goto err;
2788cfdda9d7SSteve Wise 	}
2789cfdda9d7SSteve Wise 
2790d2fe99e8SKumar Sanghvi 	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
2791d2fe99e8SKumar Sanghvi 		if (conn_param->ord > ep->ird) {
27924c2c5763SHariprasad Shenai 			if (RELAXED_IRD_NEGOTIATION) {
27934c2c5763SHariprasad Shenai 				ep->ord = ep->ird;
27944c2c5763SHariprasad Shenai 			} else {
2795d2fe99e8SKumar Sanghvi 				ep->ird = conn_param->ird;
2796d2fe99e8SKumar Sanghvi 				ep->ord = conn_param->ord;
2797d2fe99e8SKumar Sanghvi 				send_mpa_reject(ep, conn_param->private_data,
2798d2fe99e8SKumar Sanghvi 						conn_param->private_data_len);
2799d2fe99e8SKumar Sanghvi 				abort_connection(ep, NULL, GFP_KERNEL);
2800d2fe99e8SKumar Sanghvi 				err = -ENOMEM;
2801d2fe99e8SKumar Sanghvi 				goto err;
2802d2fe99e8SKumar Sanghvi 			}
28034c2c5763SHariprasad Shenai 		}
28044c2c5763SHariprasad Shenai 		if (conn_param->ird < ep->ord) {
28054c2c5763SHariprasad Shenai 			if (RELAXED_IRD_NEGOTIATION &&
28064c2c5763SHariprasad Shenai 			    ep->ord <= h->rdev.lldi.max_ordird_qp) {
28074c2c5763SHariprasad Shenai 				conn_param->ird = ep->ord;
28084c2c5763SHariprasad Shenai 			} else {
2809d2fe99e8SKumar Sanghvi 				abort_connection(ep, NULL, GFP_KERNEL);
2810d2fe99e8SKumar Sanghvi 				err = -ENOMEM;
2811d2fe99e8SKumar Sanghvi 				goto err;
2812d2fe99e8SKumar Sanghvi 			}
2813d2fe99e8SKumar Sanghvi 		}
2814d2fe99e8SKumar Sanghvi 	}
2815cfdda9d7SSteve Wise 	ep->ird = conn_param->ird;
2816cfdda9d7SSteve Wise 	ep->ord = conn_param->ord;
2817cfdda9d7SSteve Wise 
28184c2c5763SHariprasad Shenai 	if (ep->mpa_attr.version == 1) {
2819cfdda9d7SSteve Wise 		if (peer2peer && ep->ird == 0)
2820cfdda9d7SSteve Wise 			ep->ird = 1;
28214c2c5763SHariprasad Shenai 	} else {
28224c2c5763SHariprasad Shenai 		if (peer2peer &&
28234c2c5763SHariprasad Shenai 		    (ep->mpa_attr.p2p_type != FW_RI_INIT_P2PTYPE_DISABLED) &&
28244c2c5763SHariprasad Shenai 		    (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) && ep->ord == 0)
28254c2c5763SHariprasad Shenai 			ep->ird = 1;
28264c2c5763SHariprasad Shenai 	}
2827cfdda9d7SSteve Wise 
2828cfdda9d7SSteve Wise 	PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord);
2829cfdda9d7SSteve Wise 
2830d2fe99e8SKumar Sanghvi 	cm_id->add_ref(cm_id);
2831d2fe99e8SKumar Sanghvi 	ep->com.cm_id = cm_id;
2832d2fe99e8SKumar Sanghvi 	ep->com.qp = qp;
2833325abeadSVipul Pandya 	ref_qp(ep);
2834d2fe99e8SKumar Sanghvi 
2835cfdda9d7SSteve Wise 	/* bind QP to EP and move to RTS */
2836cfdda9d7SSteve Wise 	attrs.mpa_attr = ep->mpa_attr;
2837cfdda9d7SSteve Wise 	attrs.max_ird = ep->ird;
2838cfdda9d7SSteve Wise 	attrs.max_ord = ep->ord;
2839cfdda9d7SSteve Wise 	attrs.llp_stream_handle = ep;
2840cfdda9d7SSteve Wise 	attrs.next_state = C4IW_QP_STATE_RTS;
2841cfdda9d7SSteve Wise 
2842cfdda9d7SSteve Wise 	/* bind QP and TID with INIT_WR */
2843cfdda9d7SSteve Wise 	mask = C4IW_QP_ATTR_NEXT_STATE |
2844cfdda9d7SSteve Wise 			     C4IW_QP_ATTR_LLP_STREAM_HANDLE |
2845cfdda9d7SSteve Wise 			     C4IW_QP_ATTR_MPA_ATTR |
2846cfdda9d7SSteve Wise 			     C4IW_QP_ATTR_MAX_IRD |
2847cfdda9d7SSteve Wise 			     C4IW_QP_ATTR_MAX_ORD;
2848cfdda9d7SSteve Wise 
2849cfdda9d7SSteve Wise 	err = c4iw_modify_qp(ep->com.qp->rhp,
2850cfdda9d7SSteve Wise 			     ep->com.qp, mask, &attrs, 1);
2851cfdda9d7SSteve Wise 	if (err)
2852cfdda9d7SSteve Wise 		goto err1;
2853cfdda9d7SSteve Wise 	err = send_mpa_reply(ep, conn_param->private_data,
2854cfdda9d7SSteve Wise 			     conn_param->private_data_len);
2855cfdda9d7SSteve Wise 	if (err)
2856cfdda9d7SSteve Wise 		goto err1;
2857cfdda9d7SSteve Wise 
2858a7db89ebSSteve Wise 	__state_set(&ep->com, FPDU_MODE);
2859cfdda9d7SSteve Wise 	established_upcall(ep);
2860a7db89ebSSteve Wise 	mutex_unlock(&ep->com.mutex);
2861cfdda9d7SSteve Wise 	c4iw_put_ep(&ep->com);
2862cfdda9d7SSteve Wise 	return 0;
2863cfdda9d7SSteve Wise err1:
2864cfdda9d7SSteve Wise 	ep->com.cm_id = NULL;
28654c2c5763SHariprasad Shenai 	abort_connection(ep, NULL, GFP_KERNEL);
2866cfdda9d7SSteve Wise 	cm_id->rem_ref(cm_id);
2867cfdda9d7SSteve Wise err:
2868a7db89ebSSteve Wise 	mutex_unlock(&ep->com.mutex);
2869cfdda9d7SSteve Wise 	c4iw_put_ep(&ep->com);
2870cfdda9d7SSteve Wise 	return err;
2871cfdda9d7SSteve Wise }
2872cfdda9d7SSteve Wise 
2873830662f6SVipul Pandya static int pick_local_ipaddrs(struct c4iw_dev *dev, struct iw_cm_id *cm_id)
2874830662f6SVipul Pandya {
2875830662f6SVipul Pandya 	struct in_device *ind;
2876830662f6SVipul Pandya 	int found = 0;
2877830662f6SVipul Pandya 	struct sockaddr_in *laddr = (struct sockaddr_in *)&cm_id->local_addr;
2878830662f6SVipul Pandya 	struct sockaddr_in *raddr = (struct sockaddr_in *)&cm_id->remote_addr;
2879830662f6SVipul Pandya 
2880830662f6SVipul Pandya 	ind = in_dev_get(dev->rdev.lldi.ports[0]);
2881830662f6SVipul Pandya 	if (!ind)
2882830662f6SVipul Pandya 		return -EADDRNOTAVAIL;
2883830662f6SVipul Pandya 	for_primary_ifa(ind) {
2884830662f6SVipul Pandya 		laddr->sin_addr.s_addr = ifa->ifa_address;
2885830662f6SVipul Pandya 		raddr->sin_addr.s_addr = ifa->ifa_address;
2886830662f6SVipul Pandya 		found = 1;
2887830662f6SVipul Pandya 		break;
2888830662f6SVipul Pandya 	}
2889830662f6SVipul Pandya 	endfor_ifa(ind);
2890830662f6SVipul Pandya 	in_dev_put(ind);
2891830662f6SVipul Pandya 	return found ? 0 : -EADDRNOTAVAIL;
2892830662f6SVipul Pandya }
2893830662f6SVipul Pandya 
2894830662f6SVipul Pandya static int get_lladdr(struct net_device *dev, struct in6_addr *addr,
2895830662f6SVipul Pandya 		      unsigned char banned_flags)
2896830662f6SVipul Pandya {
2897830662f6SVipul Pandya 	struct inet6_dev *idev;
2898830662f6SVipul Pandya 	int err = -EADDRNOTAVAIL;
2899830662f6SVipul Pandya 
2900830662f6SVipul Pandya 	rcu_read_lock();
2901830662f6SVipul Pandya 	idev = __in6_dev_get(dev);
2902830662f6SVipul Pandya 	if (idev != NULL) {
2903830662f6SVipul Pandya 		struct inet6_ifaddr *ifp;
2904830662f6SVipul Pandya 
2905830662f6SVipul Pandya 		read_lock_bh(&idev->lock);
2906830662f6SVipul Pandya 		list_for_each_entry(ifp, &idev->addr_list, if_list) {
2907830662f6SVipul Pandya 			if (ifp->scope == IFA_LINK &&
2908830662f6SVipul Pandya 			    !(ifp->flags & banned_flags)) {
2909830662f6SVipul Pandya 				memcpy(addr, &ifp->addr, 16);
2910830662f6SVipul Pandya 				err = 0;
2911830662f6SVipul Pandya 				break;
2912830662f6SVipul Pandya 			}
2913830662f6SVipul Pandya 		}
2914830662f6SVipul Pandya 		read_unlock_bh(&idev->lock);
2915830662f6SVipul Pandya 	}
2916830662f6SVipul Pandya 	rcu_read_unlock();
2917830662f6SVipul Pandya 	return err;
2918830662f6SVipul Pandya }
2919830662f6SVipul Pandya 
2920830662f6SVipul Pandya static int pick_local_ip6addrs(struct c4iw_dev *dev, struct iw_cm_id *cm_id)
2921830662f6SVipul Pandya {
2922830662f6SVipul Pandya 	struct in6_addr uninitialized_var(addr);
2923830662f6SVipul Pandya 	struct sockaddr_in6 *la6 = (struct sockaddr_in6 *)&cm_id->local_addr;
2924830662f6SVipul Pandya 	struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)&cm_id->remote_addr;
2925830662f6SVipul Pandya 
2926830662f6SVipul Pandya 	if (get_lladdr(dev->rdev.lldi.ports[0], &addr, IFA_F_TENTATIVE)) {
2927830662f6SVipul Pandya 		memcpy(la6->sin6_addr.s6_addr, &addr, 16);
2928830662f6SVipul Pandya 		memcpy(ra6->sin6_addr.s6_addr, &addr, 16);
2929830662f6SVipul Pandya 		return 0;
2930830662f6SVipul Pandya 	}
2931830662f6SVipul Pandya 	return -EADDRNOTAVAIL;
2932830662f6SVipul Pandya }
2933830662f6SVipul Pandya 
2934cfdda9d7SSteve Wise int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
2935cfdda9d7SSteve Wise {
2936cfdda9d7SSteve Wise 	struct c4iw_dev *dev = to_c4iw_dev(cm_id->device);
2937cfdda9d7SSteve Wise 	struct c4iw_ep *ep;
29383786cf18SDavid Miller 	int err = 0;
29399eccfe10SSteve Wise 	struct sockaddr_in *laddr;
29409eccfe10SSteve Wise 	struct sockaddr_in *raddr;
29419eccfe10SSteve Wise 	struct sockaddr_in6 *laddr6;
29429eccfe10SSteve Wise 	struct sockaddr_in6 *raddr6;
29439eccfe10SSteve Wise 	struct iwpm_dev_data pm_reg_msg;
29449eccfe10SSteve Wise 	struct iwpm_sa_data pm_msg;
2945830662f6SVipul Pandya 	__u8 *ra;
2946830662f6SVipul Pandya 	int iptype;
29479eccfe10SSteve Wise 	int iwpm_err = 0;
2948cfdda9d7SSteve Wise 
29494c2c5763SHariprasad Shenai 	if ((conn_param->ord > cur_max_read_depth(dev)) ||
29504c2c5763SHariprasad Shenai 	    (conn_param->ird > cur_max_read_depth(dev))) {
2951be4c9badSRoland Dreier 		err = -EINVAL;
2952be4c9badSRoland Dreier 		goto out;
2953be4c9badSRoland Dreier 	}
2954cfdda9d7SSteve Wise 	ep = alloc_ep(sizeof(*ep), GFP_KERNEL);
2955cfdda9d7SSteve Wise 	if (!ep) {
2956cfdda9d7SSteve Wise 		printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __func__);
2957cfdda9d7SSteve Wise 		err = -ENOMEM;
2958cfdda9d7SSteve Wise 		goto out;
2959cfdda9d7SSteve Wise 	}
2960cfdda9d7SSteve Wise 	init_timer(&ep->timer);
2961cfdda9d7SSteve Wise 	ep->plen = conn_param->private_data_len;
2962cfdda9d7SSteve Wise 	if (ep->plen)
2963cfdda9d7SSteve Wise 		memcpy(ep->mpa_pkt + sizeof(struct mpa_message),
2964cfdda9d7SSteve Wise 		       conn_param->private_data, ep->plen);
2965cfdda9d7SSteve Wise 	ep->ird = conn_param->ird;
2966cfdda9d7SSteve Wise 	ep->ord = conn_param->ord;
2967cfdda9d7SSteve Wise 
2968cfdda9d7SSteve Wise 	if (peer2peer && ep->ord == 0)
2969cfdda9d7SSteve Wise 		ep->ord = 1;
2970cfdda9d7SSteve Wise 
2971cfdda9d7SSteve Wise 	cm_id->add_ref(cm_id);
2972cfdda9d7SSteve Wise 	ep->com.dev = dev;
2973cfdda9d7SSteve Wise 	ep->com.cm_id = cm_id;
2974cfdda9d7SSteve Wise 	ep->com.qp = get_qhp(dev, conn_param->qpn);
2975830662f6SVipul Pandya 	if (!ep->com.qp) {
2976830662f6SVipul Pandya 		PDBG("%s qpn 0x%x not found!\n", __func__, conn_param->qpn);
2977830662f6SVipul Pandya 		err = -EINVAL;
29789eccfe10SSteve Wise 		goto fail1;
2979830662f6SVipul Pandya 	}
2980325abeadSVipul Pandya 	ref_qp(ep);
2981cfdda9d7SSteve Wise 	PDBG("%s qpn 0x%x qp %p cm_id %p\n", __func__, conn_param->qpn,
2982cfdda9d7SSteve Wise 	     ep->com.qp, cm_id);
2983cfdda9d7SSteve Wise 
2984cfdda9d7SSteve Wise 	/*
2985cfdda9d7SSteve Wise 	 * Allocate an active TID to initiate a TCP connection.
2986cfdda9d7SSteve Wise 	 */
2987cfdda9d7SSteve Wise 	ep->atid = cxgb4_alloc_atid(dev->rdev.lldi.tids, ep);
2988cfdda9d7SSteve Wise 	if (ep->atid == -1) {
2989cfdda9d7SSteve Wise 		printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __func__);
2990cfdda9d7SSteve Wise 		err = -ENOMEM;
29919eccfe10SSteve Wise 		goto fail1;
2992cfdda9d7SSteve Wise 	}
2993793dad94SVipul Pandya 	insert_handle(dev, &dev->atid_idr, ep, ep->atid);
2994cfdda9d7SSteve Wise 
29959eccfe10SSteve Wise 	memcpy(&ep->com.local_addr, &cm_id->local_addr,
29969eccfe10SSteve Wise 	       sizeof(ep->com.local_addr));
29979eccfe10SSteve Wise 	memcpy(&ep->com.remote_addr, &cm_id->remote_addr,
29989eccfe10SSteve Wise 	       sizeof(ep->com.remote_addr));
29999eccfe10SSteve Wise 
30009eccfe10SSteve Wise 	/* No port mapper available, go with the specified peer information */
30019eccfe10SSteve Wise 	memcpy(&ep->com.mapped_local_addr, &cm_id->local_addr,
30029eccfe10SSteve Wise 	       sizeof(ep->com.mapped_local_addr));
30039eccfe10SSteve Wise 	memcpy(&ep->com.mapped_remote_addr, &cm_id->remote_addr,
30049eccfe10SSteve Wise 	       sizeof(ep->com.mapped_remote_addr));
30059eccfe10SSteve Wise 
30069eccfe10SSteve Wise 	c4iw_form_reg_msg(dev, &pm_reg_msg);
30079eccfe10SSteve Wise 	iwpm_err = iwpm_register_pid(&pm_reg_msg, RDMA_NL_C4IW);
30089eccfe10SSteve Wise 	if (iwpm_err) {
30099eccfe10SSteve Wise 		PDBG("%s: Port Mapper reg pid fail (err = %d).\n",
30109eccfe10SSteve Wise 			__func__, iwpm_err);
30119eccfe10SSteve Wise 	}
30129eccfe10SSteve Wise 	if (iwpm_valid_pid() && !iwpm_err) {
30139eccfe10SSteve Wise 		c4iw_form_pm_msg(ep, &pm_msg);
30149eccfe10SSteve Wise 		iwpm_err = iwpm_add_and_query_mapping(&pm_msg, RDMA_NL_C4IW);
30159eccfe10SSteve Wise 		if (iwpm_err)
30169eccfe10SSteve Wise 			PDBG("%s: Port Mapper query fail (err = %d).\n",
30179eccfe10SSteve Wise 				__func__, iwpm_err);
30189eccfe10SSteve Wise 		else
30199eccfe10SSteve Wise 			c4iw_record_pm_msg(ep, &pm_msg);
30209eccfe10SSteve Wise 	}
30219eccfe10SSteve Wise 	if (iwpm_create_mapinfo(&ep->com.local_addr,
30229eccfe10SSteve Wise 				&ep->com.mapped_local_addr, RDMA_NL_C4IW)) {
30239eccfe10SSteve Wise 		iwpm_remove_mapping(&ep->com.local_addr, RDMA_NL_C4IW);
30249eccfe10SSteve Wise 		err = -ENOMEM;
30259eccfe10SSteve Wise 		goto fail1;
30269eccfe10SSteve Wise 	}
30279eccfe10SSteve Wise 	print_addr(&ep->com, __func__, "add_query/create_mapinfo");
30289eccfe10SSteve Wise 	set_bit(RELEASE_MAPINFO, &ep->com.flags);
30299eccfe10SSteve Wise 
30309eccfe10SSteve Wise 	laddr = (struct sockaddr_in *)&ep->com.mapped_local_addr;
30319eccfe10SSteve Wise 	raddr = (struct sockaddr_in *)&ep->com.mapped_remote_addr;
30329eccfe10SSteve Wise 	laddr6 = (struct sockaddr_in6 *)&ep->com.mapped_local_addr;
30339eccfe10SSteve Wise 	raddr6 = (struct sockaddr_in6 *) &ep->com.mapped_remote_addr;
30349eccfe10SSteve Wise 
3035830662f6SVipul Pandya 	if (cm_id->remote_addr.ss_family == AF_INET) {
3036830662f6SVipul Pandya 		iptype = 4;
3037830662f6SVipul Pandya 		ra = (__u8 *)&raddr->sin_addr;
3038830662f6SVipul Pandya 
3039830662f6SVipul Pandya 		/*
3040830662f6SVipul Pandya 		 * Handle loopback requests to INADDR_ANY.
3041830662f6SVipul Pandya 		 */
3042830662f6SVipul Pandya 		if ((__force int)raddr->sin_addr.s_addr == INADDR_ANY) {
3043830662f6SVipul Pandya 			err = pick_local_ipaddrs(dev, cm_id);
3044830662f6SVipul Pandya 			if (err)
30459eccfe10SSteve Wise 				goto fail1;
3046830662f6SVipul Pandya 		}
3047cfdda9d7SSteve Wise 
3048cfdda9d7SSteve Wise 		/* find a route */
3049830662f6SVipul Pandya 		PDBG("%s saddr %pI4 sport 0x%x raddr %pI4 rport 0x%x\n",
3050830662f6SVipul Pandya 		     __func__, &laddr->sin_addr, ntohs(laddr->sin_port),
3051830662f6SVipul Pandya 		     ra, ntohs(raddr->sin_port));
3052830662f6SVipul Pandya 		ep->dst = find_route(dev, laddr->sin_addr.s_addr,
3053830662f6SVipul Pandya 				     raddr->sin_addr.s_addr, laddr->sin_port,
3054830662f6SVipul Pandya 				     raddr->sin_port, 0);
3055830662f6SVipul Pandya 	} else {
3056830662f6SVipul Pandya 		iptype = 6;
3057830662f6SVipul Pandya 		ra = (__u8 *)&raddr6->sin6_addr;
3058830662f6SVipul Pandya 
3059830662f6SVipul Pandya 		/*
3060830662f6SVipul Pandya 		 * Handle loopback requests to INADDR_ANY.
3061830662f6SVipul Pandya 		 */
3062830662f6SVipul Pandya 		if (ipv6_addr_type(&raddr6->sin6_addr) == IPV6_ADDR_ANY) {
3063830662f6SVipul Pandya 			err = pick_local_ip6addrs(dev, cm_id);
3064830662f6SVipul Pandya 			if (err)
30659eccfe10SSteve Wise 				goto fail1;
3066830662f6SVipul Pandya 		}
3067830662f6SVipul Pandya 
3068830662f6SVipul Pandya 		/* find a route */
3069830662f6SVipul Pandya 		PDBG("%s saddr %pI6 sport 0x%x raddr %pI6 rport 0x%x\n",
3070830662f6SVipul Pandya 		     __func__, laddr6->sin6_addr.s6_addr,
3071830662f6SVipul Pandya 		     ntohs(laddr6->sin6_port),
3072830662f6SVipul Pandya 		     raddr6->sin6_addr.s6_addr, ntohs(raddr6->sin6_port));
3073830662f6SVipul Pandya 		ep->dst = find_route6(dev, laddr6->sin6_addr.s6_addr,
3074830662f6SVipul Pandya 				      raddr6->sin6_addr.s6_addr,
3075830662f6SVipul Pandya 				      laddr6->sin6_port, raddr6->sin6_port, 0,
3076830662f6SVipul Pandya 				      raddr6->sin6_scope_id);
3077830662f6SVipul Pandya 	}
3078830662f6SVipul Pandya 	if (!ep->dst) {
3079cfdda9d7SSteve Wise 		printk(KERN_ERR MOD "%s - cannot find route.\n", __func__);
3080cfdda9d7SSteve Wise 		err = -EHOSTUNREACH;
30819eccfe10SSteve Wise 		goto fail2;
3082cfdda9d7SSteve Wise 	}
3083cfdda9d7SSteve Wise 
3084830662f6SVipul Pandya 	err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, true);
30853786cf18SDavid Miller 	if (err) {
3086cfdda9d7SSteve Wise 		printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
30879eccfe10SSteve Wise 		goto fail3;
3088cfdda9d7SSteve Wise 	}
3089cfdda9d7SSteve Wise 
3090cfdda9d7SSteve Wise 	PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n",
3091cfdda9d7SSteve Wise 		__func__, ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid,
3092cfdda9d7SSteve Wise 		ep->l2t->idx);
3093cfdda9d7SSteve Wise 
3094cfdda9d7SSteve Wise 	state_set(&ep->com, CONNECTING);
3095cfdda9d7SSteve Wise 	ep->tos = 0;
3096cfdda9d7SSteve Wise 
3097cfdda9d7SSteve Wise 	/* send connect request to rnic */
3098cfdda9d7SSteve Wise 	err = send_connect(ep);
3099cfdda9d7SSteve Wise 	if (!err)
3100cfdda9d7SSteve Wise 		goto out;
3101cfdda9d7SSteve Wise 
3102cfdda9d7SSteve Wise 	cxgb4_l2t_release(ep->l2t);
3103cfdda9d7SSteve Wise fail3:
31049eccfe10SSteve Wise 	dst_release(ep->dst);
31059eccfe10SSteve Wise fail2:
3106793dad94SVipul Pandya 	remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid);
3107cfdda9d7SSteve Wise 	cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid);
31089eccfe10SSteve Wise fail1:
3109cfdda9d7SSteve Wise 	cm_id->rem_ref(cm_id);
3110cfdda9d7SSteve Wise 	c4iw_put_ep(&ep->com);
3111cfdda9d7SSteve Wise out:
3112cfdda9d7SSteve Wise 	return err;
3113cfdda9d7SSteve Wise }
3114cfdda9d7SSteve Wise 
3115830662f6SVipul Pandya static int create_server6(struct c4iw_dev *dev, struct c4iw_listen_ep *ep)
3116830662f6SVipul Pandya {
3117830662f6SVipul Pandya 	int err;
31189eccfe10SSteve Wise 	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)
31199eccfe10SSteve Wise 				    &ep->com.mapped_local_addr;
3120830662f6SVipul Pandya 
3121830662f6SVipul Pandya 	c4iw_init_wr_wait(&ep->com.wr_wait);
3122830662f6SVipul Pandya 	err = cxgb4_create_server6(ep->com.dev->rdev.lldi.ports[0],
3123830662f6SVipul Pandya 				   ep->stid, &sin6->sin6_addr,
3124830662f6SVipul Pandya 				   sin6->sin6_port,
3125830662f6SVipul Pandya 				   ep->com.dev->rdev.lldi.rxq_ids[0]);
3126830662f6SVipul Pandya 	if (!err)
3127830662f6SVipul Pandya 		err = c4iw_wait_for_reply(&ep->com.dev->rdev,
3128830662f6SVipul Pandya 					  &ep->com.wr_wait,
3129830662f6SVipul Pandya 					  0, 0, __func__);
3130e6b11163SHariprasad S 	else if (err > 0)
3131e6b11163SHariprasad S 		err = net_xmit_errno(err);
3132830662f6SVipul Pandya 	if (err)
3133830662f6SVipul Pandya 		pr_err("cxgb4_create_server6/filter failed err %d stid %d laddr %pI6 lport %d\n",
3134830662f6SVipul Pandya 		       err, ep->stid,
3135830662f6SVipul Pandya 		       sin6->sin6_addr.s6_addr, ntohs(sin6->sin6_port));
3136830662f6SVipul Pandya 	return err;
3137830662f6SVipul Pandya }
3138830662f6SVipul Pandya 
3139830662f6SVipul Pandya static int create_server4(struct c4iw_dev *dev, struct c4iw_listen_ep *ep)
3140830662f6SVipul Pandya {
3141830662f6SVipul Pandya 	int err;
31429eccfe10SSteve Wise 	struct sockaddr_in *sin = (struct sockaddr_in *)
31439eccfe10SSteve Wise 				  &ep->com.mapped_local_addr;
3144830662f6SVipul Pandya 
3145830662f6SVipul Pandya 	if (dev->rdev.lldi.enable_fw_ofld_conn) {
3146830662f6SVipul Pandya 		do {
3147830662f6SVipul Pandya 			err = cxgb4_create_server_filter(
3148830662f6SVipul Pandya 				ep->com.dev->rdev.lldi.ports[0], ep->stid,
3149830662f6SVipul Pandya 				sin->sin_addr.s_addr, sin->sin_port, 0,
3150830662f6SVipul Pandya 				ep->com.dev->rdev.lldi.rxq_ids[0], 0, 0);
3151830662f6SVipul Pandya 			if (err == -EBUSY) {
3152830662f6SVipul Pandya 				set_current_state(TASK_UNINTERRUPTIBLE);
3153830662f6SVipul Pandya 				schedule_timeout(usecs_to_jiffies(100));
3154830662f6SVipul Pandya 			}
3155830662f6SVipul Pandya 		} while (err == -EBUSY);
3156830662f6SVipul Pandya 	} else {
3157830662f6SVipul Pandya 		c4iw_init_wr_wait(&ep->com.wr_wait);
3158830662f6SVipul Pandya 		err = cxgb4_create_server(ep->com.dev->rdev.lldi.ports[0],
3159830662f6SVipul Pandya 				ep->stid, sin->sin_addr.s_addr, sin->sin_port,
3160830662f6SVipul Pandya 				0, ep->com.dev->rdev.lldi.rxq_ids[0]);
3161830662f6SVipul Pandya 		if (!err)
3162830662f6SVipul Pandya 			err = c4iw_wait_for_reply(&ep->com.dev->rdev,
3163830662f6SVipul Pandya 						  &ep->com.wr_wait,
3164830662f6SVipul Pandya 						  0, 0, __func__);
3165e6b11163SHariprasad S 		else if (err > 0)
3166e6b11163SHariprasad S 			err = net_xmit_errno(err);
3167830662f6SVipul Pandya 	}
3168830662f6SVipul Pandya 	if (err)
3169830662f6SVipul Pandya 		pr_err("cxgb4_create_server/filter failed err %d stid %d laddr %pI4 lport %d\n"
3170830662f6SVipul Pandya 		       , err, ep->stid,
3171830662f6SVipul Pandya 		       &sin->sin_addr, ntohs(sin->sin_port));
3172830662f6SVipul Pandya 	return err;
3173830662f6SVipul Pandya }
3174830662f6SVipul Pandya 
3175cfdda9d7SSteve Wise int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog)
3176cfdda9d7SSteve Wise {
3177cfdda9d7SSteve Wise 	int err = 0;
3178cfdda9d7SSteve Wise 	struct c4iw_dev *dev = to_c4iw_dev(cm_id->device);
3179cfdda9d7SSteve Wise 	struct c4iw_listen_ep *ep;
31809eccfe10SSteve Wise 	struct iwpm_dev_data pm_reg_msg;
31819eccfe10SSteve Wise 	struct iwpm_sa_data pm_msg;
31829eccfe10SSteve Wise 	int iwpm_err = 0;
3183cfdda9d7SSteve Wise 
3184cfdda9d7SSteve Wise 	might_sleep();
3185cfdda9d7SSteve Wise 
3186cfdda9d7SSteve Wise 	ep = alloc_ep(sizeof(*ep), GFP_KERNEL);
3187cfdda9d7SSteve Wise 	if (!ep) {
3188cfdda9d7SSteve Wise 		printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __func__);
3189cfdda9d7SSteve Wise 		err = -ENOMEM;
3190cfdda9d7SSteve Wise 		goto fail1;
3191cfdda9d7SSteve Wise 	}
3192cfdda9d7SSteve Wise 	PDBG("%s ep %p\n", __func__, ep);
3193cfdda9d7SSteve Wise 	cm_id->add_ref(cm_id);
3194cfdda9d7SSteve Wise 	ep->com.cm_id = cm_id;
3195cfdda9d7SSteve Wise 	ep->com.dev = dev;
3196cfdda9d7SSteve Wise 	ep->backlog = backlog;
319724d44a39SSteve Wise 	memcpy(&ep->com.local_addr, &cm_id->local_addr,
319824d44a39SSteve Wise 	       sizeof(ep->com.local_addr));
3199cfdda9d7SSteve Wise 
3200cfdda9d7SSteve Wise 	/*
3201cfdda9d7SSteve Wise 	 * Allocate a server TID.
3202cfdda9d7SSteve Wise 	 */
32038c044690SKumar Sanghvi 	if (dev->rdev.lldi.enable_fw_ofld_conn &&
32048c044690SKumar Sanghvi 	    ep->com.local_addr.ss_family == AF_INET)
3205830662f6SVipul Pandya 		ep->stid = cxgb4_alloc_sftid(dev->rdev.lldi.tids,
3206830662f6SVipul Pandya 					     cm_id->local_addr.ss_family, ep);
32071cab775cSVipul Pandya 	else
3208830662f6SVipul Pandya 		ep->stid = cxgb4_alloc_stid(dev->rdev.lldi.tids,
3209830662f6SVipul Pandya 					    cm_id->local_addr.ss_family, ep);
32101cab775cSVipul Pandya 
3211cfdda9d7SSteve Wise 	if (ep->stid == -1) {
3212be4c9badSRoland Dreier 		printk(KERN_ERR MOD "%s - cannot alloc stid.\n", __func__);
3213cfdda9d7SSteve Wise 		err = -ENOMEM;
3214cfdda9d7SSteve Wise 		goto fail2;
3215cfdda9d7SSteve Wise 	}
3216793dad94SVipul Pandya 	insert_handle(dev, &dev->stid_idr, ep, ep->stid);
32179eccfe10SSteve Wise 
32189eccfe10SSteve Wise 	/* No port mapper available, go with the specified info */
32199eccfe10SSteve Wise 	memcpy(&ep->com.mapped_local_addr, &cm_id->local_addr,
32209eccfe10SSteve Wise 	       sizeof(ep->com.mapped_local_addr));
32219eccfe10SSteve Wise 
32229eccfe10SSteve Wise 	c4iw_form_reg_msg(dev, &pm_reg_msg);
32239eccfe10SSteve Wise 	iwpm_err = iwpm_register_pid(&pm_reg_msg, RDMA_NL_C4IW);
32249eccfe10SSteve Wise 	if (iwpm_err) {
32259eccfe10SSteve Wise 		PDBG("%s: Port Mapper reg pid fail (err = %d).\n",
32269eccfe10SSteve Wise 			__func__, iwpm_err);
32279eccfe10SSteve Wise 	}
32289eccfe10SSteve Wise 	if (iwpm_valid_pid() && !iwpm_err) {
32299eccfe10SSteve Wise 		memcpy(&pm_msg.loc_addr, &ep->com.local_addr,
32309eccfe10SSteve Wise 				sizeof(ep->com.local_addr));
32319eccfe10SSteve Wise 		iwpm_err = iwpm_add_mapping(&pm_msg, RDMA_NL_C4IW);
32329eccfe10SSteve Wise 		if (iwpm_err)
32339eccfe10SSteve Wise 			PDBG("%s: Port Mapper query fail (err = %d).\n",
32349eccfe10SSteve Wise 				__func__, iwpm_err);
32359eccfe10SSteve Wise 		else
32369eccfe10SSteve Wise 			memcpy(&ep->com.mapped_local_addr,
32379eccfe10SSteve Wise 				&pm_msg.mapped_loc_addr,
32389eccfe10SSteve Wise 				sizeof(ep->com.mapped_local_addr));
32399eccfe10SSteve Wise 	}
32409eccfe10SSteve Wise 	if (iwpm_create_mapinfo(&ep->com.local_addr,
32419eccfe10SSteve Wise 				&ep->com.mapped_local_addr, RDMA_NL_C4IW)) {
32429eccfe10SSteve Wise 		err = -ENOMEM;
32439eccfe10SSteve Wise 		goto fail3;
32449eccfe10SSteve Wise 	}
32459eccfe10SSteve Wise 	print_addr(&ep->com, __func__, "add_mapping/create_mapinfo");
32469eccfe10SSteve Wise 
32479eccfe10SSteve Wise 	set_bit(RELEASE_MAPINFO, &ep->com.flags);
3248cfdda9d7SSteve Wise 	state_set(&ep->com, LISTEN);
3249830662f6SVipul Pandya 	if (ep->com.local_addr.ss_family == AF_INET)
3250830662f6SVipul Pandya 		err = create_server4(dev, ep);
3251830662f6SVipul Pandya 	else
3252830662f6SVipul Pandya 		err = create_server6(dev, ep);
3253cfdda9d7SSteve Wise 	if (!err) {
3254cfdda9d7SSteve Wise 		cm_id->provider_data = ep;
3255cfdda9d7SSteve Wise 		goto out;
3256cfdda9d7SSteve Wise 	}
32579eccfe10SSteve Wise 
32589eccfe10SSteve Wise fail3:
3259830662f6SVipul Pandya 	cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid,
3260830662f6SVipul Pandya 			ep->com.local_addr.ss_family);
3261cfdda9d7SSteve Wise fail2:
3262cfdda9d7SSteve Wise 	cm_id->rem_ref(cm_id);
3263cfdda9d7SSteve Wise 	c4iw_put_ep(&ep->com);
3264cfdda9d7SSteve Wise fail1:
3265cfdda9d7SSteve Wise out:
3266cfdda9d7SSteve Wise 	return err;
3267cfdda9d7SSteve Wise }
3268cfdda9d7SSteve Wise 
3269cfdda9d7SSteve Wise int c4iw_destroy_listen(struct iw_cm_id *cm_id)
3270cfdda9d7SSteve Wise {
3271cfdda9d7SSteve Wise 	int err;
3272cfdda9d7SSteve Wise 	struct c4iw_listen_ep *ep = to_listen_ep(cm_id);
3273cfdda9d7SSteve Wise 
3274cfdda9d7SSteve Wise 	PDBG("%s ep %p\n", __func__, ep);
3275cfdda9d7SSteve Wise 
3276cfdda9d7SSteve Wise 	might_sleep();
3277cfdda9d7SSteve Wise 	state_set(&ep->com, DEAD);
3278830662f6SVipul Pandya 	if (ep->com.dev->rdev.lldi.enable_fw_ofld_conn &&
3279830662f6SVipul Pandya 	    ep->com.local_addr.ss_family == AF_INET) {
32801cab775cSVipul Pandya 		err = cxgb4_remove_server_filter(
32811cab775cSVipul Pandya 			ep->com.dev->rdev.lldi.ports[0], ep->stid,
32821cab775cSVipul Pandya 			ep->com.dev->rdev.lldi.rxq_ids[0], 0);
32831cab775cSVipul Pandya 	} else {
3284aadc4df3SSteve Wise 		c4iw_init_wr_wait(&ep->com.wr_wait);
3285830662f6SVipul Pandya 		err = cxgb4_remove_server(
3286830662f6SVipul Pandya 				ep->com.dev->rdev.lldi.ports[0], ep->stid,
3287830662f6SVipul Pandya 				ep->com.dev->rdev.lldi.rxq_ids[0], 0);
3288cfdda9d7SSteve Wise 		if (err)
3289cfdda9d7SSteve Wise 			goto done;
32901cab775cSVipul Pandya 		err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait,
32911cab775cSVipul Pandya 					  0, 0, __func__);
32921cab775cSVipul Pandya 	}
3293793dad94SVipul Pandya 	remove_handle(ep->com.dev, &ep->com.dev->stid_idr, ep->stid);
3294830662f6SVipul Pandya 	cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid,
3295830662f6SVipul Pandya 			ep->com.local_addr.ss_family);
3296cfdda9d7SSteve Wise done:
3297cfdda9d7SSteve Wise 	cm_id->rem_ref(cm_id);
3298cfdda9d7SSteve Wise 	c4iw_put_ep(&ep->com);
3299cfdda9d7SSteve Wise 	return err;
3300cfdda9d7SSteve Wise }
3301cfdda9d7SSteve Wise 
3302cfdda9d7SSteve Wise int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
3303cfdda9d7SSteve Wise {
3304cfdda9d7SSteve Wise 	int ret = 0;
3305cfdda9d7SSteve Wise 	int close = 0;
3306cfdda9d7SSteve Wise 	int fatal = 0;
3307cfdda9d7SSteve Wise 	struct c4iw_rdev *rdev;
3308cfdda9d7SSteve Wise 
33092f5b48c3SSteve Wise 	mutex_lock(&ep->com.mutex);
3310cfdda9d7SSteve Wise 
3311cfdda9d7SSteve Wise 	PDBG("%s ep %p state %s, abrupt %d\n", __func__, ep,
3312cfdda9d7SSteve Wise 	     states[ep->com.state], abrupt);
3313cfdda9d7SSteve Wise 
3314cfdda9d7SSteve Wise 	rdev = &ep->com.dev->rdev;
3315cfdda9d7SSteve Wise 	if (c4iw_fatal_error(rdev)) {
3316cfdda9d7SSteve Wise 		fatal = 1;
3317be13b2dfSSteve Wise 		close_complete_upcall(ep, -EIO);
3318cfdda9d7SSteve Wise 		ep->com.state = DEAD;
3319cfdda9d7SSteve Wise 	}
3320cfdda9d7SSteve Wise 	switch (ep->com.state) {
3321cfdda9d7SSteve Wise 	case MPA_REQ_WAIT:
3322cfdda9d7SSteve Wise 	case MPA_REQ_SENT:
3323cfdda9d7SSteve Wise 	case MPA_REQ_RCVD:
3324cfdda9d7SSteve Wise 	case MPA_REP_SENT:
3325cfdda9d7SSteve Wise 	case FPDU_MODE:
3326cfdda9d7SSteve Wise 		close = 1;
3327cfdda9d7SSteve Wise 		if (abrupt)
3328cfdda9d7SSteve Wise 			ep->com.state = ABORTING;
3329cfdda9d7SSteve Wise 		else {
3330cfdda9d7SSteve Wise 			ep->com.state = CLOSING;
3331ca5a2202SSteve Wise 			start_ep_timer(ep);
3332cfdda9d7SSteve Wise 		}
3333cfdda9d7SSteve Wise 		set_bit(CLOSE_SENT, &ep->com.flags);
3334cfdda9d7SSteve Wise 		break;
3335cfdda9d7SSteve Wise 	case CLOSING:
3336cfdda9d7SSteve Wise 		if (!test_and_set_bit(CLOSE_SENT, &ep->com.flags)) {
3337cfdda9d7SSteve Wise 			close = 1;
3338cfdda9d7SSteve Wise 			if (abrupt) {
3339b33bd0cbSSteve Wise 				(void)stop_ep_timer(ep);
3340cfdda9d7SSteve Wise 				ep->com.state = ABORTING;
3341cfdda9d7SSteve Wise 			} else
3342cfdda9d7SSteve Wise 				ep->com.state = MORIBUND;
3343cfdda9d7SSteve Wise 		}
3344cfdda9d7SSteve Wise 		break;
3345cfdda9d7SSteve Wise 	case MORIBUND:
3346cfdda9d7SSteve Wise 	case ABORTING:
3347cfdda9d7SSteve Wise 	case DEAD:
3348cfdda9d7SSteve Wise 		PDBG("%s ignoring disconnect ep %p state %u\n",
3349cfdda9d7SSteve Wise 		     __func__, ep, ep->com.state);
3350cfdda9d7SSteve Wise 		break;
3351cfdda9d7SSteve Wise 	default:
3352cfdda9d7SSteve Wise 		BUG();
3353cfdda9d7SSteve Wise 		break;
3354cfdda9d7SSteve Wise 	}
3355cfdda9d7SSteve Wise 
3356cfdda9d7SSteve Wise 	if (close) {
33578da7e7a5SSteve Wise 		if (abrupt) {
3358793dad94SVipul Pandya 			set_bit(EP_DISC_ABORT, &ep->com.history);
3359be13b2dfSSteve Wise 			close_complete_upcall(ep, -ECONNRESET);
33608da7e7a5SSteve Wise 			ret = send_abort(ep, NULL, gfp);
3361793dad94SVipul Pandya 		} else {
3362793dad94SVipul Pandya 			set_bit(EP_DISC_CLOSE, &ep->com.history);
3363cfdda9d7SSteve Wise 			ret = send_halfclose(ep, gfp);
3364793dad94SVipul Pandya 		}
3365cfdda9d7SSteve Wise 		if (ret)
3366cfdda9d7SSteve Wise 			fatal = 1;
3367cfdda9d7SSteve Wise 	}
33688da7e7a5SSteve Wise 	mutex_unlock(&ep->com.mutex);
3369cfdda9d7SSteve Wise 	if (fatal)
3370cfdda9d7SSteve Wise 		release_ep_resources(ep);
3371cfdda9d7SSteve Wise 	return ret;
3372cfdda9d7SSteve Wise }
3373cfdda9d7SSteve Wise 
33741cab775cSVipul Pandya static void active_ofld_conn_reply(struct c4iw_dev *dev, struct sk_buff *skb,
33751cab775cSVipul Pandya 			struct cpl_fw6_msg_ofld_connection_wr_rpl *req)
33761cab775cSVipul Pandya {
33771cab775cSVipul Pandya 	struct c4iw_ep *ep;
3378793dad94SVipul Pandya 	int atid = be32_to_cpu(req->tid);
33791cab775cSVipul Pandya 
3380ef5d6355SVipul Pandya 	ep = (struct c4iw_ep *)lookup_atid(dev->rdev.lldi.tids,
3381ef5d6355SVipul Pandya 					   (__force u32) req->tid);
33821cab775cSVipul Pandya 	if (!ep)
33831cab775cSVipul Pandya 		return;
33841cab775cSVipul Pandya 
33851cab775cSVipul Pandya 	switch (req->retval) {
33861cab775cSVipul Pandya 	case FW_ENOMEM:
3387793dad94SVipul Pandya 		set_bit(ACT_RETRY_NOMEM, &ep->com.history);
3388793dad94SVipul Pandya 		if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) {
3389793dad94SVipul Pandya 			send_fw_act_open_req(ep, atid);
3390793dad94SVipul Pandya 			return;
3391793dad94SVipul Pandya 		}
33921cab775cSVipul Pandya 	case FW_EADDRINUSE:
3393793dad94SVipul Pandya 		set_bit(ACT_RETRY_INUSE, &ep->com.history);
3394793dad94SVipul Pandya 		if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) {
3395793dad94SVipul Pandya 			send_fw_act_open_req(ep, atid);
3396793dad94SVipul Pandya 			return;
3397793dad94SVipul Pandya 		}
33981cab775cSVipul Pandya 		break;
33991cab775cSVipul Pandya 	default:
34001cab775cSVipul Pandya 		pr_info("%s unexpected ofld conn wr retval %d\n",
34011cab775cSVipul Pandya 		       __func__, req->retval);
34021cab775cSVipul Pandya 		break;
34031cab775cSVipul Pandya 	}
3404793dad94SVipul Pandya 	pr_err("active ofld_connect_wr failure %d atid %d\n",
3405793dad94SVipul Pandya 	       req->retval, atid);
3406793dad94SVipul Pandya 	mutex_lock(&dev->rdev.stats.lock);
3407793dad94SVipul Pandya 	dev->rdev.stats.act_ofld_conn_fails++;
3408793dad94SVipul Pandya 	mutex_unlock(&dev->rdev.stats.lock);
34091cab775cSVipul Pandya 	connect_reply_upcall(ep, status2errno(req->retval));
3410793dad94SVipul Pandya 	state_set(&ep->com, DEAD);
3411793dad94SVipul Pandya 	remove_handle(dev, &dev->atid_idr, atid);
3412793dad94SVipul Pandya 	cxgb4_free_atid(dev->rdev.lldi.tids, atid);
3413793dad94SVipul Pandya 	dst_release(ep->dst);
3414793dad94SVipul Pandya 	cxgb4_l2t_release(ep->l2t);
3415793dad94SVipul Pandya 	c4iw_put_ep(&ep->com);
34161cab775cSVipul Pandya }
34171cab775cSVipul Pandya 
34181cab775cSVipul Pandya static void passive_ofld_conn_reply(struct c4iw_dev *dev, struct sk_buff *skb,
34191cab775cSVipul Pandya 			struct cpl_fw6_msg_ofld_connection_wr_rpl *req)
34201cab775cSVipul Pandya {
34211cab775cSVipul Pandya 	struct sk_buff *rpl_skb;
34221cab775cSVipul Pandya 	struct cpl_pass_accept_req *cpl;
34231cab775cSVipul Pandya 	int ret;
34241cab775cSVipul Pandya 
3425710a3110SPaul Bolle 	rpl_skb = (struct sk_buff *)(unsigned long)req->cookie;
34261cab775cSVipul Pandya 	BUG_ON(!rpl_skb);
34271cab775cSVipul Pandya 	if (req->retval) {
34281cab775cSVipul Pandya 		PDBG("%s passive open failure %d\n", __func__, req->retval);
3429793dad94SVipul Pandya 		mutex_lock(&dev->rdev.stats.lock);
3430793dad94SVipul Pandya 		dev->rdev.stats.pas_ofld_conn_fails++;
3431793dad94SVipul Pandya 		mutex_unlock(&dev->rdev.stats.lock);
34321cab775cSVipul Pandya 		kfree_skb(rpl_skb);
34331cab775cSVipul Pandya 	} else {
34341cab775cSVipul Pandya 		cpl = (struct cpl_pass_accept_req *)cplhdr(rpl_skb);
34351cab775cSVipul Pandya 		OPCODE_TID(cpl) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_REQ,
3436ef5d6355SVipul Pandya 					(__force u32) htonl(
3437ef5d6355SVipul Pandya 					(__force u32) req->tid)));
34381cab775cSVipul Pandya 		ret = pass_accept_req(dev, rpl_skb);
34391cab775cSVipul Pandya 		if (!ret)
34401cab775cSVipul Pandya 			kfree_skb(rpl_skb);
34411cab775cSVipul Pandya 	}
34421cab775cSVipul Pandya 	return;
34431cab775cSVipul Pandya }
34441cab775cSVipul Pandya 
34451cab775cSVipul Pandya static int deferred_fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb)
34462f5b48c3SSteve Wise {
34472f5b48c3SSteve Wise 	struct cpl_fw6_msg *rpl = cplhdr(skb);
34481cab775cSVipul Pandya 	struct cpl_fw6_msg_ofld_connection_wr_rpl *req;
34491cab775cSVipul Pandya 
34501cab775cSVipul Pandya 	switch (rpl->type) {
34511cab775cSVipul Pandya 	case FW6_TYPE_CQE:
34522f5b48c3SSteve Wise 		c4iw_ev_dispatch(dev, (struct t4_cqe *)&rpl->data[0]);
34531cab775cSVipul Pandya 		break;
34541cab775cSVipul Pandya 	case FW6_TYPE_OFLD_CONNECTION_WR_RPL:
34551cab775cSVipul Pandya 		req = (struct cpl_fw6_msg_ofld_connection_wr_rpl *)rpl->data;
34561cab775cSVipul Pandya 		switch (req->t_state) {
34571cab775cSVipul Pandya 		case TCP_SYN_SENT:
34581cab775cSVipul Pandya 			active_ofld_conn_reply(dev, skb, req);
34591cab775cSVipul Pandya 			break;
34601cab775cSVipul Pandya 		case TCP_SYN_RECV:
34611cab775cSVipul Pandya 			passive_ofld_conn_reply(dev, skb, req);
34621cab775cSVipul Pandya 			break;
34631cab775cSVipul Pandya 		default:
34641cab775cSVipul Pandya 			pr_err("%s unexpected ofld conn wr state %d\n",
34651cab775cSVipul Pandya 			       __func__, req->t_state);
34661cab775cSVipul Pandya 			break;
34671cab775cSVipul Pandya 		}
34681cab775cSVipul Pandya 		break;
34691cab775cSVipul Pandya 	}
34701cab775cSVipul Pandya 	return 0;
34711cab775cSVipul Pandya }
34721cab775cSVipul Pandya 
34731cab775cSVipul Pandya static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos)
34741cab775cSVipul Pandya {
34751cab775cSVipul Pandya 	u32 l2info;
3476f079af7aSVipul Pandya 	u16 vlantag, len, hdr_len, eth_hdr_len;
34771cab775cSVipul Pandya 	u8 intf;
34781cab775cSVipul Pandya 	struct cpl_rx_pkt *cpl = cplhdr(skb);
34791cab775cSVipul Pandya 	struct cpl_pass_accept_req *req;
34801cab775cSVipul Pandya 	struct tcp_options_received tmp_opt;
3481f079af7aSVipul Pandya 	struct c4iw_dev *dev;
34821cab775cSVipul Pandya 
3483f079af7aSVipul Pandya 	dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *)));
34841cab775cSVipul Pandya 	/* Store values from cpl_rx_pkt in temporary location. */
3485ef5d6355SVipul Pandya 	vlantag = (__force u16) cpl->vlan;
3486ef5d6355SVipul Pandya 	len = (__force u16) cpl->len;
3487ef5d6355SVipul Pandya 	l2info  = (__force u32) cpl->l2info;
3488ef5d6355SVipul Pandya 	hdr_len = (__force u16) cpl->hdr_len;
34891cab775cSVipul Pandya 	intf = cpl->iff;
34901cab775cSVipul Pandya 
34911cab775cSVipul Pandya 	__skb_pull(skb, sizeof(*req) + sizeof(struct rss_header));
34921cab775cSVipul Pandya 
34931cab775cSVipul Pandya 	/*
34941cab775cSVipul Pandya 	 * We need to parse the TCP options from SYN packet.
34951cab775cSVipul Pandya 	 * to generate cpl_pass_accept_req.
34961cab775cSVipul Pandya 	 */
34971cab775cSVipul Pandya 	memset(&tmp_opt, 0, sizeof(tmp_opt));
34981cab775cSVipul Pandya 	tcp_clear_options(&tmp_opt);
34991a2c6181SChristoph Paasch 	tcp_parse_options(skb, &tmp_opt, 0, NULL);
35001cab775cSVipul Pandya 
35011cab775cSVipul Pandya 	req = (struct cpl_pass_accept_req *)__skb_push(skb, sizeof(*req));
35021cab775cSVipul Pandya 	memset(req, 0, sizeof(*req));
35031cab775cSVipul Pandya 	req->l2info = cpu_to_be16(V_SYN_INTF(intf) |
3504ef5d6355SVipul Pandya 			 V_SYN_MAC_IDX(G_RX_MACIDX(
3505ef5d6355SVipul Pandya 			 (__force int) htonl(l2info))) |
35061cab775cSVipul Pandya 			 F_SYN_XACT_MATCH);
3507f079af7aSVipul Pandya 	eth_hdr_len = is_t4(dev->rdev.lldi.adapter_type) ?
3508f079af7aSVipul Pandya 			    G_RX_ETHHDR_LEN((__force int) htonl(l2info)) :
3509f079af7aSVipul Pandya 			    G_RX_T5_ETHHDR_LEN((__force int) htonl(l2info));
3510ef5d6355SVipul Pandya 	req->hdr_len = cpu_to_be32(V_SYN_RX_CHAN(G_RX_CHAN(
3511ef5d6355SVipul Pandya 					(__force int) htonl(l2info))) |
3512ef5d6355SVipul Pandya 				   V_TCP_HDR_LEN(G_RX_TCPHDR_LEN(
3513ef5d6355SVipul Pandya 					(__force int) htons(hdr_len))) |
3514ef5d6355SVipul Pandya 				   V_IP_HDR_LEN(G_RX_IPHDR_LEN(
3515ef5d6355SVipul Pandya 					(__force int) htons(hdr_len))) |
3516f079af7aSVipul Pandya 				   V_ETH_HDR_LEN(G_RX_ETHHDR_LEN(eth_hdr_len)));
3517ef5d6355SVipul Pandya 	req->vlan = (__force __be16) vlantag;
3518ef5d6355SVipul Pandya 	req->len = (__force __be16) len;
35196c53e938SHariprasad Shenai 	req->tos_stid = cpu_to_be32(PASS_OPEN_TID_V(stid) |
35206c53e938SHariprasad Shenai 				    PASS_OPEN_TOS_V(tos));
35211cab775cSVipul Pandya 	req->tcpopt.mss = htons(tmp_opt.mss_clamp);
35221cab775cSVipul Pandya 	if (tmp_opt.wscale_ok)
35231cab775cSVipul Pandya 		req->tcpopt.wsf = tmp_opt.snd_wscale;
35241cab775cSVipul Pandya 	req->tcpopt.tstamp = tmp_opt.saw_tstamp;
35251cab775cSVipul Pandya 	if (tmp_opt.sack_ok)
35261cab775cSVipul Pandya 		req->tcpopt.sack = 1;
35271cab775cSVipul Pandya 	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_REQ, 0));
35281cab775cSVipul Pandya 	return;
35291cab775cSVipul Pandya }
35301cab775cSVipul Pandya 
35311cab775cSVipul Pandya static void send_fw_pass_open_req(struct c4iw_dev *dev, struct sk_buff *skb,
35321cab775cSVipul Pandya 				  __be32 laddr, __be16 lport,
35331cab775cSVipul Pandya 				  __be32 raddr, __be16 rport,
35341cab775cSVipul Pandya 				  u32 rcv_isn, u32 filter, u16 window,
35351cab775cSVipul Pandya 				  u32 rss_qid, u8 port_id)
35361cab775cSVipul Pandya {
35371cab775cSVipul Pandya 	struct sk_buff *req_skb;
35381cab775cSVipul Pandya 	struct fw_ofld_connection_wr *req;
35391cab775cSVipul Pandya 	struct cpl_pass_accept_req *cpl = cplhdr(skb);
35401ce1d471SSteve Wise 	int ret;
35411cab775cSVipul Pandya 
35421cab775cSVipul Pandya 	req_skb = alloc_skb(sizeof(struct fw_ofld_connection_wr), GFP_KERNEL);
35431cab775cSVipul Pandya 	req = (struct fw_ofld_connection_wr *)__skb_put(req_skb, sizeof(*req));
35441cab775cSVipul Pandya 	memset(req, 0, sizeof(*req));
35456c53e938SHariprasad Shenai 	req->op_compl = htonl(WR_OP_V(FW_OFLD_CONNECTION_WR) | FW_WR_COMPL_F);
3546e2ac9628SHariprasad Shenai 	req->len16_pkd = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*req), 16)));
354777a80e23SHariprasad Shenai 	req->le.version_cpl = htonl(FW_OFLD_CONNECTION_WR_CPL_F);
3548ef5d6355SVipul Pandya 	req->le.filter = (__force __be32) filter;
35491cab775cSVipul Pandya 	req->le.lport = lport;
35501cab775cSVipul Pandya 	req->le.pport = rport;
35511cab775cSVipul Pandya 	req->le.u.ipv4.lip = laddr;
35521cab775cSVipul Pandya 	req->le.u.ipv4.pip = raddr;
35531cab775cSVipul Pandya 	req->tcb.rcv_nxt = htonl(rcv_isn + 1);
35541cab775cSVipul Pandya 	req->tcb.rcv_adv = htons(window);
35551cab775cSVipul Pandya 	req->tcb.t_state_to_astid =
355677a80e23SHariprasad Shenai 		 htonl(FW_OFLD_CONNECTION_WR_T_STATE_V(TCP_SYN_RECV) |
355777a80e23SHariprasad Shenai 			FW_OFLD_CONNECTION_WR_RCV_SCALE_V(cpl->tcpopt.wsf) |
355877a80e23SHariprasad Shenai 			FW_OFLD_CONNECTION_WR_ASTID_V(
35596c53e938SHariprasad Shenai 			PASS_OPEN_TID_G(ntohl(cpl->tos_stid))));
35601cab775cSVipul Pandya 
35611cab775cSVipul Pandya 	/*
35621cab775cSVipul Pandya 	 * We store the qid in opt2 which will be used by the firmware
35631cab775cSVipul Pandya 	 * to send us the wr response.
35641cab775cSVipul Pandya 	 */
3565d7990b0cSAnish Bhatt 	req->tcb.opt2 = htonl(RSS_QUEUE_V(rss_qid));
35661cab775cSVipul Pandya 
35671cab775cSVipul Pandya 	/*
35681cab775cSVipul Pandya 	 * We initialize the MSS index in TCB to 0xF.
35691cab775cSVipul Pandya 	 * So that when driver sends cpl_pass_accept_rpl
35701cab775cSVipul Pandya 	 * TCB picks up the correct value. If this was 0
35711cab775cSVipul Pandya 	 * TP will ignore any value > 0 for MSS index.
35721cab775cSVipul Pandya 	 */
3573d7990b0cSAnish Bhatt 	req->tcb.opt0 = cpu_to_be64(MSS_IDX_V(0xF));
3574710a3110SPaul Bolle 	req->cookie = (unsigned long)skb;
35751cab775cSVipul Pandya 
35761cab775cSVipul Pandya 	set_wr_txq(req_skb, CPL_PRIORITY_CONTROL, port_id);
35771ce1d471SSteve Wise 	ret = cxgb4_ofld_send(dev->rdev.lldi.ports[0], req_skb);
35781ce1d471SSteve Wise 	if (ret < 0) {
35791ce1d471SSteve Wise 		pr_err("%s - cxgb4_ofld_send error %d - dropping\n", __func__,
35801ce1d471SSteve Wise 		       ret);
35811ce1d471SSteve Wise 		kfree_skb(skb);
35821ce1d471SSteve Wise 		kfree_skb(req_skb);
35831ce1d471SSteve Wise 	}
35841cab775cSVipul Pandya }
35851cab775cSVipul Pandya 
35861cab775cSVipul Pandya /*
35871cab775cSVipul Pandya  * Handler for CPL_RX_PKT message. Need to handle cpl_rx_pkt
35881cab775cSVipul Pandya  * messages when a filter is being used instead of server to
35891cab775cSVipul Pandya  * redirect a syn packet. When packets hit filter they are redirected
35901cab775cSVipul Pandya  * to the offload queue and driver tries to establish the connection
35911cab775cSVipul Pandya  * using firmware work request.
35921cab775cSVipul Pandya  */
35931cab775cSVipul Pandya static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
35941cab775cSVipul Pandya {
35951cab775cSVipul Pandya 	int stid;
35961cab775cSVipul Pandya 	unsigned int filter;
35971cab775cSVipul Pandya 	struct ethhdr *eh = NULL;
35981cab775cSVipul Pandya 	struct vlan_ethhdr *vlan_eh = NULL;
35991cab775cSVipul Pandya 	struct iphdr *iph;
36001cab775cSVipul Pandya 	struct tcphdr *tcph;
36011cab775cSVipul Pandya 	struct rss_header *rss = (void *)skb->data;
36021cab775cSVipul Pandya 	struct cpl_rx_pkt *cpl = (void *)skb->data;
36031cab775cSVipul Pandya 	struct cpl_pass_accept_req *req = (void *)(rss + 1);
36041cab775cSVipul Pandya 	struct l2t_entry *e;
36051cab775cSVipul Pandya 	struct dst_entry *dst;
36061cab775cSVipul Pandya 	struct c4iw_ep *lep;
36071cab775cSVipul Pandya 	u16 window;
36081cab775cSVipul Pandya 	struct port_info *pi;
36091cab775cSVipul Pandya 	struct net_device *pdev;
3610f079af7aSVipul Pandya 	u16 rss_qid, eth_hdr_len;
36111cab775cSVipul Pandya 	int step;
36121cab775cSVipul Pandya 	u32 tx_chan;
36131cab775cSVipul Pandya 	struct neighbour *neigh;
36141cab775cSVipul Pandya 
36151cab775cSVipul Pandya 	/* Drop all non-SYN packets */
36161cab775cSVipul Pandya 	if (!(cpl->l2info & cpu_to_be32(F_RXF_SYN)))
36171cab775cSVipul Pandya 		goto reject;
36181cab775cSVipul Pandya 
36191cab775cSVipul Pandya 	/*
36201cab775cSVipul Pandya 	 * Drop all packets which did not hit the filter.
36211cab775cSVipul Pandya 	 * Unlikely to happen.
36221cab775cSVipul Pandya 	 */
36231cab775cSVipul Pandya 	if (!(rss->filter_hit && rss->filter_tid))
36241cab775cSVipul Pandya 		goto reject;
36251cab775cSVipul Pandya 
36261cab775cSVipul Pandya 	/*
36271cab775cSVipul Pandya 	 * Calculate the server tid from filter hit index from cpl_rx_pkt.
36281cab775cSVipul Pandya 	 */
3629a4ea025fSKumar Sanghvi 	stid = (__force int) cpu_to_be32((__force u32) rss->hash_val);
36301cab775cSVipul Pandya 
36311cab775cSVipul Pandya 	lep = (struct c4iw_ep *)lookup_stid(dev->rdev.lldi.tids, stid);
36321cab775cSVipul Pandya 	if (!lep) {
36331cab775cSVipul Pandya 		PDBG("%s connect request on invalid stid %d\n", __func__, stid);
36341cab775cSVipul Pandya 		goto reject;
36351cab775cSVipul Pandya 	}
36361cab775cSVipul Pandya 
3637f079af7aSVipul Pandya 	eth_hdr_len = is_t4(dev->rdev.lldi.adapter_type) ?
3638f079af7aSVipul Pandya 			    G_RX_ETHHDR_LEN(htonl(cpl->l2info)) :
3639f079af7aSVipul Pandya 			    G_RX_T5_ETHHDR_LEN(htonl(cpl->l2info));
3640f079af7aSVipul Pandya 	if (eth_hdr_len == ETH_HLEN) {
36411cab775cSVipul Pandya 		eh = (struct ethhdr *)(req + 1);
36421cab775cSVipul Pandya 		iph = (struct iphdr *)(eh + 1);
36431cab775cSVipul Pandya 	} else {
36441cab775cSVipul Pandya 		vlan_eh = (struct vlan_ethhdr *)(req + 1);
36451cab775cSVipul Pandya 		iph = (struct iphdr *)(vlan_eh + 1);
36461cab775cSVipul Pandya 		skb->vlan_tci = ntohs(cpl->vlan);
36471cab775cSVipul Pandya 	}
36481cab775cSVipul Pandya 
36491cab775cSVipul Pandya 	if (iph->version != 0x4)
36501cab775cSVipul Pandya 		goto reject;
36511cab775cSVipul Pandya 
36521cab775cSVipul Pandya 	tcph = (struct tcphdr *)(iph + 1);
36531cab775cSVipul Pandya 	skb_set_network_header(skb, (void *)iph - (void *)rss);
36541cab775cSVipul Pandya 	skb_set_transport_header(skb, (void *)tcph - (void *)rss);
36551cab775cSVipul Pandya 	skb_get(skb);
36561cab775cSVipul Pandya 
36571cab775cSVipul Pandya 	PDBG("%s lip 0x%x lport %u pip 0x%x pport %u tos %d\n", __func__,
36581cab775cSVipul Pandya 	     ntohl(iph->daddr), ntohs(tcph->dest), ntohl(iph->saddr),
36591cab775cSVipul Pandya 	     ntohs(tcph->source), iph->tos);
36601cab775cSVipul Pandya 
3661830662f6SVipul Pandya 	dst = find_route(dev, iph->daddr, iph->saddr, tcph->dest, tcph->source,
36621cab775cSVipul Pandya 			 iph->tos);
3663830662f6SVipul Pandya 	if (!dst) {
36641cab775cSVipul Pandya 		pr_err("%s - failed to find dst entry!\n",
36651cab775cSVipul Pandya 		       __func__);
36661cab775cSVipul Pandya 		goto reject;
36671cab775cSVipul Pandya 	}
36681cab775cSVipul Pandya 	neigh = dst_neigh_lookup_skb(dst, skb);
36691cab775cSVipul Pandya 
3670aaa0c23cSZhouyi Zhou 	if (!neigh) {
3671aaa0c23cSZhouyi Zhou 		pr_err("%s - failed to allocate neigh!\n",
3672aaa0c23cSZhouyi Zhou 		       __func__);
3673aaa0c23cSZhouyi Zhou 		goto free_dst;
3674aaa0c23cSZhouyi Zhou 	}
3675aaa0c23cSZhouyi Zhou 
36761cab775cSVipul Pandya 	if (neigh->dev->flags & IFF_LOOPBACK) {
36771cab775cSVipul Pandya 		pdev = ip_dev_find(&init_net, iph->daddr);
36781cab775cSVipul Pandya 		e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh,
36791cab775cSVipul Pandya 				    pdev, 0);
36801cab775cSVipul Pandya 		pi = (struct port_info *)netdev_priv(pdev);
36811cab775cSVipul Pandya 		tx_chan = cxgb4_port_chan(pdev);
36821cab775cSVipul Pandya 		dev_put(pdev);
36831cab775cSVipul Pandya 	} else {
3684830662f6SVipul Pandya 		pdev = get_real_dev(neigh->dev);
36851cab775cSVipul Pandya 		e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh,
3686830662f6SVipul Pandya 					pdev, 0);
3687830662f6SVipul Pandya 		pi = (struct port_info *)netdev_priv(pdev);
3688830662f6SVipul Pandya 		tx_chan = cxgb4_port_chan(pdev);
36891cab775cSVipul Pandya 	}
3690ebf00060SSteve Wise 	neigh_release(neigh);
36911cab775cSVipul Pandya 	if (!e) {
36921cab775cSVipul Pandya 		pr_err("%s - failed to allocate l2t entry!\n",
36931cab775cSVipul Pandya 		       __func__);
36941cab775cSVipul Pandya 		goto free_dst;
36951cab775cSVipul Pandya 	}
36961cab775cSVipul Pandya 
36971cab775cSVipul Pandya 	step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan;
36981cab775cSVipul Pandya 	rss_qid = dev->rdev.lldi.rxq_ids[pi->port_id * step];
3699ef5d6355SVipul Pandya 	window = (__force u16) htons((__force u16)tcph->window);
37001cab775cSVipul Pandya 
37011cab775cSVipul Pandya 	/* Calcuate filter portion for LE region. */
370241b4f86cSKumar Sanghvi 	filter = (__force unsigned int) cpu_to_be32(cxgb4_select_ntuple(
370341b4f86cSKumar Sanghvi 						    dev->rdev.lldi.ports[0],
370441b4f86cSKumar Sanghvi 						    e));
37051cab775cSVipul Pandya 
37061cab775cSVipul Pandya 	/*
37071cab775cSVipul Pandya 	 * Synthesize the cpl_pass_accept_req. We have everything except the
37081cab775cSVipul Pandya 	 * TID. Once firmware sends a reply with TID we update the TID field
37091cab775cSVipul Pandya 	 * in cpl and pass it through the regular cpl_pass_accept_req path.
37101cab775cSVipul Pandya 	 */
37111cab775cSVipul Pandya 	build_cpl_pass_accept_req(skb, stid, iph->tos);
37121cab775cSVipul Pandya 	send_fw_pass_open_req(dev, skb, iph->daddr, tcph->dest, iph->saddr,
37131cab775cSVipul Pandya 			      tcph->source, ntohl(tcph->seq), filter, window,
37141cab775cSVipul Pandya 			      rss_qid, pi->port_id);
37151cab775cSVipul Pandya 	cxgb4_l2t_release(e);
37161cab775cSVipul Pandya free_dst:
37171cab775cSVipul Pandya 	dst_release(dst);
37181cab775cSVipul Pandya reject:
37192f5b48c3SSteve Wise 	return 0;
37202f5b48c3SSteve Wise }
37212f5b48c3SSteve Wise 
3722cfdda9d7SSteve Wise /*
3723be4c9badSRoland Dreier  * These are the real handlers that are called from a
3724be4c9badSRoland Dreier  * work queue.
3725be4c9badSRoland Dreier  */
3726be4c9badSRoland Dreier static c4iw_handler_func work_handlers[NUM_CPL_CMDS] = {
3727be4c9badSRoland Dreier 	[CPL_ACT_ESTABLISH] = act_establish,
3728be4c9badSRoland Dreier 	[CPL_ACT_OPEN_RPL] = act_open_rpl,
3729be4c9badSRoland Dreier 	[CPL_RX_DATA] = rx_data,
3730be4c9badSRoland Dreier 	[CPL_ABORT_RPL_RSS] = abort_rpl,
3731be4c9badSRoland Dreier 	[CPL_ABORT_RPL] = abort_rpl,
3732be4c9badSRoland Dreier 	[CPL_PASS_OPEN_RPL] = pass_open_rpl,
3733be4c9badSRoland Dreier 	[CPL_CLOSE_LISTSRV_RPL] = close_listsrv_rpl,
3734be4c9badSRoland Dreier 	[CPL_PASS_ACCEPT_REQ] = pass_accept_req,
3735be4c9badSRoland Dreier 	[CPL_PASS_ESTABLISH] = pass_establish,
3736be4c9badSRoland Dreier 	[CPL_PEER_CLOSE] = peer_close,
3737be4c9badSRoland Dreier 	[CPL_ABORT_REQ_RSS] = peer_abort,
3738be4c9badSRoland Dreier 	[CPL_CLOSE_CON_RPL] = close_con_rpl,
3739be4c9badSRoland Dreier 	[CPL_RDMA_TERMINATE] = terminate,
37402f5b48c3SSteve Wise 	[CPL_FW4_ACK] = fw4_ack,
37411cab775cSVipul Pandya 	[CPL_FW6_MSG] = deferred_fw6_msg,
37421cab775cSVipul Pandya 	[CPL_RX_PKT] = rx_pkt
3743be4c9badSRoland Dreier };
3744be4c9badSRoland Dreier 
3745be4c9badSRoland Dreier static void process_timeout(struct c4iw_ep *ep)
3746be4c9badSRoland Dreier {
3747be4c9badSRoland Dreier 	struct c4iw_qp_attributes attrs;
3748be4c9badSRoland Dreier 	int abort = 1;
3749be4c9badSRoland Dreier 
37502f5b48c3SSteve Wise 	mutex_lock(&ep->com.mutex);
3751be4c9badSRoland Dreier 	PDBG("%s ep %p tid %u state %d\n", __func__, ep, ep->hwtid,
3752be4c9badSRoland Dreier 	     ep->com.state);
3753793dad94SVipul Pandya 	set_bit(TIMEDOUT, &ep->com.history);
3754be4c9badSRoland Dreier 	switch (ep->com.state) {
3755be4c9badSRoland Dreier 	case MPA_REQ_SENT:
3756be4c9badSRoland Dreier 		__state_set(&ep->com, ABORTING);
3757be4c9badSRoland Dreier 		connect_reply_upcall(ep, -ETIMEDOUT);
3758be4c9badSRoland Dreier 		break;
3759be4c9badSRoland Dreier 	case MPA_REQ_WAIT:
3760be4c9badSRoland Dreier 		__state_set(&ep->com, ABORTING);
3761be4c9badSRoland Dreier 		break;
3762be4c9badSRoland Dreier 	case CLOSING:
3763be4c9badSRoland Dreier 	case MORIBUND:
3764be4c9badSRoland Dreier 		if (ep->com.cm_id && ep->com.qp) {
3765be4c9badSRoland Dreier 			attrs.next_state = C4IW_QP_STATE_ERROR;
3766be4c9badSRoland Dreier 			c4iw_modify_qp(ep->com.qp->rhp,
3767be4c9badSRoland Dreier 				     ep->com.qp, C4IW_QP_ATTR_NEXT_STATE,
3768be4c9badSRoland Dreier 				     &attrs, 1);
3769be4c9badSRoland Dreier 		}
3770be4c9badSRoland Dreier 		__state_set(&ep->com, ABORTING);
3771be13b2dfSSteve Wise 		close_complete_upcall(ep, -ETIMEDOUT);
3772be4c9badSRoland Dreier 		break;
3773b33bd0cbSSteve Wise 	case ABORTING:
3774b33bd0cbSSteve Wise 	case DEAD:
3775b33bd0cbSSteve Wise 
3776b33bd0cbSSteve Wise 		/*
3777b33bd0cbSSteve Wise 		 * These states are expected if the ep timed out at the same
3778b33bd0cbSSteve Wise 		 * time as another thread was calling stop_ep_timer().
3779b33bd0cbSSteve Wise 		 * So we silently do nothing for these states.
3780b33bd0cbSSteve Wise 		 */
3781b33bd0cbSSteve Wise 		abort = 0;
3782b33bd0cbSSteve Wise 		break;
3783be4c9badSRoland Dreier 	default:
378476f267b7SJulia Lawall 		WARN(1, "%s unexpected state ep %p tid %u state %u\n",
3785be4c9badSRoland Dreier 			__func__, ep, ep->hwtid, ep->com.state);
3786be4c9badSRoland Dreier 		abort = 0;
3787be4c9badSRoland Dreier 	}
3788be4c9badSRoland Dreier 	if (abort)
3789be4c9badSRoland Dreier 		abort_connection(ep, NULL, GFP_KERNEL);
3790cc18b939SSteve Wise 	mutex_unlock(&ep->com.mutex);
3791be4c9badSRoland Dreier 	c4iw_put_ep(&ep->com);
3792be4c9badSRoland Dreier }
3793be4c9badSRoland Dreier 
3794be4c9badSRoland Dreier static void process_timedout_eps(void)
3795be4c9badSRoland Dreier {
3796be4c9badSRoland Dreier 	struct c4iw_ep *ep;
3797be4c9badSRoland Dreier 
3798be4c9badSRoland Dreier 	spin_lock_irq(&timeout_lock);
3799be4c9badSRoland Dreier 	while (!list_empty(&timeout_list)) {
3800be4c9badSRoland Dreier 		struct list_head *tmp;
3801be4c9badSRoland Dreier 
3802be4c9badSRoland Dreier 		tmp = timeout_list.next;
3803be4c9badSRoland Dreier 		list_del(tmp);
3804b33bd0cbSSteve Wise 		tmp->next = NULL;
3805b33bd0cbSSteve Wise 		tmp->prev = NULL;
3806be4c9badSRoland Dreier 		spin_unlock_irq(&timeout_lock);
3807be4c9badSRoland Dreier 		ep = list_entry(tmp, struct c4iw_ep, entry);
3808be4c9badSRoland Dreier 		process_timeout(ep);
3809be4c9badSRoland Dreier 		spin_lock_irq(&timeout_lock);
3810be4c9badSRoland Dreier 	}
3811be4c9badSRoland Dreier 	spin_unlock_irq(&timeout_lock);
3812be4c9badSRoland Dreier }
3813be4c9badSRoland Dreier 
3814be4c9badSRoland Dreier static void process_work(struct work_struct *work)
3815be4c9badSRoland Dreier {
3816be4c9badSRoland Dreier 	struct sk_buff *skb = NULL;
3817be4c9badSRoland Dreier 	struct c4iw_dev *dev;
3818c1d7356cSDan Carpenter 	struct cpl_act_establish *rpl;
3819be4c9badSRoland Dreier 	unsigned int opcode;
3820be4c9badSRoland Dreier 	int ret;
3821be4c9badSRoland Dreier 
3822b33bd0cbSSteve Wise 	process_timedout_eps();
3823be4c9badSRoland Dreier 	while ((skb = skb_dequeue(&rxq))) {
3824be4c9badSRoland Dreier 		rpl = cplhdr(skb);
3825be4c9badSRoland Dreier 		dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *)));
3826be4c9badSRoland Dreier 		opcode = rpl->ot.opcode;
3827be4c9badSRoland Dreier 
3828be4c9badSRoland Dreier 		BUG_ON(!work_handlers[opcode]);
3829be4c9badSRoland Dreier 		ret = work_handlers[opcode](dev, skb);
3830be4c9badSRoland Dreier 		if (!ret)
3831be4c9badSRoland Dreier 			kfree_skb(skb);
3832be4c9badSRoland Dreier 		process_timedout_eps();
3833be4c9badSRoland Dreier 	}
3834b33bd0cbSSteve Wise }
3835be4c9badSRoland Dreier 
3836be4c9badSRoland Dreier static DECLARE_WORK(skb_work, process_work);
3837be4c9badSRoland Dreier 
3838be4c9badSRoland Dreier static void ep_timeout(unsigned long arg)
3839be4c9badSRoland Dreier {
3840be4c9badSRoland Dreier 	struct c4iw_ep *ep = (struct c4iw_ep *)arg;
38411ec779ccSVipul Pandya 	int kickit = 0;
3842be4c9badSRoland Dreier 
3843be4c9badSRoland Dreier 	spin_lock(&timeout_lock);
38441ec779ccSVipul Pandya 	if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) {
3845b33bd0cbSSteve Wise 		/*
3846b33bd0cbSSteve Wise 		 * Only insert if it is not already on the list.
3847b33bd0cbSSteve Wise 		 */
3848b33bd0cbSSteve Wise 		if (!ep->entry.next) {
3849be4c9badSRoland Dreier 			list_add_tail(&ep->entry, &timeout_list);
38501ec779ccSVipul Pandya 			kickit = 1;
38511ec779ccSVipul Pandya 		}
3852b33bd0cbSSteve Wise 	}
3853be4c9badSRoland Dreier 	spin_unlock(&timeout_lock);
38541ec779ccSVipul Pandya 	if (kickit)
3855be4c9badSRoland Dreier 		queue_work(workq, &skb_work);
3856be4c9badSRoland Dreier }
3857be4c9badSRoland Dreier 
3858be4c9badSRoland Dreier /*
3859cfdda9d7SSteve Wise  * All the CM events are handled on a work queue to have a safe context.
3860cfdda9d7SSteve Wise  */
3861cfdda9d7SSteve Wise static int sched(struct c4iw_dev *dev, struct sk_buff *skb)
3862cfdda9d7SSteve Wise {
3863cfdda9d7SSteve Wise 
3864cfdda9d7SSteve Wise 	/*
3865cfdda9d7SSteve Wise 	 * Save dev in the skb->cb area.
3866cfdda9d7SSteve Wise 	 */
3867cfdda9d7SSteve Wise 	*((struct c4iw_dev **) (skb->cb + sizeof(void *))) = dev;
3868cfdda9d7SSteve Wise 
3869cfdda9d7SSteve Wise 	/*
3870cfdda9d7SSteve Wise 	 * Queue the skb and schedule the worker thread.
3871cfdda9d7SSteve Wise 	 */
3872cfdda9d7SSteve Wise 	skb_queue_tail(&rxq, skb);
3873cfdda9d7SSteve Wise 	queue_work(workq, &skb_work);
3874cfdda9d7SSteve Wise 	return 0;
3875cfdda9d7SSteve Wise }
3876cfdda9d7SSteve Wise 
3877cfdda9d7SSteve Wise static int set_tcb_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
3878cfdda9d7SSteve Wise {
3879cfdda9d7SSteve Wise 	struct cpl_set_tcb_rpl *rpl = cplhdr(skb);
3880cfdda9d7SSteve Wise 
3881cfdda9d7SSteve Wise 	if (rpl->status != CPL_ERR_NONE) {
3882cfdda9d7SSteve Wise 		printk(KERN_ERR MOD "Unexpected SET_TCB_RPL status %u "
3883cfdda9d7SSteve Wise 		       "for tid %u\n", rpl->status, GET_TID(rpl));
3884cfdda9d7SSteve Wise 	}
38852f5b48c3SSteve Wise 	kfree_skb(skb);
3886cfdda9d7SSteve Wise 	return 0;
3887cfdda9d7SSteve Wise }
3888cfdda9d7SSteve Wise 
3889be4c9badSRoland Dreier static int fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb)
3890be4c9badSRoland Dreier {
3891be4c9badSRoland Dreier 	struct cpl_fw6_msg *rpl = cplhdr(skb);
3892be4c9badSRoland Dreier 	struct c4iw_wr_wait *wr_waitp;
3893be4c9badSRoland Dreier 	int ret;
3894be4c9badSRoland Dreier 
3895be4c9badSRoland Dreier 	PDBG("%s type %u\n", __func__, rpl->type);
3896be4c9badSRoland Dreier 
3897be4c9badSRoland Dreier 	switch (rpl->type) {
38985be78ee9SVipul Pandya 	case FW6_TYPE_WR_RPL:
3899be4c9badSRoland Dreier 		ret = (int)((be64_to_cpu(rpl->data[0]) >> 8) & 0xff);
3900c8e081a1SRoland Dreier 		wr_waitp = (struct c4iw_wr_wait *)(__force unsigned long) rpl->data[1];
3901be4c9badSRoland Dreier 		PDBG("%s wr_waitp %p ret %u\n", __func__, wr_waitp, ret);
3902d9594d99SSteve Wise 		if (wr_waitp)
3903d9594d99SSteve Wise 			c4iw_wake_up(wr_waitp, ret ? -ret : 0);
39042f5b48c3SSteve Wise 		kfree_skb(skb);
3905be4c9badSRoland Dreier 		break;
39065be78ee9SVipul Pandya 	case FW6_TYPE_CQE:
39075be78ee9SVipul Pandya 	case FW6_TYPE_OFLD_CONNECTION_WR_RPL:
39081cab775cSVipul Pandya 		sched(dev, skb);
39095be78ee9SVipul Pandya 		break;
3910be4c9badSRoland Dreier 	default:
3911be4c9badSRoland Dreier 		printk(KERN_ERR MOD "%s unexpected fw6 msg type %u\n", __func__,
3912be4c9badSRoland Dreier 		       rpl->type);
39132f5b48c3SSteve Wise 		kfree_skb(skb);
3914be4c9badSRoland Dreier 		break;
3915be4c9badSRoland Dreier 	}
3916be4c9badSRoland Dreier 	return 0;
3917be4c9badSRoland Dreier }
3918be4c9badSRoland Dreier 
39198da7e7a5SSteve Wise static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb)
39208da7e7a5SSteve Wise {
39218da7e7a5SSteve Wise 	struct cpl_abort_req_rss *req = cplhdr(skb);
39228da7e7a5SSteve Wise 	struct c4iw_ep *ep;
39238da7e7a5SSteve Wise 	struct tid_info *t = dev->rdev.lldi.tids;
39248da7e7a5SSteve Wise 	unsigned int tid = GET_TID(req);
39258da7e7a5SSteve Wise 
39268da7e7a5SSteve Wise 	ep = lookup_tid(t, tid);
392714b92228SSteve Wise 	if (!ep) {
392814b92228SSteve Wise 		printk(KERN_WARNING MOD
392914b92228SSteve Wise 		       "Abort on non-existent endpoint, tid %d\n", tid);
393014b92228SSteve Wise 		kfree_skb(skb);
393114b92228SSteve Wise 		return 0;
393214b92228SSteve Wise 	}
39337a2cea2aSSteve Wise 	if (is_neg_adv(req->status)) {
3934dd92b124SHariprasad Shenai 		dev_warn(&dev->rdev.lldi.pdev->dev,
3935dd92b124SHariprasad Shenai 			 "Negative advice on abort - tid %u status %d (%s)\n",
3936dd92b124SHariprasad Shenai 			 ep->hwtid, req->status, neg_adv_str(req->status));
39378da7e7a5SSteve Wise 		kfree_skb(skb);
39388da7e7a5SSteve Wise 		return 0;
39398da7e7a5SSteve Wise 	}
39408da7e7a5SSteve Wise 	PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid,
39418da7e7a5SSteve Wise 	     ep->com.state);
39428da7e7a5SSteve Wise 
39438da7e7a5SSteve Wise 	/*
39448da7e7a5SSteve Wise 	 * Wake up any threads in rdma_init() or rdma_fini().
39457c0a33d6SVipul Pandya 	 * However, if we are on MPAv2 and want to retry with MPAv1
39467c0a33d6SVipul Pandya 	 * then, don't wake up yet.
39478da7e7a5SSteve Wise 	 */
39487c0a33d6SVipul Pandya 	if (mpa_rev == 2 && !ep->tried_with_mpa_v1) {
39497c0a33d6SVipul Pandya 		if (ep->com.state != MPA_REQ_SENT)
39507c0a33d6SVipul Pandya 			c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
39517c0a33d6SVipul Pandya 	} else
39528da7e7a5SSteve Wise 		c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
39538da7e7a5SSteve Wise 	sched(dev, skb);
39548da7e7a5SSteve Wise 	return 0;
39558da7e7a5SSteve Wise }
39568da7e7a5SSteve Wise 
3957be4c9badSRoland Dreier /*
3958be4c9badSRoland Dreier  * Most upcalls from the T4 Core go to sched() to
3959be4c9badSRoland Dreier  * schedule the processing on a work queue.
3960be4c9badSRoland Dreier  */
3961be4c9badSRoland Dreier c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS] = {
3962be4c9badSRoland Dreier 	[CPL_ACT_ESTABLISH] = sched,
3963be4c9badSRoland Dreier 	[CPL_ACT_OPEN_RPL] = sched,
3964be4c9badSRoland Dreier 	[CPL_RX_DATA] = sched,
3965be4c9badSRoland Dreier 	[CPL_ABORT_RPL_RSS] = sched,
3966be4c9badSRoland Dreier 	[CPL_ABORT_RPL] = sched,
3967be4c9badSRoland Dreier 	[CPL_PASS_OPEN_RPL] = sched,
3968be4c9badSRoland Dreier 	[CPL_CLOSE_LISTSRV_RPL] = sched,
3969be4c9badSRoland Dreier 	[CPL_PASS_ACCEPT_REQ] = sched,
3970be4c9badSRoland Dreier 	[CPL_PASS_ESTABLISH] = sched,
3971be4c9badSRoland Dreier 	[CPL_PEER_CLOSE] = sched,
3972be4c9badSRoland Dreier 	[CPL_CLOSE_CON_RPL] = sched,
39738da7e7a5SSteve Wise 	[CPL_ABORT_REQ_RSS] = peer_abort_intr,
3974be4c9badSRoland Dreier 	[CPL_RDMA_TERMINATE] = sched,
3975be4c9badSRoland Dreier 	[CPL_FW4_ACK] = sched,
3976be4c9badSRoland Dreier 	[CPL_SET_TCB_RPL] = set_tcb_rpl,
39771cab775cSVipul Pandya 	[CPL_FW6_MSG] = fw6_msg,
39781cab775cSVipul Pandya 	[CPL_RX_PKT] = sched
3979be4c9badSRoland Dreier };
3980be4c9badSRoland Dreier 
3981cfdda9d7SSteve Wise int __init c4iw_cm_init(void)
3982cfdda9d7SSteve Wise {
3983be4c9badSRoland Dreier 	spin_lock_init(&timeout_lock);
3984cfdda9d7SSteve Wise 	skb_queue_head_init(&rxq);
3985cfdda9d7SSteve Wise 
3986cfdda9d7SSteve Wise 	workq = create_singlethread_workqueue("iw_cxgb4");
3987cfdda9d7SSteve Wise 	if (!workq)
3988cfdda9d7SSteve Wise 		return -ENOMEM;
3989cfdda9d7SSteve Wise 
3990cfdda9d7SSteve Wise 	return 0;
3991cfdda9d7SSteve Wise }
3992cfdda9d7SSteve Wise 
399346c1376dSSteve Wise void c4iw_cm_term(void)
3994cfdda9d7SSteve Wise {
3995be4c9badSRoland Dreier 	WARN_ON(!list_empty(&timeout_list));
3996cfdda9d7SSteve Wise 	flush_workqueue(workq);
3997cfdda9d7SSteve Wise 	destroy_workqueue(workq);
3998cfdda9d7SSteve Wise }
3999