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" 5384cc6ac6SHariprasad S #include "clip_tbl.h" 54cfdda9d7SSteve Wise 55cfdda9d7SSteve Wise static char *states[] = { 56cfdda9d7SSteve Wise "idle", 57cfdda9d7SSteve Wise "listen", 58cfdda9d7SSteve Wise "connecting", 59cfdda9d7SSteve Wise "mpa_wait_req", 60cfdda9d7SSteve Wise "mpa_req_sent", 61cfdda9d7SSteve Wise "mpa_req_rcvd", 62cfdda9d7SSteve Wise "mpa_rep_sent", 63cfdda9d7SSteve Wise "fpdu_mode", 64cfdda9d7SSteve Wise "aborting", 65cfdda9d7SSteve Wise "closing", 66cfdda9d7SSteve Wise "moribund", 67cfdda9d7SSteve Wise "dead", 68cfdda9d7SSteve Wise NULL, 69cfdda9d7SSteve Wise }; 70cfdda9d7SSteve Wise 715be78ee9SVipul Pandya static int nocong; 725be78ee9SVipul Pandya module_param(nocong, int, 0644); 735be78ee9SVipul Pandya MODULE_PARM_DESC(nocong, "Turn of congestion control (default=0)"); 745be78ee9SVipul Pandya 755be78ee9SVipul Pandya static int enable_ecn; 765be78ee9SVipul Pandya module_param(enable_ecn, int, 0644); 775be78ee9SVipul Pandya MODULE_PARM_DESC(enable_ecn, "Enable ECN (default=0/disabled)"); 785be78ee9SVipul Pandya 79b52fe09eSSteve Wise static int dack_mode = 1; 80ba6d3925SSteve Wise module_param(dack_mode, int, 0644); 81b52fe09eSSteve Wise MODULE_PARM_DESC(dack_mode, "Delayed ack mode (default=1)"); 82ba6d3925SSteve Wise 834c2c5763SHariprasad Shenai uint c4iw_max_read_depth = 32; 84be4c9badSRoland Dreier module_param(c4iw_max_read_depth, int, 0644); 854c2c5763SHariprasad Shenai MODULE_PARM_DESC(c4iw_max_read_depth, 864c2c5763SHariprasad Shenai "Per-connection max ORD/IRD (default=32)"); 87be4c9badSRoland Dreier 88cfdda9d7SSteve Wise static int enable_tcp_timestamps; 89cfdda9d7SSteve Wise module_param(enable_tcp_timestamps, int, 0644); 90cfdda9d7SSteve Wise MODULE_PARM_DESC(enable_tcp_timestamps, "Enable tcp timestamps (default=0)"); 91cfdda9d7SSteve Wise 92cfdda9d7SSteve Wise static int enable_tcp_sack; 93cfdda9d7SSteve Wise module_param(enable_tcp_sack, int, 0644); 94cfdda9d7SSteve Wise MODULE_PARM_DESC(enable_tcp_sack, "Enable tcp SACK (default=0)"); 95cfdda9d7SSteve Wise 96cfdda9d7SSteve Wise static int enable_tcp_window_scaling = 1; 97cfdda9d7SSteve Wise module_param(enable_tcp_window_scaling, int, 0644); 98cfdda9d7SSteve Wise MODULE_PARM_DESC(enable_tcp_window_scaling, 99cfdda9d7SSteve Wise "Enable tcp window scaling (default=1)"); 100cfdda9d7SSteve Wise 101cfdda9d7SSteve Wise int c4iw_debug; 102cfdda9d7SSteve Wise module_param(c4iw_debug, int, 0644); 103cfdda9d7SSteve Wise MODULE_PARM_DESC(c4iw_debug, "Enable debug logging (default=0)"); 104cfdda9d7SSteve Wise 105df2d5130SSteve Wise static int peer2peer = 1; 106cfdda9d7SSteve Wise module_param(peer2peer, int, 0644); 107df2d5130SSteve Wise MODULE_PARM_DESC(peer2peer, "Support peer2peer ULPs (default=1)"); 108cfdda9d7SSteve Wise 109cfdda9d7SSteve Wise static int p2p_type = FW_RI_INIT_P2PTYPE_READ_REQ; 110cfdda9d7SSteve Wise module_param(p2p_type, int, 0644); 111cfdda9d7SSteve Wise MODULE_PARM_DESC(p2p_type, "RDMAP opcode to use for the RTR message: " 112cfdda9d7SSteve Wise "1=RDMA_READ 0=RDMA_WRITE (default 1)"); 113cfdda9d7SSteve Wise 114cfdda9d7SSteve Wise static int ep_timeout_secs = 60; 115cfdda9d7SSteve Wise module_param(ep_timeout_secs, int, 0644); 116cfdda9d7SSteve Wise MODULE_PARM_DESC(ep_timeout_secs, "CM Endpoint operation timeout " 117cfdda9d7SSteve Wise "in seconds (default=60)"); 118cfdda9d7SSteve Wise 119b8ac3112SHariprasad S static int mpa_rev = 2; 120cfdda9d7SSteve Wise module_param(mpa_rev, int, 0644); 121cfdda9d7SSteve Wise MODULE_PARM_DESC(mpa_rev, "MPA Revision, 0 supports amso1100, " 122d2fe99e8SKumar Sanghvi "1 is RFC0544 spec compliant, 2 is IETF MPA Peer Connect Draft" 123b8ac3112SHariprasad S " compliant (default=2)"); 124cfdda9d7SSteve Wise 125cfdda9d7SSteve Wise static int markers_enabled; 126cfdda9d7SSteve Wise module_param(markers_enabled, int, 0644); 127cfdda9d7SSteve Wise MODULE_PARM_DESC(markers_enabled, "Enable MPA MARKERS (default(0)=disabled)"); 128cfdda9d7SSteve Wise 129cfdda9d7SSteve Wise static int crc_enabled = 1; 130cfdda9d7SSteve Wise module_param(crc_enabled, int, 0644); 131cfdda9d7SSteve Wise MODULE_PARM_DESC(crc_enabled, "Enable MPA CRC (default(1)=enabled)"); 132cfdda9d7SSteve Wise 133cfdda9d7SSteve Wise static int rcv_win = 256 * 1024; 134cfdda9d7SSteve Wise module_param(rcv_win, int, 0644); 135cfdda9d7SSteve Wise MODULE_PARM_DESC(rcv_win, "TCP receive window in bytes (default=256KB)"); 136cfdda9d7SSteve Wise 13798ae68b7SSteve Wise static int snd_win = 128 * 1024; 138cfdda9d7SSteve Wise module_param(snd_win, int, 0644); 13998ae68b7SSteve Wise MODULE_PARM_DESC(snd_win, "TCP send window in bytes (default=128KB)"); 140cfdda9d7SSteve Wise 141cfdda9d7SSteve Wise static struct workqueue_struct *workq; 142cfdda9d7SSteve Wise 143cfdda9d7SSteve Wise static struct sk_buff_head rxq; 144cfdda9d7SSteve Wise 145cfdda9d7SSteve Wise static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp); 146cfdda9d7SSteve Wise static void ep_timeout(unsigned long arg); 147cfdda9d7SSteve Wise static void connect_reply_upcall(struct c4iw_ep *ep, int status); 1489dec900cSHariprasad S static int sched(struct c4iw_dev *dev, struct sk_buff *skb); 149cfdda9d7SSteve Wise 150be4c9badSRoland Dreier static LIST_HEAD(timeout_list); 151be4c9badSRoland Dreier static spinlock_t timeout_lock; 152be4c9badSRoland Dreier 153325abeadSVipul Pandya static void deref_qp(struct c4iw_ep *ep) 154325abeadSVipul Pandya { 155325abeadSVipul Pandya c4iw_qp_rem_ref(&ep->com.qp->ibqp); 156325abeadSVipul Pandya clear_bit(QP_REFERENCED, &ep->com.flags); 157325abeadSVipul Pandya } 158325abeadSVipul Pandya 159325abeadSVipul Pandya static void ref_qp(struct c4iw_ep *ep) 160325abeadSVipul Pandya { 161325abeadSVipul Pandya set_bit(QP_REFERENCED, &ep->com.flags); 162325abeadSVipul Pandya c4iw_qp_add_ref(&ep->com.qp->ibqp); 163325abeadSVipul Pandya } 164325abeadSVipul Pandya 165cfdda9d7SSteve Wise static void start_ep_timer(struct c4iw_ep *ep) 166cfdda9d7SSteve Wise { 167cfdda9d7SSteve Wise PDBG("%s ep %p\n", __func__, ep); 168cfdda9d7SSteve Wise if (timer_pending(&ep->timer)) { 1691ec779ccSVipul Pandya pr_err("%s timer already started! ep %p\n", 1701ec779ccSVipul Pandya __func__, ep); 1711ec779ccSVipul Pandya return; 1721ec779ccSVipul Pandya } 1731ec779ccSVipul Pandya clear_bit(TIMEOUT, &ep->com.flags); 174cfdda9d7SSteve Wise c4iw_get_ep(&ep->com); 175cfdda9d7SSteve Wise ep->timer.expires = jiffies + ep_timeout_secs * HZ; 176cfdda9d7SSteve Wise ep->timer.data = (unsigned long)ep; 177cfdda9d7SSteve Wise ep->timer.function = ep_timeout; 178cfdda9d7SSteve Wise add_timer(&ep->timer); 179cfdda9d7SSteve Wise } 180cfdda9d7SSteve Wise 181b33bd0cbSSteve Wise static int stop_ep_timer(struct c4iw_ep *ep) 182cfdda9d7SSteve Wise { 1831ec779ccSVipul Pandya PDBG("%s ep %p stopping\n", __func__, ep); 184cfdda9d7SSteve Wise del_timer_sync(&ep->timer); 185b33bd0cbSSteve Wise if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) { 186cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 187b33bd0cbSSteve Wise return 0; 188b33bd0cbSSteve Wise } 189b33bd0cbSSteve Wise return 1; 190cfdda9d7SSteve Wise } 191cfdda9d7SSteve Wise 192cfdda9d7SSteve Wise static int c4iw_l2t_send(struct c4iw_rdev *rdev, struct sk_buff *skb, 193cfdda9d7SSteve Wise struct l2t_entry *l2e) 194cfdda9d7SSteve Wise { 195cfdda9d7SSteve Wise int error = 0; 196cfdda9d7SSteve Wise 197cfdda9d7SSteve Wise if (c4iw_fatal_error(rdev)) { 198cfdda9d7SSteve Wise kfree_skb(skb); 199cfdda9d7SSteve Wise PDBG("%s - device in error state - dropping\n", __func__); 200cfdda9d7SSteve Wise return -EIO; 201cfdda9d7SSteve Wise } 202cfdda9d7SSteve Wise error = cxgb4_l2t_send(rdev->lldi.ports[0], skb, l2e); 203cfdda9d7SSteve Wise if (error < 0) 204cfdda9d7SSteve Wise kfree_skb(skb); 20574594861SSteve Wise return error < 0 ? error : 0; 206cfdda9d7SSteve Wise } 207cfdda9d7SSteve Wise 208cfdda9d7SSteve Wise int c4iw_ofld_send(struct c4iw_rdev *rdev, struct sk_buff *skb) 209cfdda9d7SSteve Wise { 210cfdda9d7SSteve Wise int error = 0; 211cfdda9d7SSteve Wise 212cfdda9d7SSteve Wise if (c4iw_fatal_error(rdev)) { 213cfdda9d7SSteve Wise kfree_skb(skb); 214cfdda9d7SSteve Wise PDBG("%s - device in error state - dropping\n", __func__); 215cfdda9d7SSteve Wise return -EIO; 216cfdda9d7SSteve Wise } 217cfdda9d7SSteve Wise error = cxgb4_ofld_send(rdev->lldi.ports[0], skb); 218cfdda9d7SSteve Wise if (error < 0) 219cfdda9d7SSteve Wise kfree_skb(skb); 22074594861SSteve Wise return error < 0 ? error : 0; 221cfdda9d7SSteve Wise } 222cfdda9d7SSteve Wise 223cfdda9d7SSteve Wise static void release_tid(struct c4iw_rdev *rdev, u32 hwtid, struct sk_buff *skb) 224cfdda9d7SSteve Wise { 225cfdda9d7SSteve Wise struct cpl_tid_release *req; 226cfdda9d7SSteve Wise 227cfdda9d7SSteve Wise skb = get_skb(skb, sizeof *req, GFP_KERNEL); 228cfdda9d7SSteve Wise if (!skb) 229cfdda9d7SSteve Wise return; 230cfdda9d7SSteve Wise req = (struct cpl_tid_release *) skb_put(skb, sizeof(*req)); 231cfdda9d7SSteve Wise INIT_TP_WR(req, hwtid); 232cfdda9d7SSteve Wise OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_TID_RELEASE, hwtid)); 233cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_SETUP, 0); 234cfdda9d7SSteve Wise c4iw_ofld_send(rdev, skb); 235cfdda9d7SSteve Wise return; 236cfdda9d7SSteve Wise } 237cfdda9d7SSteve Wise 238cfdda9d7SSteve Wise static void set_emss(struct c4iw_ep *ep, u16 opt) 239cfdda9d7SSteve Wise { 2406c53e938SHariprasad Shenai ep->emss = ep->com.dev->rdev.lldi.mtus[TCPOPT_MSS_G(opt)] - 24104524a47SHariprasad S ((AF_INET == ep->com.remote_addr.ss_family) ? 24204524a47SHariprasad S sizeof(struct iphdr) : sizeof(struct ipv6hdr)) - 24304524a47SHariprasad S sizeof(struct tcphdr); 244cfdda9d7SSteve Wise ep->mss = ep->emss; 2456c53e938SHariprasad Shenai if (TCPOPT_TSTAMP_G(opt)) 24604524a47SHariprasad S ep->emss -= round_up(TCPOLEN_TIMESTAMP, 4); 247cfdda9d7SSteve Wise if (ep->emss < 128) 248cfdda9d7SSteve Wise ep->emss = 128; 24992e7ae71SHariprasad Shenai if (ep->emss & 7) 25092e7ae71SHariprasad Shenai PDBG("Warning: misaligned mtu idx %u mss %u emss=%u\n", 2516c53e938SHariprasad Shenai TCPOPT_MSS_G(opt), ep->mss, ep->emss); 2526c53e938SHariprasad Shenai PDBG("%s mss_idx %u mss %u emss=%u\n", __func__, TCPOPT_MSS_G(opt), 253cfdda9d7SSteve Wise ep->mss, ep->emss); 254cfdda9d7SSteve Wise } 255cfdda9d7SSteve Wise 256cfdda9d7SSteve Wise static enum c4iw_ep_state state_read(struct c4iw_ep_common *epc) 257cfdda9d7SSteve Wise { 258cfdda9d7SSteve Wise enum c4iw_ep_state state; 259cfdda9d7SSteve Wise 2602f5b48c3SSteve Wise mutex_lock(&epc->mutex); 261cfdda9d7SSteve Wise state = epc->state; 2622f5b48c3SSteve Wise mutex_unlock(&epc->mutex); 263cfdda9d7SSteve Wise return state; 264cfdda9d7SSteve Wise } 265cfdda9d7SSteve Wise 266cfdda9d7SSteve Wise static void __state_set(struct c4iw_ep_common *epc, enum c4iw_ep_state new) 267cfdda9d7SSteve Wise { 268cfdda9d7SSteve Wise epc->state = new; 269cfdda9d7SSteve Wise } 270cfdda9d7SSteve Wise 271cfdda9d7SSteve Wise static void state_set(struct c4iw_ep_common *epc, enum c4iw_ep_state new) 272cfdda9d7SSteve Wise { 2732f5b48c3SSteve Wise mutex_lock(&epc->mutex); 274cfdda9d7SSteve Wise PDBG("%s - %s -> %s\n", __func__, states[epc->state], states[new]); 275cfdda9d7SSteve Wise __state_set(epc, new); 2762f5b48c3SSteve Wise mutex_unlock(&epc->mutex); 277cfdda9d7SSteve Wise return; 278cfdda9d7SSteve Wise } 279cfdda9d7SSteve Wise 280cfdda9d7SSteve Wise static void *alloc_ep(int size, gfp_t gfp) 281cfdda9d7SSteve Wise { 282cfdda9d7SSteve Wise struct c4iw_ep_common *epc; 283cfdda9d7SSteve Wise 284cfdda9d7SSteve Wise epc = kzalloc(size, gfp); 285cfdda9d7SSteve Wise if (epc) { 286cfdda9d7SSteve Wise kref_init(&epc->kref); 2872f5b48c3SSteve Wise mutex_init(&epc->mutex); 288aadc4df3SSteve Wise c4iw_init_wr_wait(&epc->wr_wait); 289cfdda9d7SSteve Wise } 290cfdda9d7SSteve Wise PDBG("%s alloc ep %p\n", __func__, epc); 291cfdda9d7SSteve Wise return epc; 292cfdda9d7SSteve Wise } 293cfdda9d7SSteve Wise 294cfdda9d7SSteve Wise void _c4iw_free_ep(struct kref *kref) 295cfdda9d7SSteve Wise { 296cfdda9d7SSteve Wise struct c4iw_ep *ep; 297cfdda9d7SSteve Wise 298cfdda9d7SSteve Wise ep = container_of(kref, struct c4iw_ep, com.kref); 2999dec900cSHariprasad S PDBG("%s ep %p state %s\n", __func__, ep, states[ep->com.state]); 300325abeadSVipul Pandya if (test_bit(QP_REFERENCED, &ep->com.flags)) 301325abeadSVipul Pandya deref_qp(ep); 302cfdda9d7SSteve Wise if (test_bit(RELEASE_RESOURCES, &ep->com.flags)) { 30384cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 30484cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 30584cc6ac6SHariprasad S (struct sockaddr_in6 *) 306170003c8SSteve Wise &ep->com.local_addr; 30784cc6ac6SHariprasad S 30884cc6ac6SHariprasad S cxgb4_clip_release( 30984cc6ac6SHariprasad S ep->com.dev->rdev.lldi.ports[0], 31084cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 31184cc6ac6SHariprasad S 1); 31284cc6ac6SHariprasad S } 313fe7e0a4dSVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->hwtid_idr, ep->hwtid); 314cfdda9d7SSteve Wise cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid); 315cfdda9d7SSteve Wise dst_release(ep->dst); 316cfdda9d7SSteve Wise cxgb4_l2t_release(ep->l2t); 317cfdda9d7SSteve Wise } 318cfdda9d7SSteve Wise kfree(ep); 319cfdda9d7SSteve Wise } 320cfdda9d7SSteve Wise 321cfdda9d7SSteve Wise static void release_ep_resources(struct c4iw_ep *ep) 322cfdda9d7SSteve Wise { 323cfdda9d7SSteve Wise set_bit(RELEASE_RESOURCES, &ep->com.flags); 324cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 325cfdda9d7SSteve Wise } 326cfdda9d7SSteve Wise 327cfdda9d7SSteve Wise static int status2errno(int status) 328cfdda9d7SSteve Wise { 329cfdda9d7SSteve Wise switch (status) { 330cfdda9d7SSteve Wise case CPL_ERR_NONE: 331cfdda9d7SSteve Wise return 0; 332cfdda9d7SSteve Wise case CPL_ERR_CONN_RESET: 333cfdda9d7SSteve Wise return -ECONNRESET; 334cfdda9d7SSteve Wise case CPL_ERR_ARP_MISS: 335cfdda9d7SSteve Wise return -EHOSTUNREACH; 336cfdda9d7SSteve Wise case CPL_ERR_CONN_TIMEDOUT: 337cfdda9d7SSteve Wise return -ETIMEDOUT; 338cfdda9d7SSteve Wise case CPL_ERR_TCAM_FULL: 339cfdda9d7SSteve Wise return -ENOMEM; 340cfdda9d7SSteve Wise case CPL_ERR_CONN_EXIST: 341cfdda9d7SSteve Wise return -EADDRINUSE; 342cfdda9d7SSteve Wise default: 343cfdda9d7SSteve Wise return -EIO; 344cfdda9d7SSteve Wise } 345cfdda9d7SSteve Wise } 346cfdda9d7SSteve Wise 347cfdda9d7SSteve Wise /* 348cfdda9d7SSteve Wise * Try and reuse skbs already allocated... 349cfdda9d7SSteve Wise */ 350cfdda9d7SSteve Wise static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp) 351cfdda9d7SSteve Wise { 352cfdda9d7SSteve Wise if (skb && !skb_is_nonlinear(skb) && !skb_cloned(skb)) { 353cfdda9d7SSteve Wise skb_trim(skb, 0); 354cfdda9d7SSteve Wise skb_get(skb); 355cfdda9d7SSteve Wise skb_reset_transport_header(skb); 356cfdda9d7SSteve Wise } else { 357cfdda9d7SSteve Wise skb = alloc_skb(len, gfp); 358cfdda9d7SSteve Wise } 359b38a0ad8SSteve Wise t4_set_arp_err_handler(skb, NULL, NULL); 360cfdda9d7SSteve Wise return skb; 361cfdda9d7SSteve Wise } 362cfdda9d7SSteve Wise 363830662f6SVipul Pandya static struct net_device *get_real_dev(struct net_device *egress_dev) 364830662f6SVipul Pandya { 36511b8e22dSSteve Wise return rdma_vlan_dev_real_dev(egress_dev) ? : egress_dev; 366830662f6SVipul Pandya } 367830662f6SVipul Pandya 368830662f6SVipul Pandya static int our_interface(struct c4iw_dev *dev, struct net_device *egress_dev) 369830662f6SVipul Pandya { 370830662f6SVipul Pandya int i; 371830662f6SVipul Pandya 372830662f6SVipul Pandya egress_dev = get_real_dev(egress_dev); 373830662f6SVipul Pandya for (i = 0; i < dev->rdev.lldi.nports; i++) 374830662f6SVipul Pandya if (dev->rdev.lldi.ports[i] == egress_dev) 375830662f6SVipul Pandya return 1; 376830662f6SVipul Pandya return 0; 377830662f6SVipul Pandya } 378830662f6SVipul Pandya 379830662f6SVipul Pandya static struct dst_entry *find_route6(struct c4iw_dev *dev, __u8 *local_ip, 380830662f6SVipul Pandya __u8 *peer_ip, __be16 local_port, 381830662f6SVipul Pandya __be16 peer_port, u8 tos, 382830662f6SVipul Pandya __u32 sin6_scope_id) 383830662f6SVipul Pandya { 384830662f6SVipul Pandya struct dst_entry *dst = NULL; 385830662f6SVipul Pandya 386830662f6SVipul Pandya if (IS_ENABLED(CONFIG_IPV6)) { 387830662f6SVipul Pandya struct flowi6 fl6; 388830662f6SVipul Pandya 389830662f6SVipul Pandya memset(&fl6, 0, sizeof(fl6)); 390830662f6SVipul Pandya memcpy(&fl6.daddr, peer_ip, 16); 391830662f6SVipul Pandya memcpy(&fl6.saddr, local_ip, 16); 392830662f6SVipul Pandya if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL) 393830662f6SVipul Pandya fl6.flowi6_oif = sin6_scope_id; 394830662f6SVipul Pandya dst = ip6_route_output(&init_net, NULL, &fl6); 395830662f6SVipul Pandya if (!dst) 396830662f6SVipul Pandya goto out; 397830662f6SVipul Pandya if (!our_interface(dev, ip6_dst_idev(dst)->dev) && 398830662f6SVipul Pandya !(ip6_dst_idev(dst)->dev->flags & IFF_LOOPBACK)) { 399830662f6SVipul Pandya dst_release(dst); 400830662f6SVipul Pandya dst = NULL; 401830662f6SVipul Pandya } 402830662f6SVipul Pandya } 403830662f6SVipul Pandya 404830662f6SVipul Pandya out: 405830662f6SVipul Pandya return dst; 406830662f6SVipul Pandya } 407830662f6SVipul Pandya 408830662f6SVipul Pandya static struct dst_entry *find_route(struct c4iw_dev *dev, __be32 local_ip, 409cfdda9d7SSteve Wise __be32 peer_ip, __be16 local_port, 410cfdda9d7SSteve Wise __be16 peer_port, u8 tos) 411cfdda9d7SSteve Wise { 412cfdda9d7SSteve Wise struct rtable *rt; 41331e4543dSDavid S. Miller struct flowi4 fl4; 414830662f6SVipul Pandya struct neighbour *n; 415cfdda9d7SSteve Wise 41631e4543dSDavid S. Miller rt = ip_route_output_ports(&init_net, &fl4, NULL, peer_ip, local_ip, 41778fbfd8aSDavid S. Miller peer_port, local_port, IPPROTO_TCP, 41878fbfd8aSDavid S. Miller tos, 0); 419b23dd4feSDavid S. Miller if (IS_ERR(rt)) 420cfdda9d7SSteve Wise return NULL; 421830662f6SVipul Pandya n = dst_neigh_lookup(&rt->dst, &peer_ip); 422830662f6SVipul Pandya if (!n) 423830662f6SVipul Pandya return NULL; 424f8e81908SSteve Wise if (!our_interface(dev, n->dev) && 425f8e81908SSteve Wise !(n->dev->flags & IFF_LOOPBACK)) { 426d480201bSHariprasad S neigh_release(n); 427830662f6SVipul Pandya dst_release(&rt->dst); 428830662f6SVipul Pandya return NULL; 429830662f6SVipul Pandya } 430830662f6SVipul Pandya neigh_release(n); 431830662f6SVipul Pandya return &rt->dst; 432cfdda9d7SSteve Wise } 433cfdda9d7SSteve Wise 434cfdda9d7SSteve Wise static void arp_failure_discard(void *handle, struct sk_buff *skb) 435cfdda9d7SSteve Wise { 4369dec900cSHariprasad S pr_err(MOD "ARP failure\n"); 437cfdda9d7SSteve Wise kfree_skb(skb); 438cfdda9d7SSteve Wise } 439cfdda9d7SSteve Wise 4409dec900cSHariprasad S enum { 4419dec900cSHariprasad S NUM_FAKE_CPLS = 1, 4429dec900cSHariprasad S FAKE_CPL_PUT_EP_SAFE = NUM_CPL_CMDS + 0, 4439dec900cSHariprasad S }; 4449dec900cSHariprasad S 4459dec900cSHariprasad S static int _put_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb) 4469dec900cSHariprasad S { 4479dec900cSHariprasad S struct c4iw_ep *ep; 4489dec900cSHariprasad S 4499dec900cSHariprasad S ep = *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *))); 4509dec900cSHariprasad S release_ep_resources(ep); 4519dec900cSHariprasad S return 0; 4529dec900cSHariprasad S } 4539dec900cSHariprasad S 4549dec900cSHariprasad S /* 4559dec900cSHariprasad S * Fake up a special CPL opcode and call sched() so process_work() will call 4569dec900cSHariprasad S * _put_ep_safe() in a safe context to free the ep resources. This is needed 4579dec900cSHariprasad S * because ARP error handlers are called in an ATOMIC context, and 4589dec900cSHariprasad S * _c4iw_free_ep() needs to block. 4599dec900cSHariprasad S */ 4609dec900cSHariprasad S static void queue_arp_failure_cpl(struct c4iw_ep *ep, struct sk_buff *skb) 4619dec900cSHariprasad S { 4629dec900cSHariprasad S struct cpl_act_establish *rpl = cplhdr(skb); 4639dec900cSHariprasad S 4649dec900cSHariprasad S /* Set our special ARP_FAILURE opcode */ 4659dec900cSHariprasad S rpl->ot.opcode = FAKE_CPL_PUT_EP_SAFE; 4669dec900cSHariprasad S 4679dec900cSHariprasad S /* 4689dec900cSHariprasad S * Save ep in the skb->cb area, after where sched() will save the dev 4699dec900cSHariprasad S * ptr. 4709dec900cSHariprasad S */ 4719dec900cSHariprasad S *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *))) = ep; 4729dec900cSHariprasad S sched(ep->com.dev, skb); 4739dec900cSHariprasad S } 4749dec900cSHariprasad S 4759dec900cSHariprasad S /* Handle an ARP failure for an accept */ 4769dec900cSHariprasad S static void pass_accept_rpl_arp_failure(void *handle, struct sk_buff *skb) 4779dec900cSHariprasad S { 4789dec900cSHariprasad S struct c4iw_ep *ep = handle; 4799dec900cSHariprasad S 4809dec900cSHariprasad S pr_err(MOD "ARP failure during accept - tid %u -dropping connection\n", 4819dec900cSHariprasad S ep->hwtid); 4829dec900cSHariprasad S 4839dec900cSHariprasad S __state_set(&ep->com, DEAD); 4849dec900cSHariprasad S queue_arp_failure_cpl(ep, skb); 4859dec900cSHariprasad S } 4869dec900cSHariprasad S 487cfdda9d7SSteve Wise /* 488cfdda9d7SSteve Wise * Handle an ARP failure for an active open. 489cfdda9d7SSteve Wise */ 490cfdda9d7SSteve Wise static void act_open_req_arp_failure(void *handle, struct sk_buff *skb) 491cfdda9d7SSteve Wise { 4925dab6d3aSHariprasad S struct c4iw_ep *ep = handle; 4935dab6d3aSHariprasad S 494e3d132d1SMasanari Iida printk(KERN_ERR MOD "ARP failure during connect\n"); 4955dab6d3aSHariprasad S connect_reply_upcall(ep, -EHOSTUNREACH); 4969dec900cSHariprasad S __state_set(&ep->com, DEAD); 49784cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 49884cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 499170003c8SSteve Wise (struct sockaddr_in6 *)&ep->com.local_addr; 50084cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 50184cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 50284cc6ac6SHariprasad S } 5035dab6d3aSHariprasad S remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid); 5045dab6d3aSHariprasad S cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid); 5059dec900cSHariprasad S queue_arp_failure_cpl(ep, skb); 506cfdda9d7SSteve Wise } 507cfdda9d7SSteve Wise 508cfdda9d7SSteve Wise /* 509cfdda9d7SSteve Wise * Handle an ARP failure for a CPL_ABORT_REQ. Change it into a no RST variant 510cfdda9d7SSteve Wise * and send it along. 511cfdda9d7SSteve Wise */ 512cfdda9d7SSteve Wise static void abort_arp_failure(void *handle, struct sk_buff *skb) 513cfdda9d7SSteve Wise { 514cfdda9d7SSteve Wise struct c4iw_rdev *rdev = handle; 515cfdda9d7SSteve Wise struct cpl_abort_req *req = cplhdr(skb); 516cfdda9d7SSteve Wise 517cfdda9d7SSteve Wise PDBG("%s rdev %p\n", __func__, rdev); 518cfdda9d7SSteve Wise req->cmd = CPL_ABORT_NO_RST; 519cfdda9d7SSteve Wise c4iw_ofld_send(rdev, skb); 520cfdda9d7SSteve Wise } 521cfdda9d7SSteve Wise 522fef4422dSHariprasad S static int send_flowc(struct c4iw_ep *ep, struct sk_buff *skb) 523cfdda9d7SSteve Wise { 524cfdda9d7SSteve Wise unsigned int flowclen = 80; 525cfdda9d7SSteve Wise struct fw_flowc_wr *flowc; 526cfdda9d7SSteve Wise int i; 527ac8e4c69SHariprasad S u16 vlan = ep->l2t->vlan; 528ac8e4c69SHariprasad S int nparams; 529ac8e4c69SHariprasad S 530ac8e4c69SHariprasad S if (vlan == CPL_L2T_VLAN_NONE) 531ac8e4c69SHariprasad S nparams = 8; 532ac8e4c69SHariprasad S else 533ac8e4c69SHariprasad S nparams = 9; 534cfdda9d7SSteve Wise 535cfdda9d7SSteve Wise skb = get_skb(skb, flowclen, GFP_KERNEL); 536cfdda9d7SSteve Wise flowc = (struct fw_flowc_wr *)__skb_put(skb, flowclen); 537cfdda9d7SSteve Wise 538e2ac9628SHariprasad Shenai flowc->op_to_nparams = cpu_to_be32(FW_WR_OP_V(FW_FLOWC_WR) | 539ac8e4c69SHariprasad S FW_FLOWC_WR_NPARAMS_V(nparams)); 540e2ac9628SHariprasad Shenai flowc->flowid_len16 = cpu_to_be32(FW_WR_LEN16_V(DIV_ROUND_UP(flowclen, 541e2ac9628SHariprasad Shenai 16)) | FW_WR_FLOWID_V(ep->hwtid)); 542cfdda9d7SSteve Wise 543cfdda9d7SSteve Wise flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN; 5445167865aSHariprasad Shenai flowc->mnemval[0].val = cpu_to_be32(FW_PFVF_CMD_PFN_V 54535b1de55SHariprasad Shenai (ep->com.dev->rdev.lldi.pf)); 546cfdda9d7SSteve Wise flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH; 547cfdda9d7SSteve Wise flowc->mnemval[1].val = cpu_to_be32(ep->tx_chan); 548cfdda9d7SSteve Wise flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT; 549cfdda9d7SSteve Wise flowc->mnemval[2].val = cpu_to_be32(ep->tx_chan); 550cfdda9d7SSteve Wise flowc->mnemval[3].mnemonic = FW_FLOWC_MNEM_IQID; 551cfdda9d7SSteve Wise flowc->mnemval[3].val = cpu_to_be32(ep->rss_qid); 552cfdda9d7SSteve Wise flowc->mnemval[4].mnemonic = FW_FLOWC_MNEM_SNDNXT; 553cfdda9d7SSteve Wise flowc->mnemval[4].val = cpu_to_be32(ep->snd_seq); 554cfdda9d7SSteve Wise flowc->mnemval[5].mnemonic = FW_FLOWC_MNEM_RCVNXT; 555cfdda9d7SSteve Wise flowc->mnemval[5].val = cpu_to_be32(ep->rcv_seq); 556cfdda9d7SSteve Wise flowc->mnemval[6].mnemonic = FW_FLOWC_MNEM_SNDBUF; 557b408ff28SHariprasad Shenai flowc->mnemval[6].val = cpu_to_be32(ep->snd_win); 558cfdda9d7SSteve Wise flowc->mnemval[7].mnemonic = FW_FLOWC_MNEM_MSS; 559cfdda9d7SSteve Wise flowc->mnemval[7].val = cpu_to_be32(ep->emss); 560ac8e4c69SHariprasad S if (nparams == 9) { 561ac8e4c69SHariprasad S u16 pri; 562ac8e4c69SHariprasad S 563ac8e4c69SHariprasad S pri = (vlan & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; 564ac8e4c69SHariprasad S flowc->mnemval[8].mnemonic = FW_FLOWC_MNEM_SCHEDCLASS; 565ac8e4c69SHariprasad S flowc->mnemval[8].val = cpu_to_be32(pri); 566ac8e4c69SHariprasad S } else { 567cfdda9d7SSteve Wise /* Pad WR to 16 byte boundary */ 568cfdda9d7SSteve Wise flowc->mnemval[8].mnemonic = 0; 569cfdda9d7SSteve Wise flowc->mnemval[8].val = 0; 570ac8e4c69SHariprasad S } 571cfdda9d7SSteve Wise for (i = 0; i < 9; i++) { 572cfdda9d7SSteve Wise flowc->mnemval[i].r4[0] = 0; 573cfdda9d7SSteve Wise flowc->mnemval[i].r4[1] = 0; 574cfdda9d7SSteve Wise flowc->mnemval[i].r4[2] = 0; 575cfdda9d7SSteve Wise } 576cfdda9d7SSteve Wise 577cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 578fef4422dSHariprasad S return c4iw_ofld_send(&ep->com.dev->rdev, skb); 579cfdda9d7SSteve Wise } 580cfdda9d7SSteve Wise 581cfdda9d7SSteve Wise static int send_halfclose(struct c4iw_ep *ep, gfp_t gfp) 582cfdda9d7SSteve Wise { 583cfdda9d7SSteve Wise struct cpl_close_con_req *req; 584cfdda9d7SSteve Wise struct sk_buff *skb; 585cfdda9d7SSteve Wise int wrlen = roundup(sizeof *req, 16); 586cfdda9d7SSteve Wise 587cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 588cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, gfp); 589cfdda9d7SSteve Wise if (!skb) { 590cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - failed to alloc skb\n", __func__); 591cfdda9d7SSteve Wise return -ENOMEM; 592cfdda9d7SSteve Wise } 593cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 594cfdda9d7SSteve Wise t4_set_arp_err_handler(skb, NULL, arp_failure_discard); 595cfdda9d7SSteve Wise req = (struct cpl_close_con_req *) skb_put(skb, wrlen); 596cfdda9d7SSteve Wise memset(req, 0, wrlen); 597cfdda9d7SSteve Wise INIT_TP_WR(req, ep->hwtid); 598cfdda9d7SSteve Wise OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, 599cfdda9d7SSteve Wise ep->hwtid)); 600cfdda9d7SSteve Wise return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 601cfdda9d7SSteve Wise } 602cfdda9d7SSteve Wise 603cfdda9d7SSteve Wise static int send_abort(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp) 604cfdda9d7SSteve Wise { 605cfdda9d7SSteve Wise struct cpl_abort_req *req; 606cfdda9d7SSteve Wise int wrlen = roundup(sizeof *req, 16); 607cfdda9d7SSteve Wise 608cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 609cfdda9d7SSteve Wise skb = get_skb(skb, wrlen, gfp); 610cfdda9d7SSteve Wise if (!skb) { 611cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - failed to alloc skb.\n", 612cfdda9d7SSteve Wise __func__); 613cfdda9d7SSteve Wise return -ENOMEM; 614cfdda9d7SSteve Wise } 615cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 616cfdda9d7SSteve Wise t4_set_arp_err_handler(skb, &ep->com.dev->rdev, abort_arp_failure); 617cfdda9d7SSteve Wise req = (struct cpl_abort_req *) skb_put(skb, wrlen); 618cfdda9d7SSteve Wise memset(req, 0, wrlen); 619cfdda9d7SSteve Wise INIT_TP_WR(req, ep->hwtid); 620cfdda9d7SSteve Wise OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_REQ, ep->hwtid)); 621cfdda9d7SSteve Wise req->cmd = CPL_ABORT_SEND_RST; 622cfdda9d7SSteve Wise return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 623cfdda9d7SSteve Wise } 624cfdda9d7SSteve Wise 62592e7ae71SHariprasad Shenai static void best_mtu(const unsigned short *mtus, unsigned short mtu, 62604524a47SHariprasad S unsigned int *idx, int use_ts, int ipv6) 62792e7ae71SHariprasad Shenai { 62804524a47SHariprasad S unsigned short hdr_size = (ipv6 ? 62904524a47SHariprasad S sizeof(struct ipv6hdr) : 63004524a47SHariprasad S sizeof(struct iphdr)) + 63192e7ae71SHariprasad Shenai sizeof(struct tcphdr) + 63204524a47SHariprasad S (use_ts ? 63304524a47SHariprasad S round_up(TCPOLEN_TIMESTAMP, 4) : 0); 63492e7ae71SHariprasad Shenai unsigned short data_size = mtu - hdr_size; 63592e7ae71SHariprasad Shenai 63692e7ae71SHariprasad Shenai cxgb4_best_aligned_mtu(mtus, hdr_size, data_size, 8, idx); 63792e7ae71SHariprasad Shenai } 63892e7ae71SHariprasad Shenai 639cfdda9d7SSteve Wise static int send_connect(struct c4iw_ep *ep) 640cfdda9d7SSteve Wise { 641963cab50SHariprasad S struct cpl_act_open_req *req = NULL; 642963cab50SHariprasad S struct cpl_t5_act_open_req *t5req = NULL; 643963cab50SHariprasad S struct cpl_t6_act_open_req *t6req = NULL; 644963cab50SHariprasad S struct cpl_act_open_req6 *req6 = NULL; 645963cab50SHariprasad S struct cpl_t5_act_open_req6 *t5req6 = NULL; 646963cab50SHariprasad S struct cpl_t6_act_open_req6 *t6req6 = NULL; 647cfdda9d7SSteve Wise struct sk_buff *skb; 648cfdda9d7SSteve Wise u64 opt0; 649cfdda9d7SSteve Wise u32 opt2; 650cfdda9d7SSteve Wise unsigned int mtu_idx; 651cfdda9d7SSteve Wise int wscale; 652963cab50SHariprasad S int win, sizev4, sizev6, wrlen; 6539eccfe10SSteve Wise struct sockaddr_in *la = (struct sockaddr_in *) 654170003c8SSteve Wise &ep->com.local_addr; 6559eccfe10SSteve Wise struct sockaddr_in *ra = (struct sockaddr_in *) 656170003c8SSteve Wise &ep->com.remote_addr; 6579eccfe10SSteve Wise struct sockaddr_in6 *la6 = (struct sockaddr_in6 *) 658170003c8SSteve Wise &ep->com.local_addr; 6599eccfe10SSteve Wise struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *) 660170003c8SSteve Wise &ep->com.remote_addr; 66184cc6ac6SHariprasad S int ret; 662963cab50SHariprasad S enum chip_type adapter_type = ep->com.dev->rdev.lldi.adapter_type; 663963cab50SHariprasad S u32 isn = (prandom_u32() & ~7UL) - 1; 664963cab50SHariprasad S 665963cab50SHariprasad S switch (CHELSIO_CHIP_VERSION(adapter_type)) { 666963cab50SHariprasad S case CHELSIO_T4: 667963cab50SHariprasad S sizev4 = sizeof(struct cpl_act_open_req); 668963cab50SHariprasad S sizev6 = sizeof(struct cpl_act_open_req6); 669963cab50SHariprasad S break; 670963cab50SHariprasad S case CHELSIO_T5: 671963cab50SHariprasad S sizev4 = sizeof(struct cpl_t5_act_open_req); 672963cab50SHariprasad S sizev6 = sizeof(struct cpl_t5_act_open_req6); 673963cab50SHariprasad S break; 674963cab50SHariprasad S case CHELSIO_T6: 675963cab50SHariprasad S sizev4 = sizeof(struct cpl_t6_act_open_req); 676963cab50SHariprasad S sizev6 = sizeof(struct cpl_t6_act_open_req6); 677963cab50SHariprasad S break; 678963cab50SHariprasad S default: 679963cab50SHariprasad S pr_err("T%d Chip is not supported\n", 680963cab50SHariprasad S CHELSIO_CHIP_VERSION(adapter_type)); 681963cab50SHariprasad S return -EINVAL; 682963cab50SHariprasad S } 683830662f6SVipul Pandya 684830662f6SVipul Pandya wrlen = (ep->com.remote_addr.ss_family == AF_INET) ? 685830662f6SVipul Pandya roundup(sizev4, 16) : 686830662f6SVipul Pandya roundup(sizev6, 16); 687cfdda9d7SSteve Wise 688cfdda9d7SSteve Wise PDBG("%s ep %p atid %u\n", __func__, ep, ep->atid); 689cfdda9d7SSteve Wise 690cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 691cfdda9d7SSteve Wise if (!skb) { 692cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - failed to alloc skb.\n", 693cfdda9d7SSteve Wise __func__); 694cfdda9d7SSteve Wise return -ENOMEM; 695cfdda9d7SSteve Wise } 696d4f1a5c6SSteve Wise set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->ctrlq_idx); 697cfdda9d7SSteve Wise 69892e7ae71SHariprasad Shenai best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, 69904524a47SHariprasad S enable_tcp_timestamps, 70004524a47SHariprasad S (AF_INET == ep->com.remote_addr.ss_family) ? 0 : 1); 701cfdda9d7SSteve Wise wscale = compute_wscale(rcv_win); 702b408ff28SHariprasad Shenai 703b408ff28SHariprasad Shenai /* 704b408ff28SHariprasad Shenai * Specify the largest window that will fit in opt0. The 705b408ff28SHariprasad Shenai * remainder will be specified in the rx_data_ack. 706b408ff28SHariprasad Shenai */ 707b408ff28SHariprasad Shenai win = ep->rcv_win >> 10; 708d7990b0cSAnish Bhatt if (win > RCV_BUFSIZ_M) 709d7990b0cSAnish Bhatt win = RCV_BUFSIZ_M; 710b408ff28SHariprasad Shenai 7116c53e938SHariprasad Shenai opt0 = (nocong ? NO_CONG_F : 0) | 712d7990b0cSAnish Bhatt KEEP_ALIVE_F | 7136c53e938SHariprasad Shenai DELACK_F | 714d7990b0cSAnish Bhatt WND_SCALE_V(wscale) | 715d7990b0cSAnish Bhatt MSS_IDX_V(mtu_idx) | 716d7990b0cSAnish Bhatt L2T_IDX_V(ep->l2t->idx) | 717d7990b0cSAnish Bhatt TX_CHAN_V(ep->tx_chan) | 718d7990b0cSAnish Bhatt SMAC_SEL_V(ep->smac_idx) | 719ac8e4c69SHariprasad S DSCP_V(ep->tos >> 2) | 720d7990b0cSAnish Bhatt ULP_MODE_V(ULP_MODE_TCPDDP) | 721d7990b0cSAnish Bhatt RCV_BUFSIZ_V(win); 722d7990b0cSAnish Bhatt opt2 = RX_CHANNEL_V(0) | 7236c53e938SHariprasad Shenai CCTRL_ECN_V(enable_ecn) | 724d7990b0cSAnish Bhatt RSS_QUEUE_VALID_F | RSS_QUEUE_V(ep->rss_qid); 725cfdda9d7SSteve Wise if (enable_tcp_timestamps) 7266c53e938SHariprasad Shenai opt2 |= TSTAMPS_EN_F; 727cfdda9d7SSteve Wise if (enable_tcp_sack) 7286c53e938SHariprasad Shenai opt2 |= SACK_EN_F; 729cfdda9d7SSteve Wise if (wscale && enable_tcp_window_scaling) 730d7990b0cSAnish Bhatt opt2 |= WND_SCALE_EN_F; 731963cab50SHariprasad S if (CHELSIO_CHIP_VERSION(adapter_type) > CHELSIO_T4) { 732963cab50SHariprasad S if (peer2peer) 733963cab50SHariprasad S isn += 4; 734963cab50SHariprasad S 735d7990b0cSAnish Bhatt opt2 |= T5_OPT_2_VALID_F; 736cf7fe64aSHariprasad Shenai opt2 |= CONG_CNTRL_V(CONG_ALG_TAHOE); 7370b741047SHariprasad S opt2 |= T5_ISS_F; 73892e5011aSSteve Wise } 73984cc6ac6SHariprasad S 74084cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) 74184cc6ac6SHariprasad S cxgb4_clip_get(ep->com.dev->rdev.lldi.ports[0], 74284cc6ac6SHariprasad S (const u32 *)&la6->sin6_addr.s6_addr, 1); 74384cc6ac6SHariprasad S 7445dab6d3aSHariprasad S t4_set_arp_err_handler(skb, ep, act_open_req_arp_failure); 745cfdda9d7SSteve Wise 746830662f6SVipul Pandya if (ep->com.remote_addr.ss_family == AF_INET) { 747963cab50SHariprasad S switch (CHELSIO_CHIP_VERSION(adapter_type)) { 748963cab50SHariprasad S case CHELSIO_T4: 749cfdda9d7SSteve Wise req = (struct cpl_act_open_req *)skb_put(skb, wrlen); 750cfdda9d7SSteve Wise INIT_TP_WR(req, 0); 751963cab50SHariprasad S break; 752963cab50SHariprasad S case CHELSIO_T5: 753963cab50SHariprasad S t5req = (struct cpl_t5_act_open_req *)skb_put(skb, 754963cab50SHariprasad S wrlen); 755963cab50SHariprasad S INIT_TP_WR(t5req, 0); 756963cab50SHariprasad S req = (struct cpl_act_open_req *)t5req; 757963cab50SHariprasad S break; 758963cab50SHariprasad S case CHELSIO_T6: 759963cab50SHariprasad S t6req = (struct cpl_t6_act_open_req *)skb_put(skb, 760963cab50SHariprasad S wrlen); 761963cab50SHariprasad S INIT_TP_WR(t6req, 0); 762963cab50SHariprasad S req = (struct cpl_act_open_req *)t6req; 763963cab50SHariprasad S t5req = (struct cpl_t5_act_open_req *)t6req; 764963cab50SHariprasad S break; 765963cab50SHariprasad S default: 766963cab50SHariprasad S pr_err("T%d Chip is not supported\n", 767963cab50SHariprasad S CHELSIO_CHIP_VERSION(adapter_type)); 768963cab50SHariprasad S ret = -EINVAL; 769963cab50SHariprasad S goto clip_release; 770963cab50SHariprasad S } 771963cab50SHariprasad S 772963cab50SHariprasad S OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, 773f079af7aSVipul Pandya ((ep->rss_qid<<14) | ep->atid))); 774830662f6SVipul Pandya req->local_port = la->sin_port; 775830662f6SVipul Pandya req->peer_port = ra->sin_port; 776830662f6SVipul Pandya req->local_ip = la->sin_addr.s_addr; 777830662f6SVipul Pandya req->peer_ip = ra->sin_addr.s_addr; 778cfdda9d7SSteve Wise req->opt0 = cpu_to_be64(opt0); 779963cab50SHariprasad S 780963cab50SHariprasad S if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) { 78141b4f86cSKumar Sanghvi req->params = cpu_to_be32(cxgb4_select_ntuple( 78241b4f86cSKumar Sanghvi ep->com.dev->rdev.lldi.ports[0], 78341b4f86cSKumar Sanghvi ep->l2t)); 784cfdda9d7SSteve Wise req->opt2 = cpu_to_be32(opt2); 785f079af7aSVipul Pandya } else { 786963cab50SHariprasad S t5req->params = cpu_to_be64(FILTER_TUPLE_V( 787963cab50SHariprasad S cxgb4_select_ntuple( 788963cab50SHariprasad S ep->com.dev->rdev.lldi.ports[0], 789963cab50SHariprasad S ep->l2t))); 790963cab50SHariprasad S t5req->rsvd = cpu_to_be32(isn); 791963cab50SHariprasad S PDBG("%s snd_isn %u\n", __func__, t5req->rsvd); 792963cab50SHariprasad S t5req->opt2 = cpu_to_be32(opt2); 793963cab50SHariprasad S } 794963cab50SHariprasad S } else { 795963cab50SHariprasad S switch (CHELSIO_CHIP_VERSION(adapter_type)) { 796963cab50SHariprasad S case CHELSIO_T4: 797830662f6SVipul Pandya req6 = (struct cpl_act_open_req6 *)skb_put(skb, wrlen); 798830662f6SVipul Pandya INIT_TP_WR(req6, 0); 799963cab50SHariprasad S break; 800963cab50SHariprasad S case CHELSIO_T5: 801963cab50SHariprasad S t5req6 = (struct cpl_t5_act_open_req6 *)skb_put(skb, 802963cab50SHariprasad S wrlen); 803963cab50SHariprasad S INIT_TP_WR(t5req6, 0); 804963cab50SHariprasad S req6 = (struct cpl_act_open_req6 *)t5req6; 805963cab50SHariprasad S break; 806963cab50SHariprasad S case CHELSIO_T6: 807963cab50SHariprasad S t6req6 = (struct cpl_t6_act_open_req6 *)skb_put(skb, 808963cab50SHariprasad S wrlen); 809963cab50SHariprasad S INIT_TP_WR(t6req6, 0); 810963cab50SHariprasad S req6 = (struct cpl_act_open_req6 *)t6req6; 811963cab50SHariprasad S t5req6 = (struct cpl_t5_act_open_req6 *)t6req6; 812963cab50SHariprasad S break; 813963cab50SHariprasad S default: 814963cab50SHariprasad S pr_err("T%d Chip is not supported\n", 815963cab50SHariprasad S CHELSIO_CHIP_VERSION(adapter_type)); 816963cab50SHariprasad S ret = -EINVAL; 817963cab50SHariprasad S goto clip_release; 818963cab50SHariprasad S } 819963cab50SHariprasad S 820963cab50SHariprasad S OPCODE_TID(req6) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ6, 821830662f6SVipul Pandya ((ep->rss_qid<<14)|ep->atid))); 822830662f6SVipul Pandya req6->local_port = la6->sin6_port; 823830662f6SVipul Pandya req6->peer_port = ra6->sin6_port; 824963cab50SHariprasad S req6->local_ip_hi = *((__be64 *)(la6->sin6_addr.s6_addr)); 825963cab50SHariprasad S req6->local_ip_lo = *((__be64 *)(la6->sin6_addr.s6_addr + 8)); 826963cab50SHariprasad S req6->peer_ip_hi = *((__be64 *)(ra6->sin6_addr.s6_addr)); 827963cab50SHariprasad S req6->peer_ip_lo = *((__be64 *)(ra6->sin6_addr.s6_addr + 8)); 828830662f6SVipul Pandya req6->opt0 = cpu_to_be64(opt0); 829963cab50SHariprasad S 830963cab50SHariprasad S if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) { 83141b4f86cSKumar Sanghvi req6->params = cpu_to_be32(cxgb4_select_ntuple( 83241b4f86cSKumar Sanghvi ep->com.dev->rdev.lldi.ports[0], 833830662f6SVipul Pandya ep->l2t)); 834830662f6SVipul Pandya req6->opt2 = cpu_to_be32(opt2); 835830662f6SVipul Pandya } else { 836963cab50SHariprasad S t5req6->params = cpu_to_be64(FILTER_TUPLE_V( 83741b4f86cSKumar Sanghvi cxgb4_select_ntuple( 83841b4f86cSKumar Sanghvi ep->com.dev->rdev.lldi.ports[0], 83941b4f86cSKumar Sanghvi ep->l2t))); 840963cab50SHariprasad S t5req6->rsvd = cpu_to_be32(isn); 841963cab50SHariprasad S PDBG("%s snd_isn %u\n", __func__, t5req6->rsvd); 842963cab50SHariprasad S t5req6->opt2 = cpu_to_be32(opt2); 843830662f6SVipul Pandya } 844f079af7aSVipul Pandya } 845f079af7aSVipul Pandya 846793dad94SVipul Pandya set_bit(ACT_OPEN_REQ, &ep->com.history); 84784cc6ac6SHariprasad S ret = c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 848963cab50SHariprasad S clip_release: 84984cc6ac6SHariprasad S if (ret && ep->com.remote_addr.ss_family == AF_INET6) 85084cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 85184cc6ac6SHariprasad S (const u32 *)&la6->sin6_addr.s6_addr, 1); 85284cc6ac6SHariprasad S return ret; 853cfdda9d7SSteve Wise } 854cfdda9d7SSteve Wise 855d2fe99e8SKumar Sanghvi static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb, 856d2fe99e8SKumar Sanghvi u8 mpa_rev_to_use) 857cfdda9d7SSteve Wise { 858cfdda9d7SSteve Wise int mpalen, wrlen; 859cfdda9d7SSteve Wise struct fw_ofld_tx_data_wr *req; 860cfdda9d7SSteve Wise struct mpa_message *mpa; 861d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params mpa_v2_params; 862cfdda9d7SSteve Wise 863cfdda9d7SSteve Wise PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen); 864cfdda9d7SSteve Wise 865cfdda9d7SSteve Wise BUG_ON(skb_cloned(skb)); 866cfdda9d7SSteve Wise 867cfdda9d7SSteve Wise mpalen = sizeof(*mpa) + ep->plen; 868d2fe99e8SKumar Sanghvi if (mpa_rev_to_use == 2) 869d2fe99e8SKumar Sanghvi mpalen += sizeof(struct mpa_v2_conn_params); 870cfdda9d7SSteve Wise wrlen = roundup(mpalen + sizeof *req, 16); 871cfdda9d7SSteve Wise skb = get_skb(skb, wrlen, GFP_KERNEL); 872cfdda9d7SSteve Wise if (!skb) { 873cfdda9d7SSteve Wise connect_reply_upcall(ep, -ENOMEM); 874cfdda9d7SSteve Wise return; 875cfdda9d7SSteve Wise } 876cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 877cfdda9d7SSteve Wise 878cfdda9d7SSteve Wise req = (struct fw_ofld_tx_data_wr *)skb_put(skb, wrlen); 879cfdda9d7SSteve Wise memset(req, 0, wrlen); 880cfdda9d7SSteve Wise req->op_to_immdlen = cpu_to_be32( 881e2ac9628SHariprasad Shenai FW_WR_OP_V(FW_OFLD_TX_DATA_WR) | 882e2ac9628SHariprasad Shenai FW_WR_COMPL_F | 883e2ac9628SHariprasad Shenai FW_WR_IMMDLEN_V(mpalen)); 884cfdda9d7SSteve Wise req->flowid_len16 = cpu_to_be32( 885e2ac9628SHariprasad Shenai FW_WR_FLOWID_V(ep->hwtid) | 886e2ac9628SHariprasad Shenai FW_WR_LEN16_V(wrlen >> 4)); 887cfdda9d7SSteve Wise req->plen = cpu_to_be32(mpalen); 888cfdda9d7SSteve Wise req->tunnel_to_proxy = cpu_to_be32( 889e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_FLUSH_F | 890e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_SHOVE_F); 891cfdda9d7SSteve Wise 892cfdda9d7SSteve Wise mpa = (struct mpa_message *)(req + 1); 893cfdda9d7SSteve Wise memcpy(mpa->key, MPA_KEY_REQ, sizeof(mpa->key)); 894cfdda9d7SSteve Wise mpa->flags = (crc_enabled ? MPA_CRC : 0) | 895d2fe99e8SKumar Sanghvi (markers_enabled ? MPA_MARKERS : 0) | 896d2fe99e8SKumar Sanghvi (mpa_rev_to_use == 2 ? MPA_ENHANCED_RDMA_CONN : 0); 897cfdda9d7SSteve Wise mpa->private_data_size = htons(ep->plen); 898d2fe99e8SKumar Sanghvi mpa->revision = mpa_rev_to_use; 89901b225e1SKumar Sanghvi if (mpa_rev_to_use == 1) { 900d2fe99e8SKumar Sanghvi ep->tried_with_mpa_v1 = 1; 90101b225e1SKumar Sanghvi ep->retry_with_mpa_v1 = 0; 90201b225e1SKumar Sanghvi } 903d2fe99e8SKumar Sanghvi 904d2fe99e8SKumar Sanghvi if (mpa_rev_to_use == 2) { 905f747c34aSRoland Dreier mpa->private_data_size = htons(ntohs(mpa->private_data_size) + 906f747c34aSRoland Dreier sizeof (struct mpa_v2_conn_params)); 9074c2c5763SHariprasad Shenai PDBG("%s initiator ird %u ord %u\n", __func__, ep->ird, 9084c2c5763SHariprasad Shenai ep->ord); 909d2fe99e8SKumar Sanghvi mpa_v2_params.ird = htons((u16)ep->ird); 910d2fe99e8SKumar Sanghvi mpa_v2_params.ord = htons((u16)ep->ord); 911d2fe99e8SKumar Sanghvi 912d2fe99e8SKumar Sanghvi if (peer2peer) { 913d2fe99e8SKumar Sanghvi mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL); 914d2fe99e8SKumar Sanghvi if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE) 915d2fe99e8SKumar Sanghvi mpa_v2_params.ord |= 916d2fe99e8SKumar Sanghvi htons(MPA_V2_RDMA_WRITE_RTR); 917d2fe99e8SKumar Sanghvi else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) 918d2fe99e8SKumar Sanghvi mpa_v2_params.ord |= 919d2fe99e8SKumar Sanghvi htons(MPA_V2_RDMA_READ_RTR); 920d2fe99e8SKumar Sanghvi } 921d2fe99e8SKumar Sanghvi memcpy(mpa->private_data, &mpa_v2_params, 922d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params)); 923cfdda9d7SSteve Wise 924cfdda9d7SSteve Wise if (ep->plen) 925d2fe99e8SKumar Sanghvi memcpy(mpa->private_data + 926d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params), 927d2fe99e8SKumar Sanghvi ep->mpa_pkt + sizeof(*mpa), ep->plen); 928d2fe99e8SKumar Sanghvi } else 929d2fe99e8SKumar Sanghvi if (ep->plen) 930d2fe99e8SKumar Sanghvi memcpy(mpa->private_data, 931d2fe99e8SKumar Sanghvi ep->mpa_pkt + sizeof(*mpa), ep->plen); 932cfdda9d7SSteve Wise 933cfdda9d7SSteve Wise /* 934cfdda9d7SSteve Wise * Reference the mpa skb. This ensures the data area 935cfdda9d7SSteve Wise * will remain in memory until the hw acks the tx. 936cfdda9d7SSteve Wise * Function fw4_ack() will deref it. 937cfdda9d7SSteve Wise */ 938cfdda9d7SSteve Wise skb_get(skb); 939cfdda9d7SSteve Wise t4_set_arp_err_handler(skb, NULL, arp_failure_discard); 940cfdda9d7SSteve Wise BUG_ON(ep->mpa_skb); 941cfdda9d7SSteve Wise ep->mpa_skb = skb; 942cfdda9d7SSteve Wise c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 943cfdda9d7SSteve Wise start_ep_timer(ep); 944a7db89ebSSteve Wise __state_set(&ep->com, MPA_REQ_SENT); 945cfdda9d7SSteve Wise ep->mpa_attr.initiator = 1; 9469c88aa00SSteve Wise ep->snd_seq += mpalen; 947cfdda9d7SSteve Wise return; 948cfdda9d7SSteve Wise } 949cfdda9d7SSteve Wise 950cfdda9d7SSteve Wise static int send_mpa_reject(struct c4iw_ep *ep, const void *pdata, u8 plen) 951cfdda9d7SSteve Wise { 952cfdda9d7SSteve Wise int mpalen, wrlen; 953cfdda9d7SSteve Wise struct fw_ofld_tx_data_wr *req; 954cfdda9d7SSteve Wise struct mpa_message *mpa; 955cfdda9d7SSteve Wise struct sk_buff *skb; 956d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params mpa_v2_params; 957cfdda9d7SSteve Wise 958cfdda9d7SSteve Wise PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen); 959cfdda9d7SSteve Wise 960cfdda9d7SSteve Wise mpalen = sizeof(*mpa) + plen; 961d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) 962d2fe99e8SKumar Sanghvi mpalen += sizeof(struct mpa_v2_conn_params); 963cfdda9d7SSteve Wise wrlen = roundup(mpalen + sizeof *req, 16); 964cfdda9d7SSteve Wise 965cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 966cfdda9d7SSteve Wise if (!skb) { 967cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __func__); 968cfdda9d7SSteve Wise return -ENOMEM; 969cfdda9d7SSteve Wise } 970cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 971cfdda9d7SSteve Wise 972cfdda9d7SSteve Wise req = (struct fw_ofld_tx_data_wr *)skb_put(skb, wrlen); 973cfdda9d7SSteve Wise memset(req, 0, wrlen); 974cfdda9d7SSteve Wise req->op_to_immdlen = cpu_to_be32( 975e2ac9628SHariprasad Shenai FW_WR_OP_V(FW_OFLD_TX_DATA_WR) | 976e2ac9628SHariprasad Shenai FW_WR_COMPL_F | 977e2ac9628SHariprasad Shenai FW_WR_IMMDLEN_V(mpalen)); 978cfdda9d7SSteve Wise req->flowid_len16 = cpu_to_be32( 979e2ac9628SHariprasad Shenai FW_WR_FLOWID_V(ep->hwtid) | 980e2ac9628SHariprasad Shenai FW_WR_LEN16_V(wrlen >> 4)); 981cfdda9d7SSteve Wise req->plen = cpu_to_be32(mpalen); 982cfdda9d7SSteve Wise req->tunnel_to_proxy = cpu_to_be32( 983e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_FLUSH_F | 984e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_SHOVE_F); 985cfdda9d7SSteve Wise 986cfdda9d7SSteve Wise mpa = (struct mpa_message *)(req + 1); 987cfdda9d7SSteve Wise memset(mpa, 0, sizeof(*mpa)); 988cfdda9d7SSteve Wise memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key)); 989cfdda9d7SSteve Wise mpa->flags = MPA_REJECT; 990fe7e0a4dSVipul Pandya mpa->revision = ep->mpa_attr.version; 991cfdda9d7SSteve Wise mpa->private_data_size = htons(plen); 992d2fe99e8SKumar Sanghvi 993d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 994d2fe99e8SKumar Sanghvi mpa->flags |= MPA_ENHANCED_RDMA_CONN; 995f747c34aSRoland Dreier mpa->private_data_size = htons(ntohs(mpa->private_data_size) + 996f747c34aSRoland Dreier sizeof (struct mpa_v2_conn_params)); 997d2fe99e8SKumar Sanghvi mpa_v2_params.ird = htons(((u16)ep->ird) | 998d2fe99e8SKumar Sanghvi (peer2peer ? MPA_V2_PEER2PEER_MODEL : 999d2fe99e8SKumar Sanghvi 0)); 1000d2fe99e8SKumar Sanghvi mpa_v2_params.ord = htons(((u16)ep->ord) | (peer2peer ? 1001d2fe99e8SKumar Sanghvi (p2p_type == 1002d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_RDMA_WRITE ? 1003d2fe99e8SKumar Sanghvi MPA_V2_RDMA_WRITE_RTR : p2p_type == 1004d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_READ_REQ ? 1005d2fe99e8SKumar Sanghvi MPA_V2_RDMA_READ_RTR : 0) : 0)); 1006d2fe99e8SKumar Sanghvi memcpy(mpa->private_data, &mpa_v2_params, 1007d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params)); 1008d2fe99e8SKumar Sanghvi 1009d2fe99e8SKumar Sanghvi if (ep->plen) 1010d2fe99e8SKumar Sanghvi memcpy(mpa->private_data + 1011d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params), pdata, plen); 1012d2fe99e8SKumar Sanghvi } else 1013cfdda9d7SSteve Wise if (plen) 1014cfdda9d7SSteve Wise memcpy(mpa->private_data, pdata, plen); 1015cfdda9d7SSteve Wise 1016cfdda9d7SSteve Wise /* 1017cfdda9d7SSteve Wise * Reference the mpa skb again. This ensures the data area 1018cfdda9d7SSteve Wise * will remain in memory until the hw acks the tx. 1019cfdda9d7SSteve Wise * Function fw4_ack() will deref it. 1020cfdda9d7SSteve Wise */ 1021cfdda9d7SSteve Wise skb_get(skb); 1022cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 1023cfdda9d7SSteve Wise t4_set_arp_err_handler(skb, NULL, arp_failure_discard); 1024cfdda9d7SSteve Wise BUG_ON(ep->mpa_skb); 1025cfdda9d7SSteve Wise ep->mpa_skb = skb; 10269c88aa00SSteve Wise ep->snd_seq += mpalen; 1027cfdda9d7SSteve Wise return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 1028cfdda9d7SSteve Wise } 1029cfdda9d7SSteve Wise 1030cfdda9d7SSteve Wise static int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen) 1031cfdda9d7SSteve Wise { 1032cfdda9d7SSteve Wise int mpalen, wrlen; 1033cfdda9d7SSteve Wise struct fw_ofld_tx_data_wr *req; 1034cfdda9d7SSteve Wise struct mpa_message *mpa; 1035cfdda9d7SSteve Wise struct sk_buff *skb; 1036d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params mpa_v2_params; 1037cfdda9d7SSteve Wise 1038cfdda9d7SSteve Wise PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen); 1039cfdda9d7SSteve Wise 1040cfdda9d7SSteve Wise mpalen = sizeof(*mpa) + plen; 1041d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) 1042d2fe99e8SKumar Sanghvi mpalen += sizeof(struct mpa_v2_conn_params); 1043cfdda9d7SSteve Wise wrlen = roundup(mpalen + sizeof *req, 16); 1044cfdda9d7SSteve Wise 1045cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 1046cfdda9d7SSteve Wise if (!skb) { 1047cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __func__); 1048cfdda9d7SSteve Wise return -ENOMEM; 1049cfdda9d7SSteve Wise } 1050cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 1051cfdda9d7SSteve Wise 1052cfdda9d7SSteve Wise req = (struct fw_ofld_tx_data_wr *) skb_put(skb, wrlen); 1053cfdda9d7SSteve Wise memset(req, 0, wrlen); 1054cfdda9d7SSteve Wise req->op_to_immdlen = cpu_to_be32( 1055e2ac9628SHariprasad Shenai FW_WR_OP_V(FW_OFLD_TX_DATA_WR) | 1056e2ac9628SHariprasad Shenai FW_WR_COMPL_F | 1057e2ac9628SHariprasad Shenai FW_WR_IMMDLEN_V(mpalen)); 1058cfdda9d7SSteve Wise req->flowid_len16 = cpu_to_be32( 1059e2ac9628SHariprasad Shenai FW_WR_FLOWID_V(ep->hwtid) | 1060e2ac9628SHariprasad Shenai FW_WR_LEN16_V(wrlen >> 4)); 1061cfdda9d7SSteve Wise req->plen = cpu_to_be32(mpalen); 1062cfdda9d7SSteve Wise req->tunnel_to_proxy = cpu_to_be32( 1063e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_FLUSH_F | 1064e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_SHOVE_F); 1065cfdda9d7SSteve Wise 1066cfdda9d7SSteve Wise mpa = (struct mpa_message *)(req + 1); 1067cfdda9d7SSteve Wise memset(mpa, 0, sizeof(*mpa)); 1068cfdda9d7SSteve Wise memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key)); 1069cfdda9d7SSteve Wise mpa->flags = (ep->mpa_attr.crc_enabled ? MPA_CRC : 0) | 1070cfdda9d7SSteve Wise (markers_enabled ? MPA_MARKERS : 0); 1071d2fe99e8SKumar Sanghvi mpa->revision = ep->mpa_attr.version; 1072cfdda9d7SSteve Wise mpa->private_data_size = htons(plen); 1073d2fe99e8SKumar Sanghvi 1074d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 1075d2fe99e8SKumar Sanghvi mpa->flags |= MPA_ENHANCED_RDMA_CONN; 1076f747c34aSRoland Dreier mpa->private_data_size = htons(ntohs(mpa->private_data_size) + 1077f747c34aSRoland Dreier sizeof (struct mpa_v2_conn_params)); 1078d2fe99e8SKumar Sanghvi mpa_v2_params.ird = htons((u16)ep->ird); 1079d2fe99e8SKumar Sanghvi mpa_v2_params.ord = htons((u16)ep->ord); 1080d2fe99e8SKumar Sanghvi if (peer2peer && (ep->mpa_attr.p2p_type != 1081d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_DISABLED)) { 1082d2fe99e8SKumar Sanghvi mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL); 1083d2fe99e8SKumar Sanghvi 1084d2fe99e8SKumar Sanghvi if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE) 1085d2fe99e8SKumar Sanghvi mpa_v2_params.ord |= 1086d2fe99e8SKumar Sanghvi htons(MPA_V2_RDMA_WRITE_RTR); 1087d2fe99e8SKumar Sanghvi else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) 1088d2fe99e8SKumar Sanghvi mpa_v2_params.ord |= 1089d2fe99e8SKumar Sanghvi htons(MPA_V2_RDMA_READ_RTR); 1090d2fe99e8SKumar Sanghvi } 1091d2fe99e8SKumar Sanghvi 1092d2fe99e8SKumar Sanghvi memcpy(mpa->private_data, &mpa_v2_params, 1093d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params)); 1094d2fe99e8SKumar Sanghvi 1095d2fe99e8SKumar Sanghvi if (ep->plen) 1096d2fe99e8SKumar Sanghvi memcpy(mpa->private_data + 1097d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params), pdata, plen); 1098d2fe99e8SKumar Sanghvi } else 1099cfdda9d7SSteve Wise if (plen) 1100cfdda9d7SSteve Wise memcpy(mpa->private_data, pdata, plen); 1101cfdda9d7SSteve Wise 1102cfdda9d7SSteve Wise /* 1103cfdda9d7SSteve Wise * Reference the mpa skb. This ensures the data area 1104cfdda9d7SSteve Wise * will remain in memory until the hw acks the tx. 1105cfdda9d7SSteve Wise * Function fw4_ack() will deref it. 1106cfdda9d7SSteve Wise */ 1107cfdda9d7SSteve Wise skb_get(skb); 1108cfdda9d7SSteve Wise t4_set_arp_err_handler(skb, NULL, arp_failure_discard); 1109cfdda9d7SSteve Wise ep->mpa_skb = skb; 1110a7db89ebSSteve Wise __state_set(&ep->com, MPA_REP_SENT); 11119c88aa00SSteve Wise ep->snd_seq += mpalen; 1112cfdda9d7SSteve Wise return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 1113cfdda9d7SSteve Wise } 1114cfdda9d7SSteve Wise 1115cfdda9d7SSteve Wise static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb) 1116cfdda9d7SSteve Wise { 1117cfdda9d7SSteve Wise struct c4iw_ep *ep; 1118cfdda9d7SSteve Wise struct cpl_act_establish *req = cplhdr(skb); 1119cfdda9d7SSteve Wise unsigned int tid = GET_TID(req); 11206c53e938SHariprasad Shenai unsigned int atid = TID_TID_G(ntohl(req->tos_atid)); 1121cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 1122fef4422dSHariprasad S int ret; 1123cfdda9d7SSteve Wise 1124cfdda9d7SSteve Wise ep = lookup_atid(t, atid); 1125cfdda9d7SSteve Wise 1126cfdda9d7SSteve Wise PDBG("%s ep %p tid %u snd_isn %u rcv_isn %u\n", __func__, ep, tid, 1127cfdda9d7SSteve Wise be32_to_cpu(req->snd_isn), be32_to_cpu(req->rcv_isn)); 1128cfdda9d7SSteve Wise 1129a7db89ebSSteve Wise mutex_lock(&ep->com.mutex); 1130cfdda9d7SSteve Wise dst_confirm(ep->dst); 1131cfdda9d7SSteve Wise 1132cfdda9d7SSteve Wise /* setup the hwtid for this connection */ 1133cfdda9d7SSteve Wise ep->hwtid = tid; 1134cfdda9d7SSteve Wise cxgb4_insert_tid(t, ep, tid); 1135793dad94SVipul Pandya insert_handle(dev, &dev->hwtid_idr, ep, ep->hwtid); 1136cfdda9d7SSteve Wise 1137cfdda9d7SSteve Wise ep->snd_seq = be32_to_cpu(req->snd_isn); 1138cfdda9d7SSteve Wise ep->rcv_seq = be32_to_cpu(req->rcv_isn); 1139cfdda9d7SSteve Wise 1140cfdda9d7SSteve Wise set_emss(ep, ntohs(req->tcp_opt)); 1141cfdda9d7SSteve Wise 1142cfdda9d7SSteve Wise /* dealloc the atid */ 1143793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, atid); 1144cfdda9d7SSteve Wise cxgb4_free_atid(t, atid); 1145793dad94SVipul Pandya set_bit(ACT_ESTAB, &ep->com.history); 1146cfdda9d7SSteve Wise 1147cfdda9d7SSteve Wise /* start MPA negotiation */ 1148fef4422dSHariprasad S ret = send_flowc(ep, NULL); 1149fef4422dSHariprasad S if (ret) 1150fef4422dSHariprasad S goto err; 1151d2fe99e8SKumar Sanghvi if (ep->retry_with_mpa_v1) 1152d2fe99e8SKumar Sanghvi send_mpa_req(ep, skb, 1); 1153d2fe99e8SKumar Sanghvi else 1154d2fe99e8SKumar Sanghvi send_mpa_req(ep, skb, mpa_rev); 1155a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 1156cfdda9d7SSteve Wise return 0; 1157fef4422dSHariprasad S err: 1158fef4422dSHariprasad S mutex_unlock(&ep->com.mutex); 1159fef4422dSHariprasad S connect_reply_upcall(ep, -ENOMEM); 1160fef4422dSHariprasad S c4iw_ep_disconnect(ep, 0, GFP_KERNEL); 1161fef4422dSHariprasad S return 0; 1162cfdda9d7SSteve Wise } 1163cfdda9d7SSteve Wise 1164be13b2dfSSteve Wise static void close_complete_upcall(struct c4iw_ep *ep, int status) 1165cfdda9d7SSteve Wise { 1166cfdda9d7SSteve Wise struct iw_cm_event event; 1167cfdda9d7SSteve Wise 1168cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1169cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1170cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CLOSE; 1171be13b2dfSSteve Wise event.status = status; 1172cfdda9d7SSteve Wise if (ep->com.cm_id) { 1173cfdda9d7SSteve Wise PDBG("close complete delivered ep %p cm_id %p tid %u\n", 1174cfdda9d7SSteve Wise ep, ep->com.cm_id, ep->hwtid); 1175cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 1176cfdda9d7SSteve Wise ep->com.cm_id->rem_ref(ep->com.cm_id); 1177cfdda9d7SSteve Wise ep->com.cm_id = NULL; 1178793dad94SVipul Pandya set_bit(CLOSE_UPCALL, &ep->com.history); 1179cfdda9d7SSteve Wise } 1180cfdda9d7SSteve Wise } 1181cfdda9d7SSteve Wise 1182cfdda9d7SSteve Wise static int abort_connection(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp) 1183cfdda9d7SSteve Wise { 1184cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1185cc18b939SSteve Wise __state_set(&ep->com, ABORTING); 1186793dad94SVipul Pandya set_bit(ABORT_CONN, &ep->com.history); 1187cfdda9d7SSteve Wise return send_abort(ep, skb, gfp); 1188cfdda9d7SSteve Wise } 1189cfdda9d7SSteve Wise 1190cfdda9d7SSteve Wise static void peer_close_upcall(struct c4iw_ep *ep) 1191cfdda9d7SSteve Wise { 1192cfdda9d7SSteve Wise struct iw_cm_event event; 1193cfdda9d7SSteve Wise 1194cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1195cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1196cfdda9d7SSteve Wise event.event = IW_CM_EVENT_DISCONNECT; 1197cfdda9d7SSteve Wise if (ep->com.cm_id) { 1198cfdda9d7SSteve Wise PDBG("peer close delivered ep %p cm_id %p tid %u\n", 1199cfdda9d7SSteve Wise ep, ep->com.cm_id, ep->hwtid); 1200cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 1201793dad94SVipul Pandya set_bit(DISCONN_UPCALL, &ep->com.history); 1202cfdda9d7SSteve Wise } 1203cfdda9d7SSteve Wise } 1204cfdda9d7SSteve Wise 1205cfdda9d7SSteve Wise static void peer_abort_upcall(struct c4iw_ep *ep) 1206cfdda9d7SSteve Wise { 1207cfdda9d7SSteve Wise struct iw_cm_event event; 1208cfdda9d7SSteve Wise 1209cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1210cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1211cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CLOSE; 1212cfdda9d7SSteve Wise event.status = -ECONNRESET; 1213cfdda9d7SSteve Wise if (ep->com.cm_id) { 1214cfdda9d7SSteve Wise PDBG("abort delivered ep %p cm_id %p tid %u\n", ep, 1215cfdda9d7SSteve Wise ep->com.cm_id, ep->hwtid); 1216cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 1217cfdda9d7SSteve Wise ep->com.cm_id->rem_ref(ep->com.cm_id); 1218cfdda9d7SSteve Wise ep->com.cm_id = NULL; 1219793dad94SVipul Pandya set_bit(ABORT_UPCALL, &ep->com.history); 1220cfdda9d7SSteve Wise } 1221cfdda9d7SSteve Wise } 1222cfdda9d7SSteve Wise 1223cfdda9d7SSteve Wise static void connect_reply_upcall(struct c4iw_ep *ep, int status) 1224cfdda9d7SSteve Wise { 1225cfdda9d7SSteve Wise struct iw_cm_event event; 1226cfdda9d7SSteve Wise 1227cfdda9d7SSteve Wise PDBG("%s ep %p tid %u status %d\n", __func__, ep, ep->hwtid, status); 1228cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1229cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CONNECT_REPLY; 1230cfdda9d7SSteve Wise event.status = status; 123124d44a39SSteve Wise memcpy(&event.local_addr, &ep->com.local_addr, 123224d44a39SSteve Wise sizeof(ep->com.local_addr)); 123324d44a39SSteve Wise memcpy(&event.remote_addr, &ep->com.remote_addr, 123424d44a39SSteve Wise sizeof(ep->com.remote_addr)); 1235cfdda9d7SSteve Wise 1236cfdda9d7SSteve Wise if ((status == 0) || (status == -ECONNREFUSED)) { 1237d2fe99e8SKumar Sanghvi if (!ep->tried_with_mpa_v1) { 1238d2fe99e8SKumar Sanghvi /* this means MPA_v2 is used */ 1239158c776dSHariprasad S event.ord = ep->ird; 1240158c776dSHariprasad S event.ird = ep->ord; 1241d2fe99e8SKumar Sanghvi event.private_data_len = ep->plen - 1242d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1243d2fe99e8SKumar Sanghvi event.private_data = ep->mpa_pkt + 1244d2fe99e8SKumar Sanghvi sizeof(struct mpa_message) + 1245d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1246d2fe99e8SKumar Sanghvi } else { 1247d2fe99e8SKumar Sanghvi /* this means MPA_v1 is used */ 1248158c776dSHariprasad S event.ord = cur_max_read_depth(ep->com.dev); 1249158c776dSHariprasad S event.ird = cur_max_read_depth(ep->com.dev); 1250cfdda9d7SSteve Wise event.private_data_len = ep->plen; 1251d2fe99e8SKumar Sanghvi event.private_data = ep->mpa_pkt + 1252d2fe99e8SKumar Sanghvi sizeof(struct mpa_message); 1253d2fe99e8SKumar Sanghvi } 1254cfdda9d7SSteve Wise } 125585963e4cSRoland Dreier 1256cfdda9d7SSteve Wise PDBG("%s ep %p tid %u status %d\n", __func__, ep, 1257cfdda9d7SSteve Wise ep->hwtid, status); 1258793dad94SVipul Pandya set_bit(CONN_RPL_UPCALL, &ep->com.history); 1259cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 126085963e4cSRoland Dreier 1261cfdda9d7SSteve Wise if (status < 0) { 1262cfdda9d7SSteve Wise ep->com.cm_id->rem_ref(ep->com.cm_id); 1263cfdda9d7SSteve Wise ep->com.cm_id = NULL; 1264cfdda9d7SSteve Wise } 1265cfdda9d7SSteve Wise } 1266cfdda9d7SSteve Wise 1267be13b2dfSSteve Wise static int connect_request_upcall(struct c4iw_ep *ep) 1268cfdda9d7SSteve Wise { 1269cfdda9d7SSteve Wise struct iw_cm_event event; 1270be13b2dfSSteve Wise int ret; 1271cfdda9d7SSteve Wise 1272cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1273cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1274cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CONNECT_REQUEST; 127524d44a39SSteve Wise memcpy(&event.local_addr, &ep->com.local_addr, 127624d44a39SSteve Wise sizeof(ep->com.local_addr)); 127724d44a39SSteve Wise memcpy(&event.remote_addr, &ep->com.remote_addr, 127824d44a39SSteve Wise sizeof(ep->com.remote_addr)); 1279d2fe99e8SKumar Sanghvi event.provider_data = ep; 1280d2fe99e8SKumar Sanghvi if (!ep->tried_with_mpa_v1) { 1281d2fe99e8SKumar Sanghvi /* this means MPA_v2 is used */ 1282d2fe99e8SKumar Sanghvi event.ord = ep->ord; 1283d2fe99e8SKumar Sanghvi event.ird = ep->ird; 1284d2fe99e8SKumar Sanghvi event.private_data_len = ep->plen - 1285d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1286d2fe99e8SKumar Sanghvi event.private_data = ep->mpa_pkt + sizeof(struct mpa_message) + 1287d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1288d2fe99e8SKumar Sanghvi } else { 1289d2fe99e8SKumar Sanghvi /* this means MPA_v1 is used. Send max supported */ 12904c2c5763SHariprasad Shenai event.ord = cur_max_read_depth(ep->com.dev); 12914c2c5763SHariprasad Shenai event.ird = cur_max_read_depth(ep->com.dev); 1292cfdda9d7SSteve Wise event.private_data_len = ep->plen; 1293cfdda9d7SSteve Wise event.private_data = ep->mpa_pkt + sizeof(struct mpa_message); 1294d2fe99e8SKumar Sanghvi } 1295cfdda9d7SSteve Wise c4iw_get_ep(&ep->com); 1296be13b2dfSSteve Wise ret = ep->parent_ep->com.cm_id->event_handler(ep->parent_ep->com.cm_id, 1297cfdda9d7SSteve Wise &event); 1298be13b2dfSSteve Wise if (ret) 1299be13b2dfSSteve Wise c4iw_put_ep(&ep->com); 1300793dad94SVipul Pandya set_bit(CONNREQ_UPCALL, &ep->com.history); 1301cfdda9d7SSteve Wise c4iw_put_ep(&ep->parent_ep->com); 1302be13b2dfSSteve Wise return ret; 1303cfdda9d7SSteve Wise } 1304cfdda9d7SSteve Wise 1305cfdda9d7SSteve Wise static void established_upcall(struct c4iw_ep *ep) 1306cfdda9d7SSteve Wise { 1307cfdda9d7SSteve Wise struct iw_cm_event event; 1308cfdda9d7SSteve Wise 1309cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1310cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1311cfdda9d7SSteve Wise event.event = IW_CM_EVENT_ESTABLISHED; 13123dd9a5dcSHariprasad S event.ird = ep->ord; 13133dd9a5dcSHariprasad S event.ord = ep->ird; 1314cfdda9d7SSteve Wise if (ep->com.cm_id) { 1315cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1316cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 1317793dad94SVipul Pandya set_bit(ESTAB_UPCALL, &ep->com.history); 1318cfdda9d7SSteve Wise } 1319cfdda9d7SSteve Wise } 1320cfdda9d7SSteve Wise 1321cfdda9d7SSteve Wise static int update_rx_credits(struct c4iw_ep *ep, u32 credits) 1322cfdda9d7SSteve Wise { 1323cfdda9d7SSteve Wise struct cpl_rx_data_ack *req; 1324cfdda9d7SSteve Wise struct sk_buff *skb; 1325cfdda9d7SSteve Wise int wrlen = roundup(sizeof *req, 16); 1326cfdda9d7SSteve Wise 1327cfdda9d7SSteve Wise PDBG("%s ep %p tid %u credits %u\n", __func__, ep, ep->hwtid, credits); 1328cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 1329cfdda9d7SSteve Wise if (!skb) { 1330cfdda9d7SSteve Wise printk(KERN_ERR MOD "update_rx_credits - cannot alloc skb!\n"); 1331cfdda9d7SSteve Wise return 0; 1332cfdda9d7SSteve Wise } 1333cfdda9d7SSteve Wise 1334b408ff28SHariprasad Shenai /* 1335b408ff28SHariprasad Shenai * If we couldn't specify the entire rcv window at connection setup 1336b408ff28SHariprasad Shenai * due to the limit in the number of bits in the RCV_BUFSIZ field, 1337b408ff28SHariprasad Shenai * then add the overage in to the credits returned. 1338b408ff28SHariprasad Shenai */ 1339d7990b0cSAnish Bhatt if (ep->rcv_win > RCV_BUFSIZ_M * 1024) 1340d7990b0cSAnish Bhatt credits += ep->rcv_win - RCV_BUFSIZ_M * 1024; 1341b408ff28SHariprasad Shenai 1342cfdda9d7SSteve Wise req = (struct cpl_rx_data_ack *) skb_put(skb, wrlen); 1343cfdda9d7SSteve Wise memset(req, 0, wrlen); 1344cfdda9d7SSteve Wise INIT_TP_WR(req, ep->hwtid); 1345cfdda9d7SSteve Wise OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_RX_DATA_ACK, 1346cfdda9d7SSteve Wise ep->hwtid)); 1347d7990b0cSAnish Bhatt req->credit_dack = cpu_to_be32(credits | RX_FORCE_ACK_F | 1348cf7fe64aSHariprasad Shenai RX_DACK_CHANGE_F | 1349cf7fe64aSHariprasad Shenai RX_DACK_MODE_V(dack_mode)); 1350d4f1a5c6SSteve Wise set_wr_txq(skb, CPL_PRIORITY_ACK, ep->ctrlq_idx); 1351cfdda9d7SSteve Wise c4iw_ofld_send(&ep->com.dev->rdev, skb); 1352cfdda9d7SSteve Wise return credits; 1353cfdda9d7SSteve Wise } 1354cfdda9d7SSteve Wise 13554c2c5763SHariprasad Shenai #define RELAXED_IRD_NEGOTIATION 1 13564c2c5763SHariprasad Shenai 1357f8e1e1d1SHariprasad S /* 1358f8e1e1d1SHariprasad S * process_mpa_reply - process streaming mode MPA reply 1359f8e1e1d1SHariprasad S * 1360f8e1e1d1SHariprasad S * Returns: 1361f8e1e1d1SHariprasad S * 1362f8e1e1d1SHariprasad S * 0 upon success indicating a connect request was delivered to the ULP 1363f8e1e1d1SHariprasad S * or the mpa request is incomplete but valid so far. 1364f8e1e1d1SHariprasad S * 1365f8e1e1d1SHariprasad S * 1 if a failure requires the caller to close the connection. 1366f8e1e1d1SHariprasad S * 1367f8e1e1d1SHariprasad S * 2 if a failure requires the caller to abort the connection. 1368f8e1e1d1SHariprasad S */ 1369cc18b939SSteve Wise static int process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb) 1370cfdda9d7SSteve Wise { 1371cfdda9d7SSteve Wise struct mpa_message *mpa; 1372d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params *mpa_v2_params; 1373cfdda9d7SSteve Wise u16 plen; 1374d2fe99e8SKumar Sanghvi u16 resp_ird, resp_ord; 1375d2fe99e8SKumar Sanghvi u8 rtr_mismatch = 0, insuff_ird = 0; 1376cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 1377cfdda9d7SSteve Wise enum c4iw_qp_attr_mask mask; 1378cfdda9d7SSteve Wise int err; 1379cc18b939SSteve Wise int disconnect = 0; 1380cfdda9d7SSteve Wise 1381cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1382cfdda9d7SSteve Wise 1383cfdda9d7SSteve Wise /* 1384b33bd0cbSSteve Wise * Stop mpa timer. If it expired, then 1385b33bd0cbSSteve Wise * we ignore the MPA reply. process_timeout() 1386b33bd0cbSSteve Wise * will abort the connection. 1387cfdda9d7SSteve Wise */ 1388b33bd0cbSSteve Wise if (stop_ep_timer(ep)) 1389cc18b939SSteve Wise return 0; 1390cfdda9d7SSteve Wise 1391cfdda9d7SSteve Wise /* 1392cfdda9d7SSteve Wise * If we get more than the supported amount of private data 1393cfdda9d7SSteve Wise * then we must fail this connection. 1394cfdda9d7SSteve Wise */ 1395cfdda9d7SSteve Wise if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) { 1396cfdda9d7SSteve Wise err = -EINVAL; 1397cfdda9d7SSteve Wise goto err; 1398cfdda9d7SSteve Wise } 1399cfdda9d7SSteve Wise 1400cfdda9d7SSteve Wise /* 1401cfdda9d7SSteve Wise * copy the new data into our accumulation buffer. 1402cfdda9d7SSteve Wise */ 1403cfdda9d7SSteve Wise skb_copy_from_linear_data(skb, &(ep->mpa_pkt[ep->mpa_pkt_len]), 1404cfdda9d7SSteve Wise skb->len); 1405cfdda9d7SSteve Wise ep->mpa_pkt_len += skb->len; 1406cfdda9d7SSteve Wise 1407cfdda9d7SSteve Wise /* 1408cfdda9d7SSteve Wise * if we don't even have the mpa message, then bail. 1409cfdda9d7SSteve Wise */ 1410cfdda9d7SSteve Wise if (ep->mpa_pkt_len < sizeof(*mpa)) 1411cc18b939SSteve Wise return 0; 1412cfdda9d7SSteve Wise mpa = (struct mpa_message *) ep->mpa_pkt; 1413cfdda9d7SSteve Wise 1414cfdda9d7SSteve Wise /* Validate MPA header. */ 1415d2fe99e8SKumar Sanghvi if (mpa->revision > mpa_rev) { 1416d2fe99e8SKumar Sanghvi printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d," 1417d2fe99e8SKumar Sanghvi " Received = %d\n", __func__, mpa_rev, mpa->revision); 1418cfdda9d7SSteve Wise err = -EPROTO; 1419cfdda9d7SSteve Wise goto err; 1420cfdda9d7SSteve Wise } 1421cfdda9d7SSteve Wise if (memcmp(mpa->key, MPA_KEY_REP, sizeof(mpa->key))) { 1422cfdda9d7SSteve Wise err = -EPROTO; 1423cfdda9d7SSteve Wise goto err; 1424cfdda9d7SSteve Wise } 1425cfdda9d7SSteve Wise 1426cfdda9d7SSteve Wise plen = ntohs(mpa->private_data_size); 1427cfdda9d7SSteve Wise 1428cfdda9d7SSteve Wise /* 1429cfdda9d7SSteve Wise * Fail if there's too much private data. 1430cfdda9d7SSteve Wise */ 1431cfdda9d7SSteve Wise if (plen > MPA_MAX_PRIVATE_DATA) { 1432cfdda9d7SSteve Wise err = -EPROTO; 1433cfdda9d7SSteve Wise goto err; 1434cfdda9d7SSteve Wise } 1435cfdda9d7SSteve Wise 1436cfdda9d7SSteve Wise /* 1437cfdda9d7SSteve Wise * If plen does not account for pkt size 1438cfdda9d7SSteve Wise */ 1439cfdda9d7SSteve Wise if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) { 1440cfdda9d7SSteve Wise err = -EPROTO; 1441cfdda9d7SSteve Wise goto err; 1442cfdda9d7SSteve Wise } 1443cfdda9d7SSteve Wise 1444cfdda9d7SSteve Wise ep->plen = (u8) plen; 1445cfdda9d7SSteve Wise 1446cfdda9d7SSteve Wise /* 1447cfdda9d7SSteve Wise * If we don't have all the pdata yet, then bail. 1448cfdda9d7SSteve Wise * We'll continue process when more data arrives. 1449cfdda9d7SSteve Wise */ 1450cfdda9d7SSteve Wise if (ep->mpa_pkt_len < (sizeof(*mpa) + plen)) 1451cc18b939SSteve Wise return 0; 1452cfdda9d7SSteve Wise 1453cfdda9d7SSteve Wise if (mpa->flags & MPA_REJECT) { 1454cfdda9d7SSteve Wise err = -ECONNREFUSED; 1455cfdda9d7SSteve Wise goto err; 1456cfdda9d7SSteve Wise } 1457cfdda9d7SSteve Wise 1458cfdda9d7SSteve Wise /* 1459cfdda9d7SSteve Wise * If we get here we have accumulated the entire mpa 1460cfdda9d7SSteve Wise * start reply message including private data. And 1461cfdda9d7SSteve Wise * the MPA header is valid. 1462cfdda9d7SSteve Wise */ 1463c529fb50SSteve Wise __state_set(&ep->com, FPDU_MODE); 1464cfdda9d7SSteve Wise ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0; 1465cfdda9d7SSteve Wise ep->mpa_attr.recv_marker_enabled = markers_enabled; 1466cfdda9d7SSteve Wise ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0; 1467d2fe99e8SKumar Sanghvi ep->mpa_attr.version = mpa->revision; 1468d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED; 1469d2fe99e8SKumar Sanghvi 1470d2fe99e8SKumar Sanghvi if (mpa->revision == 2) { 1471d2fe99e8SKumar Sanghvi ep->mpa_attr.enhanced_rdma_conn = 1472d2fe99e8SKumar Sanghvi mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0; 1473d2fe99e8SKumar Sanghvi if (ep->mpa_attr.enhanced_rdma_conn) { 1474d2fe99e8SKumar Sanghvi mpa_v2_params = (struct mpa_v2_conn_params *) 1475d2fe99e8SKumar Sanghvi (ep->mpa_pkt + sizeof(*mpa)); 1476d2fe99e8SKumar Sanghvi resp_ird = ntohs(mpa_v2_params->ird) & 1477d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 1478d2fe99e8SKumar Sanghvi resp_ord = ntohs(mpa_v2_params->ord) & 1479d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 14804c2c5763SHariprasad Shenai PDBG("%s responder ird %u ord %u ep ird %u ord %u\n", 14814c2c5763SHariprasad Shenai __func__, resp_ird, resp_ord, ep->ird, ep->ord); 1482d2fe99e8SKumar Sanghvi 1483d2fe99e8SKumar Sanghvi /* 1484d2fe99e8SKumar Sanghvi * This is a double-check. Ideally, below checks are 1485d2fe99e8SKumar Sanghvi * not required since ird/ord stuff has been taken 1486d2fe99e8SKumar Sanghvi * care of in c4iw_accept_cr 1487d2fe99e8SKumar Sanghvi */ 14884c2c5763SHariprasad Shenai if (ep->ird < resp_ord) { 14894c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION && resp_ord <= 14904c2c5763SHariprasad Shenai ep->com.dev->rdev.lldi.max_ordird_qp) 14914c2c5763SHariprasad Shenai ep->ird = resp_ord; 14924c2c5763SHariprasad Shenai else 14934c2c5763SHariprasad Shenai insuff_ird = 1; 14944c2c5763SHariprasad Shenai } else if (ep->ird > resp_ord) { 14954c2c5763SHariprasad Shenai ep->ird = resp_ord; 14964c2c5763SHariprasad Shenai } 14974c2c5763SHariprasad Shenai if (ep->ord > resp_ird) { 14984c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION) 14994c2c5763SHariprasad Shenai ep->ord = resp_ird; 15004c2c5763SHariprasad Shenai else 15014c2c5763SHariprasad Shenai insuff_ird = 1; 15024c2c5763SHariprasad Shenai } 15034c2c5763SHariprasad Shenai if (insuff_ird) { 1504d2fe99e8SKumar Sanghvi err = -ENOMEM; 1505d2fe99e8SKumar Sanghvi ep->ird = resp_ord; 1506d2fe99e8SKumar Sanghvi ep->ord = resp_ird; 1507d2fe99e8SKumar Sanghvi } 1508d2fe99e8SKumar Sanghvi 1509d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ird) & 1510d2fe99e8SKumar Sanghvi MPA_V2_PEER2PEER_MODEL) { 1511d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ord) & 1512d2fe99e8SKumar Sanghvi MPA_V2_RDMA_WRITE_RTR) 1513d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1514d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_RDMA_WRITE; 1515d2fe99e8SKumar Sanghvi else if (ntohs(mpa_v2_params->ord) & 1516d2fe99e8SKumar Sanghvi MPA_V2_RDMA_READ_RTR) 1517d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1518d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_READ_REQ; 1519d2fe99e8SKumar Sanghvi } 1520d2fe99e8SKumar Sanghvi } 1521d2fe99e8SKumar Sanghvi } else if (mpa->revision == 1) 1522d2fe99e8SKumar Sanghvi if (peer2peer) 1523d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = p2p_type; 1524d2fe99e8SKumar Sanghvi 1525cfdda9d7SSteve Wise PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, " 1526d2fe99e8SKumar Sanghvi "xmit_marker_enabled=%d, version=%d p2p_type=%d local-p2p_type = " 1527d2fe99e8SKumar Sanghvi "%d\n", __func__, ep->mpa_attr.crc_enabled, 1528d2fe99e8SKumar Sanghvi ep->mpa_attr.recv_marker_enabled, 1529d2fe99e8SKumar Sanghvi ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version, 1530d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type, p2p_type); 1531d2fe99e8SKumar Sanghvi 1532d2fe99e8SKumar Sanghvi /* 1533d2fe99e8SKumar Sanghvi * If responder's RTR does not match with that of initiator, assign 1534d2fe99e8SKumar Sanghvi * FW_RI_INIT_P2PTYPE_DISABLED in mpa attributes so that RTR is not 1535d2fe99e8SKumar Sanghvi * generated when moving QP to RTS state. 1536d2fe99e8SKumar Sanghvi * A TERM message will be sent after QP has moved to RTS state 1537d2fe99e8SKumar Sanghvi */ 153891018f86SKumar Sanghvi if ((ep->mpa_attr.version == 2) && peer2peer && 1539d2fe99e8SKumar Sanghvi (ep->mpa_attr.p2p_type != p2p_type)) { 1540d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED; 1541d2fe99e8SKumar Sanghvi rtr_mismatch = 1; 1542d2fe99e8SKumar Sanghvi } 1543cfdda9d7SSteve Wise 1544cfdda9d7SSteve Wise attrs.mpa_attr = ep->mpa_attr; 1545cfdda9d7SSteve Wise attrs.max_ird = ep->ird; 1546cfdda9d7SSteve Wise attrs.max_ord = ep->ord; 1547cfdda9d7SSteve Wise attrs.llp_stream_handle = ep; 1548cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_RTS; 1549cfdda9d7SSteve Wise 1550cfdda9d7SSteve Wise mask = C4IW_QP_ATTR_NEXT_STATE | 1551cfdda9d7SSteve Wise C4IW_QP_ATTR_LLP_STREAM_HANDLE | C4IW_QP_ATTR_MPA_ATTR | 1552cfdda9d7SSteve Wise C4IW_QP_ATTR_MAX_IRD | C4IW_QP_ATTR_MAX_ORD; 1553cfdda9d7SSteve Wise 1554cfdda9d7SSteve Wise /* bind QP and TID with INIT_WR */ 1555cfdda9d7SSteve Wise err = c4iw_modify_qp(ep->com.qp->rhp, 1556cfdda9d7SSteve Wise ep->com.qp, mask, &attrs, 1); 1557cfdda9d7SSteve Wise if (err) 1558cfdda9d7SSteve Wise goto err; 1559d2fe99e8SKumar Sanghvi 1560d2fe99e8SKumar Sanghvi /* 1561d2fe99e8SKumar Sanghvi * If responder's RTR requirement did not match with what initiator 1562d2fe99e8SKumar Sanghvi * supports, generate TERM message 1563d2fe99e8SKumar Sanghvi */ 1564d2fe99e8SKumar Sanghvi if (rtr_mismatch) { 1565d2fe99e8SKumar Sanghvi printk(KERN_ERR "%s: RTR mismatch, sending TERM\n", __func__); 1566d2fe99e8SKumar Sanghvi attrs.layer_etype = LAYER_MPA | DDP_LLP; 1567d2fe99e8SKumar Sanghvi attrs.ecode = MPA_NOMATCH_RTR; 1568d2fe99e8SKumar Sanghvi attrs.next_state = C4IW_QP_STATE_TERMINATE; 1569cc18b939SSteve Wise attrs.send_term = 1; 1570d2fe99e8SKumar Sanghvi err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 1571cc18b939SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 1572d2fe99e8SKumar Sanghvi err = -ENOMEM; 1573cc18b939SSteve Wise disconnect = 1; 1574d2fe99e8SKumar Sanghvi goto out; 1575d2fe99e8SKumar Sanghvi } 1576d2fe99e8SKumar Sanghvi 1577d2fe99e8SKumar Sanghvi /* 1578d2fe99e8SKumar Sanghvi * Generate TERM if initiator IRD is not sufficient for responder 1579d2fe99e8SKumar Sanghvi * provided ORD. Currently, we do the same behaviour even when 1580d2fe99e8SKumar Sanghvi * responder provided IRD is also not sufficient as regards to 1581d2fe99e8SKumar Sanghvi * initiator ORD. 1582d2fe99e8SKumar Sanghvi */ 1583d2fe99e8SKumar Sanghvi if (insuff_ird) { 1584d2fe99e8SKumar Sanghvi printk(KERN_ERR "%s: Insufficient IRD, sending TERM\n", 1585d2fe99e8SKumar Sanghvi __func__); 1586d2fe99e8SKumar Sanghvi attrs.layer_etype = LAYER_MPA | DDP_LLP; 1587d2fe99e8SKumar Sanghvi attrs.ecode = MPA_INSUFF_IRD; 1588d2fe99e8SKumar Sanghvi attrs.next_state = C4IW_QP_STATE_TERMINATE; 1589cc18b939SSteve Wise attrs.send_term = 1; 1590d2fe99e8SKumar Sanghvi err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 1591cc18b939SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 1592d2fe99e8SKumar Sanghvi err = -ENOMEM; 1593cc18b939SSteve Wise disconnect = 1; 1594d2fe99e8SKumar Sanghvi goto out; 1595d2fe99e8SKumar Sanghvi } 1596cfdda9d7SSteve Wise goto out; 1597cfdda9d7SSteve Wise err: 1598f8e1e1d1SHariprasad S disconnect = 2; 1599cfdda9d7SSteve Wise out: 1600cfdda9d7SSteve Wise connect_reply_upcall(ep, err); 1601cc18b939SSteve Wise return disconnect; 1602cfdda9d7SSteve Wise } 1603cfdda9d7SSteve Wise 1604fd6aabe4SHariprasad S /* 1605fd6aabe4SHariprasad S * process_mpa_request - process streaming mode MPA request 1606fd6aabe4SHariprasad S * 1607fd6aabe4SHariprasad S * Returns: 1608fd6aabe4SHariprasad S * 1609fd6aabe4SHariprasad S * 0 upon success indicating a connect request was delivered to the ULP 1610fd6aabe4SHariprasad S * or the mpa request is incomplete but valid so far. 1611fd6aabe4SHariprasad S * 1612fd6aabe4SHariprasad S * 1 if a failure requires the caller to close the connection. 1613fd6aabe4SHariprasad S * 1614fd6aabe4SHariprasad S * 2 if a failure requires the caller to abort the connection. 1615fd6aabe4SHariprasad S */ 1616fd6aabe4SHariprasad S static int process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb) 1617cfdda9d7SSteve Wise { 1618cfdda9d7SSteve Wise struct mpa_message *mpa; 1619d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params *mpa_v2_params; 1620cfdda9d7SSteve Wise u16 plen; 1621cfdda9d7SSteve Wise 1622cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1623cfdda9d7SSteve Wise 1624cfdda9d7SSteve Wise /* 1625cfdda9d7SSteve Wise * If we get more than the supported amount of private data 1626cfdda9d7SSteve Wise * then we must fail this connection. 1627cfdda9d7SSteve Wise */ 1628fd6aabe4SHariprasad S if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) 1629fd6aabe4SHariprasad S goto err_stop_timer; 1630cfdda9d7SSteve Wise 1631cfdda9d7SSteve Wise PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__); 1632cfdda9d7SSteve Wise 1633cfdda9d7SSteve Wise /* 1634cfdda9d7SSteve Wise * Copy the new data into our accumulation buffer. 1635cfdda9d7SSteve Wise */ 1636cfdda9d7SSteve Wise skb_copy_from_linear_data(skb, &(ep->mpa_pkt[ep->mpa_pkt_len]), 1637cfdda9d7SSteve Wise skb->len); 1638cfdda9d7SSteve Wise ep->mpa_pkt_len += skb->len; 1639cfdda9d7SSteve Wise 1640cfdda9d7SSteve Wise /* 1641cfdda9d7SSteve Wise * If we don't even have the mpa message, then bail. 1642cfdda9d7SSteve Wise * We'll continue process when more data arrives. 1643cfdda9d7SSteve Wise */ 1644cfdda9d7SSteve Wise if (ep->mpa_pkt_len < sizeof(*mpa)) 1645fd6aabe4SHariprasad S return 0; 1646cfdda9d7SSteve Wise 1647cfdda9d7SSteve Wise PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__); 1648cfdda9d7SSteve Wise mpa = (struct mpa_message *) ep->mpa_pkt; 1649cfdda9d7SSteve Wise 1650cfdda9d7SSteve Wise /* 1651cfdda9d7SSteve Wise * Validate MPA Header. 1652cfdda9d7SSteve Wise */ 1653d2fe99e8SKumar Sanghvi if (mpa->revision > mpa_rev) { 1654d2fe99e8SKumar Sanghvi printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d," 1655d2fe99e8SKumar Sanghvi " Received = %d\n", __func__, mpa_rev, mpa->revision); 1656fd6aabe4SHariprasad S goto err_stop_timer; 1657cfdda9d7SSteve Wise } 1658cfdda9d7SSteve Wise 1659fd6aabe4SHariprasad S if (memcmp(mpa->key, MPA_KEY_REQ, sizeof(mpa->key))) 1660fd6aabe4SHariprasad S goto err_stop_timer; 1661cfdda9d7SSteve Wise 1662cfdda9d7SSteve Wise plen = ntohs(mpa->private_data_size); 1663cfdda9d7SSteve Wise 1664cfdda9d7SSteve Wise /* 1665cfdda9d7SSteve Wise * Fail if there's too much private data. 1666cfdda9d7SSteve Wise */ 1667fd6aabe4SHariprasad S if (plen > MPA_MAX_PRIVATE_DATA) 1668fd6aabe4SHariprasad S goto err_stop_timer; 1669cfdda9d7SSteve Wise 1670cfdda9d7SSteve Wise /* 1671cfdda9d7SSteve Wise * If plen does not account for pkt size 1672cfdda9d7SSteve Wise */ 1673fd6aabe4SHariprasad S if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) 1674fd6aabe4SHariprasad S goto err_stop_timer; 1675cfdda9d7SSteve Wise ep->plen = (u8) plen; 1676cfdda9d7SSteve Wise 1677cfdda9d7SSteve Wise /* 1678cfdda9d7SSteve Wise * If we don't have all the pdata yet, then bail. 1679cfdda9d7SSteve Wise */ 1680cfdda9d7SSteve Wise if (ep->mpa_pkt_len < (sizeof(*mpa) + plen)) 1681fd6aabe4SHariprasad S return 0; 1682cfdda9d7SSteve Wise 1683cfdda9d7SSteve Wise /* 1684cfdda9d7SSteve Wise * If we get here we have accumulated the entire mpa 1685cfdda9d7SSteve Wise * start reply message including private data. 1686cfdda9d7SSteve Wise */ 1687cfdda9d7SSteve Wise ep->mpa_attr.initiator = 0; 1688cfdda9d7SSteve Wise ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0; 1689cfdda9d7SSteve Wise ep->mpa_attr.recv_marker_enabled = markers_enabled; 1690cfdda9d7SSteve Wise ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0; 1691d2fe99e8SKumar Sanghvi ep->mpa_attr.version = mpa->revision; 1692d2fe99e8SKumar Sanghvi if (mpa->revision == 1) 1693d2fe99e8SKumar Sanghvi ep->tried_with_mpa_v1 = 1; 1694d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED; 1695d2fe99e8SKumar Sanghvi 1696d2fe99e8SKumar Sanghvi if (mpa->revision == 2) { 1697d2fe99e8SKumar Sanghvi ep->mpa_attr.enhanced_rdma_conn = 1698d2fe99e8SKumar Sanghvi mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0; 1699d2fe99e8SKumar Sanghvi if (ep->mpa_attr.enhanced_rdma_conn) { 1700d2fe99e8SKumar Sanghvi mpa_v2_params = (struct mpa_v2_conn_params *) 1701d2fe99e8SKumar Sanghvi (ep->mpa_pkt + sizeof(*mpa)); 1702d2fe99e8SKumar Sanghvi ep->ird = ntohs(mpa_v2_params->ird) & 1703d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 1704d2fe99e8SKumar Sanghvi ep->ord = ntohs(mpa_v2_params->ord) & 1705d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 17064c2c5763SHariprasad Shenai PDBG("%s initiator ird %u ord %u\n", __func__, ep->ird, 17074c2c5763SHariprasad Shenai ep->ord); 1708d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ird) & MPA_V2_PEER2PEER_MODEL) 1709d2fe99e8SKumar Sanghvi if (peer2peer) { 1710d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ord) & 1711d2fe99e8SKumar Sanghvi MPA_V2_RDMA_WRITE_RTR) 1712d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1713d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_RDMA_WRITE; 1714d2fe99e8SKumar Sanghvi else if (ntohs(mpa_v2_params->ord) & 1715d2fe99e8SKumar Sanghvi MPA_V2_RDMA_READ_RTR) 1716d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1717d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_READ_REQ; 1718d2fe99e8SKumar Sanghvi } 1719d2fe99e8SKumar Sanghvi } 1720d2fe99e8SKumar Sanghvi } else if (mpa->revision == 1) 1721d2fe99e8SKumar Sanghvi if (peer2peer) 1722d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = p2p_type; 1723d2fe99e8SKumar Sanghvi 1724cfdda9d7SSteve Wise PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, " 1725cfdda9d7SSteve Wise "xmit_marker_enabled=%d, version=%d p2p_type=%d\n", __func__, 1726cfdda9d7SSteve Wise ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled, 1727cfdda9d7SSteve Wise ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version, 1728cfdda9d7SSteve Wise ep->mpa_attr.p2p_type); 1729cfdda9d7SSteve Wise 1730b33bd0cbSSteve Wise /* 1731b33bd0cbSSteve Wise * If the endpoint timer already expired, then we ignore 1732b33bd0cbSSteve Wise * the start request. process_timeout() will abort 1733b33bd0cbSSteve Wise * the connection. 1734b33bd0cbSSteve Wise */ 1735b33bd0cbSSteve Wise if (!stop_ep_timer(ep)) { 1736c529fb50SSteve Wise __state_set(&ep->com, MPA_REQ_RCVD); 1737cfdda9d7SSteve Wise 1738cfdda9d7SSteve Wise /* drive upcall */ 173910be6b48SHariprasad Shenai mutex_lock_nested(&ep->parent_ep->com.mutex, 174010be6b48SHariprasad Shenai SINGLE_DEPTH_NESTING); 1741be13b2dfSSteve Wise if (ep->parent_ep->com.state != DEAD) { 1742be13b2dfSSteve Wise if (connect_request_upcall(ep)) 1743fd6aabe4SHariprasad S goto err_unlock_parent; 1744be13b2dfSSteve Wise } else { 1745fd6aabe4SHariprasad S goto err_unlock_parent; 1746be13b2dfSSteve Wise } 1747be13b2dfSSteve Wise mutex_unlock(&ep->parent_ep->com.mutex); 1748b33bd0cbSSteve Wise } 1749fd6aabe4SHariprasad S return 0; 1750fd6aabe4SHariprasad S 1751fd6aabe4SHariprasad S err_unlock_parent: 1752fd6aabe4SHariprasad S mutex_unlock(&ep->parent_ep->com.mutex); 1753fd6aabe4SHariprasad S goto err_out; 1754fd6aabe4SHariprasad S err_stop_timer: 1755fd6aabe4SHariprasad S (void)stop_ep_timer(ep); 1756fd6aabe4SHariprasad S err_out: 1757fd6aabe4SHariprasad S return 2; 1758cfdda9d7SSteve Wise } 1759cfdda9d7SSteve Wise 1760cfdda9d7SSteve Wise static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb) 1761cfdda9d7SSteve Wise { 1762cfdda9d7SSteve Wise struct c4iw_ep *ep; 1763cfdda9d7SSteve Wise struct cpl_rx_data *hdr = cplhdr(skb); 1764cfdda9d7SSteve Wise unsigned int dlen = ntohs(hdr->len); 1765cfdda9d7SSteve Wise unsigned int tid = GET_TID(hdr); 1766cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 1767793dad94SVipul Pandya __u8 status = hdr->status; 1768cc18b939SSteve Wise int disconnect = 0; 1769cfdda9d7SSteve Wise 1770cfdda9d7SSteve Wise ep = lookup_tid(t, tid); 1771977116c6SSteve Wise if (!ep) 1772977116c6SSteve Wise return 0; 1773cfdda9d7SSteve Wise PDBG("%s ep %p tid %u dlen %u\n", __func__, ep, ep->hwtid, dlen); 1774cfdda9d7SSteve Wise skb_pull(skb, sizeof(*hdr)); 1775cfdda9d7SSteve Wise skb_trim(skb, dlen); 1776c529fb50SSteve Wise mutex_lock(&ep->com.mutex); 1777cfdda9d7SSteve Wise 1778cfdda9d7SSteve Wise /* update RX credits */ 1779cfdda9d7SSteve Wise update_rx_credits(ep, dlen); 1780cfdda9d7SSteve Wise 1781c529fb50SSteve Wise switch (ep->com.state) { 1782cfdda9d7SSteve Wise case MPA_REQ_SENT: 178355abf8dfSVipul Pandya ep->rcv_seq += dlen; 1784cc18b939SSteve Wise disconnect = process_mpa_reply(ep, skb); 1785cfdda9d7SSteve Wise break; 1786cfdda9d7SSteve Wise case MPA_REQ_WAIT: 178755abf8dfSVipul Pandya ep->rcv_seq += dlen; 1788cfdda9d7SSteve Wise process_mpa_request(ep, skb); 1789cfdda9d7SSteve Wise break; 17901557967bSVipul Pandya case FPDU_MODE: { 17911557967bSVipul Pandya struct c4iw_qp_attributes attrs; 17921557967bSVipul Pandya BUG_ON(!ep->com.qp); 1793e8e5b927SVipul Pandya if (status) 1794793dad94SVipul Pandya pr_err("%s Unexpected streaming data." \ 179504236df2SVipul Pandya " qpid %u ep %p state %d tid %u status %d\n", 179604236df2SVipul Pandya __func__, ep->com.qp->wq.sq.qid, ep, 1797c529fb50SSteve Wise ep->com.state, ep->hwtid, status); 179897d7ec0cSSteve Wise attrs.next_state = C4IW_QP_STATE_TERMINATE; 179955abf8dfSVipul Pandya c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 1800cc18b939SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 1801cc18b939SSteve Wise disconnect = 1; 1802cfdda9d7SSteve Wise break; 1803cfdda9d7SSteve Wise } 18041557967bSVipul Pandya default: 18051557967bSVipul Pandya break; 18061557967bSVipul Pandya } 1807c529fb50SSteve Wise mutex_unlock(&ep->com.mutex); 1808cc18b939SSteve Wise if (disconnect) 1809cc18b939SSteve Wise c4iw_ep_disconnect(ep, 0, GFP_KERNEL); 1810cfdda9d7SSteve Wise return 0; 1811cfdda9d7SSteve Wise } 1812cfdda9d7SSteve Wise 1813cfdda9d7SSteve Wise static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 1814cfdda9d7SSteve Wise { 1815cfdda9d7SSteve Wise struct c4iw_ep *ep; 1816cfdda9d7SSteve Wise struct cpl_abort_rpl_rss *rpl = cplhdr(skb); 1817cfdda9d7SSteve Wise int release = 0; 1818cfdda9d7SSteve Wise unsigned int tid = GET_TID(rpl); 1819cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 1820cfdda9d7SSteve Wise 1821cfdda9d7SSteve Wise ep = lookup_tid(t, tid); 18224984037bSVipul Pandya if (!ep) { 18234984037bSVipul Pandya printk(KERN_WARNING MOD "Abort rpl to freed endpoint\n"); 18244984037bSVipul Pandya return 0; 18254984037bSVipul Pandya } 182692dd6c3dSWei Yongjun PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 18272f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 1828cfdda9d7SSteve Wise switch (ep->com.state) { 1829cfdda9d7SSteve Wise case ABORTING: 183091e9c071SVipul Pandya c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 1831cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 1832cfdda9d7SSteve Wise release = 1; 1833cfdda9d7SSteve Wise break; 1834cfdda9d7SSteve Wise default: 1835cfdda9d7SSteve Wise printk(KERN_ERR "%s ep %p state %d\n", 1836cfdda9d7SSteve Wise __func__, ep, ep->com.state); 1837cfdda9d7SSteve Wise break; 1838cfdda9d7SSteve Wise } 18392f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 1840cfdda9d7SSteve Wise 1841cfdda9d7SSteve Wise if (release) 1842cfdda9d7SSteve Wise release_ep_resources(ep); 1843cfdda9d7SSteve Wise return 0; 1844cfdda9d7SSteve Wise } 1845cfdda9d7SSteve Wise 18465be78ee9SVipul Pandya static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid) 18475be78ee9SVipul Pandya { 18485be78ee9SVipul Pandya struct sk_buff *skb; 18495be78ee9SVipul Pandya struct fw_ofld_connection_wr *req; 18505be78ee9SVipul Pandya unsigned int mtu_idx; 18515be78ee9SVipul Pandya int wscale; 1852830662f6SVipul Pandya struct sockaddr_in *sin; 1853b408ff28SHariprasad Shenai int win; 18545be78ee9SVipul Pandya 18555be78ee9SVipul Pandya skb = get_skb(NULL, sizeof(*req), GFP_KERNEL); 18565be78ee9SVipul Pandya req = (struct fw_ofld_connection_wr *)__skb_put(skb, sizeof(*req)); 18575be78ee9SVipul Pandya memset(req, 0, sizeof(*req)); 18586c53e938SHariprasad Shenai req->op_compl = htonl(WR_OP_V(FW_OFLD_CONNECTION_WR)); 1859e2ac9628SHariprasad Shenai req->len16_pkd = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*req), 16))); 186041b4f86cSKumar Sanghvi req->le.filter = cpu_to_be32(cxgb4_select_ntuple( 186141b4f86cSKumar Sanghvi ep->com.dev->rdev.lldi.ports[0], 18625be78ee9SVipul Pandya ep->l2t)); 1863170003c8SSteve Wise sin = (struct sockaddr_in *)&ep->com.local_addr; 1864830662f6SVipul Pandya req->le.lport = sin->sin_port; 1865830662f6SVipul Pandya req->le.u.ipv4.lip = sin->sin_addr.s_addr; 1866170003c8SSteve Wise sin = (struct sockaddr_in *)&ep->com.remote_addr; 1867830662f6SVipul Pandya req->le.pport = sin->sin_port; 1868830662f6SVipul Pandya req->le.u.ipv4.pip = sin->sin_addr.s_addr; 18695be78ee9SVipul Pandya req->tcb.t_state_to_astid = 187077a80e23SHariprasad Shenai htonl(FW_OFLD_CONNECTION_WR_T_STATE_V(TCP_SYN_SENT) | 187177a80e23SHariprasad Shenai FW_OFLD_CONNECTION_WR_ASTID_V(atid)); 18725be78ee9SVipul Pandya req->tcb.cplrxdataack_cplpassacceptrpl = 187377a80e23SHariprasad Shenai htons(FW_OFLD_CONNECTION_WR_CPLRXDATAACK_F); 1874ef5d6355SVipul Pandya req->tcb.tx_max = (__force __be32) jiffies; 1875793dad94SVipul Pandya req->tcb.rcv_adv = htons(1); 187692e7ae71SHariprasad Shenai best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, 187704524a47SHariprasad S enable_tcp_timestamps, 187804524a47SHariprasad S (AF_INET == ep->com.remote_addr.ss_family) ? 0 : 1); 18795be78ee9SVipul Pandya wscale = compute_wscale(rcv_win); 1880b408ff28SHariprasad Shenai 1881b408ff28SHariprasad Shenai /* 1882b408ff28SHariprasad Shenai * Specify the largest window that will fit in opt0. The 1883b408ff28SHariprasad Shenai * remainder will be specified in the rx_data_ack. 1884b408ff28SHariprasad Shenai */ 1885b408ff28SHariprasad Shenai win = ep->rcv_win >> 10; 1886d7990b0cSAnish Bhatt if (win > RCV_BUFSIZ_M) 1887d7990b0cSAnish Bhatt win = RCV_BUFSIZ_M; 1888b408ff28SHariprasad Shenai 18896c53e938SHariprasad Shenai req->tcb.opt0 = (__force __be64) (TCAM_BYPASS_F | 18906c53e938SHariprasad Shenai (nocong ? NO_CONG_F : 0) | 1891d7990b0cSAnish Bhatt KEEP_ALIVE_F | 18926c53e938SHariprasad Shenai DELACK_F | 1893d7990b0cSAnish Bhatt WND_SCALE_V(wscale) | 1894d7990b0cSAnish Bhatt MSS_IDX_V(mtu_idx) | 1895d7990b0cSAnish Bhatt L2T_IDX_V(ep->l2t->idx) | 1896d7990b0cSAnish Bhatt TX_CHAN_V(ep->tx_chan) | 1897d7990b0cSAnish Bhatt SMAC_SEL_V(ep->smac_idx) | 1898ac8e4c69SHariprasad S DSCP_V(ep->tos >> 2) | 1899d7990b0cSAnish Bhatt ULP_MODE_V(ULP_MODE_TCPDDP) | 1900d7990b0cSAnish Bhatt RCV_BUFSIZ_V(win)); 19016c53e938SHariprasad Shenai req->tcb.opt2 = (__force __be32) (PACE_V(1) | 19026c53e938SHariprasad Shenai TX_QUEUE_V(ep->com.dev->rdev.lldi.tx_modq[ep->tx_chan]) | 1903d7990b0cSAnish Bhatt RX_CHANNEL_V(0) | 19046c53e938SHariprasad Shenai CCTRL_ECN_V(enable_ecn) | 1905d7990b0cSAnish Bhatt RSS_QUEUE_VALID_F | RSS_QUEUE_V(ep->rss_qid)); 19065be78ee9SVipul Pandya if (enable_tcp_timestamps) 19076c53e938SHariprasad Shenai req->tcb.opt2 |= (__force __be32)TSTAMPS_EN_F; 19085be78ee9SVipul Pandya if (enable_tcp_sack) 19096c53e938SHariprasad Shenai req->tcb.opt2 |= (__force __be32)SACK_EN_F; 19105be78ee9SVipul Pandya if (wscale && enable_tcp_window_scaling) 1911d7990b0cSAnish Bhatt req->tcb.opt2 |= (__force __be32)WND_SCALE_EN_F; 1912ef5d6355SVipul Pandya req->tcb.opt0 = cpu_to_be64((__force u64)req->tcb.opt0); 1913ef5d6355SVipul Pandya req->tcb.opt2 = cpu_to_be32((__force u32)req->tcb.opt2); 1914793dad94SVipul Pandya set_wr_txq(skb, CPL_PRIORITY_CONTROL, ep->ctrlq_idx); 1915793dad94SVipul Pandya set_bit(ACT_OFLD_CONN, &ep->com.history); 19165be78ee9SVipul Pandya c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 19175be78ee9SVipul Pandya } 19185be78ee9SVipul Pandya 1919cfdda9d7SSteve Wise /* 1920cfdda9d7SSteve Wise * Return whether a failed active open has allocated a TID 1921cfdda9d7SSteve Wise */ 1922cfdda9d7SSteve Wise static inline int act_open_has_tid(int status) 1923cfdda9d7SSteve Wise { 1924cfdda9d7SSteve Wise return status != CPL_ERR_TCAM_FULL && status != CPL_ERR_CONN_EXIST && 1925cfdda9d7SSteve Wise status != CPL_ERR_ARP_MISS; 1926cfdda9d7SSteve Wise } 1927cfdda9d7SSteve Wise 19287a2cea2aSSteve Wise /* Returns whether a CPL status conveys negative advice. 19297a2cea2aSSteve Wise */ 19307a2cea2aSSteve Wise static int is_neg_adv(unsigned int status) 19317a2cea2aSSteve Wise { 19327a2cea2aSSteve Wise return status == CPL_ERR_RTX_NEG_ADVICE || 19337a2cea2aSSteve Wise status == CPL_ERR_PERSIST_NEG_ADVICE || 19347a2cea2aSSteve Wise status == CPL_ERR_KEEPALV_NEG_ADVICE; 19357a2cea2aSSteve Wise } 19367a2cea2aSSteve Wise 1937dd92b124SHariprasad Shenai static char *neg_adv_str(unsigned int status) 1938dd92b124SHariprasad Shenai { 1939dd92b124SHariprasad Shenai switch (status) { 1940dd92b124SHariprasad Shenai case CPL_ERR_RTX_NEG_ADVICE: 1941dd92b124SHariprasad Shenai return "Retransmit timeout"; 1942dd92b124SHariprasad Shenai case CPL_ERR_PERSIST_NEG_ADVICE: 1943dd92b124SHariprasad Shenai return "Persist timeout"; 1944dd92b124SHariprasad Shenai case CPL_ERR_KEEPALV_NEG_ADVICE: 1945dd92b124SHariprasad Shenai return "Keepalive timeout"; 1946dd92b124SHariprasad Shenai default: 1947dd92b124SHariprasad Shenai return "Unknown"; 1948dd92b124SHariprasad Shenai } 1949dd92b124SHariprasad Shenai } 1950dd92b124SHariprasad Shenai 1951b408ff28SHariprasad Shenai static void set_tcp_window(struct c4iw_ep *ep, struct port_info *pi) 1952b408ff28SHariprasad Shenai { 1953b408ff28SHariprasad Shenai ep->snd_win = snd_win; 1954b408ff28SHariprasad Shenai ep->rcv_win = rcv_win; 1955b408ff28SHariprasad Shenai PDBG("%s snd_win %d rcv_win %d\n", __func__, ep->snd_win, ep->rcv_win); 1956b408ff28SHariprasad Shenai } 1957b408ff28SHariprasad Shenai 1958793dad94SVipul Pandya #define ACT_OPEN_RETRY_COUNT 2 1959793dad94SVipul Pandya 1960830662f6SVipul Pandya static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, 1961830662f6SVipul Pandya struct dst_entry *dst, struct c4iw_dev *cdev, 1962ac8e4c69SHariprasad S bool clear_mpa_v1, enum chip_type adapter_type, u8 tos) 1963830662f6SVipul Pandya { 1964830662f6SVipul Pandya struct neighbour *n; 1965830662f6SVipul Pandya int err, step; 1966830662f6SVipul Pandya struct net_device *pdev; 1967830662f6SVipul Pandya 1968830662f6SVipul Pandya n = dst_neigh_lookup(dst, peer_ip); 1969830662f6SVipul Pandya if (!n) 1970830662f6SVipul Pandya return -ENODEV; 1971830662f6SVipul Pandya 1972830662f6SVipul Pandya rcu_read_lock(); 1973830662f6SVipul Pandya err = -ENOMEM; 1974830662f6SVipul Pandya if (n->dev->flags & IFF_LOOPBACK) { 1975830662f6SVipul Pandya if (iptype == 4) 1976830662f6SVipul Pandya pdev = ip_dev_find(&init_net, *(__be32 *)peer_ip); 1977830662f6SVipul Pandya else if (IS_ENABLED(CONFIG_IPV6)) 1978830662f6SVipul Pandya for_each_netdev(&init_net, pdev) { 1979830662f6SVipul Pandya if (ipv6_chk_addr(&init_net, 1980830662f6SVipul Pandya (struct in6_addr *)peer_ip, 1981830662f6SVipul Pandya pdev, 1)) 1982830662f6SVipul Pandya break; 1983830662f6SVipul Pandya } 1984830662f6SVipul Pandya else 1985830662f6SVipul Pandya pdev = NULL; 1986830662f6SVipul Pandya 1987830662f6SVipul Pandya if (!pdev) { 1988830662f6SVipul Pandya err = -ENODEV; 1989830662f6SVipul Pandya goto out; 1990830662f6SVipul Pandya } 1991830662f6SVipul Pandya ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, 1992ac8e4c69SHariprasad S n, pdev, rt_tos2priority(tos)); 1993830662f6SVipul Pandya if (!ep->l2t) 1994830662f6SVipul Pandya goto out; 1995830662f6SVipul Pandya ep->mtu = pdev->mtu; 1996830662f6SVipul Pandya ep->tx_chan = cxgb4_port_chan(pdev); 1997963cab50SHariprasad S ep->smac_idx = cxgb4_tp_smt_idx(adapter_type, 1998963cab50SHariprasad S cxgb4_port_viid(pdev)); 1999830662f6SVipul Pandya step = cdev->rdev.lldi.ntxq / 2000830662f6SVipul Pandya cdev->rdev.lldi.nchan; 2001830662f6SVipul Pandya ep->txq_idx = cxgb4_port_idx(pdev) * step; 2002830662f6SVipul Pandya step = cdev->rdev.lldi.nrxq / 2003830662f6SVipul Pandya cdev->rdev.lldi.nchan; 2004830662f6SVipul Pandya ep->ctrlq_idx = cxgb4_port_idx(pdev); 2005830662f6SVipul Pandya ep->rss_qid = cdev->rdev.lldi.rxq_ids[ 2006830662f6SVipul Pandya cxgb4_port_idx(pdev) * step]; 2007b408ff28SHariprasad Shenai set_tcp_window(ep, (struct port_info *)netdev_priv(pdev)); 2008830662f6SVipul Pandya dev_put(pdev); 2009830662f6SVipul Pandya } else { 2010830662f6SVipul Pandya pdev = get_real_dev(n->dev); 2011830662f6SVipul Pandya ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, 2012830662f6SVipul Pandya n, pdev, 0); 2013830662f6SVipul Pandya if (!ep->l2t) 2014830662f6SVipul Pandya goto out; 2015830662f6SVipul Pandya ep->mtu = dst_mtu(dst); 201611b8e22dSSteve Wise ep->tx_chan = cxgb4_port_chan(pdev); 2017963cab50SHariprasad S ep->smac_idx = cxgb4_tp_smt_idx(adapter_type, 2018963cab50SHariprasad S cxgb4_port_viid(pdev)); 2019830662f6SVipul Pandya step = cdev->rdev.lldi.ntxq / 2020830662f6SVipul Pandya cdev->rdev.lldi.nchan; 202111b8e22dSSteve Wise ep->txq_idx = cxgb4_port_idx(pdev) * step; 202211b8e22dSSteve Wise ep->ctrlq_idx = cxgb4_port_idx(pdev); 2023830662f6SVipul Pandya step = cdev->rdev.lldi.nrxq / 2024830662f6SVipul Pandya cdev->rdev.lldi.nchan; 2025830662f6SVipul Pandya ep->rss_qid = cdev->rdev.lldi.rxq_ids[ 202611b8e22dSSteve Wise cxgb4_port_idx(pdev) * step]; 2027b408ff28SHariprasad Shenai set_tcp_window(ep, (struct port_info *)netdev_priv(pdev)); 2028830662f6SVipul Pandya 2029830662f6SVipul Pandya if (clear_mpa_v1) { 2030830662f6SVipul Pandya ep->retry_with_mpa_v1 = 0; 2031830662f6SVipul Pandya ep->tried_with_mpa_v1 = 0; 2032830662f6SVipul Pandya } 2033830662f6SVipul Pandya } 2034830662f6SVipul Pandya err = 0; 2035830662f6SVipul Pandya out: 2036830662f6SVipul Pandya rcu_read_unlock(); 2037830662f6SVipul Pandya 2038830662f6SVipul Pandya neigh_release(n); 2039830662f6SVipul Pandya 2040830662f6SVipul Pandya return err; 2041830662f6SVipul Pandya } 2042830662f6SVipul Pandya 2043793dad94SVipul Pandya static int c4iw_reconnect(struct c4iw_ep *ep) 2044793dad94SVipul Pandya { 2045793dad94SVipul Pandya int err = 0; 204624d44a39SSteve Wise struct sockaddr_in *laddr = (struct sockaddr_in *) 2047170003c8SSteve Wise &ep->com.cm_id->m_local_addr; 204824d44a39SSteve Wise struct sockaddr_in *raddr = (struct sockaddr_in *) 2049170003c8SSteve Wise &ep->com.cm_id->m_remote_addr; 2050830662f6SVipul Pandya struct sockaddr_in6 *laddr6 = (struct sockaddr_in6 *) 2051170003c8SSteve Wise &ep->com.cm_id->m_local_addr; 2052830662f6SVipul Pandya struct sockaddr_in6 *raddr6 = (struct sockaddr_in6 *) 2053170003c8SSteve Wise &ep->com.cm_id->m_remote_addr; 2054830662f6SVipul Pandya int iptype; 2055830662f6SVipul Pandya __u8 *ra; 2056793dad94SVipul Pandya 2057793dad94SVipul Pandya PDBG("%s qp %p cm_id %p\n", __func__, ep->com.qp, ep->com.cm_id); 2058793dad94SVipul Pandya init_timer(&ep->timer); 2059793dad94SVipul Pandya 2060793dad94SVipul Pandya /* 2061793dad94SVipul Pandya * Allocate an active TID to initiate a TCP connection. 2062793dad94SVipul Pandya */ 2063793dad94SVipul Pandya ep->atid = cxgb4_alloc_atid(ep->com.dev->rdev.lldi.tids, ep); 2064793dad94SVipul Pandya if (ep->atid == -1) { 2065793dad94SVipul Pandya pr_err("%s - cannot alloc atid.\n", __func__); 2066793dad94SVipul Pandya err = -ENOMEM; 2067793dad94SVipul Pandya goto fail2; 2068793dad94SVipul Pandya } 2069793dad94SVipul Pandya insert_handle(ep->com.dev, &ep->com.dev->atid_idr, ep, ep->atid); 2070793dad94SVipul Pandya 2071793dad94SVipul Pandya /* find a route */ 2072170003c8SSteve Wise if (ep->com.cm_id->m_local_addr.ss_family == AF_INET) { 2073830662f6SVipul Pandya ep->dst = find_route(ep->com.dev, laddr->sin_addr.s_addr, 2074830662f6SVipul Pandya raddr->sin_addr.s_addr, laddr->sin_port, 2075ac8e4c69SHariprasad S raddr->sin_port, ep->com.cm_id->tos); 2076830662f6SVipul Pandya iptype = 4; 2077830662f6SVipul Pandya ra = (__u8 *)&raddr->sin_addr; 2078830662f6SVipul Pandya } else { 2079830662f6SVipul Pandya ep->dst = find_route6(ep->com.dev, laddr6->sin6_addr.s6_addr, 2080830662f6SVipul Pandya raddr6->sin6_addr.s6_addr, 2081830662f6SVipul Pandya laddr6->sin6_port, raddr6->sin6_port, 0, 2082830662f6SVipul Pandya raddr6->sin6_scope_id); 2083830662f6SVipul Pandya iptype = 6; 2084830662f6SVipul Pandya ra = (__u8 *)&raddr6->sin6_addr; 2085830662f6SVipul Pandya } 2086830662f6SVipul Pandya if (!ep->dst) { 2087793dad94SVipul Pandya pr_err("%s - cannot find route.\n", __func__); 2088793dad94SVipul Pandya err = -EHOSTUNREACH; 2089793dad94SVipul Pandya goto fail3; 2090793dad94SVipul Pandya } 2091963cab50SHariprasad S err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, false, 2092ac8e4c69SHariprasad S ep->com.dev->rdev.lldi.adapter_type, 2093ac8e4c69SHariprasad S ep->com.cm_id->tos); 2094830662f6SVipul Pandya if (err) { 2095793dad94SVipul Pandya pr_err("%s - cannot alloc l2e.\n", __func__); 2096793dad94SVipul Pandya goto fail4; 2097793dad94SVipul Pandya } 2098793dad94SVipul Pandya 2099793dad94SVipul Pandya PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n", 2100793dad94SVipul Pandya __func__, ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid, 2101793dad94SVipul Pandya ep->l2t->idx); 2102793dad94SVipul Pandya 2103793dad94SVipul Pandya state_set(&ep->com, CONNECTING); 2104ac8e4c69SHariprasad S ep->tos = ep->com.cm_id->tos; 2105793dad94SVipul Pandya 2106793dad94SVipul Pandya /* send connect request to rnic */ 2107793dad94SVipul Pandya err = send_connect(ep); 2108793dad94SVipul Pandya if (!err) 2109793dad94SVipul Pandya goto out; 2110793dad94SVipul Pandya 2111793dad94SVipul Pandya cxgb4_l2t_release(ep->l2t); 2112793dad94SVipul Pandya fail4: 2113793dad94SVipul Pandya dst_release(ep->dst); 2114793dad94SVipul Pandya fail3: 2115793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid); 2116793dad94SVipul Pandya cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid); 2117793dad94SVipul Pandya fail2: 2118793dad94SVipul Pandya /* 2119793dad94SVipul Pandya * remember to send notification to upper layer. 2120793dad94SVipul Pandya * We are in here so the upper layer is not aware that this is 2121793dad94SVipul Pandya * re-connect attempt and so, upper layer is still waiting for 2122793dad94SVipul Pandya * response of 1st connect request. 2123793dad94SVipul Pandya */ 2124793dad94SVipul Pandya connect_reply_upcall(ep, -ECONNRESET); 2125793dad94SVipul Pandya c4iw_put_ep(&ep->com); 2126793dad94SVipul Pandya out: 2127793dad94SVipul Pandya return err; 2128793dad94SVipul Pandya } 2129793dad94SVipul Pandya 2130cfdda9d7SSteve Wise static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2131cfdda9d7SSteve Wise { 2132cfdda9d7SSteve Wise struct c4iw_ep *ep; 2133cfdda9d7SSteve Wise struct cpl_act_open_rpl *rpl = cplhdr(skb); 21346c53e938SHariprasad Shenai unsigned int atid = TID_TID_G(AOPEN_ATID_G( 2135cfdda9d7SSteve Wise ntohl(rpl->atid_status))); 2136cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 21376c53e938SHariprasad Shenai int status = AOPEN_STATUS_G(ntohl(rpl->atid_status)); 2138830662f6SVipul Pandya struct sockaddr_in *la; 2139830662f6SVipul Pandya struct sockaddr_in *ra; 2140830662f6SVipul Pandya struct sockaddr_in6 *la6; 2141830662f6SVipul Pandya struct sockaddr_in6 *ra6; 2142cfdda9d7SSteve Wise 2143cfdda9d7SSteve Wise ep = lookup_atid(t, atid); 2144170003c8SSteve Wise la = (struct sockaddr_in *)&ep->com.local_addr; 2145170003c8SSteve Wise ra = (struct sockaddr_in *)&ep->com.remote_addr; 2146170003c8SSteve Wise la6 = (struct sockaddr_in6 *)&ep->com.local_addr; 2147170003c8SSteve Wise ra6 = (struct sockaddr_in6 *)&ep->com.remote_addr; 2148cfdda9d7SSteve Wise 2149cfdda9d7SSteve Wise PDBG("%s ep %p atid %u status %u errno %d\n", __func__, ep, atid, 2150cfdda9d7SSteve Wise status, status2errno(status)); 2151cfdda9d7SSteve Wise 21527a2cea2aSSteve Wise if (is_neg_adv(status)) { 2153179d03bbSHariprasad S PDBG("%s Connection problems for atid %u status %u (%s)\n", 2154179d03bbSHariprasad S __func__, atid, status, neg_adv_str(status)); 2155179d03bbSHariprasad S ep->stats.connect_neg_adv++; 2156179d03bbSHariprasad S mutex_lock(&dev->rdev.stats.lock); 2157179d03bbSHariprasad S dev->rdev.stats.neg_adv++; 2158179d03bbSHariprasad S mutex_unlock(&dev->rdev.stats.lock); 2159cfdda9d7SSteve Wise return 0; 2160cfdda9d7SSteve Wise } 2161cfdda9d7SSteve Wise 2162793dad94SVipul Pandya set_bit(ACT_OPEN_RPL, &ep->com.history); 2163793dad94SVipul Pandya 2164d716a2a0SVipul Pandya /* 2165d716a2a0SVipul Pandya * Log interesting failures. 2166d716a2a0SVipul Pandya */ 2167d716a2a0SVipul Pandya switch (status) { 2168d716a2a0SVipul Pandya case CPL_ERR_CONN_RESET: 2169d716a2a0SVipul Pandya case CPL_ERR_CONN_TIMEDOUT: 2170d716a2a0SVipul Pandya break; 21715be78ee9SVipul Pandya case CPL_ERR_TCAM_FULL: 21725be78ee9SVipul Pandya mutex_lock(&dev->rdev.stats.lock); 2173830662f6SVipul Pandya dev->rdev.stats.tcam_full++; 21745be78ee9SVipul Pandya mutex_unlock(&dev->rdev.stats.lock); 2175830662f6SVipul Pandya if (ep->com.local_addr.ss_family == AF_INET && 2176830662f6SVipul Pandya dev->rdev.lldi.enable_fw_ofld_conn) { 21775be78ee9SVipul Pandya send_fw_act_open_req(ep, 21786c53e938SHariprasad Shenai TID_TID_G(AOPEN_ATID_G( 2179793dad94SVipul Pandya ntohl(rpl->atid_status)))); 21805be78ee9SVipul Pandya return 0; 2181793dad94SVipul Pandya } 2182793dad94SVipul Pandya break; 2183793dad94SVipul Pandya case CPL_ERR_CONN_EXIST: 2184793dad94SVipul Pandya if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) { 2185793dad94SVipul Pandya set_bit(ACT_RETRY_INUSE, &ep->com.history); 218684cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 218784cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 218884cc6ac6SHariprasad S (struct sockaddr_in6 *) 2189170003c8SSteve Wise &ep->com.local_addr; 219084cc6ac6SHariprasad S cxgb4_clip_release( 219184cc6ac6SHariprasad S ep->com.dev->rdev.lldi.ports[0], 219284cc6ac6SHariprasad S (const u32 *) 219384cc6ac6SHariprasad S &sin6->sin6_addr.s6_addr, 1); 219484cc6ac6SHariprasad S } 2195793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, 2196793dad94SVipul Pandya atid); 2197793dad94SVipul Pandya cxgb4_free_atid(t, atid); 2198793dad94SVipul Pandya dst_release(ep->dst); 2199793dad94SVipul Pandya cxgb4_l2t_release(ep->l2t); 2200793dad94SVipul Pandya c4iw_reconnect(ep); 2201793dad94SVipul Pandya return 0; 2202793dad94SVipul Pandya } 22035be78ee9SVipul Pandya break; 2204d716a2a0SVipul Pandya default: 2205830662f6SVipul Pandya if (ep->com.local_addr.ss_family == AF_INET) { 2206830662f6SVipul Pandya pr_info("Active open failure - atid %u status %u errno %d %pI4:%u->%pI4:%u\n", 2207d716a2a0SVipul Pandya atid, status, status2errno(status), 2208830662f6SVipul Pandya &la->sin_addr.s_addr, ntohs(la->sin_port), 2209830662f6SVipul Pandya &ra->sin_addr.s_addr, ntohs(ra->sin_port)); 2210830662f6SVipul Pandya } else { 2211830662f6SVipul Pandya pr_info("Active open failure - atid %u status %u errno %d %pI6:%u->%pI6:%u\n", 2212830662f6SVipul Pandya atid, status, status2errno(status), 2213830662f6SVipul Pandya la6->sin6_addr.s6_addr, ntohs(la6->sin6_port), 2214830662f6SVipul Pandya ra6->sin6_addr.s6_addr, ntohs(ra6->sin6_port)); 2215830662f6SVipul Pandya } 2216d716a2a0SVipul Pandya break; 2217d716a2a0SVipul Pandya } 2218d716a2a0SVipul Pandya 2219cfdda9d7SSteve Wise connect_reply_upcall(ep, status2errno(status)); 2220cfdda9d7SSteve Wise state_set(&ep->com, DEAD); 2221cfdda9d7SSteve Wise 222284cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 222384cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 2224170003c8SSteve Wise (struct sockaddr_in6 *)&ep->com.local_addr; 222584cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 222684cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 222784cc6ac6SHariprasad S } 2228cfdda9d7SSteve Wise if (status && act_open_has_tid(status)) 2229cfdda9d7SSteve Wise cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, GET_TID(rpl)); 2230cfdda9d7SSteve Wise 2231793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, atid); 2232cfdda9d7SSteve Wise cxgb4_free_atid(t, atid); 2233cfdda9d7SSteve Wise dst_release(ep->dst); 2234cfdda9d7SSteve Wise cxgb4_l2t_release(ep->l2t); 2235cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 2236cfdda9d7SSteve Wise 2237cfdda9d7SSteve Wise return 0; 2238cfdda9d7SSteve Wise } 2239cfdda9d7SSteve Wise 2240cfdda9d7SSteve Wise static int pass_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2241cfdda9d7SSteve Wise { 2242cfdda9d7SSteve Wise struct cpl_pass_open_rpl *rpl = cplhdr(skb); 2243cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 2244cfdda9d7SSteve Wise unsigned int stid = GET_TID(rpl); 2245cfdda9d7SSteve Wise struct c4iw_listen_ep *ep = lookup_stid(t, stid); 2246cfdda9d7SSteve Wise 2247cfdda9d7SSteve Wise if (!ep) { 22481cab775cSVipul Pandya PDBG("%s stid %d lookup failure!\n", __func__, stid); 22491cab775cSVipul Pandya goto out; 2250cfdda9d7SSteve Wise } 2251cfdda9d7SSteve Wise PDBG("%s ep %p status %d error %d\n", __func__, ep, 2252cfdda9d7SSteve Wise rpl->status, status2errno(rpl->status)); 2253d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, status2errno(rpl->status)); 2254cfdda9d7SSteve Wise 22551cab775cSVipul Pandya out: 2256cfdda9d7SSteve Wise return 0; 2257cfdda9d7SSteve Wise } 2258cfdda9d7SSteve Wise 2259cfdda9d7SSteve Wise static int close_listsrv_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2260cfdda9d7SSteve Wise { 2261cfdda9d7SSteve Wise struct cpl_close_listsvr_rpl *rpl = cplhdr(skb); 2262cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 2263cfdda9d7SSteve Wise unsigned int stid = GET_TID(rpl); 2264cfdda9d7SSteve Wise struct c4iw_listen_ep *ep = lookup_stid(t, stid); 2265cfdda9d7SSteve Wise 2266cfdda9d7SSteve Wise PDBG("%s ep %p\n", __func__, ep); 2267d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, status2errno(rpl->status)); 2268cfdda9d7SSteve Wise return 0; 2269cfdda9d7SSteve Wise } 2270cfdda9d7SSteve Wise 22719dec900cSHariprasad S static int accept_cr(struct c4iw_ep *ep, struct sk_buff *skb, 2272cfdda9d7SSteve Wise struct cpl_pass_accept_req *req) 2273cfdda9d7SSteve Wise { 2274cfdda9d7SSteve Wise struct cpl_pass_accept_rpl *rpl; 2275cfdda9d7SSteve Wise unsigned int mtu_idx; 2276cfdda9d7SSteve Wise u64 opt0; 2277cfdda9d7SSteve Wise u32 opt2; 2278cfdda9d7SSteve Wise int wscale; 227992e7ae71SHariprasad Shenai struct cpl_t5_pass_accept_rpl *rpl5 = NULL; 2280b408ff28SHariprasad Shenai int win; 2281963cab50SHariprasad S enum chip_type adapter_type = ep->com.dev->rdev.lldi.adapter_type; 2282cfdda9d7SSteve Wise 2283cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2284cfdda9d7SSteve Wise BUG_ON(skb_cloned(skb)); 228592e7ae71SHariprasad Shenai 2286cfdda9d7SSteve Wise skb_get(skb); 228792e7ae71SHariprasad Shenai rpl = cplhdr(skb); 2288963cab50SHariprasad S if (!is_t4(adapter_type)) { 228992e7ae71SHariprasad Shenai skb_trim(skb, roundup(sizeof(*rpl5), 16)); 229092e7ae71SHariprasad Shenai rpl5 = (void *)rpl; 229192e7ae71SHariprasad Shenai INIT_TP_WR(rpl5, ep->hwtid); 229292e7ae71SHariprasad Shenai } else { 229392e7ae71SHariprasad Shenai skb_trim(skb, sizeof(*rpl)); 229492e7ae71SHariprasad Shenai INIT_TP_WR(rpl, ep->hwtid); 229592e7ae71SHariprasad Shenai } 229692e7ae71SHariprasad Shenai OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_PASS_ACCEPT_RPL, 229792e7ae71SHariprasad Shenai ep->hwtid)); 229892e7ae71SHariprasad Shenai 229992e7ae71SHariprasad Shenai best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, 230004524a47SHariprasad S enable_tcp_timestamps && req->tcpopt.tstamp, 230104524a47SHariprasad S (AF_INET == ep->com.remote_addr.ss_family) ? 0 : 1); 2302cfdda9d7SSteve Wise wscale = compute_wscale(rcv_win); 2303b408ff28SHariprasad Shenai 2304b408ff28SHariprasad Shenai /* 2305b408ff28SHariprasad Shenai * Specify the largest window that will fit in opt0. The 2306b408ff28SHariprasad Shenai * remainder will be specified in the rx_data_ack. 2307b408ff28SHariprasad Shenai */ 2308b408ff28SHariprasad Shenai win = ep->rcv_win >> 10; 2309d7990b0cSAnish Bhatt if (win > RCV_BUFSIZ_M) 2310d7990b0cSAnish Bhatt win = RCV_BUFSIZ_M; 23116c53e938SHariprasad Shenai opt0 = (nocong ? NO_CONG_F : 0) | 2312d7990b0cSAnish Bhatt KEEP_ALIVE_F | 23136c53e938SHariprasad Shenai DELACK_F | 2314d7990b0cSAnish Bhatt WND_SCALE_V(wscale) | 2315d7990b0cSAnish Bhatt MSS_IDX_V(mtu_idx) | 2316d7990b0cSAnish Bhatt L2T_IDX_V(ep->l2t->idx) | 2317d7990b0cSAnish Bhatt TX_CHAN_V(ep->tx_chan) | 2318d7990b0cSAnish Bhatt SMAC_SEL_V(ep->smac_idx) | 23196c53e938SHariprasad Shenai DSCP_V(ep->tos >> 2) | 2320d7990b0cSAnish Bhatt ULP_MODE_V(ULP_MODE_TCPDDP) | 2321d7990b0cSAnish Bhatt RCV_BUFSIZ_V(win); 2322d7990b0cSAnish Bhatt opt2 = RX_CHANNEL_V(0) | 2323d7990b0cSAnish Bhatt RSS_QUEUE_VALID_F | RSS_QUEUE_V(ep->rss_qid); 2324cfdda9d7SSteve Wise 2325cfdda9d7SSteve Wise if (enable_tcp_timestamps && req->tcpopt.tstamp) 23266c53e938SHariprasad Shenai opt2 |= TSTAMPS_EN_F; 2327cfdda9d7SSteve Wise if (enable_tcp_sack && req->tcpopt.sack) 23286c53e938SHariprasad Shenai opt2 |= SACK_EN_F; 2329cfdda9d7SSteve Wise if (wscale && enable_tcp_window_scaling) 2330d7990b0cSAnish Bhatt opt2 |= WND_SCALE_EN_F; 23315be78ee9SVipul Pandya if (enable_ecn) { 23325be78ee9SVipul Pandya const struct tcphdr *tcph; 23335be78ee9SVipul Pandya u32 hlen = ntohl(req->hdr_len); 23345be78ee9SVipul Pandya 2335963cab50SHariprasad S if (CHELSIO_CHIP_VERSION(adapter_type) <= CHELSIO_T5) 2336cf7fe64aSHariprasad Shenai tcph = (const void *)(req + 1) + ETH_HDR_LEN_G(hlen) + 2337cf7fe64aSHariprasad Shenai IP_HDR_LEN_G(hlen); 2338963cab50SHariprasad S else 2339963cab50SHariprasad S tcph = (const void *)(req + 1) + 2340963cab50SHariprasad S T6_ETH_HDR_LEN_G(hlen) + T6_IP_HDR_LEN_G(hlen); 23415be78ee9SVipul Pandya if (tcph->ece && tcph->cwr) 23426c53e938SHariprasad Shenai opt2 |= CCTRL_ECN_V(1); 23435be78ee9SVipul Pandya } 2344963cab50SHariprasad S if (CHELSIO_CHIP_VERSION(adapter_type) > CHELSIO_T4) { 234592e7ae71SHariprasad Shenai u32 isn = (prandom_u32() & ~7UL) - 1; 2346d7990b0cSAnish Bhatt opt2 |= T5_OPT_2_VALID_F; 2347cf7fe64aSHariprasad Shenai opt2 |= CONG_CNTRL_V(CONG_ALG_TAHOE); 23480b741047SHariprasad S opt2 |= T5_ISS_F; 234992e7ae71SHariprasad Shenai rpl5 = (void *)rpl; 235092e7ae71SHariprasad Shenai memset(&rpl5->iss, 0, roundup(sizeof(*rpl5)-sizeof(*rpl), 16)); 235192e7ae71SHariprasad Shenai if (peer2peer) 235292e7ae71SHariprasad Shenai isn += 4; 235392e7ae71SHariprasad Shenai rpl5->iss = cpu_to_be32(isn); 235492e7ae71SHariprasad Shenai PDBG("%s iss %u\n", __func__, be32_to_cpu(rpl5->iss)); 235592e5011aSSteve Wise } 2356cfdda9d7SSteve Wise 2357cfdda9d7SSteve Wise rpl->opt0 = cpu_to_be64(opt0); 2358cfdda9d7SSteve Wise rpl->opt2 = cpu_to_be32(opt2); 2359d4f1a5c6SSteve Wise set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->ctrlq_idx); 23609dec900cSHariprasad S t4_set_arp_err_handler(skb, ep, pass_accept_rpl_arp_failure); 2361cfdda9d7SSteve Wise 23629dec900cSHariprasad S return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 2363cfdda9d7SSteve Wise } 2364cfdda9d7SSteve Wise 2365830662f6SVipul Pandya static void reject_cr(struct c4iw_dev *dev, u32 hwtid, struct sk_buff *skb) 2366cfdda9d7SSteve Wise { 2367830662f6SVipul Pandya PDBG("%s c4iw_dev %p tid %u\n", __func__, dev, hwtid); 2368cfdda9d7SSteve Wise BUG_ON(skb_cloned(skb)); 2369cfdda9d7SSteve Wise skb_trim(skb, sizeof(struct cpl_tid_release)); 2370cfdda9d7SSteve Wise release_tid(&dev->rdev, hwtid, skb); 2371cfdda9d7SSteve Wise return; 2372cfdda9d7SSteve Wise } 2373cfdda9d7SSteve Wise 2374963cab50SHariprasad S static void get_4tuple(struct cpl_pass_accept_req *req, enum chip_type type, 2375963cab50SHariprasad S int *iptype, __u8 *local_ip, __u8 *peer_ip, 2376cfdda9d7SSteve Wise __be16 *local_port, __be16 *peer_port) 2377cfdda9d7SSteve Wise { 2378963cab50SHariprasad S int eth_len = (CHELSIO_CHIP_VERSION(type) <= CHELSIO_T5) ? 2379963cab50SHariprasad S ETH_HDR_LEN_G(be32_to_cpu(req->hdr_len)) : 2380963cab50SHariprasad S T6_ETH_HDR_LEN_G(be32_to_cpu(req->hdr_len)); 2381963cab50SHariprasad S int ip_len = (CHELSIO_CHIP_VERSION(type) <= CHELSIO_T5) ? 2382963cab50SHariprasad S IP_HDR_LEN_G(be32_to_cpu(req->hdr_len)) : 2383963cab50SHariprasad S T6_IP_HDR_LEN_G(be32_to_cpu(req->hdr_len)); 2384cfdda9d7SSteve Wise struct iphdr *ip = (struct iphdr *)((u8 *)(req + 1) + eth_len); 2385830662f6SVipul Pandya struct ipv6hdr *ip6 = (struct ipv6hdr *)((u8 *)(req + 1) + eth_len); 2386cfdda9d7SSteve Wise struct tcphdr *tcp = (struct tcphdr *) 2387cfdda9d7SSteve Wise ((u8 *)(req + 1) + eth_len + ip_len); 2388cfdda9d7SSteve Wise 2389830662f6SVipul Pandya if (ip->version == 4) { 2390cfdda9d7SSteve Wise PDBG("%s saddr 0x%x daddr 0x%x sport %u dport %u\n", __func__, 2391cfdda9d7SSteve Wise ntohl(ip->saddr), ntohl(ip->daddr), ntohs(tcp->source), 2392cfdda9d7SSteve Wise ntohs(tcp->dest)); 2393830662f6SVipul Pandya *iptype = 4; 2394830662f6SVipul Pandya memcpy(peer_ip, &ip->saddr, 4); 2395830662f6SVipul Pandya memcpy(local_ip, &ip->daddr, 4); 2396830662f6SVipul Pandya } else { 2397830662f6SVipul Pandya PDBG("%s saddr %pI6 daddr %pI6 sport %u dport %u\n", __func__, 2398830662f6SVipul Pandya ip6->saddr.s6_addr, ip6->daddr.s6_addr, ntohs(tcp->source), 2399830662f6SVipul Pandya ntohs(tcp->dest)); 2400830662f6SVipul Pandya *iptype = 6; 2401830662f6SVipul Pandya memcpy(peer_ip, ip6->saddr.s6_addr, 16); 2402830662f6SVipul Pandya memcpy(local_ip, ip6->daddr.s6_addr, 16); 2403830662f6SVipul Pandya } 2404cfdda9d7SSteve Wise *peer_port = tcp->source; 2405cfdda9d7SSteve Wise *local_port = tcp->dest; 2406cfdda9d7SSteve Wise 2407cfdda9d7SSteve Wise return; 2408cfdda9d7SSteve Wise } 2409cfdda9d7SSteve Wise 2410cfdda9d7SSteve Wise static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) 2411cfdda9d7SSteve Wise { 2412793dad94SVipul Pandya struct c4iw_ep *child_ep = NULL, *parent_ep; 2413cfdda9d7SSteve Wise struct cpl_pass_accept_req *req = cplhdr(skb); 24146c53e938SHariprasad Shenai unsigned int stid = PASS_OPEN_TID_G(ntohl(req->tos_stid)); 2415cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 2416cfdda9d7SSteve Wise unsigned int hwtid = GET_TID(req); 2417cfdda9d7SSteve Wise struct dst_entry *dst; 2418830662f6SVipul Pandya __u8 local_ip[16], peer_ip[16]; 2419cfdda9d7SSteve Wise __be16 local_port, peer_port; 242084cc6ac6SHariprasad S struct sockaddr_in6 *sin6; 24213786cf18SDavid Miller int err; 24221cab775cSVipul Pandya u16 peer_mss = ntohs(req->tcpopt.mss); 2423830662f6SVipul Pandya int iptype; 242492e7ae71SHariprasad Shenai unsigned short hdrs; 2425ac8e4c69SHariprasad S u8 tos = PASS_OPEN_TOS_G(ntohl(req->tos_stid)); 2426cfdda9d7SSteve Wise 2427cfdda9d7SSteve Wise parent_ep = lookup_stid(t, stid); 24281cab775cSVipul Pandya if (!parent_ep) { 24291cab775cSVipul Pandya PDBG("%s connect request on invalid stid %d\n", __func__, stid); 24301cab775cSVipul Pandya goto reject; 24311cab775cSVipul Pandya } 24321cab775cSVipul Pandya 2433cfdda9d7SSteve Wise if (state_read(&parent_ep->com) != LISTEN) { 24346812faefSHariprasad S PDBG("%s - listening ep not in LISTEN\n", __func__); 2435cfdda9d7SSteve Wise goto reject; 2436cfdda9d7SSteve Wise } 2437cfdda9d7SSteve Wise 2438963cab50SHariprasad S get_4tuple(req, parent_ep->com.dev->rdev.lldi.adapter_type, &iptype, 2439963cab50SHariprasad S local_ip, peer_ip, &local_port, &peer_port); 2440830662f6SVipul Pandya 2441cfdda9d7SSteve Wise /* Find output route */ 2442830662f6SVipul Pandya if (iptype == 4) { 2443830662f6SVipul Pandya PDBG("%s parent ep %p hwtid %u laddr %pI4 raddr %pI4 lport %d rport %d peer_mss %d\n" 2444830662f6SVipul Pandya , __func__, parent_ep, hwtid, 2445830662f6SVipul Pandya local_ip, peer_ip, ntohs(local_port), 2446830662f6SVipul Pandya ntohs(peer_port), peer_mss); 2447830662f6SVipul Pandya dst = find_route(dev, *(__be32 *)local_ip, *(__be32 *)peer_ip, 2448830662f6SVipul Pandya local_port, peer_port, 2449ac8e4c69SHariprasad S tos); 2450830662f6SVipul Pandya } else { 2451830662f6SVipul Pandya PDBG("%s parent ep %p hwtid %u laddr %pI6 raddr %pI6 lport %d rport %d peer_mss %d\n" 2452830662f6SVipul Pandya , __func__, parent_ep, hwtid, 2453830662f6SVipul Pandya local_ip, peer_ip, ntohs(local_port), 2454830662f6SVipul Pandya ntohs(peer_port), peer_mss); 2455830662f6SVipul Pandya dst = find_route6(dev, local_ip, peer_ip, local_port, peer_port, 24566c53e938SHariprasad Shenai PASS_OPEN_TOS_G(ntohl(req->tos_stid)), 2457830662f6SVipul Pandya ((struct sockaddr_in6 *) 2458830662f6SVipul Pandya &parent_ep->com.local_addr)->sin6_scope_id); 2459830662f6SVipul Pandya } 2460830662f6SVipul Pandya if (!dst) { 2461cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - failed to find dst entry!\n", 2462cfdda9d7SSteve Wise __func__); 2463cfdda9d7SSteve Wise goto reject; 2464cfdda9d7SSteve Wise } 2465cfdda9d7SSteve Wise 2466cfdda9d7SSteve Wise child_ep = alloc_ep(sizeof(*child_ep), GFP_KERNEL); 2467cfdda9d7SSteve Wise if (!child_ep) { 2468cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - failed to allocate ep entry!\n", 2469cfdda9d7SSteve Wise __func__); 2470cfdda9d7SSteve Wise dst_release(dst); 2471cfdda9d7SSteve Wise goto reject; 2472cfdda9d7SSteve Wise } 24733786cf18SDavid Miller 2474963cab50SHariprasad S err = import_ep(child_ep, iptype, peer_ip, dst, dev, false, 2475ac8e4c69SHariprasad S parent_ep->com.dev->rdev.lldi.adapter_type, tos); 24763786cf18SDavid Miller if (err) { 24773786cf18SDavid Miller printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n", 24783786cf18SDavid Miller __func__); 24793786cf18SDavid Miller dst_release(dst); 24803786cf18SDavid Miller kfree(child_ep); 24813786cf18SDavid Miller goto reject; 24823786cf18SDavid Miller } 24833786cf18SDavid Miller 248492e7ae71SHariprasad Shenai hdrs = sizeof(struct iphdr) + sizeof(struct tcphdr) + 248592e7ae71SHariprasad Shenai ((enable_tcp_timestamps && req->tcpopt.tstamp) ? 12 : 0); 248692e7ae71SHariprasad Shenai if (peer_mss && child_ep->mtu > (peer_mss + hdrs)) 248792e7ae71SHariprasad Shenai child_ep->mtu = peer_mss + hdrs; 24881cab775cSVipul Pandya 2489cfdda9d7SSteve Wise state_set(&child_ep->com, CONNECTING); 2490cfdda9d7SSteve Wise child_ep->com.dev = dev; 2491cfdda9d7SSteve Wise child_ep->com.cm_id = NULL; 24925b6b8fe6SSteve Wise 2493830662f6SVipul Pandya if (iptype == 4) { 2494830662f6SVipul Pandya struct sockaddr_in *sin = (struct sockaddr_in *) 2495170003c8SSteve Wise &child_ep->com.local_addr; 24965b6b8fe6SSteve Wise 2497830662f6SVipul Pandya sin->sin_family = PF_INET; 2498830662f6SVipul Pandya sin->sin_port = local_port; 2499830662f6SVipul Pandya sin->sin_addr.s_addr = *(__be32 *)local_ip; 25005b6b8fe6SSteve Wise 25015b6b8fe6SSteve Wise sin = (struct sockaddr_in *)&child_ep->com.local_addr; 25025b6b8fe6SSteve Wise sin->sin_family = PF_INET; 25035b6b8fe6SSteve Wise sin->sin_port = ((struct sockaddr_in *) 25045b6b8fe6SSteve Wise &parent_ep->com.local_addr)->sin_port; 25055b6b8fe6SSteve Wise sin->sin_addr.s_addr = *(__be32 *)local_ip; 25065b6b8fe6SSteve Wise 2507170003c8SSteve Wise sin = (struct sockaddr_in *)&child_ep->com.remote_addr; 2508830662f6SVipul Pandya sin->sin_family = PF_INET; 2509830662f6SVipul Pandya sin->sin_port = peer_port; 2510830662f6SVipul Pandya sin->sin_addr.s_addr = *(__be32 *)peer_ip; 2511830662f6SVipul Pandya } else { 2512170003c8SSteve Wise sin6 = (struct sockaddr_in6 *)&child_ep->com.local_addr; 2513830662f6SVipul Pandya sin6->sin6_family = PF_INET6; 2514830662f6SVipul Pandya sin6->sin6_port = local_port; 2515830662f6SVipul Pandya memcpy(sin6->sin6_addr.s6_addr, local_ip, 16); 25165b6b8fe6SSteve Wise 25175b6b8fe6SSteve Wise sin6 = (struct sockaddr_in6 *)&child_ep->com.local_addr; 25185b6b8fe6SSteve Wise sin6->sin6_family = PF_INET6; 25195b6b8fe6SSteve Wise sin6->sin6_port = ((struct sockaddr_in6 *) 25205b6b8fe6SSteve Wise &parent_ep->com.local_addr)->sin6_port; 25215b6b8fe6SSteve Wise memcpy(sin6->sin6_addr.s6_addr, local_ip, 16); 25225b6b8fe6SSteve Wise 2523170003c8SSteve Wise sin6 = (struct sockaddr_in6 *)&child_ep->com.remote_addr; 2524830662f6SVipul Pandya sin6->sin6_family = PF_INET6; 2525830662f6SVipul Pandya sin6->sin6_port = peer_port; 2526830662f6SVipul Pandya memcpy(sin6->sin6_addr.s6_addr, peer_ip, 16); 2527830662f6SVipul Pandya } 25285b6b8fe6SSteve Wise 2529cfdda9d7SSteve Wise c4iw_get_ep(&parent_ep->com); 2530cfdda9d7SSteve Wise child_ep->parent_ep = parent_ep; 2531ac8e4c69SHariprasad S child_ep->tos = tos; 2532cfdda9d7SSteve Wise child_ep->dst = dst; 2533cfdda9d7SSteve Wise child_ep->hwtid = hwtid; 2534cfdda9d7SSteve Wise 2535cfdda9d7SSteve Wise PDBG("%s tx_chan %u smac_idx %u rss_qid %u\n", __func__, 25363786cf18SDavid Miller child_ep->tx_chan, child_ep->smac_idx, child_ep->rss_qid); 2537cfdda9d7SSteve Wise 2538cfdda9d7SSteve Wise init_timer(&child_ep->timer); 2539cfdda9d7SSteve Wise cxgb4_insert_tid(t, child_ep, hwtid); 2540b3de6cfeSVipul Pandya insert_handle(dev, &dev->hwtid_idr, child_ep, child_ep->hwtid); 25419dec900cSHariprasad S if (accept_cr(child_ep, skb, req)) { 25429dec900cSHariprasad S c4iw_put_ep(&parent_ep->com); 25439dec900cSHariprasad S release_ep_resources(child_ep); 25449dec900cSHariprasad S } else { 2545793dad94SVipul Pandya set_bit(PASS_ACCEPT_REQ, &child_ep->com.history); 25469dec900cSHariprasad S } 254784cc6ac6SHariprasad S if (iptype == 6) { 2548170003c8SSteve Wise sin6 = (struct sockaddr_in6 *)&child_ep->com.local_addr; 254984cc6ac6SHariprasad S cxgb4_clip_get(child_ep->com.dev->rdev.lldi.ports[0], 255084cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 255184cc6ac6SHariprasad S } 2552cfdda9d7SSteve Wise goto out; 2553cfdda9d7SSteve Wise reject: 2554830662f6SVipul Pandya reject_cr(dev, hwtid, skb); 2555cfdda9d7SSteve Wise out: 2556cfdda9d7SSteve Wise return 0; 2557cfdda9d7SSteve Wise } 2558cfdda9d7SSteve Wise 2559cfdda9d7SSteve Wise static int pass_establish(struct c4iw_dev *dev, struct sk_buff *skb) 2560cfdda9d7SSteve Wise { 2561cfdda9d7SSteve Wise struct c4iw_ep *ep; 2562cfdda9d7SSteve Wise struct cpl_pass_establish *req = cplhdr(skb); 2563cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 2564cfdda9d7SSteve Wise unsigned int tid = GET_TID(req); 2565fef4422dSHariprasad S int ret; 2566cfdda9d7SSteve Wise 2567cfdda9d7SSteve Wise ep = lookup_tid(t, tid); 2568cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2569cfdda9d7SSteve Wise ep->snd_seq = be32_to_cpu(req->snd_isn); 2570cfdda9d7SSteve Wise ep->rcv_seq = be32_to_cpu(req->rcv_isn); 2571cfdda9d7SSteve Wise 25721cab775cSVipul Pandya PDBG("%s ep %p hwtid %u tcp_opt 0x%02x\n", __func__, ep, tid, 25731cab775cSVipul Pandya ntohs(req->tcp_opt)); 25741cab775cSVipul Pandya 2575cfdda9d7SSteve Wise set_emss(ep, ntohs(req->tcp_opt)); 2576cfdda9d7SSteve Wise 2577cfdda9d7SSteve Wise dst_confirm(ep->dst); 2578fef4422dSHariprasad S mutex_lock(&ep->com.mutex); 2579fef4422dSHariprasad S ep->com.state = MPA_REQ_WAIT; 2580cfdda9d7SSteve Wise start_ep_timer(ep); 2581793dad94SVipul Pandya set_bit(PASS_ESTAB, &ep->com.history); 2582fef4422dSHariprasad S ret = send_flowc(ep, skb); 2583fef4422dSHariprasad S mutex_unlock(&ep->com.mutex); 2584fef4422dSHariprasad S if (ret) 2585fef4422dSHariprasad S c4iw_ep_disconnect(ep, 1, GFP_KERNEL); 2586cfdda9d7SSteve Wise 2587cfdda9d7SSteve Wise return 0; 2588cfdda9d7SSteve Wise } 2589cfdda9d7SSteve Wise 2590cfdda9d7SSteve Wise static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb) 2591cfdda9d7SSteve Wise { 2592cfdda9d7SSteve Wise struct cpl_peer_close *hdr = cplhdr(skb); 2593cfdda9d7SSteve Wise struct c4iw_ep *ep; 2594cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 2595cfdda9d7SSteve Wise int disconnect = 1; 2596cfdda9d7SSteve Wise int release = 0; 2597cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 2598cfdda9d7SSteve Wise unsigned int tid = GET_TID(hdr); 25998da7e7a5SSteve Wise int ret; 2600cfdda9d7SSteve Wise 2601cfdda9d7SSteve Wise ep = lookup_tid(t, tid); 2602cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2603cfdda9d7SSteve Wise dst_confirm(ep->dst); 2604cfdda9d7SSteve Wise 2605793dad94SVipul Pandya set_bit(PEER_CLOSE, &ep->com.history); 26062f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 2607cfdda9d7SSteve Wise switch (ep->com.state) { 2608cfdda9d7SSteve Wise case MPA_REQ_WAIT: 2609cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2610cfdda9d7SSteve Wise break; 2611cfdda9d7SSteve Wise case MPA_REQ_SENT: 2612cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2613cfdda9d7SSteve Wise connect_reply_upcall(ep, -ECONNRESET); 2614cfdda9d7SSteve Wise break; 2615cfdda9d7SSteve Wise case MPA_REQ_RCVD: 2616cfdda9d7SSteve Wise 2617cfdda9d7SSteve Wise /* 2618cfdda9d7SSteve Wise * We're gonna mark this puppy DEAD, but keep 2619cfdda9d7SSteve Wise * the reference on it until the ULP accepts or 2620cfdda9d7SSteve Wise * rejects the CR. Also wake up anyone waiting 2621cfdda9d7SSteve Wise * in rdma connection migration (see c4iw_accept_cr()). 2622cfdda9d7SSteve Wise */ 2623cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2624cfdda9d7SSteve Wise PDBG("waking up ep %p tid %u\n", ep, ep->hwtid); 2625d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 2626cfdda9d7SSteve Wise break; 2627cfdda9d7SSteve Wise case MPA_REP_SENT: 2628cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2629cfdda9d7SSteve Wise PDBG("waking up ep %p tid %u\n", ep, ep->hwtid); 2630d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 2631cfdda9d7SSteve Wise break; 2632cfdda9d7SSteve Wise case FPDU_MODE: 2633ca5a2202SSteve Wise start_ep_timer(ep); 2634cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 263530c95c2dSSteve Wise attrs.next_state = C4IW_QP_STATE_CLOSING; 26368da7e7a5SSteve Wise ret = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 263730c95c2dSSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 26388da7e7a5SSteve Wise if (ret != -ECONNRESET) { 2639cfdda9d7SSteve Wise peer_close_upcall(ep); 264030c95c2dSSteve Wise disconnect = 1; 26418da7e7a5SSteve Wise } 2642cfdda9d7SSteve Wise break; 2643cfdda9d7SSteve Wise case ABORTING: 2644cfdda9d7SSteve Wise disconnect = 0; 2645cfdda9d7SSteve Wise break; 2646cfdda9d7SSteve Wise case CLOSING: 2647cfdda9d7SSteve Wise __state_set(&ep->com, MORIBUND); 2648cfdda9d7SSteve Wise disconnect = 0; 2649cfdda9d7SSteve Wise break; 2650cfdda9d7SSteve Wise case MORIBUND: 2651b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 2652cfdda9d7SSteve Wise if (ep->com.cm_id && ep->com.qp) { 2653cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_IDLE; 2654cfdda9d7SSteve Wise c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 2655cfdda9d7SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 2656cfdda9d7SSteve Wise } 2657be13b2dfSSteve Wise close_complete_upcall(ep, 0); 2658cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 2659cfdda9d7SSteve Wise release = 1; 2660cfdda9d7SSteve Wise disconnect = 0; 2661cfdda9d7SSteve Wise break; 2662cfdda9d7SSteve Wise case DEAD: 2663cfdda9d7SSteve Wise disconnect = 0; 2664cfdda9d7SSteve Wise break; 2665cfdda9d7SSteve Wise default: 2666cfdda9d7SSteve Wise BUG_ON(1); 2667cfdda9d7SSteve Wise } 26682f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 2669cfdda9d7SSteve Wise if (disconnect) 2670cfdda9d7SSteve Wise c4iw_ep_disconnect(ep, 0, GFP_KERNEL); 2671cfdda9d7SSteve Wise if (release) 2672cfdda9d7SSteve Wise release_ep_resources(ep); 2673cfdda9d7SSteve Wise return 0; 2674cfdda9d7SSteve Wise } 2675cfdda9d7SSteve Wise 2676cfdda9d7SSteve Wise static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) 2677cfdda9d7SSteve Wise { 2678cfdda9d7SSteve Wise struct cpl_abort_req_rss *req = cplhdr(skb); 2679cfdda9d7SSteve Wise struct c4iw_ep *ep; 2680cfdda9d7SSteve Wise struct cpl_abort_rpl *rpl; 2681cfdda9d7SSteve Wise struct sk_buff *rpl_skb; 2682cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 2683cfdda9d7SSteve Wise int ret; 2684cfdda9d7SSteve Wise int release = 0; 2685cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 2686cfdda9d7SSteve Wise unsigned int tid = GET_TID(req); 2687cfdda9d7SSteve Wise 2688cfdda9d7SSteve Wise ep = lookup_tid(t, tid); 26897a2cea2aSSteve Wise if (is_neg_adv(req->status)) { 2690179d03bbSHariprasad S PDBG("%s Negative advice on abort- tid %u status %d (%s)\n", 2691179d03bbSHariprasad S __func__, ep->hwtid, req->status, 2692179d03bbSHariprasad S neg_adv_str(req->status)); 2693179d03bbSHariprasad S ep->stats.abort_neg_adv++; 2694179d03bbSHariprasad S mutex_lock(&dev->rdev.stats.lock); 2695179d03bbSHariprasad S dev->rdev.stats.neg_adv++; 2696179d03bbSHariprasad S mutex_unlock(&dev->rdev.stats.lock); 2697cfdda9d7SSteve Wise return 0; 2698cfdda9d7SSteve Wise } 2699cfdda9d7SSteve Wise PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid, 2700cfdda9d7SSteve Wise ep->com.state); 2701793dad94SVipul Pandya set_bit(PEER_ABORT, &ep->com.history); 27022f5b48c3SSteve Wise 27032f5b48c3SSteve Wise /* 27042f5b48c3SSteve Wise * Wake up any threads in rdma_init() or rdma_fini(). 2705d2fe99e8SKumar Sanghvi * However, this is not needed if com state is just 2706d2fe99e8SKumar Sanghvi * MPA_REQ_SENT 27072f5b48c3SSteve Wise */ 2708d2fe99e8SKumar Sanghvi if (ep->com.state != MPA_REQ_SENT) 2709d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 27102f5b48c3SSteve Wise 27112f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 2712cfdda9d7SSteve Wise switch (ep->com.state) { 2713cfdda9d7SSteve Wise case CONNECTING: 27149dec900cSHariprasad S c4iw_put_ep(&ep->parent_ep->com); 2715cfdda9d7SSteve Wise break; 2716cfdda9d7SSteve Wise case MPA_REQ_WAIT: 2717b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 2718cfdda9d7SSteve Wise break; 2719cfdda9d7SSteve Wise case MPA_REQ_SENT: 2720b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 2721fe7e0a4dSVipul Pandya if (mpa_rev == 1 || (mpa_rev == 2 && ep->tried_with_mpa_v1)) 2722cfdda9d7SSteve Wise connect_reply_upcall(ep, -ECONNRESET); 2723d2fe99e8SKumar Sanghvi else { 2724d2fe99e8SKumar Sanghvi /* 2725d2fe99e8SKumar Sanghvi * we just don't send notification upwards because we 2726d2fe99e8SKumar Sanghvi * want to retry with mpa_v1 without upper layers even 2727d2fe99e8SKumar Sanghvi * knowing it. 2728d2fe99e8SKumar Sanghvi * 2729d2fe99e8SKumar Sanghvi * do some housekeeping so as to re-initiate the 2730d2fe99e8SKumar Sanghvi * connection 2731d2fe99e8SKumar Sanghvi */ 2732d2fe99e8SKumar Sanghvi PDBG("%s: mpa_rev=%d. Retrying with mpav1\n", __func__, 2733d2fe99e8SKumar Sanghvi mpa_rev); 2734d2fe99e8SKumar Sanghvi ep->retry_with_mpa_v1 = 1; 2735d2fe99e8SKumar Sanghvi } 2736cfdda9d7SSteve Wise break; 2737cfdda9d7SSteve Wise case MPA_REP_SENT: 2738cfdda9d7SSteve Wise break; 2739cfdda9d7SSteve Wise case MPA_REQ_RCVD: 2740cfdda9d7SSteve Wise break; 2741cfdda9d7SSteve Wise case MORIBUND: 2742cfdda9d7SSteve Wise case CLOSING: 2743ca5a2202SSteve Wise stop_ep_timer(ep); 2744cfdda9d7SSteve Wise /*FALLTHROUGH*/ 2745cfdda9d7SSteve Wise case FPDU_MODE: 2746cfdda9d7SSteve Wise if (ep->com.cm_id && ep->com.qp) { 2747cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_ERROR; 2748cfdda9d7SSteve Wise ret = c4iw_modify_qp(ep->com.qp->rhp, 2749cfdda9d7SSteve Wise ep->com.qp, C4IW_QP_ATTR_NEXT_STATE, 2750cfdda9d7SSteve Wise &attrs, 1); 2751cfdda9d7SSteve Wise if (ret) 2752cfdda9d7SSteve Wise printk(KERN_ERR MOD 2753cfdda9d7SSteve Wise "%s - qp <- error failed!\n", 2754cfdda9d7SSteve Wise __func__); 2755cfdda9d7SSteve Wise } 2756cfdda9d7SSteve Wise peer_abort_upcall(ep); 2757cfdda9d7SSteve Wise break; 2758cfdda9d7SSteve Wise case ABORTING: 2759cfdda9d7SSteve Wise break; 2760cfdda9d7SSteve Wise case DEAD: 2761cfdda9d7SSteve Wise PDBG("%s PEER_ABORT IN DEAD STATE!!!!\n", __func__); 27622f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 2763cfdda9d7SSteve Wise return 0; 2764cfdda9d7SSteve Wise default: 2765cfdda9d7SSteve Wise BUG_ON(1); 2766cfdda9d7SSteve Wise break; 2767cfdda9d7SSteve Wise } 2768cfdda9d7SSteve Wise dst_confirm(ep->dst); 2769cfdda9d7SSteve Wise if (ep->com.state != ABORTING) { 2770cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 2771d2fe99e8SKumar Sanghvi /* we don't release if we want to retry with mpa_v1 */ 2772d2fe99e8SKumar Sanghvi if (!ep->retry_with_mpa_v1) 2773cfdda9d7SSteve Wise release = 1; 2774cfdda9d7SSteve Wise } 27752f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 2776cfdda9d7SSteve Wise 2777cfdda9d7SSteve Wise rpl_skb = get_skb(skb, sizeof(*rpl), GFP_KERNEL); 2778cfdda9d7SSteve Wise if (!rpl_skb) { 2779cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot allocate skb!\n", 2780cfdda9d7SSteve Wise __func__); 2781cfdda9d7SSteve Wise release = 1; 2782cfdda9d7SSteve Wise goto out; 2783cfdda9d7SSteve Wise } 2784cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 2785cfdda9d7SSteve Wise rpl = (struct cpl_abort_rpl *) skb_put(rpl_skb, sizeof(*rpl)); 2786cfdda9d7SSteve Wise INIT_TP_WR(rpl, ep->hwtid); 2787cfdda9d7SSteve Wise OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_RPL, ep->hwtid)); 2788cfdda9d7SSteve Wise rpl->cmd = CPL_ABORT_NO_RST; 2789cfdda9d7SSteve Wise c4iw_ofld_send(&ep->com.dev->rdev, rpl_skb); 2790cfdda9d7SSteve Wise out: 2791cfdda9d7SSteve Wise if (release) 2792cfdda9d7SSteve Wise release_ep_resources(ep); 2793fe7e0a4dSVipul Pandya else if (ep->retry_with_mpa_v1) { 279484cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 279584cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 279684cc6ac6SHariprasad S (struct sockaddr_in6 *) 2797170003c8SSteve Wise &ep->com.local_addr; 279884cc6ac6SHariprasad S cxgb4_clip_release( 279984cc6ac6SHariprasad S ep->com.dev->rdev.lldi.ports[0], 280084cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 280184cc6ac6SHariprasad S 1); 280284cc6ac6SHariprasad S } 2803fe7e0a4dSVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->hwtid_idr, ep->hwtid); 2804d2fe99e8SKumar Sanghvi cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid); 2805d2fe99e8SKumar Sanghvi dst_release(ep->dst); 2806d2fe99e8SKumar Sanghvi cxgb4_l2t_release(ep->l2t); 2807d2fe99e8SKumar Sanghvi c4iw_reconnect(ep); 2808d2fe99e8SKumar Sanghvi } 2809d2fe99e8SKumar Sanghvi 2810cfdda9d7SSteve Wise return 0; 2811cfdda9d7SSteve Wise } 2812cfdda9d7SSteve Wise 2813cfdda9d7SSteve Wise static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2814cfdda9d7SSteve Wise { 2815cfdda9d7SSteve Wise struct c4iw_ep *ep; 2816cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 2817cfdda9d7SSteve Wise struct cpl_close_con_rpl *rpl = cplhdr(skb); 2818cfdda9d7SSteve Wise int release = 0; 2819cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 2820cfdda9d7SSteve Wise unsigned int tid = GET_TID(rpl); 2821cfdda9d7SSteve Wise 2822cfdda9d7SSteve Wise ep = lookup_tid(t, tid); 2823cfdda9d7SSteve Wise 2824cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2825cfdda9d7SSteve Wise BUG_ON(!ep); 2826cfdda9d7SSteve Wise 2827cfdda9d7SSteve Wise /* The cm_id may be null if we failed to connect */ 28282f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 2829cfdda9d7SSteve Wise switch (ep->com.state) { 2830cfdda9d7SSteve Wise case CLOSING: 2831cfdda9d7SSteve Wise __state_set(&ep->com, MORIBUND); 2832cfdda9d7SSteve Wise break; 2833cfdda9d7SSteve Wise case MORIBUND: 2834b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 2835cfdda9d7SSteve Wise if ((ep->com.cm_id) && (ep->com.qp)) { 2836cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_IDLE; 2837cfdda9d7SSteve Wise c4iw_modify_qp(ep->com.qp->rhp, 2838cfdda9d7SSteve Wise ep->com.qp, 2839cfdda9d7SSteve Wise C4IW_QP_ATTR_NEXT_STATE, 2840cfdda9d7SSteve Wise &attrs, 1); 2841cfdda9d7SSteve Wise } 2842be13b2dfSSteve Wise close_complete_upcall(ep, 0); 2843cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 2844cfdda9d7SSteve Wise release = 1; 2845cfdda9d7SSteve Wise break; 2846cfdda9d7SSteve Wise case ABORTING: 2847cfdda9d7SSteve Wise case DEAD: 2848cfdda9d7SSteve Wise break; 2849cfdda9d7SSteve Wise default: 2850cfdda9d7SSteve Wise BUG_ON(1); 2851cfdda9d7SSteve Wise break; 2852cfdda9d7SSteve Wise } 28532f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 2854cfdda9d7SSteve Wise if (release) 2855cfdda9d7SSteve Wise release_ep_resources(ep); 2856cfdda9d7SSteve Wise return 0; 2857cfdda9d7SSteve Wise } 2858cfdda9d7SSteve Wise 2859cfdda9d7SSteve Wise static int terminate(struct c4iw_dev *dev, struct sk_buff *skb) 2860cfdda9d7SSteve Wise { 28610e42c1f4SSteve Wise struct cpl_rdma_terminate *rpl = cplhdr(skb); 2862cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 28630e42c1f4SSteve Wise unsigned int tid = GET_TID(rpl); 28640e42c1f4SSteve Wise struct c4iw_ep *ep; 28650e42c1f4SSteve Wise struct c4iw_qp_attributes attrs; 2866cfdda9d7SSteve Wise 2867cfdda9d7SSteve Wise ep = lookup_tid(t, tid); 28680e42c1f4SSteve Wise BUG_ON(!ep); 2869cfdda9d7SSteve Wise 287030c95c2dSSteve Wise if (ep && ep->com.qp) { 28710e42c1f4SSteve Wise printk(KERN_WARNING MOD "TERM received tid %u qpid %u\n", tid, 28720e42c1f4SSteve Wise ep->com.qp->wq.sq.qid); 28730e42c1f4SSteve Wise attrs.next_state = C4IW_QP_STATE_TERMINATE; 28740e42c1f4SSteve Wise c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 28750e42c1f4SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 28760e42c1f4SSteve Wise } else 287730c95c2dSSteve Wise printk(KERN_WARNING MOD "TERM received tid %u no ep/qp\n", tid); 2878cfdda9d7SSteve Wise 2879cfdda9d7SSteve Wise return 0; 2880cfdda9d7SSteve Wise } 2881cfdda9d7SSteve Wise 2882cfdda9d7SSteve Wise /* 2883cfdda9d7SSteve Wise * Upcall from the adapter indicating data has been transmitted. 2884cfdda9d7SSteve Wise * For us its just the single MPA request or reply. We can now free 2885cfdda9d7SSteve Wise * the skb holding the mpa message. 2886cfdda9d7SSteve Wise */ 2887cfdda9d7SSteve Wise static int fw4_ack(struct c4iw_dev *dev, struct sk_buff *skb) 2888cfdda9d7SSteve Wise { 2889cfdda9d7SSteve Wise struct c4iw_ep *ep; 2890cfdda9d7SSteve Wise struct cpl_fw4_ack *hdr = cplhdr(skb); 2891cfdda9d7SSteve Wise u8 credits = hdr->credits; 2892cfdda9d7SSteve Wise unsigned int tid = GET_TID(hdr); 2893cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 2894cfdda9d7SSteve Wise 2895cfdda9d7SSteve Wise 2896cfdda9d7SSteve Wise ep = lookup_tid(t, tid); 2897cfdda9d7SSteve Wise PDBG("%s ep %p tid %u credits %u\n", __func__, ep, ep->hwtid, credits); 2898cfdda9d7SSteve Wise if (credits == 0) { 2899aa1ad260SJoe Perches PDBG("%s 0 credit ack ep %p tid %u state %u\n", 2900cfdda9d7SSteve Wise __func__, ep, ep->hwtid, state_read(&ep->com)); 2901cfdda9d7SSteve Wise return 0; 2902cfdda9d7SSteve Wise } 2903cfdda9d7SSteve Wise 2904cfdda9d7SSteve Wise dst_confirm(ep->dst); 2905cfdda9d7SSteve Wise if (ep->mpa_skb) { 2906cfdda9d7SSteve Wise PDBG("%s last streaming msg ack ep %p tid %u state %u " 2907cfdda9d7SSteve Wise "initiator %u freeing skb\n", __func__, ep, ep->hwtid, 2908cfdda9d7SSteve Wise state_read(&ep->com), ep->mpa_attr.initiator ? 1 : 0); 2909cfdda9d7SSteve Wise kfree_skb(ep->mpa_skb); 2910cfdda9d7SSteve Wise ep->mpa_skb = NULL; 2911cfdda9d7SSteve Wise } 2912cfdda9d7SSteve Wise return 0; 2913cfdda9d7SSteve Wise } 2914cfdda9d7SSteve Wise 2915cfdda9d7SSteve Wise int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) 2916cfdda9d7SSteve Wise { 2917a7db89ebSSteve Wise int err = 0; 2918a7db89ebSSteve Wise int disconnect = 0; 2919cfdda9d7SSteve Wise struct c4iw_ep *ep = to_ep(cm_id); 2920cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2921cfdda9d7SSteve Wise 2922a7db89ebSSteve Wise mutex_lock(&ep->com.mutex); 2923a7db89ebSSteve Wise if (ep->com.state == DEAD) { 2924a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 2925cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 2926cfdda9d7SSteve Wise return -ECONNRESET; 2927cfdda9d7SSteve Wise } 2928793dad94SVipul Pandya set_bit(ULP_REJECT, &ep->com.history); 2929a7db89ebSSteve Wise BUG_ON(ep->com.state != MPA_REQ_RCVD); 2930cfdda9d7SSteve Wise if (mpa_rev == 0) 2931eaf4c6d4SHariprasad S disconnect = 2; 2932cfdda9d7SSteve Wise else { 2933cfdda9d7SSteve Wise err = send_mpa_reject(ep, pdata, pdata_len); 2934a7db89ebSSteve Wise disconnect = 1; 2935cfdda9d7SSteve Wise } 2936a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 2937a7db89ebSSteve Wise if (disconnect) 2938eaf4c6d4SHariprasad S err = c4iw_ep_disconnect(ep, disconnect == 2, GFP_KERNEL); 2939cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 2940cfdda9d7SSteve Wise return 0; 2941cfdda9d7SSteve Wise } 2942cfdda9d7SSteve Wise 2943cfdda9d7SSteve Wise int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) 2944cfdda9d7SSteve Wise { 2945cfdda9d7SSteve Wise int err; 2946cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 2947cfdda9d7SSteve Wise enum c4iw_qp_attr_mask mask; 2948cfdda9d7SSteve Wise struct c4iw_ep *ep = to_ep(cm_id); 2949cfdda9d7SSteve Wise struct c4iw_dev *h = to_c4iw_dev(cm_id->device); 2950cfdda9d7SSteve Wise struct c4iw_qp *qp = get_qhp(h, conn_param->qpn); 2951eaf4c6d4SHariprasad S int abort = 0; 2952cfdda9d7SSteve Wise 2953cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2954a7db89ebSSteve Wise 2955a7db89ebSSteve Wise mutex_lock(&ep->com.mutex); 2956a7db89ebSSteve Wise if (ep->com.state == DEAD) { 2957cfdda9d7SSteve Wise err = -ECONNRESET; 2958eaf4c6d4SHariprasad S goto err_out; 2959cfdda9d7SSteve Wise } 2960cfdda9d7SSteve Wise 2961a7db89ebSSteve Wise BUG_ON(ep->com.state != MPA_REQ_RCVD); 2962cfdda9d7SSteve Wise BUG_ON(!qp); 2963cfdda9d7SSteve Wise 2964793dad94SVipul Pandya set_bit(ULP_ACCEPT, &ep->com.history); 29654c2c5763SHariprasad Shenai if ((conn_param->ord > cur_max_read_depth(ep->com.dev)) || 29664c2c5763SHariprasad Shenai (conn_param->ird > cur_max_read_depth(ep->com.dev))) { 2967cfdda9d7SSteve Wise err = -EINVAL; 2968eaf4c6d4SHariprasad S goto err_abort; 2969cfdda9d7SSteve Wise } 2970cfdda9d7SSteve Wise 2971d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 2972d2fe99e8SKumar Sanghvi if (conn_param->ord > ep->ird) { 29734c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION) { 29744c2c5763SHariprasad Shenai ep->ord = ep->ird; 29754c2c5763SHariprasad Shenai } else { 2976d2fe99e8SKumar Sanghvi ep->ird = conn_param->ird; 2977d2fe99e8SKumar Sanghvi ep->ord = conn_param->ord; 2978d2fe99e8SKumar Sanghvi send_mpa_reject(ep, conn_param->private_data, 2979d2fe99e8SKumar Sanghvi conn_param->private_data_len); 2980d2fe99e8SKumar Sanghvi err = -ENOMEM; 2981eaf4c6d4SHariprasad S goto err_abort; 2982d2fe99e8SKumar Sanghvi } 29834c2c5763SHariprasad Shenai } 29844c2c5763SHariprasad Shenai if (conn_param->ird < ep->ord) { 29854c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION && 29864c2c5763SHariprasad Shenai ep->ord <= h->rdev.lldi.max_ordird_qp) { 29874c2c5763SHariprasad Shenai conn_param->ird = ep->ord; 29884c2c5763SHariprasad Shenai } else { 2989d2fe99e8SKumar Sanghvi err = -ENOMEM; 2990eaf4c6d4SHariprasad S goto err_abort; 2991d2fe99e8SKumar Sanghvi } 2992d2fe99e8SKumar Sanghvi } 2993d2fe99e8SKumar Sanghvi } 2994cfdda9d7SSteve Wise ep->ird = conn_param->ird; 2995cfdda9d7SSteve Wise ep->ord = conn_param->ord; 2996cfdda9d7SSteve Wise 29974c2c5763SHariprasad Shenai if (ep->mpa_attr.version == 1) { 2998cfdda9d7SSteve Wise if (peer2peer && ep->ird == 0) 2999cfdda9d7SSteve Wise ep->ird = 1; 30004c2c5763SHariprasad Shenai } else { 30014c2c5763SHariprasad Shenai if (peer2peer && 30024c2c5763SHariprasad Shenai (ep->mpa_attr.p2p_type != FW_RI_INIT_P2PTYPE_DISABLED) && 3003f57b780cSHariprasad S (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) && ep->ird == 0) 30044c2c5763SHariprasad Shenai ep->ird = 1; 30054c2c5763SHariprasad Shenai } 3006cfdda9d7SSteve Wise 3007cfdda9d7SSteve Wise PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord); 3008cfdda9d7SSteve Wise 3009d2fe99e8SKumar Sanghvi cm_id->add_ref(cm_id); 3010d2fe99e8SKumar Sanghvi ep->com.cm_id = cm_id; 3011d2fe99e8SKumar Sanghvi ep->com.qp = qp; 3012325abeadSVipul Pandya ref_qp(ep); 3013d2fe99e8SKumar Sanghvi 3014cfdda9d7SSteve Wise /* bind QP to EP and move to RTS */ 3015cfdda9d7SSteve Wise attrs.mpa_attr = ep->mpa_attr; 3016cfdda9d7SSteve Wise attrs.max_ird = ep->ird; 3017cfdda9d7SSteve Wise attrs.max_ord = ep->ord; 3018cfdda9d7SSteve Wise attrs.llp_stream_handle = ep; 3019cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_RTS; 3020cfdda9d7SSteve Wise 3021cfdda9d7SSteve Wise /* bind QP and TID with INIT_WR */ 3022cfdda9d7SSteve Wise mask = C4IW_QP_ATTR_NEXT_STATE | 3023cfdda9d7SSteve Wise C4IW_QP_ATTR_LLP_STREAM_HANDLE | 3024cfdda9d7SSteve Wise C4IW_QP_ATTR_MPA_ATTR | 3025cfdda9d7SSteve Wise C4IW_QP_ATTR_MAX_IRD | 3026cfdda9d7SSteve Wise C4IW_QP_ATTR_MAX_ORD; 3027cfdda9d7SSteve Wise 3028cfdda9d7SSteve Wise err = c4iw_modify_qp(ep->com.qp->rhp, 3029cfdda9d7SSteve Wise ep->com.qp, mask, &attrs, 1); 3030cfdda9d7SSteve Wise if (err) 3031eaf4c6d4SHariprasad S goto err_deref_cm_id; 3032cfdda9d7SSteve Wise err = send_mpa_reply(ep, conn_param->private_data, 3033cfdda9d7SSteve Wise conn_param->private_data_len); 3034cfdda9d7SSteve Wise if (err) 3035eaf4c6d4SHariprasad S goto err_deref_cm_id; 3036cfdda9d7SSteve Wise 3037a7db89ebSSteve Wise __state_set(&ep->com, FPDU_MODE); 3038cfdda9d7SSteve Wise established_upcall(ep); 3039a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 3040cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3041cfdda9d7SSteve Wise return 0; 3042eaf4c6d4SHariprasad S err_deref_cm_id: 3043cfdda9d7SSteve Wise ep->com.cm_id = NULL; 3044cfdda9d7SSteve Wise cm_id->rem_ref(cm_id); 3045eaf4c6d4SHariprasad S err_abort: 3046eaf4c6d4SHariprasad S abort = 1; 3047eaf4c6d4SHariprasad S err_out: 3048a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 3049eaf4c6d4SHariprasad S if (abort) 3050eaf4c6d4SHariprasad S c4iw_ep_disconnect(ep, 1, GFP_KERNEL); 3051cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3052cfdda9d7SSteve Wise return err; 3053cfdda9d7SSteve Wise } 3054cfdda9d7SSteve Wise 3055830662f6SVipul Pandya static int pick_local_ipaddrs(struct c4iw_dev *dev, struct iw_cm_id *cm_id) 3056830662f6SVipul Pandya { 3057830662f6SVipul Pandya struct in_device *ind; 3058830662f6SVipul Pandya int found = 0; 3059170003c8SSteve Wise struct sockaddr_in *laddr = (struct sockaddr_in *)&cm_id->m_local_addr; 3060170003c8SSteve Wise struct sockaddr_in *raddr = (struct sockaddr_in *)&cm_id->m_remote_addr; 3061830662f6SVipul Pandya 3062830662f6SVipul Pandya ind = in_dev_get(dev->rdev.lldi.ports[0]); 3063830662f6SVipul Pandya if (!ind) 3064830662f6SVipul Pandya return -EADDRNOTAVAIL; 3065830662f6SVipul Pandya for_primary_ifa(ind) { 3066830662f6SVipul Pandya laddr->sin_addr.s_addr = ifa->ifa_address; 3067830662f6SVipul Pandya raddr->sin_addr.s_addr = ifa->ifa_address; 3068830662f6SVipul Pandya found = 1; 3069830662f6SVipul Pandya break; 3070830662f6SVipul Pandya } 3071830662f6SVipul Pandya endfor_ifa(ind); 3072830662f6SVipul Pandya in_dev_put(ind); 3073830662f6SVipul Pandya return found ? 0 : -EADDRNOTAVAIL; 3074830662f6SVipul Pandya } 3075830662f6SVipul Pandya 3076830662f6SVipul Pandya static int get_lladdr(struct net_device *dev, struct in6_addr *addr, 3077830662f6SVipul Pandya unsigned char banned_flags) 3078830662f6SVipul Pandya { 3079830662f6SVipul Pandya struct inet6_dev *idev; 3080830662f6SVipul Pandya int err = -EADDRNOTAVAIL; 3081830662f6SVipul Pandya 3082830662f6SVipul Pandya rcu_read_lock(); 3083830662f6SVipul Pandya idev = __in6_dev_get(dev); 3084830662f6SVipul Pandya if (idev != NULL) { 3085830662f6SVipul Pandya struct inet6_ifaddr *ifp; 3086830662f6SVipul Pandya 3087830662f6SVipul Pandya read_lock_bh(&idev->lock); 3088830662f6SVipul Pandya list_for_each_entry(ifp, &idev->addr_list, if_list) { 3089830662f6SVipul Pandya if (ifp->scope == IFA_LINK && 3090830662f6SVipul Pandya !(ifp->flags & banned_flags)) { 3091830662f6SVipul Pandya memcpy(addr, &ifp->addr, 16); 3092830662f6SVipul Pandya err = 0; 3093830662f6SVipul Pandya break; 3094830662f6SVipul Pandya } 3095830662f6SVipul Pandya } 3096830662f6SVipul Pandya read_unlock_bh(&idev->lock); 3097830662f6SVipul Pandya } 3098830662f6SVipul Pandya rcu_read_unlock(); 3099830662f6SVipul Pandya return err; 3100830662f6SVipul Pandya } 3101830662f6SVipul Pandya 3102830662f6SVipul Pandya static int pick_local_ip6addrs(struct c4iw_dev *dev, struct iw_cm_id *cm_id) 3103830662f6SVipul Pandya { 3104830662f6SVipul Pandya struct in6_addr uninitialized_var(addr); 3105170003c8SSteve Wise struct sockaddr_in6 *la6 = (struct sockaddr_in6 *)&cm_id->m_local_addr; 3106170003c8SSteve Wise struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)&cm_id->m_remote_addr; 3107830662f6SVipul Pandya 310854b9a96fSNicholas Krause if (!get_lladdr(dev->rdev.lldi.ports[0], &addr, IFA_F_TENTATIVE)) { 3109830662f6SVipul Pandya memcpy(la6->sin6_addr.s6_addr, &addr, 16); 3110830662f6SVipul Pandya memcpy(ra6->sin6_addr.s6_addr, &addr, 16); 3111830662f6SVipul Pandya return 0; 3112830662f6SVipul Pandya } 3113830662f6SVipul Pandya return -EADDRNOTAVAIL; 3114830662f6SVipul Pandya } 3115830662f6SVipul Pandya 3116cfdda9d7SSteve Wise int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) 3117cfdda9d7SSteve Wise { 3118cfdda9d7SSteve Wise struct c4iw_dev *dev = to_c4iw_dev(cm_id->device); 3119cfdda9d7SSteve Wise struct c4iw_ep *ep; 31203786cf18SDavid Miller int err = 0; 31219eccfe10SSteve Wise struct sockaddr_in *laddr; 31229eccfe10SSteve Wise struct sockaddr_in *raddr; 31239eccfe10SSteve Wise struct sockaddr_in6 *laddr6; 31249eccfe10SSteve Wise struct sockaddr_in6 *raddr6; 3125830662f6SVipul Pandya __u8 *ra; 3126830662f6SVipul Pandya int iptype; 3127cfdda9d7SSteve Wise 31284c2c5763SHariprasad Shenai if ((conn_param->ord > cur_max_read_depth(dev)) || 31294c2c5763SHariprasad Shenai (conn_param->ird > cur_max_read_depth(dev))) { 3130be4c9badSRoland Dreier err = -EINVAL; 3131be4c9badSRoland Dreier goto out; 3132be4c9badSRoland Dreier } 3133cfdda9d7SSteve Wise ep = alloc_ep(sizeof(*ep), GFP_KERNEL); 3134cfdda9d7SSteve Wise if (!ep) { 3135cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __func__); 3136cfdda9d7SSteve Wise err = -ENOMEM; 3137cfdda9d7SSteve Wise goto out; 3138cfdda9d7SSteve Wise } 3139cfdda9d7SSteve Wise init_timer(&ep->timer); 3140cfdda9d7SSteve Wise ep->plen = conn_param->private_data_len; 3141cfdda9d7SSteve Wise if (ep->plen) 3142cfdda9d7SSteve Wise memcpy(ep->mpa_pkt + sizeof(struct mpa_message), 3143cfdda9d7SSteve Wise conn_param->private_data, ep->plen); 3144cfdda9d7SSteve Wise ep->ird = conn_param->ird; 3145cfdda9d7SSteve Wise ep->ord = conn_param->ord; 3146cfdda9d7SSteve Wise 3147cfdda9d7SSteve Wise if (peer2peer && ep->ord == 0) 3148cfdda9d7SSteve Wise ep->ord = 1; 3149cfdda9d7SSteve Wise 3150cfdda9d7SSteve Wise cm_id->add_ref(cm_id); 3151cfdda9d7SSteve Wise ep->com.dev = dev; 3152cfdda9d7SSteve Wise ep->com.cm_id = cm_id; 3153cfdda9d7SSteve Wise ep->com.qp = get_qhp(dev, conn_param->qpn); 3154830662f6SVipul Pandya if (!ep->com.qp) { 3155830662f6SVipul Pandya PDBG("%s qpn 0x%x not found!\n", __func__, conn_param->qpn); 3156830662f6SVipul Pandya err = -EINVAL; 31579eccfe10SSteve Wise goto fail1; 3158830662f6SVipul Pandya } 3159325abeadSVipul Pandya ref_qp(ep); 3160cfdda9d7SSteve Wise PDBG("%s qpn 0x%x qp %p cm_id %p\n", __func__, conn_param->qpn, 3161cfdda9d7SSteve Wise ep->com.qp, cm_id); 3162cfdda9d7SSteve Wise 3163cfdda9d7SSteve Wise /* 3164cfdda9d7SSteve Wise * Allocate an active TID to initiate a TCP connection. 3165cfdda9d7SSteve Wise */ 3166cfdda9d7SSteve Wise ep->atid = cxgb4_alloc_atid(dev->rdev.lldi.tids, ep); 3167cfdda9d7SSteve Wise if (ep->atid == -1) { 3168cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __func__); 3169cfdda9d7SSteve Wise err = -ENOMEM; 31709eccfe10SSteve Wise goto fail1; 3171cfdda9d7SSteve Wise } 3172793dad94SVipul Pandya insert_handle(dev, &dev->atid_idr, ep, ep->atid); 3173cfdda9d7SSteve Wise 3174170003c8SSteve Wise memcpy(&ep->com.local_addr, &cm_id->m_local_addr, 31759eccfe10SSteve Wise sizeof(ep->com.local_addr)); 3176170003c8SSteve Wise memcpy(&ep->com.remote_addr, &cm_id->m_remote_addr, 31779eccfe10SSteve Wise sizeof(ep->com.remote_addr)); 31789eccfe10SSteve Wise 3179170003c8SSteve Wise laddr = (struct sockaddr_in *)&ep->com.local_addr; 3180170003c8SSteve Wise raddr = (struct sockaddr_in *)&ep->com.remote_addr; 3181170003c8SSteve Wise laddr6 = (struct sockaddr_in6 *)&ep->com.local_addr; 3182170003c8SSteve Wise raddr6 = (struct sockaddr_in6 *) &ep->com.remote_addr; 31839eccfe10SSteve Wise 3184170003c8SSteve Wise if (cm_id->m_remote_addr.ss_family == AF_INET) { 3185830662f6SVipul Pandya iptype = 4; 3186830662f6SVipul Pandya ra = (__u8 *)&raddr->sin_addr; 3187830662f6SVipul Pandya 3188830662f6SVipul Pandya /* 3189830662f6SVipul Pandya * Handle loopback requests to INADDR_ANY. 3190830662f6SVipul Pandya */ 3191830662f6SVipul Pandya if ((__force int)raddr->sin_addr.s_addr == INADDR_ANY) { 3192830662f6SVipul Pandya err = pick_local_ipaddrs(dev, cm_id); 3193830662f6SVipul Pandya if (err) 31949eccfe10SSteve Wise goto fail1; 3195830662f6SVipul Pandya } 3196cfdda9d7SSteve Wise 3197cfdda9d7SSteve Wise /* find a route */ 3198830662f6SVipul Pandya PDBG("%s saddr %pI4 sport 0x%x raddr %pI4 rport 0x%x\n", 3199830662f6SVipul Pandya __func__, &laddr->sin_addr, ntohs(laddr->sin_port), 3200830662f6SVipul Pandya ra, ntohs(raddr->sin_port)); 3201830662f6SVipul Pandya ep->dst = find_route(dev, laddr->sin_addr.s_addr, 3202830662f6SVipul Pandya raddr->sin_addr.s_addr, laddr->sin_port, 3203ac8e4c69SHariprasad S raddr->sin_port, cm_id->tos); 3204830662f6SVipul Pandya } else { 3205830662f6SVipul Pandya iptype = 6; 3206830662f6SVipul Pandya ra = (__u8 *)&raddr6->sin6_addr; 3207830662f6SVipul Pandya 3208830662f6SVipul Pandya /* 3209830662f6SVipul Pandya * Handle loopback requests to INADDR_ANY. 3210830662f6SVipul Pandya */ 3211830662f6SVipul Pandya if (ipv6_addr_type(&raddr6->sin6_addr) == IPV6_ADDR_ANY) { 3212830662f6SVipul Pandya err = pick_local_ip6addrs(dev, cm_id); 3213830662f6SVipul Pandya if (err) 32149eccfe10SSteve Wise goto fail1; 3215830662f6SVipul Pandya } 3216830662f6SVipul Pandya 3217830662f6SVipul Pandya /* find a route */ 3218830662f6SVipul Pandya PDBG("%s saddr %pI6 sport 0x%x raddr %pI6 rport 0x%x\n", 3219830662f6SVipul Pandya __func__, laddr6->sin6_addr.s6_addr, 3220830662f6SVipul Pandya ntohs(laddr6->sin6_port), 3221830662f6SVipul Pandya raddr6->sin6_addr.s6_addr, ntohs(raddr6->sin6_port)); 3222830662f6SVipul Pandya ep->dst = find_route6(dev, laddr6->sin6_addr.s6_addr, 3223830662f6SVipul Pandya raddr6->sin6_addr.s6_addr, 3224830662f6SVipul Pandya laddr6->sin6_port, raddr6->sin6_port, 0, 3225830662f6SVipul Pandya raddr6->sin6_scope_id); 3226830662f6SVipul Pandya } 3227830662f6SVipul Pandya if (!ep->dst) { 3228cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot find route.\n", __func__); 3229cfdda9d7SSteve Wise err = -EHOSTUNREACH; 32309eccfe10SSteve Wise goto fail2; 3231cfdda9d7SSteve Wise } 3232cfdda9d7SSteve Wise 3233963cab50SHariprasad S err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, true, 3234ac8e4c69SHariprasad S ep->com.dev->rdev.lldi.adapter_type, cm_id->tos); 32353786cf18SDavid Miller if (err) { 3236cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); 32379eccfe10SSteve Wise goto fail3; 3238cfdda9d7SSteve Wise } 3239cfdda9d7SSteve Wise 3240cfdda9d7SSteve Wise PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n", 3241cfdda9d7SSteve Wise __func__, ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid, 3242cfdda9d7SSteve Wise ep->l2t->idx); 3243cfdda9d7SSteve Wise 3244cfdda9d7SSteve Wise state_set(&ep->com, CONNECTING); 3245ac8e4c69SHariprasad S ep->tos = cm_id->tos; 3246cfdda9d7SSteve Wise 3247cfdda9d7SSteve Wise /* send connect request to rnic */ 3248cfdda9d7SSteve Wise err = send_connect(ep); 3249cfdda9d7SSteve Wise if (!err) 3250cfdda9d7SSteve Wise goto out; 3251cfdda9d7SSteve Wise 3252cfdda9d7SSteve Wise cxgb4_l2t_release(ep->l2t); 3253cfdda9d7SSteve Wise fail3: 32549eccfe10SSteve Wise dst_release(ep->dst); 32559eccfe10SSteve Wise fail2: 3256793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid); 3257cfdda9d7SSteve Wise cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid); 32589eccfe10SSteve Wise fail1: 3259cfdda9d7SSteve Wise cm_id->rem_ref(cm_id); 3260cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3261cfdda9d7SSteve Wise out: 3262cfdda9d7SSteve Wise return err; 3263cfdda9d7SSteve Wise } 3264cfdda9d7SSteve Wise 3265830662f6SVipul Pandya static int create_server6(struct c4iw_dev *dev, struct c4iw_listen_ep *ep) 3266830662f6SVipul Pandya { 3267830662f6SVipul Pandya int err; 32689eccfe10SSteve Wise struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) 3269170003c8SSteve Wise &ep->com.local_addr; 3270830662f6SVipul Pandya 327128de1f74SHariprasad S if (ipv6_addr_type(&sin6->sin6_addr) != IPV6_ADDR_ANY) { 327228de1f74SHariprasad S err = cxgb4_clip_get(ep->com.dev->rdev.lldi.ports[0], 327328de1f74SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 327428de1f74SHariprasad S if (err) 327528de1f74SHariprasad S return err; 327628de1f74SHariprasad S } 3277830662f6SVipul Pandya c4iw_init_wr_wait(&ep->com.wr_wait); 3278830662f6SVipul Pandya err = cxgb4_create_server6(ep->com.dev->rdev.lldi.ports[0], 3279830662f6SVipul Pandya ep->stid, &sin6->sin6_addr, 3280830662f6SVipul Pandya sin6->sin6_port, 3281830662f6SVipul Pandya ep->com.dev->rdev.lldi.rxq_ids[0]); 3282830662f6SVipul Pandya if (!err) 3283830662f6SVipul Pandya err = c4iw_wait_for_reply(&ep->com.dev->rdev, 3284830662f6SVipul Pandya &ep->com.wr_wait, 3285830662f6SVipul Pandya 0, 0, __func__); 3286e6b11163SHariprasad S else if (err > 0) 3287e6b11163SHariprasad S err = net_xmit_errno(err); 328828de1f74SHariprasad S if (err) { 328928de1f74SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 329028de1f74SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 3291830662f6SVipul Pandya pr_err("cxgb4_create_server6/filter failed err %d stid %d laddr %pI6 lport %d\n", 3292830662f6SVipul Pandya err, ep->stid, 3293830662f6SVipul Pandya sin6->sin6_addr.s6_addr, ntohs(sin6->sin6_port)); 329428de1f74SHariprasad S } 3295830662f6SVipul Pandya return err; 3296830662f6SVipul Pandya } 3297830662f6SVipul Pandya 3298830662f6SVipul Pandya static int create_server4(struct c4iw_dev *dev, struct c4iw_listen_ep *ep) 3299830662f6SVipul Pandya { 3300830662f6SVipul Pandya int err; 33019eccfe10SSteve Wise struct sockaddr_in *sin = (struct sockaddr_in *) 3302170003c8SSteve Wise &ep->com.local_addr; 3303830662f6SVipul Pandya 3304830662f6SVipul Pandya if (dev->rdev.lldi.enable_fw_ofld_conn) { 3305830662f6SVipul Pandya do { 3306830662f6SVipul Pandya err = cxgb4_create_server_filter( 3307830662f6SVipul Pandya ep->com.dev->rdev.lldi.ports[0], ep->stid, 3308830662f6SVipul Pandya sin->sin_addr.s_addr, sin->sin_port, 0, 3309830662f6SVipul Pandya ep->com.dev->rdev.lldi.rxq_ids[0], 0, 0); 3310830662f6SVipul Pandya if (err == -EBUSY) { 331199718e59SHariprasad S if (c4iw_fatal_error(&ep->com.dev->rdev)) { 331299718e59SHariprasad S err = -EIO; 331399718e59SHariprasad S break; 331499718e59SHariprasad S } 3315830662f6SVipul Pandya set_current_state(TASK_UNINTERRUPTIBLE); 3316830662f6SVipul Pandya schedule_timeout(usecs_to_jiffies(100)); 3317830662f6SVipul Pandya } 3318830662f6SVipul Pandya } while (err == -EBUSY); 3319830662f6SVipul Pandya } else { 3320830662f6SVipul Pandya c4iw_init_wr_wait(&ep->com.wr_wait); 3321830662f6SVipul Pandya err = cxgb4_create_server(ep->com.dev->rdev.lldi.ports[0], 3322830662f6SVipul Pandya ep->stid, sin->sin_addr.s_addr, sin->sin_port, 3323830662f6SVipul Pandya 0, ep->com.dev->rdev.lldi.rxq_ids[0]); 3324830662f6SVipul Pandya if (!err) 3325830662f6SVipul Pandya err = c4iw_wait_for_reply(&ep->com.dev->rdev, 3326830662f6SVipul Pandya &ep->com.wr_wait, 3327830662f6SVipul Pandya 0, 0, __func__); 3328e6b11163SHariprasad S else if (err > 0) 3329e6b11163SHariprasad S err = net_xmit_errno(err); 3330830662f6SVipul Pandya } 3331830662f6SVipul Pandya if (err) 3332830662f6SVipul Pandya pr_err("cxgb4_create_server/filter failed err %d stid %d laddr %pI4 lport %d\n" 3333830662f6SVipul Pandya , err, ep->stid, 3334830662f6SVipul Pandya &sin->sin_addr, ntohs(sin->sin_port)); 3335830662f6SVipul Pandya return err; 3336830662f6SVipul Pandya } 3337830662f6SVipul Pandya 3338cfdda9d7SSteve Wise int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog) 3339cfdda9d7SSteve Wise { 3340cfdda9d7SSteve Wise int err = 0; 3341cfdda9d7SSteve Wise struct c4iw_dev *dev = to_c4iw_dev(cm_id->device); 3342cfdda9d7SSteve Wise struct c4iw_listen_ep *ep; 3343cfdda9d7SSteve Wise 3344cfdda9d7SSteve Wise might_sleep(); 3345cfdda9d7SSteve Wise 3346cfdda9d7SSteve Wise ep = alloc_ep(sizeof(*ep), GFP_KERNEL); 3347cfdda9d7SSteve Wise if (!ep) { 3348cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __func__); 3349cfdda9d7SSteve Wise err = -ENOMEM; 3350cfdda9d7SSteve Wise goto fail1; 3351cfdda9d7SSteve Wise } 3352cfdda9d7SSteve Wise PDBG("%s ep %p\n", __func__, ep); 3353cfdda9d7SSteve Wise cm_id->add_ref(cm_id); 3354cfdda9d7SSteve Wise ep->com.cm_id = cm_id; 3355cfdda9d7SSteve Wise ep->com.dev = dev; 3356cfdda9d7SSteve Wise ep->backlog = backlog; 3357170003c8SSteve Wise memcpy(&ep->com.local_addr, &cm_id->m_local_addr, 335824d44a39SSteve Wise sizeof(ep->com.local_addr)); 3359cfdda9d7SSteve Wise 3360cfdda9d7SSteve Wise /* 3361cfdda9d7SSteve Wise * Allocate a server TID. 3362cfdda9d7SSteve Wise */ 33638c044690SKumar Sanghvi if (dev->rdev.lldi.enable_fw_ofld_conn && 33648c044690SKumar Sanghvi ep->com.local_addr.ss_family == AF_INET) 3365830662f6SVipul Pandya ep->stid = cxgb4_alloc_sftid(dev->rdev.lldi.tids, 3366170003c8SSteve Wise cm_id->m_local_addr.ss_family, ep); 33671cab775cSVipul Pandya else 3368830662f6SVipul Pandya ep->stid = cxgb4_alloc_stid(dev->rdev.lldi.tids, 3369170003c8SSteve Wise cm_id->m_local_addr.ss_family, ep); 33701cab775cSVipul Pandya 3371cfdda9d7SSteve Wise if (ep->stid == -1) { 3372be4c9badSRoland Dreier printk(KERN_ERR MOD "%s - cannot alloc stid.\n", __func__); 3373cfdda9d7SSteve Wise err = -ENOMEM; 3374cfdda9d7SSteve Wise goto fail2; 3375cfdda9d7SSteve Wise } 3376793dad94SVipul Pandya insert_handle(dev, &dev->stid_idr, ep, ep->stid); 33779eccfe10SSteve Wise 3378170003c8SSteve Wise memcpy(&ep->com.local_addr, &cm_id->m_local_addr, 33799eccfe10SSteve Wise sizeof(ep->com.local_addr)); 33809eccfe10SSteve Wise 3381cfdda9d7SSteve Wise state_set(&ep->com, LISTEN); 3382830662f6SVipul Pandya if (ep->com.local_addr.ss_family == AF_INET) 3383830662f6SVipul Pandya err = create_server4(dev, ep); 3384830662f6SVipul Pandya else 3385830662f6SVipul Pandya err = create_server6(dev, ep); 3386cfdda9d7SSteve Wise if (!err) { 3387cfdda9d7SSteve Wise cm_id->provider_data = ep; 3388cfdda9d7SSteve Wise goto out; 3389cfdda9d7SSteve Wise } 33909eccfe10SSteve Wise 3391830662f6SVipul Pandya cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, 3392830662f6SVipul Pandya ep->com.local_addr.ss_family); 3393cfdda9d7SSteve Wise fail2: 3394cfdda9d7SSteve Wise cm_id->rem_ref(cm_id); 3395cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3396cfdda9d7SSteve Wise fail1: 3397cfdda9d7SSteve Wise out: 3398cfdda9d7SSteve Wise return err; 3399cfdda9d7SSteve Wise } 3400cfdda9d7SSteve Wise 3401cfdda9d7SSteve Wise int c4iw_destroy_listen(struct iw_cm_id *cm_id) 3402cfdda9d7SSteve Wise { 3403cfdda9d7SSteve Wise int err; 3404cfdda9d7SSteve Wise struct c4iw_listen_ep *ep = to_listen_ep(cm_id); 3405cfdda9d7SSteve Wise 3406cfdda9d7SSteve Wise PDBG("%s ep %p\n", __func__, ep); 3407cfdda9d7SSteve Wise 3408cfdda9d7SSteve Wise might_sleep(); 3409cfdda9d7SSteve Wise state_set(&ep->com, DEAD); 3410830662f6SVipul Pandya if (ep->com.dev->rdev.lldi.enable_fw_ofld_conn && 3411830662f6SVipul Pandya ep->com.local_addr.ss_family == AF_INET) { 34121cab775cSVipul Pandya err = cxgb4_remove_server_filter( 34131cab775cSVipul Pandya ep->com.dev->rdev.lldi.ports[0], ep->stid, 34141cab775cSVipul Pandya ep->com.dev->rdev.lldi.rxq_ids[0], 0); 34151cab775cSVipul Pandya } else { 341684cc6ac6SHariprasad S struct sockaddr_in6 *sin6; 3417aadc4df3SSteve Wise c4iw_init_wr_wait(&ep->com.wr_wait); 3418830662f6SVipul Pandya err = cxgb4_remove_server( 3419830662f6SVipul Pandya ep->com.dev->rdev.lldi.ports[0], ep->stid, 3420830662f6SVipul Pandya ep->com.dev->rdev.lldi.rxq_ids[0], 0); 3421cfdda9d7SSteve Wise if (err) 3422cfdda9d7SSteve Wise goto done; 34231cab775cSVipul Pandya err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait, 34241cab775cSVipul Pandya 0, 0, __func__); 3425170003c8SSteve Wise sin6 = (struct sockaddr_in6 *)&ep->com.local_addr; 342684cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 342784cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 34281cab775cSVipul Pandya } 3429793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->stid_idr, ep->stid); 3430830662f6SVipul Pandya cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, 3431830662f6SVipul Pandya ep->com.local_addr.ss_family); 3432cfdda9d7SSteve Wise done: 3433cfdda9d7SSteve Wise cm_id->rem_ref(cm_id); 3434cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3435cfdda9d7SSteve Wise return err; 3436cfdda9d7SSteve Wise } 3437cfdda9d7SSteve Wise 3438cfdda9d7SSteve Wise int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) 3439cfdda9d7SSteve Wise { 3440cfdda9d7SSteve Wise int ret = 0; 3441cfdda9d7SSteve Wise int close = 0; 3442cfdda9d7SSteve Wise int fatal = 0; 3443cfdda9d7SSteve Wise struct c4iw_rdev *rdev; 3444cfdda9d7SSteve Wise 34452f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 3446cfdda9d7SSteve Wise 3447cfdda9d7SSteve Wise PDBG("%s ep %p state %s, abrupt %d\n", __func__, ep, 3448cfdda9d7SSteve Wise states[ep->com.state], abrupt); 3449cfdda9d7SSteve Wise 34506e410d8fSHariprasad S /* 34516e410d8fSHariprasad S * Ref the ep here in case we have fatal errors causing the 34526e410d8fSHariprasad S * ep to be released and freed. 34536e410d8fSHariprasad S */ 34546e410d8fSHariprasad S c4iw_get_ep(&ep->com); 34556e410d8fSHariprasad S 3456cfdda9d7SSteve Wise rdev = &ep->com.dev->rdev; 3457cfdda9d7SSteve Wise if (c4iw_fatal_error(rdev)) { 3458cfdda9d7SSteve Wise fatal = 1; 3459be13b2dfSSteve Wise close_complete_upcall(ep, -EIO); 3460cfdda9d7SSteve Wise ep->com.state = DEAD; 3461cfdda9d7SSteve Wise } 3462cfdda9d7SSteve Wise switch (ep->com.state) { 3463cfdda9d7SSteve Wise case MPA_REQ_WAIT: 3464cfdda9d7SSteve Wise case MPA_REQ_SENT: 3465cfdda9d7SSteve Wise case MPA_REQ_RCVD: 3466cfdda9d7SSteve Wise case MPA_REP_SENT: 3467cfdda9d7SSteve Wise case FPDU_MODE: 3468cfdda9d7SSteve Wise close = 1; 3469cfdda9d7SSteve Wise if (abrupt) 3470cfdda9d7SSteve Wise ep->com.state = ABORTING; 3471cfdda9d7SSteve Wise else { 3472cfdda9d7SSteve Wise ep->com.state = CLOSING; 3473ca5a2202SSteve Wise start_ep_timer(ep); 3474cfdda9d7SSteve Wise } 3475cfdda9d7SSteve Wise set_bit(CLOSE_SENT, &ep->com.flags); 3476cfdda9d7SSteve Wise break; 3477cfdda9d7SSteve Wise case CLOSING: 3478cfdda9d7SSteve Wise if (!test_and_set_bit(CLOSE_SENT, &ep->com.flags)) { 3479cfdda9d7SSteve Wise close = 1; 3480cfdda9d7SSteve Wise if (abrupt) { 3481b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 3482cfdda9d7SSteve Wise ep->com.state = ABORTING; 3483cfdda9d7SSteve Wise } else 3484cfdda9d7SSteve Wise ep->com.state = MORIBUND; 3485cfdda9d7SSteve Wise } 3486cfdda9d7SSteve Wise break; 3487cfdda9d7SSteve Wise case MORIBUND: 3488cfdda9d7SSteve Wise case ABORTING: 3489cfdda9d7SSteve Wise case DEAD: 3490cfdda9d7SSteve Wise PDBG("%s ignoring disconnect ep %p state %u\n", 3491cfdda9d7SSteve Wise __func__, ep, ep->com.state); 3492cfdda9d7SSteve Wise break; 3493cfdda9d7SSteve Wise default: 3494cfdda9d7SSteve Wise BUG(); 3495cfdda9d7SSteve Wise break; 3496cfdda9d7SSteve Wise } 3497cfdda9d7SSteve Wise 3498cfdda9d7SSteve Wise if (close) { 34998da7e7a5SSteve Wise if (abrupt) { 3500793dad94SVipul Pandya set_bit(EP_DISC_ABORT, &ep->com.history); 3501be13b2dfSSteve Wise close_complete_upcall(ep, -ECONNRESET); 35028da7e7a5SSteve Wise ret = send_abort(ep, NULL, gfp); 3503793dad94SVipul Pandya } else { 3504793dad94SVipul Pandya set_bit(EP_DISC_CLOSE, &ep->com.history); 3505cfdda9d7SSteve Wise ret = send_halfclose(ep, gfp); 3506793dad94SVipul Pandya } 350788bc230dSHariprasad S if (ret) { 350888bc230dSHariprasad S if (!abrupt) { 350988bc230dSHariprasad S stop_ep_timer(ep); 351088bc230dSHariprasad S close_complete_upcall(ep, -EIO); 351188bc230dSHariprasad S } 3512cfdda9d7SSteve Wise fatal = 1; 3513cfdda9d7SSteve Wise } 351488bc230dSHariprasad S } 35158da7e7a5SSteve Wise mutex_unlock(&ep->com.mutex); 35166e410d8fSHariprasad S c4iw_put_ep(&ep->com); 3517cfdda9d7SSteve Wise if (fatal) 3518cfdda9d7SSteve Wise release_ep_resources(ep); 3519cfdda9d7SSteve Wise return ret; 3520cfdda9d7SSteve Wise } 3521cfdda9d7SSteve Wise 35221cab775cSVipul Pandya static void active_ofld_conn_reply(struct c4iw_dev *dev, struct sk_buff *skb, 35231cab775cSVipul Pandya struct cpl_fw6_msg_ofld_connection_wr_rpl *req) 35241cab775cSVipul Pandya { 35251cab775cSVipul Pandya struct c4iw_ep *ep; 3526793dad94SVipul Pandya int atid = be32_to_cpu(req->tid); 35271cab775cSVipul Pandya 3528ef5d6355SVipul Pandya ep = (struct c4iw_ep *)lookup_atid(dev->rdev.lldi.tids, 3529ef5d6355SVipul Pandya (__force u32) req->tid); 35301cab775cSVipul Pandya if (!ep) 35311cab775cSVipul Pandya return; 35321cab775cSVipul Pandya 35331cab775cSVipul Pandya switch (req->retval) { 35341cab775cSVipul Pandya case FW_ENOMEM: 3535793dad94SVipul Pandya set_bit(ACT_RETRY_NOMEM, &ep->com.history); 3536793dad94SVipul Pandya if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) { 3537793dad94SVipul Pandya send_fw_act_open_req(ep, atid); 3538793dad94SVipul Pandya return; 3539793dad94SVipul Pandya } 35401cab775cSVipul Pandya case FW_EADDRINUSE: 3541793dad94SVipul Pandya set_bit(ACT_RETRY_INUSE, &ep->com.history); 3542793dad94SVipul Pandya if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) { 3543793dad94SVipul Pandya send_fw_act_open_req(ep, atid); 3544793dad94SVipul Pandya return; 3545793dad94SVipul Pandya } 35461cab775cSVipul Pandya break; 35471cab775cSVipul Pandya default: 35481cab775cSVipul Pandya pr_info("%s unexpected ofld conn wr retval %d\n", 35491cab775cSVipul Pandya __func__, req->retval); 35501cab775cSVipul Pandya break; 35511cab775cSVipul Pandya } 3552793dad94SVipul Pandya pr_err("active ofld_connect_wr failure %d atid %d\n", 3553793dad94SVipul Pandya req->retval, atid); 3554793dad94SVipul Pandya mutex_lock(&dev->rdev.stats.lock); 3555793dad94SVipul Pandya dev->rdev.stats.act_ofld_conn_fails++; 3556793dad94SVipul Pandya mutex_unlock(&dev->rdev.stats.lock); 35571cab775cSVipul Pandya connect_reply_upcall(ep, status2errno(req->retval)); 3558793dad94SVipul Pandya state_set(&ep->com, DEAD); 355984cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 356084cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 3561170003c8SSteve Wise (struct sockaddr_in6 *)&ep->com.local_addr; 356284cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 356384cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 356484cc6ac6SHariprasad S } 3565793dad94SVipul Pandya remove_handle(dev, &dev->atid_idr, atid); 3566793dad94SVipul Pandya cxgb4_free_atid(dev->rdev.lldi.tids, atid); 3567793dad94SVipul Pandya dst_release(ep->dst); 3568793dad94SVipul Pandya cxgb4_l2t_release(ep->l2t); 3569793dad94SVipul Pandya c4iw_put_ep(&ep->com); 35701cab775cSVipul Pandya } 35711cab775cSVipul Pandya 35721cab775cSVipul Pandya static void passive_ofld_conn_reply(struct c4iw_dev *dev, struct sk_buff *skb, 35731cab775cSVipul Pandya struct cpl_fw6_msg_ofld_connection_wr_rpl *req) 35741cab775cSVipul Pandya { 35751cab775cSVipul Pandya struct sk_buff *rpl_skb; 35761cab775cSVipul Pandya struct cpl_pass_accept_req *cpl; 35771cab775cSVipul Pandya int ret; 35781cab775cSVipul Pandya 3579710a3110SPaul Bolle rpl_skb = (struct sk_buff *)(unsigned long)req->cookie; 35801cab775cSVipul Pandya BUG_ON(!rpl_skb); 35811cab775cSVipul Pandya if (req->retval) { 35821cab775cSVipul Pandya PDBG("%s passive open failure %d\n", __func__, req->retval); 3583793dad94SVipul Pandya mutex_lock(&dev->rdev.stats.lock); 3584793dad94SVipul Pandya dev->rdev.stats.pas_ofld_conn_fails++; 3585793dad94SVipul Pandya mutex_unlock(&dev->rdev.stats.lock); 35861cab775cSVipul Pandya kfree_skb(rpl_skb); 35871cab775cSVipul Pandya } else { 35881cab775cSVipul Pandya cpl = (struct cpl_pass_accept_req *)cplhdr(rpl_skb); 35891cab775cSVipul Pandya OPCODE_TID(cpl) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_REQ, 3590ef5d6355SVipul Pandya (__force u32) htonl( 3591ef5d6355SVipul Pandya (__force u32) req->tid))); 35921cab775cSVipul Pandya ret = pass_accept_req(dev, rpl_skb); 35931cab775cSVipul Pandya if (!ret) 35941cab775cSVipul Pandya kfree_skb(rpl_skb); 35951cab775cSVipul Pandya } 35961cab775cSVipul Pandya return; 35971cab775cSVipul Pandya } 35981cab775cSVipul Pandya 35991cab775cSVipul Pandya static int deferred_fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb) 36002f5b48c3SSteve Wise { 36012f5b48c3SSteve Wise struct cpl_fw6_msg *rpl = cplhdr(skb); 36021cab775cSVipul Pandya struct cpl_fw6_msg_ofld_connection_wr_rpl *req; 36031cab775cSVipul Pandya 36041cab775cSVipul Pandya switch (rpl->type) { 36051cab775cSVipul Pandya case FW6_TYPE_CQE: 36062f5b48c3SSteve Wise c4iw_ev_dispatch(dev, (struct t4_cqe *)&rpl->data[0]); 36071cab775cSVipul Pandya break; 36081cab775cSVipul Pandya case FW6_TYPE_OFLD_CONNECTION_WR_RPL: 36091cab775cSVipul Pandya req = (struct cpl_fw6_msg_ofld_connection_wr_rpl *)rpl->data; 36101cab775cSVipul Pandya switch (req->t_state) { 36111cab775cSVipul Pandya case TCP_SYN_SENT: 36121cab775cSVipul Pandya active_ofld_conn_reply(dev, skb, req); 36131cab775cSVipul Pandya break; 36141cab775cSVipul Pandya case TCP_SYN_RECV: 36151cab775cSVipul Pandya passive_ofld_conn_reply(dev, skb, req); 36161cab775cSVipul Pandya break; 36171cab775cSVipul Pandya default: 36181cab775cSVipul Pandya pr_err("%s unexpected ofld conn wr state %d\n", 36191cab775cSVipul Pandya __func__, req->t_state); 36201cab775cSVipul Pandya break; 36211cab775cSVipul Pandya } 36221cab775cSVipul Pandya break; 36231cab775cSVipul Pandya } 36241cab775cSVipul Pandya return 0; 36251cab775cSVipul Pandya } 36261cab775cSVipul Pandya 36271cab775cSVipul Pandya static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos) 36281cab775cSVipul Pandya { 3629963cab50SHariprasad S __be32 l2info; 3630963cab50SHariprasad S __be16 hdr_len, vlantag, len; 3631963cab50SHariprasad S u16 eth_hdr_len; 3632963cab50SHariprasad S int tcp_hdr_len, ip_hdr_len; 36331cab775cSVipul Pandya u8 intf; 36341cab775cSVipul Pandya struct cpl_rx_pkt *cpl = cplhdr(skb); 36351cab775cSVipul Pandya struct cpl_pass_accept_req *req; 36361cab775cSVipul Pandya struct tcp_options_received tmp_opt; 3637f079af7aSVipul Pandya struct c4iw_dev *dev; 3638963cab50SHariprasad S enum chip_type type; 36391cab775cSVipul Pandya 3640f079af7aSVipul Pandya dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *))); 36411cab775cSVipul Pandya /* Store values from cpl_rx_pkt in temporary location. */ 3642963cab50SHariprasad S vlantag = cpl->vlan; 3643963cab50SHariprasad S len = cpl->len; 3644963cab50SHariprasad S l2info = cpl->l2info; 3645963cab50SHariprasad S hdr_len = cpl->hdr_len; 36461cab775cSVipul Pandya intf = cpl->iff; 36471cab775cSVipul Pandya 36481cab775cSVipul Pandya __skb_pull(skb, sizeof(*req) + sizeof(struct rss_header)); 36491cab775cSVipul Pandya 36501cab775cSVipul Pandya /* 36511cab775cSVipul Pandya * We need to parse the TCP options from SYN packet. 36521cab775cSVipul Pandya * to generate cpl_pass_accept_req. 36531cab775cSVipul Pandya */ 36541cab775cSVipul Pandya memset(&tmp_opt, 0, sizeof(tmp_opt)); 36551cab775cSVipul Pandya tcp_clear_options(&tmp_opt); 36561a2c6181SChristoph Paasch tcp_parse_options(skb, &tmp_opt, 0, NULL); 36571cab775cSVipul Pandya 36581cab775cSVipul Pandya req = (struct cpl_pass_accept_req *)__skb_push(skb, sizeof(*req)); 36591cab775cSVipul Pandya memset(req, 0, sizeof(*req)); 3660cf7fe64aSHariprasad Shenai req->l2info = cpu_to_be16(SYN_INTF_V(intf) | 3661cf7fe64aSHariprasad Shenai SYN_MAC_IDX_V(RX_MACIDX_G( 3662963cab50SHariprasad S be32_to_cpu(l2info))) | 3663cf7fe64aSHariprasad Shenai SYN_XACT_MATCH_F); 3664963cab50SHariprasad S type = dev->rdev.lldi.adapter_type; 3665963cab50SHariprasad S tcp_hdr_len = RX_TCPHDR_LEN_G(be16_to_cpu(hdr_len)); 3666963cab50SHariprasad S ip_hdr_len = RX_IPHDR_LEN_G(be16_to_cpu(hdr_len)); 3667963cab50SHariprasad S req->hdr_len = 3668963cab50SHariprasad S cpu_to_be32(SYN_RX_CHAN_V(RX_CHAN_G(be32_to_cpu(l2info)))); 3669963cab50SHariprasad S if (CHELSIO_CHIP_VERSION(type) <= CHELSIO_T5) { 3670963cab50SHariprasad S eth_hdr_len = is_t4(type) ? 3671963cab50SHariprasad S RX_ETHHDR_LEN_G(be32_to_cpu(l2info)) : 3672963cab50SHariprasad S RX_T5_ETHHDR_LEN_G(be32_to_cpu(l2info)); 3673963cab50SHariprasad S req->hdr_len |= cpu_to_be32(TCP_HDR_LEN_V(tcp_hdr_len) | 3674963cab50SHariprasad S IP_HDR_LEN_V(ip_hdr_len) | 3675963cab50SHariprasad S ETH_HDR_LEN_V(eth_hdr_len)); 3676963cab50SHariprasad S } else { /* T6 and later */ 3677963cab50SHariprasad S eth_hdr_len = RX_T6_ETHHDR_LEN_G(be32_to_cpu(l2info)); 3678963cab50SHariprasad S req->hdr_len |= cpu_to_be32(T6_TCP_HDR_LEN_V(tcp_hdr_len) | 3679963cab50SHariprasad S T6_IP_HDR_LEN_V(ip_hdr_len) | 3680963cab50SHariprasad S T6_ETH_HDR_LEN_V(eth_hdr_len)); 3681963cab50SHariprasad S } 3682963cab50SHariprasad S req->vlan = vlantag; 3683963cab50SHariprasad S req->len = len; 36846c53e938SHariprasad Shenai req->tos_stid = cpu_to_be32(PASS_OPEN_TID_V(stid) | 36856c53e938SHariprasad Shenai PASS_OPEN_TOS_V(tos)); 36861cab775cSVipul Pandya req->tcpopt.mss = htons(tmp_opt.mss_clamp); 36871cab775cSVipul Pandya if (tmp_opt.wscale_ok) 36881cab775cSVipul Pandya req->tcpopt.wsf = tmp_opt.snd_wscale; 36891cab775cSVipul Pandya req->tcpopt.tstamp = tmp_opt.saw_tstamp; 36901cab775cSVipul Pandya if (tmp_opt.sack_ok) 36911cab775cSVipul Pandya req->tcpopt.sack = 1; 36921cab775cSVipul Pandya OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_REQ, 0)); 36931cab775cSVipul Pandya return; 36941cab775cSVipul Pandya } 36951cab775cSVipul Pandya 36961cab775cSVipul Pandya static void send_fw_pass_open_req(struct c4iw_dev *dev, struct sk_buff *skb, 36971cab775cSVipul Pandya __be32 laddr, __be16 lport, 36981cab775cSVipul Pandya __be32 raddr, __be16 rport, 36991cab775cSVipul Pandya u32 rcv_isn, u32 filter, u16 window, 37001cab775cSVipul Pandya u32 rss_qid, u8 port_id) 37011cab775cSVipul Pandya { 37021cab775cSVipul Pandya struct sk_buff *req_skb; 37031cab775cSVipul Pandya struct fw_ofld_connection_wr *req; 37041cab775cSVipul Pandya struct cpl_pass_accept_req *cpl = cplhdr(skb); 37051ce1d471SSteve Wise int ret; 37061cab775cSVipul Pandya 37071cab775cSVipul Pandya req_skb = alloc_skb(sizeof(struct fw_ofld_connection_wr), GFP_KERNEL); 37081cab775cSVipul Pandya req = (struct fw_ofld_connection_wr *)__skb_put(req_skb, sizeof(*req)); 37091cab775cSVipul Pandya memset(req, 0, sizeof(*req)); 37106c53e938SHariprasad Shenai req->op_compl = htonl(WR_OP_V(FW_OFLD_CONNECTION_WR) | FW_WR_COMPL_F); 3711e2ac9628SHariprasad Shenai req->len16_pkd = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*req), 16))); 371277a80e23SHariprasad Shenai req->le.version_cpl = htonl(FW_OFLD_CONNECTION_WR_CPL_F); 3713ef5d6355SVipul Pandya req->le.filter = (__force __be32) filter; 37141cab775cSVipul Pandya req->le.lport = lport; 37151cab775cSVipul Pandya req->le.pport = rport; 37161cab775cSVipul Pandya req->le.u.ipv4.lip = laddr; 37171cab775cSVipul Pandya req->le.u.ipv4.pip = raddr; 37181cab775cSVipul Pandya req->tcb.rcv_nxt = htonl(rcv_isn + 1); 37191cab775cSVipul Pandya req->tcb.rcv_adv = htons(window); 37201cab775cSVipul Pandya req->tcb.t_state_to_astid = 372177a80e23SHariprasad Shenai htonl(FW_OFLD_CONNECTION_WR_T_STATE_V(TCP_SYN_RECV) | 372277a80e23SHariprasad Shenai FW_OFLD_CONNECTION_WR_RCV_SCALE_V(cpl->tcpopt.wsf) | 372377a80e23SHariprasad Shenai FW_OFLD_CONNECTION_WR_ASTID_V( 37246c53e938SHariprasad Shenai PASS_OPEN_TID_G(ntohl(cpl->tos_stid)))); 37251cab775cSVipul Pandya 37261cab775cSVipul Pandya /* 37271cab775cSVipul Pandya * We store the qid in opt2 which will be used by the firmware 37281cab775cSVipul Pandya * to send us the wr response. 37291cab775cSVipul Pandya */ 3730d7990b0cSAnish Bhatt req->tcb.opt2 = htonl(RSS_QUEUE_V(rss_qid)); 37311cab775cSVipul Pandya 37321cab775cSVipul Pandya /* 37331cab775cSVipul Pandya * We initialize the MSS index in TCB to 0xF. 37341cab775cSVipul Pandya * So that when driver sends cpl_pass_accept_rpl 37351cab775cSVipul Pandya * TCB picks up the correct value. If this was 0 37361cab775cSVipul Pandya * TP will ignore any value > 0 for MSS index. 37371cab775cSVipul Pandya */ 3738d7990b0cSAnish Bhatt req->tcb.opt0 = cpu_to_be64(MSS_IDX_V(0xF)); 37396198dd8dSHariprasad S req->cookie = (uintptr_t)skb; 37401cab775cSVipul Pandya 37411cab775cSVipul Pandya set_wr_txq(req_skb, CPL_PRIORITY_CONTROL, port_id); 37421ce1d471SSteve Wise ret = cxgb4_ofld_send(dev->rdev.lldi.ports[0], req_skb); 37431ce1d471SSteve Wise if (ret < 0) { 37441ce1d471SSteve Wise pr_err("%s - cxgb4_ofld_send error %d - dropping\n", __func__, 37451ce1d471SSteve Wise ret); 37461ce1d471SSteve Wise kfree_skb(skb); 37471ce1d471SSteve Wise kfree_skb(req_skb); 37481ce1d471SSteve Wise } 37491cab775cSVipul Pandya } 37501cab775cSVipul Pandya 37511cab775cSVipul Pandya /* 37521cab775cSVipul Pandya * Handler for CPL_RX_PKT message. Need to handle cpl_rx_pkt 37531cab775cSVipul Pandya * messages when a filter is being used instead of server to 37541cab775cSVipul Pandya * redirect a syn packet. When packets hit filter they are redirected 37551cab775cSVipul Pandya * to the offload queue and driver tries to establish the connection 37561cab775cSVipul Pandya * using firmware work request. 37571cab775cSVipul Pandya */ 37581cab775cSVipul Pandya static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb) 37591cab775cSVipul Pandya { 37601cab775cSVipul Pandya int stid; 37611cab775cSVipul Pandya unsigned int filter; 37621cab775cSVipul Pandya struct ethhdr *eh = NULL; 37631cab775cSVipul Pandya struct vlan_ethhdr *vlan_eh = NULL; 37641cab775cSVipul Pandya struct iphdr *iph; 37651cab775cSVipul Pandya struct tcphdr *tcph; 37661cab775cSVipul Pandya struct rss_header *rss = (void *)skb->data; 37671cab775cSVipul Pandya struct cpl_rx_pkt *cpl = (void *)skb->data; 37681cab775cSVipul Pandya struct cpl_pass_accept_req *req = (void *)(rss + 1); 37691cab775cSVipul Pandya struct l2t_entry *e; 37701cab775cSVipul Pandya struct dst_entry *dst; 37711cab775cSVipul Pandya struct c4iw_ep *lep; 37721cab775cSVipul Pandya u16 window; 37731cab775cSVipul Pandya struct port_info *pi; 37741cab775cSVipul Pandya struct net_device *pdev; 3775f079af7aSVipul Pandya u16 rss_qid, eth_hdr_len; 37761cab775cSVipul Pandya int step; 37771cab775cSVipul Pandya u32 tx_chan; 37781cab775cSVipul Pandya struct neighbour *neigh; 37791cab775cSVipul Pandya 37801cab775cSVipul Pandya /* Drop all non-SYN packets */ 3781bdc590b9SHariprasad Shenai if (!(cpl->l2info & cpu_to_be32(RXF_SYN_F))) 37821cab775cSVipul Pandya goto reject; 37831cab775cSVipul Pandya 37841cab775cSVipul Pandya /* 37851cab775cSVipul Pandya * Drop all packets which did not hit the filter. 37861cab775cSVipul Pandya * Unlikely to happen. 37871cab775cSVipul Pandya */ 37881cab775cSVipul Pandya if (!(rss->filter_hit && rss->filter_tid)) 37891cab775cSVipul Pandya goto reject; 37901cab775cSVipul Pandya 37911cab775cSVipul Pandya /* 37921cab775cSVipul Pandya * Calculate the server tid from filter hit index from cpl_rx_pkt. 37931cab775cSVipul Pandya */ 3794a4ea025fSKumar Sanghvi stid = (__force int) cpu_to_be32((__force u32) rss->hash_val); 37951cab775cSVipul Pandya 37961cab775cSVipul Pandya lep = (struct c4iw_ep *)lookup_stid(dev->rdev.lldi.tids, stid); 37971cab775cSVipul Pandya if (!lep) { 37981cab775cSVipul Pandya PDBG("%s connect request on invalid stid %d\n", __func__, stid); 37991cab775cSVipul Pandya goto reject; 38001cab775cSVipul Pandya } 38011cab775cSVipul Pandya 3802963cab50SHariprasad S switch (CHELSIO_CHIP_VERSION(dev->rdev.lldi.adapter_type)) { 3803963cab50SHariprasad S case CHELSIO_T4: 3804963cab50SHariprasad S eth_hdr_len = RX_ETHHDR_LEN_G(be32_to_cpu(cpl->l2info)); 3805963cab50SHariprasad S break; 3806963cab50SHariprasad S case CHELSIO_T5: 3807963cab50SHariprasad S eth_hdr_len = RX_T5_ETHHDR_LEN_G(be32_to_cpu(cpl->l2info)); 3808963cab50SHariprasad S break; 3809963cab50SHariprasad S case CHELSIO_T6: 3810963cab50SHariprasad S eth_hdr_len = RX_T6_ETHHDR_LEN_G(be32_to_cpu(cpl->l2info)); 3811963cab50SHariprasad S break; 3812963cab50SHariprasad S default: 3813963cab50SHariprasad S pr_err("T%d Chip is not supported\n", 3814963cab50SHariprasad S CHELSIO_CHIP_VERSION(dev->rdev.lldi.adapter_type)); 3815963cab50SHariprasad S goto reject; 3816963cab50SHariprasad S } 3817963cab50SHariprasad S 3818f079af7aSVipul Pandya if (eth_hdr_len == ETH_HLEN) { 38191cab775cSVipul Pandya eh = (struct ethhdr *)(req + 1); 38201cab775cSVipul Pandya iph = (struct iphdr *)(eh + 1); 38211cab775cSVipul Pandya } else { 38221cab775cSVipul Pandya vlan_eh = (struct vlan_ethhdr *)(req + 1); 38231cab775cSVipul Pandya iph = (struct iphdr *)(vlan_eh + 1); 38241cab775cSVipul Pandya skb->vlan_tci = ntohs(cpl->vlan); 38251cab775cSVipul Pandya } 38261cab775cSVipul Pandya 38271cab775cSVipul Pandya if (iph->version != 0x4) 38281cab775cSVipul Pandya goto reject; 38291cab775cSVipul Pandya 38301cab775cSVipul Pandya tcph = (struct tcphdr *)(iph + 1); 38311cab775cSVipul Pandya skb_set_network_header(skb, (void *)iph - (void *)rss); 38321cab775cSVipul Pandya skb_set_transport_header(skb, (void *)tcph - (void *)rss); 38331cab775cSVipul Pandya skb_get(skb); 38341cab775cSVipul Pandya 38351cab775cSVipul Pandya PDBG("%s lip 0x%x lport %u pip 0x%x pport %u tos %d\n", __func__, 38361cab775cSVipul Pandya ntohl(iph->daddr), ntohs(tcph->dest), ntohl(iph->saddr), 38371cab775cSVipul Pandya ntohs(tcph->source), iph->tos); 38381cab775cSVipul Pandya 3839830662f6SVipul Pandya dst = find_route(dev, iph->daddr, iph->saddr, tcph->dest, tcph->source, 38401cab775cSVipul Pandya iph->tos); 3841830662f6SVipul Pandya if (!dst) { 38421cab775cSVipul Pandya pr_err("%s - failed to find dst entry!\n", 38431cab775cSVipul Pandya __func__); 38441cab775cSVipul Pandya goto reject; 38451cab775cSVipul Pandya } 38461cab775cSVipul Pandya neigh = dst_neigh_lookup_skb(dst, skb); 38471cab775cSVipul Pandya 3848aaa0c23cSZhouyi Zhou if (!neigh) { 3849aaa0c23cSZhouyi Zhou pr_err("%s - failed to allocate neigh!\n", 3850aaa0c23cSZhouyi Zhou __func__); 3851aaa0c23cSZhouyi Zhou goto free_dst; 3852aaa0c23cSZhouyi Zhou } 3853aaa0c23cSZhouyi Zhou 38541cab775cSVipul Pandya if (neigh->dev->flags & IFF_LOOPBACK) { 38551cab775cSVipul Pandya pdev = ip_dev_find(&init_net, iph->daddr); 38561cab775cSVipul Pandya e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, 38571cab775cSVipul Pandya pdev, 0); 38581cab775cSVipul Pandya pi = (struct port_info *)netdev_priv(pdev); 38591cab775cSVipul Pandya tx_chan = cxgb4_port_chan(pdev); 38601cab775cSVipul Pandya dev_put(pdev); 38611cab775cSVipul Pandya } else { 3862830662f6SVipul Pandya pdev = get_real_dev(neigh->dev); 38631cab775cSVipul Pandya e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, 3864830662f6SVipul Pandya pdev, 0); 3865830662f6SVipul Pandya pi = (struct port_info *)netdev_priv(pdev); 3866830662f6SVipul Pandya tx_chan = cxgb4_port_chan(pdev); 38671cab775cSVipul Pandya } 3868ebf00060SSteve Wise neigh_release(neigh); 38691cab775cSVipul Pandya if (!e) { 38701cab775cSVipul Pandya pr_err("%s - failed to allocate l2t entry!\n", 38711cab775cSVipul Pandya __func__); 38721cab775cSVipul Pandya goto free_dst; 38731cab775cSVipul Pandya } 38741cab775cSVipul Pandya 38751cab775cSVipul Pandya step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan; 38761cab775cSVipul Pandya rss_qid = dev->rdev.lldi.rxq_ids[pi->port_id * step]; 3877ef5d6355SVipul Pandya window = (__force u16) htons((__force u16)tcph->window); 38781cab775cSVipul Pandya 38791cab775cSVipul Pandya /* Calcuate filter portion for LE region. */ 388041b4f86cSKumar Sanghvi filter = (__force unsigned int) cpu_to_be32(cxgb4_select_ntuple( 388141b4f86cSKumar Sanghvi dev->rdev.lldi.ports[0], 388241b4f86cSKumar Sanghvi e)); 38831cab775cSVipul Pandya 38841cab775cSVipul Pandya /* 38851cab775cSVipul Pandya * Synthesize the cpl_pass_accept_req. We have everything except the 38861cab775cSVipul Pandya * TID. Once firmware sends a reply with TID we update the TID field 38871cab775cSVipul Pandya * in cpl and pass it through the regular cpl_pass_accept_req path. 38881cab775cSVipul Pandya */ 38891cab775cSVipul Pandya build_cpl_pass_accept_req(skb, stid, iph->tos); 38901cab775cSVipul Pandya send_fw_pass_open_req(dev, skb, iph->daddr, tcph->dest, iph->saddr, 38911cab775cSVipul Pandya tcph->source, ntohl(tcph->seq), filter, window, 38921cab775cSVipul Pandya rss_qid, pi->port_id); 38931cab775cSVipul Pandya cxgb4_l2t_release(e); 38941cab775cSVipul Pandya free_dst: 38951cab775cSVipul Pandya dst_release(dst); 38961cab775cSVipul Pandya reject: 38972f5b48c3SSteve Wise return 0; 38982f5b48c3SSteve Wise } 38992f5b48c3SSteve Wise 3900cfdda9d7SSteve Wise /* 3901be4c9badSRoland Dreier * These are the real handlers that are called from a 3902be4c9badSRoland Dreier * work queue. 3903be4c9badSRoland Dreier */ 39049dec900cSHariprasad S static c4iw_handler_func work_handlers[NUM_CPL_CMDS + NUM_FAKE_CPLS] = { 3905be4c9badSRoland Dreier [CPL_ACT_ESTABLISH] = act_establish, 3906be4c9badSRoland Dreier [CPL_ACT_OPEN_RPL] = act_open_rpl, 3907be4c9badSRoland Dreier [CPL_RX_DATA] = rx_data, 3908be4c9badSRoland Dreier [CPL_ABORT_RPL_RSS] = abort_rpl, 3909be4c9badSRoland Dreier [CPL_ABORT_RPL] = abort_rpl, 3910be4c9badSRoland Dreier [CPL_PASS_OPEN_RPL] = pass_open_rpl, 3911be4c9badSRoland Dreier [CPL_CLOSE_LISTSRV_RPL] = close_listsrv_rpl, 3912be4c9badSRoland Dreier [CPL_PASS_ACCEPT_REQ] = pass_accept_req, 3913be4c9badSRoland Dreier [CPL_PASS_ESTABLISH] = pass_establish, 3914be4c9badSRoland Dreier [CPL_PEER_CLOSE] = peer_close, 3915be4c9badSRoland Dreier [CPL_ABORT_REQ_RSS] = peer_abort, 3916be4c9badSRoland Dreier [CPL_CLOSE_CON_RPL] = close_con_rpl, 3917be4c9badSRoland Dreier [CPL_RDMA_TERMINATE] = terminate, 39182f5b48c3SSteve Wise [CPL_FW4_ACK] = fw4_ack, 39191cab775cSVipul Pandya [CPL_FW6_MSG] = deferred_fw6_msg, 39209dec900cSHariprasad S [CPL_RX_PKT] = rx_pkt, 39219dec900cSHariprasad S [FAKE_CPL_PUT_EP_SAFE] = _put_ep_safe 3922be4c9badSRoland Dreier }; 3923be4c9badSRoland Dreier 3924be4c9badSRoland Dreier static void process_timeout(struct c4iw_ep *ep) 3925be4c9badSRoland Dreier { 3926be4c9badSRoland Dreier struct c4iw_qp_attributes attrs; 3927be4c9badSRoland Dreier int abort = 1; 3928be4c9badSRoland Dreier 39292f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 3930be4c9badSRoland Dreier PDBG("%s ep %p tid %u state %d\n", __func__, ep, ep->hwtid, 3931be4c9badSRoland Dreier ep->com.state); 3932793dad94SVipul Pandya set_bit(TIMEDOUT, &ep->com.history); 3933be4c9badSRoland Dreier switch (ep->com.state) { 3934be4c9badSRoland Dreier case MPA_REQ_SENT: 3935be4c9badSRoland Dreier __state_set(&ep->com, ABORTING); 3936be4c9badSRoland Dreier connect_reply_upcall(ep, -ETIMEDOUT); 3937be4c9badSRoland Dreier break; 3938be4c9badSRoland Dreier case MPA_REQ_WAIT: 3939be4c9badSRoland Dreier __state_set(&ep->com, ABORTING); 3940be4c9badSRoland Dreier break; 3941be4c9badSRoland Dreier case CLOSING: 3942be4c9badSRoland Dreier case MORIBUND: 3943be4c9badSRoland Dreier if (ep->com.cm_id && ep->com.qp) { 3944be4c9badSRoland Dreier attrs.next_state = C4IW_QP_STATE_ERROR; 3945be4c9badSRoland Dreier c4iw_modify_qp(ep->com.qp->rhp, 3946be4c9badSRoland Dreier ep->com.qp, C4IW_QP_ATTR_NEXT_STATE, 3947be4c9badSRoland Dreier &attrs, 1); 3948be4c9badSRoland Dreier } 3949be4c9badSRoland Dreier __state_set(&ep->com, ABORTING); 3950be13b2dfSSteve Wise close_complete_upcall(ep, -ETIMEDOUT); 3951be4c9badSRoland Dreier break; 3952b33bd0cbSSteve Wise case ABORTING: 3953b33bd0cbSSteve Wise case DEAD: 3954b33bd0cbSSteve Wise 3955b33bd0cbSSteve Wise /* 3956b33bd0cbSSteve Wise * These states are expected if the ep timed out at the same 3957b33bd0cbSSteve Wise * time as another thread was calling stop_ep_timer(). 3958b33bd0cbSSteve Wise * So we silently do nothing for these states. 3959b33bd0cbSSteve Wise */ 3960b33bd0cbSSteve Wise abort = 0; 3961b33bd0cbSSteve Wise break; 3962be4c9badSRoland Dreier default: 396376f267b7SJulia Lawall WARN(1, "%s unexpected state ep %p tid %u state %u\n", 3964be4c9badSRoland Dreier __func__, ep, ep->hwtid, ep->com.state); 3965be4c9badSRoland Dreier abort = 0; 3966be4c9badSRoland Dreier } 3967be4c9badSRoland Dreier if (abort) 3968be4c9badSRoland Dreier abort_connection(ep, NULL, GFP_KERNEL); 3969cc18b939SSteve Wise mutex_unlock(&ep->com.mutex); 3970be4c9badSRoland Dreier c4iw_put_ep(&ep->com); 3971be4c9badSRoland Dreier } 3972be4c9badSRoland Dreier 3973be4c9badSRoland Dreier static void process_timedout_eps(void) 3974be4c9badSRoland Dreier { 3975be4c9badSRoland Dreier struct c4iw_ep *ep; 3976be4c9badSRoland Dreier 3977be4c9badSRoland Dreier spin_lock_irq(&timeout_lock); 3978be4c9badSRoland Dreier while (!list_empty(&timeout_list)) { 3979be4c9badSRoland Dreier struct list_head *tmp; 3980be4c9badSRoland Dreier 3981be4c9badSRoland Dreier tmp = timeout_list.next; 3982be4c9badSRoland Dreier list_del(tmp); 3983b33bd0cbSSteve Wise tmp->next = NULL; 3984b33bd0cbSSteve Wise tmp->prev = NULL; 3985be4c9badSRoland Dreier spin_unlock_irq(&timeout_lock); 3986be4c9badSRoland Dreier ep = list_entry(tmp, struct c4iw_ep, entry); 3987be4c9badSRoland Dreier process_timeout(ep); 3988be4c9badSRoland Dreier spin_lock_irq(&timeout_lock); 3989be4c9badSRoland Dreier } 3990be4c9badSRoland Dreier spin_unlock_irq(&timeout_lock); 3991be4c9badSRoland Dreier } 3992be4c9badSRoland Dreier 3993be4c9badSRoland Dreier static void process_work(struct work_struct *work) 3994be4c9badSRoland Dreier { 3995be4c9badSRoland Dreier struct sk_buff *skb = NULL; 3996be4c9badSRoland Dreier struct c4iw_dev *dev; 3997c1d7356cSDan Carpenter struct cpl_act_establish *rpl; 3998be4c9badSRoland Dreier unsigned int opcode; 3999be4c9badSRoland Dreier int ret; 4000be4c9badSRoland Dreier 4001b33bd0cbSSteve Wise process_timedout_eps(); 4002be4c9badSRoland Dreier while ((skb = skb_dequeue(&rxq))) { 4003be4c9badSRoland Dreier rpl = cplhdr(skb); 4004be4c9badSRoland Dreier dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *))); 4005be4c9badSRoland Dreier opcode = rpl->ot.opcode; 4006be4c9badSRoland Dreier 4007be4c9badSRoland Dreier BUG_ON(!work_handlers[opcode]); 4008be4c9badSRoland Dreier ret = work_handlers[opcode](dev, skb); 4009be4c9badSRoland Dreier if (!ret) 4010be4c9badSRoland Dreier kfree_skb(skb); 4011be4c9badSRoland Dreier process_timedout_eps(); 4012be4c9badSRoland Dreier } 4013b33bd0cbSSteve Wise } 4014be4c9badSRoland Dreier 4015be4c9badSRoland Dreier static DECLARE_WORK(skb_work, process_work); 4016be4c9badSRoland Dreier 4017be4c9badSRoland Dreier static void ep_timeout(unsigned long arg) 4018be4c9badSRoland Dreier { 4019be4c9badSRoland Dreier struct c4iw_ep *ep = (struct c4iw_ep *)arg; 40201ec779ccSVipul Pandya int kickit = 0; 4021be4c9badSRoland Dreier 4022be4c9badSRoland Dreier spin_lock(&timeout_lock); 40231ec779ccSVipul Pandya if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) { 4024b33bd0cbSSteve Wise /* 4025b33bd0cbSSteve Wise * Only insert if it is not already on the list. 4026b33bd0cbSSteve Wise */ 4027b33bd0cbSSteve Wise if (!ep->entry.next) { 4028be4c9badSRoland Dreier list_add_tail(&ep->entry, &timeout_list); 40291ec779ccSVipul Pandya kickit = 1; 40301ec779ccSVipul Pandya } 4031b33bd0cbSSteve Wise } 4032be4c9badSRoland Dreier spin_unlock(&timeout_lock); 40331ec779ccSVipul Pandya if (kickit) 4034be4c9badSRoland Dreier queue_work(workq, &skb_work); 4035be4c9badSRoland Dreier } 4036be4c9badSRoland Dreier 4037be4c9badSRoland Dreier /* 4038cfdda9d7SSteve Wise * All the CM events are handled on a work queue to have a safe context. 4039cfdda9d7SSteve Wise */ 4040cfdda9d7SSteve Wise static int sched(struct c4iw_dev *dev, struct sk_buff *skb) 4041cfdda9d7SSteve Wise { 4042cfdda9d7SSteve Wise 4043cfdda9d7SSteve Wise /* 4044cfdda9d7SSteve Wise * Save dev in the skb->cb area. 4045cfdda9d7SSteve Wise */ 4046cfdda9d7SSteve Wise *((struct c4iw_dev **) (skb->cb + sizeof(void *))) = dev; 4047cfdda9d7SSteve Wise 4048cfdda9d7SSteve Wise /* 4049cfdda9d7SSteve Wise * Queue the skb and schedule the worker thread. 4050cfdda9d7SSteve Wise */ 4051cfdda9d7SSteve Wise skb_queue_tail(&rxq, skb); 4052cfdda9d7SSteve Wise queue_work(workq, &skb_work); 4053cfdda9d7SSteve Wise return 0; 4054cfdda9d7SSteve Wise } 4055cfdda9d7SSteve Wise 4056cfdda9d7SSteve Wise static int set_tcb_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 4057cfdda9d7SSteve Wise { 4058cfdda9d7SSteve Wise struct cpl_set_tcb_rpl *rpl = cplhdr(skb); 4059cfdda9d7SSteve Wise 4060cfdda9d7SSteve Wise if (rpl->status != CPL_ERR_NONE) { 4061cfdda9d7SSteve Wise printk(KERN_ERR MOD "Unexpected SET_TCB_RPL status %u " 4062cfdda9d7SSteve Wise "for tid %u\n", rpl->status, GET_TID(rpl)); 4063cfdda9d7SSteve Wise } 40642f5b48c3SSteve Wise kfree_skb(skb); 4065cfdda9d7SSteve Wise return 0; 4066cfdda9d7SSteve Wise } 4067cfdda9d7SSteve Wise 4068be4c9badSRoland Dreier static int fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb) 4069be4c9badSRoland Dreier { 4070be4c9badSRoland Dreier struct cpl_fw6_msg *rpl = cplhdr(skb); 4071be4c9badSRoland Dreier struct c4iw_wr_wait *wr_waitp; 4072be4c9badSRoland Dreier int ret; 4073be4c9badSRoland Dreier 4074be4c9badSRoland Dreier PDBG("%s type %u\n", __func__, rpl->type); 4075be4c9badSRoland Dreier 4076be4c9badSRoland Dreier switch (rpl->type) { 40775be78ee9SVipul Pandya case FW6_TYPE_WR_RPL: 4078be4c9badSRoland Dreier ret = (int)((be64_to_cpu(rpl->data[0]) >> 8) & 0xff); 4079c8e081a1SRoland Dreier wr_waitp = (struct c4iw_wr_wait *)(__force unsigned long) rpl->data[1]; 4080be4c9badSRoland Dreier PDBG("%s wr_waitp %p ret %u\n", __func__, wr_waitp, ret); 4081d9594d99SSteve Wise if (wr_waitp) 4082d9594d99SSteve Wise c4iw_wake_up(wr_waitp, ret ? -ret : 0); 40832f5b48c3SSteve Wise kfree_skb(skb); 4084be4c9badSRoland Dreier break; 40855be78ee9SVipul Pandya case FW6_TYPE_CQE: 40865be78ee9SVipul Pandya case FW6_TYPE_OFLD_CONNECTION_WR_RPL: 40871cab775cSVipul Pandya sched(dev, skb); 40885be78ee9SVipul Pandya break; 4089be4c9badSRoland Dreier default: 4090be4c9badSRoland Dreier printk(KERN_ERR MOD "%s unexpected fw6 msg type %u\n", __func__, 4091be4c9badSRoland Dreier rpl->type); 40922f5b48c3SSteve Wise kfree_skb(skb); 4093be4c9badSRoland Dreier break; 4094be4c9badSRoland Dreier } 4095be4c9badSRoland Dreier return 0; 4096be4c9badSRoland Dreier } 4097be4c9badSRoland Dreier 40988da7e7a5SSteve Wise static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb) 40998da7e7a5SSteve Wise { 41008da7e7a5SSteve Wise struct cpl_abort_req_rss *req = cplhdr(skb); 41018da7e7a5SSteve Wise struct c4iw_ep *ep; 41028da7e7a5SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 41038da7e7a5SSteve Wise unsigned int tid = GET_TID(req); 41048da7e7a5SSteve Wise 41058da7e7a5SSteve Wise ep = lookup_tid(t, tid); 410614b92228SSteve Wise if (!ep) { 410714b92228SSteve Wise printk(KERN_WARNING MOD 410814b92228SSteve Wise "Abort on non-existent endpoint, tid %d\n", tid); 410914b92228SSteve Wise kfree_skb(skb); 411014b92228SSteve Wise return 0; 411114b92228SSteve Wise } 41127a2cea2aSSteve Wise if (is_neg_adv(req->status)) { 4113179d03bbSHariprasad S PDBG("%s Negative advice on abort- tid %u status %d (%s)\n", 4114179d03bbSHariprasad S __func__, ep->hwtid, req->status, 4115179d03bbSHariprasad S neg_adv_str(req->status)); 4116179d03bbSHariprasad S ep->stats.abort_neg_adv++; 4117179d03bbSHariprasad S dev->rdev.stats.neg_adv++; 41188da7e7a5SSteve Wise kfree_skb(skb); 41198da7e7a5SSteve Wise return 0; 41208da7e7a5SSteve Wise } 41218da7e7a5SSteve Wise PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid, 41228da7e7a5SSteve Wise ep->com.state); 41238da7e7a5SSteve Wise 41248da7e7a5SSteve Wise /* 41258da7e7a5SSteve Wise * Wake up any threads in rdma_init() or rdma_fini(). 41267c0a33d6SVipul Pandya * However, if we are on MPAv2 and want to retry with MPAv1 41277c0a33d6SVipul Pandya * then, don't wake up yet. 41288da7e7a5SSteve Wise */ 41297c0a33d6SVipul Pandya if (mpa_rev == 2 && !ep->tried_with_mpa_v1) { 41307c0a33d6SVipul Pandya if (ep->com.state != MPA_REQ_SENT) 41317c0a33d6SVipul Pandya c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 41327c0a33d6SVipul Pandya } else 41338da7e7a5SSteve Wise c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 41348da7e7a5SSteve Wise sched(dev, skb); 41358da7e7a5SSteve Wise return 0; 41368da7e7a5SSteve Wise } 41378da7e7a5SSteve Wise 4138be4c9badSRoland Dreier /* 4139be4c9badSRoland Dreier * Most upcalls from the T4 Core go to sched() to 4140be4c9badSRoland Dreier * schedule the processing on a work queue. 4141be4c9badSRoland Dreier */ 4142be4c9badSRoland Dreier c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS] = { 4143be4c9badSRoland Dreier [CPL_ACT_ESTABLISH] = sched, 4144be4c9badSRoland Dreier [CPL_ACT_OPEN_RPL] = sched, 4145be4c9badSRoland Dreier [CPL_RX_DATA] = sched, 4146be4c9badSRoland Dreier [CPL_ABORT_RPL_RSS] = sched, 4147be4c9badSRoland Dreier [CPL_ABORT_RPL] = sched, 4148be4c9badSRoland Dreier [CPL_PASS_OPEN_RPL] = sched, 4149be4c9badSRoland Dreier [CPL_CLOSE_LISTSRV_RPL] = sched, 4150be4c9badSRoland Dreier [CPL_PASS_ACCEPT_REQ] = sched, 4151be4c9badSRoland Dreier [CPL_PASS_ESTABLISH] = sched, 4152be4c9badSRoland Dreier [CPL_PEER_CLOSE] = sched, 4153be4c9badSRoland Dreier [CPL_CLOSE_CON_RPL] = sched, 41548da7e7a5SSteve Wise [CPL_ABORT_REQ_RSS] = peer_abort_intr, 4155be4c9badSRoland Dreier [CPL_RDMA_TERMINATE] = sched, 4156be4c9badSRoland Dreier [CPL_FW4_ACK] = sched, 4157be4c9badSRoland Dreier [CPL_SET_TCB_RPL] = set_tcb_rpl, 41581cab775cSVipul Pandya [CPL_FW6_MSG] = fw6_msg, 41591cab775cSVipul Pandya [CPL_RX_PKT] = sched 4160be4c9badSRoland Dreier }; 4161be4c9badSRoland Dreier 4162cfdda9d7SSteve Wise int __init c4iw_cm_init(void) 4163cfdda9d7SSteve Wise { 4164be4c9badSRoland Dreier spin_lock_init(&timeout_lock); 4165cfdda9d7SSteve Wise skb_queue_head_init(&rxq); 4166cfdda9d7SSteve Wise 4167cfdda9d7SSteve Wise workq = create_singlethread_workqueue("iw_cxgb4"); 4168cfdda9d7SSteve Wise if (!workq) 4169cfdda9d7SSteve Wise return -ENOMEM; 4170cfdda9d7SSteve Wise 4171cfdda9d7SSteve Wise return 0; 4172cfdda9d7SSteve Wise } 4173cfdda9d7SSteve Wise 417446c1376dSSteve Wise void c4iw_cm_term(void) 4175cfdda9d7SSteve Wise { 4176be4c9badSRoland Dreier WARN_ON(!list_empty(&timeout_list)); 4177cfdda9d7SSteve Wise flush_workqueue(workq); 4178cfdda9d7SSteve Wise destroy_workqueue(workq); 4179cfdda9d7SSteve Wise } 4180