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 5285e42b04SVarun Prakash #include <libcxgb_cm.h> 53cfdda9d7SSteve Wise #include "iw_cxgb4.h" 5484cc6ac6SHariprasad S #include "clip_tbl.h" 55cfdda9d7SSteve Wise 56cfdda9d7SSteve Wise static char *states[] = { 57cfdda9d7SSteve Wise "idle", 58cfdda9d7SSteve Wise "listen", 59cfdda9d7SSteve Wise "connecting", 60cfdda9d7SSteve Wise "mpa_wait_req", 61cfdda9d7SSteve Wise "mpa_req_sent", 62cfdda9d7SSteve Wise "mpa_req_rcvd", 63cfdda9d7SSteve Wise "mpa_rep_sent", 64cfdda9d7SSteve Wise "fpdu_mode", 65cfdda9d7SSteve Wise "aborting", 66cfdda9d7SSteve Wise "closing", 67cfdda9d7SSteve Wise "moribund", 68cfdda9d7SSteve Wise "dead", 69cfdda9d7SSteve Wise NULL, 70cfdda9d7SSteve Wise }; 71cfdda9d7SSteve Wise 725be78ee9SVipul Pandya static int nocong; 735be78ee9SVipul Pandya module_param(nocong, int, 0644); 745be78ee9SVipul Pandya MODULE_PARM_DESC(nocong, "Turn of congestion control (default=0)"); 755be78ee9SVipul Pandya 765be78ee9SVipul Pandya static int enable_ecn; 775be78ee9SVipul Pandya module_param(enable_ecn, int, 0644); 785be78ee9SVipul Pandya MODULE_PARM_DESC(enable_ecn, "Enable ECN (default=0/disabled)"); 795be78ee9SVipul Pandya 808d539c61SPotnuri Bharat Teja static int dack_mode; 81ba6d3925SSteve Wise module_param(dack_mode, int, 0644); 828d539c61SPotnuri Bharat Teja MODULE_PARM_DESC(dack_mode, "Delayed ack mode (default=0)"); 83ba6d3925SSteve Wise 844c2c5763SHariprasad Shenai uint c4iw_max_read_depth = 32; 85be4c9badSRoland Dreier module_param(c4iw_max_read_depth, int, 0644); 864c2c5763SHariprasad Shenai MODULE_PARM_DESC(c4iw_max_read_depth, 874c2c5763SHariprasad Shenai "Per-connection max ORD/IRD (default=32)"); 88be4c9badSRoland Dreier 89cfdda9d7SSteve Wise static int enable_tcp_timestamps; 90cfdda9d7SSteve Wise module_param(enable_tcp_timestamps, int, 0644); 91cfdda9d7SSteve Wise MODULE_PARM_DESC(enable_tcp_timestamps, "Enable tcp timestamps (default=0)"); 92cfdda9d7SSteve Wise 93cfdda9d7SSteve Wise static int enable_tcp_sack; 94cfdda9d7SSteve Wise module_param(enable_tcp_sack, int, 0644); 95cfdda9d7SSteve Wise MODULE_PARM_DESC(enable_tcp_sack, "Enable tcp SACK (default=0)"); 96cfdda9d7SSteve Wise 97cfdda9d7SSteve Wise static int enable_tcp_window_scaling = 1; 98cfdda9d7SSteve Wise module_param(enable_tcp_window_scaling, int, 0644); 99cfdda9d7SSteve Wise MODULE_PARM_DESC(enable_tcp_window_scaling, 100cfdda9d7SSteve Wise "Enable tcp window scaling (default=1)"); 101cfdda9d7SSteve Wise 102df2d5130SSteve Wise static int peer2peer = 1; 103cfdda9d7SSteve Wise module_param(peer2peer, int, 0644); 104df2d5130SSteve Wise MODULE_PARM_DESC(peer2peer, "Support peer2peer ULPs (default=1)"); 105cfdda9d7SSteve Wise 106cfdda9d7SSteve Wise static int p2p_type = FW_RI_INIT_P2PTYPE_READ_REQ; 107cfdda9d7SSteve Wise module_param(p2p_type, int, 0644); 108cfdda9d7SSteve Wise MODULE_PARM_DESC(p2p_type, "RDMAP opcode to use for the RTR message: " 109cfdda9d7SSteve Wise "1=RDMA_READ 0=RDMA_WRITE (default 1)"); 110cfdda9d7SSteve Wise 111cfdda9d7SSteve Wise static int ep_timeout_secs = 60; 112cfdda9d7SSteve Wise module_param(ep_timeout_secs, int, 0644); 113cfdda9d7SSteve Wise MODULE_PARM_DESC(ep_timeout_secs, "CM Endpoint operation timeout " 114cfdda9d7SSteve Wise "in seconds (default=60)"); 115cfdda9d7SSteve Wise 116b8ac3112SHariprasad S static int mpa_rev = 2; 117cfdda9d7SSteve Wise module_param(mpa_rev, int, 0644); 118cfdda9d7SSteve Wise MODULE_PARM_DESC(mpa_rev, "MPA Revision, 0 supports amso1100, " 119ccd2c30bSHariprasad S "1 is RFC5044 spec compliant, 2 is IETF MPA Peer Connect Draft" 120b8ac3112SHariprasad S " compliant (default=2)"); 121cfdda9d7SSteve Wise 122cfdda9d7SSteve Wise static int markers_enabled; 123cfdda9d7SSteve Wise module_param(markers_enabled, int, 0644); 124cfdda9d7SSteve Wise MODULE_PARM_DESC(markers_enabled, "Enable MPA MARKERS (default(0)=disabled)"); 125cfdda9d7SSteve Wise 126cfdda9d7SSteve Wise static int crc_enabled = 1; 127cfdda9d7SSteve Wise module_param(crc_enabled, int, 0644); 128cfdda9d7SSteve Wise MODULE_PARM_DESC(crc_enabled, "Enable MPA CRC (default(1)=enabled)"); 129cfdda9d7SSteve Wise 130cfdda9d7SSteve Wise static int rcv_win = 256 * 1024; 131cfdda9d7SSteve Wise module_param(rcv_win, int, 0644); 132cfdda9d7SSteve Wise MODULE_PARM_DESC(rcv_win, "TCP receive window in bytes (default=256KB)"); 133cfdda9d7SSteve Wise 13498ae68b7SSteve Wise static int snd_win = 128 * 1024; 135cfdda9d7SSteve Wise module_param(snd_win, int, 0644); 13698ae68b7SSteve Wise MODULE_PARM_DESC(snd_win, "TCP send window in bytes (default=128KB)"); 137cfdda9d7SSteve Wise 138cfdda9d7SSteve Wise static struct workqueue_struct *workq; 139cfdda9d7SSteve Wise 140cfdda9d7SSteve Wise static struct sk_buff_head rxq; 141cfdda9d7SSteve Wise 142cfdda9d7SSteve Wise static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp); 143a9346abeSKees Cook static void ep_timeout(struct timer_list *t); 144cfdda9d7SSteve Wise static void connect_reply_upcall(struct c4iw_ep *ep, int status); 1459dec900cSHariprasad S static int sched(struct c4iw_dev *dev, struct sk_buff *skb); 146cfdda9d7SSteve Wise 147be4c9badSRoland Dreier static LIST_HEAD(timeout_list); 1482e919a32STang Yizhou static DEFINE_SPINLOCK(timeout_lock); 149be4c9badSRoland Dreier 1509ca6f7cfSHariprasad S static void deref_cm_id(struct c4iw_ep_common *epc) 1519ca6f7cfSHariprasad S { 1529ca6f7cfSHariprasad S epc->cm_id->rem_ref(epc->cm_id); 1539ca6f7cfSHariprasad S epc->cm_id = NULL; 1549ca6f7cfSHariprasad S set_bit(CM_ID_DEREFED, &epc->history); 1559ca6f7cfSHariprasad S } 1569ca6f7cfSHariprasad S 1579ca6f7cfSHariprasad S static void ref_cm_id(struct c4iw_ep_common *epc) 1589ca6f7cfSHariprasad S { 1599ca6f7cfSHariprasad S set_bit(CM_ID_REFED, &epc->history); 1609ca6f7cfSHariprasad S epc->cm_id->add_ref(epc->cm_id); 1619ca6f7cfSHariprasad S } 1629ca6f7cfSHariprasad S 163325abeadSVipul Pandya static void deref_qp(struct c4iw_ep *ep) 164325abeadSVipul Pandya { 165325abeadSVipul Pandya c4iw_qp_rem_ref(&ep->com.qp->ibqp); 166325abeadSVipul Pandya clear_bit(QP_REFERENCED, &ep->com.flags); 1679ca6f7cfSHariprasad S set_bit(QP_DEREFED, &ep->com.history); 168325abeadSVipul Pandya } 169325abeadSVipul Pandya 170325abeadSVipul Pandya static void ref_qp(struct c4iw_ep *ep) 171325abeadSVipul Pandya { 172325abeadSVipul Pandya set_bit(QP_REFERENCED, &ep->com.flags); 1739ca6f7cfSHariprasad S set_bit(QP_REFED, &ep->com.history); 174325abeadSVipul Pandya c4iw_qp_add_ref(&ep->com.qp->ibqp); 175325abeadSVipul Pandya } 176325abeadSVipul Pandya 177cfdda9d7SSteve Wise static void start_ep_timer(struct c4iw_ep *ep) 178cfdda9d7SSteve Wise { 179548ddb19SBharat Potnuri pr_debug("ep %p\n", ep); 180cfdda9d7SSteve Wise if (timer_pending(&ep->timer)) { 1811ec779ccSVipul Pandya pr_err("%s timer already started! ep %p\n", 1821ec779ccSVipul Pandya __func__, ep); 1831ec779ccSVipul Pandya return; 1841ec779ccSVipul Pandya } 1851ec779ccSVipul Pandya clear_bit(TIMEOUT, &ep->com.flags); 186cfdda9d7SSteve Wise c4iw_get_ep(&ep->com); 187cfdda9d7SSteve Wise ep->timer.expires = jiffies + ep_timeout_secs * HZ; 188cfdda9d7SSteve Wise add_timer(&ep->timer); 189cfdda9d7SSteve Wise } 190cfdda9d7SSteve Wise 191b33bd0cbSSteve Wise static int stop_ep_timer(struct c4iw_ep *ep) 192cfdda9d7SSteve Wise { 193548ddb19SBharat Potnuri pr_debug("ep %p stopping\n", ep); 194cfdda9d7SSteve Wise del_timer_sync(&ep->timer); 195b33bd0cbSSteve Wise if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) { 196cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 197b33bd0cbSSteve Wise return 0; 198b33bd0cbSSteve Wise } 199b33bd0cbSSteve Wise return 1; 200cfdda9d7SSteve Wise } 201cfdda9d7SSteve Wise 202cfdda9d7SSteve Wise static int c4iw_l2t_send(struct c4iw_rdev *rdev, struct sk_buff *skb, 203cfdda9d7SSteve Wise struct l2t_entry *l2e) 204cfdda9d7SSteve Wise { 205cfdda9d7SSteve Wise int error = 0; 206cfdda9d7SSteve Wise 207cfdda9d7SSteve Wise if (c4iw_fatal_error(rdev)) { 208cfdda9d7SSteve Wise kfree_skb(skb); 2094d45b757SBharat Potnuri pr_err("%s - device in error state - dropping\n", __func__); 210cfdda9d7SSteve Wise return -EIO; 211cfdda9d7SSteve Wise } 212cfdda9d7SSteve Wise error = cxgb4_l2t_send(rdev->lldi.ports[0], skb, l2e); 213cfdda9d7SSteve Wise if (error < 0) 214cfdda9d7SSteve Wise kfree_skb(skb); 215caa6c9f2SHariprasad S else if (error == NET_XMIT_DROP) 216caa6c9f2SHariprasad S return -ENOMEM; 21774594861SSteve Wise return error < 0 ? error : 0; 218cfdda9d7SSteve Wise } 219cfdda9d7SSteve Wise 220cfdda9d7SSteve Wise int c4iw_ofld_send(struct c4iw_rdev *rdev, struct sk_buff *skb) 221cfdda9d7SSteve Wise { 222cfdda9d7SSteve Wise int error = 0; 223cfdda9d7SSteve Wise 224cfdda9d7SSteve Wise if (c4iw_fatal_error(rdev)) { 225cfdda9d7SSteve Wise kfree_skb(skb); 2264d45b757SBharat Potnuri pr_err("%s - device in error state - dropping\n", __func__); 227cfdda9d7SSteve Wise return -EIO; 228cfdda9d7SSteve Wise } 229cfdda9d7SSteve Wise error = cxgb4_ofld_send(rdev->lldi.ports[0], skb); 230cfdda9d7SSteve Wise if (error < 0) 231cfdda9d7SSteve Wise kfree_skb(skb); 23274594861SSteve Wise return error < 0 ? error : 0; 233cfdda9d7SSteve Wise } 234cfdda9d7SSteve Wise 235cfdda9d7SSteve Wise static void release_tid(struct c4iw_rdev *rdev, u32 hwtid, struct sk_buff *skb) 236cfdda9d7SSteve Wise { 237a1a23454SVarun Prakash u32 len = roundup(sizeof(struct cpl_tid_release), 16); 238cfdda9d7SSteve Wise 239a1a23454SVarun Prakash skb = get_skb(skb, len, GFP_KERNEL); 240cfdda9d7SSteve Wise if (!skb) 241cfdda9d7SSteve Wise return; 242a1a23454SVarun Prakash 243a1a23454SVarun Prakash cxgb_mk_tid_release(skb, len, hwtid, 0); 244cfdda9d7SSteve Wise c4iw_ofld_send(rdev, skb); 245cfdda9d7SSteve Wise return; 246cfdda9d7SSteve Wise } 247cfdda9d7SSteve Wise 248cfdda9d7SSteve Wise static void set_emss(struct c4iw_ep *ep, u16 opt) 249cfdda9d7SSteve Wise { 2506c53e938SHariprasad Shenai ep->emss = ep->com.dev->rdev.lldi.mtus[TCPOPT_MSS_G(opt)] - 25104524a47SHariprasad S ((AF_INET == ep->com.remote_addr.ss_family) ? 25204524a47SHariprasad S sizeof(struct iphdr) : sizeof(struct ipv6hdr)) - 25304524a47SHariprasad S sizeof(struct tcphdr); 254cfdda9d7SSteve Wise ep->mss = ep->emss; 2556c53e938SHariprasad Shenai if (TCPOPT_TSTAMP_G(opt)) 25604524a47SHariprasad S ep->emss -= round_up(TCPOLEN_TIMESTAMP, 4); 257cfdda9d7SSteve Wise if (ep->emss < 128) 258cfdda9d7SSteve Wise ep->emss = 128; 25992e7ae71SHariprasad Shenai if (ep->emss & 7) 260f48fca4dSBharat Potnuri pr_debug("Warning: misaligned mtu idx %u mss %u emss=%u\n", 2616c53e938SHariprasad Shenai TCPOPT_MSS_G(opt), ep->mss, ep->emss); 262548ddb19SBharat Potnuri pr_debug("mss_idx %u mss %u emss=%u\n", TCPOPT_MSS_G(opt), ep->mss, 263548ddb19SBharat Potnuri ep->emss); 264cfdda9d7SSteve Wise } 265cfdda9d7SSteve Wise 266cfdda9d7SSteve Wise static enum c4iw_ep_state state_read(struct c4iw_ep_common *epc) 267cfdda9d7SSteve Wise { 268cfdda9d7SSteve Wise enum c4iw_ep_state state; 269cfdda9d7SSteve Wise 2702f5b48c3SSteve Wise mutex_lock(&epc->mutex); 271cfdda9d7SSteve Wise state = epc->state; 2722f5b48c3SSteve Wise mutex_unlock(&epc->mutex); 273cfdda9d7SSteve Wise return state; 274cfdda9d7SSteve Wise } 275cfdda9d7SSteve Wise 276cfdda9d7SSteve Wise static void __state_set(struct c4iw_ep_common *epc, enum c4iw_ep_state new) 277cfdda9d7SSteve Wise { 278cfdda9d7SSteve Wise epc->state = new; 279cfdda9d7SSteve Wise } 280cfdda9d7SSteve Wise 281cfdda9d7SSteve Wise static void state_set(struct c4iw_ep_common *epc, enum c4iw_ep_state new) 282cfdda9d7SSteve Wise { 2832f5b48c3SSteve Wise mutex_lock(&epc->mutex); 284548ddb19SBharat Potnuri pr_debug("%s -> %s\n", states[epc->state], states[new]); 285cfdda9d7SSteve Wise __state_set(epc, new); 2862f5b48c3SSteve Wise mutex_unlock(&epc->mutex); 287cfdda9d7SSteve Wise return; 288cfdda9d7SSteve Wise } 289cfdda9d7SSteve Wise 2904a740838SHariprasad S static int alloc_ep_skb_list(struct sk_buff_head *ep_skb_list, int size) 2914a740838SHariprasad S { 2924a740838SHariprasad S struct sk_buff *skb; 2934a740838SHariprasad S unsigned int i; 2944a740838SHariprasad S size_t len; 2954a740838SHariprasad S 2964a740838SHariprasad S len = roundup(sizeof(union cpl_wr_size), 16); 2974a740838SHariprasad S for (i = 0; i < size; i++) { 2984a740838SHariprasad S skb = alloc_skb(len, GFP_KERNEL); 2994a740838SHariprasad S if (!skb) 3004a740838SHariprasad S goto fail; 3014a740838SHariprasad S skb_queue_tail(ep_skb_list, skb); 3024a740838SHariprasad S } 3034a740838SHariprasad S return 0; 3044a740838SHariprasad S fail: 3054a740838SHariprasad S skb_queue_purge(ep_skb_list); 3064a740838SHariprasad S return -ENOMEM; 3074a740838SHariprasad S } 3084a740838SHariprasad S 309cfdda9d7SSteve Wise static void *alloc_ep(int size, gfp_t gfp) 310cfdda9d7SSteve Wise { 311cfdda9d7SSteve Wise struct c4iw_ep_common *epc; 312cfdda9d7SSteve Wise 313cfdda9d7SSteve Wise epc = kzalloc(size, gfp); 314cfdda9d7SSteve Wise if (epc) { 3152015f26cSSteve Wise epc->wr_waitp = c4iw_alloc_wr_wait(gfp); 316ef885dc6SSteve Wise if (!epc->wr_waitp) { 317ef885dc6SSteve Wise kfree(epc); 318ef885dc6SSteve Wise epc = NULL; 319ef885dc6SSteve Wise goto out; 320ef885dc6SSteve Wise } 321cfdda9d7SSteve Wise kref_init(&epc->kref); 3222f5b48c3SSteve Wise mutex_init(&epc->mutex); 323ef885dc6SSteve Wise c4iw_init_wr_wait(epc->wr_waitp); 324cfdda9d7SSteve Wise } 325548ddb19SBharat Potnuri pr_debug("alloc ep %p\n", epc); 326ef885dc6SSteve Wise out: 327cfdda9d7SSteve Wise return epc; 328cfdda9d7SSteve Wise } 329cfdda9d7SSteve Wise 330944661ddSHariprasad S static void remove_ep_tid(struct c4iw_ep *ep) 331944661ddSHariprasad S { 332944661ddSHariprasad S unsigned long flags; 333944661ddSHariprasad S 334f254ba6aSMatthew Wilcox xa_lock_irqsave(&ep->com.dev->hwtids, flags); 335f254ba6aSMatthew Wilcox __xa_erase(&ep->com.dev->hwtids, ep->hwtid); 336f254ba6aSMatthew Wilcox if (xa_empty(&ep->com.dev->hwtids)) 33737eb816cSSteve Wise wake_up(&ep->com.dev->wait); 338f254ba6aSMatthew Wilcox xa_unlock_irqrestore(&ep->com.dev->hwtids, flags); 339944661ddSHariprasad S } 340944661ddSHariprasad S 341f254ba6aSMatthew Wilcox static int insert_ep_tid(struct c4iw_ep *ep) 342944661ddSHariprasad S { 343944661ddSHariprasad S unsigned long flags; 344f254ba6aSMatthew Wilcox int err; 345944661ddSHariprasad S 346f254ba6aSMatthew Wilcox xa_lock_irqsave(&ep->com.dev->hwtids, flags); 347f254ba6aSMatthew Wilcox err = __xa_insert(&ep->com.dev->hwtids, ep->hwtid, ep, GFP_KERNEL); 348f254ba6aSMatthew Wilcox xa_unlock_irqrestore(&ep->com.dev->hwtids, flags); 349f254ba6aSMatthew Wilcox 350f254ba6aSMatthew Wilcox return err; 351944661ddSHariprasad S } 352944661ddSHariprasad S 353944661ddSHariprasad S /* 354944661ddSHariprasad S * Atomically lookup the ep ptr given the tid and grab a reference on the ep. 355944661ddSHariprasad S */ 356944661ddSHariprasad S static struct c4iw_ep *get_ep_from_tid(struct c4iw_dev *dev, unsigned int tid) 357944661ddSHariprasad S { 358944661ddSHariprasad S struct c4iw_ep *ep; 359944661ddSHariprasad S unsigned long flags; 360944661ddSHariprasad S 361f254ba6aSMatthew Wilcox xa_lock_irqsave(&dev->hwtids, flags); 362f254ba6aSMatthew Wilcox ep = xa_load(&dev->hwtids, tid); 363944661ddSHariprasad S if (ep) 364944661ddSHariprasad S c4iw_get_ep(&ep->com); 365f254ba6aSMatthew Wilcox xa_unlock_irqrestore(&dev->hwtids, flags); 366944661ddSHariprasad S return ep; 367944661ddSHariprasad S } 368944661ddSHariprasad S 369f86fac79SHariprasad S /* 370f86fac79SHariprasad S * Atomically lookup the ep ptr given the stid and grab a reference on the ep. 371f86fac79SHariprasad S */ 372f86fac79SHariprasad S static struct c4iw_listen_ep *get_ep_from_stid(struct c4iw_dev *dev, 373f86fac79SHariprasad S unsigned int stid) 374f86fac79SHariprasad S { 375f86fac79SHariprasad S struct c4iw_listen_ep *ep; 376f86fac79SHariprasad S unsigned long flags; 377f86fac79SHariprasad S 378401b4480SMatthew Wilcox xa_lock_irqsave(&dev->stids, flags); 379401b4480SMatthew Wilcox ep = xa_load(&dev->stids, stid); 380f86fac79SHariprasad S if (ep) 381f86fac79SHariprasad S c4iw_get_ep(&ep->com); 382401b4480SMatthew Wilcox xa_unlock_irqrestore(&dev->stids, flags); 383f86fac79SHariprasad S return ep; 384f86fac79SHariprasad S } 385f86fac79SHariprasad S 386cfdda9d7SSteve Wise void _c4iw_free_ep(struct kref *kref) 387cfdda9d7SSteve Wise { 388cfdda9d7SSteve Wise struct c4iw_ep *ep; 389cfdda9d7SSteve Wise 390cfdda9d7SSteve Wise ep = container_of(kref, struct c4iw_ep, com.kref); 391548ddb19SBharat Potnuri pr_debug("ep %p state %s\n", ep, states[ep->com.state]); 392325abeadSVipul Pandya if (test_bit(QP_REFERENCED, &ep->com.flags)) 393325abeadSVipul Pandya deref_qp(ep); 394cfdda9d7SSteve Wise if (test_bit(RELEASE_RESOURCES, &ep->com.flags)) { 39584cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 39684cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 39784cc6ac6SHariprasad S (struct sockaddr_in6 *) 398170003c8SSteve Wise &ep->com.local_addr; 39984cc6ac6SHariprasad S 40084cc6ac6SHariprasad S cxgb4_clip_release( 40184cc6ac6SHariprasad S ep->com.dev->rdev.lldi.ports[0], 40284cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 40384cc6ac6SHariprasad S 1); 40484cc6ac6SHariprasad S } 4051dec4cecSGanesh Goudar cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid, 4061dec4cecSGanesh Goudar ep->com.local_addr.ss_family); 407cfdda9d7SSteve Wise dst_release(ep->dst); 408cfdda9d7SSteve Wise cxgb4_l2t_release(ep->l2t); 409c878b706SHariprasad S kfree_skb(ep->mpa_skb); 410cfdda9d7SSteve Wise } 4114a740838SHariprasad S if (!skb_queue_empty(&ep->com.ep_skb_list)) 4124a740838SHariprasad S skb_queue_purge(&ep->com.ep_skb_list); 4132015f26cSSteve Wise c4iw_put_wr_wait(ep->com.wr_waitp); 414cfdda9d7SSteve Wise kfree(ep); 415cfdda9d7SSteve Wise } 416cfdda9d7SSteve Wise 417cfdda9d7SSteve Wise static void release_ep_resources(struct c4iw_ep *ep) 418cfdda9d7SSteve Wise { 419cfdda9d7SSteve Wise set_bit(RELEASE_RESOURCES, &ep->com.flags); 420944661ddSHariprasad S 421944661ddSHariprasad S /* 422944661ddSHariprasad S * If we have a hwtid, then remove it from the idr table 423944661ddSHariprasad S * so lookups will no longer find this endpoint. Otherwise 424944661ddSHariprasad S * we have a race where one thread finds the ep ptr just 425944661ddSHariprasad S * before the other thread is freeing the ep memory. 426944661ddSHariprasad S */ 427944661ddSHariprasad S if (ep->hwtid != -1) 428944661ddSHariprasad S remove_ep_tid(ep); 429cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 430cfdda9d7SSteve Wise } 431cfdda9d7SSteve Wise 432cfdda9d7SSteve Wise static int status2errno(int status) 433cfdda9d7SSteve Wise { 434cfdda9d7SSteve Wise switch (status) { 435cfdda9d7SSteve Wise case CPL_ERR_NONE: 436cfdda9d7SSteve Wise return 0; 437cfdda9d7SSteve Wise case CPL_ERR_CONN_RESET: 438cfdda9d7SSteve Wise return -ECONNRESET; 439cfdda9d7SSteve Wise case CPL_ERR_ARP_MISS: 440cfdda9d7SSteve Wise return -EHOSTUNREACH; 441cfdda9d7SSteve Wise case CPL_ERR_CONN_TIMEDOUT: 442cfdda9d7SSteve Wise return -ETIMEDOUT; 443cfdda9d7SSteve Wise case CPL_ERR_TCAM_FULL: 444cfdda9d7SSteve Wise return -ENOMEM; 445cfdda9d7SSteve Wise case CPL_ERR_CONN_EXIST: 446cfdda9d7SSteve Wise return -EADDRINUSE; 447cfdda9d7SSteve Wise default: 448cfdda9d7SSteve Wise return -EIO; 449cfdda9d7SSteve Wise } 450cfdda9d7SSteve Wise } 451cfdda9d7SSteve Wise 452cfdda9d7SSteve Wise /* 453cfdda9d7SSteve Wise * Try and reuse skbs already allocated... 454cfdda9d7SSteve Wise */ 455cfdda9d7SSteve Wise static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp) 456cfdda9d7SSteve Wise { 457cfdda9d7SSteve Wise if (skb && !skb_is_nonlinear(skb) && !skb_cloned(skb)) { 458cfdda9d7SSteve Wise skb_trim(skb, 0); 459cfdda9d7SSteve Wise skb_get(skb); 460cfdda9d7SSteve Wise skb_reset_transport_header(skb); 461cfdda9d7SSteve Wise } else { 462cfdda9d7SSteve Wise skb = alloc_skb(len, gfp); 463a6d2a5a9SColin Ian King if (!skb) 464a6d2a5a9SColin Ian King return NULL; 465cfdda9d7SSteve Wise } 466b38a0ad8SSteve Wise t4_set_arp_err_handler(skb, NULL, NULL); 467cfdda9d7SSteve Wise return skb; 468cfdda9d7SSteve Wise } 469cfdda9d7SSteve Wise 470830662f6SVipul Pandya static struct net_device *get_real_dev(struct net_device *egress_dev) 471830662f6SVipul Pandya { 47211b8e22dSSteve Wise return rdma_vlan_dev_real_dev(egress_dev) ? : egress_dev; 473830662f6SVipul Pandya } 474830662f6SVipul Pandya 475cfdda9d7SSteve Wise static void arp_failure_discard(void *handle, struct sk_buff *skb) 476cfdda9d7SSteve Wise { 477700456bdSJoe Perches pr_err("ARP failure\n"); 478cfdda9d7SSteve Wise kfree_skb(skb); 479cfdda9d7SSteve Wise } 480cfdda9d7SSteve Wise 48164bec74aSHariprasad S static void mpa_start_arp_failure(void *handle, struct sk_buff *skb) 48264bec74aSHariprasad S { 48364bec74aSHariprasad S pr_err("ARP failure during MPA Negotiation - Closing Connection\n"); 48464bec74aSHariprasad S } 48564bec74aSHariprasad S 4869dec900cSHariprasad S enum { 4878d1f1a6bSHariprasad S NUM_FAKE_CPLS = 2, 4889dec900cSHariprasad S FAKE_CPL_PUT_EP_SAFE = NUM_CPL_CMDS + 0, 4898d1f1a6bSHariprasad S FAKE_CPL_PASS_PUT_EP_SAFE = NUM_CPL_CMDS + 1, 4909dec900cSHariprasad S }; 4919dec900cSHariprasad S 4929dec900cSHariprasad S static int _put_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb) 4939dec900cSHariprasad S { 4949dec900cSHariprasad S struct c4iw_ep *ep; 4959dec900cSHariprasad S 4969dec900cSHariprasad S ep = *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *))); 4979dec900cSHariprasad S release_ep_resources(ep); 4989dec900cSHariprasad S return 0; 4999dec900cSHariprasad S } 5009dec900cSHariprasad S 5018d1f1a6bSHariprasad S static int _put_pass_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb) 5028d1f1a6bSHariprasad S { 5038d1f1a6bSHariprasad S struct c4iw_ep *ep; 5048d1f1a6bSHariprasad S 5058d1f1a6bSHariprasad S ep = *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *))); 5068d1f1a6bSHariprasad S c4iw_put_ep(&ep->parent_ep->com); 5078d1f1a6bSHariprasad S release_ep_resources(ep); 5088d1f1a6bSHariprasad S return 0; 5098d1f1a6bSHariprasad S } 5108d1f1a6bSHariprasad S 5119dec900cSHariprasad S /* 5129dec900cSHariprasad S * Fake up a special CPL opcode and call sched() so process_work() will call 5139dec900cSHariprasad S * _put_ep_safe() in a safe context to free the ep resources. This is needed 5149dec900cSHariprasad S * because ARP error handlers are called in an ATOMIC context, and 5159dec900cSHariprasad S * _c4iw_free_ep() needs to block. 5169dec900cSHariprasad S */ 5178d1f1a6bSHariprasad S static void queue_arp_failure_cpl(struct c4iw_ep *ep, struct sk_buff *skb, 5188d1f1a6bSHariprasad S int cpl) 5199dec900cSHariprasad S { 5209dec900cSHariprasad S struct cpl_act_establish *rpl = cplhdr(skb); 5219dec900cSHariprasad S 5229dec900cSHariprasad S /* Set our special ARP_FAILURE opcode */ 5238d1f1a6bSHariprasad S rpl->ot.opcode = cpl; 5249dec900cSHariprasad S 5259dec900cSHariprasad S /* 5269dec900cSHariprasad S * Save ep in the skb->cb area, after where sched() will save the dev 5279dec900cSHariprasad S * ptr. 5289dec900cSHariprasad S */ 5299dec900cSHariprasad S *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *))) = ep; 5309dec900cSHariprasad S sched(ep->com.dev, skb); 5319dec900cSHariprasad S } 5329dec900cSHariprasad S 5339dec900cSHariprasad S /* Handle an ARP failure for an accept */ 5349dec900cSHariprasad S static void pass_accept_rpl_arp_failure(void *handle, struct sk_buff *skb) 5359dec900cSHariprasad S { 5369dec900cSHariprasad S struct c4iw_ep *ep = handle; 5379dec900cSHariprasad S 538700456bdSJoe Perches pr_err("ARP failure during accept - tid %u - dropping connection\n", 5399dec900cSHariprasad S ep->hwtid); 5409dec900cSHariprasad S 5419dec900cSHariprasad S __state_set(&ep->com, DEAD); 5428d1f1a6bSHariprasad S queue_arp_failure_cpl(ep, skb, FAKE_CPL_PASS_PUT_EP_SAFE); 5439dec900cSHariprasad S } 5449dec900cSHariprasad S 545cfdda9d7SSteve Wise /* 546cfdda9d7SSteve Wise * Handle an ARP failure for an active open. 547cfdda9d7SSteve Wise */ 548cfdda9d7SSteve Wise static void act_open_req_arp_failure(void *handle, struct sk_buff *skb) 549cfdda9d7SSteve Wise { 5505dab6d3aSHariprasad S struct c4iw_ep *ep = handle; 5515dab6d3aSHariprasad S 552700456bdSJoe Perches pr_err("ARP failure during connect\n"); 5535dab6d3aSHariprasad S connect_reply_upcall(ep, -EHOSTUNREACH); 5549dec900cSHariprasad S __state_set(&ep->com, DEAD); 55584cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 55684cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 557170003c8SSteve Wise (struct sockaddr_in6 *)&ep->com.local_addr; 55884cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 55984cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 56084cc6ac6SHariprasad S } 5619f5a9632SMatthew Wilcox xa_erase_irq(&ep->com.dev->atids, ep->atid); 5625dab6d3aSHariprasad S cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid); 5638d1f1a6bSHariprasad S queue_arp_failure_cpl(ep, skb, FAKE_CPL_PUT_EP_SAFE); 564cfdda9d7SSteve Wise } 565cfdda9d7SSteve Wise 566cfdda9d7SSteve Wise /* 567cfdda9d7SSteve Wise * Handle an ARP failure for a CPL_ABORT_REQ. Change it into a no RST variant 568cfdda9d7SSteve Wise * and send it along. 569cfdda9d7SSteve Wise */ 570cfdda9d7SSteve Wise static void abort_arp_failure(void *handle, struct sk_buff *skb) 571cfdda9d7SSteve Wise { 572761e19a5SHariprasad S int ret; 573761e19a5SHariprasad S struct c4iw_ep *ep = handle; 574761e19a5SHariprasad S struct c4iw_rdev *rdev = &ep->com.dev->rdev; 575cfdda9d7SSteve Wise struct cpl_abort_req *req = cplhdr(skb); 576cfdda9d7SSteve Wise 577548ddb19SBharat Potnuri pr_debug("rdev %p\n", rdev); 578cfdda9d7SSteve Wise req->cmd = CPL_ABORT_NO_RST; 5791dad0ebeSRaju Rangoju skb_get(skb); 580761e19a5SHariprasad S ret = c4iw_ofld_send(rdev, skb); 581761e19a5SHariprasad S if (ret) { 582761e19a5SHariprasad S __state_set(&ep->com, DEAD); 583761e19a5SHariprasad S queue_arp_failure_cpl(ep, skb, FAKE_CPL_PUT_EP_SAFE); 5841dad0ebeSRaju Rangoju } else 5851dad0ebeSRaju Rangoju kfree_skb(skb); 586cfdda9d7SSteve Wise } 587cfdda9d7SSteve Wise 5884a740838SHariprasad S static int send_flowc(struct c4iw_ep *ep) 589cfdda9d7SSteve Wise { 590cfdda9d7SSteve Wise struct fw_flowc_wr *flowc; 5914a740838SHariprasad S struct sk_buff *skb = skb_dequeue(&ep->com.ep_skb_list); 592ac8e4c69SHariprasad S u16 vlan = ep->l2t->vlan; 593ac8e4c69SHariprasad S int nparams; 5942e51e45cSPotnuri Bharat Teja int flowclen, flowclen16; 595ac8e4c69SHariprasad S 5964a740838SHariprasad S if (WARN_ON(!skb)) 5974a740838SHariprasad S return -ENOMEM; 5984a740838SHariprasad S 599ac8e4c69SHariprasad S if (vlan == CPL_L2T_VLAN_NONE) 600ac8e4c69SHariprasad S nparams = 9; 6012e51e45cSPotnuri Bharat Teja else 6022e51e45cSPotnuri Bharat Teja nparams = 10; 603cfdda9d7SSteve Wise 6042e51e45cSPotnuri Bharat Teja flowclen = offsetof(struct fw_flowc_wr, mnemval[nparams]); 6052e51e45cSPotnuri Bharat Teja flowclen16 = DIV_ROUND_UP(flowclen, 16); 6062e51e45cSPotnuri Bharat Teja flowclen = flowclen16 * 16; 6072e51e45cSPotnuri Bharat Teja 6082e51e45cSPotnuri Bharat Teja flowc = __skb_put(skb, flowclen); 6092e51e45cSPotnuri Bharat Teja memset(flowc, 0, flowclen); 610cfdda9d7SSteve Wise 611e2ac9628SHariprasad Shenai flowc->op_to_nparams = cpu_to_be32(FW_WR_OP_V(FW_FLOWC_WR) | 612ac8e4c69SHariprasad S FW_FLOWC_WR_NPARAMS_V(nparams)); 6132e51e45cSPotnuri Bharat Teja flowc->flowid_len16 = cpu_to_be32(FW_WR_LEN16_V(flowclen16) | 6142e51e45cSPotnuri Bharat Teja FW_WR_FLOWID_V(ep->hwtid)); 615cfdda9d7SSteve Wise 616cfdda9d7SSteve Wise flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN; 6175167865aSHariprasad Shenai flowc->mnemval[0].val = cpu_to_be32(FW_PFVF_CMD_PFN_V 61835b1de55SHariprasad Shenai (ep->com.dev->rdev.lldi.pf)); 619cfdda9d7SSteve Wise flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH; 620cfdda9d7SSteve Wise flowc->mnemval[1].val = cpu_to_be32(ep->tx_chan); 621cfdda9d7SSteve Wise flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT; 622cfdda9d7SSteve Wise flowc->mnemval[2].val = cpu_to_be32(ep->tx_chan); 623cfdda9d7SSteve Wise flowc->mnemval[3].mnemonic = FW_FLOWC_MNEM_IQID; 624cfdda9d7SSteve Wise flowc->mnemval[3].val = cpu_to_be32(ep->rss_qid); 625cfdda9d7SSteve Wise flowc->mnemval[4].mnemonic = FW_FLOWC_MNEM_SNDNXT; 626cfdda9d7SSteve Wise flowc->mnemval[4].val = cpu_to_be32(ep->snd_seq); 627cfdda9d7SSteve Wise flowc->mnemval[5].mnemonic = FW_FLOWC_MNEM_RCVNXT; 628cfdda9d7SSteve Wise flowc->mnemval[5].val = cpu_to_be32(ep->rcv_seq); 629cfdda9d7SSteve Wise flowc->mnemval[6].mnemonic = FW_FLOWC_MNEM_SNDBUF; 630b408ff28SHariprasad Shenai flowc->mnemval[6].val = cpu_to_be32(ep->snd_win); 631cfdda9d7SSteve Wise flowc->mnemval[7].mnemonic = FW_FLOWC_MNEM_MSS; 632cfdda9d7SSteve Wise flowc->mnemval[7].val = cpu_to_be32(ep->emss); 6332e51e45cSPotnuri Bharat Teja flowc->mnemval[8].mnemonic = FW_FLOWC_MNEM_RCV_SCALE; 6342e51e45cSPotnuri Bharat Teja flowc->mnemval[8].val = cpu_to_be32(ep->snd_wscale); 6352e51e45cSPotnuri Bharat Teja if (nparams == 10) { 636ac8e4c69SHariprasad S u16 pri; 637ac8e4c69SHariprasad S pri = (vlan & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; 6382e51e45cSPotnuri Bharat Teja flowc->mnemval[9].mnemonic = FW_FLOWC_MNEM_SCHEDCLASS; 6392e51e45cSPotnuri Bharat Teja flowc->mnemval[9].val = cpu_to_be32(pri); 640cfdda9d7SSteve Wise } 641cfdda9d7SSteve Wise 642cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 643fef4422dSHariprasad S return c4iw_ofld_send(&ep->com.dev->rdev, skb); 644cfdda9d7SSteve Wise } 645cfdda9d7SSteve Wise 6464a740838SHariprasad S static int send_halfclose(struct c4iw_ep *ep) 647cfdda9d7SSteve Wise { 6484a740838SHariprasad S struct sk_buff *skb = skb_dequeue(&ep->com.ep_skb_list); 64929fb6f42SVarun Prakash u32 wrlen = roundup(sizeof(struct cpl_close_con_req), 16); 650cfdda9d7SSteve Wise 651548ddb19SBharat Potnuri pr_debug("ep %p tid %u\n", ep, ep->hwtid); 6524a740838SHariprasad S if (WARN_ON(!skb)) 653cfdda9d7SSteve Wise return -ENOMEM; 6544a740838SHariprasad S 65529fb6f42SVarun Prakash cxgb_mk_close_con_req(skb, wrlen, ep->hwtid, ep->txq_idx, 65629fb6f42SVarun Prakash NULL, arp_failure_discard); 65729fb6f42SVarun Prakash 658cfdda9d7SSteve Wise return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 659cfdda9d7SSteve Wise } 660cfdda9d7SSteve Wise 6613b8f8b95SWei Yongjun static void read_tcb(struct c4iw_ep *ep) 66211a27e21SRaju Rangoju { 66311a27e21SRaju Rangoju struct sk_buff *skb; 66411a27e21SRaju Rangoju struct cpl_get_tcb *req; 66511a27e21SRaju Rangoju int wrlen = roundup(sizeof(*req), 16); 66611a27e21SRaju Rangoju 66711a27e21SRaju Rangoju skb = get_skb(NULL, sizeof(*req), GFP_KERNEL); 66811a27e21SRaju Rangoju if (WARN_ON(!skb)) 66911a27e21SRaju Rangoju return; 67011a27e21SRaju Rangoju 67111a27e21SRaju Rangoju set_wr_txq(skb, CPL_PRIORITY_CONTROL, ep->ctrlq_idx); 67211a27e21SRaju Rangoju req = (struct cpl_get_tcb *) skb_put(skb, wrlen); 67311a27e21SRaju Rangoju memset(req, 0, wrlen); 67411a27e21SRaju Rangoju INIT_TP_WR(req, ep->hwtid); 67511a27e21SRaju Rangoju OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_GET_TCB, ep->hwtid)); 67611a27e21SRaju Rangoju req->reply_ctrl = htons(REPLY_CHAN_V(0) | QUEUENO_V(ep->rss_qid)); 67711a27e21SRaju Rangoju 67811a27e21SRaju Rangoju /* 67911a27e21SRaju Rangoju * keep a ref on the ep so the tcb is not unlocked before this 68011a27e21SRaju Rangoju * cpl completes. The ref is released in read_tcb_rpl(). 68111a27e21SRaju Rangoju */ 68211a27e21SRaju Rangoju c4iw_get_ep(&ep->com); 68311a27e21SRaju Rangoju if (WARN_ON(c4iw_ofld_send(&ep->com.dev->rdev, skb))) 68411a27e21SRaju Rangoju c4iw_put_ep(&ep->com); 68511a27e21SRaju Rangoju } 68611a27e21SRaju Rangoju 68711a27e21SRaju Rangoju static int send_abort_req(struct c4iw_ep *ep) 688cfdda9d7SSteve Wise { 689a7e1a97fSVarun Prakash u32 wrlen = roundup(sizeof(struct cpl_abort_req), 16); 6904a740838SHariprasad S struct sk_buff *req_skb = skb_dequeue(&ep->com.ep_skb_list); 691cfdda9d7SSteve Wise 692548ddb19SBharat Potnuri pr_debug("ep %p tid %u\n", ep, ep->hwtid); 6934a740838SHariprasad S if (WARN_ON(!req_skb)) 694cfdda9d7SSteve Wise return -ENOMEM; 6954a740838SHariprasad S 696a7e1a97fSVarun Prakash cxgb_mk_abort_req(req_skb, wrlen, ep->hwtid, ep->txq_idx, 697a7e1a97fSVarun Prakash ep, abort_arp_failure); 698a7e1a97fSVarun Prakash 6994a740838SHariprasad S return c4iw_l2t_send(&ep->com.dev->rdev, req_skb, ep->l2t); 700cfdda9d7SSteve Wise } 701cfdda9d7SSteve Wise 70211a27e21SRaju Rangoju static int send_abort(struct c4iw_ep *ep) 70311a27e21SRaju Rangoju { 70411a27e21SRaju Rangoju if (!ep->com.qp || !ep->com.qp->srq) { 70511a27e21SRaju Rangoju send_abort_req(ep); 70611a27e21SRaju Rangoju return 0; 70711a27e21SRaju Rangoju } 70811a27e21SRaju Rangoju set_bit(ABORT_REQ_IN_PROGRESS, &ep->com.flags); 70911a27e21SRaju Rangoju read_tcb(ep); 71011a27e21SRaju Rangoju return 0; 71111a27e21SRaju Rangoju } 71211a27e21SRaju Rangoju 713cfdda9d7SSteve Wise static int send_connect(struct c4iw_ep *ep) 714cfdda9d7SSteve Wise { 715963cab50SHariprasad S struct cpl_act_open_req *req = NULL; 716963cab50SHariprasad S struct cpl_t5_act_open_req *t5req = NULL; 717963cab50SHariprasad S struct cpl_t6_act_open_req *t6req = NULL; 718963cab50SHariprasad S struct cpl_act_open_req6 *req6 = NULL; 719963cab50SHariprasad S struct cpl_t5_act_open_req6 *t5req6 = NULL; 720963cab50SHariprasad S struct cpl_t6_act_open_req6 *t6req6 = NULL; 721cfdda9d7SSteve Wise struct sk_buff *skb; 722cfdda9d7SSteve Wise u64 opt0; 723cfdda9d7SSteve Wise u32 opt2; 724cfdda9d7SSteve Wise unsigned int mtu_idx; 725cc516700SVarun Prakash u32 wscale; 726963cab50SHariprasad S int win, sizev4, sizev6, wrlen; 7279eccfe10SSteve Wise struct sockaddr_in *la = (struct sockaddr_in *) 728170003c8SSteve Wise &ep->com.local_addr; 7299eccfe10SSteve Wise struct sockaddr_in *ra = (struct sockaddr_in *) 730170003c8SSteve Wise &ep->com.remote_addr; 7319eccfe10SSteve Wise struct sockaddr_in6 *la6 = (struct sockaddr_in6 *) 732170003c8SSteve Wise &ep->com.local_addr; 7339eccfe10SSteve Wise struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *) 734170003c8SSteve Wise &ep->com.remote_addr; 73584cc6ac6SHariprasad S int ret; 736963cab50SHariprasad S enum chip_type adapter_type = ep->com.dev->rdev.lldi.adapter_type; 737a251c17aSJason A. Donenfeld u32 isn = (get_random_u32() & ~7UL) - 1; 738192539f4SGanesh Goudar struct net_device *netdev; 739192539f4SGanesh Goudar u64 params; 740192539f4SGanesh Goudar 741192539f4SGanesh Goudar netdev = ep->com.dev->rdev.lldi.ports[0]; 742963cab50SHariprasad S 743963cab50SHariprasad S switch (CHELSIO_CHIP_VERSION(adapter_type)) { 744963cab50SHariprasad S case CHELSIO_T4: 745963cab50SHariprasad S sizev4 = sizeof(struct cpl_act_open_req); 746963cab50SHariprasad S sizev6 = sizeof(struct cpl_act_open_req6); 747963cab50SHariprasad S break; 748963cab50SHariprasad S case CHELSIO_T5: 749963cab50SHariprasad S sizev4 = sizeof(struct cpl_t5_act_open_req); 750963cab50SHariprasad S sizev6 = sizeof(struct cpl_t5_act_open_req6); 751963cab50SHariprasad S break; 752963cab50SHariprasad S case CHELSIO_T6: 753963cab50SHariprasad S sizev4 = sizeof(struct cpl_t6_act_open_req); 754963cab50SHariprasad S sizev6 = sizeof(struct cpl_t6_act_open_req6); 755963cab50SHariprasad S break; 756963cab50SHariprasad S default: 757963cab50SHariprasad S pr_err("T%d Chip is not supported\n", 758963cab50SHariprasad S CHELSIO_CHIP_VERSION(adapter_type)); 759963cab50SHariprasad S return -EINVAL; 760963cab50SHariprasad S } 761830662f6SVipul Pandya 762830662f6SVipul Pandya wrlen = (ep->com.remote_addr.ss_family == AF_INET) ? 763830662f6SVipul Pandya roundup(sizev4, 16) : 764830662f6SVipul Pandya roundup(sizev6, 16); 765cfdda9d7SSteve Wise 766548ddb19SBharat Potnuri pr_debug("ep %p atid %u\n", ep, ep->atid); 767cfdda9d7SSteve Wise 768cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 769cfdda9d7SSteve Wise if (!skb) { 770700456bdSJoe Perches pr_err("%s - failed to alloc skb\n", __func__); 771cfdda9d7SSteve Wise return -ENOMEM; 772cfdda9d7SSteve Wise } 773d4f1a5c6SSteve Wise set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->ctrlq_idx); 774cfdda9d7SSteve Wise 77544c6d069SVarun Prakash cxgb_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, 77604524a47SHariprasad S enable_tcp_timestamps, 77744c6d069SVarun Prakash (ep->com.remote_addr.ss_family == AF_INET) ? 0 : 1); 778cc516700SVarun Prakash wscale = cxgb_compute_wscale(rcv_win); 779b408ff28SHariprasad Shenai 780b408ff28SHariprasad Shenai /* 781b408ff28SHariprasad Shenai * Specify the largest window that will fit in opt0. The 782b408ff28SHariprasad Shenai * remainder will be specified in the rx_data_ack. 783b408ff28SHariprasad Shenai */ 784b408ff28SHariprasad Shenai win = ep->rcv_win >> 10; 785d7990b0cSAnish Bhatt if (win > RCV_BUFSIZ_M) 786d7990b0cSAnish Bhatt win = RCV_BUFSIZ_M; 787b408ff28SHariprasad Shenai 7886c53e938SHariprasad Shenai opt0 = (nocong ? NO_CONG_F : 0) | 789d7990b0cSAnish Bhatt KEEP_ALIVE_F | 7906c53e938SHariprasad Shenai DELACK_F | 791d7990b0cSAnish Bhatt WND_SCALE_V(wscale) | 792d7990b0cSAnish Bhatt MSS_IDX_V(mtu_idx) | 793d7990b0cSAnish Bhatt L2T_IDX_V(ep->l2t->idx) | 794d7990b0cSAnish Bhatt TX_CHAN_V(ep->tx_chan) | 795d7990b0cSAnish Bhatt SMAC_SEL_V(ep->smac_idx) | 796ac8e4c69SHariprasad S DSCP_V(ep->tos >> 2) | 797d7990b0cSAnish Bhatt ULP_MODE_V(ULP_MODE_TCPDDP) | 798d7990b0cSAnish Bhatt RCV_BUFSIZ_V(win); 799d7990b0cSAnish Bhatt opt2 = RX_CHANNEL_V(0) | 8006c53e938SHariprasad Shenai CCTRL_ECN_V(enable_ecn) | 801d7990b0cSAnish Bhatt RSS_QUEUE_VALID_F | RSS_QUEUE_V(ep->rss_qid); 802cfdda9d7SSteve Wise if (enable_tcp_timestamps) 8036c53e938SHariprasad Shenai opt2 |= TSTAMPS_EN_F; 804cfdda9d7SSteve Wise if (enable_tcp_sack) 8056c53e938SHariprasad Shenai opt2 |= SACK_EN_F; 806cfdda9d7SSteve Wise if (wscale && enable_tcp_window_scaling) 807d7990b0cSAnish Bhatt opt2 |= WND_SCALE_EN_F; 808963cab50SHariprasad S if (CHELSIO_CHIP_VERSION(adapter_type) > CHELSIO_T4) { 809963cab50SHariprasad S if (peer2peer) 810963cab50SHariprasad S isn += 4; 811963cab50SHariprasad S 812d7990b0cSAnish Bhatt opt2 |= T5_OPT_2_VALID_F; 813cf7fe64aSHariprasad Shenai opt2 |= CONG_CNTRL_V(CONG_ALG_TAHOE); 8140b741047SHariprasad S opt2 |= T5_ISS_F; 81592e5011aSSteve Wise } 81684cc6ac6SHariprasad S 817192539f4SGanesh Goudar params = cxgb4_select_ntuple(netdev, ep->l2t); 818192539f4SGanesh Goudar 81984cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) 82084cc6ac6SHariprasad S cxgb4_clip_get(ep->com.dev->rdev.lldi.ports[0], 82184cc6ac6SHariprasad S (const u32 *)&la6->sin6_addr.s6_addr, 1); 82284cc6ac6SHariprasad S 8235dab6d3aSHariprasad S t4_set_arp_err_handler(skb, ep, act_open_req_arp_failure); 824cfdda9d7SSteve Wise 825830662f6SVipul Pandya if (ep->com.remote_addr.ss_family == AF_INET) { 826963cab50SHariprasad S switch (CHELSIO_CHIP_VERSION(adapter_type)) { 827963cab50SHariprasad S case CHELSIO_T4: 8284df864c1SJohannes Berg req = skb_put(skb, wrlen); 829cfdda9d7SSteve Wise INIT_TP_WR(req, 0); 830963cab50SHariprasad S break; 831963cab50SHariprasad S case CHELSIO_T5: 8324df864c1SJohannes Berg t5req = skb_put(skb, wrlen); 833963cab50SHariprasad S INIT_TP_WR(t5req, 0); 834963cab50SHariprasad S req = (struct cpl_act_open_req *)t5req; 835963cab50SHariprasad S break; 836963cab50SHariprasad S case CHELSIO_T6: 8374df864c1SJohannes Berg t6req = skb_put(skb, wrlen); 838963cab50SHariprasad S INIT_TP_WR(t6req, 0); 839963cab50SHariprasad S req = (struct cpl_act_open_req *)t6req; 840963cab50SHariprasad S t5req = (struct cpl_t5_act_open_req *)t6req; 841963cab50SHariprasad S break; 842963cab50SHariprasad S default: 843963cab50SHariprasad S pr_err("T%d Chip is not supported\n", 844963cab50SHariprasad S CHELSIO_CHIP_VERSION(adapter_type)); 845963cab50SHariprasad S ret = -EINVAL; 846963cab50SHariprasad S goto clip_release; 847963cab50SHariprasad S } 848963cab50SHariprasad S 849963cab50SHariprasad S OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, 850f079af7aSVipul Pandya ((ep->rss_qid<<14) | ep->atid))); 851830662f6SVipul Pandya req->local_port = la->sin_port; 852830662f6SVipul Pandya req->peer_port = ra->sin_port; 853830662f6SVipul Pandya req->local_ip = la->sin_addr.s_addr; 854830662f6SVipul Pandya req->peer_ip = ra->sin_addr.s_addr; 855cfdda9d7SSteve Wise req->opt0 = cpu_to_be64(opt0); 856963cab50SHariprasad S 857963cab50SHariprasad S if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) { 858192539f4SGanesh Goudar req->params = cpu_to_be32(params); 859cfdda9d7SSteve Wise req->opt2 = cpu_to_be32(opt2); 860f079af7aSVipul Pandya } else { 861192539f4SGanesh Goudar if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) { 862192539f4SGanesh Goudar t5req->params = 863192539f4SGanesh Goudar cpu_to_be64(FILTER_TUPLE_V(params)); 864963cab50SHariprasad S t5req->rsvd = cpu_to_be32(isn); 865548ddb19SBharat Potnuri pr_debug("snd_isn %u\n", t5req->rsvd); 866963cab50SHariprasad S t5req->opt2 = cpu_to_be32(opt2); 867192539f4SGanesh Goudar } else { 868192539f4SGanesh Goudar t6req->params = 869192539f4SGanesh Goudar cpu_to_be64(FILTER_TUPLE_V(params)); 870192539f4SGanesh Goudar t6req->rsvd = cpu_to_be32(isn); 871548ddb19SBharat Potnuri pr_debug("snd_isn %u\n", t6req->rsvd); 872192539f4SGanesh Goudar t6req->opt2 = cpu_to_be32(opt2); 873192539f4SGanesh Goudar } 874963cab50SHariprasad S } 875963cab50SHariprasad S } else { 876963cab50SHariprasad S switch (CHELSIO_CHIP_VERSION(adapter_type)) { 877963cab50SHariprasad S case CHELSIO_T4: 8784df864c1SJohannes Berg req6 = skb_put(skb, wrlen); 879830662f6SVipul Pandya INIT_TP_WR(req6, 0); 880963cab50SHariprasad S break; 881963cab50SHariprasad S case CHELSIO_T5: 8824df864c1SJohannes Berg t5req6 = skb_put(skb, wrlen); 883963cab50SHariprasad S INIT_TP_WR(t5req6, 0); 884963cab50SHariprasad S req6 = (struct cpl_act_open_req6 *)t5req6; 885963cab50SHariprasad S break; 886963cab50SHariprasad S case CHELSIO_T6: 8874df864c1SJohannes Berg t6req6 = skb_put(skb, wrlen); 888963cab50SHariprasad S INIT_TP_WR(t6req6, 0); 889963cab50SHariprasad S req6 = (struct cpl_act_open_req6 *)t6req6; 890963cab50SHariprasad S t5req6 = (struct cpl_t5_act_open_req6 *)t6req6; 891963cab50SHariprasad S break; 892963cab50SHariprasad S default: 893963cab50SHariprasad S pr_err("T%d Chip is not supported\n", 894963cab50SHariprasad S CHELSIO_CHIP_VERSION(adapter_type)); 895963cab50SHariprasad S ret = -EINVAL; 896963cab50SHariprasad S goto clip_release; 897963cab50SHariprasad S } 898963cab50SHariprasad S 899963cab50SHariprasad S OPCODE_TID(req6) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ6, 900830662f6SVipul Pandya ((ep->rss_qid<<14)|ep->atid))); 901830662f6SVipul Pandya req6->local_port = la6->sin6_port; 902830662f6SVipul Pandya req6->peer_port = ra6->sin6_port; 903963cab50SHariprasad S req6->local_ip_hi = *((__be64 *)(la6->sin6_addr.s6_addr)); 904963cab50SHariprasad S req6->local_ip_lo = *((__be64 *)(la6->sin6_addr.s6_addr + 8)); 905963cab50SHariprasad S req6->peer_ip_hi = *((__be64 *)(ra6->sin6_addr.s6_addr)); 906963cab50SHariprasad S req6->peer_ip_lo = *((__be64 *)(ra6->sin6_addr.s6_addr + 8)); 907830662f6SVipul Pandya req6->opt0 = cpu_to_be64(opt0); 908963cab50SHariprasad S 909963cab50SHariprasad S if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) { 910192539f4SGanesh Goudar req6->params = cpu_to_be32(cxgb4_select_ntuple(netdev, 911830662f6SVipul Pandya ep->l2t)); 912830662f6SVipul Pandya req6->opt2 = cpu_to_be32(opt2); 913830662f6SVipul Pandya } else { 914192539f4SGanesh Goudar if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) { 915192539f4SGanesh Goudar t5req6->params = 916192539f4SGanesh Goudar cpu_to_be64(FILTER_TUPLE_V(params)); 917963cab50SHariprasad S t5req6->rsvd = cpu_to_be32(isn); 918548ddb19SBharat Potnuri pr_debug("snd_isn %u\n", t5req6->rsvd); 919963cab50SHariprasad S t5req6->opt2 = cpu_to_be32(opt2); 920192539f4SGanesh Goudar } else { 921192539f4SGanesh Goudar t6req6->params = 922192539f4SGanesh Goudar cpu_to_be64(FILTER_TUPLE_V(params)); 923192539f4SGanesh Goudar t6req6->rsvd = cpu_to_be32(isn); 924548ddb19SBharat Potnuri pr_debug("snd_isn %u\n", t6req6->rsvd); 925192539f4SGanesh Goudar t6req6->opt2 = cpu_to_be32(opt2); 926192539f4SGanesh Goudar } 927192539f4SGanesh Goudar 928830662f6SVipul Pandya } 929f079af7aSVipul Pandya } 930f079af7aSVipul Pandya 931793dad94SVipul Pandya set_bit(ACT_OPEN_REQ, &ep->com.history); 93284cc6ac6SHariprasad S ret = c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 933963cab50SHariprasad S clip_release: 93484cc6ac6SHariprasad S if (ret && ep->com.remote_addr.ss_family == AF_INET6) 93584cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 93684cc6ac6SHariprasad S (const u32 *)&la6->sin6_addr.s6_addr, 1); 93784cc6ac6SHariprasad S return ret; 938cfdda9d7SSteve Wise } 939cfdda9d7SSteve Wise 940caa6c9f2SHariprasad S static int send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb, 941d2fe99e8SKumar Sanghvi u8 mpa_rev_to_use) 942cfdda9d7SSteve Wise { 943caa6c9f2SHariprasad S int mpalen, wrlen, ret; 944cfdda9d7SSteve Wise struct fw_ofld_tx_data_wr *req; 945cfdda9d7SSteve Wise struct mpa_message *mpa; 946d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params mpa_v2_params; 947cfdda9d7SSteve Wise 948548ddb19SBharat Potnuri pr_debug("ep %p tid %u pd_len %d\n", 949548ddb19SBharat Potnuri ep, ep->hwtid, ep->plen); 950cfdda9d7SSteve Wise 951cfdda9d7SSteve Wise mpalen = sizeof(*mpa) + ep->plen; 952d2fe99e8SKumar Sanghvi if (mpa_rev_to_use == 2) 953d2fe99e8SKumar Sanghvi mpalen += sizeof(struct mpa_v2_conn_params); 95434d56893SLeon Romanovsky wrlen = roundup(mpalen + sizeof(*req), 16); 955cfdda9d7SSteve Wise skb = get_skb(skb, wrlen, GFP_KERNEL); 956cfdda9d7SSteve Wise if (!skb) { 957cfdda9d7SSteve Wise connect_reply_upcall(ep, -ENOMEM); 958caa6c9f2SHariprasad S return -ENOMEM; 959cfdda9d7SSteve Wise } 960cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 961cfdda9d7SSteve Wise 962b080db58SJohannes Berg req = skb_put_zero(skb, wrlen); 963cfdda9d7SSteve Wise req->op_to_immdlen = cpu_to_be32( 964e2ac9628SHariprasad Shenai FW_WR_OP_V(FW_OFLD_TX_DATA_WR) | 965e2ac9628SHariprasad Shenai FW_WR_COMPL_F | 966e2ac9628SHariprasad Shenai FW_WR_IMMDLEN_V(mpalen)); 967cfdda9d7SSteve Wise req->flowid_len16 = cpu_to_be32( 968e2ac9628SHariprasad Shenai FW_WR_FLOWID_V(ep->hwtid) | 969e2ac9628SHariprasad Shenai FW_WR_LEN16_V(wrlen >> 4)); 970cfdda9d7SSteve Wise req->plen = cpu_to_be32(mpalen); 971cfdda9d7SSteve Wise req->tunnel_to_proxy = cpu_to_be32( 972e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_FLUSH_F | 973e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_SHOVE_F); 974cfdda9d7SSteve Wise 975cfdda9d7SSteve Wise mpa = (struct mpa_message *)(req + 1); 976cfdda9d7SSteve Wise memcpy(mpa->key, MPA_KEY_REQ, sizeof(mpa->key)); 9773d4e7994SHariprasad S 9783d4e7994SHariprasad S mpa->flags = 0; 9793d4e7994SHariprasad S if (crc_enabled) 9803d4e7994SHariprasad S mpa->flags |= MPA_CRC; 9813d4e7994SHariprasad S if (markers_enabled) { 9823d4e7994SHariprasad S mpa->flags |= MPA_MARKERS; 9833d4e7994SHariprasad S ep->mpa_attr.recv_marker_enabled = 1; 9843d4e7994SHariprasad S } else { 9853d4e7994SHariprasad S ep->mpa_attr.recv_marker_enabled = 0; 9863d4e7994SHariprasad S } 9873d4e7994SHariprasad S if (mpa_rev_to_use == 2) 9883d4e7994SHariprasad S mpa->flags |= MPA_ENHANCED_RDMA_CONN; 9893d4e7994SHariprasad S 990cfdda9d7SSteve Wise mpa->private_data_size = htons(ep->plen); 991d2fe99e8SKumar Sanghvi mpa->revision = mpa_rev_to_use; 99201b225e1SKumar Sanghvi if (mpa_rev_to_use == 1) { 993d2fe99e8SKumar Sanghvi ep->tried_with_mpa_v1 = 1; 99401b225e1SKumar Sanghvi ep->retry_with_mpa_v1 = 0; 99501b225e1SKumar Sanghvi } 996d2fe99e8SKumar Sanghvi 997d2fe99e8SKumar Sanghvi if (mpa_rev_to_use == 2) { 99834d56893SLeon Romanovsky mpa->private_data_size = 99934d56893SLeon Romanovsky htons(ntohs(mpa->private_data_size) + 1000f747c34aSRoland Dreier sizeof(struct mpa_v2_conn_params)); 1001548ddb19SBharat Potnuri pr_debug("initiator ird %u ord %u\n", ep->ird, 10024c2c5763SHariprasad Shenai ep->ord); 1003d2fe99e8SKumar Sanghvi mpa_v2_params.ird = htons((u16)ep->ird); 1004d2fe99e8SKumar Sanghvi mpa_v2_params.ord = htons((u16)ep->ord); 1005d2fe99e8SKumar Sanghvi 1006d2fe99e8SKumar Sanghvi if (peer2peer) { 1007d2fe99e8SKumar Sanghvi mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL); 1008d2fe99e8SKumar Sanghvi if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE) 1009d2fe99e8SKumar Sanghvi mpa_v2_params.ord |= 1010d2fe99e8SKumar Sanghvi htons(MPA_V2_RDMA_WRITE_RTR); 1011d2fe99e8SKumar Sanghvi else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) 1012d2fe99e8SKumar Sanghvi mpa_v2_params.ord |= 1013d2fe99e8SKumar Sanghvi htons(MPA_V2_RDMA_READ_RTR); 1014d2fe99e8SKumar Sanghvi } 1015d2fe99e8SKumar Sanghvi memcpy(mpa->private_data, &mpa_v2_params, 1016d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params)); 1017cfdda9d7SSteve Wise 1018cfdda9d7SSteve Wise if (ep->plen) 1019d2fe99e8SKumar Sanghvi memcpy(mpa->private_data + 1020d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params), 1021d2fe99e8SKumar Sanghvi ep->mpa_pkt + sizeof(*mpa), ep->plen); 1022d2fe99e8SKumar Sanghvi } else 1023d2fe99e8SKumar Sanghvi if (ep->plen) 1024d2fe99e8SKumar Sanghvi memcpy(mpa->private_data, 1025d2fe99e8SKumar Sanghvi ep->mpa_pkt + sizeof(*mpa), ep->plen); 1026cfdda9d7SSteve Wise 1027cfdda9d7SSteve Wise /* 1028cfdda9d7SSteve Wise * Reference the mpa skb. This ensures the data area 1029cfdda9d7SSteve Wise * will remain in memory until the hw acks the tx. 1030cfdda9d7SSteve Wise * Function fw4_ack() will deref it. 1031cfdda9d7SSteve Wise */ 1032cfdda9d7SSteve Wise skb_get(skb); 1033cfdda9d7SSteve Wise t4_set_arp_err_handler(skb, NULL, arp_failure_discard); 1034cfdda9d7SSteve Wise ep->mpa_skb = skb; 1035caa6c9f2SHariprasad S ret = c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 1036caa6c9f2SHariprasad S if (ret) 1037caa6c9f2SHariprasad S return ret; 1038cfdda9d7SSteve Wise start_ep_timer(ep); 1039a7db89ebSSteve Wise __state_set(&ep->com, MPA_REQ_SENT); 1040cfdda9d7SSteve Wise ep->mpa_attr.initiator = 1; 10419c88aa00SSteve Wise ep->snd_seq += mpalen; 1042caa6c9f2SHariprasad S return ret; 1043cfdda9d7SSteve Wise } 1044cfdda9d7SSteve Wise 1045cfdda9d7SSteve Wise static int send_mpa_reject(struct c4iw_ep *ep, const void *pdata, u8 plen) 1046cfdda9d7SSteve Wise { 1047cfdda9d7SSteve Wise int mpalen, wrlen; 1048cfdda9d7SSteve Wise struct fw_ofld_tx_data_wr *req; 1049cfdda9d7SSteve Wise struct mpa_message *mpa; 1050cfdda9d7SSteve Wise struct sk_buff *skb; 1051d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params mpa_v2_params; 1052cfdda9d7SSteve Wise 1053548ddb19SBharat Potnuri pr_debug("ep %p tid %u pd_len %d\n", 1054548ddb19SBharat Potnuri ep, ep->hwtid, ep->plen); 1055cfdda9d7SSteve Wise 1056cfdda9d7SSteve Wise mpalen = sizeof(*mpa) + plen; 1057d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) 1058d2fe99e8SKumar Sanghvi mpalen += sizeof(struct mpa_v2_conn_params); 105934d56893SLeon Romanovsky wrlen = roundup(mpalen + sizeof(*req), 16); 1060cfdda9d7SSteve Wise 1061cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 1062cfdda9d7SSteve Wise if (!skb) { 1063700456bdSJoe Perches pr_err("%s - cannot alloc skb!\n", __func__); 1064cfdda9d7SSteve Wise return -ENOMEM; 1065cfdda9d7SSteve Wise } 1066cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 1067cfdda9d7SSteve Wise 1068b080db58SJohannes Berg req = skb_put_zero(skb, wrlen); 1069cfdda9d7SSteve Wise req->op_to_immdlen = cpu_to_be32( 1070e2ac9628SHariprasad Shenai FW_WR_OP_V(FW_OFLD_TX_DATA_WR) | 1071e2ac9628SHariprasad Shenai FW_WR_COMPL_F | 1072e2ac9628SHariprasad Shenai FW_WR_IMMDLEN_V(mpalen)); 1073cfdda9d7SSteve Wise req->flowid_len16 = cpu_to_be32( 1074e2ac9628SHariprasad Shenai FW_WR_FLOWID_V(ep->hwtid) | 1075e2ac9628SHariprasad Shenai FW_WR_LEN16_V(wrlen >> 4)); 1076cfdda9d7SSteve Wise req->plen = cpu_to_be32(mpalen); 1077cfdda9d7SSteve Wise req->tunnel_to_proxy = cpu_to_be32( 1078e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_FLUSH_F | 1079e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_SHOVE_F); 1080cfdda9d7SSteve Wise 1081cfdda9d7SSteve Wise mpa = (struct mpa_message *)(req + 1); 1082cfdda9d7SSteve Wise memset(mpa, 0, sizeof(*mpa)); 1083cfdda9d7SSteve Wise memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key)); 1084cfdda9d7SSteve Wise mpa->flags = MPA_REJECT; 1085fe7e0a4dSVipul Pandya mpa->revision = ep->mpa_attr.version; 1086cfdda9d7SSteve Wise mpa->private_data_size = htons(plen); 1087d2fe99e8SKumar Sanghvi 1088d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 1089d2fe99e8SKumar Sanghvi mpa->flags |= MPA_ENHANCED_RDMA_CONN; 109034d56893SLeon Romanovsky mpa->private_data_size = 109134d56893SLeon Romanovsky htons(ntohs(mpa->private_data_size) + 1092f747c34aSRoland Dreier sizeof(struct mpa_v2_conn_params)); 1093d2fe99e8SKumar Sanghvi mpa_v2_params.ird = htons(((u16)ep->ird) | 1094d2fe99e8SKumar Sanghvi (peer2peer ? MPA_V2_PEER2PEER_MODEL : 1095d2fe99e8SKumar Sanghvi 0)); 1096d2fe99e8SKumar Sanghvi mpa_v2_params.ord = htons(((u16)ep->ord) | (peer2peer ? 1097d2fe99e8SKumar Sanghvi (p2p_type == 1098d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_RDMA_WRITE ? 1099d2fe99e8SKumar Sanghvi MPA_V2_RDMA_WRITE_RTR : p2p_type == 1100d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_READ_REQ ? 1101d2fe99e8SKumar Sanghvi MPA_V2_RDMA_READ_RTR : 0) : 0)); 1102d2fe99e8SKumar Sanghvi memcpy(mpa->private_data, &mpa_v2_params, 1103d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params)); 1104d2fe99e8SKumar Sanghvi 1105d2fe99e8SKumar Sanghvi if (ep->plen) 1106d2fe99e8SKumar Sanghvi memcpy(mpa->private_data + 1107d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params), pdata, plen); 1108d2fe99e8SKumar Sanghvi } else 1109cfdda9d7SSteve Wise if (plen) 1110cfdda9d7SSteve Wise memcpy(mpa->private_data, pdata, plen); 1111cfdda9d7SSteve Wise 1112cfdda9d7SSteve Wise /* 1113cfdda9d7SSteve Wise * Reference the mpa skb again. This ensures the data area 1114cfdda9d7SSteve Wise * will remain in memory until the hw acks the tx. 1115cfdda9d7SSteve Wise * Function fw4_ack() will deref it. 1116cfdda9d7SSteve Wise */ 1117cfdda9d7SSteve Wise skb_get(skb); 1118cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 111964bec74aSHariprasad S t4_set_arp_err_handler(skb, NULL, mpa_start_arp_failure); 1120cfdda9d7SSteve Wise ep->mpa_skb = skb; 11219c88aa00SSteve Wise ep->snd_seq += mpalen; 1122cfdda9d7SSteve Wise return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 1123cfdda9d7SSteve Wise } 1124cfdda9d7SSteve Wise 1125cfdda9d7SSteve Wise static int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen) 1126cfdda9d7SSteve Wise { 1127cfdda9d7SSteve Wise int mpalen, wrlen; 1128cfdda9d7SSteve Wise struct fw_ofld_tx_data_wr *req; 1129cfdda9d7SSteve Wise struct mpa_message *mpa; 1130cfdda9d7SSteve Wise struct sk_buff *skb; 1131d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params mpa_v2_params; 1132cfdda9d7SSteve Wise 1133548ddb19SBharat Potnuri pr_debug("ep %p tid %u pd_len %d\n", 1134548ddb19SBharat Potnuri ep, ep->hwtid, ep->plen); 1135cfdda9d7SSteve Wise 1136cfdda9d7SSteve Wise mpalen = sizeof(*mpa) + plen; 1137d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) 1138d2fe99e8SKumar Sanghvi mpalen += sizeof(struct mpa_v2_conn_params); 113934d56893SLeon Romanovsky wrlen = roundup(mpalen + sizeof(*req), 16); 1140cfdda9d7SSteve Wise 1141cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 1142cfdda9d7SSteve Wise if (!skb) { 1143700456bdSJoe Perches pr_err("%s - cannot alloc skb!\n", __func__); 1144cfdda9d7SSteve Wise return -ENOMEM; 1145cfdda9d7SSteve Wise } 1146cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 1147cfdda9d7SSteve Wise 1148b080db58SJohannes Berg req = skb_put_zero(skb, wrlen); 1149cfdda9d7SSteve Wise req->op_to_immdlen = cpu_to_be32( 1150e2ac9628SHariprasad Shenai FW_WR_OP_V(FW_OFLD_TX_DATA_WR) | 1151e2ac9628SHariprasad Shenai FW_WR_COMPL_F | 1152e2ac9628SHariprasad Shenai FW_WR_IMMDLEN_V(mpalen)); 1153cfdda9d7SSteve Wise req->flowid_len16 = cpu_to_be32( 1154e2ac9628SHariprasad Shenai FW_WR_FLOWID_V(ep->hwtid) | 1155e2ac9628SHariprasad Shenai FW_WR_LEN16_V(wrlen >> 4)); 1156cfdda9d7SSteve Wise req->plen = cpu_to_be32(mpalen); 1157cfdda9d7SSteve Wise req->tunnel_to_proxy = cpu_to_be32( 1158e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_FLUSH_F | 1159e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_SHOVE_F); 1160cfdda9d7SSteve Wise 1161cfdda9d7SSteve Wise mpa = (struct mpa_message *)(req + 1); 1162cfdda9d7SSteve Wise memset(mpa, 0, sizeof(*mpa)); 1163cfdda9d7SSteve Wise memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key)); 11643d4e7994SHariprasad S mpa->flags = 0; 11653d4e7994SHariprasad S if (ep->mpa_attr.crc_enabled) 11663d4e7994SHariprasad S mpa->flags |= MPA_CRC; 11673d4e7994SHariprasad S if (ep->mpa_attr.recv_marker_enabled) 11683d4e7994SHariprasad S mpa->flags |= MPA_MARKERS; 1169d2fe99e8SKumar Sanghvi mpa->revision = ep->mpa_attr.version; 1170cfdda9d7SSteve Wise mpa->private_data_size = htons(plen); 1171d2fe99e8SKumar Sanghvi 1172d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 1173d2fe99e8SKumar Sanghvi mpa->flags |= MPA_ENHANCED_RDMA_CONN; 117434d56893SLeon Romanovsky mpa->private_data_size = 117534d56893SLeon Romanovsky htons(ntohs(mpa->private_data_size) + 1176f747c34aSRoland Dreier sizeof(struct mpa_v2_conn_params)); 1177d2fe99e8SKumar Sanghvi mpa_v2_params.ird = htons((u16)ep->ird); 1178d2fe99e8SKumar Sanghvi mpa_v2_params.ord = htons((u16)ep->ord); 1179d2fe99e8SKumar Sanghvi if (peer2peer && (ep->mpa_attr.p2p_type != 1180d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_DISABLED)) { 1181d2fe99e8SKumar Sanghvi mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL); 1182d2fe99e8SKumar Sanghvi 1183d2fe99e8SKumar Sanghvi if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE) 1184d2fe99e8SKumar Sanghvi mpa_v2_params.ord |= 1185d2fe99e8SKumar Sanghvi htons(MPA_V2_RDMA_WRITE_RTR); 1186d2fe99e8SKumar Sanghvi else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) 1187d2fe99e8SKumar Sanghvi mpa_v2_params.ord |= 1188d2fe99e8SKumar Sanghvi htons(MPA_V2_RDMA_READ_RTR); 1189d2fe99e8SKumar Sanghvi } 1190d2fe99e8SKumar Sanghvi 1191d2fe99e8SKumar Sanghvi memcpy(mpa->private_data, &mpa_v2_params, 1192d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params)); 1193d2fe99e8SKumar Sanghvi 1194d2fe99e8SKumar Sanghvi if (ep->plen) 1195d2fe99e8SKumar Sanghvi memcpy(mpa->private_data + 1196d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params), pdata, plen); 1197d2fe99e8SKumar Sanghvi } else 1198cfdda9d7SSteve Wise if (plen) 1199cfdda9d7SSteve Wise memcpy(mpa->private_data, pdata, plen); 1200cfdda9d7SSteve Wise 1201cfdda9d7SSteve Wise /* 1202cfdda9d7SSteve Wise * Reference the mpa skb. This ensures the data area 1203cfdda9d7SSteve Wise * will remain in memory until the hw acks the tx. 1204cfdda9d7SSteve Wise * Function fw4_ack() will deref it. 1205cfdda9d7SSteve Wise */ 1206cfdda9d7SSteve Wise skb_get(skb); 120764bec74aSHariprasad S t4_set_arp_err_handler(skb, NULL, mpa_start_arp_failure); 1208cfdda9d7SSteve Wise ep->mpa_skb = skb; 1209a7db89ebSSteve Wise __state_set(&ep->com, MPA_REP_SENT); 12109c88aa00SSteve Wise ep->snd_seq += mpalen; 1211cfdda9d7SSteve Wise return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 1212cfdda9d7SSteve Wise } 1213cfdda9d7SSteve Wise 1214cfdda9d7SSteve Wise static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb) 1215cfdda9d7SSteve Wise { 1216cfdda9d7SSteve Wise struct c4iw_ep *ep; 1217cfdda9d7SSteve Wise struct cpl_act_establish *req = cplhdr(skb); 12182e51e45cSPotnuri Bharat Teja unsigned short tcp_opt = ntohs(req->tcp_opt); 1219cfdda9d7SSteve Wise unsigned int tid = GET_TID(req); 12206c53e938SHariprasad Shenai unsigned int atid = TID_TID_G(ntohl(req->tos_atid)); 1221cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 1222fef4422dSHariprasad S int ret; 1223cfdda9d7SSteve Wise 1224cfdda9d7SSteve Wise ep = lookup_atid(t, atid); 1225cfdda9d7SSteve Wise 1226548ddb19SBharat Potnuri pr_debug("ep %p tid %u snd_isn %u rcv_isn %u\n", ep, tid, 1227cfdda9d7SSteve Wise be32_to_cpu(req->snd_isn), be32_to_cpu(req->rcv_isn)); 1228cfdda9d7SSteve Wise 1229a7db89ebSSteve Wise mutex_lock(&ep->com.mutex); 1230cfdda9d7SSteve Wise dst_confirm(ep->dst); 1231cfdda9d7SSteve Wise 1232cfdda9d7SSteve Wise /* setup the hwtid for this connection */ 1233cfdda9d7SSteve Wise ep->hwtid = tid; 12341dec4cecSGanesh Goudar cxgb4_insert_tid(t, ep, tid, ep->com.local_addr.ss_family); 1235944661ddSHariprasad S insert_ep_tid(ep); 1236cfdda9d7SSteve Wise 1237cfdda9d7SSteve Wise ep->snd_seq = be32_to_cpu(req->snd_isn); 1238cfdda9d7SSteve Wise ep->rcv_seq = be32_to_cpu(req->rcv_isn); 12392e51e45cSPotnuri Bharat Teja ep->snd_wscale = TCPOPT_SND_WSCALE_G(tcp_opt); 1240cfdda9d7SSteve Wise 12412e51e45cSPotnuri Bharat Teja set_emss(ep, tcp_opt); 1242cfdda9d7SSteve Wise 1243cfdda9d7SSteve Wise /* dealloc the atid */ 12449f5a9632SMatthew Wilcox xa_erase_irq(&ep->com.dev->atids, atid); 1245cfdda9d7SSteve Wise cxgb4_free_atid(t, atid); 1246793dad94SVipul Pandya set_bit(ACT_ESTAB, &ep->com.history); 1247cfdda9d7SSteve Wise 1248cfdda9d7SSteve Wise /* start MPA negotiation */ 12494a740838SHariprasad S ret = send_flowc(ep); 1250fef4422dSHariprasad S if (ret) 1251fef4422dSHariprasad S goto err; 1252d2fe99e8SKumar Sanghvi if (ep->retry_with_mpa_v1) 1253caa6c9f2SHariprasad S ret = send_mpa_req(ep, skb, 1); 1254d2fe99e8SKumar Sanghvi else 1255caa6c9f2SHariprasad S ret = send_mpa_req(ep, skb, mpa_rev); 1256caa6c9f2SHariprasad S if (ret) 1257caa6c9f2SHariprasad S goto err; 1258a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 1259cfdda9d7SSteve Wise return 0; 1260fef4422dSHariprasad S err: 1261fef4422dSHariprasad S mutex_unlock(&ep->com.mutex); 1262fef4422dSHariprasad S connect_reply_upcall(ep, -ENOMEM); 1263fef4422dSHariprasad S c4iw_ep_disconnect(ep, 0, GFP_KERNEL); 1264fef4422dSHariprasad S return 0; 1265cfdda9d7SSteve Wise } 1266cfdda9d7SSteve Wise 1267be13b2dfSSteve Wise static void close_complete_upcall(struct c4iw_ep *ep, int status) 1268cfdda9d7SSteve Wise { 1269cfdda9d7SSteve Wise struct iw_cm_event event; 1270cfdda9d7SSteve Wise 1271548ddb19SBharat Potnuri pr_debug("ep %p tid %u\n", ep, ep->hwtid); 1272cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1273cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CLOSE; 1274be13b2dfSSteve Wise event.status = status; 1275cfdda9d7SSteve Wise if (ep->com.cm_id) { 1276a9a42886SJoe Perches pr_debug("close complete delivered ep %p cm_id %p tid %u\n", 1277cfdda9d7SSteve Wise ep, ep->com.cm_id, ep->hwtid); 1278cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 12799ca6f7cfSHariprasad S deref_cm_id(&ep->com); 1280793dad94SVipul Pandya set_bit(CLOSE_UPCALL, &ep->com.history); 1281cfdda9d7SSteve Wise } 1282cfdda9d7SSteve Wise } 1283cfdda9d7SSteve Wise 1284cfdda9d7SSteve Wise static void peer_close_upcall(struct c4iw_ep *ep) 1285cfdda9d7SSteve Wise { 1286cfdda9d7SSteve Wise struct iw_cm_event event; 1287cfdda9d7SSteve Wise 1288548ddb19SBharat Potnuri pr_debug("ep %p tid %u\n", ep, ep->hwtid); 1289cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1290cfdda9d7SSteve Wise event.event = IW_CM_EVENT_DISCONNECT; 1291cfdda9d7SSteve Wise if (ep->com.cm_id) { 1292a9a42886SJoe Perches pr_debug("peer close delivered ep %p cm_id %p tid %u\n", 1293cfdda9d7SSteve Wise ep, ep->com.cm_id, ep->hwtid); 1294cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 1295793dad94SVipul Pandya set_bit(DISCONN_UPCALL, &ep->com.history); 1296cfdda9d7SSteve Wise } 1297cfdda9d7SSteve Wise } 1298cfdda9d7SSteve Wise 1299cfdda9d7SSteve Wise static void peer_abort_upcall(struct c4iw_ep *ep) 1300cfdda9d7SSteve Wise { 1301cfdda9d7SSteve Wise struct iw_cm_event event; 1302cfdda9d7SSteve Wise 1303548ddb19SBharat Potnuri pr_debug("ep %p tid %u\n", ep, ep->hwtid); 1304cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1305cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CLOSE; 1306cfdda9d7SSteve Wise event.status = -ECONNRESET; 1307cfdda9d7SSteve Wise if (ep->com.cm_id) { 1308a9a42886SJoe Perches pr_debug("abort delivered ep %p cm_id %p tid %u\n", ep, 1309cfdda9d7SSteve Wise ep->com.cm_id, ep->hwtid); 1310cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 13119ca6f7cfSHariprasad S deref_cm_id(&ep->com); 1312793dad94SVipul Pandya set_bit(ABORT_UPCALL, &ep->com.history); 1313cfdda9d7SSteve Wise } 1314cfdda9d7SSteve Wise } 1315cfdda9d7SSteve Wise 1316cfdda9d7SSteve Wise static void connect_reply_upcall(struct c4iw_ep *ep, int status) 1317cfdda9d7SSteve Wise { 1318cfdda9d7SSteve Wise struct iw_cm_event event; 1319cfdda9d7SSteve Wise 1320548ddb19SBharat Potnuri pr_debug("ep %p tid %u status %d\n", 1321548ddb19SBharat Potnuri ep, ep->hwtid, status); 1322cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1323cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CONNECT_REPLY; 1324cfdda9d7SSteve Wise event.status = status; 132524d44a39SSteve Wise memcpy(&event.local_addr, &ep->com.local_addr, 132624d44a39SSteve Wise sizeof(ep->com.local_addr)); 132724d44a39SSteve Wise memcpy(&event.remote_addr, &ep->com.remote_addr, 132824d44a39SSteve Wise sizeof(ep->com.remote_addr)); 1329cfdda9d7SSteve Wise 1330cfdda9d7SSteve Wise if ((status == 0) || (status == -ECONNREFUSED)) { 1331d2fe99e8SKumar Sanghvi if (!ep->tried_with_mpa_v1) { 1332d2fe99e8SKumar Sanghvi /* this means MPA_v2 is used */ 1333158c776dSHariprasad S event.ord = ep->ird; 1334158c776dSHariprasad S event.ird = ep->ord; 1335d2fe99e8SKumar Sanghvi event.private_data_len = ep->plen - 1336d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1337d2fe99e8SKumar Sanghvi event.private_data = ep->mpa_pkt + 1338d2fe99e8SKumar Sanghvi sizeof(struct mpa_message) + 1339d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1340d2fe99e8SKumar Sanghvi } else { 1341d2fe99e8SKumar Sanghvi /* this means MPA_v1 is used */ 1342158c776dSHariprasad S event.ord = cur_max_read_depth(ep->com.dev); 1343158c776dSHariprasad S event.ird = cur_max_read_depth(ep->com.dev); 1344cfdda9d7SSteve Wise event.private_data_len = ep->plen; 1345d2fe99e8SKumar Sanghvi event.private_data = ep->mpa_pkt + 1346d2fe99e8SKumar Sanghvi sizeof(struct mpa_message); 1347d2fe99e8SKumar Sanghvi } 1348cfdda9d7SSteve Wise } 134985963e4cSRoland Dreier 1350548ddb19SBharat Potnuri pr_debug("ep %p tid %u status %d\n", ep, 1351cfdda9d7SSteve Wise ep->hwtid, status); 1352793dad94SVipul Pandya set_bit(CONN_RPL_UPCALL, &ep->com.history); 1353cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 135485963e4cSRoland Dreier 13559ca6f7cfSHariprasad S if (status < 0) 13569ca6f7cfSHariprasad S deref_cm_id(&ep->com); 1357cfdda9d7SSteve Wise } 1358cfdda9d7SSteve Wise 1359be13b2dfSSteve Wise static int connect_request_upcall(struct c4iw_ep *ep) 1360cfdda9d7SSteve Wise { 1361cfdda9d7SSteve Wise struct iw_cm_event event; 1362be13b2dfSSteve Wise int ret; 1363cfdda9d7SSteve Wise 1364548ddb19SBharat Potnuri pr_debug("ep %p tid %u\n", ep, ep->hwtid); 1365cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1366cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CONNECT_REQUEST; 136724d44a39SSteve Wise memcpy(&event.local_addr, &ep->com.local_addr, 136824d44a39SSteve Wise sizeof(ep->com.local_addr)); 136924d44a39SSteve Wise memcpy(&event.remote_addr, &ep->com.remote_addr, 137024d44a39SSteve Wise sizeof(ep->com.remote_addr)); 1371d2fe99e8SKumar Sanghvi event.provider_data = ep; 1372d2fe99e8SKumar Sanghvi if (!ep->tried_with_mpa_v1) { 1373d2fe99e8SKumar Sanghvi /* this means MPA_v2 is used */ 1374d2fe99e8SKumar Sanghvi event.ord = ep->ord; 1375d2fe99e8SKumar Sanghvi event.ird = ep->ird; 1376d2fe99e8SKumar Sanghvi event.private_data_len = ep->plen - 1377d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1378d2fe99e8SKumar Sanghvi event.private_data = ep->mpa_pkt + sizeof(struct mpa_message) + 1379d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1380d2fe99e8SKumar Sanghvi } else { 1381d2fe99e8SKumar Sanghvi /* this means MPA_v1 is used. Send max supported */ 13824c2c5763SHariprasad Shenai event.ord = cur_max_read_depth(ep->com.dev); 13834c2c5763SHariprasad Shenai event.ird = cur_max_read_depth(ep->com.dev); 1384cfdda9d7SSteve Wise event.private_data_len = ep->plen; 1385cfdda9d7SSteve Wise event.private_data = ep->mpa_pkt + sizeof(struct mpa_message); 1386d2fe99e8SKumar Sanghvi } 1387cfdda9d7SSteve Wise c4iw_get_ep(&ep->com); 1388be13b2dfSSteve Wise ret = ep->parent_ep->com.cm_id->event_handler(ep->parent_ep->com.cm_id, 1389cfdda9d7SSteve Wise &event); 1390be13b2dfSSteve Wise if (ret) 1391be13b2dfSSteve Wise c4iw_put_ep(&ep->com); 1392793dad94SVipul Pandya set_bit(CONNREQ_UPCALL, &ep->com.history); 1393cfdda9d7SSteve Wise c4iw_put_ep(&ep->parent_ep->com); 1394be13b2dfSSteve Wise return ret; 1395cfdda9d7SSteve Wise } 1396cfdda9d7SSteve Wise 1397cfdda9d7SSteve Wise static void established_upcall(struct c4iw_ep *ep) 1398cfdda9d7SSteve Wise { 1399cfdda9d7SSteve Wise struct iw_cm_event event; 1400cfdda9d7SSteve Wise 1401548ddb19SBharat Potnuri pr_debug("ep %p tid %u\n", ep, ep->hwtid); 1402cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1403cfdda9d7SSteve Wise event.event = IW_CM_EVENT_ESTABLISHED; 14043dd9a5dcSHariprasad S event.ird = ep->ord; 14053dd9a5dcSHariprasad S event.ord = ep->ird; 1406cfdda9d7SSteve Wise if (ep->com.cm_id) { 1407548ddb19SBharat Potnuri pr_debug("ep %p tid %u\n", ep, ep->hwtid); 1408cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 1409793dad94SVipul Pandya set_bit(ESTAB_UPCALL, &ep->com.history); 1410cfdda9d7SSteve Wise } 1411cfdda9d7SSteve Wise } 1412cfdda9d7SSteve Wise 1413cfdda9d7SSteve Wise static int update_rx_credits(struct c4iw_ep *ep, u32 credits) 1414cfdda9d7SSteve Wise { 1415cfdda9d7SSteve Wise struct sk_buff *skb; 14166e3b6fc2SVarun Prakash u32 wrlen = roundup(sizeof(struct cpl_rx_data_ack), 16); 14176e3b6fc2SVarun Prakash u32 credit_dack; 1418cfdda9d7SSteve Wise 1419548ddb19SBharat Potnuri pr_debug("ep %p tid %u credits %u\n", 1420548ddb19SBharat Potnuri ep, ep->hwtid, credits); 1421cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 1422cfdda9d7SSteve Wise if (!skb) { 1423700456bdSJoe Perches pr_err("update_rx_credits - cannot alloc skb!\n"); 1424cfdda9d7SSteve Wise return 0; 1425cfdda9d7SSteve Wise } 1426cfdda9d7SSteve Wise 1427b408ff28SHariprasad Shenai /* 1428b408ff28SHariprasad Shenai * If we couldn't specify the entire rcv window at connection setup 1429b408ff28SHariprasad Shenai * due to the limit in the number of bits in the RCV_BUFSIZ field, 1430b408ff28SHariprasad Shenai * then add the overage in to the credits returned. 1431b408ff28SHariprasad Shenai */ 1432d7990b0cSAnish Bhatt if (ep->rcv_win > RCV_BUFSIZ_M * 1024) 1433d7990b0cSAnish Bhatt credits += ep->rcv_win - RCV_BUFSIZ_M * 1024; 1434b408ff28SHariprasad Shenai 14356e3b6fc2SVarun Prakash credit_dack = credits | RX_FORCE_ACK_F | RX_DACK_CHANGE_F | 14366e3b6fc2SVarun Prakash RX_DACK_MODE_V(dack_mode); 14376e3b6fc2SVarun Prakash 14386e3b6fc2SVarun Prakash cxgb_mk_rx_data_ack(skb, wrlen, ep->hwtid, ep->ctrlq_idx, 14396e3b6fc2SVarun Prakash credit_dack); 14406e3b6fc2SVarun Prakash 1441cfdda9d7SSteve Wise c4iw_ofld_send(&ep->com.dev->rdev, skb); 1442cfdda9d7SSteve Wise return credits; 1443cfdda9d7SSteve Wise } 1444cfdda9d7SSteve Wise 14454c2c5763SHariprasad Shenai #define RELAXED_IRD_NEGOTIATION 1 14464c2c5763SHariprasad Shenai 1447f8e1e1d1SHariprasad S /* 1448f8e1e1d1SHariprasad S * process_mpa_reply - process streaming mode MPA reply 1449f8e1e1d1SHariprasad S * 1450f8e1e1d1SHariprasad S * Returns: 1451f8e1e1d1SHariprasad S * 1452f8e1e1d1SHariprasad S * 0 upon success indicating a connect request was delivered to the ULP 1453f8e1e1d1SHariprasad S * or the mpa request is incomplete but valid so far. 1454f8e1e1d1SHariprasad S * 1455f8e1e1d1SHariprasad S * 1 if a failure requires the caller to close the connection. 1456f8e1e1d1SHariprasad S * 1457f8e1e1d1SHariprasad S * 2 if a failure requires the caller to abort the connection. 1458f8e1e1d1SHariprasad S */ 1459cc18b939SSteve Wise static int process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb) 1460cfdda9d7SSteve Wise { 1461cfdda9d7SSteve Wise struct mpa_message *mpa; 1462d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params *mpa_v2_params; 1463cfdda9d7SSteve Wise u16 plen; 1464d2fe99e8SKumar Sanghvi u16 resp_ird, resp_ord; 1465d2fe99e8SKumar Sanghvi u8 rtr_mismatch = 0, insuff_ird = 0; 1466cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 1467cfdda9d7SSteve Wise enum c4iw_qp_attr_mask mask; 1468cfdda9d7SSteve Wise int err; 1469cc18b939SSteve Wise int disconnect = 0; 1470cfdda9d7SSteve Wise 1471548ddb19SBharat Potnuri pr_debug("ep %p tid %u\n", ep, ep->hwtid); 1472cfdda9d7SSteve Wise 1473cfdda9d7SSteve Wise /* 1474cfdda9d7SSteve Wise * If we get more than the supported amount of private data 1475cfdda9d7SSteve Wise * then we must fail this connection. 1476cfdda9d7SSteve Wise */ 1477cfdda9d7SSteve Wise if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) { 1478cfdda9d7SSteve Wise err = -EINVAL; 1479da1cecdfSHariprasad S goto err_stop_timer; 1480cfdda9d7SSteve Wise } 1481cfdda9d7SSteve Wise 1482cfdda9d7SSteve Wise /* 1483cfdda9d7SSteve Wise * copy the new data into our accumulation buffer. 1484cfdda9d7SSteve Wise */ 1485cfdda9d7SSteve Wise skb_copy_from_linear_data(skb, &(ep->mpa_pkt[ep->mpa_pkt_len]), 1486cfdda9d7SSteve Wise skb->len); 1487cfdda9d7SSteve Wise ep->mpa_pkt_len += skb->len; 1488cfdda9d7SSteve Wise 1489cfdda9d7SSteve Wise /* 1490cfdda9d7SSteve Wise * if we don't even have the mpa message, then bail. 1491cfdda9d7SSteve Wise */ 1492cfdda9d7SSteve Wise if (ep->mpa_pkt_len < sizeof(*mpa)) 1493cc18b939SSteve Wise return 0; 1494cfdda9d7SSteve Wise mpa = (struct mpa_message *) ep->mpa_pkt; 1495cfdda9d7SSteve Wise 1496cfdda9d7SSteve Wise /* Validate MPA header. */ 1497d2fe99e8SKumar Sanghvi if (mpa->revision > mpa_rev) { 1498700456bdSJoe Perches pr_err("%s MPA version mismatch. Local = %d, Received = %d\n", 1499700456bdSJoe Perches __func__, mpa_rev, mpa->revision); 1500cfdda9d7SSteve Wise err = -EPROTO; 1501da1cecdfSHariprasad S goto err_stop_timer; 1502cfdda9d7SSteve Wise } 1503cfdda9d7SSteve Wise if (memcmp(mpa->key, MPA_KEY_REP, sizeof(mpa->key))) { 1504cfdda9d7SSteve Wise err = -EPROTO; 1505da1cecdfSHariprasad S goto err_stop_timer; 1506cfdda9d7SSteve Wise } 1507cfdda9d7SSteve Wise 1508cfdda9d7SSteve Wise plen = ntohs(mpa->private_data_size); 1509cfdda9d7SSteve Wise 1510cfdda9d7SSteve Wise /* 1511cfdda9d7SSteve Wise * Fail if there's too much private data. 1512cfdda9d7SSteve Wise */ 1513cfdda9d7SSteve Wise if (plen > MPA_MAX_PRIVATE_DATA) { 1514cfdda9d7SSteve Wise err = -EPROTO; 1515da1cecdfSHariprasad S goto err_stop_timer; 1516cfdda9d7SSteve Wise } 1517cfdda9d7SSteve Wise 1518cfdda9d7SSteve Wise /* 1519cfdda9d7SSteve Wise * If plen does not account for pkt size 1520cfdda9d7SSteve Wise */ 1521cfdda9d7SSteve Wise if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) { 1522cfdda9d7SSteve Wise err = -EPROTO; 1523da1cecdfSHariprasad S goto err_stop_timer; 1524cfdda9d7SSteve Wise } 1525cfdda9d7SSteve Wise 1526cfdda9d7SSteve Wise ep->plen = (u8) plen; 1527cfdda9d7SSteve Wise 1528cfdda9d7SSteve Wise /* 1529cfdda9d7SSteve Wise * If we don't have all the pdata yet, then bail. 1530cfdda9d7SSteve Wise * We'll continue process when more data arrives. 1531cfdda9d7SSteve Wise */ 1532cfdda9d7SSteve Wise if (ep->mpa_pkt_len < (sizeof(*mpa) + plen)) 1533cc18b939SSteve Wise return 0; 1534cfdda9d7SSteve Wise 1535cfdda9d7SSteve Wise if (mpa->flags & MPA_REJECT) { 1536cfdda9d7SSteve Wise err = -ECONNREFUSED; 1537da1cecdfSHariprasad S goto err_stop_timer; 1538cfdda9d7SSteve Wise } 1539cfdda9d7SSteve Wise 1540cfdda9d7SSteve Wise /* 1541da1cecdfSHariprasad S * Stop mpa timer. If it expired, then 1542da1cecdfSHariprasad S * we ignore the MPA reply. process_timeout() 1543da1cecdfSHariprasad S * will abort the connection. 1544da1cecdfSHariprasad S */ 1545da1cecdfSHariprasad S if (stop_ep_timer(ep)) 1546da1cecdfSHariprasad S return 0; 1547da1cecdfSHariprasad S 1548da1cecdfSHariprasad S /* 1549cfdda9d7SSteve Wise * If we get here we have accumulated the entire mpa 1550cfdda9d7SSteve Wise * start reply message including private data. And 1551cfdda9d7SSteve Wise * the MPA header is valid. 1552cfdda9d7SSteve Wise */ 1553c529fb50SSteve Wise __state_set(&ep->com, FPDU_MODE); 1554cfdda9d7SSteve Wise ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0; 1555cfdda9d7SSteve Wise ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0; 1556d2fe99e8SKumar Sanghvi ep->mpa_attr.version = mpa->revision; 1557d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED; 1558d2fe99e8SKumar Sanghvi 1559d2fe99e8SKumar Sanghvi if (mpa->revision == 2) { 1560d2fe99e8SKumar Sanghvi ep->mpa_attr.enhanced_rdma_conn = 1561d2fe99e8SKumar Sanghvi mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0; 1562d2fe99e8SKumar Sanghvi if (ep->mpa_attr.enhanced_rdma_conn) { 1563d2fe99e8SKumar Sanghvi mpa_v2_params = (struct mpa_v2_conn_params *) 1564d2fe99e8SKumar Sanghvi (ep->mpa_pkt + sizeof(*mpa)); 1565d2fe99e8SKumar Sanghvi resp_ird = ntohs(mpa_v2_params->ird) & 1566d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 1567d2fe99e8SKumar Sanghvi resp_ord = ntohs(mpa_v2_params->ord) & 1568d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 1569548ddb19SBharat Potnuri pr_debug("responder ird %u ord %u ep ird %u ord %u\n", 1570a9a42886SJoe Perches resp_ird, resp_ord, ep->ird, ep->ord); 1571d2fe99e8SKumar Sanghvi 1572d2fe99e8SKumar Sanghvi /* 1573d2fe99e8SKumar Sanghvi * This is a double-check. Ideally, below checks are 1574d2fe99e8SKumar Sanghvi * not required since ird/ord stuff has been taken 1575d2fe99e8SKumar Sanghvi * care of in c4iw_accept_cr 1576d2fe99e8SKumar Sanghvi */ 15774c2c5763SHariprasad Shenai if (ep->ird < resp_ord) { 15784c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION && resp_ord <= 15794c2c5763SHariprasad Shenai ep->com.dev->rdev.lldi.max_ordird_qp) 15804c2c5763SHariprasad Shenai ep->ird = resp_ord; 15814c2c5763SHariprasad Shenai else 15824c2c5763SHariprasad Shenai insuff_ird = 1; 15834c2c5763SHariprasad Shenai } else if (ep->ird > resp_ord) { 15844c2c5763SHariprasad Shenai ep->ird = resp_ord; 15854c2c5763SHariprasad Shenai } 15864c2c5763SHariprasad Shenai if (ep->ord > resp_ird) { 15874c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION) 15884c2c5763SHariprasad Shenai ep->ord = resp_ird; 15894c2c5763SHariprasad Shenai else 15904c2c5763SHariprasad Shenai insuff_ird = 1; 15914c2c5763SHariprasad Shenai } 15924c2c5763SHariprasad Shenai if (insuff_ird) { 1593d2fe99e8SKumar Sanghvi err = -ENOMEM; 1594d2fe99e8SKumar Sanghvi ep->ird = resp_ord; 1595d2fe99e8SKumar Sanghvi ep->ord = resp_ird; 1596d2fe99e8SKumar Sanghvi } 1597d2fe99e8SKumar Sanghvi 1598d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ird) & 1599d2fe99e8SKumar Sanghvi MPA_V2_PEER2PEER_MODEL) { 1600d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ord) & 1601d2fe99e8SKumar Sanghvi MPA_V2_RDMA_WRITE_RTR) 1602d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1603d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_RDMA_WRITE; 1604d2fe99e8SKumar Sanghvi else if (ntohs(mpa_v2_params->ord) & 1605d2fe99e8SKumar Sanghvi MPA_V2_RDMA_READ_RTR) 1606d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1607d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_READ_REQ; 1608d2fe99e8SKumar Sanghvi } 1609d2fe99e8SKumar Sanghvi } 1610d2fe99e8SKumar Sanghvi } else if (mpa->revision == 1) 1611d2fe99e8SKumar Sanghvi if (peer2peer) 1612d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = p2p_type; 1613d2fe99e8SKumar Sanghvi 1614548ddb19SBharat Potnuri pr_debug("crc_enabled=%d, recv_marker_enabled=%d, xmit_marker_enabled=%d, version=%d p2p_type=%d local-p2p_type = %d\n", 1615548ddb19SBharat Potnuri ep->mpa_attr.crc_enabled, 1616d2fe99e8SKumar Sanghvi ep->mpa_attr.recv_marker_enabled, 1617d2fe99e8SKumar Sanghvi ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version, 1618d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type, p2p_type); 1619d2fe99e8SKumar Sanghvi 1620d2fe99e8SKumar Sanghvi /* 1621d2fe99e8SKumar Sanghvi * If responder's RTR does not match with that of initiator, assign 1622d2fe99e8SKumar Sanghvi * FW_RI_INIT_P2PTYPE_DISABLED in mpa attributes so that RTR is not 1623d2fe99e8SKumar Sanghvi * generated when moving QP to RTS state. 1624d2fe99e8SKumar Sanghvi * A TERM message will be sent after QP has moved to RTS state 1625d2fe99e8SKumar Sanghvi */ 162691018f86SKumar Sanghvi if ((ep->mpa_attr.version == 2) && peer2peer && 1627d2fe99e8SKumar Sanghvi (ep->mpa_attr.p2p_type != p2p_type)) { 1628d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED; 1629d2fe99e8SKumar Sanghvi rtr_mismatch = 1; 1630d2fe99e8SKumar Sanghvi } 1631cfdda9d7SSteve Wise 1632cfdda9d7SSteve Wise attrs.mpa_attr = ep->mpa_attr; 1633cfdda9d7SSteve Wise attrs.max_ird = ep->ird; 1634cfdda9d7SSteve Wise attrs.max_ord = ep->ord; 1635cfdda9d7SSteve Wise attrs.llp_stream_handle = ep; 1636cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_RTS; 1637cfdda9d7SSteve Wise 1638cfdda9d7SSteve Wise mask = C4IW_QP_ATTR_NEXT_STATE | 1639cfdda9d7SSteve Wise C4IW_QP_ATTR_LLP_STREAM_HANDLE | C4IW_QP_ATTR_MPA_ATTR | 1640cfdda9d7SSteve Wise C4IW_QP_ATTR_MAX_IRD | C4IW_QP_ATTR_MAX_ORD; 1641cfdda9d7SSteve Wise 1642cfdda9d7SSteve Wise /* bind QP and TID with INIT_WR */ 1643cfdda9d7SSteve Wise err = c4iw_modify_qp(ep->com.qp->rhp, 1644cfdda9d7SSteve Wise ep->com.qp, mask, &attrs, 1); 1645cfdda9d7SSteve Wise if (err) 1646cfdda9d7SSteve Wise goto err; 1647d2fe99e8SKumar Sanghvi 1648d2fe99e8SKumar Sanghvi /* 1649d2fe99e8SKumar Sanghvi * If responder's RTR requirement did not match with what initiator 1650d2fe99e8SKumar Sanghvi * supports, generate TERM message 1651d2fe99e8SKumar Sanghvi */ 1652d2fe99e8SKumar Sanghvi if (rtr_mismatch) { 1653700456bdSJoe Perches pr_err("%s: RTR mismatch, sending TERM\n", __func__); 1654d2fe99e8SKumar Sanghvi attrs.layer_etype = LAYER_MPA | DDP_LLP; 1655d2fe99e8SKumar Sanghvi attrs.ecode = MPA_NOMATCH_RTR; 1656d2fe99e8SKumar Sanghvi attrs.next_state = C4IW_QP_STATE_TERMINATE; 1657cc18b939SSteve Wise attrs.send_term = 1; 1658d2fe99e8SKumar Sanghvi err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 1659cc18b939SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 1660d2fe99e8SKumar Sanghvi err = -ENOMEM; 1661cc18b939SSteve Wise disconnect = 1; 1662d2fe99e8SKumar Sanghvi goto out; 1663d2fe99e8SKumar Sanghvi } 1664d2fe99e8SKumar Sanghvi 1665d2fe99e8SKumar Sanghvi /* 1666d2fe99e8SKumar Sanghvi * Generate TERM if initiator IRD is not sufficient for responder 1667d2fe99e8SKumar Sanghvi * provided ORD. Currently, we do the same behaviour even when 1668d2fe99e8SKumar Sanghvi * responder provided IRD is also not sufficient as regards to 1669d2fe99e8SKumar Sanghvi * initiator ORD. 1670d2fe99e8SKumar Sanghvi */ 1671d2fe99e8SKumar Sanghvi if (insuff_ird) { 1672700456bdSJoe Perches pr_err("%s: Insufficient IRD, sending TERM\n", __func__); 1673d2fe99e8SKumar Sanghvi attrs.layer_etype = LAYER_MPA | DDP_LLP; 1674d2fe99e8SKumar Sanghvi attrs.ecode = MPA_INSUFF_IRD; 1675d2fe99e8SKumar Sanghvi attrs.next_state = C4IW_QP_STATE_TERMINATE; 1676cc18b939SSteve Wise attrs.send_term = 1; 1677d2fe99e8SKumar Sanghvi err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 1678cc18b939SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 1679d2fe99e8SKumar Sanghvi err = -ENOMEM; 1680cc18b939SSteve Wise disconnect = 1; 1681d2fe99e8SKumar Sanghvi goto out; 1682d2fe99e8SKumar Sanghvi } 1683cfdda9d7SSteve Wise goto out; 1684da1cecdfSHariprasad S err_stop_timer: 1685da1cecdfSHariprasad S stop_ep_timer(ep); 1686cfdda9d7SSteve Wise err: 1687f8e1e1d1SHariprasad S disconnect = 2; 1688cfdda9d7SSteve Wise out: 1689cfdda9d7SSteve Wise connect_reply_upcall(ep, err); 1690cc18b939SSteve Wise return disconnect; 1691cfdda9d7SSteve Wise } 1692cfdda9d7SSteve Wise 1693fd6aabe4SHariprasad S /* 1694fd6aabe4SHariprasad S * process_mpa_request - process streaming mode MPA request 1695fd6aabe4SHariprasad S * 1696fd6aabe4SHariprasad S * Returns: 1697fd6aabe4SHariprasad S * 1698fd6aabe4SHariprasad S * 0 upon success indicating a connect request was delivered to the ULP 1699fd6aabe4SHariprasad S * or the mpa request is incomplete but valid so far. 1700fd6aabe4SHariprasad S * 1701fd6aabe4SHariprasad S * 1 if a failure requires the caller to close the connection. 1702fd6aabe4SHariprasad S * 1703fd6aabe4SHariprasad S * 2 if a failure requires the caller to abort the connection. 1704fd6aabe4SHariprasad S */ 1705fd6aabe4SHariprasad S static int process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb) 1706cfdda9d7SSteve Wise { 1707cfdda9d7SSteve Wise struct mpa_message *mpa; 1708d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params *mpa_v2_params; 1709cfdda9d7SSteve Wise u16 plen; 1710cfdda9d7SSteve Wise 1711548ddb19SBharat Potnuri pr_debug("ep %p tid %u\n", ep, ep->hwtid); 1712cfdda9d7SSteve Wise 1713cfdda9d7SSteve Wise /* 1714cfdda9d7SSteve Wise * If we get more than the supported amount of private data 1715cfdda9d7SSteve Wise * then we must fail this connection. 1716cfdda9d7SSteve Wise */ 1717fd6aabe4SHariprasad S if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) 1718fd6aabe4SHariprasad S goto err_stop_timer; 1719cfdda9d7SSteve Wise 1720548ddb19SBharat Potnuri pr_debug("enter (%s line %u)\n", __FILE__, __LINE__); 1721cfdda9d7SSteve Wise 1722cfdda9d7SSteve Wise /* 1723cfdda9d7SSteve Wise * Copy the new data into our accumulation buffer. 1724cfdda9d7SSteve Wise */ 1725cfdda9d7SSteve Wise skb_copy_from_linear_data(skb, &(ep->mpa_pkt[ep->mpa_pkt_len]), 1726cfdda9d7SSteve Wise skb->len); 1727cfdda9d7SSteve Wise ep->mpa_pkt_len += skb->len; 1728cfdda9d7SSteve Wise 1729cfdda9d7SSteve Wise /* 1730cfdda9d7SSteve Wise * If we don't even have the mpa message, then bail. 1731cfdda9d7SSteve Wise * We'll continue process when more data arrives. 1732cfdda9d7SSteve Wise */ 1733cfdda9d7SSteve Wise if (ep->mpa_pkt_len < sizeof(*mpa)) 1734fd6aabe4SHariprasad S return 0; 1735cfdda9d7SSteve Wise 1736548ddb19SBharat Potnuri pr_debug("enter (%s line %u)\n", __FILE__, __LINE__); 1737cfdda9d7SSteve Wise mpa = (struct mpa_message *) ep->mpa_pkt; 1738cfdda9d7SSteve Wise 1739cfdda9d7SSteve Wise /* 1740cfdda9d7SSteve Wise * Validate MPA Header. 1741cfdda9d7SSteve Wise */ 1742d2fe99e8SKumar Sanghvi if (mpa->revision > mpa_rev) { 1743700456bdSJoe Perches pr_err("%s MPA version mismatch. Local = %d, Received = %d\n", 1744700456bdSJoe Perches __func__, mpa_rev, mpa->revision); 1745fd6aabe4SHariprasad S goto err_stop_timer; 1746cfdda9d7SSteve Wise } 1747cfdda9d7SSteve Wise 1748fd6aabe4SHariprasad S if (memcmp(mpa->key, MPA_KEY_REQ, sizeof(mpa->key))) 1749fd6aabe4SHariprasad S goto err_stop_timer; 1750cfdda9d7SSteve Wise 1751cfdda9d7SSteve Wise plen = ntohs(mpa->private_data_size); 1752cfdda9d7SSteve Wise 1753cfdda9d7SSteve Wise /* 1754cfdda9d7SSteve Wise * Fail if there's too much private data. 1755cfdda9d7SSteve Wise */ 1756fd6aabe4SHariprasad S if (plen > MPA_MAX_PRIVATE_DATA) 1757fd6aabe4SHariprasad S goto err_stop_timer; 1758cfdda9d7SSteve Wise 1759cfdda9d7SSteve Wise /* 1760cfdda9d7SSteve Wise * If plen does not account for pkt size 1761cfdda9d7SSteve Wise */ 1762fd6aabe4SHariprasad S if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) 1763fd6aabe4SHariprasad S goto err_stop_timer; 1764cfdda9d7SSteve Wise ep->plen = (u8) plen; 1765cfdda9d7SSteve Wise 1766cfdda9d7SSteve Wise /* 1767cfdda9d7SSteve Wise * If we don't have all the pdata yet, then bail. 1768cfdda9d7SSteve Wise */ 1769cfdda9d7SSteve Wise if (ep->mpa_pkt_len < (sizeof(*mpa) + plen)) 1770fd6aabe4SHariprasad S return 0; 1771cfdda9d7SSteve Wise 1772cfdda9d7SSteve Wise /* 1773cfdda9d7SSteve Wise * If we get here we have accumulated the entire mpa 1774cfdda9d7SSteve Wise * start reply message including private data. 1775cfdda9d7SSteve Wise */ 1776cfdda9d7SSteve Wise ep->mpa_attr.initiator = 0; 1777cfdda9d7SSteve Wise ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0; 1778cfdda9d7SSteve Wise ep->mpa_attr.recv_marker_enabled = markers_enabled; 1779cfdda9d7SSteve Wise ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0; 1780d2fe99e8SKumar Sanghvi ep->mpa_attr.version = mpa->revision; 1781d2fe99e8SKumar Sanghvi if (mpa->revision == 1) 1782d2fe99e8SKumar Sanghvi ep->tried_with_mpa_v1 = 1; 1783d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED; 1784d2fe99e8SKumar Sanghvi 1785d2fe99e8SKumar Sanghvi if (mpa->revision == 2) { 1786d2fe99e8SKumar Sanghvi ep->mpa_attr.enhanced_rdma_conn = 1787d2fe99e8SKumar Sanghvi mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0; 1788d2fe99e8SKumar Sanghvi if (ep->mpa_attr.enhanced_rdma_conn) { 1789d2fe99e8SKumar Sanghvi mpa_v2_params = (struct mpa_v2_conn_params *) 1790d2fe99e8SKumar Sanghvi (ep->mpa_pkt + sizeof(*mpa)); 1791d2fe99e8SKumar Sanghvi ep->ird = ntohs(mpa_v2_params->ird) & 1792d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 17937f446abfSSteve Wise ep->ird = min_t(u32, ep->ird, 17947f446abfSSteve Wise cur_max_read_depth(ep->com.dev)); 1795d2fe99e8SKumar Sanghvi ep->ord = ntohs(mpa_v2_params->ord) & 1796d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 17977f446abfSSteve Wise ep->ord = min_t(u32, ep->ord, 17987f446abfSSteve Wise cur_max_read_depth(ep->com.dev)); 1799548ddb19SBharat Potnuri pr_debug("initiator ird %u ord %u\n", 1800548ddb19SBharat Potnuri ep->ird, ep->ord); 1801d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ird) & MPA_V2_PEER2PEER_MODEL) 1802d2fe99e8SKumar Sanghvi if (peer2peer) { 1803d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ord) & 1804d2fe99e8SKumar Sanghvi MPA_V2_RDMA_WRITE_RTR) 1805d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1806d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_RDMA_WRITE; 1807d2fe99e8SKumar Sanghvi else if (ntohs(mpa_v2_params->ord) & 1808d2fe99e8SKumar Sanghvi MPA_V2_RDMA_READ_RTR) 1809d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1810d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_READ_REQ; 1811d2fe99e8SKumar Sanghvi } 1812d2fe99e8SKumar Sanghvi } 1813d2fe99e8SKumar Sanghvi } else if (mpa->revision == 1) 1814d2fe99e8SKumar Sanghvi if (peer2peer) 1815d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = p2p_type; 1816d2fe99e8SKumar Sanghvi 1817548ddb19SBharat Potnuri pr_debug("crc_enabled=%d, recv_marker_enabled=%d, xmit_marker_enabled=%d, version=%d p2p_type=%d\n", 1818cfdda9d7SSteve Wise ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled, 1819cfdda9d7SSteve Wise ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version, 1820cfdda9d7SSteve Wise ep->mpa_attr.p2p_type); 1821cfdda9d7SSteve Wise 1822c529fb50SSteve Wise __state_set(&ep->com, MPA_REQ_RCVD); 1823cfdda9d7SSteve Wise 1824cfdda9d7SSteve Wise /* drive upcall */ 1825e4b76a2aSHariprasad S mutex_lock_nested(&ep->parent_ep->com.mutex, SINGLE_DEPTH_NESTING); 1826be13b2dfSSteve Wise if (ep->parent_ep->com.state != DEAD) { 1827be13b2dfSSteve Wise if (connect_request_upcall(ep)) 1828fd6aabe4SHariprasad S goto err_unlock_parent; 1829be13b2dfSSteve Wise } else { 1830fd6aabe4SHariprasad S goto err_unlock_parent; 1831be13b2dfSSteve Wise } 1832be13b2dfSSteve Wise mutex_unlock(&ep->parent_ep->com.mutex); 1833fd6aabe4SHariprasad S return 0; 1834fd6aabe4SHariprasad S 1835fd6aabe4SHariprasad S err_unlock_parent: 1836fd6aabe4SHariprasad S mutex_unlock(&ep->parent_ep->com.mutex); 1837fd6aabe4SHariprasad S goto err_out; 1838fd6aabe4SHariprasad S err_stop_timer: 1839fd6aabe4SHariprasad S (void)stop_ep_timer(ep); 1840fd6aabe4SHariprasad S err_out: 1841fd6aabe4SHariprasad S return 2; 1842cfdda9d7SSteve Wise } 1843cfdda9d7SSteve Wise 1844cfdda9d7SSteve Wise static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb) 1845cfdda9d7SSteve Wise { 1846cfdda9d7SSteve Wise struct c4iw_ep *ep; 1847cfdda9d7SSteve Wise struct cpl_rx_data *hdr = cplhdr(skb); 1848cfdda9d7SSteve Wise unsigned int dlen = ntohs(hdr->len); 1849cfdda9d7SSteve Wise unsigned int tid = GET_TID(hdr); 1850793dad94SVipul Pandya __u8 status = hdr->status; 1851cc18b939SSteve Wise int disconnect = 0; 1852cfdda9d7SSteve Wise 1853944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 1854977116c6SSteve Wise if (!ep) 1855977116c6SSteve Wise return 0; 1856548ddb19SBharat Potnuri pr_debug("ep %p tid %u dlen %u\n", ep, ep->hwtid, dlen); 1857cfdda9d7SSteve Wise skb_pull(skb, sizeof(*hdr)); 1858cfdda9d7SSteve Wise skb_trim(skb, dlen); 1859c529fb50SSteve Wise mutex_lock(&ep->com.mutex); 1860cfdda9d7SSteve Wise 1861c529fb50SSteve Wise switch (ep->com.state) { 1862cfdda9d7SSteve Wise case MPA_REQ_SENT: 18633bcf96e0SSteve Wise update_rx_credits(ep, dlen); 186455abf8dfSVipul Pandya ep->rcv_seq += dlen; 1865cc18b939SSteve Wise disconnect = process_mpa_reply(ep, skb); 1866cfdda9d7SSteve Wise break; 1867cfdda9d7SSteve Wise case MPA_REQ_WAIT: 18683bcf96e0SSteve Wise update_rx_credits(ep, dlen); 186955abf8dfSVipul Pandya ep->rcv_seq += dlen; 18704a4dd8dbSHariprasad S disconnect = process_mpa_request(ep, skb); 1871cfdda9d7SSteve Wise break; 18721557967bSVipul Pandya case FPDU_MODE: { 18731557967bSVipul Pandya struct c4iw_qp_attributes attrs; 18743bcf96e0SSteve Wise 18753bcf96e0SSteve Wise update_rx_credits(ep, dlen); 1876e8e5b927SVipul Pandya if (status) 1877793dad94SVipul Pandya pr_err("%s Unexpected streaming data." \ 187804236df2SVipul Pandya " qpid %u ep %p state %d tid %u status %d\n", 187904236df2SVipul Pandya __func__, ep->com.qp->wq.sq.qid, ep, 1880c529fb50SSteve Wise ep->com.state, ep->hwtid, status); 188197d7ec0cSSteve Wise attrs.next_state = C4IW_QP_STATE_TERMINATE; 188255abf8dfSVipul Pandya c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 1883cc18b939SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 1884cc18b939SSteve Wise disconnect = 1; 1885cfdda9d7SSteve Wise break; 1886cfdda9d7SSteve Wise } 18871557967bSVipul Pandya default: 18881557967bSVipul Pandya break; 18891557967bSVipul Pandya } 1890c529fb50SSteve Wise mutex_unlock(&ep->com.mutex); 1891cc18b939SSteve Wise if (disconnect) 18924a4dd8dbSHariprasad S c4iw_ep_disconnect(ep, disconnect == 2, GFP_KERNEL); 1893944661ddSHariprasad S c4iw_put_ep(&ep->com); 1894cfdda9d7SSteve Wise return 0; 1895cfdda9d7SSteve Wise } 1896cfdda9d7SSteve Wise 189711a27e21SRaju Rangoju static void complete_cached_srq_buffers(struct c4iw_ep *ep, u32 srqidx) 18986a0b6174SRaju Rangoju { 18996a0b6174SRaju Rangoju enum chip_type adapter_type; 19006a0b6174SRaju Rangoju 19016a0b6174SRaju Rangoju adapter_type = ep->com.dev->rdev.lldi.adapter_type; 19026a0b6174SRaju Rangoju 19036a0b6174SRaju Rangoju /* 19046a0b6174SRaju Rangoju * If this TCB had a srq buffer cached, then we must complete 19056a0b6174SRaju Rangoju * it. For user mode, that means saving the srqidx in the 19066a0b6174SRaju Rangoju * user/kernel status page for this qp. For kernel mode, just 19076a0b6174SRaju Rangoju * synthesize the CQE now. 19086a0b6174SRaju Rangoju */ 19096a0b6174SRaju Rangoju if (CHELSIO_CHIP_VERSION(adapter_type) > CHELSIO_T5 && srqidx) { 19106a0b6174SRaju Rangoju if (ep->com.qp->ibqp.uobject) 19116a0b6174SRaju Rangoju t4_set_wq_in_error(&ep->com.qp->wq, srqidx); 19126a0b6174SRaju Rangoju else 19136a0b6174SRaju Rangoju c4iw_flush_srqidx(ep->com.qp, srqidx); 19146a0b6174SRaju Rangoju } 19156a0b6174SRaju Rangoju } 19166a0b6174SRaju Rangoju 1917cfdda9d7SSteve Wise static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 1918cfdda9d7SSteve Wise { 191911a27e21SRaju Rangoju u32 srqidx; 1920cfdda9d7SSteve Wise struct c4iw_ep *ep; 19216a0b6174SRaju Rangoju struct cpl_abort_rpl_rss6 *rpl = cplhdr(skb); 1922cfdda9d7SSteve Wise int release = 0; 1923cfdda9d7SSteve Wise unsigned int tid = GET_TID(rpl); 1924cfdda9d7SSteve Wise 1925944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 19264984037bSVipul Pandya if (!ep) { 1927700456bdSJoe Perches pr_warn("Abort rpl to freed endpoint\n"); 19284984037bSVipul Pandya return 0; 19294984037bSVipul Pandya } 19306a0b6174SRaju Rangoju 193111a27e21SRaju Rangoju if (ep->com.qp && ep->com.qp->srq) { 193211a27e21SRaju Rangoju srqidx = ABORT_RSS_SRQIDX_G(be32_to_cpu(rpl->srqidx_status)); 193311a27e21SRaju Rangoju complete_cached_srq_buffers(ep, srqidx ? srqidx : ep->srqe_idx); 193411a27e21SRaju Rangoju } 19356a0b6174SRaju Rangoju 1936548ddb19SBharat Potnuri pr_debug("ep %p tid %u\n", ep, ep->hwtid); 19372f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 1938cfdda9d7SSteve Wise switch (ep->com.state) { 1939cfdda9d7SSteve Wise case ABORTING: 19402015f26cSSteve Wise c4iw_wake_up_noref(ep->com.wr_waitp, -ECONNRESET); 1941cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 1942cfdda9d7SSteve Wise release = 1; 1943cfdda9d7SSteve Wise break; 1944cfdda9d7SSteve Wise default: 1945700456bdSJoe Perches pr_err("%s ep %p state %d\n", __func__, ep, ep->com.state); 1946cfdda9d7SSteve Wise break; 1947cfdda9d7SSteve Wise } 19482f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 1949cfdda9d7SSteve Wise 1950f368ff18SRaju Rangoju if (release) { 1951f368ff18SRaju Rangoju close_complete_upcall(ep, -ECONNRESET); 1952cfdda9d7SSteve Wise release_ep_resources(ep); 1953f368ff18SRaju Rangoju } 1954944661ddSHariprasad S c4iw_put_ep(&ep->com); 1955cfdda9d7SSteve Wise return 0; 1956cfdda9d7SSteve Wise } 1957cfdda9d7SSteve Wise 1958caa6c9f2SHariprasad S static int send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid) 19595be78ee9SVipul Pandya { 19605be78ee9SVipul Pandya struct sk_buff *skb; 19615be78ee9SVipul Pandya struct fw_ofld_connection_wr *req; 19625be78ee9SVipul Pandya unsigned int mtu_idx; 1963cc516700SVarun Prakash u32 wscale; 1964830662f6SVipul Pandya struct sockaddr_in *sin; 1965b408ff28SHariprasad Shenai int win; 19665be78ee9SVipul Pandya 19675be78ee9SVipul Pandya skb = get_skb(NULL, sizeof(*req), GFP_KERNEL); 1968de77b966Syuan linyu req = __skb_put_zero(skb, sizeof(*req)); 19696c53e938SHariprasad Shenai req->op_compl = htonl(WR_OP_V(FW_OFLD_CONNECTION_WR)); 1970e2ac9628SHariprasad Shenai req->len16_pkd = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*req), 16))); 197141b4f86cSKumar Sanghvi req->le.filter = cpu_to_be32(cxgb4_select_ntuple( 197241b4f86cSKumar Sanghvi ep->com.dev->rdev.lldi.ports[0], 19735be78ee9SVipul Pandya ep->l2t)); 1974170003c8SSteve Wise sin = (struct sockaddr_in *)&ep->com.local_addr; 1975830662f6SVipul Pandya req->le.lport = sin->sin_port; 1976830662f6SVipul Pandya req->le.u.ipv4.lip = sin->sin_addr.s_addr; 1977170003c8SSteve Wise sin = (struct sockaddr_in *)&ep->com.remote_addr; 1978830662f6SVipul Pandya req->le.pport = sin->sin_port; 1979830662f6SVipul Pandya req->le.u.ipv4.pip = sin->sin_addr.s_addr; 19805be78ee9SVipul Pandya req->tcb.t_state_to_astid = 198177a80e23SHariprasad Shenai htonl(FW_OFLD_CONNECTION_WR_T_STATE_V(TCP_SYN_SENT) | 198277a80e23SHariprasad Shenai FW_OFLD_CONNECTION_WR_ASTID_V(atid)); 19835be78ee9SVipul Pandya req->tcb.cplrxdataack_cplpassacceptrpl = 198477a80e23SHariprasad Shenai htons(FW_OFLD_CONNECTION_WR_CPLRXDATAACK_F); 1985ef5d6355SVipul Pandya req->tcb.tx_max = (__force __be32) jiffies; 1986793dad94SVipul Pandya req->tcb.rcv_adv = htons(1); 198744c6d069SVarun Prakash cxgb_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, 198804524a47SHariprasad S enable_tcp_timestamps, 198944c6d069SVarun Prakash (ep->com.remote_addr.ss_family == AF_INET) ? 0 : 1); 1990cc516700SVarun Prakash wscale = cxgb_compute_wscale(rcv_win); 1991b408ff28SHariprasad Shenai 1992b408ff28SHariprasad Shenai /* 1993b408ff28SHariprasad Shenai * Specify the largest window that will fit in opt0. The 1994b408ff28SHariprasad Shenai * remainder will be specified in the rx_data_ack. 1995b408ff28SHariprasad Shenai */ 1996b408ff28SHariprasad Shenai win = ep->rcv_win >> 10; 1997d7990b0cSAnish Bhatt if (win > RCV_BUFSIZ_M) 1998d7990b0cSAnish Bhatt win = RCV_BUFSIZ_M; 1999b408ff28SHariprasad Shenai 20006c53e938SHariprasad Shenai req->tcb.opt0 = (__force __be64) (TCAM_BYPASS_F | 20016c53e938SHariprasad Shenai (nocong ? NO_CONG_F : 0) | 2002d7990b0cSAnish Bhatt KEEP_ALIVE_F | 20036c53e938SHariprasad Shenai DELACK_F | 2004d7990b0cSAnish Bhatt WND_SCALE_V(wscale) | 2005d7990b0cSAnish Bhatt MSS_IDX_V(mtu_idx) | 2006d7990b0cSAnish Bhatt L2T_IDX_V(ep->l2t->idx) | 2007d7990b0cSAnish Bhatt TX_CHAN_V(ep->tx_chan) | 2008d7990b0cSAnish Bhatt SMAC_SEL_V(ep->smac_idx) | 2009ac8e4c69SHariprasad S DSCP_V(ep->tos >> 2) | 2010d7990b0cSAnish Bhatt ULP_MODE_V(ULP_MODE_TCPDDP) | 2011d7990b0cSAnish Bhatt RCV_BUFSIZ_V(win)); 20126c53e938SHariprasad Shenai req->tcb.opt2 = (__force __be32) (PACE_V(1) | 20136c53e938SHariprasad Shenai TX_QUEUE_V(ep->com.dev->rdev.lldi.tx_modq[ep->tx_chan]) | 2014d7990b0cSAnish Bhatt RX_CHANNEL_V(0) | 20156c53e938SHariprasad Shenai CCTRL_ECN_V(enable_ecn) | 2016d7990b0cSAnish Bhatt RSS_QUEUE_VALID_F | RSS_QUEUE_V(ep->rss_qid)); 20175be78ee9SVipul Pandya if (enable_tcp_timestamps) 20186c53e938SHariprasad Shenai req->tcb.opt2 |= (__force __be32)TSTAMPS_EN_F; 20195be78ee9SVipul Pandya if (enable_tcp_sack) 20206c53e938SHariprasad Shenai req->tcb.opt2 |= (__force __be32)SACK_EN_F; 20215be78ee9SVipul Pandya if (wscale && enable_tcp_window_scaling) 2022d7990b0cSAnish Bhatt req->tcb.opt2 |= (__force __be32)WND_SCALE_EN_F; 2023ef5d6355SVipul Pandya req->tcb.opt0 = cpu_to_be64((__force u64)req->tcb.opt0); 2024ef5d6355SVipul Pandya req->tcb.opt2 = cpu_to_be32((__force u32)req->tcb.opt2); 2025793dad94SVipul Pandya set_wr_txq(skb, CPL_PRIORITY_CONTROL, ep->ctrlq_idx); 2026793dad94SVipul Pandya set_bit(ACT_OFLD_CONN, &ep->com.history); 2027caa6c9f2SHariprasad S return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 20285be78ee9SVipul Pandya } 20295be78ee9SVipul Pandya 2030cfdda9d7SSteve Wise /* 20314c72efefSHariprasad S * Some of the error codes above implicitly indicate that there is no TID 20324c72efefSHariprasad S * allocated with the result of an ACT_OPEN. We use this predicate to make 20334c72efefSHariprasad S * that explicit. 2034cfdda9d7SSteve Wise */ 2035cfdda9d7SSteve Wise static inline int act_open_has_tid(int status) 2036cfdda9d7SSteve Wise { 20374c72efefSHariprasad S return (status != CPL_ERR_TCAM_PARITY && 20384c72efefSHariprasad S status != CPL_ERR_TCAM_MISS && 20394c72efefSHariprasad S status != CPL_ERR_TCAM_FULL && 20404c72efefSHariprasad S status != CPL_ERR_CONN_EXIST_SYNRECV && 20414c72efefSHariprasad S status != CPL_ERR_CONN_EXIST); 2042cfdda9d7SSteve Wise } 2043cfdda9d7SSteve Wise 2044dd92b124SHariprasad Shenai static char *neg_adv_str(unsigned int status) 2045dd92b124SHariprasad Shenai { 2046dd92b124SHariprasad Shenai switch (status) { 2047dd92b124SHariprasad Shenai case CPL_ERR_RTX_NEG_ADVICE: 2048dd92b124SHariprasad Shenai return "Retransmit timeout"; 2049dd92b124SHariprasad Shenai case CPL_ERR_PERSIST_NEG_ADVICE: 2050dd92b124SHariprasad Shenai return "Persist timeout"; 2051dd92b124SHariprasad Shenai case CPL_ERR_KEEPALV_NEG_ADVICE: 2052dd92b124SHariprasad Shenai return "Keepalive timeout"; 2053dd92b124SHariprasad Shenai default: 2054dd92b124SHariprasad Shenai return "Unknown"; 2055dd92b124SHariprasad Shenai } 2056dd92b124SHariprasad Shenai } 2057dd92b124SHariprasad Shenai 2058b408ff28SHariprasad Shenai static void set_tcp_window(struct c4iw_ep *ep, struct port_info *pi) 2059b408ff28SHariprasad Shenai { 2060b408ff28SHariprasad Shenai ep->snd_win = snd_win; 2061b408ff28SHariprasad Shenai ep->rcv_win = rcv_win; 2062548ddb19SBharat Potnuri pr_debug("snd_win %d rcv_win %d\n", 2063548ddb19SBharat Potnuri ep->snd_win, ep->rcv_win); 2064b408ff28SHariprasad Shenai } 2065b408ff28SHariprasad Shenai 2066793dad94SVipul Pandya #define ACT_OPEN_RETRY_COUNT 2 2067793dad94SVipul Pandya 2068830662f6SVipul Pandya static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, 2069830662f6SVipul Pandya struct dst_entry *dst, struct c4iw_dev *cdev, 2070ac8e4c69SHariprasad S bool clear_mpa_v1, enum chip_type adapter_type, u8 tos) 2071830662f6SVipul Pandya { 2072830662f6SVipul Pandya struct neighbour *n; 2073830662f6SVipul Pandya int err, step; 2074830662f6SVipul Pandya struct net_device *pdev; 2075830662f6SVipul Pandya 2076830662f6SVipul Pandya n = dst_neigh_lookup(dst, peer_ip); 2077830662f6SVipul Pandya if (!n) 2078830662f6SVipul Pandya return -ENODEV; 2079830662f6SVipul Pandya 2080830662f6SVipul Pandya rcu_read_lock(); 2081830662f6SVipul Pandya err = -ENOMEM; 2082830662f6SVipul Pandya if (n->dev->flags & IFF_LOOPBACK) { 2083830662f6SVipul Pandya if (iptype == 4) 2084830662f6SVipul Pandya pdev = ip_dev_find(&init_net, *(__be32 *)peer_ip); 2085830662f6SVipul Pandya else if (IS_ENABLED(CONFIG_IPV6)) 2086830662f6SVipul Pandya for_each_netdev(&init_net, pdev) { 2087830662f6SVipul Pandya if (ipv6_chk_addr(&init_net, 2088830662f6SVipul Pandya (struct in6_addr *)peer_ip, 2089830662f6SVipul Pandya pdev, 1)) 2090830662f6SVipul Pandya break; 2091830662f6SVipul Pandya } 2092830662f6SVipul Pandya else 2093830662f6SVipul Pandya pdev = NULL; 2094830662f6SVipul Pandya 2095830662f6SVipul Pandya if (!pdev) { 2096830662f6SVipul Pandya err = -ENODEV; 2097830662f6SVipul Pandya goto out; 2098830662f6SVipul Pandya } 2099830662f6SVipul Pandya ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, 2100ac8e4c69SHariprasad S n, pdev, rt_tos2priority(tos)); 2101609e941aSSteve Wise if (!ep->l2t) { 2102609e941aSSteve Wise dev_put(pdev); 2103830662f6SVipul Pandya goto out; 2104609e941aSSteve Wise } 2105830662f6SVipul Pandya ep->mtu = pdev->mtu; 2106830662f6SVipul Pandya ep->tx_chan = cxgb4_port_chan(pdev); 210702d805dcSSantosh Rastapur ep->smac_idx = ((struct port_info *)netdev_priv(pdev))->smt_idx; 2108830662f6SVipul Pandya step = cdev->rdev.lldi.ntxq / 2109830662f6SVipul Pandya cdev->rdev.lldi.nchan; 2110830662f6SVipul Pandya ep->txq_idx = cxgb4_port_idx(pdev) * step; 2111830662f6SVipul Pandya step = cdev->rdev.lldi.nrxq / 2112830662f6SVipul Pandya cdev->rdev.lldi.nchan; 2113830662f6SVipul Pandya ep->ctrlq_idx = cxgb4_port_idx(pdev); 2114830662f6SVipul Pandya ep->rss_qid = cdev->rdev.lldi.rxq_ids[ 2115830662f6SVipul Pandya cxgb4_port_idx(pdev) * step]; 2116b408ff28SHariprasad Shenai set_tcp_window(ep, (struct port_info *)netdev_priv(pdev)); 2117830662f6SVipul Pandya dev_put(pdev); 2118830662f6SVipul Pandya } else { 2119830662f6SVipul Pandya pdev = get_real_dev(n->dev); 2120830662f6SVipul Pandya ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, 2121cb3ba0bdSSteve Wise n, pdev, rt_tos2priority(tos)); 2122830662f6SVipul Pandya if (!ep->l2t) 2123830662f6SVipul Pandya goto out; 2124830662f6SVipul Pandya ep->mtu = dst_mtu(dst); 212511b8e22dSSteve Wise ep->tx_chan = cxgb4_port_chan(pdev); 212602d805dcSSantosh Rastapur ep->smac_idx = ((struct port_info *)netdev_priv(pdev))->smt_idx; 2127830662f6SVipul Pandya step = cdev->rdev.lldi.ntxq / 2128830662f6SVipul Pandya cdev->rdev.lldi.nchan; 212911b8e22dSSteve Wise ep->txq_idx = cxgb4_port_idx(pdev) * step; 213011b8e22dSSteve Wise ep->ctrlq_idx = cxgb4_port_idx(pdev); 2131830662f6SVipul Pandya step = cdev->rdev.lldi.nrxq / 2132830662f6SVipul Pandya cdev->rdev.lldi.nchan; 2133830662f6SVipul Pandya ep->rss_qid = cdev->rdev.lldi.rxq_ids[ 213411b8e22dSSteve Wise cxgb4_port_idx(pdev) * step]; 2135b408ff28SHariprasad Shenai set_tcp_window(ep, (struct port_info *)netdev_priv(pdev)); 2136830662f6SVipul Pandya 2137830662f6SVipul Pandya if (clear_mpa_v1) { 2138830662f6SVipul Pandya ep->retry_with_mpa_v1 = 0; 2139830662f6SVipul Pandya ep->tried_with_mpa_v1 = 0; 2140830662f6SVipul Pandya } 2141830662f6SVipul Pandya } 2142830662f6SVipul Pandya err = 0; 2143830662f6SVipul Pandya out: 2144830662f6SVipul Pandya rcu_read_unlock(); 2145830662f6SVipul Pandya 2146830662f6SVipul Pandya neigh_release(n); 2147830662f6SVipul Pandya 2148830662f6SVipul Pandya return err; 2149830662f6SVipul Pandya } 2150830662f6SVipul Pandya 2151793dad94SVipul Pandya static int c4iw_reconnect(struct c4iw_ep *ep) 2152793dad94SVipul Pandya { 2153793dad94SVipul Pandya int err = 0; 21544a740838SHariprasad S int size = 0; 215524d44a39SSteve Wise struct sockaddr_in *laddr = (struct sockaddr_in *) 2156170003c8SSteve Wise &ep->com.cm_id->m_local_addr; 215724d44a39SSteve Wise struct sockaddr_in *raddr = (struct sockaddr_in *) 2158170003c8SSteve Wise &ep->com.cm_id->m_remote_addr; 2159830662f6SVipul Pandya struct sockaddr_in6 *laddr6 = (struct sockaddr_in6 *) 2160170003c8SSteve Wise &ep->com.cm_id->m_local_addr; 2161830662f6SVipul Pandya struct sockaddr_in6 *raddr6 = (struct sockaddr_in6 *) 2162170003c8SSteve Wise &ep->com.cm_id->m_remote_addr; 2163830662f6SVipul Pandya int iptype; 2164830662f6SVipul Pandya __u8 *ra; 2165793dad94SVipul Pandya 2166548ddb19SBharat Potnuri pr_debug("qp %p cm_id %p\n", ep->com.qp, ep->com.cm_id); 2167ef885dc6SSteve Wise c4iw_init_wr_wait(ep->com.wr_waitp); 2168793dad94SVipul Pandya 21694a740838SHariprasad S /* When MPA revision is different on nodes, the node with MPA_rev=2 21704a740838SHariprasad S * tries to reconnect with MPA_rev 1 for the same EP through 21714a740838SHariprasad S * c4iw_reconnect(), where the same EP is assigned with new tid for 21724a740838SHariprasad S * further connection establishment. As we are using the same EP pointer 21734a740838SHariprasad S * for reconnect, few skbs are used during the previous c4iw_connect(), 21744a740838SHariprasad S * which leaves the EP with inadequate skbs for further 2175ba97b749SSteve Wise * c4iw_reconnect(), Further causing a crash due to an empty 21764a740838SHariprasad S * skb_list() during peer_abort(). Allocate skbs which is already used. 21774a740838SHariprasad S */ 21784a740838SHariprasad S size = (CN_MAX_CON_BUF - skb_queue_len(&ep->com.ep_skb_list)); 21794a740838SHariprasad S if (alloc_ep_skb_list(&ep->com.ep_skb_list, size)) { 21804a740838SHariprasad S err = -ENOMEM; 21814a740838SHariprasad S goto fail1; 21824a740838SHariprasad S } 21834a740838SHariprasad S 2184793dad94SVipul Pandya /* 2185793dad94SVipul Pandya * Allocate an active TID to initiate a TCP connection. 2186793dad94SVipul Pandya */ 2187793dad94SVipul Pandya ep->atid = cxgb4_alloc_atid(ep->com.dev->rdev.lldi.tids, ep); 2188793dad94SVipul Pandya if (ep->atid == -1) { 2189700456bdSJoe Perches pr_err("%s - cannot alloc atid\n", __func__); 2190793dad94SVipul Pandya err = -ENOMEM; 2191793dad94SVipul Pandya goto fail2; 2192793dad94SVipul Pandya } 21939f5a9632SMatthew Wilcox err = xa_insert_irq(&ep->com.dev->atids, ep->atid, ep, GFP_KERNEL); 21949f5a9632SMatthew Wilcox if (err) 21959f5a9632SMatthew Wilcox goto fail2a; 2196793dad94SVipul Pandya 2197793dad94SVipul Pandya /* find a route */ 2198170003c8SSteve Wise if (ep->com.cm_id->m_local_addr.ss_family == AF_INET) { 2199804c2f3eSVarun Prakash ep->dst = cxgb_find_route(&ep->com.dev->rdev.lldi, get_real_dev, 2200804c2f3eSVarun Prakash laddr->sin_addr.s_addr, 2201804c2f3eSVarun Prakash raddr->sin_addr.s_addr, 2202804c2f3eSVarun Prakash laddr->sin_port, 2203ac8e4c69SHariprasad S raddr->sin_port, ep->com.cm_id->tos); 2204830662f6SVipul Pandya iptype = 4; 2205830662f6SVipul Pandya ra = (__u8 *)&raddr->sin_addr; 2206830662f6SVipul Pandya } else { 220795554761SVarun Prakash ep->dst = cxgb_find_route6(&ep->com.dev->rdev.lldi, 220895554761SVarun Prakash get_real_dev, 220995554761SVarun Prakash laddr6->sin6_addr.s6_addr, 2210830662f6SVipul Pandya raddr6->sin6_addr.s6_addr, 221195554761SVarun Prakash laddr6->sin6_port, 2212c8a7eb55SSteve Wise raddr6->sin6_port, 2213c8a7eb55SSteve Wise ep->com.cm_id->tos, 2214830662f6SVipul Pandya raddr6->sin6_scope_id); 2215830662f6SVipul Pandya iptype = 6; 2216830662f6SVipul Pandya ra = (__u8 *)&raddr6->sin6_addr; 2217830662f6SVipul Pandya } 2218830662f6SVipul Pandya if (!ep->dst) { 2219700456bdSJoe Perches pr_err("%s - cannot find route\n", __func__); 2220793dad94SVipul Pandya err = -EHOSTUNREACH; 2221793dad94SVipul Pandya goto fail3; 2222793dad94SVipul Pandya } 2223963cab50SHariprasad S err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, false, 2224ac8e4c69SHariprasad S ep->com.dev->rdev.lldi.adapter_type, 2225ac8e4c69SHariprasad S ep->com.cm_id->tos); 2226830662f6SVipul Pandya if (err) { 2227700456bdSJoe Perches pr_err("%s - cannot alloc l2e\n", __func__); 2228793dad94SVipul Pandya goto fail4; 2229793dad94SVipul Pandya } 2230793dad94SVipul Pandya 2231548ddb19SBharat Potnuri pr_debug("txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n", 2232548ddb19SBharat Potnuri ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid, 2233793dad94SVipul Pandya ep->l2t->idx); 2234793dad94SVipul Pandya 2235793dad94SVipul Pandya state_set(&ep->com, CONNECTING); 2236ac8e4c69SHariprasad S ep->tos = ep->com.cm_id->tos; 2237793dad94SVipul Pandya 2238793dad94SVipul Pandya /* send connect request to rnic */ 2239793dad94SVipul Pandya err = send_connect(ep); 2240793dad94SVipul Pandya if (!err) 2241793dad94SVipul Pandya goto out; 2242793dad94SVipul Pandya 2243793dad94SVipul Pandya cxgb4_l2t_release(ep->l2t); 2244793dad94SVipul Pandya fail4: 2245793dad94SVipul Pandya dst_release(ep->dst); 2246793dad94SVipul Pandya fail3: 22479f5a9632SMatthew Wilcox xa_erase_irq(&ep->com.dev->atids, ep->atid); 22489f5a9632SMatthew Wilcox fail2a: 2249793dad94SVipul Pandya cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid); 2250793dad94SVipul Pandya fail2: 2251793dad94SVipul Pandya /* 2252793dad94SVipul Pandya * remember to send notification to upper layer. 2253793dad94SVipul Pandya * We are in here so the upper layer is not aware that this is 2254793dad94SVipul Pandya * re-connect attempt and so, upper layer is still waiting for 2255793dad94SVipul Pandya * response of 1st connect request. 2256793dad94SVipul Pandya */ 2257793dad94SVipul Pandya connect_reply_upcall(ep, -ECONNRESET); 22584a740838SHariprasad S fail1: 2259793dad94SVipul Pandya c4iw_put_ep(&ep->com); 2260793dad94SVipul Pandya out: 2261793dad94SVipul Pandya return err; 2262793dad94SVipul Pandya } 2263793dad94SVipul Pandya 2264cfdda9d7SSteve Wise static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2265cfdda9d7SSteve Wise { 2266cfdda9d7SSteve Wise struct c4iw_ep *ep; 2267cfdda9d7SSteve Wise struct cpl_act_open_rpl *rpl = cplhdr(skb); 22686c53e938SHariprasad Shenai unsigned int atid = TID_TID_G(AOPEN_ATID_G( 2269cfdda9d7SSteve Wise ntohl(rpl->atid_status))); 2270cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 22716c53e938SHariprasad Shenai int status = AOPEN_STATUS_G(ntohl(rpl->atid_status)); 2272830662f6SVipul Pandya struct sockaddr_in *la; 2273830662f6SVipul Pandya struct sockaddr_in *ra; 2274830662f6SVipul Pandya struct sockaddr_in6 *la6; 2275830662f6SVipul Pandya struct sockaddr_in6 *ra6; 2276caa6c9f2SHariprasad S int ret = 0; 2277cfdda9d7SSteve Wise 2278cfdda9d7SSteve Wise ep = lookup_atid(t, atid); 2279170003c8SSteve Wise la = (struct sockaddr_in *)&ep->com.local_addr; 2280170003c8SSteve Wise ra = (struct sockaddr_in *)&ep->com.remote_addr; 2281170003c8SSteve Wise la6 = (struct sockaddr_in6 *)&ep->com.local_addr; 2282170003c8SSteve Wise ra6 = (struct sockaddr_in6 *)&ep->com.remote_addr; 2283cfdda9d7SSteve Wise 2284548ddb19SBharat Potnuri pr_debug("ep %p atid %u status %u errno %d\n", ep, atid, 2285cfdda9d7SSteve Wise status, status2errno(status)); 2286cfdda9d7SSteve Wise 2287b65eef0aSVarun Prakash if (cxgb_is_neg_adv(status)) { 2288548ddb19SBharat Potnuri pr_debug("Connection problems for atid %u status %u (%s)\n", 2289548ddb19SBharat Potnuri atid, status, neg_adv_str(status)); 2290179d03bbSHariprasad S ep->stats.connect_neg_adv++; 2291179d03bbSHariprasad S mutex_lock(&dev->rdev.stats.lock); 2292179d03bbSHariprasad S dev->rdev.stats.neg_adv++; 2293179d03bbSHariprasad S mutex_unlock(&dev->rdev.stats.lock); 2294cfdda9d7SSteve Wise return 0; 2295cfdda9d7SSteve Wise } 2296cfdda9d7SSteve Wise 2297793dad94SVipul Pandya set_bit(ACT_OPEN_RPL, &ep->com.history); 2298793dad94SVipul Pandya 2299d716a2a0SVipul Pandya /* 2300d716a2a0SVipul Pandya * Log interesting failures. 2301d716a2a0SVipul Pandya */ 2302d716a2a0SVipul Pandya switch (status) { 2303d716a2a0SVipul Pandya case CPL_ERR_CONN_RESET: 2304d716a2a0SVipul Pandya case CPL_ERR_CONN_TIMEDOUT: 2305d716a2a0SVipul Pandya break; 23065be78ee9SVipul Pandya case CPL_ERR_TCAM_FULL: 23075be78ee9SVipul Pandya mutex_lock(&dev->rdev.stats.lock); 2308830662f6SVipul Pandya dev->rdev.stats.tcam_full++; 23095be78ee9SVipul Pandya mutex_unlock(&dev->rdev.stats.lock); 2310830662f6SVipul Pandya if (ep->com.local_addr.ss_family == AF_INET && 2311830662f6SVipul Pandya dev->rdev.lldi.enable_fw_ofld_conn) { 2312caa6c9f2SHariprasad S ret = send_fw_act_open_req(ep, TID_TID_G(AOPEN_ATID_G( 2313793dad94SVipul Pandya ntohl(rpl->atid_status)))); 2314caa6c9f2SHariprasad S if (ret) 2315caa6c9f2SHariprasad S goto fail; 23165be78ee9SVipul Pandya return 0; 2317793dad94SVipul Pandya } 2318793dad94SVipul Pandya break; 2319793dad94SVipul Pandya case CPL_ERR_CONN_EXIST: 2320793dad94SVipul Pandya if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) { 2321793dad94SVipul Pandya set_bit(ACT_RETRY_INUSE, &ep->com.history); 232284cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 232384cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 232484cc6ac6SHariprasad S (struct sockaddr_in6 *) 2325170003c8SSteve Wise &ep->com.local_addr; 232684cc6ac6SHariprasad S cxgb4_clip_release( 232784cc6ac6SHariprasad S ep->com.dev->rdev.lldi.ports[0], 232884cc6ac6SHariprasad S (const u32 *) 232984cc6ac6SHariprasad S &sin6->sin6_addr.s6_addr, 1); 233084cc6ac6SHariprasad S } 23319f5a9632SMatthew Wilcox xa_erase_irq(&ep->com.dev->atids, atid); 2332793dad94SVipul Pandya cxgb4_free_atid(t, atid); 2333793dad94SVipul Pandya dst_release(ep->dst); 2334793dad94SVipul Pandya cxgb4_l2t_release(ep->l2t); 2335793dad94SVipul Pandya c4iw_reconnect(ep); 2336793dad94SVipul Pandya return 0; 2337793dad94SVipul Pandya } 23385be78ee9SVipul Pandya break; 2339d716a2a0SVipul Pandya default: 2340830662f6SVipul Pandya if (ep->com.local_addr.ss_family == AF_INET) { 2341830662f6SVipul Pandya pr_info("Active open failure - atid %u status %u errno %d %pI4:%u->%pI4:%u\n", 2342d716a2a0SVipul Pandya atid, status, status2errno(status), 2343830662f6SVipul Pandya &la->sin_addr.s_addr, ntohs(la->sin_port), 2344830662f6SVipul Pandya &ra->sin_addr.s_addr, ntohs(ra->sin_port)); 2345830662f6SVipul Pandya } else { 2346830662f6SVipul Pandya pr_info("Active open failure - atid %u status %u errno %d %pI6:%u->%pI6:%u\n", 2347830662f6SVipul Pandya atid, status, status2errno(status), 2348830662f6SVipul Pandya la6->sin6_addr.s6_addr, ntohs(la6->sin6_port), 2349830662f6SVipul Pandya ra6->sin6_addr.s6_addr, ntohs(ra6->sin6_port)); 2350830662f6SVipul Pandya } 2351d716a2a0SVipul Pandya break; 2352d716a2a0SVipul Pandya } 2353d716a2a0SVipul Pandya 2354caa6c9f2SHariprasad S fail: 2355cfdda9d7SSteve Wise connect_reply_upcall(ep, status2errno(status)); 2356cfdda9d7SSteve Wise state_set(&ep->com, DEAD); 2357cfdda9d7SSteve Wise 235884cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 235984cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 2360170003c8SSteve Wise (struct sockaddr_in6 *)&ep->com.local_addr; 236184cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 236284cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 236384cc6ac6SHariprasad S } 2364cfdda9d7SSteve Wise if (status && act_open_has_tid(status)) 23651dec4cecSGanesh Goudar cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, GET_TID(rpl), 23661dec4cecSGanesh Goudar ep->com.local_addr.ss_family); 2367cfdda9d7SSteve Wise 23689f5a9632SMatthew Wilcox xa_erase_irq(&ep->com.dev->atids, atid); 2369cfdda9d7SSteve Wise cxgb4_free_atid(t, atid); 2370cfdda9d7SSteve Wise dst_release(ep->dst); 2371cfdda9d7SSteve Wise cxgb4_l2t_release(ep->l2t); 2372cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 2373cfdda9d7SSteve Wise 2374cfdda9d7SSteve Wise return 0; 2375cfdda9d7SSteve Wise } 2376cfdda9d7SSteve Wise 2377cfdda9d7SSteve Wise static int pass_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2378cfdda9d7SSteve Wise { 2379cfdda9d7SSteve Wise struct cpl_pass_open_rpl *rpl = cplhdr(skb); 2380cfdda9d7SSteve Wise unsigned int stid = GET_TID(rpl); 2381f86fac79SHariprasad S struct c4iw_listen_ep *ep = get_ep_from_stid(dev, stid); 2382cfdda9d7SSteve Wise 2383cfdda9d7SSteve Wise if (!ep) { 23844d45b757SBharat Potnuri pr_warn("%s stid %d lookup failure!\n", __func__, stid); 23851cab775cSVipul Pandya goto out; 2386cfdda9d7SSteve Wise } 2387548ddb19SBharat Potnuri pr_debug("ep %p status %d error %d\n", ep, 2388cfdda9d7SSteve Wise rpl->status, status2errno(rpl->status)); 23892015f26cSSteve Wise c4iw_wake_up_noref(ep->com.wr_waitp, status2errno(rpl->status)); 2390f86fac79SHariprasad S c4iw_put_ep(&ep->com); 23911cab775cSVipul Pandya out: 2392cfdda9d7SSteve Wise return 0; 2393cfdda9d7SSteve Wise } 2394cfdda9d7SSteve Wise 2395cfdda9d7SSteve Wise static int close_listsrv_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2396cfdda9d7SSteve Wise { 2397cfdda9d7SSteve Wise struct cpl_close_listsvr_rpl *rpl = cplhdr(skb); 2398cfdda9d7SSteve Wise unsigned int stid = GET_TID(rpl); 2399f86fac79SHariprasad S struct c4iw_listen_ep *ep = get_ep_from_stid(dev, stid); 2400cfdda9d7SSteve Wise 24013c8415ccSSteve Wise if (!ep) { 24024d45b757SBharat Potnuri pr_warn("%s stid %d lookup failure!\n", __func__, stid); 24033c8415ccSSteve Wise goto out; 24043c8415ccSSteve Wise } 2405548ddb19SBharat Potnuri pr_debug("ep %p\n", ep); 24062015f26cSSteve Wise c4iw_wake_up_noref(ep->com.wr_waitp, status2errno(rpl->status)); 2407f86fac79SHariprasad S c4iw_put_ep(&ep->com); 24083c8415ccSSteve Wise out: 2409cfdda9d7SSteve Wise return 0; 2410cfdda9d7SSteve Wise } 2411cfdda9d7SSteve Wise 24129dec900cSHariprasad S static int accept_cr(struct c4iw_ep *ep, struct sk_buff *skb, 2413cfdda9d7SSteve Wise struct cpl_pass_accept_req *req) 2414cfdda9d7SSteve Wise { 2415cfdda9d7SSteve Wise struct cpl_pass_accept_rpl *rpl; 2416cfdda9d7SSteve Wise unsigned int mtu_idx; 2417cfdda9d7SSteve Wise u64 opt0; 2418cfdda9d7SSteve Wise u32 opt2; 2419cc516700SVarun Prakash u32 wscale; 242092e7ae71SHariprasad Shenai struct cpl_t5_pass_accept_rpl *rpl5 = NULL; 2421b408ff28SHariprasad Shenai int win; 2422963cab50SHariprasad S enum chip_type adapter_type = ep->com.dev->rdev.lldi.adapter_type; 2423cfdda9d7SSteve Wise 2424548ddb19SBharat Potnuri pr_debug("ep %p tid %u\n", ep, ep->hwtid); 242544c6d069SVarun Prakash cxgb_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, 242604524a47SHariprasad S enable_tcp_timestamps && req->tcpopt.tstamp, 242744c6d069SVarun Prakash (ep->com.remote_addr.ss_family == AF_INET) ? 0 : 1); 2428cc516700SVarun Prakash wscale = cxgb_compute_wscale(rcv_win); 2429b408ff28SHariprasad Shenai 2430b408ff28SHariprasad Shenai /* 2431b408ff28SHariprasad Shenai * Specify the largest window that will fit in opt0. The 2432b408ff28SHariprasad Shenai * remainder will be specified in the rx_data_ack. 2433b408ff28SHariprasad Shenai */ 2434b408ff28SHariprasad Shenai win = ep->rcv_win >> 10; 2435d7990b0cSAnish Bhatt if (win > RCV_BUFSIZ_M) 2436d7990b0cSAnish Bhatt win = RCV_BUFSIZ_M; 24376c53e938SHariprasad Shenai opt0 = (nocong ? NO_CONG_F : 0) | 2438d7990b0cSAnish Bhatt KEEP_ALIVE_F | 24396c53e938SHariprasad Shenai DELACK_F | 2440d7990b0cSAnish Bhatt WND_SCALE_V(wscale) | 2441d7990b0cSAnish Bhatt MSS_IDX_V(mtu_idx) | 2442d7990b0cSAnish Bhatt L2T_IDX_V(ep->l2t->idx) | 2443d7990b0cSAnish Bhatt TX_CHAN_V(ep->tx_chan) | 2444d7990b0cSAnish Bhatt SMAC_SEL_V(ep->smac_idx) | 24456c53e938SHariprasad Shenai DSCP_V(ep->tos >> 2) | 2446d7990b0cSAnish Bhatt ULP_MODE_V(ULP_MODE_TCPDDP) | 2447d7990b0cSAnish Bhatt RCV_BUFSIZ_V(win); 2448d7990b0cSAnish Bhatt opt2 = RX_CHANNEL_V(0) | 2449d7990b0cSAnish Bhatt RSS_QUEUE_VALID_F | RSS_QUEUE_V(ep->rss_qid); 2450cfdda9d7SSteve Wise 2451cfdda9d7SSteve Wise if (enable_tcp_timestamps && req->tcpopt.tstamp) 24526c53e938SHariprasad Shenai opt2 |= TSTAMPS_EN_F; 2453cfdda9d7SSteve Wise if (enable_tcp_sack && req->tcpopt.sack) 24546c53e938SHariprasad Shenai opt2 |= SACK_EN_F; 2455cfdda9d7SSteve Wise if (wscale && enable_tcp_window_scaling) 2456d7990b0cSAnish Bhatt opt2 |= WND_SCALE_EN_F; 24575be78ee9SVipul Pandya if (enable_ecn) { 24585be78ee9SVipul Pandya const struct tcphdr *tcph; 24595be78ee9SVipul Pandya u32 hlen = ntohl(req->hdr_len); 24605be78ee9SVipul Pandya 2461963cab50SHariprasad S if (CHELSIO_CHIP_VERSION(adapter_type) <= CHELSIO_T5) 2462cf7fe64aSHariprasad Shenai tcph = (const void *)(req + 1) + ETH_HDR_LEN_G(hlen) + 2463cf7fe64aSHariprasad Shenai IP_HDR_LEN_G(hlen); 2464963cab50SHariprasad S else 2465963cab50SHariprasad S tcph = (const void *)(req + 1) + 2466963cab50SHariprasad S T6_ETH_HDR_LEN_G(hlen) + T6_IP_HDR_LEN_G(hlen); 24675be78ee9SVipul Pandya if (tcph->ece && tcph->cwr) 24686c53e938SHariprasad Shenai opt2 |= CCTRL_ECN_V(1); 24695be78ee9SVipul Pandya } 2470612e0486SPotnuri Bharat Teja 2471612e0486SPotnuri Bharat Teja if (!is_t4(adapter_type)) { 2472a251c17aSJason A. Donenfeld u32 isn = (get_random_u32() & ~7UL) - 1; 2473ef016229SPotnuri Bharat Teja 2474ef016229SPotnuri Bharat Teja skb = get_skb(skb, roundup(sizeof(*rpl5), 16), GFP_KERNEL); 2475ef016229SPotnuri Bharat Teja rpl5 = __skb_put_zero(skb, roundup(sizeof(*rpl5), 16)); 2476ef016229SPotnuri Bharat Teja rpl = (void *)rpl5; 2477ef016229SPotnuri Bharat Teja INIT_TP_WR_CPL(rpl5, CPL_PASS_ACCEPT_RPL, ep->hwtid); 2478d7990b0cSAnish Bhatt opt2 |= T5_OPT_2_VALID_F; 2479cf7fe64aSHariprasad Shenai opt2 |= CONG_CNTRL_V(CONG_ALG_TAHOE); 24800b741047SHariprasad S opt2 |= T5_ISS_F; 248192e7ae71SHariprasad Shenai if (peer2peer) 248292e7ae71SHariprasad Shenai isn += 4; 248392e7ae71SHariprasad Shenai rpl5->iss = cpu_to_be32(isn); 2484548ddb19SBharat Potnuri pr_debug("iss %u\n", be32_to_cpu(rpl5->iss)); 2485ef016229SPotnuri Bharat Teja } else { 2486ef016229SPotnuri Bharat Teja skb = get_skb(skb, sizeof(*rpl), GFP_KERNEL); 2487ef016229SPotnuri Bharat Teja rpl = __skb_put_zero(skb, sizeof(*rpl)); 2488ef016229SPotnuri Bharat Teja INIT_TP_WR_CPL(rpl, CPL_PASS_ACCEPT_RPL, ep->hwtid); 248992e5011aSSteve Wise } 2490cfdda9d7SSteve Wise 2491cfdda9d7SSteve Wise rpl->opt0 = cpu_to_be64(opt0); 2492cfdda9d7SSteve Wise rpl->opt2 = cpu_to_be32(opt2); 2493d4f1a5c6SSteve Wise set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->ctrlq_idx); 24949dec900cSHariprasad S t4_set_arp_err_handler(skb, ep, pass_accept_rpl_arp_failure); 2495cfdda9d7SSteve Wise 24969dec900cSHariprasad S return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 2497cfdda9d7SSteve Wise } 2498cfdda9d7SSteve Wise 2499830662f6SVipul Pandya static void reject_cr(struct c4iw_dev *dev, u32 hwtid, struct sk_buff *skb) 2500cfdda9d7SSteve Wise { 2501548ddb19SBharat Potnuri pr_debug("c4iw_dev %p tid %u\n", dev, hwtid); 2502cfdda9d7SSteve Wise skb_trim(skb, sizeof(struct cpl_tid_release)); 2503cfdda9d7SSteve Wise release_tid(&dev->rdev, hwtid, skb); 2504cfdda9d7SSteve Wise return; 2505cfdda9d7SSteve Wise } 2506cfdda9d7SSteve Wise 2507cfdda9d7SSteve Wise static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) 2508cfdda9d7SSteve Wise { 2509793dad94SVipul Pandya struct c4iw_ep *child_ep = NULL, *parent_ep; 2510cfdda9d7SSteve Wise struct cpl_pass_accept_req *req = cplhdr(skb); 25116c53e938SHariprasad Shenai unsigned int stid = PASS_OPEN_TID_G(ntohl(req->tos_stid)); 2512cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 2513cfdda9d7SSteve Wise unsigned int hwtid = GET_TID(req); 2514cfdda9d7SSteve Wise struct dst_entry *dst; 2515830662f6SVipul Pandya __u8 local_ip[16], peer_ip[16]; 2516cfdda9d7SSteve Wise __be16 local_port, peer_port; 251784cc6ac6SHariprasad S struct sockaddr_in6 *sin6; 25183786cf18SDavid Miller int err; 25191cab775cSVipul Pandya u16 peer_mss = ntohs(req->tcpopt.mss); 2520830662f6SVipul Pandya int iptype; 252192e7ae71SHariprasad Shenai unsigned short hdrs; 25227235ea22SSteve Wise u8 tos; 2523cfdda9d7SSteve Wise 2524f86fac79SHariprasad S parent_ep = (struct c4iw_ep *)get_ep_from_stid(dev, stid); 25251cab775cSVipul Pandya if (!parent_ep) { 25264d45b757SBharat Potnuri pr_err("%s connect request on invalid stid %d\n", 2527a9a42886SJoe Perches __func__, stid); 25281cab775cSVipul Pandya goto reject; 25291cab775cSVipul Pandya } 25301cab775cSVipul Pandya 2531cfdda9d7SSteve Wise if (state_read(&parent_ep->com) != LISTEN) { 25324d45b757SBharat Potnuri pr_err("%s - listening ep not in LISTEN\n", __func__); 2533cfdda9d7SSteve Wise goto reject; 2534cfdda9d7SSteve Wise } 2535cfdda9d7SSteve Wise 25367235ea22SSteve Wise if (parent_ep->com.cm_id->tos_set) 25377235ea22SSteve Wise tos = parent_ep->com.cm_id->tos; 25387235ea22SSteve Wise else 25397235ea22SSteve Wise tos = PASS_OPEN_TOS_G(ntohl(req->tos_stid)); 25407235ea22SSteve Wise 254185e42b04SVarun Prakash cxgb_get_4tuple(req, parent_ep->com.dev->rdev.lldi.adapter_type, 254285e42b04SVarun Prakash &iptype, local_ip, peer_ip, &local_port, &peer_port); 2543830662f6SVipul Pandya 2544cfdda9d7SSteve Wise /* Find output route */ 2545830662f6SVipul Pandya if (iptype == 4) { 2546548ddb19SBharat Potnuri pr_debug("parent ep %p hwtid %u laddr %pI4 raddr %pI4 lport %d rport %d peer_mss %d\n" 2547548ddb19SBharat Potnuri , parent_ep, hwtid, 2548830662f6SVipul Pandya local_ip, peer_ip, ntohs(local_port), 2549830662f6SVipul Pandya ntohs(peer_port), peer_mss); 2550804c2f3eSVarun Prakash dst = cxgb_find_route(&dev->rdev.lldi, get_real_dev, 2551804c2f3eSVarun Prakash *(__be32 *)local_ip, *(__be32 *)peer_ip, 2552804c2f3eSVarun Prakash local_port, peer_port, tos); 2553830662f6SVipul Pandya } else { 2554548ddb19SBharat Potnuri pr_debug("parent ep %p hwtid %u laddr %pI6 raddr %pI6 lport %d rport %d peer_mss %d\n" 2555548ddb19SBharat Potnuri , parent_ep, hwtid, 2556830662f6SVipul Pandya local_ip, peer_ip, ntohs(local_port), 2557830662f6SVipul Pandya ntohs(peer_port), peer_mss); 255895554761SVarun Prakash dst = cxgb_find_route6(&dev->rdev.lldi, get_real_dev, 255995554761SVarun Prakash local_ip, peer_ip, local_port, peer_port, 25607235ea22SSteve Wise tos, 2561830662f6SVipul Pandya ((struct sockaddr_in6 *) 2562830662f6SVipul Pandya &parent_ep->com.local_addr)->sin6_scope_id); 2563830662f6SVipul Pandya } 2564830662f6SVipul Pandya if (!dst) { 2565700456bdSJoe Perches pr_err("%s - failed to find dst entry!\n", __func__); 2566cfdda9d7SSteve Wise goto reject; 2567cfdda9d7SSteve Wise } 2568cfdda9d7SSteve Wise 2569cfdda9d7SSteve Wise child_ep = alloc_ep(sizeof(*child_ep), GFP_KERNEL); 2570cfdda9d7SSteve Wise if (!child_ep) { 2571700456bdSJoe Perches pr_err("%s - failed to allocate ep entry!\n", __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) { 2579700456bdSJoe Perches pr_err("%s - failed to allocate l2t entry!\n", __func__); 25803786cf18SDavid Miller dst_release(dst); 25813786cf18SDavid Miller kfree(child_ep); 25823786cf18SDavid Miller goto reject; 25833786cf18SDavid Miller } 25843786cf18SDavid Miller 258598b80a2aSRaju Rangoju hdrs = ((iptype == 4) ? sizeof(struct iphdr) : sizeof(struct ipv6hdr)) + 258698b80a2aSRaju Rangoju 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 25914a740838SHariprasad S skb_queue_head_init(&child_ep->com.ep_skb_list); 25924a740838SHariprasad S if (alloc_ep_skb_list(&child_ep->com.ep_skb_list, CN_MAX_CON_BUF)) 25934a740838SHariprasad S goto fail; 25944a740838SHariprasad S 2595cfdda9d7SSteve Wise state_set(&child_ep->com, CONNECTING); 2596cfdda9d7SSteve Wise child_ep->com.dev = dev; 2597cfdda9d7SSteve Wise child_ep->com.cm_id = NULL; 25985b6b8fe6SSteve Wise 2599830662f6SVipul Pandya if (iptype == 4) { 2600830662f6SVipul Pandya struct sockaddr_in *sin = (struct sockaddr_in *) 2601170003c8SSteve Wise &child_ep->com.local_addr; 26025b6b8fe6SSteve Wise 2603b462b06eSssh10 sin->sin_family = AF_INET; 2604830662f6SVipul Pandya sin->sin_port = local_port; 2605830662f6SVipul Pandya sin->sin_addr.s_addr = *(__be32 *)local_ip; 26065b6b8fe6SSteve Wise 26075b6b8fe6SSteve Wise sin = (struct sockaddr_in *)&child_ep->com.local_addr; 2608b462b06eSssh10 sin->sin_family = AF_INET; 26095b6b8fe6SSteve Wise sin->sin_port = ((struct sockaddr_in *) 26105b6b8fe6SSteve Wise &parent_ep->com.local_addr)->sin_port; 26115b6b8fe6SSteve Wise sin->sin_addr.s_addr = *(__be32 *)local_ip; 26125b6b8fe6SSteve Wise 2613170003c8SSteve Wise sin = (struct sockaddr_in *)&child_ep->com.remote_addr; 2614b462b06eSssh10 sin->sin_family = AF_INET; 2615830662f6SVipul Pandya sin->sin_port = peer_port; 2616830662f6SVipul Pandya sin->sin_addr.s_addr = *(__be32 *)peer_ip; 2617830662f6SVipul Pandya } else { 2618170003c8SSteve Wise sin6 = (struct sockaddr_in6 *)&child_ep->com.local_addr; 2619830662f6SVipul Pandya sin6->sin6_family = PF_INET6; 2620830662f6SVipul Pandya sin6->sin6_port = local_port; 2621830662f6SVipul Pandya memcpy(sin6->sin6_addr.s6_addr, local_ip, 16); 26225b6b8fe6SSteve Wise 26235b6b8fe6SSteve Wise sin6 = (struct sockaddr_in6 *)&child_ep->com.local_addr; 26245b6b8fe6SSteve Wise sin6->sin6_family = PF_INET6; 26255b6b8fe6SSteve Wise sin6->sin6_port = ((struct sockaddr_in6 *) 26265b6b8fe6SSteve Wise &parent_ep->com.local_addr)->sin6_port; 26275b6b8fe6SSteve Wise memcpy(sin6->sin6_addr.s6_addr, local_ip, 16); 26285b6b8fe6SSteve Wise 2629170003c8SSteve Wise sin6 = (struct sockaddr_in6 *)&child_ep->com.remote_addr; 2630830662f6SVipul Pandya sin6->sin6_family = PF_INET6; 2631830662f6SVipul Pandya sin6->sin6_port = peer_port; 2632830662f6SVipul Pandya memcpy(sin6->sin6_addr.s6_addr, peer_ip, 16); 2633830662f6SVipul Pandya } 26345b6b8fe6SSteve Wise 2635cfdda9d7SSteve Wise c4iw_get_ep(&parent_ep->com); 2636cfdda9d7SSteve Wise child_ep->parent_ep = parent_ep; 2637ac8e4c69SHariprasad S child_ep->tos = tos; 2638cfdda9d7SSteve Wise child_ep->dst = dst; 2639cfdda9d7SSteve Wise child_ep->hwtid = hwtid; 2640cfdda9d7SSteve Wise 2641548ddb19SBharat Potnuri pr_debug("tx_chan %u smac_idx %u rss_qid %u\n", 26423786cf18SDavid Miller child_ep->tx_chan, child_ep->smac_idx, child_ep->rss_qid); 2643cfdda9d7SSteve Wise 2644a9346abeSKees Cook timer_setup(&child_ep->timer, ep_timeout, 0); 26451dec4cecSGanesh Goudar cxgb4_insert_tid(t, child_ep, hwtid, 26461dec4cecSGanesh Goudar child_ep->com.local_addr.ss_family); 2647944661ddSHariprasad S insert_ep_tid(child_ep); 26489dec900cSHariprasad S if (accept_cr(child_ep, skb, req)) { 26499dec900cSHariprasad S c4iw_put_ep(&parent_ep->com); 26509dec900cSHariprasad S release_ep_resources(child_ep); 26519dec900cSHariprasad S } else { 2652793dad94SVipul Pandya set_bit(PASS_ACCEPT_REQ, &child_ep->com.history); 26539dec900cSHariprasad S } 265484cc6ac6SHariprasad S if (iptype == 6) { 2655170003c8SSteve Wise sin6 = (struct sockaddr_in6 *)&child_ep->com.local_addr; 265684cc6ac6SHariprasad S cxgb4_clip_get(child_ep->com.dev->rdev.lldi.ports[0], 265784cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 265884cc6ac6SHariprasad S } 2659cfdda9d7SSteve Wise goto out; 26604a740838SHariprasad S fail: 26614a740838SHariprasad S c4iw_put_ep(&child_ep->com); 2662cfdda9d7SSteve Wise reject: 2663830662f6SVipul Pandya reject_cr(dev, hwtid, skb); 26643d318605SSteve Wise out: 2665f86fac79SHariprasad S if (parent_ep) 2666f86fac79SHariprasad S c4iw_put_ep(&parent_ep->com); 2667cfdda9d7SSteve Wise return 0; 2668cfdda9d7SSteve Wise } 2669cfdda9d7SSteve Wise 2670cfdda9d7SSteve Wise static int pass_establish(struct c4iw_dev *dev, struct sk_buff *skb) 2671cfdda9d7SSteve Wise { 2672cfdda9d7SSteve Wise struct c4iw_ep *ep; 2673cfdda9d7SSteve Wise struct cpl_pass_establish *req = cplhdr(skb); 2674cfdda9d7SSteve Wise unsigned int tid = GET_TID(req); 2675fef4422dSHariprasad S int ret; 26762e51e45cSPotnuri Bharat Teja u16 tcp_opt = ntohs(req->tcp_opt); 2677cfdda9d7SSteve Wise 2678944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 2679548ddb19SBharat Potnuri pr_debug("ep %p tid %u\n", ep, ep->hwtid); 2680cfdda9d7SSteve Wise ep->snd_seq = be32_to_cpu(req->snd_isn); 2681cfdda9d7SSteve Wise ep->rcv_seq = be32_to_cpu(req->rcv_isn); 26822e51e45cSPotnuri Bharat Teja ep->snd_wscale = TCPOPT_SND_WSCALE_G(tcp_opt); 2683cfdda9d7SSteve Wise 26842e51e45cSPotnuri Bharat Teja pr_debug("ep %p hwtid %u tcp_opt 0x%02x\n", ep, tid, tcp_opt); 26851cab775cSVipul Pandya 26862e51e45cSPotnuri Bharat Teja set_emss(ep, tcp_opt); 2687cfdda9d7SSteve Wise 2688cfdda9d7SSteve Wise dst_confirm(ep->dst); 2689fef4422dSHariprasad S mutex_lock(&ep->com.mutex); 2690fef4422dSHariprasad S ep->com.state = MPA_REQ_WAIT; 2691cfdda9d7SSteve Wise start_ep_timer(ep); 2692793dad94SVipul Pandya set_bit(PASS_ESTAB, &ep->com.history); 26934a740838SHariprasad S ret = send_flowc(ep); 2694fef4422dSHariprasad S mutex_unlock(&ep->com.mutex); 2695fef4422dSHariprasad S if (ret) 2696fef4422dSHariprasad S c4iw_ep_disconnect(ep, 1, GFP_KERNEL); 2697944661ddSHariprasad S c4iw_put_ep(&ep->com); 2698cfdda9d7SSteve Wise 2699cfdda9d7SSteve Wise return 0; 2700cfdda9d7SSteve Wise } 2701cfdda9d7SSteve Wise 2702cfdda9d7SSteve Wise static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb) 2703cfdda9d7SSteve Wise { 2704cfdda9d7SSteve Wise struct cpl_peer_close *hdr = cplhdr(skb); 2705cfdda9d7SSteve Wise struct c4iw_ep *ep; 2706cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 2707cfdda9d7SSteve Wise int disconnect = 1; 2708cfdda9d7SSteve Wise int release = 0; 2709cfdda9d7SSteve Wise unsigned int tid = GET_TID(hdr); 27108da7e7a5SSteve Wise int ret; 2711cfdda9d7SSteve Wise 2712944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 2713944661ddSHariprasad S if (!ep) 2714944661ddSHariprasad S return 0; 2715944661ddSHariprasad S 2716548ddb19SBharat Potnuri pr_debug("ep %p tid %u\n", ep, ep->hwtid); 2717cfdda9d7SSteve Wise dst_confirm(ep->dst); 2718cfdda9d7SSteve Wise 2719793dad94SVipul Pandya set_bit(PEER_CLOSE, &ep->com.history); 27202f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 2721cfdda9d7SSteve Wise switch (ep->com.state) { 2722cfdda9d7SSteve Wise case MPA_REQ_WAIT: 2723cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2724cfdda9d7SSteve Wise break; 2725cfdda9d7SSteve Wise case MPA_REQ_SENT: 2726cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2727cfdda9d7SSteve Wise connect_reply_upcall(ep, -ECONNRESET); 2728cfdda9d7SSteve Wise break; 2729cfdda9d7SSteve Wise case MPA_REQ_RCVD: 2730cfdda9d7SSteve Wise 2731cfdda9d7SSteve Wise /* 2732cfdda9d7SSteve Wise * We're gonna mark this puppy DEAD, but keep 2733cfdda9d7SSteve Wise * the reference on it until the ULP accepts or 2734cfdda9d7SSteve Wise * rejects the CR. Also wake up anyone waiting 2735cfdda9d7SSteve Wise * in rdma connection migration (see c4iw_accept_cr()). 2736cfdda9d7SSteve Wise */ 2737cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2738a9a42886SJoe Perches pr_debug("waking up ep %p tid %u\n", ep, ep->hwtid); 27392015f26cSSteve Wise c4iw_wake_up_noref(ep->com.wr_waitp, -ECONNRESET); 2740cfdda9d7SSteve Wise break; 2741cfdda9d7SSteve Wise case MPA_REP_SENT: 2742cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2743a9a42886SJoe Perches pr_debug("waking up ep %p tid %u\n", ep, ep->hwtid); 27442015f26cSSteve Wise c4iw_wake_up_noref(ep->com.wr_waitp, -ECONNRESET); 2745cfdda9d7SSteve Wise break; 2746cfdda9d7SSteve Wise case FPDU_MODE: 2747ca5a2202SSteve Wise start_ep_timer(ep); 2748cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 274930c95c2dSSteve Wise attrs.next_state = C4IW_QP_STATE_CLOSING; 27508da7e7a5SSteve Wise ret = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 275130c95c2dSSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 27528da7e7a5SSteve Wise if (ret != -ECONNRESET) { 2753cfdda9d7SSteve Wise peer_close_upcall(ep); 275430c95c2dSSteve Wise disconnect = 1; 27558da7e7a5SSteve Wise } 2756cfdda9d7SSteve Wise break; 2757cfdda9d7SSteve Wise case ABORTING: 2758cfdda9d7SSteve Wise disconnect = 0; 2759cfdda9d7SSteve Wise break; 2760cfdda9d7SSteve Wise case CLOSING: 2761cfdda9d7SSteve Wise __state_set(&ep->com, MORIBUND); 2762cfdda9d7SSteve Wise disconnect = 0; 2763cfdda9d7SSteve Wise break; 2764cfdda9d7SSteve Wise case MORIBUND: 2765b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 2766cfdda9d7SSteve Wise if (ep->com.cm_id && ep->com.qp) { 2767cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_IDLE; 2768cfdda9d7SSteve Wise c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 2769cfdda9d7SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 2770cfdda9d7SSteve Wise } 2771be13b2dfSSteve Wise close_complete_upcall(ep, 0); 2772cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 2773cfdda9d7SSteve Wise release = 1; 2774cfdda9d7SSteve Wise disconnect = 0; 2775cfdda9d7SSteve Wise break; 2776cfdda9d7SSteve Wise case DEAD: 2777cfdda9d7SSteve Wise disconnect = 0; 2778cfdda9d7SSteve Wise break; 2779cfdda9d7SSteve Wise default: 2780ba97b749SSteve Wise WARN_ONCE(1, "Bad endpoint state %u\n", ep->com.state); 2781cfdda9d7SSteve Wise } 27822f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 2783cfdda9d7SSteve Wise if (disconnect) 2784cfdda9d7SSteve Wise c4iw_ep_disconnect(ep, 0, GFP_KERNEL); 2785cfdda9d7SSteve Wise if (release) 2786cfdda9d7SSteve Wise release_ep_resources(ep); 2787944661ddSHariprasad S c4iw_put_ep(&ep->com); 2788cfdda9d7SSteve Wise return 0; 2789cfdda9d7SSteve Wise } 2790cfdda9d7SSteve Wise 279111a27e21SRaju Rangoju static void finish_peer_abort(struct c4iw_dev *dev, struct c4iw_ep *ep) 279211a27e21SRaju Rangoju { 279311a27e21SRaju Rangoju complete_cached_srq_buffers(ep, ep->srqe_idx); 279411a27e21SRaju Rangoju if (ep->com.cm_id && ep->com.qp) { 279511a27e21SRaju Rangoju struct c4iw_qp_attributes attrs; 279611a27e21SRaju Rangoju 279711a27e21SRaju Rangoju attrs.next_state = C4IW_QP_STATE_ERROR; 279811a27e21SRaju Rangoju c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 279911a27e21SRaju Rangoju C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 280011a27e21SRaju Rangoju } 280111a27e21SRaju Rangoju peer_abort_upcall(ep); 280211a27e21SRaju Rangoju release_ep_resources(ep); 280311a27e21SRaju Rangoju c4iw_put_ep(&ep->com); 280411a27e21SRaju Rangoju } 280511a27e21SRaju Rangoju 2806cfdda9d7SSteve Wise static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) 2807cfdda9d7SSteve Wise { 28086a0b6174SRaju Rangoju struct cpl_abort_req_rss6 *req = cplhdr(skb); 2809cfdda9d7SSteve Wise struct c4iw_ep *ep; 2810cfdda9d7SSteve Wise struct sk_buff *rpl_skb; 2811cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 2812cfdda9d7SSteve Wise int ret; 2813cfdda9d7SSteve Wise int release = 0; 2814cfdda9d7SSteve Wise unsigned int tid = GET_TID(req); 28156a0b6174SRaju Rangoju u8 status; 281611a27e21SRaju Rangoju u32 srqidx; 28176a0b6174SRaju Rangoju 2818052f4731SVarun Prakash u32 len = roundup(sizeof(struct cpl_abort_rpl), 16); 2819cfdda9d7SSteve Wise 2820944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 2821944661ddSHariprasad S if (!ep) 2822944661ddSHariprasad S return 0; 2823944661ddSHariprasad S 28246a0b6174SRaju Rangoju status = ABORT_RSS_STATUS_G(be32_to_cpu(req->srqidx_status)); 28256a0b6174SRaju Rangoju 28266a0b6174SRaju Rangoju if (cxgb_is_neg_adv(status)) { 2827f48fca4dSBharat Potnuri pr_debug("Negative advice on abort- tid %u status %d (%s)\n", 28286a0b6174SRaju Rangoju ep->hwtid, status, neg_adv_str(status)); 2829179d03bbSHariprasad S ep->stats.abort_neg_adv++; 2830179d03bbSHariprasad S mutex_lock(&dev->rdev.stats.lock); 2831179d03bbSHariprasad S dev->rdev.stats.neg_adv++; 2832179d03bbSHariprasad S mutex_unlock(&dev->rdev.stats.lock); 2833944661ddSHariprasad S goto deref_ep; 2834cfdda9d7SSteve Wise } 28356a0b6174SRaju Rangoju 2836548ddb19SBharat Potnuri pr_debug("ep %p tid %u state %u\n", ep, ep->hwtid, 2837cfdda9d7SSteve Wise ep->com.state); 2838793dad94SVipul Pandya set_bit(PEER_ABORT, &ep->com.history); 28392f5b48c3SSteve Wise 28402f5b48c3SSteve Wise /* 28412f5b48c3SSteve Wise * Wake up any threads in rdma_init() or rdma_fini(). 2842d2fe99e8SKumar Sanghvi * However, this is not needed if com state is just 2843d2fe99e8SKumar Sanghvi * MPA_REQ_SENT 28442f5b48c3SSteve Wise */ 2845d2fe99e8SKumar Sanghvi if (ep->com.state != MPA_REQ_SENT) 28462015f26cSSteve Wise c4iw_wake_up_noref(ep->com.wr_waitp, -ECONNRESET); 28472f5b48c3SSteve Wise 28482f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 2849cfdda9d7SSteve Wise switch (ep->com.state) { 2850cfdda9d7SSteve Wise case CONNECTING: 28519dec900cSHariprasad S c4iw_put_ep(&ep->parent_ep->com); 2852cfdda9d7SSteve Wise break; 2853cfdda9d7SSteve Wise case MPA_REQ_WAIT: 2854b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 2855cfdda9d7SSteve Wise break; 2856cfdda9d7SSteve Wise case MPA_REQ_SENT: 2857b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 28589828ca65SSteve Wise if (status != CPL_ERR_CONN_RESET || mpa_rev == 1 || 28599828ca65SSteve Wise (mpa_rev == 2 && ep->tried_with_mpa_v1)) 2860cfdda9d7SSteve Wise connect_reply_upcall(ep, -ECONNRESET); 2861d2fe99e8SKumar Sanghvi else { 2862d2fe99e8SKumar Sanghvi /* 2863d2fe99e8SKumar Sanghvi * we just don't send notification upwards because we 2864d2fe99e8SKumar Sanghvi * want to retry with mpa_v1 without upper layers even 2865d2fe99e8SKumar Sanghvi * knowing it. 2866d2fe99e8SKumar Sanghvi * 2867d2fe99e8SKumar Sanghvi * do some housekeeping so as to re-initiate the 2868d2fe99e8SKumar Sanghvi * connection 2869d2fe99e8SKumar Sanghvi */ 28704d45b757SBharat Potnuri pr_info("%s: mpa_rev=%d. Retrying with mpav1\n", 2871a9a42886SJoe Perches __func__, mpa_rev); 2872d2fe99e8SKumar Sanghvi ep->retry_with_mpa_v1 = 1; 2873d2fe99e8SKumar Sanghvi } 2874cfdda9d7SSteve Wise break; 2875cfdda9d7SSteve Wise case MPA_REP_SENT: 2876cfdda9d7SSteve Wise break; 2877cfdda9d7SSteve Wise case MPA_REQ_RCVD: 2878cfdda9d7SSteve Wise break; 2879cfdda9d7SSteve Wise case MORIBUND: 2880cfdda9d7SSteve Wise case CLOSING: 2881ca5a2202SSteve Wise stop_ep_timer(ep); 2882df561f66SGustavo A. R. Silva fallthrough; 2883cfdda9d7SSteve Wise case FPDU_MODE: 288411a27e21SRaju Rangoju if (ep->com.qp && ep->com.qp->srq) { 288511a27e21SRaju Rangoju srqidx = ABORT_RSS_SRQIDX_G( 288611a27e21SRaju Rangoju be32_to_cpu(req->srqidx_status)); 288711a27e21SRaju Rangoju if (srqidx) { 2888c8b1f340SPotnuri Bharat Teja complete_cached_srq_buffers(ep, srqidx); 288911a27e21SRaju Rangoju } else { 289011a27e21SRaju Rangoju /* Hold ep ref until finish_peer_abort() */ 289111a27e21SRaju Rangoju c4iw_get_ep(&ep->com); 289211a27e21SRaju Rangoju __state_set(&ep->com, ABORTING); 289311a27e21SRaju Rangoju set_bit(PEER_ABORT_IN_PROGRESS, &ep->com.flags); 289411a27e21SRaju Rangoju read_tcb(ep); 289511a27e21SRaju Rangoju break; 289611a27e21SRaju Rangoju 289711a27e21SRaju Rangoju } 289811a27e21SRaju Rangoju } 289911a27e21SRaju Rangoju 2900cfdda9d7SSteve Wise if (ep->com.cm_id && ep->com.qp) { 2901cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_ERROR; 2902cfdda9d7SSteve Wise ret = c4iw_modify_qp(ep->com.qp->rhp, 2903cfdda9d7SSteve Wise ep->com.qp, C4IW_QP_ATTR_NEXT_STATE, 2904cfdda9d7SSteve Wise &attrs, 1); 2905cfdda9d7SSteve Wise if (ret) 2906700456bdSJoe Perches pr_err("%s - qp <- error failed!\n", __func__); 2907cfdda9d7SSteve Wise } 2908cfdda9d7SSteve Wise peer_abort_upcall(ep); 2909cfdda9d7SSteve Wise break; 2910cfdda9d7SSteve Wise case ABORTING: 2911cfdda9d7SSteve Wise break; 2912cfdda9d7SSteve Wise case DEAD: 29134d45b757SBharat Potnuri pr_warn("%s PEER_ABORT IN DEAD STATE!!!!\n", __func__); 29142f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 2915944661ddSHariprasad S goto deref_ep; 2916cfdda9d7SSteve Wise default: 2917ba97b749SSteve Wise WARN_ONCE(1, "Bad endpoint state %u\n", ep->com.state); 2918cfdda9d7SSteve Wise break; 2919cfdda9d7SSteve Wise } 2920cfdda9d7SSteve Wise dst_confirm(ep->dst); 2921cfdda9d7SSteve Wise if (ep->com.state != ABORTING) { 2922cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 2923d2fe99e8SKumar Sanghvi /* we don't release if we want to retry with mpa_v1 */ 2924d2fe99e8SKumar Sanghvi if (!ep->retry_with_mpa_v1) 2925cfdda9d7SSteve Wise release = 1; 2926cfdda9d7SSteve Wise } 29272f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 2928cfdda9d7SSteve Wise 29294a740838SHariprasad S rpl_skb = skb_dequeue(&ep->com.ep_skb_list); 29304a740838SHariprasad S if (WARN_ON(!rpl_skb)) { 2931cfdda9d7SSteve Wise release = 1; 2932cfdda9d7SSteve Wise goto out; 2933cfdda9d7SSteve Wise } 2934052f4731SVarun Prakash 2935052f4731SVarun Prakash cxgb_mk_abort_rpl(rpl_skb, len, ep->hwtid, ep->txq_idx); 2936052f4731SVarun Prakash 2937cfdda9d7SSteve Wise c4iw_ofld_send(&ep->com.dev->rdev, rpl_skb); 2938cfdda9d7SSteve Wise out: 2939cfdda9d7SSteve Wise if (release) 2940cfdda9d7SSteve Wise release_ep_resources(ep); 2941fe7e0a4dSVipul Pandya else if (ep->retry_with_mpa_v1) { 294284cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 294384cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 294484cc6ac6SHariprasad S (struct sockaddr_in6 *) 2945170003c8SSteve Wise &ep->com.local_addr; 294684cc6ac6SHariprasad S cxgb4_clip_release( 294784cc6ac6SHariprasad S ep->com.dev->rdev.lldi.ports[0], 294884cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 294984cc6ac6SHariprasad S 1); 295084cc6ac6SHariprasad S } 2951f254ba6aSMatthew Wilcox xa_erase_irq(&ep->com.dev->hwtids, ep->hwtid); 29521dec4cecSGanesh Goudar cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid, 29531dec4cecSGanesh Goudar ep->com.local_addr.ss_family); 2954d2fe99e8SKumar Sanghvi dst_release(ep->dst); 2955d2fe99e8SKumar Sanghvi cxgb4_l2t_release(ep->l2t); 2956d2fe99e8SKumar Sanghvi c4iw_reconnect(ep); 2957d2fe99e8SKumar Sanghvi } 2958d2fe99e8SKumar Sanghvi 2959944661ddSHariprasad S deref_ep: 2960944661ddSHariprasad S c4iw_put_ep(&ep->com); 2961944661ddSHariprasad S /* Dereferencing ep, referenced in peer_abort_intr() */ 2962944661ddSHariprasad S c4iw_put_ep(&ep->com); 2963cfdda9d7SSteve Wise return 0; 2964cfdda9d7SSteve Wise } 2965cfdda9d7SSteve Wise 2966cfdda9d7SSteve Wise static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2967cfdda9d7SSteve Wise { 2968cfdda9d7SSteve Wise struct c4iw_ep *ep; 2969cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 2970cfdda9d7SSteve Wise struct cpl_close_con_rpl *rpl = cplhdr(skb); 2971cfdda9d7SSteve Wise int release = 0; 2972cfdda9d7SSteve Wise unsigned int tid = GET_TID(rpl); 2973cfdda9d7SSteve Wise 2974944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 2975944661ddSHariprasad S if (!ep) 2976944661ddSHariprasad S return 0; 2977cfdda9d7SSteve Wise 2978548ddb19SBharat Potnuri pr_debug("ep %p tid %u\n", ep, ep->hwtid); 2979cfdda9d7SSteve Wise 2980cfdda9d7SSteve Wise /* The cm_id may be null if we failed to connect */ 29812f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 29829ca6f7cfSHariprasad S set_bit(CLOSE_CON_RPL, &ep->com.history); 2983cfdda9d7SSteve Wise switch (ep->com.state) { 2984cfdda9d7SSteve Wise case CLOSING: 2985cfdda9d7SSteve Wise __state_set(&ep->com, MORIBUND); 2986cfdda9d7SSteve Wise break; 2987cfdda9d7SSteve Wise case MORIBUND: 2988b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 2989cfdda9d7SSteve Wise if ((ep->com.cm_id) && (ep->com.qp)) { 2990cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_IDLE; 2991cfdda9d7SSteve Wise c4iw_modify_qp(ep->com.qp->rhp, 2992cfdda9d7SSteve Wise ep->com.qp, 2993cfdda9d7SSteve Wise C4IW_QP_ATTR_NEXT_STATE, 2994cfdda9d7SSteve Wise &attrs, 1); 2995cfdda9d7SSteve Wise } 2996be13b2dfSSteve Wise close_complete_upcall(ep, 0); 2997cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 2998cfdda9d7SSteve Wise release = 1; 2999cfdda9d7SSteve Wise break; 3000cfdda9d7SSteve Wise case ABORTING: 3001cfdda9d7SSteve Wise case DEAD: 3002cfdda9d7SSteve Wise break; 3003cfdda9d7SSteve Wise default: 3004ba97b749SSteve Wise WARN_ONCE(1, "Bad endpoint state %u\n", ep->com.state); 3005cfdda9d7SSteve Wise break; 3006cfdda9d7SSteve Wise } 30072f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 3008cfdda9d7SSteve Wise if (release) 3009cfdda9d7SSteve Wise release_ep_resources(ep); 3010944661ddSHariprasad S c4iw_put_ep(&ep->com); 3011cfdda9d7SSteve Wise return 0; 3012cfdda9d7SSteve Wise } 3013cfdda9d7SSteve Wise 3014cfdda9d7SSteve Wise static int terminate(struct c4iw_dev *dev, struct sk_buff *skb) 3015cfdda9d7SSteve Wise { 30160e42c1f4SSteve Wise struct cpl_rdma_terminate *rpl = cplhdr(skb); 30170e42c1f4SSteve Wise unsigned int tid = GET_TID(rpl); 30180e42c1f4SSteve Wise struct c4iw_ep *ep; 30190e42c1f4SSteve Wise struct c4iw_qp_attributes attrs; 3020cfdda9d7SSteve Wise 3021944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 3022cfdda9d7SSteve Wise 30233352976cSRaju Rangoju if (ep) { 30243352976cSRaju Rangoju if (ep->com.qp) { 30253352976cSRaju Rangoju pr_warn("TERM received tid %u qpid %u\n", tid, 30263352976cSRaju Rangoju ep->com.qp->wq.sq.qid); 30270e42c1f4SSteve Wise attrs.next_state = C4IW_QP_STATE_TERMINATE; 30280e42c1f4SSteve Wise c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 30290e42c1f4SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 30303352976cSRaju Rangoju } 30313352976cSRaju Rangoju 3032d219faceSKrishnamraju Eraparaju /* As per draft-hilland-iwarp-verbs-v1.0, sec 6.2.3, 3033d219faceSKrishnamraju Eraparaju * when entering the TERM state the RNIC MUST initiate a CLOSE. 3034d219faceSKrishnamraju Eraparaju */ 3035d219faceSKrishnamraju Eraparaju c4iw_ep_disconnect(ep, 1, GFP_KERNEL); 30363352976cSRaju Rangoju c4iw_put_ep(&ep->com); 30370e42c1f4SSteve Wise } else 3038700456bdSJoe Perches pr_warn("TERM received tid %u no ep/qp\n", tid); 3039cfdda9d7SSteve Wise 3040cfdda9d7SSteve Wise return 0; 3041cfdda9d7SSteve Wise } 3042cfdda9d7SSteve Wise 3043cfdda9d7SSteve Wise /* 3044cfdda9d7SSteve Wise * Upcall from the adapter indicating data has been transmitted. 3045cfdda9d7SSteve Wise * For us its just the single MPA request or reply. We can now free 3046cfdda9d7SSteve Wise * the skb holding the mpa message. 3047cfdda9d7SSteve Wise */ 3048cfdda9d7SSteve Wise static int fw4_ack(struct c4iw_dev *dev, struct sk_buff *skb) 3049cfdda9d7SSteve Wise { 3050cfdda9d7SSteve Wise struct c4iw_ep *ep; 3051cfdda9d7SSteve Wise struct cpl_fw4_ack *hdr = cplhdr(skb); 3052cfdda9d7SSteve Wise u8 credits = hdr->credits; 3053cfdda9d7SSteve Wise unsigned int tid = GET_TID(hdr); 3054cfdda9d7SSteve Wise 3055cfdda9d7SSteve Wise 3056944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 3057944661ddSHariprasad S if (!ep) 3058944661ddSHariprasad S return 0; 3059548ddb19SBharat Potnuri pr_debug("ep %p tid %u credits %u\n", 3060548ddb19SBharat Potnuri ep, ep->hwtid, credits); 3061cfdda9d7SSteve Wise if (credits == 0) { 3062548ddb19SBharat Potnuri pr_debug("0 credit ack ep %p tid %u state %u\n", 3063548ddb19SBharat Potnuri ep, ep->hwtid, state_read(&ep->com)); 3064944661ddSHariprasad S goto out; 3065cfdda9d7SSteve Wise } 3066cfdda9d7SSteve Wise 3067cfdda9d7SSteve Wise dst_confirm(ep->dst); 3068cfdda9d7SSteve Wise if (ep->mpa_skb) { 3069548ddb19SBharat Potnuri pr_debug("last streaming msg ack ep %p tid %u state %u initiator %u freeing skb\n", 3070548ddb19SBharat Potnuri ep, ep->hwtid, state_read(&ep->com), 3071548ddb19SBharat Potnuri ep->mpa_attr.initiator ? 1 : 0); 307212eb5137SSteve Wise mutex_lock(&ep->com.mutex); 3073cfdda9d7SSteve Wise kfree_skb(ep->mpa_skb); 3074cfdda9d7SSteve Wise ep->mpa_skb = NULL; 3075e4b76a2aSHariprasad S if (test_bit(STOP_MPA_TIMER, &ep->com.flags)) 3076e4b76a2aSHariprasad S stop_ep_timer(ep); 3077e4b76a2aSHariprasad S mutex_unlock(&ep->com.mutex); 3078cfdda9d7SSteve Wise } 3079944661ddSHariprasad S out: 3080944661ddSHariprasad S c4iw_put_ep(&ep->com); 3081cfdda9d7SSteve Wise return 0; 3082cfdda9d7SSteve Wise } 3083cfdda9d7SSteve Wise 3084cfdda9d7SSteve Wise int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) 3085cfdda9d7SSteve Wise { 3086bce2841fSHariprasad S int abort; 3087cfdda9d7SSteve Wise struct c4iw_ep *ep = to_ep(cm_id); 3088bce2841fSHariprasad S 3089548ddb19SBharat Potnuri pr_debug("ep %p tid %u\n", ep, ep->hwtid); 3090cfdda9d7SSteve Wise 3091a7db89ebSSteve Wise mutex_lock(&ep->com.mutex); 3092e8667a9bSHariprasad S if (ep->com.state != MPA_REQ_RCVD) { 3093a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 3094cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3095cfdda9d7SSteve Wise return -ECONNRESET; 3096cfdda9d7SSteve Wise } 3097793dad94SVipul Pandya set_bit(ULP_REJECT, &ep->com.history); 3098cfdda9d7SSteve Wise if (mpa_rev == 0) 3099bce2841fSHariprasad S abort = 1; 3100bce2841fSHariprasad S else 3101bce2841fSHariprasad S abort = send_mpa_reject(ep, pdata, pdata_len); 3102a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 3103bce2841fSHariprasad S 3104e4b76a2aSHariprasad S stop_ep_timer(ep); 3105bce2841fSHariprasad S c4iw_ep_disconnect(ep, abort != 0, GFP_KERNEL); 3106cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3107cfdda9d7SSteve Wise return 0; 3108cfdda9d7SSteve Wise } 3109cfdda9d7SSteve Wise 3110cfdda9d7SSteve Wise int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) 3111cfdda9d7SSteve Wise { 3112cfdda9d7SSteve Wise int err; 3113cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 3114cfdda9d7SSteve Wise enum c4iw_qp_attr_mask mask; 3115cfdda9d7SSteve Wise struct c4iw_ep *ep = to_ep(cm_id); 3116cfdda9d7SSteve Wise struct c4iw_dev *h = to_c4iw_dev(cm_id->device); 3117cfdda9d7SSteve Wise struct c4iw_qp *qp = get_qhp(h, conn_param->qpn); 3118eaf4c6d4SHariprasad S int abort = 0; 3119cfdda9d7SSteve Wise 3120548ddb19SBharat Potnuri pr_debug("ep %p tid %u\n", ep, ep->hwtid); 3121a7db89ebSSteve Wise 3122a7db89ebSSteve Wise mutex_lock(&ep->com.mutex); 3123e8667a9bSHariprasad S if (ep->com.state != MPA_REQ_RCVD) { 3124cfdda9d7SSteve Wise err = -ECONNRESET; 3125eaf4c6d4SHariprasad S goto err_out; 3126cfdda9d7SSteve Wise } 3127cfdda9d7SSteve Wise 3128ba97b749SSteve Wise if (!qp) { 3129ba97b749SSteve Wise err = -EINVAL; 3130ba97b749SSteve Wise goto err_out; 3131ba97b749SSteve Wise } 3132cfdda9d7SSteve Wise 3133793dad94SVipul Pandya set_bit(ULP_ACCEPT, &ep->com.history); 31344c2c5763SHariprasad Shenai if ((conn_param->ord > cur_max_read_depth(ep->com.dev)) || 31354c2c5763SHariprasad Shenai (conn_param->ird > cur_max_read_depth(ep->com.dev))) { 3136cfdda9d7SSteve Wise err = -EINVAL; 3137eaf4c6d4SHariprasad S goto err_abort; 3138cfdda9d7SSteve Wise } 3139cfdda9d7SSteve Wise 3140d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 3141d2fe99e8SKumar Sanghvi if (conn_param->ord > ep->ird) { 31424c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION) { 314330b03b15SSteve Wise conn_param->ord = ep->ird; 31444c2c5763SHariprasad Shenai } else { 3145d2fe99e8SKumar Sanghvi ep->ird = conn_param->ird; 3146d2fe99e8SKumar Sanghvi ep->ord = conn_param->ord; 3147d2fe99e8SKumar Sanghvi send_mpa_reject(ep, conn_param->private_data, 3148d2fe99e8SKumar Sanghvi conn_param->private_data_len); 3149d2fe99e8SKumar Sanghvi err = -ENOMEM; 3150eaf4c6d4SHariprasad S goto err_abort; 3151d2fe99e8SKumar Sanghvi } 31524c2c5763SHariprasad Shenai } 31534c2c5763SHariprasad Shenai if (conn_param->ird < ep->ord) { 31544c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION && 31554c2c5763SHariprasad Shenai ep->ord <= h->rdev.lldi.max_ordird_qp) { 31564c2c5763SHariprasad Shenai conn_param->ird = ep->ord; 31574c2c5763SHariprasad Shenai } else { 3158d2fe99e8SKumar Sanghvi err = -ENOMEM; 3159eaf4c6d4SHariprasad S goto err_abort; 3160d2fe99e8SKumar Sanghvi } 3161d2fe99e8SKumar Sanghvi } 3162d2fe99e8SKumar Sanghvi } 3163cfdda9d7SSteve Wise ep->ird = conn_param->ird; 3164cfdda9d7SSteve Wise ep->ord = conn_param->ord; 3165cfdda9d7SSteve Wise 31664c2c5763SHariprasad Shenai if (ep->mpa_attr.version == 1) { 3167cfdda9d7SSteve Wise if (peer2peer && ep->ird == 0) 3168cfdda9d7SSteve Wise ep->ird = 1; 31694c2c5763SHariprasad Shenai } else { 31704c2c5763SHariprasad Shenai if (peer2peer && 31714c2c5763SHariprasad Shenai (ep->mpa_attr.p2p_type != FW_RI_INIT_P2PTYPE_DISABLED) && 3172f57b780cSHariprasad S (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) && ep->ird == 0) 31734c2c5763SHariprasad Shenai ep->ird = 1; 31744c2c5763SHariprasad Shenai } 3175cfdda9d7SSteve Wise 3176548ddb19SBharat Potnuri pr_debug("ird %d ord %d\n", ep->ird, ep->ord); 3177cfdda9d7SSteve Wise 3178d2fe99e8SKumar Sanghvi ep->com.cm_id = cm_id; 31799ca6f7cfSHariprasad S ref_cm_id(&ep->com); 3180d2fe99e8SKumar Sanghvi ep->com.qp = qp; 3181325abeadSVipul Pandya ref_qp(ep); 3182d2fe99e8SKumar Sanghvi 3183cfdda9d7SSteve Wise /* bind QP to EP and move to RTS */ 3184cfdda9d7SSteve Wise attrs.mpa_attr = ep->mpa_attr; 3185cfdda9d7SSteve Wise attrs.max_ird = ep->ird; 3186cfdda9d7SSteve Wise attrs.max_ord = ep->ord; 3187cfdda9d7SSteve Wise attrs.llp_stream_handle = ep; 3188cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_RTS; 3189cfdda9d7SSteve Wise 3190cfdda9d7SSteve Wise /* bind QP and TID with INIT_WR */ 3191cfdda9d7SSteve Wise mask = C4IW_QP_ATTR_NEXT_STATE | 3192cfdda9d7SSteve Wise C4IW_QP_ATTR_LLP_STREAM_HANDLE | 3193cfdda9d7SSteve Wise C4IW_QP_ATTR_MPA_ATTR | 3194cfdda9d7SSteve Wise C4IW_QP_ATTR_MAX_IRD | 3195cfdda9d7SSteve Wise C4IW_QP_ATTR_MAX_ORD; 3196cfdda9d7SSteve Wise 3197cfdda9d7SSteve Wise err = c4iw_modify_qp(ep->com.qp->rhp, 3198cfdda9d7SSteve Wise ep->com.qp, mask, &attrs, 1); 3199cfdda9d7SSteve Wise if (err) 3200eaf4c6d4SHariprasad S goto err_deref_cm_id; 3201e4b76a2aSHariprasad S 3202e4b76a2aSHariprasad S set_bit(STOP_MPA_TIMER, &ep->com.flags); 3203cfdda9d7SSteve Wise err = send_mpa_reply(ep, conn_param->private_data, 3204cfdda9d7SSteve Wise conn_param->private_data_len); 3205cfdda9d7SSteve Wise if (err) 3206eaf4c6d4SHariprasad S goto err_deref_cm_id; 3207cfdda9d7SSteve Wise 3208a7db89ebSSteve Wise __state_set(&ep->com, FPDU_MODE); 3209cfdda9d7SSteve Wise established_upcall(ep); 3210a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 3211cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3212cfdda9d7SSteve Wise return 0; 3213eaf4c6d4SHariprasad S err_deref_cm_id: 32149ca6f7cfSHariprasad S deref_cm_id(&ep->com); 3215eaf4c6d4SHariprasad S err_abort: 3216eaf4c6d4SHariprasad S abort = 1; 3217eaf4c6d4SHariprasad S err_out: 3218a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 3219eaf4c6d4SHariprasad S if (abort) 3220eaf4c6d4SHariprasad S c4iw_ep_disconnect(ep, 1, GFP_KERNEL); 3221cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3222cfdda9d7SSteve Wise return err; 3223cfdda9d7SSteve Wise } 3224cfdda9d7SSteve Wise 3225830662f6SVipul Pandya static int pick_local_ipaddrs(struct c4iw_dev *dev, struct iw_cm_id *cm_id) 3226830662f6SVipul Pandya { 3227830662f6SVipul Pandya struct in_device *ind; 3228830662f6SVipul Pandya int found = 0; 3229170003c8SSteve Wise struct sockaddr_in *laddr = (struct sockaddr_in *)&cm_id->m_local_addr; 3230170003c8SSteve Wise struct sockaddr_in *raddr = (struct sockaddr_in *)&cm_id->m_remote_addr; 3231cb8f1478SFlorian Westphal const struct in_ifaddr *ifa; 3232830662f6SVipul Pandya 3233830662f6SVipul Pandya ind = in_dev_get(dev->rdev.lldi.ports[0]); 3234830662f6SVipul Pandya if (!ind) 3235830662f6SVipul Pandya return -EADDRNOTAVAIL; 3236cb8f1478SFlorian Westphal rcu_read_lock(); 3237cb8f1478SFlorian Westphal in_dev_for_each_ifa_rcu(ifa, ind) { 3238cb8f1478SFlorian Westphal if (ifa->ifa_flags & IFA_F_SECONDARY) 3239cb8f1478SFlorian Westphal continue; 3240830662f6SVipul Pandya laddr->sin_addr.s_addr = ifa->ifa_address; 3241830662f6SVipul Pandya raddr->sin_addr.s_addr = ifa->ifa_address; 3242830662f6SVipul Pandya found = 1; 3243830662f6SVipul Pandya break; 3244830662f6SVipul Pandya } 3245cb8f1478SFlorian Westphal rcu_read_unlock(); 3246cb8f1478SFlorian Westphal 3247830662f6SVipul Pandya in_dev_put(ind); 3248830662f6SVipul Pandya return found ? 0 : -EADDRNOTAVAIL; 3249830662f6SVipul Pandya } 3250830662f6SVipul Pandya 3251830662f6SVipul Pandya static int get_lladdr(struct net_device *dev, struct in6_addr *addr, 3252830662f6SVipul Pandya unsigned char banned_flags) 3253830662f6SVipul Pandya { 3254830662f6SVipul Pandya struct inet6_dev *idev; 3255830662f6SVipul Pandya int err = -EADDRNOTAVAIL; 3256830662f6SVipul Pandya 3257830662f6SVipul Pandya rcu_read_lock(); 3258830662f6SVipul Pandya idev = __in6_dev_get(dev); 3259830662f6SVipul Pandya if (idev != NULL) { 3260830662f6SVipul Pandya struct inet6_ifaddr *ifp; 3261830662f6SVipul Pandya 3262830662f6SVipul Pandya read_lock_bh(&idev->lock); 3263830662f6SVipul Pandya list_for_each_entry(ifp, &idev->addr_list, if_list) { 3264830662f6SVipul Pandya if (ifp->scope == IFA_LINK && 3265830662f6SVipul Pandya !(ifp->flags & banned_flags)) { 3266830662f6SVipul Pandya memcpy(addr, &ifp->addr, 16); 3267830662f6SVipul Pandya err = 0; 3268830662f6SVipul Pandya break; 3269830662f6SVipul Pandya } 3270830662f6SVipul Pandya } 3271830662f6SVipul Pandya read_unlock_bh(&idev->lock); 3272830662f6SVipul Pandya } 3273830662f6SVipul Pandya rcu_read_unlock(); 3274830662f6SVipul Pandya return err; 3275830662f6SVipul Pandya } 3276830662f6SVipul Pandya 3277830662f6SVipul Pandya static int pick_local_ip6addrs(struct c4iw_dev *dev, struct iw_cm_id *cm_id) 3278830662f6SVipul Pandya { 32793f649ab7SKees Cook struct in6_addr addr; 3280170003c8SSteve Wise struct sockaddr_in6 *la6 = (struct sockaddr_in6 *)&cm_id->m_local_addr; 3281170003c8SSteve Wise struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)&cm_id->m_remote_addr; 3282830662f6SVipul Pandya 328354b9a96fSNicholas Krause if (!get_lladdr(dev->rdev.lldi.ports[0], &addr, IFA_F_TENTATIVE)) { 3284830662f6SVipul Pandya memcpy(la6->sin6_addr.s6_addr, &addr, 16); 3285830662f6SVipul Pandya memcpy(ra6->sin6_addr.s6_addr, &addr, 16); 3286830662f6SVipul Pandya return 0; 3287830662f6SVipul Pandya } 3288830662f6SVipul Pandya return -EADDRNOTAVAIL; 3289830662f6SVipul Pandya } 3290830662f6SVipul Pandya 3291cfdda9d7SSteve Wise int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) 3292cfdda9d7SSteve Wise { 3293cfdda9d7SSteve Wise struct c4iw_dev *dev = to_c4iw_dev(cm_id->device); 3294cfdda9d7SSteve Wise struct c4iw_ep *ep; 32953786cf18SDavid Miller int err = 0; 32969eccfe10SSteve Wise struct sockaddr_in *laddr; 32979eccfe10SSteve Wise struct sockaddr_in *raddr; 32989eccfe10SSteve Wise struct sockaddr_in6 *laddr6; 32999eccfe10SSteve Wise struct sockaddr_in6 *raddr6; 3300830662f6SVipul Pandya __u8 *ra; 3301830662f6SVipul Pandya int iptype; 3302cfdda9d7SSteve Wise 33034c2c5763SHariprasad Shenai if ((conn_param->ord > cur_max_read_depth(dev)) || 33044c2c5763SHariprasad Shenai (conn_param->ird > cur_max_read_depth(dev))) { 3305be4c9badSRoland Dreier err = -EINVAL; 3306be4c9badSRoland Dreier goto out; 3307be4c9badSRoland Dreier } 3308cfdda9d7SSteve Wise ep = alloc_ep(sizeof(*ep), GFP_KERNEL); 3309cfdda9d7SSteve Wise if (!ep) { 3310700456bdSJoe Perches pr_err("%s - cannot alloc ep\n", __func__); 3311cfdda9d7SSteve Wise err = -ENOMEM; 3312cfdda9d7SSteve Wise goto out; 3313cfdda9d7SSteve Wise } 33144a740838SHariprasad S 33154a740838SHariprasad S skb_queue_head_init(&ep->com.ep_skb_list); 33164a740838SHariprasad S if (alloc_ep_skb_list(&ep->com.ep_skb_list, CN_MAX_CON_BUF)) { 33174a740838SHariprasad S err = -ENOMEM; 33184a740838SHariprasad S goto fail1; 33194a740838SHariprasad S } 33204a740838SHariprasad S 3321a9346abeSKees Cook timer_setup(&ep->timer, ep_timeout, 0); 3322cfdda9d7SSteve Wise ep->plen = conn_param->private_data_len; 3323cfdda9d7SSteve Wise if (ep->plen) 3324cfdda9d7SSteve Wise memcpy(ep->mpa_pkt + sizeof(struct mpa_message), 3325cfdda9d7SSteve Wise conn_param->private_data, ep->plen); 3326cfdda9d7SSteve Wise ep->ird = conn_param->ird; 3327cfdda9d7SSteve Wise ep->ord = conn_param->ord; 3328cfdda9d7SSteve Wise 3329cfdda9d7SSteve Wise if (peer2peer && ep->ord == 0) 3330cfdda9d7SSteve Wise ep->ord = 1; 3331cfdda9d7SSteve Wise 3332cfdda9d7SSteve Wise ep->com.cm_id = cm_id; 33339ca6f7cfSHariprasad S ref_cm_id(&ep->com); 3334b06f2efdSSteve Wise cm_id->provider_data = ep; 33359ca6f7cfSHariprasad S ep->com.dev = dev; 3336cfdda9d7SSteve Wise ep->com.qp = get_qhp(dev, conn_param->qpn); 3337830662f6SVipul Pandya if (!ep->com.qp) { 33384d45b757SBharat Potnuri pr_warn("%s qpn 0x%x not found!\n", __func__, conn_param->qpn); 3339830662f6SVipul Pandya err = -EINVAL; 33404a740838SHariprasad S goto fail2; 3341830662f6SVipul Pandya } 3342325abeadSVipul Pandya ref_qp(ep); 3343548ddb19SBharat Potnuri pr_debug("qpn 0x%x qp %p cm_id %p\n", conn_param->qpn, 3344cfdda9d7SSteve Wise ep->com.qp, cm_id); 3345cfdda9d7SSteve Wise 3346cfdda9d7SSteve Wise /* 3347cfdda9d7SSteve Wise * Allocate an active TID to initiate a TCP connection. 3348cfdda9d7SSteve Wise */ 3349cfdda9d7SSteve Wise ep->atid = cxgb4_alloc_atid(dev->rdev.lldi.tids, ep); 3350cfdda9d7SSteve Wise if (ep->atid == -1) { 3351700456bdSJoe Perches pr_err("%s - cannot alloc atid\n", __func__); 3352cfdda9d7SSteve Wise err = -ENOMEM; 33534a740838SHariprasad S goto fail2; 3354cfdda9d7SSteve Wise } 33559f5a9632SMatthew Wilcox err = xa_insert_irq(&dev->atids, ep->atid, ep, GFP_KERNEL); 33569f5a9632SMatthew Wilcox if (err) 33579f5a9632SMatthew Wilcox goto fail5; 3358cfdda9d7SSteve Wise 3359170003c8SSteve Wise memcpy(&ep->com.local_addr, &cm_id->m_local_addr, 33609eccfe10SSteve Wise sizeof(ep->com.local_addr)); 3361170003c8SSteve Wise memcpy(&ep->com.remote_addr, &cm_id->m_remote_addr, 33629eccfe10SSteve Wise sizeof(ep->com.remote_addr)); 33639eccfe10SSteve Wise 3364170003c8SSteve Wise laddr = (struct sockaddr_in *)&ep->com.local_addr; 3365170003c8SSteve Wise raddr = (struct sockaddr_in *)&ep->com.remote_addr; 3366170003c8SSteve Wise laddr6 = (struct sockaddr_in6 *)&ep->com.local_addr; 3367170003c8SSteve Wise raddr6 = (struct sockaddr_in6 *) &ep->com.remote_addr; 33689eccfe10SSteve Wise 3369170003c8SSteve Wise if (cm_id->m_remote_addr.ss_family == AF_INET) { 3370830662f6SVipul Pandya iptype = 4; 3371830662f6SVipul Pandya ra = (__u8 *)&raddr->sin_addr; 3372830662f6SVipul Pandya 3373830662f6SVipul Pandya /* 3374830662f6SVipul Pandya * Handle loopback requests to INADDR_ANY. 3375830662f6SVipul Pandya */ 3376ba987e51SBart Van Assche if (raddr->sin_addr.s_addr == htonl(INADDR_ANY)) { 3377830662f6SVipul Pandya err = pick_local_ipaddrs(dev, cm_id); 3378830662f6SVipul Pandya if (err) 33799067f2f0SChristophe JAILLET goto fail3; 3380830662f6SVipul Pandya } 3381cfdda9d7SSteve Wise 3382cfdda9d7SSteve Wise /* find a route */ 3383548ddb19SBharat Potnuri pr_debug("saddr %pI4 sport 0x%x raddr %pI4 rport 0x%x\n", 3384548ddb19SBharat Potnuri &laddr->sin_addr, ntohs(laddr->sin_port), 3385830662f6SVipul Pandya ra, ntohs(raddr->sin_port)); 3386804c2f3eSVarun Prakash ep->dst = cxgb_find_route(&dev->rdev.lldi, get_real_dev, 3387804c2f3eSVarun Prakash laddr->sin_addr.s_addr, 3388804c2f3eSVarun Prakash raddr->sin_addr.s_addr, 3389804c2f3eSVarun Prakash laddr->sin_port, 3390ac8e4c69SHariprasad S raddr->sin_port, cm_id->tos); 3391830662f6SVipul Pandya } else { 3392830662f6SVipul Pandya iptype = 6; 3393830662f6SVipul Pandya ra = (__u8 *)&raddr6->sin6_addr; 3394830662f6SVipul Pandya 3395830662f6SVipul Pandya /* 3396830662f6SVipul Pandya * Handle loopback requests to INADDR_ANY. 3397830662f6SVipul Pandya */ 3398830662f6SVipul Pandya if (ipv6_addr_type(&raddr6->sin6_addr) == IPV6_ADDR_ANY) { 3399830662f6SVipul Pandya err = pick_local_ip6addrs(dev, cm_id); 3400830662f6SVipul Pandya if (err) 34019067f2f0SChristophe JAILLET goto fail3; 3402830662f6SVipul Pandya } 3403830662f6SVipul Pandya 3404830662f6SVipul Pandya /* find a route */ 3405548ddb19SBharat Potnuri pr_debug("saddr %pI6 sport 0x%x raddr %pI6 rport 0x%x\n", 3406548ddb19SBharat Potnuri laddr6->sin6_addr.s6_addr, 3407830662f6SVipul Pandya ntohs(laddr6->sin6_port), 3408830662f6SVipul Pandya raddr6->sin6_addr.s6_addr, ntohs(raddr6->sin6_port)); 340995554761SVarun Prakash ep->dst = cxgb_find_route6(&dev->rdev.lldi, get_real_dev, 341095554761SVarun Prakash laddr6->sin6_addr.s6_addr, 3411830662f6SVipul Pandya raddr6->sin6_addr.s6_addr, 341295554761SVarun Prakash laddr6->sin6_port, 3413c8a7eb55SSteve Wise raddr6->sin6_port, cm_id->tos, 3414830662f6SVipul Pandya raddr6->sin6_scope_id); 3415830662f6SVipul Pandya } 3416830662f6SVipul Pandya if (!ep->dst) { 3417700456bdSJoe Perches pr_err("%s - cannot find route\n", __func__); 3418cfdda9d7SSteve Wise err = -EHOSTUNREACH; 34194a740838SHariprasad S goto fail3; 3420cfdda9d7SSteve Wise } 3421cfdda9d7SSteve Wise 3422963cab50SHariprasad S err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, true, 3423ac8e4c69SHariprasad S ep->com.dev->rdev.lldi.adapter_type, cm_id->tos); 34243786cf18SDavid Miller if (err) { 3425700456bdSJoe Perches pr_err("%s - cannot alloc l2e\n", __func__); 34264a740838SHariprasad S goto fail4; 3427cfdda9d7SSteve Wise } 3428cfdda9d7SSteve Wise 3429548ddb19SBharat Potnuri pr_debug("txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n", 3430548ddb19SBharat Potnuri ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid, 3431cfdda9d7SSteve Wise ep->l2t->idx); 3432cfdda9d7SSteve Wise 3433cfdda9d7SSteve Wise state_set(&ep->com, CONNECTING); 3434ac8e4c69SHariprasad S ep->tos = cm_id->tos; 3435cfdda9d7SSteve Wise 3436cfdda9d7SSteve Wise /* send connect request to rnic */ 3437cfdda9d7SSteve Wise err = send_connect(ep); 3438cfdda9d7SSteve Wise if (!err) 3439cfdda9d7SSteve Wise goto out; 3440cfdda9d7SSteve Wise 3441cfdda9d7SSteve Wise cxgb4_l2t_release(ep->l2t); 34424a740838SHariprasad S fail4: 34439eccfe10SSteve Wise dst_release(ep->dst); 34444a740838SHariprasad S fail3: 34459f5a9632SMatthew Wilcox xa_erase_irq(&ep->com.dev->atids, ep->atid); 34469f5a9632SMatthew Wilcox fail5: 3447cfdda9d7SSteve Wise cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid); 34484a740838SHariprasad S fail2: 34494a740838SHariprasad S skb_queue_purge(&ep->com.ep_skb_list); 34509ca6f7cfSHariprasad S deref_cm_id(&ep->com); 34514a740838SHariprasad S fail1: 3452cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3453cfdda9d7SSteve Wise out: 3454cfdda9d7SSteve Wise return err; 3455cfdda9d7SSteve Wise } 3456cfdda9d7SSteve Wise 3457830662f6SVipul Pandya static int create_server6(struct c4iw_dev *dev, struct c4iw_listen_ep *ep) 3458830662f6SVipul Pandya { 3459830662f6SVipul Pandya int err; 34609eccfe10SSteve Wise struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) 3461170003c8SSteve Wise &ep->com.local_addr; 3462830662f6SVipul Pandya 346328de1f74SHariprasad S if (ipv6_addr_type(&sin6->sin6_addr) != IPV6_ADDR_ANY) { 346428de1f74SHariprasad S err = cxgb4_clip_get(ep->com.dev->rdev.lldi.ports[0], 346528de1f74SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 346628de1f74SHariprasad S if (err) 346728de1f74SHariprasad S return err; 346828de1f74SHariprasad S } 3469ef885dc6SSteve Wise c4iw_init_wr_wait(ep->com.wr_waitp); 3470830662f6SVipul Pandya err = cxgb4_create_server6(ep->com.dev->rdev.lldi.ports[0], 3471830662f6SVipul Pandya ep->stid, &sin6->sin6_addr, 3472830662f6SVipul Pandya sin6->sin6_port, 3473830662f6SVipul Pandya ep->com.dev->rdev.lldi.rxq_ids[0]); 3474830662f6SVipul Pandya if (!err) 3475830662f6SVipul Pandya err = c4iw_wait_for_reply(&ep->com.dev->rdev, 3476ef885dc6SSteve Wise ep->com.wr_waitp, 3477830662f6SVipul Pandya 0, 0, __func__); 3478e6b11163SHariprasad S else if (err > 0) 3479e6b11163SHariprasad S err = net_xmit_errno(err); 348028de1f74SHariprasad S if (err) { 348128de1f74SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 348228de1f74SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 3483830662f6SVipul Pandya pr_err("cxgb4_create_server6/filter failed err %d stid %d laddr %pI6 lport %d\n", 3484830662f6SVipul Pandya err, ep->stid, 3485830662f6SVipul Pandya sin6->sin6_addr.s6_addr, ntohs(sin6->sin6_port)); 348628de1f74SHariprasad S } 3487830662f6SVipul Pandya return err; 3488830662f6SVipul Pandya } 3489830662f6SVipul Pandya 3490830662f6SVipul Pandya static int create_server4(struct c4iw_dev *dev, struct c4iw_listen_ep *ep) 3491830662f6SVipul Pandya { 3492830662f6SVipul Pandya int err; 34939eccfe10SSteve Wise struct sockaddr_in *sin = (struct sockaddr_in *) 3494170003c8SSteve Wise &ep->com.local_addr; 3495830662f6SVipul Pandya 3496830662f6SVipul Pandya if (dev->rdev.lldi.enable_fw_ofld_conn) { 3497830662f6SVipul Pandya do { 3498830662f6SVipul Pandya err = cxgb4_create_server_filter( 3499830662f6SVipul Pandya ep->com.dev->rdev.lldi.ports[0], ep->stid, 3500830662f6SVipul Pandya sin->sin_addr.s_addr, sin->sin_port, 0, 3501830662f6SVipul Pandya ep->com.dev->rdev.lldi.rxq_ids[0], 0, 0); 3502830662f6SVipul Pandya if (err == -EBUSY) { 350399718e59SHariprasad S if (c4iw_fatal_error(&ep->com.dev->rdev)) { 350499718e59SHariprasad S err = -EIO; 350599718e59SHariprasad S break; 350699718e59SHariprasad S } 3507830662f6SVipul Pandya set_current_state(TASK_UNINTERRUPTIBLE); 3508830662f6SVipul Pandya schedule_timeout(usecs_to_jiffies(100)); 3509830662f6SVipul Pandya } 3510830662f6SVipul Pandya } while (err == -EBUSY); 3511830662f6SVipul Pandya } else { 3512ef885dc6SSteve Wise c4iw_init_wr_wait(ep->com.wr_waitp); 3513830662f6SVipul Pandya err = cxgb4_create_server(ep->com.dev->rdev.lldi.ports[0], 3514830662f6SVipul Pandya ep->stid, sin->sin_addr.s_addr, sin->sin_port, 3515830662f6SVipul Pandya 0, ep->com.dev->rdev.lldi.rxq_ids[0]); 3516830662f6SVipul Pandya if (!err) 3517830662f6SVipul Pandya err = c4iw_wait_for_reply(&ep->com.dev->rdev, 3518ef885dc6SSteve Wise ep->com.wr_waitp, 3519830662f6SVipul Pandya 0, 0, __func__); 3520e6b11163SHariprasad S else if (err > 0) 3521e6b11163SHariprasad S err = net_xmit_errno(err); 3522830662f6SVipul Pandya } 3523830662f6SVipul Pandya if (err) 3524830662f6SVipul Pandya pr_err("cxgb4_create_server/filter failed err %d stid %d laddr %pI4 lport %d\n" 3525830662f6SVipul Pandya , err, ep->stid, 3526830662f6SVipul Pandya &sin->sin_addr, ntohs(sin->sin_port)); 3527830662f6SVipul Pandya return err; 3528830662f6SVipul Pandya } 3529830662f6SVipul Pandya 3530cfdda9d7SSteve Wise int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog) 3531cfdda9d7SSteve Wise { 3532cfdda9d7SSteve Wise int err = 0; 3533cfdda9d7SSteve Wise struct c4iw_dev *dev = to_c4iw_dev(cm_id->device); 3534cfdda9d7SSteve Wise struct c4iw_listen_ep *ep; 3535cfdda9d7SSteve Wise 3536cfdda9d7SSteve Wise might_sleep(); 3537cfdda9d7SSteve Wise 3538cfdda9d7SSteve Wise ep = alloc_ep(sizeof(*ep), GFP_KERNEL); 3539cfdda9d7SSteve Wise if (!ep) { 3540700456bdSJoe Perches pr_err("%s - cannot alloc ep\n", __func__); 3541cfdda9d7SSteve Wise err = -ENOMEM; 3542cfdda9d7SSteve Wise goto fail1; 3543cfdda9d7SSteve Wise } 35444a740838SHariprasad S skb_queue_head_init(&ep->com.ep_skb_list); 3545548ddb19SBharat Potnuri pr_debug("ep %p\n", ep); 3546cfdda9d7SSteve Wise ep->com.cm_id = cm_id; 35479ca6f7cfSHariprasad S ref_cm_id(&ep->com); 3548cfdda9d7SSteve Wise ep->com.dev = dev; 3549cfdda9d7SSteve Wise ep->backlog = backlog; 3550170003c8SSteve Wise memcpy(&ep->com.local_addr, &cm_id->m_local_addr, 355124d44a39SSteve Wise sizeof(ep->com.local_addr)); 3552cfdda9d7SSteve Wise 3553cfdda9d7SSteve Wise /* 3554cfdda9d7SSteve Wise * Allocate a server TID. 3555cfdda9d7SSteve Wise */ 35568c044690SKumar Sanghvi if (dev->rdev.lldi.enable_fw_ofld_conn && 35578c044690SKumar Sanghvi ep->com.local_addr.ss_family == AF_INET) 3558830662f6SVipul Pandya ep->stid = cxgb4_alloc_sftid(dev->rdev.lldi.tids, 3559170003c8SSteve Wise cm_id->m_local_addr.ss_family, ep); 35601cab775cSVipul Pandya else 3561830662f6SVipul Pandya ep->stid = cxgb4_alloc_stid(dev->rdev.lldi.tids, 3562170003c8SSteve Wise cm_id->m_local_addr.ss_family, ep); 35631cab775cSVipul Pandya 3564cfdda9d7SSteve Wise if (ep->stid == -1) { 3565700456bdSJoe Perches pr_err("%s - cannot alloc stid\n", __func__); 3566cfdda9d7SSteve Wise err = -ENOMEM; 3567cfdda9d7SSteve Wise goto fail2; 3568cfdda9d7SSteve Wise } 3569401b4480SMatthew Wilcox err = xa_insert_irq(&dev->stids, ep->stid, ep, GFP_KERNEL); 3570401b4480SMatthew Wilcox if (err) 3571401b4480SMatthew Wilcox goto fail3; 35729eccfe10SSteve Wise 3573cfdda9d7SSteve Wise state_set(&ep->com, LISTEN); 3574830662f6SVipul Pandya if (ep->com.local_addr.ss_family == AF_INET) 3575830662f6SVipul Pandya err = create_server4(dev, ep); 3576830662f6SVipul Pandya else 3577830662f6SVipul Pandya err = create_server6(dev, ep); 3578cfdda9d7SSteve Wise if (!err) { 3579cfdda9d7SSteve Wise cm_id->provider_data = ep; 3580cfdda9d7SSteve Wise goto out; 3581cfdda9d7SSteve Wise } 3582401b4480SMatthew Wilcox xa_erase_irq(&ep->com.dev->stids, ep->stid); 3583401b4480SMatthew Wilcox fail3: 3584830662f6SVipul Pandya cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, 3585830662f6SVipul Pandya ep->com.local_addr.ss_family); 3586cfdda9d7SSteve Wise fail2: 35879ca6f7cfSHariprasad S deref_cm_id(&ep->com); 3588cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3589cfdda9d7SSteve Wise fail1: 3590cfdda9d7SSteve Wise out: 3591cfdda9d7SSteve Wise return err; 3592cfdda9d7SSteve Wise } 3593cfdda9d7SSteve Wise 3594cfdda9d7SSteve Wise int c4iw_destroy_listen(struct iw_cm_id *cm_id) 3595cfdda9d7SSteve Wise { 3596cfdda9d7SSteve Wise int err; 3597cfdda9d7SSteve Wise struct c4iw_listen_ep *ep = to_listen_ep(cm_id); 3598cfdda9d7SSteve Wise 3599548ddb19SBharat Potnuri pr_debug("ep %p\n", ep); 3600cfdda9d7SSteve Wise 3601cfdda9d7SSteve Wise might_sleep(); 3602cfdda9d7SSteve Wise state_set(&ep->com, DEAD); 3603830662f6SVipul Pandya if (ep->com.dev->rdev.lldi.enable_fw_ofld_conn && 3604830662f6SVipul Pandya ep->com.local_addr.ss_family == AF_INET) { 36051cab775cSVipul Pandya err = cxgb4_remove_server_filter( 36061cab775cSVipul Pandya ep->com.dev->rdev.lldi.ports[0], ep->stid, 36073408be14SPotnuri Bharat Teja ep->com.dev->rdev.lldi.rxq_ids[0], false); 36081cab775cSVipul Pandya } else { 360984cc6ac6SHariprasad S struct sockaddr_in6 *sin6; 3610ef885dc6SSteve Wise c4iw_init_wr_wait(ep->com.wr_waitp); 3611830662f6SVipul Pandya err = cxgb4_remove_server( 3612830662f6SVipul Pandya ep->com.dev->rdev.lldi.ports[0], ep->stid, 3613603c4690SPotnuri Bharat Teja ep->com.dev->rdev.lldi.rxq_ids[0], 3614603c4690SPotnuri Bharat Teja ep->com.local_addr.ss_family == AF_INET6); 3615cfdda9d7SSteve Wise if (err) 3616cfdda9d7SSteve Wise goto done; 3617ef885dc6SSteve Wise err = c4iw_wait_for_reply(&ep->com.dev->rdev, ep->com.wr_waitp, 36181cab775cSVipul Pandya 0, 0, __func__); 3619170003c8SSteve Wise sin6 = (struct sockaddr_in6 *)&ep->com.local_addr; 362084cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 362184cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 36221cab775cSVipul Pandya } 3623401b4480SMatthew Wilcox xa_erase_irq(&ep->com.dev->stids, ep->stid); 3624830662f6SVipul Pandya cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, 3625830662f6SVipul Pandya ep->com.local_addr.ss_family); 3626cfdda9d7SSteve Wise done: 36279ca6f7cfSHariprasad S deref_cm_id(&ep->com); 3628cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3629cfdda9d7SSteve Wise return err; 3630cfdda9d7SSteve Wise } 3631cfdda9d7SSteve Wise 3632cfdda9d7SSteve Wise int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) 3633cfdda9d7SSteve Wise { 3634cfdda9d7SSteve Wise int ret = 0; 3635cfdda9d7SSteve Wise int close = 0; 3636cfdda9d7SSteve Wise int fatal = 0; 3637cfdda9d7SSteve Wise struct c4iw_rdev *rdev; 3638cfdda9d7SSteve Wise 36392f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 3640cfdda9d7SSteve Wise 3641548ddb19SBharat Potnuri pr_debug("ep %p state %s, abrupt %d\n", ep, 3642cfdda9d7SSteve Wise states[ep->com.state], abrupt); 3643cfdda9d7SSteve Wise 36446e410d8fSHariprasad S /* 36456e410d8fSHariprasad S * Ref the ep here in case we have fatal errors causing the 36466e410d8fSHariprasad S * ep to be released and freed. 36476e410d8fSHariprasad S */ 36486e410d8fSHariprasad S c4iw_get_ep(&ep->com); 36496e410d8fSHariprasad S 3650cfdda9d7SSteve Wise rdev = &ep->com.dev->rdev; 3651cfdda9d7SSteve Wise if (c4iw_fatal_error(rdev)) { 3652cfdda9d7SSteve Wise fatal = 1; 3653be13b2dfSSteve Wise close_complete_upcall(ep, -EIO); 3654cfdda9d7SSteve Wise ep->com.state = DEAD; 3655cfdda9d7SSteve Wise } 3656cfdda9d7SSteve Wise switch (ep->com.state) { 3657cfdda9d7SSteve Wise case MPA_REQ_WAIT: 3658cfdda9d7SSteve Wise case MPA_REQ_SENT: 3659cfdda9d7SSteve Wise case MPA_REQ_RCVD: 3660cfdda9d7SSteve Wise case MPA_REP_SENT: 3661cfdda9d7SSteve Wise case FPDU_MODE: 36624a740838SHariprasad S case CONNECTING: 3663cfdda9d7SSteve Wise close = 1; 3664cfdda9d7SSteve Wise if (abrupt) 3665cfdda9d7SSteve Wise ep->com.state = ABORTING; 3666cfdda9d7SSteve Wise else { 3667cfdda9d7SSteve Wise ep->com.state = CLOSING; 366812eb5137SSteve Wise 366912eb5137SSteve Wise /* 367012eb5137SSteve Wise * if we close before we see the fw4_ack() then we fix 367112eb5137SSteve Wise * up the timer state since we're reusing it. 367212eb5137SSteve Wise */ 367312eb5137SSteve Wise if (ep->mpa_skb && 367412eb5137SSteve Wise test_bit(STOP_MPA_TIMER, &ep->com.flags)) { 367512eb5137SSteve Wise clear_bit(STOP_MPA_TIMER, &ep->com.flags); 367612eb5137SSteve Wise stop_ep_timer(ep); 367712eb5137SSteve Wise } 3678ca5a2202SSteve Wise start_ep_timer(ep); 3679cfdda9d7SSteve Wise } 3680cfdda9d7SSteve Wise set_bit(CLOSE_SENT, &ep->com.flags); 3681cfdda9d7SSteve Wise break; 3682cfdda9d7SSteve Wise case CLOSING: 3683cfdda9d7SSteve Wise if (!test_and_set_bit(CLOSE_SENT, &ep->com.flags)) { 3684cfdda9d7SSteve Wise close = 1; 3685cfdda9d7SSteve Wise if (abrupt) { 3686b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 3687cfdda9d7SSteve Wise ep->com.state = ABORTING; 3688cfdda9d7SSteve Wise } else 3689cfdda9d7SSteve Wise ep->com.state = MORIBUND; 3690cfdda9d7SSteve Wise } 3691cfdda9d7SSteve Wise break; 3692cfdda9d7SSteve Wise case MORIBUND: 3693cfdda9d7SSteve Wise case ABORTING: 3694cfdda9d7SSteve Wise case DEAD: 3695f48fca4dSBharat Potnuri pr_debug("ignoring disconnect ep %p state %u\n", 3696f48fca4dSBharat Potnuri ep, ep->com.state); 3697cfdda9d7SSteve Wise break; 3698cfdda9d7SSteve Wise default: 3699ba97b749SSteve Wise WARN_ONCE(1, "Bad endpoint state %u\n", ep->com.state); 3700cfdda9d7SSteve Wise break; 3701cfdda9d7SSteve Wise } 3702cfdda9d7SSteve Wise 3703cfdda9d7SSteve Wise if (close) { 37048da7e7a5SSteve Wise if (abrupt) { 3705793dad94SVipul Pandya set_bit(EP_DISC_ABORT, &ep->com.history); 37064a740838SHariprasad S ret = send_abort(ep); 3707793dad94SVipul Pandya } else { 3708793dad94SVipul Pandya set_bit(EP_DISC_CLOSE, &ep->com.history); 37094a740838SHariprasad S ret = send_halfclose(ep); 3710793dad94SVipul Pandya } 371188bc230dSHariprasad S if (ret) { 37129ca6f7cfSHariprasad S set_bit(EP_DISC_FAIL, &ep->com.history); 371388bc230dSHariprasad S if (!abrupt) { 371488bc230dSHariprasad S stop_ep_timer(ep); 371588bc230dSHariprasad S close_complete_upcall(ep, -EIO); 371688bc230dSHariprasad S } 3717c00dcbafSHariprasad S if (ep->com.qp) { 3718c00dcbafSHariprasad S struct c4iw_qp_attributes attrs; 3719c00dcbafSHariprasad S 3720c00dcbafSHariprasad S attrs.next_state = C4IW_QP_STATE_ERROR; 3721c00dcbafSHariprasad S ret = c4iw_modify_qp(ep->com.qp->rhp, 3722c00dcbafSHariprasad S ep->com.qp, 3723c00dcbafSHariprasad S C4IW_QP_ATTR_NEXT_STATE, 3724c00dcbafSHariprasad S &attrs, 1); 3725c00dcbafSHariprasad S if (ret) 3726700456bdSJoe Perches pr_err("%s - qp <- error failed!\n", 3727c00dcbafSHariprasad S __func__); 3728c00dcbafSHariprasad S } 3729cfdda9d7SSteve Wise fatal = 1; 3730cfdda9d7SSteve Wise } 373188bc230dSHariprasad S } 37328da7e7a5SSteve Wise mutex_unlock(&ep->com.mutex); 37336e410d8fSHariprasad S c4iw_put_ep(&ep->com); 3734cfdda9d7SSteve Wise if (fatal) 3735cfdda9d7SSteve Wise release_ep_resources(ep); 3736cfdda9d7SSteve Wise return ret; 3737cfdda9d7SSteve Wise } 3738cfdda9d7SSteve Wise 37391cab775cSVipul Pandya static void active_ofld_conn_reply(struct c4iw_dev *dev, struct sk_buff *skb, 37401cab775cSVipul Pandya struct cpl_fw6_msg_ofld_connection_wr_rpl *req) 37411cab775cSVipul Pandya { 37421cab775cSVipul Pandya struct c4iw_ep *ep; 3743793dad94SVipul Pandya int atid = be32_to_cpu(req->tid); 37441cab775cSVipul Pandya 3745ef5d6355SVipul Pandya ep = (struct c4iw_ep *)lookup_atid(dev->rdev.lldi.tids, 3746ef5d6355SVipul Pandya (__force u32) req->tid); 37471cab775cSVipul Pandya if (!ep) 37481cab775cSVipul Pandya return; 37491cab775cSVipul Pandya 37501cab775cSVipul Pandya switch (req->retval) { 37511cab775cSVipul Pandya case FW_ENOMEM: 3752793dad94SVipul Pandya set_bit(ACT_RETRY_NOMEM, &ep->com.history); 3753793dad94SVipul Pandya if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) { 3754793dad94SVipul Pandya send_fw_act_open_req(ep, atid); 3755793dad94SVipul Pandya return; 3756793dad94SVipul Pandya } 3757df561f66SGustavo A. R. Silva fallthrough; 37581cab775cSVipul Pandya case FW_EADDRINUSE: 3759793dad94SVipul Pandya set_bit(ACT_RETRY_INUSE, &ep->com.history); 3760793dad94SVipul Pandya if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) { 3761793dad94SVipul Pandya send_fw_act_open_req(ep, atid); 3762793dad94SVipul Pandya return; 3763793dad94SVipul Pandya } 37641cab775cSVipul Pandya break; 37651cab775cSVipul Pandya default: 37661cab775cSVipul Pandya pr_info("%s unexpected ofld conn wr retval %d\n", 37671cab775cSVipul Pandya __func__, req->retval); 37681cab775cSVipul Pandya break; 37691cab775cSVipul Pandya } 3770793dad94SVipul Pandya pr_err("active ofld_connect_wr failure %d atid %d\n", 3771793dad94SVipul Pandya req->retval, atid); 3772793dad94SVipul Pandya mutex_lock(&dev->rdev.stats.lock); 3773793dad94SVipul Pandya dev->rdev.stats.act_ofld_conn_fails++; 3774793dad94SVipul Pandya mutex_unlock(&dev->rdev.stats.lock); 37751cab775cSVipul Pandya connect_reply_upcall(ep, status2errno(req->retval)); 3776793dad94SVipul Pandya state_set(&ep->com, DEAD); 377784cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 377884cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 3779170003c8SSteve Wise (struct sockaddr_in6 *)&ep->com.local_addr; 378084cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 378184cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 378284cc6ac6SHariprasad S } 37839f5a9632SMatthew Wilcox xa_erase_irq(&dev->atids, atid); 3784793dad94SVipul Pandya cxgb4_free_atid(dev->rdev.lldi.tids, atid); 3785793dad94SVipul Pandya dst_release(ep->dst); 3786793dad94SVipul Pandya cxgb4_l2t_release(ep->l2t); 3787793dad94SVipul Pandya c4iw_put_ep(&ep->com); 37881cab775cSVipul Pandya } 37891cab775cSVipul Pandya 37901cab775cSVipul Pandya static void passive_ofld_conn_reply(struct c4iw_dev *dev, struct sk_buff *skb, 37911cab775cSVipul Pandya struct cpl_fw6_msg_ofld_connection_wr_rpl *req) 37921cab775cSVipul Pandya { 37931cab775cSVipul Pandya struct sk_buff *rpl_skb; 37941cab775cSVipul Pandya struct cpl_pass_accept_req *cpl; 37951cab775cSVipul Pandya int ret; 37961cab775cSVipul Pandya 3797710a3110SPaul Bolle rpl_skb = (struct sk_buff *)(unsigned long)req->cookie; 37981cab775cSVipul Pandya if (req->retval) { 37994d45b757SBharat Potnuri pr_err("%s passive open failure %d\n", __func__, req->retval); 3800793dad94SVipul Pandya mutex_lock(&dev->rdev.stats.lock); 3801793dad94SVipul Pandya dev->rdev.stats.pas_ofld_conn_fails++; 3802793dad94SVipul Pandya mutex_unlock(&dev->rdev.stats.lock); 38031cab775cSVipul Pandya kfree_skb(rpl_skb); 38041cab775cSVipul Pandya } else { 38051cab775cSVipul Pandya cpl = (struct cpl_pass_accept_req *)cplhdr(rpl_skb); 38061cab775cSVipul Pandya OPCODE_TID(cpl) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_REQ, 3807ef5d6355SVipul Pandya (__force u32) htonl( 3808ef5d6355SVipul Pandya (__force u32) req->tid))); 38091cab775cSVipul Pandya ret = pass_accept_req(dev, rpl_skb); 38101cab775cSVipul Pandya if (!ret) 38111cab775cSVipul Pandya kfree_skb(rpl_skb); 38121cab775cSVipul Pandya } 38131cab775cSVipul Pandya return; 38141cab775cSVipul Pandya } 38151cab775cSVipul Pandya 381611a27e21SRaju Rangoju static inline u64 t4_tcb_get_field64(__be64 *tcb, u16 word) 381711a27e21SRaju Rangoju { 381811a27e21SRaju Rangoju u64 tlo = be64_to_cpu(tcb[((31 - word) / 2)]); 381911a27e21SRaju Rangoju u64 thi = be64_to_cpu(tcb[((31 - word) / 2) - 1]); 382011a27e21SRaju Rangoju u64 t; 382111a27e21SRaju Rangoju u32 shift = 32; 382211a27e21SRaju Rangoju 382311a27e21SRaju Rangoju t = (thi << shift) | (tlo >> shift); 382411a27e21SRaju Rangoju 382511a27e21SRaju Rangoju return t; 382611a27e21SRaju Rangoju } 382711a27e21SRaju Rangoju 382811a27e21SRaju Rangoju static inline u32 t4_tcb_get_field32(__be64 *tcb, u16 word, u32 mask, u32 shift) 382911a27e21SRaju Rangoju { 383011a27e21SRaju Rangoju u32 v; 383111a27e21SRaju Rangoju u64 t = be64_to_cpu(tcb[(31 - word) / 2]); 383211a27e21SRaju Rangoju 383311a27e21SRaju Rangoju if (word & 0x1) 383411a27e21SRaju Rangoju shift += 32; 383511a27e21SRaju Rangoju v = (t >> shift) & mask; 383611a27e21SRaju Rangoju return v; 383711a27e21SRaju Rangoju } 383811a27e21SRaju Rangoju 383911a27e21SRaju Rangoju static int read_tcb_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 384011a27e21SRaju Rangoju { 384111a27e21SRaju Rangoju struct cpl_get_tcb_rpl *rpl = cplhdr(skb); 384211a27e21SRaju Rangoju __be64 *tcb = (__be64 *)(rpl + 1); 384311a27e21SRaju Rangoju unsigned int tid = GET_TID(rpl); 384411a27e21SRaju Rangoju struct c4iw_ep *ep; 384511a27e21SRaju Rangoju u64 t_flags_64; 384611a27e21SRaju Rangoju u32 rx_pdu_out; 384711a27e21SRaju Rangoju 384811a27e21SRaju Rangoju ep = get_ep_from_tid(dev, tid); 384911a27e21SRaju Rangoju if (!ep) 385011a27e21SRaju Rangoju return 0; 385111a27e21SRaju Rangoju /* Examine the TF_RX_PDU_OUT (bit 49 of the t_flags) in order to 385211a27e21SRaju Rangoju * determine if there's a rx PDU feedback event pending. 385311a27e21SRaju Rangoju * 385411a27e21SRaju Rangoju * If that bit is set, it means we'll need to re-read the TCB's 385511a27e21SRaju Rangoju * rq_start value. The final value is the one present in a TCB 385611a27e21SRaju Rangoju * with the TF_RX_PDU_OUT bit cleared. 385711a27e21SRaju Rangoju */ 385811a27e21SRaju Rangoju 385911a27e21SRaju Rangoju t_flags_64 = t4_tcb_get_field64(tcb, TCB_T_FLAGS_W); 386011a27e21SRaju Rangoju rx_pdu_out = (t_flags_64 & TF_RX_PDU_OUT_V(1)) >> TF_RX_PDU_OUT_S; 386111a27e21SRaju Rangoju 386211a27e21SRaju Rangoju c4iw_put_ep(&ep->com); /* from get_ep_from_tid() */ 386311a27e21SRaju Rangoju c4iw_put_ep(&ep->com); /* from read_tcb() */ 386411a27e21SRaju Rangoju 386511a27e21SRaju Rangoju /* If TF_RX_PDU_OUT bit is set, re-read the TCB */ 386611a27e21SRaju Rangoju if (rx_pdu_out) { 386711a27e21SRaju Rangoju if (++ep->rx_pdu_out_cnt >= 2) { 386811a27e21SRaju Rangoju WARN_ONCE(1, "tcb re-read() reached the guard limit, finishing the cleanup\n"); 386911a27e21SRaju Rangoju goto cleanup; 387011a27e21SRaju Rangoju } 387111a27e21SRaju Rangoju read_tcb(ep); 387211a27e21SRaju Rangoju return 0; 387311a27e21SRaju Rangoju } 387411a27e21SRaju Rangoju 3875c8b1f340SPotnuri Bharat Teja ep->srqe_idx = t4_tcb_get_field32(tcb, TCB_RQ_START_W, TCB_RQ_START_M, 387611a27e21SRaju Rangoju TCB_RQ_START_S); 387711a27e21SRaju Rangoju cleanup: 387811a27e21SRaju Rangoju pr_debug("ep %p tid %u %016x\n", ep, ep->hwtid, ep->srqe_idx); 387911a27e21SRaju Rangoju 388011a27e21SRaju Rangoju if (test_bit(PEER_ABORT_IN_PROGRESS, &ep->com.flags)) 388111a27e21SRaju Rangoju finish_peer_abort(dev, ep); 388211a27e21SRaju Rangoju else if (test_bit(ABORT_REQ_IN_PROGRESS, &ep->com.flags)) 388311a27e21SRaju Rangoju send_abort_req(ep); 388411a27e21SRaju Rangoju else 388511a27e21SRaju Rangoju WARN_ONCE(1, "unexpected state!"); 388611a27e21SRaju Rangoju 388711a27e21SRaju Rangoju return 0; 388811a27e21SRaju Rangoju } 388911a27e21SRaju Rangoju 38901cab775cSVipul Pandya static int deferred_fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb) 38912f5b48c3SSteve Wise { 38922f5b48c3SSteve Wise struct cpl_fw6_msg *rpl = cplhdr(skb); 38931cab775cSVipul Pandya struct cpl_fw6_msg_ofld_connection_wr_rpl *req; 38941cab775cSVipul Pandya 38951cab775cSVipul Pandya switch (rpl->type) { 38961cab775cSVipul Pandya case FW6_TYPE_CQE: 38972f5b48c3SSteve Wise c4iw_ev_dispatch(dev, (struct t4_cqe *)&rpl->data[0]); 38981cab775cSVipul Pandya break; 38991cab775cSVipul Pandya case FW6_TYPE_OFLD_CONNECTION_WR_RPL: 39001cab775cSVipul Pandya req = (struct cpl_fw6_msg_ofld_connection_wr_rpl *)rpl->data; 39011cab775cSVipul Pandya switch (req->t_state) { 39021cab775cSVipul Pandya case TCP_SYN_SENT: 39031cab775cSVipul Pandya active_ofld_conn_reply(dev, skb, req); 39041cab775cSVipul Pandya break; 39051cab775cSVipul Pandya case TCP_SYN_RECV: 39061cab775cSVipul Pandya passive_ofld_conn_reply(dev, skb, req); 39071cab775cSVipul Pandya break; 39081cab775cSVipul Pandya default: 39091cab775cSVipul Pandya pr_err("%s unexpected ofld conn wr state %d\n", 39101cab775cSVipul Pandya __func__, req->t_state); 39111cab775cSVipul Pandya break; 39121cab775cSVipul Pandya } 39131cab775cSVipul Pandya break; 39141cab775cSVipul Pandya } 39151cab775cSVipul Pandya return 0; 39161cab775cSVipul Pandya } 39171cab775cSVipul Pandya 39181cab775cSVipul Pandya static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos) 39191cab775cSVipul Pandya { 3920963cab50SHariprasad S __be32 l2info; 3921963cab50SHariprasad S __be16 hdr_len, vlantag, len; 3922963cab50SHariprasad S u16 eth_hdr_len; 3923963cab50SHariprasad S int tcp_hdr_len, ip_hdr_len; 39241cab775cSVipul Pandya u8 intf; 39251cab775cSVipul Pandya struct cpl_rx_pkt *cpl = cplhdr(skb); 39261cab775cSVipul Pandya struct cpl_pass_accept_req *req; 39271cab775cSVipul Pandya struct tcp_options_received tmp_opt; 3928f079af7aSVipul Pandya struct c4iw_dev *dev; 3929963cab50SHariprasad S enum chip_type type; 39301cab775cSVipul Pandya 3931f079af7aSVipul Pandya dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *))); 39321cab775cSVipul Pandya /* Store values from cpl_rx_pkt in temporary location. */ 3933963cab50SHariprasad S vlantag = cpl->vlan; 3934963cab50SHariprasad S len = cpl->len; 3935963cab50SHariprasad S l2info = cpl->l2info; 3936963cab50SHariprasad S hdr_len = cpl->hdr_len; 39371cab775cSVipul Pandya intf = cpl->iff; 39381cab775cSVipul Pandya 39391cab775cSVipul Pandya __skb_pull(skb, sizeof(*req) + sizeof(struct rss_header)); 39401cab775cSVipul Pandya 39411cab775cSVipul Pandya /* 39421cab775cSVipul Pandya * We need to parse the TCP options from SYN packet. 39431cab775cSVipul Pandya * to generate cpl_pass_accept_req. 39441cab775cSVipul Pandya */ 39451cab775cSVipul Pandya memset(&tmp_opt, 0, sizeof(tmp_opt)); 39461cab775cSVipul Pandya tcp_clear_options(&tmp_opt); 3947eed29f17SEric Dumazet tcp_parse_options(&init_net, skb, &tmp_opt, 0, NULL); 39481cab775cSVipul Pandya 3949d58ff351SJohannes Berg req = __skb_push(skb, sizeof(*req)); 39501cab775cSVipul Pandya memset(req, 0, sizeof(*req)); 3951cf7fe64aSHariprasad Shenai req->l2info = cpu_to_be16(SYN_INTF_V(intf) | 3952cf7fe64aSHariprasad Shenai SYN_MAC_IDX_V(RX_MACIDX_G( 3953963cab50SHariprasad S be32_to_cpu(l2info))) | 3954cf7fe64aSHariprasad Shenai SYN_XACT_MATCH_F); 3955963cab50SHariprasad S type = dev->rdev.lldi.adapter_type; 3956963cab50SHariprasad S tcp_hdr_len = RX_TCPHDR_LEN_G(be16_to_cpu(hdr_len)); 3957963cab50SHariprasad S ip_hdr_len = RX_IPHDR_LEN_G(be16_to_cpu(hdr_len)); 3958963cab50SHariprasad S req->hdr_len = 3959963cab50SHariprasad S cpu_to_be32(SYN_RX_CHAN_V(RX_CHAN_G(be32_to_cpu(l2info)))); 3960963cab50SHariprasad S if (CHELSIO_CHIP_VERSION(type) <= CHELSIO_T5) { 3961963cab50SHariprasad S eth_hdr_len = is_t4(type) ? 3962963cab50SHariprasad S RX_ETHHDR_LEN_G(be32_to_cpu(l2info)) : 3963963cab50SHariprasad S RX_T5_ETHHDR_LEN_G(be32_to_cpu(l2info)); 3964963cab50SHariprasad S req->hdr_len |= cpu_to_be32(TCP_HDR_LEN_V(tcp_hdr_len) | 3965963cab50SHariprasad S IP_HDR_LEN_V(ip_hdr_len) | 3966963cab50SHariprasad S ETH_HDR_LEN_V(eth_hdr_len)); 3967963cab50SHariprasad S } else { /* T6 and later */ 3968963cab50SHariprasad S eth_hdr_len = RX_T6_ETHHDR_LEN_G(be32_to_cpu(l2info)); 3969963cab50SHariprasad S req->hdr_len |= cpu_to_be32(T6_TCP_HDR_LEN_V(tcp_hdr_len) | 3970963cab50SHariprasad S T6_IP_HDR_LEN_V(ip_hdr_len) | 3971963cab50SHariprasad S T6_ETH_HDR_LEN_V(eth_hdr_len)); 3972963cab50SHariprasad S } 3973963cab50SHariprasad S req->vlan = vlantag; 3974963cab50SHariprasad S req->len = len; 39756c53e938SHariprasad Shenai req->tos_stid = cpu_to_be32(PASS_OPEN_TID_V(stid) | 39766c53e938SHariprasad Shenai PASS_OPEN_TOS_V(tos)); 39771cab775cSVipul Pandya req->tcpopt.mss = htons(tmp_opt.mss_clamp); 39781cab775cSVipul Pandya if (tmp_opt.wscale_ok) 39791cab775cSVipul Pandya req->tcpopt.wsf = tmp_opt.snd_wscale; 39801cab775cSVipul Pandya req->tcpopt.tstamp = tmp_opt.saw_tstamp; 39811cab775cSVipul Pandya if (tmp_opt.sack_ok) 39821cab775cSVipul Pandya req->tcpopt.sack = 1; 39831cab775cSVipul Pandya OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_REQ, 0)); 39841cab775cSVipul Pandya return; 39851cab775cSVipul Pandya } 39861cab775cSVipul Pandya 39871cab775cSVipul Pandya static void send_fw_pass_open_req(struct c4iw_dev *dev, struct sk_buff *skb, 39881cab775cSVipul Pandya __be32 laddr, __be16 lport, 39891cab775cSVipul Pandya __be32 raddr, __be16 rport, 39901cab775cSVipul Pandya u32 rcv_isn, u32 filter, u16 window, 39911cab775cSVipul Pandya u32 rss_qid, u8 port_id) 39921cab775cSVipul Pandya { 39931cab775cSVipul Pandya struct sk_buff *req_skb; 39941cab775cSVipul Pandya struct fw_ofld_connection_wr *req; 39951cab775cSVipul Pandya struct cpl_pass_accept_req *cpl = cplhdr(skb); 39961ce1d471SSteve Wise int ret; 39971cab775cSVipul Pandya 39981cab775cSVipul Pandya req_skb = alloc_skb(sizeof(struct fw_ofld_connection_wr), GFP_KERNEL); 39999ef63f31SPan Bian if (!req_skb) 40009ef63f31SPan Bian return; 4001de77b966Syuan linyu req = __skb_put_zero(req_skb, sizeof(*req)); 40026c53e938SHariprasad Shenai req->op_compl = htonl(WR_OP_V(FW_OFLD_CONNECTION_WR) | FW_WR_COMPL_F); 4003e2ac9628SHariprasad Shenai req->len16_pkd = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*req), 16))); 400477a80e23SHariprasad Shenai req->le.version_cpl = htonl(FW_OFLD_CONNECTION_WR_CPL_F); 4005ef5d6355SVipul Pandya req->le.filter = (__force __be32) filter; 40061cab775cSVipul Pandya req->le.lport = lport; 40071cab775cSVipul Pandya req->le.pport = rport; 40081cab775cSVipul Pandya req->le.u.ipv4.lip = laddr; 40091cab775cSVipul Pandya req->le.u.ipv4.pip = raddr; 40101cab775cSVipul Pandya req->tcb.rcv_nxt = htonl(rcv_isn + 1); 40111cab775cSVipul Pandya req->tcb.rcv_adv = htons(window); 40121cab775cSVipul Pandya req->tcb.t_state_to_astid = 401377a80e23SHariprasad Shenai htonl(FW_OFLD_CONNECTION_WR_T_STATE_V(TCP_SYN_RECV) | 401477a80e23SHariprasad Shenai FW_OFLD_CONNECTION_WR_RCV_SCALE_V(cpl->tcpopt.wsf) | 401577a80e23SHariprasad Shenai FW_OFLD_CONNECTION_WR_ASTID_V( 40166c53e938SHariprasad Shenai PASS_OPEN_TID_G(ntohl(cpl->tos_stid)))); 40171cab775cSVipul Pandya 40181cab775cSVipul Pandya /* 40191cab775cSVipul Pandya * We store the qid in opt2 which will be used by the firmware 40201cab775cSVipul Pandya * to send us the wr response. 40211cab775cSVipul Pandya */ 4022d7990b0cSAnish Bhatt req->tcb.opt2 = htonl(RSS_QUEUE_V(rss_qid)); 40231cab775cSVipul Pandya 40241cab775cSVipul Pandya /* 40251cab775cSVipul Pandya * We initialize the MSS index in TCB to 0xF. 40261cab775cSVipul Pandya * So that when driver sends cpl_pass_accept_rpl 40271cab775cSVipul Pandya * TCB picks up the correct value. If this was 0 40281cab775cSVipul Pandya * TP will ignore any value > 0 for MSS index. 40291cab775cSVipul Pandya */ 4030d7990b0cSAnish Bhatt req->tcb.opt0 = cpu_to_be64(MSS_IDX_V(0xF)); 40316198dd8dSHariprasad S req->cookie = (uintptr_t)skb; 40321cab775cSVipul Pandya 40331cab775cSVipul Pandya set_wr_txq(req_skb, CPL_PRIORITY_CONTROL, port_id); 40341ce1d471SSteve Wise ret = cxgb4_ofld_send(dev->rdev.lldi.ports[0], req_skb); 40351ce1d471SSteve Wise if (ret < 0) { 40361ce1d471SSteve Wise pr_err("%s - cxgb4_ofld_send error %d - dropping\n", __func__, 40371ce1d471SSteve Wise ret); 40381ce1d471SSteve Wise kfree_skb(skb); 40391ce1d471SSteve Wise kfree_skb(req_skb); 40401ce1d471SSteve Wise } 40411cab775cSVipul Pandya } 40421cab775cSVipul Pandya 40431cab775cSVipul Pandya /* 40441cab775cSVipul Pandya * Handler for CPL_RX_PKT message. Need to handle cpl_rx_pkt 40451cab775cSVipul Pandya * messages when a filter is being used instead of server to 40461cab775cSVipul Pandya * redirect a syn packet. When packets hit filter they are redirected 40471cab775cSVipul Pandya * to the offload queue and driver tries to establish the connection 40481cab775cSVipul Pandya * using firmware work request. 40491cab775cSVipul Pandya */ 40501cab775cSVipul Pandya static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb) 40511cab775cSVipul Pandya { 40521cab775cSVipul Pandya int stid; 40531cab775cSVipul Pandya unsigned int filter; 40541cab775cSVipul Pandya struct ethhdr *eh = NULL; 40551cab775cSVipul Pandya struct vlan_ethhdr *vlan_eh = NULL; 40561cab775cSVipul Pandya struct iphdr *iph; 40571cab775cSVipul Pandya struct tcphdr *tcph; 40581cab775cSVipul Pandya struct rss_header *rss = (void *)skb->data; 40591cab775cSVipul Pandya struct cpl_rx_pkt *cpl = (void *)skb->data; 40601cab775cSVipul Pandya struct cpl_pass_accept_req *req = (void *)(rss + 1); 40611cab775cSVipul Pandya struct l2t_entry *e; 40621cab775cSVipul Pandya struct dst_entry *dst; 4063f86fac79SHariprasad S struct c4iw_ep *lep = NULL; 40641cab775cSVipul Pandya u16 window; 40651cab775cSVipul Pandya struct port_info *pi; 40661cab775cSVipul Pandya struct net_device *pdev; 4067f079af7aSVipul Pandya u16 rss_qid, eth_hdr_len; 40681cab775cSVipul Pandya int step; 40691cab775cSVipul Pandya struct neighbour *neigh; 40701cab775cSVipul Pandya 40711cab775cSVipul Pandya /* Drop all non-SYN packets */ 4072bdc590b9SHariprasad Shenai if (!(cpl->l2info & cpu_to_be32(RXF_SYN_F))) 40731cab775cSVipul Pandya goto reject; 40741cab775cSVipul Pandya 40751cab775cSVipul Pandya /* 40761cab775cSVipul Pandya * Drop all packets which did not hit the filter. 40771cab775cSVipul Pandya * Unlikely to happen. 40781cab775cSVipul Pandya */ 40791cab775cSVipul Pandya if (!(rss->filter_hit && rss->filter_tid)) 40801cab775cSVipul Pandya goto reject; 40811cab775cSVipul Pandya 40821cab775cSVipul Pandya /* 40831cab775cSVipul Pandya * Calculate the server tid from filter hit index from cpl_rx_pkt. 40841cab775cSVipul Pandya */ 4085a4ea025fSKumar Sanghvi stid = (__force int) cpu_to_be32((__force u32) rss->hash_val); 40861cab775cSVipul Pandya 4087f86fac79SHariprasad S lep = (struct c4iw_ep *)get_ep_from_stid(dev, stid); 40881cab775cSVipul Pandya if (!lep) { 40894d45b757SBharat Potnuri pr_warn("%s connect request on invalid stid %d\n", 4090a9a42886SJoe Perches __func__, stid); 40911cab775cSVipul Pandya goto reject; 40921cab775cSVipul Pandya } 40931cab775cSVipul Pandya 4094963cab50SHariprasad S switch (CHELSIO_CHIP_VERSION(dev->rdev.lldi.adapter_type)) { 4095963cab50SHariprasad S case CHELSIO_T4: 4096963cab50SHariprasad S eth_hdr_len = RX_ETHHDR_LEN_G(be32_to_cpu(cpl->l2info)); 4097963cab50SHariprasad S break; 4098963cab50SHariprasad S case CHELSIO_T5: 4099963cab50SHariprasad S eth_hdr_len = RX_T5_ETHHDR_LEN_G(be32_to_cpu(cpl->l2info)); 4100963cab50SHariprasad S break; 4101963cab50SHariprasad S case CHELSIO_T6: 4102963cab50SHariprasad S eth_hdr_len = RX_T6_ETHHDR_LEN_G(be32_to_cpu(cpl->l2info)); 4103963cab50SHariprasad S break; 4104963cab50SHariprasad S default: 4105963cab50SHariprasad S pr_err("T%d Chip is not supported\n", 4106963cab50SHariprasad S CHELSIO_CHIP_VERSION(dev->rdev.lldi.adapter_type)); 4107963cab50SHariprasad S goto reject; 4108963cab50SHariprasad S } 4109963cab50SHariprasad S 4110f079af7aSVipul Pandya if (eth_hdr_len == ETH_HLEN) { 41111cab775cSVipul Pandya eh = (struct ethhdr *)(req + 1); 41121cab775cSVipul Pandya iph = (struct iphdr *)(eh + 1); 41131cab775cSVipul Pandya } else { 41141cab775cSVipul Pandya vlan_eh = (struct vlan_ethhdr *)(req + 1); 41151cab775cSVipul Pandya iph = (struct iphdr *)(vlan_eh + 1); 411635c4a95dSMichał Mirosław __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(cpl->vlan)); 41171cab775cSVipul Pandya } 41181cab775cSVipul Pandya 41191cab775cSVipul Pandya if (iph->version != 0x4) 41201cab775cSVipul Pandya goto reject; 41211cab775cSVipul Pandya 41221cab775cSVipul Pandya tcph = (struct tcphdr *)(iph + 1); 41231cab775cSVipul Pandya skb_set_network_header(skb, (void *)iph - (void *)rss); 41241cab775cSVipul Pandya skb_set_transport_header(skb, (void *)tcph - (void *)rss); 41251cab775cSVipul Pandya skb_get(skb); 41261cab775cSVipul Pandya 4127548ddb19SBharat Potnuri pr_debug("lip 0x%x lport %u pip 0x%x pport %u tos %d\n", 41281cab775cSVipul Pandya ntohl(iph->daddr), ntohs(tcph->dest), ntohl(iph->saddr), 41291cab775cSVipul Pandya ntohs(tcph->source), iph->tos); 41301cab775cSVipul Pandya 4131804c2f3eSVarun Prakash dst = cxgb_find_route(&dev->rdev.lldi, get_real_dev, 4132804c2f3eSVarun Prakash iph->daddr, iph->saddr, tcph->dest, 4133804c2f3eSVarun Prakash tcph->source, iph->tos); 4134830662f6SVipul Pandya if (!dst) { 4135548ddb19SBharat Potnuri pr_err("%s - failed to find dst entry!\n", __func__); 41361cab775cSVipul Pandya goto reject; 41371cab775cSVipul Pandya } 41381cab775cSVipul Pandya neigh = dst_neigh_lookup_skb(dst, skb); 41391cab775cSVipul Pandya 4140aaa0c23cSZhouyi Zhou if (!neigh) { 4141548ddb19SBharat Potnuri pr_err("%s - failed to allocate neigh!\n", __func__); 4142aaa0c23cSZhouyi Zhou goto free_dst; 4143aaa0c23cSZhouyi Zhou } 4144aaa0c23cSZhouyi Zhou 41451cab775cSVipul Pandya if (neigh->dev->flags & IFF_LOOPBACK) { 41461cab775cSVipul Pandya pdev = ip_dev_find(&init_net, iph->daddr); 4147*ef425202SNikita Zhandarovich if (!pdev) { 4148*ef425202SNikita Zhandarovich pr_err("%s - failed to find device!\n", __func__); 4149*ef425202SNikita Zhandarovich goto free_dst; 4150*ef425202SNikita Zhandarovich } 41511cab775cSVipul Pandya e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, 41521cab775cSVipul Pandya pdev, 0); 41531cab775cSVipul Pandya pi = (struct port_info *)netdev_priv(pdev); 41541cab775cSVipul Pandya dev_put(pdev); 41551cab775cSVipul Pandya } else { 4156830662f6SVipul Pandya pdev = get_real_dev(neigh->dev); 41571cab775cSVipul Pandya e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, 4158830662f6SVipul Pandya pdev, 0); 4159830662f6SVipul Pandya pi = (struct port_info *)netdev_priv(pdev); 41601cab775cSVipul Pandya } 4161ebf00060SSteve Wise neigh_release(neigh); 41621cab775cSVipul Pandya if (!e) { 41631cab775cSVipul Pandya pr_err("%s - failed to allocate l2t entry!\n", 41641cab775cSVipul Pandya __func__); 41651cab775cSVipul Pandya goto free_dst; 41661cab775cSVipul Pandya } 41671cab775cSVipul Pandya 41681cab775cSVipul Pandya step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan; 41691cab775cSVipul Pandya rss_qid = dev->rdev.lldi.rxq_ids[pi->port_id * step]; 4170ef5d6355SVipul Pandya window = (__force u16) htons((__force u16)tcph->window); 41711cab775cSVipul Pandya 41721cab775cSVipul Pandya /* Calcuate filter portion for LE region. */ 417341b4f86cSKumar Sanghvi filter = (__force unsigned int) cpu_to_be32(cxgb4_select_ntuple( 417441b4f86cSKumar Sanghvi dev->rdev.lldi.ports[0], 417541b4f86cSKumar Sanghvi e)); 41761cab775cSVipul Pandya 41771cab775cSVipul Pandya /* 41781cab775cSVipul Pandya * Synthesize the cpl_pass_accept_req. We have everything except the 41791cab775cSVipul Pandya * TID. Once firmware sends a reply with TID we update the TID field 41801cab775cSVipul Pandya * in cpl and pass it through the regular cpl_pass_accept_req path. 41811cab775cSVipul Pandya */ 41821cab775cSVipul Pandya build_cpl_pass_accept_req(skb, stid, iph->tos); 41831cab775cSVipul Pandya send_fw_pass_open_req(dev, skb, iph->daddr, tcph->dest, iph->saddr, 41841cab775cSVipul Pandya tcph->source, ntohl(tcph->seq), filter, window, 41851cab775cSVipul Pandya rss_qid, pi->port_id); 41861cab775cSVipul Pandya cxgb4_l2t_release(e); 41871cab775cSVipul Pandya free_dst: 41881cab775cSVipul Pandya dst_release(dst); 41891cab775cSVipul Pandya reject: 4190f86fac79SHariprasad S if (lep) 4191f86fac79SHariprasad S c4iw_put_ep(&lep->com); 41922f5b48c3SSteve Wise return 0; 41932f5b48c3SSteve Wise } 41942f5b48c3SSteve Wise 4195cfdda9d7SSteve Wise /* 4196be4c9badSRoland Dreier * These are the real handlers that are called from a 4197be4c9badSRoland Dreier * work queue. 4198be4c9badSRoland Dreier */ 41999dec900cSHariprasad S static c4iw_handler_func work_handlers[NUM_CPL_CMDS + NUM_FAKE_CPLS] = { 4200be4c9badSRoland Dreier [CPL_ACT_ESTABLISH] = act_establish, 4201be4c9badSRoland Dreier [CPL_ACT_OPEN_RPL] = act_open_rpl, 4202be4c9badSRoland Dreier [CPL_RX_DATA] = rx_data, 4203be4c9badSRoland Dreier [CPL_ABORT_RPL_RSS] = abort_rpl, 4204be4c9badSRoland Dreier [CPL_ABORT_RPL] = abort_rpl, 4205be4c9badSRoland Dreier [CPL_PASS_OPEN_RPL] = pass_open_rpl, 4206be4c9badSRoland Dreier [CPL_CLOSE_LISTSRV_RPL] = close_listsrv_rpl, 4207be4c9badSRoland Dreier [CPL_PASS_ACCEPT_REQ] = pass_accept_req, 4208be4c9badSRoland Dreier [CPL_PASS_ESTABLISH] = pass_establish, 4209be4c9badSRoland Dreier [CPL_PEER_CLOSE] = peer_close, 4210be4c9badSRoland Dreier [CPL_ABORT_REQ_RSS] = peer_abort, 4211be4c9badSRoland Dreier [CPL_CLOSE_CON_RPL] = close_con_rpl, 4212be4c9badSRoland Dreier [CPL_RDMA_TERMINATE] = terminate, 42132f5b48c3SSteve Wise [CPL_FW4_ACK] = fw4_ack, 421411a27e21SRaju Rangoju [CPL_GET_TCB_RPL] = read_tcb_rpl, 42151cab775cSVipul Pandya [CPL_FW6_MSG] = deferred_fw6_msg, 42169dec900cSHariprasad S [CPL_RX_PKT] = rx_pkt, 42178d1f1a6bSHariprasad S [FAKE_CPL_PUT_EP_SAFE] = _put_ep_safe, 42188d1f1a6bSHariprasad S [FAKE_CPL_PASS_PUT_EP_SAFE] = _put_pass_ep_safe 4219be4c9badSRoland Dreier }; 4220be4c9badSRoland Dreier 4221be4c9badSRoland Dreier static void process_timeout(struct c4iw_ep *ep) 4222be4c9badSRoland Dreier { 4223be4c9badSRoland Dreier struct c4iw_qp_attributes attrs; 4224be4c9badSRoland Dreier int abort = 1; 4225be4c9badSRoland Dreier 42262f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 4227548ddb19SBharat Potnuri pr_debug("ep %p tid %u state %d\n", ep, ep->hwtid, ep->com.state); 4228793dad94SVipul Pandya set_bit(TIMEDOUT, &ep->com.history); 4229be4c9badSRoland Dreier switch (ep->com.state) { 4230be4c9badSRoland Dreier case MPA_REQ_SENT: 4231be4c9badSRoland Dreier connect_reply_upcall(ep, -ETIMEDOUT); 4232be4c9badSRoland Dreier break; 4233be4c9badSRoland Dreier case MPA_REQ_WAIT: 4234ceb110a8SHariprasad S case MPA_REQ_RCVD: 4235e4b76a2aSHariprasad S case MPA_REP_SENT: 4236ceb110a8SHariprasad S case FPDU_MODE: 4237be4c9badSRoland Dreier break; 4238be4c9badSRoland Dreier case CLOSING: 4239be4c9badSRoland Dreier case MORIBUND: 4240be4c9badSRoland Dreier if (ep->com.cm_id && ep->com.qp) { 4241be4c9badSRoland Dreier attrs.next_state = C4IW_QP_STATE_ERROR; 4242be4c9badSRoland Dreier c4iw_modify_qp(ep->com.qp->rhp, 4243be4c9badSRoland Dreier ep->com.qp, C4IW_QP_ATTR_NEXT_STATE, 4244be4c9badSRoland Dreier &attrs, 1); 4245be4c9badSRoland Dreier } 4246be13b2dfSSteve Wise close_complete_upcall(ep, -ETIMEDOUT); 4247be4c9badSRoland Dreier break; 4248b33bd0cbSSteve Wise case ABORTING: 4249b33bd0cbSSteve Wise case DEAD: 4250b33bd0cbSSteve Wise 4251b33bd0cbSSteve Wise /* 4252b33bd0cbSSteve Wise * These states are expected if the ep timed out at the same 4253b33bd0cbSSteve Wise * time as another thread was calling stop_ep_timer(). 4254b33bd0cbSSteve Wise * So we silently do nothing for these states. 4255b33bd0cbSSteve Wise */ 4256b33bd0cbSSteve Wise abort = 0; 4257b33bd0cbSSteve Wise break; 4258be4c9badSRoland Dreier default: 425976f267b7SJulia Lawall WARN(1, "%s unexpected state ep %p tid %u state %u\n", 4260be4c9badSRoland Dreier __func__, ep, ep->hwtid, ep->com.state); 4261be4c9badSRoland Dreier abort = 0; 4262be4c9badSRoland Dreier } 4263cc18b939SSteve Wise mutex_unlock(&ep->com.mutex); 426469736279SHariprasad S if (abort) 426569736279SHariprasad S c4iw_ep_disconnect(ep, 1, GFP_KERNEL); 4266be4c9badSRoland Dreier c4iw_put_ep(&ep->com); 4267be4c9badSRoland Dreier } 4268be4c9badSRoland Dreier 4269be4c9badSRoland Dreier static void process_timedout_eps(void) 4270be4c9badSRoland Dreier { 4271be4c9badSRoland Dreier struct c4iw_ep *ep; 4272be4c9badSRoland Dreier 4273be4c9badSRoland Dreier spin_lock_irq(&timeout_lock); 4274be4c9badSRoland Dreier while (!list_empty(&timeout_list)) { 4275be4c9badSRoland Dreier struct list_head *tmp; 4276be4c9badSRoland Dreier 4277be4c9badSRoland Dreier tmp = timeout_list.next; 4278be4c9badSRoland Dreier list_del(tmp); 4279b33bd0cbSSteve Wise tmp->next = NULL; 4280b33bd0cbSSteve Wise tmp->prev = NULL; 4281be4c9badSRoland Dreier spin_unlock_irq(&timeout_lock); 4282be4c9badSRoland Dreier ep = list_entry(tmp, struct c4iw_ep, entry); 4283be4c9badSRoland Dreier process_timeout(ep); 4284be4c9badSRoland Dreier spin_lock_irq(&timeout_lock); 4285be4c9badSRoland Dreier } 4286be4c9badSRoland Dreier spin_unlock_irq(&timeout_lock); 4287be4c9badSRoland Dreier } 4288be4c9badSRoland Dreier 4289be4c9badSRoland Dreier static void process_work(struct work_struct *work) 4290be4c9badSRoland Dreier { 4291be4c9badSRoland Dreier struct sk_buff *skb = NULL; 4292be4c9badSRoland Dreier struct c4iw_dev *dev; 4293c1d7356cSDan Carpenter struct cpl_act_establish *rpl; 4294be4c9badSRoland Dreier unsigned int opcode; 4295be4c9badSRoland Dreier int ret; 4296be4c9badSRoland Dreier 4297b33bd0cbSSteve Wise process_timedout_eps(); 4298be4c9badSRoland Dreier while ((skb = skb_dequeue(&rxq))) { 4299be4c9badSRoland Dreier rpl = cplhdr(skb); 4300be4c9badSRoland Dreier dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *))); 4301be4c9badSRoland Dreier opcode = rpl->ot.opcode; 4302be4c9badSRoland Dreier 4303ccc04cddSDan Carpenter if (opcode >= ARRAY_SIZE(work_handlers) || 4304ccc04cddSDan Carpenter !work_handlers[opcode]) { 4305ccc04cddSDan Carpenter pr_err("No handler for opcode 0x%x.\n", opcode); 4306ccc04cddSDan Carpenter kfree_skb(skb); 4307ccc04cddSDan Carpenter } else { 4308be4c9badSRoland Dreier ret = work_handlers[opcode](dev, skb); 4309be4c9badSRoland Dreier if (!ret) 4310be4c9badSRoland Dreier kfree_skb(skb); 4311ccc04cddSDan Carpenter } 4312be4c9badSRoland Dreier process_timedout_eps(); 4313be4c9badSRoland Dreier } 4314b33bd0cbSSteve Wise } 4315be4c9badSRoland Dreier 4316be4c9badSRoland Dreier static DECLARE_WORK(skb_work, process_work); 4317be4c9badSRoland Dreier 4318a9346abeSKees Cook static void ep_timeout(struct timer_list *t) 4319be4c9badSRoland Dreier { 4320a9346abeSKees Cook struct c4iw_ep *ep = from_timer(ep, t, timer); 43211ec779ccSVipul Pandya int kickit = 0; 4322be4c9badSRoland Dreier 4323be4c9badSRoland Dreier spin_lock(&timeout_lock); 43241ec779ccSVipul Pandya if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) { 4325b33bd0cbSSteve Wise /* 4326b33bd0cbSSteve Wise * Only insert if it is not already on the list. 4327b33bd0cbSSteve Wise */ 4328b33bd0cbSSteve Wise if (!ep->entry.next) { 4329be4c9badSRoland Dreier list_add_tail(&ep->entry, &timeout_list); 43301ec779ccSVipul Pandya kickit = 1; 43311ec779ccSVipul Pandya } 4332b33bd0cbSSteve Wise } 4333be4c9badSRoland Dreier spin_unlock(&timeout_lock); 43341ec779ccSVipul Pandya if (kickit) 4335be4c9badSRoland Dreier queue_work(workq, &skb_work); 4336be4c9badSRoland Dreier } 4337be4c9badSRoland Dreier 4338be4c9badSRoland Dreier /* 4339cfdda9d7SSteve Wise * All the CM events are handled on a work queue to have a safe context. 4340cfdda9d7SSteve Wise */ 4341cfdda9d7SSteve Wise static int sched(struct c4iw_dev *dev, struct sk_buff *skb) 4342cfdda9d7SSteve Wise { 4343cfdda9d7SSteve Wise 4344cfdda9d7SSteve Wise /* 4345cfdda9d7SSteve Wise * Save dev in the skb->cb area. 4346cfdda9d7SSteve Wise */ 4347cfdda9d7SSteve Wise *((struct c4iw_dev **) (skb->cb + sizeof(void *))) = dev; 4348cfdda9d7SSteve Wise 4349cfdda9d7SSteve Wise /* 4350cfdda9d7SSteve Wise * Queue the skb and schedule the worker thread. 4351cfdda9d7SSteve Wise */ 4352cfdda9d7SSteve Wise skb_queue_tail(&rxq, skb); 4353cfdda9d7SSteve Wise queue_work(workq, &skb_work); 4354cfdda9d7SSteve Wise return 0; 4355cfdda9d7SSteve Wise } 4356cfdda9d7SSteve Wise 4357cfdda9d7SSteve Wise static int set_tcb_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 4358cfdda9d7SSteve Wise { 4359cfdda9d7SSteve Wise struct cpl_set_tcb_rpl *rpl = cplhdr(skb); 4360cfdda9d7SSteve Wise 4361cfdda9d7SSteve Wise if (rpl->status != CPL_ERR_NONE) { 4362700456bdSJoe Perches pr_err("Unexpected SET_TCB_RPL status %u for tid %u\n", 4363700456bdSJoe Perches rpl->status, GET_TID(rpl)); 4364cfdda9d7SSteve Wise } 43652f5b48c3SSteve Wise kfree_skb(skb); 4366cfdda9d7SSteve Wise return 0; 4367cfdda9d7SSteve Wise } 4368cfdda9d7SSteve Wise 4369be4c9badSRoland Dreier static int fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb) 4370be4c9badSRoland Dreier { 4371be4c9badSRoland Dreier struct cpl_fw6_msg *rpl = cplhdr(skb); 4372be4c9badSRoland Dreier struct c4iw_wr_wait *wr_waitp; 4373be4c9badSRoland Dreier int ret; 4374be4c9badSRoland Dreier 4375548ddb19SBharat Potnuri pr_debug("type %u\n", rpl->type); 4376be4c9badSRoland Dreier 4377be4c9badSRoland Dreier switch (rpl->type) { 43785be78ee9SVipul Pandya case FW6_TYPE_WR_RPL: 4379be4c9badSRoland Dreier ret = (int)((be64_to_cpu(rpl->data[0]) >> 8) & 0xff); 4380c8e081a1SRoland Dreier wr_waitp = (struct c4iw_wr_wait *)(__force unsigned long) rpl->data[1]; 4381548ddb19SBharat Potnuri pr_debug("wr_waitp %p ret %u\n", wr_waitp, ret); 4382d9594d99SSteve Wise if (wr_waitp) 43832015f26cSSteve Wise c4iw_wake_up_deref(wr_waitp, ret ? -ret : 0); 43842f5b48c3SSteve Wise kfree_skb(skb); 4385be4c9badSRoland Dreier break; 43865be78ee9SVipul Pandya case FW6_TYPE_CQE: 43875be78ee9SVipul Pandya case FW6_TYPE_OFLD_CONNECTION_WR_RPL: 43881cab775cSVipul Pandya sched(dev, skb); 43895be78ee9SVipul Pandya break; 4390be4c9badSRoland Dreier default: 4391700456bdSJoe Perches pr_err("%s unexpected fw6 msg type %u\n", 4392700456bdSJoe Perches __func__, rpl->type); 43932f5b48c3SSteve Wise kfree_skb(skb); 4394be4c9badSRoland Dreier break; 4395be4c9badSRoland Dreier } 4396be4c9badSRoland Dreier return 0; 4397be4c9badSRoland Dreier } 4398be4c9badSRoland Dreier 43998da7e7a5SSteve Wise static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb) 44008da7e7a5SSteve Wise { 44018da7e7a5SSteve Wise struct cpl_abort_req_rss *req = cplhdr(skb); 44028da7e7a5SSteve Wise struct c4iw_ep *ep; 44038da7e7a5SSteve Wise unsigned int tid = GET_TID(req); 44048da7e7a5SSteve Wise 4405944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 4406944661ddSHariprasad S /* This EP will be dereferenced in peer_abort() */ 440714b92228SSteve Wise if (!ep) { 4408700456bdSJoe Perches pr_warn("Abort on non-existent endpoint, tid %d\n", tid); 440914b92228SSteve Wise kfree_skb(skb); 441014b92228SSteve Wise return 0; 441114b92228SSteve Wise } 4412b65eef0aSVarun Prakash if (cxgb_is_neg_adv(req->status)) { 4413f48fca4dSBharat Potnuri pr_debug("Negative advice on abort- tid %u status %d (%s)\n", 4414f48fca4dSBharat Potnuri ep->hwtid, req->status, 4415179d03bbSHariprasad S neg_adv_str(req->status)); 4416944661ddSHariprasad S goto out; 44178da7e7a5SSteve Wise } 4418548ddb19SBharat Potnuri pr_debug("ep %p tid %u state %u\n", ep, ep->hwtid, ep->com.state); 44198da7e7a5SSteve Wise 44202015f26cSSteve Wise c4iw_wake_up_noref(ep->com.wr_waitp, -ECONNRESET); 4421944661ddSHariprasad S out: 44228da7e7a5SSteve Wise sched(dev, skb); 44238da7e7a5SSteve Wise return 0; 44248da7e7a5SSteve Wise } 44258da7e7a5SSteve Wise 4426be4c9badSRoland Dreier /* 4427be4c9badSRoland Dreier * Most upcalls from the T4 Core go to sched() to 4428be4c9badSRoland Dreier * schedule the processing on a work queue. 4429be4c9badSRoland Dreier */ 4430be4c9badSRoland Dreier c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS] = { 4431be4c9badSRoland Dreier [CPL_ACT_ESTABLISH] = sched, 4432be4c9badSRoland Dreier [CPL_ACT_OPEN_RPL] = sched, 4433be4c9badSRoland Dreier [CPL_RX_DATA] = sched, 4434be4c9badSRoland Dreier [CPL_ABORT_RPL_RSS] = sched, 4435be4c9badSRoland Dreier [CPL_ABORT_RPL] = sched, 4436be4c9badSRoland Dreier [CPL_PASS_OPEN_RPL] = sched, 4437be4c9badSRoland Dreier [CPL_CLOSE_LISTSRV_RPL] = sched, 4438be4c9badSRoland Dreier [CPL_PASS_ACCEPT_REQ] = sched, 4439be4c9badSRoland Dreier [CPL_PASS_ESTABLISH] = sched, 4440be4c9badSRoland Dreier [CPL_PEER_CLOSE] = sched, 4441be4c9badSRoland Dreier [CPL_CLOSE_CON_RPL] = sched, 44428da7e7a5SSteve Wise [CPL_ABORT_REQ_RSS] = peer_abort_intr, 4443be4c9badSRoland Dreier [CPL_RDMA_TERMINATE] = sched, 4444be4c9badSRoland Dreier [CPL_FW4_ACK] = sched, 4445be4c9badSRoland Dreier [CPL_SET_TCB_RPL] = set_tcb_rpl, 444611a27e21SRaju Rangoju [CPL_GET_TCB_RPL] = sched, 44471cab775cSVipul Pandya [CPL_FW6_MSG] = fw6_msg, 44481cab775cSVipul Pandya [CPL_RX_PKT] = sched 4449be4c9badSRoland Dreier }; 4450be4c9badSRoland Dreier 4451cfdda9d7SSteve Wise int __init c4iw_cm_init(void) 4452cfdda9d7SSteve Wise { 4453cfdda9d7SSteve Wise skb_queue_head_init(&rxq); 4454cfdda9d7SSteve Wise 445552ee1a05SBhaktipriya Shridhar workq = alloc_ordered_workqueue("iw_cxgb4", WQ_MEM_RECLAIM); 4456cfdda9d7SSteve Wise if (!workq) 4457cfdda9d7SSteve Wise return -ENOMEM; 4458cfdda9d7SSteve Wise 4459cfdda9d7SSteve Wise return 0; 4460cfdda9d7SSteve Wise } 4461cfdda9d7SSteve Wise 446246c1376dSSteve Wise void c4iw_cm_term(void) 4463cfdda9d7SSteve Wise { 4464be4c9badSRoland Dreier WARN_ON(!list_empty(&timeout_list)); 4465cfdda9d7SSteve Wise destroy_workqueue(workq); 4466cfdda9d7SSteve Wise } 4467