1cfdda9d7SSteve Wise /* 29eccfe10SSteve Wise * Copyright (c) 2009-2014 Chelsio, Inc. All rights reserved. 3cfdda9d7SSteve Wise * 4cfdda9d7SSteve Wise * This software is available to you under a choice of one of two 5cfdda9d7SSteve Wise * licenses. You may choose to be licensed under the terms of the GNU 6cfdda9d7SSteve Wise * General Public License (GPL) Version 2, available from the file 7cfdda9d7SSteve Wise * COPYING in the main directory of this source tree, or the 8cfdda9d7SSteve Wise * OpenIB.org BSD license below: 9cfdda9d7SSteve Wise * 10cfdda9d7SSteve Wise * Redistribution and use in source and binary forms, with or 11cfdda9d7SSteve Wise * without modification, are permitted provided that the following 12cfdda9d7SSteve Wise * conditions are met: 13cfdda9d7SSteve Wise * 14cfdda9d7SSteve Wise * - Redistributions of source code must retain the above 15cfdda9d7SSteve Wise * copyright notice, this list of conditions and the following 16cfdda9d7SSteve Wise * disclaimer. 17cfdda9d7SSteve Wise * 18cfdda9d7SSteve Wise * - Redistributions in binary form must reproduce the above 19cfdda9d7SSteve Wise * copyright notice, this list of conditions and the following 20cfdda9d7SSteve Wise * disclaimer in the documentation and/or other materials 21cfdda9d7SSteve Wise * provided with the distribution. 22cfdda9d7SSteve Wise * 23cfdda9d7SSteve Wise * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24cfdda9d7SSteve Wise * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25cfdda9d7SSteve Wise * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26cfdda9d7SSteve Wise * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27cfdda9d7SSteve Wise * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28cfdda9d7SSteve Wise * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29cfdda9d7SSteve Wise * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30cfdda9d7SSteve Wise * SOFTWARE. 31cfdda9d7SSteve Wise */ 32cfdda9d7SSteve Wise #include <linux/module.h> 33cfdda9d7SSteve Wise #include <linux/list.h> 34cfdda9d7SSteve Wise #include <linux/workqueue.h> 35cfdda9d7SSteve Wise #include <linux/skbuff.h> 36cfdda9d7SSteve Wise #include <linux/timer.h> 37cfdda9d7SSteve Wise #include <linux/notifier.h> 38cfdda9d7SSteve Wise #include <linux/inetdevice.h> 39cfdda9d7SSteve Wise #include <linux/ip.h> 40cfdda9d7SSteve Wise #include <linux/tcp.h> 411cab775cSVipul Pandya #include <linux/if_vlan.h> 42cfdda9d7SSteve Wise 43cfdda9d7SSteve Wise #include <net/neighbour.h> 44cfdda9d7SSteve Wise #include <net/netevent.h> 45cfdda9d7SSteve Wise #include <net/route.h> 461cab775cSVipul Pandya #include <net/tcp.h> 47830662f6SVipul Pandya #include <net/ip6_route.h> 48830662f6SVipul Pandya #include <net/addrconf.h> 49cfdda9d7SSteve Wise 5011b8e22dSSteve Wise #include <rdma/ib_addr.h> 5111b8e22dSSteve Wise 52cfdda9d7SSteve Wise #include "iw_cxgb4.h" 5384cc6ac6SHariprasad S #include "clip_tbl.h" 54cfdda9d7SSteve Wise 55cfdda9d7SSteve Wise static char *states[] = { 56cfdda9d7SSteve Wise "idle", 57cfdda9d7SSteve Wise "listen", 58cfdda9d7SSteve Wise "connecting", 59cfdda9d7SSteve Wise "mpa_wait_req", 60cfdda9d7SSteve Wise "mpa_req_sent", 61cfdda9d7SSteve Wise "mpa_req_rcvd", 62cfdda9d7SSteve Wise "mpa_rep_sent", 63cfdda9d7SSteve Wise "fpdu_mode", 64cfdda9d7SSteve Wise "aborting", 65cfdda9d7SSteve Wise "closing", 66cfdda9d7SSteve Wise "moribund", 67cfdda9d7SSteve Wise "dead", 68cfdda9d7SSteve Wise NULL, 69cfdda9d7SSteve Wise }; 70cfdda9d7SSteve Wise 715be78ee9SVipul Pandya static int nocong; 725be78ee9SVipul Pandya module_param(nocong, int, 0644); 735be78ee9SVipul Pandya MODULE_PARM_DESC(nocong, "Turn of congestion control (default=0)"); 745be78ee9SVipul Pandya 755be78ee9SVipul Pandya static int enable_ecn; 765be78ee9SVipul Pandya module_param(enable_ecn, int, 0644); 775be78ee9SVipul Pandya MODULE_PARM_DESC(enable_ecn, "Enable ECN (default=0/disabled)"); 785be78ee9SVipul Pandya 79b52fe09eSSteve Wise static int dack_mode = 1; 80ba6d3925SSteve Wise module_param(dack_mode, int, 0644); 81b52fe09eSSteve Wise MODULE_PARM_DESC(dack_mode, "Delayed ack mode (default=1)"); 82ba6d3925SSteve Wise 834c2c5763SHariprasad Shenai uint c4iw_max_read_depth = 32; 84be4c9badSRoland Dreier module_param(c4iw_max_read_depth, int, 0644); 854c2c5763SHariprasad Shenai MODULE_PARM_DESC(c4iw_max_read_depth, 864c2c5763SHariprasad Shenai "Per-connection max ORD/IRD (default=32)"); 87be4c9badSRoland Dreier 88cfdda9d7SSteve Wise static int enable_tcp_timestamps; 89cfdda9d7SSteve Wise module_param(enable_tcp_timestamps, int, 0644); 90cfdda9d7SSteve Wise MODULE_PARM_DESC(enable_tcp_timestamps, "Enable tcp timestamps (default=0)"); 91cfdda9d7SSteve Wise 92cfdda9d7SSteve Wise static int enable_tcp_sack; 93cfdda9d7SSteve Wise module_param(enable_tcp_sack, int, 0644); 94cfdda9d7SSteve Wise MODULE_PARM_DESC(enable_tcp_sack, "Enable tcp SACK (default=0)"); 95cfdda9d7SSteve Wise 96cfdda9d7SSteve Wise static int enable_tcp_window_scaling = 1; 97cfdda9d7SSteve Wise module_param(enable_tcp_window_scaling, int, 0644); 98cfdda9d7SSteve Wise MODULE_PARM_DESC(enable_tcp_window_scaling, 99cfdda9d7SSteve Wise "Enable tcp window scaling (default=1)"); 100cfdda9d7SSteve Wise 101cfdda9d7SSteve Wise int c4iw_debug; 102cfdda9d7SSteve Wise module_param(c4iw_debug, int, 0644); 103cfdda9d7SSteve Wise MODULE_PARM_DESC(c4iw_debug, "Enable debug logging (default=0)"); 104cfdda9d7SSteve Wise 105df2d5130SSteve Wise static int peer2peer = 1; 106cfdda9d7SSteve Wise module_param(peer2peer, int, 0644); 107df2d5130SSteve Wise MODULE_PARM_DESC(peer2peer, "Support peer2peer ULPs (default=1)"); 108cfdda9d7SSteve Wise 109cfdda9d7SSteve Wise static int p2p_type = FW_RI_INIT_P2PTYPE_READ_REQ; 110cfdda9d7SSteve Wise module_param(p2p_type, int, 0644); 111cfdda9d7SSteve Wise MODULE_PARM_DESC(p2p_type, "RDMAP opcode to use for the RTR message: " 112cfdda9d7SSteve Wise "1=RDMA_READ 0=RDMA_WRITE (default 1)"); 113cfdda9d7SSteve Wise 114cfdda9d7SSteve Wise static int ep_timeout_secs = 60; 115cfdda9d7SSteve Wise module_param(ep_timeout_secs, int, 0644); 116cfdda9d7SSteve Wise MODULE_PARM_DESC(ep_timeout_secs, "CM Endpoint operation timeout " 117cfdda9d7SSteve Wise "in seconds (default=60)"); 118cfdda9d7SSteve Wise 119b8ac3112SHariprasad S static int mpa_rev = 2; 120cfdda9d7SSteve Wise module_param(mpa_rev, int, 0644); 121cfdda9d7SSteve Wise MODULE_PARM_DESC(mpa_rev, "MPA Revision, 0 supports amso1100, " 122ccd2c30bSHariprasad S "1 is RFC5044 spec compliant, 2 is IETF MPA Peer Connect Draft" 123b8ac3112SHariprasad S " compliant (default=2)"); 124cfdda9d7SSteve Wise 125cfdda9d7SSteve Wise static int markers_enabled; 126cfdda9d7SSteve Wise module_param(markers_enabled, int, 0644); 127cfdda9d7SSteve Wise MODULE_PARM_DESC(markers_enabled, "Enable MPA MARKERS (default(0)=disabled)"); 128cfdda9d7SSteve Wise 129cfdda9d7SSteve Wise static int crc_enabled = 1; 130cfdda9d7SSteve Wise module_param(crc_enabled, int, 0644); 131cfdda9d7SSteve Wise MODULE_PARM_DESC(crc_enabled, "Enable MPA CRC (default(1)=enabled)"); 132cfdda9d7SSteve Wise 133cfdda9d7SSteve Wise static int rcv_win = 256 * 1024; 134cfdda9d7SSteve Wise module_param(rcv_win, int, 0644); 135cfdda9d7SSteve Wise MODULE_PARM_DESC(rcv_win, "TCP receive window in bytes (default=256KB)"); 136cfdda9d7SSteve Wise 13798ae68b7SSteve Wise static int snd_win = 128 * 1024; 138cfdda9d7SSteve Wise module_param(snd_win, int, 0644); 13998ae68b7SSteve Wise MODULE_PARM_DESC(snd_win, "TCP send window in bytes (default=128KB)"); 140cfdda9d7SSteve Wise 141cfdda9d7SSteve Wise static struct workqueue_struct *workq; 142cfdda9d7SSteve Wise 143cfdda9d7SSteve Wise static struct sk_buff_head rxq; 144cfdda9d7SSteve Wise 145cfdda9d7SSteve Wise static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp); 146cfdda9d7SSteve Wise static void ep_timeout(unsigned long arg); 147cfdda9d7SSteve Wise static void connect_reply_upcall(struct c4iw_ep *ep, int status); 1489dec900cSHariprasad S static int sched(struct c4iw_dev *dev, struct sk_buff *skb); 149cfdda9d7SSteve Wise 150be4c9badSRoland Dreier static LIST_HEAD(timeout_list); 151be4c9badSRoland Dreier static spinlock_t timeout_lock; 152be4c9badSRoland Dreier 1539ca6f7cfSHariprasad S static void deref_cm_id(struct c4iw_ep_common *epc) 1549ca6f7cfSHariprasad S { 1559ca6f7cfSHariprasad S epc->cm_id->rem_ref(epc->cm_id); 1569ca6f7cfSHariprasad S epc->cm_id = NULL; 1579ca6f7cfSHariprasad S set_bit(CM_ID_DEREFED, &epc->history); 1589ca6f7cfSHariprasad S } 1599ca6f7cfSHariprasad S 1609ca6f7cfSHariprasad S static void ref_cm_id(struct c4iw_ep_common *epc) 1619ca6f7cfSHariprasad S { 1629ca6f7cfSHariprasad S set_bit(CM_ID_REFED, &epc->history); 1639ca6f7cfSHariprasad S epc->cm_id->add_ref(epc->cm_id); 1649ca6f7cfSHariprasad S } 1659ca6f7cfSHariprasad S 166325abeadSVipul Pandya static void deref_qp(struct c4iw_ep *ep) 167325abeadSVipul Pandya { 168325abeadSVipul Pandya c4iw_qp_rem_ref(&ep->com.qp->ibqp); 169325abeadSVipul Pandya clear_bit(QP_REFERENCED, &ep->com.flags); 1709ca6f7cfSHariprasad S set_bit(QP_DEREFED, &ep->com.history); 171325abeadSVipul Pandya } 172325abeadSVipul Pandya 173325abeadSVipul Pandya static void ref_qp(struct c4iw_ep *ep) 174325abeadSVipul Pandya { 175325abeadSVipul Pandya set_bit(QP_REFERENCED, &ep->com.flags); 1769ca6f7cfSHariprasad S set_bit(QP_REFED, &ep->com.history); 177325abeadSVipul Pandya c4iw_qp_add_ref(&ep->com.qp->ibqp); 178325abeadSVipul Pandya } 179325abeadSVipul Pandya 180cfdda9d7SSteve Wise static void start_ep_timer(struct c4iw_ep *ep) 181cfdda9d7SSteve Wise { 182cfdda9d7SSteve Wise PDBG("%s ep %p\n", __func__, ep); 183cfdda9d7SSteve Wise if (timer_pending(&ep->timer)) { 1841ec779ccSVipul Pandya pr_err("%s timer already started! ep %p\n", 1851ec779ccSVipul Pandya __func__, ep); 1861ec779ccSVipul Pandya return; 1871ec779ccSVipul Pandya } 1881ec779ccSVipul Pandya clear_bit(TIMEOUT, &ep->com.flags); 189cfdda9d7SSteve Wise c4iw_get_ep(&ep->com); 190cfdda9d7SSteve Wise ep->timer.expires = jiffies + ep_timeout_secs * HZ; 191cfdda9d7SSteve Wise ep->timer.data = (unsigned long)ep; 192cfdda9d7SSteve Wise ep->timer.function = ep_timeout; 193cfdda9d7SSteve Wise add_timer(&ep->timer); 194cfdda9d7SSteve Wise } 195cfdda9d7SSteve Wise 196b33bd0cbSSteve Wise static int stop_ep_timer(struct c4iw_ep *ep) 197cfdda9d7SSteve Wise { 1981ec779ccSVipul Pandya PDBG("%s ep %p stopping\n", __func__, ep); 199cfdda9d7SSteve Wise del_timer_sync(&ep->timer); 200b33bd0cbSSteve Wise if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) { 201cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 202b33bd0cbSSteve Wise return 0; 203b33bd0cbSSteve Wise } 204b33bd0cbSSteve Wise return 1; 205cfdda9d7SSteve Wise } 206cfdda9d7SSteve Wise 207cfdda9d7SSteve Wise static int c4iw_l2t_send(struct c4iw_rdev *rdev, struct sk_buff *skb, 208cfdda9d7SSteve Wise struct l2t_entry *l2e) 209cfdda9d7SSteve Wise { 210cfdda9d7SSteve Wise int error = 0; 211cfdda9d7SSteve Wise 212cfdda9d7SSteve Wise if (c4iw_fatal_error(rdev)) { 213cfdda9d7SSteve Wise kfree_skb(skb); 214cfdda9d7SSteve Wise PDBG("%s - device in error state - dropping\n", __func__); 215cfdda9d7SSteve Wise return -EIO; 216cfdda9d7SSteve Wise } 217cfdda9d7SSteve Wise error = cxgb4_l2t_send(rdev->lldi.ports[0], skb, l2e); 218cfdda9d7SSteve Wise if (error < 0) 219cfdda9d7SSteve Wise kfree_skb(skb); 220caa6c9f2SHariprasad S else if (error == NET_XMIT_DROP) 221caa6c9f2SHariprasad S return -ENOMEM; 22274594861SSteve Wise return error < 0 ? error : 0; 223cfdda9d7SSteve Wise } 224cfdda9d7SSteve Wise 225cfdda9d7SSteve Wise int c4iw_ofld_send(struct c4iw_rdev *rdev, struct sk_buff *skb) 226cfdda9d7SSteve Wise { 227cfdda9d7SSteve Wise int error = 0; 228cfdda9d7SSteve Wise 229cfdda9d7SSteve Wise if (c4iw_fatal_error(rdev)) { 230cfdda9d7SSteve Wise kfree_skb(skb); 231cfdda9d7SSteve Wise PDBG("%s - device in error state - dropping\n", __func__); 232cfdda9d7SSteve Wise return -EIO; 233cfdda9d7SSteve Wise } 234cfdda9d7SSteve Wise error = cxgb4_ofld_send(rdev->lldi.ports[0], skb); 235cfdda9d7SSteve Wise if (error < 0) 236cfdda9d7SSteve Wise kfree_skb(skb); 23774594861SSteve Wise return error < 0 ? error : 0; 238cfdda9d7SSteve Wise } 239cfdda9d7SSteve Wise 240cfdda9d7SSteve Wise static void release_tid(struct c4iw_rdev *rdev, u32 hwtid, struct sk_buff *skb) 241cfdda9d7SSteve Wise { 242cfdda9d7SSteve Wise struct cpl_tid_release *req; 243cfdda9d7SSteve Wise 244cfdda9d7SSteve Wise skb = get_skb(skb, sizeof *req, GFP_KERNEL); 245cfdda9d7SSteve Wise if (!skb) 246cfdda9d7SSteve Wise return; 247cfdda9d7SSteve Wise req = (struct cpl_tid_release *) skb_put(skb, sizeof(*req)); 248cfdda9d7SSteve Wise INIT_TP_WR(req, hwtid); 249cfdda9d7SSteve Wise OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_TID_RELEASE, hwtid)); 250cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_SETUP, 0); 251cfdda9d7SSteve Wise c4iw_ofld_send(rdev, skb); 252cfdda9d7SSteve Wise return; 253cfdda9d7SSteve Wise } 254cfdda9d7SSteve Wise 255cfdda9d7SSteve Wise static void set_emss(struct c4iw_ep *ep, u16 opt) 256cfdda9d7SSteve Wise { 2576c53e938SHariprasad Shenai ep->emss = ep->com.dev->rdev.lldi.mtus[TCPOPT_MSS_G(opt)] - 25804524a47SHariprasad S ((AF_INET == ep->com.remote_addr.ss_family) ? 25904524a47SHariprasad S sizeof(struct iphdr) : sizeof(struct ipv6hdr)) - 26004524a47SHariprasad S sizeof(struct tcphdr); 261cfdda9d7SSteve Wise ep->mss = ep->emss; 2626c53e938SHariprasad Shenai if (TCPOPT_TSTAMP_G(opt)) 26304524a47SHariprasad S ep->emss -= round_up(TCPOLEN_TIMESTAMP, 4); 264cfdda9d7SSteve Wise if (ep->emss < 128) 265cfdda9d7SSteve Wise ep->emss = 128; 26692e7ae71SHariprasad Shenai if (ep->emss & 7) 26792e7ae71SHariprasad Shenai PDBG("Warning: misaligned mtu idx %u mss %u emss=%u\n", 2686c53e938SHariprasad Shenai TCPOPT_MSS_G(opt), ep->mss, ep->emss); 2696c53e938SHariprasad Shenai PDBG("%s mss_idx %u mss %u emss=%u\n", __func__, TCPOPT_MSS_G(opt), 270cfdda9d7SSteve Wise ep->mss, ep->emss); 271cfdda9d7SSteve Wise } 272cfdda9d7SSteve Wise 273cfdda9d7SSteve Wise static enum c4iw_ep_state state_read(struct c4iw_ep_common *epc) 274cfdda9d7SSteve Wise { 275cfdda9d7SSteve Wise enum c4iw_ep_state state; 276cfdda9d7SSteve Wise 2772f5b48c3SSteve Wise mutex_lock(&epc->mutex); 278cfdda9d7SSteve Wise state = epc->state; 2792f5b48c3SSteve Wise mutex_unlock(&epc->mutex); 280cfdda9d7SSteve Wise return state; 281cfdda9d7SSteve Wise } 282cfdda9d7SSteve Wise 283cfdda9d7SSteve Wise static void __state_set(struct c4iw_ep_common *epc, enum c4iw_ep_state new) 284cfdda9d7SSteve Wise { 285cfdda9d7SSteve Wise epc->state = new; 286cfdda9d7SSteve Wise } 287cfdda9d7SSteve Wise 288cfdda9d7SSteve Wise static void state_set(struct c4iw_ep_common *epc, enum c4iw_ep_state new) 289cfdda9d7SSteve Wise { 2902f5b48c3SSteve Wise mutex_lock(&epc->mutex); 291cfdda9d7SSteve Wise PDBG("%s - %s -> %s\n", __func__, states[epc->state], states[new]); 292cfdda9d7SSteve Wise __state_set(epc, new); 2932f5b48c3SSteve Wise mutex_unlock(&epc->mutex); 294cfdda9d7SSteve Wise return; 295cfdda9d7SSteve Wise } 296cfdda9d7SSteve Wise 297cfdda9d7SSteve Wise static void *alloc_ep(int size, gfp_t gfp) 298cfdda9d7SSteve Wise { 299cfdda9d7SSteve Wise struct c4iw_ep_common *epc; 300cfdda9d7SSteve Wise 301cfdda9d7SSteve Wise epc = kzalloc(size, gfp); 302cfdda9d7SSteve Wise if (epc) { 303cfdda9d7SSteve Wise kref_init(&epc->kref); 3042f5b48c3SSteve Wise mutex_init(&epc->mutex); 305aadc4df3SSteve Wise c4iw_init_wr_wait(&epc->wr_wait); 306cfdda9d7SSteve Wise } 307cfdda9d7SSteve Wise PDBG("%s alloc ep %p\n", __func__, epc); 308cfdda9d7SSteve Wise return epc; 309cfdda9d7SSteve Wise } 310cfdda9d7SSteve Wise 311944661ddSHariprasad S static void remove_ep_tid(struct c4iw_ep *ep) 312944661ddSHariprasad S { 313944661ddSHariprasad S unsigned long flags; 314944661ddSHariprasad S 315944661ddSHariprasad S spin_lock_irqsave(&ep->com.dev->lock, flags); 316944661ddSHariprasad S _remove_handle(ep->com.dev, &ep->com.dev->hwtid_idr, ep->hwtid, 0); 317944661ddSHariprasad S spin_unlock_irqrestore(&ep->com.dev->lock, flags); 318944661ddSHariprasad S } 319944661ddSHariprasad S 320944661ddSHariprasad S static void insert_ep_tid(struct c4iw_ep *ep) 321944661ddSHariprasad S { 322944661ddSHariprasad S unsigned long flags; 323944661ddSHariprasad S 324944661ddSHariprasad S spin_lock_irqsave(&ep->com.dev->lock, flags); 325944661ddSHariprasad S _insert_handle(ep->com.dev, &ep->com.dev->hwtid_idr, ep, ep->hwtid, 0); 326944661ddSHariprasad S spin_unlock_irqrestore(&ep->com.dev->lock, flags); 327944661ddSHariprasad S } 328944661ddSHariprasad S 329944661ddSHariprasad S /* 330944661ddSHariprasad S * Atomically lookup the ep ptr given the tid and grab a reference on the ep. 331944661ddSHariprasad S */ 332944661ddSHariprasad S static struct c4iw_ep *get_ep_from_tid(struct c4iw_dev *dev, unsigned int tid) 333944661ddSHariprasad S { 334944661ddSHariprasad S struct c4iw_ep *ep; 335944661ddSHariprasad S unsigned long flags; 336944661ddSHariprasad S 337944661ddSHariprasad S spin_lock_irqsave(&dev->lock, flags); 338944661ddSHariprasad S ep = idr_find(&dev->hwtid_idr, tid); 339944661ddSHariprasad S if (ep) 340944661ddSHariprasad S c4iw_get_ep(&ep->com); 341944661ddSHariprasad S spin_unlock_irqrestore(&dev->lock, flags); 342944661ddSHariprasad S return ep; 343944661ddSHariprasad S } 344944661ddSHariprasad S 345f86fac79SHariprasad S /* 346f86fac79SHariprasad S * Atomically lookup the ep ptr given the stid and grab a reference on the ep. 347f86fac79SHariprasad S */ 348f86fac79SHariprasad S static struct c4iw_listen_ep *get_ep_from_stid(struct c4iw_dev *dev, 349f86fac79SHariprasad S unsigned int stid) 350f86fac79SHariprasad S { 351f86fac79SHariprasad S struct c4iw_listen_ep *ep; 352f86fac79SHariprasad S unsigned long flags; 353f86fac79SHariprasad S 354f86fac79SHariprasad S spin_lock_irqsave(&dev->lock, flags); 355f86fac79SHariprasad S ep = idr_find(&dev->stid_idr, stid); 356f86fac79SHariprasad S if (ep) 357f86fac79SHariprasad S c4iw_get_ep(&ep->com); 358f86fac79SHariprasad S spin_unlock_irqrestore(&dev->lock, flags); 359f86fac79SHariprasad S return ep; 360f86fac79SHariprasad S } 361f86fac79SHariprasad S 362cfdda9d7SSteve Wise void _c4iw_free_ep(struct kref *kref) 363cfdda9d7SSteve Wise { 364cfdda9d7SSteve Wise struct c4iw_ep *ep; 365cfdda9d7SSteve Wise 366cfdda9d7SSteve Wise ep = container_of(kref, struct c4iw_ep, com.kref); 3679dec900cSHariprasad S PDBG("%s ep %p state %s\n", __func__, ep, states[ep->com.state]); 368325abeadSVipul Pandya if (test_bit(QP_REFERENCED, &ep->com.flags)) 369325abeadSVipul Pandya deref_qp(ep); 370cfdda9d7SSteve Wise if (test_bit(RELEASE_RESOURCES, &ep->com.flags)) { 37184cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 37284cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 37384cc6ac6SHariprasad S (struct sockaddr_in6 *) 374170003c8SSteve Wise &ep->com.local_addr; 37584cc6ac6SHariprasad S 37684cc6ac6SHariprasad S cxgb4_clip_release( 37784cc6ac6SHariprasad S ep->com.dev->rdev.lldi.ports[0], 37884cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 37984cc6ac6SHariprasad S 1); 38084cc6ac6SHariprasad S } 381cfdda9d7SSteve Wise cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid); 382cfdda9d7SSteve Wise dst_release(ep->dst); 383cfdda9d7SSteve Wise cxgb4_l2t_release(ep->l2t); 384c878b706SHariprasad S if (ep->mpa_skb) 385c878b706SHariprasad S kfree_skb(ep->mpa_skb); 386cfdda9d7SSteve Wise } 387cfdda9d7SSteve Wise kfree(ep); 388cfdda9d7SSteve Wise } 389cfdda9d7SSteve Wise 390cfdda9d7SSteve Wise static void release_ep_resources(struct c4iw_ep *ep) 391cfdda9d7SSteve Wise { 392cfdda9d7SSteve Wise set_bit(RELEASE_RESOURCES, &ep->com.flags); 393944661ddSHariprasad S 394944661ddSHariprasad S /* 395944661ddSHariprasad S * If we have a hwtid, then remove it from the idr table 396944661ddSHariprasad S * so lookups will no longer find this endpoint. Otherwise 397944661ddSHariprasad S * we have a race where one thread finds the ep ptr just 398944661ddSHariprasad S * before the other thread is freeing the ep memory. 399944661ddSHariprasad S */ 400944661ddSHariprasad S if (ep->hwtid != -1) 401944661ddSHariprasad S remove_ep_tid(ep); 402cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 403cfdda9d7SSteve Wise } 404cfdda9d7SSteve Wise 405cfdda9d7SSteve Wise static int status2errno(int status) 406cfdda9d7SSteve Wise { 407cfdda9d7SSteve Wise switch (status) { 408cfdda9d7SSteve Wise case CPL_ERR_NONE: 409cfdda9d7SSteve Wise return 0; 410cfdda9d7SSteve Wise case CPL_ERR_CONN_RESET: 411cfdda9d7SSteve Wise return -ECONNRESET; 412cfdda9d7SSteve Wise case CPL_ERR_ARP_MISS: 413cfdda9d7SSteve Wise return -EHOSTUNREACH; 414cfdda9d7SSteve Wise case CPL_ERR_CONN_TIMEDOUT: 415cfdda9d7SSteve Wise return -ETIMEDOUT; 416cfdda9d7SSteve Wise case CPL_ERR_TCAM_FULL: 417cfdda9d7SSteve Wise return -ENOMEM; 418cfdda9d7SSteve Wise case CPL_ERR_CONN_EXIST: 419cfdda9d7SSteve Wise return -EADDRINUSE; 420cfdda9d7SSteve Wise default: 421cfdda9d7SSteve Wise return -EIO; 422cfdda9d7SSteve Wise } 423cfdda9d7SSteve Wise } 424cfdda9d7SSteve Wise 425cfdda9d7SSteve Wise /* 426cfdda9d7SSteve Wise * Try and reuse skbs already allocated... 427cfdda9d7SSteve Wise */ 428cfdda9d7SSteve Wise static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp) 429cfdda9d7SSteve Wise { 430cfdda9d7SSteve Wise if (skb && !skb_is_nonlinear(skb) && !skb_cloned(skb)) { 431cfdda9d7SSteve Wise skb_trim(skb, 0); 432cfdda9d7SSteve Wise skb_get(skb); 433cfdda9d7SSteve Wise skb_reset_transport_header(skb); 434cfdda9d7SSteve Wise } else { 435cfdda9d7SSteve Wise skb = alloc_skb(len, gfp); 436cfdda9d7SSteve Wise } 437b38a0ad8SSteve Wise t4_set_arp_err_handler(skb, NULL, NULL); 438cfdda9d7SSteve Wise return skb; 439cfdda9d7SSteve Wise } 440cfdda9d7SSteve Wise 441830662f6SVipul Pandya static struct net_device *get_real_dev(struct net_device *egress_dev) 442830662f6SVipul Pandya { 44311b8e22dSSteve Wise return rdma_vlan_dev_real_dev(egress_dev) ? : egress_dev; 444830662f6SVipul Pandya } 445830662f6SVipul Pandya 446830662f6SVipul Pandya static int our_interface(struct c4iw_dev *dev, struct net_device *egress_dev) 447830662f6SVipul Pandya { 448830662f6SVipul Pandya int i; 449830662f6SVipul Pandya 450830662f6SVipul Pandya egress_dev = get_real_dev(egress_dev); 451830662f6SVipul Pandya for (i = 0; i < dev->rdev.lldi.nports; i++) 452830662f6SVipul Pandya if (dev->rdev.lldi.ports[i] == egress_dev) 453830662f6SVipul Pandya return 1; 454830662f6SVipul Pandya return 0; 455830662f6SVipul Pandya } 456830662f6SVipul Pandya 457830662f6SVipul Pandya static struct dst_entry *find_route6(struct c4iw_dev *dev, __u8 *local_ip, 458830662f6SVipul Pandya __u8 *peer_ip, __be16 local_port, 459830662f6SVipul Pandya __be16 peer_port, u8 tos, 460830662f6SVipul Pandya __u32 sin6_scope_id) 461830662f6SVipul Pandya { 462830662f6SVipul Pandya struct dst_entry *dst = NULL; 463830662f6SVipul Pandya 464830662f6SVipul Pandya if (IS_ENABLED(CONFIG_IPV6)) { 465830662f6SVipul Pandya struct flowi6 fl6; 466830662f6SVipul Pandya 467830662f6SVipul Pandya memset(&fl6, 0, sizeof(fl6)); 468830662f6SVipul Pandya memcpy(&fl6.daddr, peer_ip, 16); 469830662f6SVipul Pandya memcpy(&fl6.saddr, local_ip, 16); 470830662f6SVipul Pandya if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL) 471830662f6SVipul Pandya fl6.flowi6_oif = sin6_scope_id; 472830662f6SVipul Pandya dst = ip6_route_output(&init_net, NULL, &fl6); 473830662f6SVipul Pandya if (!dst) 474830662f6SVipul Pandya goto out; 475830662f6SVipul Pandya if (!our_interface(dev, ip6_dst_idev(dst)->dev) && 476830662f6SVipul Pandya !(ip6_dst_idev(dst)->dev->flags & IFF_LOOPBACK)) { 477830662f6SVipul Pandya dst_release(dst); 478830662f6SVipul Pandya dst = NULL; 479830662f6SVipul Pandya } 480830662f6SVipul Pandya } 481830662f6SVipul Pandya 482830662f6SVipul Pandya out: 483830662f6SVipul Pandya return dst; 484830662f6SVipul Pandya } 485830662f6SVipul Pandya 486830662f6SVipul Pandya static struct dst_entry *find_route(struct c4iw_dev *dev, __be32 local_ip, 487cfdda9d7SSteve Wise __be32 peer_ip, __be16 local_port, 488cfdda9d7SSteve Wise __be16 peer_port, u8 tos) 489cfdda9d7SSteve Wise { 490cfdda9d7SSteve Wise struct rtable *rt; 49131e4543dSDavid S. Miller struct flowi4 fl4; 492830662f6SVipul Pandya struct neighbour *n; 493cfdda9d7SSteve Wise 49431e4543dSDavid S. Miller rt = ip_route_output_ports(&init_net, &fl4, NULL, peer_ip, local_ip, 49578fbfd8aSDavid S. Miller peer_port, local_port, IPPROTO_TCP, 49678fbfd8aSDavid S. Miller tos, 0); 497b23dd4feSDavid S. Miller if (IS_ERR(rt)) 498cfdda9d7SSteve Wise return NULL; 499830662f6SVipul Pandya n = dst_neigh_lookup(&rt->dst, &peer_ip); 500830662f6SVipul Pandya if (!n) 501830662f6SVipul Pandya return NULL; 502f8e81908SSteve Wise if (!our_interface(dev, n->dev) && 503f8e81908SSteve Wise !(n->dev->flags & IFF_LOOPBACK)) { 504d480201bSHariprasad S neigh_release(n); 505830662f6SVipul Pandya dst_release(&rt->dst); 506830662f6SVipul Pandya return NULL; 507830662f6SVipul Pandya } 508830662f6SVipul Pandya neigh_release(n); 509830662f6SVipul Pandya return &rt->dst; 510cfdda9d7SSteve Wise } 511cfdda9d7SSteve Wise 512cfdda9d7SSteve Wise static void arp_failure_discard(void *handle, struct sk_buff *skb) 513cfdda9d7SSteve Wise { 5149dec900cSHariprasad S pr_err(MOD "ARP failure\n"); 515cfdda9d7SSteve Wise kfree_skb(skb); 516cfdda9d7SSteve Wise } 517cfdda9d7SSteve Wise 51864bec74aSHariprasad S static void mpa_start_arp_failure(void *handle, struct sk_buff *skb) 51964bec74aSHariprasad S { 52064bec74aSHariprasad S pr_err("ARP failure during MPA Negotiation - Closing Connection\n"); 52164bec74aSHariprasad S } 52264bec74aSHariprasad S 5239dec900cSHariprasad S enum { 5248d1f1a6bSHariprasad S NUM_FAKE_CPLS = 2, 5259dec900cSHariprasad S FAKE_CPL_PUT_EP_SAFE = NUM_CPL_CMDS + 0, 5268d1f1a6bSHariprasad S FAKE_CPL_PASS_PUT_EP_SAFE = NUM_CPL_CMDS + 1, 5279dec900cSHariprasad S }; 5289dec900cSHariprasad S 5299dec900cSHariprasad S static int _put_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb) 5309dec900cSHariprasad S { 5319dec900cSHariprasad S struct c4iw_ep *ep; 5329dec900cSHariprasad S 5339dec900cSHariprasad S ep = *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *))); 5349dec900cSHariprasad S release_ep_resources(ep); 5359dec900cSHariprasad S return 0; 5369dec900cSHariprasad S } 5379dec900cSHariprasad S 5388d1f1a6bSHariprasad S static int _put_pass_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb) 5398d1f1a6bSHariprasad S { 5408d1f1a6bSHariprasad S struct c4iw_ep *ep; 5418d1f1a6bSHariprasad S 5428d1f1a6bSHariprasad S ep = *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *))); 5438d1f1a6bSHariprasad S c4iw_put_ep(&ep->parent_ep->com); 5448d1f1a6bSHariprasad S release_ep_resources(ep); 5458d1f1a6bSHariprasad S return 0; 5468d1f1a6bSHariprasad S } 5478d1f1a6bSHariprasad S 5489dec900cSHariprasad S /* 5499dec900cSHariprasad S * Fake up a special CPL opcode and call sched() so process_work() will call 5509dec900cSHariprasad S * _put_ep_safe() in a safe context to free the ep resources. This is needed 5519dec900cSHariprasad S * because ARP error handlers are called in an ATOMIC context, and 5529dec900cSHariprasad S * _c4iw_free_ep() needs to block. 5539dec900cSHariprasad S */ 5548d1f1a6bSHariprasad S static void queue_arp_failure_cpl(struct c4iw_ep *ep, struct sk_buff *skb, 5558d1f1a6bSHariprasad S int cpl) 5569dec900cSHariprasad S { 5579dec900cSHariprasad S struct cpl_act_establish *rpl = cplhdr(skb); 5589dec900cSHariprasad S 5599dec900cSHariprasad S /* Set our special ARP_FAILURE opcode */ 5608d1f1a6bSHariprasad S rpl->ot.opcode = cpl; 5619dec900cSHariprasad S 5629dec900cSHariprasad S /* 5639dec900cSHariprasad S * Save ep in the skb->cb area, after where sched() will save the dev 5649dec900cSHariprasad S * ptr. 5659dec900cSHariprasad S */ 5669dec900cSHariprasad S *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *))) = ep; 5679dec900cSHariprasad S sched(ep->com.dev, skb); 5689dec900cSHariprasad S } 5699dec900cSHariprasad S 5709dec900cSHariprasad S /* Handle an ARP failure for an accept */ 5719dec900cSHariprasad S static void pass_accept_rpl_arp_failure(void *handle, struct sk_buff *skb) 5729dec900cSHariprasad S { 5739dec900cSHariprasad S struct c4iw_ep *ep = handle; 5749dec900cSHariprasad S 5759dec900cSHariprasad S pr_err(MOD "ARP failure during accept - tid %u -dropping connection\n", 5769dec900cSHariprasad S ep->hwtid); 5779dec900cSHariprasad S 5789dec900cSHariprasad S __state_set(&ep->com, DEAD); 5798d1f1a6bSHariprasad S queue_arp_failure_cpl(ep, skb, FAKE_CPL_PASS_PUT_EP_SAFE); 5809dec900cSHariprasad S } 5819dec900cSHariprasad S 582cfdda9d7SSteve Wise /* 583cfdda9d7SSteve Wise * Handle an ARP failure for an active open. 584cfdda9d7SSteve Wise */ 585cfdda9d7SSteve Wise static void act_open_req_arp_failure(void *handle, struct sk_buff *skb) 586cfdda9d7SSteve Wise { 5875dab6d3aSHariprasad S struct c4iw_ep *ep = handle; 5885dab6d3aSHariprasad S 589e3d132d1SMasanari Iida printk(KERN_ERR MOD "ARP failure during connect\n"); 5905dab6d3aSHariprasad S connect_reply_upcall(ep, -EHOSTUNREACH); 5919dec900cSHariprasad S __state_set(&ep->com, DEAD); 59284cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 59384cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 594170003c8SSteve Wise (struct sockaddr_in6 *)&ep->com.local_addr; 59584cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 59684cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 59784cc6ac6SHariprasad S } 5985dab6d3aSHariprasad S remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid); 5995dab6d3aSHariprasad S cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid); 6008d1f1a6bSHariprasad S queue_arp_failure_cpl(ep, skb, FAKE_CPL_PUT_EP_SAFE); 601cfdda9d7SSteve Wise } 602cfdda9d7SSteve Wise 603cfdda9d7SSteve Wise /* 604cfdda9d7SSteve Wise * Handle an ARP failure for a CPL_ABORT_REQ. Change it into a no RST variant 605cfdda9d7SSteve Wise * and send it along. 606cfdda9d7SSteve Wise */ 607cfdda9d7SSteve Wise static void abort_arp_failure(void *handle, struct sk_buff *skb) 608cfdda9d7SSteve Wise { 609761e19a5SHariprasad S int ret; 610761e19a5SHariprasad S struct c4iw_ep *ep = handle; 611761e19a5SHariprasad S struct c4iw_rdev *rdev = &ep->com.dev->rdev; 612cfdda9d7SSteve Wise struct cpl_abort_req *req = cplhdr(skb); 613cfdda9d7SSteve Wise 614cfdda9d7SSteve Wise PDBG("%s rdev %p\n", __func__, rdev); 615cfdda9d7SSteve Wise req->cmd = CPL_ABORT_NO_RST; 616761e19a5SHariprasad S ret = c4iw_ofld_send(rdev, skb); 617761e19a5SHariprasad S if (ret) { 618761e19a5SHariprasad S __state_set(&ep->com, DEAD); 619761e19a5SHariprasad S queue_arp_failure_cpl(ep, skb, FAKE_CPL_PUT_EP_SAFE); 620761e19a5SHariprasad S } 621cfdda9d7SSteve Wise } 622cfdda9d7SSteve Wise 623fef4422dSHariprasad S static int send_flowc(struct c4iw_ep *ep, struct sk_buff *skb) 624cfdda9d7SSteve Wise { 625cfdda9d7SSteve Wise unsigned int flowclen = 80; 626cfdda9d7SSteve Wise struct fw_flowc_wr *flowc; 627cfdda9d7SSteve Wise int i; 628ac8e4c69SHariprasad S u16 vlan = ep->l2t->vlan; 629ac8e4c69SHariprasad S int nparams; 630ac8e4c69SHariprasad S 631ac8e4c69SHariprasad S if (vlan == CPL_L2T_VLAN_NONE) 632ac8e4c69SHariprasad S nparams = 8; 633ac8e4c69SHariprasad S else 634ac8e4c69SHariprasad S nparams = 9; 635cfdda9d7SSteve Wise 636cfdda9d7SSteve Wise skb = get_skb(skb, flowclen, GFP_KERNEL); 637cfdda9d7SSteve Wise flowc = (struct fw_flowc_wr *)__skb_put(skb, flowclen); 638cfdda9d7SSteve Wise 639e2ac9628SHariprasad Shenai flowc->op_to_nparams = cpu_to_be32(FW_WR_OP_V(FW_FLOWC_WR) | 640ac8e4c69SHariprasad S FW_FLOWC_WR_NPARAMS_V(nparams)); 641e2ac9628SHariprasad Shenai flowc->flowid_len16 = cpu_to_be32(FW_WR_LEN16_V(DIV_ROUND_UP(flowclen, 642e2ac9628SHariprasad Shenai 16)) | FW_WR_FLOWID_V(ep->hwtid)); 643cfdda9d7SSteve Wise 644cfdda9d7SSteve Wise flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN; 6455167865aSHariprasad Shenai flowc->mnemval[0].val = cpu_to_be32(FW_PFVF_CMD_PFN_V 64635b1de55SHariprasad Shenai (ep->com.dev->rdev.lldi.pf)); 647cfdda9d7SSteve Wise flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH; 648cfdda9d7SSteve Wise flowc->mnemval[1].val = cpu_to_be32(ep->tx_chan); 649cfdda9d7SSteve Wise flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT; 650cfdda9d7SSteve Wise flowc->mnemval[2].val = cpu_to_be32(ep->tx_chan); 651cfdda9d7SSteve Wise flowc->mnemval[3].mnemonic = FW_FLOWC_MNEM_IQID; 652cfdda9d7SSteve Wise flowc->mnemval[3].val = cpu_to_be32(ep->rss_qid); 653cfdda9d7SSteve Wise flowc->mnemval[4].mnemonic = FW_FLOWC_MNEM_SNDNXT; 654cfdda9d7SSteve Wise flowc->mnemval[4].val = cpu_to_be32(ep->snd_seq); 655cfdda9d7SSteve Wise flowc->mnemval[5].mnemonic = FW_FLOWC_MNEM_RCVNXT; 656cfdda9d7SSteve Wise flowc->mnemval[5].val = cpu_to_be32(ep->rcv_seq); 657cfdda9d7SSteve Wise flowc->mnemval[6].mnemonic = FW_FLOWC_MNEM_SNDBUF; 658b408ff28SHariprasad Shenai flowc->mnemval[6].val = cpu_to_be32(ep->snd_win); 659cfdda9d7SSteve Wise flowc->mnemval[7].mnemonic = FW_FLOWC_MNEM_MSS; 660cfdda9d7SSteve Wise flowc->mnemval[7].val = cpu_to_be32(ep->emss); 661ac8e4c69SHariprasad S if (nparams == 9) { 662ac8e4c69SHariprasad S u16 pri; 663ac8e4c69SHariprasad S 664ac8e4c69SHariprasad S pri = (vlan & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; 665ac8e4c69SHariprasad S flowc->mnemval[8].mnemonic = FW_FLOWC_MNEM_SCHEDCLASS; 666ac8e4c69SHariprasad S flowc->mnemval[8].val = cpu_to_be32(pri); 667ac8e4c69SHariprasad S } else { 668cfdda9d7SSteve Wise /* Pad WR to 16 byte boundary */ 669cfdda9d7SSteve Wise flowc->mnemval[8].mnemonic = 0; 670cfdda9d7SSteve Wise flowc->mnemval[8].val = 0; 671ac8e4c69SHariprasad S } 672cfdda9d7SSteve Wise for (i = 0; i < 9; i++) { 673cfdda9d7SSteve Wise flowc->mnemval[i].r4[0] = 0; 674cfdda9d7SSteve Wise flowc->mnemval[i].r4[1] = 0; 675cfdda9d7SSteve Wise flowc->mnemval[i].r4[2] = 0; 676cfdda9d7SSteve Wise } 677cfdda9d7SSteve Wise 678cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 679fef4422dSHariprasad S return c4iw_ofld_send(&ep->com.dev->rdev, skb); 680cfdda9d7SSteve Wise } 681cfdda9d7SSteve Wise 682cfdda9d7SSteve Wise static int send_halfclose(struct c4iw_ep *ep, gfp_t gfp) 683cfdda9d7SSteve Wise { 684cfdda9d7SSteve Wise struct cpl_close_con_req *req; 685cfdda9d7SSteve Wise struct sk_buff *skb; 686cfdda9d7SSteve Wise int wrlen = roundup(sizeof *req, 16); 687cfdda9d7SSteve Wise 688cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 689cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, gfp); 690cfdda9d7SSteve Wise if (!skb) { 691cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - failed to alloc skb\n", __func__); 692cfdda9d7SSteve Wise return -ENOMEM; 693cfdda9d7SSteve Wise } 694cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 695cfdda9d7SSteve Wise t4_set_arp_err_handler(skb, NULL, arp_failure_discard); 696cfdda9d7SSteve Wise req = (struct cpl_close_con_req *) skb_put(skb, wrlen); 697cfdda9d7SSteve Wise memset(req, 0, wrlen); 698cfdda9d7SSteve Wise INIT_TP_WR(req, ep->hwtid); 699cfdda9d7SSteve Wise OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, 700cfdda9d7SSteve Wise ep->hwtid)); 701cfdda9d7SSteve Wise return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 702cfdda9d7SSteve Wise } 703cfdda9d7SSteve Wise 704cfdda9d7SSteve Wise static int send_abort(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp) 705cfdda9d7SSteve Wise { 706cfdda9d7SSteve Wise struct cpl_abort_req *req; 707cfdda9d7SSteve Wise int wrlen = roundup(sizeof *req, 16); 708cfdda9d7SSteve Wise 709cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 710cfdda9d7SSteve Wise skb = get_skb(skb, wrlen, gfp); 711cfdda9d7SSteve Wise if (!skb) { 712cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - failed to alloc skb.\n", 713cfdda9d7SSteve Wise __func__); 714cfdda9d7SSteve Wise return -ENOMEM; 715cfdda9d7SSteve Wise } 716cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 717761e19a5SHariprasad S t4_set_arp_err_handler(skb, ep, abort_arp_failure); 718cfdda9d7SSteve Wise req = (struct cpl_abort_req *) skb_put(skb, wrlen); 719cfdda9d7SSteve Wise memset(req, 0, wrlen); 720cfdda9d7SSteve Wise INIT_TP_WR(req, ep->hwtid); 721cfdda9d7SSteve Wise OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_REQ, ep->hwtid)); 722cfdda9d7SSteve Wise req->cmd = CPL_ABORT_SEND_RST; 723cfdda9d7SSteve Wise return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 724cfdda9d7SSteve Wise } 725cfdda9d7SSteve Wise 72692e7ae71SHariprasad Shenai static void best_mtu(const unsigned short *mtus, unsigned short mtu, 72704524a47SHariprasad S unsigned int *idx, int use_ts, int ipv6) 72892e7ae71SHariprasad Shenai { 72904524a47SHariprasad S unsigned short hdr_size = (ipv6 ? 73004524a47SHariprasad S sizeof(struct ipv6hdr) : 73104524a47SHariprasad S sizeof(struct iphdr)) + 73292e7ae71SHariprasad Shenai sizeof(struct tcphdr) + 73304524a47SHariprasad S (use_ts ? 73404524a47SHariprasad S round_up(TCPOLEN_TIMESTAMP, 4) : 0); 73592e7ae71SHariprasad Shenai unsigned short data_size = mtu - hdr_size; 73692e7ae71SHariprasad Shenai 73792e7ae71SHariprasad Shenai cxgb4_best_aligned_mtu(mtus, hdr_size, data_size, 8, idx); 73892e7ae71SHariprasad Shenai } 73992e7ae71SHariprasad Shenai 740cfdda9d7SSteve Wise static int send_connect(struct c4iw_ep *ep) 741cfdda9d7SSteve Wise { 742963cab50SHariprasad S struct cpl_act_open_req *req = NULL; 743963cab50SHariprasad S struct cpl_t5_act_open_req *t5req = NULL; 744963cab50SHariprasad S struct cpl_t6_act_open_req *t6req = NULL; 745963cab50SHariprasad S struct cpl_act_open_req6 *req6 = NULL; 746963cab50SHariprasad S struct cpl_t5_act_open_req6 *t5req6 = NULL; 747963cab50SHariprasad S struct cpl_t6_act_open_req6 *t6req6 = NULL; 748cfdda9d7SSteve Wise struct sk_buff *skb; 749cfdda9d7SSteve Wise u64 opt0; 750cfdda9d7SSteve Wise u32 opt2; 751cfdda9d7SSteve Wise unsigned int mtu_idx; 752cfdda9d7SSteve Wise int wscale; 753963cab50SHariprasad S int win, sizev4, sizev6, wrlen; 7549eccfe10SSteve Wise struct sockaddr_in *la = (struct sockaddr_in *) 755170003c8SSteve Wise &ep->com.local_addr; 7569eccfe10SSteve Wise struct sockaddr_in *ra = (struct sockaddr_in *) 757170003c8SSteve Wise &ep->com.remote_addr; 7589eccfe10SSteve Wise struct sockaddr_in6 *la6 = (struct sockaddr_in6 *) 759170003c8SSteve Wise &ep->com.local_addr; 7609eccfe10SSteve Wise struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *) 761170003c8SSteve Wise &ep->com.remote_addr; 76284cc6ac6SHariprasad S int ret; 763963cab50SHariprasad S enum chip_type adapter_type = ep->com.dev->rdev.lldi.adapter_type; 764963cab50SHariprasad S u32 isn = (prandom_u32() & ~7UL) - 1; 765963cab50SHariprasad S 766963cab50SHariprasad S switch (CHELSIO_CHIP_VERSION(adapter_type)) { 767963cab50SHariprasad S case CHELSIO_T4: 768963cab50SHariprasad S sizev4 = sizeof(struct cpl_act_open_req); 769963cab50SHariprasad S sizev6 = sizeof(struct cpl_act_open_req6); 770963cab50SHariprasad S break; 771963cab50SHariprasad S case CHELSIO_T5: 772963cab50SHariprasad S sizev4 = sizeof(struct cpl_t5_act_open_req); 773963cab50SHariprasad S sizev6 = sizeof(struct cpl_t5_act_open_req6); 774963cab50SHariprasad S break; 775963cab50SHariprasad S case CHELSIO_T6: 776963cab50SHariprasad S sizev4 = sizeof(struct cpl_t6_act_open_req); 777963cab50SHariprasad S sizev6 = sizeof(struct cpl_t6_act_open_req6); 778963cab50SHariprasad S break; 779963cab50SHariprasad S default: 780963cab50SHariprasad S pr_err("T%d Chip is not supported\n", 781963cab50SHariprasad S CHELSIO_CHIP_VERSION(adapter_type)); 782963cab50SHariprasad S return -EINVAL; 783963cab50SHariprasad S } 784830662f6SVipul Pandya 785830662f6SVipul Pandya wrlen = (ep->com.remote_addr.ss_family == AF_INET) ? 786830662f6SVipul Pandya roundup(sizev4, 16) : 787830662f6SVipul Pandya roundup(sizev6, 16); 788cfdda9d7SSteve Wise 789cfdda9d7SSteve Wise PDBG("%s ep %p atid %u\n", __func__, ep, ep->atid); 790cfdda9d7SSteve Wise 791cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 792cfdda9d7SSteve Wise if (!skb) { 793cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - failed to alloc skb.\n", 794cfdda9d7SSteve Wise __func__); 795cfdda9d7SSteve Wise return -ENOMEM; 796cfdda9d7SSteve Wise } 797d4f1a5c6SSteve Wise set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->ctrlq_idx); 798cfdda9d7SSteve Wise 79992e7ae71SHariprasad Shenai best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, 80004524a47SHariprasad S enable_tcp_timestamps, 80104524a47SHariprasad S (AF_INET == ep->com.remote_addr.ss_family) ? 0 : 1); 802cfdda9d7SSteve Wise wscale = compute_wscale(rcv_win); 803b408ff28SHariprasad Shenai 804b408ff28SHariprasad Shenai /* 805b408ff28SHariprasad Shenai * Specify the largest window that will fit in opt0. The 806b408ff28SHariprasad Shenai * remainder will be specified in the rx_data_ack. 807b408ff28SHariprasad Shenai */ 808b408ff28SHariprasad Shenai win = ep->rcv_win >> 10; 809d7990b0cSAnish Bhatt if (win > RCV_BUFSIZ_M) 810d7990b0cSAnish Bhatt win = RCV_BUFSIZ_M; 811b408ff28SHariprasad Shenai 8126c53e938SHariprasad Shenai opt0 = (nocong ? NO_CONG_F : 0) | 813d7990b0cSAnish Bhatt KEEP_ALIVE_F | 8146c53e938SHariprasad Shenai DELACK_F | 815d7990b0cSAnish Bhatt WND_SCALE_V(wscale) | 816d7990b0cSAnish Bhatt MSS_IDX_V(mtu_idx) | 817d7990b0cSAnish Bhatt L2T_IDX_V(ep->l2t->idx) | 818d7990b0cSAnish Bhatt TX_CHAN_V(ep->tx_chan) | 819d7990b0cSAnish Bhatt SMAC_SEL_V(ep->smac_idx) | 820ac8e4c69SHariprasad S DSCP_V(ep->tos >> 2) | 821d7990b0cSAnish Bhatt ULP_MODE_V(ULP_MODE_TCPDDP) | 822d7990b0cSAnish Bhatt RCV_BUFSIZ_V(win); 823d7990b0cSAnish Bhatt opt2 = RX_CHANNEL_V(0) | 8246c53e938SHariprasad Shenai CCTRL_ECN_V(enable_ecn) | 825d7990b0cSAnish Bhatt RSS_QUEUE_VALID_F | RSS_QUEUE_V(ep->rss_qid); 826cfdda9d7SSteve Wise if (enable_tcp_timestamps) 8276c53e938SHariprasad Shenai opt2 |= TSTAMPS_EN_F; 828cfdda9d7SSteve Wise if (enable_tcp_sack) 8296c53e938SHariprasad Shenai opt2 |= SACK_EN_F; 830cfdda9d7SSteve Wise if (wscale && enable_tcp_window_scaling) 831d7990b0cSAnish Bhatt opt2 |= WND_SCALE_EN_F; 832963cab50SHariprasad S if (CHELSIO_CHIP_VERSION(adapter_type) > CHELSIO_T4) { 833963cab50SHariprasad S if (peer2peer) 834963cab50SHariprasad S isn += 4; 835963cab50SHariprasad S 836d7990b0cSAnish Bhatt opt2 |= T5_OPT_2_VALID_F; 837cf7fe64aSHariprasad Shenai opt2 |= CONG_CNTRL_V(CONG_ALG_TAHOE); 8380b741047SHariprasad S opt2 |= T5_ISS_F; 83992e5011aSSteve Wise } 84084cc6ac6SHariprasad S 84184cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) 84284cc6ac6SHariprasad S cxgb4_clip_get(ep->com.dev->rdev.lldi.ports[0], 84384cc6ac6SHariprasad S (const u32 *)&la6->sin6_addr.s6_addr, 1); 84484cc6ac6SHariprasad S 8455dab6d3aSHariprasad S t4_set_arp_err_handler(skb, ep, act_open_req_arp_failure); 846cfdda9d7SSteve Wise 847830662f6SVipul Pandya if (ep->com.remote_addr.ss_family == AF_INET) { 848963cab50SHariprasad S switch (CHELSIO_CHIP_VERSION(adapter_type)) { 849963cab50SHariprasad S case CHELSIO_T4: 850cfdda9d7SSteve Wise req = (struct cpl_act_open_req *)skb_put(skb, wrlen); 851cfdda9d7SSteve Wise INIT_TP_WR(req, 0); 852963cab50SHariprasad S break; 853963cab50SHariprasad S case CHELSIO_T5: 854963cab50SHariprasad S t5req = (struct cpl_t5_act_open_req *)skb_put(skb, 855963cab50SHariprasad S wrlen); 856963cab50SHariprasad S INIT_TP_WR(t5req, 0); 857963cab50SHariprasad S req = (struct cpl_act_open_req *)t5req; 858963cab50SHariprasad S break; 859963cab50SHariprasad S case CHELSIO_T6: 860963cab50SHariprasad S t6req = (struct cpl_t6_act_open_req *)skb_put(skb, 861963cab50SHariprasad S wrlen); 862963cab50SHariprasad S INIT_TP_WR(t6req, 0); 863963cab50SHariprasad S req = (struct cpl_act_open_req *)t6req; 864963cab50SHariprasad S t5req = (struct cpl_t5_act_open_req *)t6req; 865963cab50SHariprasad S break; 866963cab50SHariprasad S default: 867963cab50SHariprasad S pr_err("T%d Chip is not supported\n", 868963cab50SHariprasad S CHELSIO_CHIP_VERSION(adapter_type)); 869963cab50SHariprasad S ret = -EINVAL; 870963cab50SHariprasad S goto clip_release; 871963cab50SHariprasad S } 872963cab50SHariprasad S 873963cab50SHariprasad S OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, 874f079af7aSVipul Pandya ((ep->rss_qid<<14) | ep->atid))); 875830662f6SVipul Pandya req->local_port = la->sin_port; 876830662f6SVipul Pandya req->peer_port = ra->sin_port; 877830662f6SVipul Pandya req->local_ip = la->sin_addr.s_addr; 878830662f6SVipul Pandya req->peer_ip = ra->sin_addr.s_addr; 879cfdda9d7SSteve Wise req->opt0 = cpu_to_be64(opt0); 880963cab50SHariprasad S 881963cab50SHariprasad S if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) { 88241b4f86cSKumar Sanghvi req->params = cpu_to_be32(cxgb4_select_ntuple( 88341b4f86cSKumar Sanghvi ep->com.dev->rdev.lldi.ports[0], 88441b4f86cSKumar Sanghvi ep->l2t)); 885cfdda9d7SSteve Wise req->opt2 = cpu_to_be32(opt2); 886f079af7aSVipul Pandya } else { 887963cab50SHariprasad S t5req->params = cpu_to_be64(FILTER_TUPLE_V( 888963cab50SHariprasad S cxgb4_select_ntuple( 889963cab50SHariprasad S ep->com.dev->rdev.lldi.ports[0], 890963cab50SHariprasad S ep->l2t))); 891963cab50SHariprasad S t5req->rsvd = cpu_to_be32(isn); 892963cab50SHariprasad S PDBG("%s snd_isn %u\n", __func__, t5req->rsvd); 893963cab50SHariprasad S t5req->opt2 = cpu_to_be32(opt2); 894963cab50SHariprasad S } 895963cab50SHariprasad S } else { 896963cab50SHariprasad S switch (CHELSIO_CHIP_VERSION(adapter_type)) { 897963cab50SHariprasad S case CHELSIO_T4: 898830662f6SVipul Pandya req6 = (struct cpl_act_open_req6 *)skb_put(skb, wrlen); 899830662f6SVipul Pandya INIT_TP_WR(req6, 0); 900963cab50SHariprasad S break; 901963cab50SHariprasad S case CHELSIO_T5: 902963cab50SHariprasad S t5req6 = (struct cpl_t5_act_open_req6 *)skb_put(skb, 903963cab50SHariprasad S wrlen); 904963cab50SHariprasad S INIT_TP_WR(t5req6, 0); 905963cab50SHariprasad S req6 = (struct cpl_act_open_req6 *)t5req6; 906963cab50SHariprasad S break; 907963cab50SHariprasad S case CHELSIO_T6: 908963cab50SHariprasad S t6req6 = (struct cpl_t6_act_open_req6 *)skb_put(skb, 909963cab50SHariprasad S wrlen); 910963cab50SHariprasad S INIT_TP_WR(t6req6, 0); 911963cab50SHariprasad S req6 = (struct cpl_act_open_req6 *)t6req6; 912963cab50SHariprasad S t5req6 = (struct cpl_t5_act_open_req6 *)t6req6; 913963cab50SHariprasad S break; 914963cab50SHariprasad S default: 915963cab50SHariprasad S pr_err("T%d Chip is not supported\n", 916963cab50SHariprasad S CHELSIO_CHIP_VERSION(adapter_type)); 917963cab50SHariprasad S ret = -EINVAL; 918963cab50SHariprasad S goto clip_release; 919963cab50SHariprasad S } 920963cab50SHariprasad S 921963cab50SHariprasad S OPCODE_TID(req6) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ6, 922830662f6SVipul Pandya ((ep->rss_qid<<14)|ep->atid))); 923830662f6SVipul Pandya req6->local_port = la6->sin6_port; 924830662f6SVipul Pandya req6->peer_port = ra6->sin6_port; 925963cab50SHariprasad S req6->local_ip_hi = *((__be64 *)(la6->sin6_addr.s6_addr)); 926963cab50SHariprasad S req6->local_ip_lo = *((__be64 *)(la6->sin6_addr.s6_addr + 8)); 927963cab50SHariprasad S req6->peer_ip_hi = *((__be64 *)(ra6->sin6_addr.s6_addr)); 928963cab50SHariprasad S req6->peer_ip_lo = *((__be64 *)(ra6->sin6_addr.s6_addr + 8)); 929830662f6SVipul Pandya req6->opt0 = cpu_to_be64(opt0); 930963cab50SHariprasad S 931963cab50SHariprasad S if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) { 93241b4f86cSKumar Sanghvi req6->params = cpu_to_be32(cxgb4_select_ntuple( 93341b4f86cSKumar Sanghvi ep->com.dev->rdev.lldi.ports[0], 934830662f6SVipul Pandya ep->l2t)); 935830662f6SVipul Pandya req6->opt2 = cpu_to_be32(opt2); 936830662f6SVipul Pandya } else { 937963cab50SHariprasad S t5req6->params = cpu_to_be64(FILTER_TUPLE_V( 93841b4f86cSKumar Sanghvi cxgb4_select_ntuple( 93941b4f86cSKumar Sanghvi ep->com.dev->rdev.lldi.ports[0], 94041b4f86cSKumar Sanghvi ep->l2t))); 941963cab50SHariprasad S t5req6->rsvd = cpu_to_be32(isn); 942963cab50SHariprasad S PDBG("%s snd_isn %u\n", __func__, t5req6->rsvd); 943963cab50SHariprasad S t5req6->opt2 = cpu_to_be32(opt2); 944830662f6SVipul Pandya } 945f079af7aSVipul Pandya } 946f079af7aSVipul Pandya 947793dad94SVipul Pandya set_bit(ACT_OPEN_REQ, &ep->com.history); 94884cc6ac6SHariprasad S ret = c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 949963cab50SHariprasad S clip_release: 95084cc6ac6SHariprasad S if (ret && ep->com.remote_addr.ss_family == AF_INET6) 95184cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 95284cc6ac6SHariprasad S (const u32 *)&la6->sin6_addr.s6_addr, 1); 95384cc6ac6SHariprasad S return ret; 954cfdda9d7SSteve Wise } 955cfdda9d7SSteve Wise 956caa6c9f2SHariprasad S static int send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb, 957d2fe99e8SKumar Sanghvi u8 mpa_rev_to_use) 958cfdda9d7SSteve Wise { 959caa6c9f2SHariprasad S int mpalen, wrlen, ret; 960cfdda9d7SSteve Wise struct fw_ofld_tx_data_wr *req; 961cfdda9d7SSteve Wise struct mpa_message *mpa; 962d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params mpa_v2_params; 963cfdda9d7SSteve Wise 964cfdda9d7SSteve Wise PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen); 965cfdda9d7SSteve Wise 966cfdda9d7SSteve Wise BUG_ON(skb_cloned(skb)); 967cfdda9d7SSteve Wise 968cfdda9d7SSteve Wise mpalen = sizeof(*mpa) + ep->plen; 969d2fe99e8SKumar Sanghvi if (mpa_rev_to_use == 2) 970d2fe99e8SKumar Sanghvi mpalen += sizeof(struct mpa_v2_conn_params); 971cfdda9d7SSteve Wise wrlen = roundup(mpalen + sizeof *req, 16); 972cfdda9d7SSteve Wise skb = get_skb(skb, wrlen, GFP_KERNEL); 973cfdda9d7SSteve Wise if (!skb) { 974cfdda9d7SSteve Wise connect_reply_upcall(ep, -ENOMEM); 975caa6c9f2SHariprasad S return -ENOMEM; 976cfdda9d7SSteve Wise } 977cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 978cfdda9d7SSteve Wise 979cfdda9d7SSteve Wise req = (struct fw_ofld_tx_data_wr *)skb_put(skb, wrlen); 980cfdda9d7SSteve Wise memset(req, 0, wrlen); 981cfdda9d7SSteve Wise req->op_to_immdlen = cpu_to_be32( 982e2ac9628SHariprasad Shenai FW_WR_OP_V(FW_OFLD_TX_DATA_WR) | 983e2ac9628SHariprasad Shenai FW_WR_COMPL_F | 984e2ac9628SHariprasad Shenai FW_WR_IMMDLEN_V(mpalen)); 985cfdda9d7SSteve Wise req->flowid_len16 = cpu_to_be32( 986e2ac9628SHariprasad Shenai FW_WR_FLOWID_V(ep->hwtid) | 987e2ac9628SHariprasad Shenai FW_WR_LEN16_V(wrlen >> 4)); 988cfdda9d7SSteve Wise req->plen = cpu_to_be32(mpalen); 989cfdda9d7SSteve Wise req->tunnel_to_proxy = cpu_to_be32( 990e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_FLUSH_F | 991e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_SHOVE_F); 992cfdda9d7SSteve Wise 993cfdda9d7SSteve Wise mpa = (struct mpa_message *)(req + 1); 994cfdda9d7SSteve Wise memcpy(mpa->key, MPA_KEY_REQ, sizeof(mpa->key)); 9953d4e7994SHariprasad S 9963d4e7994SHariprasad S mpa->flags = 0; 9973d4e7994SHariprasad S if (crc_enabled) 9983d4e7994SHariprasad S mpa->flags |= MPA_CRC; 9993d4e7994SHariprasad S if (markers_enabled) { 10003d4e7994SHariprasad S mpa->flags |= MPA_MARKERS; 10013d4e7994SHariprasad S ep->mpa_attr.recv_marker_enabled = 1; 10023d4e7994SHariprasad S } else { 10033d4e7994SHariprasad S ep->mpa_attr.recv_marker_enabled = 0; 10043d4e7994SHariprasad S } 10053d4e7994SHariprasad S if (mpa_rev_to_use == 2) 10063d4e7994SHariprasad S mpa->flags |= MPA_ENHANCED_RDMA_CONN; 10073d4e7994SHariprasad S 1008cfdda9d7SSteve Wise mpa->private_data_size = htons(ep->plen); 1009d2fe99e8SKumar Sanghvi mpa->revision = mpa_rev_to_use; 101001b225e1SKumar Sanghvi if (mpa_rev_to_use == 1) { 1011d2fe99e8SKumar Sanghvi ep->tried_with_mpa_v1 = 1; 101201b225e1SKumar Sanghvi ep->retry_with_mpa_v1 = 0; 101301b225e1SKumar Sanghvi } 1014d2fe99e8SKumar Sanghvi 1015d2fe99e8SKumar Sanghvi if (mpa_rev_to_use == 2) { 1016f747c34aSRoland Dreier mpa->private_data_size = htons(ntohs(mpa->private_data_size) + 1017f747c34aSRoland Dreier sizeof (struct mpa_v2_conn_params)); 10184c2c5763SHariprasad Shenai PDBG("%s initiator ird %u ord %u\n", __func__, ep->ird, 10194c2c5763SHariprasad Shenai ep->ord); 1020d2fe99e8SKumar Sanghvi mpa_v2_params.ird = htons((u16)ep->ird); 1021d2fe99e8SKumar Sanghvi mpa_v2_params.ord = htons((u16)ep->ord); 1022d2fe99e8SKumar Sanghvi 1023d2fe99e8SKumar Sanghvi if (peer2peer) { 1024d2fe99e8SKumar Sanghvi mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL); 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 memcpy(mpa->private_data, &mpa_v2_params, 1033d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params)); 1034cfdda9d7SSteve Wise 1035cfdda9d7SSteve Wise if (ep->plen) 1036d2fe99e8SKumar Sanghvi memcpy(mpa->private_data + 1037d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params), 1038d2fe99e8SKumar Sanghvi ep->mpa_pkt + sizeof(*mpa), ep->plen); 1039d2fe99e8SKumar Sanghvi } else 1040d2fe99e8SKumar Sanghvi if (ep->plen) 1041d2fe99e8SKumar Sanghvi memcpy(mpa->private_data, 1042d2fe99e8SKumar Sanghvi ep->mpa_pkt + sizeof(*mpa), ep->plen); 1043cfdda9d7SSteve Wise 1044cfdda9d7SSteve Wise /* 1045cfdda9d7SSteve Wise * Reference the mpa skb. This ensures the data area 1046cfdda9d7SSteve Wise * will remain in memory until the hw acks the tx. 1047cfdda9d7SSteve Wise * Function fw4_ack() will deref it. 1048cfdda9d7SSteve Wise */ 1049cfdda9d7SSteve Wise skb_get(skb); 1050cfdda9d7SSteve Wise t4_set_arp_err_handler(skb, NULL, arp_failure_discard); 1051cfdda9d7SSteve Wise BUG_ON(ep->mpa_skb); 1052cfdda9d7SSteve Wise ep->mpa_skb = skb; 1053caa6c9f2SHariprasad S ret = c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 1054caa6c9f2SHariprasad S if (ret) 1055caa6c9f2SHariprasad S return ret; 1056cfdda9d7SSteve Wise start_ep_timer(ep); 1057a7db89ebSSteve Wise __state_set(&ep->com, MPA_REQ_SENT); 1058cfdda9d7SSteve Wise ep->mpa_attr.initiator = 1; 10599c88aa00SSteve Wise ep->snd_seq += mpalen; 1060caa6c9f2SHariprasad S return ret; 1061cfdda9d7SSteve Wise } 1062cfdda9d7SSteve Wise 1063cfdda9d7SSteve Wise static int send_mpa_reject(struct c4iw_ep *ep, const void *pdata, u8 plen) 1064cfdda9d7SSteve Wise { 1065cfdda9d7SSteve Wise int mpalen, wrlen; 1066cfdda9d7SSteve Wise struct fw_ofld_tx_data_wr *req; 1067cfdda9d7SSteve Wise struct mpa_message *mpa; 1068cfdda9d7SSteve Wise struct sk_buff *skb; 1069d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params mpa_v2_params; 1070cfdda9d7SSteve Wise 1071cfdda9d7SSteve Wise PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen); 1072cfdda9d7SSteve Wise 1073cfdda9d7SSteve Wise mpalen = sizeof(*mpa) + plen; 1074d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) 1075d2fe99e8SKumar Sanghvi mpalen += sizeof(struct mpa_v2_conn_params); 1076cfdda9d7SSteve Wise wrlen = roundup(mpalen + sizeof *req, 16); 1077cfdda9d7SSteve Wise 1078cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 1079cfdda9d7SSteve Wise if (!skb) { 1080cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __func__); 1081cfdda9d7SSteve Wise return -ENOMEM; 1082cfdda9d7SSteve Wise } 1083cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 1084cfdda9d7SSteve Wise 1085cfdda9d7SSteve Wise req = (struct fw_ofld_tx_data_wr *)skb_put(skb, wrlen); 1086cfdda9d7SSteve Wise memset(req, 0, wrlen); 1087cfdda9d7SSteve Wise req->op_to_immdlen = cpu_to_be32( 1088e2ac9628SHariprasad Shenai FW_WR_OP_V(FW_OFLD_TX_DATA_WR) | 1089e2ac9628SHariprasad Shenai FW_WR_COMPL_F | 1090e2ac9628SHariprasad Shenai FW_WR_IMMDLEN_V(mpalen)); 1091cfdda9d7SSteve Wise req->flowid_len16 = cpu_to_be32( 1092e2ac9628SHariprasad Shenai FW_WR_FLOWID_V(ep->hwtid) | 1093e2ac9628SHariprasad Shenai FW_WR_LEN16_V(wrlen >> 4)); 1094cfdda9d7SSteve Wise req->plen = cpu_to_be32(mpalen); 1095cfdda9d7SSteve Wise req->tunnel_to_proxy = cpu_to_be32( 1096e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_FLUSH_F | 1097e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_SHOVE_F); 1098cfdda9d7SSteve Wise 1099cfdda9d7SSteve Wise mpa = (struct mpa_message *)(req + 1); 1100cfdda9d7SSteve Wise memset(mpa, 0, sizeof(*mpa)); 1101cfdda9d7SSteve Wise memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key)); 1102cfdda9d7SSteve Wise mpa->flags = MPA_REJECT; 1103fe7e0a4dSVipul Pandya mpa->revision = ep->mpa_attr.version; 1104cfdda9d7SSteve Wise mpa->private_data_size = htons(plen); 1105d2fe99e8SKumar Sanghvi 1106d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 1107d2fe99e8SKumar Sanghvi mpa->flags |= MPA_ENHANCED_RDMA_CONN; 1108f747c34aSRoland Dreier mpa->private_data_size = htons(ntohs(mpa->private_data_size) + 1109f747c34aSRoland Dreier sizeof (struct mpa_v2_conn_params)); 1110d2fe99e8SKumar Sanghvi mpa_v2_params.ird = htons(((u16)ep->ird) | 1111d2fe99e8SKumar Sanghvi (peer2peer ? MPA_V2_PEER2PEER_MODEL : 1112d2fe99e8SKumar Sanghvi 0)); 1113d2fe99e8SKumar Sanghvi mpa_v2_params.ord = htons(((u16)ep->ord) | (peer2peer ? 1114d2fe99e8SKumar Sanghvi (p2p_type == 1115d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_RDMA_WRITE ? 1116d2fe99e8SKumar Sanghvi MPA_V2_RDMA_WRITE_RTR : p2p_type == 1117d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_READ_REQ ? 1118d2fe99e8SKumar Sanghvi MPA_V2_RDMA_READ_RTR : 0) : 0)); 1119d2fe99e8SKumar Sanghvi memcpy(mpa->private_data, &mpa_v2_params, 1120d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params)); 1121d2fe99e8SKumar Sanghvi 1122d2fe99e8SKumar Sanghvi if (ep->plen) 1123d2fe99e8SKumar Sanghvi memcpy(mpa->private_data + 1124d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params), pdata, plen); 1125d2fe99e8SKumar Sanghvi } else 1126cfdda9d7SSteve Wise if (plen) 1127cfdda9d7SSteve Wise memcpy(mpa->private_data, pdata, plen); 1128cfdda9d7SSteve Wise 1129cfdda9d7SSteve Wise /* 1130cfdda9d7SSteve Wise * Reference the mpa skb again. This ensures the data area 1131cfdda9d7SSteve Wise * will remain in memory until the hw acks the tx. 1132cfdda9d7SSteve Wise * Function fw4_ack() will deref it. 1133cfdda9d7SSteve Wise */ 1134cfdda9d7SSteve Wise skb_get(skb); 1135cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 113664bec74aSHariprasad S t4_set_arp_err_handler(skb, NULL, mpa_start_arp_failure); 1137cfdda9d7SSteve Wise BUG_ON(ep->mpa_skb); 1138cfdda9d7SSteve Wise ep->mpa_skb = skb; 11399c88aa00SSteve Wise ep->snd_seq += mpalen; 1140cfdda9d7SSteve Wise return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 1141cfdda9d7SSteve Wise } 1142cfdda9d7SSteve Wise 1143cfdda9d7SSteve Wise static int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen) 1144cfdda9d7SSteve Wise { 1145cfdda9d7SSteve Wise int mpalen, wrlen; 1146cfdda9d7SSteve Wise struct fw_ofld_tx_data_wr *req; 1147cfdda9d7SSteve Wise struct mpa_message *mpa; 1148cfdda9d7SSteve Wise struct sk_buff *skb; 1149d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params mpa_v2_params; 1150cfdda9d7SSteve Wise 1151cfdda9d7SSteve Wise PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen); 1152cfdda9d7SSteve Wise 1153cfdda9d7SSteve Wise mpalen = sizeof(*mpa) + plen; 1154d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) 1155d2fe99e8SKumar Sanghvi mpalen += sizeof(struct mpa_v2_conn_params); 1156cfdda9d7SSteve Wise wrlen = roundup(mpalen + sizeof *req, 16); 1157cfdda9d7SSteve Wise 1158cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 1159cfdda9d7SSteve Wise if (!skb) { 1160cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __func__); 1161cfdda9d7SSteve Wise return -ENOMEM; 1162cfdda9d7SSteve Wise } 1163cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 1164cfdda9d7SSteve Wise 1165cfdda9d7SSteve Wise req = (struct fw_ofld_tx_data_wr *) skb_put(skb, wrlen); 1166cfdda9d7SSteve Wise memset(req, 0, wrlen); 1167cfdda9d7SSteve Wise req->op_to_immdlen = cpu_to_be32( 1168e2ac9628SHariprasad Shenai FW_WR_OP_V(FW_OFLD_TX_DATA_WR) | 1169e2ac9628SHariprasad Shenai FW_WR_COMPL_F | 1170e2ac9628SHariprasad Shenai FW_WR_IMMDLEN_V(mpalen)); 1171cfdda9d7SSteve Wise req->flowid_len16 = cpu_to_be32( 1172e2ac9628SHariprasad Shenai FW_WR_FLOWID_V(ep->hwtid) | 1173e2ac9628SHariprasad Shenai FW_WR_LEN16_V(wrlen >> 4)); 1174cfdda9d7SSteve Wise req->plen = cpu_to_be32(mpalen); 1175cfdda9d7SSteve Wise req->tunnel_to_proxy = cpu_to_be32( 1176e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_FLUSH_F | 1177e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_SHOVE_F); 1178cfdda9d7SSteve Wise 1179cfdda9d7SSteve Wise mpa = (struct mpa_message *)(req + 1); 1180cfdda9d7SSteve Wise memset(mpa, 0, sizeof(*mpa)); 1181cfdda9d7SSteve Wise memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key)); 11823d4e7994SHariprasad S mpa->flags = 0; 11833d4e7994SHariprasad S if (ep->mpa_attr.crc_enabled) 11843d4e7994SHariprasad S mpa->flags |= MPA_CRC; 11853d4e7994SHariprasad S if (ep->mpa_attr.recv_marker_enabled) 11863d4e7994SHariprasad S mpa->flags |= MPA_MARKERS; 1187d2fe99e8SKumar Sanghvi mpa->revision = ep->mpa_attr.version; 1188cfdda9d7SSteve Wise mpa->private_data_size = htons(plen); 1189d2fe99e8SKumar Sanghvi 1190d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 1191d2fe99e8SKumar Sanghvi mpa->flags |= MPA_ENHANCED_RDMA_CONN; 1192f747c34aSRoland Dreier mpa->private_data_size = htons(ntohs(mpa->private_data_size) + 1193f747c34aSRoland Dreier sizeof (struct mpa_v2_conn_params)); 1194d2fe99e8SKumar Sanghvi mpa_v2_params.ird = htons((u16)ep->ird); 1195d2fe99e8SKumar Sanghvi mpa_v2_params.ord = htons((u16)ep->ord); 1196d2fe99e8SKumar Sanghvi if (peer2peer && (ep->mpa_attr.p2p_type != 1197d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_DISABLED)) { 1198d2fe99e8SKumar Sanghvi mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL); 1199d2fe99e8SKumar Sanghvi 1200d2fe99e8SKumar Sanghvi if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE) 1201d2fe99e8SKumar Sanghvi mpa_v2_params.ord |= 1202d2fe99e8SKumar Sanghvi htons(MPA_V2_RDMA_WRITE_RTR); 1203d2fe99e8SKumar Sanghvi else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) 1204d2fe99e8SKumar Sanghvi mpa_v2_params.ord |= 1205d2fe99e8SKumar Sanghvi htons(MPA_V2_RDMA_READ_RTR); 1206d2fe99e8SKumar Sanghvi } 1207d2fe99e8SKumar Sanghvi 1208d2fe99e8SKumar Sanghvi memcpy(mpa->private_data, &mpa_v2_params, 1209d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params)); 1210d2fe99e8SKumar Sanghvi 1211d2fe99e8SKumar Sanghvi if (ep->plen) 1212d2fe99e8SKumar Sanghvi memcpy(mpa->private_data + 1213d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params), pdata, plen); 1214d2fe99e8SKumar Sanghvi } else 1215cfdda9d7SSteve Wise if (plen) 1216cfdda9d7SSteve Wise memcpy(mpa->private_data, pdata, plen); 1217cfdda9d7SSteve Wise 1218cfdda9d7SSteve Wise /* 1219cfdda9d7SSteve Wise * Reference the mpa skb. This ensures the data area 1220cfdda9d7SSteve Wise * will remain in memory until the hw acks the tx. 1221cfdda9d7SSteve Wise * Function fw4_ack() will deref it. 1222cfdda9d7SSteve Wise */ 1223cfdda9d7SSteve Wise skb_get(skb); 122464bec74aSHariprasad S t4_set_arp_err_handler(skb, NULL, mpa_start_arp_failure); 1225cfdda9d7SSteve Wise ep->mpa_skb = skb; 1226a7db89ebSSteve Wise __state_set(&ep->com, MPA_REP_SENT); 12279c88aa00SSteve Wise ep->snd_seq += mpalen; 1228cfdda9d7SSteve Wise return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 1229cfdda9d7SSteve Wise } 1230cfdda9d7SSteve Wise 1231cfdda9d7SSteve Wise static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb) 1232cfdda9d7SSteve Wise { 1233cfdda9d7SSteve Wise struct c4iw_ep *ep; 1234cfdda9d7SSteve Wise struct cpl_act_establish *req = cplhdr(skb); 1235cfdda9d7SSteve Wise unsigned int tid = GET_TID(req); 12366c53e938SHariprasad Shenai unsigned int atid = TID_TID_G(ntohl(req->tos_atid)); 1237cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 1238fef4422dSHariprasad S int ret; 1239cfdda9d7SSteve Wise 1240cfdda9d7SSteve Wise ep = lookup_atid(t, atid); 1241cfdda9d7SSteve Wise 1242cfdda9d7SSteve Wise PDBG("%s ep %p tid %u snd_isn %u rcv_isn %u\n", __func__, ep, tid, 1243cfdda9d7SSteve Wise be32_to_cpu(req->snd_isn), be32_to_cpu(req->rcv_isn)); 1244cfdda9d7SSteve Wise 1245a7db89ebSSteve Wise mutex_lock(&ep->com.mutex); 1246cfdda9d7SSteve Wise dst_confirm(ep->dst); 1247cfdda9d7SSteve Wise 1248cfdda9d7SSteve Wise /* setup the hwtid for this connection */ 1249cfdda9d7SSteve Wise ep->hwtid = tid; 1250cfdda9d7SSteve Wise cxgb4_insert_tid(t, ep, tid); 1251944661ddSHariprasad S insert_ep_tid(ep); 1252cfdda9d7SSteve Wise 1253cfdda9d7SSteve Wise ep->snd_seq = be32_to_cpu(req->snd_isn); 1254cfdda9d7SSteve Wise ep->rcv_seq = be32_to_cpu(req->rcv_isn); 1255cfdda9d7SSteve Wise 1256cfdda9d7SSteve Wise set_emss(ep, ntohs(req->tcp_opt)); 1257cfdda9d7SSteve Wise 1258cfdda9d7SSteve Wise /* dealloc the atid */ 1259793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, atid); 1260cfdda9d7SSteve Wise cxgb4_free_atid(t, atid); 1261793dad94SVipul Pandya set_bit(ACT_ESTAB, &ep->com.history); 1262cfdda9d7SSteve Wise 1263cfdda9d7SSteve Wise /* start MPA negotiation */ 1264fef4422dSHariprasad S ret = send_flowc(ep, NULL); 1265fef4422dSHariprasad S if (ret) 1266fef4422dSHariprasad S goto err; 1267d2fe99e8SKumar Sanghvi if (ep->retry_with_mpa_v1) 1268caa6c9f2SHariprasad S ret = send_mpa_req(ep, skb, 1); 1269d2fe99e8SKumar Sanghvi else 1270caa6c9f2SHariprasad S ret = send_mpa_req(ep, skb, mpa_rev); 1271caa6c9f2SHariprasad S if (ret) 1272caa6c9f2SHariprasad S goto err; 1273a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 1274cfdda9d7SSteve Wise return 0; 1275fef4422dSHariprasad S err: 1276fef4422dSHariprasad S mutex_unlock(&ep->com.mutex); 1277fef4422dSHariprasad S connect_reply_upcall(ep, -ENOMEM); 1278fef4422dSHariprasad S c4iw_ep_disconnect(ep, 0, GFP_KERNEL); 1279fef4422dSHariprasad S return 0; 1280cfdda9d7SSteve Wise } 1281cfdda9d7SSteve Wise 1282be13b2dfSSteve Wise static void close_complete_upcall(struct c4iw_ep *ep, int status) 1283cfdda9d7SSteve Wise { 1284cfdda9d7SSteve Wise struct iw_cm_event event; 1285cfdda9d7SSteve Wise 1286cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1287cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1288cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CLOSE; 1289be13b2dfSSteve Wise event.status = status; 1290cfdda9d7SSteve Wise if (ep->com.cm_id) { 1291cfdda9d7SSteve Wise PDBG("close complete delivered ep %p cm_id %p tid %u\n", 1292cfdda9d7SSteve Wise ep, ep->com.cm_id, ep->hwtid); 1293cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 12949ca6f7cfSHariprasad S deref_cm_id(&ep->com); 1295793dad94SVipul Pandya set_bit(CLOSE_UPCALL, &ep->com.history); 1296cfdda9d7SSteve Wise } 1297cfdda9d7SSteve Wise } 1298cfdda9d7SSteve Wise 1299cfdda9d7SSteve Wise static void peer_close_upcall(struct c4iw_ep *ep) 1300cfdda9d7SSteve Wise { 1301cfdda9d7SSteve Wise struct iw_cm_event event; 1302cfdda9d7SSteve Wise 1303cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1304cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1305cfdda9d7SSteve Wise event.event = IW_CM_EVENT_DISCONNECT; 1306cfdda9d7SSteve Wise if (ep->com.cm_id) { 1307cfdda9d7SSteve Wise PDBG("peer close delivered ep %p cm_id %p tid %u\n", 1308cfdda9d7SSteve Wise ep, ep->com.cm_id, ep->hwtid); 1309cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 1310793dad94SVipul Pandya set_bit(DISCONN_UPCALL, &ep->com.history); 1311cfdda9d7SSteve Wise } 1312cfdda9d7SSteve Wise } 1313cfdda9d7SSteve Wise 1314cfdda9d7SSteve Wise static void peer_abort_upcall(struct c4iw_ep *ep) 1315cfdda9d7SSteve Wise { 1316cfdda9d7SSteve Wise struct iw_cm_event event; 1317cfdda9d7SSteve Wise 1318cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1319cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1320cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CLOSE; 1321cfdda9d7SSteve Wise event.status = -ECONNRESET; 1322cfdda9d7SSteve Wise if (ep->com.cm_id) { 1323cfdda9d7SSteve Wise PDBG("abort delivered ep %p cm_id %p tid %u\n", ep, 1324cfdda9d7SSteve Wise ep->com.cm_id, ep->hwtid); 1325cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 13269ca6f7cfSHariprasad S deref_cm_id(&ep->com); 1327793dad94SVipul Pandya set_bit(ABORT_UPCALL, &ep->com.history); 1328cfdda9d7SSteve Wise } 1329cfdda9d7SSteve Wise } 1330cfdda9d7SSteve Wise 1331cfdda9d7SSteve Wise static void connect_reply_upcall(struct c4iw_ep *ep, int status) 1332cfdda9d7SSteve Wise { 1333cfdda9d7SSteve Wise struct iw_cm_event event; 1334cfdda9d7SSteve Wise 1335cfdda9d7SSteve Wise PDBG("%s ep %p tid %u status %d\n", __func__, ep, ep->hwtid, status); 1336cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1337cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CONNECT_REPLY; 1338cfdda9d7SSteve Wise event.status = status; 133924d44a39SSteve Wise memcpy(&event.local_addr, &ep->com.local_addr, 134024d44a39SSteve Wise sizeof(ep->com.local_addr)); 134124d44a39SSteve Wise memcpy(&event.remote_addr, &ep->com.remote_addr, 134224d44a39SSteve Wise sizeof(ep->com.remote_addr)); 1343cfdda9d7SSteve Wise 1344cfdda9d7SSteve Wise if ((status == 0) || (status == -ECONNREFUSED)) { 1345d2fe99e8SKumar Sanghvi if (!ep->tried_with_mpa_v1) { 1346d2fe99e8SKumar Sanghvi /* this means MPA_v2 is used */ 1347158c776dSHariprasad S event.ord = ep->ird; 1348158c776dSHariprasad S event.ird = ep->ord; 1349d2fe99e8SKumar Sanghvi event.private_data_len = ep->plen - 1350d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1351d2fe99e8SKumar Sanghvi event.private_data = ep->mpa_pkt + 1352d2fe99e8SKumar Sanghvi sizeof(struct mpa_message) + 1353d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1354d2fe99e8SKumar Sanghvi } else { 1355d2fe99e8SKumar Sanghvi /* this means MPA_v1 is used */ 1356158c776dSHariprasad S event.ord = cur_max_read_depth(ep->com.dev); 1357158c776dSHariprasad S event.ird = cur_max_read_depth(ep->com.dev); 1358cfdda9d7SSteve Wise event.private_data_len = ep->plen; 1359d2fe99e8SKumar Sanghvi event.private_data = ep->mpa_pkt + 1360d2fe99e8SKumar Sanghvi sizeof(struct mpa_message); 1361d2fe99e8SKumar Sanghvi } 1362cfdda9d7SSteve Wise } 136385963e4cSRoland Dreier 1364cfdda9d7SSteve Wise PDBG("%s ep %p tid %u status %d\n", __func__, ep, 1365cfdda9d7SSteve Wise ep->hwtid, status); 1366793dad94SVipul Pandya set_bit(CONN_RPL_UPCALL, &ep->com.history); 1367cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 136885963e4cSRoland Dreier 13699ca6f7cfSHariprasad S if (status < 0) 13709ca6f7cfSHariprasad S deref_cm_id(&ep->com); 1371cfdda9d7SSteve Wise } 1372cfdda9d7SSteve Wise 1373be13b2dfSSteve Wise static int connect_request_upcall(struct c4iw_ep *ep) 1374cfdda9d7SSteve Wise { 1375cfdda9d7SSteve Wise struct iw_cm_event event; 1376be13b2dfSSteve Wise int ret; 1377cfdda9d7SSteve Wise 1378cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1379cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1380cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CONNECT_REQUEST; 138124d44a39SSteve Wise memcpy(&event.local_addr, &ep->com.local_addr, 138224d44a39SSteve Wise sizeof(ep->com.local_addr)); 138324d44a39SSteve Wise memcpy(&event.remote_addr, &ep->com.remote_addr, 138424d44a39SSteve Wise sizeof(ep->com.remote_addr)); 1385d2fe99e8SKumar Sanghvi event.provider_data = ep; 1386d2fe99e8SKumar Sanghvi if (!ep->tried_with_mpa_v1) { 1387d2fe99e8SKumar Sanghvi /* this means MPA_v2 is used */ 1388d2fe99e8SKumar Sanghvi event.ord = ep->ord; 1389d2fe99e8SKumar Sanghvi event.ird = ep->ird; 1390d2fe99e8SKumar Sanghvi event.private_data_len = ep->plen - 1391d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1392d2fe99e8SKumar Sanghvi event.private_data = ep->mpa_pkt + sizeof(struct mpa_message) + 1393d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1394d2fe99e8SKumar Sanghvi } else { 1395d2fe99e8SKumar Sanghvi /* this means MPA_v1 is used. Send max supported */ 13964c2c5763SHariprasad Shenai event.ord = cur_max_read_depth(ep->com.dev); 13974c2c5763SHariprasad Shenai event.ird = cur_max_read_depth(ep->com.dev); 1398cfdda9d7SSteve Wise event.private_data_len = ep->plen; 1399cfdda9d7SSteve Wise event.private_data = ep->mpa_pkt + sizeof(struct mpa_message); 1400d2fe99e8SKumar Sanghvi } 1401cfdda9d7SSteve Wise c4iw_get_ep(&ep->com); 1402be13b2dfSSteve Wise ret = ep->parent_ep->com.cm_id->event_handler(ep->parent_ep->com.cm_id, 1403cfdda9d7SSteve Wise &event); 1404be13b2dfSSteve Wise if (ret) 1405be13b2dfSSteve Wise c4iw_put_ep(&ep->com); 1406793dad94SVipul Pandya set_bit(CONNREQ_UPCALL, &ep->com.history); 1407cfdda9d7SSteve Wise c4iw_put_ep(&ep->parent_ep->com); 1408be13b2dfSSteve Wise return ret; 1409cfdda9d7SSteve Wise } 1410cfdda9d7SSteve Wise 1411cfdda9d7SSteve Wise static void established_upcall(struct c4iw_ep *ep) 1412cfdda9d7SSteve Wise { 1413cfdda9d7SSteve Wise struct iw_cm_event event; 1414cfdda9d7SSteve Wise 1415cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1416cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1417cfdda9d7SSteve Wise event.event = IW_CM_EVENT_ESTABLISHED; 14183dd9a5dcSHariprasad S event.ird = ep->ord; 14193dd9a5dcSHariprasad S event.ord = ep->ird; 1420cfdda9d7SSteve Wise if (ep->com.cm_id) { 1421cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1422cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 1423793dad94SVipul Pandya set_bit(ESTAB_UPCALL, &ep->com.history); 1424cfdda9d7SSteve Wise } 1425cfdda9d7SSteve Wise } 1426cfdda9d7SSteve Wise 1427cfdda9d7SSteve Wise static int update_rx_credits(struct c4iw_ep *ep, u32 credits) 1428cfdda9d7SSteve Wise { 1429cfdda9d7SSteve Wise struct cpl_rx_data_ack *req; 1430cfdda9d7SSteve Wise struct sk_buff *skb; 1431cfdda9d7SSteve Wise int wrlen = roundup(sizeof *req, 16); 1432cfdda9d7SSteve Wise 1433cfdda9d7SSteve Wise PDBG("%s ep %p tid %u credits %u\n", __func__, ep, ep->hwtid, credits); 1434cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 1435cfdda9d7SSteve Wise if (!skb) { 1436cfdda9d7SSteve Wise printk(KERN_ERR MOD "update_rx_credits - cannot alloc skb!\n"); 1437cfdda9d7SSteve Wise return 0; 1438cfdda9d7SSteve Wise } 1439cfdda9d7SSteve Wise 1440b408ff28SHariprasad Shenai /* 1441b408ff28SHariprasad Shenai * If we couldn't specify the entire rcv window at connection setup 1442b408ff28SHariprasad Shenai * due to the limit in the number of bits in the RCV_BUFSIZ field, 1443b408ff28SHariprasad Shenai * then add the overage in to the credits returned. 1444b408ff28SHariprasad Shenai */ 1445d7990b0cSAnish Bhatt if (ep->rcv_win > RCV_BUFSIZ_M * 1024) 1446d7990b0cSAnish Bhatt credits += ep->rcv_win - RCV_BUFSIZ_M * 1024; 1447b408ff28SHariprasad Shenai 1448cfdda9d7SSteve Wise req = (struct cpl_rx_data_ack *) skb_put(skb, wrlen); 1449cfdda9d7SSteve Wise memset(req, 0, wrlen); 1450cfdda9d7SSteve Wise INIT_TP_WR(req, ep->hwtid); 1451cfdda9d7SSteve Wise OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_RX_DATA_ACK, 1452cfdda9d7SSteve Wise ep->hwtid)); 1453d7990b0cSAnish Bhatt req->credit_dack = cpu_to_be32(credits | RX_FORCE_ACK_F | 1454cf7fe64aSHariprasad Shenai RX_DACK_CHANGE_F | 1455cf7fe64aSHariprasad Shenai RX_DACK_MODE_V(dack_mode)); 1456d4f1a5c6SSteve Wise set_wr_txq(skb, CPL_PRIORITY_ACK, ep->ctrlq_idx); 1457cfdda9d7SSteve Wise c4iw_ofld_send(&ep->com.dev->rdev, skb); 1458cfdda9d7SSteve Wise return credits; 1459cfdda9d7SSteve Wise } 1460cfdda9d7SSteve Wise 14614c2c5763SHariprasad Shenai #define RELAXED_IRD_NEGOTIATION 1 14624c2c5763SHariprasad Shenai 1463f8e1e1d1SHariprasad S /* 1464f8e1e1d1SHariprasad S * process_mpa_reply - process streaming mode MPA reply 1465f8e1e1d1SHariprasad S * 1466f8e1e1d1SHariprasad S * Returns: 1467f8e1e1d1SHariprasad S * 1468f8e1e1d1SHariprasad S * 0 upon success indicating a connect request was delivered to the ULP 1469f8e1e1d1SHariprasad S * or the mpa request is incomplete but valid so far. 1470f8e1e1d1SHariprasad S * 1471f8e1e1d1SHariprasad S * 1 if a failure requires the caller to close the connection. 1472f8e1e1d1SHariprasad S * 1473f8e1e1d1SHariprasad S * 2 if a failure requires the caller to abort the connection. 1474f8e1e1d1SHariprasad S */ 1475cc18b939SSteve Wise static int process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb) 1476cfdda9d7SSteve Wise { 1477cfdda9d7SSteve Wise struct mpa_message *mpa; 1478d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params *mpa_v2_params; 1479cfdda9d7SSteve Wise u16 plen; 1480d2fe99e8SKumar Sanghvi u16 resp_ird, resp_ord; 1481d2fe99e8SKumar Sanghvi u8 rtr_mismatch = 0, insuff_ird = 0; 1482cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 1483cfdda9d7SSteve Wise enum c4iw_qp_attr_mask mask; 1484cfdda9d7SSteve Wise int err; 1485cc18b939SSteve Wise int disconnect = 0; 1486cfdda9d7SSteve Wise 1487cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1488cfdda9d7SSteve Wise 1489cfdda9d7SSteve Wise /* 1490cfdda9d7SSteve Wise * If we get more than the supported amount of private data 1491cfdda9d7SSteve Wise * then we must fail this connection. 1492cfdda9d7SSteve Wise */ 1493cfdda9d7SSteve Wise if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) { 1494cfdda9d7SSteve Wise err = -EINVAL; 1495da1cecdfSHariprasad S goto err_stop_timer; 1496cfdda9d7SSteve Wise } 1497cfdda9d7SSteve Wise 1498cfdda9d7SSteve Wise /* 1499cfdda9d7SSteve Wise * copy the new data into our accumulation buffer. 1500cfdda9d7SSteve Wise */ 1501cfdda9d7SSteve Wise skb_copy_from_linear_data(skb, &(ep->mpa_pkt[ep->mpa_pkt_len]), 1502cfdda9d7SSteve Wise skb->len); 1503cfdda9d7SSteve Wise ep->mpa_pkt_len += skb->len; 1504cfdda9d7SSteve Wise 1505cfdda9d7SSteve Wise /* 1506cfdda9d7SSteve Wise * if we don't even have the mpa message, then bail. 1507cfdda9d7SSteve Wise */ 1508cfdda9d7SSteve Wise if (ep->mpa_pkt_len < sizeof(*mpa)) 1509cc18b939SSteve Wise return 0; 1510cfdda9d7SSteve Wise mpa = (struct mpa_message *) ep->mpa_pkt; 1511cfdda9d7SSteve Wise 1512cfdda9d7SSteve Wise /* Validate MPA header. */ 1513d2fe99e8SKumar Sanghvi if (mpa->revision > mpa_rev) { 1514d2fe99e8SKumar Sanghvi printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d," 1515d2fe99e8SKumar Sanghvi " Received = %d\n", __func__, mpa_rev, mpa->revision); 1516cfdda9d7SSteve Wise err = -EPROTO; 1517da1cecdfSHariprasad S goto err_stop_timer; 1518cfdda9d7SSteve Wise } 1519cfdda9d7SSteve Wise if (memcmp(mpa->key, MPA_KEY_REP, sizeof(mpa->key))) { 1520cfdda9d7SSteve Wise err = -EPROTO; 1521da1cecdfSHariprasad S goto err_stop_timer; 1522cfdda9d7SSteve Wise } 1523cfdda9d7SSteve Wise 1524cfdda9d7SSteve Wise plen = ntohs(mpa->private_data_size); 1525cfdda9d7SSteve Wise 1526cfdda9d7SSteve Wise /* 1527cfdda9d7SSteve Wise * Fail if there's too much private data. 1528cfdda9d7SSteve Wise */ 1529cfdda9d7SSteve Wise if (plen > MPA_MAX_PRIVATE_DATA) { 1530cfdda9d7SSteve Wise err = -EPROTO; 1531da1cecdfSHariprasad S goto err_stop_timer; 1532cfdda9d7SSteve Wise } 1533cfdda9d7SSteve Wise 1534cfdda9d7SSteve Wise /* 1535cfdda9d7SSteve Wise * If plen does not account for pkt size 1536cfdda9d7SSteve Wise */ 1537cfdda9d7SSteve Wise if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) { 1538cfdda9d7SSteve Wise err = -EPROTO; 1539da1cecdfSHariprasad S goto err_stop_timer; 1540cfdda9d7SSteve Wise } 1541cfdda9d7SSteve Wise 1542cfdda9d7SSteve Wise ep->plen = (u8) plen; 1543cfdda9d7SSteve Wise 1544cfdda9d7SSteve Wise /* 1545cfdda9d7SSteve Wise * If we don't have all the pdata yet, then bail. 1546cfdda9d7SSteve Wise * We'll continue process when more data arrives. 1547cfdda9d7SSteve Wise */ 1548cfdda9d7SSteve Wise if (ep->mpa_pkt_len < (sizeof(*mpa) + plen)) 1549cc18b939SSteve Wise return 0; 1550cfdda9d7SSteve Wise 1551cfdda9d7SSteve Wise if (mpa->flags & MPA_REJECT) { 1552cfdda9d7SSteve Wise err = -ECONNREFUSED; 1553da1cecdfSHariprasad S goto err_stop_timer; 1554cfdda9d7SSteve Wise } 1555cfdda9d7SSteve Wise 1556cfdda9d7SSteve Wise /* 1557da1cecdfSHariprasad S * Stop mpa timer. If it expired, then 1558da1cecdfSHariprasad S * we ignore the MPA reply. process_timeout() 1559da1cecdfSHariprasad S * will abort the connection. 1560da1cecdfSHariprasad S */ 1561da1cecdfSHariprasad S if (stop_ep_timer(ep)) 1562da1cecdfSHariprasad S return 0; 1563da1cecdfSHariprasad S 1564da1cecdfSHariprasad S /* 1565cfdda9d7SSteve Wise * If we get here we have accumulated the entire mpa 1566cfdda9d7SSteve Wise * start reply message including private data. And 1567cfdda9d7SSteve Wise * the MPA header is valid. 1568cfdda9d7SSteve Wise */ 1569c529fb50SSteve Wise __state_set(&ep->com, FPDU_MODE); 1570cfdda9d7SSteve Wise ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0; 1571cfdda9d7SSteve Wise ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0; 1572d2fe99e8SKumar Sanghvi ep->mpa_attr.version = mpa->revision; 1573d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED; 1574d2fe99e8SKumar Sanghvi 1575d2fe99e8SKumar Sanghvi if (mpa->revision == 2) { 1576d2fe99e8SKumar Sanghvi ep->mpa_attr.enhanced_rdma_conn = 1577d2fe99e8SKumar Sanghvi mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0; 1578d2fe99e8SKumar Sanghvi if (ep->mpa_attr.enhanced_rdma_conn) { 1579d2fe99e8SKumar Sanghvi mpa_v2_params = (struct mpa_v2_conn_params *) 1580d2fe99e8SKumar Sanghvi (ep->mpa_pkt + sizeof(*mpa)); 1581d2fe99e8SKumar Sanghvi resp_ird = ntohs(mpa_v2_params->ird) & 1582d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 1583d2fe99e8SKumar Sanghvi resp_ord = ntohs(mpa_v2_params->ord) & 1584d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 15854c2c5763SHariprasad Shenai PDBG("%s responder ird %u ord %u ep ird %u ord %u\n", 15864c2c5763SHariprasad Shenai __func__, resp_ird, resp_ord, ep->ird, ep->ord); 1587d2fe99e8SKumar Sanghvi 1588d2fe99e8SKumar Sanghvi /* 1589d2fe99e8SKumar Sanghvi * This is a double-check. Ideally, below checks are 1590d2fe99e8SKumar Sanghvi * not required since ird/ord stuff has been taken 1591d2fe99e8SKumar Sanghvi * care of in c4iw_accept_cr 1592d2fe99e8SKumar Sanghvi */ 15934c2c5763SHariprasad Shenai if (ep->ird < resp_ord) { 15944c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION && resp_ord <= 15954c2c5763SHariprasad Shenai ep->com.dev->rdev.lldi.max_ordird_qp) 15964c2c5763SHariprasad Shenai ep->ird = resp_ord; 15974c2c5763SHariprasad Shenai else 15984c2c5763SHariprasad Shenai insuff_ird = 1; 15994c2c5763SHariprasad Shenai } else if (ep->ird > resp_ord) { 16004c2c5763SHariprasad Shenai ep->ird = resp_ord; 16014c2c5763SHariprasad Shenai } 16024c2c5763SHariprasad Shenai if (ep->ord > resp_ird) { 16034c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION) 16044c2c5763SHariprasad Shenai ep->ord = resp_ird; 16054c2c5763SHariprasad Shenai else 16064c2c5763SHariprasad Shenai insuff_ird = 1; 16074c2c5763SHariprasad Shenai } 16084c2c5763SHariprasad Shenai if (insuff_ird) { 1609d2fe99e8SKumar Sanghvi err = -ENOMEM; 1610d2fe99e8SKumar Sanghvi ep->ird = resp_ord; 1611d2fe99e8SKumar Sanghvi ep->ord = resp_ird; 1612d2fe99e8SKumar Sanghvi } 1613d2fe99e8SKumar Sanghvi 1614d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ird) & 1615d2fe99e8SKumar Sanghvi MPA_V2_PEER2PEER_MODEL) { 1616d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ord) & 1617d2fe99e8SKumar Sanghvi MPA_V2_RDMA_WRITE_RTR) 1618d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1619d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_RDMA_WRITE; 1620d2fe99e8SKumar Sanghvi else if (ntohs(mpa_v2_params->ord) & 1621d2fe99e8SKumar Sanghvi MPA_V2_RDMA_READ_RTR) 1622d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1623d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_READ_REQ; 1624d2fe99e8SKumar Sanghvi } 1625d2fe99e8SKumar Sanghvi } 1626d2fe99e8SKumar Sanghvi } else if (mpa->revision == 1) 1627d2fe99e8SKumar Sanghvi if (peer2peer) 1628d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = p2p_type; 1629d2fe99e8SKumar Sanghvi 1630cfdda9d7SSteve Wise PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, " 1631d2fe99e8SKumar Sanghvi "xmit_marker_enabled=%d, version=%d p2p_type=%d local-p2p_type = " 1632d2fe99e8SKumar Sanghvi "%d\n", __func__, ep->mpa_attr.crc_enabled, 1633d2fe99e8SKumar Sanghvi ep->mpa_attr.recv_marker_enabled, 1634d2fe99e8SKumar Sanghvi ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version, 1635d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type, p2p_type); 1636d2fe99e8SKumar Sanghvi 1637d2fe99e8SKumar Sanghvi /* 1638d2fe99e8SKumar Sanghvi * If responder's RTR does not match with that of initiator, assign 1639d2fe99e8SKumar Sanghvi * FW_RI_INIT_P2PTYPE_DISABLED in mpa attributes so that RTR is not 1640d2fe99e8SKumar Sanghvi * generated when moving QP to RTS state. 1641d2fe99e8SKumar Sanghvi * A TERM message will be sent after QP has moved to RTS state 1642d2fe99e8SKumar Sanghvi */ 164391018f86SKumar Sanghvi if ((ep->mpa_attr.version == 2) && peer2peer && 1644d2fe99e8SKumar Sanghvi (ep->mpa_attr.p2p_type != p2p_type)) { 1645d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED; 1646d2fe99e8SKumar Sanghvi rtr_mismatch = 1; 1647d2fe99e8SKumar Sanghvi } 1648cfdda9d7SSteve Wise 1649cfdda9d7SSteve Wise attrs.mpa_attr = ep->mpa_attr; 1650cfdda9d7SSteve Wise attrs.max_ird = ep->ird; 1651cfdda9d7SSteve Wise attrs.max_ord = ep->ord; 1652cfdda9d7SSteve Wise attrs.llp_stream_handle = ep; 1653cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_RTS; 1654cfdda9d7SSteve Wise 1655cfdda9d7SSteve Wise mask = C4IW_QP_ATTR_NEXT_STATE | 1656cfdda9d7SSteve Wise C4IW_QP_ATTR_LLP_STREAM_HANDLE | C4IW_QP_ATTR_MPA_ATTR | 1657cfdda9d7SSteve Wise C4IW_QP_ATTR_MAX_IRD | C4IW_QP_ATTR_MAX_ORD; 1658cfdda9d7SSteve Wise 1659cfdda9d7SSteve Wise /* bind QP and TID with INIT_WR */ 1660cfdda9d7SSteve Wise err = c4iw_modify_qp(ep->com.qp->rhp, 1661cfdda9d7SSteve Wise ep->com.qp, mask, &attrs, 1); 1662cfdda9d7SSteve Wise if (err) 1663cfdda9d7SSteve Wise goto err; 1664d2fe99e8SKumar Sanghvi 1665d2fe99e8SKumar Sanghvi /* 1666d2fe99e8SKumar Sanghvi * If responder's RTR requirement did not match with what initiator 1667d2fe99e8SKumar Sanghvi * supports, generate TERM message 1668d2fe99e8SKumar Sanghvi */ 1669d2fe99e8SKumar Sanghvi if (rtr_mismatch) { 1670d2fe99e8SKumar Sanghvi printk(KERN_ERR "%s: RTR mismatch, sending TERM\n", __func__); 1671d2fe99e8SKumar Sanghvi attrs.layer_etype = LAYER_MPA | DDP_LLP; 1672d2fe99e8SKumar Sanghvi attrs.ecode = MPA_NOMATCH_RTR; 1673d2fe99e8SKumar Sanghvi attrs.next_state = C4IW_QP_STATE_TERMINATE; 1674cc18b939SSteve Wise attrs.send_term = 1; 1675d2fe99e8SKumar Sanghvi err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 1676cc18b939SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 1677d2fe99e8SKumar Sanghvi err = -ENOMEM; 1678cc18b939SSteve Wise disconnect = 1; 1679d2fe99e8SKumar Sanghvi goto out; 1680d2fe99e8SKumar Sanghvi } 1681d2fe99e8SKumar Sanghvi 1682d2fe99e8SKumar Sanghvi /* 1683d2fe99e8SKumar Sanghvi * Generate TERM if initiator IRD is not sufficient for responder 1684d2fe99e8SKumar Sanghvi * provided ORD. Currently, we do the same behaviour even when 1685d2fe99e8SKumar Sanghvi * responder provided IRD is also not sufficient as regards to 1686d2fe99e8SKumar Sanghvi * initiator ORD. 1687d2fe99e8SKumar Sanghvi */ 1688d2fe99e8SKumar Sanghvi if (insuff_ird) { 1689d2fe99e8SKumar Sanghvi printk(KERN_ERR "%s: Insufficient IRD, sending TERM\n", 1690d2fe99e8SKumar Sanghvi __func__); 1691d2fe99e8SKumar Sanghvi attrs.layer_etype = LAYER_MPA | DDP_LLP; 1692d2fe99e8SKumar Sanghvi attrs.ecode = MPA_INSUFF_IRD; 1693d2fe99e8SKumar Sanghvi attrs.next_state = C4IW_QP_STATE_TERMINATE; 1694cc18b939SSteve Wise attrs.send_term = 1; 1695d2fe99e8SKumar Sanghvi err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 1696cc18b939SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 1697d2fe99e8SKumar Sanghvi err = -ENOMEM; 1698cc18b939SSteve Wise disconnect = 1; 1699d2fe99e8SKumar Sanghvi goto out; 1700d2fe99e8SKumar Sanghvi } 1701cfdda9d7SSteve Wise goto out; 1702da1cecdfSHariprasad S err_stop_timer: 1703da1cecdfSHariprasad S stop_ep_timer(ep); 1704cfdda9d7SSteve Wise err: 1705f8e1e1d1SHariprasad S disconnect = 2; 1706cfdda9d7SSteve Wise out: 1707cfdda9d7SSteve Wise connect_reply_upcall(ep, err); 1708cc18b939SSteve Wise return disconnect; 1709cfdda9d7SSteve Wise } 1710cfdda9d7SSteve Wise 1711fd6aabe4SHariprasad S /* 1712fd6aabe4SHariprasad S * process_mpa_request - process streaming mode MPA request 1713fd6aabe4SHariprasad S * 1714fd6aabe4SHariprasad S * Returns: 1715fd6aabe4SHariprasad S * 1716fd6aabe4SHariprasad S * 0 upon success indicating a connect request was delivered to the ULP 1717fd6aabe4SHariprasad S * or the mpa request is incomplete but valid so far. 1718fd6aabe4SHariprasad S * 1719fd6aabe4SHariprasad S * 1 if a failure requires the caller to close the connection. 1720fd6aabe4SHariprasad S * 1721fd6aabe4SHariprasad S * 2 if a failure requires the caller to abort the connection. 1722fd6aabe4SHariprasad S */ 1723fd6aabe4SHariprasad S static int process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb) 1724cfdda9d7SSteve Wise { 1725cfdda9d7SSteve Wise struct mpa_message *mpa; 1726d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params *mpa_v2_params; 1727cfdda9d7SSteve Wise u16 plen; 1728cfdda9d7SSteve Wise 1729cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1730cfdda9d7SSteve Wise 1731cfdda9d7SSteve Wise /* 1732cfdda9d7SSteve Wise * If we get more than the supported amount of private data 1733cfdda9d7SSteve Wise * then we must fail this connection. 1734cfdda9d7SSteve Wise */ 1735fd6aabe4SHariprasad S if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) 1736fd6aabe4SHariprasad S goto err_stop_timer; 1737cfdda9d7SSteve Wise 1738cfdda9d7SSteve Wise PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__); 1739cfdda9d7SSteve Wise 1740cfdda9d7SSteve Wise /* 1741cfdda9d7SSteve Wise * Copy the new data into our accumulation buffer. 1742cfdda9d7SSteve Wise */ 1743cfdda9d7SSteve Wise skb_copy_from_linear_data(skb, &(ep->mpa_pkt[ep->mpa_pkt_len]), 1744cfdda9d7SSteve Wise skb->len); 1745cfdda9d7SSteve Wise ep->mpa_pkt_len += skb->len; 1746cfdda9d7SSteve Wise 1747cfdda9d7SSteve Wise /* 1748cfdda9d7SSteve Wise * If we don't even have the mpa message, then bail. 1749cfdda9d7SSteve Wise * We'll continue process when more data arrives. 1750cfdda9d7SSteve Wise */ 1751cfdda9d7SSteve Wise if (ep->mpa_pkt_len < sizeof(*mpa)) 1752fd6aabe4SHariprasad S return 0; 1753cfdda9d7SSteve Wise 1754cfdda9d7SSteve Wise PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__); 1755cfdda9d7SSteve Wise mpa = (struct mpa_message *) ep->mpa_pkt; 1756cfdda9d7SSteve Wise 1757cfdda9d7SSteve Wise /* 1758cfdda9d7SSteve Wise * Validate MPA Header. 1759cfdda9d7SSteve Wise */ 1760d2fe99e8SKumar Sanghvi if (mpa->revision > mpa_rev) { 1761d2fe99e8SKumar Sanghvi printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d," 1762d2fe99e8SKumar Sanghvi " Received = %d\n", __func__, mpa_rev, mpa->revision); 1763fd6aabe4SHariprasad S goto err_stop_timer; 1764cfdda9d7SSteve Wise } 1765cfdda9d7SSteve Wise 1766fd6aabe4SHariprasad S if (memcmp(mpa->key, MPA_KEY_REQ, sizeof(mpa->key))) 1767fd6aabe4SHariprasad S goto err_stop_timer; 1768cfdda9d7SSteve Wise 1769cfdda9d7SSteve Wise plen = ntohs(mpa->private_data_size); 1770cfdda9d7SSteve Wise 1771cfdda9d7SSteve Wise /* 1772cfdda9d7SSteve Wise * Fail if there's too much private data. 1773cfdda9d7SSteve Wise */ 1774fd6aabe4SHariprasad S if (plen > MPA_MAX_PRIVATE_DATA) 1775fd6aabe4SHariprasad S goto err_stop_timer; 1776cfdda9d7SSteve Wise 1777cfdda9d7SSteve Wise /* 1778cfdda9d7SSteve Wise * If plen does not account for pkt size 1779cfdda9d7SSteve Wise */ 1780fd6aabe4SHariprasad S if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) 1781fd6aabe4SHariprasad S goto err_stop_timer; 1782cfdda9d7SSteve Wise ep->plen = (u8) plen; 1783cfdda9d7SSteve Wise 1784cfdda9d7SSteve Wise /* 1785cfdda9d7SSteve Wise * If we don't have all the pdata yet, then bail. 1786cfdda9d7SSteve Wise */ 1787cfdda9d7SSteve Wise if (ep->mpa_pkt_len < (sizeof(*mpa) + plen)) 1788fd6aabe4SHariprasad S return 0; 1789cfdda9d7SSteve Wise 1790cfdda9d7SSteve Wise /* 1791cfdda9d7SSteve Wise * If we get here we have accumulated the entire mpa 1792cfdda9d7SSteve Wise * start reply message including private data. 1793cfdda9d7SSteve Wise */ 1794cfdda9d7SSteve Wise ep->mpa_attr.initiator = 0; 1795cfdda9d7SSteve Wise ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0; 1796cfdda9d7SSteve Wise ep->mpa_attr.recv_marker_enabled = markers_enabled; 1797cfdda9d7SSteve Wise ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0; 1798d2fe99e8SKumar Sanghvi ep->mpa_attr.version = mpa->revision; 1799d2fe99e8SKumar Sanghvi if (mpa->revision == 1) 1800d2fe99e8SKumar Sanghvi ep->tried_with_mpa_v1 = 1; 1801d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED; 1802d2fe99e8SKumar Sanghvi 1803d2fe99e8SKumar Sanghvi if (mpa->revision == 2) { 1804d2fe99e8SKumar Sanghvi ep->mpa_attr.enhanced_rdma_conn = 1805d2fe99e8SKumar Sanghvi mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0; 1806d2fe99e8SKumar Sanghvi if (ep->mpa_attr.enhanced_rdma_conn) { 1807d2fe99e8SKumar Sanghvi mpa_v2_params = (struct mpa_v2_conn_params *) 1808d2fe99e8SKumar Sanghvi (ep->mpa_pkt + sizeof(*mpa)); 1809d2fe99e8SKumar Sanghvi ep->ird = ntohs(mpa_v2_params->ird) & 1810d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 1811d2fe99e8SKumar Sanghvi ep->ord = ntohs(mpa_v2_params->ord) & 1812d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 18134c2c5763SHariprasad Shenai PDBG("%s initiator ird %u ord %u\n", __func__, ep->ird, 18144c2c5763SHariprasad Shenai ep->ord); 1815d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ird) & MPA_V2_PEER2PEER_MODEL) 1816d2fe99e8SKumar Sanghvi if (peer2peer) { 1817d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ord) & 1818d2fe99e8SKumar Sanghvi MPA_V2_RDMA_WRITE_RTR) 1819d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1820d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_RDMA_WRITE; 1821d2fe99e8SKumar Sanghvi else if (ntohs(mpa_v2_params->ord) & 1822d2fe99e8SKumar Sanghvi MPA_V2_RDMA_READ_RTR) 1823d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1824d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_READ_REQ; 1825d2fe99e8SKumar Sanghvi } 1826d2fe99e8SKumar Sanghvi } 1827d2fe99e8SKumar Sanghvi } else if (mpa->revision == 1) 1828d2fe99e8SKumar Sanghvi if (peer2peer) 1829d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = p2p_type; 1830d2fe99e8SKumar Sanghvi 1831cfdda9d7SSteve Wise PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, " 1832cfdda9d7SSteve Wise "xmit_marker_enabled=%d, version=%d p2p_type=%d\n", __func__, 1833cfdda9d7SSteve Wise ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled, 1834cfdda9d7SSteve Wise ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version, 1835cfdda9d7SSteve Wise ep->mpa_attr.p2p_type); 1836cfdda9d7SSteve Wise 1837c529fb50SSteve Wise __state_set(&ep->com, MPA_REQ_RCVD); 1838cfdda9d7SSteve Wise 1839cfdda9d7SSteve Wise /* drive upcall */ 1840e4b76a2aSHariprasad S mutex_lock_nested(&ep->parent_ep->com.mutex, SINGLE_DEPTH_NESTING); 1841be13b2dfSSteve Wise if (ep->parent_ep->com.state != DEAD) { 1842be13b2dfSSteve Wise if (connect_request_upcall(ep)) 1843fd6aabe4SHariprasad S goto err_unlock_parent; 1844be13b2dfSSteve Wise } else { 1845fd6aabe4SHariprasad S goto err_unlock_parent; 1846be13b2dfSSteve Wise } 1847be13b2dfSSteve Wise mutex_unlock(&ep->parent_ep->com.mutex); 1848fd6aabe4SHariprasad S return 0; 1849fd6aabe4SHariprasad S 1850fd6aabe4SHariprasad S err_unlock_parent: 1851fd6aabe4SHariprasad S mutex_unlock(&ep->parent_ep->com.mutex); 1852fd6aabe4SHariprasad S goto err_out; 1853fd6aabe4SHariprasad S err_stop_timer: 1854fd6aabe4SHariprasad S (void)stop_ep_timer(ep); 1855fd6aabe4SHariprasad S err_out: 1856fd6aabe4SHariprasad S return 2; 1857cfdda9d7SSteve Wise } 1858cfdda9d7SSteve Wise 1859cfdda9d7SSteve Wise static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb) 1860cfdda9d7SSteve Wise { 1861cfdda9d7SSteve Wise struct c4iw_ep *ep; 1862cfdda9d7SSteve Wise struct cpl_rx_data *hdr = cplhdr(skb); 1863cfdda9d7SSteve Wise unsigned int dlen = ntohs(hdr->len); 1864cfdda9d7SSteve Wise unsigned int tid = GET_TID(hdr); 1865793dad94SVipul Pandya __u8 status = hdr->status; 1866cc18b939SSteve Wise int disconnect = 0; 1867cfdda9d7SSteve Wise 1868944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 1869977116c6SSteve Wise if (!ep) 1870977116c6SSteve Wise return 0; 1871cfdda9d7SSteve Wise PDBG("%s ep %p tid %u dlen %u\n", __func__, ep, ep->hwtid, dlen); 1872cfdda9d7SSteve Wise skb_pull(skb, sizeof(*hdr)); 1873cfdda9d7SSteve Wise skb_trim(skb, dlen); 1874c529fb50SSteve Wise mutex_lock(&ep->com.mutex); 1875cfdda9d7SSteve Wise 1876cfdda9d7SSteve Wise /* update RX credits */ 1877cfdda9d7SSteve Wise update_rx_credits(ep, dlen); 1878cfdda9d7SSteve Wise 1879c529fb50SSteve Wise switch (ep->com.state) { 1880cfdda9d7SSteve Wise case MPA_REQ_SENT: 188155abf8dfSVipul Pandya ep->rcv_seq += dlen; 1882cc18b939SSteve Wise disconnect = process_mpa_reply(ep, skb); 1883cfdda9d7SSteve Wise break; 1884cfdda9d7SSteve Wise case MPA_REQ_WAIT: 188555abf8dfSVipul Pandya ep->rcv_seq += dlen; 18864a4dd8dbSHariprasad S disconnect = process_mpa_request(ep, skb); 1887cfdda9d7SSteve Wise break; 18881557967bSVipul Pandya case FPDU_MODE: { 18891557967bSVipul Pandya struct c4iw_qp_attributes attrs; 18901557967bSVipul Pandya BUG_ON(!ep->com.qp); 1891e8e5b927SVipul Pandya if (status) 1892793dad94SVipul Pandya pr_err("%s Unexpected streaming data." \ 189304236df2SVipul Pandya " qpid %u ep %p state %d tid %u status %d\n", 189404236df2SVipul Pandya __func__, ep->com.qp->wq.sq.qid, ep, 1895c529fb50SSteve Wise ep->com.state, ep->hwtid, status); 189697d7ec0cSSteve Wise attrs.next_state = C4IW_QP_STATE_TERMINATE; 189755abf8dfSVipul Pandya c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 1898cc18b939SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 1899cc18b939SSteve Wise disconnect = 1; 1900cfdda9d7SSteve Wise break; 1901cfdda9d7SSteve Wise } 19021557967bSVipul Pandya default: 19031557967bSVipul Pandya break; 19041557967bSVipul Pandya } 1905c529fb50SSteve Wise mutex_unlock(&ep->com.mutex); 1906cc18b939SSteve Wise if (disconnect) 19074a4dd8dbSHariprasad S c4iw_ep_disconnect(ep, disconnect == 2, GFP_KERNEL); 1908944661ddSHariprasad S c4iw_put_ep(&ep->com); 1909cfdda9d7SSteve Wise return 0; 1910cfdda9d7SSteve Wise } 1911cfdda9d7SSteve Wise 1912cfdda9d7SSteve Wise static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 1913cfdda9d7SSteve Wise { 1914cfdda9d7SSteve Wise struct c4iw_ep *ep; 1915cfdda9d7SSteve Wise struct cpl_abort_rpl_rss *rpl = cplhdr(skb); 1916cfdda9d7SSteve Wise int release = 0; 1917cfdda9d7SSteve Wise unsigned int tid = GET_TID(rpl); 1918cfdda9d7SSteve Wise 1919944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 19204984037bSVipul Pandya if (!ep) { 19214984037bSVipul Pandya printk(KERN_WARNING MOD "Abort rpl to freed endpoint\n"); 19224984037bSVipul Pandya return 0; 19234984037bSVipul Pandya } 192492dd6c3dSWei Yongjun PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 19252f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 1926cfdda9d7SSteve Wise switch (ep->com.state) { 1927cfdda9d7SSteve Wise case ABORTING: 192891e9c071SVipul Pandya c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 1929cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 1930cfdda9d7SSteve Wise release = 1; 1931cfdda9d7SSteve Wise break; 1932cfdda9d7SSteve Wise default: 1933cfdda9d7SSteve Wise printk(KERN_ERR "%s ep %p state %d\n", 1934cfdda9d7SSteve Wise __func__, ep, ep->com.state); 1935cfdda9d7SSteve Wise break; 1936cfdda9d7SSteve Wise } 19372f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 1938cfdda9d7SSteve Wise 1939cfdda9d7SSteve Wise if (release) 1940cfdda9d7SSteve Wise release_ep_resources(ep); 1941944661ddSHariprasad S c4iw_put_ep(&ep->com); 1942cfdda9d7SSteve Wise return 0; 1943cfdda9d7SSteve Wise } 1944cfdda9d7SSteve Wise 1945caa6c9f2SHariprasad S static int send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid) 19465be78ee9SVipul Pandya { 19475be78ee9SVipul Pandya struct sk_buff *skb; 19485be78ee9SVipul Pandya struct fw_ofld_connection_wr *req; 19495be78ee9SVipul Pandya unsigned int mtu_idx; 19505be78ee9SVipul Pandya int wscale; 1951830662f6SVipul Pandya struct sockaddr_in *sin; 1952b408ff28SHariprasad Shenai int win; 19535be78ee9SVipul Pandya 19545be78ee9SVipul Pandya skb = get_skb(NULL, sizeof(*req), GFP_KERNEL); 19555be78ee9SVipul Pandya req = (struct fw_ofld_connection_wr *)__skb_put(skb, sizeof(*req)); 19565be78ee9SVipul Pandya memset(req, 0, sizeof(*req)); 19576c53e938SHariprasad Shenai req->op_compl = htonl(WR_OP_V(FW_OFLD_CONNECTION_WR)); 1958e2ac9628SHariprasad Shenai req->len16_pkd = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*req), 16))); 195941b4f86cSKumar Sanghvi req->le.filter = cpu_to_be32(cxgb4_select_ntuple( 196041b4f86cSKumar Sanghvi ep->com.dev->rdev.lldi.ports[0], 19615be78ee9SVipul Pandya ep->l2t)); 1962170003c8SSteve Wise sin = (struct sockaddr_in *)&ep->com.local_addr; 1963830662f6SVipul Pandya req->le.lport = sin->sin_port; 1964830662f6SVipul Pandya req->le.u.ipv4.lip = sin->sin_addr.s_addr; 1965170003c8SSteve Wise sin = (struct sockaddr_in *)&ep->com.remote_addr; 1966830662f6SVipul Pandya req->le.pport = sin->sin_port; 1967830662f6SVipul Pandya req->le.u.ipv4.pip = sin->sin_addr.s_addr; 19685be78ee9SVipul Pandya req->tcb.t_state_to_astid = 196977a80e23SHariprasad Shenai htonl(FW_OFLD_CONNECTION_WR_T_STATE_V(TCP_SYN_SENT) | 197077a80e23SHariprasad Shenai FW_OFLD_CONNECTION_WR_ASTID_V(atid)); 19715be78ee9SVipul Pandya req->tcb.cplrxdataack_cplpassacceptrpl = 197277a80e23SHariprasad Shenai htons(FW_OFLD_CONNECTION_WR_CPLRXDATAACK_F); 1973ef5d6355SVipul Pandya req->tcb.tx_max = (__force __be32) jiffies; 1974793dad94SVipul Pandya req->tcb.rcv_adv = htons(1); 197592e7ae71SHariprasad Shenai best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, 197604524a47SHariprasad S enable_tcp_timestamps, 197704524a47SHariprasad S (AF_INET == ep->com.remote_addr.ss_family) ? 0 : 1); 19785be78ee9SVipul Pandya wscale = compute_wscale(rcv_win); 1979b408ff28SHariprasad Shenai 1980b408ff28SHariprasad Shenai /* 1981b408ff28SHariprasad Shenai * Specify the largest window that will fit in opt0. The 1982b408ff28SHariprasad Shenai * remainder will be specified in the rx_data_ack. 1983b408ff28SHariprasad Shenai */ 1984b408ff28SHariprasad Shenai win = ep->rcv_win >> 10; 1985d7990b0cSAnish Bhatt if (win > RCV_BUFSIZ_M) 1986d7990b0cSAnish Bhatt win = RCV_BUFSIZ_M; 1987b408ff28SHariprasad Shenai 19886c53e938SHariprasad Shenai req->tcb.opt0 = (__force __be64) (TCAM_BYPASS_F | 19896c53e938SHariprasad Shenai (nocong ? NO_CONG_F : 0) | 1990d7990b0cSAnish Bhatt KEEP_ALIVE_F | 19916c53e938SHariprasad Shenai DELACK_F | 1992d7990b0cSAnish Bhatt WND_SCALE_V(wscale) | 1993d7990b0cSAnish Bhatt MSS_IDX_V(mtu_idx) | 1994d7990b0cSAnish Bhatt L2T_IDX_V(ep->l2t->idx) | 1995d7990b0cSAnish Bhatt TX_CHAN_V(ep->tx_chan) | 1996d7990b0cSAnish Bhatt SMAC_SEL_V(ep->smac_idx) | 1997ac8e4c69SHariprasad S DSCP_V(ep->tos >> 2) | 1998d7990b0cSAnish Bhatt ULP_MODE_V(ULP_MODE_TCPDDP) | 1999d7990b0cSAnish Bhatt RCV_BUFSIZ_V(win)); 20006c53e938SHariprasad Shenai req->tcb.opt2 = (__force __be32) (PACE_V(1) | 20016c53e938SHariprasad Shenai TX_QUEUE_V(ep->com.dev->rdev.lldi.tx_modq[ep->tx_chan]) | 2002d7990b0cSAnish Bhatt RX_CHANNEL_V(0) | 20036c53e938SHariprasad Shenai CCTRL_ECN_V(enable_ecn) | 2004d7990b0cSAnish Bhatt RSS_QUEUE_VALID_F | RSS_QUEUE_V(ep->rss_qid)); 20055be78ee9SVipul Pandya if (enable_tcp_timestamps) 20066c53e938SHariprasad Shenai req->tcb.opt2 |= (__force __be32)TSTAMPS_EN_F; 20075be78ee9SVipul Pandya if (enable_tcp_sack) 20086c53e938SHariprasad Shenai req->tcb.opt2 |= (__force __be32)SACK_EN_F; 20095be78ee9SVipul Pandya if (wscale && enable_tcp_window_scaling) 2010d7990b0cSAnish Bhatt req->tcb.opt2 |= (__force __be32)WND_SCALE_EN_F; 2011ef5d6355SVipul Pandya req->tcb.opt0 = cpu_to_be64((__force u64)req->tcb.opt0); 2012ef5d6355SVipul Pandya req->tcb.opt2 = cpu_to_be32((__force u32)req->tcb.opt2); 2013793dad94SVipul Pandya set_wr_txq(skb, CPL_PRIORITY_CONTROL, ep->ctrlq_idx); 2014793dad94SVipul Pandya set_bit(ACT_OFLD_CONN, &ep->com.history); 2015caa6c9f2SHariprasad S return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 20165be78ee9SVipul Pandya } 20175be78ee9SVipul Pandya 2018cfdda9d7SSteve Wise /* 2019cfdda9d7SSteve Wise * Return whether a failed active open has allocated a TID 2020cfdda9d7SSteve Wise */ 2021cfdda9d7SSteve Wise static inline int act_open_has_tid(int status) 2022cfdda9d7SSteve Wise { 2023cfdda9d7SSteve Wise return status != CPL_ERR_TCAM_FULL && status != CPL_ERR_CONN_EXIST && 2024cfdda9d7SSteve Wise status != CPL_ERR_ARP_MISS; 2025cfdda9d7SSteve Wise } 2026cfdda9d7SSteve Wise 20277a2cea2aSSteve Wise /* Returns whether a CPL status conveys negative advice. 20287a2cea2aSSteve Wise */ 20297a2cea2aSSteve Wise static int is_neg_adv(unsigned int status) 20307a2cea2aSSteve Wise { 20317a2cea2aSSteve Wise return status == CPL_ERR_RTX_NEG_ADVICE || 20327a2cea2aSSteve Wise status == CPL_ERR_PERSIST_NEG_ADVICE || 20337a2cea2aSSteve Wise status == CPL_ERR_KEEPALV_NEG_ADVICE; 20347a2cea2aSSteve Wise } 20357a2cea2aSSteve Wise 2036dd92b124SHariprasad Shenai static char *neg_adv_str(unsigned int status) 2037dd92b124SHariprasad Shenai { 2038dd92b124SHariprasad Shenai switch (status) { 2039dd92b124SHariprasad Shenai case CPL_ERR_RTX_NEG_ADVICE: 2040dd92b124SHariprasad Shenai return "Retransmit timeout"; 2041dd92b124SHariprasad Shenai case CPL_ERR_PERSIST_NEG_ADVICE: 2042dd92b124SHariprasad Shenai return "Persist timeout"; 2043dd92b124SHariprasad Shenai case CPL_ERR_KEEPALV_NEG_ADVICE: 2044dd92b124SHariprasad Shenai return "Keepalive timeout"; 2045dd92b124SHariprasad Shenai default: 2046dd92b124SHariprasad Shenai return "Unknown"; 2047dd92b124SHariprasad Shenai } 2048dd92b124SHariprasad Shenai } 2049dd92b124SHariprasad Shenai 2050b408ff28SHariprasad Shenai static void set_tcp_window(struct c4iw_ep *ep, struct port_info *pi) 2051b408ff28SHariprasad Shenai { 2052b408ff28SHariprasad Shenai ep->snd_win = snd_win; 2053b408ff28SHariprasad Shenai ep->rcv_win = rcv_win; 2054b408ff28SHariprasad Shenai PDBG("%s snd_win %d rcv_win %d\n", __func__, ep->snd_win, ep->rcv_win); 2055b408ff28SHariprasad Shenai } 2056b408ff28SHariprasad Shenai 2057793dad94SVipul Pandya #define ACT_OPEN_RETRY_COUNT 2 2058793dad94SVipul Pandya 2059830662f6SVipul Pandya static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, 2060830662f6SVipul Pandya struct dst_entry *dst, struct c4iw_dev *cdev, 2061ac8e4c69SHariprasad S bool clear_mpa_v1, enum chip_type adapter_type, u8 tos) 2062830662f6SVipul Pandya { 2063830662f6SVipul Pandya struct neighbour *n; 2064830662f6SVipul Pandya int err, step; 2065830662f6SVipul Pandya struct net_device *pdev; 2066830662f6SVipul Pandya 2067830662f6SVipul Pandya n = dst_neigh_lookup(dst, peer_ip); 2068830662f6SVipul Pandya if (!n) 2069830662f6SVipul Pandya return -ENODEV; 2070830662f6SVipul Pandya 2071830662f6SVipul Pandya rcu_read_lock(); 2072830662f6SVipul Pandya err = -ENOMEM; 2073830662f6SVipul Pandya if (n->dev->flags & IFF_LOOPBACK) { 2074830662f6SVipul Pandya if (iptype == 4) 2075830662f6SVipul Pandya pdev = ip_dev_find(&init_net, *(__be32 *)peer_ip); 2076830662f6SVipul Pandya else if (IS_ENABLED(CONFIG_IPV6)) 2077830662f6SVipul Pandya for_each_netdev(&init_net, pdev) { 2078830662f6SVipul Pandya if (ipv6_chk_addr(&init_net, 2079830662f6SVipul Pandya (struct in6_addr *)peer_ip, 2080830662f6SVipul Pandya pdev, 1)) 2081830662f6SVipul Pandya break; 2082830662f6SVipul Pandya } 2083830662f6SVipul Pandya else 2084830662f6SVipul Pandya pdev = NULL; 2085830662f6SVipul Pandya 2086830662f6SVipul Pandya if (!pdev) { 2087830662f6SVipul Pandya err = -ENODEV; 2088830662f6SVipul Pandya goto out; 2089830662f6SVipul Pandya } 2090830662f6SVipul Pandya ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, 2091ac8e4c69SHariprasad S n, pdev, rt_tos2priority(tos)); 2092830662f6SVipul Pandya if (!ep->l2t) 2093830662f6SVipul Pandya goto out; 2094830662f6SVipul Pandya ep->mtu = pdev->mtu; 2095830662f6SVipul Pandya ep->tx_chan = cxgb4_port_chan(pdev); 2096963cab50SHariprasad S ep->smac_idx = cxgb4_tp_smt_idx(adapter_type, 2097963cab50SHariprasad S cxgb4_port_viid(pdev)); 2098830662f6SVipul Pandya step = cdev->rdev.lldi.ntxq / 2099830662f6SVipul Pandya cdev->rdev.lldi.nchan; 2100830662f6SVipul Pandya ep->txq_idx = cxgb4_port_idx(pdev) * step; 2101830662f6SVipul Pandya step = cdev->rdev.lldi.nrxq / 2102830662f6SVipul Pandya cdev->rdev.lldi.nchan; 2103830662f6SVipul Pandya ep->ctrlq_idx = cxgb4_port_idx(pdev); 2104830662f6SVipul Pandya ep->rss_qid = cdev->rdev.lldi.rxq_ids[ 2105830662f6SVipul Pandya cxgb4_port_idx(pdev) * step]; 2106b408ff28SHariprasad Shenai set_tcp_window(ep, (struct port_info *)netdev_priv(pdev)); 2107830662f6SVipul Pandya dev_put(pdev); 2108830662f6SVipul Pandya } else { 2109830662f6SVipul Pandya pdev = get_real_dev(n->dev); 2110830662f6SVipul Pandya ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, 2111830662f6SVipul Pandya n, pdev, 0); 2112830662f6SVipul Pandya if (!ep->l2t) 2113830662f6SVipul Pandya goto out; 2114830662f6SVipul Pandya ep->mtu = dst_mtu(dst); 211511b8e22dSSteve Wise ep->tx_chan = cxgb4_port_chan(pdev); 2116963cab50SHariprasad S ep->smac_idx = cxgb4_tp_smt_idx(adapter_type, 2117963cab50SHariprasad S cxgb4_port_viid(pdev)); 2118830662f6SVipul Pandya step = cdev->rdev.lldi.ntxq / 2119830662f6SVipul Pandya cdev->rdev.lldi.nchan; 212011b8e22dSSteve Wise ep->txq_idx = cxgb4_port_idx(pdev) * step; 212111b8e22dSSteve Wise ep->ctrlq_idx = cxgb4_port_idx(pdev); 2122830662f6SVipul Pandya step = cdev->rdev.lldi.nrxq / 2123830662f6SVipul Pandya cdev->rdev.lldi.nchan; 2124830662f6SVipul Pandya ep->rss_qid = cdev->rdev.lldi.rxq_ids[ 212511b8e22dSSteve Wise cxgb4_port_idx(pdev) * step]; 2126b408ff28SHariprasad Shenai set_tcp_window(ep, (struct port_info *)netdev_priv(pdev)); 2127830662f6SVipul Pandya 2128830662f6SVipul Pandya if (clear_mpa_v1) { 2129830662f6SVipul Pandya ep->retry_with_mpa_v1 = 0; 2130830662f6SVipul Pandya ep->tried_with_mpa_v1 = 0; 2131830662f6SVipul Pandya } 2132830662f6SVipul Pandya } 2133830662f6SVipul Pandya err = 0; 2134830662f6SVipul Pandya out: 2135830662f6SVipul Pandya rcu_read_unlock(); 2136830662f6SVipul Pandya 2137830662f6SVipul Pandya neigh_release(n); 2138830662f6SVipul Pandya 2139830662f6SVipul Pandya return err; 2140830662f6SVipul Pandya } 2141830662f6SVipul Pandya 2142793dad94SVipul Pandya static int c4iw_reconnect(struct c4iw_ep *ep) 2143793dad94SVipul Pandya { 2144793dad94SVipul Pandya int err = 0; 214524d44a39SSteve Wise struct sockaddr_in *laddr = (struct sockaddr_in *) 2146170003c8SSteve Wise &ep->com.cm_id->m_local_addr; 214724d44a39SSteve Wise struct sockaddr_in *raddr = (struct sockaddr_in *) 2148170003c8SSteve Wise &ep->com.cm_id->m_remote_addr; 2149830662f6SVipul Pandya struct sockaddr_in6 *laddr6 = (struct sockaddr_in6 *) 2150170003c8SSteve Wise &ep->com.cm_id->m_local_addr; 2151830662f6SVipul Pandya struct sockaddr_in6 *raddr6 = (struct sockaddr_in6 *) 2152170003c8SSteve Wise &ep->com.cm_id->m_remote_addr; 2153830662f6SVipul Pandya int iptype; 2154830662f6SVipul Pandya __u8 *ra; 2155793dad94SVipul Pandya 2156793dad94SVipul Pandya PDBG("%s qp %p cm_id %p\n", __func__, ep->com.qp, ep->com.cm_id); 2157793dad94SVipul Pandya init_timer(&ep->timer); 2158093108cbSHariprasad S c4iw_init_wr_wait(&ep->com.wr_wait); 2159793dad94SVipul Pandya 2160793dad94SVipul Pandya /* 2161793dad94SVipul Pandya * Allocate an active TID to initiate a TCP connection. 2162793dad94SVipul Pandya */ 2163793dad94SVipul Pandya ep->atid = cxgb4_alloc_atid(ep->com.dev->rdev.lldi.tids, ep); 2164793dad94SVipul Pandya if (ep->atid == -1) { 2165793dad94SVipul Pandya pr_err("%s - cannot alloc atid.\n", __func__); 2166793dad94SVipul Pandya err = -ENOMEM; 2167793dad94SVipul Pandya goto fail2; 2168793dad94SVipul Pandya } 2169793dad94SVipul Pandya insert_handle(ep->com.dev, &ep->com.dev->atid_idr, ep, ep->atid); 2170793dad94SVipul Pandya 2171793dad94SVipul Pandya /* find a route */ 2172170003c8SSteve Wise if (ep->com.cm_id->m_local_addr.ss_family == AF_INET) { 2173830662f6SVipul Pandya ep->dst = find_route(ep->com.dev, laddr->sin_addr.s_addr, 2174830662f6SVipul Pandya raddr->sin_addr.s_addr, laddr->sin_port, 2175ac8e4c69SHariprasad S raddr->sin_port, ep->com.cm_id->tos); 2176830662f6SVipul Pandya iptype = 4; 2177830662f6SVipul Pandya ra = (__u8 *)&raddr->sin_addr; 2178830662f6SVipul Pandya } else { 2179830662f6SVipul Pandya ep->dst = find_route6(ep->com.dev, laddr6->sin6_addr.s6_addr, 2180830662f6SVipul Pandya raddr6->sin6_addr.s6_addr, 2181830662f6SVipul Pandya laddr6->sin6_port, raddr6->sin6_port, 0, 2182830662f6SVipul Pandya raddr6->sin6_scope_id); 2183830662f6SVipul Pandya iptype = 6; 2184830662f6SVipul Pandya ra = (__u8 *)&raddr6->sin6_addr; 2185830662f6SVipul Pandya } 2186830662f6SVipul Pandya if (!ep->dst) { 2187793dad94SVipul Pandya pr_err("%s - cannot find route.\n", __func__); 2188793dad94SVipul Pandya err = -EHOSTUNREACH; 2189793dad94SVipul Pandya goto fail3; 2190793dad94SVipul Pandya } 2191963cab50SHariprasad S err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, false, 2192ac8e4c69SHariprasad S ep->com.dev->rdev.lldi.adapter_type, 2193ac8e4c69SHariprasad S ep->com.cm_id->tos); 2194830662f6SVipul Pandya if (err) { 2195793dad94SVipul Pandya pr_err("%s - cannot alloc l2e.\n", __func__); 2196793dad94SVipul Pandya goto fail4; 2197793dad94SVipul Pandya } 2198793dad94SVipul Pandya 2199793dad94SVipul Pandya PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n", 2200793dad94SVipul Pandya __func__, ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid, 2201793dad94SVipul Pandya ep->l2t->idx); 2202793dad94SVipul Pandya 2203793dad94SVipul Pandya state_set(&ep->com, CONNECTING); 2204ac8e4c69SHariprasad S ep->tos = ep->com.cm_id->tos; 2205793dad94SVipul Pandya 2206793dad94SVipul Pandya /* send connect request to rnic */ 2207793dad94SVipul Pandya err = send_connect(ep); 2208793dad94SVipul Pandya if (!err) 2209793dad94SVipul Pandya goto out; 2210793dad94SVipul Pandya 2211793dad94SVipul Pandya cxgb4_l2t_release(ep->l2t); 2212793dad94SVipul Pandya fail4: 2213793dad94SVipul Pandya dst_release(ep->dst); 2214793dad94SVipul Pandya fail3: 2215793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid); 2216793dad94SVipul Pandya cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid); 2217793dad94SVipul Pandya fail2: 2218793dad94SVipul Pandya /* 2219793dad94SVipul Pandya * remember to send notification to upper layer. 2220793dad94SVipul Pandya * We are in here so the upper layer is not aware that this is 2221793dad94SVipul Pandya * re-connect attempt and so, upper layer is still waiting for 2222793dad94SVipul Pandya * response of 1st connect request. 2223793dad94SVipul Pandya */ 2224793dad94SVipul Pandya connect_reply_upcall(ep, -ECONNRESET); 2225793dad94SVipul Pandya c4iw_put_ep(&ep->com); 2226793dad94SVipul Pandya out: 2227793dad94SVipul Pandya return err; 2228793dad94SVipul Pandya } 2229793dad94SVipul Pandya 2230cfdda9d7SSteve Wise static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2231cfdda9d7SSteve Wise { 2232cfdda9d7SSteve Wise struct c4iw_ep *ep; 2233cfdda9d7SSteve Wise struct cpl_act_open_rpl *rpl = cplhdr(skb); 22346c53e938SHariprasad Shenai unsigned int atid = TID_TID_G(AOPEN_ATID_G( 2235cfdda9d7SSteve Wise ntohl(rpl->atid_status))); 2236cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 22376c53e938SHariprasad Shenai int status = AOPEN_STATUS_G(ntohl(rpl->atid_status)); 2238830662f6SVipul Pandya struct sockaddr_in *la; 2239830662f6SVipul Pandya struct sockaddr_in *ra; 2240830662f6SVipul Pandya struct sockaddr_in6 *la6; 2241830662f6SVipul Pandya struct sockaddr_in6 *ra6; 2242caa6c9f2SHariprasad S int ret = 0; 2243cfdda9d7SSteve Wise 2244cfdda9d7SSteve Wise ep = lookup_atid(t, atid); 2245170003c8SSteve Wise la = (struct sockaddr_in *)&ep->com.local_addr; 2246170003c8SSteve Wise ra = (struct sockaddr_in *)&ep->com.remote_addr; 2247170003c8SSteve Wise la6 = (struct sockaddr_in6 *)&ep->com.local_addr; 2248170003c8SSteve Wise ra6 = (struct sockaddr_in6 *)&ep->com.remote_addr; 2249cfdda9d7SSteve Wise 2250cfdda9d7SSteve Wise PDBG("%s ep %p atid %u status %u errno %d\n", __func__, ep, atid, 2251cfdda9d7SSteve Wise status, status2errno(status)); 2252cfdda9d7SSteve Wise 22537a2cea2aSSteve Wise if (is_neg_adv(status)) { 2254179d03bbSHariprasad S PDBG("%s Connection problems for atid %u status %u (%s)\n", 2255179d03bbSHariprasad S __func__, atid, status, neg_adv_str(status)); 2256179d03bbSHariprasad S ep->stats.connect_neg_adv++; 2257179d03bbSHariprasad S mutex_lock(&dev->rdev.stats.lock); 2258179d03bbSHariprasad S dev->rdev.stats.neg_adv++; 2259179d03bbSHariprasad S mutex_unlock(&dev->rdev.stats.lock); 2260cfdda9d7SSteve Wise return 0; 2261cfdda9d7SSteve Wise } 2262cfdda9d7SSteve Wise 2263793dad94SVipul Pandya set_bit(ACT_OPEN_RPL, &ep->com.history); 2264793dad94SVipul Pandya 2265d716a2a0SVipul Pandya /* 2266d716a2a0SVipul Pandya * Log interesting failures. 2267d716a2a0SVipul Pandya */ 2268d716a2a0SVipul Pandya switch (status) { 2269d716a2a0SVipul Pandya case CPL_ERR_CONN_RESET: 2270d716a2a0SVipul Pandya case CPL_ERR_CONN_TIMEDOUT: 2271d716a2a0SVipul Pandya break; 22725be78ee9SVipul Pandya case CPL_ERR_TCAM_FULL: 22735be78ee9SVipul Pandya mutex_lock(&dev->rdev.stats.lock); 2274830662f6SVipul Pandya dev->rdev.stats.tcam_full++; 22755be78ee9SVipul Pandya mutex_unlock(&dev->rdev.stats.lock); 2276830662f6SVipul Pandya if (ep->com.local_addr.ss_family == AF_INET && 2277830662f6SVipul Pandya dev->rdev.lldi.enable_fw_ofld_conn) { 2278caa6c9f2SHariprasad S ret = send_fw_act_open_req(ep, TID_TID_G(AOPEN_ATID_G( 2279793dad94SVipul Pandya ntohl(rpl->atid_status)))); 2280caa6c9f2SHariprasad S if (ret) 2281caa6c9f2SHariprasad S goto fail; 22825be78ee9SVipul Pandya return 0; 2283793dad94SVipul Pandya } 2284793dad94SVipul Pandya break; 2285793dad94SVipul Pandya case CPL_ERR_CONN_EXIST: 2286793dad94SVipul Pandya if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) { 2287793dad94SVipul Pandya set_bit(ACT_RETRY_INUSE, &ep->com.history); 228884cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 228984cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 229084cc6ac6SHariprasad S (struct sockaddr_in6 *) 2291170003c8SSteve Wise &ep->com.local_addr; 229284cc6ac6SHariprasad S cxgb4_clip_release( 229384cc6ac6SHariprasad S ep->com.dev->rdev.lldi.ports[0], 229484cc6ac6SHariprasad S (const u32 *) 229584cc6ac6SHariprasad S &sin6->sin6_addr.s6_addr, 1); 229684cc6ac6SHariprasad S } 2297793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, 2298793dad94SVipul Pandya atid); 2299793dad94SVipul Pandya cxgb4_free_atid(t, atid); 2300793dad94SVipul Pandya dst_release(ep->dst); 2301793dad94SVipul Pandya cxgb4_l2t_release(ep->l2t); 2302793dad94SVipul Pandya c4iw_reconnect(ep); 2303793dad94SVipul Pandya return 0; 2304793dad94SVipul Pandya } 23055be78ee9SVipul Pandya break; 2306d716a2a0SVipul Pandya default: 2307830662f6SVipul Pandya if (ep->com.local_addr.ss_family == AF_INET) { 2308830662f6SVipul Pandya pr_info("Active open failure - atid %u status %u errno %d %pI4:%u->%pI4:%u\n", 2309d716a2a0SVipul Pandya atid, status, status2errno(status), 2310830662f6SVipul Pandya &la->sin_addr.s_addr, ntohs(la->sin_port), 2311830662f6SVipul Pandya &ra->sin_addr.s_addr, ntohs(ra->sin_port)); 2312830662f6SVipul Pandya } else { 2313830662f6SVipul Pandya pr_info("Active open failure - atid %u status %u errno %d %pI6:%u->%pI6:%u\n", 2314830662f6SVipul Pandya atid, status, status2errno(status), 2315830662f6SVipul Pandya la6->sin6_addr.s6_addr, ntohs(la6->sin6_port), 2316830662f6SVipul Pandya ra6->sin6_addr.s6_addr, ntohs(ra6->sin6_port)); 2317830662f6SVipul Pandya } 2318d716a2a0SVipul Pandya break; 2319d716a2a0SVipul Pandya } 2320d716a2a0SVipul Pandya 2321caa6c9f2SHariprasad S fail: 2322cfdda9d7SSteve Wise connect_reply_upcall(ep, status2errno(status)); 2323cfdda9d7SSteve Wise state_set(&ep->com, DEAD); 2324cfdda9d7SSteve Wise 232584cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 232684cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 2327170003c8SSteve Wise (struct sockaddr_in6 *)&ep->com.local_addr; 232884cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 232984cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 233084cc6ac6SHariprasad S } 2331cfdda9d7SSteve Wise if (status && act_open_has_tid(status)) 2332cfdda9d7SSteve Wise cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, GET_TID(rpl)); 2333cfdda9d7SSteve Wise 2334793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, atid); 2335cfdda9d7SSteve Wise cxgb4_free_atid(t, atid); 2336cfdda9d7SSteve Wise dst_release(ep->dst); 2337cfdda9d7SSteve Wise cxgb4_l2t_release(ep->l2t); 2338cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 2339cfdda9d7SSteve Wise 2340cfdda9d7SSteve Wise return 0; 2341cfdda9d7SSteve Wise } 2342cfdda9d7SSteve Wise 2343cfdda9d7SSteve Wise static int pass_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2344cfdda9d7SSteve Wise { 2345cfdda9d7SSteve Wise struct cpl_pass_open_rpl *rpl = cplhdr(skb); 2346cfdda9d7SSteve Wise unsigned int stid = GET_TID(rpl); 2347f86fac79SHariprasad S struct c4iw_listen_ep *ep = get_ep_from_stid(dev, stid); 2348cfdda9d7SSteve Wise 2349cfdda9d7SSteve Wise if (!ep) { 23501cab775cSVipul Pandya PDBG("%s stid %d lookup failure!\n", __func__, stid); 23511cab775cSVipul Pandya goto out; 2352cfdda9d7SSteve Wise } 2353cfdda9d7SSteve Wise PDBG("%s ep %p status %d error %d\n", __func__, ep, 2354cfdda9d7SSteve Wise rpl->status, status2errno(rpl->status)); 2355d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, status2errno(rpl->status)); 2356f86fac79SHariprasad S c4iw_put_ep(&ep->com); 23571cab775cSVipul Pandya out: 2358cfdda9d7SSteve Wise return 0; 2359cfdda9d7SSteve Wise } 2360cfdda9d7SSteve Wise 2361cfdda9d7SSteve Wise static int close_listsrv_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2362cfdda9d7SSteve Wise { 2363cfdda9d7SSteve Wise struct cpl_close_listsvr_rpl *rpl = cplhdr(skb); 2364cfdda9d7SSteve Wise unsigned int stid = GET_TID(rpl); 2365f86fac79SHariprasad S struct c4iw_listen_ep *ep = get_ep_from_stid(dev, stid); 2366cfdda9d7SSteve Wise 2367cfdda9d7SSteve Wise PDBG("%s ep %p\n", __func__, ep); 2368d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, status2errno(rpl->status)); 2369f86fac79SHariprasad S c4iw_put_ep(&ep->com); 2370cfdda9d7SSteve Wise return 0; 2371cfdda9d7SSteve Wise } 2372cfdda9d7SSteve Wise 23739dec900cSHariprasad S static int accept_cr(struct c4iw_ep *ep, struct sk_buff *skb, 2374cfdda9d7SSteve Wise struct cpl_pass_accept_req *req) 2375cfdda9d7SSteve Wise { 2376cfdda9d7SSteve Wise struct cpl_pass_accept_rpl *rpl; 2377cfdda9d7SSteve Wise unsigned int mtu_idx; 2378cfdda9d7SSteve Wise u64 opt0; 2379cfdda9d7SSteve Wise u32 opt2; 2380cfdda9d7SSteve Wise int wscale; 238192e7ae71SHariprasad Shenai struct cpl_t5_pass_accept_rpl *rpl5 = NULL; 2382b408ff28SHariprasad Shenai int win; 2383963cab50SHariprasad S enum chip_type adapter_type = ep->com.dev->rdev.lldi.adapter_type; 2384cfdda9d7SSteve Wise 2385cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2386cfdda9d7SSteve Wise BUG_ON(skb_cloned(skb)); 238792e7ae71SHariprasad Shenai 2388cfdda9d7SSteve Wise skb_get(skb); 238992e7ae71SHariprasad Shenai rpl = cplhdr(skb); 2390963cab50SHariprasad S if (!is_t4(adapter_type)) { 239192e7ae71SHariprasad Shenai skb_trim(skb, roundup(sizeof(*rpl5), 16)); 239292e7ae71SHariprasad Shenai rpl5 = (void *)rpl; 239392e7ae71SHariprasad Shenai INIT_TP_WR(rpl5, ep->hwtid); 239492e7ae71SHariprasad Shenai } else { 239592e7ae71SHariprasad Shenai skb_trim(skb, sizeof(*rpl)); 239692e7ae71SHariprasad Shenai INIT_TP_WR(rpl, ep->hwtid); 239792e7ae71SHariprasad Shenai } 239892e7ae71SHariprasad Shenai OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_PASS_ACCEPT_RPL, 239992e7ae71SHariprasad Shenai ep->hwtid)); 240092e7ae71SHariprasad Shenai 240192e7ae71SHariprasad Shenai best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, 240204524a47SHariprasad S enable_tcp_timestamps && req->tcpopt.tstamp, 240304524a47SHariprasad S (AF_INET == ep->com.remote_addr.ss_family) ? 0 : 1); 2404cfdda9d7SSteve Wise wscale = compute_wscale(rcv_win); 2405b408ff28SHariprasad Shenai 2406b408ff28SHariprasad Shenai /* 2407b408ff28SHariprasad Shenai * Specify the largest window that will fit in opt0. The 2408b408ff28SHariprasad Shenai * remainder will be specified in the rx_data_ack. 2409b408ff28SHariprasad Shenai */ 2410b408ff28SHariprasad Shenai win = ep->rcv_win >> 10; 2411d7990b0cSAnish Bhatt if (win > RCV_BUFSIZ_M) 2412d7990b0cSAnish Bhatt win = RCV_BUFSIZ_M; 24136c53e938SHariprasad Shenai opt0 = (nocong ? NO_CONG_F : 0) | 2414d7990b0cSAnish Bhatt KEEP_ALIVE_F | 24156c53e938SHariprasad Shenai DELACK_F | 2416d7990b0cSAnish Bhatt WND_SCALE_V(wscale) | 2417d7990b0cSAnish Bhatt MSS_IDX_V(mtu_idx) | 2418d7990b0cSAnish Bhatt L2T_IDX_V(ep->l2t->idx) | 2419d7990b0cSAnish Bhatt TX_CHAN_V(ep->tx_chan) | 2420d7990b0cSAnish Bhatt SMAC_SEL_V(ep->smac_idx) | 24216c53e938SHariprasad Shenai DSCP_V(ep->tos >> 2) | 2422d7990b0cSAnish Bhatt ULP_MODE_V(ULP_MODE_TCPDDP) | 2423d7990b0cSAnish Bhatt RCV_BUFSIZ_V(win); 2424d7990b0cSAnish Bhatt opt2 = RX_CHANNEL_V(0) | 2425d7990b0cSAnish Bhatt RSS_QUEUE_VALID_F | RSS_QUEUE_V(ep->rss_qid); 2426cfdda9d7SSteve Wise 2427cfdda9d7SSteve Wise if (enable_tcp_timestamps && req->tcpopt.tstamp) 24286c53e938SHariprasad Shenai opt2 |= TSTAMPS_EN_F; 2429cfdda9d7SSteve Wise if (enable_tcp_sack && req->tcpopt.sack) 24306c53e938SHariprasad Shenai opt2 |= SACK_EN_F; 2431cfdda9d7SSteve Wise if (wscale && enable_tcp_window_scaling) 2432d7990b0cSAnish Bhatt opt2 |= WND_SCALE_EN_F; 24335be78ee9SVipul Pandya if (enable_ecn) { 24345be78ee9SVipul Pandya const struct tcphdr *tcph; 24355be78ee9SVipul Pandya u32 hlen = ntohl(req->hdr_len); 24365be78ee9SVipul Pandya 2437963cab50SHariprasad S if (CHELSIO_CHIP_VERSION(adapter_type) <= CHELSIO_T5) 2438cf7fe64aSHariprasad Shenai tcph = (const void *)(req + 1) + ETH_HDR_LEN_G(hlen) + 2439cf7fe64aSHariprasad Shenai IP_HDR_LEN_G(hlen); 2440963cab50SHariprasad S else 2441963cab50SHariprasad S tcph = (const void *)(req + 1) + 2442963cab50SHariprasad S T6_ETH_HDR_LEN_G(hlen) + T6_IP_HDR_LEN_G(hlen); 24435be78ee9SVipul Pandya if (tcph->ece && tcph->cwr) 24446c53e938SHariprasad Shenai opt2 |= CCTRL_ECN_V(1); 24455be78ee9SVipul Pandya } 2446963cab50SHariprasad S if (CHELSIO_CHIP_VERSION(adapter_type) > CHELSIO_T4) { 244792e7ae71SHariprasad Shenai u32 isn = (prandom_u32() & ~7UL) - 1; 2448d7990b0cSAnish Bhatt opt2 |= T5_OPT_2_VALID_F; 2449cf7fe64aSHariprasad Shenai opt2 |= CONG_CNTRL_V(CONG_ALG_TAHOE); 24500b741047SHariprasad S opt2 |= T5_ISS_F; 245192e7ae71SHariprasad Shenai rpl5 = (void *)rpl; 245292e7ae71SHariprasad Shenai memset(&rpl5->iss, 0, roundup(sizeof(*rpl5)-sizeof(*rpl), 16)); 245392e7ae71SHariprasad Shenai if (peer2peer) 245492e7ae71SHariprasad Shenai isn += 4; 245592e7ae71SHariprasad Shenai rpl5->iss = cpu_to_be32(isn); 245692e7ae71SHariprasad Shenai PDBG("%s iss %u\n", __func__, be32_to_cpu(rpl5->iss)); 245792e5011aSSteve Wise } 2458cfdda9d7SSteve Wise 2459cfdda9d7SSteve Wise rpl->opt0 = cpu_to_be64(opt0); 2460cfdda9d7SSteve Wise rpl->opt2 = cpu_to_be32(opt2); 2461d4f1a5c6SSteve Wise set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->ctrlq_idx); 24629dec900cSHariprasad S t4_set_arp_err_handler(skb, ep, pass_accept_rpl_arp_failure); 2463cfdda9d7SSteve Wise 24649dec900cSHariprasad S return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 2465cfdda9d7SSteve Wise } 2466cfdda9d7SSteve Wise 2467830662f6SVipul Pandya static void reject_cr(struct c4iw_dev *dev, u32 hwtid, struct sk_buff *skb) 2468cfdda9d7SSteve Wise { 2469830662f6SVipul Pandya PDBG("%s c4iw_dev %p tid %u\n", __func__, dev, hwtid); 2470cfdda9d7SSteve Wise BUG_ON(skb_cloned(skb)); 2471cfdda9d7SSteve Wise skb_trim(skb, sizeof(struct cpl_tid_release)); 2472cfdda9d7SSteve Wise release_tid(&dev->rdev, hwtid, skb); 2473cfdda9d7SSteve Wise return; 2474cfdda9d7SSteve Wise } 2475cfdda9d7SSteve Wise 2476963cab50SHariprasad S static void get_4tuple(struct cpl_pass_accept_req *req, enum chip_type type, 2477963cab50SHariprasad S int *iptype, __u8 *local_ip, __u8 *peer_ip, 2478cfdda9d7SSteve Wise __be16 *local_port, __be16 *peer_port) 2479cfdda9d7SSteve Wise { 2480963cab50SHariprasad S int eth_len = (CHELSIO_CHIP_VERSION(type) <= CHELSIO_T5) ? 2481963cab50SHariprasad S ETH_HDR_LEN_G(be32_to_cpu(req->hdr_len)) : 2482963cab50SHariprasad S T6_ETH_HDR_LEN_G(be32_to_cpu(req->hdr_len)); 2483963cab50SHariprasad S int ip_len = (CHELSIO_CHIP_VERSION(type) <= CHELSIO_T5) ? 2484963cab50SHariprasad S IP_HDR_LEN_G(be32_to_cpu(req->hdr_len)) : 2485963cab50SHariprasad S T6_IP_HDR_LEN_G(be32_to_cpu(req->hdr_len)); 2486cfdda9d7SSteve Wise struct iphdr *ip = (struct iphdr *)((u8 *)(req + 1) + eth_len); 2487830662f6SVipul Pandya struct ipv6hdr *ip6 = (struct ipv6hdr *)((u8 *)(req + 1) + eth_len); 2488cfdda9d7SSteve Wise struct tcphdr *tcp = (struct tcphdr *) 2489cfdda9d7SSteve Wise ((u8 *)(req + 1) + eth_len + ip_len); 2490cfdda9d7SSteve Wise 2491830662f6SVipul Pandya if (ip->version == 4) { 2492cfdda9d7SSteve Wise PDBG("%s saddr 0x%x daddr 0x%x sport %u dport %u\n", __func__, 2493cfdda9d7SSteve Wise ntohl(ip->saddr), ntohl(ip->daddr), ntohs(tcp->source), 2494cfdda9d7SSteve Wise ntohs(tcp->dest)); 2495830662f6SVipul Pandya *iptype = 4; 2496830662f6SVipul Pandya memcpy(peer_ip, &ip->saddr, 4); 2497830662f6SVipul Pandya memcpy(local_ip, &ip->daddr, 4); 2498830662f6SVipul Pandya } else { 2499830662f6SVipul Pandya PDBG("%s saddr %pI6 daddr %pI6 sport %u dport %u\n", __func__, 2500830662f6SVipul Pandya ip6->saddr.s6_addr, ip6->daddr.s6_addr, ntohs(tcp->source), 2501830662f6SVipul Pandya ntohs(tcp->dest)); 2502830662f6SVipul Pandya *iptype = 6; 2503830662f6SVipul Pandya memcpy(peer_ip, ip6->saddr.s6_addr, 16); 2504830662f6SVipul Pandya memcpy(local_ip, ip6->daddr.s6_addr, 16); 2505830662f6SVipul Pandya } 2506cfdda9d7SSteve Wise *peer_port = tcp->source; 2507cfdda9d7SSteve Wise *local_port = tcp->dest; 2508cfdda9d7SSteve Wise 2509cfdda9d7SSteve Wise return; 2510cfdda9d7SSteve Wise } 2511cfdda9d7SSteve Wise 2512cfdda9d7SSteve Wise static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) 2513cfdda9d7SSteve Wise { 2514793dad94SVipul Pandya struct c4iw_ep *child_ep = NULL, *parent_ep; 2515cfdda9d7SSteve Wise struct cpl_pass_accept_req *req = cplhdr(skb); 25166c53e938SHariprasad Shenai unsigned int stid = PASS_OPEN_TID_G(ntohl(req->tos_stid)); 2517cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 2518cfdda9d7SSteve Wise unsigned int hwtid = GET_TID(req); 2519cfdda9d7SSteve Wise struct dst_entry *dst; 2520830662f6SVipul Pandya __u8 local_ip[16], peer_ip[16]; 2521cfdda9d7SSteve Wise __be16 local_port, peer_port; 252284cc6ac6SHariprasad S struct sockaddr_in6 *sin6; 25233786cf18SDavid Miller int err; 25241cab775cSVipul Pandya u16 peer_mss = ntohs(req->tcpopt.mss); 2525830662f6SVipul Pandya int iptype; 252692e7ae71SHariprasad Shenai unsigned short hdrs; 2527ac8e4c69SHariprasad S u8 tos = PASS_OPEN_TOS_G(ntohl(req->tos_stid)); 2528cfdda9d7SSteve Wise 2529f86fac79SHariprasad S parent_ep = (struct c4iw_ep *)get_ep_from_stid(dev, stid); 25301cab775cSVipul Pandya if (!parent_ep) { 25311cab775cSVipul Pandya PDBG("%s connect request on invalid stid %d\n", __func__, stid); 25321cab775cSVipul Pandya goto reject; 25331cab775cSVipul Pandya } 25341cab775cSVipul Pandya 2535cfdda9d7SSteve Wise if (state_read(&parent_ep->com) != LISTEN) { 25366812faefSHariprasad S PDBG("%s - listening ep not in LISTEN\n", __func__); 2537cfdda9d7SSteve Wise goto reject; 2538cfdda9d7SSteve Wise } 2539cfdda9d7SSteve Wise 2540963cab50SHariprasad S get_4tuple(req, parent_ep->com.dev->rdev.lldi.adapter_type, &iptype, 2541963cab50SHariprasad S local_ip, peer_ip, &local_port, &peer_port); 2542830662f6SVipul Pandya 2543cfdda9d7SSteve Wise /* Find output route */ 2544830662f6SVipul Pandya if (iptype == 4) { 2545830662f6SVipul Pandya PDBG("%s parent ep %p hwtid %u laddr %pI4 raddr %pI4 lport %d rport %d peer_mss %d\n" 2546830662f6SVipul Pandya , __func__, parent_ep, hwtid, 2547830662f6SVipul Pandya local_ip, peer_ip, ntohs(local_port), 2548830662f6SVipul Pandya ntohs(peer_port), peer_mss); 2549830662f6SVipul Pandya dst = find_route(dev, *(__be32 *)local_ip, *(__be32 *)peer_ip, 2550830662f6SVipul Pandya local_port, peer_port, 2551ac8e4c69SHariprasad S tos); 2552830662f6SVipul Pandya } else { 2553830662f6SVipul Pandya PDBG("%s parent ep %p hwtid %u laddr %pI6 raddr %pI6 lport %d rport %d peer_mss %d\n" 2554830662f6SVipul Pandya , __func__, parent_ep, hwtid, 2555830662f6SVipul Pandya local_ip, peer_ip, ntohs(local_port), 2556830662f6SVipul Pandya ntohs(peer_port), peer_mss); 2557830662f6SVipul Pandya dst = find_route6(dev, local_ip, peer_ip, local_port, peer_port, 25586c53e938SHariprasad Shenai PASS_OPEN_TOS_G(ntohl(req->tos_stid)), 2559830662f6SVipul Pandya ((struct sockaddr_in6 *) 2560830662f6SVipul Pandya &parent_ep->com.local_addr)->sin6_scope_id); 2561830662f6SVipul Pandya } 2562830662f6SVipul Pandya if (!dst) { 2563cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - failed to find dst entry!\n", 2564cfdda9d7SSteve Wise __func__); 2565cfdda9d7SSteve Wise goto reject; 2566cfdda9d7SSteve Wise } 2567cfdda9d7SSteve Wise 2568cfdda9d7SSteve Wise child_ep = alloc_ep(sizeof(*child_ep), GFP_KERNEL); 2569cfdda9d7SSteve Wise if (!child_ep) { 2570cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - failed to allocate ep entry!\n", 2571cfdda9d7SSteve Wise __func__); 2572cfdda9d7SSteve Wise dst_release(dst); 2573cfdda9d7SSteve Wise goto reject; 2574cfdda9d7SSteve Wise } 25753786cf18SDavid Miller 2576963cab50SHariprasad S err = import_ep(child_ep, iptype, peer_ip, dst, dev, false, 2577ac8e4c69SHariprasad S parent_ep->com.dev->rdev.lldi.adapter_type, tos); 25783786cf18SDavid Miller if (err) { 25793786cf18SDavid Miller printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n", 25803786cf18SDavid Miller __func__); 25813786cf18SDavid Miller dst_release(dst); 25823786cf18SDavid Miller kfree(child_ep); 25833786cf18SDavid Miller goto reject; 25843786cf18SDavid Miller } 25853786cf18SDavid Miller 258692e7ae71SHariprasad Shenai hdrs = sizeof(struct iphdr) + sizeof(struct tcphdr) + 258792e7ae71SHariprasad Shenai ((enable_tcp_timestamps && req->tcpopt.tstamp) ? 12 : 0); 258892e7ae71SHariprasad Shenai if (peer_mss && child_ep->mtu > (peer_mss + hdrs)) 258992e7ae71SHariprasad Shenai child_ep->mtu = peer_mss + hdrs; 25901cab775cSVipul Pandya 2591cfdda9d7SSteve Wise state_set(&child_ep->com, CONNECTING); 2592cfdda9d7SSteve Wise child_ep->com.dev = dev; 2593cfdda9d7SSteve Wise child_ep->com.cm_id = NULL; 25945b6b8fe6SSteve Wise 2595830662f6SVipul Pandya if (iptype == 4) { 2596830662f6SVipul Pandya struct sockaddr_in *sin = (struct sockaddr_in *) 2597170003c8SSteve Wise &child_ep->com.local_addr; 25985b6b8fe6SSteve Wise 2599830662f6SVipul Pandya sin->sin_family = PF_INET; 2600830662f6SVipul Pandya sin->sin_port = local_port; 2601830662f6SVipul Pandya sin->sin_addr.s_addr = *(__be32 *)local_ip; 26025b6b8fe6SSteve Wise 26035b6b8fe6SSteve Wise sin = (struct sockaddr_in *)&child_ep->com.local_addr; 26045b6b8fe6SSteve Wise sin->sin_family = PF_INET; 26055b6b8fe6SSteve Wise sin->sin_port = ((struct sockaddr_in *) 26065b6b8fe6SSteve Wise &parent_ep->com.local_addr)->sin_port; 26075b6b8fe6SSteve Wise sin->sin_addr.s_addr = *(__be32 *)local_ip; 26085b6b8fe6SSteve Wise 2609170003c8SSteve Wise sin = (struct sockaddr_in *)&child_ep->com.remote_addr; 2610830662f6SVipul Pandya sin->sin_family = PF_INET; 2611830662f6SVipul Pandya sin->sin_port = peer_port; 2612830662f6SVipul Pandya sin->sin_addr.s_addr = *(__be32 *)peer_ip; 2613830662f6SVipul Pandya } else { 2614170003c8SSteve Wise sin6 = (struct sockaddr_in6 *)&child_ep->com.local_addr; 2615830662f6SVipul Pandya sin6->sin6_family = PF_INET6; 2616830662f6SVipul Pandya sin6->sin6_port = local_port; 2617830662f6SVipul Pandya memcpy(sin6->sin6_addr.s6_addr, local_ip, 16); 26185b6b8fe6SSteve Wise 26195b6b8fe6SSteve Wise sin6 = (struct sockaddr_in6 *)&child_ep->com.local_addr; 26205b6b8fe6SSteve Wise sin6->sin6_family = PF_INET6; 26215b6b8fe6SSteve Wise sin6->sin6_port = ((struct sockaddr_in6 *) 26225b6b8fe6SSteve Wise &parent_ep->com.local_addr)->sin6_port; 26235b6b8fe6SSteve Wise memcpy(sin6->sin6_addr.s6_addr, local_ip, 16); 26245b6b8fe6SSteve Wise 2625170003c8SSteve Wise sin6 = (struct sockaddr_in6 *)&child_ep->com.remote_addr; 2626830662f6SVipul Pandya sin6->sin6_family = PF_INET6; 2627830662f6SVipul Pandya sin6->sin6_port = peer_port; 2628830662f6SVipul Pandya memcpy(sin6->sin6_addr.s6_addr, peer_ip, 16); 2629830662f6SVipul Pandya } 26305b6b8fe6SSteve Wise 2631cfdda9d7SSteve Wise c4iw_get_ep(&parent_ep->com); 2632cfdda9d7SSteve Wise child_ep->parent_ep = parent_ep; 2633ac8e4c69SHariprasad S child_ep->tos = tos; 2634cfdda9d7SSteve Wise child_ep->dst = dst; 2635cfdda9d7SSteve Wise child_ep->hwtid = hwtid; 2636cfdda9d7SSteve Wise 2637cfdda9d7SSteve Wise PDBG("%s tx_chan %u smac_idx %u rss_qid %u\n", __func__, 26383786cf18SDavid Miller child_ep->tx_chan, child_ep->smac_idx, child_ep->rss_qid); 2639cfdda9d7SSteve Wise 2640cfdda9d7SSteve Wise init_timer(&child_ep->timer); 2641cfdda9d7SSteve Wise cxgb4_insert_tid(t, child_ep, hwtid); 2642944661ddSHariprasad S insert_ep_tid(child_ep); 26439dec900cSHariprasad S if (accept_cr(child_ep, skb, req)) { 26449dec900cSHariprasad S c4iw_put_ep(&parent_ep->com); 26459dec900cSHariprasad S release_ep_resources(child_ep); 26469dec900cSHariprasad S } else { 2647793dad94SVipul Pandya set_bit(PASS_ACCEPT_REQ, &child_ep->com.history); 26489dec900cSHariprasad S } 264984cc6ac6SHariprasad S if (iptype == 6) { 2650170003c8SSteve Wise sin6 = (struct sockaddr_in6 *)&child_ep->com.local_addr; 265184cc6ac6SHariprasad S cxgb4_clip_get(child_ep->com.dev->rdev.lldi.ports[0], 265284cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 265384cc6ac6SHariprasad S } 2654cfdda9d7SSteve Wise goto out; 2655cfdda9d7SSteve Wise reject: 2656830662f6SVipul Pandya reject_cr(dev, hwtid, skb); 2657f86fac79SHariprasad S if (parent_ep) 2658f86fac79SHariprasad S c4iw_put_ep(&parent_ep->com); 2659cfdda9d7SSteve Wise out: 2660cfdda9d7SSteve Wise return 0; 2661cfdda9d7SSteve Wise } 2662cfdda9d7SSteve Wise 2663cfdda9d7SSteve Wise static int pass_establish(struct c4iw_dev *dev, struct sk_buff *skb) 2664cfdda9d7SSteve Wise { 2665cfdda9d7SSteve Wise struct c4iw_ep *ep; 2666cfdda9d7SSteve Wise struct cpl_pass_establish *req = cplhdr(skb); 2667cfdda9d7SSteve Wise unsigned int tid = GET_TID(req); 2668fef4422dSHariprasad S int ret; 2669cfdda9d7SSteve Wise 2670944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 2671cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2672cfdda9d7SSteve Wise ep->snd_seq = be32_to_cpu(req->snd_isn); 2673cfdda9d7SSteve Wise ep->rcv_seq = be32_to_cpu(req->rcv_isn); 2674cfdda9d7SSteve Wise 26751cab775cSVipul Pandya PDBG("%s ep %p hwtid %u tcp_opt 0x%02x\n", __func__, ep, tid, 26761cab775cSVipul Pandya ntohs(req->tcp_opt)); 26771cab775cSVipul Pandya 2678cfdda9d7SSteve Wise set_emss(ep, ntohs(req->tcp_opt)); 2679cfdda9d7SSteve Wise 2680cfdda9d7SSteve Wise dst_confirm(ep->dst); 2681fef4422dSHariprasad S mutex_lock(&ep->com.mutex); 2682fef4422dSHariprasad S ep->com.state = MPA_REQ_WAIT; 2683cfdda9d7SSteve Wise start_ep_timer(ep); 2684793dad94SVipul Pandya set_bit(PASS_ESTAB, &ep->com.history); 2685fef4422dSHariprasad S ret = send_flowc(ep, skb); 2686fef4422dSHariprasad S mutex_unlock(&ep->com.mutex); 2687fef4422dSHariprasad S if (ret) 2688fef4422dSHariprasad S c4iw_ep_disconnect(ep, 1, GFP_KERNEL); 2689944661ddSHariprasad S c4iw_put_ep(&ep->com); 2690cfdda9d7SSteve Wise 2691cfdda9d7SSteve Wise return 0; 2692cfdda9d7SSteve Wise } 2693cfdda9d7SSteve Wise 2694cfdda9d7SSteve Wise static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb) 2695cfdda9d7SSteve Wise { 2696cfdda9d7SSteve Wise struct cpl_peer_close *hdr = cplhdr(skb); 2697cfdda9d7SSteve Wise struct c4iw_ep *ep; 2698cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 2699cfdda9d7SSteve Wise int disconnect = 1; 2700cfdda9d7SSteve Wise int release = 0; 2701cfdda9d7SSteve Wise unsigned int tid = GET_TID(hdr); 27028da7e7a5SSteve Wise int ret; 2703cfdda9d7SSteve Wise 2704944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 2705944661ddSHariprasad S if (!ep) 2706944661ddSHariprasad S return 0; 2707944661ddSHariprasad S 2708cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2709cfdda9d7SSteve Wise dst_confirm(ep->dst); 2710cfdda9d7SSteve Wise 2711793dad94SVipul Pandya set_bit(PEER_CLOSE, &ep->com.history); 27122f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 2713cfdda9d7SSteve Wise switch (ep->com.state) { 2714cfdda9d7SSteve Wise case MPA_REQ_WAIT: 2715cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2716cfdda9d7SSteve Wise break; 2717cfdda9d7SSteve Wise case MPA_REQ_SENT: 2718cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2719cfdda9d7SSteve Wise connect_reply_upcall(ep, -ECONNRESET); 2720cfdda9d7SSteve Wise break; 2721cfdda9d7SSteve Wise case MPA_REQ_RCVD: 2722cfdda9d7SSteve Wise 2723cfdda9d7SSteve Wise /* 2724cfdda9d7SSteve Wise * We're gonna mark this puppy DEAD, but keep 2725cfdda9d7SSteve Wise * the reference on it until the ULP accepts or 2726cfdda9d7SSteve Wise * rejects the CR. Also wake up anyone waiting 2727cfdda9d7SSteve Wise * in rdma connection migration (see c4iw_accept_cr()). 2728cfdda9d7SSteve Wise */ 2729cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2730cfdda9d7SSteve Wise PDBG("waking up ep %p tid %u\n", ep, ep->hwtid); 2731d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 2732cfdda9d7SSteve Wise break; 2733cfdda9d7SSteve Wise case MPA_REP_SENT: 2734cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2735cfdda9d7SSteve Wise PDBG("waking up ep %p tid %u\n", ep, ep->hwtid); 2736d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 2737cfdda9d7SSteve Wise break; 2738cfdda9d7SSteve Wise case FPDU_MODE: 2739ca5a2202SSteve Wise start_ep_timer(ep); 2740cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 274130c95c2dSSteve Wise attrs.next_state = C4IW_QP_STATE_CLOSING; 27428da7e7a5SSteve Wise ret = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 274330c95c2dSSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 27448da7e7a5SSteve Wise if (ret != -ECONNRESET) { 2745cfdda9d7SSteve Wise peer_close_upcall(ep); 274630c95c2dSSteve Wise disconnect = 1; 27478da7e7a5SSteve Wise } 2748cfdda9d7SSteve Wise break; 2749cfdda9d7SSteve Wise case ABORTING: 2750cfdda9d7SSteve Wise disconnect = 0; 2751cfdda9d7SSteve Wise break; 2752cfdda9d7SSteve Wise case CLOSING: 2753cfdda9d7SSteve Wise __state_set(&ep->com, MORIBUND); 2754cfdda9d7SSteve Wise disconnect = 0; 2755cfdda9d7SSteve Wise break; 2756cfdda9d7SSteve Wise case MORIBUND: 2757b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 2758cfdda9d7SSteve Wise if (ep->com.cm_id && ep->com.qp) { 2759cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_IDLE; 2760cfdda9d7SSteve Wise c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 2761cfdda9d7SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 2762cfdda9d7SSteve Wise } 2763be13b2dfSSteve Wise close_complete_upcall(ep, 0); 2764cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 2765cfdda9d7SSteve Wise release = 1; 2766cfdda9d7SSteve Wise disconnect = 0; 2767cfdda9d7SSteve Wise break; 2768cfdda9d7SSteve Wise case DEAD: 2769cfdda9d7SSteve Wise disconnect = 0; 2770cfdda9d7SSteve Wise break; 2771cfdda9d7SSteve Wise default: 2772cfdda9d7SSteve Wise BUG_ON(1); 2773cfdda9d7SSteve Wise } 27742f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 2775cfdda9d7SSteve Wise if (disconnect) 2776cfdda9d7SSteve Wise c4iw_ep_disconnect(ep, 0, GFP_KERNEL); 2777cfdda9d7SSteve Wise if (release) 2778cfdda9d7SSteve Wise release_ep_resources(ep); 2779944661ddSHariprasad S c4iw_put_ep(&ep->com); 2780cfdda9d7SSteve Wise return 0; 2781cfdda9d7SSteve Wise } 2782cfdda9d7SSteve Wise 2783cfdda9d7SSteve Wise static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) 2784cfdda9d7SSteve Wise { 2785cfdda9d7SSteve Wise struct cpl_abort_req_rss *req = cplhdr(skb); 2786cfdda9d7SSteve Wise struct c4iw_ep *ep; 2787cfdda9d7SSteve Wise struct cpl_abort_rpl *rpl; 2788cfdda9d7SSteve Wise struct sk_buff *rpl_skb; 2789cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 2790cfdda9d7SSteve Wise int ret; 2791cfdda9d7SSteve Wise int release = 0; 2792cfdda9d7SSteve Wise unsigned int tid = GET_TID(req); 2793cfdda9d7SSteve Wise 2794944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 2795944661ddSHariprasad S if (!ep) 2796944661ddSHariprasad S return 0; 2797944661ddSHariprasad S 27987a2cea2aSSteve Wise if (is_neg_adv(req->status)) { 2799179d03bbSHariprasad S PDBG("%s Negative advice on abort- tid %u status %d (%s)\n", 2800179d03bbSHariprasad S __func__, ep->hwtid, req->status, 2801179d03bbSHariprasad S neg_adv_str(req->status)); 2802179d03bbSHariprasad S ep->stats.abort_neg_adv++; 2803179d03bbSHariprasad S mutex_lock(&dev->rdev.stats.lock); 2804179d03bbSHariprasad S dev->rdev.stats.neg_adv++; 2805179d03bbSHariprasad S mutex_unlock(&dev->rdev.stats.lock); 2806944661ddSHariprasad S goto deref_ep; 2807cfdda9d7SSteve Wise } 2808cfdda9d7SSteve Wise PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid, 2809cfdda9d7SSteve Wise ep->com.state); 2810793dad94SVipul Pandya set_bit(PEER_ABORT, &ep->com.history); 28112f5b48c3SSteve Wise 28122f5b48c3SSteve Wise /* 28132f5b48c3SSteve Wise * Wake up any threads in rdma_init() or rdma_fini(). 2814d2fe99e8SKumar Sanghvi * However, this is not needed if com state is just 2815d2fe99e8SKumar Sanghvi * MPA_REQ_SENT 28162f5b48c3SSteve Wise */ 2817d2fe99e8SKumar Sanghvi if (ep->com.state != MPA_REQ_SENT) 2818d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 28192f5b48c3SSteve Wise 28202f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 2821cfdda9d7SSteve Wise switch (ep->com.state) { 2822cfdda9d7SSteve Wise case CONNECTING: 28239dec900cSHariprasad S c4iw_put_ep(&ep->parent_ep->com); 2824cfdda9d7SSteve Wise break; 2825cfdda9d7SSteve Wise case MPA_REQ_WAIT: 2826b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 2827cfdda9d7SSteve Wise break; 2828cfdda9d7SSteve Wise case MPA_REQ_SENT: 2829b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 2830fe7e0a4dSVipul Pandya if (mpa_rev == 1 || (mpa_rev == 2 && ep->tried_with_mpa_v1)) 2831cfdda9d7SSteve Wise connect_reply_upcall(ep, -ECONNRESET); 2832d2fe99e8SKumar Sanghvi else { 2833d2fe99e8SKumar Sanghvi /* 2834d2fe99e8SKumar Sanghvi * we just don't send notification upwards because we 2835d2fe99e8SKumar Sanghvi * want to retry with mpa_v1 without upper layers even 2836d2fe99e8SKumar Sanghvi * knowing it. 2837d2fe99e8SKumar Sanghvi * 2838d2fe99e8SKumar Sanghvi * do some housekeeping so as to re-initiate the 2839d2fe99e8SKumar Sanghvi * connection 2840d2fe99e8SKumar Sanghvi */ 2841d2fe99e8SKumar Sanghvi PDBG("%s: mpa_rev=%d. Retrying with mpav1\n", __func__, 2842d2fe99e8SKumar Sanghvi mpa_rev); 2843d2fe99e8SKumar Sanghvi ep->retry_with_mpa_v1 = 1; 2844d2fe99e8SKumar Sanghvi } 2845cfdda9d7SSteve Wise break; 2846cfdda9d7SSteve Wise case MPA_REP_SENT: 2847cfdda9d7SSteve Wise break; 2848cfdda9d7SSteve Wise case MPA_REQ_RCVD: 2849cfdda9d7SSteve Wise break; 2850cfdda9d7SSteve Wise case MORIBUND: 2851cfdda9d7SSteve Wise case CLOSING: 2852ca5a2202SSteve Wise stop_ep_timer(ep); 2853cfdda9d7SSteve Wise /*FALLTHROUGH*/ 2854cfdda9d7SSteve Wise case FPDU_MODE: 2855cfdda9d7SSteve Wise if (ep->com.cm_id && ep->com.qp) { 2856cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_ERROR; 2857cfdda9d7SSteve Wise ret = c4iw_modify_qp(ep->com.qp->rhp, 2858cfdda9d7SSteve Wise ep->com.qp, C4IW_QP_ATTR_NEXT_STATE, 2859cfdda9d7SSteve Wise &attrs, 1); 2860cfdda9d7SSteve Wise if (ret) 2861cfdda9d7SSteve Wise printk(KERN_ERR MOD 2862cfdda9d7SSteve Wise "%s - qp <- error failed!\n", 2863cfdda9d7SSteve Wise __func__); 2864cfdda9d7SSteve Wise } 2865cfdda9d7SSteve Wise peer_abort_upcall(ep); 2866cfdda9d7SSteve Wise break; 2867cfdda9d7SSteve Wise case ABORTING: 2868cfdda9d7SSteve Wise break; 2869cfdda9d7SSteve Wise case DEAD: 2870cfdda9d7SSteve Wise PDBG("%s PEER_ABORT IN DEAD STATE!!!!\n", __func__); 28712f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 2872944661ddSHariprasad S goto deref_ep; 2873cfdda9d7SSteve Wise default: 2874cfdda9d7SSteve Wise BUG_ON(1); 2875cfdda9d7SSteve Wise break; 2876cfdda9d7SSteve Wise } 2877cfdda9d7SSteve Wise dst_confirm(ep->dst); 2878cfdda9d7SSteve Wise if (ep->com.state != ABORTING) { 2879cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 2880d2fe99e8SKumar Sanghvi /* we don't release if we want to retry with mpa_v1 */ 2881d2fe99e8SKumar Sanghvi if (!ep->retry_with_mpa_v1) 2882cfdda9d7SSteve Wise release = 1; 2883cfdda9d7SSteve Wise } 28842f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 2885cfdda9d7SSteve Wise 2886cfdda9d7SSteve Wise rpl_skb = get_skb(skb, sizeof(*rpl), GFP_KERNEL); 2887cfdda9d7SSteve Wise if (!rpl_skb) { 2888cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot allocate skb!\n", 2889cfdda9d7SSteve Wise __func__); 2890cfdda9d7SSteve Wise release = 1; 2891cfdda9d7SSteve Wise goto out; 2892cfdda9d7SSteve Wise } 2893cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 2894cfdda9d7SSteve Wise rpl = (struct cpl_abort_rpl *) skb_put(rpl_skb, sizeof(*rpl)); 2895cfdda9d7SSteve Wise INIT_TP_WR(rpl, ep->hwtid); 2896cfdda9d7SSteve Wise OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_RPL, ep->hwtid)); 2897cfdda9d7SSteve Wise rpl->cmd = CPL_ABORT_NO_RST; 2898cfdda9d7SSteve Wise c4iw_ofld_send(&ep->com.dev->rdev, rpl_skb); 2899cfdda9d7SSteve Wise out: 2900cfdda9d7SSteve Wise if (release) 2901cfdda9d7SSteve Wise release_ep_resources(ep); 2902fe7e0a4dSVipul Pandya else if (ep->retry_with_mpa_v1) { 290384cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 290484cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 290584cc6ac6SHariprasad S (struct sockaddr_in6 *) 2906170003c8SSteve Wise &ep->com.local_addr; 290784cc6ac6SHariprasad S cxgb4_clip_release( 290884cc6ac6SHariprasad S ep->com.dev->rdev.lldi.ports[0], 290984cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 291084cc6ac6SHariprasad S 1); 291184cc6ac6SHariprasad S } 2912fe7e0a4dSVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->hwtid_idr, ep->hwtid); 2913d2fe99e8SKumar Sanghvi cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid); 2914d2fe99e8SKumar Sanghvi dst_release(ep->dst); 2915d2fe99e8SKumar Sanghvi cxgb4_l2t_release(ep->l2t); 2916d2fe99e8SKumar Sanghvi c4iw_reconnect(ep); 2917d2fe99e8SKumar Sanghvi } 2918d2fe99e8SKumar Sanghvi 2919944661ddSHariprasad S deref_ep: 2920944661ddSHariprasad S c4iw_put_ep(&ep->com); 2921944661ddSHariprasad S /* Dereferencing ep, referenced in peer_abort_intr() */ 2922944661ddSHariprasad S c4iw_put_ep(&ep->com); 2923cfdda9d7SSteve Wise return 0; 2924cfdda9d7SSteve Wise } 2925cfdda9d7SSteve Wise 2926cfdda9d7SSteve Wise static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2927cfdda9d7SSteve Wise { 2928cfdda9d7SSteve Wise struct c4iw_ep *ep; 2929cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 2930cfdda9d7SSteve Wise struct cpl_close_con_rpl *rpl = cplhdr(skb); 2931cfdda9d7SSteve Wise int release = 0; 2932cfdda9d7SSteve Wise unsigned int tid = GET_TID(rpl); 2933cfdda9d7SSteve Wise 2934944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 2935944661ddSHariprasad S if (!ep) 2936944661ddSHariprasad S return 0; 2937cfdda9d7SSteve Wise 2938cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2939cfdda9d7SSteve Wise BUG_ON(!ep); 2940cfdda9d7SSteve Wise 2941cfdda9d7SSteve Wise /* The cm_id may be null if we failed to connect */ 29422f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 29439ca6f7cfSHariprasad S set_bit(CLOSE_CON_RPL, &ep->com.history); 2944cfdda9d7SSteve Wise switch (ep->com.state) { 2945cfdda9d7SSteve Wise case CLOSING: 2946cfdda9d7SSteve Wise __state_set(&ep->com, MORIBUND); 2947cfdda9d7SSteve Wise break; 2948cfdda9d7SSteve Wise case MORIBUND: 2949b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 2950cfdda9d7SSteve Wise if ((ep->com.cm_id) && (ep->com.qp)) { 2951cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_IDLE; 2952cfdda9d7SSteve Wise c4iw_modify_qp(ep->com.qp->rhp, 2953cfdda9d7SSteve Wise ep->com.qp, 2954cfdda9d7SSteve Wise C4IW_QP_ATTR_NEXT_STATE, 2955cfdda9d7SSteve Wise &attrs, 1); 2956cfdda9d7SSteve Wise } 2957be13b2dfSSteve Wise close_complete_upcall(ep, 0); 2958cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 2959cfdda9d7SSteve Wise release = 1; 2960cfdda9d7SSteve Wise break; 2961cfdda9d7SSteve Wise case ABORTING: 2962cfdda9d7SSteve Wise case DEAD: 2963cfdda9d7SSteve Wise break; 2964cfdda9d7SSteve Wise default: 2965cfdda9d7SSteve Wise BUG_ON(1); 2966cfdda9d7SSteve Wise break; 2967cfdda9d7SSteve Wise } 29682f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 2969cfdda9d7SSteve Wise if (release) 2970cfdda9d7SSteve Wise release_ep_resources(ep); 2971944661ddSHariprasad S c4iw_put_ep(&ep->com); 2972cfdda9d7SSteve Wise return 0; 2973cfdda9d7SSteve Wise } 2974cfdda9d7SSteve Wise 2975cfdda9d7SSteve Wise static int terminate(struct c4iw_dev *dev, struct sk_buff *skb) 2976cfdda9d7SSteve Wise { 29770e42c1f4SSteve Wise struct cpl_rdma_terminate *rpl = cplhdr(skb); 29780e42c1f4SSteve Wise unsigned int tid = GET_TID(rpl); 29790e42c1f4SSteve Wise struct c4iw_ep *ep; 29800e42c1f4SSteve Wise struct c4iw_qp_attributes attrs; 2981cfdda9d7SSteve Wise 2982944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 29830e42c1f4SSteve Wise BUG_ON(!ep); 2984cfdda9d7SSteve Wise 298530c95c2dSSteve Wise if (ep && ep->com.qp) { 29860e42c1f4SSteve Wise printk(KERN_WARNING MOD "TERM received tid %u qpid %u\n", tid, 29870e42c1f4SSteve Wise ep->com.qp->wq.sq.qid); 29880e42c1f4SSteve Wise attrs.next_state = C4IW_QP_STATE_TERMINATE; 29890e42c1f4SSteve Wise c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 29900e42c1f4SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 29910e42c1f4SSteve Wise } else 299230c95c2dSSteve Wise printk(KERN_WARNING MOD "TERM received tid %u no ep/qp\n", tid); 2993944661ddSHariprasad S c4iw_put_ep(&ep->com); 2994cfdda9d7SSteve Wise 2995cfdda9d7SSteve Wise return 0; 2996cfdda9d7SSteve Wise } 2997cfdda9d7SSteve Wise 2998cfdda9d7SSteve Wise /* 2999cfdda9d7SSteve Wise * Upcall from the adapter indicating data has been transmitted. 3000cfdda9d7SSteve Wise * For us its just the single MPA request or reply. We can now free 3001cfdda9d7SSteve Wise * the skb holding the mpa message. 3002cfdda9d7SSteve Wise */ 3003cfdda9d7SSteve Wise static int fw4_ack(struct c4iw_dev *dev, struct sk_buff *skb) 3004cfdda9d7SSteve Wise { 3005cfdda9d7SSteve Wise struct c4iw_ep *ep; 3006cfdda9d7SSteve Wise struct cpl_fw4_ack *hdr = cplhdr(skb); 3007cfdda9d7SSteve Wise u8 credits = hdr->credits; 3008cfdda9d7SSteve Wise unsigned int tid = GET_TID(hdr); 3009cfdda9d7SSteve Wise 3010cfdda9d7SSteve Wise 3011944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 3012944661ddSHariprasad S if (!ep) 3013944661ddSHariprasad S return 0; 3014cfdda9d7SSteve Wise PDBG("%s ep %p tid %u credits %u\n", __func__, ep, ep->hwtid, credits); 3015cfdda9d7SSteve Wise if (credits == 0) { 3016aa1ad260SJoe Perches PDBG("%s 0 credit ack ep %p tid %u state %u\n", 3017cfdda9d7SSteve Wise __func__, ep, ep->hwtid, state_read(&ep->com)); 3018944661ddSHariprasad S goto out; 3019cfdda9d7SSteve Wise } 3020cfdda9d7SSteve Wise 3021cfdda9d7SSteve Wise dst_confirm(ep->dst); 3022cfdda9d7SSteve Wise if (ep->mpa_skb) { 3023cfdda9d7SSteve Wise PDBG("%s last streaming msg ack ep %p tid %u state %u " 3024cfdda9d7SSteve Wise "initiator %u freeing skb\n", __func__, ep, ep->hwtid, 3025cfdda9d7SSteve Wise state_read(&ep->com), ep->mpa_attr.initiator ? 1 : 0); 3026cfdda9d7SSteve Wise kfree_skb(ep->mpa_skb); 3027cfdda9d7SSteve Wise ep->mpa_skb = NULL; 3028e4b76a2aSHariprasad S mutex_lock(&ep->com.mutex); 3029e4b76a2aSHariprasad S if (test_bit(STOP_MPA_TIMER, &ep->com.flags)) 3030e4b76a2aSHariprasad S stop_ep_timer(ep); 3031e4b76a2aSHariprasad S mutex_unlock(&ep->com.mutex); 3032cfdda9d7SSteve Wise } 3033944661ddSHariprasad S out: 3034944661ddSHariprasad S c4iw_put_ep(&ep->com); 3035cfdda9d7SSteve Wise return 0; 3036cfdda9d7SSteve Wise } 3037cfdda9d7SSteve Wise 3038cfdda9d7SSteve Wise int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) 3039cfdda9d7SSteve Wise { 3040a7db89ebSSteve Wise int err = 0; 3041a7db89ebSSteve Wise int disconnect = 0; 3042cfdda9d7SSteve Wise struct c4iw_ep *ep = to_ep(cm_id); 3043cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 3044cfdda9d7SSteve Wise 3045a7db89ebSSteve Wise mutex_lock(&ep->com.mutex); 3046e8667a9bSHariprasad S if (ep->com.state != MPA_REQ_RCVD) { 3047a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 3048cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3049cfdda9d7SSteve Wise return -ECONNRESET; 3050cfdda9d7SSteve Wise } 3051793dad94SVipul Pandya set_bit(ULP_REJECT, &ep->com.history); 3052cfdda9d7SSteve Wise if (mpa_rev == 0) 3053eaf4c6d4SHariprasad S disconnect = 2; 3054cfdda9d7SSteve Wise else { 3055cfdda9d7SSteve Wise err = send_mpa_reject(ep, pdata, pdata_len); 3056a7db89ebSSteve Wise disconnect = 1; 3057cfdda9d7SSteve Wise } 3058a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 3059e4b76a2aSHariprasad S if (disconnect) { 3060e4b76a2aSHariprasad S stop_ep_timer(ep); 3061eaf4c6d4SHariprasad S err = c4iw_ep_disconnect(ep, disconnect == 2, GFP_KERNEL); 3062e4b76a2aSHariprasad S } 3063cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3064cfdda9d7SSteve Wise return 0; 3065cfdda9d7SSteve Wise } 3066cfdda9d7SSteve Wise 3067cfdda9d7SSteve Wise int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) 3068cfdda9d7SSteve Wise { 3069cfdda9d7SSteve Wise int err; 3070cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 3071cfdda9d7SSteve Wise enum c4iw_qp_attr_mask mask; 3072cfdda9d7SSteve Wise struct c4iw_ep *ep = to_ep(cm_id); 3073cfdda9d7SSteve Wise struct c4iw_dev *h = to_c4iw_dev(cm_id->device); 3074cfdda9d7SSteve Wise struct c4iw_qp *qp = get_qhp(h, conn_param->qpn); 3075eaf4c6d4SHariprasad S int abort = 0; 3076cfdda9d7SSteve Wise 3077cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 3078a7db89ebSSteve Wise 3079a7db89ebSSteve Wise mutex_lock(&ep->com.mutex); 3080e8667a9bSHariprasad S if (ep->com.state != MPA_REQ_RCVD) { 3081cfdda9d7SSteve Wise err = -ECONNRESET; 3082eaf4c6d4SHariprasad S goto err_out; 3083cfdda9d7SSteve Wise } 3084cfdda9d7SSteve Wise 3085cfdda9d7SSteve Wise BUG_ON(!qp); 3086cfdda9d7SSteve Wise 3087793dad94SVipul Pandya set_bit(ULP_ACCEPT, &ep->com.history); 30884c2c5763SHariprasad Shenai if ((conn_param->ord > cur_max_read_depth(ep->com.dev)) || 30894c2c5763SHariprasad Shenai (conn_param->ird > cur_max_read_depth(ep->com.dev))) { 3090cfdda9d7SSteve Wise err = -EINVAL; 3091eaf4c6d4SHariprasad S goto err_abort; 3092cfdda9d7SSteve Wise } 3093cfdda9d7SSteve Wise 3094d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 3095d2fe99e8SKumar Sanghvi if (conn_param->ord > ep->ird) { 30964c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION) { 30974c2c5763SHariprasad Shenai ep->ord = ep->ird; 30984c2c5763SHariprasad Shenai } else { 3099d2fe99e8SKumar Sanghvi ep->ird = conn_param->ird; 3100d2fe99e8SKumar Sanghvi ep->ord = conn_param->ord; 3101d2fe99e8SKumar Sanghvi send_mpa_reject(ep, conn_param->private_data, 3102d2fe99e8SKumar Sanghvi conn_param->private_data_len); 3103d2fe99e8SKumar Sanghvi err = -ENOMEM; 3104eaf4c6d4SHariprasad S goto err_abort; 3105d2fe99e8SKumar Sanghvi } 31064c2c5763SHariprasad Shenai } 31074c2c5763SHariprasad Shenai if (conn_param->ird < ep->ord) { 31084c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION && 31094c2c5763SHariprasad Shenai ep->ord <= h->rdev.lldi.max_ordird_qp) { 31104c2c5763SHariprasad Shenai conn_param->ird = ep->ord; 31114c2c5763SHariprasad Shenai } else { 3112d2fe99e8SKumar Sanghvi err = -ENOMEM; 3113eaf4c6d4SHariprasad S goto err_abort; 3114d2fe99e8SKumar Sanghvi } 3115d2fe99e8SKumar Sanghvi } 3116d2fe99e8SKumar Sanghvi } 3117cfdda9d7SSteve Wise ep->ird = conn_param->ird; 3118cfdda9d7SSteve Wise ep->ord = conn_param->ord; 3119cfdda9d7SSteve Wise 31204c2c5763SHariprasad Shenai if (ep->mpa_attr.version == 1) { 3121cfdda9d7SSteve Wise if (peer2peer && ep->ird == 0) 3122cfdda9d7SSteve Wise ep->ird = 1; 31234c2c5763SHariprasad Shenai } else { 31244c2c5763SHariprasad Shenai if (peer2peer && 31254c2c5763SHariprasad Shenai (ep->mpa_attr.p2p_type != FW_RI_INIT_P2PTYPE_DISABLED) && 3126f57b780cSHariprasad S (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) && ep->ird == 0) 31274c2c5763SHariprasad Shenai ep->ird = 1; 31284c2c5763SHariprasad Shenai } 3129cfdda9d7SSteve Wise 3130cfdda9d7SSteve Wise PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord); 3131cfdda9d7SSteve Wise 3132d2fe99e8SKumar Sanghvi ep->com.cm_id = cm_id; 31339ca6f7cfSHariprasad S ref_cm_id(&ep->com); 3134d2fe99e8SKumar Sanghvi ep->com.qp = qp; 3135325abeadSVipul Pandya ref_qp(ep); 3136d2fe99e8SKumar Sanghvi 3137cfdda9d7SSteve Wise /* bind QP to EP and move to RTS */ 3138cfdda9d7SSteve Wise attrs.mpa_attr = ep->mpa_attr; 3139cfdda9d7SSteve Wise attrs.max_ird = ep->ird; 3140cfdda9d7SSteve Wise attrs.max_ord = ep->ord; 3141cfdda9d7SSteve Wise attrs.llp_stream_handle = ep; 3142cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_RTS; 3143cfdda9d7SSteve Wise 3144cfdda9d7SSteve Wise /* bind QP and TID with INIT_WR */ 3145cfdda9d7SSteve Wise mask = C4IW_QP_ATTR_NEXT_STATE | 3146cfdda9d7SSteve Wise C4IW_QP_ATTR_LLP_STREAM_HANDLE | 3147cfdda9d7SSteve Wise C4IW_QP_ATTR_MPA_ATTR | 3148cfdda9d7SSteve Wise C4IW_QP_ATTR_MAX_IRD | 3149cfdda9d7SSteve Wise C4IW_QP_ATTR_MAX_ORD; 3150cfdda9d7SSteve Wise 3151cfdda9d7SSteve Wise err = c4iw_modify_qp(ep->com.qp->rhp, 3152cfdda9d7SSteve Wise ep->com.qp, mask, &attrs, 1); 3153cfdda9d7SSteve Wise if (err) 3154eaf4c6d4SHariprasad S goto err_deref_cm_id; 3155e4b76a2aSHariprasad S 3156e4b76a2aSHariprasad S set_bit(STOP_MPA_TIMER, &ep->com.flags); 3157cfdda9d7SSteve Wise err = send_mpa_reply(ep, conn_param->private_data, 3158cfdda9d7SSteve Wise conn_param->private_data_len); 3159cfdda9d7SSteve Wise if (err) 3160eaf4c6d4SHariprasad S goto err_deref_cm_id; 3161cfdda9d7SSteve Wise 3162a7db89ebSSteve Wise __state_set(&ep->com, FPDU_MODE); 3163cfdda9d7SSteve Wise established_upcall(ep); 3164a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 3165cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3166cfdda9d7SSteve Wise return 0; 3167eaf4c6d4SHariprasad S err_deref_cm_id: 31689ca6f7cfSHariprasad S deref_cm_id(&ep->com); 3169eaf4c6d4SHariprasad S err_abort: 3170eaf4c6d4SHariprasad S abort = 1; 3171eaf4c6d4SHariprasad S err_out: 3172a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 3173eaf4c6d4SHariprasad S if (abort) 3174eaf4c6d4SHariprasad S c4iw_ep_disconnect(ep, 1, GFP_KERNEL); 3175cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3176cfdda9d7SSteve Wise return err; 3177cfdda9d7SSteve Wise } 3178cfdda9d7SSteve Wise 3179830662f6SVipul Pandya static int pick_local_ipaddrs(struct c4iw_dev *dev, struct iw_cm_id *cm_id) 3180830662f6SVipul Pandya { 3181830662f6SVipul Pandya struct in_device *ind; 3182830662f6SVipul Pandya int found = 0; 3183170003c8SSteve Wise struct sockaddr_in *laddr = (struct sockaddr_in *)&cm_id->m_local_addr; 3184170003c8SSteve Wise struct sockaddr_in *raddr = (struct sockaddr_in *)&cm_id->m_remote_addr; 3185830662f6SVipul Pandya 3186830662f6SVipul Pandya ind = in_dev_get(dev->rdev.lldi.ports[0]); 3187830662f6SVipul Pandya if (!ind) 3188830662f6SVipul Pandya return -EADDRNOTAVAIL; 3189830662f6SVipul Pandya for_primary_ifa(ind) { 3190830662f6SVipul Pandya laddr->sin_addr.s_addr = ifa->ifa_address; 3191830662f6SVipul Pandya raddr->sin_addr.s_addr = ifa->ifa_address; 3192830662f6SVipul Pandya found = 1; 3193830662f6SVipul Pandya break; 3194830662f6SVipul Pandya } 3195830662f6SVipul Pandya endfor_ifa(ind); 3196830662f6SVipul Pandya in_dev_put(ind); 3197830662f6SVipul Pandya return found ? 0 : -EADDRNOTAVAIL; 3198830662f6SVipul Pandya } 3199830662f6SVipul Pandya 3200830662f6SVipul Pandya static int get_lladdr(struct net_device *dev, struct in6_addr *addr, 3201830662f6SVipul Pandya unsigned char banned_flags) 3202830662f6SVipul Pandya { 3203830662f6SVipul Pandya struct inet6_dev *idev; 3204830662f6SVipul Pandya int err = -EADDRNOTAVAIL; 3205830662f6SVipul Pandya 3206830662f6SVipul Pandya rcu_read_lock(); 3207830662f6SVipul Pandya idev = __in6_dev_get(dev); 3208830662f6SVipul Pandya if (idev != NULL) { 3209830662f6SVipul Pandya struct inet6_ifaddr *ifp; 3210830662f6SVipul Pandya 3211830662f6SVipul Pandya read_lock_bh(&idev->lock); 3212830662f6SVipul Pandya list_for_each_entry(ifp, &idev->addr_list, if_list) { 3213830662f6SVipul Pandya if (ifp->scope == IFA_LINK && 3214830662f6SVipul Pandya !(ifp->flags & banned_flags)) { 3215830662f6SVipul Pandya memcpy(addr, &ifp->addr, 16); 3216830662f6SVipul Pandya err = 0; 3217830662f6SVipul Pandya break; 3218830662f6SVipul Pandya } 3219830662f6SVipul Pandya } 3220830662f6SVipul Pandya read_unlock_bh(&idev->lock); 3221830662f6SVipul Pandya } 3222830662f6SVipul Pandya rcu_read_unlock(); 3223830662f6SVipul Pandya return err; 3224830662f6SVipul Pandya } 3225830662f6SVipul Pandya 3226830662f6SVipul Pandya static int pick_local_ip6addrs(struct c4iw_dev *dev, struct iw_cm_id *cm_id) 3227830662f6SVipul Pandya { 3228830662f6SVipul Pandya struct in6_addr uninitialized_var(addr); 3229170003c8SSteve Wise struct sockaddr_in6 *la6 = (struct sockaddr_in6 *)&cm_id->m_local_addr; 3230170003c8SSteve Wise struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)&cm_id->m_remote_addr; 3231830662f6SVipul Pandya 323254b9a96fSNicholas Krause if (!get_lladdr(dev->rdev.lldi.ports[0], &addr, IFA_F_TENTATIVE)) { 3233830662f6SVipul Pandya memcpy(la6->sin6_addr.s6_addr, &addr, 16); 3234830662f6SVipul Pandya memcpy(ra6->sin6_addr.s6_addr, &addr, 16); 3235830662f6SVipul Pandya return 0; 3236830662f6SVipul Pandya } 3237830662f6SVipul Pandya return -EADDRNOTAVAIL; 3238830662f6SVipul Pandya } 3239830662f6SVipul Pandya 3240cfdda9d7SSteve Wise int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) 3241cfdda9d7SSteve Wise { 3242cfdda9d7SSteve Wise struct c4iw_dev *dev = to_c4iw_dev(cm_id->device); 3243cfdda9d7SSteve Wise struct c4iw_ep *ep; 32443786cf18SDavid Miller int err = 0; 32459eccfe10SSteve Wise struct sockaddr_in *laddr; 32469eccfe10SSteve Wise struct sockaddr_in *raddr; 32479eccfe10SSteve Wise struct sockaddr_in6 *laddr6; 32489eccfe10SSteve Wise struct sockaddr_in6 *raddr6; 3249830662f6SVipul Pandya __u8 *ra; 3250830662f6SVipul Pandya int iptype; 3251cfdda9d7SSteve Wise 32524c2c5763SHariprasad Shenai if ((conn_param->ord > cur_max_read_depth(dev)) || 32534c2c5763SHariprasad Shenai (conn_param->ird > cur_max_read_depth(dev))) { 3254be4c9badSRoland Dreier err = -EINVAL; 3255be4c9badSRoland Dreier goto out; 3256be4c9badSRoland Dreier } 3257cfdda9d7SSteve Wise ep = alloc_ep(sizeof(*ep), GFP_KERNEL); 3258cfdda9d7SSteve Wise if (!ep) { 3259cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __func__); 3260cfdda9d7SSteve Wise err = -ENOMEM; 3261cfdda9d7SSteve Wise goto out; 3262cfdda9d7SSteve Wise } 3263cfdda9d7SSteve Wise init_timer(&ep->timer); 3264cfdda9d7SSteve Wise ep->plen = conn_param->private_data_len; 3265cfdda9d7SSteve Wise if (ep->plen) 3266cfdda9d7SSteve Wise memcpy(ep->mpa_pkt + sizeof(struct mpa_message), 3267cfdda9d7SSteve Wise conn_param->private_data, ep->plen); 3268cfdda9d7SSteve Wise ep->ird = conn_param->ird; 3269cfdda9d7SSteve Wise ep->ord = conn_param->ord; 3270cfdda9d7SSteve Wise 3271cfdda9d7SSteve Wise if (peer2peer && ep->ord == 0) 3272cfdda9d7SSteve Wise ep->ord = 1; 3273cfdda9d7SSteve Wise 3274cfdda9d7SSteve Wise ep->com.cm_id = cm_id; 32759ca6f7cfSHariprasad S ref_cm_id(&ep->com); 32769ca6f7cfSHariprasad S ep->com.dev = dev; 3277cfdda9d7SSteve Wise ep->com.qp = get_qhp(dev, conn_param->qpn); 3278830662f6SVipul Pandya if (!ep->com.qp) { 3279830662f6SVipul Pandya PDBG("%s qpn 0x%x not found!\n", __func__, conn_param->qpn); 3280830662f6SVipul Pandya err = -EINVAL; 32819eccfe10SSteve Wise goto fail1; 3282830662f6SVipul Pandya } 3283325abeadSVipul Pandya ref_qp(ep); 3284cfdda9d7SSteve Wise PDBG("%s qpn 0x%x qp %p cm_id %p\n", __func__, conn_param->qpn, 3285cfdda9d7SSteve Wise ep->com.qp, cm_id); 3286cfdda9d7SSteve Wise 3287cfdda9d7SSteve Wise /* 3288cfdda9d7SSteve Wise * Allocate an active TID to initiate a TCP connection. 3289cfdda9d7SSteve Wise */ 3290cfdda9d7SSteve Wise ep->atid = cxgb4_alloc_atid(dev->rdev.lldi.tids, ep); 3291cfdda9d7SSteve Wise if (ep->atid == -1) { 3292cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __func__); 3293cfdda9d7SSteve Wise err = -ENOMEM; 32949eccfe10SSteve Wise goto fail1; 3295cfdda9d7SSteve Wise } 3296793dad94SVipul Pandya insert_handle(dev, &dev->atid_idr, ep, ep->atid); 3297cfdda9d7SSteve Wise 3298170003c8SSteve Wise memcpy(&ep->com.local_addr, &cm_id->m_local_addr, 32999eccfe10SSteve Wise sizeof(ep->com.local_addr)); 3300170003c8SSteve Wise memcpy(&ep->com.remote_addr, &cm_id->m_remote_addr, 33019eccfe10SSteve Wise sizeof(ep->com.remote_addr)); 33029eccfe10SSteve Wise 3303170003c8SSteve Wise laddr = (struct sockaddr_in *)&ep->com.local_addr; 3304170003c8SSteve Wise raddr = (struct sockaddr_in *)&ep->com.remote_addr; 3305170003c8SSteve Wise laddr6 = (struct sockaddr_in6 *)&ep->com.local_addr; 3306170003c8SSteve Wise raddr6 = (struct sockaddr_in6 *) &ep->com.remote_addr; 33079eccfe10SSteve Wise 3308170003c8SSteve Wise if (cm_id->m_remote_addr.ss_family == AF_INET) { 3309830662f6SVipul Pandya iptype = 4; 3310830662f6SVipul Pandya ra = (__u8 *)&raddr->sin_addr; 3311830662f6SVipul Pandya 3312830662f6SVipul Pandya /* 3313830662f6SVipul Pandya * Handle loopback requests to INADDR_ANY. 3314830662f6SVipul Pandya */ 3315ba987e51SBart Van Assche if (raddr->sin_addr.s_addr == htonl(INADDR_ANY)) { 3316830662f6SVipul Pandya err = pick_local_ipaddrs(dev, cm_id); 3317830662f6SVipul Pandya if (err) 33189eccfe10SSteve Wise goto fail1; 3319830662f6SVipul Pandya } 3320cfdda9d7SSteve Wise 3321cfdda9d7SSteve Wise /* find a route */ 3322830662f6SVipul Pandya PDBG("%s saddr %pI4 sport 0x%x raddr %pI4 rport 0x%x\n", 3323830662f6SVipul Pandya __func__, &laddr->sin_addr, ntohs(laddr->sin_port), 3324830662f6SVipul Pandya ra, ntohs(raddr->sin_port)); 3325830662f6SVipul Pandya ep->dst = find_route(dev, laddr->sin_addr.s_addr, 3326830662f6SVipul Pandya raddr->sin_addr.s_addr, laddr->sin_port, 3327ac8e4c69SHariprasad S raddr->sin_port, cm_id->tos); 3328830662f6SVipul Pandya } else { 3329830662f6SVipul Pandya iptype = 6; 3330830662f6SVipul Pandya ra = (__u8 *)&raddr6->sin6_addr; 3331830662f6SVipul Pandya 3332830662f6SVipul Pandya /* 3333830662f6SVipul Pandya * Handle loopback requests to INADDR_ANY. 3334830662f6SVipul Pandya */ 3335830662f6SVipul Pandya if (ipv6_addr_type(&raddr6->sin6_addr) == IPV6_ADDR_ANY) { 3336830662f6SVipul Pandya err = pick_local_ip6addrs(dev, cm_id); 3337830662f6SVipul Pandya if (err) 33389eccfe10SSteve Wise goto fail1; 3339830662f6SVipul Pandya } 3340830662f6SVipul Pandya 3341830662f6SVipul Pandya /* find a route */ 3342830662f6SVipul Pandya PDBG("%s saddr %pI6 sport 0x%x raddr %pI6 rport 0x%x\n", 3343830662f6SVipul Pandya __func__, laddr6->sin6_addr.s6_addr, 3344830662f6SVipul Pandya ntohs(laddr6->sin6_port), 3345830662f6SVipul Pandya raddr6->sin6_addr.s6_addr, ntohs(raddr6->sin6_port)); 3346830662f6SVipul Pandya ep->dst = find_route6(dev, laddr6->sin6_addr.s6_addr, 3347830662f6SVipul Pandya raddr6->sin6_addr.s6_addr, 3348830662f6SVipul Pandya laddr6->sin6_port, raddr6->sin6_port, 0, 3349830662f6SVipul Pandya raddr6->sin6_scope_id); 3350830662f6SVipul Pandya } 3351830662f6SVipul Pandya if (!ep->dst) { 3352cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot find route.\n", __func__); 3353cfdda9d7SSteve Wise err = -EHOSTUNREACH; 33549eccfe10SSteve Wise goto fail2; 3355cfdda9d7SSteve Wise } 3356cfdda9d7SSteve Wise 3357963cab50SHariprasad S err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, true, 3358ac8e4c69SHariprasad S ep->com.dev->rdev.lldi.adapter_type, cm_id->tos); 33593786cf18SDavid Miller if (err) { 3360cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); 33619eccfe10SSteve Wise goto fail3; 3362cfdda9d7SSteve Wise } 3363cfdda9d7SSteve Wise 3364cfdda9d7SSteve Wise PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n", 3365cfdda9d7SSteve Wise __func__, ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid, 3366cfdda9d7SSteve Wise ep->l2t->idx); 3367cfdda9d7SSteve Wise 3368cfdda9d7SSteve Wise state_set(&ep->com, CONNECTING); 3369ac8e4c69SHariprasad S ep->tos = cm_id->tos; 3370cfdda9d7SSteve Wise 3371cfdda9d7SSteve Wise /* send connect request to rnic */ 3372cfdda9d7SSteve Wise err = send_connect(ep); 3373cfdda9d7SSteve Wise if (!err) 3374cfdda9d7SSteve Wise goto out; 3375cfdda9d7SSteve Wise 3376cfdda9d7SSteve Wise cxgb4_l2t_release(ep->l2t); 3377cfdda9d7SSteve Wise fail3: 33789eccfe10SSteve Wise dst_release(ep->dst); 33799eccfe10SSteve Wise fail2: 3380793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid); 3381cfdda9d7SSteve Wise cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid); 33829eccfe10SSteve Wise fail1: 33839ca6f7cfSHariprasad S deref_cm_id(&ep->com); 3384cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3385cfdda9d7SSteve Wise out: 3386cfdda9d7SSteve Wise return err; 3387cfdda9d7SSteve Wise } 3388cfdda9d7SSteve Wise 3389830662f6SVipul Pandya static int create_server6(struct c4iw_dev *dev, struct c4iw_listen_ep *ep) 3390830662f6SVipul Pandya { 3391830662f6SVipul Pandya int err; 33929eccfe10SSteve Wise struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) 3393170003c8SSteve Wise &ep->com.local_addr; 3394830662f6SVipul Pandya 339528de1f74SHariprasad S if (ipv6_addr_type(&sin6->sin6_addr) != IPV6_ADDR_ANY) { 339628de1f74SHariprasad S err = cxgb4_clip_get(ep->com.dev->rdev.lldi.ports[0], 339728de1f74SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 339828de1f74SHariprasad S if (err) 339928de1f74SHariprasad S return err; 340028de1f74SHariprasad S } 3401830662f6SVipul Pandya c4iw_init_wr_wait(&ep->com.wr_wait); 3402830662f6SVipul Pandya err = cxgb4_create_server6(ep->com.dev->rdev.lldi.ports[0], 3403830662f6SVipul Pandya ep->stid, &sin6->sin6_addr, 3404830662f6SVipul Pandya sin6->sin6_port, 3405830662f6SVipul Pandya ep->com.dev->rdev.lldi.rxq_ids[0]); 3406830662f6SVipul Pandya if (!err) 3407830662f6SVipul Pandya err = c4iw_wait_for_reply(&ep->com.dev->rdev, 3408830662f6SVipul Pandya &ep->com.wr_wait, 3409830662f6SVipul Pandya 0, 0, __func__); 3410e6b11163SHariprasad S else if (err > 0) 3411e6b11163SHariprasad S err = net_xmit_errno(err); 341228de1f74SHariprasad S if (err) { 341328de1f74SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 341428de1f74SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 3415830662f6SVipul Pandya pr_err("cxgb4_create_server6/filter failed err %d stid %d laddr %pI6 lport %d\n", 3416830662f6SVipul Pandya err, ep->stid, 3417830662f6SVipul Pandya sin6->sin6_addr.s6_addr, ntohs(sin6->sin6_port)); 341828de1f74SHariprasad S } 3419830662f6SVipul Pandya return err; 3420830662f6SVipul Pandya } 3421830662f6SVipul Pandya 3422830662f6SVipul Pandya static int create_server4(struct c4iw_dev *dev, struct c4iw_listen_ep *ep) 3423830662f6SVipul Pandya { 3424830662f6SVipul Pandya int err; 34259eccfe10SSteve Wise struct sockaddr_in *sin = (struct sockaddr_in *) 3426170003c8SSteve Wise &ep->com.local_addr; 3427830662f6SVipul Pandya 3428830662f6SVipul Pandya if (dev->rdev.lldi.enable_fw_ofld_conn) { 3429830662f6SVipul Pandya do { 3430830662f6SVipul Pandya err = cxgb4_create_server_filter( 3431830662f6SVipul Pandya ep->com.dev->rdev.lldi.ports[0], ep->stid, 3432830662f6SVipul Pandya sin->sin_addr.s_addr, sin->sin_port, 0, 3433830662f6SVipul Pandya ep->com.dev->rdev.lldi.rxq_ids[0], 0, 0); 3434830662f6SVipul Pandya if (err == -EBUSY) { 343599718e59SHariprasad S if (c4iw_fatal_error(&ep->com.dev->rdev)) { 343699718e59SHariprasad S err = -EIO; 343799718e59SHariprasad S break; 343899718e59SHariprasad S } 3439830662f6SVipul Pandya set_current_state(TASK_UNINTERRUPTIBLE); 3440830662f6SVipul Pandya schedule_timeout(usecs_to_jiffies(100)); 3441830662f6SVipul Pandya } 3442830662f6SVipul Pandya } while (err == -EBUSY); 3443830662f6SVipul Pandya } else { 3444830662f6SVipul Pandya c4iw_init_wr_wait(&ep->com.wr_wait); 3445830662f6SVipul Pandya err = cxgb4_create_server(ep->com.dev->rdev.lldi.ports[0], 3446830662f6SVipul Pandya ep->stid, sin->sin_addr.s_addr, sin->sin_port, 3447830662f6SVipul Pandya 0, ep->com.dev->rdev.lldi.rxq_ids[0]); 3448830662f6SVipul Pandya if (!err) 3449830662f6SVipul Pandya err = c4iw_wait_for_reply(&ep->com.dev->rdev, 3450830662f6SVipul Pandya &ep->com.wr_wait, 3451830662f6SVipul Pandya 0, 0, __func__); 3452e6b11163SHariprasad S else if (err > 0) 3453e6b11163SHariprasad S err = net_xmit_errno(err); 3454830662f6SVipul Pandya } 3455830662f6SVipul Pandya if (err) 3456830662f6SVipul Pandya pr_err("cxgb4_create_server/filter failed err %d stid %d laddr %pI4 lport %d\n" 3457830662f6SVipul Pandya , err, ep->stid, 3458830662f6SVipul Pandya &sin->sin_addr, ntohs(sin->sin_port)); 3459830662f6SVipul Pandya return err; 3460830662f6SVipul Pandya } 3461830662f6SVipul Pandya 3462cfdda9d7SSteve Wise int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog) 3463cfdda9d7SSteve Wise { 3464cfdda9d7SSteve Wise int err = 0; 3465cfdda9d7SSteve Wise struct c4iw_dev *dev = to_c4iw_dev(cm_id->device); 3466cfdda9d7SSteve Wise struct c4iw_listen_ep *ep; 3467cfdda9d7SSteve Wise 3468cfdda9d7SSteve Wise might_sleep(); 3469cfdda9d7SSteve Wise 3470cfdda9d7SSteve Wise ep = alloc_ep(sizeof(*ep), GFP_KERNEL); 3471cfdda9d7SSteve Wise if (!ep) { 3472cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __func__); 3473cfdda9d7SSteve Wise err = -ENOMEM; 3474cfdda9d7SSteve Wise goto fail1; 3475cfdda9d7SSteve Wise } 3476cfdda9d7SSteve Wise PDBG("%s ep %p\n", __func__, ep); 3477cfdda9d7SSteve Wise ep->com.cm_id = cm_id; 34789ca6f7cfSHariprasad S ref_cm_id(&ep->com); 3479cfdda9d7SSteve Wise ep->com.dev = dev; 3480cfdda9d7SSteve Wise ep->backlog = backlog; 3481170003c8SSteve Wise memcpy(&ep->com.local_addr, &cm_id->m_local_addr, 348224d44a39SSteve Wise sizeof(ep->com.local_addr)); 3483cfdda9d7SSteve Wise 3484cfdda9d7SSteve Wise /* 3485cfdda9d7SSteve Wise * Allocate a server TID. 3486cfdda9d7SSteve Wise */ 34878c044690SKumar Sanghvi if (dev->rdev.lldi.enable_fw_ofld_conn && 34888c044690SKumar Sanghvi ep->com.local_addr.ss_family == AF_INET) 3489830662f6SVipul Pandya ep->stid = cxgb4_alloc_sftid(dev->rdev.lldi.tids, 3490170003c8SSteve Wise cm_id->m_local_addr.ss_family, ep); 34911cab775cSVipul Pandya else 3492830662f6SVipul Pandya ep->stid = cxgb4_alloc_stid(dev->rdev.lldi.tids, 3493170003c8SSteve Wise cm_id->m_local_addr.ss_family, ep); 34941cab775cSVipul Pandya 3495cfdda9d7SSteve Wise if (ep->stid == -1) { 3496be4c9badSRoland Dreier printk(KERN_ERR MOD "%s - cannot alloc stid.\n", __func__); 3497cfdda9d7SSteve Wise err = -ENOMEM; 3498cfdda9d7SSteve Wise goto fail2; 3499cfdda9d7SSteve Wise } 3500793dad94SVipul Pandya insert_handle(dev, &dev->stid_idr, ep, ep->stid); 35019eccfe10SSteve Wise 3502170003c8SSteve Wise memcpy(&ep->com.local_addr, &cm_id->m_local_addr, 35039eccfe10SSteve Wise sizeof(ep->com.local_addr)); 35049eccfe10SSteve Wise 3505cfdda9d7SSteve Wise state_set(&ep->com, LISTEN); 3506830662f6SVipul Pandya if (ep->com.local_addr.ss_family == AF_INET) 3507830662f6SVipul Pandya err = create_server4(dev, ep); 3508830662f6SVipul Pandya else 3509830662f6SVipul Pandya err = create_server6(dev, ep); 3510cfdda9d7SSteve Wise if (!err) { 3511cfdda9d7SSteve Wise cm_id->provider_data = ep; 3512cfdda9d7SSteve Wise goto out; 3513cfdda9d7SSteve Wise } 35149eccfe10SSteve Wise 3515830662f6SVipul Pandya cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, 3516830662f6SVipul Pandya ep->com.local_addr.ss_family); 3517cfdda9d7SSteve Wise fail2: 35189ca6f7cfSHariprasad S deref_cm_id(&ep->com); 3519cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3520cfdda9d7SSteve Wise fail1: 3521cfdda9d7SSteve Wise out: 3522cfdda9d7SSteve Wise return err; 3523cfdda9d7SSteve Wise } 3524cfdda9d7SSteve Wise 3525cfdda9d7SSteve Wise int c4iw_destroy_listen(struct iw_cm_id *cm_id) 3526cfdda9d7SSteve Wise { 3527cfdda9d7SSteve Wise int err; 3528cfdda9d7SSteve Wise struct c4iw_listen_ep *ep = to_listen_ep(cm_id); 3529cfdda9d7SSteve Wise 3530cfdda9d7SSteve Wise PDBG("%s ep %p\n", __func__, ep); 3531cfdda9d7SSteve Wise 3532cfdda9d7SSteve Wise might_sleep(); 3533cfdda9d7SSteve Wise state_set(&ep->com, DEAD); 3534830662f6SVipul Pandya if (ep->com.dev->rdev.lldi.enable_fw_ofld_conn && 3535830662f6SVipul Pandya ep->com.local_addr.ss_family == AF_INET) { 35361cab775cSVipul Pandya err = cxgb4_remove_server_filter( 35371cab775cSVipul Pandya ep->com.dev->rdev.lldi.ports[0], ep->stid, 35381cab775cSVipul Pandya ep->com.dev->rdev.lldi.rxq_ids[0], 0); 35391cab775cSVipul Pandya } else { 354084cc6ac6SHariprasad S struct sockaddr_in6 *sin6; 3541aadc4df3SSteve Wise c4iw_init_wr_wait(&ep->com.wr_wait); 3542830662f6SVipul Pandya err = cxgb4_remove_server( 3543830662f6SVipul Pandya ep->com.dev->rdev.lldi.ports[0], ep->stid, 3544830662f6SVipul Pandya ep->com.dev->rdev.lldi.rxq_ids[0], 0); 3545cfdda9d7SSteve Wise if (err) 3546cfdda9d7SSteve Wise goto done; 35471cab775cSVipul Pandya err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait, 35481cab775cSVipul Pandya 0, 0, __func__); 3549170003c8SSteve Wise sin6 = (struct sockaddr_in6 *)&ep->com.local_addr; 355084cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 355184cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 35521cab775cSVipul Pandya } 3553793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->stid_idr, ep->stid); 3554830662f6SVipul Pandya cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, 3555830662f6SVipul Pandya ep->com.local_addr.ss_family); 3556cfdda9d7SSteve Wise done: 35579ca6f7cfSHariprasad S deref_cm_id(&ep->com); 3558cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3559cfdda9d7SSteve Wise return err; 3560cfdda9d7SSteve Wise } 3561cfdda9d7SSteve Wise 3562cfdda9d7SSteve Wise int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) 3563cfdda9d7SSteve Wise { 3564cfdda9d7SSteve Wise int ret = 0; 3565cfdda9d7SSteve Wise int close = 0; 3566cfdda9d7SSteve Wise int fatal = 0; 3567cfdda9d7SSteve Wise struct c4iw_rdev *rdev; 3568cfdda9d7SSteve Wise 35692f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 3570cfdda9d7SSteve Wise 3571cfdda9d7SSteve Wise PDBG("%s ep %p state %s, abrupt %d\n", __func__, ep, 3572cfdda9d7SSteve Wise states[ep->com.state], abrupt); 3573cfdda9d7SSteve Wise 35746e410d8fSHariprasad S /* 35756e410d8fSHariprasad S * Ref the ep here in case we have fatal errors causing the 35766e410d8fSHariprasad S * ep to be released and freed. 35776e410d8fSHariprasad S */ 35786e410d8fSHariprasad S c4iw_get_ep(&ep->com); 35796e410d8fSHariprasad S 3580cfdda9d7SSteve Wise rdev = &ep->com.dev->rdev; 3581cfdda9d7SSteve Wise if (c4iw_fatal_error(rdev)) { 3582cfdda9d7SSteve Wise fatal = 1; 3583be13b2dfSSteve Wise close_complete_upcall(ep, -EIO); 3584cfdda9d7SSteve Wise ep->com.state = DEAD; 3585cfdda9d7SSteve Wise } 3586cfdda9d7SSteve Wise switch (ep->com.state) { 3587cfdda9d7SSteve Wise case MPA_REQ_WAIT: 3588cfdda9d7SSteve Wise case MPA_REQ_SENT: 3589cfdda9d7SSteve Wise case MPA_REQ_RCVD: 3590cfdda9d7SSteve Wise case MPA_REP_SENT: 3591cfdda9d7SSteve Wise case FPDU_MODE: 3592cfdda9d7SSteve Wise close = 1; 3593cfdda9d7SSteve Wise if (abrupt) 3594cfdda9d7SSteve Wise ep->com.state = ABORTING; 3595cfdda9d7SSteve Wise else { 3596cfdda9d7SSteve Wise ep->com.state = CLOSING; 3597ca5a2202SSteve Wise start_ep_timer(ep); 3598cfdda9d7SSteve Wise } 3599cfdda9d7SSteve Wise set_bit(CLOSE_SENT, &ep->com.flags); 3600cfdda9d7SSteve Wise break; 3601cfdda9d7SSteve Wise case CLOSING: 3602cfdda9d7SSteve Wise if (!test_and_set_bit(CLOSE_SENT, &ep->com.flags)) { 3603cfdda9d7SSteve Wise close = 1; 3604cfdda9d7SSteve Wise if (abrupt) { 3605b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 3606cfdda9d7SSteve Wise ep->com.state = ABORTING; 3607cfdda9d7SSteve Wise } else 3608cfdda9d7SSteve Wise ep->com.state = MORIBUND; 3609cfdda9d7SSteve Wise } 3610cfdda9d7SSteve Wise break; 3611cfdda9d7SSteve Wise case MORIBUND: 3612cfdda9d7SSteve Wise case ABORTING: 3613cfdda9d7SSteve Wise case DEAD: 3614cfdda9d7SSteve Wise PDBG("%s ignoring disconnect ep %p state %u\n", 3615cfdda9d7SSteve Wise __func__, ep, ep->com.state); 3616cfdda9d7SSteve Wise break; 3617cfdda9d7SSteve Wise default: 3618cfdda9d7SSteve Wise BUG(); 3619cfdda9d7SSteve Wise break; 3620cfdda9d7SSteve Wise } 3621cfdda9d7SSteve Wise 3622cfdda9d7SSteve Wise if (close) { 36238da7e7a5SSteve Wise if (abrupt) { 3624793dad94SVipul Pandya set_bit(EP_DISC_ABORT, &ep->com.history); 3625be13b2dfSSteve Wise close_complete_upcall(ep, -ECONNRESET); 36268da7e7a5SSteve Wise ret = send_abort(ep, NULL, gfp); 3627793dad94SVipul Pandya } else { 3628793dad94SVipul Pandya set_bit(EP_DISC_CLOSE, &ep->com.history); 3629cfdda9d7SSteve Wise ret = send_halfclose(ep, gfp); 3630793dad94SVipul Pandya } 363188bc230dSHariprasad S if (ret) { 36329ca6f7cfSHariprasad S set_bit(EP_DISC_FAIL, &ep->com.history); 363388bc230dSHariprasad S if (!abrupt) { 363488bc230dSHariprasad S stop_ep_timer(ep); 363588bc230dSHariprasad S close_complete_upcall(ep, -EIO); 363688bc230dSHariprasad S } 3637c00dcbafSHariprasad S if (ep->com.qp) { 3638c00dcbafSHariprasad S struct c4iw_qp_attributes attrs; 3639c00dcbafSHariprasad S 3640c00dcbafSHariprasad S attrs.next_state = C4IW_QP_STATE_ERROR; 3641c00dcbafSHariprasad S ret = c4iw_modify_qp(ep->com.qp->rhp, 3642c00dcbafSHariprasad S ep->com.qp, 3643c00dcbafSHariprasad S C4IW_QP_ATTR_NEXT_STATE, 3644c00dcbafSHariprasad S &attrs, 1); 3645c00dcbafSHariprasad S if (ret) 3646c00dcbafSHariprasad S pr_err(MOD 3647c00dcbafSHariprasad S "%s - qp <- error failed!\n", 3648c00dcbafSHariprasad S __func__); 3649c00dcbafSHariprasad S } 3650cfdda9d7SSteve Wise fatal = 1; 3651cfdda9d7SSteve Wise } 365288bc230dSHariprasad S } 36538da7e7a5SSteve Wise mutex_unlock(&ep->com.mutex); 36546e410d8fSHariprasad S c4iw_put_ep(&ep->com); 3655cfdda9d7SSteve Wise if (fatal) 3656cfdda9d7SSteve Wise release_ep_resources(ep); 3657cfdda9d7SSteve Wise return ret; 3658cfdda9d7SSteve Wise } 3659cfdda9d7SSteve Wise 36601cab775cSVipul Pandya static void active_ofld_conn_reply(struct c4iw_dev *dev, struct sk_buff *skb, 36611cab775cSVipul Pandya struct cpl_fw6_msg_ofld_connection_wr_rpl *req) 36621cab775cSVipul Pandya { 36631cab775cSVipul Pandya struct c4iw_ep *ep; 3664793dad94SVipul Pandya int atid = be32_to_cpu(req->tid); 36651cab775cSVipul Pandya 3666ef5d6355SVipul Pandya ep = (struct c4iw_ep *)lookup_atid(dev->rdev.lldi.tids, 3667ef5d6355SVipul Pandya (__force u32) req->tid); 36681cab775cSVipul Pandya if (!ep) 36691cab775cSVipul Pandya return; 36701cab775cSVipul Pandya 36711cab775cSVipul Pandya switch (req->retval) { 36721cab775cSVipul Pandya case FW_ENOMEM: 3673793dad94SVipul Pandya set_bit(ACT_RETRY_NOMEM, &ep->com.history); 3674793dad94SVipul Pandya if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) { 3675793dad94SVipul Pandya send_fw_act_open_req(ep, atid); 3676793dad94SVipul Pandya return; 3677793dad94SVipul Pandya } 36781cab775cSVipul Pandya case FW_EADDRINUSE: 3679793dad94SVipul Pandya set_bit(ACT_RETRY_INUSE, &ep->com.history); 3680793dad94SVipul Pandya if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) { 3681793dad94SVipul Pandya send_fw_act_open_req(ep, atid); 3682793dad94SVipul Pandya return; 3683793dad94SVipul Pandya } 36841cab775cSVipul Pandya break; 36851cab775cSVipul Pandya default: 36861cab775cSVipul Pandya pr_info("%s unexpected ofld conn wr retval %d\n", 36871cab775cSVipul Pandya __func__, req->retval); 36881cab775cSVipul Pandya break; 36891cab775cSVipul Pandya } 3690793dad94SVipul Pandya pr_err("active ofld_connect_wr failure %d atid %d\n", 3691793dad94SVipul Pandya req->retval, atid); 3692793dad94SVipul Pandya mutex_lock(&dev->rdev.stats.lock); 3693793dad94SVipul Pandya dev->rdev.stats.act_ofld_conn_fails++; 3694793dad94SVipul Pandya mutex_unlock(&dev->rdev.stats.lock); 36951cab775cSVipul Pandya connect_reply_upcall(ep, status2errno(req->retval)); 3696793dad94SVipul Pandya state_set(&ep->com, DEAD); 369784cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 369884cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 3699170003c8SSteve Wise (struct sockaddr_in6 *)&ep->com.local_addr; 370084cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 370184cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 370284cc6ac6SHariprasad S } 3703793dad94SVipul Pandya remove_handle(dev, &dev->atid_idr, atid); 3704793dad94SVipul Pandya cxgb4_free_atid(dev->rdev.lldi.tids, atid); 3705793dad94SVipul Pandya dst_release(ep->dst); 3706793dad94SVipul Pandya cxgb4_l2t_release(ep->l2t); 3707793dad94SVipul Pandya c4iw_put_ep(&ep->com); 37081cab775cSVipul Pandya } 37091cab775cSVipul Pandya 37101cab775cSVipul Pandya static void passive_ofld_conn_reply(struct c4iw_dev *dev, struct sk_buff *skb, 37111cab775cSVipul Pandya struct cpl_fw6_msg_ofld_connection_wr_rpl *req) 37121cab775cSVipul Pandya { 37131cab775cSVipul Pandya struct sk_buff *rpl_skb; 37141cab775cSVipul Pandya struct cpl_pass_accept_req *cpl; 37151cab775cSVipul Pandya int ret; 37161cab775cSVipul Pandya 3717710a3110SPaul Bolle rpl_skb = (struct sk_buff *)(unsigned long)req->cookie; 37181cab775cSVipul Pandya BUG_ON(!rpl_skb); 37191cab775cSVipul Pandya if (req->retval) { 37201cab775cSVipul Pandya PDBG("%s passive open failure %d\n", __func__, req->retval); 3721793dad94SVipul Pandya mutex_lock(&dev->rdev.stats.lock); 3722793dad94SVipul Pandya dev->rdev.stats.pas_ofld_conn_fails++; 3723793dad94SVipul Pandya mutex_unlock(&dev->rdev.stats.lock); 37241cab775cSVipul Pandya kfree_skb(rpl_skb); 37251cab775cSVipul Pandya } else { 37261cab775cSVipul Pandya cpl = (struct cpl_pass_accept_req *)cplhdr(rpl_skb); 37271cab775cSVipul Pandya OPCODE_TID(cpl) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_REQ, 3728ef5d6355SVipul Pandya (__force u32) htonl( 3729ef5d6355SVipul Pandya (__force u32) req->tid))); 37301cab775cSVipul Pandya ret = pass_accept_req(dev, rpl_skb); 37311cab775cSVipul Pandya if (!ret) 37321cab775cSVipul Pandya kfree_skb(rpl_skb); 37331cab775cSVipul Pandya } 37341cab775cSVipul Pandya return; 37351cab775cSVipul Pandya } 37361cab775cSVipul Pandya 37371cab775cSVipul Pandya static int deferred_fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb) 37382f5b48c3SSteve Wise { 37392f5b48c3SSteve Wise struct cpl_fw6_msg *rpl = cplhdr(skb); 37401cab775cSVipul Pandya struct cpl_fw6_msg_ofld_connection_wr_rpl *req; 37411cab775cSVipul Pandya 37421cab775cSVipul Pandya switch (rpl->type) { 37431cab775cSVipul Pandya case FW6_TYPE_CQE: 37442f5b48c3SSteve Wise c4iw_ev_dispatch(dev, (struct t4_cqe *)&rpl->data[0]); 37451cab775cSVipul Pandya break; 37461cab775cSVipul Pandya case FW6_TYPE_OFLD_CONNECTION_WR_RPL: 37471cab775cSVipul Pandya req = (struct cpl_fw6_msg_ofld_connection_wr_rpl *)rpl->data; 37481cab775cSVipul Pandya switch (req->t_state) { 37491cab775cSVipul Pandya case TCP_SYN_SENT: 37501cab775cSVipul Pandya active_ofld_conn_reply(dev, skb, req); 37511cab775cSVipul Pandya break; 37521cab775cSVipul Pandya case TCP_SYN_RECV: 37531cab775cSVipul Pandya passive_ofld_conn_reply(dev, skb, req); 37541cab775cSVipul Pandya break; 37551cab775cSVipul Pandya default: 37561cab775cSVipul Pandya pr_err("%s unexpected ofld conn wr state %d\n", 37571cab775cSVipul Pandya __func__, req->t_state); 37581cab775cSVipul Pandya break; 37591cab775cSVipul Pandya } 37601cab775cSVipul Pandya break; 37611cab775cSVipul Pandya } 37621cab775cSVipul Pandya return 0; 37631cab775cSVipul Pandya } 37641cab775cSVipul Pandya 37651cab775cSVipul Pandya static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos) 37661cab775cSVipul Pandya { 3767963cab50SHariprasad S __be32 l2info; 3768963cab50SHariprasad S __be16 hdr_len, vlantag, len; 3769963cab50SHariprasad S u16 eth_hdr_len; 3770963cab50SHariprasad S int tcp_hdr_len, ip_hdr_len; 37711cab775cSVipul Pandya u8 intf; 37721cab775cSVipul Pandya struct cpl_rx_pkt *cpl = cplhdr(skb); 37731cab775cSVipul Pandya struct cpl_pass_accept_req *req; 37741cab775cSVipul Pandya struct tcp_options_received tmp_opt; 3775f079af7aSVipul Pandya struct c4iw_dev *dev; 3776963cab50SHariprasad S enum chip_type type; 37771cab775cSVipul Pandya 3778f079af7aSVipul Pandya dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *))); 37791cab775cSVipul Pandya /* Store values from cpl_rx_pkt in temporary location. */ 3780963cab50SHariprasad S vlantag = cpl->vlan; 3781963cab50SHariprasad S len = cpl->len; 3782963cab50SHariprasad S l2info = cpl->l2info; 3783963cab50SHariprasad S hdr_len = cpl->hdr_len; 37841cab775cSVipul Pandya intf = cpl->iff; 37851cab775cSVipul Pandya 37861cab775cSVipul Pandya __skb_pull(skb, sizeof(*req) + sizeof(struct rss_header)); 37871cab775cSVipul Pandya 37881cab775cSVipul Pandya /* 37891cab775cSVipul Pandya * We need to parse the TCP options from SYN packet. 37901cab775cSVipul Pandya * to generate cpl_pass_accept_req. 37911cab775cSVipul Pandya */ 37921cab775cSVipul Pandya memset(&tmp_opt, 0, sizeof(tmp_opt)); 37931cab775cSVipul Pandya tcp_clear_options(&tmp_opt); 37941a2c6181SChristoph Paasch tcp_parse_options(skb, &tmp_opt, 0, NULL); 37951cab775cSVipul Pandya 37961cab775cSVipul Pandya req = (struct cpl_pass_accept_req *)__skb_push(skb, sizeof(*req)); 37971cab775cSVipul Pandya memset(req, 0, sizeof(*req)); 3798cf7fe64aSHariprasad Shenai req->l2info = cpu_to_be16(SYN_INTF_V(intf) | 3799cf7fe64aSHariprasad Shenai SYN_MAC_IDX_V(RX_MACIDX_G( 3800963cab50SHariprasad S be32_to_cpu(l2info))) | 3801cf7fe64aSHariprasad Shenai SYN_XACT_MATCH_F); 3802963cab50SHariprasad S type = dev->rdev.lldi.adapter_type; 3803963cab50SHariprasad S tcp_hdr_len = RX_TCPHDR_LEN_G(be16_to_cpu(hdr_len)); 3804963cab50SHariprasad S ip_hdr_len = RX_IPHDR_LEN_G(be16_to_cpu(hdr_len)); 3805963cab50SHariprasad S req->hdr_len = 3806963cab50SHariprasad S cpu_to_be32(SYN_RX_CHAN_V(RX_CHAN_G(be32_to_cpu(l2info)))); 3807963cab50SHariprasad S if (CHELSIO_CHIP_VERSION(type) <= CHELSIO_T5) { 3808963cab50SHariprasad S eth_hdr_len = is_t4(type) ? 3809963cab50SHariprasad S RX_ETHHDR_LEN_G(be32_to_cpu(l2info)) : 3810963cab50SHariprasad S RX_T5_ETHHDR_LEN_G(be32_to_cpu(l2info)); 3811963cab50SHariprasad S req->hdr_len |= cpu_to_be32(TCP_HDR_LEN_V(tcp_hdr_len) | 3812963cab50SHariprasad S IP_HDR_LEN_V(ip_hdr_len) | 3813963cab50SHariprasad S ETH_HDR_LEN_V(eth_hdr_len)); 3814963cab50SHariprasad S } else { /* T6 and later */ 3815963cab50SHariprasad S eth_hdr_len = RX_T6_ETHHDR_LEN_G(be32_to_cpu(l2info)); 3816963cab50SHariprasad S req->hdr_len |= cpu_to_be32(T6_TCP_HDR_LEN_V(tcp_hdr_len) | 3817963cab50SHariprasad S T6_IP_HDR_LEN_V(ip_hdr_len) | 3818963cab50SHariprasad S T6_ETH_HDR_LEN_V(eth_hdr_len)); 3819963cab50SHariprasad S } 3820963cab50SHariprasad S req->vlan = vlantag; 3821963cab50SHariprasad S req->len = len; 38226c53e938SHariprasad Shenai req->tos_stid = cpu_to_be32(PASS_OPEN_TID_V(stid) | 38236c53e938SHariprasad Shenai PASS_OPEN_TOS_V(tos)); 38241cab775cSVipul Pandya req->tcpopt.mss = htons(tmp_opt.mss_clamp); 38251cab775cSVipul Pandya if (tmp_opt.wscale_ok) 38261cab775cSVipul Pandya req->tcpopt.wsf = tmp_opt.snd_wscale; 38271cab775cSVipul Pandya req->tcpopt.tstamp = tmp_opt.saw_tstamp; 38281cab775cSVipul Pandya if (tmp_opt.sack_ok) 38291cab775cSVipul Pandya req->tcpopt.sack = 1; 38301cab775cSVipul Pandya OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_REQ, 0)); 38311cab775cSVipul Pandya return; 38321cab775cSVipul Pandya } 38331cab775cSVipul Pandya 38341cab775cSVipul Pandya static void send_fw_pass_open_req(struct c4iw_dev *dev, struct sk_buff *skb, 38351cab775cSVipul Pandya __be32 laddr, __be16 lport, 38361cab775cSVipul Pandya __be32 raddr, __be16 rport, 38371cab775cSVipul Pandya u32 rcv_isn, u32 filter, u16 window, 38381cab775cSVipul Pandya u32 rss_qid, u8 port_id) 38391cab775cSVipul Pandya { 38401cab775cSVipul Pandya struct sk_buff *req_skb; 38411cab775cSVipul Pandya struct fw_ofld_connection_wr *req; 38421cab775cSVipul Pandya struct cpl_pass_accept_req *cpl = cplhdr(skb); 38431ce1d471SSteve Wise int ret; 38441cab775cSVipul Pandya 38451cab775cSVipul Pandya req_skb = alloc_skb(sizeof(struct fw_ofld_connection_wr), GFP_KERNEL); 38461cab775cSVipul Pandya req = (struct fw_ofld_connection_wr *)__skb_put(req_skb, sizeof(*req)); 38471cab775cSVipul Pandya memset(req, 0, sizeof(*req)); 38486c53e938SHariprasad Shenai req->op_compl = htonl(WR_OP_V(FW_OFLD_CONNECTION_WR) | FW_WR_COMPL_F); 3849e2ac9628SHariprasad Shenai req->len16_pkd = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*req), 16))); 385077a80e23SHariprasad Shenai req->le.version_cpl = htonl(FW_OFLD_CONNECTION_WR_CPL_F); 3851ef5d6355SVipul Pandya req->le.filter = (__force __be32) filter; 38521cab775cSVipul Pandya req->le.lport = lport; 38531cab775cSVipul Pandya req->le.pport = rport; 38541cab775cSVipul Pandya req->le.u.ipv4.lip = laddr; 38551cab775cSVipul Pandya req->le.u.ipv4.pip = raddr; 38561cab775cSVipul Pandya req->tcb.rcv_nxt = htonl(rcv_isn + 1); 38571cab775cSVipul Pandya req->tcb.rcv_adv = htons(window); 38581cab775cSVipul Pandya req->tcb.t_state_to_astid = 385977a80e23SHariprasad Shenai htonl(FW_OFLD_CONNECTION_WR_T_STATE_V(TCP_SYN_RECV) | 386077a80e23SHariprasad Shenai FW_OFLD_CONNECTION_WR_RCV_SCALE_V(cpl->tcpopt.wsf) | 386177a80e23SHariprasad Shenai FW_OFLD_CONNECTION_WR_ASTID_V( 38626c53e938SHariprasad Shenai PASS_OPEN_TID_G(ntohl(cpl->tos_stid)))); 38631cab775cSVipul Pandya 38641cab775cSVipul Pandya /* 38651cab775cSVipul Pandya * We store the qid in opt2 which will be used by the firmware 38661cab775cSVipul Pandya * to send us the wr response. 38671cab775cSVipul Pandya */ 3868d7990b0cSAnish Bhatt req->tcb.opt2 = htonl(RSS_QUEUE_V(rss_qid)); 38691cab775cSVipul Pandya 38701cab775cSVipul Pandya /* 38711cab775cSVipul Pandya * We initialize the MSS index in TCB to 0xF. 38721cab775cSVipul Pandya * So that when driver sends cpl_pass_accept_rpl 38731cab775cSVipul Pandya * TCB picks up the correct value. If this was 0 38741cab775cSVipul Pandya * TP will ignore any value > 0 for MSS index. 38751cab775cSVipul Pandya */ 3876d7990b0cSAnish Bhatt req->tcb.opt0 = cpu_to_be64(MSS_IDX_V(0xF)); 38776198dd8dSHariprasad S req->cookie = (uintptr_t)skb; 38781cab775cSVipul Pandya 38791cab775cSVipul Pandya set_wr_txq(req_skb, CPL_PRIORITY_CONTROL, port_id); 38801ce1d471SSteve Wise ret = cxgb4_ofld_send(dev->rdev.lldi.ports[0], req_skb); 38811ce1d471SSteve Wise if (ret < 0) { 38821ce1d471SSteve Wise pr_err("%s - cxgb4_ofld_send error %d - dropping\n", __func__, 38831ce1d471SSteve Wise ret); 38841ce1d471SSteve Wise kfree_skb(skb); 38851ce1d471SSteve Wise kfree_skb(req_skb); 38861ce1d471SSteve Wise } 38871cab775cSVipul Pandya } 38881cab775cSVipul Pandya 38891cab775cSVipul Pandya /* 38901cab775cSVipul Pandya * Handler for CPL_RX_PKT message. Need to handle cpl_rx_pkt 38911cab775cSVipul Pandya * messages when a filter is being used instead of server to 38921cab775cSVipul Pandya * redirect a syn packet. When packets hit filter they are redirected 38931cab775cSVipul Pandya * to the offload queue and driver tries to establish the connection 38941cab775cSVipul Pandya * using firmware work request. 38951cab775cSVipul Pandya */ 38961cab775cSVipul Pandya static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb) 38971cab775cSVipul Pandya { 38981cab775cSVipul Pandya int stid; 38991cab775cSVipul Pandya unsigned int filter; 39001cab775cSVipul Pandya struct ethhdr *eh = NULL; 39011cab775cSVipul Pandya struct vlan_ethhdr *vlan_eh = NULL; 39021cab775cSVipul Pandya struct iphdr *iph; 39031cab775cSVipul Pandya struct tcphdr *tcph; 39041cab775cSVipul Pandya struct rss_header *rss = (void *)skb->data; 39051cab775cSVipul Pandya struct cpl_rx_pkt *cpl = (void *)skb->data; 39061cab775cSVipul Pandya struct cpl_pass_accept_req *req = (void *)(rss + 1); 39071cab775cSVipul Pandya struct l2t_entry *e; 39081cab775cSVipul Pandya struct dst_entry *dst; 3909f86fac79SHariprasad S struct c4iw_ep *lep = NULL; 39101cab775cSVipul Pandya u16 window; 39111cab775cSVipul Pandya struct port_info *pi; 39121cab775cSVipul Pandya struct net_device *pdev; 3913f079af7aSVipul Pandya u16 rss_qid, eth_hdr_len; 39141cab775cSVipul Pandya int step; 39151cab775cSVipul Pandya u32 tx_chan; 39161cab775cSVipul Pandya struct neighbour *neigh; 39171cab775cSVipul Pandya 39181cab775cSVipul Pandya /* Drop all non-SYN packets */ 3919bdc590b9SHariprasad Shenai if (!(cpl->l2info & cpu_to_be32(RXF_SYN_F))) 39201cab775cSVipul Pandya goto reject; 39211cab775cSVipul Pandya 39221cab775cSVipul Pandya /* 39231cab775cSVipul Pandya * Drop all packets which did not hit the filter. 39241cab775cSVipul Pandya * Unlikely to happen. 39251cab775cSVipul Pandya */ 39261cab775cSVipul Pandya if (!(rss->filter_hit && rss->filter_tid)) 39271cab775cSVipul Pandya goto reject; 39281cab775cSVipul Pandya 39291cab775cSVipul Pandya /* 39301cab775cSVipul Pandya * Calculate the server tid from filter hit index from cpl_rx_pkt. 39311cab775cSVipul Pandya */ 3932a4ea025fSKumar Sanghvi stid = (__force int) cpu_to_be32((__force u32) rss->hash_val); 39331cab775cSVipul Pandya 3934f86fac79SHariprasad S lep = (struct c4iw_ep *)get_ep_from_stid(dev, stid); 39351cab775cSVipul Pandya if (!lep) { 39361cab775cSVipul Pandya PDBG("%s connect request on invalid stid %d\n", __func__, stid); 39371cab775cSVipul Pandya goto reject; 39381cab775cSVipul Pandya } 39391cab775cSVipul Pandya 3940963cab50SHariprasad S switch (CHELSIO_CHIP_VERSION(dev->rdev.lldi.adapter_type)) { 3941963cab50SHariprasad S case CHELSIO_T4: 3942963cab50SHariprasad S eth_hdr_len = RX_ETHHDR_LEN_G(be32_to_cpu(cpl->l2info)); 3943963cab50SHariprasad S break; 3944963cab50SHariprasad S case CHELSIO_T5: 3945963cab50SHariprasad S eth_hdr_len = RX_T5_ETHHDR_LEN_G(be32_to_cpu(cpl->l2info)); 3946963cab50SHariprasad S break; 3947963cab50SHariprasad S case CHELSIO_T6: 3948963cab50SHariprasad S eth_hdr_len = RX_T6_ETHHDR_LEN_G(be32_to_cpu(cpl->l2info)); 3949963cab50SHariprasad S break; 3950963cab50SHariprasad S default: 3951963cab50SHariprasad S pr_err("T%d Chip is not supported\n", 3952963cab50SHariprasad S CHELSIO_CHIP_VERSION(dev->rdev.lldi.adapter_type)); 3953963cab50SHariprasad S goto reject; 3954963cab50SHariprasad S } 3955963cab50SHariprasad S 3956f079af7aSVipul Pandya if (eth_hdr_len == ETH_HLEN) { 39571cab775cSVipul Pandya eh = (struct ethhdr *)(req + 1); 39581cab775cSVipul Pandya iph = (struct iphdr *)(eh + 1); 39591cab775cSVipul Pandya } else { 39601cab775cSVipul Pandya vlan_eh = (struct vlan_ethhdr *)(req + 1); 39611cab775cSVipul Pandya iph = (struct iphdr *)(vlan_eh + 1); 39621cab775cSVipul Pandya skb->vlan_tci = ntohs(cpl->vlan); 39631cab775cSVipul Pandya } 39641cab775cSVipul Pandya 39651cab775cSVipul Pandya if (iph->version != 0x4) 39661cab775cSVipul Pandya goto reject; 39671cab775cSVipul Pandya 39681cab775cSVipul Pandya tcph = (struct tcphdr *)(iph + 1); 39691cab775cSVipul Pandya skb_set_network_header(skb, (void *)iph - (void *)rss); 39701cab775cSVipul Pandya skb_set_transport_header(skb, (void *)tcph - (void *)rss); 39711cab775cSVipul Pandya skb_get(skb); 39721cab775cSVipul Pandya 39731cab775cSVipul Pandya PDBG("%s lip 0x%x lport %u pip 0x%x pport %u tos %d\n", __func__, 39741cab775cSVipul Pandya ntohl(iph->daddr), ntohs(tcph->dest), ntohl(iph->saddr), 39751cab775cSVipul Pandya ntohs(tcph->source), iph->tos); 39761cab775cSVipul Pandya 3977830662f6SVipul Pandya dst = find_route(dev, iph->daddr, iph->saddr, tcph->dest, tcph->source, 39781cab775cSVipul Pandya iph->tos); 3979830662f6SVipul Pandya if (!dst) { 39801cab775cSVipul Pandya pr_err("%s - failed to find dst entry!\n", 39811cab775cSVipul Pandya __func__); 39821cab775cSVipul Pandya goto reject; 39831cab775cSVipul Pandya } 39841cab775cSVipul Pandya neigh = dst_neigh_lookup_skb(dst, skb); 39851cab775cSVipul Pandya 3986aaa0c23cSZhouyi Zhou if (!neigh) { 3987aaa0c23cSZhouyi Zhou pr_err("%s - failed to allocate neigh!\n", 3988aaa0c23cSZhouyi Zhou __func__); 3989aaa0c23cSZhouyi Zhou goto free_dst; 3990aaa0c23cSZhouyi Zhou } 3991aaa0c23cSZhouyi Zhou 39921cab775cSVipul Pandya if (neigh->dev->flags & IFF_LOOPBACK) { 39931cab775cSVipul Pandya pdev = ip_dev_find(&init_net, iph->daddr); 39941cab775cSVipul Pandya e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, 39951cab775cSVipul Pandya pdev, 0); 39961cab775cSVipul Pandya pi = (struct port_info *)netdev_priv(pdev); 39971cab775cSVipul Pandya tx_chan = cxgb4_port_chan(pdev); 39981cab775cSVipul Pandya dev_put(pdev); 39991cab775cSVipul Pandya } else { 4000830662f6SVipul Pandya pdev = get_real_dev(neigh->dev); 40011cab775cSVipul Pandya e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, 4002830662f6SVipul Pandya pdev, 0); 4003830662f6SVipul Pandya pi = (struct port_info *)netdev_priv(pdev); 4004830662f6SVipul Pandya tx_chan = cxgb4_port_chan(pdev); 40051cab775cSVipul Pandya } 4006ebf00060SSteve Wise neigh_release(neigh); 40071cab775cSVipul Pandya if (!e) { 40081cab775cSVipul Pandya pr_err("%s - failed to allocate l2t entry!\n", 40091cab775cSVipul Pandya __func__); 40101cab775cSVipul Pandya goto free_dst; 40111cab775cSVipul Pandya } 40121cab775cSVipul Pandya 40131cab775cSVipul Pandya step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan; 40141cab775cSVipul Pandya rss_qid = dev->rdev.lldi.rxq_ids[pi->port_id * step]; 4015ef5d6355SVipul Pandya window = (__force u16) htons((__force u16)tcph->window); 40161cab775cSVipul Pandya 40171cab775cSVipul Pandya /* Calcuate filter portion for LE region. */ 401841b4f86cSKumar Sanghvi filter = (__force unsigned int) cpu_to_be32(cxgb4_select_ntuple( 401941b4f86cSKumar Sanghvi dev->rdev.lldi.ports[0], 402041b4f86cSKumar Sanghvi e)); 40211cab775cSVipul Pandya 40221cab775cSVipul Pandya /* 40231cab775cSVipul Pandya * Synthesize the cpl_pass_accept_req. We have everything except the 40241cab775cSVipul Pandya * TID. Once firmware sends a reply with TID we update the TID field 40251cab775cSVipul Pandya * in cpl and pass it through the regular cpl_pass_accept_req path. 40261cab775cSVipul Pandya */ 40271cab775cSVipul Pandya build_cpl_pass_accept_req(skb, stid, iph->tos); 40281cab775cSVipul Pandya send_fw_pass_open_req(dev, skb, iph->daddr, tcph->dest, iph->saddr, 40291cab775cSVipul Pandya tcph->source, ntohl(tcph->seq), filter, window, 40301cab775cSVipul Pandya rss_qid, pi->port_id); 40311cab775cSVipul Pandya cxgb4_l2t_release(e); 40321cab775cSVipul Pandya free_dst: 40331cab775cSVipul Pandya dst_release(dst); 40341cab775cSVipul Pandya reject: 4035f86fac79SHariprasad S if (lep) 4036f86fac79SHariprasad S c4iw_put_ep(&lep->com); 40372f5b48c3SSteve Wise return 0; 40382f5b48c3SSteve Wise } 40392f5b48c3SSteve Wise 4040cfdda9d7SSteve Wise /* 4041be4c9badSRoland Dreier * These are the real handlers that are called from a 4042be4c9badSRoland Dreier * work queue. 4043be4c9badSRoland Dreier */ 40449dec900cSHariprasad S static c4iw_handler_func work_handlers[NUM_CPL_CMDS + NUM_FAKE_CPLS] = { 4045be4c9badSRoland Dreier [CPL_ACT_ESTABLISH] = act_establish, 4046be4c9badSRoland Dreier [CPL_ACT_OPEN_RPL] = act_open_rpl, 4047be4c9badSRoland Dreier [CPL_RX_DATA] = rx_data, 4048be4c9badSRoland Dreier [CPL_ABORT_RPL_RSS] = abort_rpl, 4049be4c9badSRoland Dreier [CPL_ABORT_RPL] = abort_rpl, 4050be4c9badSRoland Dreier [CPL_PASS_OPEN_RPL] = pass_open_rpl, 4051be4c9badSRoland Dreier [CPL_CLOSE_LISTSRV_RPL] = close_listsrv_rpl, 4052be4c9badSRoland Dreier [CPL_PASS_ACCEPT_REQ] = pass_accept_req, 4053be4c9badSRoland Dreier [CPL_PASS_ESTABLISH] = pass_establish, 4054be4c9badSRoland Dreier [CPL_PEER_CLOSE] = peer_close, 4055be4c9badSRoland Dreier [CPL_ABORT_REQ_RSS] = peer_abort, 4056be4c9badSRoland Dreier [CPL_CLOSE_CON_RPL] = close_con_rpl, 4057be4c9badSRoland Dreier [CPL_RDMA_TERMINATE] = terminate, 40582f5b48c3SSteve Wise [CPL_FW4_ACK] = fw4_ack, 40591cab775cSVipul Pandya [CPL_FW6_MSG] = deferred_fw6_msg, 40609dec900cSHariprasad S [CPL_RX_PKT] = rx_pkt, 40618d1f1a6bSHariprasad S [FAKE_CPL_PUT_EP_SAFE] = _put_ep_safe, 40628d1f1a6bSHariprasad S [FAKE_CPL_PASS_PUT_EP_SAFE] = _put_pass_ep_safe 4063be4c9badSRoland Dreier }; 4064be4c9badSRoland Dreier 4065be4c9badSRoland Dreier static void process_timeout(struct c4iw_ep *ep) 4066be4c9badSRoland Dreier { 4067be4c9badSRoland Dreier struct c4iw_qp_attributes attrs; 4068be4c9badSRoland Dreier int abort = 1; 4069be4c9badSRoland Dreier 40702f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 4071be4c9badSRoland Dreier PDBG("%s ep %p tid %u state %d\n", __func__, ep, ep->hwtid, 4072be4c9badSRoland Dreier ep->com.state); 4073793dad94SVipul Pandya set_bit(TIMEDOUT, &ep->com.history); 4074be4c9badSRoland Dreier switch (ep->com.state) { 4075be4c9badSRoland Dreier case MPA_REQ_SENT: 4076be4c9badSRoland Dreier connect_reply_upcall(ep, -ETIMEDOUT); 4077be4c9badSRoland Dreier break; 4078be4c9badSRoland Dreier case MPA_REQ_WAIT: 4079ceb110a8SHariprasad S case MPA_REQ_RCVD: 4080e4b76a2aSHariprasad S case MPA_REP_SENT: 4081ceb110a8SHariprasad S case FPDU_MODE: 4082be4c9badSRoland Dreier break; 4083be4c9badSRoland Dreier case CLOSING: 4084be4c9badSRoland Dreier case MORIBUND: 4085be4c9badSRoland Dreier if (ep->com.cm_id && ep->com.qp) { 4086be4c9badSRoland Dreier attrs.next_state = C4IW_QP_STATE_ERROR; 4087be4c9badSRoland Dreier c4iw_modify_qp(ep->com.qp->rhp, 4088be4c9badSRoland Dreier ep->com.qp, C4IW_QP_ATTR_NEXT_STATE, 4089be4c9badSRoland Dreier &attrs, 1); 4090be4c9badSRoland Dreier } 4091be13b2dfSSteve Wise close_complete_upcall(ep, -ETIMEDOUT); 4092be4c9badSRoland Dreier break; 4093b33bd0cbSSteve Wise case ABORTING: 4094b33bd0cbSSteve Wise case DEAD: 4095b33bd0cbSSteve Wise 4096b33bd0cbSSteve Wise /* 4097b33bd0cbSSteve Wise * These states are expected if the ep timed out at the same 4098b33bd0cbSSteve Wise * time as another thread was calling stop_ep_timer(). 4099b33bd0cbSSteve Wise * So we silently do nothing for these states. 4100b33bd0cbSSteve Wise */ 4101b33bd0cbSSteve Wise abort = 0; 4102b33bd0cbSSteve Wise break; 4103be4c9badSRoland Dreier default: 410476f267b7SJulia Lawall WARN(1, "%s unexpected state ep %p tid %u state %u\n", 4105be4c9badSRoland Dreier __func__, ep, ep->hwtid, ep->com.state); 4106be4c9badSRoland Dreier abort = 0; 4107be4c9badSRoland Dreier } 4108cc18b939SSteve Wise mutex_unlock(&ep->com.mutex); 410969736279SHariprasad S if (abort) 411069736279SHariprasad S c4iw_ep_disconnect(ep, 1, GFP_KERNEL); 4111be4c9badSRoland Dreier c4iw_put_ep(&ep->com); 4112be4c9badSRoland Dreier } 4113be4c9badSRoland Dreier 4114be4c9badSRoland Dreier static void process_timedout_eps(void) 4115be4c9badSRoland Dreier { 4116be4c9badSRoland Dreier struct c4iw_ep *ep; 4117be4c9badSRoland Dreier 4118be4c9badSRoland Dreier spin_lock_irq(&timeout_lock); 4119be4c9badSRoland Dreier while (!list_empty(&timeout_list)) { 4120be4c9badSRoland Dreier struct list_head *tmp; 4121be4c9badSRoland Dreier 4122be4c9badSRoland Dreier tmp = timeout_list.next; 4123be4c9badSRoland Dreier list_del(tmp); 4124b33bd0cbSSteve Wise tmp->next = NULL; 4125b33bd0cbSSteve Wise tmp->prev = NULL; 4126be4c9badSRoland Dreier spin_unlock_irq(&timeout_lock); 4127be4c9badSRoland Dreier ep = list_entry(tmp, struct c4iw_ep, entry); 4128be4c9badSRoland Dreier process_timeout(ep); 4129be4c9badSRoland Dreier spin_lock_irq(&timeout_lock); 4130be4c9badSRoland Dreier } 4131be4c9badSRoland Dreier spin_unlock_irq(&timeout_lock); 4132be4c9badSRoland Dreier } 4133be4c9badSRoland Dreier 4134be4c9badSRoland Dreier static void process_work(struct work_struct *work) 4135be4c9badSRoland Dreier { 4136be4c9badSRoland Dreier struct sk_buff *skb = NULL; 4137be4c9badSRoland Dreier struct c4iw_dev *dev; 4138c1d7356cSDan Carpenter struct cpl_act_establish *rpl; 4139be4c9badSRoland Dreier unsigned int opcode; 4140be4c9badSRoland Dreier int ret; 4141be4c9badSRoland Dreier 4142b33bd0cbSSteve Wise process_timedout_eps(); 4143be4c9badSRoland Dreier while ((skb = skb_dequeue(&rxq))) { 4144be4c9badSRoland Dreier rpl = cplhdr(skb); 4145be4c9badSRoland Dreier dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *))); 4146be4c9badSRoland Dreier opcode = rpl->ot.opcode; 4147be4c9badSRoland Dreier 4148be4c9badSRoland Dreier BUG_ON(!work_handlers[opcode]); 4149be4c9badSRoland Dreier ret = work_handlers[opcode](dev, skb); 4150be4c9badSRoland Dreier if (!ret) 4151be4c9badSRoland Dreier kfree_skb(skb); 4152be4c9badSRoland Dreier process_timedout_eps(); 4153be4c9badSRoland Dreier } 4154b33bd0cbSSteve Wise } 4155be4c9badSRoland Dreier 4156be4c9badSRoland Dreier static DECLARE_WORK(skb_work, process_work); 4157be4c9badSRoland Dreier 4158be4c9badSRoland Dreier static void ep_timeout(unsigned long arg) 4159be4c9badSRoland Dreier { 4160be4c9badSRoland Dreier struct c4iw_ep *ep = (struct c4iw_ep *)arg; 41611ec779ccSVipul Pandya int kickit = 0; 4162be4c9badSRoland Dreier 4163be4c9badSRoland Dreier spin_lock(&timeout_lock); 41641ec779ccSVipul Pandya if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) { 4165b33bd0cbSSteve Wise /* 4166b33bd0cbSSteve Wise * Only insert if it is not already on the list. 4167b33bd0cbSSteve Wise */ 4168b33bd0cbSSteve Wise if (!ep->entry.next) { 4169be4c9badSRoland Dreier list_add_tail(&ep->entry, &timeout_list); 41701ec779ccSVipul Pandya kickit = 1; 41711ec779ccSVipul Pandya } 4172b33bd0cbSSteve Wise } 4173be4c9badSRoland Dreier spin_unlock(&timeout_lock); 41741ec779ccSVipul Pandya if (kickit) 4175be4c9badSRoland Dreier queue_work(workq, &skb_work); 4176be4c9badSRoland Dreier } 4177be4c9badSRoland Dreier 4178be4c9badSRoland Dreier /* 4179cfdda9d7SSteve Wise * All the CM events are handled on a work queue to have a safe context. 4180cfdda9d7SSteve Wise */ 4181cfdda9d7SSteve Wise static int sched(struct c4iw_dev *dev, struct sk_buff *skb) 4182cfdda9d7SSteve Wise { 4183cfdda9d7SSteve Wise 4184cfdda9d7SSteve Wise /* 4185cfdda9d7SSteve Wise * Save dev in the skb->cb area. 4186cfdda9d7SSteve Wise */ 4187cfdda9d7SSteve Wise *((struct c4iw_dev **) (skb->cb + sizeof(void *))) = dev; 4188cfdda9d7SSteve Wise 4189cfdda9d7SSteve Wise /* 4190cfdda9d7SSteve Wise * Queue the skb and schedule the worker thread. 4191cfdda9d7SSteve Wise */ 4192cfdda9d7SSteve Wise skb_queue_tail(&rxq, skb); 4193cfdda9d7SSteve Wise queue_work(workq, &skb_work); 4194cfdda9d7SSteve Wise return 0; 4195cfdda9d7SSteve Wise } 4196cfdda9d7SSteve Wise 4197cfdda9d7SSteve Wise static int set_tcb_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 4198cfdda9d7SSteve Wise { 4199cfdda9d7SSteve Wise struct cpl_set_tcb_rpl *rpl = cplhdr(skb); 4200cfdda9d7SSteve Wise 4201cfdda9d7SSteve Wise if (rpl->status != CPL_ERR_NONE) { 4202cfdda9d7SSteve Wise printk(KERN_ERR MOD "Unexpected SET_TCB_RPL status %u " 4203cfdda9d7SSteve Wise "for tid %u\n", rpl->status, GET_TID(rpl)); 4204cfdda9d7SSteve Wise } 42052f5b48c3SSteve Wise kfree_skb(skb); 4206cfdda9d7SSteve Wise return 0; 4207cfdda9d7SSteve Wise } 4208cfdda9d7SSteve Wise 4209be4c9badSRoland Dreier static int fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb) 4210be4c9badSRoland Dreier { 4211be4c9badSRoland Dreier struct cpl_fw6_msg *rpl = cplhdr(skb); 4212be4c9badSRoland Dreier struct c4iw_wr_wait *wr_waitp; 4213be4c9badSRoland Dreier int ret; 4214be4c9badSRoland Dreier 4215be4c9badSRoland Dreier PDBG("%s type %u\n", __func__, rpl->type); 4216be4c9badSRoland Dreier 4217be4c9badSRoland Dreier switch (rpl->type) { 42185be78ee9SVipul Pandya case FW6_TYPE_WR_RPL: 4219be4c9badSRoland Dreier ret = (int)((be64_to_cpu(rpl->data[0]) >> 8) & 0xff); 4220c8e081a1SRoland Dreier wr_waitp = (struct c4iw_wr_wait *)(__force unsigned long) rpl->data[1]; 4221be4c9badSRoland Dreier PDBG("%s wr_waitp %p ret %u\n", __func__, wr_waitp, ret); 4222d9594d99SSteve Wise if (wr_waitp) 4223d9594d99SSteve Wise c4iw_wake_up(wr_waitp, ret ? -ret : 0); 42242f5b48c3SSteve Wise kfree_skb(skb); 4225be4c9badSRoland Dreier break; 42265be78ee9SVipul Pandya case FW6_TYPE_CQE: 42275be78ee9SVipul Pandya case FW6_TYPE_OFLD_CONNECTION_WR_RPL: 42281cab775cSVipul Pandya sched(dev, skb); 42295be78ee9SVipul Pandya break; 4230be4c9badSRoland Dreier default: 4231be4c9badSRoland Dreier printk(KERN_ERR MOD "%s unexpected fw6 msg type %u\n", __func__, 4232be4c9badSRoland Dreier rpl->type); 42332f5b48c3SSteve Wise kfree_skb(skb); 4234be4c9badSRoland Dreier break; 4235be4c9badSRoland Dreier } 4236be4c9badSRoland Dreier return 0; 4237be4c9badSRoland Dreier } 4238be4c9badSRoland Dreier 42398da7e7a5SSteve Wise static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb) 42408da7e7a5SSteve Wise { 42418da7e7a5SSteve Wise struct cpl_abort_req_rss *req = cplhdr(skb); 42428da7e7a5SSteve Wise struct c4iw_ep *ep; 42438da7e7a5SSteve Wise unsigned int tid = GET_TID(req); 42448da7e7a5SSteve Wise 4245944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 4246944661ddSHariprasad S /* This EP will be dereferenced in peer_abort() */ 424714b92228SSteve Wise if (!ep) { 424814b92228SSteve Wise printk(KERN_WARNING MOD 424914b92228SSteve Wise "Abort on non-existent endpoint, tid %d\n", tid); 425014b92228SSteve Wise kfree_skb(skb); 425114b92228SSteve Wise return 0; 425214b92228SSteve Wise } 42537a2cea2aSSteve Wise if (is_neg_adv(req->status)) { 4254179d03bbSHariprasad S PDBG("%s Negative advice on abort- tid %u status %d (%s)\n", 4255179d03bbSHariprasad S __func__, ep->hwtid, req->status, 4256179d03bbSHariprasad S neg_adv_str(req->status)); 4257944661ddSHariprasad S goto out; 42588da7e7a5SSteve Wise } 42598da7e7a5SSteve Wise PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid, 42608da7e7a5SSteve Wise ep->com.state); 42618da7e7a5SSteve Wise 42628da7e7a5SSteve Wise c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 4263944661ddSHariprasad S out: 42648da7e7a5SSteve Wise sched(dev, skb); 42658da7e7a5SSteve Wise return 0; 42668da7e7a5SSteve Wise } 42678da7e7a5SSteve Wise 4268be4c9badSRoland Dreier /* 4269be4c9badSRoland Dreier * Most upcalls from the T4 Core go to sched() to 4270be4c9badSRoland Dreier * schedule the processing on a work queue. 4271be4c9badSRoland Dreier */ 4272be4c9badSRoland Dreier c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS] = { 4273be4c9badSRoland Dreier [CPL_ACT_ESTABLISH] = sched, 4274be4c9badSRoland Dreier [CPL_ACT_OPEN_RPL] = sched, 4275be4c9badSRoland Dreier [CPL_RX_DATA] = sched, 4276be4c9badSRoland Dreier [CPL_ABORT_RPL_RSS] = sched, 4277be4c9badSRoland Dreier [CPL_ABORT_RPL] = sched, 4278be4c9badSRoland Dreier [CPL_PASS_OPEN_RPL] = sched, 4279be4c9badSRoland Dreier [CPL_CLOSE_LISTSRV_RPL] = sched, 4280be4c9badSRoland Dreier [CPL_PASS_ACCEPT_REQ] = sched, 4281be4c9badSRoland Dreier [CPL_PASS_ESTABLISH] = sched, 4282be4c9badSRoland Dreier [CPL_PEER_CLOSE] = sched, 4283be4c9badSRoland Dreier [CPL_CLOSE_CON_RPL] = sched, 42848da7e7a5SSteve Wise [CPL_ABORT_REQ_RSS] = peer_abort_intr, 4285be4c9badSRoland Dreier [CPL_RDMA_TERMINATE] = sched, 4286be4c9badSRoland Dreier [CPL_FW4_ACK] = sched, 4287be4c9badSRoland Dreier [CPL_SET_TCB_RPL] = set_tcb_rpl, 42881cab775cSVipul Pandya [CPL_FW6_MSG] = fw6_msg, 42891cab775cSVipul Pandya [CPL_RX_PKT] = sched 4290be4c9badSRoland Dreier }; 4291be4c9badSRoland Dreier 4292cfdda9d7SSteve Wise int __init c4iw_cm_init(void) 4293cfdda9d7SSteve Wise { 4294be4c9badSRoland Dreier spin_lock_init(&timeout_lock); 4295cfdda9d7SSteve Wise skb_queue_head_init(&rxq); 4296cfdda9d7SSteve Wise 4297cfdda9d7SSteve Wise workq = create_singlethread_workqueue("iw_cxgb4"); 4298cfdda9d7SSteve Wise if (!workq) 4299cfdda9d7SSteve Wise return -ENOMEM; 4300cfdda9d7SSteve Wise 4301cfdda9d7SSteve Wise return 0; 4302cfdda9d7SSteve Wise } 4303cfdda9d7SSteve Wise 430446c1376dSSteve Wise void c4iw_cm_term(void) 4305cfdda9d7SSteve Wise { 4306be4c9badSRoland Dreier WARN_ON(!list_empty(&timeout_list)); 4307cfdda9d7SSteve Wise flush_workqueue(workq); 4308cfdda9d7SSteve Wise destroy_workqueue(workq); 4309cfdda9d7SSteve Wise } 4310