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 5865b6b8fe6SSteve Wise static int get_remote_addr(struct c4iw_ep *ep) 5875b6b8fe6SSteve Wise { 5885b6b8fe6SSteve Wise int ret; 5895b6b8fe6SSteve Wise 5905b6b8fe6SSteve Wise print_addr(&ep->com, __func__, "get_remote_addr"); 5915b6b8fe6SSteve Wise 5925b6b8fe6SSteve Wise ret = iwpm_get_remote_info(&ep->com.mapped_local_addr, 5935b6b8fe6SSteve Wise &ep->com.mapped_remote_addr, 5945b6b8fe6SSteve Wise &ep->com.remote_addr, RDMA_NL_C4IW); 5955b6b8fe6SSteve Wise if (ret) 5965b6b8fe6SSteve Wise pr_info(MOD "Unable to find remote peer addr info - err %d\n", 5975b6b8fe6SSteve Wise ret); 5985b6b8fe6SSteve Wise 5995b6b8fe6SSteve Wise return ret; 6005b6b8fe6SSteve Wise } 6015b6b8fe6SSteve Wise 60292e7ae71SHariprasad Shenai static void best_mtu(const unsigned short *mtus, unsigned short mtu, 60304524a47SHariprasad S unsigned int *idx, int use_ts, int ipv6) 60492e7ae71SHariprasad Shenai { 60504524a47SHariprasad S unsigned short hdr_size = (ipv6 ? 60604524a47SHariprasad S sizeof(struct ipv6hdr) : 60704524a47SHariprasad S sizeof(struct iphdr)) + 60892e7ae71SHariprasad Shenai sizeof(struct tcphdr) + 60904524a47SHariprasad S (use_ts ? 61004524a47SHariprasad S round_up(TCPOLEN_TIMESTAMP, 4) : 0); 61192e7ae71SHariprasad Shenai unsigned short data_size = mtu - hdr_size; 61292e7ae71SHariprasad Shenai 61392e7ae71SHariprasad Shenai cxgb4_best_aligned_mtu(mtus, hdr_size, data_size, 8, idx); 61492e7ae71SHariprasad Shenai } 61592e7ae71SHariprasad Shenai 616cfdda9d7SSteve Wise static int send_connect(struct c4iw_ep *ep) 617cfdda9d7SSteve Wise { 618cfdda9d7SSteve Wise struct cpl_act_open_req *req; 619f079af7aSVipul Pandya struct cpl_t5_act_open_req *t5_req; 620830662f6SVipul Pandya struct cpl_act_open_req6 *req6; 621830662f6SVipul Pandya struct cpl_t5_act_open_req6 *t5_req6; 622cfdda9d7SSteve Wise struct sk_buff *skb; 623cfdda9d7SSteve Wise u64 opt0; 624cfdda9d7SSteve Wise u32 opt2; 625cfdda9d7SSteve Wise unsigned int mtu_idx; 626cfdda9d7SSteve Wise int wscale; 627830662f6SVipul Pandya int wrlen; 628830662f6SVipul Pandya int sizev4 = is_t4(ep->com.dev->rdev.lldi.adapter_type) ? 629f079af7aSVipul Pandya sizeof(struct cpl_act_open_req) : 630f079af7aSVipul Pandya sizeof(struct cpl_t5_act_open_req); 631830662f6SVipul Pandya int sizev6 = is_t4(ep->com.dev->rdev.lldi.adapter_type) ? 632830662f6SVipul Pandya sizeof(struct cpl_act_open_req6) : 633830662f6SVipul Pandya sizeof(struct cpl_t5_act_open_req6); 6349eccfe10SSteve Wise struct sockaddr_in *la = (struct sockaddr_in *) 6359eccfe10SSteve Wise &ep->com.mapped_local_addr; 6369eccfe10SSteve Wise struct sockaddr_in *ra = (struct sockaddr_in *) 6379eccfe10SSteve Wise &ep->com.mapped_remote_addr; 6389eccfe10SSteve Wise struct sockaddr_in6 *la6 = (struct sockaddr_in6 *) 6399eccfe10SSteve Wise &ep->com.mapped_local_addr; 6409eccfe10SSteve Wise struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *) 6419eccfe10SSteve Wise &ep->com.mapped_remote_addr; 642b408ff28SHariprasad Shenai int win; 643830662f6SVipul Pandya 644830662f6SVipul Pandya wrlen = (ep->com.remote_addr.ss_family == AF_INET) ? 645830662f6SVipul Pandya roundup(sizev4, 16) : 646830662f6SVipul Pandya roundup(sizev6, 16); 647cfdda9d7SSteve Wise 648cfdda9d7SSteve Wise PDBG("%s ep %p atid %u\n", __func__, ep, ep->atid); 649cfdda9d7SSteve Wise 650cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 651cfdda9d7SSteve Wise if (!skb) { 652cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - failed to alloc skb.\n", 653cfdda9d7SSteve Wise __func__); 654cfdda9d7SSteve Wise return -ENOMEM; 655cfdda9d7SSteve Wise } 656d4f1a5c6SSteve Wise set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->ctrlq_idx); 657cfdda9d7SSteve Wise 65892e7ae71SHariprasad Shenai best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, 65904524a47SHariprasad S enable_tcp_timestamps, 66004524a47SHariprasad S (AF_INET == ep->com.remote_addr.ss_family) ? 0 : 1); 661cfdda9d7SSteve Wise wscale = compute_wscale(rcv_win); 662b408ff28SHariprasad Shenai 663b408ff28SHariprasad Shenai /* 664b408ff28SHariprasad Shenai * Specify the largest window that will fit in opt0. The 665b408ff28SHariprasad Shenai * remainder will be specified in the rx_data_ack. 666b408ff28SHariprasad Shenai */ 667b408ff28SHariprasad Shenai win = ep->rcv_win >> 10; 668d7990b0cSAnish Bhatt if (win > RCV_BUFSIZ_M) 669d7990b0cSAnish Bhatt win = RCV_BUFSIZ_M; 670b408ff28SHariprasad Shenai 6716c53e938SHariprasad Shenai opt0 = (nocong ? NO_CONG_F : 0) | 672d7990b0cSAnish Bhatt KEEP_ALIVE_F | 6736c53e938SHariprasad Shenai DELACK_F | 674d7990b0cSAnish Bhatt WND_SCALE_V(wscale) | 675d7990b0cSAnish Bhatt MSS_IDX_V(mtu_idx) | 676d7990b0cSAnish Bhatt L2T_IDX_V(ep->l2t->idx) | 677d7990b0cSAnish Bhatt TX_CHAN_V(ep->tx_chan) | 678d7990b0cSAnish Bhatt SMAC_SEL_V(ep->smac_idx) | 6796c53e938SHariprasad Shenai DSCP_V(ep->tos) | 680d7990b0cSAnish Bhatt ULP_MODE_V(ULP_MODE_TCPDDP) | 681d7990b0cSAnish Bhatt RCV_BUFSIZ_V(win); 682d7990b0cSAnish Bhatt opt2 = RX_CHANNEL_V(0) | 6836c53e938SHariprasad Shenai CCTRL_ECN_V(enable_ecn) | 684d7990b0cSAnish Bhatt RSS_QUEUE_VALID_F | RSS_QUEUE_V(ep->rss_qid); 685cfdda9d7SSteve Wise if (enable_tcp_timestamps) 6866c53e938SHariprasad Shenai opt2 |= TSTAMPS_EN_F; 687cfdda9d7SSteve Wise if (enable_tcp_sack) 6886c53e938SHariprasad Shenai opt2 |= SACK_EN_F; 689cfdda9d7SSteve Wise if (wscale && enable_tcp_window_scaling) 690d7990b0cSAnish Bhatt opt2 |= WND_SCALE_EN_F; 69192e5011aSSteve Wise if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) { 692d7990b0cSAnish Bhatt opt2 |= T5_OPT_2_VALID_F; 693cf7fe64aSHariprasad Shenai opt2 |= CONG_CNTRL_V(CONG_ALG_TAHOE); 6940b741047SHariprasad S opt2 |= T5_ISS_F; 69592e5011aSSteve Wise } 6965dab6d3aSHariprasad S t4_set_arp_err_handler(skb, ep, act_open_req_arp_failure); 697cfdda9d7SSteve Wise 698f079af7aSVipul Pandya if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) { 699830662f6SVipul Pandya if (ep->com.remote_addr.ss_family == AF_INET) { 700cfdda9d7SSteve Wise req = (struct cpl_act_open_req *) skb_put(skb, wrlen); 701cfdda9d7SSteve Wise INIT_TP_WR(req, 0); 702cfdda9d7SSteve Wise OPCODE_TID(req) = cpu_to_be32( 703f079af7aSVipul Pandya MK_OPCODE_TID(CPL_ACT_OPEN_REQ, 704f079af7aSVipul Pandya ((ep->rss_qid << 14) | ep->atid))); 705830662f6SVipul Pandya req->local_port = la->sin_port; 706830662f6SVipul Pandya req->peer_port = ra->sin_port; 707830662f6SVipul Pandya req->local_ip = la->sin_addr.s_addr; 708830662f6SVipul Pandya req->peer_ip = ra->sin_addr.s_addr; 709cfdda9d7SSteve Wise req->opt0 = cpu_to_be64(opt0); 71041b4f86cSKumar Sanghvi req->params = cpu_to_be32(cxgb4_select_ntuple( 71141b4f86cSKumar Sanghvi ep->com.dev->rdev.lldi.ports[0], 71241b4f86cSKumar Sanghvi ep->l2t)); 713cfdda9d7SSteve Wise req->opt2 = cpu_to_be32(opt2); 714f079af7aSVipul Pandya } else { 715830662f6SVipul Pandya req6 = (struct cpl_act_open_req6 *)skb_put(skb, wrlen); 716830662f6SVipul Pandya 717830662f6SVipul Pandya INIT_TP_WR(req6, 0); 718830662f6SVipul Pandya OPCODE_TID(req6) = cpu_to_be32( 719830662f6SVipul Pandya MK_OPCODE_TID(CPL_ACT_OPEN_REQ6, 720830662f6SVipul Pandya ((ep->rss_qid<<14)|ep->atid))); 721830662f6SVipul Pandya req6->local_port = la6->sin6_port; 722830662f6SVipul Pandya req6->peer_port = ra6->sin6_port; 723830662f6SVipul Pandya req6->local_ip_hi = *((__be64 *) 724830662f6SVipul Pandya (la6->sin6_addr.s6_addr)); 725830662f6SVipul Pandya req6->local_ip_lo = *((__be64 *) 726830662f6SVipul Pandya (la6->sin6_addr.s6_addr + 8)); 727830662f6SVipul Pandya req6->peer_ip_hi = *((__be64 *) 728830662f6SVipul Pandya (ra6->sin6_addr.s6_addr)); 729830662f6SVipul Pandya req6->peer_ip_lo = *((__be64 *) 730830662f6SVipul Pandya (ra6->sin6_addr.s6_addr + 8)); 731830662f6SVipul Pandya req6->opt0 = cpu_to_be64(opt0); 73241b4f86cSKumar Sanghvi req6->params = cpu_to_be32(cxgb4_select_ntuple( 73341b4f86cSKumar Sanghvi ep->com.dev->rdev.lldi.ports[0], 734830662f6SVipul Pandya ep->l2t)); 735830662f6SVipul Pandya req6->opt2 = cpu_to_be32(opt2); 736830662f6SVipul Pandya } 737830662f6SVipul Pandya } else { 73892e7ae71SHariprasad Shenai u32 isn = (prandom_u32() & ~7UL) - 1; 73992e7ae71SHariprasad Shenai 74092e7ae71SHariprasad Shenai if (peer2peer) 74192e7ae71SHariprasad Shenai isn += 4; 74292e7ae71SHariprasad Shenai 743830662f6SVipul Pandya if (ep->com.remote_addr.ss_family == AF_INET) { 744830662f6SVipul Pandya t5_req = (struct cpl_t5_act_open_req *) 745830662f6SVipul Pandya skb_put(skb, wrlen); 746f079af7aSVipul Pandya INIT_TP_WR(t5_req, 0); 747f079af7aSVipul Pandya OPCODE_TID(t5_req) = cpu_to_be32( 748f079af7aSVipul Pandya MK_OPCODE_TID(CPL_ACT_OPEN_REQ, 749f079af7aSVipul Pandya ((ep->rss_qid << 14) | ep->atid))); 750830662f6SVipul Pandya t5_req->local_port = la->sin_port; 751830662f6SVipul Pandya t5_req->peer_port = ra->sin_port; 752830662f6SVipul Pandya t5_req->local_ip = la->sin_addr.s_addr; 753830662f6SVipul Pandya t5_req->peer_ip = ra->sin_addr.s_addr; 754f079af7aSVipul Pandya t5_req->opt0 = cpu_to_be64(opt0); 755d7990b0cSAnish Bhatt t5_req->params = cpu_to_be64(FILTER_TUPLE_V( 75641b4f86cSKumar Sanghvi cxgb4_select_ntuple( 75741b4f86cSKumar Sanghvi ep->com.dev->rdev.lldi.ports[0], 75841b4f86cSKumar Sanghvi ep->l2t))); 75992e7ae71SHariprasad Shenai t5_req->rsvd = cpu_to_be32(isn); 76092e7ae71SHariprasad Shenai PDBG("%s snd_isn %u\n", __func__, 76192e7ae71SHariprasad Shenai be32_to_cpu(t5_req->rsvd)); 762f079af7aSVipul Pandya t5_req->opt2 = cpu_to_be32(opt2); 763830662f6SVipul Pandya } else { 764830662f6SVipul Pandya t5_req6 = (struct cpl_t5_act_open_req6 *) 765830662f6SVipul Pandya skb_put(skb, wrlen); 766830662f6SVipul Pandya INIT_TP_WR(t5_req6, 0); 767830662f6SVipul Pandya OPCODE_TID(t5_req6) = cpu_to_be32( 768830662f6SVipul Pandya MK_OPCODE_TID(CPL_ACT_OPEN_REQ6, 769830662f6SVipul Pandya ((ep->rss_qid<<14)|ep->atid))); 770830662f6SVipul Pandya t5_req6->local_port = la6->sin6_port; 771830662f6SVipul Pandya t5_req6->peer_port = ra6->sin6_port; 772830662f6SVipul Pandya t5_req6->local_ip_hi = *((__be64 *) 773830662f6SVipul Pandya (la6->sin6_addr.s6_addr)); 774830662f6SVipul Pandya t5_req6->local_ip_lo = *((__be64 *) 775830662f6SVipul Pandya (la6->sin6_addr.s6_addr + 8)); 776830662f6SVipul Pandya t5_req6->peer_ip_hi = *((__be64 *) 777830662f6SVipul Pandya (ra6->sin6_addr.s6_addr)); 778830662f6SVipul Pandya t5_req6->peer_ip_lo = *((__be64 *) 779830662f6SVipul Pandya (ra6->sin6_addr.s6_addr + 8)); 780830662f6SVipul Pandya t5_req6->opt0 = cpu_to_be64(opt0); 781d7990b0cSAnish Bhatt t5_req6->params = cpu_to_be64(FILTER_TUPLE_V( 78241b4f86cSKumar Sanghvi cxgb4_select_ntuple( 78341b4f86cSKumar Sanghvi ep->com.dev->rdev.lldi.ports[0], 784da22b896SHariprasad S ep->l2t))); 78592e7ae71SHariprasad Shenai t5_req6->rsvd = cpu_to_be32(isn); 78692e7ae71SHariprasad Shenai PDBG("%s snd_isn %u\n", __func__, 78792e7ae71SHariprasad Shenai be32_to_cpu(t5_req6->rsvd)); 788830662f6SVipul Pandya t5_req6->opt2 = cpu_to_be32(opt2); 789830662f6SVipul Pandya } 790f079af7aSVipul Pandya } 791f079af7aSVipul Pandya 792793dad94SVipul Pandya set_bit(ACT_OPEN_REQ, &ep->com.history); 793cfdda9d7SSteve Wise return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 794cfdda9d7SSteve Wise } 795cfdda9d7SSteve Wise 796d2fe99e8SKumar Sanghvi static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb, 797d2fe99e8SKumar Sanghvi u8 mpa_rev_to_use) 798cfdda9d7SSteve Wise { 799cfdda9d7SSteve Wise int mpalen, wrlen; 800cfdda9d7SSteve Wise struct fw_ofld_tx_data_wr *req; 801cfdda9d7SSteve Wise struct mpa_message *mpa; 802d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params mpa_v2_params; 803cfdda9d7SSteve Wise 804cfdda9d7SSteve Wise PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen); 805cfdda9d7SSteve Wise 806cfdda9d7SSteve Wise BUG_ON(skb_cloned(skb)); 807cfdda9d7SSteve Wise 808cfdda9d7SSteve Wise mpalen = sizeof(*mpa) + ep->plen; 809d2fe99e8SKumar Sanghvi if (mpa_rev_to_use == 2) 810d2fe99e8SKumar Sanghvi mpalen += sizeof(struct mpa_v2_conn_params); 811cfdda9d7SSteve Wise wrlen = roundup(mpalen + sizeof *req, 16); 812cfdda9d7SSteve Wise skb = get_skb(skb, wrlen, GFP_KERNEL); 813cfdda9d7SSteve Wise if (!skb) { 814cfdda9d7SSteve Wise connect_reply_upcall(ep, -ENOMEM); 815cfdda9d7SSteve Wise return; 816cfdda9d7SSteve Wise } 817cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 818cfdda9d7SSteve Wise 819cfdda9d7SSteve Wise req = (struct fw_ofld_tx_data_wr *)skb_put(skb, wrlen); 820cfdda9d7SSteve Wise memset(req, 0, wrlen); 821cfdda9d7SSteve Wise req->op_to_immdlen = cpu_to_be32( 822e2ac9628SHariprasad Shenai FW_WR_OP_V(FW_OFLD_TX_DATA_WR) | 823e2ac9628SHariprasad Shenai FW_WR_COMPL_F | 824e2ac9628SHariprasad Shenai FW_WR_IMMDLEN_V(mpalen)); 825cfdda9d7SSteve Wise req->flowid_len16 = cpu_to_be32( 826e2ac9628SHariprasad Shenai FW_WR_FLOWID_V(ep->hwtid) | 827e2ac9628SHariprasad Shenai FW_WR_LEN16_V(wrlen >> 4)); 828cfdda9d7SSteve Wise req->plen = cpu_to_be32(mpalen); 829cfdda9d7SSteve Wise req->tunnel_to_proxy = cpu_to_be32( 830e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_FLUSH_F | 831e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_SHOVE_F); 832cfdda9d7SSteve Wise 833cfdda9d7SSteve Wise mpa = (struct mpa_message *)(req + 1); 834cfdda9d7SSteve Wise memcpy(mpa->key, MPA_KEY_REQ, sizeof(mpa->key)); 835cfdda9d7SSteve Wise mpa->flags = (crc_enabled ? MPA_CRC : 0) | 836d2fe99e8SKumar Sanghvi (markers_enabled ? MPA_MARKERS : 0) | 837d2fe99e8SKumar Sanghvi (mpa_rev_to_use == 2 ? MPA_ENHANCED_RDMA_CONN : 0); 838cfdda9d7SSteve Wise mpa->private_data_size = htons(ep->plen); 839d2fe99e8SKumar Sanghvi mpa->revision = mpa_rev_to_use; 84001b225e1SKumar Sanghvi if (mpa_rev_to_use == 1) { 841d2fe99e8SKumar Sanghvi ep->tried_with_mpa_v1 = 1; 84201b225e1SKumar Sanghvi ep->retry_with_mpa_v1 = 0; 84301b225e1SKumar Sanghvi } 844d2fe99e8SKumar Sanghvi 845d2fe99e8SKumar Sanghvi if (mpa_rev_to_use == 2) { 846f747c34aSRoland Dreier mpa->private_data_size = htons(ntohs(mpa->private_data_size) + 847f747c34aSRoland Dreier sizeof (struct mpa_v2_conn_params)); 8484c2c5763SHariprasad Shenai PDBG("%s initiator ird %u ord %u\n", __func__, ep->ird, 8494c2c5763SHariprasad Shenai ep->ord); 850d2fe99e8SKumar Sanghvi mpa_v2_params.ird = htons((u16)ep->ird); 851d2fe99e8SKumar Sanghvi mpa_v2_params.ord = htons((u16)ep->ord); 852d2fe99e8SKumar Sanghvi 853d2fe99e8SKumar Sanghvi if (peer2peer) { 854d2fe99e8SKumar Sanghvi mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL); 855d2fe99e8SKumar Sanghvi if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE) 856d2fe99e8SKumar Sanghvi mpa_v2_params.ord |= 857d2fe99e8SKumar Sanghvi htons(MPA_V2_RDMA_WRITE_RTR); 858d2fe99e8SKumar Sanghvi else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) 859d2fe99e8SKumar Sanghvi mpa_v2_params.ord |= 860d2fe99e8SKumar Sanghvi htons(MPA_V2_RDMA_READ_RTR); 861d2fe99e8SKumar Sanghvi } 862d2fe99e8SKumar Sanghvi memcpy(mpa->private_data, &mpa_v2_params, 863d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params)); 864cfdda9d7SSteve Wise 865cfdda9d7SSteve Wise if (ep->plen) 866d2fe99e8SKumar Sanghvi memcpy(mpa->private_data + 867d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params), 868d2fe99e8SKumar Sanghvi ep->mpa_pkt + sizeof(*mpa), ep->plen); 869d2fe99e8SKumar Sanghvi } else 870d2fe99e8SKumar Sanghvi if (ep->plen) 871d2fe99e8SKumar Sanghvi memcpy(mpa->private_data, 872d2fe99e8SKumar Sanghvi ep->mpa_pkt + sizeof(*mpa), ep->plen); 873cfdda9d7SSteve Wise 874cfdda9d7SSteve Wise /* 875cfdda9d7SSteve Wise * Reference the mpa skb. This ensures the data area 876cfdda9d7SSteve Wise * will remain in memory until the hw acks the tx. 877cfdda9d7SSteve Wise * Function fw4_ack() will deref it. 878cfdda9d7SSteve Wise */ 879cfdda9d7SSteve Wise skb_get(skb); 880cfdda9d7SSteve Wise t4_set_arp_err_handler(skb, NULL, arp_failure_discard); 881cfdda9d7SSteve Wise BUG_ON(ep->mpa_skb); 882cfdda9d7SSteve Wise ep->mpa_skb = skb; 883cfdda9d7SSteve Wise c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 884cfdda9d7SSteve Wise start_ep_timer(ep); 885a7db89ebSSteve Wise __state_set(&ep->com, MPA_REQ_SENT); 886cfdda9d7SSteve Wise ep->mpa_attr.initiator = 1; 8879c88aa00SSteve Wise ep->snd_seq += mpalen; 888cfdda9d7SSteve Wise return; 889cfdda9d7SSteve Wise } 890cfdda9d7SSteve Wise 891cfdda9d7SSteve Wise static int send_mpa_reject(struct c4iw_ep *ep, const void *pdata, u8 plen) 892cfdda9d7SSteve Wise { 893cfdda9d7SSteve Wise int mpalen, wrlen; 894cfdda9d7SSteve Wise struct fw_ofld_tx_data_wr *req; 895cfdda9d7SSteve Wise struct mpa_message *mpa; 896cfdda9d7SSteve Wise struct sk_buff *skb; 897d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params mpa_v2_params; 898cfdda9d7SSteve Wise 899cfdda9d7SSteve Wise PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen); 900cfdda9d7SSteve Wise 901cfdda9d7SSteve Wise mpalen = sizeof(*mpa) + plen; 902d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) 903d2fe99e8SKumar Sanghvi mpalen += sizeof(struct mpa_v2_conn_params); 904cfdda9d7SSteve Wise wrlen = roundup(mpalen + sizeof *req, 16); 905cfdda9d7SSteve Wise 906cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 907cfdda9d7SSteve Wise if (!skb) { 908cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __func__); 909cfdda9d7SSteve Wise return -ENOMEM; 910cfdda9d7SSteve Wise } 911cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 912cfdda9d7SSteve Wise 913cfdda9d7SSteve Wise req = (struct fw_ofld_tx_data_wr *)skb_put(skb, wrlen); 914cfdda9d7SSteve Wise memset(req, 0, wrlen); 915cfdda9d7SSteve Wise req->op_to_immdlen = cpu_to_be32( 916e2ac9628SHariprasad Shenai FW_WR_OP_V(FW_OFLD_TX_DATA_WR) | 917e2ac9628SHariprasad Shenai FW_WR_COMPL_F | 918e2ac9628SHariprasad Shenai FW_WR_IMMDLEN_V(mpalen)); 919cfdda9d7SSteve Wise req->flowid_len16 = cpu_to_be32( 920e2ac9628SHariprasad Shenai FW_WR_FLOWID_V(ep->hwtid) | 921e2ac9628SHariprasad Shenai FW_WR_LEN16_V(wrlen >> 4)); 922cfdda9d7SSteve Wise req->plen = cpu_to_be32(mpalen); 923cfdda9d7SSteve Wise req->tunnel_to_proxy = cpu_to_be32( 924e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_FLUSH_F | 925e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_SHOVE_F); 926cfdda9d7SSteve Wise 927cfdda9d7SSteve Wise mpa = (struct mpa_message *)(req + 1); 928cfdda9d7SSteve Wise memset(mpa, 0, sizeof(*mpa)); 929cfdda9d7SSteve Wise memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key)); 930cfdda9d7SSteve Wise mpa->flags = MPA_REJECT; 931fe7e0a4dSVipul Pandya mpa->revision = ep->mpa_attr.version; 932cfdda9d7SSteve Wise mpa->private_data_size = htons(plen); 933d2fe99e8SKumar Sanghvi 934d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 935d2fe99e8SKumar Sanghvi mpa->flags |= MPA_ENHANCED_RDMA_CONN; 936f747c34aSRoland Dreier mpa->private_data_size = htons(ntohs(mpa->private_data_size) + 937f747c34aSRoland Dreier sizeof (struct mpa_v2_conn_params)); 938d2fe99e8SKumar Sanghvi mpa_v2_params.ird = htons(((u16)ep->ird) | 939d2fe99e8SKumar Sanghvi (peer2peer ? MPA_V2_PEER2PEER_MODEL : 940d2fe99e8SKumar Sanghvi 0)); 941d2fe99e8SKumar Sanghvi mpa_v2_params.ord = htons(((u16)ep->ord) | (peer2peer ? 942d2fe99e8SKumar Sanghvi (p2p_type == 943d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_RDMA_WRITE ? 944d2fe99e8SKumar Sanghvi MPA_V2_RDMA_WRITE_RTR : p2p_type == 945d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_READ_REQ ? 946d2fe99e8SKumar Sanghvi MPA_V2_RDMA_READ_RTR : 0) : 0)); 947d2fe99e8SKumar Sanghvi memcpy(mpa->private_data, &mpa_v2_params, 948d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params)); 949d2fe99e8SKumar Sanghvi 950d2fe99e8SKumar Sanghvi if (ep->plen) 951d2fe99e8SKumar Sanghvi memcpy(mpa->private_data + 952d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params), pdata, plen); 953d2fe99e8SKumar Sanghvi } else 954cfdda9d7SSteve Wise if (plen) 955cfdda9d7SSteve Wise memcpy(mpa->private_data, pdata, plen); 956cfdda9d7SSteve Wise 957cfdda9d7SSteve Wise /* 958cfdda9d7SSteve Wise * Reference the mpa skb again. This ensures the data area 959cfdda9d7SSteve Wise * will remain in memory until the hw acks the tx. 960cfdda9d7SSteve Wise * Function fw4_ack() will deref it. 961cfdda9d7SSteve Wise */ 962cfdda9d7SSteve Wise skb_get(skb); 963cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 964cfdda9d7SSteve Wise t4_set_arp_err_handler(skb, NULL, arp_failure_discard); 965cfdda9d7SSteve Wise BUG_ON(ep->mpa_skb); 966cfdda9d7SSteve Wise ep->mpa_skb = skb; 9679c88aa00SSteve Wise ep->snd_seq += mpalen; 968cfdda9d7SSteve Wise return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 969cfdda9d7SSteve Wise } 970cfdda9d7SSteve Wise 971cfdda9d7SSteve Wise static int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen) 972cfdda9d7SSteve Wise { 973cfdda9d7SSteve Wise int mpalen, wrlen; 974cfdda9d7SSteve Wise struct fw_ofld_tx_data_wr *req; 975cfdda9d7SSteve Wise struct mpa_message *mpa; 976cfdda9d7SSteve Wise struct sk_buff *skb; 977d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params mpa_v2_params; 978cfdda9d7SSteve Wise 979cfdda9d7SSteve Wise PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen); 980cfdda9d7SSteve Wise 981cfdda9d7SSteve Wise mpalen = sizeof(*mpa) + plen; 982d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) 983d2fe99e8SKumar Sanghvi mpalen += sizeof(struct mpa_v2_conn_params); 984cfdda9d7SSteve Wise wrlen = roundup(mpalen + sizeof *req, 16); 985cfdda9d7SSteve Wise 986cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 987cfdda9d7SSteve Wise if (!skb) { 988cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __func__); 989cfdda9d7SSteve Wise return -ENOMEM; 990cfdda9d7SSteve Wise } 991cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 992cfdda9d7SSteve Wise 993cfdda9d7SSteve Wise req = (struct fw_ofld_tx_data_wr *) skb_put(skb, wrlen); 994cfdda9d7SSteve Wise memset(req, 0, wrlen); 995cfdda9d7SSteve Wise req->op_to_immdlen = cpu_to_be32( 996e2ac9628SHariprasad Shenai FW_WR_OP_V(FW_OFLD_TX_DATA_WR) | 997e2ac9628SHariprasad Shenai FW_WR_COMPL_F | 998e2ac9628SHariprasad Shenai FW_WR_IMMDLEN_V(mpalen)); 999cfdda9d7SSteve Wise req->flowid_len16 = cpu_to_be32( 1000e2ac9628SHariprasad Shenai FW_WR_FLOWID_V(ep->hwtid) | 1001e2ac9628SHariprasad Shenai FW_WR_LEN16_V(wrlen >> 4)); 1002cfdda9d7SSteve Wise req->plen = cpu_to_be32(mpalen); 1003cfdda9d7SSteve Wise req->tunnel_to_proxy = cpu_to_be32( 1004e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_FLUSH_F | 1005e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_SHOVE_F); 1006cfdda9d7SSteve Wise 1007cfdda9d7SSteve Wise mpa = (struct mpa_message *)(req + 1); 1008cfdda9d7SSteve Wise memset(mpa, 0, sizeof(*mpa)); 1009cfdda9d7SSteve Wise memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key)); 1010cfdda9d7SSteve Wise mpa->flags = (ep->mpa_attr.crc_enabled ? MPA_CRC : 0) | 1011cfdda9d7SSteve Wise (markers_enabled ? MPA_MARKERS : 0); 1012d2fe99e8SKumar Sanghvi mpa->revision = ep->mpa_attr.version; 1013cfdda9d7SSteve Wise mpa->private_data_size = htons(plen); 1014d2fe99e8SKumar Sanghvi 1015d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 1016d2fe99e8SKumar Sanghvi mpa->flags |= MPA_ENHANCED_RDMA_CONN; 1017f747c34aSRoland Dreier mpa->private_data_size = htons(ntohs(mpa->private_data_size) + 1018f747c34aSRoland Dreier sizeof (struct mpa_v2_conn_params)); 1019d2fe99e8SKumar Sanghvi mpa_v2_params.ird = htons((u16)ep->ird); 1020d2fe99e8SKumar Sanghvi mpa_v2_params.ord = htons((u16)ep->ord); 1021d2fe99e8SKumar Sanghvi if (peer2peer && (ep->mpa_attr.p2p_type != 1022d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_DISABLED)) { 1023d2fe99e8SKumar Sanghvi mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL); 1024d2fe99e8SKumar Sanghvi 1025d2fe99e8SKumar Sanghvi if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE) 1026d2fe99e8SKumar Sanghvi mpa_v2_params.ord |= 1027d2fe99e8SKumar Sanghvi htons(MPA_V2_RDMA_WRITE_RTR); 1028d2fe99e8SKumar Sanghvi else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) 1029d2fe99e8SKumar Sanghvi mpa_v2_params.ord |= 1030d2fe99e8SKumar Sanghvi htons(MPA_V2_RDMA_READ_RTR); 1031d2fe99e8SKumar Sanghvi } 1032d2fe99e8SKumar Sanghvi 1033d2fe99e8SKumar Sanghvi memcpy(mpa->private_data, &mpa_v2_params, 1034d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params)); 1035d2fe99e8SKumar Sanghvi 1036d2fe99e8SKumar Sanghvi if (ep->plen) 1037d2fe99e8SKumar Sanghvi memcpy(mpa->private_data + 1038d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params), pdata, plen); 1039d2fe99e8SKumar Sanghvi } else 1040cfdda9d7SSteve Wise if (plen) 1041cfdda9d7SSteve Wise memcpy(mpa->private_data, pdata, plen); 1042cfdda9d7SSteve Wise 1043cfdda9d7SSteve Wise /* 1044cfdda9d7SSteve Wise * Reference the mpa skb. This ensures the data area 1045cfdda9d7SSteve Wise * will remain in memory until the hw acks the tx. 1046cfdda9d7SSteve Wise * Function fw4_ack() will deref it. 1047cfdda9d7SSteve Wise */ 1048cfdda9d7SSteve Wise skb_get(skb); 1049cfdda9d7SSteve Wise t4_set_arp_err_handler(skb, NULL, arp_failure_discard); 1050cfdda9d7SSteve Wise ep->mpa_skb = skb; 1051a7db89ebSSteve Wise __state_set(&ep->com, MPA_REP_SENT); 10529c88aa00SSteve Wise ep->snd_seq += mpalen; 1053cfdda9d7SSteve Wise return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 1054cfdda9d7SSteve Wise } 1055cfdda9d7SSteve Wise 1056cfdda9d7SSteve Wise static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb) 1057cfdda9d7SSteve Wise { 1058cfdda9d7SSteve Wise struct c4iw_ep *ep; 1059cfdda9d7SSteve Wise struct cpl_act_establish *req = cplhdr(skb); 1060cfdda9d7SSteve Wise unsigned int tid = GET_TID(req); 10616c53e938SHariprasad Shenai unsigned int atid = TID_TID_G(ntohl(req->tos_atid)); 1062cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 1063cfdda9d7SSteve Wise 1064cfdda9d7SSteve Wise ep = lookup_atid(t, atid); 1065cfdda9d7SSteve Wise 1066cfdda9d7SSteve Wise PDBG("%s ep %p tid %u snd_isn %u rcv_isn %u\n", __func__, ep, tid, 1067cfdda9d7SSteve Wise be32_to_cpu(req->snd_isn), be32_to_cpu(req->rcv_isn)); 1068cfdda9d7SSteve Wise 1069a7db89ebSSteve Wise mutex_lock(&ep->com.mutex); 1070cfdda9d7SSteve Wise dst_confirm(ep->dst); 1071cfdda9d7SSteve Wise 1072cfdda9d7SSteve Wise /* setup the hwtid for this connection */ 1073cfdda9d7SSteve Wise ep->hwtid = tid; 1074cfdda9d7SSteve Wise cxgb4_insert_tid(t, ep, tid); 1075793dad94SVipul Pandya insert_handle(dev, &dev->hwtid_idr, ep, ep->hwtid); 1076cfdda9d7SSteve Wise 1077cfdda9d7SSteve Wise ep->snd_seq = be32_to_cpu(req->snd_isn); 1078cfdda9d7SSteve Wise ep->rcv_seq = be32_to_cpu(req->rcv_isn); 1079cfdda9d7SSteve Wise 1080cfdda9d7SSteve Wise set_emss(ep, ntohs(req->tcp_opt)); 1081cfdda9d7SSteve Wise 1082cfdda9d7SSteve Wise /* dealloc the atid */ 1083793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, atid); 1084cfdda9d7SSteve Wise cxgb4_free_atid(t, atid); 1085793dad94SVipul Pandya set_bit(ACT_ESTAB, &ep->com.history); 1086cfdda9d7SSteve Wise 1087cfdda9d7SSteve Wise /* start MPA negotiation */ 1088cfdda9d7SSteve Wise send_flowc(ep, NULL); 1089d2fe99e8SKumar Sanghvi if (ep->retry_with_mpa_v1) 1090d2fe99e8SKumar Sanghvi send_mpa_req(ep, skb, 1); 1091d2fe99e8SKumar Sanghvi else 1092d2fe99e8SKumar Sanghvi send_mpa_req(ep, skb, mpa_rev); 1093a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 1094cfdda9d7SSteve Wise return 0; 1095cfdda9d7SSteve Wise } 1096cfdda9d7SSteve Wise 1097be13b2dfSSteve Wise static void close_complete_upcall(struct c4iw_ep *ep, int status) 1098cfdda9d7SSteve Wise { 1099cfdda9d7SSteve Wise struct iw_cm_event event; 1100cfdda9d7SSteve Wise 1101cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1102cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1103cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CLOSE; 1104be13b2dfSSteve Wise event.status = status; 1105cfdda9d7SSteve Wise if (ep->com.cm_id) { 1106cfdda9d7SSteve Wise PDBG("close complete delivered ep %p cm_id %p tid %u\n", 1107cfdda9d7SSteve Wise ep, ep->com.cm_id, ep->hwtid); 1108cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 1109cfdda9d7SSteve Wise ep->com.cm_id->rem_ref(ep->com.cm_id); 1110cfdda9d7SSteve Wise ep->com.cm_id = NULL; 1111793dad94SVipul Pandya set_bit(CLOSE_UPCALL, &ep->com.history); 1112cfdda9d7SSteve Wise } 1113cfdda9d7SSteve Wise } 1114cfdda9d7SSteve Wise 1115cfdda9d7SSteve Wise static int abort_connection(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp) 1116cfdda9d7SSteve Wise { 1117cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1118cc18b939SSteve Wise __state_set(&ep->com, ABORTING); 1119793dad94SVipul Pandya set_bit(ABORT_CONN, &ep->com.history); 1120cfdda9d7SSteve Wise return send_abort(ep, skb, gfp); 1121cfdda9d7SSteve Wise } 1122cfdda9d7SSteve Wise 1123cfdda9d7SSteve Wise static void peer_close_upcall(struct c4iw_ep *ep) 1124cfdda9d7SSteve Wise { 1125cfdda9d7SSteve Wise struct iw_cm_event event; 1126cfdda9d7SSteve Wise 1127cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1128cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1129cfdda9d7SSteve Wise event.event = IW_CM_EVENT_DISCONNECT; 1130cfdda9d7SSteve Wise if (ep->com.cm_id) { 1131cfdda9d7SSteve Wise PDBG("peer close delivered ep %p cm_id %p tid %u\n", 1132cfdda9d7SSteve Wise ep, ep->com.cm_id, ep->hwtid); 1133cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 1134793dad94SVipul Pandya set_bit(DISCONN_UPCALL, &ep->com.history); 1135cfdda9d7SSteve Wise } 1136cfdda9d7SSteve Wise } 1137cfdda9d7SSteve Wise 1138cfdda9d7SSteve Wise static void peer_abort_upcall(struct c4iw_ep *ep) 1139cfdda9d7SSteve Wise { 1140cfdda9d7SSteve Wise struct iw_cm_event event; 1141cfdda9d7SSteve Wise 1142cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1143cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1144cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CLOSE; 1145cfdda9d7SSteve Wise event.status = -ECONNRESET; 1146cfdda9d7SSteve Wise if (ep->com.cm_id) { 1147cfdda9d7SSteve Wise PDBG("abort delivered ep %p cm_id %p tid %u\n", ep, 1148cfdda9d7SSteve Wise ep->com.cm_id, ep->hwtid); 1149cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 1150cfdda9d7SSteve Wise ep->com.cm_id->rem_ref(ep->com.cm_id); 1151cfdda9d7SSteve Wise ep->com.cm_id = NULL; 1152793dad94SVipul Pandya set_bit(ABORT_UPCALL, &ep->com.history); 1153cfdda9d7SSteve Wise } 1154cfdda9d7SSteve Wise } 1155cfdda9d7SSteve Wise 1156cfdda9d7SSteve Wise static void connect_reply_upcall(struct c4iw_ep *ep, int status) 1157cfdda9d7SSteve Wise { 1158cfdda9d7SSteve Wise struct iw_cm_event event; 1159cfdda9d7SSteve Wise 1160cfdda9d7SSteve Wise PDBG("%s ep %p tid %u status %d\n", __func__, ep, ep->hwtid, status); 1161cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1162cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CONNECT_REPLY; 1163cfdda9d7SSteve Wise event.status = status; 116424d44a39SSteve Wise memcpy(&event.local_addr, &ep->com.local_addr, 116524d44a39SSteve Wise sizeof(ep->com.local_addr)); 116624d44a39SSteve Wise memcpy(&event.remote_addr, &ep->com.remote_addr, 116724d44a39SSteve Wise sizeof(ep->com.remote_addr)); 1168cfdda9d7SSteve Wise 1169cfdda9d7SSteve Wise if ((status == 0) || (status == -ECONNREFUSED)) { 1170d2fe99e8SKumar Sanghvi if (!ep->tried_with_mpa_v1) { 1171d2fe99e8SKumar Sanghvi /* this means MPA_v2 is used */ 1172d2fe99e8SKumar Sanghvi event.private_data_len = ep->plen - 1173d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1174d2fe99e8SKumar Sanghvi event.private_data = ep->mpa_pkt + 1175d2fe99e8SKumar Sanghvi sizeof(struct mpa_message) + 1176d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1177d2fe99e8SKumar Sanghvi } else { 1178d2fe99e8SKumar Sanghvi /* this means MPA_v1 is used */ 1179cfdda9d7SSteve Wise event.private_data_len = ep->plen; 1180d2fe99e8SKumar Sanghvi event.private_data = ep->mpa_pkt + 1181d2fe99e8SKumar Sanghvi sizeof(struct mpa_message); 1182d2fe99e8SKumar Sanghvi } 1183cfdda9d7SSteve Wise } 118485963e4cSRoland Dreier 1185cfdda9d7SSteve Wise PDBG("%s ep %p tid %u status %d\n", __func__, ep, 1186cfdda9d7SSteve Wise ep->hwtid, status); 1187793dad94SVipul Pandya set_bit(CONN_RPL_UPCALL, &ep->com.history); 1188cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 118985963e4cSRoland Dreier 1190cfdda9d7SSteve Wise if (status < 0) { 1191cfdda9d7SSteve Wise ep->com.cm_id->rem_ref(ep->com.cm_id); 1192cfdda9d7SSteve Wise ep->com.cm_id = NULL; 1193cfdda9d7SSteve Wise } 1194cfdda9d7SSteve Wise } 1195cfdda9d7SSteve Wise 1196be13b2dfSSteve Wise static int connect_request_upcall(struct c4iw_ep *ep) 1197cfdda9d7SSteve Wise { 1198cfdda9d7SSteve Wise struct iw_cm_event event; 1199be13b2dfSSteve Wise int ret; 1200cfdda9d7SSteve Wise 1201cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1202cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1203cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CONNECT_REQUEST; 120424d44a39SSteve Wise memcpy(&event.local_addr, &ep->com.local_addr, 120524d44a39SSteve Wise sizeof(ep->com.local_addr)); 120624d44a39SSteve Wise memcpy(&event.remote_addr, &ep->com.remote_addr, 120724d44a39SSteve Wise sizeof(ep->com.remote_addr)); 1208d2fe99e8SKumar Sanghvi event.provider_data = ep; 1209d2fe99e8SKumar Sanghvi if (!ep->tried_with_mpa_v1) { 1210d2fe99e8SKumar Sanghvi /* this means MPA_v2 is used */ 1211d2fe99e8SKumar Sanghvi event.ord = ep->ord; 1212d2fe99e8SKumar Sanghvi event.ird = ep->ird; 1213d2fe99e8SKumar Sanghvi event.private_data_len = ep->plen - 1214d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1215d2fe99e8SKumar Sanghvi event.private_data = ep->mpa_pkt + sizeof(struct mpa_message) + 1216d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1217d2fe99e8SKumar Sanghvi } else { 1218d2fe99e8SKumar Sanghvi /* this means MPA_v1 is used. Send max supported */ 12194c2c5763SHariprasad Shenai event.ord = cur_max_read_depth(ep->com.dev); 12204c2c5763SHariprasad Shenai event.ird = cur_max_read_depth(ep->com.dev); 1221cfdda9d7SSteve Wise event.private_data_len = ep->plen; 1222cfdda9d7SSteve Wise event.private_data = ep->mpa_pkt + sizeof(struct mpa_message); 1223d2fe99e8SKumar Sanghvi } 1224cfdda9d7SSteve Wise c4iw_get_ep(&ep->com); 1225be13b2dfSSteve Wise ret = ep->parent_ep->com.cm_id->event_handler(ep->parent_ep->com.cm_id, 1226cfdda9d7SSteve Wise &event); 1227be13b2dfSSteve Wise if (ret) 1228be13b2dfSSteve Wise c4iw_put_ep(&ep->com); 1229793dad94SVipul Pandya set_bit(CONNREQ_UPCALL, &ep->com.history); 1230cfdda9d7SSteve Wise c4iw_put_ep(&ep->parent_ep->com); 1231be13b2dfSSteve Wise return ret; 1232cfdda9d7SSteve Wise } 1233cfdda9d7SSteve Wise 1234cfdda9d7SSteve Wise static void established_upcall(struct c4iw_ep *ep) 1235cfdda9d7SSteve Wise { 1236cfdda9d7SSteve Wise struct iw_cm_event event; 1237cfdda9d7SSteve Wise 1238cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1239cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1240cfdda9d7SSteve Wise event.event = IW_CM_EVENT_ESTABLISHED; 1241d2fe99e8SKumar Sanghvi event.ird = ep->ird; 1242d2fe99e8SKumar Sanghvi event.ord = ep->ord; 1243cfdda9d7SSteve Wise if (ep->com.cm_id) { 1244cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1245cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 1246793dad94SVipul Pandya set_bit(ESTAB_UPCALL, &ep->com.history); 1247cfdda9d7SSteve Wise } 1248cfdda9d7SSteve Wise } 1249cfdda9d7SSteve Wise 1250cfdda9d7SSteve Wise static int update_rx_credits(struct c4iw_ep *ep, u32 credits) 1251cfdda9d7SSteve Wise { 1252cfdda9d7SSteve Wise struct cpl_rx_data_ack *req; 1253cfdda9d7SSteve Wise struct sk_buff *skb; 1254cfdda9d7SSteve Wise int wrlen = roundup(sizeof *req, 16); 1255cfdda9d7SSteve Wise 1256cfdda9d7SSteve Wise PDBG("%s ep %p tid %u credits %u\n", __func__, ep, ep->hwtid, credits); 1257cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 1258cfdda9d7SSteve Wise if (!skb) { 1259cfdda9d7SSteve Wise printk(KERN_ERR MOD "update_rx_credits - cannot alloc skb!\n"); 1260cfdda9d7SSteve Wise return 0; 1261cfdda9d7SSteve Wise } 1262cfdda9d7SSteve Wise 1263b408ff28SHariprasad Shenai /* 1264b408ff28SHariprasad Shenai * If we couldn't specify the entire rcv window at connection setup 1265b408ff28SHariprasad Shenai * due to the limit in the number of bits in the RCV_BUFSIZ field, 1266b408ff28SHariprasad Shenai * then add the overage in to the credits returned. 1267b408ff28SHariprasad Shenai */ 1268d7990b0cSAnish Bhatt if (ep->rcv_win > RCV_BUFSIZ_M * 1024) 1269d7990b0cSAnish Bhatt credits += ep->rcv_win - RCV_BUFSIZ_M * 1024; 1270b408ff28SHariprasad Shenai 1271cfdda9d7SSteve Wise req = (struct cpl_rx_data_ack *) skb_put(skb, wrlen); 1272cfdda9d7SSteve Wise memset(req, 0, wrlen); 1273cfdda9d7SSteve Wise INIT_TP_WR(req, ep->hwtid); 1274cfdda9d7SSteve Wise OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_RX_DATA_ACK, 1275cfdda9d7SSteve Wise ep->hwtid)); 1276d7990b0cSAnish Bhatt req->credit_dack = cpu_to_be32(credits | RX_FORCE_ACK_F | 1277cf7fe64aSHariprasad Shenai RX_DACK_CHANGE_F | 1278cf7fe64aSHariprasad Shenai RX_DACK_MODE_V(dack_mode)); 1279d4f1a5c6SSteve Wise set_wr_txq(skb, CPL_PRIORITY_ACK, ep->ctrlq_idx); 1280cfdda9d7SSteve Wise c4iw_ofld_send(&ep->com.dev->rdev, skb); 1281cfdda9d7SSteve Wise return credits; 1282cfdda9d7SSteve Wise } 1283cfdda9d7SSteve Wise 12844c2c5763SHariprasad Shenai #define RELAXED_IRD_NEGOTIATION 1 12854c2c5763SHariprasad Shenai 1286cc18b939SSteve Wise static int process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb) 1287cfdda9d7SSteve Wise { 1288cfdda9d7SSteve Wise struct mpa_message *mpa; 1289d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params *mpa_v2_params; 1290cfdda9d7SSteve Wise u16 plen; 1291d2fe99e8SKumar Sanghvi u16 resp_ird, resp_ord; 1292d2fe99e8SKumar Sanghvi u8 rtr_mismatch = 0, insuff_ird = 0; 1293cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 1294cfdda9d7SSteve Wise enum c4iw_qp_attr_mask mask; 1295cfdda9d7SSteve Wise int err; 1296cc18b939SSteve Wise int disconnect = 0; 1297cfdda9d7SSteve Wise 1298cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1299cfdda9d7SSteve Wise 1300cfdda9d7SSteve Wise /* 1301b33bd0cbSSteve Wise * Stop mpa timer. If it expired, then 1302b33bd0cbSSteve Wise * we ignore the MPA reply. process_timeout() 1303b33bd0cbSSteve Wise * will abort the connection. 1304cfdda9d7SSteve Wise */ 1305b33bd0cbSSteve Wise if (stop_ep_timer(ep)) 1306cc18b939SSteve Wise return 0; 1307cfdda9d7SSteve Wise 1308cfdda9d7SSteve Wise /* 1309cfdda9d7SSteve Wise * If we get more than the supported amount of private data 1310cfdda9d7SSteve Wise * then we must fail this connection. 1311cfdda9d7SSteve Wise */ 1312cfdda9d7SSteve Wise if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) { 1313cfdda9d7SSteve Wise err = -EINVAL; 1314cfdda9d7SSteve Wise goto err; 1315cfdda9d7SSteve Wise } 1316cfdda9d7SSteve Wise 1317cfdda9d7SSteve Wise /* 1318cfdda9d7SSteve Wise * copy the new data into our accumulation buffer. 1319cfdda9d7SSteve Wise */ 1320cfdda9d7SSteve Wise skb_copy_from_linear_data(skb, &(ep->mpa_pkt[ep->mpa_pkt_len]), 1321cfdda9d7SSteve Wise skb->len); 1322cfdda9d7SSteve Wise ep->mpa_pkt_len += skb->len; 1323cfdda9d7SSteve Wise 1324cfdda9d7SSteve Wise /* 1325cfdda9d7SSteve Wise * if we don't even have the mpa message, then bail. 1326cfdda9d7SSteve Wise */ 1327cfdda9d7SSteve Wise if (ep->mpa_pkt_len < sizeof(*mpa)) 1328cc18b939SSteve Wise return 0; 1329cfdda9d7SSteve Wise mpa = (struct mpa_message *) ep->mpa_pkt; 1330cfdda9d7SSteve Wise 1331cfdda9d7SSteve Wise /* Validate MPA header. */ 1332d2fe99e8SKumar Sanghvi if (mpa->revision > mpa_rev) { 1333d2fe99e8SKumar Sanghvi printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d," 1334d2fe99e8SKumar Sanghvi " Received = %d\n", __func__, mpa_rev, mpa->revision); 1335cfdda9d7SSteve Wise err = -EPROTO; 1336cfdda9d7SSteve Wise goto err; 1337cfdda9d7SSteve Wise } 1338cfdda9d7SSteve Wise if (memcmp(mpa->key, MPA_KEY_REP, sizeof(mpa->key))) { 1339cfdda9d7SSteve Wise err = -EPROTO; 1340cfdda9d7SSteve Wise goto err; 1341cfdda9d7SSteve Wise } 1342cfdda9d7SSteve Wise 1343cfdda9d7SSteve Wise plen = ntohs(mpa->private_data_size); 1344cfdda9d7SSteve Wise 1345cfdda9d7SSteve Wise /* 1346cfdda9d7SSteve Wise * Fail if there's too much private data. 1347cfdda9d7SSteve Wise */ 1348cfdda9d7SSteve Wise if (plen > MPA_MAX_PRIVATE_DATA) { 1349cfdda9d7SSteve Wise err = -EPROTO; 1350cfdda9d7SSteve Wise goto err; 1351cfdda9d7SSteve Wise } 1352cfdda9d7SSteve Wise 1353cfdda9d7SSteve Wise /* 1354cfdda9d7SSteve Wise * If plen does not account for pkt size 1355cfdda9d7SSteve Wise */ 1356cfdda9d7SSteve Wise if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) { 1357cfdda9d7SSteve Wise err = -EPROTO; 1358cfdda9d7SSteve Wise goto err; 1359cfdda9d7SSteve Wise } 1360cfdda9d7SSteve Wise 1361cfdda9d7SSteve Wise ep->plen = (u8) plen; 1362cfdda9d7SSteve Wise 1363cfdda9d7SSteve Wise /* 1364cfdda9d7SSteve Wise * If we don't have all the pdata yet, then bail. 1365cfdda9d7SSteve Wise * We'll continue process when more data arrives. 1366cfdda9d7SSteve Wise */ 1367cfdda9d7SSteve Wise if (ep->mpa_pkt_len < (sizeof(*mpa) + plen)) 1368cc18b939SSteve Wise return 0; 1369cfdda9d7SSteve Wise 1370cfdda9d7SSteve Wise if (mpa->flags & MPA_REJECT) { 1371cfdda9d7SSteve Wise err = -ECONNREFUSED; 1372cfdda9d7SSteve Wise goto err; 1373cfdda9d7SSteve Wise } 1374cfdda9d7SSteve Wise 1375cfdda9d7SSteve Wise /* 1376cfdda9d7SSteve Wise * If we get here we have accumulated the entire mpa 1377cfdda9d7SSteve Wise * start reply message including private data. And 1378cfdda9d7SSteve Wise * the MPA header is valid. 1379cfdda9d7SSteve Wise */ 1380c529fb50SSteve Wise __state_set(&ep->com, FPDU_MODE); 1381cfdda9d7SSteve Wise ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0; 1382cfdda9d7SSteve Wise ep->mpa_attr.recv_marker_enabled = markers_enabled; 1383cfdda9d7SSteve Wise ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0; 1384d2fe99e8SKumar Sanghvi ep->mpa_attr.version = mpa->revision; 1385d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED; 1386d2fe99e8SKumar Sanghvi 1387d2fe99e8SKumar Sanghvi if (mpa->revision == 2) { 1388d2fe99e8SKumar Sanghvi ep->mpa_attr.enhanced_rdma_conn = 1389d2fe99e8SKumar Sanghvi mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0; 1390d2fe99e8SKumar Sanghvi if (ep->mpa_attr.enhanced_rdma_conn) { 1391d2fe99e8SKumar Sanghvi mpa_v2_params = (struct mpa_v2_conn_params *) 1392d2fe99e8SKumar Sanghvi (ep->mpa_pkt + sizeof(*mpa)); 1393d2fe99e8SKumar Sanghvi resp_ird = ntohs(mpa_v2_params->ird) & 1394d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 1395d2fe99e8SKumar Sanghvi resp_ord = ntohs(mpa_v2_params->ord) & 1396d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 13974c2c5763SHariprasad Shenai PDBG("%s responder ird %u ord %u ep ird %u ord %u\n", 13984c2c5763SHariprasad Shenai __func__, resp_ird, resp_ord, ep->ird, ep->ord); 1399d2fe99e8SKumar Sanghvi 1400d2fe99e8SKumar Sanghvi /* 1401d2fe99e8SKumar Sanghvi * This is a double-check. Ideally, below checks are 1402d2fe99e8SKumar Sanghvi * not required since ird/ord stuff has been taken 1403d2fe99e8SKumar Sanghvi * care of in c4iw_accept_cr 1404d2fe99e8SKumar Sanghvi */ 14054c2c5763SHariprasad Shenai if (ep->ird < resp_ord) { 14064c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION && resp_ord <= 14074c2c5763SHariprasad Shenai ep->com.dev->rdev.lldi.max_ordird_qp) 14084c2c5763SHariprasad Shenai ep->ird = resp_ord; 14094c2c5763SHariprasad Shenai else 14104c2c5763SHariprasad Shenai insuff_ird = 1; 14114c2c5763SHariprasad Shenai } else if (ep->ird > resp_ord) { 14124c2c5763SHariprasad Shenai ep->ird = resp_ord; 14134c2c5763SHariprasad Shenai } 14144c2c5763SHariprasad Shenai if (ep->ord > resp_ird) { 14154c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION) 14164c2c5763SHariprasad Shenai ep->ord = resp_ird; 14174c2c5763SHariprasad Shenai else 14184c2c5763SHariprasad Shenai insuff_ird = 1; 14194c2c5763SHariprasad Shenai } 14204c2c5763SHariprasad Shenai if (insuff_ird) { 1421d2fe99e8SKumar Sanghvi err = -ENOMEM; 1422d2fe99e8SKumar Sanghvi ep->ird = resp_ord; 1423d2fe99e8SKumar Sanghvi ep->ord = resp_ird; 1424d2fe99e8SKumar Sanghvi } 1425d2fe99e8SKumar Sanghvi 1426d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ird) & 1427d2fe99e8SKumar Sanghvi MPA_V2_PEER2PEER_MODEL) { 1428d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ord) & 1429d2fe99e8SKumar Sanghvi MPA_V2_RDMA_WRITE_RTR) 1430d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1431d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_RDMA_WRITE; 1432d2fe99e8SKumar Sanghvi else if (ntohs(mpa_v2_params->ord) & 1433d2fe99e8SKumar Sanghvi MPA_V2_RDMA_READ_RTR) 1434d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1435d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_READ_REQ; 1436d2fe99e8SKumar Sanghvi } 1437d2fe99e8SKumar Sanghvi } 1438d2fe99e8SKumar Sanghvi } else if (mpa->revision == 1) 1439d2fe99e8SKumar Sanghvi if (peer2peer) 1440d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = p2p_type; 1441d2fe99e8SKumar Sanghvi 1442cfdda9d7SSteve Wise PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, " 1443d2fe99e8SKumar Sanghvi "xmit_marker_enabled=%d, version=%d p2p_type=%d local-p2p_type = " 1444d2fe99e8SKumar Sanghvi "%d\n", __func__, ep->mpa_attr.crc_enabled, 1445d2fe99e8SKumar Sanghvi ep->mpa_attr.recv_marker_enabled, 1446d2fe99e8SKumar Sanghvi ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version, 1447d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type, p2p_type); 1448d2fe99e8SKumar Sanghvi 1449d2fe99e8SKumar Sanghvi /* 1450d2fe99e8SKumar Sanghvi * If responder's RTR does not match with that of initiator, assign 1451d2fe99e8SKumar Sanghvi * FW_RI_INIT_P2PTYPE_DISABLED in mpa attributes so that RTR is not 1452d2fe99e8SKumar Sanghvi * generated when moving QP to RTS state. 1453d2fe99e8SKumar Sanghvi * A TERM message will be sent after QP has moved to RTS state 1454d2fe99e8SKumar Sanghvi */ 145591018f86SKumar Sanghvi if ((ep->mpa_attr.version == 2) && peer2peer && 1456d2fe99e8SKumar Sanghvi (ep->mpa_attr.p2p_type != p2p_type)) { 1457d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED; 1458d2fe99e8SKumar Sanghvi rtr_mismatch = 1; 1459d2fe99e8SKumar Sanghvi } 1460cfdda9d7SSteve Wise 1461cfdda9d7SSteve Wise attrs.mpa_attr = ep->mpa_attr; 1462cfdda9d7SSteve Wise attrs.max_ird = ep->ird; 1463cfdda9d7SSteve Wise attrs.max_ord = ep->ord; 1464cfdda9d7SSteve Wise attrs.llp_stream_handle = ep; 1465cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_RTS; 1466cfdda9d7SSteve Wise 1467cfdda9d7SSteve Wise mask = C4IW_QP_ATTR_NEXT_STATE | 1468cfdda9d7SSteve Wise C4IW_QP_ATTR_LLP_STREAM_HANDLE | C4IW_QP_ATTR_MPA_ATTR | 1469cfdda9d7SSteve Wise C4IW_QP_ATTR_MAX_IRD | C4IW_QP_ATTR_MAX_ORD; 1470cfdda9d7SSteve Wise 1471cfdda9d7SSteve Wise /* bind QP and TID with INIT_WR */ 1472cfdda9d7SSteve Wise err = c4iw_modify_qp(ep->com.qp->rhp, 1473cfdda9d7SSteve Wise ep->com.qp, mask, &attrs, 1); 1474cfdda9d7SSteve Wise if (err) 1475cfdda9d7SSteve Wise goto err; 1476d2fe99e8SKumar Sanghvi 1477d2fe99e8SKumar Sanghvi /* 1478d2fe99e8SKumar Sanghvi * If responder's RTR requirement did not match with what initiator 1479d2fe99e8SKumar Sanghvi * supports, generate TERM message 1480d2fe99e8SKumar Sanghvi */ 1481d2fe99e8SKumar Sanghvi if (rtr_mismatch) { 1482d2fe99e8SKumar Sanghvi printk(KERN_ERR "%s: RTR mismatch, sending TERM\n", __func__); 1483d2fe99e8SKumar Sanghvi attrs.layer_etype = LAYER_MPA | DDP_LLP; 1484d2fe99e8SKumar Sanghvi attrs.ecode = MPA_NOMATCH_RTR; 1485d2fe99e8SKumar Sanghvi attrs.next_state = C4IW_QP_STATE_TERMINATE; 1486cc18b939SSteve Wise attrs.send_term = 1; 1487d2fe99e8SKumar Sanghvi err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 1488cc18b939SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 1489d2fe99e8SKumar Sanghvi err = -ENOMEM; 1490cc18b939SSteve Wise disconnect = 1; 1491d2fe99e8SKumar Sanghvi goto out; 1492d2fe99e8SKumar Sanghvi } 1493d2fe99e8SKumar Sanghvi 1494d2fe99e8SKumar Sanghvi /* 1495d2fe99e8SKumar Sanghvi * Generate TERM if initiator IRD is not sufficient for responder 1496d2fe99e8SKumar Sanghvi * provided ORD. Currently, we do the same behaviour even when 1497d2fe99e8SKumar Sanghvi * responder provided IRD is also not sufficient as regards to 1498d2fe99e8SKumar Sanghvi * initiator ORD. 1499d2fe99e8SKumar Sanghvi */ 1500d2fe99e8SKumar Sanghvi if (insuff_ird) { 1501d2fe99e8SKumar Sanghvi printk(KERN_ERR "%s: Insufficient IRD, sending TERM\n", 1502d2fe99e8SKumar Sanghvi __func__); 1503d2fe99e8SKumar Sanghvi attrs.layer_etype = LAYER_MPA | DDP_LLP; 1504d2fe99e8SKumar Sanghvi attrs.ecode = MPA_INSUFF_IRD; 1505d2fe99e8SKumar Sanghvi attrs.next_state = C4IW_QP_STATE_TERMINATE; 1506cc18b939SSteve Wise attrs.send_term = 1; 1507d2fe99e8SKumar Sanghvi err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 1508cc18b939SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 1509d2fe99e8SKumar Sanghvi err = -ENOMEM; 1510cc18b939SSteve Wise disconnect = 1; 1511d2fe99e8SKumar Sanghvi goto out; 1512d2fe99e8SKumar Sanghvi } 1513cfdda9d7SSteve Wise goto out; 1514cfdda9d7SSteve Wise err: 1515c529fb50SSteve Wise __state_set(&ep->com, ABORTING); 1516b21ef16aSSteve Wise send_abort(ep, skb, GFP_KERNEL); 1517cfdda9d7SSteve Wise out: 1518cfdda9d7SSteve Wise connect_reply_upcall(ep, err); 1519cc18b939SSteve Wise return disconnect; 1520cfdda9d7SSteve Wise } 1521cfdda9d7SSteve Wise 1522cfdda9d7SSteve Wise static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb) 1523cfdda9d7SSteve Wise { 1524cfdda9d7SSteve Wise struct mpa_message *mpa; 1525d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params *mpa_v2_params; 1526cfdda9d7SSteve Wise u16 plen; 1527cfdda9d7SSteve Wise 1528cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1529cfdda9d7SSteve Wise 1530cfdda9d7SSteve Wise /* 1531cfdda9d7SSteve Wise * If we get more than the supported amount of private data 1532cfdda9d7SSteve Wise * then we must fail this connection. 1533cfdda9d7SSteve Wise */ 1534cfdda9d7SSteve Wise if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) { 1535b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 1536cfdda9d7SSteve Wise abort_connection(ep, skb, GFP_KERNEL); 1537cfdda9d7SSteve Wise return; 1538cfdda9d7SSteve Wise } 1539cfdda9d7SSteve Wise 1540cfdda9d7SSteve Wise PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__); 1541cfdda9d7SSteve Wise 1542cfdda9d7SSteve Wise /* 1543cfdda9d7SSteve Wise * Copy the new data into our accumulation buffer. 1544cfdda9d7SSteve Wise */ 1545cfdda9d7SSteve Wise skb_copy_from_linear_data(skb, &(ep->mpa_pkt[ep->mpa_pkt_len]), 1546cfdda9d7SSteve Wise skb->len); 1547cfdda9d7SSteve Wise ep->mpa_pkt_len += skb->len; 1548cfdda9d7SSteve Wise 1549cfdda9d7SSteve Wise /* 1550cfdda9d7SSteve Wise * If we don't even have the mpa message, then bail. 1551cfdda9d7SSteve Wise * We'll continue process when more data arrives. 1552cfdda9d7SSteve Wise */ 1553cfdda9d7SSteve Wise if (ep->mpa_pkt_len < sizeof(*mpa)) 1554cfdda9d7SSteve Wise return; 1555cfdda9d7SSteve Wise 1556cfdda9d7SSteve Wise PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__); 1557cfdda9d7SSteve Wise mpa = (struct mpa_message *) ep->mpa_pkt; 1558cfdda9d7SSteve Wise 1559cfdda9d7SSteve Wise /* 1560cfdda9d7SSteve Wise * Validate MPA Header. 1561cfdda9d7SSteve Wise */ 1562d2fe99e8SKumar Sanghvi if (mpa->revision > mpa_rev) { 1563d2fe99e8SKumar Sanghvi printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d," 1564d2fe99e8SKumar Sanghvi " Received = %d\n", __func__, mpa_rev, mpa->revision); 1565b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 1566cfdda9d7SSteve Wise abort_connection(ep, skb, GFP_KERNEL); 1567cfdda9d7SSteve Wise return; 1568cfdda9d7SSteve Wise } 1569cfdda9d7SSteve Wise 1570cfdda9d7SSteve Wise if (memcmp(mpa->key, MPA_KEY_REQ, sizeof(mpa->key))) { 1571b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 1572cfdda9d7SSteve Wise abort_connection(ep, skb, GFP_KERNEL); 1573cfdda9d7SSteve Wise return; 1574cfdda9d7SSteve Wise } 1575cfdda9d7SSteve Wise 1576cfdda9d7SSteve Wise plen = ntohs(mpa->private_data_size); 1577cfdda9d7SSteve Wise 1578cfdda9d7SSteve Wise /* 1579cfdda9d7SSteve Wise * Fail if there's too much private data. 1580cfdda9d7SSteve Wise */ 1581cfdda9d7SSteve Wise if (plen > MPA_MAX_PRIVATE_DATA) { 1582b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 1583cfdda9d7SSteve Wise abort_connection(ep, skb, GFP_KERNEL); 1584cfdda9d7SSteve Wise return; 1585cfdda9d7SSteve Wise } 1586cfdda9d7SSteve Wise 1587cfdda9d7SSteve Wise /* 1588cfdda9d7SSteve Wise * If plen does not account for pkt size 1589cfdda9d7SSteve Wise */ 1590cfdda9d7SSteve Wise if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) { 1591b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 1592cfdda9d7SSteve Wise abort_connection(ep, skb, GFP_KERNEL); 1593cfdda9d7SSteve Wise return; 1594cfdda9d7SSteve Wise } 1595cfdda9d7SSteve Wise ep->plen = (u8) plen; 1596cfdda9d7SSteve Wise 1597cfdda9d7SSteve Wise /* 1598cfdda9d7SSteve Wise * If we don't have all the pdata yet, then bail. 1599cfdda9d7SSteve Wise */ 1600cfdda9d7SSteve Wise if (ep->mpa_pkt_len < (sizeof(*mpa) + plen)) 1601cfdda9d7SSteve Wise return; 1602cfdda9d7SSteve Wise 1603cfdda9d7SSteve Wise /* 1604cfdda9d7SSteve Wise * If we get here we have accumulated the entire mpa 1605cfdda9d7SSteve Wise * start reply message including private data. 1606cfdda9d7SSteve Wise */ 1607cfdda9d7SSteve Wise ep->mpa_attr.initiator = 0; 1608cfdda9d7SSteve Wise ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0; 1609cfdda9d7SSteve Wise ep->mpa_attr.recv_marker_enabled = markers_enabled; 1610cfdda9d7SSteve Wise ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0; 1611d2fe99e8SKumar Sanghvi ep->mpa_attr.version = mpa->revision; 1612d2fe99e8SKumar Sanghvi if (mpa->revision == 1) 1613d2fe99e8SKumar Sanghvi ep->tried_with_mpa_v1 = 1; 1614d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED; 1615d2fe99e8SKumar Sanghvi 1616d2fe99e8SKumar Sanghvi if (mpa->revision == 2) { 1617d2fe99e8SKumar Sanghvi ep->mpa_attr.enhanced_rdma_conn = 1618d2fe99e8SKumar Sanghvi mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0; 1619d2fe99e8SKumar Sanghvi if (ep->mpa_attr.enhanced_rdma_conn) { 1620d2fe99e8SKumar Sanghvi mpa_v2_params = (struct mpa_v2_conn_params *) 1621d2fe99e8SKumar Sanghvi (ep->mpa_pkt + sizeof(*mpa)); 1622d2fe99e8SKumar Sanghvi ep->ird = ntohs(mpa_v2_params->ird) & 1623d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 1624d2fe99e8SKumar Sanghvi ep->ord = ntohs(mpa_v2_params->ord) & 1625d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 16264c2c5763SHariprasad Shenai PDBG("%s initiator ird %u ord %u\n", __func__, ep->ird, 16274c2c5763SHariprasad Shenai ep->ord); 1628d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ird) & MPA_V2_PEER2PEER_MODEL) 1629d2fe99e8SKumar Sanghvi if (peer2peer) { 1630d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ord) & 1631d2fe99e8SKumar Sanghvi MPA_V2_RDMA_WRITE_RTR) 1632d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1633d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_RDMA_WRITE; 1634d2fe99e8SKumar Sanghvi else if (ntohs(mpa_v2_params->ord) & 1635d2fe99e8SKumar Sanghvi MPA_V2_RDMA_READ_RTR) 1636d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1637d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_READ_REQ; 1638d2fe99e8SKumar Sanghvi } 1639d2fe99e8SKumar Sanghvi } 1640d2fe99e8SKumar Sanghvi } else if (mpa->revision == 1) 1641d2fe99e8SKumar Sanghvi if (peer2peer) 1642d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = p2p_type; 1643d2fe99e8SKumar Sanghvi 1644cfdda9d7SSteve Wise PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, " 1645cfdda9d7SSteve Wise "xmit_marker_enabled=%d, version=%d p2p_type=%d\n", __func__, 1646cfdda9d7SSteve Wise ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled, 1647cfdda9d7SSteve Wise ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version, 1648cfdda9d7SSteve Wise ep->mpa_attr.p2p_type); 1649cfdda9d7SSteve Wise 1650b33bd0cbSSteve Wise /* 1651b33bd0cbSSteve Wise * If the endpoint timer already expired, then we ignore 1652b33bd0cbSSteve Wise * the start request. process_timeout() will abort 1653b33bd0cbSSteve Wise * the connection. 1654b33bd0cbSSteve Wise */ 1655b33bd0cbSSteve Wise if (!stop_ep_timer(ep)) { 1656c529fb50SSteve Wise __state_set(&ep->com, MPA_REQ_RCVD); 1657cfdda9d7SSteve Wise 1658cfdda9d7SSteve Wise /* drive upcall */ 165910be6b48SHariprasad Shenai mutex_lock_nested(&ep->parent_ep->com.mutex, 166010be6b48SHariprasad Shenai SINGLE_DEPTH_NESTING); 1661be13b2dfSSteve Wise if (ep->parent_ep->com.state != DEAD) { 1662be13b2dfSSteve Wise if (connect_request_upcall(ep)) 1663be13b2dfSSteve Wise abort_connection(ep, skb, GFP_KERNEL); 1664be13b2dfSSteve Wise } else { 1665be13b2dfSSteve Wise abort_connection(ep, skb, GFP_KERNEL); 1666be13b2dfSSteve Wise } 1667be13b2dfSSteve Wise mutex_unlock(&ep->parent_ep->com.mutex); 1668b33bd0cbSSteve Wise } 1669cfdda9d7SSteve Wise return; 1670cfdda9d7SSteve Wise } 1671cfdda9d7SSteve Wise 1672cfdda9d7SSteve Wise static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb) 1673cfdda9d7SSteve Wise { 1674cfdda9d7SSteve Wise struct c4iw_ep *ep; 1675cfdda9d7SSteve Wise struct cpl_rx_data *hdr = cplhdr(skb); 1676cfdda9d7SSteve Wise unsigned int dlen = ntohs(hdr->len); 1677cfdda9d7SSteve Wise unsigned int tid = GET_TID(hdr); 1678cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 1679793dad94SVipul Pandya __u8 status = hdr->status; 1680cc18b939SSteve Wise int disconnect = 0; 1681cfdda9d7SSteve Wise 1682cfdda9d7SSteve Wise ep = lookup_tid(t, tid); 1683977116c6SSteve Wise if (!ep) 1684977116c6SSteve Wise return 0; 1685cfdda9d7SSteve Wise PDBG("%s ep %p tid %u dlen %u\n", __func__, ep, ep->hwtid, dlen); 1686cfdda9d7SSteve Wise skb_pull(skb, sizeof(*hdr)); 1687cfdda9d7SSteve Wise skb_trim(skb, dlen); 1688c529fb50SSteve Wise mutex_lock(&ep->com.mutex); 1689cfdda9d7SSteve Wise 1690cfdda9d7SSteve Wise /* update RX credits */ 1691cfdda9d7SSteve Wise update_rx_credits(ep, dlen); 1692cfdda9d7SSteve Wise 1693c529fb50SSteve Wise switch (ep->com.state) { 1694cfdda9d7SSteve Wise case MPA_REQ_SENT: 169555abf8dfSVipul Pandya ep->rcv_seq += dlen; 1696cc18b939SSteve Wise disconnect = process_mpa_reply(ep, skb); 1697cfdda9d7SSteve Wise break; 1698cfdda9d7SSteve Wise case MPA_REQ_WAIT: 169955abf8dfSVipul Pandya ep->rcv_seq += dlen; 1700cfdda9d7SSteve Wise process_mpa_request(ep, skb); 1701cfdda9d7SSteve Wise break; 17021557967bSVipul Pandya case FPDU_MODE: { 17031557967bSVipul Pandya struct c4iw_qp_attributes attrs; 17041557967bSVipul Pandya BUG_ON(!ep->com.qp); 1705e8e5b927SVipul Pandya if (status) 1706793dad94SVipul Pandya pr_err("%s Unexpected streaming data." \ 170704236df2SVipul Pandya " qpid %u ep %p state %d tid %u status %d\n", 170804236df2SVipul Pandya __func__, ep->com.qp->wq.sq.qid, ep, 1709c529fb50SSteve Wise ep->com.state, ep->hwtid, status); 171097d7ec0cSSteve Wise attrs.next_state = C4IW_QP_STATE_TERMINATE; 171155abf8dfSVipul Pandya c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 1712cc18b939SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 1713cc18b939SSteve Wise disconnect = 1; 1714cfdda9d7SSteve Wise break; 1715cfdda9d7SSteve Wise } 17161557967bSVipul Pandya default: 17171557967bSVipul Pandya break; 17181557967bSVipul Pandya } 1719c529fb50SSteve Wise mutex_unlock(&ep->com.mutex); 1720cc18b939SSteve Wise if (disconnect) 1721cc18b939SSteve Wise c4iw_ep_disconnect(ep, 0, GFP_KERNEL); 1722cfdda9d7SSteve Wise return 0; 1723cfdda9d7SSteve Wise } 1724cfdda9d7SSteve Wise 1725cfdda9d7SSteve Wise static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 1726cfdda9d7SSteve Wise { 1727cfdda9d7SSteve Wise struct c4iw_ep *ep; 1728cfdda9d7SSteve Wise struct cpl_abort_rpl_rss *rpl = cplhdr(skb); 1729cfdda9d7SSteve Wise int release = 0; 1730cfdda9d7SSteve Wise unsigned int tid = GET_TID(rpl); 1731cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 1732cfdda9d7SSteve Wise 1733cfdda9d7SSteve Wise ep = lookup_tid(t, tid); 17344984037bSVipul Pandya if (!ep) { 17354984037bSVipul Pandya printk(KERN_WARNING MOD "Abort rpl to freed endpoint\n"); 17364984037bSVipul Pandya return 0; 17374984037bSVipul Pandya } 173892dd6c3dSWei Yongjun PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 17392f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 1740cfdda9d7SSteve Wise switch (ep->com.state) { 1741cfdda9d7SSteve Wise case ABORTING: 174291e9c071SVipul Pandya c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 1743cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 1744cfdda9d7SSteve Wise release = 1; 1745cfdda9d7SSteve Wise break; 1746cfdda9d7SSteve Wise default: 1747cfdda9d7SSteve Wise printk(KERN_ERR "%s ep %p state %d\n", 1748cfdda9d7SSteve Wise __func__, ep, ep->com.state); 1749cfdda9d7SSteve Wise break; 1750cfdda9d7SSteve Wise } 17512f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 1752cfdda9d7SSteve Wise 1753cfdda9d7SSteve Wise if (release) 1754cfdda9d7SSteve Wise release_ep_resources(ep); 1755cfdda9d7SSteve Wise return 0; 1756cfdda9d7SSteve Wise } 1757cfdda9d7SSteve Wise 17585be78ee9SVipul Pandya static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid) 17595be78ee9SVipul Pandya { 17605be78ee9SVipul Pandya struct sk_buff *skb; 17615be78ee9SVipul Pandya struct fw_ofld_connection_wr *req; 17625be78ee9SVipul Pandya unsigned int mtu_idx; 17635be78ee9SVipul Pandya int wscale; 1764830662f6SVipul Pandya struct sockaddr_in *sin; 1765b408ff28SHariprasad Shenai int win; 17665be78ee9SVipul Pandya 17675be78ee9SVipul Pandya skb = get_skb(NULL, sizeof(*req), GFP_KERNEL); 17685be78ee9SVipul Pandya req = (struct fw_ofld_connection_wr *)__skb_put(skb, sizeof(*req)); 17695be78ee9SVipul Pandya memset(req, 0, sizeof(*req)); 17706c53e938SHariprasad Shenai req->op_compl = htonl(WR_OP_V(FW_OFLD_CONNECTION_WR)); 1771e2ac9628SHariprasad Shenai req->len16_pkd = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*req), 16))); 177241b4f86cSKumar Sanghvi req->le.filter = cpu_to_be32(cxgb4_select_ntuple( 177341b4f86cSKumar Sanghvi ep->com.dev->rdev.lldi.ports[0], 17745be78ee9SVipul Pandya ep->l2t)); 17759eccfe10SSteve Wise sin = (struct sockaddr_in *)&ep->com.mapped_local_addr; 1776830662f6SVipul Pandya req->le.lport = sin->sin_port; 1777830662f6SVipul Pandya req->le.u.ipv4.lip = sin->sin_addr.s_addr; 17789eccfe10SSteve Wise sin = (struct sockaddr_in *)&ep->com.mapped_remote_addr; 1779830662f6SVipul Pandya req->le.pport = sin->sin_port; 1780830662f6SVipul Pandya req->le.u.ipv4.pip = sin->sin_addr.s_addr; 17815be78ee9SVipul Pandya req->tcb.t_state_to_astid = 178277a80e23SHariprasad Shenai htonl(FW_OFLD_CONNECTION_WR_T_STATE_V(TCP_SYN_SENT) | 178377a80e23SHariprasad Shenai FW_OFLD_CONNECTION_WR_ASTID_V(atid)); 17845be78ee9SVipul Pandya req->tcb.cplrxdataack_cplpassacceptrpl = 178577a80e23SHariprasad Shenai htons(FW_OFLD_CONNECTION_WR_CPLRXDATAACK_F); 1786ef5d6355SVipul Pandya req->tcb.tx_max = (__force __be32) jiffies; 1787793dad94SVipul Pandya req->tcb.rcv_adv = htons(1); 178892e7ae71SHariprasad Shenai best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, 178904524a47SHariprasad S enable_tcp_timestamps, 179004524a47SHariprasad S (AF_INET == ep->com.remote_addr.ss_family) ? 0 : 1); 17915be78ee9SVipul Pandya wscale = compute_wscale(rcv_win); 1792b408ff28SHariprasad Shenai 1793b408ff28SHariprasad Shenai /* 1794b408ff28SHariprasad Shenai * Specify the largest window that will fit in opt0. The 1795b408ff28SHariprasad Shenai * remainder will be specified in the rx_data_ack. 1796b408ff28SHariprasad Shenai */ 1797b408ff28SHariprasad Shenai win = ep->rcv_win >> 10; 1798d7990b0cSAnish Bhatt if (win > RCV_BUFSIZ_M) 1799d7990b0cSAnish Bhatt win = RCV_BUFSIZ_M; 1800b408ff28SHariprasad Shenai 18016c53e938SHariprasad Shenai req->tcb.opt0 = (__force __be64) (TCAM_BYPASS_F | 18026c53e938SHariprasad Shenai (nocong ? NO_CONG_F : 0) | 1803d7990b0cSAnish Bhatt KEEP_ALIVE_F | 18046c53e938SHariprasad Shenai DELACK_F | 1805d7990b0cSAnish Bhatt WND_SCALE_V(wscale) | 1806d7990b0cSAnish Bhatt MSS_IDX_V(mtu_idx) | 1807d7990b0cSAnish Bhatt L2T_IDX_V(ep->l2t->idx) | 1808d7990b0cSAnish Bhatt TX_CHAN_V(ep->tx_chan) | 1809d7990b0cSAnish Bhatt SMAC_SEL_V(ep->smac_idx) | 18106c53e938SHariprasad Shenai DSCP_V(ep->tos) | 1811d7990b0cSAnish Bhatt ULP_MODE_V(ULP_MODE_TCPDDP) | 1812d7990b0cSAnish Bhatt RCV_BUFSIZ_V(win)); 18136c53e938SHariprasad Shenai req->tcb.opt2 = (__force __be32) (PACE_V(1) | 18146c53e938SHariprasad Shenai TX_QUEUE_V(ep->com.dev->rdev.lldi.tx_modq[ep->tx_chan]) | 1815d7990b0cSAnish Bhatt RX_CHANNEL_V(0) | 18166c53e938SHariprasad Shenai CCTRL_ECN_V(enable_ecn) | 1817d7990b0cSAnish Bhatt RSS_QUEUE_VALID_F | RSS_QUEUE_V(ep->rss_qid)); 18185be78ee9SVipul Pandya if (enable_tcp_timestamps) 18196c53e938SHariprasad Shenai req->tcb.opt2 |= (__force __be32)TSTAMPS_EN_F; 18205be78ee9SVipul Pandya if (enable_tcp_sack) 18216c53e938SHariprasad Shenai req->tcb.opt2 |= (__force __be32)SACK_EN_F; 18225be78ee9SVipul Pandya if (wscale && enable_tcp_window_scaling) 1823d7990b0cSAnish Bhatt req->tcb.opt2 |= (__force __be32)WND_SCALE_EN_F; 1824ef5d6355SVipul Pandya req->tcb.opt0 = cpu_to_be64((__force u64)req->tcb.opt0); 1825ef5d6355SVipul Pandya req->tcb.opt2 = cpu_to_be32((__force u32)req->tcb.opt2); 1826793dad94SVipul Pandya set_wr_txq(skb, CPL_PRIORITY_CONTROL, ep->ctrlq_idx); 1827793dad94SVipul Pandya set_bit(ACT_OFLD_CONN, &ep->com.history); 18285be78ee9SVipul Pandya c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 18295be78ee9SVipul Pandya } 18305be78ee9SVipul Pandya 1831cfdda9d7SSteve Wise /* 1832cfdda9d7SSteve Wise * Return whether a failed active open has allocated a TID 1833cfdda9d7SSteve Wise */ 1834cfdda9d7SSteve Wise static inline int act_open_has_tid(int status) 1835cfdda9d7SSteve Wise { 1836cfdda9d7SSteve Wise return status != CPL_ERR_TCAM_FULL && status != CPL_ERR_CONN_EXIST && 1837cfdda9d7SSteve Wise status != CPL_ERR_ARP_MISS; 1838cfdda9d7SSteve Wise } 1839cfdda9d7SSteve Wise 18407a2cea2aSSteve Wise /* Returns whether a CPL status conveys negative advice. 18417a2cea2aSSteve Wise */ 18427a2cea2aSSteve Wise static int is_neg_adv(unsigned int status) 18437a2cea2aSSteve Wise { 18447a2cea2aSSteve Wise return status == CPL_ERR_RTX_NEG_ADVICE || 18457a2cea2aSSteve Wise status == CPL_ERR_PERSIST_NEG_ADVICE || 18467a2cea2aSSteve Wise status == CPL_ERR_KEEPALV_NEG_ADVICE; 18477a2cea2aSSteve Wise } 18487a2cea2aSSteve Wise 1849dd92b124SHariprasad Shenai static char *neg_adv_str(unsigned int status) 1850dd92b124SHariprasad Shenai { 1851dd92b124SHariprasad Shenai switch (status) { 1852dd92b124SHariprasad Shenai case CPL_ERR_RTX_NEG_ADVICE: 1853dd92b124SHariprasad Shenai return "Retransmit timeout"; 1854dd92b124SHariprasad Shenai case CPL_ERR_PERSIST_NEG_ADVICE: 1855dd92b124SHariprasad Shenai return "Persist timeout"; 1856dd92b124SHariprasad Shenai case CPL_ERR_KEEPALV_NEG_ADVICE: 1857dd92b124SHariprasad Shenai return "Keepalive timeout"; 1858dd92b124SHariprasad Shenai default: 1859dd92b124SHariprasad Shenai return "Unknown"; 1860dd92b124SHariprasad Shenai } 1861dd92b124SHariprasad Shenai } 1862dd92b124SHariprasad Shenai 1863b408ff28SHariprasad Shenai static void set_tcp_window(struct c4iw_ep *ep, struct port_info *pi) 1864b408ff28SHariprasad Shenai { 1865b408ff28SHariprasad Shenai ep->snd_win = snd_win; 1866b408ff28SHariprasad Shenai ep->rcv_win = rcv_win; 1867b408ff28SHariprasad Shenai PDBG("%s snd_win %d rcv_win %d\n", __func__, ep->snd_win, ep->rcv_win); 1868b408ff28SHariprasad Shenai } 1869b408ff28SHariprasad Shenai 1870793dad94SVipul Pandya #define ACT_OPEN_RETRY_COUNT 2 1871793dad94SVipul Pandya 1872830662f6SVipul Pandya static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, 1873830662f6SVipul Pandya struct dst_entry *dst, struct c4iw_dev *cdev, 1874830662f6SVipul Pandya bool clear_mpa_v1) 1875830662f6SVipul Pandya { 1876830662f6SVipul Pandya struct neighbour *n; 1877830662f6SVipul Pandya int err, step; 1878830662f6SVipul Pandya struct net_device *pdev; 1879830662f6SVipul Pandya 1880830662f6SVipul Pandya n = dst_neigh_lookup(dst, peer_ip); 1881830662f6SVipul Pandya if (!n) 1882830662f6SVipul Pandya return -ENODEV; 1883830662f6SVipul Pandya 1884830662f6SVipul Pandya rcu_read_lock(); 1885830662f6SVipul Pandya err = -ENOMEM; 1886830662f6SVipul Pandya if (n->dev->flags & IFF_LOOPBACK) { 1887830662f6SVipul Pandya if (iptype == 4) 1888830662f6SVipul Pandya pdev = ip_dev_find(&init_net, *(__be32 *)peer_ip); 1889830662f6SVipul Pandya else if (IS_ENABLED(CONFIG_IPV6)) 1890830662f6SVipul Pandya for_each_netdev(&init_net, pdev) { 1891830662f6SVipul Pandya if (ipv6_chk_addr(&init_net, 1892830662f6SVipul Pandya (struct in6_addr *)peer_ip, 1893830662f6SVipul Pandya pdev, 1)) 1894830662f6SVipul Pandya break; 1895830662f6SVipul Pandya } 1896830662f6SVipul Pandya else 1897830662f6SVipul Pandya pdev = NULL; 1898830662f6SVipul Pandya 1899830662f6SVipul Pandya if (!pdev) { 1900830662f6SVipul Pandya err = -ENODEV; 1901830662f6SVipul Pandya goto out; 1902830662f6SVipul Pandya } 1903830662f6SVipul Pandya ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, 1904830662f6SVipul Pandya n, pdev, 0); 1905830662f6SVipul Pandya if (!ep->l2t) 1906830662f6SVipul Pandya goto out; 1907830662f6SVipul Pandya ep->mtu = pdev->mtu; 1908830662f6SVipul Pandya ep->tx_chan = cxgb4_port_chan(pdev); 1909830662f6SVipul Pandya ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1; 1910830662f6SVipul Pandya step = cdev->rdev.lldi.ntxq / 1911830662f6SVipul Pandya cdev->rdev.lldi.nchan; 1912830662f6SVipul Pandya ep->txq_idx = cxgb4_port_idx(pdev) * step; 1913830662f6SVipul Pandya step = cdev->rdev.lldi.nrxq / 1914830662f6SVipul Pandya cdev->rdev.lldi.nchan; 1915830662f6SVipul Pandya ep->ctrlq_idx = cxgb4_port_idx(pdev); 1916830662f6SVipul Pandya ep->rss_qid = cdev->rdev.lldi.rxq_ids[ 1917830662f6SVipul Pandya cxgb4_port_idx(pdev) * step]; 1918b408ff28SHariprasad Shenai set_tcp_window(ep, (struct port_info *)netdev_priv(pdev)); 1919830662f6SVipul Pandya dev_put(pdev); 1920830662f6SVipul Pandya } else { 1921830662f6SVipul Pandya pdev = get_real_dev(n->dev); 1922830662f6SVipul Pandya ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, 1923830662f6SVipul Pandya n, pdev, 0); 1924830662f6SVipul Pandya if (!ep->l2t) 1925830662f6SVipul Pandya goto out; 1926830662f6SVipul Pandya ep->mtu = dst_mtu(dst); 192711b8e22dSSteve Wise ep->tx_chan = cxgb4_port_chan(pdev); 192811b8e22dSSteve Wise ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1; 1929830662f6SVipul Pandya step = cdev->rdev.lldi.ntxq / 1930830662f6SVipul Pandya cdev->rdev.lldi.nchan; 193111b8e22dSSteve Wise ep->txq_idx = cxgb4_port_idx(pdev) * step; 193211b8e22dSSteve Wise ep->ctrlq_idx = cxgb4_port_idx(pdev); 1933830662f6SVipul Pandya step = cdev->rdev.lldi.nrxq / 1934830662f6SVipul Pandya cdev->rdev.lldi.nchan; 1935830662f6SVipul Pandya ep->rss_qid = cdev->rdev.lldi.rxq_ids[ 193611b8e22dSSteve Wise cxgb4_port_idx(pdev) * step]; 1937b408ff28SHariprasad Shenai set_tcp_window(ep, (struct port_info *)netdev_priv(pdev)); 1938830662f6SVipul Pandya 1939830662f6SVipul Pandya if (clear_mpa_v1) { 1940830662f6SVipul Pandya ep->retry_with_mpa_v1 = 0; 1941830662f6SVipul Pandya ep->tried_with_mpa_v1 = 0; 1942830662f6SVipul Pandya } 1943830662f6SVipul Pandya } 1944830662f6SVipul Pandya err = 0; 1945830662f6SVipul Pandya out: 1946830662f6SVipul Pandya rcu_read_unlock(); 1947830662f6SVipul Pandya 1948830662f6SVipul Pandya neigh_release(n); 1949830662f6SVipul Pandya 1950830662f6SVipul Pandya return err; 1951830662f6SVipul Pandya } 1952830662f6SVipul Pandya 1953793dad94SVipul Pandya static int c4iw_reconnect(struct c4iw_ep *ep) 1954793dad94SVipul Pandya { 1955793dad94SVipul Pandya int err = 0; 195624d44a39SSteve Wise struct sockaddr_in *laddr = (struct sockaddr_in *) 195724d44a39SSteve Wise &ep->com.cm_id->local_addr; 195824d44a39SSteve Wise struct sockaddr_in *raddr = (struct sockaddr_in *) 195924d44a39SSteve Wise &ep->com.cm_id->remote_addr; 1960830662f6SVipul Pandya struct sockaddr_in6 *laddr6 = (struct sockaddr_in6 *) 1961830662f6SVipul Pandya &ep->com.cm_id->local_addr; 1962830662f6SVipul Pandya struct sockaddr_in6 *raddr6 = (struct sockaddr_in6 *) 1963830662f6SVipul Pandya &ep->com.cm_id->remote_addr; 1964830662f6SVipul Pandya int iptype; 1965830662f6SVipul Pandya __u8 *ra; 1966793dad94SVipul Pandya 1967793dad94SVipul Pandya PDBG("%s qp %p cm_id %p\n", __func__, ep->com.qp, ep->com.cm_id); 1968793dad94SVipul Pandya init_timer(&ep->timer); 1969793dad94SVipul Pandya 1970793dad94SVipul Pandya /* 1971793dad94SVipul Pandya * Allocate an active TID to initiate a TCP connection. 1972793dad94SVipul Pandya */ 1973793dad94SVipul Pandya ep->atid = cxgb4_alloc_atid(ep->com.dev->rdev.lldi.tids, ep); 1974793dad94SVipul Pandya if (ep->atid == -1) { 1975793dad94SVipul Pandya pr_err("%s - cannot alloc atid.\n", __func__); 1976793dad94SVipul Pandya err = -ENOMEM; 1977793dad94SVipul Pandya goto fail2; 1978793dad94SVipul Pandya } 1979793dad94SVipul Pandya insert_handle(ep->com.dev, &ep->com.dev->atid_idr, ep, ep->atid); 1980793dad94SVipul Pandya 1981793dad94SVipul Pandya /* find a route */ 1982830662f6SVipul Pandya if (ep->com.cm_id->local_addr.ss_family == AF_INET) { 1983830662f6SVipul Pandya ep->dst = find_route(ep->com.dev, laddr->sin_addr.s_addr, 1984830662f6SVipul Pandya raddr->sin_addr.s_addr, laddr->sin_port, 1985830662f6SVipul Pandya raddr->sin_port, 0); 1986830662f6SVipul Pandya iptype = 4; 1987830662f6SVipul Pandya ra = (__u8 *)&raddr->sin_addr; 1988830662f6SVipul Pandya } else { 1989830662f6SVipul Pandya ep->dst = find_route6(ep->com.dev, laddr6->sin6_addr.s6_addr, 1990830662f6SVipul Pandya raddr6->sin6_addr.s6_addr, 1991830662f6SVipul Pandya laddr6->sin6_port, raddr6->sin6_port, 0, 1992830662f6SVipul Pandya raddr6->sin6_scope_id); 1993830662f6SVipul Pandya iptype = 6; 1994830662f6SVipul Pandya ra = (__u8 *)&raddr6->sin6_addr; 1995830662f6SVipul Pandya } 1996830662f6SVipul Pandya if (!ep->dst) { 1997793dad94SVipul Pandya pr_err("%s - cannot find route.\n", __func__); 1998793dad94SVipul Pandya err = -EHOSTUNREACH; 1999793dad94SVipul Pandya goto fail3; 2000793dad94SVipul Pandya } 2001830662f6SVipul Pandya err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, false); 2002830662f6SVipul Pandya if (err) { 2003793dad94SVipul Pandya pr_err("%s - cannot alloc l2e.\n", __func__); 2004793dad94SVipul Pandya goto fail4; 2005793dad94SVipul Pandya } 2006793dad94SVipul Pandya 2007793dad94SVipul Pandya PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n", 2008793dad94SVipul Pandya __func__, ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid, 2009793dad94SVipul Pandya ep->l2t->idx); 2010793dad94SVipul Pandya 2011793dad94SVipul Pandya state_set(&ep->com, CONNECTING); 2012793dad94SVipul Pandya ep->tos = 0; 2013793dad94SVipul Pandya 2014793dad94SVipul Pandya /* send connect request to rnic */ 2015793dad94SVipul Pandya err = send_connect(ep); 2016793dad94SVipul Pandya if (!err) 2017793dad94SVipul Pandya goto out; 2018793dad94SVipul Pandya 2019793dad94SVipul Pandya cxgb4_l2t_release(ep->l2t); 2020793dad94SVipul Pandya fail4: 2021793dad94SVipul Pandya dst_release(ep->dst); 2022793dad94SVipul Pandya fail3: 2023793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid); 2024793dad94SVipul Pandya cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid); 2025793dad94SVipul Pandya fail2: 2026793dad94SVipul Pandya /* 2027793dad94SVipul Pandya * remember to send notification to upper layer. 2028793dad94SVipul Pandya * We are in here so the upper layer is not aware that this is 2029793dad94SVipul Pandya * re-connect attempt and so, upper layer is still waiting for 2030793dad94SVipul Pandya * response of 1st connect request. 2031793dad94SVipul Pandya */ 2032793dad94SVipul Pandya connect_reply_upcall(ep, -ECONNRESET); 2033793dad94SVipul Pandya c4iw_put_ep(&ep->com); 2034793dad94SVipul Pandya out: 2035793dad94SVipul Pandya return err; 2036793dad94SVipul Pandya } 2037793dad94SVipul Pandya 2038cfdda9d7SSteve Wise static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2039cfdda9d7SSteve Wise { 2040cfdda9d7SSteve Wise struct c4iw_ep *ep; 2041cfdda9d7SSteve Wise struct cpl_act_open_rpl *rpl = cplhdr(skb); 20426c53e938SHariprasad Shenai unsigned int atid = TID_TID_G(AOPEN_ATID_G( 2043cfdda9d7SSteve Wise ntohl(rpl->atid_status))); 2044cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 20456c53e938SHariprasad Shenai int status = AOPEN_STATUS_G(ntohl(rpl->atid_status)); 2046830662f6SVipul Pandya struct sockaddr_in *la; 2047830662f6SVipul Pandya struct sockaddr_in *ra; 2048830662f6SVipul Pandya struct sockaddr_in6 *la6; 2049830662f6SVipul Pandya struct sockaddr_in6 *ra6; 2050cfdda9d7SSteve Wise 2051cfdda9d7SSteve Wise ep = lookup_atid(t, atid); 20529eccfe10SSteve Wise la = (struct sockaddr_in *)&ep->com.mapped_local_addr; 20539eccfe10SSteve Wise ra = (struct sockaddr_in *)&ep->com.mapped_remote_addr; 20549eccfe10SSteve Wise la6 = (struct sockaddr_in6 *)&ep->com.mapped_local_addr; 20559eccfe10SSteve Wise ra6 = (struct sockaddr_in6 *)&ep->com.mapped_remote_addr; 2056cfdda9d7SSteve Wise 2057cfdda9d7SSteve Wise PDBG("%s ep %p atid %u status %u errno %d\n", __func__, ep, atid, 2058cfdda9d7SSteve Wise status, status2errno(status)); 2059cfdda9d7SSteve Wise 20607a2cea2aSSteve Wise if (is_neg_adv(status)) { 2061dd92b124SHariprasad Shenai dev_warn(&dev->rdev.lldi.pdev->dev, 2062dd92b124SHariprasad Shenai "Connection problems for atid %u status %u (%s)\n", 2063dd92b124SHariprasad Shenai atid, status, neg_adv_str(status)); 2064cfdda9d7SSteve Wise return 0; 2065cfdda9d7SSteve Wise } 2066cfdda9d7SSteve Wise 2067793dad94SVipul Pandya set_bit(ACT_OPEN_RPL, &ep->com.history); 2068793dad94SVipul Pandya 2069d716a2a0SVipul Pandya /* 2070d716a2a0SVipul Pandya * Log interesting failures. 2071d716a2a0SVipul Pandya */ 2072d716a2a0SVipul Pandya switch (status) { 2073d716a2a0SVipul Pandya case CPL_ERR_CONN_RESET: 2074d716a2a0SVipul Pandya case CPL_ERR_CONN_TIMEDOUT: 2075d716a2a0SVipul Pandya break; 20765be78ee9SVipul Pandya case CPL_ERR_TCAM_FULL: 20775be78ee9SVipul Pandya mutex_lock(&dev->rdev.stats.lock); 2078830662f6SVipul Pandya dev->rdev.stats.tcam_full++; 20795be78ee9SVipul Pandya mutex_unlock(&dev->rdev.stats.lock); 2080830662f6SVipul Pandya if (ep->com.local_addr.ss_family == AF_INET && 2081830662f6SVipul Pandya dev->rdev.lldi.enable_fw_ofld_conn) { 20825be78ee9SVipul Pandya send_fw_act_open_req(ep, 20836c53e938SHariprasad Shenai TID_TID_G(AOPEN_ATID_G( 2084793dad94SVipul Pandya ntohl(rpl->atid_status)))); 20855be78ee9SVipul Pandya return 0; 2086793dad94SVipul Pandya } 2087793dad94SVipul Pandya break; 2088793dad94SVipul Pandya case CPL_ERR_CONN_EXIST: 2089793dad94SVipul Pandya if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) { 2090793dad94SVipul Pandya set_bit(ACT_RETRY_INUSE, &ep->com.history); 2091793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, 2092793dad94SVipul Pandya atid); 2093793dad94SVipul Pandya cxgb4_free_atid(t, atid); 2094793dad94SVipul Pandya dst_release(ep->dst); 2095793dad94SVipul Pandya cxgb4_l2t_release(ep->l2t); 2096793dad94SVipul Pandya c4iw_reconnect(ep); 2097793dad94SVipul Pandya return 0; 2098793dad94SVipul Pandya } 20995be78ee9SVipul Pandya break; 2100d716a2a0SVipul Pandya default: 2101830662f6SVipul Pandya if (ep->com.local_addr.ss_family == AF_INET) { 2102830662f6SVipul Pandya pr_info("Active open failure - atid %u status %u errno %d %pI4:%u->%pI4:%u\n", 2103d716a2a0SVipul Pandya atid, status, status2errno(status), 2104830662f6SVipul Pandya &la->sin_addr.s_addr, ntohs(la->sin_port), 2105830662f6SVipul Pandya &ra->sin_addr.s_addr, ntohs(ra->sin_port)); 2106830662f6SVipul Pandya } else { 2107830662f6SVipul Pandya pr_info("Active open failure - atid %u status %u errno %d %pI6:%u->%pI6:%u\n", 2108830662f6SVipul Pandya atid, status, status2errno(status), 2109830662f6SVipul Pandya la6->sin6_addr.s6_addr, ntohs(la6->sin6_port), 2110830662f6SVipul Pandya ra6->sin6_addr.s6_addr, ntohs(ra6->sin6_port)); 2111830662f6SVipul Pandya } 2112d716a2a0SVipul Pandya break; 2113d716a2a0SVipul Pandya } 2114d716a2a0SVipul Pandya 2115cfdda9d7SSteve Wise connect_reply_upcall(ep, status2errno(status)); 2116cfdda9d7SSteve Wise state_set(&ep->com, DEAD); 2117cfdda9d7SSteve Wise 2118cfdda9d7SSteve Wise if (status && act_open_has_tid(status)) 2119cfdda9d7SSteve Wise cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, GET_TID(rpl)); 2120cfdda9d7SSteve Wise 2121793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, atid); 2122cfdda9d7SSteve Wise cxgb4_free_atid(t, atid); 2123cfdda9d7SSteve Wise dst_release(ep->dst); 2124cfdda9d7SSteve Wise cxgb4_l2t_release(ep->l2t); 2125cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 2126cfdda9d7SSteve Wise 2127cfdda9d7SSteve Wise return 0; 2128cfdda9d7SSteve Wise } 2129cfdda9d7SSteve Wise 2130cfdda9d7SSteve Wise static int pass_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2131cfdda9d7SSteve Wise { 2132cfdda9d7SSteve Wise struct cpl_pass_open_rpl *rpl = cplhdr(skb); 2133cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 2134cfdda9d7SSteve Wise unsigned int stid = GET_TID(rpl); 2135cfdda9d7SSteve Wise struct c4iw_listen_ep *ep = lookup_stid(t, stid); 2136cfdda9d7SSteve Wise 2137cfdda9d7SSteve Wise if (!ep) { 21381cab775cSVipul Pandya PDBG("%s stid %d lookup failure!\n", __func__, stid); 21391cab775cSVipul Pandya goto out; 2140cfdda9d7SSteve Wise } 2141cfdda9d7SSteve Wise PDBG("%s ep %p status %d error %d\n", __func__, ep, 2142cfdda9d7SSteve Wise rpl->status, status2errno(rpl->status)); 2143d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, status2errno(rpl->status)); 2144cfdda9d7SSteve Wise 21451cab775cSVipul Pandya out: 2146cfdda9d7SSteve Wise return 0; 2147cfdda9d7SSteve Wise } 2148cfdda9d7SSteve Wise 2149cfdda9d7SSteve Wise static int close_listsrv_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2150cfdda9d7SSteve Wise { 2151cfdda9d7SSteve Wise struct cpl_close_listsvr_rpl *rpl = cplhdr(skb); 2152cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 2153cfdda9d7SSteve Wise unsigned int stid = GET_TID(rpl); 2154cfdda9d7SSteve Wise struct c4iw_listen_ep *ep = lookup_stid(t, stid); 2155cfdda9d7SSteve Wise 2156cfdda9d7SSteve Wise PDBG("%s ep %p\n", __func__, ep); 2157d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, status2errno(rpl->status)); 2158cfdda9d7SSteve Wise return 0; 2159cfdda9d7SSteve Wise } 2160cfdda9d7SSteve Wise 2161830662f6SVipul Pandya static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb, 2162cfdda9d7SSteve Wise struct cpl_pass_accept_req *req) 2163cfdda9d7SSteve Wise { 2164cfdda9d7SSteve Wise struct cpl_pass_accept_rpl *rpl; 2165cfdda9d7SSteve Wise unsigned int mtu_idx; 2166cfdda9d7SSteve Wise u64 opt0; 2167cfdda9d7SSteve Wise u32 opt2; 2168cfdda9d7SSteve Wise int wscale; 216992e7ae71SHariprasad Shenai struct cpl_t5_pass_accept_rpl *rpl5 = NULL; 2170b408ff28SHariprasad Shenai int win; 2171cfdda9d7SSteve Wise 2172cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2173cfdda9d7SSteve Wise BUG_ON(skb_cloned(skb)); 217492e7ae71SHariprasad Shenai 2175cfdda9d7SSteve Wise skb_get(skb); 217692e7ae71SHariprasad Shenai rpl = cplhdr(skb); 217792e7ae71SHariprasad Shenai if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) { 217892e7ae71SHariprasad Shenai skb_trim(skb, roundup(sizeof(*rpl5), 16)); 217992e7ae71SHariprasad Shenai rpl5 = (void *)rpl; 218092e7ae71SHariprasad Shenai INIT_TP_WR(rpl5, ep->hwtid); 218192e7ae71SHariprasad Shenai } else { 218292e7ae71SHariprasad Shenai skb_trim(skb, sizeof(*rpl)); 218392e7ae71SHariprasad Shenai INIT_TP_WR(rpl, ep->hwtid); 218492e7ae71SHariprasad Shenai } 218592e7ae71SHariprasad Shenai OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_PASS_ACCEPT_RPL, 218692e7ae71SHariprasad Shenai ep->hwtid)); 218792e7ae71SHariprasad Shenai 218892e7ae71SHariprasad Shenai best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, 218904524a47SHariprasad S enable_tcp_timestamps && req->tcpopt.tstamp, 219004524a47SHariprasad S (AF_INET == ep->com.remote_addr.ss_family) ? 0 : 1); 2191cfdda9d7SSteve Wise wscale = compute_wscale(rcv_win); 2192b408ff28SHariprasad Shenai 2193b408ff28SHariprasad Shenai /* 2194b408ff28SHariprasad Shenai * Specify the largest window that will fit in opt0. The 2195b408ff28SHariprasad Shenai * remainder will be specified in the rx_data_ack. 2196b408ff28SHariprasad Shenai */ 2197b408ff28SHariprasad Shenai win = ep->rcv_win >> 10; 2198d7990b0cSAnish Bhatt if (win > RCV_BUFSIZ_M) 2199d7990b0cSAnish Bhatt win = RCV_BUFSIZ_M; 22006c53e938SHariprasad Shenai opt0 = (nocong ? NO_CONG_F : 0) | 2201d7990b0cSAnish Bhatt KEEP_ALIVE_F | 22026c53e938SHariprasad Shenai DELACK_F | 2203d7990b0cSAnish Bhatt WND_SCALE_V(wscale) | 2204d7990b0cSAnish Bhatt MSS_IDX_V(mtu_idx) | 2205d7990b0cSAnish Bhatt L2T_IDX_V(ep->l2t->idx) | 2206d7990b0cSAnish Bhatt TX_CHAN_V(ep->tx_chan) | 2207d7990b0cSAnish Bhatt SMAC_SEL_V(ep->smac_idx) | 22086c53e938SHariprasad Shenai DSCP_V(ep->tos >> 2) | 2209d7990b0cSAnish Bhatt ULP_MODE_V(ULP_MODE_TCPDDP) | 2210d7990b0cSAnish Bhatt RCV_BUFSIZ_V(win); 2211d7990b0cSAnish Bhatt opt2 = RX_CHANNEL_V(0) | 2212d7990b0cSAnish Bhatt RSS_QUEUE_VALID_F | RSS_QUEUE_V(ep->rss_qid); 2213cfdda9d7SSteve Wise 2214cfdda9d7SSteve Wise if (enable_tcp_timestamps && req->tcpopt.tstamp) 22156c53e938SHariprasad Shenai opt2 |= TSTAMPS_EN_F; 2216cfdda9d7SSteve Wise if (enable_tcp_sack && req->tcpopt.sack) 22176c53e938SHariprasad Shenai opt2 |= SACK_EN_F; 2218cfdda9d7SSteve Wise if (wscale && enable_tcp_window_scaling) 2219d7990b0cSAnish Bhatt opt2 |= WND_SCALE_EN_F; 22205be78ee9SVipul Pandya if (enable_ecn) { 22215be78ee9SVipul Pandya const struct tcphdr *tcph; 22225be78ee9SVipul Pandya u32 hlen = ntohl(req->hdr_len); 22235be78ee9SVipul Pandya 2224cf7fe64aSHariprasad Shenai tcph = (const void *)(req + 1) + ETH_HDR_LEN_G(hlen) + 2225cf7fe64aSHariprasad Shenai IP_HDR_LEN_G(hlen); 22265be78ee9SVipul Pandya if (tcph->ece && tcph->cwr) 22276c53e938SHariprasad Shenai opt2 |= CCTRL_ECN_V(1); 22285be78ee9SVipul Pandya } 222992e5011aSSteve Wise if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) { 223092e7ae71SHariprasad Shenai u32 isn = (prandom_u32() & ~7UL) - 1; 2231d7990b0cSAnish Bhatt opt2 |= T5_OPT_2_VALID_F; 2232cf7fe64aSHariprasad Shenai opt2 |= CONG_CNTRL_V(CONG_ALG_TAHOE); 22330b741047SHariprasad S opt2 |= T5_ISS_F; 223492e7ae71SHariprasad Shenai rpl5 = (void *)rpl; 223592e7ae71SHariprasad Shenai memset(&rpl5->iss, 0, roundup(sizeof(*rpl5)-sizeof(*rpl), 16)); 223692e7ae71SHariprasad Shenai if (peer2peer) 223792e7ae71SHariprasad Shenai isn += 4; 223892e7ae71SHariprasad Shenai rpl5->iss = cpu_to_be32(isn); 223992e7ae71SHariprasad Shenai PDBG("%s iss %u\n", __func__, be32_to_cpu(rpl5->iss)); 224092e5011aSSteve Wise } 2241cfdda9d7SSteve Wise 2242cfdda9d7SSteve Wise rpl->opt0 = cpu_to_be64(opt0); 2243cfdda9d7SSteve Wise rpl->opt2 = cpu_to_be32(opt2); 2244d4f1a5c6SSteve Wise set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->ctrlq_idx); 2245b38a0ad8SSteve Wise t4_set_arp_err_handler(skb, NULL, arp_failure_discard); 2246cfdda9d7SSteve Wise c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 2247cfdda9d7SSteve Wise 2248cfdda9d7SSteve Wise return; 2249cfdda9d7SSteve Wise } 2250cfdda9d7SSteve Wise 2251830662f6SVipul Pandya static void reject_cr(struct c4iw_dev *dev, u32 hwtid, struct sk_buff *skb) 2252cfdda9d7SSteve Wise { 2253830662f6SVipul Pandya PDBG("%s c4iw_dev %p tid %u\n", __func__, dev, hwtid); 2254cfdda9d7SSteve Wise BUG_ON(skb_cloned(skb)); 2255cfdda9d7SSteve Wise skb_trim(skb, sizeof(struct cpl_tid_release)); 2256cfdda9d7SSteve Wise release_tid(&dev->rdev, hwtid, skb); 2257cfdda9d7SSteve Wise return; 2258cfdda9d7SSteve Wise } 2259cfdda9d7SSteve Wise 2260830662f6SVipul Pandya static void get_4tuple(struct cpl_pass_accept_req *req, int *iptype, 2261830662f6SVipul Pandya __u8 *local_ip, __u8 *peer_ip, 2262cfdda9d7SSteve Wise __be16 *local_port, __be16 *peer_port) 2263cfdda9d7SSteve Wise { 2264cf7fe64aSHariprasad Shenai int eth_len = ETH_HDR_LEN_G(be32_to_cpu(req->hdr_len)); 2265cf7fe64aSHariprasad Shenai int ip_len = IP_HDR_LEN_G(be32_to_cpu(req->hdr_len)); 2266cfdda9d7SSteve Wise struct iphdr *ip = (struct iphdr *)((u8 *)(req + 1) + eth_len); 2267830662f6SVipul Pandya struct ipv6hdr *ip6 = (struct ipv6hdr *)((u8 *)(req + 1) + eth_len); 2268cfdda9d7SSteve Wise struct tcphdr *tcp = (struct tcphdr *) 2269cfdda9d7SSteve Wise ((u8 *)(req + 1) + eth_len + ip_len); 2270cfdda9d7SSteve Wise 2271830662f6SVipul Pandya if (ip->version == 4) { 2272cfdda9d7SSteve Wise PDBG("%s saddr 0x%x daddr 0x%x sport %u dport %u\n", __func__, 2273cfdda9d7SSteve Wise ntohl(ip->saddr), ntohl(ip->daddr), ntohs(tcp->source), 2274cfdda9d7SSteve Wise ntohs(tcp->dest)); 2275830662f6SVipul Pandya *iptype = 4; 2276830662f6SVipul Pandya memcpy(peer_ip, &ip->saddr, 4); 2277830662f6SVipul Pandya memcpy(local_ip, &ip->daddr, 4); 2278830662f6SVipul Pandya } else { 2279830662f6SVipul Pandya PDBG("%s saddr %pI6 daddr %pI6 sport %u dport %u\n", __func__, 2280830662f6SVipul Pandya ip6->saddr.s6_addr, ip6->daddr.s6_addr, ntohs(tcp->source), 2281830662f6SVipul Pandya ntohs(tcp->dest)); 2282830662f6SVipul Pandya *iptype = 6; 2283830662f6SVipul Pandya memcpy(peer_ip, ip6->saddr.s6_addr, 16); 2284830662f6SVipul Pandya memcpy(local_ip, ip6->daddr.s6_addr, 16); 2285830662f6SVipul Pandya } 2286cfdda9d7SSteve Wise *peer_port = tcp->source; 2287cfdda9d7SSteve Wise *local_port = tcp->dest; 2288cfdda9d7SSteve Wise 2289cfdda9d7SSteve Wise return; 2290cfdda9d7SSteve Wise } 2291cfdda9d7SSteve Wise 2292cfdda9d7SSteve Wise static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) 2293cfdda9d7SSteve Wise { 2294793dad94SVipul Pandya struct c4iw_ep *child_ep = NULL, *parent_ep; 2295cfdda9d7SSteve Wise struct cpl_pass_accept_req *req = cplhdr(skb); 22966c53e938SHariprasad Shenai unsigned int stid = PASS_OPEN_TID_G(ntohl(req->tos_stid)); 2297cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 2298cfdda9d7SSteve Wise unsigned int hwtid = GET_TID(req); 2299cfdda9d7SSteve Wise struct dst_entry *dst; 2300830662f6SVipul Pandya __u8 local_ip[16], peer_ip[16]; 2301cfdda9d7SSteve Wise __be16 local_port, peer_port; 23023786cf18SDavid Miller int err; 23031cab775cSVipul Pandya u16 peer_mss = ntohs(req->tcpopt.mss); 2304830662f6SVipul Pandya int iptype; 230592e7ae71SHariprasad Shenai unsigned short hdrs; 2306cfdda9d7SSteve Wise 2307cfdda9d7SSteve Wise parent_ep = lookup_stid(t, stid); 23081cab775cSVipul Pandya if (!parent_ep) { 23091cab775cSVipul Pandya PDBG("%s connect request on invalid stid %d\n", __func__, stid); 23101cab775cSVipul Pandya goto reject; 23111cab775cSVipul Pandya } 23121cab775cSVipul Pandya 2313cfdda9d7SSteve Wise if (state_read(&parent_ep->com) != LISTEN) { 2314cfdda9d7SSteve Wise printk(KERN_ERR "%s - listening ep not in LISTEN\n", 2315cfdda9d7SSteve Wise __func__); 2316cfdda9d7SSteve Wise goto reject; 2317cfdda9d7SSteve Wise } 2318cfdda9d7SSteve Wise 2319830662f6SVipul Pandya get_4tuple(req, &iptype, local_ip, peer_ip, &local_port, &peer_port); 2320830662f6SVipul Pandya 2321cfdda9d7SSteve Wise /* Find output route */ 2322830662f6SVipul Pandya if (iptype == 4) { 2323830662f6SVipul Pandya PDBG("%s parent ep %p hwtid %u laddr %pI4 raddr %pI4 lport %d rport %d peer_mss %d\n" 2324830662f6SVipul Pandya , __func__, parent_ep, hwtid, 2325830662f6SVipul Pandya local_ip, peer_ip, ntohs(local_port), 2326830662f6SVipul Pandya ntohs(peer_port), peer_mss); 2327830662f6SVipul Pandya dst = find_route(dev, *(__be32 *)local_ip, *(__be32 *)peer_ip, 2328830662f6SVipul Pandya local_port, peer_port, 23296c53e938SHariprasad Shenai PASS_OPEN_TOS_G(ntohl(req->tos_stid))); 2330830662f6SVipul Pandya } else { 2331830662f6SVipul Pandya PDBG("%s parent ep %p hwtid %u laddr %pI6 raddr %pI6 lport %d rport %d peer_mss %d\n" 2332830662f6SVipul Pandya , __func__, parent_ep, hwtid, 2333830662f6SVipul Pandya local_ip, peer_ip, ntohs(local_port), 2334830662f6SVipul Pandya ntohs(peer_port), peer_mss); 2335830662f6SVipul Pandya dst = find_route6(dev, local_ip, peer_ip, local_port, peer_port, 23366c53e938SHariprasad Shenai PASS_OPEN_TOS_G(ntohl(req->tos_stid)), 2337830662f6SVipul Pandya ((struct sockaddr_in6 *) 2338830662f6SVipul Pandya &parent_ep->com.local_addr)->sin6_scope_id); 2339830662f6SVipul Pandya } 2340830662f6SVipul Pandya if (!dst) { 2341cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - failed to find dst entry!\n", 2342cfdda9d7SSteve Wise __func__); 2343cfdda9d7SSteve Wise goto reject; 2344cfdda9d7SSteve Wise } 2345cfdda9d7SSteve Wise 2346cfdda9d7SSteve Wise child_ep = alloc_ep(sizeof(*child_ep), GFP_KERNEL); 2347cfdda9d7SSteve Wise if (!child_ep) { 2348cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - failed to allocate ep entry!\n", 2349cfdda9d7SSteve Wise __func__); 2350cfdda9d7SSteve Wise dst_release(dst); 2351cfdda9d7SSteve Wise goto reject; 2352cfdda9d7SSteve Wise } 23533786cf18SDavid Miller 2354830662f6SVipul Pandya err = import_ep(child_ep, iptype, peer_ip, dst, dev, false); 23553786cf18SDavid Miller if (err) { 23563786cf18SDavid Miller printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n", 23573786cf18SDavid Miller __func__); 23583786cf18SDavid Miller dst_release(dst); 23593786cf18SDavid Miller kfree(child_ep); 23603786cf18SDavid Miller goto reject; 23613786cf18SDavid Miller } 23623786cf18SDavid Miller 236392e7ae71SHariprasad Shenai hdrs = sizeof(struct iphdr) + sizeof(struct tcphdr) + 236492e7ae71SHariprasad Shenai ((enable_tcp_timestamps && req->tcpopt.tstamp) ? 12 : 0); 236592e7ae71SHariprasad Shenai if (peer_mss && child_ep->mtu > (peer_mss + hdrs)) 236692e7ae71SHariprasad Shenai child_ep->mtu = peer_mss + hdrs; 23671cab775cSVipul Pandya 2368cfdda9d7SSteve Wise state_set(&child_ep->com, CONNECTING); 2369cfdda9d7SSteve Wise child_ep->com.dev = dev; 2370cfdda9d7SSteve Wise child_ep->com.cm_id = NULL; 23715b6b8fe6SSteve Wise 23725b6b8fe6SSteve Wise /* 23735b6b8fe6SSteve Wise * The mapped_local and mapped_remote addresses get setup with 23745b6b8fe6SSteve Wise * the actual 4-tuple. The local address will be based on the 23755b6b8fe6SSteve Wise * actual local address of the connection, but on the port number 23765b6b8fe6SSteve Wise * of the parent listening endpoint. The remote address is 23775b6b8fe6SSteve Wise * setup based on a query to the IWPM since we don't know what it 23785b6b8fe6SSteve Wise * originally was before mapping. If no mapping was done, then 23795b6b8fe6SSteve Wise * mapped_remote == remote, and mapped_local == local. 23805b6b8fe6SSteve Wise */ 2381830662f6SVipul Pandya if (iptype == 4) { 2382830662f6SVipul Pandya struct sockaddr_in *sin = (struct sockaddr_in *) 23835b6b8fe6SSteve Wise &child_ep->com.mapped_local_addr; 23845b6b8fe6SSteve Wise 2385830662f6SVipul Pandya sin->sin_family = PF_INET; 2386830662f6SVipul Pandya sin->sin_port = local_port; 2387830662f6SVipul Pandya sin->sin_addr.s_addr = *(__be32 *)local_ip; 23885b6b8fe6SSteve Wise 23895b6b8fe6SSteve Wise sin = (struct sockaddr_in *)&child_ep->com.local_addr; 23905b6b8fe6SSteve Wise sin->sin_family = PF_INET; 23915b6b8fe6SSteve Wise sin->sin_port = ((struct sockaddr_in *) 23925b6b8fe6SSteve Wise &parent_ep->com.local_addr)->sin_port; 23935b6b8fe6SSteve Wise sin->sin_addr.s_addr = *(__be32 *)local_ip; 23945b6b8fe6SSteve Wise 23955b6b8fe6SSteve Wise sin = (struct sockaddr_in *)&child_ep->com.mapped_remote_addr; 2396830662f6SVipul Pandya sin->sin_family = PF_INET; 2397830662f6SVipul Pandya sin->sin_port = peer_port; 2398830662f6SVipul Pandya sin->sin_addr.s_addr = *(__be32 *)peer_ip; 2399830662f6SVipul Pandya } else { 2400830662f6SVipul Pandya struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) 24015b6b8fe6SSteve Wise &child_ep->com.mapped_local_addr; 24025b6b8fe6SSteve Wise 2403830662f6SVipul Pandya sin6->sin6_family = PF_INET6; 2404830662f6SVipul Pandya sin6->sin6_port = local_port; 2405830662f6SVipul Pandya memcpy(sin6->sin6_addr.s6_addr, local_ip, 16); 24065b6b8fe6SSteve Wise 24075b6b8fe6SSteve Wise sin6 = (struct sockaddr_in6 *)&child_ep->com.local_addr; 24085b6b8fe6SSteve Wise sin6->sin6_family = PF_INET6; 24095b6b8fe6SSteve Wise sin6->sin6_port = ((struct sockaddr_in6 *) 24105b6b8fe6SSteve Wise &parent_ep->com.local_addr)->sin6_port; 24115b6b8fe6SSteve Wise memcpy(sin6->sin6_addr.s6_addr, local_ip, 16); 24125b6b8fe6SSteve Wise 24135b6b8fe6SSteve Wise sin6 = (struct sockaddr_in6 *)&child_ep->com.mapped_remote_addr; 2414830662f6SVipul Pandya sin6->sin6_family = PF_INET6; 2415830662f6SVipul Pandya sin6->sin6_port = peer_port; 2416830662f6SVipul Pandya memcpy(sin6->sin6_addr.s6_addr, peer_ip, 16); 2417830662f6SVipul Pandya } 24185b6b8fe6SSteve Wise memcpy(&child_ep->com.remote_addr, &child_ep->com.mapped_remote_addr, 24195b6b8fe6SSteve Wise sizeof(child_ep->com.remote_addr)); 24205b6b8fe6SSteve Wise get_remote_addr(child_ep); 24215b6b8fe6SSteve Wise 2422cfdda9d7SSteve Wise c4iw_get_ep(&parent_ep->com); 2423cfdda9d7SSteve Wise child_ep->parent_ep = parent_ep; 24246c53e938SHariprasad Shenai child_ep->tos = PASS_OPEN_TOS_G(ntohl(req->tos_stid)); 2425cfdda9d7SSteve Wise child_ep->dst = dst; 2426cfdda9d7SSteve Wise child_ep->hwtid = hwtid; 2427cfdda9d7SSteve Wise 2428cfdda9d7SSteve Wise PDBG("%s tx_chan %u smac_idx %u rss_qid %u\n", __func__, 24293786cf18SDavid Miller child_ep->tx_chan, child_ep->smac_idx, child_ep->rss_qid); 2430cfdda9d7SSteve Wise 2431cfdda9d7SSteve Wise init_timer(&child_ep->timer); 2432cfdda9d7SSteve Wise cxgb4_insert_tid(t, child_ep, hwtid); 2433b3de6cfeSVipul Pandya insert_handle(dev, &dev->hwtid_idr, child_ep, child_ep->hwtid); 2434830662f6SVipul Pandya accept_cr(child_ep, skb, req); 2435793dad94SVipul Pandya set_bit(PASS_ACCEPT_REQ, &child_ep->com.history); 2436cfdda9d7SSteve Wise goto out; 2437cfdda9d7SSteve Wise reject: 2438830662f6SVipul Pandya reject_cr(dev, hwtid, skb); 2439cfdda9d7SSteve Wise out: 2440cfdda9d7SSteve Wise return 0; 2441cfdda9d7SSteve Wise } 2442cfdda9d7SSteve Wise 2443cfdda9d7SSteve Wise static int pass_establish(struct c4iw_dev *dev, struct sk_buff *skb) 2444cfdda9d7SSteve Wise { 2445cfdda9d7SSteve Wise struct c4iw_ep *ep; 2446cfdda9d7SSteve Wise struct cpl_pass_establish *req = cplhdr(skb); 2447cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 2448cfdda9d7SSteve Wise unsigned int tid = GET_TID(req); 2449cfdda9d7SSteve Wise 2450cfdda9d7SSteve Wise ep = lookup_tid(t, tid); 2451cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2452cfdda9d7SSteve Wise ep->snd_seq = be32_to_cpu(req->snd_isn); 2453cfdda9d7SSteve Wise ep->rcv_seq = be32_to_cpu(req->rcv_isn); 2454cfdda9d7SSteve Wise 24551cab775cSVipul Pandya PDBG("%s ep %p hwtid %u tcp_opt 0x%02x\n", __func__, ep, tid, 24561cab775cSVipul Pandya ntohs(req->tcp_opt)); 24571cab775cSVipul Pandya 2458cfdda9d7SSteve Wise set_emss(ep, ntohs(req->tcp_opt)); 2459cfdda9d7SSteve Wise 2460cfdda9d7SSteve Wise dst_confirm(ep->dst); 2461cfdda9d7SSteve Wise state_set(&ep->com, MPA_REQ_WAIT); 2462cfdda9d7SSteve Wise start_ep_timer(ep); 2463cfdda9d7SSteve Wise send_flowc(ep, skb); 2464793dad94SVipul Pandya set_bit(PASS_ESTAB, &ep->com.history); 2465cfdda9d7SSteve Wise 2466cfdda9d7SSteve Wise return 0; 2467cfdda9d7SSteve Wise } 2468cfdda9d7SSteve Wise 2469cfdda9d7SSteve Wise static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb) 2470cfdda9d7SSteve Wise { 2471cfdda9d7SSteve Wise struct cpl_peer_close *hdr = cplhdr(skb); 2472cfdda9d7SSteve Wise struct c4iw_ep *ep; 2473cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 2474cfdda9d7SSteve Wise int disconnect = 1; 2475cfdda9d7SSteve Wise int release = 0; 2476cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 2477cfdda9d7SSteve Wise unsigned int tid = GET_TID(hdr); 24788da7e7a5SSteve Wise int ret; 2479cfdda9d7SSteve Wise 2480cfdda9d7SSteve Wise ep = lookup_tid(t, tid); 2481cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2482cfdda9d7SSteve Wise dst_confirm(ep->dst); 2483cfdda9d7SSteve Wise 2484793dad94SVipul Pandya set_bit(PEER_CLOSE, &ep->com.history); 24852f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 2486cfdda9d7SSteve Wise switch (ep->com.state) { 2487cfdda9d7SSteve Wise case MPA_REQ_WAIT: 2488cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2489cfdda9d7SSteve Wise break; 2490cfdda9d7SSteve Wise case MPA_REQ_SENT: 2491cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2492cfdda9d7SSteve Wise connect_reply_upcall(ep, -ECONNRESET); 2493cfdda9d7SSteve Wise break; 2494cfdda9d7SSteve Wise case MPA_REQ_RCVD: 2495cfdda9d7SSteve Wise 2496cfdda9d7SSteve Wise /* 2497cfdda9d7SSteve Wise * We're gonna mark this puppy DEAD, but keep 2498cfdda9d7SSteve Wise * the reference on it until the ULP accepts or 2499cfdda9d7SSteve Wise * rejects the CR. Also wake up anyone waiting 2500cfdda9d7SSteve Wise * in rdma connection migration (see c4iw_accept_cr()). 2501cfdda9d7SSteve Wise */ 2502cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2503cfdda9d7SSteve Wise PDBG("waking up ep %p tid %u\n", ep, ep->hwtid); 2504d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 2505cfdda9d7SSteve Wise break; 2506cfdda9d7SSteve Wise case MPA_REP_SENT: 2507cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2508cfdda9d7SSteve Wise PDBG("waking up ep %p tid %u\n", ep, ep->hwtid); 2509d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 2510cfdda9d7SSteve Wise break; 2511cfdda9d7SSteve Wise case FPDU_MODE: 2512ca5a2202SSteve Wise start_ep_timer(ep); 2513cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 251430c95c2dSSteve Wise attrs.next_state = C4IW_QP_STATE_CLOSING; 25158da7e7a5SSteve Wise ret = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 251630c95c2dSSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 25178da7e7a5SSteve Wise if (ret != -ECONNRESET) { 2518cfdda9d7SSteve Wise peer_close_upcall(ep); 251930c95c2dSSteve Wise disconnect = 1; 25208da7e7a5SSteve Wise } 2521cfdda9d7SSteve Wise break; 2522cfdda9d7SSteve Wise case ABORTING: 2523cfdda9d7SSteve Wise disconnect = 0; 2524cfdda9d7SSteve Wise break; 2525cfdda9d7SSteve Wise case CLOSING: 2526cfdda9d7SSteve Wise __state_set(&ep->com, MORIBUND); 2527cfdda9d7SSteve Wise disconnect = 0; 2528cfdda9d7SSteve Wise break; 2529cfdda9d7SSteve Wise case MORIBUND: 2530b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 2531cfdda9d7SSteve Wise if (ep->com.cm_id && ep->com.qp) { 2532cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_IDLE; 2533cfdda9d7SSteve Wise c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 2534cfdda9d7SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 2535cfdda9d7SSteve Wise } 2536be13b2dfSSteve Wise close_complete_upcall(ep, 0); 2537cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 2538cfdda9d7SSteve Wise release = 1; 2539cfdda9d7SSteve Wise disconnect = 0; 2540cfdda9d7SSteve Wise break; 2541cfdda9d7SSteve Wise case DEAD: 2542cfdda9d7SSteve Wise disconnect = 0; 2543cfdda9d7SSteve Wise break; 2544cfdda9d7SSteve Wise default: 2545cfdda9d7SSteve Wise BUG_ON(1); 2546cfdda9d7SSteve Wise } 25472f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 2548cfdda9d7SSteve Wise if (disconnect) 2549cfdda9d7SSteve Wise c4iw_ep_disconnect(ep, 0, GFP_KERNEL); 2550cfdda9d7SSteve Wise if (release) 2551cfdda9d7SSteve Wise release_ep_resources(ep); 2552cfdda9d7SSteve Wise return 0; 2553cfdda9d7SSteve Wise } 2554cfdda9d7SSteve Wise 2555cfdda9d7SSteve Wise static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) 2556cfdda9d7SSteve Wise { 2557cfdda9d7SSteve Wise struct cpl_abort_req_rss *req = cplhdr(skb); 2558cfdda9d7SSteve Wise struct c4iw_ep *ep; 2559cfdda9d7SSteve Wise struct cpl_abort_rpl *rpl; 2560cfdda9d7SSteve Wise struct sk_buff *rpl_skb; 2561cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 2562cfdda9d7SSteve Wise int ret; 2563cfdda9d7SSteve Wise int release = 0; 2564cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 2565cfdda9d7SSteve Wise unsigned int tid = GET_TID(req); 2566cfdda9d7SSteve Wise 2567cfdda9d7SSteve Wise ep = lookup_tid(t, tid); 25687a2cea2aSSteve Wise if (is_neg_adv(req->status)) { 2569dd92b124SHariprasad Shenai dev_warn(&dev->rdev.lldi.pdev->dev, 2570dd92b124SHariprasad Shenai "Negative advice on abort - tid %u status %d (%s)\n", 2571dd92b124SHariprasad Shenai ep->hwtid, req->status, neg_adv_str(req->status)); 2572cfdda9d7SSteve Wise return 0; 2573cfdda9d7SSteve Wise } 2574cfdda9d7SSteve Wise PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid, 2575cfdda9d7SSteve Wise ep->com.state); 2576793dad94SVipul Pandya set_bit(PEER_ABORT, &ep->com.history); 25772f5b48c3SSteve Wise 25782f5b48c3SSteve Wise /* 25792f5b48c3SSteve Wise * Wake up any threads in rdma_init() or rdma_fini(). 2580d2fe99e8SKumar Sanghvi * However, this is not needed if com state is just 2581d2fe99e8SKumar Sanghvi * MPA_REQ_SENT 25822f5b48c3SSteve Wise */ 2583d2fe99e8SKumar Sanghvi if (ep->com.state != MPA_REQ_SENT) 2584d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 25852f5b48c3SSteve Wise 25862f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 2587cfdda9d7SSteve Wise switch (ep->com.state) { 2588cfdda9d7SSteve Wise case CONNECTING: 2589cfdda9d7SSteve Wise break; 2590cfdda9d7SSteve Wise case MPA_REQ_WAIT: 2591b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 2592cfdda9d7SSteve Wise break; 2593cfdda9d7SSteve Wise case MPA_REQ_SENT: 2594b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 2595fe7e0a4dSVipul Pandya if (mpa_rev == 1 || (mpa_rev == 2 && ep->tried_with_mpa_v1)) 2596cfdda9d7SSteve Wise connect_reply_upcall(ep, -ECONNRESET); 2597d2fe99e8SKumar Sanghvi else { 2598d2fe99e8SKumar Sanghvi /* 2599d2fe99e8SKumar Sanghvi * we just don't send notification upwards because we 2600d2fe99e8SKumar Sanghvi * want to retry with mpa_v1 without upper layers even 2601d2fe99e8SKumar Sanghvi * knowing it. 2602d2fe99e8SKumar Sanghvi * 2603d2fe99e8SKumar Sanghvi * do some housekeeping so as to re-initiate the 2604d2fe99e8SKumar Sanghvi * connection 2605d2fe99e8SKumar Sanghvi */ 2606d2fe99e8SKumar Sanghvi PDBG("%s: mpa_rev=%d. Retrying with mpav1\n", __func__, 2607d2fe99e8SKumar Sanghvi mpa_rev); 2608d2fe99e8SKumar Sanghvi ep->retry_with_mpa_v1 = 1; 2609d2fe99e8SKumar Sanghvi } 2610cfdda9d7SSteve Wise break; 2611cfdda9d7SSteve Wise case MPA_REP_SENT: 2612cfdda9d7SSteve Wise break; 2613cfdda9d7SSteve Wise case MPA_REQ_RCVD: 2614cfdda9d7SSteve Wise break; 2615cfdda9d7SSteve Wise case MORIBUND: 2616cfdda9d7SSteve Wise case CLOSING: 2617ca5a2202SSteve Wise stop_ep_timer(ep); 2618cfdda9d7SSteve Wise /*FALLTHROUGH*/ 2619cfdda9d7SSteve Wise case FPDU_MODE: 2620cfdda9d7SSteve Wise if (ep->com.cm_id && ep->com.qp) { 2621cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_ERROR; 2622cfdda9d7SSteve Wise ret = c4iw_modify_qp(ep->com.qp->rhp, 2623cfdda9d7SSteve Wise ep->com.qp, C4IW_QP_ATTR_NEXT_STATE, 2624cfdda9d7SSteve Wise &attrs, 1); 2625cfdda9d7SSteve Wise if (ret) 2626cfdda9d7SSteve Wise printk(KERN_ERR MOD 2627cfdda9d7SSteve Wise "%s - qp <- error failed!\n", 2628cfdda9d7SSteve Wise __func__); 2629cfdda9d7SSteve Wise } 2630cfdda9d7SSteve Wise peer_abort_upcall(ep); 2631cfdda9d7SSteve Wise break; 2632cfdda9d7SSteve Wise case ABORTING: 2633cfdda9d7SSteve Wise break; 2634cfdda9d7SSteve Wise case DEAD: 2635cfdda9d7SSteve Wise PDBG("%s PEER_ABORT IN DEAD STATE!!!!\n", __func__); 26362f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 2637cfdda9d7SSteve Wise return 0; 2638cfdda9d7SSteve Wise default: 2639cfdda9d7SSteve Wise BUG_ON(1); 2640cfdda9d7SSteve Wise break; 2641cfdda9d7SSteve Wise } 2642cfdda9d7SSteve Wise dst_confirm(ep->dst); 2643cfdda9d7SSteve Wise if (ep->com.state != ABORTING) { 2644cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 2645d2fe99e8SKumar Sanghvi /* we don't release if we want to retry with mpa_v1 */ 2646d2fe99e8SKumar Sanghvi if (!ep->retry_with_mpa_v1) 2647cfdda9d7SSteve Wise release = 1; 2648cfdda9d7SSteve Wise } 26492f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 2650cfdda9d7SSteve Wise 2651cfdda9d7SSteve Wise rpl_skb = get_skb(skb, sizeof(*rpl), GFP_KERNEL); 2652cfdda9d7SSteve Wise if (!rpl_skb) { 2653cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot allocate skb!\n", 2654cfdda9d7SSteve Wise __func__); 2655cfdda9d7SSteve Wise release = 1; 2656cfdda9d7SSteve Wise goto out; 2657cfdda9d7SSteve Wise } 2658cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 2659cfdda9d7SSteve Wise rpl = (struct cpl_abort_rpl *) skb_put(rpl_skb, sizeof(*rpl)); 2660cfdda9d7SSteve Wise INIT_TP_WR(rpl, ep->hwtid); 2661cfdda9d7SSteve Wise OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_RPL, ep->hwtid)); 2662cfdda9d7SSteve Wise rpl->cmd = CPL_ABORT_NO_RST; 2663cfdda9d7SSteve Wise c4iw_ofld_send(&ep->com.dev->rdev, rpl_skb); 2664cfdda9d7SSteve Wise out: 2665cfdda9d7SSteve Wise if (release) 2666cfdda9d7SSteve Wise release_ep_resources(ep); 2667fe7e0a4dSVipul Pandya else if (ep->retry_with_mpa_v1) { 2668fe7e0a4dSVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->hwtid_idr, ep->hwtid); 2669d2fe99e8SKumar Sanghvi cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid); 2670d2fe99e8SKumar Sanghvi dst_release(ep->dst); 2671d2fe99e8SKumar Sanghvi cxgb4_l2t_release(ep->l2t); 2672d2fe99e8SKumar Sanghvi c4iw_reconnect(ep); 2673d2fe99e8SKumar Sanghvi } 2674d2fe99e8SKumar Sanghvi 2675cfdda9d7SSteve Wise return 0; 2676cfdda9d7SSteve Wise } 2677cfdda9d7SSteve Wise 2678cfdda9d7SSteve Wise static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2679cfdda9d7SSteve Wise { 2680cfdda9d7SSteve Wise struct c4iw_ep *ep; 2681cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 2682cfdda9d7SSteve Wise struct cpl_close_con_rpl *rpl = cplhdr(skb); 2683cfdda9d7SSteve Wise int release = 0; 2684cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 2685cfdda9d7SSteve Wise unsigned int tid = GET_TID(rpl); 2686cfdda9d7SSteve Wise 2687cfdda9d7SSteve Wise ep = lookup_tid(t, tid); 2688cfdda9d7SSteve Wise 2689cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2690cfdda9d7SSteve Wise BUG_ON(!ep); 2691cfdda9d7SSteve Wise 2692cfdda9d7SSteve Wise /* The cm_id may be null if we failed to connect */ 26932f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 2694cfdda9d7SSteve Wise switch (ep->com.state) { 2695cfdda9d7SSteve Wise case CLOSING: 2696cfdda9d7SSteve Wise __state_set(&ep->com, MORIBUND); 2697cfdda9d7SSteve Wise break; 2698cfdda9d7SSteve Wise case MORIBUND: 2699b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 2700cfdda9d7SSteve Wise if ((ep->com.cm_id) && (ep->com.qp)) { 2701cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_IDLE; 2702cfdda9d7SSteve Wise c4iw_modify_qp(ep->com.qp->rhp, 2703cfdda9d7SSteve Wise ep->com.qp, 2704cfdda9d7SSteve Wise C4IW_QP_ATTR_NEXT_STATE, 2705cfdda9d7SSteve Wise &attrs, 1); 2706cfdda9d7SSteve Wise } 2707be13b2dfSSteve Wise close_complete_upcall(ep, 0); 2708cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 2709cfdda9d7SSteve Wise release = 1; 2710cfdda9d7SSteve Wise break; 2711cfdda9d7SSteve Wise case ABORTING: 2712cfdda9d7SSteve Wise case DEAD: 2713cfdda9d7SSteve Wise break; 2714cfdda9d7SSteve Wise default: 2715cfdda9d7SSteve Wise BUG_ON(1); 2716cfdda9d7SSteve Wise break; 2717cfdda9d7SSteve Wise } 27182f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 2719cfdda9d7SSteve Wise if (release) 2720cfdda9d7SSteve Wise release_ep_resources(ep); 2721cfdda9d7SSteve Wise return 0; 2722cfdda9d7SSteve Wise } 2723cfdda9d7SSteve Wise 2724cfdda9d7SSteve Wise static int terminate(struct c4iw_dev *dev, struct sk_buff *skb) 2725cfdda9d7SSteve Wise { 27260e42c1f4SSteve Wise struct cpl_rdma_terminate *rpl = cplhdr(skb); 2727cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 27280e42c1f4SSteve Wise unsigned int tid = GET_TID(rpl); 27290e42c1f4SSteve Wise struct c4iw_ep *ep; 27300e42c1f4SSteve Wise struct c4iw_qp_attributes attrs; 2731cfdda9d7SSteve Wise 2732cfdda9d7SSteve Wise ep = lookup_tid(t, tid); 27330e42c1f4SSteve Wise BUG_ON(!ep); 2734cfdda9d7SSteve Wise 273530c95c2dSSteve Wise if (ep && ep->com.qp) { 27360e42c1f4SSteve Wise printk(KERN_WARNING MOD "TERM received tid %u qpid %u\n", tid, 27370e42c1f4SSteve Wise ep->com.qp->wq.sq.qid); 27380e42c1f4SSteve Wise attrs.next_state = C4IW_QP_STATE_TERMINATE; 27390e42c1f4SSteve Wise c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 27400e42c1f4SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 27410e42c1f4SSteve Wise } else 274230c95c2dSSteve Wise printk(KERN_WARNING MOD "TERM received tid %u no ep/qp\n", tid); 2743cfdda9d7SSteve Wise 2744cfdda9d7SSteve Wise return 0; 2745cfdda9d7SSteve Wise } 2746cfdda9d7SSteve Wise 2747cfdda9d7SSteve Wise /* 2748cfdda9d7SSteve Wise * Upcall from the adapter indicating data has been transmitted. 2749cfdda9d7SSteve Wise * For us its just the single MPA request or reply. We can now free 2750cfdda9d7SSteve Wise * the skb holding the mpa message. 2751cfdda9d7SSteve Wise */ 2752cfdda9d7SSteve Wise static int fw4_ack(struct c4iw_dev *dev, struct sk_buff *skb) 2753cfdda9d7SSteve Wise { 2754cfdda9d7SSteve Wise struct c4iw_ep *ep; 2755cfdda9d7SSteve Wise struct cpl_fw4_ack *hdr = cplhdr(skb); 2756cfdda9d7SSteve Wise u8 credits = hdr->credits; 2757cfdda9d7SSteve Wise unsigned int tid = GET_TID(hdr); 2758cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 2759cfdda9d7SSteve Wise 2760cfdda9d7SSteve Wise 2761cfdda9d7SSteve Wise ep = lookup_tid(t, tid); 2762cfdda9d7SSteve Wise PDBG("%s ep %p tid %u credits %u\n", __func__, ep, ep->hwtid, credits); 2763cfdda9d7SSteve Wise if (credits == 0) { 2764aa1ad260SJoe Perches PDBG("%s 0 credit ack ep %p tid %u state %u\n", 2765cfdda9d7SSteve Wise __func__, ep, ep->hwtid, state_read(&ep->com)); 2766cfdda9d7SSteve Wise return 0; 2767cfdda9d7SSteve Wise } 2768cfdda9d7SSteve Wise 2769cfdda9d7SSteve Wise dst_confirm(ep->dst); 2770cfdda9d7SSteve Wise if (ep->mpa_skb) { 2771cfdda9d7SSteve Wise PDBG("%s last streaming msg ack ep %p tid %u state %u " 2772cfdda9d7SSteve Wise "initiator %u freeing skb\n", __func__, ep, ep->hwtid, 2773cfdda9d7SSteve Wise state_read(&ep->com), ep->mpa_attr.initiator ? 1 : 0); 2774cfdda9d7SSteve Wise kfree_skb(ep->mpa_skb); 2775cfdda9d7SSteve Wise ep->mpa_skb = NULL; 2776cfdda9d7SSteve Wise } 2777cfdda9d7SSteve Wise return 0; 2778cfdda9d7SSteve Wise } 2779cfdda9d7SSteve Wise 2780cfdda9d7SSteve Wise int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) 2781cfdda9d7SSteve Wise { 2782a7db89ebSSteve Wise int err = 0; 2783a7db89ebSSteve Wise int disconnect = 0; 2784cfdda9d7SSteve Wise struct c4iw_ep *ep = to_ep(cm_id); 2785cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2786cfdda9d7SSteve Wise 2787a7db89ebSSteve Wise mutex_lock(&ep->com.mutex); 2788a7db89ebSSteve Wise if (ep->com.state == DEAD) { 2789a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 2790cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 2791cfdda9d7SSteve Wise return -ECONNRESET; 2792cfdda9d7SSteve Wise } 2793793dad94SVipul Pandya set_bit(ULP_REJECT, &ep->com.history); 2794a7db89ebSSteve Wise BUG_ON(ep->com.state != MPA_REQ_RCVD); 2795cfdda9d7SSteve Wise if (mpa_rev == 0) 2796cfdda9d7SSteve Wise abort_connection(ep, NULL, GFP_KERNEL); 2797cfdda9d7SSteve Wise else { 2798cfdda9d7SSteve Wise err = send_mpa_reject(ep, pdata, pdata_len); 2799a7db89ebSSteve Wise disconnect = 1; 2800cfdda9d7SSteve Wise } 2801a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 2802a7db89ebSSteve Wise if (disconnect) 2803a7db89ebSSteve Wise err = c4iw_ep_disconnect(ep, 0, GFP_KERNEL); 2804cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 2805cfdda9d7SSteve Wise return 0; 2806cfdda9d7SSteve Wise } 2807cfdda9d7SSteve Wise 2808cfdda9d7SSteve Wise int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) 2809cfdda9d7SSteve Wise { 2810cfdda9d7SSteve Wise int err; 2811cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 2812cfdda9d7SSteve Wise enum c4iw_qp_attr_mask mask; 2813cfdda9d7SSteve Wise struct c4iw_ep *ep = to_ep(cm_id); 2814cfdda9d7SSteve Wise struct c4iw_dev *h = to_c4iw_dev(cm_id->device); 2815cfdda9d7SSteve Wise struct c4iw_qp *qp = get_qhp(h, conn_param->qpn); 2816cfdda9d7SSteve Wise 2817cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2818a7db89ebSSteve Wise 2819a7db89ebSSteve Wise mutex_lock(&ep->com.mutex); 2820a7db89ebSSteve Wise if (ep->com.state == DEAD) { 2821cfdda9d7SSteve Wise err = -ECONNRESET; 2822cfdda9d7SSteve Wise goto err; 2823cfdda9d7SSteve Wise } 2824cfdda9d7SSteve Wise 2825a7db89ebSSteve Wise BUG_ON(ep->com.state != MPA_REQ_RCVD); 2826cfdda9d7SSteve Wise BUG_ON(!qp); 2827cfdda9d7SSteve Wise 2828793dad94SVipul Pandya set_bit(ULP_ACCEPT, &ep->com.history); 28294c2c5763SHariprasad Shenai if ((conn_param->ord > cur_max_read_depth(ep->com.dev)) || 28304c2c5763SHariprasad Shenai (conn_param->ird > cur_max_read_depth(ep->com.dev))) { 2831cfdda9d7SSteve Wise abort_connection(ep, NULL, GFP_KERNEL); 2832cfdda9d7SSteve Wise err = -EINVAL; 2833cfdda9d7SSteve Wise goto err; 2834cfdda9d7SSteve Wise } 2835cfdda9d7SSteve Wise 2836d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 2837d2fe99e8SKumar Sanghvi if (conn_param->ord > ep->ird) { 28384c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION) { 28394c2c5763SHariprasad Shenai ep->ord = ep->ird; 28404c2c5763SHariprasad Shenai } else { 2841d2fe99e8SKumar Sanghvi ep->ird = conn_param->ird; 2842d2fe99e8SKumar Sanghvi ep->ord = conn_param->ord; 2843d2fe99e8SKumar Sanghvi send_mpa_reject(ep, conn_param->private_data, 2844d2fe99e8SKumar Sanghvi conn_param->private_data_len); 2845d2fe99e8SKumar Sanghvi abort_connection(ep, NULL, GFP_KERNEL); 2846d2fe99e8SKumar Sanghvi err = -ENOMEM; 2847d2fe99e8SKumar Sanghvi goto err; 2848d2fe99e8SKumar Sanghvi } 28494c2c5763SHariprasad Shenai } 28504c2c5763SHariprasad Shenai if (conn_param->ird < ep->ord) { 28514c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION && 28524c2c5763SHariprasad Shenai ep->ord <= h->rdev.lldi.max_ordird_qp) { 28534c2c5763SHariprasad Shenai conn_param->ird = ep->ord; 28544c2c5763SHariprasad Shenai } else { 2855d2fe99e8SKumar Sanghvi abort_connection(ep, NULL, GFP_KERNEL); 2856d2fe99e8SKumar Sanghvi err = -ENOMEM; 2857d2fe99e8SKumar Sanghvi goto err; 2858d2fe99e8SKumar Sanghvi } 2859d2fe99e8SKumar Sanghvi } 2860d2fe99e8SKumar Sanghvi } 2861cfdda9d7SSteve Wise ep->ird = conn_param->ird; 2862cfdda9d7SSteve Wise ep->ord = conn_param->ord; 2863cfdda9d7SSteve Wise 28644c2c5763SHariprasad Shenai if (ep->mpa_attr.version == 1) { 2865cfdda9d7SSteve Wise if (peer2peer && ep->ird == 0) 2866cfdda9d7SSteve Wise ep->ird = 1; 28674c2c5763SHariprasad Shenai } else { 28684c2c5763SHariprasad Shenai if (peer2peer && 28694c2c5763SHariprasad Shenai (ep->mpa_attr.p2p_type != FW_RI_INIT_P2PTYPE_DISABLED) && 28704c2c5763SHariprasad Shenai (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) && ep->ord == 0) 28714c2c5763SHariprasad Shenai ep->ird = 1; 28724c2c5763SHariprasad Shenai } 2873cfdda9d7SSteve Wise 2874cfdda9d7SSteve Wise PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord); 2875cfdda9d7SSteve Wise 2876d2fe99e8SKumar Sanghvi cm_id->add_ref(cm_id); 2877d2fe99e8SKumar Sanghvi ep->com.cm_id = cm_id; 2878d2fe99e8SKumar Sanghvi ep->com.qp = qp; 2879325abeadSVipul Pandya ref_qp(ep); 2880d2fe99e8SKumar Sanghvi 2881cfdda9d7SSteve Wise /* bind QP to EP and move to RTS */ 2882cfdda9d7SSteve Wise attrs.mpa_attr = ep->mpa_attr; 2883cfdda9d7SSteve Wise attrs.max_ird = ep->ird; 2884cfdda9d7SSteve Wise attrs.max_ord = ep->ord; 2885cfdda9d7SSteve Wise attrs.llp_stream_handle = ep; 2886cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_RTS; 2887cfdda9d7SSteve Wise 2888cfdda9d7SSteve Wise /* bind QP and TID with INIT_WR */ 2889cfdda9d7SSteve Wise mask = C4IW_QP_ATTR_NEXT_STATE | 2890cfdda9d7SSteve Wise C4IW_QP_ATTR_LLP_STREAM_HANDLE | 2891cfdda9d7SSteve Wise C4IW_QP_ATTR_MPA_ATTR | 2892cfdda9d7SSteve Wise C4IW_QP_ATTR_MAX_IRD | 2893cfdda9d7SSteve Wise C4IW_QP_ATTR_MAX_ORD; 2894cfdda9d7SSteve Wise 2895cfdda9d7SSteve Wise err = c4iw_modify_qp(ep->com.qp->rhp, 2896cfdda9d7SSteve Wise ep->com.qp, mask, &attrs, 1); 2897cfdda9d7SSteve Wise if (err) 2898cfdda9d7SSteve Wise goto err1; 2899cfdda9d7SSteve Wise err = send_mpa_reply(ep, conn_param->private_data, 2900cfdda9d7SSteve Wise conn_param->private_data_len); 2901cfdda9d7SSteve Wise if (err) 2902cfdda9d7SSteve Wise goto err1; 2903cfdda9d7SSteve Wise 2904a7db89ebSSteve Wise __state_set(&ep->com, FPDU_MODE); 2905cfdda9d7SSteve Wise established_upcall(ep); 2906a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 2907cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 2908cfdda9d7SSteve Wise return 0; 2909cfdda9d7SSteve Wise err1: 2910cfdda9d7SSteve Wise ep->com.cm_id = NULL; 29114c2c5763SHariprasad Shenai abort_connection(ep, NULL, GFP_KERNEL); 2912cfdda9d7SSteve Wise cm_id->rem_ref(cm_id); 2913cfdda9d7SSteve Wise err: 2914a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 2915cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 2916cfdda9d7SSteve Wise return err; 2917cfdda9d7SSteve Wise } 2918cfdda9d7SSteve Wise 2919830662f6SVipul Pandya static int pick_local_ipaddrs(struct c4iw_dev *dev, struct iw_cm_id *cm_id) 2920830662f6SVipul Pandya { 2921830662f6SVipul Pandya struct in_device *ind; 2922830662f6SVipul Pandya int found = 0; 2923830662f6SVipul Pandya struct sockaddr_in *laddr = (struct sockaddr_in *)&cm_id->local_addr; 2924830662f6SVipul Pandya struct sockaddr_in *raddr = (struct sockaddr_in *)&cm_id->remote_addr; 2925830662f6SVipul Pandya 2926830662f6SVipul Pandya ind = in_dev_get(dev->rdev.lldi.ports[0]); 2927830662f6SVipul Pandya if (!ind) 2928830662f6SVipul Pandya return -EADDRNOTAVAIL; 2929830662f6SVipul Pandya for_primary_ifa(ind) { 2930830662f6SVipul Pandya laddr->sin_addr.s_addr = ifa->ifa_address; 2931830662f6SVipul Pandya raddr->sin_addr.s_addr = ifa->ifa_address; 2932830662f6SVipul Pandya found = 1; 2933830662f6SVipul Pandya break; 2934830662f6SVipul Pandya } 2935830662f6SVipul Pandya endfor_ifa(ind); 2936830662f6SVipul Pandya in_dev_put(ind); 2937830662f6SVipul Pandya return found ? 0 : -EADDRNOTAVAIL; 2938830662f6SVipul Pandya } 2939830662f6SVipul Pandya 2940830662f6SVipul Pandya static int get_lladdr(struct net_device *dev, struct in6_addr *addr, 2941830662f6SVipul Pandya unsigned char banned_flags) 2942830662f6SVipul Pandya { 2943830662f6SVipul Pandya struct inet6_dev *idev; 2944830662f6SVipul Pandya int err = -EADDRNOTAVAIL; 2945830662f6SVipul Pandya 2946830662f6SVipul Pandya rcu_read_lock(); 2947830662f6SVipul Pandya idev = __in6_dev_get(dev); 2948830662f6SVipul Pandya if (idev != NULL) { 2949830662f6SVipul Pandya struct inet6_ifaddr *ifp; 2950830662f6SVipul Pandya 2951830662f6SVipul Pandya read_lock_bh(&idev->lock); 2952830662f6SVipul Pandya list_for_each_entry(ifp, &idev->addr_list, if_list) { 2953830662f6SVipul Pandya if (ifp->scope == IFA_LINK && 2954830662f6SVipul Pandya !(ifp->flags & banned_flags)) { 2955830662f6SVipul Pandya memcpy(addr, &ifp->addr, 16); 2956830662f6SVipul Pandya err = 0; 2957830662f6SVipul Pandya break; 2958830662f6SVipul Pandya } 2959830662f6SVipul Pandya } 2960830662f6SVipul Pandya read_unlock_bh(&idev->lock); 2961830662f6SVipul Pandya } 2962830662f6SVipul Pandya rcu_read_unlock(); 2963830662f6SVipul Pandya return err; 2964830662f6SVipul Pandya } 2965830662f6SVipul Pandya 2966830662f6SVipul Pandya static int pick_local_ip6addrs(struct c4iw_dev *dev, struct iw_cm_id *cm_id) 2967830662f6SVipul Pandya { 2968830662f6SVipul Pandya struct in6_addr uninitialized_var(addr); 2969830662f6SVipul Pandya struct sockaddr_in6 *la6 = (struct sockaddr_in6 *)&cm_id->local_addr; 2970830662f6SVipul Pandya struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)&cm_id->remote_addr; 2971830662f6SVipul Pandya 2972830662f6SVipul Pandya if (get_lladdr(dev->rdev.lldi.ports[0], &addr, IFA_F_TENTATIVE)) { 2973830662f6SVipul Pandya memcpy(la6->sin6_addr.s6_addr, &addr, 16); 2974830662f6SVipul Pandya memcpy(ra6->sin6_addr.s6_addr, &addr, 16); 2975830662f6SVipul Pandya return 0; 2976830662f6SVipul Pandya } 2977830662f6SVipul Pandya return -EADDRNOTAVAIL; 2978830662f6SVipul Pandya } 2979830662f6SVipul Pandya 2980cfdda9d7SSteve Wise int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) 2981cfdda9d7SSteve Wise { 2982cfdda9d7SSteve Wise struct c4iw_dev *dev = to_c4iw_dev(cm_id->device); 2983cfdda9d7SSteve Wise struct c4iw_ep *ep; 29843786cf18SDavid Miller int err = 0; 29859eccfe10SSteve Wise struct sockaddr_in *laddr; 29869eccfe10SSteve Wise struct sockaddr_in *raddr; 29879eccfe10SSteve Wise struct sockaddr_in6 *laddr6; 29889eccfe10SSteve Wise struct sockaddr_in6 *raddr6; 29899eccfe10SSteve Wise struct iwpm_dev_data pm_reg_msg; 29909eccfe10SSteve Wise struct iwpm_sa_data pm_msg; 2991830662f6SVipul Pandya __u8 *ra; 2992830662f6SVipul Pandya int iptype; 29939eccfe10SSteve Wise int iwpm_err = 0; 2994cfdda9d7SSteve Wise 29954c2c5763SHariprasad Shenai if ((conn_param->ord > cur_max_read_depth(dev)) || 29964c2c5763SHariprasad Shenai (conn_param->ird > cur_max_read_depth(dev))) { 2997be4c9badSRoland Dreier err = -EINVAL; 2998be4c9badSRoland Dreier goto out; 2999be4c9badSRoland Dreier } 3000cfdda9d7SSteve Wise ep = alloc_ep(sizeof(*ep), GFP_KERNEL); 3001cfdda9d7SSteve Wise if (!ep) { 3002cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __func__); 3003cfdda9d7SSteve Wise err = -ENOMEM; 3004cfdda9d7SSteve Wise goto out; 3005cfdda9d7SSteve Wise } 3006cfdda9d7SSteve Wise init_timer(&ep->timer); 3007cfdda9d7SSteve Wise ep->plen = conn_param->private_data_len; 3008cfdda9d7SSteve Wise if (ep->plen) 3009cfdda9d7SSteve Wise memcpy(ep->mpa_pkt + sizeof(struct mpa_message), 3010cfdda9d7SSteve Wise conn_param->private_data, ep->plen); 3011cfdda9d7SSteve Wise ep->ird = conn_param->ird; 3012cfdda9d7SSteve Wise ep->ord = conn_param->ord; 3013cfdda9d7SSteve Wise 3014cfdda9d7SSteve Wise if (peer2peer && ep->ord == 0) 3015cfdda9d7SSteve Wise ep->ord = 1; 3016cfdda9d7SSteve Wise 3017cfdda9d7SSteve Wise cm_id->add_ref(cm_id); 3018cfdda9d7SSteve Wise ep->com.dev = dev; 3019cfdda9d7SSteve Wise ep->com.cm_id = cm_id; 3020cfdda9d7SSteve Wise ep->com.qp = get_qhp(dev, conn_param->qpn); 3021830662f6SVipul Pandya if (!ep->com.qp) { 3022830662f6SVipul Pandya PDBG("%s qpn 0x%x not found!\n", __func__, conn_param->qpn); 3023830662f6SVipul Pandya err = -EINVAL; 30249eccfe10SSteve Wise goto fail1; 3025830662f6SVipul Pandya } 3026325abeadSVipul Pandya ref_qp(ep); 3027cfdda9d7SSteve Wise PDBG("%s qpn 0x%x qp %p cm_id %p\n", __func__, conn_param->qpn, 3028cfdda9d7SSteve Wise ep->com.qp, cm_id); 3029cfdda9d7SSteve Wise 3030cfdda9d7SSteve Wise /* 3031cfdda9d7SSteve Wise * Allocate an active TID to initiate a TCP connection. 3032cfdda9d7SSteve Wise */ 3033cfdda9d7SSteve Wise ep->atid = cxgb4_alloc_atid(dev->rdev.lldi.tids, ep); 3034cfdda9d7SSteve Wise if (ep->atid == -1) { 3035cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __func__); 3036cfdda9d7SSteve Wise err = -ENOMEM; 30379eccfe10SSteve Wise goto fail1; 3038cfdda9d7SSteve Wise } 3039793dad94SVipul Pandya insert_handle(dev, &dev->atid_idr, ep, ep->atid); 3040cfdda9d7SSteve Wise 30419eccfe10SSteve Wise memcpy(&ep->com.local_addr, &cm_id->local_addr, 30429eccfe10SSteve Wise sizeof(ep->com.local_addr)); 30439eccfe10SSteve Wise memcpy(&ep->com.remote_addr, &cm_id->remote_addr, 30449eccfe10SSteve Wise sizeof(ep->com.remote_addr)); 30459eccfe10SSteve Wise 30469eccfe10SSteve Wise /* No port mapper available, go with the specified peer information */ 30479eccfe10SSteve Wise memcpy(&ep->com.mapped_local_addr, &cm_id->local_addr, 30489eccfe10SSteve Wise sizeof(ep->com.mapped_local_addr)); 30499eccfe10SSteve Wise memcpy(&ep->com.mapped_remote_addr, &cm_id->remote_addr, 30509eccfe10SSteve Wise sizeof(ep->com.mapped_remote_addr)); 30519eccfe10SSteve Wise 30529eccfe10SSteve Wise c4iw_form_reg_msg(dev, &pm_reg_msg); 30539eccfe10SSteve Wise iwpm_err = iwpm_register_pid(&pm_reg_msg, RDMA_NL_C4IW); 30549eccfe10SSteve Wise if (iwpm_err) { 30559eccfe10SSteve Wise PDBG("%s: Port Mapper reg pid fail (err = %d).\n", 30569eccfe10SSteve Wise __func__, iwpm_err); 30579eccfe10SSteve Wise } 30589eccfe10SSteve Wise if (iwpm_valid_pid() && !iwpm_err) { 30599eccfe10SSteve Wise c4iw_form_pm_msg(ep, &pm_msg); 30609eccfe10SSteve Wise iwpm_err = iwpm_add_and_query_mapping(&pm_msg, RDMA_NL_C4IW); 30619eccfe10SSteve Wise if (iwpm_err) 30629eccfe10SSteve Wise PDBG("%s: Port Mapper query fail (err = %d).\n", 30639eccfe10SSteve Wise __func__, iwpm_err); 30649eccfe10SSteve Wise else 30659eccfe10SSteve Wise c4iw_record_pm_msg(ep, &pm_msg); 30669eccfe10SSteve Wise } 30679eccfe10SSteve Wise if (iwpm_create_mapinfo(&ep->com.local_addr, 30689eccfe10SSteve Wise &ep->com.mapped_local_addr, RDMA_NL_C4IW)) { 30699eccfe10SSteve Wise iwpm_remove_mapping(&ep->com.local_addr, RDMA_NL_C4IW); 30709eccfe10SSteve Wise err = -ENOMEM; 30719eccfe10SSteve Wise goto fail1; 30729eccfe10SSteve Wise } 30739eccfe10SSteve Wise print_addr(&ep->com, __func__, "add_query/create_mapinfo"); 30749eccfe10SSteve Wise set_bit(RELEASE_MAPINFO, &ep->com.flags); 30759eccfe10SSteve Wise 30769eccfe10SSteve Wise laddr = (struct sockaddr_in *)&ep->com.mapped_local_addr; 30779eccfe10SSteve Wise raddr = (struct sockaddr_in *)&ep->com.mapped_remote_addr; 30789eccfe10SSteve Wise laddr6 = (struct sockaddr_in6 *)&ep->com.mapped_local_addr; 30799eccfe10SSteve Wise raddr6 = (struct sockaddr_in6 *) &ep->com.mapped_remote_addr; 30809eccfe10SSteve Wise 3081830662f6SVipul Pandya if (cm_id->remote_addr.ss_family == AF_INET) { 3082830662f6SVipul Pandya iptype = 4; 3083830662f6SVipul Pandya ra = (__u8 *)&raddr->sin_addr; 3084830662f6SVipul Pandya 3085830662f6SVipul Pandya /* 3086830662f6SVipul Pandya * Handle loopback requests to INADDR_ANY. 3087830662f6SVipul Pandya */ 3088830662f6SVipul Pandya if ((__force int)raddr->sin_addr.s_addr == INADDR_ANY) { 3089830662f6SVipul Pandya err = pick_local_ipaddrs(dev, cm_id); 3090830662f6SVipul Pandya if (err) 30919eccfe10SSteve Wise goto fail1; 3092830662f6SVipul Pandya } 3093cfdda9d7SSteve Wise 3094cfdda9d7SSteve Wise /* find a route */ 3095830662f6SVipul Pandya PDBG("%s saddr %pI4 sport 0x%x raddr %pI4 rport 0x%x\n", 3096830662f6SVipul Pandya __func__, &laddr->sin_addr, ntohs(laddr->sin_port), 3097830662f6SVipul Pandya ra, ntohs(raddr->sin_port)); 3098830662f6SVipul Pandya ep->dst = find_route(dev, laddr->sin_addr.s_addr, 3099830662f6SVipul Pandya raddr->sin_addr.s_addr, laddr->sin_port, 3100830662f6SVipul Pandya raddr->sin_port, 0); 3101830662f6SVipul Pandya } else { 3102830662f6SVipul Pandya iptype = 6; 3103830662f6SVipul Pandya ra = (__u8 *)&raddr6->sin6_addr; 3104830662f6SVipul Pandya 3105830662f6SVipul Pandya /* 3106830662f6SVipul Pandya * Handle loopback requests to INADDR_ANY. 3107830662f6SVipul Pandya */ 3108830662f6SVipul Pandya if (ipv6_addr_type(&raddr6->sin6_addr) == IPV6_ADDR_ANY) { 3109830662f6SVipul Pandya err = pick_local_ip6addrs(dev, cm_id); 3110830662f6SVipul Pandya if (err) 31119eccfe10SSteve Wise goto fail1; 3112830662f6SVipul Pandya } 3113830662f6SVipul Pandya 3114830662f6SVipul Pandya /* find a route */ 3115830662f6SVipul Pandya PDBG("%s saddr %pI6 sport 0x%x raddr %pI6 rport 0x%x\n", 3116830662f6SVipul Pandya __func__, laddr6->sin6_addr.s6_addr, 3117830662f6SVipul Pandya ntohs(laddr6->sin6_port), 3118830662f6SVipul Pandya raddr6->sin6_addr.s6_addr, ntohs(raddr6->sin6_port)); 3119830662f6SVipul Pandya ep->dst = find_route6(dev, laddr6->sin6_addr.s6_addr, 3120830662f6SVipul Pandya raddr6->sin6_addr.s6_addr, 3121830662f6SVipul Pandya laddr6->sin6_port, raddr6->sin6_port, 0, 3122830662f6SVipul Pandya raddr6->sin6_scope_id); 3123830662f6SVipul Pandya } 3124830662f6SVipul Pandya if (!ep->dst) { 3125cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot find route.\n", __func__); 3126cfdda9d7SSteve Wise err = -EHOSTUNREACH; 31279eccfe10SSteve Wise goto fail2; 3128cfdda9d7SSteve Wise } 3129cfdda9d7SSteve Wise 3130830662f6SVipul Pandya err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, true); 31313786cf18SDavid Miller if (err) { 3132cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); 31339eccfe10SSteve Wise goto fail3; 3134cfdda9d7SSteve Wise } 3135cfdda9d7SSteve Wise 3136cfdda9d7SSteve Wise PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n", 3137cfdda9d7SSteve Wise __func__, ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid, 3138cfdda9d7SSteve Wise ep->l2t->idx); 3139cfdda9d7SSteve Wise 3140cfdda9d7SSteve Wise state_set(&ep->com, CONNECTING); 3141cfdda9d7SSteve Wise ep->tos = 0; 3142cfdda9d7SSteve Wise 3143cfdda9d7SSteve Wise /* send connect request to rnic */ 3144cfdda9d7SSteve Wise err = send_connect(ep); 3145cfdda9d7SSteve Wise if (!err) 3146cfdda9d7SSteve Wise goto out; 3147cfdda9d7SSteve Wise 3148cfdda9d7SSteve Wise cxgb4_l2t_release(ep->l2t); 3149cfdda9d7SSteve Wise fail3: 31509eccfe10SSteve Wise dst_release(ep->dst); 31519eccfe10SSteve Wise fail2: 3152793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid); 3153cfdda9d7SSteve Wise cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid); 31549eccfe10SSteve Wise fail1: 3155cfdda9d7SSteve Wise cm_id->rem_ref(cm_id); 3156cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3157cfdda9d7SSteve Wise out: 3158cfdda9d7SSteve Wise return err; 3159cfdda9d7SSteve Wise } 3160cfdda9d7SSteve Wise 3161830662f6SVipul Pandya static int create_server6(struct c4iw_dev *dev, struct c4iw_listen_ep *ep) 3162830662f6SVipul Pandya { 3163830662f6SVipul Pandya int err; 31649eccfe10SSteve Wise struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) 31659eccfe10SSteve Wise &ep->com.mapped_local_addr; 3166830662f6SVipul Pandya 3167830662f6SVipul Pandya c4iw_init_wr_wait(&ep->com.wr_wait); 3168830662f6SVipul Pandya err = cxgb4_create_server6(ep->com.dev->rdev.lldi.ports[0], 3169830662f6SVipul Pandya ep->stid, &sin6->sin6_addr, 3170830662f6SVipul Pandya sin6->sin6_port, 3171830662f6SVipul Pandya ep->com.dev->rdev.lldi.rxq_ids[0]); 3172830662f6SVipul Pandya if (!err) 3173830662f6SVipul Pandya err = c4iw_wait_for_reply(&ep->com.dev->rdev, 3174830662f6SVipul Pandya &ep->com.wr_wait, 3175830662f6SVipul Pandya 0, 0, __func__); 3176e6b11163SHariprasad S else if (err > 0) 3177e6b11163SHariprasad S err = net_xmit_errno(err); 3178830662f6SVipul Pandya if (err) 3179830662f6SVipul Pandya pr_err("cxgb4_create_server6/filter failed err %d stid %d laddr %pI6 lport %d\n", 3180830662f6SVipul Pandya err, ep->stid, 3181830662f6SVipul Pandya sin6->sin6_addr.s6_addr, ntohs(sin6->sin6_port)); 3182830662f6SVipul Pandya return err; 3183830662f6SVipul Pandya } 3184830662f6SVipul Pandya 3185830662f6SVipul Pandya static int create_server4(struct c4iw_dev *dev, struct c4iw_listen_ep *ep) 3186830662f6SVipul Pandya { 3187830662f6SVipul Pandya int err; 31889eccfe10SSteve Wise struct sockaddr_in *sin = (struct sockaddr_in *) 31899eccfe10SSteve Wise &ep->com.mapped_local_addr; 3190830662f6SVipul Pandya 3191830662f6SVipul Pandya if (dev->rdev.lldi.enable_fw_ofld_conn) { 3192830662f6SVipul Pandya do { 3193830662f6SVipul Pandya err = cxgb4_create_server_filter( 3194830662f6SVipul Pandya ep->com.dev->rdev.lldi.ports[0], ep->stid, 3195830662f6SVipul Pandya sin->sin_addr.s_addr, sin->sin_port, 0, 3196830662f6SVipul Pandya ep->com.dev->rdev.lldi.rxq_ids[0], 0, 0); 3197830662f6SVipul Pandya if (err == -EBUSY) { 3198830662f6SVipul Pandya set_current_state(TASK_UNINTERRUPTIBLE); 3199830662f6SVipul Pandya schedule_timeout(usecs_to_jiffies(100)); 3200830662f6SVipul Pandya } 3201830662f6SVipul Pandya } while (err == -EBUSY); 3202830662f6SVipul Pandya } else { 3203830662f6SVipul Pandya c4iw_init_wr_wait(&ep->com.wr_wait); 3204830662f6SVipul Pandya err = cxgb4_create_server(ep->com.dev->rdev.lldi.ports[0], 3205830662f6SVipul Pandya ep->stid, sin->sin_addr.s_addr, sin->sin_port, 3206830662f6SVipul Pandya 0, ep->com.dev->rdev.lldi.rxq_ids[0]); 3207830662f6SVipul Pandya if (!err) 3208830662f6SVipul Pandya err = c4iw_wait_for_reply(&ep->com.dev->rdev, 3209830662f6SVipul Pandya &ep->com.wr_wait, 3210830662f6SVipul Pandya 0, 0, __func__); 3211e6b11163SHariprasad S else if (err > 0) 3212e6b11163SHariprasad S err = net_xmit_errno(err); 3213830662f6SVipul Pandya } 3214830662f6SVipul Pandya if (err) 3215830662f6SVipul Pandya pr_err("cxgb4_create_server/filter failed err %d stid %d laddr %pI4 lport %d\n" 3216830662f6SVipul Pandya , err, ep->stid, 3217830662f6SVipul Pandya &sin->sin_addr, ntohs(sin->sin_port)); 3218830662f6SVipul Pandya return err; 3219830662f6SVipul Pandya } 3220830662f6SVipul Pandya 3221cfdda9d7SSteve Wise int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog) 3222cfdda9d7SSteve Wise { 3223cfdda9d7SSteve Wise int err = 0; 3224cfdda9d7SSteve Wise struct c4iw_dev *dev = to_c4iw_dev(cm_id->device); 3225cfdda9d7SSteve Wise struct c4iw_listen_ep *ep; 32269eccfe10SSteve Wise struct iwpm_dev_data pm_reg_msg; 32279eccfe10SSteve Wise struct iwpm_sa_data pm_msg; 32289eccfe10SSteve Wise int iwpm_err = 0; 3229cfdda9d7SSteve Wise 3230cfdda9d7SSteve Wise might_sleep(); 3231cfdda9d7SSteve Wise 3232cfdda9d7SSteve Wise ep = alloc_ep(sizeof(*ep), GFP_KERNEL); 3233cfdda9d7SSteve Wise if (!ep) { 3234cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __func__); 3235cfdda9d7SSteve Wise err = -ENOMEM; 3236cfdda9d7SSteve Wise goto fail1; 3237cfdda9d7SSteve Wise } 3238cfdda9d7SSteve Wise PDBG("%s ep %p\n", __func__, ep); 3239cfdda9d7SSteve Wise cm_id->add_ref(cm_id); 3240cfdda9d7SSteve Wise ep->com.cm_id = cm_id; 3241cfdda9d7SSteve Wise ep->com.dev = dev; 3242cfdda9d7SSteve Wise ep->backlog = backlog; 324324d44a39SSteve Wise memcpy(&ep->com.local_addr, &cm_id->local_addr, 324424d44a39SSteve Wise sizeof(ep->com.local_addr)); 3245cfdda9d7SSteve Wise 3246cfdda9d7SSteve Wise /* 3247cfdda9d7SSteve Wise * Allocate a server TID. 3248cfdda9d7SSteve Wise */ 32498c044690SKumar Sanghvi if (dev->rdev.lldi.enable_fw_ofld_conn && 32508c044690SKumar Sanghvi ep->com.local_addr.ss_family == AF_INET) 3251830662f6SVipul Pandya ep->stid = cxgb4_alloc_sftid(dev->rdev.lldi.tids, 3252830662f6SVipul Pandya cm_id->local_addr.ss_family, ep); 32531cab775cSVipul Pandya else 3254830662f6SVipul Pandya ep->stid = cxgb4_alloc_stid(dev->rdev.lldi.tids, 3255830662f6SVipul Pandya cm_id->local_addr.ss_family, ep); 32561cab775cSVipul Pandya 3257cfdda9d7SSteve Wise if (ep->stid == -1) { 3258be4c9badSRoland Dreier printk(KERN_ERR MOD "%s - cannot alloc stid.\n", __func__); 3259cfdda9d7SSteve Wise err = -ENOMEM; 3260cfdda9d7SSteve Wise goto fail2; 3261cfdda9d7SSteve Wise } 3262793dad94SVipul Pandya insert_handle(dev, &dev->stid_idr, ep, ep->stid); 32639eccfe10SSteve Wise 32649eccfe10SSteve Wise /* No port mapper available, go with the specified info */ 32659eccfe10SSteve Wise memcpy(&ep->com.mapped_local_addr, &cm_id->local_addr, 32669eccfe10SSteve Wise sizeof(ep->com.mapped_local_addr)); 32679eccfe10SSteve Wise 32689eccfe10SSteve Wise c4iw_form_reg_msg(dev, &pm_reg_msg); 32699eccfe10SSteve Wise iwpm_err = iwpm_register_pid(&pm_reg_msg, RDMA_NL_C4IW); 32709eccfe10SSteve Wise if (iwpm_err) { 32719eccfe10SSteve Wise PDBG("%s: Port Mapper reg pid fail (err = %d).\n", 32729eccfe10SSteve Wise __func__, iwpm_err); 32739eccfe10SSteve Wise } 32749eccfe10SSteve Wise if (iwpm_valid_pid() && !iwpm_err) { 32759eccfe10SSteve Wise memcpy(&pm_msg.loc_addr, &ep->com.local_addr, 32769eccfe10SSteve Wise sizeof(ep->com.local_addr)); 32779eccfe10SSteve Wise iwpm_err = iwpm_add_mapping(&pm_msg, RDMA_NL_C4IW); 32789eccfe10SSteve Wise if (iwpm_err) 32799eccfe10SSteve Wise PDBG("%s: Port Mapper query fail (err = %d).\n", 32809eccfe10SSteve Wise __func__, iwpm_err); 32819eccfe10SSteve Wise else 32829eccfe10SSteve Wise memcpy(&ep->com.mapped_local_addr, 32839eccfe10SSteve Wise &pm_msg.mapped_loc_addr, 32849eccfe10SSteve Wise sizeof(ep->com.mapped_local_addr)); 32859eccfe10SSteve Wise } 32869eccfe10SSteve Wise if (iwpm_create_mapinfo(&ep->com.local_addr, 32879eccfe10SSteve Wise &ep->com.mapped_local_addr, RDMA_NL_C4IW)) { 32889eccfe10SSteve Wise err = -ENOMEM; 32899eccfe10SSteve Wise goto fail3; 32909eccfe10SSteve Wise } 32919eccfe10SSteve Wise print_addr(&ep->com, __func__, "add_mapping/create_mapinfo"); 32929eccfe10SSteve Wise 32939eccfe10SSteve Wise set_bit(RELEASE_MAPINFO, &ep->com.flags); 3294cfdda9d7SSteve Wise state_set(&ep->com, LISTEN); 3295830662f6SVipul Pandya if (ep->com.local_addr.ss_family == AF_INET) 3296830662f6SVipul Pandya err = create_server4(dev, ep); 3297830662f6SVipul Pandya else 3298830662f6SVipul Pandya err = create_server6(dev, ep); 3299cfdda9d7SSteve Wise if (!err) { 3300cfdda9d7SSteve Wise cm_id->provider_data = ep; 3301cfdda9d7SSteve Wise goto out; 3302cfdda9d7SSteve Wise } 33039eccfe10SSteve Wise 33049eccfe10SSteve Wise fail3: 3305830662f6SVipul Pandya cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, 3306830662f6SVipul Pandya ep->com.local_addr.ss_family); 3307cfdda9d7SSteve Wise fail2: 3308cfdda9d7SSteve Wise cm_id->rem_ref(cm_id); 3309cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3310cfdda9d7SSteve Wise fail1: 3311cfdda9d7SSteve Wise out: 3312cfdda9d7SSteve Wise return err; 3313cfdda9d7SSteve Wise } 3314cfdda9d7SSteve Wise 3315cfdda9d7SSteve Wise int c4iw_destroy_listen(struct iw_cm_id *cm_id) 3316cfdda9d7SSteve Wise { 3317cfdda9d7SSteve Wise int err; 3318cfdda9d7SSteve Wise struct c4iw_listen_ep *ep = to_listen_ep(cm_id); 3319cfdda9d7SSteve Wise 3320cfdda9d7SSteve Wise PDBG("%s ep %p\n", __func__, ep); 3321cfdda9d7SSteve Wise 3322cfdda9d7SSteve Wise might_sleep(); 3323cfdda9d7SSteve Wise state_set(&ep->com, DEAD); 3324830662f6SVipul Pandya if (ep->com.dev->rdev.lldi.enable_fw_ofld_conn && 3325830662f6SVipul Pandya ep->com.local_addr.ss_family == AF_INET) { 33261cab775cSVipul Pandya err = cxgb4_remove_server_filter( 33271cab775cSVipul Pandya ep->com.dev->rdev.lldi.ports[0], ep->stid, 33281cab775cSVipul Pandya ep->com.dev->rdev.lldi.rxq_ids[0], 0); 33291cab775cSVipul Pandya } else { 3330aadc4df3SSteve Wise c4iw_init_wr_wait(&ep->com.wr_wait); 3331830662f6SVipul Pandya err = cxgb4_remove_server( 3332830662f6SVipul Pandya ep->com.dev->rdev.lldi.ports[0], ep->stid, 3333830662f6SVipul Pandya ep->com.dev->rdev.lldi.rxq_ids[0], 0); 3334cfdda9d7SSteve Wise if (err) 3335cfdda9d7SSteve Wise goto done; 33361cab775cSVipul Pandya err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait, 33371cab775cSVipul Pandya 0, 0, __func__); 33381cab775cSVipul Pandya } 3339793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->stid_idr, ep->stid); 3340830662f6SVipul Pandya cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, 3341830662f6SVipul Pandya ep->com.local_addr.ss_family); 3342cfdda9d7SSteve Wise done: 3343cfdda9d7SSteve Wise cm_id->rem_ref(cm_id); 3344cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3345cfdda9d7SSteve Wise return err; 3346cfdda9d7SSteve Wise } 3347cfdda9d7SSteve Wise 3348cfdda9d7SSteve Wise int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) 3349cfdda9d7SSteve Wise { 3350cfdda9d7SSteve Wise int ret = 0; 3351cfdda9d7SSteve Wise int close = 0; 3352cfdda9d7SSteve Wise int fatal = 0; 3353cfdda9d7SSteve Wise struct c4iw_rdev *rdev; 3354cfdda9d7SSteve Wise 33552f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 3356cfdda9d7SSteve Wise 3357cfdda9d7SSteve Wise PDBG("%s ep %p state %s, abrupt %d\n", __func__, ep, 3358cfdda9d7SSteve Wise states[ep->com.state], abrupt); 3359cfdda9d7SSteve Wise 3360cfdda9d7SSteve Wise rdev = &ep->com.dev->rdev; 3361cfdda9d7SSteve Wise if (c4iw_fatal_error(rdev)) { 3362cfdda9d7SSteve Wise fatal = 1; 3363be13b2dfSSteve Wise close_complete_upcall(ep, -EIO); 3364cfdda9d7SSteve Wise ep->com.state = DEAD; 3365cfdda9d7SSteve Wise } 3366cfdda9d7SSteve Wise switch (ep->com.state) { 3367cfdda9d7SSteve Wise case MPA_REQ_WAIT: 3368cfdda9d7SSteve Wise case MPA_REQ_SENT: 3369cfdda9d7SSteve Wise case MPA_REQ_RCVD: 3370cfdda9d7SSteve Wise case MPA_REP_SENT: 3371cfdda9d7SSteve Wise case FPDU_MODE: 3372cfdda9d7SSteve Wise close = 1; 3373cfdda9d7SSteve Wise if (abrupt) 3374cfdda9d7SSteve Wise ep->com.state = ABORTING; 3375cfdda9d7SSteve Wise else { 3376cfdda9d7SSteve Wise ep->com.state = CLOSING; 3377ca5a2202SSteve Wise start_ep_timer(ep); 3378cfdda9d7SSteve Wise } 3379cfdda9d7SSteve Wise set_bit(CLOSE_SENT, &ep->com.flags); 3380cfdda9d7SSteve Wise break; 3381cfdda9d7SSteve Wise case CLOSING: 3382cfdda9d7SSteve Wise if (!test_and_set_bit(CLOSE_SENT, &ep->com.flags)) { 3383cfdda9d7SSteve Wise close = 1; 3384cfdda9d7SSteve Wise if (abrupt) { 3385b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 3386cfdda9d7SSteve Wise ep->com.state = ABORTING; 3387cfdda9d7SSteve Wise } else 3388cfdda9d7SSteve Wise ep->com.state = MORIBUND; 3389cfdda9d7SSteve Wise } 3390cfdda9d7SSteve Wise break; 3391cfdda9d7SSteve Wise case MORIBUND: 3392cfdda9d7SSteve Wise case ABORTING: 3393cfdda9d7SSteve Wise case DEAD: 3394cfdda9d7SSteve Wise PDBG("%s ignoring disconnect ep %p state %u\n", 3395cfdda9d7SSteve Wise __func__, ep, ep->com.state); 3396cfdda9d7SSteve Wise break; 3397cfdda9d7SSteve Wise default: 3398cfdda9d7SSteve Wise BUG(); 3399cfdda9d7SSteve Wise break; 3400cfdda9d7SSteve Wise } 3401cfdda9d7SSteve Wise 3402cfdda9d7SSteve Wise if (close) { 34038da7e7a5SSteve Wise if (abrupt) { 3404793dad94SVipul Pandya set_bit(EP_DISC_ABORT, &ep->com.history); 3405be13b2dfSSteve Wise close_complete_upcall(ep, -ECONNRESET); 34068da7e7a5SSteve Wise ret = send_abort(ep, NULL, gfp); 3407793dad94SVipul Pandya } else { 3408793dad94SVipul Pandya set_bit(EP_DISC_CLOSE, &ep->com.history); 3409cfdda9d7SSteve Wise ret = send_halfclose(ep, gfp); 3410793dad94SVipul Pandya } 3411cfdda9d7SSteve Wise if (ret) 3412cfdda9d7SSteve Wise fatal = 1; 3413cfdda9d7SSteve Wise } 34148da7e7a5SSteve Wise mutex_unlock(&ep->com.mutex); 3415cfdda9d7SSteve Wise if (fatal) 3416cfdda9d7SSteve Wise release_ep_resources(ep); 3417cfdda9d7SSteve Wise return ret; 3418cfdda9d7SSteve Wise } 3419cfdda9d7SSteve Wise 34201cab775cSVipul Pandya static void active_ofld_conn_reply(struct c4iw_dev *dev, struct sk_buff *skb, 34211cab775cSVipul Pandya struct cpl_fw6_msg_ofld_connection_wr_rpl *req) 34221cab775cSVipul Pandya { 34231cab775cSVipul Pandya struct c4iw_ep *ep; 3424793dad94SVipul Pandya int atid = be32_to_cpu(req->tid); 34251cab775cSVipul Pandya 3426ef5d6355SVipul Pandya ep = (struct c4iw_ep *)lookup_atid(dev->rdev.lldi.tids, 3427ef5d6355SVipul Pandya (__force u32) req->tid); 34281cab775cSVipul Pandya if (!ep) 34291cab775cSVipul Pandya return; 34301cab775cSVipul Pandya 34311cab775cSVipul Pandya switch (req->retval) { 34321cab775cSVipul Pandya case FW_ENOMEM: 3433793dad94SVipul Pandya set_bit(ACT_RETRY_NOMEM, &ep->com.history); 3434793dad94SVipul Pandya if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) { 3435793dad94SVipul Pandya send_fw_act_open_req(ep, atid); 3436793dad94SVipul Pandya return; 3437793dad94SVipul Pandya } 34381cab775cSVipul Pandya case FW_EADDRINUSE: 3439793dad94SVipul Pandya set_bit(ACT_RETRY_INUSE, &ep->com.history); 3440793dad94SVipul Pandya if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) { 3441793dad94SVipul Pandya send_fw_act_open_req(ep, atid); 3442793dad94SVipul Pandya return; 3443793dad94SVipul Pandya } 34441cab775cSVipul Pandya break; 34451cab775cSVipul Pandya default: 34461cab775cSVipul Pandya pr_info("%s unexpected ofld conn wr retval %d\n", 34471cab775cSVipul Pandya __func__, req->retval); 34481cab775cSVipul Pandya break; 34491cab775cSVipul Pandya } 3450793dad94SVipul Pandya pr_err("active ofld_connect_wr failure %d atid %d\n", 3451793dad94SVipul Pandya req->retval, atid); 3452793dad94SVipul Pandya mutex_lock(&dev->rdev.stats.lock); 3453793dad94SVipul Pandya dev->rdev.stats.act_ofld_conn_fails++; 3454793dad94SVipul Pandya mutex_unlock(&dev->rdev.stats.lock); 34551cab775cSVipul Pandya connect_reply_upcall(ep, status2errno(req->retval)); 3456793dad94SVipul Pandya state_set(&ep->com, DEAD); 3457793dad94SVipul Pandya remove_handle(dev, &dev->atid_idr, atid); 3458793dad94SVipul Pandya cxgb4_free_atid(dev->rdev.lldi.tids, atid); 3459793dad94SVipul Pandya dst_release(ep->dst); 3460793dad94SVipul Pandya cxgb4_l2t_release(ep->l2t); 3461793dad94SVipul Pandya c4iw_put_ep(&ep->com); 34621cab775cSVipul Pandya } 34631cab775cSVipul Pandya 34641cab775cSVipul Pandya static void passive_ofld_conn_reply(struct c4iw_dev *dev, struct sk_buff *skb, 34651cab775cSVipul Pandya struct cpl_fw6_msg_ofld_connection_wr_rpl *req) 34661cab775cSVipul Pandya { 34671cab775cSVipul Pandya struct sk_buff *rpl_skb; 34681cab775cSVipul Pandya struct cpl_pass_accept_req *cpl; 34691cab775cSVipul Pandya int ret; 34701cab775cSVipul Pandya 3471710a3110SPaul Bolle rpl_skb = (struct sk_buff *)(unsigned long)req->cookie; 34721cab775cSVipul Pandya BUG_ON(!rpl_skb); 34731cab775cSVipul Pandya if (req->retval) { 34741cab775cSVipul Pandya PDBG("%s passive open failure %d\n", __func__, req->retval); 3475793dad94SVipul Pandya mutex_lock(&dev->rdev.stats.lock); 3476793dad94SVipul Pandya dev->rdev.stats.pas_ofld_conn_fails++; 3477793dad94SVipul Pandya mutex_unlock(&dev->rdev.stats.lock); 34781cab775cSVipul Pandya kfree_skb(rpl_skb); 34791cab775cSVipul Pandya } else { 34801cab775cSVipul Pandya cpl = (struct cpl_pass_accept_req *)cplhdr(rpl_skb); 34811cab775cSVipul Pandya OPCODE_TID(cpl) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_REQ, 3482ef5d6355SVipul Pandya (__force u32) htonl( 3483ef5d6355SVipul Pandya (__force u32) req->tid))); 34841cab775cSVipul Pandya ret = pass_accept_req(dev, rpl_skb); 34851cab775cSVipul Pandya if (!ret) 34861cab775cSVipul Pandya kfree_skb(rpl_skb); 34871cab775cSVipul Pandya } 34881cab775cSVipul Pandya return; 34891cab775cSVipul Pandya } 34901cab775cSVipul Pandya 34911cab775cSVipul Pandya static int deferred_fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb) 34922f5b48c3SSteve Wise { 34932f5b48c3SSteve Wise struct cpl_fw6_msg *rpl = cplhdr(skb); 34941cab775cSVipul Pandya struct cpl_fw6_msg_ofld_connection_wr_rpl *req; 34951cab775cSVipul Pandya 34961cab775cSVipul Pandya switch (rpl->type) { 34971cab775cSVipul Pandya case FW6_TYPE_CQE: 34982f5b48c3SSteve Wise c4iw_ev_dispatch(dev, (struct t4_cqe *)&rpl->data[0]); 34991cab775cSVipul Pandya break; 35001cab775cSVipul Pandya case FW6_TYPE_OFLD_CONNECTION_WR_RPL: 35011cab775cSVipul Pandya req = (struct cpl_fw6_msg_ofld_connection_wr_rpl *)rpl->data; 35021cab775cSVipul Pandya switch (req->t_state) { 35031cab775cSVipul Pandya case TCP_SYN_SENT: 35041cab775cSVipul Pandya active_ofld_conn_reply(dev, skb, req); 35051cab775cSVipul Pandya break; 35061cab775cSVipul Pandya case TCP_SYN_RECV: 35071cab775cSVipul Pandya passive_ofld_conn_reply(dev, skb, req); 35081cab775cSVipul Pandya break; 35091cab775cSVipul Pandya default: 35101cab775cSVipul Pandya pr_err("%s unexpected ofld conn wr state %d\n", 35111cab775cSVipul Pandya __func__, req->t_state); 35121cab775cSVipul Pandya break; 35131cab775cSVipul Pandya } 35141cab775cSVipul Pandya break; 35151cab775cSVipul Pandya } 35161cab775cSVipul Pandya return 0; 35171cab775cSVipul Pandya } 35181cab775cSVipul Pandya 35191cab775cSVipul Pandya static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos) 35201cab775cSVipul Pandya { 35211cab775cSVipul Pandya u32 l2info; 3522f079af7aSVipul Pandya u16 vlantag, len, hdr_len, eth_hdr_len; 35231cab775cSVipul Pandya u8 intf; 35241cab775cSVipul Pandya struct cpl_rx_pkt *cpl = cplhdr(skb); 35251cab775cSVipul Pandya struct cpl_pass_accept_req *req; 35261cab775cSVipul Pandya struct tcp_options_received tmp_opt; 3527f079af7aSVipul Pandya struct c4iw_dev *dev; 35281cab775cSVipul Pandya 3529f079af7aSVipul Pandya dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *))); 35301cab775cSVipul Pandya /* Store values from cpl_rx_pkt in temporary location. */ 3531ef5d6355SVipul Pandya vlantag = (__force u16) cpl->vlan; 3532ef5d6355SVipul Pandya len = (__force u16) cpl->len; 3533ef5d6355SVipul Pandya l2info = (__force u32) cpl->l2info; 3534ef5d6355SVipul Pandya hdr_len = (__force u16) cpl->hdr_len; 35351cab775cSVipul Pandya intf = cpl->iff; 35361cab775cSVipul Pandya 35371cab775cSVipul Pandya __skb_pull(skb, sizeof(*req) + sizeof(struct rss_header)); 35381cab775cSVipul Pandya 35391cab775cSVipul Pandya /* 35401cab775cSVipul Pandya * We need to parse the TCP options from SYN packet. 35411cab775cSVipul Pandya * to generate cpl_pass_accept_req. 35421cab775cSVipul Pandya */ 35431cab775cSVipul Pandya memset(&tmp_opt, 0, sizeof(tmp_opt)); 35441cab775cSVipul Pandya tcp_clear_options(&tmp_opt); 35451a2c6181SChristoph Paasch tcp_parse_options(skb, &tmp_opt, 0, NULL); 35461cab775cSVipul Pandya 35471cab775cSVipul Pandya req = (struct cpl_pass_accept_req *)__skb_push(skb, sizeof(*req)); 35481cab775cSVipul Pandya memset(req, 0, sizeof(*req)); 3549cf7fe64aSHariprasad Shenai req->l2info = cpu_to_be16(SYN_INTF_V(intf) | 3550cf7fe64aSHariprasad Shenai SYN_MAC_IDX_V(RX_MACIDX_G( 3551ef5d6355SVipul Pandya (__force int) htonl(l2info))) | 3552cf7fe64aSHariprasad Shenai SYN_XACT_MATCH_F); 3553f079af7aSVipul Pandya eth_hdr_len = is_t4(dev->rdev.lldi.adapter_type) ? 3554bdc590b9SHariprasad Shenai RX_ETHHDR_LEN_G((__force int)htonl(l2info)) : 3555bdc590b9SHariprasad Shenai RX_T5_ETHHDR_LEN_G((__force int)htonl(l2info)); 3556cf7fe64aSHariprasad Shenai req->hdr_len = cpu_to_be32(SYN_RX_CHAN_V(RX_CHAN_G( 3557ef5d6355SVipul Pandya (__force int) htonl(l2info))) | 3558cf7fe64aSHariprasad Shenai TCP_HDR_LEN_V(RX_TCPHDR_LEN_G( 3559ef5d6355SVipul Pandya (__force int) htons(hdr_len))) | 3560cf7fe64aSHariprasad Shenai IP_HDR_LEN_V(RX_IPHDR_LEN_G( 3561ef5d6355SVipul Pandya (__force int) htons(hdr_len))) | 3562cf7fe64aSHariprasad Shenai ETH_HDR_LEN_V(RX_ETHHDR_LEN_G(eth_hdr_len))); 3563ef5d6355SVipul Pandya req->vlan = (__force __be16) vlantag; 3564ef5d6355SVipul Pandya req->len = (__force __be16) len; 35656c53e938SHariprasad Shenai req->tos_stid = cpu_to_be32(PASS_OPEN_TID_V(stid) | 35666c53e938SHariprasad Shenai PASS_OPEN_TOS_V(tos)); 35671cab775cSVipul Pandya req->tcpopt.mss = htons(tmp_opt.mss_clamp); 35681cab775cSVipul Pandya if (tmp_opt.wscale_ok) 35691cab775cSVipul Pandya req->tcpopt.wsf = tmp_opt.snd_wscale; 35701cab775cSVipul Pandya req->tcpopt.tstamp = tmp_opt.saw_tstamp; 35711cab775cSVipul Pandya if (tmp_opt.sack_ok) 35721cab775cSVipul Pandya req->tcpopt.sack = 1; 35731cab775cSVipul Pandya OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_REQ, 0)); 35741cab775cSVipul Pandya return; 35751cab775cSVipul Pandya } 35761cab775cSVipul Pandya 35771cab775cSVipul Pandya static void send_fw_pass_open_req(struct c4iw_dev *dev, struct sk_buff *skb, 35781cab775cSVipul Pandya __be32 laddr, __be16 lport, 35791cab775cSVipul Pandya __be32 raddr, __be16 rport, 35801cab775cSVipul Pandya u32 rcv_isn, u32 filter, u16 window, 35811cab775cSVipul Pandya u32 rss_qid, u8 port_id) 35821cab775cSVipul Pandya { 35831cab775cSVipul Pandya struct sk_buff *req_skb; 35841cab775cSVipul Pandya struct fw_ofld_connection_wr *req; 35851cab775cSVipul Pandya struct cpl_pass_accept_req *cpl = cplhdr(skb); 35861ce1d471SSteve Wise int ret; 35871cab775cSVipul Pandya 35881cab775cSVipul Pandya req_skb = alloc_skb(sizeof(struct fw_ofld_connection_wr), GFP_KERNEL); 35891cab775cSVipul Pandya req = (struct fw_ofld_connection_wr *)__skb_put(req_skb, sizeof(*req)); 35901cab775cSVipul Pandya memset(req, 0, sizeof(*req)); 35916c53e938SHariprasad Shenai req->op_compl = htonl(WR_OP_V(FW_OFLD_CONNECTION_WR) | FW_WR_COMPL_F); 3592e2ac9628SHariprasad Shenai req->len16_pkd = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*req), 16))); 359377a80e23SHariprasad Shenai req->le.version_cpl = htonl(FW_OFLD_CONNECTION_WR_CPL_F); 3594ef5d6355SVipul Pandya req->le.filter = (__force __be32) filter; 35951cab775cSVipul Pandya req->le.lport = lport; 35961cab775cSVipul Pandya req->le.pport = rport; 35971cab775cSVipul Pandya req->le.u.ipv4.lip = laddr; 35981cab775cSVipul Pandya req->le.u.ipv4.pip = raddr; 35991cab775cSVipul Pandya req->tcb.rcv_nxt = htonl(rcv_isn + 1); 36001cab775cSVipul Pandya req->tcb.rcv_adv = htons(window); 36011cab775cSVipul Pandya req->tcb.t_state_to_astid = 360277a80e23SHariprasad Shenai htonl(FW_OFLD_CONNECTION_WR_T_STATE_V(TCP_SYN_RECV) | 360377a80e23SHariprasad Shenai FW_OFLD_CONNECTION_WR_RCV_SCALE_V(cpl->tcpopt.wsf) | 360477a80e23SHariprasad Shenai FW_OFLD_CONNECTION_WR_ASTID_V( 36056c53e938SHariprasad Shenai PASS_OPEN_TID_G(ntohl(cpl->tos_stid)))); 36061cab775cSVipul Pandya 36071cab775cSVipul Pandya /* 36081cab775cSVipul Pandya * We store the qid in opt2 which will be used by the firmware 36091cab775cSVipul Pandya * to send us the wr response. 36101cab775cSVipul Pandya */ 3611d7990b0cSAnish Bhatt req->tcb.opt2 = htonl(RSS_QUEUE_V(rss_qid)); 36121cab775cSVipul Pandya 36131cab775cSVipul Pandya /* 36141cab775cSVipul Pandya * We initialize the MSS index in TCB to 0xF. 36151cab775cSVipul Pandya * So that when driver sends cpl_pass_accept_rpl 36161cab775cSVipul Pandya * TCB picks up the correct value. If this was 0 36171cab775cSVipul Pandya * TP will ignore any value > 0 for MSS index. 36181cab775cSVipul Pandya */ 3619d7990b0cSAnish Bhatt req->tcb.opt0 = cpu_to_be64(MSS_IDX_V(0xF)); 36206198dd8dSHariprasad S req->cookie = (uintptr_t)skb; 36211cab775cSVipul Pandya 36221cab775cSVipul Pandya set_wr_txq(req_skb, CPL_PRIORITY_CONTROL, port_id); 36231ce1d471SSteve Wise ret = cxgb4_ofld_send(dev->rdev.lldi.ports[0], req_skb); 36241ce1d471SSteve Wise if (ret < 0) { 36251ce1d471SSteve Wise pr_err("%s - cxgb4_ofld_send error %d - dropping\n", __func__, 36261ce1d471SSteve Wise ret); 36271ce1d471SSteve Wise kfree_skb(skb); 36281ce1d471SSteve Wise kfree_skb(req_skb); 36291ce1d471SSteve Wise } 36301cab775cSVipul Pandya } 36311cab775cSVipul Pandya 36321cab775cSVipul Pandya /* 36331cab775cSVipul Pandya * Handler for CPL_RX_PKT message. Need to handle cpl_rx_pkt 36341cab775cSVipul Pandya * messages when a filter is being used instead of server to 36351cab775cSVipul Pandya * redirect a syn packet. When packets hit filter they are redirected 36361cab775cSVipul Pandya * to the offload queue and driver tries to establish the connection 36371cab775cSVipul Pandya * using firmware work request. 36381cab775cSVipul Pandya */ 36391cab775cSVipul Pandya static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb) 36401cab775cSVipul Pandya { 36411cab775cSVipul Pandya int stid; 36421cab775cSVipul Pandya unsigned int filter; 36431cab775cSVipul Pandya struct ethhdr *eh = NULL; 36441cab775cSVipul Pandya struct vlan_ethhdr *vlan_eh = NULL; 36451cab775cSVipul Pandya struct iphdr *iph; 36461cab775cSVipul Pandya struct tcphdr *tcph; 36471cab775cSVipul Pandya struct rss_header *rss = (void *)skb->data; 36481cab775cSVipul Pandya struct cpl_rx_pkt *cpl = (void *)skb->data; 36491cab775cSVipul Pandya struct cpl_pass_accept_req *req = (void *)(rss + 1); 36501cab775cSVipul Pandya struct l2t_entry *e; 36511cab775cSVipul Pandya struct dst_entry *dst; 36521cab775cSVipul Pandya struct c4iw_ep *lep; 36531cab775cSVipul Pandya u16 window; 36541cab775cSVipul Pandya struct port_info *pi; 36551cab775cSVipul Pandya struct net_device *pdev; 3656f079af7aSVipul Pandya u16 rss_qid, eth_hdr_len; 36571cab775cSVipul Pandya int step; 36581cab775cSVipul Pandya u32 tx_chan; 36591cab775cSVipul Pandya struct neighbour *neigh; 36601cab775cSVipul Pandya 36611cab775cSVipul Pandya /* Drop all non-SYN packets */ 3662bdc590b9SHariprasad Shenai if (!(cpl->l2info & cpu_to_be32(RXF_SYN_F))) 36631cab775cSVipul Pandya goto reject; 36641cab775cSVipul Pandya 36651cab775cSVipul Pandya /* 36661cab775cSVipul Pandya * Drop all packets which did not hit the filter. 36671cab775cSVipul Pandya * Unlikely to happen. 36681cab775cSVipul Pandya */ 36691cab775cSVipul Pandya if (!(rss->filter_hit && rss->filter_tid)) 36701cab775cSVipul Pandya goto reject; 36711cab775cSVipul Pandya 36721cab775cSVipul Pandya /* 36731cab775cSVipul Pandya * Calculate the server tid from filter hit index from cpl_rx_pkt. 36741cab775cSVipul Pandya */ 3675a4ea025fSKumar Sanghvi stid = (__force int) cpu_to_be32((__force u32) rss->hash_val); 36761cab775cSVipul Pandya 36771cab775cSVipul Pandya lep = (struct c4iw_ep *)lookup_stid(dev->rdev.lldi.tids, stid); 36781cab775cSVipul Pandya if (!lep) { 36791cab775cSVipul Pandya PDBG("%s connect request on invalid stid %d\n", __func__, stid); 36801cab775cSVipul Pandya goto reject; 36811cab775cSVipul Pandya } 36821cab775cSVipul Pandya 3683f079af7aSVipul Pandya eth_hdr_len = is_t4(dev->rdev.lldi.adapter_type) ? 3684bdc590b9SHariprasad Shenai RX_ETHHDR_LEN_G(htonl(cpl->l2info)) : 3685bdc590b9SHariprasad Shenai RX_T5_ETHHDR_LEN_G(htonl(cpl->l2info)); 3686f079af7aSVipul Pandya if (eth_hdr_len == ETH_HLEN) { 36871cab775cSVipul Pandya eh = (struct ethhdr *)(req + 1); 36881cab775cSVipul Pandya iph = (struct iphdr *)(eh + 1); 36891cab775cSVipul Pandya } else { 36901cab775cSVipul Pandya vlan_eh = (struct vlan_ethhdr *)(req + 1); 36911cab775cSVipul Pandya iph = (struct iphdr *)(vlan_eh + 1); 36921cab775cSVipul Pandya skb->vlan_tci = ntohs(cpl->vlan); 36931cab775cSVipul Pandya } 36941cab775cSVipul Pandya 36951cab775cSVipul Pandya if (iph->version != 0x4) 36961cab775cSVipul Pandya goto reject; 36971cab775cSVipul Pandya 36981cab775cSVipul Pandya tcph = (struct tcphdr *)(iph + 1); 36991cab775cSVipul Pandya skb_set_network_header(skb, (void *)iph - (void *)rss); 37001cab775cSVipul Pandya skb_set_transport_header(skb, (void *)tcph - (void *)rss); 37011cab775cSVipul Pandya skb_get(skb); 37021cab775cSVipul Pandya 37031cab775cSVipul Pandya PDBG("%s lip 0x%x lport %u pip 0x%x pport %u tos %d\n", __func__, 37041cab775cSVipul Pandya ntohl(iph->daddr), ntohs(tcph->dest), ntohl(iph->saddr), 37051cab775cSVipul Pandya ntohs(tcph->source), iph->tos); 37061cab775cSVipul Pandya 3707830662f6SVipul Pandya dst = find_route(dev, iph->daddr, iph->saddr, tcph->dest, tcph->source, 37081cab775cSVipul Pandya iph->tos); 3709830662f6SVipul Pandya if (!dst) { 37101cab775cSVipul Pandya pr_err("%s - failed to find dst entry!\n", 37111cab775cSVipul Pandya __func__); 37121cab775cSVipul Pandya goto reject; 37131cab775cSVipul Pandya } 37141cab775cSVipul Pandya neigh = dst_neigh_lookup_skb(dst, skb); 37151cab775cSVipul Pandya 3716aaa0c23cSZhouyi Zhou if (!neigh) { 3717aaa0c23cSZhouyi Zhou pr_err("%s - failed to allocate neigh!\n", 3718aaa0c23cSZhouyi Zhou __func__); 3719aaa0c23cSZhouyi Zhou goto free_dst; 3720aaa0c23cSZhouyi Zhou } 3721aaa0c23cSZhouyi Zhou 37221cab775cSVipul Pandya if (neigh->dev->flags & IFF_LOOPBACK) { 37231cab775cSVipul Pandya pdev = ip_dev_find(&init_net, iph->daddr); 37241cab775cSVipul Pandya e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, 37251cab775cSVipul Pandya pdev, 0); 37261cab775cSVipul Pandya pi = (struct port_info *)netdev_priv(pdev); 37271cab775cSVipul Pandya tx_chan = cxgb4_port_chan(pdev); 37281cab775cSVipul Pandya dev_put(pdev); 37291cab775cSVipul Pandya } else { 3730830662f6SVipul Pandya pdev = get_real_dev(neigh->dev); 37311cab775cSVipul Pandya e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, 3732830662f6SVipul Pandya pdev, 0); 3733830662f6SVipul Pandya pi = (struct port_info *)netdev_priv(pdev); 3734830662f6SVipul Pandya tx_chan = cxgb4_port_chan(pdev); 37351cab775cSVipul Pandya } 3736ebf00060SSteve Wise neigh_release(neigh); 37371cab775cSVipul Pandya if (!e) { 37381cab775cSVipul Pandya pr_err("%s - failed to allocate l2t entry!\n", 37391cab775cSVipul Pandya __func__); 37401cab775cSVipul Pandya goto free_dst; 37411cab775cSVipul Pandya } 37421cab775cSVipul Pandya 37431cab775cSVipul Pandya step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan; 37441cab775cSVipul Pandya rss_qid = dev->rdev.lldi.rxq_ids[pi->port_id * step]; 3745ef5d6355SVipul Pandya window = (__force u16) htons((__force u16)tcph->window); 37461cab775cSVipul Pandya 37471cab775cSVipul Pandya /* Calcuate filter portion for LE region. */ 374841b4f86cSKumar Sanghvi filter = (__force unsigned int) cpu_to_be32(cxgb4_select_ntuple( 374941b4f86cSKumar Sanghvi dev->rdev.lldi.ports[0], 375041b4f86cSKumar Sanghvi e)); 37511cab775cSVipul Pandya 37521cab775cSVipul Pandya /* 37531cab775cSVipul Pandya * Synthesize the cpl_pass_accept_req. We have everything except the 37541cab775cSVipul Pandya * TID. Once firmware sends a reply with TID we update the TID field 37551cab775cSVipul Pandya * in cpl and pass it through the regular cpl_pass_accept_req path. 37561cab775cSVipul Pandya */ 37571cab775cSVipul Pandya build_cpl_pass_accept_req(skb, stid, iph->tos); 37581cab775cSVipul Pandya send_fw_pass_open_req(dev, skb, iph->daddr, tcph->dest, iph->saddr, 37591cab775cSVipul Pandya tcph->source, ntohl(tcph->seq), filter, window, 37601cab775cSVipul Pandya rss_qid, pi->port_id); 37611cab775cSVipul Pandya cxgb4_l2t_release(e); 37621cab775cSVipul Pandya free_dst: 37631cab775cSVipul Pandya dst_release(dst); 37641cab775cSVipul Pandya reject: 37652f5b48c3SSteve Wise return 0; 37662f5b48c3SSteve Wise } 37672f5b48c3SSteve Wise 3768cfdda9d7SSteve Wise /* 3769be4c9badSRoland Dreier * These are the real handlers that are called from a 3770be4c9badSRoland Dreier * work queue. 3771be4c9badSRoland Dreier */ 3772be4c9badSRoland Dreier static c4iw_handler_func work_handlers[NUM_CPL_CMDS] = { 3773be4c9badSRoland Dreier [CPL_ACT_ESTABLISH] = act_establish, 3774be4c9badSRoland Dreier [CPL_ACT_OPEN_RPL] = act_open_rpl, 3775be4c9badSRoland Dreier [CPL_RX_DATA] = rx_data, 3776be4c9badSRoland Dreier [CPL_ABORT_RPL_RSS] = abort_rpl, 3777be4c9badSRoland Dreier [CPL_ABORT_RPL] = abort_rpl, 3778be4c9badSRoland Dreier [CPL_PASS_OPEN_RPL] = pass_open_rpl, 3779be4c9badSRoland Dreier [CPL_CLOSE_LISTSRV_RPL] = close_listsrv_rpl, 3780be4c9badSRoland Dreier [CPL_PASS_ACCEPT_REQ] = pass_accept_req, 3781be4c9badSRoland Dreier [CPL_PASS_ESTABLISH] = pass_establish, 3782be4c9badSRoland Dreier [CPL_PEER_CLOSE] = peer_close, 3783be4c9badSRoland Dreier [CPL_ABORT_REQ_RSS] = peer_abort, 3784be4c9badSRoland Dreier [CPL_CLOSE_CON_RPL] = close_con_rpl, 3785be4c9badSRoland Dreier [CPL_RDMA_TERMINATE] = terminate, 37862f5b48c3SSteve Wise [CPL_FW4_ACK] = fw4_ack, 37871cab775cSVipul Pandya [CPL_FW6_MSG] = deferred_fw6_msg, 37881cab775cSVipul Pandya [CPL_RX_PKT] = rx_pkt 3789be4c9badSRoland Dreier }; 3790be4c9badSRoland Dreier 3791be4c9badSRoland Dreier static void process_timeout(struct c4iw_ep *ep) 3792be4c9badSRoland Dreier { 3793be4c9badSRoland Dreier struct c4iw_qp_attributes attrs; 3794be4c9badSRoland Dreier int abort = 1; 3795be4c9badSRoland Dreier 37962f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 3797be4c9badSRoland Dreier PDBG("%s ep %p tid %u state %d\n", __func__, ep, ep->hwtid, 3798be4c9badSRoland Dreier ep->com.state); 3799793dad94SVipul Pandya set_bit(TIMEDOUT, &ep->com.history); 3800be4c9badSRoland Dreier switch (ep->com.state) { 3801be4c9badSRoland Dreier case MPA_REQ_SENT: 3802be4c9badSRoland Dreier __state_set(&ep->com, ABORTING); 3803be4c9badSRoland Dreier connect_reply_upcall(ep, -ETIMEDOUT); 3804be4c9badSRoland Dreier break; 3805be4c9badSRoland Dreier case MPA_REQ_WAIT: 3806be4c9badSRoland Dreier __state_set(&ep->com, ABORTING); 3807be4c9badSRoland Dreier break; 3808be4c9badSRoland Dreier case CLOSING: 3809be4c9badSRoland Dreier case MORIBUND: 3810be4c9badSRoland Dreier if (ep->com.cm_id && ep->com.qp) { 3811be4c9badSRoland Dreier attrs.next_state = C4IW_QP_STATE_ERROR; 3812be4c9badSRoland Dreier c4iw_modify_qp(ep->com.qp->rhp, 3813be4c9badSRoland Dreier ep->com.qp, C4IW_QP_ATTR_NEXT_STATE, 3814be4c9badSRoland Dreier &attrs, 1); 3815be4c9badSRoland Dreier } 3816be4c9badSRoland Dreier __state_set(&ep->com, ABORTING); 3817be13b2dfSSteve Wise close_complete_upcall(ep, -ETIMEDOUT); 3818be4c9badSRoland Dreier break; 3819b33bd0cbSSteve Wise case ABORTING: 3820b33bd0cbSSteve Wise case DEAD: 3821b33bd0cbSSteve Wise 3822b33bd0cbSSteve Wise /* 3823b33bd0cbSSteve Wise * These states are expected if the ep timed out at the same 3824b33bd0cbSSteve Wise * time as another thread was calling stop_ep_timer(). 3825b33bd0cbSSteve Wise * So we silently do nothing for these states. 3826b33bd0cbSSteve Wise */ 3827b33bd0cbSSteve Wise abort = 0; 3828b33bd0cbSSteve Wise break; 3829be4c9badSRoland Dreier default: 383076f267b7SJulia Lawall WARN(1, "%s unexpected state ep %p tid %u state %u\n", 3831be4c9badSRoland Dreier __func__, ep, ep->hwtid, ep->com.state); 3832be4c9badSRoland Dreier abort = 0; 3833be4c9badSRoland Dreier } 3834be4c9badSRoland Dreier if (abort) 3835be4c9badSRoland Dreier abort_connection(ep, NULL, GFP_KERNEL); 3836cc18b939SSteve Wise mutex_unlock(&ep->com.mutex); 3837be4c9badSRoland Dreier c4iw_put_ep(&ep->com); 3838be4c9badSRoland Dreier } 3839be4c9badSRoland Dreier 3840be4c9badSRoland Dreier static void process_timedout_eps(void) 3841be4c9badSRoland Dreier { 3842be4c9badSRoland Dreier struct c4iw_ep *ep; 3843be4c9badSRoland Dreier 3844be4c9badSRoland Dreier spin_lock_irq(&timeout_lock); 3845be4c9badSRoland Dreier while (!list_empty(&timeout_list)) { 3846be4c9badSRoland Dreier struct list_head *tmp; 3847be4c9badSRoland Dreier 3848be4c9badSRoland Dreier tmp = timeout_list.next; 3849be4c9badSRoland Dreier list_del(tmp); 3850b33bd0cbSSteve Wise tmp->next = NULL; 3851b33bd0cbSSteve Wise tmp->prev = NULL; 3852be4c9badSRoland Dreier spin_unlock_irq(&timeout_lock); 3853be4c9badSRoland Dreier ep = list_entry(tmp, struct c4iw_ep, entry); 3854be4c9badSRoland Dreier process_timeout(ep); 3855be4c9badSRoland Dreier spin_lock_irq(&timeout_lock); 3856be4c9badSRoland Dreier } 3857be4c9badSRoland Dreier spin_unlock_irq(&timeout_lock); 3858be4c9badSRoland Dreier } 3859be4c9badSRoland Dreier 3860be4c9badSRoland Dreier static void process_work(struct work_struct *work) 3861be4c9badSRoland Dreier { 3862be4c9badSRoland Dreier struct sk_buff *skb = NULL; 3863be4c9badSRoland Dreier struct c4iw_dev *dev; 3864c1d7356cSDan Carpenter struct cpl_act_establish *rpl; 3865be4c9badSRoland Dreier unsigned int opcode; 3866be4c9badSRoland Dreier int ret; 3867be4c9badSRoland Dreier 3868b33bd0cbSSteve Wise process_timedout_eps(); 3869be4c9badSRoland Dreier while ((skb = skb_dequeue(&rxq))) { 3870be4c9badSRoland Dreier rpl = cplhdr(skb); 3871be4c9badSRoland Dreier dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *))); 3872be4c9badSRoland Dreier opcode = rpl->ot.opcode; 3873be4c9badSRoland Dreier 3874be4c9badSRoland Dreier BUG_ON(!work_handlers[opcode]); 3875be4c9badSRoland Dreier ret = work_handlers[opcode](dev, skb); 3876be4c9badSRoland Dreier if (!ret) 3877be4c9badSRoland Dreier kfree_skb(skb); 3878be4c9badSRoland Dreier process_timedout_eps(); 3879be4c9badSRoland Dreier } 3880b33bd0cbSSteve Wise } 3881be4c9badSRoland Dreier 3882be4c9badSRoland Dreier static DECLARE_WORK(skb_work, process_work); 3883be4c9badSRoland Dreier 3884be4c9badSRoland Dreier static void ep_timeout(unsigned long arg) 3885be4c9badSRoland Dreier { 3886be4c9badSRoland Dreier struct c4iw_ep *ep = (struct c4iw_ep *)arg; 38871ec779ccSVipul Pandya int kickit = 0; 3888be4c9badSRoland Dreier 3889be4c9badSRoland Dreier spin_lock(&timeout_lock); 38901ec779ccSVipul Pandya if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) { 3891b33bd0cbSSteve Wise /* 3892b33bd0cbSSteve Wise * Only insert if it is not already on the list. 3893b33bd0cbSSteve Wise */ 3894b33bd0cbSSteve Wise if (!ep->entry.next) { 3895be4c9badSRoland Dreier list_add_tail(&ep->entry, &timeout_list); 38961ec779ccSVipul Pandya kickit = 1; 38971ec779ccSVipul Pandya } 3898b33bd0cbSSteve Wise } 3899be4c9badSRoland Dreier spin_unlock(&timeout_lock); 39001ec779ccSVipul Pandya if (kickit) 3901be4c9badSRoland Dreier queue_work(workq, &skb_work); 3902be4c9badSRoland Dreier } 3903be4c9badSRoland Dreier 3904be4c9badSRoland Dreier /* 3905cfdda9d7SSteve Wise * All the CM events are handled on a work queue to have a safe context. 3906cfdda9d7SSteve Wise */ 3907cfdda9d7SSteve Wise static int sched(struct c4iw_dev *dev, struct sk_buff *skb) 3908cfdda9d7SSteve Wise { 3909cfdda9d7SSteve Wise 3910cfdda9d7SSteve Wise /* 3911cfdda9d7SSteve Wise * Save dev in the skb->cb area. 3912cfdda9d7SSteve Wise */ 3913cfdda9d7SSteve Wise *((struct c4iw_dev **) (skb->cb + sizeof(void *))) = dev; 3914cfdda9d7SSteve Wise 3915cfdda9d7SSteve Wise /* 3916cfdda9d7SSteve Wise * Queue the skb and schedule the worker thread. 3917cfdda9d7SSteve Wise */ 3918cfdda9d7SSteve Wise skb_queue_tail(&rxq, skb); 3919cfdda9d7SSteve Wise queue_work(workq, &skb_work); 3920cfdda9d7SSteve Wise return 0; 3921cfdda9d7SSteve Wise } 3922cfdda9d7SSteve Wise 3923cfdda9d7SSteve Wise static int set_tcb_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 3924cfdda9d7SSteve Wise { 3925cfdda9d7SSteve Wise struct cpl_set_tcb_rpl *rpl = cplhdr(skb); 3926cfdda9d7SSteve Wise 3927cfdda9d7SSteve Wise if (rpl->status != CPL_ERR_NONE) { 3928cfdda9d7SSteve Wise printk(KERN_ERR MOD "Unexpected SET_TCB_RPL status %u " 3929cfdda9d7SSteve Wise "for tid %u\n", rpl->status, GET_TID(rpl)); 3930cfdda9d7SSteve Wise } 39312f5b48c3SSteve Wise kfree_skb(skb); 3932cfdda9d7SSteve Wise return 0; 3933cfdda9d7SSteve Wise } 3934cfdda9d7SSteve Wise 3935be4c9badSRoland Dreier static int fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb) 3936be4c9badSRoland Dreier { 3937be4c9badSRoland Dreier struct cpl_fw6_msg *rpl = cplhdr(skb); 3938be4c9badSRoland Dreier struct c4iw_wr_wait *wr_waitp; 3939be4c9badSRoland Dreier int ret; 3940be4c9badSRoland Dreier 3941be4c9badSRoland Dreier PDBG("%s type %u\n", __func__, rpl->type); 3942be4c9badSRoland Dreier 3943be4c9badSRoland Dreier switch (rpl->type) { 39445be78ee9SVipul Pandya case FW6_TYPE_WR_RPL: 3945be4c9badSRoland Dreier ret = (int)((be64_to_cpu(rpl->data[0]) >> 8) & 0xff); 3946c8e081a1SRoland Dreier wr_waitp = (struct c4iw_wr_wait *)(__force unsigned long) rpl->data[1]; 3947be4c9badSRoland Dreier PDBG("%s wr_waitp %p ret %u\n", __func__, wr_waitp, ret); 3948d9594d99SSteve Wise if (wr_waitp) 3949d9594d99SSteve Wise c4iw_wake_up(wr_waitp, ret ? -ret : 0); 39502f5b48c3SSteve Wise kfree_skb(skb); 3951be4c9badSRoland Dreier break; 39525be78ee9SVipul Pandya case FW6_TYPE_CQE: 39535be78ee9SVipul Pandya case FW6_TYPE_OFLD_CONNECTION_WR_RPL: 39541cab775cSVipul Pandya sched(dev, skb); 39555be78ee9SVipul Pandya break; 3956be4c9badSRoland Dreier default: 3957be4c9badSRoland Dreier printk(KERN_ERR MOD "%s unexpected fw6 msg type %u\n", __func__, 3958be4c9badSRoland Dreier rpl->type); 39592f5b48c3SSteve Wise kfree_skb(skb); 3960be4c9badSRoland Dreier break; 3961be4c9badSRoland Dreier } 3962be4c9badSRoland Dreier return 0; 3963be4c9badSRoland Dreier } 3964be4c9badSRoland Dreier 39658da7e7a5SSteve Wise static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb) 39668da7e7a5SSteve Wise { 39678da7e7a5SSteve Wise struct cpl_abort_req_rss *req = cplhdr(skb); 39688da7e7a5SSteve Wise struct c4iw_ep *ep; 39698da7e7a5SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 39708da7e7a5SSteve Wise unsigned int tid = GET_TID(req); 39718da7e7a5SSteve Wise 39728da7e7a5SSteve Wise ep = lookup_tid(t, tid); 397314b92228SSteve Wise if (!ep) { 397414b92228SSteve Wise printk(KERN_WARNING MOD 397514b92228SSteve Wise "Abort on non-existent endpoint, tid %d\n", tid); 397614b92228SSteve Wise kfree_skb(skb); 397714b92228SSteve Wise return 0; 397814b92228SSteve Wise } 39797a2cea2aSSteve Wise if (is_neg_adv(req->status)) { 3980dd92b124SHariprasad Shenai dev_warn(&dev->rdev.lldi.pdev->dev, 3981dd92b124SHariprasad Shenai "Negative advice on abort - tid %u status %d (%s)\n", 3982dd92b124SHariprasad Shenai ep->hwtid, req->status, neg_adv_str(req->status)); 39838da7e7a5SSteve Wise kfree_skb(skb); 39848da7e7a5SSteve Wise return 0; 39858da7e7a5SSteve Wise } 39868da7e7a5SSteve Wise PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid, 39878da7e7a5SSteve Wise ep->com.state); 39888da7e7a5SSteve Wise 39898da7e7a5SSteve Wise /* 39908da7e7a5SSteve Wise * Wake up any threads in rdma_init() or rdma_fini(). 39917c0a33d6SVipul Pandya * However, if we are on MPAv2 and want to retry with MPAv1 39927c0a33d6SVipul Pandya * then, don't wake up yet. 39938da7e7a5SSteve Wise */ 39947c0a33d6SVipul Pandya if (mpa_rev == 2 && !ep->tried_with_mpa_v1) { 39957c0a33d6SVipul Pandya if (ep->com.state != MPA_REQ_SENT) 39967c0a33d6SVipul Pandya c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 39977c0a33d6SVipul Pandya } else 39988da7e7a5SSteve Wise c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 39998da7e7a5SSteve Wise sched(dev, skb); 40008da7e7a5SSteve Wise return 0; 40018da7e7a5SSteve Wise } 40028da7e7a5SSteve Wise 4003be4c9badSRoland Dreier /* 4004be4c9badSRoland Dreier * Most upcalls from the T4 Core go to sched() to 4005be4c9badSRoland Dreier * schedule the processing on a work queue. 4006be4c9badSRoland Dreier */ 4007be4c9badSRoland Dreier c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS] = { 4008be4c9badSRoland Dreier [CPL_ACT_ESTABLISH] = sched, 4009be4c9badSRoland Dreier [CPL_ACT_OPEN_RPL] = sched, 4010be4c9badSRoland Dreier [CPL_RX_DATA] = sched, 4011be4c9badSRoland Dreier [CPL_ABORT_RPL_RSS] = sched, 4012be4c9badSRoland Dreier [CPL_ABORT_RPL] = sched, 4013be4c9badSRoland Dreier [CPL_PASS_OPEN_RPL] = sched, 4014be4c9badSRoland Dreier [CPL_CLOSE_LISTSRV_RPL] = sched, 4015be4c9badSRoland Dreier [CPL_PASS_ACCEPT_REQ] = sched, 4016be4c9badSRoland Dreier [CPL_PASS_ESTABLISH] = sched, 4017be4c9badSRoland Dreier [CPL_PEER_CLOSE] = sched, 4018be4c9badSRoland Dreier [CPL_CLOSE_CON_RPL] = sched, 40198da7e7a5SSteve Wise [CPL_ABORT_REQ_RSS] = peer_abort_intr, 4020be4c9badSRoland Dreier [CPL_RDMA_TERMINATE] = sched, 4021be4c9badSRoland Dreier [CPL_FW4_ACK] = sched, 4022be4c9badSRoland Dreier [CPL_SET_TCB_RPL] = set_tcb_rpl, 40231cab775cSVipul Pandya [CPL_FW6_MSG] = fw6_msg, 40241cab775cSVipul Pandya [CPL_RX_PKT] = sched 4025be4c9badSRoland Dreier }; 4026be4c9badSRoland Dreier 4027cfdda9d7SSteve Wise int __init c4iw_cm_init(void) 4028cfdda9d7SSteve Wise { 4029be4c9badSRoland Dreier spin_lock_init(&timeout_lock); 4030cfdda9d7SSteve Wise skb_queue_head_init(&rxq); 4031cfdda9d7SSteve Wise 4032cfdda9d7SSteve Wise workq = create_singlethread_workqueue("iw_cxgb4"); 4033cfdda9d7SSteve Wise if (!workq) 4034cfdda9d7SSteve Wise return -ENOMEM; 4035cfdda9d7SSteve Wise 4036cfdda9d7SSteve Wise return 0; 4037cfdda9d7SSteve Wise } 4038cfdda9d7SSteve Wise 403946c1376dSSteve Wise void c4iw_cm_term(void) 4040cfdda9d7SSteve Wise { 4041be4c9badSRoland Dreier WARN_ON(!list_empty(&timeout_list)); 4042cfdda9d7SSteve Wise flush_workqueue(workq); 4043cfdda9d7SSteve Wise destroy_workqueue(workq); 4044cfdda9d7SSteve Wise } 4045