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 80b52fe09eSSteve Wise static int dack_mode = 1; 81ba6d3925SSteve Wise module_param(dack_mode, int, 0644); 82b52fe09eSSteve Wise MODULE_PARM_DESC(dack_mode, "Delayed ack mode (default=1)"); 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 102cfdda9d7SSteve Wise int c4iw_debug; 103cfdda9d7SSteve Wise module_param(c4iw_debug, int, 0644); 104cfdda9d7SSteve Wise MODULE_PARM_DESC(c4iw_debug, "Enable debug logging (default=0)"); 105cfdda9d7SSteve Wise 106df2d5130SSteve Wise static int peer2peer = 1; 107cfdda9d7SSteve Wise module_param(peer2peer, int, 0644); 108df2d5130SSteve Wise MODULE_PARM_DESC(peer2peer, "Support peer2peer ULPs (default=1)"); 109cfdda9d7SSteve Wise 110cfdda9d7SSteve Wise static int p2p_type = FW_RI_INIT_P2PTYPE_READ_REQ; 111cfdda9d7SSteve Wise module_param(p2p_type, int, 0644); 112cfdda9d7SSteve Wise MODULE_PARM_DESC(p2p_type, "RDMAP opcode to use for the RTR message: " 113cfdda9d7SSteve Wise "1=RDMA_READ 0=RDMA_WRITE (default 1)"); 114cfdda9d7SSteve Wise 115cfdda9d7SSteve Wise static int ep_timeout_secs = 60; 116cfdda9d7SSteve Wise module_param(ep_timeout_secs, int, 0644); 117cfdda9d7SSteve Wise MODULE_PARM_DESC(ep_timeout_secs, "CM Endpoint operation timeout " 118cfdda9d7SSteve Wise "in seconds (default=60)"); 119cfdda9d7SSteve Wise 120b8ac3112SHariprasad S static int mpa_rev = 2; 121cfdda9d7SSteve Wise module_param(mpa_rev, int, 0644); 122cfdda9d7SSteve Wise MODULE_PARM_DESC(mpa_rev, "MPA Revision, 0 supports amso1100, " 123ccd2c30bSHariprasad S "1 is RFC5044 spec compliant, 2 is IETF MPA Peer Connect Draft" 124b8ac3112SHariprasad S " compliant (default=2)"); 125cfdda9d7SSteve Wise 126cfdda9d7SSteve Wise static int markers_enabled; 127cfdda9d7SSteve Wise module_param(markers_enabled, int, 0644); 128cfdda9d7SSteve Wise MODULE_PARM_DESC(markers_enabled, "Enable MPA MARKERS (default(0)=disabled)"); 129cfdda9d7SSteve Wise 130cfdda9d7SSteve Wise static int crc_enabled = 1; 131cfdda9d7SSteve Wise module_param(crc_enabled, int, 0644); 132cfdda9d7SSteve Wise MODULE_PARM_DESC(crc_enabled, "Enable MPA CRC (default(1)=enabled)"); 133cfdda9d7SSteve Wise 134cfdda9d7SSteve Wise static int rcv_win = 256 * 1024; 135cfdda9d7SSteve Wise module_param(rcv_win, int, 0644); 136cfdda9d7SSteve Wise MODULE_PARM_DESC(rcv_win, "TCP receive window in bytes (default=256KB)"); 137cfdda9d7SSteve Wise 13898ae68b7SSteve Wise static int snd_win = 128 * 1024; 139cfdda9d7SSteve Wise module_param(snd_win, int, 0644); 14098ae68b7SSteve Wise MODULE_PARM_DESC(snd_win, "TCP send window in bytes (default=128KB)"); 141cfdda9d7SSteve Wise 142cfdda9d7SSteve Wise static struct workqueue_struct *workq; 143cfdda9d7SSteve Wise 144cfdda9d7SSteve Wise static struct sk_buff_head rxq; 145cfdda9d7SSteve Wise 146cfdda9d7SSteve Wise static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp); 147cfdda9d7SSteve Wise static void ep_timeout(unsigned long arg); 148cfdda9d7SSteve Wise static void connect_reply_upcall(struct c4iw_ep *ep, int status); 1499dec900cSHariprasad S static int sched(struct c4iw_dev *dev, struct sk_buff *skb); 150cfdda9d7SSteve Wise 151be4c9badSRoland Dreier static LIST_HEAD(timeout_list); 152be4c9badSRoland Dreier static spinlock_t timeout_lock; 153be4c9badSRoland Dreier 1549ca6f7cfSHariprasad S static void deref_cm_id(struct c4iw_ep_common *epc) 1559ca6f7cfSHariprasad S { 1569ca6f7cfSHariprasad S epc->cm_id->rem_ref(epc->cm_id); 1579ca6f7cfSHariprasad S epc->cm_id = NULL; 1589ca6f7cfSHariprasad S set_bit(CM_ID_DEREFED, &epc->history); 1599ca6f7cfSHariprasad S } 1609ca6f7cfSHariprasad S 1619ca6f7cfSHariprasad S static void ref_cm_id(struct c4iw_ep_common *epc) 1629ca6f7cfSHariprasad S { 1639ca6f7cfSHariprasad S set_bit(CM_ID_REFED, &epc->history); 1649ca6f7cfSHariprasad S epc->cm_id->add_ref(epc->cm_id); 1659ca6f7cfSHariprasad S } 1669ca6f7cfSHariprasad S 167325abeadSVipul Pandya static void deref_qp(struct c4iw_ep *ep) 168325abeadSVipul Pandya { 169325abeadSVipul Pandya c4iw_qp_rem_ref(&ep->com.qp->ibqp); 170325abeadSVipul Pandya clear_bit(QP_REFERENCED, &ep->com.flags); 1719ca6f7cfSHariprasad S set_bit(QP_DEREFED, &ep->com.history); 172325abeadSVipul Pandya } 173325abeadSVipul Pandya 174325abeadSVipul Pandya static void ref_qp(struct c4iw_ep *ep) 175325abeadSVipul Pandya { 176325abeadSVipul Pandya set_bit(QP_REFERENCED, &ep->com.flags); 1779ca6f7cfSHariprasad S set_bit(QP_REFED, &ep->com.history); 178325abeadSVipul Pandya c4iw_qp_add_ref(&ep->com.qp->ibqp); 179325abeadSVipul Pandya } 180325abeadSVipul Pandya 181cfdda9d7SSteve Wise static void start_ep_timer(struct c4iw_ep *ep) 182cfdda9d7SSteve Wise { 183cfdda9d7SSteve Wise PDBG("%s ep %p\n", __func__, ep); 184cfdda9d7SSteve Wise if (timer_pending(&ep->timer)) { 1851ec779ccSVipul Pandya pr_err("%s timer already started! ep %p\n", 1861ec779ccSVipul Pandya __func__, ep); 1871ec779ccSVipul Pandya return; 1881ec779ccSVipul Pandya } 1891ec779ccSVipul Pandya clear_bit(TIMEOUT, &ep->com.flags); 190cfdda9d7SSteve Wise c4iw_get_ep(&ep->com); 191cfdda9d7SSteve Wise ep->timer.expires = jiffies + ep_timeout_secs * HZ; 192cfdda9d7SSteve Wise ep->timer.data = (unsigned long)ep; 193cfdda9d7SSteve Wise ep->timer.function = ep_timeout; 194cfdda9d7SSteve Wise add_timer(&ep->timer); 195cfdda9d7SSteve Wise } 196cfdda9d7SSteve Wise 197b33bd0cbSSteve Wise static int stop_ep_timer(struct c4iw_ep *ep) 198cfdda9d7SSteve Wise { 1991ec779ccSVipul Pandya PDBG("%s ep %p stopping\n", __func__, ep); 200cfdda9d7SSteve Wise del_timer_sync(&ep->timer); 201b33bd0cbSSteve Wise if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) { 202cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 203b33bd0cbSSteve Wise return 0; 204b33bd0cbSSteve Wise } 205b33bd0cbSSteve Wise return 1; 206cfdda9d7SSteve Wise } 207cfdda9d7SSteve Wise 208cfdda9d7SSteve Wise static int c4iw_l2t_send(struct c4iw_rdev *rdev, struct sk_buff *skb, 209cfdda9d7SSteve Wise struct l2t_entry *l2e) 210cfdda9d7SSteve Wise { 211cfdda9d7SSteve Wise int error = 0; 212cfdda9d7SSteve Wise 213cfdda9d7SSteve Wise if (c4iw_fatal_error(rdev)) { 214cfdda9d7SSteve Wise kfree_skb(skb); 215cfdda9d7SSteve Wise PDBG("%s - device in error state - dropping\n", __func__); 216cfdda9d7SSteve Wise return -EIO; 217cfdda9d7SSteve Wise } 218cfdda9d7SSteve Wise error = cxgb4_l2t_send(rdev->lldi.ports[0], skb, l2e); 219cfdda9d7SSteve Wise if (error < 0) 220cfdda9d7SSteve Wise kfree_skb(skb); 221caa6c9f2SHariprasad S else if (error == NET_XMIT_DROP) 222caa6c9f2SHariprasad S return -ENOMEM; 22374594861SSteve Wise return error < 0 ? error : 0; 224cfdda9d7SSteve Wise } 225cfdda9d7SSteve Wise 226cfdda9d7SSteve Wise int c4iw_ofld_send(struct c4iw_rdev *rdev, struct sk_buff *skb) 227cfdda9d7SSteve Wise { 228cfdda9d7SSteve Wise int error = 0; 229cfdda9d7SSteve Wise 230cfdda9d7SSteve Wise if (c4iw_fatal_error(rdev)) { 231cfdda9d7SSteve Wise kfree_skb(skb); 232cfdda9d7SSteve Wise PDBG("%s - device in error state - dropping\n", __func__); 233cfdda9d7SSteve Wise return -EIO; 234cfdda9d7SSteve Wise } 235cfdda9d7SSteve Wise error = cxgb4_ofld_send(rdev->lldi.ports[0], skb); 236cfdda9d7SSteve Wise if (error < 0) 237cfdda9d7SSteve Wise kfree_skb(skb); 23874594861SSteve Wise return error < 0 ? error : 0; 239cfdda9d7SSteve Wise } 240cfdda9d7SSteve Wise 241cfdda9d7SSteve Wise static void release_tid(struct c4iw_rdev *rdev, u32 hwtid, struct sk_buff *skb) 242cfdda9d7SSteve Wise { 243cfdda9d7SSteve Wise struct cpl_tid_release *req; 244cfdda9d7SSteve Wise 245cfdda9d7SSteve Wise skb = get_skb(skb, sizeof *req, GFP_KERNEL); 246cfdda9d7SSteve Wise if (!skb) 247cfdda9d7SSteve Wise return; 248cfdda9d7SSteve Wise req = (struct cpl_tid_release *) skb_put(skb, sizeof(*req)); 249cfdda9d7SSteve Wise INIT_TP_WR(req, hwtid); 250cfdda9d7SSteve Wise OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_TID_RELEASE, hwtid)); 251cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_SETUP, 0); 252cfdda9d7SSteve Wise c4iw_ofld_send(rdev, skb); 253cfdda9d7SSteve Wise return; 254cfdda9d7SSteve Wise } 255cfdda9d7SSteve Wise 256cfdda9d7SSteve Wise static void set_emss(struct c4iw_ep *ep, u16 opt) 257cfdda9d7SSteve Wise { 2586c53e938SHariprasad Shenai ep->emss = ep->com.dev->rdev.lldi.mtus[TCPOPT_MSS_G(opt)] - 25904524a47SHariprasad S ((AF_INET == ep->com.remote_addr.ss_family) ? 26004524a47SHariprasad S sizeof(struct iphdr) : sizeof(struct ipv6hdr)) - 26104524a47SHariprasad S sizeof(struct tcphdr); 262cfdda9d7SSteve Wise ep->mss = ep->emss; 2636c53e938SHariprasad Shenai if (TCPOPT_TSTAMP_G(opt)) 26404524a47SHariprasad S ep->emss -= round_up(TCPOLEN_TIMESTAMP, 4); 265cfdda9d7SSteve Wise if (ep->emss < 128) 266cfdda9d7SSteve Wise ep->emss = 128; 26792e7ae71SHariprasad Shenai if (ep->emss & 7) 26892e7ae71SHariprasad Shenai PDBG("Warning: misaligned mtu idx %u mss %u emss=%u\n", 2696c53e938SHariprasad Shenai TCPOPT_MSS_G(opt), ep->mss, ep->emss); 2706c53e938SHariprasad Shenai PDBG("%s mss_idx %u mss %u emss=%u\n", __func__, TCPOPT_MSS_G(opt), 271cfdda9d7SSteve Wise ep->mss, ep->emss); 272cfdda9d7SSteve Wise } 273cfdda9d7SSteve Wise 274cfdda9d7SSteve Wise static enum c4iw_ep_state state_read(struct c4iw_ep_common *epc) 275cfdda9d7SSteve Wise { 276cfdda9d7SSteve Wise enum c4iw_ep_state state; 277cfdda9d7SSteve Wise 2782f5b48c3SSteve Wise mutex_lock(&epc->mutex); 279cfdda9d7SSteve Wise state = epc->state; 2802f5b48c3SSteve Wise mutex_unlock(&epc->mutex); 281cfdda9d7SSteve Wise return state; 282cfdda9d7SSteve Wise } 283cfdda9d7SSteve Wise 284cfdda9d7SSteve Wise static void __state_set(struct c4iw_ep_common *epc, enum c4iw_ep_state new) 285cfdda9d7SSteve Wise { 286cfdda9d7SSteve Wise epc->state = new; 287cfdda9d7SSteve Wise } 288cfdda9d7SSteve Wise 289cfdda9d7SSteve Wise static void state_set(struct c4iw_ep_common *epc, enum c4iw_ep_state new) 290cfdda9d7SSteve Wise { 2912f5b48c3SSteve Wise mutex_lock(&epc->mutex); 292cfdda9d7SSteve Wise PDBG("%s - %s -> %s\n", __func__, states[epc->state], states[new]); 293cfdda9d7SSteve Wise __state_set(epc, new); 2942f5b48c3SSteve Wise mutex_unlock(&epc->mutex); 295cfdda9d7SSteve Wise return; 296cfdda9d7SSteve Wise } 297cfdda9d7SSteve Wise 2984a740838SHariprasad S static int alloc_ep_skb_list(struct sk_buff_head *ep_skb_list, int size) 2994a740838SHariprasad S { 3004a740838SHariprasad S struct sk_buff *skb; 3014a740838SHariprasad S unsigned int i; 3024a740838SHariprasad S size_t len; 3034a740838SHariprasad S 3044a740838SHariprasad S len = roundup(sizeof(union cpl_wr_size), 16); 3054a740838SHariprasad S for (i = 0; i < size; i++) { 3064a740838SHariprasad S skb = alloc_skb(len, GFP_KERNEL); 3074a740838SHariprasad S if (!skb) 3084a740838SHariprasad S goto fail; 3094a740838SHariprasad S skb_queue_tail(ep_skb_list, skb); 3104a740838SHariprasad S } 3114a740838SHariprasad S return 0; 3124a740838SHariprasad S fail: 3134a740838SHariprasad S skb_queue_purge(ep_skb_list); 3144a740838SHariprasad S return -ENOMEM; 3154a740838SHariprasad S } 3164a740838SHariprasad S 317cfdda9d7SSteve Wise static void *alloc_ep(int size, gfp_t gfp) 318cfdda9d7SSteve Wise { 319cfdda9d7SSteve Wise struct c4iw_ep_common *epc; 320cfdda9d7SSteve Wise 321cfdda9d7SSteve Wise epc = kzalloc(size, gfp); 322cfdda9d7SSteve Wise if (epc) { 323cfdda9d7SSteve Wise kref_init(&epc->kref); 3242f5b48c3SSteve Wise mutex_init(&epc->mutex); 325aadc4df3SSteve Wise c4iw_init_wr_wait(&epc->wr_wait); 326cfdda9d7SSteve Wise } 327cfdda9d7SSteve Wise PDBG("%s alloc ep %p\n", __func__, epc); 328cfdda9d7SSteve Wise return epc; 329cfdda9d7SSteve Wise } 330cfdda9d7SSteve Wise 331944661ddSHariprasad S static void remove_ep_tid(struct c4iw_ep *ep) 332944661ddSHariprasad S { 333944661ddSHariprasad S unsigned long flags; 334944661ddSHariprasad S 335944661ddSHariprasad S spin_lock_irqsave(&ep->com.dev->lock, flags); 336944661ddSHariprasad S _remove_handle(ep->com.dev, &ep->com.dev->hwtid_idr, ep->hwtid, 0); 337944661ddSHariprasad S spin_unlock_irqrestore(&ep->com.dev->lock, flags); 338944661ddSHariprasad S } 339944661ddSHariprasad S 340944661ddSHariprasad S static void insert_ep_tid(struct c4iw_ep *ep) 341944661ddSHariprasad S { 342944661ddSHariprasad S unsigned long flags; 343944661ddSHariprasad S 344944661ddSHariprasad S spin_lock_irqsave(&ep->com.dev->lock, flags); 345944661ddSHariprasad S _insert_handle(ep->com.dev, &ep->com.dev->hwtid_idr, ep, ep->hwtid, 0); 346944661ddSHariprasad S spin_unlock_irqrestore(&ep->com.dev->lock, flags); 347944661ddSHariprasad S } 348944661ddSHariprasad S 349944661ddSHariprasad S /* 350944661ddSHariprasad S * Atomically lookup the ep ptr given the tid and grab a reference on the ep. 351944661ddSHariprasad S */ 352944661ddSHariprasad S static struct c4iw_ep *get_ep_from_tid(struct c4iw_dev *dev, unsigned int tid) 353944661ddSHariprasad S { 354944661ddSHariprasad S struct c4iw_ep *ep; 355944661ddSHariprasad S unsigned long flags; 356944661ddSHariprasad S 357944661ddSHariprasad S spin_lock_irqsave(&dev->lock, flags); 358944661ddSHariprasad S ep = idr_find(&dev->hwtid_idr, tid); 359944661ddSHariprasad S if (ep) 360944661ddSHariprasad S c4iw_get_ep(&ep->com); 361944661ddSHariprasad S spin_unlock_irqrestore(&dev->lock, flags); 362944661ddSHariprasad S return ep; 363944661ddSHariprasad S } 364944661ddSHariprasad S 365f86fac79SHariprasad S /* 366f86fac79SHariprasad S * Atomically lookup the ep ptr given the stid and grab a reference on the ep. 367f86fac79SHariprasad S */ 368f86fac79SHariprasad S static struct c4iw_listen_ep *get_ep_from_stid(struct c4iw_dev *dev, 369f86fac79SHariprasad S unsigned int stid) 370f86fac79SHariprasad S { 371f86fac79SHariprasad S struct c4iw_listen_ep *ep; 372f86fac79SHariprasad S unsigned long flags; 373f86fac79SHariprasad S 374f86fac79SHariprasad S spin_lock_irqsave(&dev->lock, flags); 375f86fac79SHariprasad S ep = idr_find(&dev->stid_idr, stid); 376f86fac79SHariprasad S if (ep) 377f86fac79SHariprasad S c4iw_get_ep(&ep->com); 378f86fac79SHariprasad S spin_unlock_irqrestore(&dev->lock, flags); 379f86fac79SHariprasad S return ep; 380f86fac79SHariprasad S } 381f86fac79SHariprasad S 382cfdda9d7SSteve Wise void _c4iw_free_ep(struct kref *kref) 383cfdda9d7SSteve Wise { 384cfdda9d7SSteve Wise struct c4iw_ep *ep; 385cfdda9d7SSteve Wise 386cfdda9d7SSteve Wise ep = container_of(kref, struct c4iw_ep, com.kref); 3879dec900cSHariprasad S PDBG("%s ep %p state %s\n", __func__, ep, states[ep->com.state]); 388325abeadSVipul Pandya if (test_bit(QP_REFERENCED, &ep->com.flags)) 389325abeadSVipul Pandya deref_qp(ep); 390cfdda9d7SSteve Wise if (test_bit(RELEASE_RESOURCES, &ep->com.flags)) { 39184cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 39284cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 39384cc6ac6SHariprasad S (struct sockaddr_in6 *) 394170003c8SSteve Wise &ep->com.local_addr; 39584cc6ac6SHariprasad S 39684cc6ac6SHariprasad S cxgb4_clip_release( 39784cc6ac6SHariprasad S ep->com.dev->rdev.lldi.ports[0], 39884cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 39984cc6ac6SHariprasad S 1); 40084cc6ac6SHariprasad S } 401cfdda9d7SSteve Wise cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid); 402cfdda9d7SSteve Wise dst_release(ep->dst); 403cfdda9d7SSteve Wise cxgb4_l2t_release(ep->l2t); 404c878b706SHariprasad S if (ep->mpa_skb) 405c878b706SHariprasad S kfree_skb(ep->mpa_skb); 406cfdda9d7SSteve Wise } 4074a740838SHariprasad S if (!skb_queue_empty(&ep->com.ep_skb_list)) 4084a740838SHariprasad S skb_queue_purge(&ep->com.ep_skb_list); 409cfdda9d7SSteve Wise kfree(ep); 410cfdda9d7SSteve Wise } 411cfdda9d7SSteve Wise 412cfdda9d7SSteve Wise static void release_ep_resources(struct c4iw_ep *ep) 413cfdda9d7SSteve Wise { 414cfdda9d7SSteve Wise set_bit(RELEASE_RESOURCES, &ep->com.flags); 415944661ddSHariprasad S 416944661ddSHariprasad S /* 417944661ddSHariprasad S * If we have a hwtid, then remove it from the idr table 418944661ddSHariprasad S * so lookups will no longer find this endpoint. Otherwise 419944661ddSHariprasad S * we have a race where one thread finds the ep ptr just 420944661ddSHariprasad S * before the other thread is freeing the ep memory. 421944661ddSHariprasad S */ 422944661ddSHariprasad S if (ep->hwtid != -1) 423944661ddSHariprasad S remove_ep_tid(ep); 424cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 425cfdda9d7SSteve Wise } 426cfdda9d7SSteve Wise 427cfdda9d7SSteve Wise static int status2errno(int status) 428cfdda9d7SSteve Wise { 429cfdda9d7SSteve Wise switch (status) { 430cfdda9d7SSteve Wise case CPL_ERR_NONE: 431cfdda9d7SSteve Wise return 0; 432cfdda9d7SSteve Wise case CPL_ERR_CONN_RESET: 433cfdda9d7SSteve Wise return -ECONNRESET; 434cfdda9d7SSteve Wise case CPL_ERR_ARP_MISS: 435cfdda9d7SSteve Wise return -EHOSTUNREACH; 436cfdda9d7SSteve Wise case CPL_ERR_CONN_TIMEDOUT: 437cfdda9d7SSteve Wise return -ETIMEDOUT; 438cfdda9d7SSteve Wise case CPL_ERR_TCAM_FULL: 439cfdda9d7SSteve Wise return -ENOMEM; 440cfdda9d7SSteve Wise case CPL_ERR_CONN_EXIST: 441cfdda9d7SSteve Wise return -EADDRINUSE; 442cfdda9d7SSteve Wise default: 443cfdda9d7SSteve Wise return -EIO; 444cfdda9d7SSteve Wise } 445cfdda9d7SSteve Wise } 446cfdda9d7SSteve Wise 447cfdda9d7SSteve Wise /* 448cfdda9d7SSteve Wise * Try and reuse skbs already allocated... 449cfdda9d7SSteve Wise */ 450cfdda9d7SSteve Wise static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp) 451cfdda9d7SSteve Wise { 452cfdda9d7SSteve Wise if (skb && !skb_is_nonlinear(skb) && !skb_cloned(skb)) { 453cfdda9d7SSteve Wise skb_trim(skb, 0); 454cfdda9d7SSteve Wise skb_get(skb); 455cfdda9d7SSteve Wise skb_reset_transport_header(skb); 456cfdda9d7SSteve Wise } else { 457cfdda9d7SSteve Wise skb = alloc_skb(len, gfp); 458cfdda9d7SSteve Wise } 459b38a0ad8SSteve Wise t4_set_arp_err_handler(skb, NULL, NULL); 460cfdda9d7SSteve Wise return skb; 461cfdda9d7SSteve Wise } 462cfdda9d7SSteve Wise 463830662f6SVipul Pandya static struct net_device *get_real_dev(struct net_device *egress_dev) 464830662f6SVipul Pandya { 46511b8e22dSSteve Wise return rdma_vlan_dev_real_dev(egress_dev) ? : egress_dev; 466830662f6SVipul Pandya } 467830662f6SVipul Pandya 468cfdda9d7SSteve Wise static void arp_failure_discard(void *handle, struct sk_buff *skb) 469cfdda9d7SSteve Wise { 4709dec900cSHariprasad S pr_err(MOD "ARP failure\n"); 471cfdda9d7SSteve Wise kfree_skb(skb); 472cfdda9d7SSteve Wise } 473cfdda9d7SSteve Wise 47464bec74aSHariprasad S static void mpa_start_arp_failure(void *handle, struct sk_buff *skb) 47564bec74aSHariprasad S { 47664bec74aSHariprasad S pr_err("ARP failure during MPA Negotiation - Closing Connection\n"); 47764bec74aSHariprasad S } 47864bec74aSHariprasad S 4799dec900cSHariprasad S enum { 4808d1f1a6bSHariprasad S NUM_FAKE_CPLS = 2, 4819dec900cSHariprasad S FAKE_CPL_PUT_EP_SAFE = NUM_CPL_CMDS + 0, 4828d1f1a6bSHariprasad S FAKE_CPL_PASS_PUT_EP_SAFE = NUM_CPL_CMDS + 1, 4839dec900cSHariprasad S }; 4849dec900cSHariprasad S 4859dec900cSHariprasad S static int _put_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb) 4869dec900cSHariprasad S { 4879dec900cSHariprasad S struct c4iw_ep *ep; 4889dec900cSHariprasad S 4899dec900cSHariprasad S ep = *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *))); 4909dec900cSHariprasad S release_ep_resources(ep); 4919dec900cSHariprasad S return 0; 4929dec900cSHariprasad S } 4939dec900cSHariprasad S 4948d1f1a6bSHariprasad S static int _put_pass_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb) 4958d1f1a6bSHariprasad S { 4968d1f1a6bSHariprasad S struct c4iw_ep *ep; 4978d1f1a6bSHariprasad S 4988d1f1a6bSHariprasad S ep = *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *))); 4998d1f1a6bSHariprasad S c4iw_put_ep(&ep->parent_ep->com); 5008d1f1a6bSHariprasad S release_ep_resources(ep); 5018d1f1a6bSHariprasad S return 0; 5028d1f1a6bSHariprasad S } 5038d1f1a6bSHariprasad S 5049dec900cSHariprasad S /* 5059dec900cSHariprasad S * Fake up a special CPL opcode and call sched() so process_work() will call 5069dec900cSHariprasad S * _put_ep_safe() in a safe context to free the ep resources. This is needed 5079dec900cSHariprasad S * because ARP error handlers are called in an ATOMIC context, and 5089dec900cSHariprasad S * _c4iw_free_ep() needs to block. 5099dec900cSHariprasad S */ 5108d1f1a6bSHariprasad S static void queue_arp_failure_cpl(struct c4iw_ep *ep, struct sk_buff *skb, 5118d1f1a6bSHariprasad S int cpl) 5129dec900cSHariprasad S { 5139dec900cSHariprasad S struct cpl_act_establish *rpl = cplhdr(skb); 5149dec900cSHariprasad S 5159dec900cSHariprasad S /* Set our special ARP_FAILURE opcode */ 5168d1f1a6bSHariprasad S rpl->ot.opcode = cpl; 5179dec900cSHariprasad S 5189dec900cSHariprasad S /* 5199dec900cSHariprasad S * Save ep in the skb->cb area, after where sched() will save the dev 5209dec900cSHariprasad S * ptr. 5219dec900cSHariprasad S */ 5229dec900cSHariprasad S *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *))) = ep; 5239dec900cSHariprasad S sched(ep->com.dev, skb); 5249dec900cSHariprasad S } 5259dec900cSHariprasad S 5269dec900cSHariprasad S /* Handle an ARP failure for an accept */ 5279dec900cSHariprasad S static void pass_accept_rpl_arp_failure(void *handle, struct sk_buff *skb) 5289dec900cSHariprasad S { 5299dec900cSHariprasad S struct c4iw_ep *ep = handle; 5309dec900cSHariprasad S 5319dec900cSHariprasad S pr_err(MOD "ARP failure during accept - tid %u -dropping connection\n", 5329dec900cSHariprasad S ep->hwtid); 5339dec900cSHariprasad S 5349dec900cSHariprasad S __state_set(&ep->com, DEAD); 5358d1f1a6bSHariprasad S queue_arp_failure_cpl(ep, skb, FAKE_CPL_PASS_PUT_EP_SAFE); 5369dec900cSHariprasad S } 5379dec900cSHariprasad S 538cfdda9d7SSteve Wise /* 539cfdda9d7SSteve Wise * Handle an ARP failure for an active open. 540cfdda9d7SSteve Wise */ 541cfdda9d7SSteve Wise static void act_open_req_arp_failure(void *handle, struct sk_buff *skb) 542cfdda9d7SSteve Wise { 5435dab6d3aSHariprasad S struct c4iw_ep *ep = handle; 5445dab6d3aSHariprasad S 545e3d132d1SMasanari Iida printk(KERN_ERR MOD "ARP failure during connect\n"); 5465dab6d3aSHariprasad S connect_reply_upcall(ep, -EHOSTUNREACH); 5479dec900cSHariprasad S __state_set(&ep->com, DEAD); 54884cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 54984cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 550170003c8SSteve Wise (struct sockaddr_in6 *)&ep->com.local_addr; 55184cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 55284cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 55384cc6ac6SHariprasad S } 5545dab6d3aSHariprasad S remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid); 5555dab6d3aSHariprasad S cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid); 5568d1f1a6bSHariprasad S queue_arp_failure_cpl(ep, skb, FAKE_CPL_PUT_EP_SAFE); 557cfdda9d7SSteve Wise } 558cfdda9d7SSteve Wise 559cfdda9d7SSteve Wise /* 560cfdda9d7SSteve Wise * Handle an ARP failure for a CPL_ABORT_REQ. Change it into a no RST variant 561cfdda9d7SSteve Wise * and send it along. 562cfdda9d7SSteve Wise */ 563cfdda9d7SSteve Wise static void abort_arp_failure(void *handle, struct sk_buff *skb) 564cfdda9d7SSteve Wise { 565761e19a5SHariprasad S int ret; 566761e19a5SHariprasad S struct c4iw_ep *ep = handle; 567761e19a5SHariprasad S struct c4iw_rdev *rdev = &ep->com.dev->rdev; 568cfdda9d7SSteve Wise struct cpl_abort_req *req = cplhdr(skb); 569cfdda9d7SSteve Wise 570cfdda9d7SSteve Wise PDBG("%s rdev %p\n", __func__, rdev); 571cfdda9d7SSteve Wise req->cmd = CPL_ABORT_NO_RST; 572761e19a5SHariprasad S ret = c4iw_ofld_send(rdev, skb); 573761e19a5SHariprasad S if (ret) { 574761e19a5SHariprasad S __state_set(&ep->com, DEAD); 575761e19a5SHariprasad S queue_arp_failure_cpl(ep, skb, FAKE_CPL_PUT_EP_SAFE); 576761e19a5SHariprasad S } 577cfdda9d7SSteve Wise } 578cfdda9d7SSteve Wise 5794a740838SHariprasad S static int send_flowc(struct c4iw_ep *ep) 580cfdda9d7SSteve Wise { 581cfdda9d7SSteve Wise struct fw_flowc_wr *flowc; 5824a740838SHariprasad S struct sk_buff *skb = skb_dequeue(&ep->com.ep_skb_list); 583cfdda9d7SSteve Wise int i; 584ac8e4c69SHariprasad S u16 vlan = ep->l2t->vlan; 585ac8e4c69SHariprasad S int nparams; 586ac8e4c69SHariprasad S 5874a740838SHariprasad S if (WARN_ON(!skb)) 5884a740838SHariprasad S return -ENOMEM; 5894a740838SHariprasad S 590ac8e4c69SHariprasad S if (vlan == CPL_L2T_VLAN_NONE) 591ac8e4c69SHariprasad S nparams = 8; 592ac8e4c69SHariprasad S else 593ac8e4c69SHariprasad S nparams = 9; 594cfdda9d7SSteve Wise 5954a740838SHariprasad S flowc = (struct fw_flowc_wr *)__skb_put(skb, FLOWC_LEN); 596cfdda9d7SSteve Wise 597e2ac9628SHariprasad Shenai flowc->op_to_nparams = cpu_to_be32(FW_WR_OP_V(FW_FLOWC_WR) | 598ac8e4c69SHariprasad S FW_FLOWC_WR_NPARAMS_V(nparams)); 5994a740838SHariprasad S flowc->flowid_len16 = cpu_to_be32(FW_WR_LEN16_V(DIV_ROUND_UP(FLOWC_LEN, 600e2ac9628SHariprasad Shenai 16)) | FW_WR_FLOWID_V(ep->hwtid)); 601cfdda9d7SSteve Wise 602cfdda9d7SSteve Wise flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN; 6035167865aSHariprasad Shenai flowc->mnemval[0].val = cpu_to_be32(FW_PFVF_CMD_PFN_V 60435b1de55SHariprasad Shenai (ep->com.dev->rdev.lldi.pf)); 605cfdda9d7SSteve Wise flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH; 606cfdda9d7SSteve Wise flowc->mnemval[1].val = cpu_to_be32(ep->tx_chan); 607cfdda9d7SSteve Wise flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT; 608cfdda9d7SSteve Wise flowc->mnemval[2].val = cpu_to_be32(ep->tx_chan); 609cfdda9d7SSteve Wise flowc->mnemval[3].mnemonic = FW_FLOWC_MNEM_IQID; 610cfdda9d7SSteve Wise flowc->mnemval[3].val = cpu_to_be32(ep->rss_qid); 611cfdda9d7SSteve Wise flowc->mnemval[4].mnemonic = FW_FLOWC_MNEM_SNDNXT; 612cfdda9d7SSteve Wise flowc->mnemval[4].val = cpu_to_be32(ep->snd_seq); 613cfdda9d7SSteve Wise flowc->mnemval[5].mnemonic = FW_FLOWC_MNEM_RCVNXT; 614cfdda9d7SSteve Wise flowc->mnemval[5].val = cpu_to_be32(ep->rcv_seq); 615cfdda9d7SSteve Wise flowc->mnemval[6].mnemonic = FW_FLOWC_MNEM_SNDBUF; 616b408ff28SHariprasad Shenai flowc->mnemval[6].val = cpu_to_be32(ep->snd_win); 617cfdda9d7SSteve Wise flowc->mnemval[7].mnemonic = FW_FLOWC_MNEM_MSS; 618cfdda9d7SSteve Wise flowc->mnemval[7].val = cpu_to_be32(ep->emss); 619ac8e4c69SHariprasad S if (nparams == 9) { 620ac8e4c69SHariprasad S u16 pri; 621ac8e4c69SHariprasad S 622ac8e4c69SHariprasad S pri = (vlan & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; 623ac8e4c69SHariprasad S flowc->mnemval[8].mnemonic = FW_FLOWC_MNEM_SCHEDCLASS; 624ac8e4c69SHariprasad S flowc->mnemval[8].val = cpu_to_be32(pri); 625ac8e4c69SHariprasad S } else { 626cfdda9d7SSteve Wise /* Pad WR to 16 byte boundary */ 627cfdda9d7SSteve Wise flowc->mnemval[8].mnemonic = 0; 628cfdda9d7SSteve Wise flowc->mnemval[8].val = 0; 629ac8e4c69SHariprasad S } 630cfdda9d7SSteve Wise for (i = 0; i < 9; i++) { 631cfdda9d7SSteve Wise flowc->mnemval[i].r4[0] = 0; 632cfdda9d7SSteve Wise flowc->mnemval[i].r4[1] = 0; 633cfdda9d7SSteve Wise flowc->mnemval[i].r4[2] = 0; 634cfdda9d7SSteve Wise } 635cfdda9d7SSteve Wise 636cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 637fef4422dSHariprasad S return c4iw_ofld_send(&ep->com.dev->rdev, skb); 638cfdda9d7SSteve Wise } 639cfdda9d7SSteve Wise 6404a740838SHariprasad S static int send_halfclose(struct c4iw_ep *ep) 641cfdda9d7SSteve Wise { 642cfdda9d7SSteve Wise struct cpl_close_con_req *req; 6434a740838SHariprasad S struct sk_buff *skb = skb_dequeue(&ep->com.ep_skb_list); 644cfdda9d7SSteve Wise int wrlen = roundup(sizeof *req, 16); 645cfdda9d7SSteve Wise 646cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 6474a740838SHariprasad S if (WARN_ON(!skb)) 648cfdda9d7SSteve Wise return -ENOMEM; 6494a740838SHariprasad S 650cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 651cfdda9d7SSteve Wise t4_set_arp_err_handler(skb, NULL, arp_failure_discard); 652cfdda9d7SSteve Wise req = (struct cpl_close_con_req *) skb_put(skb, wrlen); 653cfdda9d7SSteve Wise memset(req, 0, wrlen); 654cfdda9d7SSteve Wise INIT_TP_WR(req, ep->hwtid); 655cfdda9d7SSteve Wise OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, 656cfdda9d7SSteve Wise ep->hwtid)); 657cfdda9d7SSteve Wise return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 658cfdda9d7SSteve Wise } 659cfdda9d7SSteve Wise 6604a740838SHariprasad S static int send_abort(struct c4iw_ep *ep) 661cfdda9d7SSteve Wise { 662cfdda9d7SSteve Wise struct cpl_abort_req *req; 663cfdda9d7SSteve Wise int wrlen = roundup(sizeof *req, 16); 6644a740838SHariprasad S struct sk_buff *req_skb = skb_dequeue(&ep->com.ep_skb_list); 665cfdda9d7SSteve Wise 666cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 6674a740838SHariprasad S if (WARN_ON(!req_skb)) 668cfdda9d7SSteve Wise return -ENOMEM; 6694a740838SHariprasad S 6704a740838SHariprasad S set_wr_txq(req_skb, CPL_PRIORITY_DATA, ep->txq_idx); 6714a740838SHariprasad S t4_set_arp_err_handler(req_skb, ep, abort_arp_failure); 6724a740838SHariprasad S req = (struct cpl_abort_req *)skb_put(req_skb, wrlen); 673cfdda9d7SSteve Wise memset(req, 0, wrlen); 674cfdda9d7SSteve Wise INIT_TP_WR(req, ep->hwtid); 675cfdda9d7SSteve Wise OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_REQ, ep->hwtid)); 676cfdda9d7SSteve Wise req->cmd = CPL_ABORT_SEND_RST; 6774a740838SHariprasad S return c4iw_l2t_send(&ep->com.dev->rdev, req_skb, ep->l2t); 678cfdda9d7SSteve Wise } 679cfdda9d7SSteve Wise 680cfdda9d7SSteve Wise static int send_connect(struct c4iw_ep *ep) 681cfdda9d7SSteve Wise { 682963cab50SHariprasad S struct cpl_act_open_req *req = NULL; 683963cab50SHariprasad S struct cpl_t5_act_open_req *t5req = NULL; 684963cab50SHariprasad S struct cpl_t6_act_open_req *t6req = NULL; 685963cab50SHariprasad S struct cpl_act_open_req6 *req6 = NULL; 686963cab50SHariprasad S struct cpl_t5_act_open_req6 *t5req6 = NULL; 687963cab50SHariprasad S struct cpl_t6_act_open_req6 *t6req6 = NULL; 688cfdda9d7SSteve Wise struct sk_buff *skb; 689cfdda9d7SSteve Wise u64 opt0; 690cfdda9d7SSteve Wise u32 opt2; 691cfdda9d7SSteve Wise unsigned int mtu_idx; 692cfdda9d7SSteve Wise int wscale; 693963cab50SHariprasad S int win, sizev4, sizev6, wrlen; 6949eccfe10SSteve Wise struct sockaddr_in *la = (struct sockaddr_in *) 695170003c8SSteve Wise &ep->com.local_addr; 6969eccfe10SSteve Wise struct sockaddr_in *ra = (struct sockaddr_in *) 697170003c8SSteve Wise &ep->com.remote_addr; 6989eccfe10SSteve Wise struct sockaddr_in6 *la6 = (struct sockaddr_in6 *) 699170003c8SSteve Wise &ep->com.local_addr; 7009eccfe10SSteve Wise struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *) 701170003c8SSteve Wise &ep->com.remote_addr; 70284cc6ac6SHariprasad S int ret; 703963cab50SHariprasad S enum chip_type adapter_type = ep->com.dev->rdev.lldi.adapter_type; 704963cab50SHariprasad S u32 isn = (prandom_u32() & ~7UL) - 1; 705963cab50SHariprasad S 706963cab50SHariprasad S switch (CHELSIO_CHIP_VERSION(adapter_type)) { 707963cab50SHariprasad S case CHELSIO_T4: 708963cab50SHariprasad S sizev4 = sizeof(struct cpl_act_open_req); 709963cab50SHariprasad S sizev6 = sizeof(struct cpl_act_open_req6); 710963cab50SHariprasad S break; 711963cab50SHariprasad S case CHELSIO_T5: 712963cab50SHariprasad S sizev4 = sizeof(struct cpl_t5_act_open_req); 713963cab50SHariprasad S sizev6 = sizeof(struct cpl_t5_act_open_req6); 714963cab50SHariprasad S break; 715963cab50SHariprasad S case CHELSIO_T6: 716963cab50SHariprasad S sizev4 = sizeof(struct cpl_t6_act_open_req); 717963cab50SHariprasad S sizev6 = sizeof(struct cpl_t6_act_open_req6); 718963cab50SHariprasad S break; 719963cab50SHariprasad S default: 720963cab50SHariprasad S pr_err("T%d Chip is not supported\n", 721963cab50SHariprasad S CHELSIO_CHIP_VERSION(adapter_type)); 722963cab50SHariprasad S return -EINVAL; 723963cab50SHariprasad S } 724830662f6SVipul Pandya 725830662f6SVipul Pandya wrlen = (ep->com.remote_addr.ss_family == AF_INET) ? 726830662f6SVipul Pandya roundup(sizev4, 16) : 727830662f6SVipul Pandya roundup(sizev6, 16); 728cfdda9d7SSteve Wise 729cfdda9d7SSteve Wise PDBG("%s ep %p atid %u\n", __func__, ep, ep->atid); 730cfdda9d7SSteve Wise 731cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 732cfdda9d7SSteve Wise if (!skb) { 733cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - failed to alloc skb.\n", 734cfdda9d7SSteve Wise __func__); 735cfdda9d7SSteve Wise return -ENOMEM; 736cfdda9d7SSteve Wise } 737d4f1a5c6SSteve Wise set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->ctrlq_idx); 738cfdda9d7SSteve Wise 73944c6d069SVarun Prakash cxgb_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, 74004524a47SHariprasad S enable_tcp_timestamps, 74144c6d069SVarun Prakash (ep->com.remote_addr.ss_family == AF_INET) ? 0 : 1); 742cfdda9d7SSteve Wise wscale = compute_wscale(rcv_win); 743b408ff28SHariprasad Shenai 744b408ff28SHariprasad Shenai /* 745b408ff28SHariprasad Shenai * Specify the largest window that will fit in opt0. The 746b408ff28SHariprasad Shenai * remainder will be specified in the rx_data_ack. 747b408ff28SHariprasad Shenai */ 748b408ff28SHariprasad Shenai win = ep->rcv_win >> 10; 749d7990b0cSAnish Bhatt if (win > RCV_BUFSIZ_M) 750d7990b0cSAnish Bhatt win = RCV_BUFSIZ_M; 751b408ff28SHariprasad Shenai 7526c53e938SHariprasad Shenai opt0 = (nocong ? NO_CONG_F : 0) | 753d7990b0cSAnish Bhatt KEEP_ALIVE_F | 7546c53e938SHariprasad Shenai DELACK_F | 755d7990b0cSAnish Bhatt WND_SCALE_V(wscale) | 756d7990b0cSAnish Bhatt MSS_IDX_V(mtu_idx) | 757d7990b0cSAnish Bhatt L2T_IDX_V(ep->l2t->idx) | 758d7990b0cSAnish Bhatt TX_CHAN_V(ep->tx_chan) | 759d7990b0cSAnish Bhatt SMAC_SEL_V(ep->smac_idx) | 760ac8e4c69SHariprasad S DSCP_V(ep->tos >> 2) | 761d7990b0cSAnish Bhatt ULP_MODE_V(ULP_MODE_TCPDDP) | 762d7990b0cSAnish Bhatt RCV_BUFSIZ_V(win); 763d7990b0cSAnish Bhatt opt2 = RX_CHANNEL_V(0) | 7646c53e938SHariprasad Shenai CCTRL_ECN_V(enable_ecn) | 765d7990b0cSAnish Bhatt RSS_QUEUE_VALID_F | RSS_QUEUE_V(ep->rss_qid); 766cfdda9d7SSteve Wise if (enable_tcp_timestamps) 7676c53e938SHariprasad Shenai opt2 |= TSTAMPS_EN_F; 768cfdda9d7SSteve Wise if (enable_tcp_sack) 7696c53e938SHariprasad Shenai opt2 |= SACK_EN_F; 770cfdda9d7SSteve Wise if (wscale && enable_tcp_window_scaling) 771d7990b0cSAnish Bhatt opt2 |= WND_SCALE_EN_F; 772963cab50SHariprasad S if (CHELSIO_CHIP_VERSION(adapter_type) > CHELSIO_T4) { 773963cab50SHariprasad S if (peer2peer) 774963cab50SHariprasad S isn += 4; 775963cab50SHariprasad S 776d7990b0cSAnish Bhatt opt2 |= T5_OPT_2_VALID_F; 777cf7fe64aSHariprasad Shenai opt2 |= CONG_CNTRL_V(CONG_ALG_TAHOE); 7780b741047SHariprasad S opt2 |= T5_ISS_F; 77992e5011aSSteve Wise } 78084cc6ac6SHariprasad S 78184cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) 78284cc6ac6SHariprasad S cxgb4_clip_get(ep->com.dev->rdev.lldi.ports[0], 78384cc6ac6SHariprasad S (const u32 *)&la6->sin6_addr.s6_addr, 1); 78484cc6ac6SHariprasad S 7855dab6d3aSHariprasad S t4_set_arp_err_handler(skb, ep, act_open_req_arp_failure); 786cfdda9d7SSteve Wise 787830662f6SVipul Pandya if (ep->com.remote_addr.ss_family == AF_INET) { 788963cab50SHariprasad S switch (CHELSIO_CHIP_VERSION(adapter_type)) { 789963cab50SHariprasad S case CHELSIO_T4: 790cfdda9d7SSteve Wise req = (struct cpl_act_open_req *)skb_put(skb, wrlen); 791cfdda9d7SSteve Wise INIT_TP_WR(req, 0); 792963cab50SHariprasad S break; 793963cab50SHariprasad S case CHELSIO_T5: 794963cab50SHariprasad S t5req = (struct cpl_t5_act_open_req *)skb_put(skb, 795963cab50SHariprasad S wrlen); 796963cab50SHariprasad S INIT_TP_WR(t5req, 0); 797963cab50SHariprasad S req = (struct cpl_act_open_req *)t5req; 798963cab50SHariprasad S break; 799963cab50SHariprasad S case CHELSIO_T6: 800963cab50SHariprasad S t6req = (struct cpl_t6_act_open_req *)skb_put(skb, 801963cab50SHariprasad S wrlen); 802963cab50SHariprasad S INIT_TP_WR(t6req, 0); 803963cab50SHariprasad S req = (struct cpl_act_open_req *)t6req; 804963cab50SHariprasad S t5req = (struct cpl_t5_act_open_req *)t6req; 805963cab50SHariprasad S break; 806963cab50SHariprasad S default: 807963cab50SHariprasad S pr_err("T%d Chip is not supported\n", 808963cab50SHariprasad S CHELSIO_CHIP_VERSION(adapter_type)); 809963cab50SHariprasad S ret = -EINVAL; 810963cab50SHariprasad S goto clip_release; 811963cab50SHariprasad S } 812963cab50SHariprasad S 813963cab50SHariprasad S OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, 814f079af7aSVipul Pandya ((ep->rss_qid<<14) | ep->atid))); 815830662f6SVipul Pandya req->local_port = la->sin_port; 816830662f6SVipul Pandya req->peer_port = ra->sin_port; 817830662f6SVipul Pandya req->local_ip = la->sin_addr.s_addr; 818830662f6SVipul Pandya req->peer_ip = ra->sin_addr.s_addr; 819cfdda9d7SSteve Wise req->opt0 = cpu_to_be64(opt0); 820963cab50SHariprasad S 821963cab50SHariprasad S if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) { 82241b4f86cSKumar Sanghvi req->params = cpu_to_be32(cxgb4_select_ntuple( 82341b4f86cSKumar Sanghvi ep->com.dev->rdev.lldi.ports[0], 82441b4f86cSKumar Sanghvi ep->l2t)); 825cfdda9d7SSteve Wise req->opt2 = cpu_to_be32(opt2); 826f079af7aSVipul Pandya } else { 827963cab50SHariprasad S t5req->params = cpu_to_be64(FILTER_TUPLE_V( 828963cab50SHariprasad S cxgb4_select_ntuple( 829963cab50SHariprasad S ep->com.dev->rdev.lldi.ports[0], 830963cab50SHariprasad S ep->l2t))); 831963cab50SHariprasad S t5req->rsvd = cpu_to_be32(isn); 832963cab50SHariprasad S PDBG("%s snd_isn %u\n", __func__, t5req->rsvd); 833963cab50SHariprasad S t5req->opt2 = cpu_to_be32(opt2); 834963cab50SHariprasad S } 835963cab50SHariprasad S } else { 836963cab50SHariprasad S switch (CHELSIO_CHIP_VERSION(adapter_type)) { 837963cab50SHariprasad S case CHELSIO_T4: 838830662f6SVipul Pandya req6 = (struct cpl_act_open_req6 *)skb_put(skb, wrlen); 839830662f6SVipul Pandya INIT_TP_WR(req6, 0); 840963cab50SHariprasad S break; 841963cab50SHariprasad S case CHELSIO_T5: 842963cab50SHariprasad S t5req6 = (struct cpl_t5_act_open_req6 *)skb_put(skb, 843963cab50SHariprasad S wrlen); 844963cab50SHariprasad S INIT_TP_WR(t5req6, 0); 845963cab50SHariprasad S req6 = (struct cpl_act_open_req6 *)t5req6; 846963cab50SHariprasad S break; 847963cab50SHariprasad S case CHELSIO_T6: 848963cab50SHariprasad S t6req6 = (struct cpl_t6_act_open_req6 *)skb_put(skb, 849963cab50SHariprasad S wrlen); 850963cab50SHariprasad S INIT_TP_WR(t6req6, 0); 851963cab50SHariprasad S req6 = (struct cpl_act_open_req6 *)t6req6; 852963cab50SHariprasad S t5req6 = (struct cpl_t5_act_open_req6 *)t6req6; 853963cab50SHariprasad S break; 854963cab50SHariprasad S default: 855963cab50SHariprasad S pr_err("T%d Chip is not supported\n", 856963cab50SHariprasad S CHELSIO_CHIP_VERSION(adapter_type)); 857963cab50SHariprasad S ret = -EINVAL; 858963cab50SHariprasad S goto clip_release; 859963cab50SHariprasad S } 860963cab50SHariprasad S 861963cab50SHariprasad S OPCODE_TID(req6) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ6, 862830662f6SVipul Pandya ((ep->rss_qid<<14)|ep->atid))); 863830662f6SVipul Pandya req6->local_port = la6->sin6_port; 864830662f6SVipul Pandya req6->peer_port = ra6->sin6_port; 865963cab50SHariprasad S req6->local_ip_hi = *((__be64 *)(la6->sin6_addr.s6_addr)); 866963cab50SHariprasad S req6->local_ip_lo = *((__be64 *)(la6->sin6_addr.s6_addr + 8)); 867963cab50SHariprasad S req6->peer_ip_hi = *((__be64 *)(ra6->sin6_addr.s6_addr)); 868963cab50SHariprasad S req6->peer_ip_lo = *((__be64 *)(ra6->sin6_addr.s6_addr + 8)); 869830662f6SVipul Pandya req6->opt0 = cpu_to_be64(opt0); 870963cab50SHariprasad S 871963cab50SHariprasad S if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) { 87241b4f86cSKumar Sanghvi req6->params = cpu_to_be32(cxgb4_select_ntuple( 87341b4f86cSKumar Sanghvi ep->com.dev->rdev.lldi.ports[0], 874830662f6SVipul Pandya ep->l2t)); 875830662f6SVipul Pandya req6->opt2 = cpu_to_be32(opt2); 876830662f6SVipul Pandya } else { 877963cab50SHariprasad S t5req6->params = cpu_to_be64(FILTER_TUPLE_V( 87841b4f86cSKumar Sanghvi cxgb4_select_ntuple( 87941b4f86cSKumar Sanghvi ep->com.dev->rdev.lldi.ports[0], 88041b4f86cSKumar Sanghvi ep->l2t))); 881963cab50SHariprasad S t5req6->rsvd = cpu_to_be32(isn); 882963cab50SHariprasad S PDBG("%s snd_isn %u\n", __func__, t5req6->rsvd); 883963cab50SHariprasad S t5req6->opt2 = cpu_to_be32(opt2); 884830662f6SVipul Pandya } 885f079af7aSVipul Pandya } 886f079af7aSVipul Pandya 887793dad94SVipul Pandya set_bit(ACT_OPEN_REQ, &ep->com.history); 88884cc6ac6SHariprasad S ret = c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 889963cab50SHariprasad S clip_release: 89084cc6ac6SHariprasad S if (ret && ep->com.remote_addr.ss_family == AF_INET6) 89184cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 89284cc6ac6SHariprasad S (const u32 *)&la6->sin6_addr.s6_addr, 1); 89384cc6ac6SHariprasad S return ret; 894cfdda9d7SSteve Wise } 895cfdda9d7SSteve Wise 896caa6c9f2SHariprasad S static int send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb, 897d2fe99e8SKumar Sanghvi u8 mpa_rev_to_use) 898cfdda9d7SSteve Wise { 899caa6c9f2SHariprasad S int mpalen, wrlen, ret; 900cfdda9d7SSteve Wise struct fw_ofld_tx_data_wr *req; 901cfdda9d7SSteve Wise struct mpa_message *mpa; 902d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params mpa_v2_params; 903cfdda9d7SSteve Wise 904cfdda9d7SSteve Wise PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen); 905cfdda9d7SSteve Wise 906cfdda9d7SSteve Wise BUG_ON(skb_cloned(skb)); 907cfdda9d7SSteve Wise 908cfdda9d7SSteve Wise mpalen = sizeof(*mpa) + ep->plen; 909d2fe99e8SKumar Sanghvi if (mpa_rev_to_use == 2) 910d2fe99e8SKumar Sanghvi mpalen += sizeof(struct mpa_v2_conn_params); 911cfdda9d7SSteve Wise wrlen = roundup(mpalen + sizeof *req, 16); 912cfdda9d7SSteve Wise skb = get_skb(skb, wrlen, GFP_KERNEL); 913cfdda9d7SSteve Wise if (!skb) { 914cfdda9d7SSteve Wise connect_reply_upcall(ep, -ENOMEM); 915caa6c9f2SHariprasad S return -ENOMEM; 916cfdda9d7SSteve Wise } 917cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 918cfdda9d7SSteve Wise 919cfdda9d7SSteve Wise req = (struct fw_ofld_tx_data_wr *)skb_put(skb, wrlen); 920cfdda9d7SSteve Wise memset(req, 0, wrlen); 921cfdda9d7SSteve Wise req->op_to_immdlen = cpu_to_be32( 922e2ac9628SHariprasad Shenai FW_WR_OP_V(FW_OFLD_TX_DATA_WR) | 923e2ac9628SHariprasad Shenai FW_WR_COMPL_F | 924e2ac9628SHariprasad Shenai FW_WR_IMMDLEN_V(mpalen)); 925cfdda9d7SSteve Wise req->flowid_len16 = cpu_to_be32( 926e2ac9628SHariprasad Shenai FW_WR_FLOWID_V(ep->hwtid) | 927e2ac9628SHariprasad Shenai FW_WR_LEN16_V(wrlen >> 4)); 928cfdda9d7SSteve Wise req->plen = cpu_to_be32(mpalen); 929cfdda9d7SSteve Wise req->tunnel_to_proxy = cpu_to_be32( 930e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_FLUSH_F | 931e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_SHOVE_F); 932cfdda9d7SSteve Wise 933cfdda9d7SSteve Wise mpa = (struct mpa_message *)(req + 1); 934cfdda9d7SSteve Wise memcpy(mpa->key, MPA_KEY_REQ, sizeof(mpa->key)); 9353d4e7994SHariprasad S 9363d4e7994SHariprasad S mpa->flags = 0; 9373d4e7994SHariprasad S if (crc_enabled) 9383d4e7994SHariprasad S mpa->flags |= MPA_CRC; 9393d4e7994SHariprasad S if (markers_enabled) { 9403d4e7994SHariprasad S mpa->flags |= MPA_MARKERS; 9413d4e7994SHariprasad S ep->mpa_attr.recv_marker_enabled = 1; 9423d4e7994SHariprasad S } else { 9433d4e7994SHariprasad S ep->mpa_attr.recv_marker_enabled = 0; 9443d4e7994SHariprasad S } 9453d4e7994SHariprasad S if (mpa_rev_to_use == 2) 9463d4e7994SHariprasad S mpa->flags |= MPA_ENHANCED_RDMA_CONN; 9473d4e7994SHariprasad S 948cfdda9d7SSteve Wise mpa->private_data_size = htons(ep->plen); 949d2fe99e8SKumar Sanghvi mpa->revision = mpa_rev_to_use; 95001b225e1SKumar Sanghvi if (mpa_rev_to_use == 1) { 951d2fe99e8SKumar Sanghvi ep->tried_with_mpa_v1 = 1; 95201b225e1SKumar Sanghvi ep->retry_with_mpa_v1 = 0; 95301b225e1SKumar Sanghvi } 954d2fe99e8SKumar Sanghvi 955d2fe99e8SKumar Sanghvi if (mpa_rev_to_use == 2) { 956f747c34aSRoland Dreier mpa->private_data_size = htons(ntohs(mpa->private_data_size) + 957f747c34aSRoland Dreier sizeof (struct mpa_v2_conn_params)); 9584c2c5763SHariprasad Shenai PDBG("%s initiator ird %u ord %u\n", __func__, ep->ird, 9594c2c5763SHariprasad Shenai ep->ord); 960d2fe99e8SKumar Sanghvi mpa_v2_params.ird = htons((u16)ep->ird); 961d2fe99e8SKumar Sanghvi mpa_v2_params.ord = htons((u16)ep->ord); 962d2fe99e8SKumar Sanghvi 963d2fe99e8SKumar Sanghvi if (peer2peer) { 964d2fe99e8SKumar Sanghvi mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL); 965d2fe99e8SKumar Sanghvi if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE) 966d2fe99e8SKumar Sanghvi mpa_v2_params.ord |= 967d2fe99e8SKumar Sanghvi htons(MPA_V2_RDMA_WRITE_RTR); 968d2fe99e8SKumar Sanghvi else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) 969d2fe99e8SKumar Sanghvi mpa_v2_params.ord |= 970d2fe99e8SKumar Sanghvi htons(MPA_V2_RDMA_READ_RTR); 971d2fe99e8SKumar Sanghvi } 972d2fe99e8SKumar Sanghvi memcpy(mpa->private_data, &mpa_v2_params, 973d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params)); 974cfdda9d7SSteve Wise 975cfdda9d7SSteve Wise if (ep->plen) 976d2fe99e8SKumar Sanghvi memcpy(mpa->private_data + 977d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params), 978d2fe99e8SKumar Sanghvi ep->mpa_pkt + sizeof(*mpa), ep->plen); 979d2fe99e8SKumar Sanghvi } else 980d2fe99e8SKumar Sanghvi if (ep->plen) 981d2fe99e8SKumar Sanghvi memcpy(mpa->private_data, 982d2fe99e8SKumar Sanghvi ep->mpa_pkt + sizeof(*mpa), ep->plen); 983cfdda9d7SSteve Wise 984cfdda9d7SSteve Wise /* 985cfdda9d7SSteve Wise * Reference the mpa skb. This ensures the data area 986cfdda9d7SSteve Wise * will remain in memory until the hw acks the tx. 987cfdda9d7SSteve Wise * Function fw4_ack() will deref it. 988cfdda9d7SSteve Wise */ 989cfdda9d7SSteve Wise skb_get(skb); 990cfdda9d7SSteve Wise t4_set_arp_err_handler(skb, NULL, arp_failure_discard); 991cfdda9d7SSteve Wise BUG_ON(ep->mpa_skb); 992cfdda9d7SSteve Wise ep->mpa_skb = skb; 993caa6c9f2SHariprasad S ret = c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 994caa6c9f2SHariprasad S if (ret) 995caa6c9f2SHariprasad S return ret; 996cfdda9d7SSteve Wise start_ep_timer(ep); 997a7db89ebSSteve Wise __state_set(&ep->com, MPA_REQ_SENT); 998cfdda9d7SSteve Wise ep->mpa_attr.initiator = 1; 9999c88aa00SSteve Wise ep->snd_seq += mpalen; 1000caa6c9f2SHariprasad S return ret; 1001cfdda9d7SSteve Wise } 1002cfdda9d7SSteve Wise 1003cfdda9d7SSteve Wise static int send_mpa_reject(struct c4iw_ep *ep, const void *pdata, u8 plen) 1004cfdda9d7SSteve Wise { 1005cfdda9d7SSteve Wise int mpalen, wrlen; 1006cfdda9d7SSteve Wise struct fw_ofld_tx_data_wr *req; 1007cfdda9d7SSteve Wise struct mpa_message *mpa; 1008cfdda9d7SSteve Wise struct sk_buff *skb; 1009d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params mpa_v2_params; 1010cfdda9d7SSteve Wise 1011cfdda9d7SSteve Wise PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen); 1012cfdda9d7SSteve Wise 1013cfdda9d7SSteve Wise mpalen = sizeof(*mpa) + plen; 1014d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) 1015d2fe99e8SKumar Sanghvi mpalen += sizeof(struct mpa_v2_conn_params); 1016cfdda9d7SSteve Wise wrlen = roundup(mpalen + sizeof *req, 16); 1017cfdda9d7SSteve Wise 1018cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 1019cfdda9d7SSteve Wise if (!skb) { 1020cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __func__); 1021cfdda9d7SSteve Wise return -ENOMEM; 1022cfdda9d7SSteve Wise } 1023cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 1024cfdda9d7SSteve Wise 1025cfdda9d7SSteve Wise req = (struct fw_ofld_tx_data_wr *)skb_put(skb, wrlen); 1026cfdda9d7SSteve Wise memset(req, 0, wrlen); 1027cfdda9d7SSteve Wise req->op_to_immdlen = cpu_to_be32( 1028e2ac9628SHariprasad Shenai FW_WR_OP_V(FW_OFLD_TX_DATA_WR) | 1029e2ac9628SHariprasad Shenai FW_WR_COMPL_F | 1030e2ac9628SHariprasad Shenai FW_WR_IMMDLEN_V(mpalen)); 1031cfdda9d7SSteve Wise req->flowid_len16 = cpu_to_be32( 1032e2ac9628SHariprasad Shenai FW_WR_FLOWID_V(ep->hwtid) | 1033e2ac9628SHariprasad Shenai FW_WR_LEN16_V(wrlen >> 4)); 1034cfdda9d7SSteve Wise req->plen = cpu_to_be32(mpalen); 1035cfdda9d7SSteve Wise req->tunnel_to_proxy = cpu_to_be32( 1036e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_FLUSH_F | 1037e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_SHOVE_F); 1038cfdda9d7SSteve Wise 1039cfdda9d7SSteve Wise mpa = (struct mpa_message *)(req + 1); 1040cfdda9d7SSteve Wise memset(mpa, 0, sizeof(*mpa)); 1041cfdda9d7SSteve Wise memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key)); 1042cfdda9d7SSteve Wise mpa->flags = MPA_REJECT; 1043fe7e0a4dSVipul Pandya mpa->revision = ep->mpa_attr.version; 1044cfdda9d7SSteve Wise mpa->private_data_size = htons(plen); 1045d2fe99e8SKumar Sanghvi 1046d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 1047d2fe99e8SKumar Sanghvi mpa->flags |= MPA_ENHANCED_RDMA_CONN; 1048f747c34aSRoland Dreier mpa->private_data_size = htons(ntohs(mpa->private_data_size) + 1049f747c34aSRoland Dreier sizeof (struct mpa_v2_conn_params)); 1050d2fe99e8SKumar Sanghvi mpa_v2_params.ird = htons(((u16)ep->ird) | 1051d2fe99e8SKumar Sanghvi (peer2peer ? MPA_V2_PEER2PEER_MODEL : 1052d2fe99e8SKumar Sanghvi 0)); 1053d2fe99e8SKumar Sanghvi mpa_v2_params.ord = htons(((u16)ep->ord) | (peer2peer ? 1054d2fe99e8SKumar Sanghvi (p2p_type == 1055d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_RDMA_WRITE ? 1056d2fe99e8SKumar Sanghvi MPA_V2_RDMA_WRITE_RTR : p2p_type == 1057d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_READ_REQ ? 1058d2fe99e8SKumar Sanghvi MPA_V2_RDMA_READ_RTR : 0) : 0)); 1059d2fe99e8SKumar Sanghvi memcpy(mpa->private_data, &mpa_v2_params, 1060d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params)); 1061d2fe99e8SKumar Sanghvi 1062d2fe99e8SKumar Sanghvi if (ep->plen) 1063d2fe99e8SKumar Sanghvi memcpy(mpa->private_data + 1064d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params), pdata, plen); 1065d2fe99e8SKumar Sanghvi } else 1066cfdda9d7SSteve Wise if (plen) 1067cfdda9d7SSteve Wise memcpy(mpa->private_data, pdata, plen); 1068cfdda9d7SSteve Wise 1069cfdda9d7SSteve Wise /* 1070cfdda9d7SSteve Wise * Reference the mpa skb again. This ensures the data area 1071cfdda9d7SSteve Wise * will remain in memory until the hw acks the tx. 1072cfdda9d7SSteve Wise * Function fw4_ack() will deref it. 1073cfdda9d7SSteve Wise */ 1074cfdda9d7SSteve Wise skb_get(skb); 1075cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 107664bec74aSHariprasad S t4_set_arp_err_handler(skb, NULL, mpa_start_arp_failure); 1077cfdda9d7SSteve Wise BUG_ON(ep->mpa_skb); 1078cfdda9d7SSteve Wise ep->mpa_skb = skb; 10799c88aa00SSteve Wise ep->snd_seq += mpalen; 1080cfdda9d7SSteve Wise return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 1081cfdda9d7SSteve Wise } 1082cfdda9d7SSteve Wise 1083cfdda9d7SSteve Wise static int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen) 1084cfdda9d7SSteve Wise { 1085cfdda9d7SSteve Wise int mpalen, wrlen; 1086cfdda9d7SSteve Wise struct fw_ofld_tx_data_wr *req; 1087cfdda9d7SSteve Wise struct mpa_message *mpa; 1088cfdda9d7SSteve Wise struct sk_buff *skb; 1089d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params mpa_v2_params; 1090cfdda9d7SSteve Wise 1091cfdda9d7SSteve Wise PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen); 1092cfdda9d7SSteve Wise 1093cfdda9d7SSteve Wise mpalen = sizeof(*mpa) + plen; 1094d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) 1095d2fe99e8SKumar Sanghvi mpalen += sizeof(struct mpa_v2_conn_params); 1096cfdda9d7SSteve Wise wrlen = roundup(mpalen + sizeof *req, 16); 1097cfdda9d7SSteve Wise 1098cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 1099cfdda9d7SSteve Wise if (!skb) { 1100cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __func__); 1101cfdda9d7SSteve Wise return -ENOMEM; 1102cfdda9d7SSteve Wise } 1103cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 1104cfdda9d7SSteve Wise 1105cfdda9d7SSteve Wise req = (struct fw_ofld_tx_data_wr *) skb_put(skb, wrlen); 1106cfdda9d7SSteve Wise memset(req, 0, wrlen); 1107cfdda9d7SSteve Wise req->op_to_immdlen = cpu_to_be32( 1108e2ac9628SHariprasad Shenai FW_WR_OP_V(FW_OFLD_TX_DATA_WR) | 1109e2ac9628SHariprasad Shenai FW_WR_COMPL_F | 1110e2ac9628SHariprasad Shenai FW_WR_IMMDLEN_V(mpalen)); 1111cfdda9d7SSteve Wise req->flowid_len16 = cpu_to_be32( 1112e2ac9628SHariprasad Shenai FW_WR_FLOWID_V(ep->hwtid) | 1113e2ac9628SHariprasad Shenai FW_WR_LEN16_V(wrlen >> 4)); 1114cfdda9d7SSteve Wise req->plen = cpu_to_be32(mpalen); 1115cfdda9d7SSteve Wise req->tunnel_to_proxy = cpu_to_be32( 1116e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_FLUSH_F | 1117e2ac9628SHariprasad Shenai FW_OFLD_TX_DATA_WR_SHOVE_F); 1118cfdda9d7SSteve Wise 1119cfdda9d7SSteve Wise mpa = (struct mpa_message *)(req + 1); 1120cfdda9d7SSteve Wise memset(mpa, 0, sizeof(*mpa)); 1121cfdda9d7SSteve Wise memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key)); 11223d4e7994SHariprasad S mpa->flags = 0; 11233d4e7994SHariprasad S if (ep->mpa_attr.crc_enabled) 11243d4e7994SHariprasad S mpa->flags |= MPA_CRC; 11253d4e7994SHariprasad S if (ep->mpa_attr.recv_marker_enabled) 11263d4e7994SHariprasad S mpa->flags |= MPA_MARKERS; 1127d2fe99e8SKumar Sanghvi mpa->revision = ep->mpa_attr.version; 1128cfdda9d7SSteve Wise mpa->private_data_size = htons(plen); 1129d2fe99e8SKumar Sanghvi 1130d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 1131d2fe99e8SKumar Sanghvi mpa->flags |= MPA_ENHANCED_RDMA_CONN; 1132f747c34aSRoland Dreier mpa->private_data_size = htons(ntohs(mpa->private_data_size) + 1133f747c34aSRoland Dreier sizeof (struct mpa_v2_conn_params)); 1134d2fe99e8SKumar Sanghvi mpa_v2_params.ird = htons((u16)ep->ird); 1135d2fe99e8SKumar Sanghvi mpa_v2_params.ord = htons((u16)ep->ord); 1136d2fe99e8SKumar Sanghvi if (peer2peer && (ep->mpa_attr.p2p_type != 1137d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_DISABLED)) { 1138d2fe99e8SKumar Sanghvi mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL); 1139d2fe99e8SKumar Sanghvi 1140d2fe99e8SKumar Sanghvi if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE) 1141d2fe99e8SKumar Sanghvi mpa_v2_params.ord |= 1142d2fe99e8SKumar Sanghvi htons(MPA_V2_RDMA_WRITE_RTR); 1143d2fe99e8SKumar Sanghvi else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) 1144d2fe99e8SKumar Sanghvi mpa_v2_params.ord |= 1145d2fe99e8SKumar Sanghvi htons(MPA_V2_RDMA_READ_RTR); 1146d2fe99e8SKumar Sanghvi } 1147d2fe99e8SKumar Sanghvi 1148d2fe99e8SKumar Sanghvi memcpy(mpa->private_data, &mpa_v2_params, 1149d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params)); 1150d2fe99e8SKumar Sanghvi 1151d2fe99e8SKumar Sanghvi if (ep->plen) 1152d2fe99e8SKumar Sanghvi memcpy(mpa->private_data + 1153d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params), pdata, plen); 1154d2fe99e8SKumar Sanghvi } else 1155cfdda9d7SSteve Wise if (plen) 1156cfdda9d7SSteve Wise memcpy(mpa->private_data, pdata, plen); 1157cfdda9d7SSteve Wise 1158cfdda9d7SSteve Wise /* 1159cfdda9d7SSteve Wise * Reference the mpa skb. This ensures the data area 1160cfdda9d7SSteve Wise * will remain in memory until the hw acks the tx. 1161cfdda9d7SSteve Wise * Function fw4_ack() will deref it. 1162cfdda9d7SSteve Wise */ 1163cfdda9d7SSteve Wise skb_get(skb); 116464bec74aSHariprasad S t4_set_arp_err_handler(skb, NULL, mpa_start_arp_failure); 1165cfdda9d7SSteve Wise ep->mpa_skb = skb; 1166a7db89ebSSteve Wise __state_set(&ep->com, MPA_REP_SENT); 11679c88aa00SSteve Wise ep->snd_seq += mpalen; 1168cfdda9d7SSteve Wise return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 1169cfdda9d7SSteve Wise } 1170cfdda9d7SSteve Wise 1171cfdda9d7SSteve Wise static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb) 1172cfdda9d7SSteve Wise { 1173cfdda9d7SSteve Wise struct c4iw_ep *ep; 1174cfdda9d7SSteve Wise struct cpl_act_establish *req = cplhdr(skb); 1175cfdda9d7SSteve Wise unsigned int tid = GET_TID(req); 11766c53e938SHariprasad Shenai unsigned int atid = TID_TID_G(ntohl(req->tos_atid)); 1177cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 1178fef4422dSHariprasad S int ret; 1179cfdda9d7SSteve Wise 1180cfdda9d7SSteve Wise ep = lookup_atid(t, atid); 1181cfdda9d7SSteve Wise 1182cfdda9d7SSteve Wise PDBG("%s ep %p tid %u snd_isn %u rcv_isn %u\n", __func__, ep, tid, 1183cfdda9d7SSteve Wise be32_to_cpu(req->snd_isn), be32_to_cpu(req->rcv_isn)); 1184cfdda9d7SSteve Wise 1185a7db89ebSSteve Wise mutex_lock(&ep->com.mutex); 1186cfdda9d7SSteve Wise dst_confirm(ep->dst); 1187cfdda9d7SSteve Wise 1188cfdda9d7SSteve Wise /* setup the hwtid for this connection */ 1189cfdda9d7SSteve Wise ep->hwtid = tid; 1190cfdda9d7SSteve Wise cxgb4_insert_tid(t, ep, tid); 1191944661ddSHariprasad S insert_ep_tid(ep); 1192cfdda9d7SSteve Wise 1193cfdda9d7SSteve Wise ep->snd_seq = be32_to_cpu(req->snd_isn); 1194cfdda9d7SSteve Wise ep->rcv_seq = be32_to_cpu(req->rcv_isn); 1195cfdda9d7SSteve Wise 1196cfdda9d7SSteve Wise set_emss(ep, ntohs(req->tcp_opt)); 1197cfdda9d7SSteve Wise 1198cfdda9d7SSteve Wise /* dealloc the atid */ 1199793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, atid); 1200cfdda9d7SSteve Wise cxgb4_free_atid(t, atid); 1201793dad94SVipul Pandya set_bit(ACT_ESTAB, &ep->com.history); 1202cfdda9d7SSteve Wise 1203cfdda9d7SSteve Wise /* start MPA negotiation */ 12044a740838SHariprasad S ret = send_flowc(ep); 1205fef4422dSHariprasad S if (ret) 1206fef4422dSHariprasad S goto err; 1207d2fe99e8SKumar Sanghvi if (ep->retry_with_mpa_v1) 1208caa6c9f2SHariprasad S ret = send_mpa_req(ep, skb, 1); 1209d2fe99e8SKumar Sanghvi else 1210caa6c9f2SHariprasad S ret = send_mpa_req(ep, skb, mpa_rev); 1211caa6c9f2SHariprasad S if (ret) 1212caa6c9f2SHariprasad S goto err; 1213a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 1214cfdda9d7SSteve Wise return 0; 1215fef4422dSHariprasad S err: 1216fef4422dSHariprasad S mutex_unlock(&ep->com.mutex); 1217fef4422dSHariprasad S connect_reply_upcall(ep, -ENOMEM); 1218fef4422dSHariprasad S c4iw_ep_disconnect(ep, 0, GFP_KERNEL); 1219fef4422dSHariprasad S return 0; 1220cfdda9d7SSteve Wise } 1221cfdda9d7SSteve Wise 1222be13b2dfSSteve Wise static void close_complete_upcall(struct c4iw_ep *ep, int status) 1223cfdda9d7SSteve Wise { 1224cfdda9d7SSteve Wise struct iw_cm_event event; 1225cfdda9d7SSteve Wise 1226cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1227cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1228cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CLOSE; 1229be13b2dfSSteve Wise event.status = status; 1230cfdda9d7SSteve Wise if (ep->com.cm_id) { 1231cfdda9d7SSteve Wise PDBG("close complete delivered ep %p cm_id %p tid %u\n", 1232cfdda9d7SSteve Wise ep, ep->com.cm_id, ep->hwtid); 1233cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 12349ca6f7cfSHariprasad S deref_cm_id(&ep->com); 1235793dad94SVipul Pandya set_bit(CLOSE_UPCALL, &ep->com.history); 1236cfdda9d7SSteve Wise } 1237cfdda9d7SSteve Wise } 1238cfdda9d7SSteve Wise 1239cfdda9d7SSteve Wise static void peer_close_upcall(struct c4iw_ep *ep) 1240cfdda9d7SSteve Wise { 1241cfdda9d7SSteve Wise struct iw_cm_event event; 1242cfdda9d7SSteve Wise 1243cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1244cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1245cfdda9d7SSteve Wise event.event = IW_CM_EVENT_DISCONNECT; 1246cfdda9d7SSteve Wise if (ep->com.cm_id) { 1247cfdda9d7SSteve Wise PDBG("peer close delivered ep %p cm_id %p tid %u\n", 1248cfdda9d7SSteve Wise ep, ep->com.cm_id, ep->hwtid); 1249cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 1250793dad94SVipul Pandya set_bit(DISCONN_UPCALL, &ep->com.history); 1251cfdda9d7SSteve Wise } 1252cfdda9d7SSteve Wise } 1253cfdda9d7SSteve Wise 1254cfdda9d7SSteve Wise static void peer_abort_upcall(struct c4iw_ep *ep) 1255cfdda9d7SSteve Wise { 1256cfdda9d7SSteve Wise struct iw_cm_event event; 1257cfdda9d7SSteve Wise 1258cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1259cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1260cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CLOSE; 1261cfdda9d7SSteve Wise event.status = -ECONNRESET; 1262cfdda9d7SSteve Wise if (ep->com.cm_id) { 1263cfdda9d7SSteve Wise PDBG("abort delivered ep %p cm_id %p tid %u\n", ep, 1264cfdda9d7SSteve Wise ep->com.cm_id, ep->hwtid); 1265cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 12669ca6f7cfSHariprasad S deref_cm_id(&ep->com); 1267793dad94SVipul Pandya set_bit(ABORT_UPCALL, &ep->com.history); 1268cfdda9d7SSteve Wise } 1269cfdda9d7SSteve Wise } 1270cfdda9d7SSteve Wise 1271cfdda9d7SSteve Wise static void connect_reply_upcall(struct c4iw_ep *ep, int status) 1272cfdda9d7SSteve Wise { 1273cfdda9d7SSteve Wise struct iw_cm_event event; 1274cfdda9d7SSteve Wise 1275cfdda9d7SSteve Wise PDBG("%s ep %p tid %u status %d\n", __func__, ep, ep->hwtid, status); 1276cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1277cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CONNECT_REPLY; 1278cfdda9d7SSteve Wise event.status = status; 127924d44a39SSteve Wise memcpy(&event.local_addr, &ep->com.local_addr, 128024d44a39SSteve Wise sizeof(ep->com.local_addr)); 128124d44a39SSteve Wise memcpy(&event.remote_addr, &ep->com.remote_addr, 128224d44a39SSteve Wise sizeof(ep->com.remote_addr)); 1283cfdda9d7SSteve Wise 1284cfdda9d7SSteve Wise if ((status == 0) || (status == -ECONNREFUSED)) { 1285d2fe99e8SKumar Sanghvi if (!ep->tried_with_mpa_v1) { 1286d2fe99e8SKumar Sanghvi /* this means MPA_v2 is used */ 1287158c776dSHariprasad S event.ord = ep->ird; 1288158c776dSHariprasad S event.ird = ep->ord; 1289d2fe99e8SKumar Sanghvi event.private_data_len = ep->plen - 1290d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1291d2fe99e8SKumar Sanghvi event.private_data = ep->mpa_pkt + 1292d2fe99e8SKumar Sanghvi sizeof(struct mpa_message) + 1293d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1294d2fe99e8SKumar Sanghvi } else { 1295d2fe99e8SKumar Sanghvi /* this means MPA_v1 is used */ 1296158c776dSHariprasad S event.ord = cur_max_read_depth(ep->com.dev); 1297158c776dSHariprasad S event.ird = cur_max_read_depth(ep->com.dev); 1298cfdda9d7SSteve Wise event.private_data_len = ep->plen; 1299d2fe99e8SKumar Sanghvi event.private_data = ep->mpa_pkt + 1300d2fe99e8SKumar Sanghvi sizeof(struct mpa_message); 1301d2fe99e8SKumar Sanghvi } 1302cfdda9d7SSteve Wise } 130385963e4cSRoland Dreier 1304cfdda9d7SSteve Wise PDBG("%s ep %p tid %u status %d\n", __func__, ep, 1305cfdda9d7SSteve Wise ep->hwtid, status); 1306793dad94SVipul Pandya set_bit(CONN_RPL_UPCALL, &ep->com.history); 1307cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 130885963e4cSRoland Dreier 13099ca6f7cfSHariprasad S if (status < 0) 13109ca6f7cfSHariprasad S deref_cm_id(&ep->com); 1311cfdda9d7SSteve Wise } 1312cfdda9d7SSteve Wise 1313be13b2dfSSteve Wise static int connect_request_upcall(struct c4iw_ep *ep) 1314cfdda9d7SSteve Wise { 1315cfdda9d7SSteve Wise struct iw_cm_event event; 1316be13b2dfSSteve Wise int ret; 1317cfdda9d7SSteve Wise 1318cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1319cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1320cfdda9d7SSteve Wise event.event = IW_CM_EVENT_CONNECT_REQUEST; 132124d44a39SSteve Wise memcpy(&event.local_addr, &ep->com.local_addr, 132224d44a39SSteve Wise sizeof(ep->com.local_addr)); 132324d44a39SSteve Wise memcpy(&event.remote_addr, &ep->com.remote_addr, 132424d44a39SSteve Wise sizeof(ep->com.remote_addr)); 1325d2fe99e8SKumar Sanghvi event.provider_data = ep; 1326d2fe99e8SKumar Sanghvi if (!ep->tried_with_mpa_v1) { 1327d2fe99e8SKumar Sanghvi /* this means MPA_v2 is used */ 1328d2fe99e8SKumar Sanghvi event.ord = ep->ord; 1329d2fe99e8SKumar Sanghvi event.ird = ep->ird; 1330d2fe99e8SKumar Sanghvi event.private_data_len = ep->plen - 1331d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1332d2fe99e8SKumar Sanghvi event.private_data = ep->mpa_pkt + sizeof(struct mpa_message) + 1333d2fe99e8SKumar Sanghvi sizeof(struct mpa_v2_conn_params); 1334d2fe99e8SKumar Sanghvi } else { 1335d2fe99e8SKumar Sanghvi /* this means MPA_v1 is used. Send max supported */ 13364c2c5763SHariprasad Shenai event.ord = cur_max_read_depth(ep->com.dev); 13374c2c5763SHariprasad Shenai event.ird = cur_max_read_depth(ep->com.dev); 1338cfdda9d7SSteve Wise event.private_data_len = ep->plen; 1339cfdda9d7SSteve Wise event.private_data = ep->mpa_pkt + sizeof(struct mpa_message); 1340d2fe99e8SKumar Sanghvi } 1341cfdda9d7SSteve Wise c4iw_get_ep(&ep->com); 1342be13b2dfSSteve Wise ret = ep->parent_ep->com.cm_id->event_handler(ep->parent_ep->com.cm_id, 1343cfdda9d7SSteve Wise &event); 1344be13b2dfSSteve Wise if (ret) 1345be13b2dfSSteve Wise c4iw_put_ep(&ep->com); 1346793dad94SVipul Pandya set_bit(CONNREQ_UPCALL, &ep->com.history); 1347cfdda9d7SSteve Wise c4iw_put_ep(&ep->parent_ep->com); 1348be13b2dfSSteve Wise return ret; 1349cfdda9d7SSteve Wise } 1350cfdda9d7SSteve Wise 1351cfdda9d7SSteve Wise static void established_upcall(struct c4iw_ep *ep) 1352cfdda9d7SSteve Wise { 1353cfdda9d7SSteve Wise struct iw_cm_event event; 1354cfdda9d7SSteve Wise 1355cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1356cfdda9d7SSteve Wise memset(&event, 0, sizeof(event)); 1357cfdda9d7SSteve Wise event.event = IW_CM_EVENT_ESTABLISHED; 13583dd9a5dcSHariprasad S event.ird = ep->ord; 13593dd9a5dcSHariprasad S event.ord = ep->ird; 1360cfdda9d7SSteve Wise if (ep->com.cm_id) { 1361cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1362cfdda9d7SSteve Wise ep->com.cm_id->event_handler(ep->com.cm_id, &event); 1363793dad94SVipul Pandya set_bit(ESTAB_UPCALL, &ep->com.history); 1364cfdda9d7SSteve Wise } 1365cfdda9d7SSteve Wise } 1366cfdda9d7SSteve Wise 1367cfdda9d7SSteve Wise static int update_rx_credits(struct c4iw_ep *ep, u32 credits) 1368cfdda9d7SSteve Wise { 1369cfdda9d7SSteve Wise struct cpl_rx_data_ack *req; 1370cfdda9d7SSteve Wise struct sk_buff *skb; 1371cfdda9d7SSteve Wise int wrlen = roundup(sizeof *req, 16); 1372cfdda9d7SSteve Wise 1373cfdda9d7SSteve Wise PDBG("%s ep %p tid %u credits %u\n", __func__, ep, ep->hwtid, credits); 1374cfdda9d7SSteve Wise skb = get_skb(NULL, wrlen, GFP_KERNEL); 1375cfdda9d7SSteve Wise if (!skb) { 1376cfdda9d7SSteve Wise printk(KERN_ERR MOD "update_rx_credits - cannot alloc skb!\n"); 1377cfdda9d7SSteve Wise return 0; 1378cfdda9d7SSteve Wise } 1379cfdda9d7SSteve Wise 1380b408ff28SHariprasad Shenai /* 1381b408ff28SHariprasad Shenai * If we couldn't specify the entire rcv window at connection setup 1382b408ff28SHariprasad Shenai * due to the limit in the number of bits in the RCV_BUFSIZ field, 1383b408ff28SHariprasad Shenai * then add the overage in to the credits returned. 1384b408ff28SHariprasad Shenai */ 1385d7990b0cSAnish Bhatt if (ep->rcv_win > RCV_BUFSIZ_M * 1024) 1386d7990b0cSAnish Bhatt credits += ep->rcv_win - RCV_BUFSIZ_M * 1024; 1387b408ff28SHariprasad Shenai 1388cfdda9d7SSteve Wise req = (struct cpl_rx_data_ack *) skb_put(skb, wrlen); 1389cfdda9d7SSteve Wise memset(req, 0, wrlen); 1390cfdda9d7SSteve Wise INIT_TP_WR(req, ep->hwtid); 1391cfdda9d7SSteve Wise OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_RX_DATA_ACK, 1392cfdda9d7SSteve Wise ep->hwtid)); 1393d7990b0cSAnish Bhatt req->credit_dack = cpu_to_be32(credits | RX_FORCE_ACK_F | 1394cf7fe64aSHariprasad Shenai RX_DACK_CHANGE_F | 1395cf7fe64aSHariprasad Shenai RX_DACK_MODE_V(dack_mode)); 1396d4f1a5c6SSteve Wise set_wr_txq(skb, CPL_PRIORITY_ACK, ep->ctrlq_idx); 1397cfdda9d7SSteve Wise c4iw_ofld_send(&ep->com.dev->rdev, skb); 1398cfdda9d7SSteve Wise return credits; 1399cfdda9d7SSteve Wise } 1400cfdda9d7SSteve Wise 14014c2c5763SHariprasad Shenai #define RELAXED_IRD_NEGOTIATION 1 14024c2c5763SHariprasad Shenai 1403f8e1e1d1SHariprasad S /* 1404f8e1e1d1SHariprasad S * process_mpa_reply - process streaming mode MPA reply 1405f8e1e1d1SHariprasad S * 1406f8e1e1d1SHariprasad S * Returns: 1407f8e1e1d1SHariprasad S * 1408f8e1e1d1SHariprasad S * 0 upon success indicating a connect request was delivered to the ULP 1409f8e1e1d1SHariprasad S * or the mpa request is incomplete but valid so far. 1410f8e1e1d1SHariprasad S * 1411f8e1e1d1SHariprasad S * 1 if a failure requires the caller to close the connection. 1412f8e1e1d1SHariprasad S * 1413f8e1e1d1SHariprasad S * 2 if a failure requires the caller to abort the connection. 1414f8e1e1d1SHariprasad S */ 1415cc18b939SSteve Wise static int process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb) 1416cfdda9d7SSteve Wise { 1417cfdda9d7SSteve Wise struct mpa_message *mpa; 1418d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params *mpa_v2_params; 1419cfdda9d7SSteve Wise u16 plen; 1420d2fe99e8SKumar Sanghvi u16 resp_ird, resp_ord; 1421d2fe99e8SKumar Sanghvi u8 rtr_mismatch = 0, insuff_ird = 0; 1422cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 1423cfdda9d7SSteve Wise enum c4iw_qp_attr_mask mask; 1424cfdda9d7SSteve Wise int err; 1425cc18b939SSteve Wise int disconnect = 0; 1426cfdda9d7SSteve Wise 1427cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1428cfdda9d7SSteve Wise 1429cfdda9d7SSteve Wise /* 1430cfdda9d7SSteve Wise * If we get more than the supported amount of private data 1431cfdda9d7SSteve Wise * then we must fail this connection. 1432cfdda9d7SSteve Wise */ 1433cfdda9d7SSteve Wise if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) { 1434cfdda9d7SSteve Wise err = -EINVAL; 1435da1cecdfSHariprasad S goto err_stop_timer; 1436cfdda9d7SSteve Wise } 1437cfdda9d7SSteve Wise 1438cfdda9d7SSteve Wise /* 1439cfdda9d7SSteve Wise * copy the new data into our accumulation buffer. 1440cfdda9d7SSteve Wise */ 1441cfdda9d7SSteve Wise skb_copy_from_linear_data(skb, &(ep->mpa_pkt[ep->mpa_pkt_len]), 1442cfdda9d7SSteve Wise skb->len); 1443cfdda9d7SSteve Wise ep->mpa_pkt_len += skb->len; 1444cfdda9d7SSteve Wise 1445cfdda9d7SSteve Wise /* 1446cfdda9d7SSteve Wise * if we don't even have the mpa message, then bail. 1447cfdda9d7SSteve Wise */ 1448cfdda9d7SSteve Wise if (ep->mpa_pkt_len < sizeof(*mpa)) 1449cc18b939SSteve Wise return 0; 1450cfdda9d7SSteve Wise mpa = (struct mpa_message *) ep->mpa_pkt; 1451cfdda9d7SSteve Wise 1452cfdda9d7SSteve Wise /* Validate MPA header. */ 1453d2fe99e8SKumar Sanghvi if (mpa->revision > mpa_rev) { 1454d2fe99e8SKumar Sanghvi printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d," 1455d2fe99e8SKumar Sanghvi " Received = %d\n", __func__, mpa_rev, mpa->revision); 1456cfdda9d7SSteve Wise err = -EPROTO; 1457da1cecdfSHariprasad S goto err_stop_timer; 1458cfdda9d7SSteve Wise } 1459cfdda9d7SSteve Wise if (memcmp(mpa->key, MPA_KEY_REP, sizeof(mpa->key))) { 1460cfdda9d7SSteve Wise err = -EPROTO; 1461da1cecdfSHariprasad S goto err_stop_timer; 1462cfdda9d7SSteve Wise } 1463cfdda9d7SSteve Wise 1464cfdda9d7SSteve Wise plen = ntohs(mpa->private_data_size); 1465cfdda9d7SSteve Wise 1466cfdda9d7SSteve Wise /* 1467cfdda9d7SSteve Wise * Fail if there's too much private data. 1468cfdda9d7SSteve Wise */ 1469cfdda9d7SSteve Wise if (plen > MPA_MAX_PRIVATE_DATA) { 1470cfdda9d7SSteve Wise err = -EPROTO; 1471da1cecdfSHariprasad S goto err_stop_timer; 1472cfdda9d7SSteve Wise } 1473cfdda9d7SSteve Wise 1474cfdda9d7SSteve Wise /* 1475cfdda9d7SSteve Wise * If plen does not account for pkt size 1476cfdda9d7SSteve Wise */ 1477cfdda9d7SSteve Wise if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) { 1478cfdda9d7SSteve Wise err = -EPROTO; 1479da1cecdfSHariprasad S goto err_stop_timer; 1480cfdda9d7SSteve Wise } 1481cfdda9d7SSteve Wise 1482cfdda9d7SSteve Wise ep->plen = (u8) plen; 1483cfdda9d7SSteve Wise 1484cfdda9d7SSteve Wise /* 1485cfdda9d7SSteve Wise * If we don't have all the pdata yet, then bail. 1486cfdda9d7SSteve Wise * We'll continue process when more data arrives. 1487cfdda9d7SSteve Wise */ 1488cfdda9d7SSteve Wise if (ep->mpa_pkt_len < (sizeof(*mpa) + plen)) 1489cc18b939SSteve Wise return 0; 1490cfdda9d7SSteve Wise 1491cfdda9d7SSteve Wise if (mpa->flags & MPA_REJECT) { 1492cfdda9d7SSteve Wise err = -ECONNREFUSED; 1493da1cecdfSHariprasad S goto err_stop_timer; 1494cfdda9d7SSteve Wise } 1495cfdda9d7SSteve Wise 1496cfdda9d7SSteve Wise /* 1497da1cecdfSHariprasad S * Stop mpa timer. If it expired, then 1498da1cecdfSHariprasad S * we ignore the MPA reply. process_timeout() 1499da1cecdfSHariprasad S * will abort the connection. 1500da1cecdfSHariprasad S */ 1501da1cecdfSHariprasad S if (stop_ep_timer(ep)) 1502da1cecdfSHariprasad S return 0; 1503da1cecdfSHariprasad S 1504da1cecdfSHariprasad S /* 1505cfdda9d7SSteve Wise * If we get here we have accumulated the entire mpa 1506cfdda9d7SSteve Wise * start reply message including private data. And 1507cfdda9d7SSteve Wise * the MPA header is valid. 1508cfdda9d7SSteve Wise */ 1509c529fb50SSteve Wise __state_set(&ep->com, FPDU_MODE); 1510cfdda9d7SSteve Wise ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0; 1511cfdda9d7SSteve Wise ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0; 1512d2fe99e8SKumar Sanghvi ep->mpa_attr.version = mpa->revision; 1513d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED; 1514d2fe99e8SKumar Sanghvi 1515d2fe99e8SKumar Sanghvi if (mpa->revision == 2) { 1516d2fe99e8SKumar Sanghvi ep->mpa_attr.enhanced_rdma_conn = 1517d2fe99e8SKumar Sanghvi mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0; 1518d2fe99e8SKumar Sanghvi if (ep->mpa_attr.enhanced_rdma_conn) { 1519d2fe99e8SKumar Sanghvi mpa_v2_params = (struct mpa_v2_conn_params *) 1520d2fe99e8SKumar Sanghvi (ep->mpa_pkt + sizeof(*mpa)); 1521d2fe99e8SKumar Sanghvi resp_ird = ntohs(mpa_v2_params->ird) & 1522d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 1523d2fe99e8SKumar Sanghvi resp_ord = ntohs(mpa_v2_params->ord) & 1524d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 15254c2c5763SHariprasad Shenai PDBG("%s responder ird %u ord %u ep ird %u ord %u\n", 15264c2c5763SHariprasad Shenai __func__, resp_ird, resp_ord, ep->ird, ep->ord); 1527d2fe99e8SKumar Sanghvi 1528d2fe99e8SKumar Sanghvi /* 1529d2fe99e8SKumar Sanghvi * This is a double-check. Ideally, below checks are 1530d2fe99e8SKumar Sanghvi * not required since ird/ord stuff has been taken 1531d2fe99e8SKumar Sanghvi * care of in c4iw_accept_cr 1532d2fe99e8SKumar Sanghvi */ 15334c2c5763SHariprasad Shenai if (ep->ird < resp_ord) { 15344c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION && resp_ord <= 15354c2c5763SHariprasad Shenai ep->com.dev->rdev.lldi.max_ordird_qp) 15364c2c5763SHariprasad Shenai ep->ird = resp_ord; 15374c2c5763SHariprasad Shenai else 15384c2c5763SHariprasad Shenai insuff_ird = 1; 15394c2c5763SHariprasad Shenai } else if (ep->ird > resp_ord) { 15404c2c5763SHariprasad Shenai ep->ird = resp_ord; 15414c2c5763SHariprasad Shenai } 15424c2c5763SHariprasad Shenai if (ep->ord > resp_ird) { 15434c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION) 15444c2c5763SHariprasad Shenai ep->ord = resp_ird; 15454c2c5763SHariprasad Shenai else 15464c2c5763SHariprasad Shenai insuff_ird = 1; 15474c2c5763SHariprasad Shenai } 15484c2c5763SHariprasad Shenai if (insuff_ird) { 1549d2fe99e8SKumar Sanghvi err = -ENOMEM; 1550d2fe99e8SKumar Sanghvi ep->ird = resp_ord; 1551d2fe99e8SKumar Sanghvi ep->ord = resp_ird; 1552d2fe99e8SKumar Sanghvi } 1553d2fe99e8SKumar Sanghvi 1554d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ird) & 1555d2fe99e8SKumar Sanghvi MPA_V2_PEER2PEER_MODEL) { 1556d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ord) & 1557d2fe99e8SKumar Sanghvi MPA_V2_RDMA_WRITE_RTR) 1558d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1559d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_RDMA_WRITE; 1560d2fe99e8SKumar Sanghvi else if (ntohs(mpa_v2_params->ord) & 1561d2fe99e8SKumar Sanghvi MPA_V2_RDMA_READ_RTR) 1562d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1563d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_READ_REQ; 1564d2fe99e8SKumar Sanghvi } 1565d2fe99e8SKumar Sanghvi } 1566d2fe99e8SKumar Sanghvi } else if (mpa->revision == 1) 1567d2fe99e8SKumar Sanghvi if (peer2peer) 1568d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = p2p_type; 1569d2fe99e8SKumar Sanghvi 1570cfdda9d7SSteve Wise PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, " 1571d2fe99e8SKumar Sanghvi "xmit_marker_enabled=%d, version=%d p2p_type=%d local-p2p_type = " 1572d2fe99e8SKumar Sanghvi "%d\n", __func__, ep->mpa_attr.crc_enabled, 1573d2fe99e8SKumar Sanghvi ep->mpa_attr.recv_marker_enabled, 1574d2fe99e8SKumar Sanghvi ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version, 1575d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type, p2p_type); 1576d2fe99e8SKumar Sanghvi 1577d2fe99e8SKumar Sanghvi /* 1578d2fe99e8SKumar Sanghvi * If responder's RTR does not match with that of initiator, assign 1579d2fe99e8SKumar Sanghvi * FW_RI_INIT_P2PTYPE_DISABLED in mpa attributes so that RTR is not 1580d2fe99e8SKumar Sanghvi * generated when moving QP to RTS state. 1581d2fe99e8SKumar Sanghvi * A TERM message will be sent after QP has moved to RTS state 1582d2fe99e8SKumar Sanghvi */ 158391018f86SKumar Sanghvi if ((ep->mpa_attr.version == 2) && peer2peer && 1584d2fe99e8SKumar Sanghvi (ep->mpa_attr.p2p_type != p2p_type)) { 1585d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED; 1586d2fe99e8SKumar Sanghvi rtr_mismatch = 1; 1587d2fe99e8SKumar Sanghvi } 1588cfdda9d7SSteve Wise 1589cfdda9d7SSteve Wise attrs.mpa_attr = ep->mpa_attr; 1590cfdda9d7SSteve Wise attrs.max_ird = ep->ird; 1591cfdda9d7SSteve Wise attrs.max_ord = ep->ord; 1592cfdda9d7SSteve Wise attrs.llp_stream_handle = ep; 1593cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_RTS; 1594cfdda9d7SSteve Wise 1595cfdda9d7SSteve Wise mask = C4IW_QP_ATTR_NEXT_STATE | 1596cfdda9d7SSteve Wise C4IW_QP_ATTR_LLP_STREAM_HANDLE | C4IW_QP_ATTR_MPA_ATTR | 1597cfdda9d7SSteve Wise C4IW_QP_ATTR_MAX_IRD | C4IW_QP_ATTR_MAX_ORD; 1598cfdda9d7SSteve Wise 1599cfdda9d7SSteve Wise /* bind QP and TID with INIT_WR */ 1600cfdda9d7SSteve Wise err = c4iw_modify_qp(ep->com.qp->rhp, 1601cfdda9d7SSteve Wise ep->com.qp, mask, &attrs, 1); 1602cfdda9d7SSteve Wise if (err) 1603cfdda9d7SSteve Wise goto err; 1604d2fe99e8SKumar Sanghvi 1605d2fe99e8SKumar Sanghvi /* 1606d2fe99e8SKumar Sanghvi * If responder's RTR requirement did not match with what initiator 1607d2fe99e8SKumar Sanghvi * supports, generate TERM message 1608d2fe99e8SKumar Sanghvi */ 1609d2fe99e8SKumar Sanghvi if (rtr_mismatch) { 1610d2fe99e8SKumar Sanghvi printk(KERN_ERR "%s: RTR mismatch, sending TERM\n", __func__); 1611d2fe99e8SKumar Sanghvi attrs.layer_etype = LAYER_MPA | DDP_LLP; 1612d2fe99e8SKumar Sanghvi attrs.ecode = MPA_NOMATCH_RTR; 1613d2fe99e8SKumar Sanghvi attrs.next_state = C4IW_QP_STATE_TERMINATE; 1614cc18b939SSteve Wise attrs.send_term = 1; 1615d2fe99e8SKumar Sanghvi err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 1616cc18b939SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 1617d2fe99e8SKumar Sanghvi err = -ENOMEM; 1618cc18b939SSteve Wise disconnect = 1; 1619d2fe99e8SKumar Sanghvi goto out; 1620d2fe99e8SKumar Sanghvi } 1621d2fe99e8SKumar Sanghvi 1622d2fe99e8SKumar Sanghvi /* 1623d2fe99e8SKumar Sanghvi * Generate TERM if initiator IRD is not sufficient for responder 1624d2fe99e8SKumar Sanghvi * provided ORD. Currently, we do the same behaviour even when 1625d2fe99e8SKumar Sanghvi * responder provided IRD is also not sufficient as regards to 1626d2fe99e8SKumar Sanghvi * initiator ORD. 1627d2fe99e8SKumar Sanghvi */ 1628d2fe99e8SKumar Sanghvi if (insuff_ird) { 1629d2fe99e8SKumar Sanghvi printk(KERN_ERR "%s: Insufficient IRD, sending TERM\n", 1630d2fe99e8SKumar Sanghvi __func__); 1631d2fe99e8SKumar Sanghvi attrs.layer_etype = LAYER_MPA | DDP_LLP; 1632d2fe99e8SKumar Sanghvi attrs.ecode = MPA_INSUFF_IRD; 1633d2fe99e8SKumar Sanghvi attrs.next_state = C4IW_QP_STATE_TERMINATE; 1634cc18b939SSteve Wise attrs.send_term = 1; 1635d2fe99e8SKumar Sanghvi err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 1636cc18b939SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 1637d2fe99e8SKumar Sanghvi err = -ENOMEM; 1638cc18b939SSteve Wise disconnect = 1; 1639d2fe99e8SKumar Sanghvi goto out; 1640d2fe99e8SKumar Sanghvi } 1641cfdda9d7SSteve Wise goto out; 1642da1cecdfSHariprasad S err_stop_timer: 1643da1cecdfSHariprasad S stop_ep_timer(ep); 1644cfdda9d7SSteve Wise err: 1645f8e1e1d1SHariprasad S disconnect = 2; 1646cfdda9d7SSteve Wise out: 1647cfdda9d7SSteve Wise connect_reply_upcall(ep, err); 1648cc18b939SSteve Wise return disconnect; 1649cfdda9d7SSteve Wise } 1650cfdda9d7SSteve Wise 1651fd6aabe4SHariprasad S /* 1652fd6aabe4SHariprasad S * process_mpa_request - process streaming mode MPA request 1653fd6aabe4SHariprasad S * 1654fd6aabe4SHariprasad S * Returns: 1655fd6aabe4SHariprasad S * 1656fd6aabe4SHariprasad S * 0 upon success indicating a connect request was delivered to the ULP 1657fd6aabe4SHariprasad S * or the mpa request is incomplete but valid so far. 1658fd6aabe4SHariprasad S * 1659fd6aabe4SHariprasad S * 1 if a failure requires the caller to close the connection. 1660fd6aabe4SHariprasad S * 1661fd6aabe4SHariprasad S * 2 if a failure requires the caller to abort the connection. 1662fd6aabe4SHariprasad S */ 1663fd6aabe4SHariprasad S static int process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb) 1664cfdda9d7SSteve Wise { 1665cfdda9d7SSteve Wise struct mpa_message *mpa; 1666d2fe99e8SKumar Sanghvi struct mpa_v2_conn_params *mpa_v2_params; 1667cfdda9d7SSteve Wise u16 plen; 1668cfdda9d7SSteve Wise 1669cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 1670cfdda9d7SSteve Wise 1671cfdda9d7SSteve Wise /* 1672cfdda9d7SSteve Wise * If we get more than the supported amount of private data 1673cfdda9d7SSteve Wise * then we must fail this connection. 1674cfdda9d7SSteve Wise */ 1675fd6aabe4SHariprasad S if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) 1676fd6aabe4SHariprasad S goto err_stop_timer; 1677cfdda9d7SSteve Wise 1678cfdda9d7SSteve Wise PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__); 1679cfdda9d7SSteve Wise 1680cfdda9d7SSteve Wise /* 1681cfdda9d7SSteve Wise * Copy the new data into our accumulation buffer. 1682cfdda9d7SSteve Wise */ 1683cfdda9d7SSteve Wise skb_copy_from_linear_data(skb, &(ep->mpa_pkt[ep->mpa_pkt_len]), 1684cfdda9d7SSteve Wise skb->len); 1685cfdda9d7SSteve Wise ep->mpa_pkt_len += skb->len; 1686cfdda9d7SSteve Wise 1687cfdda9d7SSteve Wise /* 1688cfdda9d7SSteve Wise * If we don't even have the mpa message, then bail. 1689cfdda9d7SSteve Wise * We'll continue process when more data arrives. 1690cfdda9d7SSteve Wise */ 1691cfdda9d7SSteve Wise if (ep->mpa_pkt_len < sizeof(*mpa)) 1692fd6aabe4SHariprasad S return 0; 1693cfdda9d7SSteve Wise 1694cfdda9d7SSteve Wise PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__); 1695cfdda9d7SSteve Wise mpa = (struct mpa_message *) ep->mpa_pkt; 1696cfdda9d7SSteve Wise 1697cfdda9d7SSteve Wise /* 1698cfdda9d7SSteve Wise * Validate MPA Header. 1699cfdda9d7SSteve Wise */ 1700d2fe99e8SKumar Sanghvi if (mpa->revision > mpa_rev) { 1701d2fe99e8SKumar Sanghvi printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d," 1702d2fe99e8SKumar Sanghvi " Received = %d\n", __func__, mpa_rev, mpa->revision); 1703fd6aabe4SHariprasad S goto err_stop_timer; 1704cfdda9d7SSteve Wise } 1705cfdda9d7SSteve Wise 1706fd6aabe4SHariprasad S if (memcmp(mpa->key, MPA_KEY_REQ, sizeof(mpa->key))) 1707fd6aabe4SHariprasad S goto err_stop_timer; 1708cfdda9d7SSteve Wise 1709cfdda9d7SSteve Wise plen = ntohs(mpa->private_data_size); 1710cfdda9d7SSteve Wise 1711cfdda9d7SSteve Wise /* 1712cfdda9d7SSteve Wise * Fail if there's too much private data. 1713cfdda9d7SSteve Wise */ 1714fd6aabe4SHariprasad S if (plen > MPA_MAX_PRIVATE_DATA) 1715fd6aabe4SHariprasad S goto err_stop_timer; 1716cfdda9d7SSteve Wise 1717cfdda9d7SSteve Wise /* 1718cfdda9d7SSteve Wise * If plen does not account for pkt size 1719cfdda9d7SSteve Wise */ 1720fd6aabe4SHariprasad S if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) 1721fd6aabe4SHariprasad S goto err_stop_timer; 1722cfdda9d7SSteve Wise ep->plen = (u8) plen; 1723cfdda9d7SSteve Wise 1724cfdda9d7SSteve Wise /* 1725cfdda9d7SSteve Wise * If we don't have all the pdata yet, then bail. 1726cfdda9d7SSteve Wise */ 1727cfdda9d7SSteve Wise if (ep->mpa_pkt_len < (sizeof(*mpa) + plen)) 1728fd6aabe4SHariprasad S return 0; 1729cfdda9d7SSteve Wise 1730cfdda9d7SSteve Wise /* 1731cfdda9d7SSteve Wise * If we get here we have accumulated the entire mpa 1732cfdda9d7SSteve Wise * start reply message including private data. 1733cfdda9d7SSteve Wise */ 1734cfdda9d7SSteve Wise ep->mpa_attr.initiator = 0; 1735cfdda9d7SSteve Wise ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0; 1736cfdda9d7SSteve Wise ep->mpa_attr.recv_marker_enabled = markers_enabled; 1737cfdda9d7SSteve Wise ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0; 1738d2fe99e8SKumar Sanghvi ep->mpa_attr.version = mpa->revision; 1739d2fe99e8SKumar Sanghvi if (mpa->revision == 1) 1740d2fe99e8SKumar Sanghvi ep->tried_with_mpa_v1 = 1; 1741d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED; 1742d2fe99e8SKumar Sanghvi 1743d2fe99e8SKumar Sanghvi if (mpa->revision == 2) { 1744d2fe99e8SKumar Sanghvi ep->mpa_attr.enhanced_rdma_conn = 1745d2fe99e8SKumar Sanghvi mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0; 1746d2fe99e8SKumar Sanghvi if (ep->mpa_attr.enhanced_rdma_conn) { 1747d2fe99e8SKumar Sanghvi mpa_v2_params = (struct mpa_v2_conn_params *) 1748d2fe99e8SKumar Sanghvi (ep->mpa_pkt + sizeof(*mpa)); 1749d2fe99e8SKumar Sanghvi ep->ird = ntohs(mpa_v2_params->ird) & 1750d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 17517f446abfSSteve Wise ep->ird = min_t(u32, ep->ird, 17527f446abfSSteve Wise cur_max_read_depth(ep->com.dev)); 1753d2fe99e8SKumar Sanghvi ep->ord = ntohs(mpa_v2_params->ord) & 1754d2fe99e8SKumar Sanghvi MPA_V2_IRD_ORD_MASK; 17557f446abfSSteve Wise ep->ord = min_t(u32, ep->ord, 17567f446abfSSteve Wise cur_max_read_depth(ep->com.dev)); 17574c2c5763SHariprasad Shenai PDBG("%s initiator ird %u ord %u\n", __func__, ep->ird, 17584c2c5763SHariprasad Shenai ep->ord); 1759d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ird) & MPA_V2_PEER2PEER_MODEL) 1760d2fe99e8SKumar Sanghvi if (peer2peer) { 1761d2fe99e8SKumar Sanghvi if (ntohs(mpa_v2_params->ord) & 1762d2fe99e8SKumar Sanghvi MPA_V2_RDMA_WRITE_RTR) 1763d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1764d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_RDMA_WRITE; 1765d2fe99e8SKumar Sanghvi else if (ntohs(mpa_v2_params->ord) & 1766d2fe99e8SKumar Sanghvi MPA_V2_RDMA_READ_RTR) 1767d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = 1768d2fe99e8SKumar Sanghvi FW_RI_INIT_P2PTYPE_READ_REQ; 1769d2fe99e8SKumar Sanghvi } 1770d2fe99e8SKumar Sanghvi } 1771d2fe99e8SKumar Sanghvi } else if (mpa->revision == 1) 1772d2fe99e8SKumar Sanghvi if (peer2peer) 1773d2fe99e8SKumar Sanghvi ep->mpa_attr.p2p_type = p2p_type; 1774d2fe99e8SKumar Sanghvi 1775cfdda9d7SSteve Wise PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, " 1776cfdda9d7SSteve Wise "xmit_marker_enabled=%d, version=%d p2p_type=%d\n", __func__, 1777cfdda9d7SSteve Wise ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled, 1778cfdda9d7SSteve Wise ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version, 1779cfdda9d7SSteve Wise ep->mpa_attr.p2p_type); 1780cfdda9d7SSteve Wise 1781c529fb50SSteve Wise __state_set(&ep->com, MPA_REQ_RCVD); 1782cfdda9d7SSteve Wise 1783cfdda9d7SSteve Wise /* drive upcall */ 1784e4b76a2aSHariprasad S mutex_lock_nested(&ep->parent_ep->com.mutex, SINGLE_DEPTH_NESTING); 1785be13b2dfSSteve Wise if (ep->parent_ep->com.state != DEAD) { 1786be13b2dfSSteve Wise if (connect_request_upcall(ep)) 1787fd6aabe4SHariprasad S goto err_unlock_parent; 1788be13b2dfSSteve Wise } else { 1789fd6aabe4SHariprasad S goto err_unlock_parent; 1790be13b2dfSSteve Wise } 1791be13b2dfSSteve Wise mutex_unlock(&ep->parent_ep->com.mutex); 1792fd6aabe4SHariprasad S return 0; 1793fd6aabe4SHariprasad S 1794fd6aabe4SHariprasad S err_unlock_parent: 1795fd6aabe4SHariprasad S mutex_unlock(&ep->parent_ep->com.mutex); 1796fd6aabe4SHariprasad S goto err_out; 1797fd6aabe4SHariprasad S err_stop_timer: 1798fd6aabe4SHariprasad S (void)stop_ep_timer(ep); 1799fd6aabe4SHariprasad S err_out: 1800fd6aabe4SHariprasad S return 2; 1801cfdda9d7SSteve Wise } 1802cfdda9d7SSteve Wise 1803cfdda9d7SSteve Wise static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb) 1804cfdda9d7SSteve Wise { 1805cfdda9d7SSteve Wise struct c4iw_ep *ep; 1806cfdda9d7SSteve Wise struct cpl_rx_data *hdr = cplhdr(skb); 1807cfdda9d7SSteve Wise unsigned int dlen = ntohs(hdr->len); 1808cfdda9d7SSteve Wise unsigned int tid = GET_TID(hdr); 1809793dad94SVipul Pandya __u8 status = hdr->status; 1810cc18b939SSteve Wise int disconnect = 0; 1811cfdda9d7SSteve Wise 1812944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 1813977116c6SSteve Wise if (!ep) 1814977116c6SSteve Wise return 0; 1815cfdda9d7SSteve Wise PDBG("%s ep %p tid %u dlen %u\n", __func__, ep, ep->hwtid, dlen); 1816cfdda9d7SSteve Wise skb_pull(skb, sizeof(*hdr)); 1817cfdda9d7SSteve Wise skb_trim(skb, dlen); 1818c529fb50SSteve Wise mutex_lock(&ep->com.mutex); 1819cfdda9d7SSteve Wise 1820cfdda9d7SSteve Wise /* update RX credits */ 1821cfdda9d7SSteve Wise update_rx_credits(ep, dlen); 1822cfdda9d7SSteve Wise 1823c529fb50SSteve Wise switch (ep->com.state) { 1824cfdda9d7SSteve Wise case MPA_REQ_SENT: 182555abf8dfSVipul Pandya ep->rcv_seq += dlen; 1826cc18b939SSteve Wise disconnect = process_mpa_reply(ep, skb); 1827cfdda9d7SSteve Wise break; 1828cfdda9d7SSteve Wise case MPA_REQ_WAIT: 182955abf8dfSVipul Pandya ep->rcv_seq += dlen; 18304a4dd8dbSHariprasad S disconnect = process_mpa_request(ep, skb); 1831cfdda9d7SSteve Wise break; 18321557967bSVipul Pandya case FPDU_MODE: { 18331557967bSVipul Pandya struct c4iw_qp_attributes attrs; 18341557967bSVipul Pandya BUG_ON(!ep->com.qp); 1835e8e5b927SVipul Pandya if (status) 1836793dad94SVipul Pandya pr_err("%s Unexpected streaming data." \ 183704236df2SVipul Pandya " qpid %u ep %p state %d tid %u status %d\n", 183804236df2SVipul Pandya __func__, ep->com.qp->wq.sq.qid, ep, 1839c529fb50SSteve Wise ep->com.state, ep->hwtid, status); 184097d7ec0cSSteve Wise attrs.next_state = C4IW_QP_STATE_TERMINATE; 184155abf8dfSVipul Pandya c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 1842cc18b939SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 1843cc18b939SSteve Wise disconnect = 1; 1844cfdda9d7SSteve Wise break; 1845cfdda9d7SSteve Wise } 18461557967bSVipul Pandya default: 18471557967bSVipul Pandya break; 18481557967bSVipul Pandya } 1849c529fb50SSteve Wise mutex_unlock(&ep->com.mutex); 1850cc18b939SSteve Wise if (disconnect) 18514a4dd8dbSHariprasad S c4iw_ep_disconnect(ep, disconnect == 2, GFP_KERNEL); 1852944661ddSHariprasad S c4iw_put_ep(&ep->com); 1853cfdda9d7SSteve Wise return 0; 1854cfdda9d7SSteve Wise } 1855cfdda9d7SSteve Wise 1856cfdda9d7SSteve Wise static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 1857cfdda9d7SSteve Wise { 1858cfdda9d7SSteve Wise struct c4iw_ep *ep; 1859cfdda9d7SSteve Wise struct cpl_abort_rpl_rss *rpl = cplhdr(skb); 1860cfdda9d7SSteve Wise int release = 0; 1861cfdda9d7SSteve Wise unsigned int tid = GET_TID(rpl); 1862cfdda9d7SSteve Wise 1863944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 18644984037bSVipul Pandya if (!ep) { 18654984037bSVipul Pandya printk(KERN_WARNING MOD "Abort rpl to freed endpoint\n"); 18664984037bSVipul Pandya return 0; 18674984037bSVipul Pandya } 186892dd6c3dSWei Yongjun PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 18692f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 1870cfdda9d7SSteve Wise switch (ep->com.state) { 1871cfdda9d7SSteve Wise case ABORTING: 187291e9c071SVipul Pandya c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 1873cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 1874cfdda9d7SSteve Wise release = 1; 1875cfdda9d7SSteve Wise break; 1876cfdda9d7SSteve Wise default: 1877cfdda9d7SSteve Wise printk(KERN_ERR "%s ep %p state %d\n", 1878cfdda9d7SSteve Wise __func__, ep, ep->com.state); 1879cfdda9d7SSteve Wise break; 1880cfdda9d7SSteve Wise } 18812f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 1882cfdda9d7SSteve Wise 1883cfdda9d7SSteve Wise if (release) 1884cfdda9d7SSteve Wise release_ep_resources(ep); 1885944661ddSHariprasad S c4iw_put_ep(&ep->com); 1886cfdda9d7SSteve Wise return 0; 1887cfdda9d7SSteve Wise } 1888cfdda9d7SSteve Wise 1889caa6c9f2SHariprasad S static int send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid) 18905be78ee9SVipul Pandya { 18915be78ee9SVipul Pandya struct sk_buff *skb; 18925be78ee9SVipul Pandya struct fw_ofld_connection_wr *req; 18935be78ee9SVipul Pandya unsigned int mtu_idx; 18945be78ee9SVipul Pandya int wscale; 1895830662f6SVipul Pandya struct sockaddr_in *sin; 1896b408ff28SHariprasad Shenai int win; 18975be78ee9SVipul Pandya 18985be78ee9SVipul Pandya skb = get_skb(NULL, sizeof(*req), GFP_KERNEL); 18995be78ee9SVipul Pandya req = (struct fw_ofld_connection_wr *)__skb_put(skb, sizeof(*req)); 19005be78ee9SVipul Pandya memset(req, 0, sizeof(*req)); 19016c53e938SHariprasad Shenai req->op_compl = htonl(WR_OP_V(FW_OFLD_CONNECTION_WR)); 1902e2ac9628SHariprasad Shenai req->len16_pkd = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*req), 16))); 190341b4f86cSKumar Sanghvi req->le.filter = cpu_to_be32(cxgb4_select_ntuple( 190441b4f86cSKumar Sanghvi ep->com.dev->rdev.lldi.ports[0], 19055be78ee9SVipul Pandya ep->l2t)); 1906170003c8SSteve Wise sin = (struct sockaddr_in *)&ep->com.local_addr; 1907830662f6SVipul Pandya req->le.lport = sin->sin_port; 1908830662f6SVipul Pandya req->le.u.ipv4.lip = sin->sin_addr.s_addr; 1909170003c8SSteve Wise sin = (struct sockaddr_in *)&ep->com.remote_addr; 1910830662f6SVipul Pandya req->le.pport = sin->sin_port; 1911830662f6SVipul Pandya req->le.u.ipv4.pip = sin->sin_addr.s_addr; 19125be78ee9SVipul Pandya req->tcb.t_state_to_astid = 191377a80e23SHariprasad Shenai htonl(FW_OFLD_CONNECTION_WR_T_STATE_V(TCP_SYN_SENT) | 191477a80e23SHariprasad Shenai FW_OFLD_CONNECTION_WR_ASTID_V(atid)); 19155be78ee9SVipul Pandya req->tcb.cplrxdataack_cplpassacceptrpl = 191677a80e23SHariprasad Shenai htons(FW_OFLD_CONNECTION_WR_CPLRXDATAACK_F); 1917ef5d6355SVipul Pandya req->tcb.tx_max = (__force __be32) jiffies; 1918793dad94SVipul Pandya req->tcb.rcv_adv = htons(1); 191944c6d069SVarun Prakash cxgb_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, 192004524a47SHariprasad S enable_tcp_timestamps, 192144c6d069SVarun Prakash (ep->com.remote_addr.ss_family == AF_INET) ? 0 : 1); 19225be78ee9SVipul Pandya wscale = compute_wscale(rcv_win); 1923b408ff28SHariprasad Shenai 1924b408ff28SHariprasad Shenai /* 1925b408ff28SHariprasad Shenai * Specify the largest window that will fit in opt0. The 1926b408ff28SHariprasad Shenai * remainder will be specified in the rx_data_ack. 1927b408ff28SHariprasad Shenai */ 1928b408ff28SHariprasad Shenai win = ep->rcv_win >> 10; 1929d7990b0cSAnish Bhatt if (win > RCV_BUFSIZ_M) 1930d7990b0cSAnish Bhatt win = RCV_BUFSIZ_M; 1931b408ff28SHariprasad Shenai 19326c53e938SHariprasad Shenai req->tcb.opt0 = (__force __be64) (TCAM_BYPASS_F | 19336c53e938SHariprasad Shenai (nocong ? NO_CONG_F : 0) | 1934d7990b0cSAnish Bhatt KEEP_ALIVE_F | 19356c53e938SHariprasad Shenai DELACK_F | 1936d7990b0cSAnish Bhatt WND_SCALE_V(wscale) | 1937d7990b0cSAnish Bhatt MSS_IDX_V(mtu_idx) | 1938d7990b0cSAnish Bhatt L2T_IDX_V(ep->l2t->idx) | 1939d7990b0cSAnish Bhatt TX_CHAN_V(ep->tx_chan) | 1940d7990b0cSAnish Bhatt SMAC_SEL_V(ep->smac_idx) | 1941ac8e4c69SHariprasad S DSCP_V(ep->tos >> 2) | 1942d7990b0cSAnish Bhatt ULP_MODE_V(ULP_MODE_TCPDDP) | 1943d7990b0cSAnish Bhatt RCV_BUFSIZ_V(win)); 19446c53e938SHariprasad Shenai req->tcb.opt2 = (__force __be32) (PACE_V(1) | 19456c53e938SHariprasad Shenai TX_QUEUE_V(ep->com.dev->rdev.lldi.tx_modq[ep->tx_chan]) | 1946d7990b0cSAnish Bhatt RX_CHANNEL_V(0) | 19476c53e938SHariprasad Shenai CCTRL_ECN_V(enable_ecn) | 1948d7990b0cSAnish Bhatt RSS_QUEUE_VALID_F | RSS_QUEUE_V(ep->rss_qid)); 19495be78ee9SVipul Pandya if (enable_tcp_timestamps) 19506c53e938SHariprasad Shenai req->tcb.opt2 |= (__force __be32)TSTAMPS_EN_F; 19515be78ee9SVipul Pandya if (enable_tcp_sack) 19526c53e938SHariprasad Shenai req->tcb.opt2 |= (__force __be32)SACK_EN_F; 19535be78ee9SVipul Pandya if (wscale && enable_tcp_window_scaling) 1954d7990b0cSAnish Bhatt req->tcb.opt2 |= (__force __be32)WND_SCALE_EN_F; 1955ef5d6355SVipul Pandya req->tcb.opt0 = cpu_to_be64((__force u64)req->tcb.opt0); 1956ef5d6355SVipul Pandya req->tcb.opt2 = cpu_to_be32((__force u32)req->tcb.opt2); 1957793dad94SVipul Pandya set_wr_txq(skb, CPL_PRIORITY_CONTROL, ep->ctrlq_idx); 1958793dad94SVipul Pandya set_bit(ACT_OFLD_CONN, &ep->com.history); 1959caa6c9f2SHariprasad S return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 19605be78ee9SVipul Pandya } 19615be78ee9SVipul Pandya 1962cfdda9d7SSteve Wise /* 19634c72efefSHariprasad S * Some of the error codes above implicitly indicate that there is no TID 19644c72efefSHariprasad S * allocated with the result of an ACT_OPEN. We use this predicate to make 19654c72efefSHariprasad S * that explicit. 1966cfdda9d7SSteve Wise */ 1967cfdda9d7SSteve Wise static inline int act_open_has_tid(int status) 1968cfdda9d7SSteve Wise { 19694c72efefSHariprasad S return (status != CPL_ERR_TCAM_PARITY && 19704c72efefSHariprasad S status != CPL_ERR_TCAM_MISS && 19714c72efefSHariprasad S status != CPL_ERR_TCAM_FULL && 19724c72efefSHariprasad S status != CPL_ERR_CONN_EXIST_SYNRECV && 19734c72efefSHariprasad S status != CPL_ERR_CONN_EXIST); 1974cfdda9d7SSteve Wise } 1975cfdda9d7SSteve Wise 1976dd92b124SHariprasad Shenai static char *neg_adv_str(unsigned int status) 1977dd92b124SHariprasad Shenai { 1978dd92b124SHariprasad Shenai switch (status) { 1979dd92b124SHariprasad Shenai case CPL_ERR_RTX_NEG_ADVICE: 1980dd92b124SHariprasad Shenai return "Retransmit timeout"; 1981dd92b124SHariprasad Shenai case CPL_ERR_PERSIST_NEG_ADVICE: 1982dd92b124SHariprasad Shenai return "Persist timeout"; 1983dd92b124SHariprasad Shenai case CPL_ERR_KEEPALV_NEG_ADVICE: 1984dd92b124SHariprasad Shenai return "Keepalive timeout"; 1985dd92b124SHariprasad Shenai default: 1986dd92b124SHariprasad Shenai return "Unknown"; 1987dd92b124SHariprasad Shenai } 1988dd92b124SHariprasad Shenai } 1989dd92b124SHariprasad Shenai 1990b408ff28SHariprasad Shenai static void set_tcp_window(struct c4iw_ep *ep, struct port_info *pi) 1991b408ff28SHariprasad Shenai { 1992b408ff28SHariprasad Shenai ep->snd_win = snd_win; 1993b408ff28SHariprasad Shenai ep->rcv_win = rcv_win; 1994b408ff28SHariprasad Shenai PDBG("%s snd_win %d rcv_win %d\n", __func__, ep->snd_win, ep->rcv_win); 1995b408ff28SHariprasad Shenai } 1996b408ff28SHariprasad Shenai 1997793dad94SVipul Pandya #define ACT_OPEN_RETRY_COUNT 2 1998793dad94SVipul Pandya 1999830662f6SVipul Pandya static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, 2000830662f6SVipul Pandya struct dst_entry *dst, struct c4iw_dev *cdev, 2001ac8e4c69SHariprasad S bool clear_mpa_v1, enum chip_type adapter_type, u8 tos) 2002830662f6SVipul Pandya { 2003830662f6SVipul Pandya struct neighbour *n; 2004830662f6SVipul Pandya int err, step; 2005830662f6SVipul Pandya struct net_device *pdev; 2006830662f6SVipul Pandya 2007830662f6SVipul Pandya n = dst_neigh_lookup(dst, peer_ip); 2008830662f6SVipul Pandya if (!n) 2009830662f6SVipul Pandya return -ENODEV; 2010830662f6SVipul Pandya 2011830662f6SVipul Pandya rcu_read_lock(); 2012830662f6SVipul Pandya err = -ENOMEM; 2013830662f6SVipul Pandya if (n->dev->flags & IFF_LOOPBACK) { 2014830662f6SVipul Pandya if (iptype == 4) 2015830662f6SVipul Pandya pdev = ip_dev_find(&init_net, *(__be32 *)peer_ip); 2016830662f6SVipul Pandya else if (IS_ENABLED(CONFIG_IPV6)) 2017830662f6SVipul Pandya for_each_netdev(&init_net, pdev) { 2018830662f6SVipul Pandya if (ipv6_chk_addr(&init_net, 2019830662f6SVipul Pandya (struct in6_addr *)peer_ip, 2020830662f6SVipul Pandya pdev, 1)) 2021830662f6SVipul Pandya break; 2022830662f6SVipul Pandya } 2023830662f6SVipul Pandya else 2024830662f6SVipul Pandya pdev = NULL; 2025830662f6SVipul Pandya 2026830662f6SVipul Pandya if (!pdev) { 2027830662f6SVipul Pandya err = -ENODEV; 2028830662f6SVipul Pandya goto out; 2029830662f6SVipul Pandya } 2030830662f6SVipul Pandya ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, 2031ac8e4c69SHariprasad S n, pdev, rt_tos2priority(tos)); 2032830662f6SVipul Pandya if (!ep->l2t) 2033830662f6SVipul Pandya goto out; 2034830662f6SVipul Pandya ep->mtu = pdev->mtu; 2035830662f6SVipul Pandya ep->tx_chan = cxgb4_port_chan(pdev); 2036963cab50SHariprasad S ep->smac_idx = cxgb4_tp_smt_idx(adapter_type, 2037963cab50SHariprasad S cxgb4_port_viid(pdev)); 2038830662f6SVipul Pandya step = cdev->rdev.lldi.ntxq / 2039830662f6SVipul Pandya cdev->rdev.lldi.nchan; 2040830662f6SVipul Pandya ep->txq_idx = cxgb4_port_idx(pdev) * step; 2041830662f6SVipul Pandya step = cdev->rdev.lldi.nrxq / 2042830662f6SVipul Pandya cdev->rdev.lldi.nchan; 2043830662f6SVipul Pandya ep->ctrlq_idx = cxgb4_port_idx(pdev); 2044830662f6SVipul Pandya ep->rss_qid = cdev->rdev.lldi.rxq_ids[ 2045830662f6SVipul Pandya cxgb4_port_idx(pdev) * step]; 2046b408ff28SHariprasad Shenai set_tcp_window(ep, (struct port_info *)netdev_priv(pdev)); 2047830662f6SVipul Pandya dev_put(pdev); 2048830662f6SVipul Pandya } else { 2049830662f6SVipul Pandya pdev = get_real_dev(n->dev); 2050830662f6SVipul Pandya ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, 2051830662f6SVipul Pandya n, pdev, 0); 2052830662f6SVipul Pandya if (!ep->l2t) 2053830662f6SVipul Pandya goto out; 2054830662f6SVipul Pandya ep->mtu = dst_mtu(dst); 205511b8e22dSSteve Wise ep->tx_chan = cxgb4_port_chan(pdev); 2056963cab50SHariprasad S ep->smac_idx = cxgb4_tp_smt_idx(adapter_type, 2057963cab50SHariprasad S cxgb4_port_viid(pdev)); 2058830662f6SVipul Pandya step = cdev->rdev.lldi.ntxq / 2059830662f6SVipul Pandya cdev->rdev.lldi.nchan; 206011b8e22dSSteve Wise ep->txq_idx = cxgb4_port_idx(pdev) * step; 206111b8e22dSSteve Wise ep->ctrlq_idx = cxgb4_port_idx(pdev); 2062830662f6SVipul Pandya step = cdev->rdev.lldi.nrxq / 2063830662f6SVipul Pandya cdev->rdev.lldi.nchan; 2064830662f6SVipul Pandya ep->rss_qid = cdev->rdev.lldi.rxq_ids[ 206511b8e22dSSteve Wise cxgb4_port_idx(pdev) * step]; 2066b408ff28SHariprasad Shenai set_tcp_window(ep, (struct port_info *)netdev_priv(pdev)); 2067830662f6SVipul Pandya 2068830662f6SVipul Pandya if (clear_mpa_v1) { 2069830662f6SVipul Pandya ep->retry_with_mpa_v1 = 0; 2070830662f6SVipul Pandya ep->tried_with_mpa_v1 = 0; 2071830662f6SVipul Pandya } 2072830662f6SVipul Pandya } 2073830662f6SVipul Pandya err = 0; 2074830662f6SVipul Pandya out: 2075830662f6SVipul Pandya rcu_read_unlock(); 2076830662f6SVipul Pandya 2077830662f6SVipul Pandya neigh_release(n); 2078830662f6SVipul Pandya 2079830662f6SVipul Pandya return err; 2080830662f6SVipul Pandya } 2081830662f6SVipul Pandya 2082793dad94SVipul Pandya static int c4iw_reconnect(struct c4iw_ep *ep) 2083793dad94SVipul Pandya { 2084793dad94SVipul Pandya int err = 0; 20854a740838SHariprasad S int size = 0; 208624d44a39SSteve Wise struct sockaddr_in *laddr = (struct sockaddr_in *) 2087170003c8SSteve Wise &ep->com.cm_id->m_local_addr; 208824d44a39SSteve Wise struct sockaddr_in *raddr = (struct sockaddr_in *) 2089170003c8SSteve Wise &ep->com.cm_id->m_remote_addr; 2090830662f6SVipul Pandya struct sockaddr_in6 *laddr6 = (struct sockaddr_in6 *) 2091170003c8SSteve Wise &ep->com.cm_id->m_local_addr; 2092830662f6SVipul Pandya struct sockaddr_in6 *raddr6 = (struct sockaddr_in6 *) 2093170003c8SSteve Wise &ep->com.cm_id->m_remote_addr; 2094830662f6SVipul Pandya int iptype; 2095830662f6SVipul Pandya __u8 *ra; 2096793dad94SVipul Pandya 2097793dad94SVipul Pandya PDBG("%s qp %p cm_id %p\n", __func__, ep->com.qp, ep->com.cm_id); 2098793dad94SVipul Pandya init_timer(&ep->timer); 2099093108cbSHariprasad S c4iw_init_wr_wait(&ep->com.wr_wait); 2100793dad94SVipul Pandya 21014a740838SHariprasad S /* When MPA revision is different on nodes, the node with MPA_rev=2 21024a740838SHariprasad S * tries to reconnect with MPA_rev 1 for the same EP through 21034a740838SHariprasad S * c4iw_reconnect(), where the same EP is assigned with new tid for 21044a740838SHariprasad S * further connection establishment. As we are using the same EP pointer 21054a740838SHariprasad S * for reconnect, few skbs are used during the previous c4iw_connect(), 21064a740838SHariprasad S * which leaves the EP with inadequate skbs for further 21074a740838SHariprasad S * c4iw_reconnect(), Further causing an assert BUG_ON() due to empty 21084a740838SHariprasad S * skb_list() during peer_abort(). Allocate skbs which is already used. 21094a740838SHariprasad S */ 21104a740838SHariprasad S size = (CN_MAX_CON_BUF - skb_queue_len(&ep->com.ep_skb_list)); 21114a740838SHariprasad S if (alloc_ep_skb_list(&ep->com.ep_skb_list, size)) { 21124a740838SHariprasad S err = -ENOMEM; 21134a740838SHariprasad S goto fail1; 21144a740838SHariprasad S } 21154a740838SHariprasad S 2116793dad94SVipul Pandya /* 2117793dad94SVipul Pandya * Allocate an active TID to initiate a TCP connection. 2118793dad94SVipul Pandya */ 2119793dad94SVipul Pandya ep->atid = cxgb4_alloc_atid(ep->com.dev->rdev.lldi.tids, ep); 2120793dad94SVipul Pandya if (ep->atid == -1) { 2121793dad94SVipul Pandya pr_err("%s - cannot alloc atid.\n", __func__); 2122793dad94SVipul Pandya err = -ENOMEM; 2123793dad94SVipul Pandya goto fail2; 2124793dad94SVipul Pandya } 2125793dad94SVipul Pandya insert_handle(ep->com.dev, &ep->com.dev->atid_idr, ep, ep->atid); 2126793dad94SVipul Pandya 2127793dad94SVipul Pandya /* find a route */ 2128170003c8SSteve Wise if (ep->com.cm_id->m_local_addr.ss_family == AF_INET) { 2129804c2f3eSVarun Prakash ep->dst = cxgb_find_route(&ep->com.dev->rdev.lldi, get_real_dev, 2130804c2f3eSVarun Prakash laddr->sin_addr.s_addr, 2131804c2f3eSVarun Prakash raddr->sin_addr.s_addr, 2132804c2f3eSVarun Prakash laddr->sin_port, 2133ac8e4c69SHariprasad S raddr->sin_port, ep->com.cm_id->tos); 2134830662f6SVipul Pandya iptype = 4; 2135830662f6SVipul Pandya ra = (__u8 *)&raddr->sin_addr; 2136830662f6SVipul Pandya } else { 213795554761SVarun Prakash ep->dst = cxgb_find_route6(&ep->com.dev->rdev.lldi, 213895554761SVarun Prakash get_real_dev, 213995554761SVarun Prakash laddr6->sin6_addr.s6_addr, 2140830662f6SVipul Pandya raddr6->sin6_addr.s6_addr, 214195554761SVarun Prakash laddr6->sin6_port, 214295554761SVarun Prakash raddr6->sin6_port, 0, 2143830662f6SVipul Pandya raddr6->sin6_scope_id); 2144830662f6SVipul Pandya iptype = 6; 2145830662f6SVipul Pandya ra = (__u8 *)&raddr6->sin6_addr; 2146830662f6SVipul Pandya } 2147830662f6SVipul Pandya if (!ep->dst) { 2148793dad94SVipul Pandya pr_err("%s - cannot find route.\n", __func__); 2149793dad94SVipul Pandya err = -EHOSTUNREACH; 2150793dad94SVipul Pandya goto fail3; 2151793dad94SVipul Pandya } 2152963cab50SHariprasad S err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, false, 2153ac8e4c69SHariprasad S ep->com.dev->rdev.lldi.adapter_type, 2154ac8e4c69SHariprasad S ep->com.cm_id->tos); 2155830662f6SVipul Pandya if (err) { 2156793dad94SVipul Pandya pr_err("%s - cannot alloc l2e.\n", __func__); 2157793dad94SVipul Pandya goto fail4; 2158793dad94SVipul Pandya } 2159793dad94SVipul Pandya 2160793dad94SVipul Pandya PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n", 2161793dad94SVipul Pandya __func__, ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid, 2162793dad94SVipul Pandya ep->l2t->idx); 2163793dad94SVipul Pandya 2164793dad94SVipul Pandya state_set(&ep->com, CONNECTING); 2165ac8e4c69SHariprasad S ep->tos = ep->com.cm_id->tos; 2166793dad94SVipul Pandya 2167793dad94SVipul Pandya /* send connect request to rnic */ 2168793dad94SVipul Pandya err = send_connect(ep); 2169793dad94SVipul Pandya if (!err) 2170793dad94SVipul Pandya goto out; 2171793dad94SVipul Pandya 2172793dad94SVipul Pandya cxgb4_l2t_release(ep->l2t); 2173793dad94SVipul Pandya fail4: 2174793dad94SVipul Pandya dst_release(ep->dst); 2175793dad94SVipul Pandya fail3: 2176793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid); 2177793dad94SVipul Pandya cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid); 2178793dad94SVipul Pandya fail2: 2179793dad94SVipul Pandya /* 2180793dad94SVipul Pandya * remember to send notification to upper layer. 2181793dad94SVipul Pandya * We are in here so the upper layer is not aware that this is 2182793dad94SVipul Pandya * re-connect attempt and so, upper layer is still waiting for 2183793dad94SVipul Pandya * response of 1st connect request. 2184793dad94SVipul Pandya */ 2185793dad94SVipul Pandya connect_reply_upcall(ep, -ECONNRESET); 21864a740838SHariprasad S fail1: 2187793dad94SVipul Pandya c4iw_put_ep(&ep->com); 2188793dad94SVipul Pandya out: 2189793dad94SVipul Pandya return err; 2190793dad94SVipul Pandya } 2191793dad94SVipul Pandya 2192cfdda9d7SSteve Wise static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2193cfdda9d7SSteve Wise { 2194cfdda9d7SSteve Wise struct c4iw_ep *ep; 2195cfdda9d7SSteve Wise struct cpl_act_open_rpl *rpl = cplhdr(skb); 21966c53e938SHariprasad Shenai unsigned int atid = TID_TID_G(AOPEN_ATID_G( 2197cfdda9d7SSteve Wise ntohl(rpl->atid_status))); 2198cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 21996c53e938SHariprasad Shenai int status = AOPEN_STATUS_G(ntohl(rpl->atid_status)); 2200830662f6SVipul Pandya struct sockaddr_in *la; 2201830662f6SVipul Pandya struct sockaddr_in *ra; 2202830662f6SVipul Pandya struct sockaddr_in6 *la6; 2203830662f6SVipul Pandya struct sockaddr_in6 *ra6; 2204caa6c9f2SHariprasad S int ret = 0; 2205cfdda9d7SSteve Wise 2206cfdda9d7SSteve Wise ep = lookup_atid(t, atid); 2207170003c8SSteve Wise la = (struct sockaddr_in *)&ep->com.local_addr; 2208170003c8SSteve Wise ra = (struct sockaddr_in *)&ep->com.remote_addr; 2209170003c8SSteve Wise la6 = (struct sockaddr_in6 *)&ep->com.local_addr; 2210170003c8SSteve Wise ra6 = (struct sockaddr_in6 *)&ep->com.remote_addr; 2211cfdda9d7SSteve Wise 2212cfdda9d7SSteve Wise PDBG("%s ep %p atid %u status %u errno %d\n", __func__, ep, atid, 2213cfdda9d7SSteve Wise status, status2errno(status)); 2214cfdda9d7SSteve Wise 2215b65eef0aSVarun Prakash if (cxgb_is_neg_adv(status)) { 2216179d03bbSHariprasad S PDBG("%s Connection problems for atid %u status %u (%s)\n", 2217179d03bbSHariprasad S __func__, atid, status, neg_adv_str(status)); 2218179d03bbSHariprasad S ep->stats.connect_neg_adv++; 2219179d03bbSHariprasad S mutex_lock(&dev->rdev.stats.lock); 2220179d03bbSHariprasad S dev->rdev.stats.neg_adv++; 2221179d03bbSHariprasad S mutex_unlock(&dev->rdev.stats.lock); 2222cfdda9d7SSteve Wise return 0; 2223cfdda9d7SSteve Wise } 2224cfdda9d7SSteve Wise 2225793dad94SVipul Pandya set_bit(ACT_OPEN_RPL, &ep->com.history); 2226793dad94SVipul Pandya 2227d716a2a0SVipul Pandya /* 2228d716a2a0SVipul Pandya * Log interesting failures. 2229d716a2a0SVipul Pandya */ 2230d716a2a0SVipul Pandya switch (status) { 2231d716a2a0SVipul Pandya case CPL_ERR_CONN_RESET: 2232d716a2a0SVipul Pandya case CPL_ERR_CONN_TIMEDOUT: 2233d716a2a0SVipul Pandya break; 22345be78ee9SVipul Pandya case CPL_ERR_TCAM_FULL: 22355be78ee9SVipul Pandya mutex_lock(&dev->rdev.stats.lock); 2236830662f6SVipul Pandya dev->rdev.stats.tcam_full++; 22375be78ee9SVipul Pandya mutex_unlock(&dev->rdev.stats.lock); 2238830662f6SVipul Pandya if (ep->com.local_addr.ss_family == AF_INET && 2239830662f6SVipul Pandya dev->rdev.lldi.enable_fw_ofld_conn) { 2240caa6c9f2SHariprasad S ret = send_fw_act_open_req(ep, TID_TID_G(AOPEN_ATID_G( 2241793dad94SVipul Pandya ntohl(rpl->atid_status)))); 2242caa6c9f2SHariprasad S if (ret) 2243caa6c9f2SHariprasad S goto fail; 22445be78ee9SVipul Pandya return 0; 2245793dad94SVipul Pandya } 2246793dad94SVipul Pandya break; 2247793dad94SVipul Pandya case CPL_ERR_CONN_EXIST: 2248793dad94SVipul Pandya if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) { 2249793dad94SVipul Pandya set_bit(ACT_RETRY_INUSE, &ep->com.history); 225084cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 225184cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 225284cc6ac6SHariprasad S (struct sockaddr_in6 *) 2253170003c8SSteve Wise &ep->com.local_addr; 225484cc6ac6SHariprasad S cxgb4_clip_release( 225584cc6ac6SHariprasad S ep->com.dev->rdev.lldi.ports[0], 225684cc6ac6SHariprasad S (const u32 *) 225784cc6ac6SHariprasad S &sin6->sin6_addr.s6_addr, 1); 225884cc6ac6SHariprasad S } 2259793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, 2260793dad94SVipul Pandya atid); 2261793dad94SVipul Pandya cxgb4_free_atid(t, atid); 2262793dad94SVipul Pandya dst_release(ep->dst); 2263793dad94SVipul Pandya cxgb4_l2t_release(ep->l2t); 2264793dad94SVipul Pandya c4iw_reconnect(ep); 2265793dad94SVipul Pandya return 0; 2266793dad94SVipul Pandya } 22675be78ee9SVipul Pandya break; 2268d716a2a0SVipul Pandya default: 2269830662f6SVipul Pandya if (ep->com.local_addr.ss_family == AF_INET) { 2270830662f6SVipul Pandya pr_info("Active open failure - atid %u status %u errno %d %pI4:%u->%pI4:%u\n", 2271d716a2a0SVipul Pandya atid, status, status2errno(status), 2272830662f6SVipul Pandya &la->sin_addr.s_addr, ntohs(la->sin_port), 2273830662f6SVipul Pandya &ra->sin_addr.s_addr, ntohs(ra->sin_port)); 2274830662f6SVipul Pandya } else { 2275830662f6SVipul Pandya pr_info("Active open failure - atid %u status %u errno %d %pI6:%u->%pI6:%u\n", 2276830662f6SVipul Pandya atid, status, status2errno(status), 2277830662f6SVipul Pandya la6->sin6_addr.s6_addr, ntohs(la6->sin6_port), 2278830662f6SVipul Pandya ra6->sin6_addr.s6_addr, ntohs(ra6->sin6_port)); 2279830662f6SVipul Pandya } 2280d716a2a0SVipul Pandya break; 2281d716a2a0SVipul Pandya } 2282d716a2a0SVipul Pandya 2283caa6c9f2SHariprasad S fail: 2284cfdda9d7SSteve Wise connect_reply_upcall(ep, status2errno(status)); 2285cfdda9d7SSteve Wise state_set(&ep->com, DEAD); 2286cfdda9d7SSteve Wise 228784cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 228884cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 2289170003c8SSteve Wise (struct sockaddr_in6 *)&ep->com.local_addr; 229084cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 229184cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 229284cc6ac6SHariprasad S } 2293cfdda9d7SSteve Wise if (status && act_open_has_tid(status)) 2294cfdda9d7SSteve Wise cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, GET_TID(rpl)); 2295cfdda9d7SSteve Wise 2296793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, atid); 2297cfdda9d7SSteve Wise cxgb4_free_atid(t, atid); 2298cfdda9d7SSteve Wise dst_release(ep->dst); 2299cfdda9d7SSteve Wise cxgb4_l2t_release(ep->l2t); 2300cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 2301cfdda9d7SSteve Wise 2302cfdda9d7SSteve Wise return 0; 2303cfdda9d7SSteve Wise } 2304cfdda9d7SSteve Wise 2305cfdda9d7SSteve Wise static int pass_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2306cfdda9d7SSteve Wise { 2307cfdda9d7SSteve Wise struct cpl_pass_open_rpl *rpl = cplhdr(skb); 2308cfdda9d7SSteve Wise unsigned int stid = GET_TID(rpl); 2309f86fac79SHariprasad S struct c4iw_listen_ep *ep = get_ep_from_stid(dev, stid); 2310cfdda9d7SSteve Wise 2311cfdda9d7SSteve Wise if (!ep) { 23121cab775cSVipul Pandya PDBG("%s stid %d lookup failure!\n", __func__, stid); 23131cab775cSVipul Pandya goto out; 2314cfdda9d7SSteve Wise } 2315cfdda9d7SSteve Wise PDBG("%s ep %p status %d error %d\n", __func__, ep, 2316cfdda9d7SSteve Wise rpl->status, status2errno(rpl->status)); 2317d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, status2errno(rpl->status)); 2318f86fac79SHariprasad S c4iw_put_ep(&ep->com); 23191cab775cSVipul Pandya out: 2320cfdda9d7SSteve Wise return 0; 2321cfdda9d7SSteve Wise } 2322cfdda9d7SSteve Wise 2323cfdda9d7SSteve Wise static int close_listsrv_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2324cfdda9d7SSteve Wise { 2325cfdda9d7SSteve Wise struct cpl_close_listsvr_rpl *rpl = cplhdr(skb); 2326cfdda9d7SSteve Wise unsigned int stid = GET_TID(rpl); 2327f86fac79SHariprasad S struct c4iw_listen_ep *ep = get_ep_from_stid(dev, stid); 2328cfdda9d7SSteve Wise 2329cfdda9d7SSteve Wise PDBG("%s ep %p\n", __func__, ep); 2330d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, status2errno(rpl->status)); 2331f86fac79SHariprasad S c4iw_put_ep(&ep->com); 2332cfdda9d7SSteve Wise return 0; 2333cfdda9d7SSteve Wise } 2334cfdda9d7SSteve Wise 23359dec900cSHariprasad S static int accept_cr(struct c4iw_ep *ep, struct sk_buff *skb, 2336cfdda9d7SSteve Wise struct cpl_pass_accept_req *req) 2337cfdda9d7SSteve Wise { 2338cfdda9d7SSteve Wise struct cpl_pass_accept_rpl *rpl; 2339cfdda9d7SSteve Wise unsigned int mtu_idx; 2340cfdda9d7SSteve Wise u64 opt0; 2341cfdda9d7SSteve Wise u32 opt2; 2342cfdda9d7SSteve Wise int wscale; 234392e7ae71SHariprasad Shenai struct cpl_t5_pass_accept_rpl *rpl5 = NULL; 2344b408ff28SHariprasad Shenai int win; 2345963cab50SHariprasad S enum chip_type adapter_type = ep->com.dev->rdev.lldi.adapter_type; 2346cfdda9d7SSteve Wise 2347cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2348cfdda9d7SSteve Wise BUG_ON(skb_cloned(skb)); 234992e7ae71SHariprasad Shenai 2350cfdda9d7SSteve Wise skb_get(skb); 235192e7ae71SHariprasad Shenai rpl = cplhdr(skb); 2352963cab50SHariprasad S if (!is_t4(adapter_type)) { 235392e7ae71SHariprasad Shenai skb_trim(skb, roundup(sizeof(*rpl5), 16)); 235492e7ae71SHariprasad Shenai rpl5 = (void *)rpl; 235592e7ae71SHariprasad Shenai INIT_TP_WR(rpl5, ep->hwtid); 235692e7ae71SHariprasad Shenai } else { 235792e7ae71SHariprasad Shenai skb_trim(skb, sizeof(*rpl)); 235892e7ae71SHariprasad Shenai INIT_TP_WR(rpl, ep->hwtid); 235992e7ae71SHariprasad Shenai } 236092e7ae71SHariprasad Shenai OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_PASS_ACCEPT_RPL, 236192e7ae71SHariprasad Shenai ep->hwtid)); 236292e7ae71SHariprasad Shenai 236344c6d069SVarun Prakash cxgb_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, 236404524a47SHariprasad S enable_tcp_timestamps && req->tcpopt.tstamp, 236544c6d069SVarun Prakash (ep->com.remote_addr.ss_family == AF_INET) ? 0 : 1); 2366cfdda9d7SSteve Wise wscale = compute_wscale(rcv_win); 2367b408ff28SHariprasad Shenai 2368b408ff28SHariprasad Shenai /* 2369b408ff28SHariprasad Shenai * Specify the largest window that will fit in opt0. The 2370b408ff28SHariprasad Shenai * remainder will be specified in the rx_data_ack. 2371b408ff28SHariprasad Shenai */ 2372b408ff28SHariprasad Shenai win = ep->rcv_win >> 10; 2373d7990b0cSAnish Bhatt if (win > RCV_BUFSIZ_M) 2374d7990b0cSAnish Bhatt win = RCV_BUFSIZ_M; 23756c53e938SHariprasad Shenai opt0 = (nocong ? NO_CONG_F : 0) | 2376d7990b0cSAnish Bhatt KEEP_ALIVE_F | 23776c53e938SHariprasad Shenai DELACK_F | 2378d7990b0cSAnish Bhatt WND_SCALE_V(wscale) | 2379d7990b0cSAnish Bhatt MSS_IDX_V(mtu_idx) | 2380d7990b0cSAnish Bhatt L2T_IDX_V(ep->l2t->idx) | 2381d7990b0cSAnish Bhatt TX_CHAN_V(ep->tx_chan) | 2382d7990b0cSAnish Bhatt SMAC_SEL_V(ep->smac_idx) | 23836c53e938SHariprasad Shenai DSCP_V(ep->tos >> 2) | 2384d7990b0cSAnish Bhatt ULP_MODE_V(ULP_MODE_TCPDDP) | 2385d7990b0cSAnish Bhatt RCV_BUFSIZ_V(win); 2386d7990b0cSAnish Bhatt opt2 = RX_CHANNEL_V(0) | 2387d7990b0cSAnish Bhatt RSS_QUEUE_VALID_F | RSS_QUEUE_V(ep->rss_qid); 2388cfdda9d7SSteve Wise 2389cfdda9d7SSteve Wise if (enable_tcp_timestamps && req->tcpopt.tstamp) 23906c53e938SHariprasad Shenai opt2 |= TSTAMPS_EN_F; 2391cfdda9d7SSteve Wise if (enable_tcp_sack && req->tcpopt.sack) 23926c53e938SHariprasad Shenai opt2 |= SACK_EN_F; 2393cfdda9d7SSteve Wise if (wscale && enable_tcp_window_scaling) 2394d7990b0cSAnish Bhatt opt2 |= WND_SCALE_EN_F; 23955be78ee9SVipul Pandya if (enable_ecn) { 23965be78ee9SVipul Pandya const struct tcphdr *tcph; 23975be78ee9SVipul Pandya u32 hlen = ntohl(req->hdr_len); 23985be78ee9SVipul Pandya 2399963cab50SHariprasad S if (CHELSIO_CHIP_VERSION(adapter_type) <= CHELSIO_T5) 2400cf7fe64aSHariprasad Shenai tcph = (const void *)(req + 1) + ETH_HDR_LEN_G(hlen) + 2401cf7fe64aSHariprasad Shenai IP_HDR_LEN_G(hlen); 2402963cab50SHariprasad S else 2403963cab50SHariprasad S tcph = (const void *)(req + 1) + 2404963cab50SHariprasad S T6_ETH_HDR_LEN_G(hlen) + T6_IP_HDR_LEN_G(hlen); 24055be78ee9SVipul Pandya if (tcph->ece && tcph->cwr) 24066c53e938SHariprasad Shenai opt2 |= CCTRL_ECN_V(1); 24075be78ee9SVipul Pandya } 2408963cab50SHariprasad S if (CHELSIO_CHIP_VERSION(adapter_type) > CHELSIO_T4) { 240992e7ae71SHariprasad Shenai u32 isn = (prandom_u32() & ~7UL) - 1; 2410d7990b0cSAnish Bhatt opt2 |= T5_OPT_2_VALID_F; 2411cf7fe64aSHariprasad Shenai opt2 |= CONG_CNTRL_V(CONG_ALG_TAHOE); 24120b741047SHariprasad S opt2 |= T5_ISS_F; 241392e7ae71SHariprasad Shenai rpl5 = (void *)rpl; 241492e7ae71SHariprasad Shenai memset(&rpl5->iss, 0, roundup(sizeof(*rpl5)-sizeof(*rpl), 16)); 241592e7ae71SHariprasad Shenai if (peer2peer) 241692e7ae71SHariprasad Shenai isn += 4; 241792e7ae71SHariprasad Shenai rpl5->iss = cpu_to_be32(isn); 241892e7ae71SHariprasad Shenai PDBG("%s iss %u\n", __func__, be32_to_cpu(rpl5->iss)); 241992e5011aSSteve Wise } 2420cfdda9d7SSteve Wise 2421cfdda9d7SSteve Wise rpl->opt0 = cpu_to_be64(opt0); 2422cfdda9d7SSteve Wise rpl->opt2 = cpu_to_be32(opt2); 2423d4f1a5c6SSteve Wise set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->ctrlq_idx); 24249dec900cSHariprasad S t4_set_arp_err_handler(skb, ep, pass_accept_rpl_arp_failure); 2425cfdda9d7SSteve Wise 24269dec900cSHariprasad S return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); 2427cfdda9d7SSteve Wise } 2428cfdda9d7SSteve Wise 2429830662f6SVipul Pandya static void reject_cr(struct c4iw_dev *dev, u32 hwtid, struct sk_buff *skb) 2430cfdda9d7SSteve Wise { 2431830662f6SVipul Pandya PDBG("%s c4iw_dev %p tid %u\n", __func__, dev, hwtid); 2432cfdda9d7SSteve Wise BUG_ON(skb_cloned(skb)); 2433cfdda9d7SSteve Wise skb_trim(skb, sizeof(struct cpl_tid_release)); 2434cfdda9d7SSteve Wise release_tid(&dev->rdev, hwtid, skb); 2435cfdda9d7SSteve Wise return; 2436cfdda9d7SSteve Wise } 2437cfdda9d7SSteve Wise 2438cfdda9d7SSteve Wise static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) 2439cfdda9d7SSteve Wise { 2440793dad94SVipul Pandya struct c4iw_ep *child_ep = NULL, *parent_ep; 2441cfdda9d7SSteve Wise struct cpl_pass_accept_req *req = cplhdr(skb); 24426c53e938SHariprasad Shenai unsigned int stid = PASS_OPEN_TID_G(ntohl(req->tos_stid)); 2443cfdda9d7SSteve Wise struct tid_info *t = dev->rdev.lldi.tids; 2444cfdda9d7SSteve Wise unsigned int hwtid = GET_TID(req); 2445cfdda9d7SSteve Wise struct dst_entry *dst; 2446830662f6SVipul Pandya __u8 local_ip[16], peer_ip[16]; 2447cfdda9d7SSteve Wise __be16 local_port, peer_port; 244884cc6ac6SHariprasad S struct sockaddr_in6 *sin6; 24493786cf18SDavid Miller int err; 24501cab775cSVipul Pandya u16 peer_mss = ntohs(req->tcpopt.mss); 2451830662f6SVipul Pandya int iptype; 245292e7ae71SHariprasad Shenai unsigned short hdrs; 2453ac8e4c69SHariprasad S u8 tos = PASS_OPEN_TOS_G(ntohl(req->tos_stid)); 2454cfdda9d7SSteve Wise 2455f86fac79SHariprasad S parent_ep = (struct c4iw_ep *)get_ep_from_stid(dev, stid); 24561cab775cSVipul Pandya if (!parent_ep) { 24571cab775cSVipul Pandya PDBG("%s connect request on invalid stid %d\n", __func__, stid); 24581cab775cSVipul Pandya goto reject; 24591cab775cSVipul Pandya } 24601cab775cSVipul Pandya 2461cfdda9d7SSteve Wise if (state_read(&parent_ep->com) != LISTEN) { 24626812faefSHariprasad S PDBG("%s - listening ep not in LISTEN\n", __func__); 2463cfdda9d7SSteve Wise goto reject; 2464cfdda9d7SSteve Wise } 2465cfdda9d7SSteve Wise 246685e42b04SVarun Prakash cxgb_get_4tuple(req, parent_ep->com.dev->rdev.lldi.adapter_type, 246785e42b04SVarun Prakash &iptype, local_ip, peer_ip, &local_port, &peer_port); 2468830662f6SVipul Pandya 2469cfdda9d7SSteve Wise /* Find output route */ 2470830662f6SVipul Pandya if (iptype == 4) { 2471830662f6SVipul Pandya PDBG("%s parent ep %p hwtid %u laddr %pI4 raddr %pI4 lport %d rport %d peer_mss %d\n" 2472830662f6SVipul Pandya , __func__, parent_ep, hwtid, 2473830662f6SVipul Pandya local_ip, peer_ip, ntohs(local_port), 2474830662f6SVipul Pandya ntohs(peer_port), peer_mss); 2475804c2f3eSVarun Prakash dst = cxgb_find_route(&dev->rdev.lldi, get_real_dev, 2476804c2f3eSVarun Prakash *(__be32 *)local_ip, *(__be32 *)peer_ip, 2477804c2f3eSVarun Prakash local_port, peer_port, tos); 2478830662f6SVipul Pandya } else { 2479830662f6SVipul Pandya PDBG("%s parent ep %p hwtid %u laddr %pI6 raddr %pI6 lport %d rport %d peer_mss %d\n" 2480830662f6SVipul Pandya , __func__, parent_ep, hwtid, 2481830662f6SVipul Pandya local_ip, peer_ip, ntohs(local_port), 2482830662f6SVipul Pandya ntohs(peer_port), peer_mss); 248395554761SVarun Prakash dst = cxgb_find_route6(&dev->rdev.lldi, get_real_dev, 248495554761SVarun Prakash local_ip, peer_ip, local_port, peer_port, 24856c53e938SHariprasad Shenai PASS_OPEN_TOS_G(ntohl(req->tos_stid)), 2486830662f6SVipul Pandya ((struct sockaddr_in6 *) 2487830662f6SVipul Pandya &parent_ep->com.local_addr)->sin6_scope_id); 2488830662f6SVipul Pandya } 2489830662f6SVipul Pandya if (!dst) { 2490cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - failed to find dst entry!\n", 2491cfdda9d7SSteve Wise __func__); 2492cfdda9d7SSteve Wise goto reject; 2493cfdda9d7SSteve Wise } 2494cfdda9d7SSteve Wise 2495cfdda9d7SSteve Wise child_ep = alloc_ep(sizeof(*child_ep), GFP_KERNEL); 2496cfdda9d7SSteve Wise if (!child_ep) { 2497cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - failed to allocate ep entry!\n", 2498cfdda9d7SSteve Wise __func__); 2499cfdda9d7SSteve Wise dst_release(dst); 2500cfdda9d7SSteve Wise goto reject; 2501cfdda9d7SSteve Wise } 25023786cf18SDavid Miller 2503963cab50SHariprasad S err = import_ep(child_ep, iptype, peer_ip, dst, dev, false, 2504ac8e4c69SHariprasad S parent_ep->com.dev->rdev.lldi.adapter_type, tos); 25053786cf18SDavid Miller if (err) { 25063786cf18SDavid Miller printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n", 25073786cf18SDavid Miller __func__); 25083786cf18SDavid Miller dst_release(dst); 25093786cf18SDavid Miller kfree(child_ep); 25103786cf18SDavid Miller goto reject; 25113786cf18SDavid Miller } 25123786cf18SDavid Miller 251392e7ae71SHariprasad Shenai hdrs = sizeof(struct iphdr) + sizeof(struct tcphdr) + 251492e7ae71SHariprasad Shenai ((enable_tcp_timestamps && req->tcpopt.tstamp) ? 12 : 0); 251592e7ae71SHariprasad Shenai if (peer_mss && child_ep->mtu > (peer_mss + hdrs)) 251692e7ae71SHariprasad Shenai child_ep->mtu = peer_mss + hdrs; 25171cab775cSVipul Pandya 25184a740838SHariprasad S skb_queue_head_init(&child_ep->com.ep_skb_list); 25194a740838SHariprasad S if (alloc_ep_skb_list(&child_ep->com.ep_skb_list, CN_MAX_CON_BUF)) 25204a740838SHariprasad S goto fail; 25214a740838SHariprasad S 2522cfdda9d7SSteve Wise state_set(&child_ep->com, CONNECTING); 2523cfdda9d7SSteve Wise child_ep->com.dev = dev; 2524cfdda9d7SSteve Wise child_ep->com.cm_id = NULL; 25255b6b8fe6SSteve Wise 2526830662f6SVipul Pandya if (iptype == 4) { 2527830662f6SVipul Pandya struct sockaddr_in *sin = (struct sockaddr_in *) 2528170003c8SSteve Wise &child_ep->com.local_addr; 25295b6b8fe6SSteve Wise 2530830662f6SVipul Pandya sin->sin_family = PF_INET; 2531830662f6SVipul Pandya sin->sin_port = local_port; 2532830662f6SVipul Pandya sin->sin_addr.s_addr = *(__be32 *)local_ip; 25335b6b8fe6SSteve Wise 25345b6b8fe6SSteve Wise sin = (struct sockaddr_in *)&child_ep->com.local_addr; 25355b6b8fe6SSteve Wise sin->sin_family = PF_INET; 25365b6b8fe6SSteve Wise sin->sin_port = ((struct sockaddr_in *) 25375b6b8fe6SSteve Wise &parent_ep->com.local_addr)->sin_port; 25385b6b8fe6SSteve Wise sin->sin_addr.s_addr = *(__be32 *)local_ip; 25395b6b8fe6SSteve Wise 2540170003c8SSteve Wise sin = (struct sockaddr_in *)&child_ep->com.remote_addr; 2541830662f6SVipul Pandya sin->sin_family = PF_INET; 2542830662f6SVipul Pandya sin->sin_port = peer_port; 2543830662f6SVipul Pandya sin->sin_addr.s_addr = *(__be32 *)peer_ip; 2544830662f6SVipul Pandya } else { 2545170003c8SSteve Wise sin6 = (struct sockaddr_in6 *)&child_ep->com.local_addr; 2546830662f6SVipul Pandya sin6->sin6_family = PF_INET6; 2547830662f6SVipul Pandya sin6->sin6_port = local_port; 2548830662f6SVipul Pandya memcpy(sin6->sin6_addr.s6_addr, local_ip, 16); 25495b6b8fe6SSteve Wise 25505b6b8fe6SSteve Wise sin6 = (struct sockaddr_in6 *)&child_ep->com.local_addr; 25515b6b8fe6SSteve Wise sin6->sin6_family = PF_INET6; 25525b6b8fe6SSteve Wise sin6->sin6_port = ((struct sockaddr_in6 *) 25535b6b8fe6SSteve Wise &parent_ep->com.local_addr)->sin6_port; 25545b6b8fe6SSteve Wise memcpy(sin6->sin6_addr.s6_addr, local_ip, 16); 25555b6b8fe6SSteve Wise 2556170003c8SSteve Wise sin6 = (struct sockaddr_in6 *)&child_ep->com.remote_addr; 2557830662f6SVipul Pandya sin6->sin6_family = PF_INET6; 2558830662f6SVipul Pandya sin6->sin6_port = peer_port; 2559830662f6SVipul Pandya memcpy(sin6->sin6_addr.s6_addr, peer_ip, 16); 2560830662f6SVipul Pandya } 25615b6b8fe6SSteve Wise 2562cfdda9d7SSteve Wise c4iw_get_ep(&parent_ep->com); 2563cfdda9d7SSteve Wise child_ep->parent_ep = parent_ep; 2564ac8e4c69SHariprasad S child_ep->tos = tos; 2565cfdda9d7SSteve Wise child_ep->dst = dst; 2566cfdda9d7SSteve Wise child_ep->hwtid = hwtid; 2567cfdda9d7SSteve Wise 2568cfdda9d7SSteve Wise PDBG("%s tx_chan %u smac_idx %u rss_qid %u\n", __func__, 25693786cf18SDavid Miller child_ep->tx_chan, child_ep->smac_idx, child_ep->rss_qid); 2570cfdda9d7SSteve Wise 2571cfdda9d7SSteve Wise init_timer(&child_ep->timer); 2572cfdda9d7SSteve Wise cxgb4_insert_tid(t, child_ep, hwtid); 2573944661ddSHariprasad S insert_ep_tid(child_ep); 25749dec900cSHariprasad S if (accept_cr(child_ep, skb, req)) { 25759dec900cSHariprasad S c4iw_put_ep(&parent_ep->com); 25769dec900cSHariprasad S release_ep_resources(child_ep); 25779dec900cSHariprasad S } else { 2578793dad94SVipul Pandya set_bit(PASS_ACCEPT_REQ, &child_ep->com.history); 25799dec900cSHariprasad S } 258084cc6ac6SHariprasad S if (iptype == 6) { 2581170003c8SSteve Wise sin6 = (struct sockaddr_in6 *)&child_ep->com.local_addr; 258284cc6ac6SHariprasad S cxgb4_clip_get(child_ep->com.dev->rdev.lldi.ports[0], 258384cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 258484cc6ac6SHariprasad S } 2585cfdda9d7SSteve Wise goto out; 25864a740838SHariprasad S fail: 25874a740838SHariprasad S c4iw_put_ep(&child_ep->com); 2588cfdda9d7SSteve Wise reject: 2589830662f6SVipul Pandya reject_cr(dev, hwtid, skb); 2590f86fac79SHariprasad S if (parent_ep) 2591f86fac79SHariprasad S c4iw_put_ep(&parent_ep->com); 2592cfdda9d7SSteve Wise out: 2593cfdda9d7SSteve Wise return 0; 2594cfdda9d7SSteve Wise } 2595cfdda9d7SSteve Wise 2596cfdda9d7SSteve Wise static int pass_establish(struct c4iw_dev *dev, struct sk_buff *skb) 2597cfdda9d7SSteve Wise { 2598cfdda9d7SSteve Wise struct c4iw_ep *ep; 2599cfdda9d7SSteve Wise struct cpl_pass_establish *req = cplhdr(skb); 2600cfdda9d7SSteve Wise unsigned int tid = GET_TID(req); 2601fef4422dSHariprasad S int ret; 2602cfdda9d7SSteve Wise 2603944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 2604cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2605cfdda9d7SSteve Wise ep->snd_seq = be32_to_cpu(req->snd_isn); 2606cfdda9d7SSteve Wise ep->rcv_seq = be32_to_cpu(req->rcv_isn); 2607cfdda9d7SSteve Wise 26081cab775cSVipul Pandya PDBG("%s ep %p hwtid %u tcp_opt 0x%02x\n", __func__, ep, tid, 26091cab775cSVipul Pandya ntohs(req->tcp_opt)); 26101cab775cSVipul Pandya 2611cfdda9d7SSteve Wise set_emss(ep, ntohs(req->tcp_opt)); 2612cfdda9d7SSteve Wise 2613cfdda9d7SSteve Wise dst_confirm(ep->dst); 2614fef4422dSHariprasad S mutex_lock(&ep->com.mutex); 2615fef4422dSHariprasad S ep->com.state = MPA_REQ_WAIT; 2616cfdda9d7SSteve Wise start_ep_timer(ep); 2617793dad94SVipul Pandya set_bit(PASS_ESTAB, &ep->com.history); 26184a740838SHariprasad S ret = send_flowc(ep); 2619fef4422dSHariprasad S mutex_unlock(&ep->com.mutex); 2620fef4422dSHariprasad S if (ret) 2621fef4422dSHariprasad S c4iw_ep_disconnect(ep, 1, GFP_KERNEL); 2622944661ddSHariprasad S c4iw_put_ep(&ep->com); 2623cfdda9d7SSteve Wise 2624cfdda9d7SSteve Wise return 0; 2625cfdda9d7SSteve Wise } 2626cfdda9d7SSteve Wise 2627cfdda9d7SSteve Wise static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb) 2628cfdda9d7SSteve Wise { 2629cfdda9d7SSteve Wise struct cpl_peer_close *hdr = cplhdr(skb); 2630cfdda9d7SSteve Wise struct c4iw_ep *ep; 2631cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 2632cfdda9d7SSteve Wise int disconnect = 1; 2633cfdda9d7SSteve Wise int release = 0; 2634cfdda9d7SSteve Wise unsigned int tid = GET_TID(hdr); 26358da7e7a5SSteve Wise int ret; 2636cfdda9d7SSteve Wise 2637944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 2638944661ddSHariprasad S if (!ep) 2639944661ddSHariprasad S return 0; 2640944661ddSHariprasad S 2641cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2642cfdda9d7SSteve Wise dst_confirm(ep->dst); 2643cfdda9d7SSteve Wise 2644793dad94SVipul Pandya set_bit(PEER_CLOSE, &ep->com.history); 26452f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 2646cfdda9d7SSteve Wise switch (ep->com.state) { 2647cfdda9d7SSteve Wise case MPA_REQ_WAIT: 2648cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2649cfdda9d7SSteve Wise break; 2650cfdda9d7SSteve Wise case MPA_REQ_SENT: 2651cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2652cfdda9d7SSteve Wise connect_reply_upcall(ep, -ECONNRESET); 2653cfdda9d7SSteve Wise break; 2654cfdda9d7SSteve Wise case MPA_REQ_RCVD: 2655cfdda9d7SSteve Wise 2656cfdda9d7SSteve Wise /* 2657cfdda9d7SSteve Wise * We're gonna mark this puppy DEAD, but keep 2658cfdda9d7SSteve Wise * the reference on it until the ULP accepts or 2659cfdda9d7SSteve Wise * rejects the CR. Also wake up anyone waiting 2660cfdda9d7SSteve Wise * in rdma connection migration (see c4iw_accept_cr()). 2661cfdda9d7SSteve Wise */ 2662cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2663cfdda9d7SSteve Wise PDBG("waking up ep %p tid %u\n", ep, ep->hwtid); 2664d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 2665cfdda9d7SSteve Wise break; 2666cfdda9d7SSteve Wise case MPA_REP_SENT: 2667cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 2668cfdda9d7SSteve Wise PDBG("waking up ep %p tid %u\n", ep, ep->hwtid); 2669d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 2670cfdda9d7SSteve Wise break; 2671cfdda9d7SSteve Wise case FPDU_MODE: 2672ca5a2202SSteve Wise start_ep_timer(ep); 2673cfdda9d7SSteve Wise __state_set(&ep->com, CLOSING); 267430c95c2dSSteve Wise attrs.next_state = C4IW_QP_STATE_CLOSING; 26758da7e7a5SSteve Wise ret = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 267630c95c2dSSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 26778da7e7a5SSteve Wise if (ret != -ECONNRESET) { 2678cfdda9d7SSteve Wise peer_close_upcall(ep); 267930c95c2dSSteve Wise disconnect = 1; 26808da7e7a5SSteve Wise } 2681cfdda9d7SSteve Wise break; 2682cfdda9d7SSteve Wise case ABORTING: 2683cfdda9d7SSteve Wise disconnect = 0; 2684cfdda9d7SSteve Wise break; 2685cfdda9d7SSteve Wise case CLOSING: 2686cfdda9d7SSteve Wise __state_set(&ep->com, MORIBUND); 2687cfdda9d7SSteve Wise disconnect = 0; 2688cfdda9d7SSteve Wise break; 2689cfdda9d7SSteve Wise case MORIBUND: 2690b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 2691cfdda9d7SSteve Wise if (ep->com.cm_id && ep->com.qp) { 2692cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_IDLE; 2693cfdda9d7SSteve Wise c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 2694cfdda9d7SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 2695cfdda9d7SSteve Wise } 2696be13b2dfSSteve Wise close_complete_upcall(ep, 0); 2697cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 2698cfdda9d7SSteve Wise release = 1; 2699cfdda9d7SSteve Wise disconnect = 0; 2700cfdda9d7SSteve Wise break; 2701cfdda9d7SSteve Wise case DEAD: 2702cfdda9d7SSteve Wise disconnect = 0; 2703cfdda9d7SSteve Wise break; 2704cfdda9d7SSteve Wise default: 2705cfdda9d7SSteve Wise BUG_ON(1); 2706cfdda9d7SSteve Wise } 27072f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 2708cfdda9d7SSteve Wise if (disconnect) 2709cfdda9d7SSteve Wise c4iw_ep_disconnect(ep, 0, GFP_KERNEL); 2710cfdda9d7SSteve Wise if (release) 2711cfdda9d7SSteve Wise release_ep_resources(ep); 2712944661ddSHariprasad S c4iw_put_ep(&ep->com); 2713cfdda9d7SSteve Wise return 0; 2714cfdda9d7SSteve Wise } 2715cfdda9d7SSteve Wise 2716cfdda9d7SSteve Wise static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) 2717cfdda9d7SSteve Wise { 2718cfdda9d7SSteve Wise struct cpl_abort_req_rss *req = cplhdr(skb); 2719cfdda9d7SSteve Wise struct c4iw_ep *ep; 2720cfdda9d7SSteve Wise struct cpl_abort_rpl *rpl; 2721cfdda9d7SSteve Wise struct sk_buff *rpl_skb; 2722cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 2723cfdda9d7SSteve Wise int ret; 2724cfdda9d7SSteve Wise int release = 0; 2725cfdda9d7SSteve Wise unsigned int tid = GET_TID(req); 2726cfdda9d7SSteve Wise 2727944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 2728944661ddSHariprasad S if (!ep) 2729944661ddSHariprasad S return 0; 2730944661ddSHariprasad S 2731b65eef0aSVarun Prakash if (cxgb_is_neg_adv(req->status)) { 2732179d03bbSHariprasad S PDBG("%s Negative advice on abort- tid %u status %d (%s)\n", 2733179d03bbSHariprasad S __func__, ep->hwtid, req->status, 2734179d03bbSHariprasad S neg_adv_str(req->status)); 2735179d03bbSHariprasad S ep->stats.abort_neg_adv++; 2736179d03bbSHariprasad S mutex_lock(&dev->rdev.stats.lock); 2737179d03bbSHariprasad S dev->rdev.stats.neg_adv++; 2738179d03bbSHariprasad S mutex_unlock(&dev->rdev.stats.lock); 2739944661ddSHariprasad S goto deref_ep; 2740cfdda9d7SSteve Wise } 2741cfdda9d7SSteve Wise PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid, 2742cfdda9d7SSteve Wise ep->com.state); 2743793dad94SVipul Pandya set_bit(PEER_ABORT, &ep->com.history); 27442f5b48c3SSteve Wise 27452f5b48c3SSteve Wise /* 27462f5b48c3SSteve Wise * Wake up any threads in rdma_init() or rdma_fini(). 2747d2fe99e8SKumar Sanghvi * However, this is not needed if com state is just 2748d2fe99e8SKumar Sanghvi * MPA_REQ_SENT 27492f5b48c3SSteve Wise */ 2750d2fe99e8SKumar Sanghvi if (ep->com.state != MPA_REQ_SENT) 2751d9594d99SSteve Wise c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 27522f5b48c3SSteve Wise 27532f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 2754cfdda9d7SSteve Wise switch (ep->com.state) { 2755cfdda9d7SSteve Wise case CONNECTING: 27569dec900cSHariprasad S c4iw_put_ep(&ep->parent_ep->com); 2757cfdda9d7SSteve Wise break; 2758cfdda9d7SSteve Wise case MPA_REQ_WAIT: 2759b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 2760cfdda9d7SSteve Wise break; 2761cfdda9d7SSteve Wise case MPA_REQ_SENT: 2762b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 2763fe7e0a4dSVipul Pandya if (mpa_rev == 1 || (mpa_rev == 2 && ep->tried_with_mpa_v1)) 2764cfdda9d7SSteve Wise connect_reply_upcall(ep, -ECONNRESET); 2765d2fe99e8SKumar Sanghvi else { 2766d2fe99e8SKumar Sanghvi /* 2767d2fe99e8SKumar Sanghvi * we just don't send notification upwards because we 2768d2fe99e8SKumar Sanghvi * want to retry with mpa_v1 without upper layers even 2769d2fe99e8SKumar Sanghvi * knowing it. 2770d2fe99e8SKumar Sanghvi * 2771d2fe99e8SKumar Sanghvi * do some housekeeping so as to re-initiate the 2772d2fe99e8SKumar Sanghvi * connection 2773d2fe99e8SKumar Sanghvi */ 2774d2fe99e8SKumar Sanghvi PDBG("%s: mpa_rev=%d. Retrying with mpav1\n", __func__, 2775d2fe99e8SKumar Sanghvi mpa_rev); 2776d2fe99e8SKumar Sanghvi ep->retry_with_mpa_v1 = 1; 2777d2fe99e8SKumar Sanghvi } 2778cfdda9d7SSteve Wise break; 2779cfdda9d7SSteve Wise case MPA_REP_SENT: 2780cfdda9d7SSteve Wise break; 2781cfdda9d7SSteve Wise case MPA_REQ_RCVD: 2782cfdda9d7SSteve Wise break; 2783cfdda9d7SSteve Wise case MORIBUND: 2784cfdda9d7SSteve Wise case CLOSING: 2785ca5a2202SSteve Wise stop_ep_timer(ep); 2786cfdda9d7SSteve Wise /*FALLTHROUGH*/ 2787cfdda9d7SSteve Wise case FPDU_MODE: 2788cfdda9d7SSteve Wise if (ep->com.cm_id && ep->com.qp) { 2789cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_ERROR; 2790cfdda9d7SSteve Wise ret = c4iw_modify_qp(ep->com.qp->rhp, 2791cfdda9d7SSteve Wise ep->com.qp, C4IW_QP_ATTR_NEXT_STATE, 2792cfdda9d7SSteve Wise &attrs, 1); 2793cfdda9d7SSteve Wise if (ret) 2794cfdda9d7SSteve Wise printk(KERN_ERR MOD 2795cfdda9d7SSteve Wise "%s - qp <- error failed!\n", 2796cfdda9d7SSteve Wise __func__); 2797cfdda9d7SSteve Wise } 2798cfdda9d7SSteve Wise peer_abort_upcall(ep); 2799cfdda9d7SSteve Wise break; 2800cfdda9d7SSteve Wise case ABORTING: 2801cfdda9d7SSteve Wise break; 2802cfdda9d7SSteve Wise case DEAD: 2803cfdda9d7SSteve Wise PDBG("%s PEER_ABORT IN DEAD STATE!!!!\n", __func__); 28042f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 2805944661ddSHariprasad S goto deref_ep; 2806cfdda9d7SSteve Wise default: 2807cfdda9d7SSteve Wise BUG_ON(1); 2808cfdda9d7SSteve Wise break; 2809cfdda9d7SSteve Wise } 2810cfdda9d7SSteve Wise dst_confirm(ep->dst); 2811cfdda9d7SSteve Wise if (ep->com.state != ABORTING) { 2812cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 2813d2fe99e8SKumar Sanghvi /* we don't release if we want to retry with mpa_v1 */ 2814d2fe99e8SKumar Sanghvi if (!ep->retry_with_mpa_v1) 2815cfdda9d7SSteve Wise release = 1; 2816cfdda9d7SSteve Wise } 28172f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 2818cfdda9d7SSteve Wise 28194a740838SHariprasad S rpl_skb = skb_dequeue(&ep->com.ep_skb_list); 28204a740838SHariprasad S if (WARN_ON(!rpl_skb)) { 2821cfdda9d7SSteve Wise release = 1; 2822cfdda9d7SSteve Wise goto out; 2823cfdda9d7SSteve Wise } 2824cfdda9d7SSteve Wise set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); 2825cfdda9d7SSteve Wise rpl = (struct cpl_abort_rpl *) skb_put(rpl_skb, sizeof(*rpl)); 2826cfdda9d7SSteve Wise INIT_TP_WR(rpl, ep->hwtid); 2827cfdda9d7SSteve Wise OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_RPL, ep->hwtid)); 2828cfdda9d7SSteve Wise rpl->cmd = CPL_ABORT_NO_RST; 2829cfdda9d7SSteve Wise c4iw_ofld_send(&ep->com.dev->rdev, rpl_skb); 2830cfdda9d7SSteve Wise out: 2831cfdda9d7SSteve Wise if (release) 2832cfdda9d7SSteve Wise release_ep_resources(ep); 2833fe7e0a4dSVipul Pandya else if (ep->retry_with_mpa_v1) { 283484cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 283584cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 283684cc6ac6SHariprasad S (struct sockaddr_in6 *) 2837170003c8SSteve Wise &ep->com.local_addr; 283884cc6ac6SHariprasad S cxgb4_clip_release( 283984cc6ac6SHariprasad S ep->com.dev->rdev.lldi.ports[0], 284084cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 284184cc6ac6SHariprasad S 1); 284284cc6ac6SHariprasad S } 2843fe7e0a4dSVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->hwtid_idr, ep->hwtid); 2844d2fe99e8SKumar Sanghvi cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid); 2845d2fe99e8SKumar Sanghvi dst_release(ep->dst); 2846d2fe99e8SKumar Sanghvi cxgb4_l2t_release(ep->l2t); 2847d2fe99e8SKumar Sanghvi c4iw_reconnect(ep); 2848d2fe99e8SKumar Sanghvi } 2849d2fe99e8SKumar Sanghvi 2850944661ddSHariprasad S deref_ep: 2851944661ddSHariprasad S c4iw_put_ep(&ep->com); 2852944661ddSHariprasad S /* Dereferencing ep, referenced in peer_abort_intr() */ 2853944661ddSHariprasad S c4iw_put_ep(&ep->com); 2854cfdda9d7SSteve Wise return 0; 2855cfdda9d7SSteve Wise } 2856cfdda9d7SSteve Wise 2857cfdda9d7SSteve Wise static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 2858cfdda9d7SSteve Wise { 2859cfdda9d7SSteve Wise struct c4iw_ep *ep; 2860cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 2861cfdda9d7SSteve Wise struct cpl_close_con_rpl *rpl = cplhdr(skb); 2862cfdda9d7SSteve Wise int release = 0; 2863cfdda9d7SSteve Wise unsigned int tid = GET_TID(rpl); 2864cfdda9d7SSteve Wise 2865944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 2866944661ddSHariprasad S if (!ep) 2867944661ddSHariprasad S return 0; 2868cfdda9d7SSteve Wise 2869cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2870cfdda9d7SSteve Wise BUG_ON(!ep); 2871cfdda9d7SSteve Wise 2872cfdda9d7SSteve Wise /* The cm_id may be null if we failed to connect */ 28732f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 28749ca6f7cfSHariprasad S set_bit(CLOSE_CON_RPL, &ep->com.history); 2875cfdda9d7SSteve Wise switch (ep->com.state) { 2876cfdda9d7SSteve Wise case CLOSING: 2877cfdda9d7SSteve Wise __state_set(&ep->com, MORIBUND); 2878cfdda9d7SSteve Wise break; 2879cfdda9d7SSteve Wise case MORIBUND: 2880b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 2881cfdda9d7SSteve Wise if ((ep->com.cm_id) && (ep->com.qp)) { 2882cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_IDLE; 2883cfdda9d7SSteve Wise c4iw_modify_qp(ep->com.qp->rhp, 2884cfdda9d7SSteve Wise ep->com.qp, 2885cfdda9d7SSteve Wise C4IW_QP_ATTR_NEXT_STATE, 2886cfdda9d7SSteve Wise &attrs, 1); 2887cfdda9d7SSteve Wise } 2888be13b2dfSSteve Wise close_complete_upcall(ep, 0); 2889cfdda9d7SSteve Wise __state_set(&ep->com, DEAD); 2890cfdda9d7SSteve Wise release = 1; 2891cfdda9d7SSteve Wise break; 2892cfdda9d7SSteve Wise case ABORTING: 2893cfdda9d7SSteve Wise case DEAD: 2894cfdda9d7SSteve Wise break; 2895cfdda9d7SSteve Wise default: 2896cfdda9d7SSteve Wise BUG_ON(1); 2897cfdda9d7SSteve Wise break; 2898cfdda9d7SSteve Wise } 28992f5b48c3SSteve Wise mutex_unlock(&ep->com.mutex); 2900cfdda9d7SSteve Wise if (release) 2901cfdda9d7SSteve Wise release_ep_resources(ep); 2902944661ddSHariprasad S c4iw_put_ep(&ep->com); 2903cfdda9d7SSteve Wise return 0; 2904cfdda9d7SSteve Wise } 2905cfdda9d7SSteve Wise 2906cfdda9d7SSteve Wise static int terminate(struct c4iw_dev *dev, struct sk_buff *skb) 2907cfdda9d7SSteve Wise { 29080e42c1f4SSteve Wise struct cpl_rdma_terminate *rpl = cplhdr(skb); 29090e42c1f4SSteve Wise unsigned int tid = GET_TID(rpl); 29100e42c1f4SSteve Wise struct c4iw_ep *ep; 29110e42c1f4SSteve Wise struct c4iw_qp_attributes attrs; 2912cfdda9d7SSteve Wise 2913944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 29140e42c1f4SSteve Wise BUG_ON(!ep); 2915cfdda9d7SSteve Wise 291630c95c2dSSteve Wise if (ep && ep->com.qp) { 29170e42c1f4SSteve Wise printk(KERN_WARNING MOD "TERM received tid %u qpid %u\n", tid, 29180e42c1f4SSteve Wise ep->com.qp->wq.sq.qid); 29190e42c1f4SSteve Wise attrs.next_state = C4IW_QP_STATE_TERMINATE; 29200e42c1f4SSteve Wise c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, 29210e42c1f4SSteve Wise C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); 29220e42c1f4SSteve Wise } else 292330c95c2dSSteve Wise printk(KERN_WARNING MOD "TERM received tid %u no ep/qp\n", tid); 2924944661ddSHariprasad S c4iw_put_ep(&ep->com); 2925cfdda9d7SSteve Wise 2926cfdda9d7SSteve Wise return 0; 2927cfdda9d7SSteve Wise } 2928cfdda9d7SSteve Wise 2929cfdda9d7SSteve Wise /* 2930cfdda9d7SSteve Wise * Upcall from the adapter indicating data has been transmitted. 2931cfdda9d7SSteve Wise * For us its just the single MPA request or reply. We can now free 2932cfdda9d7SSteve Wise * the skb holding the mpa message. 2933cfdda9d7SSteve Wise */ 2934cfdda9d7SSteve Wise static int fw4_ack(struct c4iw_dev *dev, struct sk_buff *skb) 2935cfdda9d7SSteve Wise { 2936cfdda9d7SSteve Wise struct c4iw_ep *ep; 2937cfdda9d7SSteve Wise struct cpl_fw4_ack *hdr = cplhdr(skb); 2938cfdda9d7SSteve Wise u8 credits = hdr->credits; 2939cfdda9d7SSteve Wise unsigned int tid = GET_TID(hdr); 2940cfdda9d7SSteve Wise 2941cfdda9d7SSteve Wise 2942944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 2943944661ddSHariprasad S if (!ep) 2944944661ddSHariprasad S return 0; 2945cfdda9d7SSteve Wise PDBG("%s ep %p tid %u credits %u\n", __func__, ep, ep->hwtid, credits); 2946cfdda9d7SSteve Wise if (credits == 0) { 2947aa1ad260SJoe Perches PDBG("%s 0 credit ack ep %p tid %u state %u\n", 2948cfdda9d7SSteve Wise __func__, ep, ep->hwtid, state_read(&ep->com)); 2949944661ddSHariprasad S goto out; 2950cfdda9d7SSteve Wise } 2951cfdda9d7SSteve Wise 2952cfdda9d7SSteve Wise dst_confirm(ep->dst); 2953cfdda9d7SSteve Wise if (ep->mpa_skb) { 2954cfdda9d7SSteve Wise PDBG("%s last streaming msg ack ep %p tid %u state %u " 2955cfdda9d7SSteve Wise "initiator %u freeing skb\n", __func__, ep, ep->hwtid, 2956cfdda9d7SSteve Wise state_read(&ep->com), ep->mpa_attr.initiator ? 1 : 0); 295712eb5137SSteve Wise mutex_lock(&ep->com.mutex); 2958cfdda9d7SSteve Wise kfree_skb(ep->mpa_skb); 2959cfdda9d7SSteve Wise ep->mpa_skb = NULL; 2960e4b76a2aSHariprasad S if (test_bit(STOP_MPA_TIMER, &ep->com.flags)) 2961e4b76a2aSHariprasad S stop_ep_timer(ep); 2962e4b76a2aSHariprasad S mutex_unlock(&ep->com.mutex); 2963cfdda9d7SSteve Wise } 2964944661ddSHariprasad S out: 2965944661ddSHariprasad S c4iw_put_ep(&ep->com); 2966cfdda9d7SSteve Wise return 0; 2967cfdda9d7SSteve Wise } 2968cfdda9d7SSteve Wise 2969cfdda9d7SSteve Wise int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) 2970cfdda9d7SSteve Wise { 2971bce2841fSHariprasad S int abort; 2972cfdda9d7SSteve Wise struct c4iw_ep *ep = to_ep(cm_id); 2973bce2841fSHariprasad S 2974cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 2975cfdda9d7SSteve Wise 2976a7db89ebSSteve Wise mutex_lock(&ep->com.mutex); 2977e8667a9bSHariprasad S if (ep->com.state != MPA_REQ_RCVD) { 2978a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 2979cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 2980cfdda9d7SSteve Wise return -ECONNRESET; 2981cfdda9d7SSteve Wise } 2982793dad94SVipul Pandya set_bit(ULP_REJECT, &ep->com.history); 2983cfdda9d7SSteve Wise if (mpa_rev == 0) 2984bce2841fSHariprasad S abort = 1; 2985bce2841fSHariprasad S else 2986bce2841fSHariprasad S abort = send_mpa_reject(ep, pdata, pdata_len); 2987a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 2988bce2841fSHariprasad S 2989e4b76a2aSHariprasad S stop_ep_timer(ep); 2990bce2841fSHariprasad S c4iw_ep_disconnect(ep, abort != 0, GFP_KERNEL); 2991cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 2992cfdda9d7SSteve Wise return 0; 2993cfdda9d7SSteve Wise } 2994cfdda9d7SSteve Wise 2995cfdda9d7SSteve Wise int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) 2996cfdda9d7SSteve Wise { 2997cfdda9d7SSteve Wise int err; 2998cfdda9d7SSteve Wise struct c4iw_qp_attributes attrs; 2999cfdda9d7SSteve Wise enum c4iw_qp_attr_mask mask; 3000cfdda9d7SSteve Wise struct c4iw_ep *ep = to_ep(cm_id); 3001cfdda9d7SSteve Wise struct c4iw_dev *h = to_c4iw_dev(cm_id->device); 3002cfdda9d7SSteve Wise struct c4iw_qp *qp = get_qhp(h, conn_param->qpn); 3003eaf4c6d4SHariprasad S int abort = 0; 3004cfdda9d7SSteve Wise 3005cfdda9d7SSteve Wise PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); 3006a7db89ebSSteve Wise 3007a7db89ebSSteve Wise mutex_lock(&ep->com.mutex); 3008e8667a9bSHariprasad S if (ep->com.state != MPA_REQ_RCVD) { 3009cfdda9d7SSteve Wise err = -ECONNRESET; 3010eaf4c6d4SHariprasad S goto err_out; 3011cfdda9d7SSteve Wise } 3012cfdda9d7SSteve Wise 3013cfdda9d7SSteve Wise BUG_ON(!qp); 3014cfdda9d7SSteve Wise 3015793dad94SVipul Pandya set_bit(ULP_ACCEPT, &ep->com.history); 30164c2c5763SHariprasad Shenai if ((conn_param->ord > cur_max_read_depth(ep->com.dev)) || 30174c2c5763SHariprasad Shenai (conn_param->ird > cur_max_read_depth(ep->com.dev))) { 3018cfdda9d7SSteve Wise err = -EINVAL; 3019eaf4c6d4SHariprasad S goto err_abort; 3020cfdda9d7SSteve Wise } 3021cfdda9d7SSteve Wise 3022d2fe99e8SKumar Sanghvi if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) { 3023d2fe99e8SKumar Sanghvi if (conn_param->ord > ep->ird) { 30244c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION) { 302530b03b15SSteve Wise conn_param->ord = ep->ird; 30264c2c5763SHariprasad Shenai } else { 3027d2fe99e8SKumar Sanghvi ep->ird = conn_param->ird; 3028d2fe99e8SKumar Sanghvi ep->ord = conn_param->ord; 3029d2fe99e8SKumar Sanghvi send_mpa_reject(ep, conn_param->private_data, 3030d2fe99e8SKumar Sanghvi conn_param->private_data_len); 3031d2fe99e8SKumar Sanghvi err = -ENOMEM; 3032eaf4c6d4SHariprasad S goto err_abort; 3033d2fe99e8SKumar Sanghvi } 30344c2c5763SHariprasad Shenai } 30354c2c5763SHariprasad Shenai if (conn_param->ird < ep->ord) { 30364c2c5763SHariprasad Shenai if (RELAXED_IRD_NEGOTIATION && 30374c2c5763SHariprasad Shenai ep->ord <= h->rdev.lldi.max_ordird_qp) { 30384c2c5763SHariprasad Shenai conn_param->ird = ep->ord; 30394c2c5763SHariprasad Shenai } else { 3040d2fe99e8SKumar Sanghvi err = -ENOMEM; 3041eaf4c6d4SHariprasad S goto err_abort; 3042d2fe99e8SKumar Sanghvi } 3043d2fe99e8SKumar Sanghvi } 3044d2fe99e8SKumar Sanghvi } 3045cfdda9d7SSteve Wise ep->ird = conn_param->ird; 3046cfdda9d7SSteve Wise ep->ord = conn_param->ord; 3047cfdda9d7SSteve Wise 30484c2c5763SHariprasad Shenai if (ep->mpa_attr.version == 1) { 3049cfdda9d7SSteve Wise if (peer2peer && ep->ird == 0) 3050cfdda9d7SSteve Wise ep->ird = 1; 30514c2c5763SHariprasad Shenai } else { 30524c2c5763SHariprasad Shenai if (peer2peer && 30534c2c5763SHariprasad Shenai (ep->mpa_attr.p2p_type != FW_RI_INIT_P2PTYPE_DISABLED) && 3054f57b780cSHariprasad S (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) && ep->ird == 0) 30554c2c5763SHariprasad Shenai ep->ird = 1; 30564c2c5763SHariprasad Shenai } 3057cfdda9d7SSteve Wise 3058cfdda9d7SSteve Wise PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord); 3059cfdda9d7SSteve Wise 3060d2fe99e8SKumar Sanghvi ep->com.cm_id = cm_id; 30619ca6f7cfSHariprasad S ref_cm_id(&ep->com); 3062d2fe99e8SKumar Sanghvi ep->com.qp = qp; 3063325abeadSVipul Pandya ref_qp(ep); 3064d2fe99e8SKumar Sanghvi 3065cfdda9d7SSteve Wise /* bind QP to EP and move to RTS */ 3066cfdda9d7SSteve Wise attrs.mpa_attr = ep->mpa_attr; 3067cfdda9d7SSteve Wise attrs.max_ird = ep->ird; 3068cfdda9d7SSteve Wise attrs.max_ord = ep->ord; 3069cfdda9d7SSteve Wise attrs.llp_stream_handle = ep; 3070cfdda9d7SSteve Wise attrs.next_state = C4IW_QP_STATE_RTS; 3071cfdda9d7SSteve Wise 3072cfdda9d7SSteve Wise /* bind QP and TID with INIT_WR */ 3073cfdda9d7SSteve Wise mask = C4IW_QP_ATTR_NEXT_STATE | 3074cfdda9d7SSteve Wise C4IW_QP_ATTR_LLP_STREAM_HANDLE | 3075cfdda9d7SSteve Wise C4IW_QP_ATTR_MPA_ATTR | 3076cfdda9d7SSteve Wise C4IW_QP_ATTR_MAX_IRD | 3077cfdda9d7SSteve Wise C4IW_QP_ATTR_MAX_ORD; 3078cfdda9d7SSteve Wise 3079cfdda9d7SSteve Wise err = c4iw_modify_qp(ep->com.qp->rhp, 3080cfdda9d7SSteve Wise ep->com.qp, mask, &attrs, 1); 3081cfdda9d7SSteve Wise if (err) 3082eaf4c6d4SHariprasad S goto err_deref_cm_id; 3083e4b76a2aSHariprasad S 3084e4b76a2aSHariprasad S set_bit(STOP_MPA_TIMER, &ep->com.flags); 3085cfdda9d7SSteve Wise err = send_mpa_reply(ep, conn_param->private_data, 3086cfdda9d7SSteve Wise conn_param->private_data_len); 3087cfdda9d7SSteve Wise if (err) 3088eaf4c6d4SHariprasad S goto err_deref_cm_id; 3089cfdda9d7SSteve Wise 3090a7db89ebSSteve Wise __state_set(&ep->com, FPDU_MODE); 3091cfdda9d7SSteve Wise established_upcall(ep); 3092a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 3093cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3094cfdda9d7SSteve Wise return 0; 3095eaf4c6d4SHariprasad S err_deref_cm_id: 30969ca6f7cfSHariprasad S deref_cm_id(&ep->com); 3097eaf4c6d4SHariprasad S err_abort: 3098eaf4c6d4SHariprasad S abort = 1; 3099eaf4c6d4SHariprasad S err_out: 3100a7db89ebSSteve Wise mutex_unlock(&ep->com.mutex); 3101eaf4c6d4SHariprasad S if (abort) 3102eaf4c6d4SHariprasad S c4iw_ep_disconnect(ep, 1, GFP_KERNEL); 3103cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3104cfdda9d7SSteve Wise return err; 3105cfdda9d7SSteve Wise } 3106cfdda9d7SSteve Wise 3107830662f6SVipul Pandya static int pick_local_ipaddrs(struct c4iw_dev *dev, struct iw_cm_id *cm_id) 3108830662f6SVipul Pandya { 3109830662f6SVipul Pandya struct in_device *ind; 3110830662f6SVipul Pandya int found = 0; 3111170003c8SSteve Wise struct sockaddr_in *laddr = (struct sockaddr_in *)&cm_id->m_local_addr; 3112170003c8SSteve Wise struct sockaddr_in *raddr = (struct sockaddr_in *)&cm_id->m_remote_addr; 3113830662f6SVipul Pandya 3114830662f6SVipul Pandya ind = in_dev_get(dev->rdev.lldi.ports[0]); 3115830662f6SVipul Pandya if (!ind) 3116830662f6SVipul Pandya return -EADDRNOTAVAIL; 3117830662f6SVipul Pandya for_primary_ifa(ind) { 3118830662f6SVipul Pandya laddr->sin_addr.s_addr = ifa->ifa_address; 3119830662f6SVipul Pandya raddr->sin_addr.s_addr = ifa->ifa_address; 3120830662f6SVipul Pandya found = 1; 3121830662f6SVipul Pandya break; 3122830662f6SVipul Pandya } 3123830662f6SVipul Pandya endfor_ifa(ind); 3124830662f6SVipul Pandya in_dev_put(ind); 3125830662f6SVipul Pandya return found ? 0 : -EADDRNOTAVAIL; 3126830662f6SVipul Pandya } 3127830662f6SVipul Pandya 3128830662f6SVipul Pandya static int get_lladdr(struct net_device *dev, struct in6_addr *addr, 3129830662f6SVipul Pandya unsigned char banned_flags) 3130830662f6SVipul Pandya { 3131830662f6SVipul Pandya struct inet6_dev *idev; 3132830662f6SVipul Pandya int err = -EADDRNOTAVAIL; 3133830662f6SVipul Pandya 3134830662f6SVipul Pandya rcu_read_lock(); 3135830662f6SVipul Pandya idev = __in6_dev_get(dev); 3136830662f6SVipul Pandya if (idev != NULL) { 3137830662f6SVipul Pandya struct inet6_ifaddr *ifp; 3138830662f6SVipul Pandya 3139830662f6SVipul Pandya read_lock_bh(&idev->lock); 3140830662f6SVipul Pandya list_for_each_entry(ifp, &idev->addr_list, if_list) { 3141830662f6SVipul Pandya if (ifp->scope == IFA_LINK && 3142830662f6SVipul Pandya !(ifp->flags & banned_flags)) { 3143830662f6SVipul Pandya memcpy(addr, &ifp->addr, 16); 3144830662f6SVipul Pandya err = 0; 3145830662f6SVipul Pandya break; 3146830662f6SVipul Pandya } 3147830662f6SVipul Pandya } 3148830662f6SVipul Pandya read_unlock_bh(&idev->lock); 3149830662f6SVipul Pandya } 3150830662f6SVipul Pandya rcu_read_unlock(); 3151830662f6SVipul Pandya return err; 3152830662f6SVipul Pandya } 3153830662f6SVipul Pandya 3154830662f6SVipul Pandya static int pick_local_ip6addrs(struct c4iw_dev *dev, struct iw_cm_id *cm_id) 3155830662f6SVipul Pandya { 3156830662f6SVipul Pandya struct in6_addr uninitialized_var(addr); 3157170003c8SSteve Wise struct sockaddr_in6 *la6 = (struct sockaddr_in6 *)&cm_id->m_local_addr; 3158170003c8SSteve Wise struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)&cm_id->m_remote_addr; 3159830662f6SVipul Pandya 316054b9a96fSNicholas Krause if (!get_lladdr(dev->rdev.lldi.ports[0], &addr, IFA_F_TENTATIVE)) { 3161830662f6SVipul Pandya memcpy(la6->sin6_addr.s6_addr, &addr, 16); 3162830662f6SVipul Pandya memcpy(ra6->sin6_addr.s6_addr, &addr, 16); 3163830662f6SVipul Pandya return 0; 3164830662f6SVipul Pandya } 3165830662f6SVipul Pandya return -EADDRNOTAVAIL; 3166830662f6SVipul Pandya } 3167830662f6SVipul Pandya 3168cfdda9d7SSteve Wise int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) 3169cfdda9d7SSteve Wise { 3170cfdda9d7SSteve Wise struct c4iw_dev *dev = to_c4iw_dev(cm_id->device); 3171cfdda9d7SSteve Wise struct c4iw_ep *ep; 31723786cf18SDavid Miller int err = 0; 31739eccfe10SSteve Wise struct sockaddr_in *laddr; 31749eccfe10SSteve Wise struct sockaddr_in *raddr; 31759eccfe10SSteve Wise struct sockaddr_in6 *laddr6; 31769eccfe10SSteve Wise struct sockaddr_in6 *raddr6; 3177830662f6SVipul Pandya __u8 *ra; 3178830662f6SVipul Pandya int iptype; 3179cfdda9d7SSteve Wise 31804c2c5763SHariprasad Shenai if ((conn_param->ord > cur_max_read_depth(dev)) || 31814c2c5763SHariprasad Shenai (conn_param->ird > cur_max_read_depth(dev))) { 3182be4c9badSRoland Dreier err = -EINVAL; 3183be4c9badSRoland Dreier goto out; 3184be4c9badSRoland Dreier } 3185cfdda9d7SSteve Wise ep = alloc_ep(sizeof(*ep), GFP_KERNEL); 3186cfdda9d7SSteve Wise if (!ep) { 3187cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __func__); 3188cfdda9d7SSteve Wise err = -ENOMEM; 3189cfdda9d7SSteve Wise goto out; 3190cfdda9d7SSteve Wise } 31914a740838SHariprasad S 31924a740838SHariprasad S skb_queue_head_init(&ep->com.ep_skb_list); 31934a740838SHariprasad S if (alloc_ep_skb_list(&ep->com.ep_skb_list, CN_MAX_CON_BUF)) { 31944a740838SHariprasad S err = -ENOMEM; 31954a740838SHariprasad S goto fail1; 31964a740838SHariprasad S } 31974a740838SHariprasad S 3198cfdda9d7SSteve Wise init_timer(&ep->timer); 3199cfdda9d7SSteve Wise ep->plen = conn_param->private_data_len; 3200cfdda9d7SSteve Wise if (ep->plen) 3201cfdda9d7SSteve Wise memcpy(ep->mpa_pkt + sizeof(struct mpa_message), 3202cfdda9d7SSteve Wise conn_param->private_data, ep->plen); 3203cfdda9d7SSteve Wise ep->ird = conn_param->ird; 3204cfdda9d7SSteve Wise ep->ord = conn_param->ord; 3205cfdda9d7SSteve Wise 3206cfdda9d7SSteve Wise if (peer2peer && ep->ord == 0) 3207cfdda9d7SSteve Wise ep->ord = 1; 3208cfdda9d7SSteve Wise 3209cfdda9d7SSteve Wise ep->com.cm_id = cm_id; 32109ca6f7cfSHariprasad S ref_cm_id(&ep->com); 32119ca6f7cfSHariprasad S ep->com.dev = dev; 3212cfdda9d7SSteve Wise ep->com.qp = get_qhp(dev, conn_param->qpn); 3213830662f6SVipul Pandya if (!ep->com.qp) { 3214830662f6SVipul Pandya PDBG("%s qpn 0x%x not found!\n", __func__, conn_param->qpn); 3215830662f6SVipul Pandya err = -EINVAL; 32164a740838SHariprasad S goto fail2; 3217830662f6SVipul Pandya } 3218325abeadSVipul Pandya ref_qp(ep); 3219cfdda9d7SSteve Wise PDBG("%s qpn 0x%x qp %p cm_id %p\n", __func__, conn_param->qpn, 3220cfdda9d7SSteve Wise ep->com.qp, cm_id); 3221cfdda9d7SSteve Wise 3222cfdda9d7SSteve Wise /* 3223cfdda9d7SSteve Wise * Allocate an active TID to initiate a TCP connection. 3224cfdda9d7SSteve Wise */ 3225cfdda9d7SSteve Wise ep->atid = cxgb4_alloc_atid(dev->rdev.lldi.tids, ep); 3226cfdda9d7SSteve Wise if (ep->atid == -1) { 3227cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __func__); 3228cfdda9d7SSteve Wise err = -ENOMEM; 32294a740838SHariprasad S goto fail2; 3230cfdda9d7SSteve Wise } 3231793dad94SVipul Pandya insert_handle(dev, &dev->atid_idr, ep, ep->atid); 3232cfdda9d7SSteve Wise 3233170003c8SSteve Wise memcpy(&ep->com.local_addr, &cm_id->m_local_addr, 32349eccfe10SSteve Wise sizeof(ep->com.local_addr)); 3235170003c8SSteve Wise memcpy(&ep->com.remote_addr, &cm_id->m_remote_addr, 32369eccfe10SSteve Wise sizeof(ep->com.remote_addr)); 32379eccfe10SSteve Wise 3238170003c8SSteve Wise laddr = (struct sockaddr_in *)&ep->com.local_addr; 3239170003c8SSteve Wise raddr = (struct sockaddr_in *)&ep->com.remote_addr; 3240170003c8SSteve Wise laddr6 = (struct sockaddr_in6 *)&ep->com.local_addr; 3241170003c8SSteve Wise raddr6 = (struct sockaddr_in6 *) &ep->com.remote_addr; 32429eccfe10SSteve Wise 3243170003c8SSteve Wise if (cm_id->m_remote_addr.ss_family == AF_INET) { 3244830662f6SVipul Pandya iptype = 4; 3245830662f6SVipul Pandya ra = (__u8 *)&raddr->sin_addr; 3246830662f6SVipul Pandya 3247830662f6SVipul Pandya /* 3248830662f6SVipul Pandya * Handle loopback requests to INADDR_ANY. 3249830662f6SVipul Pandya */ 3250ba987e51SBart Van Assche if (raddr->sin_addr.s_addr == htonl(INADDR_ANY)) { 3251830662f6SVipul Pandya err = pick_local_ipaddrs(dev, cm_id); 3252830662f6SVipul Pandya if (err) 32534a740838SHariprasad S goto fail2; 3254830662f6SVipul Pandya } 3255cfdda9d7SSteve Wise 3256cfdda9d7SSteve Wise /* find a route */ 3257830662f6SVipul Pandya PDBG("%s saddr %pI4 sport 0x%x raddr %pI4 rport 0x%x\n", 3258830662f6SVipul Pandya __func__, &laddr->sin_addr, ntohs(laddr->sin_port), 3259830662f6SVipul Pandya ra, ntohs(raddr->sin_port)); 3260804c2f3eSVarun Prakash ep->dst = cxgb_find_route(&dev->rdev.lldi, get_real_dev, 3261804c2f3eSVarun Prakash laddr->sin_addr.s_addr, 3262804c2f3eSVarun Prakash raddr->sin_addr.s_addr, 3263804c2f3eSVarun Prakash laddr->sin_port, 3264ac8e4c69SHariprasad S raddr->sin_port, cm_id->tos); 3265830662f6SVipul Pandya } else { 3266830662f6SVipul Pandya iptype = 6; 3267830662f6SVipul Pandya ra = (__u8 *)&raddr6->sin6_addr; 3268830662f6SVipul Pandya 3269830662f6SVipul Pandya /* 3270830662f6SVipul Pandya * Handle loopback requests to INADDR_ANY. 3271830662f6SVipul Pandya */ 3272830662f6SVipul Pandya if (ipv6_addr_type(&raddr6->sin6_addr) == IPV6_ADDR_ANY) { 3273830662f6SVipul Pandya err = pick_local_ip6addrs(dev, cm_id); 3274830662f6SVipul Pandya if (err) 32754a740838SHariprasad S goto fail2; 3276830662f6SVipul Pandya } 3277830662f6SVipul Pandya 3278830662f6SVipul Pandya /* find a route */ 3279830662f6SVipul Pandya PDBG("%s saddr %pI6 sport 0x%x raddr %pI6 rport 0x%x\n", 3280830662f6SVipul Pandya __func__, laddr6->sin6_addr.s6_addr, 3281830662f6SVipul Pandya ntohs(laddr6->sin6_port), 3282830662f6SVipul Pandya raddr6->sin6_addr.s6_addr, ntohs(raddr6->sin6_port)); 328395554761SVarun Prakash ep->dst = cxgb_find_route6(&dev->rdev.lldi, get_real_dev, 328495554761SVarun Prakash laddr6->sin6_addr.s6_addr, 3285830662f6SVipul Pandya raddr6->sin6_addr.s6_addr, 328695554761SVarun Prakash laddr6->sin6_port, 328795554761SVarun Prakash raddr6->sin6_port, 0, 3288830662f6SVipul Pandya raddr6->sin6_scope_id); 3289830662f6SVipul Pandya } 3290830662f6SVipul Pandya if (!ep->dst) { 3291cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot find route.\n", __func__); 3292cfdda9d7SSteve Wise err = -EHOSTUNREACH; 32934a740838SHariprasad S goto fail3; 3294cfdda9d7SSteve Wise } 3295cfdda9d7SSteve Wise 3296963cab50SHariprasad S err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, true, 3297ac8e4c69SHariprasad S ep->com.dev->rdev.lldi.adapter_type, cm_id->tos); 32983786cf18SDavid Miller if (err) { 3299cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); 33004a740838SHariprasad S goto fail4; 3301cfdda9d7SSteve Wise } 3302cfdda9d7SSteve Wise 3303cfdda9d7SSteve Wise PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n", 3304cfdda9d7SSteve Wise __func__, ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid, 3305cfdda9d7SSteve Wise ep->l2t->idx); 3306cfdda9d7SSteve Wise 3307cfdda9d7SSteve Wise state_set(&ep->com, CONNECTING); 3308ac8e4c69SHariprasad S ep->tos = cm_id->tos; 3309cfdda9d7SSteve Wise 3310cfdda9d7SSteve Wise /* send connect request to rnic */ 3311cfdda9d7SSteve Wise err = send_connect(ep); 3312cfdda9d7SSteve Wise if (!err) 3313cfdda9d7SSteve Wise goto out; 3314cfdda9d7SSteve Wise 3315cfdda9d7SSteve Wise cxgb4_l2t_release(ep->l2t); 33164a740838SHariprasad S fail4: 33179eccfe10SSteve Wise dst_release(ep->dst); 33184a740838SHariprasad S fail3: 3319793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid); 3320cfdda9d7SSteve Wise cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid); 33214a740838SHariprasad S fail2: 33224a740838SHariprasad S skb_queue_purge(&ep->com.ep_skb_list); 33239ca6f7cfSHariprasad S deref_cm_id(&ep->com); 33244a740838SHariprasad S fail1: 3325cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3326cfdda9d7SSteve Wise out: 3327cfdda9d7SSteve Wise return err; 3328cfdda9d7SSteve Wise } 3329cfdda9d7SSteve Wise 3330830662f6SVipul Pandya static int create_server6(struct c4iw_dev *dev, struct c4iw_listen_ep *ep) 3331830662f6SVipul Pandya { 3332830662f6SVipul Pandya int err; 33339eccfe10SSteve Wise struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) 3334170003c8SSteve Wise &ep->com.local_addr; 3335830662f6SVipul Pandya 333628de1f74SHariprasad S if (ipv6_addr_type(&sin6->sin6_addr) != IPV6_ADDR_ANY) { 333728de1f74SHariprasad S err = cxgb4_clip_get(ep->com.dev->rdev.lldi.ports[0], 333828de1f74SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 333928de1f74SHariprasad S if (err) 334028de1f74SHariprasad S return err; 334128de1f74SHariprasad S } 3342830662f6SVipul Pandya c4iw_init_wr_wait(&ep->com.wr_wait); 3343830662f6SVipul Pandya err = cxgb4_create_server6(ep->com.dev->rdev.lldi.ports[0], 3344830662f6SVipul Pandya ep->stid, &sin6->sin6_addr, 3345830662f6SVipul Pandya sin6->sin6_port, 3346830662f6SVipul Pandya ep->com.dev->rdev.lldi.rxq_ids[0]); 3347830662f6SVipul Pandya if (!err) 3348830662f6SVipul Pandya err = c4iw_wait_for_reply(&ep->com.dev->rdev, 3349830662f6SVipul Pandya &ep->com.wr_wait, 3350830662f6SVipul Pandya 0, 0, __func__); 3351e6b11163SHariprasad S else if (err > 0) 3352e6b11163SHariprasad S err = net_xmit_errno(err); 335328de1f74SHariprasad S if (err) { 335428de1f74SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 335528de1f74SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 3356830662f6SVipul Pandya pr_err("cxgb4_create_server6/filter failed err %d stid %d laddr %pI6 lport %d\n", 3357830662f6SVipul Pandya err, ep->stid, 3358830662f6SVipul Pandya sin6->sin6_addr.s6_addr, ntohs(sin6->sin6_port)); 335928de1f74SHariprasad S } 3360830662f6SVipul Pandya return err; 3361830662f6SVipul Pandya } 3362830662f6SVipul Pandya 3363830662f6SVipul Pandya static int create_server4(struct c4iw_dev *dev, struct c4iw_listen_ep *ep) 3364830662f6SVipul Pandya { 3365830662f6SVipul Pandya int err; 33669eccfe10SSteve Wise struct sockaddr_in *sin = (struct sockaddr_in *) 3367170003c8SSteve Wise &ep->com.local_addr; 3368830662f6SVipul Pandya 3369830662f6SVipul Pandya if (dev->rdev.lldi.enable_fw_ofld_conn) { 3370830662f6SVipul Pandya do { 3371830662f6SVipul Pandya err = cxgb4_create_server_filter( 3372830662f6SVipul Pandya ep->com.dev->rdev.lldi.ports[0], ep->stid, 3373830662f6SVipul Pandya sin->sin_addr.s_addr, sin->sin_port, 0, 3374830662f6SVipul Pandya ep->com.dev->rdev.lldi.rxq_ids[0], 0, 0); 3375830662f6SVipul Pandya if (err == -EBUSY) { 337699718e59SHariprasad S if (c4iw_fatal_error(&ep->com.dev->rdev)) { 337799718e59SHariprasad S err = -EIO; 337899718e59SHariprasad S break; 337999718e59SHariprasad S } 3380830662f6SVipul Pandya set_current_state(TASK_UNINTERRUPTIBLE); 3381830662f6SVipul Pandya schedule_timeout(usecs_to_jiffies(100)); 3382830662f6SVipul Pandya } 3383830662f6SVipul Pandya } while (err == -EBUSY); 3384830662f6SVipul Pandya } else { 3385830662f6SVipul Pandya c4iw_init_wr_wait(&ep->com.wr_wait); 3386830662f6SVipul Pandya err = cxgb4_create_server(ep->com.dev->rdev.lldi.ports[0], 3387830662f6SVipul Pandya ep->stid, sin->sin_addr.s_addr, sin->sin_port, 3388830662f6SVipul Pandya 0, ep->com.dev->rdev.lldi.rxq_ids[0]); 3389830662f6SVipul Pandya if (!err) 3390830662f6SVipul Pandya err = c4iw_wait_for_reply(&ep->com.dev->rdev, 3391830662f6SVipul Pandya &ep->com.wr_wait, 3392830662f6SVipul Pandya 0, 0, __func__); 3393e6b11163SHariprasad S else if (err > 0) 3394e6b11163SHariprasad S err = net_xmit_errno(err); 3395830662f6SVipul Pandya } 3396830662f6SVipul Pandya if (err) 3397830662f6SVipul Pandya pr_err("cxgb4_create_server/filter failed err %d stid %d laddr %pI4 lport %d\n" 3398830662f6SVipul Pandya , err, ep->stid, 3399830662f6SVipul Pandya &sin->sin_addr, ntohs(sin->sin_port)); 3400830662f6SVipul Pandya return err; 3401830662f6SVipul Pandya } 3402830662f6SVipul Pandya 3403cfdda9d7SSteve Wise int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog) 3404cfdda9d7SSteve Wise { 3405cfdda9d7SSteve Wise int err = 0; 3406cfdda9d7SSteve Wise struct c4iw_dev *dev = to_c4iw_dev(cm_id->device); 3407cfdda9d7SSteve Wise struct c4iw_listen_ep *ep; 3408cfdda9d7SSteve Wise 3409cfdda9d7SSteve Wise might_sleep(); 3410cfdda9d7SSteve Wise 3411cfdda9d7SSteve Wise ep = alloc_ep(sizeof(*ep), GFP_KERNEL); 3412cfdda9d7SSteve Wise if (!ep) { 3413cfdda9d7SSteve Wise printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __func__); 3414cfdda9d7SSteve Wise err = -ENOMEM; 3415cfdda9d7SSteve Wise goto fail1; 3416cfdda9d7SSteve Wise } 34174a740838SHariprasad S skb_queue_head_init(&ep->com.ep_skb_list); 3418cfdda9d7SSteve Wise PDBG("%s ep %p\n", __func__, ep); 3419cfdda9d7SSteve Wise ep->com.cm_id = cm_id; 34209ca6f7cfSHariprasad S ref_cm_id(&ep->com); 3421cfdda9d7SSteve Wise ep->com.dev = dev; 3422cfdda9d7SSteve Wise ep->backlog = backlog; 3423170003c8SSteve Wise memcpy(&ep->com.local_addr, &cm_id->m_local_addr, 342424d44a39SSteve Wise sizeof(ep->com.local_addr)); 3425cfdda9d7SSteve Wise 3426cfdda9d7SSteve Wise /* 3427cfdda9d7SSteve Wise * Allocate a server TID. 3428cfdda9d7SSteve Wise */ 34298c044690SKumar Sanghvi if (dev->rdev.lldi.enable_fw_ofld_conn && 34308c044690SKumar Sanghvi ep->com.local_addr.ss_family == AF_INET) 3431830662f6SVipul Pandya ep->stid = cxgb4_alloc_sftid(dev->rdev.lldi.tids, 3432170003c8SSteve Wise cm_id->m_local_addr.ss_family, ep); 34331cab775cSVipul Pandya else 3434830662f6SVipul Pandya ep->stid = cxgb4_alloc_stid(dev->rdev.lldi.tids, 3435170003c8SSteve Wise cm_id->m_local_addr.ss_family, ep); 34361cab775cSVipul Pandya 3437cfdda9d7SSteve Wise if (ep->stid == -1) { 3438be4c9badSRoland Dreier printk(KERN_ERR MOD "%s - cannot alloc stid.\n", __func__); 3439cfdda9d7SSteve Wise err = -ENOMEM; 3440cfdda9d7SSteve Wise goto fail2; 3441cfdda9d7SSteve Wise } 3442793dad94SVipul Pandya insert_handle(dev, &dev->stid_idr, ep, ep->stid); 34439eccfe10SSteve Wise 3444170003c8SSteve Wise memcpy(&ep->com.local_addr, &cm_id->m_local_addr, 34459eccfe10SSteve Wise sizeof(ep->com.local_addr)); 34469eccfe10SSteve Wise 3447cfdda9d7SSteve Wise state_set(&ep->com, LISTEN); 3448830662f6SVipul Pandya if (ep->com.local_addr.ss_family == AF_INET) 3449830662f6SVipul Pandya err = create_server4(dev, ep); 3450830662f6SVipul Pandya else 3451830662f6SVipul Pandya err = create_server6(dev, ep); 3452cfdda9d7SSteve Wise if (!err) { 3453cfdda9d7SSteve Wise cm_id->provider_data = ep; 3454cfdda9d7SSteve Wise goto out; 3455cfdda9d7SSteve Wise } 34569eccfe10SSteve Wise 3457830662f6SVipul Pandya cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, 3458830662f6SVipul Pandya ep->com.local_addr.ss_family); 3459cfdda9d7SSteve Wise fail2: 34609ca6f7cfSHariprasad S deref_cm_id(&ep->com); 3461cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3462cfdda9d7SSteve Wise fail1: 3463cfdda9d7SSteve Wise out: 3464cfdda9d7SSteve Wise return err; 3465cfdda9d7SSteve Wise } 3466cfdda9d7SSteve Wise 3467cfdda9d7SSteve Wise int c4iw_destroy_listen(struct iw_cm_id *cm_id) 3468cfdda9d7SSteve Wise { 3469cfdda9d7SSteve Wise int err; 3470cfdda9d7SSteve Wise struct c4iw_listen_ep *ep = to_listen_ep(cm_id); 3471cfdda9d7SSteve Wise 3472cfdda9d7SSteve Wise PDBG("%s ep %p\n", __func__, ep); 3473cfdda9d7SSteve Wise 3474cfdda9d7SSteve Wise might_sleep(); 3475cfdda9d7SSteve Wise state_set(&ep->com, DEAD); 3476830662f6SVipul Pandya if (ep->com.dev->rdev.lldi.enable_fw_ofld_conn && 3477830662f6SVipul Pandya ep->com.local_addr.ss_family == AF_INET) { 34781cab775cSVipul Pandya err = cxgb4_remove_server_filter( 34791cab775cSVipul Pandya ep->com.dev->rdev.lldi.ports[0], ep->stid, 34801cab775cSVipul Pandya ep->com.dev->rdev.lldi.rxq_ids[0], 0); 34811cab775cSVipul Pandya } else { 348284cc6ac6SHariprasad S struct sockaddr_in6 *sin6; 3483aadc4df3SSteve Wise c4iw_init_wr_wait(&ep->com.wr_wait); 3484830662f6SVipul Pandya err = cxgb4_remove_server( 3485830662f6SVipul Pandya ep->com.dev->rdev.lldi.ports[0], ep->stid, 3486830662f6SVipul Pandya ep->com.dev->rdev.lldi.rxq_ids[0], 0); 3487cfdda9d7SSteve Wise if (err) 3488cfdda9d7SSteve Wise goto done; 34891cab775cSVipul Pandya err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait, 34901cab775cSVipul Pandya 0, 0, __func__); 3491170003c8SSteve Wise sin6 = (struct sockaddr_in6 *)&ep->com.local_addr; 349284cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 349384cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 34941cab775cSVipul Pandya } 3495793dad94SVipul Pandya remove_handle(ep->com.dev, &ep->com.dev->stid_idr, ep->stid); 3496830662f6SVipul Pandya cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, 3497830662f6SVipul Pandya ep->com.local_addr.ss_family); 3498cfdda9d7SSteve Wise done: 34999ca6f7cfSHariprasad S deref_cm_id(&ep->com); 3500cfdda9d7SSteve Wise c4iw_put_ep(&ep->com); 3501cfdda9d7SSteve Wise return err; 3502cfdda9d7SSteve Wise } 3503cfdda9d7SSteve Wise 3504cfdda9d7SSteve Wise int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) 3505cfdda9d7SSteve Wise { 3506cfdda9d7SSteve Wise int ret = 0; 3507cfdda9d7SSteve Wise int close = 0; 3508cfdda9d7SSteve Wise int fatal = 0; 3509cfdda9d7SSteve Wise struct c4iw_rdev *rdev; 3510cfdda9d7SSteve Wise 35112f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 3512cfdda9d7SSteve Wise 3513cfdda9d7SSteve Wise PDBG("%s ep %p state %s, abrupt %d\n", __func__, ep, 3514cfdda9d7SSteve Wise states[ep->com.state], abrupt); 3515cfdda9d7SSteve Wise 35166e410d8fSHariprasad S /* 35176e410d8fSHariprasad S * Ref the ep here in case we have fatal errors causing the 35186e410d8fSHariprasad S * ep to be released and freed. 35196e410d8fSHariprasad S */ 35206e410d8fSHariprasad S c4iw_get_ep(&ep->com); 35216e410d8fSHariprasad S 3522cfdda9d7SSteve Wise rdev = &ep->com.dev->rdev; 3523cfdda9d7SSteve Wise if (c4iw_fatal_error(rdev)) { 3524cfdda9d7SSteve Wise fatal = 1; 3525be13b2dfSSteve Wise close_complete_upcall(ep, -EIO); 3526cfdda9d7SSteve Wise ep->com.state = DEAD; 3527cfdda9d7SSteve Wise } 3528cfdda9d7SSteve Wise switch (ep->com.state) { 3529cfdda9d7SSteve Wise case MPA_REQ_WAIT: 3530cfdda9d7SSteve Wise case MPA_REQ_SENT: 3531cfdda9d7SSteve Wise case MPA_REQ_RCVD: 3532cfdda9d7SSteve Wise case MPA_REP_SENT: 3533cfdda9d7SSteve Wise case FPDU_MODE: 35344a740838SHariprasad S case CONNECTING: 3535cfdda9d7SSteve Wise close = 1; 3536cfdda9d7SSteve Wise if (abrupt) 3537cfdda9d7SSteve Wise ep->com.state = ABORTING; 3538cfdda9d7SSteve Wise else { 3539cfdda9d7SSteve Wise ep->com.state = CLOSING; 354012eb5137SSteve Wise 354112eb5137SSteve Wise /* 354212eb5137SSteve Wise * if we close before we see the fw4_ack() then we fix 354312eb5137SSteve Wise * up the timer state since we're reusing it. 354412eb5137SSteve Wise */ 354512eb5137SSteve Wise if (ep->mpa_skb && 354612eb5137SSteve Wise test_bit(STOP_MPA_TIMER, &ep->com.flags)) { 354712eb5137SSteve Wise clear_bit(STOP_MPA_TIMER, &ep->com.flags); 354812eb5137SSteve Wise stop_ep_timer(ep); 354912eb5137SSteve Wise } 3550ca5a2202SSteve Wise start_ep_timer(ep); 3551cfdda9d7SSteve Wise } 3552cfdda9d7SSteve Wise set_bit(CLOSE_SENT, &ep->com.flags); 3553cfdda9d7SSteve Wise break; 3554cfdda9d7SSteve Wise case CLOSING: 3555cfdda9d7SSteve Wise if (!test_and_set_bit(CLOSE_SENT, &ep->com.flags)) { 3556cfdda9d7SSteve Wise close = 1; 3557cfdda9d7SSteve Wise if (abrupt) { 3558b33bd0cbSSteve Wise (void)stop_ep_timer(ep); 3559cfdda9d7SSteve Wise ep->com.state = ABORTING; 3560cfdda9d7SSteve Wise } else 3561cfdda9d7SSteve Wise ep->com.state = MORIBUND; 3562cfdda9d7SSteve Wise } 3563cfdda9d7SSteve Wise break; 3564cfdda9d7SSteve Wise case MORIBUND: 3565cfdda9d7SSteve Wise case ABORTING: 3566cfdda9d7SSteve Wise case DEAD: 3567cfdda9d7SSteve Wise PDBG("%s ignoring disconnect ep %p state %u\n", 3568cfdda9d7SSteve Wise __func__, ep, ep->com.state); 3569cfdda9d7SSteve Wise break; 3570cfdda9d7SSteve Wise default: 3571cfdda9d7SSteve Wise BUG(); 3572cfdda9d7SSteve Wise break; 3573cfdda9d7SSteve Wise } 3574cfdda9d7SSteve Wise 3575cfdda9d7SSteve Wise if (close) { 35768da7e7a5SSteve Wise if (abrupt) { 3577793dad94SVipul Pandya set_bit(EP_DISC_ABORT, &ep->com.history); 3578be13b2dfSSteve Wise close_complete_upcall(ep, -ECONNRESET); 35794a740838SHariprasad S ret = send_abort(ep); 3580793dad94SVipul Pandya } else { 3581793dad94SVipul Pandya set_bit(EP_DISC_CLOSE, &ep->com.history); 35824a740838SHariprasad S ret = send_halfclose(ep); 3583793dad94SVipul Pandya } 358488bc230dSHariprasad S if (ret) { 35859ca6f7cfSHariprasad S set_bit(EP_DISC_FAIL, &ep->com.history); 358688bc230dSHariprasad S if (!abrupt) { 358788bc230dSHariprasad S stop_ep_timer(ep); 358888bc230dSHariprasad S close_complete_upcall(ep, -EIO); 358988bc230dSHariprasad S } 3590c00dcbafSHariprasad S if (ep->com.qp) { 3591c00dcbafSHariprasad S struct c4iw_qp_attributes attrs; 3592c00dcbafSHariprasad S 3593c00dcbafSHariprasad S attrs.next_state = C4IW_QP_STATE_ERROR; 3594c00dcbafSHariprasad S ret = c4iw_modify_qp(ep->com.qp->rhp, 3595c00dcbafSHariprasad S ep->com.qp, 3596c00dcbafSHariprasad S C4IW_QP_ATTR_NEXT_STATE, 3597c00dcbafSHariprasad S &attrs, 1); 3598c00dcbafSHariprasad S if (ret) 3599c00dcbafSHariprasad S pr_err(MOD 3600c00dcbafSHariprasad S "%s - qp <- error failed!\n", 3601c00dcbafSHariprasad S __func__); 3602c00dcbafSHariprasad S } 3603cfdda9d7SSteve Wise fatal = 1; 3604cfdda9d7SSteve Wise } 360588bc230dSHariprasad S } 36068da7e7a5SSteve Wise mutex_unlock(&ep->com.mutex); 36076e410d8fSHariprasad S c4iw_put_ep(&ep->com); 3608cfdda9d7SSteve Wise if (fatal) 3609cfdda9d7SSteve Wise release_ep_resources(ep); 3610cfdda9d7SSteve Wise return ret; 3611cfdda9d7SSteve Wise } 3612cfdda9d7SSteve Wise 36131cab775cSVipul Pandya static void active_ofld_conn_reply(struct c4iw_dev *dev, struct sk_buff *skb, 36141cab775cSVipul Pandya struct cpl_fw6_msg_ofld_connection_wr_rpl *req) 36151cab775cSVipul Pandya { 36161cab775cSVipul Pandya struct c4iw_ep *ep; 3617793dad94SVipul Pandya int atid = be32_to_cpu(req->tid); 36181cab775cSVipul Pandya 3619ef5d6355SVipul Pandya ep = (struct c4iw_ep *)lookup_atid(dev->rdev.lldi.tids, 3620ef5d6355SVipul Pandya (__force u32) req->tid); 36211cab775cSVipul Pandya if (!ep) 36221cab775cSVipul Pandya return; 36231cab775cSVipul Pandya 36241cab775cSVipul Pandya switch (req->retval) { 36251cab775cSVipul Pandya case FW_ENOMEM: 3626793dad94SVipul Pandya set_bit(ACT_RETRY_NOMEM, &ep->com.history); 3627793dad94SVipul Pandya if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) { 3628793dad94SVipul Pandya send_fw_act_open_req(ep, atid); 3629793dad94SVipul Pandya return; 3630793dad94SVipul Pandya } 36311cab775cSVipul Pandya case FW_EADDRINUSE: 3632793dad94SVipul Pandya set_bit(ACT_RETRY_INUSE, &ep->com.history); 3633793dad94SVipul Pandya if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) { 3634793dad94SVipul Pandya send_fw_act_open_req(ep, atid); 3635793dad94SVipul Pandya return; 3636793dad94SVipul Pandya } 36371cab775cSVipul Pandya break; 36381cab775cSVipul Pandya default: 36391cab775cSVipul Pandya pr_info("%s unexpected ofld conn wr retval %d\n", 36401cab775cSVipul Pandya __func__, req->retval); 36411cab775cSVipul Pandya break; 36421cab775cSVipul Pandya } 3643793dad94SVipul Pandya pr_err("active ofld_connect_wr failure %d atid %d\n", 3644793dad94SVipul Pandya req->retval, atid); 3645793dad94SVipul Pandya mutex_lock(&dev->rdev.stats.lock); 3646793dad94SVipul Pandya dev->rdev.stats.act_ofld_conn_fails++; 3647793dad94SVipul Pandya mutex_unlock(&dev->rdev.stats.lock); 36481cab775cSVipul Pandya connect_reply_upcall(ep, status2errno(req->retval)); 3649793dad94SVipul Pandya state_set(&ep->com, DEAD); 365084cc6ac6SHariprasad S if (ep->com.remote_addr.ss_family == AF_INET6) { 365184cc6ac6SHariprasad S struct sockaddr_in6 *sin6 = 3652170003c8SSteve Wise (struct sockaddr_in6 *)&ep->com.local_addr; 365384cc6ac6SHariprasad S cxgb4_clip_release(ep->com.dev->rdev.lldi.ports[0], 365484cc6ac6SHariprasad S (const u32 *)&sin6->sin6_addr.s6_addr, 1); 365584cc6ac6SHariprasad S } 3656793dad94SVipul Pandya remove_handle(dev, &dev->atid_idr, atid); 3657793dad94SVipul Pandya cxgb4_free_atid(dev->rdev.lldi.tids, atid); 3658793dad94SVipul Pandya dst_release(ep->dst); 3659793dad94SVipul Pandya cxgb4_l2t_release(ep->l2t); 3660793dad94SVipul Pandya c4iw_put_ep(&ep->com); 36611cab775cSVipul Pandya } 36621cab775cSVipul Pandya 36631cab775cSVipul Pandya static void passive_ofld_conn_reply(struct c4iw_dev *dev, struct sk_buff *skb, 36641cab775cSVipul Pandya struct cpl_fw6_msg_ofld_connection_wr_rpl *req) 36651cab775cSVipul Pandya { 36661cab775cSVipul Pandya struct sk_buff *rpl_skb; 36671cab775cSVipul Pandya struct cpl_pass_accept_req *cpl; 36681cab775cSVipul Pandya int ret; 36691cab775cSVipul Pandya 3670710a3110SPaul Bolle rpl_skb = (struct sk_buff *)(unsigned long)req->cookie; 36711cab775cSVipul Pandya BUG_ON(!rpl_skb); 36721cab775cSVipul Pandya if (req->retval) { 36731cab775cSVipul Pandya PDBG("%s passive open failure %d\n", __func__, req->retval); 3674793dad94SVipul Pandya mutex_lock(&dev->rdev.stats.lock); 3675793dad94SVipul Pandya dev->rdev.stats.pas_ofld_conn_fails++; 3676793dad94SVipul Pandya mutex_unlock(&dev->rdev.stats.lock); 36771cab775cSVipul Pandya kfree_skb(rpl_skb); 36781cab775cSVipul Pandya } else { 36791cab775cSVipul Pandya cpl = (struct cpl_pass_accept_req *)cplhdr(rpl_skb); 36801cab775cSVipul Pandya OPCODE_TID(cpl) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_REQ, 3681ef5d6355SVipul Pandya (__force u32) htonl( 3682ef5d6355SVipul Pandya (__force u32) req->tid))); 36831cab775cSVipul Pandya ret = pass_accept_req(dev, rpl_skb); 36841cab775cSVipul Pandya if (!ret) 36851cab775cSVipul Pandya kfree_skb(rpl_skb); 36861cab775cSVipul Pandya } 36871cab775cSVipul Pandya return; 36881cab775cSVipul Pandya } 36891cab775cSVipul Pandya 36901cab775cSVipul Pandya static int deferred_fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb) 36912f5b48c3SSteve Wise { 36922f5b48c3SSteve Wise struct cpl_fw6_msg *rpl = cplhdr(skb); 36931cab775cSVipul Pandya struct cpl_fw6_msg_ofld_connection_wr_rpl *req; 36941cab775cSVipul Pandya 36951cab775cSVipul Pandya switch (rpl->type) { 36961cab775cSVipul Pandya case FW6_TYPE_CQE: 36972f5b48c3SSteve Wise c4iw_ev_dispatch(dev, (struct t4_cqe *)&rpl->data[0]); 36981cab775cSVipul Pandya break; 36991cab775cSVipul Pandya case FW6_TYPE_OFLD_CONNECTION_WR_RPL: 37001cab775cSVipul Pandya req = (struct cpl_fw6_msg_ofld_connection_wr_rpl *)rpl->data; 37011cab775cSVipul Pandya switch (req->t_state) { 37021cab775cSVipul Pandya case TCP_SYN_SENT: 37031cab775cSVipul Pandya active_ofld_conn_reply(dev, skb, req); 37041cab775cSVipul Pandya break; 37051cab775cSVipul Pandya case TCP_SYN_RECV: 37061cab775cSVipul Pandya passive_ofld_conn_reply(dev, skb, req); 37071cab775cSVipul Pandya break; 37081cab775cSVipul Pandya default: 37091cab775cSVipul Pandya pr_err("%s unexpected ofld conn wr state %d\n", 37101cab775cSVipul Pandya __func__, req->t_state); 37111cab775cSVipul Pandya break; 37121cab775cSVipul Pandya } 37131cab775cSVipul Pandya break; 37141cab775cSVipul Pandya } 37151cab775cSVipul Pandya return 0; 37161cab775cSVipul Pandya } 37171cab775cSVipul Pandya 37181cab775cSVipul Pandya static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos) 37191cab775cSVipul Pandya { 3720963cab50SHariprasad S __be32 l2info; 3721963cab50SHariprasad S __be16 hdr_len, vlantag, len; 3722963cab50SHariprasad S u16 eth_hdr_len; 3723963cab50SHariprasad S int tcp_hdr_len, ip_hdr_len; 37241cab775cSVipul Pandya u8 intf; 37251cab775cSVipul Pandya struct cpl_rx_pkt *cpl = cplhdr(skb); 37261cab775cSVipul Pandya struct cpl_pass_accept_req *req; 37271cab775cSVipul Pandya struct tcp_options_received tmp_opt; 3728f079af7aSVipul Pandya struct c4iw_dev *dev; 3729963cab50SHariprasad S enum chip_type type; 37301cab775cSVipul Pandya 3731f079af7aSVipul Pandya dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *))); 37321cab775cSVipul Pandya /* Store values from cpl_rx_pkt in temporary location. */ 3733963cab50SHariprasad S vlantag = cpl->vlan; 3734963cab50SHariprasad S len = cpl->len; 3735963cab50SHariprasad S l2info = cpl->l2info; 3736963cab50SHariprasad S hdr_len = cpl->hdr_len; 37371cab775cSVipul Pandya intf = cpl->iff; 37381cab775cSVipul Pandya 37391cab775cSVipul Pandya __skb_pull(skb, sizeof(*req) + sizeof(struct rss_header)); 37401cab775cSVipul Pandya 37411cab775cSVipul Pandya /* 37421cab775cSVipul Pandya * We need to parse the TCP options from SYN packet. 37431cab775cSVipul Pandya * to generate cpl_pass_accept_req. 37441cab775cSVipul Pandya */ 37451cab775cSVipul Pandya memset(&tmp_opt, 0, sizeof(tmp_opt)); 37461cab775cSVipul Pandya tcp_clear_options(&tmp_opt); 37471a2c6181SChristoph Paasch tcp_parse_options(skb, &tmp_opt, 0, NULL); 37481cab775cSVipul Pandya 37491cab775cSVipul Pandya req = (struct cpl_pass_accept_req *)__skb_push(skb, sizeof(*req)); 37501cab775cSVipul Pandya memset(req, 0, sizeof(*req)); 3751cf7fe64aSHariprasad Shenai req->l2info = cpu_to_be16(SYN_INTF_V(intf) | 3752cf7fe64aSHariprasad Shenai SYN_MAC_IDX_V(RX_MACIDX_G( 3753963cab50SHariprasad S be32_to_cpu(l2info))) | 3754cf7fe64aSHariprasad Shenai SYN_XACT_MATCH_F); 3755963cab50SHariprasad S type = dev->rdev.lldi.adapter_type; 3756963cab50SHariprasad S tcp_hdr_len = RX_TCPHDR_LEN_G(be16_to_cpu(hdr_len)); 3757963cab50SHariprasad S ip_hdr_len = RX_IPHDR_LEN_G(be16_to_cpu(hdr_len)); 3758963cab50SHariprasad S req->hdr_len = 3759963cab50SHariprasad S cpu_to_be32(SYN_RX_CHAN_V(RX_CHAN_G(be32_to_cpu(l2info)))); 3760963cab50SHariprasad S if (CHELSIO_CHIP_VERSION(type) <= CHELSIO_T5) { 3761963cab50SHariprasad S eth_hdr_len = is_t4(type) ? 3762963cab50SHariprasad S RX_ETHHDR_LEN_G(be32_to_cpu(l2info)) : 3763963cab50SHariprasad S RX_T5_ETHHDR_LEN_G(be32_to_cpu(l2info)); 3764963cab50SHariprasad S req->hdr_len |= cpu_to_be32(TCP_HDR_LEN_V(tcp_hdr_len) | 3765963cab50SHariprasad S IP_HDR_LEN_V(ip_hdr_len) | 3766963cab50SHariprasad S ETH_HDR_LEN_V(eth_hdr_len)); 3767963cab50SHariprasad S } else { /* T6 and later */ 3768963cab50SHariprasad S eth_hdr_len = RX_T6_ETHHDR_LEN_G(be32_to_cpu(l2info)); 3769963cab50SHariprasad S req->hdr_len |= cpu_to_be32(T6_TCP_HDR_LEN_V(tcp_hdr_len) | 3770963cab50SHariprasad S T6_IP_HDR_LEN_V(ip_hdr_len) | 3771963cab50SHariprasad S T6_ETH_HDR_LEN_V(eth_hdr_len)); 3772963cab50SHariprasad S } 3773963cab50SHariprasad S req->vlan = vlantag; 3774963cab50SHariprasad S req->len = len; 37756c53e938SHariprasad Shenai req->tos_stid = cpu_to_be32(PASS_OPEN_TID_V(stid) | 37766c53e938SHariprasad Shenai PASS_OPEN_TOS_V(tos)); 37771cab775cSVipul Pandya req->tcpopt.mss = htons(tmp_opt.mss_clamp); 37781cab775cSVipul Pandya if (tmp_opt.wscale_ok) 37791cab775cSVipul Pandya req->tcpopt.wsf = tmp_opt.snd_wscale; 37801cab775cSVipul Pandya req->tcpopt.tstamp = tmp_opt.saw_tstamp; 37811cab775cSVipul Pandya if (tmp_opt.sack_ok) 37821cab775cSVipul Pandya req->tcpopt.sack = 1; 37831cab775cSVipul Pandya OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_REQ, 0)); 37841cab775cSVipul Pandya return; 37851cab775cSVipul Pandya } 37861cab775cSVipul Pandya 37871cab775cSVipul Pandya static void send_fw_pass_open_req(struct c4iw_dev *dev, struct sk_buff *skb, 37881cab775cSVipul Pandya __be32 laddr, __be16 lport, 37891cab775cSVipul Pandya __be32 raddr, __be16 rport, 37901cab775cSVipul Pandya u32 rcv_isn, u32 filter, u16 window, 37911cab775cSVipul Pandya u32 rss_qid, u8 port_id) 37921cab775cSVipul Pandya { 37931cab775cSVipul Pandya struct sk_buff *req_skb; 37941cab775cSVipul Pandya struct fw_ofld_connection_wr *req; 37951cab775cSVipul Pandya struct cpl_pass_accept_req *cpl = cplhdr(skb); 37961ce1d471SSteve Wise int ret; 37971cab775cSVipul Pandya 37981cab775cSVipul Pandya req_skb = alloc_skb(sizeof(struct fw_ofld_connection_wr), GFP_KERNEL); 37991cab775cSVipul Pandya req = (struct fw_ofld_connection_wr *)__skb_put(req_skb, sizeof(*req)); 38001cab775cSVipul Pandya memset(req, 0, sizeof(*req)); 38016c53e938SHariprasad Shenai req->op_compl = htonl(WR_OP_V(FW_OFLD_CONNECTION_WR) | FW_WR_COMPL_F); 3802e2ac9628SHariprasad Shenai req->len16_pkd = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*req), 16))); 380377a80e23SHariprasad Shenai req->le.version_cpl = htonl(FW_OFLD_CONNECTION_WR_CPL_F); 3804ef5d6355SVipul Pandya req->le.filter = (__force __be32) filter; 38051cab775cSVipul Pandya req->le.lport = lport; 38061cab775cSVipul Pandya req->le.pport = rport; 38071cab775cSVipul Pandya req->le.u.ipv4.lip = laddr; 38081cab775cSVipul Pandya req->le.u.ipv4.pip = raddr; 38091cab775cSVipul Pandya req->tcb.rcv_nxt = htonl(rcv_isn + 1); 38101cab775cSVipul Pandya req->tcb.rcv_adv = htons(window); 38111cab775cSVipul Pandya req->tcb.t_state_to_astid = 381277a80e23SHariprasad Shenai htonl(FW_OFLD_CONNECTION_WR_T_STATE_V(TCP_SYN_RECV) | 381377a80e23SHariprasad Shenai FW_OFLD_CONNECTION_WR_RCV_SCALE_V(cpl->tcpopt.wsf) | 381477a80e23SHariprasad Shenai FW_OFLD_CONNECTION_WR_ASTID_V( 38156c53e938SHariprasad Shenai PASS_OPEN_TID_G(ntohl(cpl->tos_stid)))); 38161cab775cSVipul Pandya 38171cab775cSVipul Pandya /* 38181cab775cSVipul Pandya * We store the qid in opt2 which will be used by the firmware 38191cab775cSVipul Pandya * to send us the wr response. 38201cab775cSVipul Pandya */ 3821d7990b0cSAnish Bhatt req->tcb.opt2 = htonl(RSS_QUEUE_V(rss_qid)); 38221cab775cSVipul Pandya 38231cab775cSVipul Pandya /* 38241cab775cSVipul Pandya * We initialize the MSS index in TCB to 0xF. 38251cab775cSVipul Pandya * So that when driver sends cpl_pass_accept_rpl 38261cab775cSVipul Pandya * TCB picks up the correct value. If this was 0 38271cab775cSVipul Pandya * TP will ignore any value > 0 for MSS index. 38281cab775cSVipul Pandya */ 3829d7990b0cSAnish Bhatt req->tcb.opt0 = cpu_to_be64(MSS_IDX_V(0xF)); 38306198dd8dSHariprasad S req->cookie = (uintptr_t)skb; 38311cab775cSVipul Pandya 38321cab775cSVipul Pandya set_wr_txq(req_skb, CPL_PRIORITY_CONTROL, port_id); 38331ce1d471SSteve Wise ret = cxgb4_ofld_send(dev->rdev.lldi.ports[0], req_skb); 38341ce1d471SSteve Wise if (ret < 0) { 38351ce1d471SSteve Wise pr_err("%s - cxgb4_ofld_send error %d - dropping\n", __func__, 38361ce1d471SSteve Wise ret); 38371ce1d471SSteve Wise kfree_skb(skb); 38381ce1d471SSteve Wise kfree_skb(req_skb); 38391ce1d471SSteve Wise } 38401cab775cSVipul Pandya } 38411cab775cSVipul Pandya 38421cab775cSVipul Pandya /* 38431cab775cSVipul Pandya * Handler for CPL_RX_PKT message. Need to handle cpl_rx_pkt 38441cab775cSVipul Pandya * messages when a filter is being used instead of server to 38451cab775cSVipul Pandya * redirect a syn packet. When packets hit filter they are redirected 38461cab775cSVipul Pandya * to the offload queue and driver tries to establish the connection 38471cab775cSVipul Pandya * using firmware work request. 38481cab775cSVipul Pandya */ 38491cab775cSVipul Pandya static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb) 38501cab775cSVipul Pandya { 38511cab775cSVipul Pandya int stid; 38521cab775cSVipul Pandya unsigned int filter; 38531cab775cSVipul Pandya struct ethhdr *eh = NULL; 38541cab775cSVipul Pandya struct vlan_ethhdr *vlan_eh = NULL; 38551cab775cSVipul Pandya struct iphdr *iph; 38561cab775cSVipul Pandya struct tcphdr *tcph; 38571cab775cSVipul Pandya struct rss_header *rss = (void *)skb->data; 38581cab775cSVipul Pandya struct cpl_rx_pkt *cpl = (void *)skb->data; 38591cab775cSVipul Pandya struct cpl_pass_accept_req *req = (void *)(rss + 1); 38601cab775cSVipul Pandya struct l2t_entry *e; 38611cab775cSVipul Pandya struct dst_entry *dst; 3862f86fac79SHariprasad S struct c4iw_ep *lep = NULL; 38631cab775cSVipul Pandya u16 window; 38641cab775cSVipul Pandya struct port_info *pi; 38651cab775cSVipul Pandya struct net_device *pdev; 3866f079af7aSVipul Pandya u16 rss_qid, eth_hdr_len; 38671cab775cSVipul Pandya int step; 38681cab775cSVipul Pandya u32 tx_chan; 38691cab775cSVipul Pandya struct neighbour *neigh; 38701cab775cSVipul Pandya 38711cab775cSVipul Pandya /* Drop all non-SYN packets */ 3872bdc590b9SHariprasad Shenai if (!(cpl->l2info & cpu_to_be32(RXF_SYN_F))) 38731cab775cSVipul Pandya goto reject; 38741cab775cSVipul Pandya 38751cab775cSVipul Pandya /* 38761cab775cSVipul Pandya * Drop all packets which did not hit the filter. 38771cab775cSVipul Pandya * Unlikely to happen. 38781cab775cSVipul Pandya */ 38791cab775cSVipul Pandya if (!(rss->filter_hit && rss->filter_tid)) 38801cab775cSVipul Pandya goto reject; 38811cab775cSVipul Pandya 38821cab775cSVipul Pandya /* 38831cab775cSVipul Pandya * Calculate the server tid from filter hit index from cpl_rx_pkt. 38841cab775cSVipul Pandya */ 3885a4ea025fSKumar Sanghvi stid = (__force int) cpu_to_be32((__force u32) rss->hash_val); 38861cab775cSVipul Pandya 3887f86fac79SHariprasad S lep = (struct c4iw_ep *)get_ep_from_stid(dev, stid); 38881cab775cSVipul Pandya if (!lep) { 38891cab775cSVipul Pandya PDBG("%s connect request on invalid stid %d\n", __func__, stid); 38901cab775cSVipul Pandya goto reject; 38911cab775cSVipul Pandya } 38921cab775cSVipul Pandya 3893963cab50SHariprasad S switch (CHELSIO_CHIP_VERSION(dev->rdev.lldi.adapter_type)) { 3894963cab50SHariprasad S case CHELSIO_T4: 3895963cab50SHariprasad S eth_hdr_len = RX_ETHHDR_LEN_G(be32_to_cpu(cpl->l2info)); 3896963cab50SHariprasad S break; 3897963cab50SHariprasad S case CHELSIO_T5: 3898963cab50SHariprasad S eth_hdr_len = RX_T5_ETHHDR_LEN_G(be32_to_cpu(cpl->l2info)); 3899963cab50SHariprasad S break; 3900963cab50SHariprasad S case CHELSIO_T6: 3901963cab50SHariprasad S eth_hdr_len = RX_T6_ETHHDR_LEN_G(be32_to_cpu(cpl->l2info)); 3902963cab50SHariprasad S break; 3903963cab50SHariprasad S default: 3904963cab50SHariprasad S pr_err("T%d Chip is not supported\n", 3905963cab50SHariprasad S CHELSIO_CHIP_VERSION(dev->rdev.lldi.adapter_type)); 3906963cab50SHariprasad S goto reject; 3907963cab50SHariprasad S } 3908963cab50SHariprasad S 3909f079af7aSVipul Pandya if (eth_hdr_len == ETH_HLEN) { 39101cab775cSVipul Pandya eh = (struct ethhdr *)(req + 1); 39111cab775cSVipul Pandya iph = (struct iphdr *)(eh + 1); 39121cab775cSVipul Pandya } else { 39131cab775cSVipul Pandya vlan_eh = (struct vlan_ethhdr *)(req + 1); 39141cab775cSVipul Pandya iph = (struct iphdr *)(vlan_eh + 1); 39151cab775cSVipul Pandya skb->vlan_tci = ntohs(cpl->vlan); 39161cab775cSVipul Pandya } 39171cab775cSVipul Pandya 39181cab775cSVipul Pandya if (iph->version != 0x4) 39191cab775cSVipul Pandya goto reject; 39201cab775cSVipul Pandya 39211cab775cSVipul Pandya tcph = (struct tcphdr *)(iph + 1); 39221cab775cSVipul Pandya skb_set_network_header(skb, (void *)iph - (void *)rss); 39231cab775cSVipul Pandya skb_set_transport_header(skb, (void *)tcph - (void *)rss); 39241cab775cSVipul Pandya skb_get(skb); 39251cab775cSVipul Pandya 39261cab775cSVipul Pandya PDBG("%s lip 0x%x lport %u pip 0x%x pport %u tos %d\n", __func__, 39271cab775cSVipul Pandya ntohl(iph->daddr), ntohs(tcph->dest), ntohl(iph->saddr), 39281cab775cSVipul Pandya ntohs(tcph->source), iph->tos); 39291cab775cSVipul Pandya 3930804c2f3eSVarun Prakash dst = cxgb_find_route(&dev->rdev.lldi, get_real_dev, 3931804c2f3eSVarun Prakash iph->daddr, iph->saddr, tcph->dest, 3932804c2f3eSVarun Prakash tcph->source, iph->tos); 3933830662f6SVipul Pandya if (!dst) { 39341cab775cSVipul Pandya pr_err("%s - failed to find dst entry!\n", 39351cab775cSVipul Pandya __func__); 39361cab775cSVipul Pandya goto reject; 39371cab775cSVipul Pandya } 39381cab775cSVipul Pandya neigh = dst_neigh_lookup_skb(dst, skb); 39391cab775cSVipul Pandya 3940aaa0c23cSZhouyi Zhou if (!neigh) { 3941aaa0c23cSZhouyi Zhou pr_err("%s - failed to allocate neigh!\n", 3942aaa0c23cSZhouyi Zhou __func__); 3943aaa0c23cSZhouyi Zhou goto free_dst; 3944aaa0c23cSZhouyi Zhou } 3945aaa0c23cSZhouyi Zhou 39461cab775cSVipul Pandya if (neigh->dev->flags & IFF_LOOPBACK) { 39471cab775cSVipul Pandya pdev = ip_dev_find(&init_net, iph->daddr); 39481cab775cSVipul Pandya e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, 39491cab775cSVipul Pandya pdev, 0); 39501cab775cSVipul Pandya pi = (struct port_info *)netdev_priv(pdev); 39511cab775cSVipul Pandya tx_chan = cxgb4_port_chan(pdev); 39521cab775cSVipul Pandya dev_put(pdev); 39531cab775cSVipul Pandya } else { 3954830662f6SVipul Pandya pdev = get_real_dev(neigh->dev); 39551cab775cSVipul Pandya e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, 3956830662f6SVipul Pandya pdev, 0); 3957830662f6SVipul Pandya pi = (struct port_info *)netdev_priv(pdev); 3958830662f6SVipul Pandya tx_chan = cxgb4_port_chan(pdev); 39591cab775cSVipul Pandya } 3960ebf00060SSteve Wise neigh_release(neigh); 39611cab775cSVipul Pandya if (!e) { 39621cab775cSVipul Pandya pr_err("%s - failed to allocate l2t entry!\n", 39631cab775cSVipul Pandya __func__); 39641cab775cSVipul Pandya goto free_dst; 39651cab775cSVipul Pandya } 39661cab775cSVipul Pandya 39671cab775cSVipul Pandya step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan; 39681cab775cSVipul Pandya rss_qid = dev->rdev.lldi.rxq_ids[pi->port_id * step]; 3969ef5d6355SVipul Pandya window = (__force u16) htons((__force u16)tcph->window); 39701cab775cSVipul Pandya 39711cab775cSVipul Pandya /* Calcuate filter portion for LE region. */ 397241b4f86cSKumar Sanghvi filter = (__force unsigned int) cpu_to_be32(cxgb4_select_ntuple( 397341b4f86cSKumar Sanghvi dev->rdev.lldi.ports[0], 397441b4f86cSKumar Sanghvi e)); 39751cab775cSVipul Pandya 39761cab775cSVipul Pandya /* 39771cab775cSVipul Pandya * Synthesize the cpl_pass_accept_req. We have everything except the 39781cab775cSVipul Pandya * TID. Once firmware sends a reply with TID we update the TID field 39791cab775cSVipul Pandya * in cpl and pass it through the regular cpl_pass_accept_req path. 39801cab775cSVipul Pandya */ 39811cab775cSVipul Pandya build_cpl_pass_accept_req(skb, stid, iph->tos); 39821cab775cSVipul Pandya send_fw_pass_open_req(dev, skb, iph->daddr, tcph->dest, iph->saddr, 39831cab775cSVipul Pandya tcph->source, ntohl(tcph->seq), filter, window, 39841cab775cSVipul Pandya rss_qid, pi->port_id); 39851cab775cSVipul Pandya cxgb4_l2t_release(e); 39861cab775cSVipul Pandya free_dst: 39871cab775cSVipul Pandya dst_release(dst); 39881cab775cSVipul Pandya reject: 3989f86fac79SHariprasad S if (lep) 3990f86fac79SHariprasad S c4iw_put_ep(&lep->com); 39912f5b48c3SSteve Wise return 0; 39922f5b48c3SSteve Wise } 39932f5b48c3SSteve Wise 3994cfdda9d7SSteve Wise /* 3995be4c9badSRoland Dreier * These are the real handlers that are called from a 3996be4c9badSRoland Dreier * work queue. 3997be4c9badSRoland Dreier */ 39989dec900cSHariprasad S static c4iw_handler_func work_handlers[NUM_CPL_CMDS + NUM_FAKE_CPLS] = { 3999be4c9badSRoland Dreier [CPL_ACT_ESTABLISH] = act_establish, 4000be4c9badSRoland Dreier [CPL_ACT_OPEN_RPL] = act_open_rpl, 4001be4c9badSRoland Dreier [CPL_RX_DATA] = rx_data, 4002be4c9badSRoland Dreier [CPL_ABORT_RPL_RSS] = abort_rpl, 4003be4c9badSRoland Dreier [CPL_ABORT_RPL] = abort_rpl, 4004be4c9badSRoland Dreier [CPL_PASS_OPEN_RPL] = pass_open_rpl, 4005be4c9badSRoland Dreier [CPL_CLOSE_LISTSRV_RPL] = close_listsrv_rpl, 4006be4c9badSRoland Dreier [CPL_PASS_ACCEPT_REQ] = pass_accept_req, 4007be4c9badSRoland Dreier [CPL_PASS_ESTABLISH] = pass_establish, 4008be4c9badSRoland Dreier [CPL_PEER_CLOSE] = peer_close, 4009be4c9badSRoland Dreier [CPL_ABORT_REQ_RSS] = peer_abort, 4010be4c9badSRoland Dreier [CPL_CLOSE_CON_RPL] = close_con_rpl, 4011be4c9badSRoland Dreier [CPL_RDMA_TERMINATE] = terminate, 40122f5b48c3SSteve Wise [CPL_FW4_ACK] = fw4_ack, 40131cab775cSVipul Pandya [CPL_FW6_MSG] = deferred_fw6_msg, 40149dec900cSHariprasad S [CPL_RX_PKT] = rx_pkt, 40158d1f1a6bSHariprasad S [FAKE_CPL_PUT_EP_SAFE] = _put_ep_safe, 40168d1f1a6bSHariprasad S [FAKE_CPL_PASS_PUT_EP_SAFE] = _put_pass_ep_safe 4017be4c9badSRoland Dreier }; 4018be4c9badSRoland Dreier 4019be4c9badSRoland Dreier static void process_timeout(struct c4iw_ep *ep) 4020be4c9badSRoland Dreier { 4021be4c9badSRoland Dreier struct c4iw_qp_attributes attrs; 4022be4c9badSRoland Dreier int abort = 1; 4023be4c9badSRoland Dreier 40242f5b48c3SSteve Wise mutex_lock(&ep->com.mutex); 4025be4c9badSRoland Dreier PDBG("%s ep %p tid %u state %d\n", __func__, ep, ep->hwtid, 4026be4c9badSRoland Dreier ep->com.state); 4027793dad94SVipul Pandya set_bit(TIMEDOUT, &ep->com.history); 4028be4c9badSRoland Dreier switch (ep->com.state) { 4029be4c9badSRoland Dreier case MPA_REQ_SENT: 4030be4c9badSRoland Dreier connect_reply_upcall(ep, -ETIMEDOUT); 4031be4c9badSRoland Dreier break; 4032be4c9badSRoland Dreier case MPA_REQ_WAIT: 4033ceb110a8SHariprasad S case MPA_REQ_RCVD: 4034e4b76a2aSHariprasad S case MPA_REP_SENT: 4035ceb110a8SHariprasad S case FPDU_MODE: 4036be4c9badSRoland Dreier break; 4037be4c9badSRoland Dreier case CLOSING: 4038be4c9badSRoland Dreier case MORIBUND: 4039be4c9badSRoland Dreier if (ep->com.cm_id && ep->com.qp) { 4040be4c9badSRoland Dreier attrs.next_state = C4IW_QP_STATE_ERROR; 4041be4c9badSRoland Dreier c4iw_modify_qp(ep->com.qp->rhp, 4042be4c9badSRoland Dreier ep->com.qp, C4IW_QP_ATTR_NEXT_STATE, 4043be4c9badSRoland Dreier &attrs, 1); 4044be4c9badSRoland Dreier } 4045be13b2dfSSteve Wise close_complete_upcall(ep, -ETIMEDOUT); 4046be4c9badSRoland Dreier break; 4047b33bd0cbSSteve Wise case ABORTING: 4048b33bd0cbSSteve Wise case DEAD: 4049b33bd0cbSSteve Wise 4050b33bd0cbSSteve Wise /* 4051b33bd0cbSSteve Wise * These states are expected if the ep timed out at the same 4052b33bd0cbSSteve Wise * time as another thread was calling stop_ep_timer(). 4053b33bd0cbSSteve Wise * So we silently do nothing for these states. 4054b33bd0cbSSteve Wise */ 4055b33bd0cbSSteve Wise abort = 0; 4056b33bd0cbSSteve Wise break; 4057be4c9badSRoland Dreier default: 405876f267b7SJulia Lawall WARN(1, "%s unexpected state ep %p tid %u state %u\n", 4059be4c9badSRoland Dreier __func__, ep, ep->hwtid, ep->com.state); 4060be4c9badSRoland Dreier abort = 0; 4061be4c9badSRoland Dreier } 4062cc18b939SSteve Wise mutex_unlock(&ep->com.mutex); 406369736279SHariprasad S if (abort) 406469736279SHariprasad S c4iw_ep_disconnect(ep, 1, GFP_KERNEL); 4065be4c9badSRoland Dreier c4iw_put_ep(&ep->com); 4066be4c9badSRoland Dreier } 4067be4c9badSRoland Dreier 4068be4c9badSRoland Dreier static void process_timedout_eps(void) 4069be4c9badSRoland Dreier { 4070be4c9badSRoland Dreier struct c4iw_ep *ep; 4071be4c9badSRoland Dreier 4072be4c9badSRoland Dreier spin_lock_irq(&timeout_lock); 4073be4c9badSRoland Dreier while (!list_empty(&timeout_list)) { 4074be4c9badSRoland Dreier struct list_head *tmp; 4075be4c9badSRoland Dreier 4076be4c9badSRoland Dreier tmp = timeout_list.next; 4077be4c9badSRoland Dreier list_del(tmp); 4078b33bd0cbSSteve Wise tmp->next = NULL; 4079b33bd0cbSSteve Wise tmp->prev = NULL; 4080be4c9badSRoland Dreier spin_unlock_irq(&timeout_lock); 4081be4c9badSRoland Dreier ep = list_entry(tmp, struct c4iw_ep, entry); 4082be4c9badSRoland Dreier process_timeout(ep); 4083be4c9badSRoland Dreier spin_lock_irq(&timeout_lock); 4084be4c9badSRoland Dreier } 4085be4c9badSRoland Dreier spin_unlock_irq(&timeout_lock); 4086be4c9badSRoland Dreier } 4087be4c9badSRoland Dreier 4088be4c9badSRoland Dreier static void process_work(struct work_struct *work) 4089be4c9badSRoland Dreier { 4090be4c9badSRoland Dreier struct sk_buff *skb = NULL; 4091be4c9badSRoland Dreier struct c4iw_dev *dev; 4092c1d7356cSDan Carpenter struct cpl_act_establish *rpl; 4093be4c9badSRoland Dreier unsigned int opcode; 4094be4c9badSRoland Dreier int ret; 4095be4c9badSRoland Dreier 4096b33bd0cbSSteve Wise process_timedout_eps(); 4097be4c9badSRoland Dreier while ((skb = skb_dequeue(&rxq))) { 4098be4c9badSRoland Dreier rpl = cplhdr(skb); 4099be4c9badSRoland Dreier dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *))); 4100be4c9badSRoland Dreier opcode = rpl->ot.opcode; 4101be4c9badSRoland Dreier 4102be4c9badSRoland Dreier BUG_ON(!work_handlers[opcode]); 4103be4c9badSRoland Dreier ret = work_handlers[opcode](dev, skb); 4104be4c9badSRoland Dreier if (!ret) 4105be4c9badSRoland Dreier kfree_skb(skb); 4106be4c9badSRoland Dreier process_timedout_eps(); 4107be4c9badSRoland Dreier } 4108b33bd0cbSSteve Wise } 4109be4c9badSRoland Dreier 4110be4c9badSRoland Dreier static DECLARE_WORK(skb_work, process_work); 4111be4c9badSRoland Dreier 4112be4c9badSRoland Dreier static void ep_timeout(unsigned long arg) 4113be4c9badSRoland Dreier { 4114be4c9badSRoland Dreier struct c4iw_ep *ep = (struct c4iw_ep *)arg; 41151ec779ccSVipul Pandya int kickit = 0; 4116be4c9badSRoland Dreier 4117be4c9badSRoland Dreier spin_lock(&timeout_lock); 41181ec779ccSVipul Pandya if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) { 4119b33bd0cbSSteve Wise /* 4120b33bd0cbSSteve Wise * Only insert if it is not already on the list. 4121b33bd0cbSSteve Wise */ 4122b33bd0cbSSteve Wise if (!ep->entry.next) { 4123be4c9badSRoland Dreier list_add_tail(&ep->entry, &timeout_list); 41241ec779ccSVipul Pandya kickit = 1; 41251ec779ccSVipul Pandya } 4126b33bd0cbSSteve Wise } 4127be4c9badSRoland Dreier spin_unlock(&timeout_lock); 41281ec779ccSVipul Pandya if (kickit) 4129be4c9badSRoland Dreier queue_work(workq, &skb_work); 4130be4c9badSRoland Dreier } 4131be4c9badSRoland Dreier 4132be4c9badSRoland Dreier /* 4133cfdda9d7SSteve Wise * All the CM events are handled on a work queue to have a safe context. 4134cfdda9d7SSteve Wise */ 4135cfdda9d7SSteve Wise static int sched(struct c4iw_dev *dev, struct sk_buff *skb) 4136cfdda9d7SSteve Wise { 4137cfdda9d7SSteve Wise 4138cfdda9d7SSteve Wise /* 4139cfdda9d7SSteve Wise * Save dev in the skb->cb area. 4140cfdda9d7SSteve Wise */ 4141cfdda9d7SSteve Wise *((struct c4iw_dev **) (skb->cb + sizeof(void *))) = dev; 4142cfdda9d7SSteve Wise 4143cfdda9d7SSteve Wise /* 4144cfdda9d7SSteve Wise * Queue the skb and schedule the worker thread. 4145cfdda9d7SSteve Wise */ 4146cfdda9d7SSteve Wise skb_queue_tail(&rxq, skb); 4147cfdda9d7SSteve Wise queue_work(workq, &skb_work); 4148cfdda9d7SSteve Wise return 0; 4149cfdda9d7SSteve Wise } 4150cfdda9d7SSteve Wise 4151cfdda9d7SSteve Wise static int set_tcb_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 4152cfdda9d7SSteve Wise { 4153cfdda9d7SSteve Wise struct cpl_set_tcb_rpl *rpl = cplhdr(skb); 4154cfdda9d7SSteve Wise 4155cfdda9d7SSteve Wise if (rpl->status != CPL_ERR_NONE) { 4156cfdda9d7SSteve Wise printk(KERN_ERR MOD "Unexpected SET_TCB_RPL status %u " 4157cfdda9d7SSteve Wise "for tid %u\n", rpl->status, GET_TID(rpl)); 4158cfdda9d7SSteve Wise } 41592f5b48c3SSteve Wise kfree_skb(skb); 4160cfdda9d7SSteve Wise return 0; 4161cfdda9d7SSteve Wise } 4162cfdda9d7SSteve Wise 4163be4c9badSRoland Dreier static int fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb) 4164be4c9badSRoland Dreier { 4165be4c9badSRoland Dreier struct cpl_fw6_msg *rpl = cplhdr(skb); 4166be4c9badSRoland Dreier struct c4iw_wr_wait *wr_waitp; 4167be4c9badSRoland Dreier int ret; 4168be4c9badSRoland Dreier 4169be4c9badSRoland Dreier PDBG("%s type %u\n", __func__, rpl->type); 4170be4c9badSRoland Dreier 4171be4c9badSRoland Dreier switch (rpl->type) { 41725be78ee9SVipul Pandya case FW6_TYPE_WR_RPL: 4173be4c9badSRoland Dreier ret = (int)((be64_to_cpu(rpl->data[0]) >> 8) & 0xff); 4174c8e081a1SRoland Dreier wr_waitp = (struct c4iw_wr_wait *)(__force unsigned long) rpl->data[1]; 4175be4c9badSRoland Dreier PDBG("%s wr_waitp %p ret %u\n", __func__, wr_waitp, ret); 4176d9594d99SSteve Wise if (wr_waitp) 4177d9594d99SSteve Wise c4iw_wake_up(wr_waitp, ret ? -ret : 0); 41782f5b48c3SSteve Wise kfree_skb(skb); 4179be4c9badSRoland Dreier break; 41805be78ee9SVipul Pandya case FW6_TYPE_CQE: 41815be78ee9SVipul Pandya case FW6_TYPE_OFLD_CONNECTION_WR_RPL: 41821cab775cSVipul Pandya sched(dev, skb); 41835be78ee9SVipul Pandya break; 4184be4c9badSRoland Dreier default: 4185be4c9badSRoland Dreier printk(KERN_ERR MOD "%s unexpected fw6 msg type %u\n", __func__, 4186be4c9badSRoland Dreier rpl->type); 41872f5b48c3SSteve Wise kfree_skb(skb); 4188be4c9badSRoland Dreier break; 4189be4c9badSRoland Dreier } 4190be4c9badSRoland Dreier return 0; 4191be4c9badSRoland Dreier } 4192be4c9badSRoland Dreier 41938da7e7a5SSteve Wise static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb) 41948da7e7a5SSteve Wise { 41958da7e7a5SSteve Wise struct cpl_abort_req_rss *req = cplhdr(skb); 41968da7e7a5SSteve Wise struct c4iw_ep *ep; 41978da7e7a5SSteve Wise unsigned int tid = GET_TID(req); 41988da7e7a5SSteve Wise 4199944661ddSHariprasad S ep = get_ep_from_tid(dev, tid); 4200944661ddSHariprasad S /* This EP will be dereferenced in peer_abort() */ 420114b92228SSteve Wise if (!ep) { 420214b92228SSteve Wise printk(KERN_WARNING MOD 420314b92228SSteve Wise "Abort on non-existent endpoint, tid %d\n", tid); 420414b92228SSteve Wise kfree_skb(skb); 420514b92228SSteve Wise return 0; 420614b92228SSteve Wise } 4207b65eef0aSVarun Prakash if (cxgb_is_neg_adv(req->status)) { 4208179d03bbSHariprasad S PDBG("%s Negative advice on abort- tid %u status %d (%s)\n", 4209179d03bbSHariprasad S __func__, ep->hwtid, req->status, 4210179d03bbSHariprasad S neg_adv_str(req->status)); 4211944661ddSHariprasad S goto out; 42128da7e7a5SSteve Wise } 42138da7e7a5SSteve Wise PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid, 42148da7e7a5SSteve Wise ep->com.state); 42158da7e7a5SSteve Wise 42168da7e7a5SSteve Wise c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); 4217944661ddSHariprasad S out: 42188da7e7a5SSteve Wise sched(dev, skb); 42198da7e7a5SSteve Wise return 0; 42208da7e7a5SSteve Wise } 42218da7e7a5SSteve Wise 4222be4c9badSRoland Dreier /* 4223be4c9badSRoland Dreier * Most upcalls from the T4 Core go to sched() to 4224be4c9badSRoland Dreier * schedule the processing on a work queue. 4225be4c9badSRoland Dreier */ 4226be4c9badSRoland Dreier c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS] = { 4227be4c9badSRoland Dreier [CPL_ACT_ESTABLISH] = sched, 4228be4c9badSRoland Dreier [CPL_ACT_OPEN_RPL] = sched, 4229be4c9badSRoland Dreier [CPL_RX_DATA] = sched, 4230be4c9badSRoland Dreier [CPL_ABORT_RPL_RSS] = sched, 4231be4c9badSRoland Dreier [CPL_ABORT_RPL] = sched, 4232be4c9badSRoland Dreier [CPL_PASS_OPEN_RPL] = sched, 4233be4c9badSRoland Dreier [CPL_CLOSE_LISTSRV_RPL] = sched, 4234be4c9badSRoland Dreier [CPL_PASS_ACCEPT_REQ] = sched, 4235be4c9badSRoland Dreier [CPL_PASS_ESTABLISH] = sched, 4236be4c9badSRoland Dreier [CPL_PEER_CLOSE] = sched, 4237be4c9badSRoland Dreier [CPL_CLOSE_CON_RPL] = sched, 42388da7e7a5SSteve Wise [CPL_ABORT_REQ_RSS] = peer_abort_intr, 4239be4c9badSRoland Dreier [CPL_RDMA_TERMINATE] = sched, 4240be4c9badSRoland Dreier [CPL_FW4_ACK] = sched, 4241be4c9badSRoland Dreier [CPL_SET_TCB_RPL] = set_tcb_rpl, 42421cab775cSVipul Pandya [CPL_FW6_MSG] = fw6_msg, 42431cab775cSVipul Pandya [CPL_RX_PKT] = sched 4244be4c9badSRoland Dreier }; 4245be4c9badSRoland Dreier 4246cfdda9d7SSteve Wise int __init c4iw_cm_init(void) 4247cfdda9d7SSteve Wise { 4248be4c9badSRoland Dreier spin_lock_init(&timeout_lock); 4249cfdda9d7SSteve Wise skb_queue_head_init(&rxq); 4250cfdda9d7SSteve Wise 4251cfdda9d7SSteve Wise workq = create_singlethread_workqueue("iw_cxgb4"); 4252cfdda9d7SSteve Wise if (!workq) 4253cfdda9d7SSteve Wise return -ENOMEM; 4254cfdda9d7SSteve Wise 4255cfdda9d7SSteve Wise return 0; 4256cfdda9d7SSteve Wise } 4257cfdda9d7SSteve Wise 425846c1376dSSteve Wise void c4iw_cm_term(void) 4259cfdda9d7SSteve Wise { 4260be4c9badSRoland Dreier WARN_ON(!list_empty(&timeout_list)); 4261cfdda9d7SSteve Wise flush_workqueue(workq); 4262cfdda9d7SSteve Wise destroy_workqueue(workq); 4263cfdda9d7SSteve Wise } 4264