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