1*fa790ea9SDavid C Somayajulu /*
2*fa790ea9SDavid C Somayajulu * Copyright (c) 2018-2019 Cavium, Inc.
3*fa790ea9SDavid C Somayajulu * All rights reserved.
4*fa790ea9SDavid C Somayajulu *
5*fa790ea9SDavid C Somayajulu * Redistribution and use in source and binary forms, with or without
6*fa790ea9SDavid C Somayajulu * modification, are permitted provided that the following conditions
7*fa790ea9SDavid C Somayajulu * are met:
8*fa790ea9SDavid C Somayajulu *
9*fa790ea9SDavid C Somayajulu * 1. Redistributions of source code must retain the above copyright
10*fa790ea9SDavid C Somayajulu * notice, this list of conditions and the following disclaimer.
11*fa790ea9SDavid C Somayajulu * 2. Redistributions in binary form must reproduce the above copyright
12*fa790ea9SDavid C Somayajulu * notice, this list of conditions and the following disclaimer in the
13*fa790ea9SDavid C Somayajulu * documentation and/or other materials provided with the distribution.
14*fa790ea9SDavid C Somayajulu *
15*fa790ea9SDavid C Somayajulu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16*fa790ea9SDavid C Somayajulu * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*fa790ea9SDavid C Somayajulu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*fa790ea9SDavid C Somayajulu * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19*fa790ea9SDavid C Somayajulu * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20*fa790ea9SDavid C Somayajulu * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21*fa790ea9SDavid C Somayajulu * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22*fa790ea9SDavid C Somayajulu * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23*fa790ea9SDavid C Somayajulu * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24*fa790ea9SDavid C Somayajulu * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25*fa790ea9SDavid C Somayajulu * POSSIBILITY OF SUCH DAMAGE.
26*fa790ea9SDavid C Somayajulu */
27*fa790ea9SDavid C Somayajulu
28*fa790ea9SDavid C Somayajulu /*
29*fa790ea9SDavid C Somayajulu * File : ecore_iwarp.c
30*fa790ea9SDavid C Somayajulu */
31*fa790ea9SDavid C Somayajulu #include <sys/cdefs.h>
32*fa790ea9SDavid C Somayajulu #include "bcm_osal.h"
33*fa790ea9SDavid C Somayajulu #include "ecore.h"
34*fa790ea9SDavid C Somayajulu #include "ecore_status.h"
35*fa790ea9SDavid C Somayajulu #include "ecore_sp_commands.h"
36*fa790ea9SDavid C Somayajulu #include "ecore_cxt.h"
37*fa790ea9SDavid C Somayajulu #include "ecore_rdma.h"
38*fa790ea9SDavid C Somayajulu #include "reg_addr.h"
39*fa790ea9SDavid C Somayajulu #include "ecore_hw.h"
40*fa790ea9SDavid C Somayajulu #include "ecore_hsi_iwarp.h"
41*fa790ea9SDavid C Somayajulu #include "ecore_ll2.h"
42*fa790ea9SDavid C Somayajulu #include "ecore_ooo.h"
43*fa790ea9SDavid C Somayajulu #ifndef LINUX_REMOVE
44*fa790ea9SDavid C Somayajulu #include "ecore_tcp_ip.h"
45*fa790ea9SDavid C Somayajulu #endif
46*fa790ea9SDavid C Somayajulu
47*fa790ea9SDavid C Somayajulu #ifdef _NTDDK_
48*fa790ea9SDavid C Somayajulu #pragma warning(push)
49*fa790ea9SDavid C Somayajulu #pragma warning(disable : 28123)
50*fa790ea9SDavid C Somayajulu #pragma warning(disable : 28167)
51*fa790ea9SDavid C Somayajulu #endif
52*fa790ea9SDavid C Somayajulu
53*fa790ea9SDavid C Somayajulu /* Default values used for MPA Rev 1 */
54*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_ORD_DEFAULT 32
55*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_IRD_DEFAULT 32
56*fa790ea9SDavid C Somayajulu
57*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_MAX_FW_MSS 4120
58*fa790ea9SDavid C Somayajulu
59*fa790ea9SDavid C Somayajulu struct mpa_v2_hdr {
60*fa790ea9SDavid C Somayajulu __be16 ird;
61*fa790ea9SDavid C Somayajulu __be16 ord;
62*fa790ea9SDavid C Somayajulu };
63*fa790ea9SDavid C Somayajulu
64*fa790ea9SDavid C Somayajulu #define MPA_V2_PEER2PEER_MODEL 0x8000
65*fa790ea9SDavid C Somayajulu #define MPA_V2_SEND_RTR 0x4000 /* on ird */
66*fa790ea9SDavid C Somayajulu #define MPA_V2_READ_RTR 0x4000 /* on ord */
67*fa790ea9SDavid C Somayajulu #define MPA_V2_WRITE_RTR 0x8000
68*fa790ea9SDavid C Somayajulu #define MPA_V2_IRD_ORD_MASK 0x3FFF
69*fa790ea9SDavid C Somayajulu
70*fa790ea9SDavid C Somayajulu #define MPA_REV2(_mpa_rev) (_mpa_rev == MPA_NEGOTIATION_TYPE_ENHANCED)
71*fa790ea9SDavid C Somayajulu
72*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_INVALID_TCP_CID 0xffffffff
73*fa790ea9SDavid C Somayajulu /* How many times fin will be sent before FW aborts and send RST */
74*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_MAX_FIN_RT_DEFAULT 2
75*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_RCV_WND_SIZE_MIN (0xffff)
76*fa790ea9SDavid C Somayajulu /* INTERNAL: These numbers are derived from BRB buffer sizes to obtain optimal performance */
77*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_RCV_WND_SIZE_BB_DEF_2_PORTS (200*1024)
78*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_RCV_WND_SIZE_BB_DEF_4_PORTS (100*1024)
79*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_RCV_WND_SIZE_AH_DEF_2_PORTS (150*1024)
80*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_RCV_WND_SIZE_AH_DEF_4_PORTS (90*1024)
81*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_MAX_WND_SCALE (14)
82*fa790ea9SDavid C Somayajulu /* Timestamp header is the length of the timestamp option (10):
83*fa790ea9SDavid C Somayajulu * kind:8 bit, length:8 bit, timestamp:32 bit, ack: 32bit
84*fa790ea9SDavid C Somayajulu * rounded up to a multiple of 4
85*fa790ea9SDavid C Somayajulu */
86*fa790ea9SDavid C Somayajulu #define TIMESTAMP_HEADER_SIZE (12)
87*fa790ea9SDavid C Somayajulu
88*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
89*fa790ea9SDavid C Somayajulu ecore_iwarp_async_event(struct ecore_hwfn *p_hwfn,
90*fa790ea9SDavid C Somayajulu u8 fw_event_code,
91*fa790ea9SDavid C Somayajulu u16 OSAL_UNUSED echo,
92*fa790ea9SDavid C Somayajulu union event_ring_data *data,
93*fa790ea9SDavid C Somayajulu u8 fw_return_code);
94*fa790ea9SDavid C Somayajulu
95*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
96*fa790ea9SDavid C Somayajulu ecore_iwarp_empty_ramrod(struct ecore_hwfn *p_hwfn,
97*fa790ea9SDavid C Somayajulu struct ecore_iwarp_listener *listener);
98*fa790ea9SDavid C Somayajulu
99*fa790ea9SDavid C Somayajulu static OSAL_INLINE struct ecore_iwarp_fpdu *
100*fa790ea9SDavid C Somayajulu ecore_iwarp_get_curr_fpdu(struct ecore_hwfn *p_hwfn, u16 cid);
101*fa790ea9SDavid C Somayajulu
102*fa790ea9SDavid C Somayajulu /* Override devinfo with iWARP specific values */
103*fa790ea9SDavid C Somayajulu void
ecore_iwarp_init_devinfo(struct ecore_hwfn * p_hwfn)104*fa790ea9SDavid C Somayajulu ecore_iwarp_init_devinfo(struct ecore_hwfn *p_hwfn)
105*fa790ea9SDavid C Somayajulu {
106*fa790ea9SDavid C Somayajulu struct ecore_rdma_device *dev = p_hwfn->p_rdma_info->dev;
107*fa790ea9SDavid C Somayajulu
108*fa790ea9SDavid C Somayajulu dev->max_inline = IWARP_REQ_MAX_INLINE_DATA_SIZE;
109*fa790ea9SDavid C Somayajulu dev->max_qp = OSAL_MIN_T(u64,
110*fa790ea9SDavid C Somayajulu IWARP_MAX_QPS,
111*fa790ea9SDavid C Somayajulu p_hwfn->p_rdma_info->num_qps) -
112*fa790ea9SDavid C Somayajulu ECORE_IWARP_PREALLOC_CNT;
113*fa790ea9SDavid C Somayajulu
114*fa790ea9SDavid C Somayajulu dev->max_cq = dev->max_qp;
115*fa790ea9SDavid C Somayajulu
116*fa790ea9SDavid C Somayajulu dev->max_qp_resp_rd_atomic_resc = ECORE_IWARP_IRD_DEFAULT;
117*fa790ea9SDavid C Somayajulu dev->max_qp_req_rd_atomic_resc = ECORE_IWARP_ORD_DEFAULT;
118*fa790ea9SDavid C Somayajulu }
119*fa790ea9SDavid C Somayajulu
120*fa790ea9SDavid C Somayajulu enum _ecore_status_t
ecore_iwarp_init_hw(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)121*fa790ea9SDavid C Somayajulu ecore_iwarp_init_hw(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt)
122*fa790ea9SDavid C Somayajulu {
123*fa790ea9SDavid C Somayajulu p_hwfn->rdma_prs_search_reg = PRS_REG_SEARCH_TCP;
124*fa790ea9SDavid C Somayajulu ecore_wr(p_hwfn, p_ptt, p_hwfn->rdma_prs_search_reg, 1);
125*fa790ea9SDavid C Somayajulu p_hwfn->b_rdma_enabled_in_prs = true;
126*fa790ea9SDavid C Somayajulu
127*fa790ea9SDavid C Somayajulu return 0;
128*fa790ea9SDavid C Somayajulu }
129*fa790ea9SDavid C Somayajulu
130*fa790ea9SDavid C Somayajulu void
ecore_iwarp_init_fw_ramrod(struct ecore_hwfn * p_hwfn,struct iwarp_init_func_ramrod_data * p_ramrod)131*fa790ea9SDavid C Somayajulu ecore_iwarp_init_fw_ramrod(struct ecore_hwfn *p_hwfn,
132*fa790ea9SDavid C Somayajulu struct iwarp_init_func_ramrod_data *p_ramrod)
133*fa790ea9SDavid C Somayajulu {
134*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
135*fa790ea9SDavid C Somayajulu "ooo handle = %d\n",
136*fa790ea9SDavid C Somayajulu p_hwfn->p_rdma_info->iwarp.ll2_ooo_handle);
137*fa790ea9SDavid C Somayajulu
138*fa790ea9SDavid C Somayajulu p_ramrod->iwarp.ll2_ooo_q_index =
139*fa790ea9SDavid C Somayajulu p_hwfn->hw_info.resc_start[ECORE_LL2_QUEUE] +
140*fa790ea9SDavid C Somayajulu p_hwfn->p_rdma_info->iwarp.ll2_ooo_handle;
141*fa790ea9SDavid C Somayajulu
142*fa790ea9SDavid C Somayajulu p_ramrod->tcp.max_fin_rt = ECORE_IWARP_MAX_FIN_RT_DEFAULT;
143*fa790ea9SDavid C Somayajulu return;
144*fa790ea9SDavid C Somayajulu }
145*fa790ea9SDavid C Somayajulu
146*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
ecore_iwarp_alloc_cid(struct ecore_hwfn * p_hwfn,u32 * cid)147*fa790ea9SDavid C Somayajulu ecore_iwarp_alloc_cid(struct ecore_hwfn *p_hwfn, u32 *cid)
148*fa790ea9SDavid C Somayajulu {
149*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
150*fa790ea9SDavid C Somayajulu
151*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&p_hwfn->p_rdma_info->lock);
152*fa790ea9SDavid C Somayajulu
153*fa790ea9SDavid C Somayajulu rc = ecore_rdma_bmap_alloc_id(p_hwfn,
154*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->cid_map,
155*fa790ea9SDavid C Somayajulu cid);
156*fa790ea9SDavid C Somayajulu
157*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&p_hwfn->p_rdma_info->lock);
158*fa790ea9SDavid C Somayajulu *cid += ecore_cxt_get_proto_cid_start(p_hwfn,
159*fa790ea9SDavid C Somayajulu p_hwfn->p_rdma_info->proto);
160*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS) {
161*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "Failed in allocating iwarp cid\n");
162*fa790ea9SDavid C Somayajulu return rc;
163*fa790ea9SDavid C Somayajulu }
164*fa790ea9SDavid C Somayajulu
165*fa790ea9SDavid C Somayajulu rc = ecore_cxt_dynamic_ilt_alloc(p_hwfn, ECORE_ELEM_CXT, *cid);
166*fa790ea9SDavid C Somayajulu
167*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS) {
168*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&p_hwfn->p_rdma_info->lock);
169*fa790ea9SDavid C Somayajulu *cid -= ecore_cxt_get_proto_cid_start(p_hwfn,
170*fa790ea9SDavid C Somayajulu p_hwfn->p_rdma_info->proto);
171*fa790ea9SDavid C Somayajulu
172*fa790ea9SDavid C Somayajulu ecore_bmap_release_id(p_hwfn,
173*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->cid_map,
174*fa790ea9SDavid C Somayajulu *cid);
175*fa790ea9SDavid C Somayajulu
176*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&p_hwfn->p_rdma_info->lock);
177*fa790ea9SDavid C Somayajulu }
178*fa790ea9SDavid C Somayajulu
179*fa790ea9SDavid C Somayajulu return rc;
180*fa790ea9SDavid C Somayajulu }
181*fa790ea9SDavid C Somayajulu
182*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_set_tcp_cid(struct ecore_hwfn * p_hwfn,u32 cid)183*fa790ea9SDavid C Somayajulu ecore_iwarp_set_tcp_cid(struct ecore_hwfn *p_hwfn, u32 cid)
184*fa790ea9SDavid C Somayajulu {
185*fa790ea9SDavid C Somayajulu cid -= ecore_cxt_get_proto_cid_start(p_hwfn,
186*fa790ea9SDavid C Somayajulu p_hwfn->p_rdma_info->proto);
187*fa790ea9SDavid C Somayajulu
188*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&p_hwfn->p_rdma_info->lock);
189*fa790ea9SDavid C Somayajulu ecore_bmap_set_id(p_hwfn,
190*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->tcp_cid_map,
191*fa790ea9SDavid C Somayajulu cid);
192*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&p_hwfn->p_rdma_info->lock);
193*fa790ea9SDavid C Somayajulu }
194*fa790ea9SDavid C Somayajulu
195*fa790ea9SDavid C Somayajulu /* This function allocates a cid for passive tcp ( called from syn receive)
196*fa790ea9SDavid C Somayajulu * the reason it's separate from the regular cid allocation is because it
197*fa790ea9SDavid C Somayajulu * is assured that these cids already have ilt alloacted. They are preallocated
198*fa790ea9SDavid C Somayajulu * to ensure that we won't need to allocate memory during syn processing
199*fa790ea9SDavid C Somayajulu */
200*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
ecore_iwarp_alloc_tcp_cid(struct ecore_hwfn * p_hwfn,u32 * cid)201*fa790ea9SDavid C Somayajulu ecore_iwarp_alloc_tcp_cid(struct ecore_hwfn *p_hwfn, u32 *cid)
202*fa790ea9SDavid C Somayajulu {
203*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
204*fa790ea9SDavid C Somayajulu
205*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&p_hwfn->p_rdma_info->lock);
206*fa790ea9SDavid C Somayajulu
207*fa790ea9SDavid C Somayajulu rc = ecore_rdma_bmap_alloc_id(p_hwfn,
208*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->tcp_cid_map,
209*fa790ea9SDavid C Somayajulu cid);
210*fa790ea9SDavid C Somayajulu
211*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&p_hwfn->p_rdma_info->lock);
212*fa790ea9SDavid C Somayajulu
213*fa790ea9SDavid C Somayajulu *cid += ecore_cxt_get_proto_cid_start(p_hwfn,
214*fa790ea9SDavid C Somayajulu p_hwfn->p_rdma_info->proto);
215*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS) {
216*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
217*fa790ea9SDavid C Somayajulu "can't allocate iwarp tcp cid max-count=%d\n",
218*fa790ea9SDavid C Somayajulu p_hwfn->p_rdma_info->tcp_cid_map.max_count);
219*fa790ea9SDavid C Somayajulu
220*fa790ea9SDavid C Somayajulu *cid = ECORE_IWARP_INVALID_TCP_CID;
221*fa790ea9SDavid C Somayajulu }
222*fa790ea9SDavid C Somayajulu
223*fa790ea9SDavid C Somayajulu return rc;
224*fa790ea9SDavid C Somayajulu }
225*fa790ea9SDavid C Somayajulu
226*fa790ea9SDavid C Somayajulu /* We have two cid maps, one for tcp which should be used only from passive
227*fa790ea9SDavid C Somayajulu * syn processing and replacing a pre-allocated ep in the list. the second
228*fa790ea9SDavid C Somayajulu * for active tcp and for QPs.
229*fa790ea9SDavid C Somayajulu */
ecore_iwarp_cid_cleaned(struct ecore_hwfn * p_hwfn,u32 cid)230*fa790ea9SDavid C Somayajulu static void ecore_iwarp_cid_cleaned(struct ecore_hwfn *p_hwfn, u32 cid)
231*fa790ea9SDavid C Somayajulu {
232*fa790ea9SDavid C Somayajulu cid -= ecore_cxt_get_proto_cid_start(p_hwfn,
233*fa790ea9SDavid C Somayajulu p_hwfn->p_rdma_info->proto);
234*fa790ea9SDavid C Somayajulu
235*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&p_hwfn->p_rdma_info->lock);
236*fa790ea9SDavid C Somayajulu
237*fa790ea9SDavid C Somayajulu if (cid < ECORE_IWARP_PREALLOC_CNT) {
238*fa790ea9SDavid C Somayajulu ecore_bmap_release_id(p_hwfn,
239*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->tcp_cid_map,
240*fa790ea9SDavid C Somayajulu cid);
241*fa790ea9SDavid C Somayajulu } else {
242*fa790ea9SDavid C Somayajulu ecore_bmap_release_id(p_hwfn,
243*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->cid_map,
244*fa790ea9SDavid C Somayajulu cid);
245*fa790ea9SDavid C Somayajulu }
246*fa790ea9SDavid C Somayajulu
247*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&p_hwfn->p_rdma_info->lock);
248*fa790ea9SDavid C Somayajulu }
249*fa790ea9SDavid C Somayajulu
250*fa790ea9SDavid C Somayajulu enum _ecore_status_t
ecore_iwarp_create_qp(struct ecore_hwfn * p_hwfn,struct ecore_rdma_qp * qp,struct ecore_rdma_create_qp_out_params * out_params)251*fa790ea9SDavid C Somayajulu ecore_iwarp_create_qp(struct ecore_hwfn *p_hwfn,
252*fa790ea9SDavid C Somayajulu struct ecore_rdma_qp *qp,
253*fa790ea9SDavid C Somayajulu struct ecore_rdma_create_qp_out_params *out_params)
254*fa790ea9SDavid C Somayajulu {
255*fa790ea9SDavid C Somayajulu struct iwarp_create_qp_ramrod_data *p_ramrod;
256*fa790ea9SDavid C Somayajulu struct ecore_sp_init_data init_data;
257*fa790ea9SDavid C Somayajulu struct ecore_spq_entry *p_ent;
258*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
259*fa790ea9SDavid C Somayajulu u16 physical_queue;
260*fa790ea9SDavid C Somayajulu u32 cid;
261*fa790ea9SDavid C Somayajulu
262*fa790ea9SDavid C Somayajulu qp->shared_queue =
263*fa790ea9SDavid C Somayajulu OSAL_DMA_ALLOC_COHERENT(p_hwfn->p_dev,
264*fa790ea9SDavid C Somayajulu &qp->shared_queue_phys_addr,
265*fa790ea9SDavid C Somayajulu IWARP_SHARED_QUEUE_PAGE_SIZE);
266*fa790ea9SDavid C Somayajulu if (!qp->shared_queue) {
267*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false,
268*fa790ea9SDavid C Somayajulu "ecore iwarp create qp failed: cannot allocate memory (shared queue).\n");
269*fa790ea9SDavid C Somayajulu return ECORE_NOMEM;
270*fa790ea9SDavid C Somayajulu } else {
271*fa790ea9SDavid C Somayajulu out_params->sq_pbl_virt = (u8 *)qp->shared_queue +
272*fa790ea9SDavid C Somayajulu IWARP_SHARED_QUEUE_PAGE_SQ_PBL_OFFSET;
273*fa790ea9SDavid C Somayajulu out_params->sq_pbl_phys = qp->shared_queue_phys_addr +
274*fa790ea9SDavid C Somayajulu IWARP_SHARED_QUEUE_PAGE_SQ_PBL_OFFSET;
275*fa790ea9SDavid C Somayajulu out_params->rq_pbl_virt = (u8 *)qp->shared_queue +
276*fa790ea9SDavid C Somayajulu IWARP_SHARED_QUEUE_PAGE_RQ_PBL_OFFSET;
277*fa790ea9SDavid C Somayajulu out_params->rq_pbl_phys = qp->shared_queue_phys_addr +
278*fa790ea9SDavid C Somayajulu IWARP_SHARED_QUEUE_PAGE_RQ_PBL_OFFSET;
279*fa790ea9SDavid C Somayajulu }
280*fa790ea9SDavid C Somayajulu
281*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_alloc_cid(p_hwfn, &cid);
282*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
283*fa790ea9SDavid C Somayajulu goto err1;
284*fa790ea9SDavid C Somayajulu
285*fa790ea9SDavid C Somayajulu qp->icid = (u16)cid;
286*fa790ea9SDavid C Somayajulu
287*fa790ea9SDavid C Somayajulu OSAL_MEMSET(&init_data, 0, sizeof(init_data));
288*fa790ea9SDavid C Somayajulu init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
289*fa790ea9SDavid C Somayajulu init_data.cid = qp->icid;
290*fa790ea9SDavid C Somayajulu init_data.comp_mode = ECORE_SPQ_MODE_EBLOCK;
291*fa790ea9SDavid C Somayajulu
292*fa790ea9SDavid C Somayajulu rc = ecore_sp_init_request(p_hwfn, &p_ent,
293*fa790ea9SDavid C Somayajulu IWARP_RAMROD_CMD_ID_CREATE_QP,
294*fa790ea9SDavid C Somayajulu PROTOCOLID_IWARP, &init_data);
295*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
296*fa790ea9SDavid C Somayajulu return rc;
297*fa790ea9SDavid C Somayajulu
298*fa790ea9SDavid C Somayajulu p_ramrod = &p_ent->ramrod.iwarp_create_qp;
299*fa790ea9SDavid C Somayajulu
300*fa790ea9SDavid C Somayajulu SET_FIELD(p_ramrod->flags,
301*fa790ea9SDavid C Somayajulu IWARP_CREATE_QP_RAMROD_DATA_FMR_AND_RESERVED_EN,
302*fa790ea9SDavid C Somayajulu qp->fmr_and_reserved_lkey);
303*fa790ea9SDavid C Somayajulu
304*fa790ea9SDavid C Somayajulu SET_FIELD(p_ramrod->flags,
305*fa790ea9SDavid C Somayajulu IWARP_CREATE_QP_RAMROD_DATA_SIGNALED_COMP,
306*fa790ea9SDavid C Somayajulu qp->signal_all);
307*fa790ea9SDavid C Somayajulu
308*fa790ea9SDavid C Somayajulu SET_FIELD(p_ramrod->flags,
309*fa790ea9SDavid C Somayajulu IWARP_CREATE_QP_RAMROD_DATA_RDMA_RD_EN,
310*fa790ea9SDavid C Somayajulu qp->incoming_rdma_read_en);
311*fa790ea9SDavid C Somayajulu
312*fa790ea9SDavid C Somayajulu SET_FIELD(p_ramrod->flags,
313*fa790ea9SDavid C Somayajulu IWARP_CREATE_QP_RAMROD_DATA_RDMA_WR_EN,
314*fa790ea9SDavid C Somayajulu qp->incoming_rdma_write_en);
315*fa790ea9SDavid C Somayajulu
316*fa790ea9SDavid C Somayajulu SET_FIELD(p_ramrod->flags,
317*fa790ea9SDavid C Somayajulu IWARP_CREATE_QP_RAMROD_DATA_ATOMIC_EN,
318*fa790ea9SDavid C Somayajulu qp->incoming_atomic_en);
319*fa790ea9SDavid C Somayajulu
320*fa790ea9SDavid C Somayajulu SET_FIELD(p_ramrod->flags,
321*fa790ea9SDavid C Somayajulu IWARP_CREATE_QP_RAMROD_DATA_SRQ_FLG,
322*fa790ea9SDavid C Somayajulu qp->use_srq);
323*fa790ea9SDavid C Somayajulu
324*fa790ea9SDavid C Somayajulu p_ramrod->pd = qp->pd;
325*fa790ea9SDavid C Somayajulu p_ramrod->sq_num_pages = qp->sq_num_pages;
326*fa790ea9SDavid C Somayajulu p_ramrod->rq_num_pages = qp->rq_num_pages;
327*fa790ea9SDavid C Somayajulu
328*fa790ea9SDavid C Somayajulu p_ramrod->qp_handle_for_cqe.hi = OSAL_CPU_TO_LE32(qp->qp_handle.hi);
329*fa790ea9SDavid C Somayajulu p_ramrod->qp_handle_for_cqe.lo = OSAL_CPU_TO_LE32(qp->qp_handle.lo);
330*fa790ea9SDavid C Somayajulu
331*fa790ea9SDavid C Somayajulu p_ramrod->cq_cid_for_sq =
332*fa790ea9SDavid C Somayajulu OSAL_CPU_TO_LE32((p_hwfn->hw_info.opaque_fid << 16) |
333*fa790ea9SDavid C Somayajulu qp->sq_cq_id);
334*fa790ea9SDavid C Somayajulu p_ramrod->cq_cid_for_rq =
335*fa790ea9SDavid C Somayajulu OSAL_CPU_TO_LE32((p_hwfn->hw_info.opaque_fid << 16) |
336*fa790ea9SDavid C Somayajulu qp->rq_cq_id);
337*fa790ea9SDavid C Somayajulu
338*fa790ea9SDavid C Somayajulu p_ramrod->dpi = OSAL_CPU_TO_LE16(qp->dpi);
339*fa790ea9SDavid C Somayajulu
340*fa790ea9SDavid C Somayajulu physical_queue = ecore_get_cm_pq_idx(p_hwfn, PQ_FLAGS_OFLD);
341*fa790ea9SDavid C Somayajulu p_ramrod->physical_q0 = OSAL_CPU_TO_LE16(physical_queue);
342*fa790ea9SDavid C Somayajulu physical_queue = ecore_get_cm_pq_idx(p_hwfn, PQ_FLAGS_ACK);
343*fa790ea9SDavid C Somayajulu p_ramrod->physical_q1 = OSAL_CPU_TO_LE16(physical_queue);
344*fa790ea9SDavid C Somayajulu
345*fa790ea9SDavid C Somayajulu rc = ecore_spq_post(p_hwfn, p_ent, OSAL_NULL);
346*fa790ea9SDavid C Somayajulu
347*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
348*fa790ea9SDavid C Somayajulu goto err1;
349*fa790ea9SDavid C Somayajulu
350*fa790ea9SDavid C Somayajulu return rc;
351*fa790ea9SDavid C Somayajulu
352*fa790ea9SDavid C Somayajulu err1:
353*fa790ea9SDavid C Somayajulu OSAL_DMA_FREE_COHERENT(p_hwfn->p_dev,
354*fa790ea9SDavid C Somayajulu qp->shared_queue,
355*fa790ea9SDavid C Somayajulu qp->shared_queue_phys_addr,
356*fa790ea9SDavid C Somayajulu IWARP_SHARED_QUEUE_PAGE_SIZE);
357*fa790ea9SDavid C Somayajulu
358*fa790ea9SDavid C Somayajulu return rc;
359*fa790ea9SDavid C Somayajulu }
360*fa790ea9SDavid C Somayajulu
361*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
ecore_iwarp_modify_fw(struct ecore_hwfn * p_hwfn,struct ecore_rdma_qp * qp)362*fa790ea9SDavid C Somayajulu ecore_iwarp_modify_fw(struct ecore_hwfn *p_hwfn,
363*fa790ea9SDavid C Somayajulu struct ecore_rdma_qp *qp)
364*fa790ea9SDavid C Somayajulu {
365*fa790ea9SDavid C Somayajulu struct iwarp_modify_qp_ramrod_data *p_ramrod;
366*fa790ea9SDavid C Somayajulu struct ecore_sp_init_data init_data;
367*fa790ea9SDavid C Somayajulu struct ecore_spq_entry *p_ent;
368*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
369*fa790ea9SDavid C Somayajulu
370*fa790ea9SDavid C Somayajulu /* Get SPQ entry */
371*fa790ea9SDavid C Somayajulu OSAL_MEMSET(&init_data, 0, sizeof(init_data));
372*fa790ea9SDavid C Somayajulu init_data.cid = qp->icid;
373*fa790ea9SDavid C Somayajulu init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
374*fa790ea9SDavid C Somayajulu init_data.comp_mode = ECORE_SPQ_MODE_EBLOCK;
375*fa790ea9SDavid C Somayajulu
376*fa790ea9SDavid C Somayajulu rc = ecore_sp_init_request(p_hwfn, &p_ent,
377*fa790ea9SDavid C Somayajulu IWARP_RAMROD_CMD_ID_MODIFY_QP,
378*fa790ea9SDavid C Somayajulu p_hwfn->p_rdma_info->proto,
379*fa790ea9SDavid C Somayajulu &init_data);
380*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
381*fa790ea9SDavid C Somayajulu return rc;
382*fa790ea9SDavid C Somayajulu
383*fa790ea9SDavid C Somayajulu p_ramrod = &p_ent->ramrod.iwarp_modify_qp;
384*fa790ea9SDavid C Somayajulu SET_FIELD(p_ramrod->flags, IWARP_MODIFY_QP_RAMROD_DATA_STATE_TRANS_EN,
385*fa790ea9SDavid C Somayajulu 0x1);
386*fa790ea9SDavid C Somayajulu if (qp->iwarp_state == ECORE_IWARP_QP_STATE_CLOSING)
387*fa790ea9SDavid C Somayajulu p_ramrod->transition_to_state = IWARP_MODIFY_QP_STATE_CLOSING;
388*fa790ea9SDavid C Somayajulu else
389*fa790ea9SDavid C Somayajulu p_ramrod->transition_to_state = IWARP_MODIFY_QP_STATE_ERROR;
390*fa790ea9SDavid C Somayajulu
391*fa790ea9SDavid C Somayajulu rc = ecore_spq_post(p_hwfn, p_ent, OSAL_NULL);
392*fa790ea9SDavid C Somayajulu
393*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "QP(0x%x)rc=%d\n",
394*fa790ea9SDavid C Somayajulu qp->icid, rc);
395*fa790ea9SDavid C Somayajulu
396*fa790ea9SDavid C Somayajulu return rc;
397*fa790ea9SDavid C Somayajulu }
398*fa790ea9SDavid C Somayajulu
399*fa790ea9SDavid C Somayajulu enum ecore_iwarp_qp_state
ecore_roce2iwarp_state(enum ecore_roce_qp_state state)400*fa790ea9SDavid C Somayajulu ecore_roce2iwarp_state(enum ecore_roce_qp_state state)
401*fa790ea9SDavid C Somayajulu {
402*fa790ea9SDavid C Somayajulu switch (state) {
403*fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_RESET:
404*fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_INIT:
405*fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_RTR:
406*fa790ea9SDavid C Somayajulu return ECORE_IWARP_QP_STATE_IDLE;
407*fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_RTS:
408*fa790ea9SDavid C Somayajulu return ECORE_IWARP_QP_STATE_RTS;
409*fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_SQD:
410*fa790ea9SDavid C Somayajulu return ECORE_IWARP_QP_STATE_CLOSING;
411*fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_ERR:
412*fa790ea9SDavid C Somayajulu return ECORE_IWARP_QP_STATE_ERROR;
413*fa790ea9SDavid C Somayajulu case ECORE_ROCE_QP_STATE_SQE:
414*fa790ea9SDavid C Somayajulu return ECORE_IWARP_QP_STATE_TERMINATE;
415*fa790ea9SDavid C Somayajulu }
416*fa790ea9SDavid C Somayajulu return ECORE_IWARP_QP_STATE_ERROR;
417*fa790ea9SDavid C Somayajulu }
418*fa790ea9SDavid C Somayajulu
419*fa790ea9SDavid C Somayajulu static enum ecore_roce_qp_state
ecore_iwarp2roce_state(enum ecore_iwarp_qp_state state)420*fa790ea9SDavid C Somayajulu ecore_iwarp2roce_state(enum ecore_iwarp_qp_state state)
421*fa790ea9SDavid C Somayajulu {
422*fa790ea9SDavid C Somayajulu switch (state) {
423*fa790ea9SDavid C Somayajulu case ECORE_IWARP_QP_STATE_IDLE:
424*fa790ea9SDavid C Somayajulu return ECORE_ROCE_QP_STATE_INIT;
425*fa790ea9SDavid C Somayajulu case ECORE_IWARP_QP_STATE_RTS:
426*fa790ea9SDavid C Somayajulu return ECORE_ROCE_QP_STATE_RTS;
427*fa790ea9SDavid C Somayajulu case ECORE_IWARP_QP_STATE_TERMINATE:
428*fa790ea9SDavid C Somayajulu return ECORE_ROCE_QP_STATE_SQE;
429*fa790ea9SDavid C Somayajulu case ECORE_IWARP_QP_STATE_CLOSING:
430*fa790ea9SDavid C Somayajulu return ECORE_ROCE_QP_STATE_SQD;
431*fa790ea9SDavid C Somayajulu case ECORE_IWARP_QP_STATE_ERROR:
432*fa790ea9SDavid C Somayajulu return ECORE_ROCE_QP_STATE_ERR;
433*fa790ea9SDavid C Somayajulu }
434*fa790ea9SDavid C Somayajulu return ECORE_ROCE_QP_STATE_ERR;
435*fa790ea9SDavid C Somayajulu }
436*fa790ea9SDavid C Somayajulu
437*fa790ea9SDavid C Somayajulu const char *iwarp_state_names[] = {
438*fa790ea9SDavid C Somayajulu "IDLE",
439*fa790ea9SDavid C Somayajulu "RTS",
440*fa790ea9SDavid C Somayajulu "TERMINATE",
441*fa790ea9SDavid C Somayajulu "CLOSING",
442*fa790ea9SDavid C Somayajulu "ERROR",
443*fa790ea9SDavid C Somayajulu };
444*fa790ea9SDavid C Somayajulu
445*fa790ea9SDavid C Somayajulu enum _ecore_status_t
ecore_iwarp_modify_qp(struct ecore_hwfn * p_hwfn,struct ecore_rdma_qp * qp,enum ecore_iwarp_qp_state new_state,bool internal)446*fa790ea9SDavid C Somayajulu ecore_iwarp_modify_qp(struct ecore_hwfn *p_hwfn,
447*fa790ea9SDavid C Somayajulu struct ecore_rdma_qp *qp,
448*fa790ea9SDavid C Somayajulu enum ecore_iwarp_qp_state new_state,
449*fa790ea9SDavid C Somayajulu bool internal)
450*fa790ea9SDavid C Somayajulu {
451*fa790ea9SDavid C Somayajulu enum ecore_iwarp_qp_state prev_iw_state;
452*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc = 0;
453*fa790ea9SDavid C Somayajulu bool modify_fw = false;
454*fa790ea9SDavid C Somayajulu
455*fa790ea9SDavid C Somayajulu /* modify QP can be called from upper-layer or as a result of async
456*fa790ea9SDavid C Somayajulu * RST/FIN... therefore need to protect
457*fa790ea9SDavid C Somayajulu */
458*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&p_hwfn->p_rdma_info->iwarp.qp_lock);
459*fa790ea9SDavid C Somayajulu prev_iw_state = qp->iwarp_state;
460*fa790ea9SDavid C Somayajulu
461*fa790ea9SDavid C Somayajulu if (prev_iw_state == new_state) {
462*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&p_hwfn->p_rdma_info->iwarp.qp_lock);
463*fa790ea9SDavid C Somayajulu return ECORE_SUCCESS;
464*fa790ea9SDavid C Somayajulu }
465*fa790ea9SDavid C Somayajulu
466*fa790ea9SDavid C Somayajulu switch (prev_iw_state) {
467*fa790ea9SDavid C Somayajulu case ECORE_IWARP_QP_STATE_IDLE:
468*fa790ea9SDavid C Somayajulu switch (new_state) {
469*fa790ea9SDavid C Somayajulu case ECORE_IWARP_QP_STATE_RTS:
470*fa790ea9SDavid C Somayajulu qp->iwarp_state = ECORE_IWARP_QP_STATE_RTS;
471*fa790ea9SDavid C Somayajulu break;
472*fa790ea9SDavid C Somayajulu case ECORE_IWARP_QP_STATE_ERROR:
473*fa790ea9SDavid C Somayajulu qp->iwarp_state = ECORE_IWARP_QP_STATE_ERROR;
474*fa790ea9SDavid C Somayajulu if (!internal)
475*fa790ea9SDavid C Somayajulu modify_fw = true;
476*fa790ea9SDavid C Somayajulu break;
477*fa790ea9SDavid C Somayajulu default:
478*fa790ea9SDavid C Somayajulu break;
479*fa790ea9SDavid C Somayajulu }
480*fa790ea9SDavid C Somayajulu break;
481*fa790ea9SDavid C Somayajulu case ECORE_IWARP_QP_STATE_RTS:
482*fa790ea9SDavid C Somayajulu switch (new_state) {
483*fa790ea9SDavid C Somayajulu case ECORE_IWARP_QP_STATE_CLOSING:
484*fa790ea9SDavid C Somayajulu if (!internal)
485*fa790ea9SDavid C Somayajulu modify_fw = true;
486*fa790ea9SDavid C Somayajulu
487*fa790ea9SDavid C Somayajulu qp->iwarp_state = ECORE_IWARP_QP_STATE_CLOSING;
488*fa790ea9SDavid C Somayajulu break;
489*fa790ea9SDavid C Somayajulu case ECORE_IWARP_QP_STATE_ERROR:
490*fa790ea9SDavid C Somayajulu if (!internal)
491*fa790ea9SDavid C Somayajulu modify_fw = true;
492*fa790ea9SDavid C Somayajulu qp->iwarp_state = ECORE_IWARP_QP_STATE_ERROR;
493*fa790ea9SDavid C Somayajulu break;
494*fa790ea9SDavid C Somayajulu default:
495*fa790ea9SDavid C Somayajulu break;
496*fa790ea9SDavid C Somayajulu }
497*fa790ea9SDavid C Somayajulu break;
498*fa790ea9SDavid C Somayajulu case ECORE_IWARP_QP_STATE_ERROR:
499*fa790ea9SDavid C Somayajulu switch (new_state) {
500*fa790ea9SDavid C Somayajulu case ECORE_IWARP_QP_STATE_IDLE:
501*fa790ea9SDavid C Somayajulu /* TODO: destroy flow -> need to destroy EP&QP */
502*fa790ea9SDavid C Somayajulu qp->iwarp_state = new_state;
503*fa790ea9SDavid C Somayajulu break;
504*fa790ea9SDavid C Somayajulu case ECORE_IWARP_QP_STATE_CLOSING:
505*fa790ea9SDavid C Somayajulu /* could happen due to race... do nothing.... */
506*fa790ea9SDavid C Somayajulu break;
507*fa790ea9SDavid C Somayajulu default:
508*fa790ea9SDavid C Somayajulu rc = ECORE_INVAL;
509*fa790ea9SDavid C Somayajulu }
510*fa790ea9SDavid C Somayajulu break;
511*fa790ea9SDavid C Somayajulu case ECORE_IWARP_QP_STATE_TERMINATE:
512*fa790ea9SDavid C Somayajulu case ECORE_IWARP_QP_STATE_CLOSING:
513*fa790ea9SDavid C Somayajulu qp->iwarp_state = new_state;
514*fa790ea9SDavid C Somayajulu break;
515*fa790ea9SDavid C Somayajulu default:
516*fa790ea9SDavid C Somayajulu break;
517*fa790ea9SDavid C Somayajulu }
518*fa790ea9SDavid C Somayajulu
519*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "QP(0x%x) %s --> %s %s\n",
520*fa790ea9SDavid C Somayajulu qp->icid,
521*fa790ea9SDavid C Somayajulu iwarp_state_names[prev_iw_state],
522*fa790ea9SDavid C Somayajulu iwarp_state_names[qp->iwarp_state],
523*fa790ea9SDavid C Somayajulu internal ? "internal" : " ");
524*fa790ea9SDavid C Somayajulu
525*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&p_hwfn->p_rdma_info->iwarp.qp_lock);
526*fa790ea9SDavid C Somayajulu
527*fa790ea9SDavid C Somayajulu if (modify_fw)
528*fa790ea9SDavid C Somayajulu ecore_iwarp_modify_fw(p_hwfn, qp);
529*fa790ea9SDavid C Somayajulu
530*fa790ea9SDavid C Somayajulu return rc;
531*fa790ea9SDavid C Somayajulu }
532*fa790ea9SDavid C Somayajulu
533*fa790ea9SDavid C Somayajulu enum _ecore_status_t
ecore_iwarp_fw_destroy(struct ecore_hwfn * p_hwfn,struct ecore_rdma_qp * qp)534*fa790ea9SDavid C Somayajulu ecore_iwarp_fw_destroy(struct ecore_hwfn *p_hwfn,
535*fa790ea9SDavid C Somayajulu struct ecore_rdma_qp *qp)
536*fa790ea9SDavid C Somayajulu {
537*fa790ea9SDavid C Somayajulu struct ecore_sp_init_data init_data;
538*fa790ea9SDavid C Somayajulu struct ecore_spq_entry *p_ent;
539*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
540*fa790ea9SDavid C Somayajulu
541*fa790ea9SDavid C Somayajulu /* Get SPQ entry */
542*fa790ea9SDavid C Somayajulu OSAL_MEMSET(&init_data, 0, sizeof(init_data));
543*fa790ea9SDavid C Somayajulu init_data.cid = qp->icid;
544*fa790ea9SDavid C Somayajulu init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
545*fa790ea9SDavid C Somayajulu init_data.comp_mode = ECORE_SPQ_MODE_EBLOCK;
546*fa790ea9SDavid C Somayajulu
547*fa790ea9SDavid C Somayajulu rc = ecore_sp_init_request(p_hwfn, &p_ent,
548*fa790ea9SDavid C Somayajulu IWARP_RAMROD_CMD_ID_DESTROY_QP,
549*fa790ea9SDavid C Somayajulu p_hwfn->p_rdma_info->proto,
550*fa790ea9SDavid C Somayajulu &init_data);
551*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
552*fa790ea9SDavid C Somayajulu return rc;
553*fa790ea9SDavid C Somayajulu
554*fa790ea9SDavid C Somayajulu rc = ecore_spq_post(p_hwfn, p_ent, OSAL_NULL);
555*fa790ea9SDavid C Somayajulu
556*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "QP(0x%x) rc = %d\n", qp->icid, rc);
557*fa790ea9SDavid C Somayajulu
558*fa790ea9SDavid C Somayajulu return rc;
559*fa790ea9SDavid C Somayajulu }
560*fa790ea9SDavid C Somayajulu
ecore_iwarp_destroy_ep(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_ep * ep,bool remove_from_active_list)561*fa790ea9SDavid C Somayajulu static void ecore_iwarp_destroy_ep(struct ecore_hwfn *p_hwfn,
562*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep,
563*fa790ea9SDavid C Somayajulu bool remove_from_active_list)
564*fa790ea9SDavid C Somayajulu {
565*fa790ea9SDavid C Somayajulu OSAL_DMA_FREE_COHERENT(p_hwfn->p_dev,
566*fa790ea9SDavid C Somayajulu ep->ep_buffer_virt,
567*fa790ea9SDavid C Somayajulu ep->ep_buffer_phys,
568*fa790ea9SDavid C Somayajulu sizeof(*ep->ep_buffer_virt));
569*fa790ea9SDavid C Somayajulu
570*fa790ea9SDavid C Somayajulu if (remove_from_active_list) {
571*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
572*fa790ea9SDavid C Somayajulu
573*fa790ea9SDavid C Somayajulu OSAL_LIST_REMOVE_ENTRY(&ep->list_entry,
574*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->iwarp.ep_list);
575*fa790ea9SDavid C Somayajulu
576*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
577*fa790ea9SDavid C Somayajulu }
578*fa790ea9SDavid C Somayajulu
579*fa790ea9SDavid C Somayajulu if (ep->qp)
580*fa790ea9SDavid C Somayajulu ep->qp->ep = OSAL_NULL;
581*fa790ea9SDavid C Somayajulu
582*fa790ea9SDavid C Somayajulu OSAL_FREE(p_hwfn->p_dev, ep);
583*fa790ea9SDavid C Somayajulu }
584*fa790ea9SDavid C Somayajulu
585*fa790ea9SDavid C Somayajulu enum _ecore_status_t
ecore_iwarp_destroy_qp(struct ecore_hwfn * p_hwfn,struct ecore_rdma_qp * qp)586*fa790ea9SDavid C Somayajulu ecore_iwarp_destroy_qp(struct ecore_hwfn *p_hwfn,
587*fa790ea9SDavid C Somayajulu struct ecore_rdma_qp *qp)
588*fa790ea9SDavid C Somayajulu {
589*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc = ECORE_SUCCESS;
590*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep = qp->ep;
591*fa790ea9SDavid C Somayajulu struct ecore_iwarp_fpdu *fpdu;
592*fa790ea9SDavid C Somayajulu int wait_count = 0;
593*fa790ea9SDavid C Somayajulu
594*fa790ea9SDavid C Somayajulu fpdu = ecore_iwarp_get_curr_fpdu(p_hwfn, qp->icid);
595*fa790ea9SDavid C Somayajulu if (fpdu && fpdu->incomplete_bytes)
596*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false,
597*fa790ea9SDavid C Somayajulu "Pending Partial fpdu with incomplete bytes=%d\n",
598*fa790ea9SDavid C Somayajulu fpdu->incomplete_bytes);
599*fa790ea9SDavid C Somayajulu
600*fa790ea9SDavid C Somayajulu if (qp->iwarp_state != ECORE_IWARP_QP_STATE_ERROR) {
601*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_modify_qp(p_hwfn, qp,
602*fa790ea9SDavid C Somayajulu ECORE_IWARP_QP_STATE_ERROR,
603*fa790ea9SDavid C Somayajulu false);
604*fa790ea9SDavid C Somayajulu
605*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
606*fa790ea9SDavid C Somayajulu return rc;
607*fa790ea9SDavid C Somayajulu }
608*fa790ea9SDavid C Somayajulu
609*fa790ea9SDavid C Somayajulu /* Make sure ep is closed before returning and freeing memory. */
610*fa790ea9SDavid C Somayajulu if (ep) {
611*fa790ea9SDavid C Somayajulu while (ep->state != ECORE_IWARP_EP_CLOSED) {
612*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
613*fa790ea9SDavid C Somayajulu "Waiting for ep->state to be closed...state=%x\n",
614*fa790ea9SDavid C Somayajulu ep->state);
615*fa790ea9SDavid C Somayajulu
616*fa790ea9SDavid C Somayajulu OSAL_MSLEEP(100);
617*fa790ea9SDavid C Somayajulu if (wait_count++ > 200) {
618*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "ep state close timeout state=%x\n",
619*fa790ea9SDavid C Somayajulu ep->state);
620*fa790ea9SDavid C Somayajulu break;
621*fa790ea9SDavid C Somayajulu }
622*fa790ea9SDavid C Somayajulu }
623*fa790ea9SDavid C Somayajulu
624*fa790ea9SDavid C Somayajulu ecore_iwarp_destroy_ep(p_hwfn, ep, false);
625*fa790ea9SDavid C Somayajulu }
626*fa790ea9SDavid C Somayajulu
627*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_fw_destroy(p_hwfn, qp);
628*fa790ea9SDavid C Somayajulu
629*fa790ea9SDavid C Somayajulu if (qp->shared_queue)
630*fa790ea9SDavid C Somayajulu OSAL_DMA_FREE_COHERENT(p_hwfn->p_dev,
631*fa790ea9SDavid C Somayajulu qp->shared_queue,
632*fa790ea9SDavid C Somayajulu qp->shared_queue_phys_addr,
633*fa790ea9SDavid C Somayajulu IWARP_SHARED_QUEUE_PAGE_SIZE);
634*fa790ea9SDavid C Somayajulu
635*fa790ea9SDavid C Somayajulu return rc;
636*fa790ea9SDavid C Somayajulu }
637*fa790ea9SDavid C Somayajulu
638*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
ecore_iwarp_create_ep(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_ep ** ep_out)639*fa790ea9SDavid C Somayajulu ecore_iwarp_create_ep(struct ecore_hwfn *p_hwfn,
640*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep **ep_out)
641*fa790ea9SDavid C Somayajulu {
642*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep;
643*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
644*fa790ea9SDavid C Somayajulu
645*fa790ea9SDavid C Somayajulu ep = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL, sizeof(*ep));
646*fa790ea9SDavid C Somayajulu if (!ep) {
647*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false,
648*fa790ea9SDavid C Somayajulu "ecore create ep failed: cannot allocate memory (ep). rc = %d\n",
649*fa790ea9SDavid C Somayajulu ECORE_NOMEM);
650*fa790ea9SDavid C Somayajulu return ECORE_NOMEM;
651*fa790ea9SDavid C Somayajulu }
652*fa790ea9SDavid C Somayajulu
653*fa790ea9SDavid C Somayajulu ep->state = ECORE_IWARP_EP_INIT;
654*fa790ea9SDavid C Somayajulu
655*fa790ea9SDavid C Somayajulu /* ep_buffer is allocated once and is structured as follows:
656*fa790ea9SDavid C Somayajulu * [MAX_PRIV_DATA_LEN][MAX_PRIV_DATA_LEN][union async_output]
657*fa790ea9SDavid C Somayajulu * We could have allocated this in three calls but since all together
658*fa790ea9SDavid C Somayajulu * it is less than a page, we do one allocation and initialize pointers
659*fa790ea9SDavid C Somayajulu * accordingly
660*fa790ea9SDavid C Somayajulu */
661*fa790ea9SDavid C Somayajulu ep->ep_buffer_virt = OSAL_DMA_ALLOC_COHERENT(
662*fa790ea9SDavid C Somayajulu p_hwfn->p_dev,
663*fa790ea9SDavid C Somayajulu &ep->ep_buffer_phys,
664*fa790ea9SDavid C Somayajulu sizeof(*ep->ep_buffer_virt));
665*fa790ea9SDavid C Somayajulu
666*fa790ea9SDavid C Somayajulu if (!ep->ep_buffer_virt) {
667*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false,
668*fa790ea9SDavid C Somayajulu "ecore create ep failed: cannot allocate memory (ulp buffer). rc = %d\n",
669*fa790ea9SDavid C Somayajulu ECORE_NOMEM);
670*fa790ea9SDavid C Somayajulu rc = ECORE_NOMEM;
671*fa790ea9SDavid C Somayajulu goto err;
672*fa790ea9SDavid C Somayajulu }
673*fa790ea9SDavid C Somayajulu
674*fa790ea9SDavid C Somayajulu ep->sig = 0xdeadbeef;
675*fa790ea9SDavid C Somayajulu
676*fa790ea9SDavid C Somayajulu *ep_out = ep;
677*fa790ea9SDavid C Somayajulu
678*fa790ea9SDavid C Somayajulu return ECORE_SUCCESS;
679*fa790ea9SDavid C Somayajulu
680*fa790ea9SDavid C Somayajulu err:
681*fa790ea9SDavid C Somayajulu OSAL_FREE(p_hwfn->p_dev, ep);
682*fa790ea9SDavid C Somayajulu return rc;
683*fa790ea9SDavid C Somayajulu }
684*fa790ea9SDavid C Somayajulu
685*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_print_tcp_ramrod(struct ecore_hwfn * p_hwfn,struct iwarp_tcp_offload_ramrod_data * p_tcp_ramrod)686*fa790ea9SDavid C Somayajulu ecore_iwarp_print_tcp_ramrod(struct ecore_hwfn *p_hwfn,
687*fa790ea9SDavid C Somayajulu struct iwarp_tcp_offload_ramrod_data *p_tcp_ramrod)
688*fa790ea9SDavid C Somayajulu {
689*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, ">>> PRINT TCP RAMROD\n");
690*fa790ea9SDavid C Somayajulu
691*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "local_mac=%x %x %x\n",
692*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.local_mac_addr_lo,
693*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.local_mac_addr_mid,
694*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.local_mac_addr_hi);
695*fa790ea9SDavid C Somayajulu
696*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "remote_mac=%x %x %x\n",
697*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.remote_mac_addr_lo,
698*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.remote_mac_addr_mid,
699*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.remote_mac_addr_hi);
700*fa790ea9SDavid C Somayajulu
701*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "vlan_id=%x\n",
702*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.vlan_id);
703*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "flags=%x\n",
704*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.flags);
705*fa790ea9SDavid C Somayajulu
706*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "ip_version=%x\n",
707*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.ip_version);
708*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "local_ip=%x.%x.%x.%x\n",
709*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.local_ip[0],
710*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.local_ip[1],
711*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.local_ip[2],
712*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.local_ip[3]);
713*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "remote_ip=%x.%x.%x.%x\n",
714*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.remote_ip[0],
715*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.remote_ip[1],
716*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.remote_ip[2],
717*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.remote_ip[3]);
718*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "flow_label=%x\n",
719*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.flow_label);
720*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "ttl=%x\n",
721*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.ttl);
722*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "tos_or_tc=%x\n",
723*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.tos_or_tc);
724*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "local_port=%x\n",
725*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.local_port);
726*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "remote_port=%x\n",
727*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.remote_port);
728*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "mss=%x\n",
729*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.mss);
730*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "rcv_wnd_scale=%x\n",
731*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.rcv_wnd_scale);
732*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "connect_mode=%x\n",
733*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.connect_mode);
734*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "syn_ip_payload_length=%x\n",
735*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.syn_ip_payload_length);
736*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "syn_phy_addr_lo=%x\n",
737*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.syn_phy_addr_lo);
738*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "syn_phy_addr_hi=%x\n",
739*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.syn_phy_addr_hi);
740*fa790ea9SDavid C Somayajulu
741*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "<<<f PRINT TCP RAMROD\n");
742*fa790ea9SDavid C Somayajulu }
743*fa790ea9SDavid C Somayajulu
744*fa790ea9SDavid C Somayajulu /* Default values for tcp option2 */
745*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_DEF_MAX_RT_TIME (0)
746*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_DEF_CWND_FACTOR (4)
747*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_DEF_KA_MAX_PROBE_CNT (5)
748*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_DEF_KA_TIMEOUT (1200000) /* 20 min */
749*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_DEF_KA_INTERVAL (1000) /* 1 sec */
750*fa790ea9SDavid C Somayajulu
751*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
ecore_iwarp_tcp_offload(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_ep * ep)752*fa790ea9SDavid C Somayajulu ecore_iwarp_tcp_offload(struct ecore_hwfn *p_hwfn,
753*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep)
754*fa790ea9SDavid C Somayajulu {
755*fa790ea9SDavid C Somayajulu struct ecore_iwarp_info *iwarp_info = &p_hwfn->p_rdma_info->iwarp;
756*fa790ea9SDavid C Somayajulu struct iwarp_tcp_offload_ramrod_data *p_tcp_ramrod;
757*fa790ea9SDavid C Somayajulu struct ecore_sp_init_data init_data;
758*fa790ea9SDavid C Somayajulu struct ecore_spq_entry *p_ent;
759*fa790ea9SDavid C Somayajulu dma_addr_t async_output_phys;
760*fa790ea9SDavid C Somayajulu dma_addr_t in_pdata_phys;
761*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
762*fa790ea9SDavid C Somayajulu u16 physical_q;
763*fa790ea9SDavid C Somayajulu u8 tcp_flags;
764*fa790ea9SDavid C Somayajulu int i;
765*fa790ea9SDavid C Somayajulu
766*fa790ea9SDavid C Somayajulu OSAL_MEMSET(&init_data, 0, sizeof(init_data));
767*fa790ea9SDavid C Somayajulu init_data.cid = ep->tcp_cid;
768*fa790ea9SDavid C Somayajulu init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
769*fa790ea9SDavid C Somayajulu
770*fa790ea9SDavid C Somayajulu if (ep->connect_mode == TCP_CONNECT_PASSIVE) {
771*fa790ea9SDavid C Somayajulu init_data.comp_mode = ECORE_SPQ_MODE_CB;
772*fa790ea9SDavid C Somayajulu } else {
773*fa790ea9SDavid C Somayajulu init_data.comp_mode = ECORE_SPQ_MODE_EBLOCK;
774*fa790ea9SDavid C Somayajulu }
775*fa790ea9SDavid C Somayajulu
776*fa790ea9SDavid C Somayajulu rc = ecore_sp_init_request(p_hwfn, &p_ent,
777*fa790ea9SDavid C Somayajulu IWARP_RAMROD_CMD_ID_TCP_OFFLOAD,
778*fa790ea9SDavid C Somayajulu PROTOCOLID_IWARP, &init_data);
779*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
780*fa790ea9SDavid C Somayajulu return rc;
781*fa790ea9SDavid C Somayajulu
782*fa790ea9SDavid C Somayajulu p_tcp_ramrod = &p_ent->ramrod.iwarp_tcp_offload;
783*fa790ea9SDavid C Somayajulu
784*fa790ea9SDavid C Somayajulu /* Point to the "second half" of the ulp buffer */
785*fa790ea9SDavid C Somayajulu in_pdata_phys = ep->ep_buffer_phys +
786*fa790ea9SDavid C Somayajulu OFFSETOF(struct ecore_iwarp_ep_memory, in_pdata);
787*fa790ea9SDavid C Somayajulu p_tcp_ramrod->iwarp.incoming_ulp_buffer.addr.hi =
788*fa790ea9SDavid C Somayajulu DMA_HI_LE(in_pdata_phys);
789*fa790ea9SDavid C Somayajulu p_tcp_ramrod->iwarp.incoming_ulp_buffer.addr.lo =
790*fa790ea9SDavid C Somayajulu DMA_LO_LE(in_pdata_phys);
791*fa790ea9SDavid C Somayajulu p_tcp_ramrod->iwarp.incoming_ulp_buffer.len =
792*fa790ea9SDavid C Somayajulu OSAL_CPU_TO_LE16(sizeof(ep->ep_buffer_virt->in_pdata));
793*fa790ea9SDavid C Somayajulu
794*fa790ea9SDavid C Somayajulu async_output_phys = ep->ep_buffer_phys +
795*fa790ea9SDavid C Somayajulu OFFSETOF(struct ecore_iwarp_ep_memory, async_output);
796*fa790ea9SDavid C Somayajulu
797*fa790ea9SDavid C Somayajulu p_tcp_ramrod->iwarp.async_eqe_output_buf.hi =
798*fa790ea9SDavid C Somayajulu DMA_HI_LE(async_output_phys);
799*fa790ea9SDavid C Somayajulu p_tcp_ramrod->iwarp.async_eqe_output_buf.lo =
800*fa790ea9SDavid C Somayajulu DMA_LO_LE(async_output_phys);
801*fa790ea9SDavid C Somayajulu p_tcp_ramrod->iwarp.handle_for_async.hi = OSAL_CPU_TO_LE32(PTR_HI(ep));
802*fa790ea9SDavid C Somayajulu p_tcp_ramrod->iwarp.handle_for_async.lo = OSAL_CPU_TO_LE32(PTR_LO(ep));
803*fa790ea9SDavid C Somayajulu
804*fa790ea9SDavid C Somayajulu physical_q = ecore_get_cm_pq_idx(p_hwfn, PQ_FLAGS_OFLD);
805*fa790ea9SDavid C Somayajulu p_tcp_ramrod->iwarp.physical_q0 = OSAL_CPU_TO_LE16(physical_q);
806*fa790ea9SDavid C Somayajulu physical_q = ecore_get_cm_pq_idx(p_hwfn, PQ_FLAGS_ACK);
807*fa790ea9SDavid C Somayajulu p_tcp_ramrod->iwarp.physical_q1 = OSAL_CPU_TO_LE16(physical_q);
808*fa790ea9SDavid C Somayajulu p_tcp_ramrod->iwarp.mpa_mode = iwarp_info->mpa_rev;
809*fa790ea9SDavid C Somayajulu
810*fa790ea9SDavid C Somayajulu ecore_set_fw_mac_addr(&p_tcp_ramrod->tcp.remote_mac_addr_hi,
811*fa790ea9SDavid C Somayajulu &p_tcp_ramrod->tcp.remote_mac_addr_mid,
812*fa790ea9SDavid C Somayajulu &p_tcp_ramrod->tcp.remote_mac_addr_lo,
813*fa790ea9SDavid C Somayajulu ep->remote_mac_addr);
814*fa790ea9SDavid C Somayajulu ecore_set_fw_mac_addr(&p_tcp_ramrod->tcp.local_mac_addr_hi,
815*fa790ea9SDavid C Somayajulu &p_tcp_ramrod->tcp.local_mac_addr_mid,
816*fa790ea9SDavid C Somayajulu &p_tcp_ramrod->tcp.local_mac_addr_lo,
817*fa790ea9SDavid C Somayajulu ep->local_mac_addr);
818*fa790ea9SDavid C Somayajulu
819*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.vlan_id = OSAL_CPU_TO_LE16(ep->cm_info.vlan);
820*fa790ea9SDavid C Somayajulu
821*fa790ea9SDavid C Somayajulu tcp_flags = p_hwfn->p_rdma_info->iwarp.tcp_flags;
822*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.flags = 0;
823*fa790ea9SDavid C Somayajulu SET_FIELD(p_tcp_ramrod->tcp.flags,
824*fa790ea9SDavid C Somayajulu TCP_OFFLOAD_PARAMS_OPT2_TS_EN,
825*fa790ea9SDavid C Somayajulu !!(tcp_flags & ECORE_IWARP_TS_EN));
826*fa790ea9SDavid C Somayajulu
827*fa790ea9SDavid C Somayajulu SET_FIELD(p_tcp_ramrod->tcp.flags,
828*fa790ea9SDavid C Somayajulu TCP_OFFLOAD_PARAMS_OPT2_DA_EN,
829*fa790ea9SDavid C Somayajulu !!(tcp_flags & ECORE_IWARP_DA_EN));
830*fa790ea9SDavid C Somayajulu
831*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.ip_version = ep->cm_info.ip_version;
832*fa790ea9SDavid C Somayajulu
833*fa790ea9SDavid C Somayajulu for (i = 0; i < 4; i++) {
834*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.remote_ip[i] =
835*fa790ea9SDavid C Somayajulu OSAL_CPU_TO_LE32(ep->cm_info.remote_ip[i]);
836*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.local_ip[i] =
837*fa790ea9SDavid C Somayajulu OSAL_CPU_TO_LE32(ep->cm_info.local_ip[i]);
838*fa790ea9SDavid C Somayajulu }
839*fa790ea9SDavid C Somayajulu
840*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.remote_port =
841*fa790ea9SDavid C Somayajulu OSAL_CPU_TO_LE16(ep->cm_info.remote_port);
842*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.local_port = OSAL_CPU_TO_LE16(ep->cm_info.local_port);
843*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.mss = OSAL_CPU_TO_LE16(ep->mss);
844*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.flow_label = 0;
845*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.ttl = 0x40;
846*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.tos_or_tc = 0;
847*fa790ea9SDavid C Somayajulu
848*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.max_rt_time = ECORE_IWARP_DEF_MAX_RT_TIME;
849*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.cwnd = ECORE_IWARP_DEF_CWND_FACTOR * p_tcp_ramrod->tcp.mss;
850*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.ka_max_probe_cnt = ECORE_IWARP_DEF_KA_MAX_PROBE_CNT;
851*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.ka_timeout = ECORE_IWARP_DEF_KA_TIMEOUT;
852*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.ka_interval = ECORE_IWARP_DEF_KA_INTERVAL;
853*fa790ea9SDavid C Somayajulu
854*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.rcv_wnd_scale =
855*fa790ea9SDavid C Somayajulu (u8)p_hwfn->p_rdma_info->iwarp.rcv_wnd_scale;
856*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.connect_mode = ep->connect_mode;
857*fa790ea9SDavid C Somayajulu
858*fa790ea9SDavid C Somayajulu if (ep->connect_mode == TCP_CONNECT_PASSIVE) {
859*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.syn_ip_payload_length =
860*fa790ea9SDavid C Somayajulu OSAL_CPU_TO_LE16(ep->syn_ip_payload_length);
861*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.syn_phy_addr_hi =
862*fa790ea9SDavid C Somayajulu DMA_HI_LE(ep->syn_phy_addr);
863*fa790ea9SDavid C Somayajulu p_tcp_ramrod->tcp.syn_phy_addr_lo =
864*fa790ea9SDavid C Somayajulu DMA_LO_LE(ep->syn_phy_addr);
865*fa790ea9SDavid C Somayajulu }
866*fa790ea9SDavid C Somayajulu
867*fa790ea9SDavid C Somayajulu ecore_iwarp_print_tcp_ramrod(p_hwfn, p_tcp_ramrod);
868*fa790ea9SDavid C Somayajulu
869*fa790ea9SDavid C Somayajulu rc = ecore_spq_post(p_hwfn, p_ent, OSAL_NULL);
870*fa790ea9SDavid C Somayajulu
871*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
872*fa790ea9SDavid C Somayajulu "EP(0x%x) Offload completed rc=%d\n" , ep->tcp_cid, rc);
873*fa790ea9SDavid C Somayajulu
874*fa790ea9SDavid C Somayajulu return rc;
875*fa790ea9SDavid C Somayajulu }
876*fa790ea9SDavid C Somayajulu
877*fa790ea9SDavid C Somayajulu /* This function should be called after IWARP_EVENT_TYPE_ASYNC_CONNECT_COMPLETE
878*fa790ea9SDavid C Somayajulu * is received. it will be called from the dpc context.
879*fa790ea9SDavid C Somayajulu */
880*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
ecore_iwarp_mpa_offload(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_ep * ep)881*fa790ea9SDavid C Somayajulu ecore_iwarp_mpa_offload(struct ecore_hwfn *p_hwfn,
882*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep)
883*fa790ea9SDavid C Somayajulu {
884*fa790ea9SDavid C Somayajulu struct iwarp_mpa_offload_ramrod_data *p_mpa_ramrod;
885*fa790ea9SDavid C Somayajulu struct ecore_iwarp_info *iwarp_info;
886*fa790ea9SDavid C Somayajulu struct ecore_sp_init_data init_data;
887*fa790ea9SDavid C Somayajulu struct ecore_spq_entry *p_ent;
888*fa790ea9SDavid C Somayajulu dma_addr_t async_output_phys;
889*fa790ea9SDavid C Somayajulu dma_addr_t out_pdata_phys;
890*fa790ea9SDavid C Somayajulu dma_addr_t in_pdata_phys;
891*fa790ea9SDavid C Somayajulu struct ecore_rdma_qp *qp;
892*fa790ea9SDavid C Somayajulu bool reject;
893*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
894*fa790ea9SDavid C Somayajulu
895*fa790ea9SDavid C Somayajulu if (!ep)
896*fa790ea9SDavid C Somayajulu return ECORE_INVAL;
897*fa790ea9SDavid C Somayajulu
898*fa790ea9SDavid C Somayajulu qp = ep->qp;
899*fa790ea9SDavid C Somayajulu reject = (qp == OSAL_NULL);
900*fa790ea9SDavid C Somayajulu
901*fa790ea9SDavid C Somayajulu OSAL_MEMSET(&init_data, 0, sizeof(init_data));
902*fa790ea9SDavid C Somayajulu init_data.cid = reject ? ep->tcp_cid : qp->icid;
903*fa790ea9SDavid C Somayajulu init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
904*fa790ea9SDavid C Somayajulu
905*fa790ea9SDavid C Somayajulu if (ep->connect_mode == TCP_CONNECT_ACTIVE || !ep->event_cb)
906*fa790ea9SDavid C Somayajulu init_data.comp_mode = ECORE_SPQ_MODE_CB;
907*fa790ea9SDavid C Somayajulu else
908*fa790ea9SDavid C Somayajulu init_data.comp_mode = ECORE_SPQ_MODE_EBLOCK;
909*fa790ea9SDavid C Somayajulu
910*fa790ea9SDavid C Somayajulu rc = ecore_sp_init_request(p_hwfn, &p_ent,
911*fa790ea9SDavid C Somayajulu IWARP_RAMROD_CMD_ID_MPA_OFFLOAD,
912*fa790ea9SDavid C Somayajulu PROTOCOLID_IWARP, &init_data);
913*fa790ea9SDavid C Somayajulu
914*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
915*fa790ea9SDavid C Somayajulu return rc;
916*fa790ea9SDavid C Somayajulu
917*fa790ea9SDavid C Somayajulu p_mpa_ramrod = &p_ent->ramrod.iwarp_mpa_offload;
918*fa790ea9SDavid C Somayajulu out_pdata_phys = ep->ep_buffer_phys +
919*fa790ea9SDavid C Somayajulu OFFSETOF(struct ecore_iwarp_ep_memory, out_pdata);
920*fa790ea9SDavid C Somayajulu p_mpa_ramrod->common.outgoing_ulp_buffer.addr.hi =
921*fa790ea9SDavid C Somayajulu DMA_HI_LE(out_pdata_phys);
922*fa790ea9SDavid C Somayajulu p_mpa_ramrod->common.outgoing_ulp_buffer.addr.lo =
923*fa790ea9SDavid C Somayajulu DMA_LO_LE(out_pdata_phys);
924*fa790ea9SDavid C Somayajulu p_mpa_ramrod->common.outgoing_ulp_buffer.len =
925*fa790ea9SDavid C Somayajulu ep->cm_info.private_data_len;
926*fa790ea9SDavid C Somayajulu p_mpa_ramrod->common.crc_needed = p_hwfn->p_rdma_info->iwarp.crc_needed;
927*fa790ea9SDavid C Somayajulu
928*fa790ea9SDavid C Somayajulu p_mpa_ramrod->common.out_rq.ord = ep->cm_info.ord;
929*fa790ea9SDavid C Somayajulu p_mpa_ramrod->common.out_rq.ird = ep->cm_info.ird;
930*fa790ea9SDavid C Somayajulu
931*fa790ea9SDavid C Somayajulu p_mpa_ramrod->tcp_cid = p_hwfn->hw_info.opaque_fid << 16 | ep->tcp_cid;
932*fa790ea9SDavid C Somayajulu
933*fa790ea9SDavid C Somayajulu in_pdata_phys = ep->ep_buffer_phys +
934*fa790ea9SDavid C Somayajulu OFFSETOF(struct ecore_iwarp_ep_memory, in_pdata);
935*fa790ea9SDavid C Somayajulu p_mpa_ramrod->tcp_connect_side = ep->connect_mode;
936*fa790ea9SDavid C Somayajulu p_mpa_ramrod->incoming_ulp_buffer.addr.hi =
937*fa790ea9SDavid C Somayajulu DMA_HI_LE(in_pdata_phys);
938*fa790ea9SDavid C Somayajulu p_mpa_ramrod->incoming_ulp_buffer.addr.lo =
939*fa790ea9SDavid C Somayajulu DMA_LO_LE(in_pdata_phys);
940*fa790ea9SDavid C Somayajulu p_mpa_ramrod->incoming_ulp_buffer.len =
941*fa790ea9SDavid C Somayajulu OSAL_CPU_TO_LE16(sizeof(ep->ep_buffer_virt->in_pdata));
942*fa790ea9SDavid C Somayajulu async_output_phys = ep->ep_buffer_phys +
943*fa790ea9SDavid C Somayajulu OFFSETOF(struct ecore_iwarp_ep_memory, async_output);
944*fa790ea9SDavid C Somayajulu p_mpa_ramrod->async_eqe_output_buf.hi =
945*fa790ea9SDavid C Somayajulu DMA_HI_LE(async_output_phys);
946*fa790ea9SDavid C Somayajulu p_mpa_ramrod->async_eqe_output_buf.lo =
947*fa790ea9SDavid C Somayajulu DMA_LO_LE(async_output_phys);
948*fa790ea9SDavid C Somayajulu p_mpa_ramrod->handle_for_async.hi = OSAL_CPU_TO_LE32(PTR_HI(ep));
949*fa790ea9SDavid C Somayajulu p_mpa_ramrod->handle_for_async.lo = OSAL_CPU_TO_LE32(PTR_LO(ep));
950*fa790ea9SDavid C Somayajulu
951*fa790ea9SDavid C Somayajulu if (!reject) {
952*fa790ea9SDavid C Somayajulu p_mpa_ramrod->shared_queue_addr.hi =
953*fa790ea9SDavid C Somayajulu DMA_HI_LE(qp->shared_queue_phys_addr);
954*fa790ea9SDavid C Somayajulu p_mpa_ramrod->shared_queue_addr.lo =
955*fa790ea9SDavid C Somayajulu DMA_LO_LE(qp->shared_queue_phys_addr);
956*fa790ea9SDavid C Somayajulu
957*fa790ea9SDavid C Somayajulu p_mpa_ramrod->stats_counter_id =
958*fa790ea9SDavid C Somayajulu RESC_START(p_hwfn, ECORE_RDMA_STATS_QUEUE) +
959*fa790ea9SDavid C Somayajulu qp->stats_queue;
960*fa790ea9SDavid C Somayajulu } else {
961*fa790ea9SDavid C Somayajulu p_mpa_ramrod->common.reject = 1;
962*fa790ea9SDavid C Somayajulu }
963*fa790ea9SDavid C Somayajulu
964*fa790ea9SDavid C Somayajulu iwarp_info = &p_hwfn->p_rdma_info->iwarp;
965*fa790ea9SDavid C Somayajulu p_mpa_ramrod->rcv_wnd = iwarp_info->rcv_wnd_size;
966*fa790ea9SDavid C Somayajulu p_mpa_ramrod->mode = ep->mpa_rev;
967*fa790ea9SDavid C Somayajulu SET_FIELD(p_mpa_ramrod->rtr_pref,
968*fa790ea9SDavid C Somayajulu IWARP_MPA_OFFLOAD_RAMROD_DATA_RTR_SUPPORTED,
969*fa790ea9SDavid C Somayajulu ep->rtr_type);
970*fa790ea9SDavid C Somayajulu
971*fa790ea9SDavid C Somayajulu ep->state = ECORE_IWARP_EP_MPA_OFFLOADED;
972*fa790ea9SDavid C Somayajulu rc = ecore_spq_post(p_hwfn, p_ent, OSAL_NULL);
973*fa790ea9SDavid C Somayajulu if (!reject)
974*fa790ea9SDavid C Somayajulu ep->cid = qp->icid; /* Now they're migrated. */
975*fa790ea9SDavid C Somayajulu
976*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
977*fa790ea9SDavid C Somayajulu "QP(0x%x) EP(0x%x) MPA Offload rc = %d IRD=0x%x ORD=0x%x rtr_type=%d mpa_rev=%d reject=%d\n",
978*fa790ea9SDavid C Somayajulu reject ? 0xffff : qp->icid, ep->tcp_cid, rc, ep->cm_info.ird,
979*fa790ea9SDavid C Somayajulu ep->cm_info.ord, ep->rtr_type, ep->mpa_rev, reject);
980*fa790ea9SDavid C Somayajulu return rc;
981*fa790ea9SDavid C Somayajulu }
982*fa790ea9SDavid C Somayajulu
983*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_mpa_received(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_ep * ep)984*fa790ea9SDavid C Somayajulu ecore_iwarp_mpa_received(struct ecore_hwfn *p_hwfn,
985*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep)
986*fa790ea9SDavid C Somayajulu {
987*fa790ea9SDavid C Somayajulu struct ecore_iwarp_info *iwarp_info = &p_hwfn->p_rdma_info->iwarp;
988*fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_event_params params;
989*fa790ea9SDavid C Somayajulu struct mpa_v2_hdr *mpa_v2_params;
990*fa790ea9SDavid C Somayajulu union async_output *async_data;
991*fa790ea9SDavid C Somayajulu u16 mpa_ord, mpa_ird;
992*fa790ea9SDavid C Somayajulu u8 mpa_hdr_size = 0;
993*fa790ea9SDavid C Somayajulu u8 mpa_rev;
994*fa790ea9SDavid C Somayajulu
995*fa790ea9SDavid C Somayajulu async_data = &ep->ep_buffer_virt->async_output;
996*fa790ea9SDavid C Somayajulu
997*fa790ea9SDavid C Somayajulu mpa_rev = async_data->mpa_request.mpa_handshake_mode;
998*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
999*fa790ea9SDavid C Somayajulu "private_data_len=%x handshake_mode=%x private_data=(%x)\n",
1000*fa790ea9SDavid C Somayajulu async_data->mpa_request.ulp_data_len,
1001*fa790ea9SDavid C Somayajulu mpa_rev,
1002*fa790ea9SDavid C Somayajulu *((u32 *)((u8 *)ep->ep_buffer_virt->in_pdata)));
1003*fa790ea9SDavid C Somayajulu
1004*fa790ea9SDavid C Somayajulu if (ep->listener->state > ECORE_IWARP_LISTENER_STATE_UNPAUSE) {
1005*fa790ea9SDavid C Somayajulu /* MPA reject initiated by ecore */
1006*fa790ea9SDavid C Somayajulu OSAL_MEMSET(&ep->cm_info, 0, sizeof(ep->cm_info));
1007*fa790ea9SDavid C Somayajulu ep->event_cb = OSAL_NULL;
1008*fa790ea9SDavid C Somayajulu ecore_iwarp_mpa_offload(p_hwfn, ep);
1009*fa790ea9SDavid C Somayajulu return;
1010*fa790ea9SDavid C Somayajulu }
1011*fa790ea9SDavid C Somayajulu
1012*fa790ea9SDavid C Somayajulu if (mpa_rev == MPA_NEGOTIATION_TYPE_ENHANCED) {
1013*fa790ea9SDavid C Somayajulu if (iwarp_info->mpa_rev == MPA_NEGOTIATION_TYPE_BASIC) {
1014*fa790ea9SDavid C Somayajulu DP_ERR(p_hwfn, "MPA_NEGOTIATE Received MPA rev 2 on driver supporting only MPA rev 1\n");
1015*fa790ea9SDavid C Somayajulu /* MPA_REV2 ToDo: close the tcp connection. */
1016*fa790ea9SDavid C Somayajulu return;
1017*fa790ea9SDavid C Somayajulu }
1018*fa790ea9SDavid C Somayajulu
1019*fa790ea9SDavid C Somayajulu /* Read ord/ird values from private data buffer */
1020*fa790ea9SDavid C Somayajulu mpa_v2_params =
1021*fa790ea9SDavid C Somayajulu (struct mpa_v2_hdr *)(ep->ep_buffer_virt->in_pdata);
1022*fa790ea9SDavid C Somayajulu mpa_hdr_size = sizeof(*mpa_v2_params);
1023*fa790ea9SDavid C Somayajulu
1024*fa790ea9SDavid C Somayajulu mpa_ord = ntohs(mpa_v2_params->ord);
1025*fa790ea9SDavid C Somayajulu mpa_ird = ntohs(mpa_v2_params->ird);
1026*fa790ea9SDavid C Somayajulu
1027*fa790ea9SDavid C Somayajulu /* Temprary store in cm_info incoming ord/ird requested, later
1028*fa790ea9SDavid C Somayajulu * replace with negotiated value during accept
1029*fa790ea9SDavid C Somayajulu */
1030*fa790ea9SDavid C Somayajulu ep->cm_info.ord = (u8)OSAL_MIN_T(u16,
1031*fa790ea9SDavid C Somayajulu (mpa_ord & MPA_V2_IRD_ORD_MASK),
1032*fa790ea9SDavid C Somayajulu ECORE_IWARP_ORD_DEFAULT);
1033*fa790ea9SDavid C Somayajulu
1034*fa790ea9SDavid C Somayajulu ep->cm_info.ird = (u8)OSAL_MIN_T(u16,
1035*fa790ea9SDavid C Somayajulu (mpa_ird & MPA_V2_IRD_ORD_MASK),
1036*fa790ea9SDavid C Somayajulu ECORE_IWARP_IRD_DEFAULT);
1037*fa790ea9SDavid C Somayajulu
1038*fa790ea9SDavid C Somayajulu /* Peer2Peer negotiation */
1039*fa790ea9SDavid C Somayajulu ep->rtr_type = MPA_RTR_TYPE_NONE;
1040*fa790ea9SDavid C Somayajulu if (mpa_ird & MPA_V2_PEER2PEER_MODEL) {
1041*fa790ea9SDavid C Somayajulu if (mpa_ord & MPA_V2_WRITE_RTR)
1042*fa790ea9SDavid C Somayajulu ep->rtr_type |= MPA_RTR_TYPE_ZERO_WRITE;
1043*fa790ea9SDavid C Somayajulu
1044*fa790ea9SDavid C Somayajulu if (mpa_ord & MPA_V2_READ_RTR)
1045*fa790ea9SDavid C Somayajulu ep->rtr_type |= MPA_RTR_TYPE_ZERO_READ;
1046*fa790ea9SDavid C Somayajulu
1047*fa790ea9SDavid C Somayajulu if (mpa_ird & MPA_V2_SEND_RTR)
1048*fa790ea9SDavid C Somayajulu ep->rtr_type |= MPA_RTR_TYPE_ZERO_SEND;
1049*fa790ea9SDavid C Somayajulu
1050*fa790ea9SDavid C Somayajulu ep->rtr_type &= iwarp_info->rtr_type;
1051*fa790ea9SDavid C Somayajulu /* if we're left with no match send our capabilities */
1052*fa790ea9SDavid C Somayajulu if (ep->rtr_type == MPA_RTR_TYPE_NONE)
1053*fa790ea9SDavid C Somayajulu ep->rtr_type = iwarp_info->rtr_type;
1054*fa790ea9SDavid C Somayajulu
1055*fa790ea9SDavid C Somayajulu /* prioritize write over send and read */
1056*fa790ea9SDavid C Somayajulu if (ep->rtr_type & MPA_RTR_TYPE_ZERO_WRITE)
1057*fa790ea9SDavid C Somayajulu ep->rtr_type = MPA_RTR_TYPE_ZERO_WRITE;
1058*fa790ea9SDavid C Somayajulu }
1059*fa790ea9SDavid C Somayajulu
1060*fa790ea9SDavid C Somayajulu ep->mpa_rev = MPA_NEGOTIATION_TYPE_ENHANCED;
1061*fa790ea9SDavid C Somayajulu } else {
1062*fa790ea9SDavid C Somayajulu ep->cm_info.ord = ECORE_IWARP_ORD_DEFAULT;
1063*fa790ea9SDavid C Somayajulu ep->cm_info.ird = ECORE_IWARP_IRD_DEFAULT;
1064*fa790ea9SDavid C Somayajulu ep->mpa_rev = MPA_NEGOTIATION_TYPE_BASIC;
1065*fa790ea9SDavid C Somayajulu }
1066*fa790ea9SDavid C Somayajulu
1067*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
1068*fa790ea9SDavid C Somayajulu "MPA_NEGOTIATE (v%d): ORD: 0x%x IRD: 0x%x rtr:0x%x ulp_data_len = %x mpa_hdr_size = %x\n",
1069*fa790ea9SDavid C Somayajulu mpa_rev, ep->cm_info.ord, ep->cm_info.ird, ep->rtr_type,
1070*fa790ea9SDavid C Somayajulu async_data->mpa_request.ulp_data_len,
1071*fa790ea9SDavid C Somayajulu mpa_hdr_size);
1072*fa790ea9SDavid C Somayajulu
1073*fa790ea9SDavid C Somayajulu /* Strip mpa v2 hdr from private data before sending to upper layer */
1074*fa790ea9SDavid C Somayajulu ep->cm_info.private_data =
1075*fa790ea9SDavid C Somayajulu ep->ep_buffer_virt->in_pdata + mpa_hdr_size;
1076*fa790ea9SDavid C Somayajulu
1077*fa790ea9SDavid C Somayajulu ep->cm_info.private_data_len =
1078*fa790ea9SDavid C Somayajulu async_data->mpa_request.ulp_data_len - mpa_hdr_size;
1079*fa790ea9SDavid C Somayajulu
1080*fa790ea9SDavid C Somayajulu params.event = ECORE_IWARP_EVENT_MPA_REQUEST;
1081*fa790ea9SDavid C Somayajulu params.cm_info = &ep->cm_info;
1082*fa790ea9SDavid C Somayajulu params.ep_context = ep;
1083*fa790ea9SDavid C Somayajulu params.status = ECORE_SUCCESS;
1084*fa790ea9SDavid C Somayajulu
1085*fa790ea9SDavid C Somayajulu ep->state = ECORE_IWARP_EP_MPA_REQ_RCVD;
1086*fa790ea9SDavid C Somayajulu ep->event_cb(ep->cb_context, ¶ms);
1087*fa790ea9SDavid C Somayajulu }
1088*fa790ea9SDavid C Somayajulu
1089*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_move_to_ep_list(struct ecore_hwfn * p_hwfn,osal_list_t * list,struct ecore_iwarp_ep * ep)1090*fa790ea9SDavid C Somayajulu ecore_iwarp_move_to_ep_list(struct ecore_hwfn *p_hwfn,
1091*fa790ea9SDavid C Somayajulu osal_list_t *list, struct ecore_iwarp_ep *ep)
1092*fa790ea9SDavid C Somayajulu {
1093*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&ep->listener->lock);
1094*fa790ea9SDavid C Somayajulu OSAL_LIST_REMOVE_ENTRY(&ep->list_entry, &ep->listener->ep_list);
1095*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&ep->listener->lock);
1096*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
1097*fa790ea9SDavid C Somayajulu OSAL_LIST_PUSH_TAIL(&ep->list_entry, list);
1098*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
1099*fa790ea9SDavid C Somayajulu }
1100*fa790ea9SDavid C Somayajulu
1101*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_return_ep(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_ep * ep)1102*fa790ea9SDavid C Somayajulu ecore_iwarp_return_ep(struct ecore_hwfn *p_hwfn,
1103*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep)
1104*fa790ea9SDavid C Somayajulu {
1105*fa790ea9SDavid C Somayajulu ep->state = ECORE_IWARP_EP_INIT;
1106*fa790ea9SDavid C Somayajulu if (ep->qp)
1107*fa790ea9SDavid C Somayajulu ep->qp->ep = OSAL_NULL;
1108*fa790ea9SDavid C Somayajulu ep->qp = OSAL_NULL;
1109*fa790ea9SDavid C Somayajulu OSAL_MEMSET(&ep->cm_info, 0, sizeof(ep->cm_info));
1110*fa790ea9SDavid C Somayajulu
1111*fa790ea9SDavid C Somayajulu if (ep->tcp_cid == ECORE_IWARP_INVALID_TCP_CID) {
1112*fa790ea9SDavid C Somayajulu /* We don't care about the return code, it's ok if tcp_cid
1113*fa790ea9SDavid C Somayajulu * remains invalid...in this case we'll defer allocation
1114*fa790ea9SDavid C Somayajulu */
1115*fa790ea9SDavid C Somayajulu ecore_iwarp_alloc_tcp_cid(p_hwfn, &ep->tcp_cid);
1116*fa790ea9SDavid C Somayajulu }
1117*fa790ea9SDavid C Somayajulu
1118*fa790ea9SDavid C Somayajulu ecore_iwarp_move_to_ep_list(p_hwfn,
1119*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->iwarp.ep_free_list,
1120*fa790ea9SDavid C Somayajulu ep);
1121*fa790ea9SDavid C Somayajulu }
1122*fa790ea9SDavid C Somayajulu
1123*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_parse_private_data(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_ep * ep)1124*fa790ea9SDavid C Somayajulu ecore_iwarp_parse_private_data(struct ecore_hwfn *p_hwfn,
1125*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep)
1126*fa790ea9SDavid C Somayajulu {
1127*fa790ea9SDavid C Somayajulu struct mpa_v2_hdr *mpa_v2_params;
1128*fa790ea9SDavid C Somayajulu union async_output *async_data;
1129*fa790ea9SDavid C Somayajulu u16 mpa_ird, mpa_ord;
1130*fa790ea9SDavid C Somayajulu u8 mpa_data_size = 0;
1131*fa790ea9SDavid C Somayajulu
1132*fa790ea9SDavid C Somayajulu if (MPA_REV2(p_hwfn->p_rdma_info->iwarp.mpa_rev)) {
1133*fa790ea9SDavid C Somayajulu mpa_v2_params = (struct mpa_v2_hdr *)
1134*fa790ea9SDavid C Somayajulu ((u8 *)ep->ep_buffer_virt->in_pdata);
1135*fa790ea9SDavid C Somayajulu mpa_data_size = sizeof(*mpa_v2_params);
1136*fa790ea9SDavid C Somayajulu mpa_ird = ntohs(mpa_v2_params->ird);
1137*fa790ea9SDavid C Somayajulu mpa_ord = ntohs(mpa_v2_params->ord);
1138*fa790ea9SDavid C Somayajulu
1139*fa790ea9SDavid C Somayajulu ep->cm_info.ird = (u8)(mpa_ord & MPA_V2_IRD_ORD_MASK);
1140*fa790ea9SDavid C Somayajulu ep->cm_info.ord = (u8)(mpa_ird & MPA_V2_IRD_ORD_MASK);
1141*fa790ea9SDavid C Somayajulu } /* else: Ord / Ird already configured */
1142*fa790ea9SDavid C Somayajulu
1143*fa790ea9SDavid C Somayajulu async_data = &ep->ep_buffer_virt->async_output;
1144*fa790ea9SDavid C Somayajulu
1145*fa790ea9SDavid C Somayajulu ep->cm_info.private_data = ep->ep_buffer_virt->in_pdata + mpa_data_size;
1146*fa790ea9SDavid C Somayajulu ep->cm_info.private_data_len =
1147*fa790ea9SDavid C Somayajulu async_data->mpa_response.ulp_data_len - mpa_data_size;
1148*fa790ea9SDavid C Somayajulu }
1149*fa790ea9SDavid C Somayajulu
1150*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_mpa_reply_arrived(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_ep * ep)1151*fa790ea9SDavid C Somayajulu ecore_iwarp_mpa_reply_arrived(struct ecore_hwfn *p_hwfn,
1152*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep)
1153*fa790ea9SDavid C Somayajulu {
1154*fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_event_params params;
1155*fa790ea9SDavid C Somayajulu
1156*fa790ea9SDavid C Somayajulu if (ep->connect_mode == TCP_CONNECT_PASSIVE) {
1157*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, true, "MPA reply event not expected on passive side!\n");
1158*fa790ea9SDavid C Somayajulu return;
1159*fa790ea9SDavid C Somayajulu }
1160*fa790ea9SDavid C Somayajulu
1161*fa790ea9SDavid C Somayajulu params.event = ECORE_IWARP_EVENT_ACTIVE_MPA_REPLY;
1162*fa790ea9SDavid C Somayajulu
1163*fa790ea9SDavid C Somayajulu ecore_iwarp_parse_private_data(p_hwfn, ep);
1164*fa790ea9SDavid C Somayajulu
1165*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
1166*fa790ea9SDavid C Somayajulu "MPA_NEGOTIATE (v%d): ORD: 0x%x IRD: 0x%x\n",
1167*fa790ea9SDavid C Somayajulu ep->mpa_rev, ep->cm_info.ord, ep->cm_info.ird);
1168*fa790ea9SDavid C Somayajulu
1169*fa790ea9SDavid C Somayajulu params.cm_info = &ep->cm_info;
1170*fa790ea9SDavid C Somayajulu params.ep_context = ep;
1171*fa790ea9SDavid C Somayajulu params.status = ECORE_SUCCESS;
1172*fa790ea9SDavid C Somayajulu
1173*fa790ea9SDavid C Somayajulu ep->mpa_reply_processed = true;
1174*fa790ea9SDavid C Somayajulu
1175*fa790ea9SDavid C Somayajulu ep->event_cb(ep->cb_context, ¶ms);
1176*fa790ea9SDavid C Somayajulu }
1177*fa790ea9SDavid C Somayajulu
1178*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_CONNECT_MODE_STRING(ep) \
1179*fa790ea9SDavid C Somayajulu (ep->connect_mode == TCP_CONNECT_PASSIVE) ? "Passive" : "Active"
1180*fa790ea9SDavid C Somayajulu
1181*fa790ea9SDavid C Somayajulu /* Called as a result of the event:
1182*fa790ea9SDavid C Somayajulu * IWARP_EVENT_TYPE_ASYNC_MPA_HANDSHAKE_COMPLETE
1183*fa790ea9SDavid C Somayajulu */
1184*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_mpa_complete(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_ep * ep,u8 fw_return_code)1185*fa790ea9SDavid C Somayajulu ecore_iwarp_mpa_complete(struct ecore_hwfn *p_hwfn,
1186*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep,
1187*fa790ea9SDavid C Somayajulu u8 fw_return_code)
1188*fa790ea9SDavid C Somayajulu {
1189*fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_event_params params;
1190*fa790ea9SDavid C Somayajulu
1191*fa790ea9SDavid C Somayajulu if (ep->connect_mode == TCP_CONNECT_ACTIVE)
1192*fa790ea9SDavid C Somayajulu params.event = ECORE_IWARP_EVENT_ACTIVE_COMPLETE;
1193*fa790ea9SDavid C Somayajulu else
1194*fa790ea9SDavid C Somayajulu params.event = ECORE_IWARP_EVENT_PASSIVE_COMPLETE;
1195*fa790ea9SDavid C Somayajulu
1196*fa790ea9SDavid C Somayajulu if (ep->connect_mode == TCP_CONNECT_ACTIVE &&
1197*fa790ea9SDavid C Somayajulu !ep->mpa_reply_processed) {
1198*fa790ea9SDavid C Somayajulu ecore_iwarp_parse_private_data(p_hwfn, ep);
1199*fa790ea9SDavid C Somayajulu }
1200*fa790ea9SDavid C Somayajulu
1201*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
1202*fa790ea9SDavid C Somayajulu "MPA_NEGOTIATE (v%d): ORD: 0x%x IRD: 0x%x\n",
1203*fa790ea9SDavid C Somayajulu ep->mpa_rev, ep->cm_info.ord, ep->cm_info.ird);
1204*fa790ea9SDavid C Somayajulu
1205*fa790ea9SDavid C Somayajulu params.cm_info = &ep->cm_info;
1206*fa790ea9SDavid C Somayajulu
1207*fa790ea9SDavid C Somayajulu params.ep_context = ep;
1208*fa790ea9SDavid C Somayajulu
1209*fa790ea9SDavid C Somayajulu if ((ep->connect_mode == TCP_CONNECT_PASSIVE) &&
1210*fa790ea9SDavid C Somayajulu (ep->state != ECORE_IWARP_EP_MPA_OFFLOADED)) {
1211*fa790ea9SDavid C Somayajulu /* This is a FW bug. Shouldn't get complete without offload */
1212*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "%s(0x%x) ERROR: Got MPA complete without MPA offload fw_return_code=%d ep->state=%d\n",
1213*fa790ea9SDavid C Somayajulu ECORE_IWARP_CONNECT_MODE_STRING(ep), ep->tcp_cid,
1214*fa790ea9SDavid C Somayajulu fw_return_code, ep->state);
1215*fa790ea9SDavid C Somayajulu ep->state = ECORE_IWARP_EP_CLOSED;
1216*fa790ea9SDavid C Somayajulu return;
1217*fa790ea9SDavid C Somayajulu }
1218*fa790ea9SDavid C Somayajulu
1219*fa790ea9SDavid C Somayajulu if ((ep->connect_mode == TCP_CONNECT_PASSIVE) &&
1220*fa790ea9SDavid C Somayajulu (ep->state == ECORE_IWARP_EP_ABORTING))
1221*fa790ea9SDavid C Somayajulu return;
1222*fa790ea9SDavid C Somayajulu
1223*fa790ea9SDavid C Somayajulu ep->state = ECORE_IWARP_EP_CLOSED;
1224*fa790ea9SDavid C Somayajulu
1225*fa790ea9SDavid C Somayajulu switch (fw_return_code) {
1226*fa790ea9SDavid C Somayajulu case RDMA_RETURN_OK:
1227*fa790ea9SDavid C Somayajulu ep->qp->max_rd_atomic_req = ep->cm_info.ord;
1228*fa790ea9SDavid C Somayajulu ep->qp->max_rd_atomic_resp = ep->cm_info.ird;
1229*fa790ea9SDavid C Somayajulu ecore_iwarp_modify_qp(p_hwfn, ep->qp,
1230*fa790ea9SDavid C Somayajulu ECORE_IWARP_QP_STATE_RTS,
1231*fa790ea9SDavid C Somayajulu 1);
1232*fa790ea9SDavid C Somayajulu ep->state = ECORE_IWARP_EP_ESTABLISHED;
1233*fa790ea9SDavid C Somayajulu params.status = ECORE_SUCCESS;
1234*fa790ea9SDavid C Somayajulu break;
1235*fa790ea9SDavid C Somayajulu case IWARP_CONN_ERROR_MPA_TIMEOUT:
1236*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "%s(0x%x) MPA timeout\n",
1237*fa790ea9SDavid C Somayajulu ECORE_IWARP_CONNECT_MODE_STRING(ep), ep->cid);
1238*fa790ea9SDavid C Somayajulu params.status = ECORE_TIMEOUT;
1239*fa790ea9SDavid C Somayajulu break;
1240*fa790ea9SDavid C Somayajulu case IWARP_CONN_ERROR_MPA_ERROR_REJECT:
1241*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "%s(0x%x) MPA Reject\n",
1242*fa790ea9SDavid C Somayajulu ECORE_IWARP_CONNECT_MODE_STRING(ep), ep->cid);
1243*fa790ea9SDavid C Somayajulu params.status = ECORE_CONN_REFUSED;
1244*fa790ea9SDavid C Somayajulu break;
1245*fa790ea9SDavid C Somayajulu case IWARP_CONN_ERROR_MPA_RST:
1246*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "%s(0x%x) MPA reset(tcp cid: 0x%x)\n",
1247*fa790ea9SDavid C Somayajulu ECORE_IWARP_CONNECT_MODE_STRING(ep), ep->cid,
1248*fa790ea9SDavid C Somayajulu ep->tcp_cid);
1249*fa790ea9SDavid C Somayajulu params.status = ECORE_CONN_RESET;
1250*fa790ea9SDavid C Somayajulu break;
1251*fa790ea9SDavid C Somayajulu case IWARP_CONN_ERROR_MPA_FIN:
1252*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "%s(0x%x) MPA received FIN\n",
1253*fa790ea9SDavid C Somayajulu ECORE_IWARP_CONNECT_MODE_STRING(ep), ep->cid);
1254*fa790ea9SDavid C Somayajulu params.status = ECORE_CONN_REFUSED;
1255*fa790ea9SDavid C Somayajulu break;
1256*fa790ea9SDavid C Somayajulu case IWARP_CONN_ERROR_MPA_INSUF_IRD:
1257*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "%s(0x%x) MPA insufficient ird\n",
1258*fa790ea9SDavid C Somayajulu ECORE_IWARP_CONNECT_MODE_STRING(ep), ep->cid);
1259*fa790ea9SDavid C Somayajulu params.status = ECORE_CONN_REFUSED;
1260*fa790ea9SDavid C Somayajulu break;
1261*fa790ea9SDavid C Somayajulu case IWARP_CONN_ERROR_MPA_RTR_MISMATCH:
1262*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "%s(0x%x) MPA RTR MISMATCH\n",
1263*fa790ea9SDavid C Somayajulu ECORE_IWARP_CONNECT_MODE_STRING(ep), ep->cid);
1264*fa790ea9SDavid C Somayajulu params.status = ECORE_CONN_REFUSED;
1265*fa790ea9SDavid C Somayajulu break;
1266*fa790ea9SDavid C Somayajulu case IWARP_CONN_ERROR_MPA_INVALID_PACKET:
1267*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "%s(0x%x) MPA Invalid Packet\n",
1268*fa790ea9SDavid C Somayajulu ECORE_IWARP_CONNECT_MODE_STRING(ep), ep->cid);
1269*fa790ea9SDavid C Somayajulu params.status = ECORE_CONN_REFUSED;
1270*fa790ea9SDavid C Somayajulu break;
1271*fa790ea9SDavid C Somayajulu case IWARP_CONN_ERROR_MPA_LOCAL_ERROR:
1272*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "%s(0x%x) MPA Local Error\n",
1273*fa790ea9SDavid C Somayajulu ECORE_IWARP_CONNECT_MODE_STRING(ep), ep->cid);
1274*fa790ea9SDavid C Somayajulu params.status = ECORE_CONN_REFUSED;
1275*fa790ea9SDavid C Somayajulu break;
1276*fa790ea9SDavid C Somayajulu case IWARP_CONN_ERROR_MPA_TERMINATE:
1277*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "%s(0x%x) MPA TERMINATE\n",
1278*fa790ea9SDavid C Somayajulu ECORE_IWARP_CONNECT_MODE_STRING(ep), ep->cid);
1279*fa790ea9SDavid C Somayajulu params.status = ECORE_CONN_REFUSED;
1280*fa790ea9SDavid C Somayajulu break;
1281*fa790ea9SDavid C Somayajulu default:
1282*fa790ea9SDavid C Somayajulu params.status = ECORE_CONN_RESET;
1283*fa790ea9SDavid C Somayajulu break;
1284*fa790ea9SDavid C Somayajulu }
1285*fa790ea9SDavid C Somayajulu
1286*fa790ea9SDavid C Somayajulu if (ep->event_cb)
1287*fa790ea9SDavid C Somayajulu ep->event_cb(ep->cb_context, ¶ms);
1288*fa790ea9SDavid C Somayajulu
1289*fa790ea9SDavid C Somayajulu /* on passive side, if there is no associated QP (REJECT) we need to
1290*fa790ea9SDavid C Somayajulu * return the ep to the pool, otherwise we wait for QP to release it.
1291*fa790ea9SDavid C Somayajulu * Since we add an element in accept instead of this one. in anycase
1292*fa790ea9SDavid C Somayajulu * we need to remove it from the ep_list (active connections)...
1293*fa790ea9SDavid C Somayajulu */
1294*fa790ea9SDavid C Somayajulu if (fw_return_code != RDMA_RETURN_OK) {
1295*fa790ea9SDavid C Somayajulu ep->tcp_cid = ECORE_IWARP_INVALID_TCP_CID;
1296*fa790ea9SDavid C Somayajulu if ((ep->connect_mode == TCP_CONNECT_PASSIVE) &&
1297*fa790ea9SDavid C Somayajulu (ep->qp == OSAL_NULL)) { /* Rejected */
1298*fa790ea9SDavid C Somayajulu ecore_iwarp_return_ep(p_hwfn, ep);
1299*fa790ea9SDavid C Somayajulu } else {
1300*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
1301*fa790ea9SDavid C Somayajulu OSAL_LIST_REMOVE_ENTRY(
1302*fa790ea9SDavid C Somayajulu &ep->list_entry,
1303*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->iwarp.ep_list);
1304*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
1305*fa790ea9SDavid C Somayajulu }
1306*fa790ea9SDavid C Somayajulu }
1307*fa790ea9SDavid C Somayajulu }
1308*fa790ea9SDavid C Somayajulu
1309*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_mpa_v2_set_private(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_ep * ep,u8 * mpa_data_size)1310*fa790ea9SDavid C Somayajulu ecore_iwarp_mpa_v2_set_private(struct ecore_hwfn *p_hwfn,
1311*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep,
1312*fa790ea9SDavid C Somayajulu u8 *mpa_data_size)
1313*fa790ea9SDavid C Somayajulu {
1314*fa790ea9SDavid C Somayajulu struct mpa_v2_hdr *mpa_v2_params;
1315*fa790ea9SDavid C Somayajulu u16 mpa_ird, mpa_ord;
1316*fa790ea9SDavid C Somayajulu
1317*fa790ea9SDavid C Somayajulu *mpa_data_size = 0;
1318*fa790ea9SDavid C Somayajulu if (MPA_REV2(ep->mpa_rev)) {
1319*fa790ea9SDavid C Somayajulu mpa_v2_params =
1320*fa790ea9SDavid C Somayajulu (struct mpa_v2_hdr *)ep->ep_buffer_virt->out_pdata;
1321*fa790ea9SDavid C Somayajulu *mpa_data_size = sizeof(*mpa_v2_params);
1322*fa790ea9SDavid C Somayajulu
1323*fa790ea9SDavid C Somayajulu mpa_ird = (u16)ep->cm_info.ird;
1324*fa790ea9SDavid C Somayajulu mpa_ord = (u16)ep->cm_info.ord;
1325*fa790ea9SDavid C Somayajulu
1326*fa790ea9SDavid C Somayajulu if (ep->rtr_type != MPA_RTR_TYPE_NONE) {
1327*fa790ea9SDavid C Somayajulu mpa_ird |= MPA_V2_PEER2PEER_MODEL;
1328*fa790ea9SDavid C Somayajulu
1329*fa790ea9SDavid C Somayajulu if (ep->rtr_type & MPA_RTR_TYPE_ZERO_SEND)
1330*fa790ea9SDavid C Somayajulu mpa_ird |= MPA_V2_SEND_RTR;
1331*fa790ea9SDavid C Somayajulu
1332*fa790ea9SDavid C Somayajulu if (ep->rtr_type & MPA_RTR_TYPE_ZERO_WRITE)
1333*fa790ea9SDavid C Somayajulu mpa_ord |= MPA_V2_WRITE_RTR;
1334*fa790ea9SDavid C Somayajulu
1335*fa790ea9SDavid C Somayajulu if (ep->rtr_type & MPA_RTR_TYPE_ZERO_READ)
1336*fa790ea9SDavid C Somayajulu mpa_ord |= MPA_V2_READ_RTR;
1337*fa790ea9SDavid C Somayajulu }
1338*fa790ea9SDavid C Somayajulu
1339*fa790ea9SDavid C Somayajulu mpa_v2_params->ird = htons(mpa_ird);
1340*fa790ea9SDavid C Somayajulu mpa_v2_params->ord = htons(mpa_ord);
1341*fa790ea9SDavid C Somayajulu
1342*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
1343*fa790ea9SDavid C Somayajulu "MPA_NEGOTIATE Header: [%x ord:%x ird] %x ord:%x ird:%x peer2peer:%x rtr_send:%x rtr_write:%x rtr_read:%x\n",
1344*fa790ea9SDavid C Somayajulu mpa_v2_params->ird,
1345*fa790ea9SDavid C Somayajulu mpa_v2_params->ord,
1346*fa790ea9SDavid C Somayajulu *((u32 *)mpa_v2_params),
1347*fa790ea9SDavid C Somayajulu mpa_ord & MPA_V2_IRD_ORD_MASK,
1348*fa790ea9SDavid C Somayajulu mpa_ird & MPA_V2_IRD_ORD_MASK,
1349*fa790ea9SDavid C Somayajulu !!(mpa_ird & MPA_V2_PEER2PEER_MODEL),
1350*fa790ea9SDavid C Somayajulu !!(mpa_ird & MPA_V2_SEND_RTR),
1351*fa790ea9SDavid C Somayajulu !!(mpa_ord & MPA_V2_WRITE_RTR),
1352*fa790ea9SDavid C Somayajulu !!(mpa_ord & MPA_V2_READ_RTR));
1353*fa790ea9SDavid C Somayajulu }
1354*fa790ea9SDavid C Somayajulu }
1355*fa790ea9SDavid C Somayajulu
1356*fa790ea9SDavid C Somayajulu enum _ecore_status_t
ecore_iwarp_connect(void * rdma_cxt,struct ecore_iwarp_connect_in * iparams,struct ecore_iwarp_connect_out * oparams)1357*fa790ea9SDavid C Somayajulu ecore_iwarp_connect(void *rdma_cxt,
1358*fa790ea9SDavid C Somayajulu struct ecore_iwarp_connect_in *iparams,
1359*fa790ea9SDavid C Somayajulu struct ecore_iwarp_connect_out *oparams)
1360*fa790ea9SDavid C Somayajulu {
1361*fa790ea9SDavid C Somayajulu struct ecore_hwfn *p_hwfn = (struct ecore_hwfn *)rdma_cxt;
1362*fa790ea9SDavid C Somayajulu struct ecore_iwarp_info *iwarp_info;
1363*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep;
1364*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
1365*fa790ea9SDavid C Somayajulu u8 mpa_data_size = 0;
1366*fa790ea9SDavid C Somayajulu u8 ts_hdr_size = 0;
1367*fa790ea9SDavid C Somayajulu u32 cid;
1368*fa790ea9SDavid C Somayajulu
1369*fa790ea9SDavid C Somayajulu if ((iparams->cm_info.ord > ECORE_IWARP_ORD_DEFAULT) ||
1370*fa790ea9SDavid C Somayajulu (iparams->cm_info.ird > ECORE_IWARP_IRD_DEFAULT)) {
1371*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
1372*fa790ea9SDavid C Somayajulu "QP(0x%x) ERROR: Invalid ord(0x%x)/ird(0x%x)\n",
1373*fa790ea9SDavid C Somayajulu iparams->qp->icid, iparams->cm_info.ord,
1374*fa790ea9SDavid C Somayajulu iparams->cm_info.ird);
1375*fa790ea9SDavid C Somayajulu
1376*fa790ea9SDavid C Somayajulu return ECORE_INVAL;
1377*fa790ea9SDavid C Somayajulu }
1378*fa790ea9SDavid C Somayajulu
1379*fa790ea9SDavid C Somayajulu iwarp_info = &p_hwfn->p_rdma_info->iwarp;
1380*fa790ea9SDavid C Somayajulu
1381*fa790ea9SDavid C Somayajulu /* Allocate ep object */
1382*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_alloc_cid(p_hwfn, &cid);
1383*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
1384*fa790ea9SDavid C Somayajulu return rc;
1385*fa790ea9SDavid C Somayajulu
1386*fa790ea9SDavid C Somayajulu if (iparams->qp->ep == OSAL_NULL) {
1387*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_create_ep(p_hwfn, &ep);
1388*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
1389*fa790ea9SDavid C Somayajulu return rc;
1390*fa790ea9SDavid C Somayajulu } else {
1391*fa790ea9SDavid C Somayajulu ep = iparams->qp->ep;
1392*fa790ea9SDavid C Somayajulu DP_ERR(p_hwfn, "Note re-use of QP for different connect\n");
1393*fa790ea9SDavid C Somayajulu ep->state = ECORE_IWARP_EP_INIT;
1394*fa790ea9SDavid C Somayajulu }
1395*fa790ea9SDavid C Somayajulu
1396*fa790ea9SDavid C Somayajulu ep->tcp_cid = cid;
1397*fa790ea9SDavid C Somayajulu
1398*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
1399*fa790ea9SDavid C Somayajulu OSAL_LIST_PUSH_TAIL(&ep->list_entry,
1400*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->iwarp.ep_list);
1401*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
1402*fa790ea9SDavid C Somayajulu
1403*fa790ea9SDavid C Somayajulu ep->qp = iparams->qp;
1404*fa790ea9SDavid C Somayajulu ep->qp->ep = ep;
1405*fa790ea9SDavid C Somayajulu OSAL_MEMCPY(ep->remote_mac_addr,
1406*fa790ea9SDavid C Somayajulu iparams->remote_mac_addr,
1407*fa790ea9SDavid C Somayajulu ETH_ALEN);
1408*fa790ea9SDavid C Somayajulu OSAL_MEMCPY(ep->local_mac_addr,
1409*fa790ea9SDavid C Somayajulu iparams->local_mac_addr,
1410*fa790ea9SDavid C Somayajulu ETH_ALEN);
1411*fa790ea9SDavid C Somayajulu OSAL_MEMCPY(&ep->cm_info, &iparams->cm_info, sizeof(ep->cm_info));
1412*fa790ea9SDavid C Somayajulu
1413*fa790ea9SDavid C Somayajulu ep->cm_info.ord = iparams->cm_info.ord;
1414*fa790ea9SDavid C Somayajulu ep->cm_info.ird = iparams->cm_info.ird;
1415*fa790ea9SDavid C Somayajulu
1416*fa790ea9SDavid C Somayajulu ep->rtr_type = iwarp_info->rtr_type;
1417*fa790ea9SDavid C Somayajulu if (iwarp_info->peer2peer == 0)
1418*fa790ea9SDavid C Somayajulu ep->rtr_type = MPA_RTR_TYPE_NONE;
1419*fa790ea9SDavid C Somayajulu
1420*fa790ea9SDavid C Somayajulu if ((ep->rtr_type & MPA_RTR_TYPE_ZERO_READ) &&
1421*fa790ea9SDavid C Somayajulu (ep->cm_info.ord == 0))
1422*fa790ea9SDavid C Somayajulu ep->cm_info.ord = 1;
1423*fa790ea9SDavid C Somayajulu
1424*fa790ea9SDavid C Somayajulu ep->mpa_rev = iwarp_info->mpa_rev;
1425*fa790ea9SDavid C Somayajulu
1426*fa790ea9SDavid C Somayajulu ecore_iwarp_mpa_v2_set_private(p_hwfn, ep, &mpa_data_size);
1427*fa790ea9SDavid C Somayajulu
1428*fa790ea9SDavid C Somayajulu ep->cm_info.private_data = (u8 *)ep->ep_buffer_virt->out_pdata;
1429*fa790ea9SDavid C Somayajulu ep->cm_info.private_data_len =
1430*fa790ea9SDavid C Somayajulu iparams->cm_info.private_data_len + mpa_data_size;
1431*fa790ea9SDavid C Somayajulu
1432*fa790ea9SDavid C Somayajulu OSAL_MEMCPY((u8 *)(u8 *)ep->ep_buffer_virt->out_pdata + mpa_data_size,
1433*fa790ea9SDavid C Somayajulu iparams->cm_info.private_data,
1434*fa790ea9SDavid C Somayajulu iparams->cm_info.private_data_len);
1435*fa790ea9SDavid C Somayajulu
1436*fa790ea9SDavid C Somayajulu if (p_hwfn->p_rdma_info->iwarp.tcp_flags & ECORE_IWARP_TS_EN)
1437*fa790ea9SDavid C Somayajulu ts_hdr_size = TIMESTAMP_HEADER_SIZE;
1438*fa790ea9SDavid C Somayajulu
1439*fa790ea9SDavid C Somayajulu ep->mss = iparams->mss - ts_hdr_size;
1440*fa790ea9SDavid C Somayajulu ep->mss = OSAL_MIN_T(u16, ECORE_IWARP_MAX_FW_MSS, ep->mss);
1441*fa790ea9SDavid C Somayajulu
1442*fa790ea9SDavid C Somayajulu ep->event_cb = iparams->event_cb;
1443*fa790ea9SDavid C Somayajulu ep->cb_context = iparams->cb_context;
1444*fa790ea9SDavid C Somayajulu ep->connect_mode = TCP_CONNECT_ACTIVE;
1445*fa790ea9SDavid C Somayajulu
1446*fa790ea9SDavid C Somayajulu oparams->ep_context = ep;
1447*fa790ea9SDavid C Somayajulu
1448*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_tcp_offload(p_hwfn, ep);
1449*fa790ea9SDavid C Somayajulu
1450*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "QP(0x%x) EP(0x%x) rc = %d\n",
1451*fa790ea9SDavid C Somayajulu iparams->qp->icid, ep->tcp_cid, rc);
1452*fa790ea9SDavid C Somayajulu
1453*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
1454*fa790ea9SDavid C Somayajulu ecore_iwarp_destroy_ep(p_hwfn, ep, true);
1455*fa790ea9SDavid C Somayajulu
1456*fa790ea9SDavid C Somayajulu return rc;
1457*fa790ea9SDavid C Somayajulu }
1458*fa790ea9SDavid C Somayajulu
1459*fa790ea9SDavid C Somayajulu static struct ecore_iwarp_ep *
ecore_iwarp_get_free_ep(struct ecore_hwfn * p_hwfn)1460*fa790ea9SDavid C Somayajulu ecore_iwarp_get_free_ep(struct ecore_hwfn *p_hwfn)
1461*fa790ea9SDavid C Somayajulu {
1462*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep = OSAL_NULL;
1463*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
1464*fa790ea9SDavid C Somayajulu
1465*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
1466*fa790ea9SDavid C Somayajulu
1467*fa790ea9SDavid C Somayajulu if (OSAL_LIST_IS_EMPTY(&p_hwfn->p_rdma_info->iwarp.ep_free_list)) {
1468*fa790ea9SDavid C Somayajulu DP_ERR(p_hwfn, "Ep list is empty\n");
1469*fa790ea9SDavid C Somayajulu goto out;
1470*fa790ea9SDavid C Somayajulu }
1471*fa790ea9SDavid C Somayajulu
1472*fa790ea9SDavid C Somayajulu ep = OSAL_LIST_FIRST_ENTRY(&p_hwfn->p_rdma_info->iwarp.ep_free_list,
1473*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep,
1474*fa790ea9SDavid C Somayajulu list_entry);
1475*fa790ea9SDavid C Somayajulu
1476*fa790ea9SDavid C Somayajulu /* in some cases we could have failed allocating a tcp cid when added
1477*fa790ea9SDavid C Somayajulu * from accept / failure... retry now..this is not the common case.
1478*fa790ea9SDavid C Somayajulu */
1479*fa790ea9SDavid C Somayajulu if (ep->tcp_cid == ECORE_IWARP_INVALID_TCP_CID) {
1480*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_alloc_tcp_cid(p_hwfn, &ep->tcp_cid);
1481*fa790ea9SDavid C Somayajulu /* if we fail we could look for another entry with a valid
1482*fa790ea9SDavid C Somayajulu * tcp_cid, but since we don't expect to reach this anyway
1483*fa790ea9SDavid C Somayajulu * it's not worth the handling
1484*fa790ea9SDavid C Somayajulu */
1485*fa790ea9SDavid C Somayajulu if (rc) {
1486*fa790ea9SDavid C Somayajulu ep->tcp_cid = ECORE_IWARP_INVALID_TCP_CID;
1487*fa790ea9SDavid C Somayajulu ep = OSAL_NULL;
1488*fa790ea9SDavid C Somayajulu goto out;
1489*fa790ea9SDavid C Somayajulu }
1490*fa790ea9SDavid C Somayajulu }
1491*fa790ea9SDavid C Somayajulu
1492*fa790ea9SDavid C Somayajulu OSAL_LIST_REMOVE_ENTRY(&ep->list_entry,
1493*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->iwarp.ep_free_list);
1494*fa790ea9SDavid C Somayajulu
1495*fa790ea9SDavid C Somayajulu out:
1496*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
1497*fa790ea9SDavid C Somayajulu return ep;
1498*fa790ea9SDavid C Somayajulu }
1499*fa790ea9SDavid C Somayajulu
1500*fa790ea9SDavid C Somayajulu /* takes into account timer scan ~20 ms and interrupt/dpc overhead */
1501*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_MAX_CID_CLEAN_TIME 100
1502*fa790ea9SDavid C Somayajulu /* Technically we shouldn't reach this count with 100 ms iteration sleep */
1503*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_MAX_NO_PROGRESS_CNT 5
1504*fa790ea9SDavid C Somayajulu
1505*fa790ea9SDavid C Somayajulu /* This function waits for all the bits of a bmap to be cleared, as long as
1506*fa790ea9SDavid C Somayajulu * there is progress ( i.e. the number of bits left to be cleared decreases )
1507*fa790ea9SDavid C Somayajulu * the function continues.
1508*fa790ea9SDavid C Somayajulu */
1509*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
ecore_iwarp_wait_cid_map_cleared(struct ecore_hwfn * p_hwfn,struct ecore_bmap * bmap)1510*fa790ea9SDavid C Somayajulu ecore_iwarp_wait_cid_map_cleared(struct ecore_hwfn *p_hwfn,
1511*fa790ea9SDavid C Somayajulu struct ecore_bmap *bmap)
1512*fa790ea9SDavid C Somayajulu {
1513*fa790ea9SDavid C Somayajulu int prev_weight = 0;
1514*fa790ea9SDavid C Somayajulu int wait_count = 0;
1515*fa790ea9SDavid C Somayajulu int weight = 0;
1516*fa790ea9SDavid C Somayajulu
1517*fa790ea9SDavid C Somayajulu weight = OSAL_BITMAP_WEIGHT(bmap->bitmap, bmap->max_count);
1518*fa790ea9SDavid C Somayajulu prev_weight = weight;
1519*fa790ea9SDavid C Somayajulu
1520*fa790ea9SDavid C Somayajulu while (weight) {
1521*fa790ea9SDavid C Somayajulu OSAL_MSLEEP(ECORE_IWARP_MAX_CID_CLEAN_TIME);
1522*fa790ea9SDavid C Somayajulu
1523*fa790ea9SDavid C Somayajulu weight = OSAL_BITMAP_WEIGHT(bmap->bitmap, bmap->max_count);
1524*fa790ea9SDavid C Somayajulu
1525*fa790ea9SDavid C Somayajulu if (prev_weight == weight) {
1526*fa790ea9SDavid C Somayajulu wait_count++;
1527*fa790ea9SDavid C Somayajulu } else {
1528*fa790ea9SDavid C Somayajulu prev_weight = weight;
1529*fa790ea9SDavid C Somayajulu wait_count = 0;
1530*fa790ea9SDavid C Somayajulu }
1531*fa790ea9SDavid C Somayajulu
1532*fa790ea9SDavid C Somayajulu if (wait_count > ECORE_IWARP_MAX_NO_PROGRESS_CNT) {
1533*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false,
1534*fa790ea9SDavid C Somayajulu "%s bitmap wait timed out (%d cids pending)\n",
1535*fa790ea9SDavid C Somayajulu bmap->name, weight);
1536*fa790ea9SDavid C Somayajulu return ECORE_TIMEOUT;
1537*fa790ea9SDavid C Somayajulu }
1538*fa790ea9SDavid C Somayajulu }
1539*fa790ea9SDavid C Somayajulu return ECORE_SUCCESS;
1540*fa790ea9SDavid C Somayajulu }
1541*fa790ea9SDavid C Somayajulu
1542*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
ecore_iwarp_wait_for_all_cids(struct ecore_hwfn * p_hwfn)1543*fa790ea9SDavid C Somayajulu ecore_iwarp_wait_for_all_cids(struct ecore_hwfn *p_hwfn)
1544*fa790ea9SDavid C Somayajulu {
1545*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
1546*fa790ea9SDavid C Somayajulu int i;
1547*fa790ea9SDavid C Somayajulu
1548*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_wait_cid_map_cleared(
1549*fa790ea9SDavid C Somayajulu p_hwfn, &p_hwfn->p_rdma_info->tcp_cid_map);
1550*fa790ea9SDavid C Somayajulu if (rc)
1551*fa790ea9SDavid C Somayajulu return rc;
1552*fa790ea9SDavid C Somayajulu
1553*fa790ea9SDavid C Somayajulu /* Now free the tcp cids from the main cid map */
1554*fa790ea9SDavid C Somayajulu for (i = 0; i < ECORE_IWARP_PREALLOC_CNT; i++) {
1555*fa790ea9SDavid C Somayajulu ecore_bmap_release_id(p_hwfn,
1556*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->cid_map,
1557*fa790ea9SDavid C Somayajulu i);
1558*fa790ea9SDavid C Somayajulu }
1559*fa790ea9SDavid C Somayajulu
1560*fa790ea9SDavid C Somayajulu /* Now wait for all cids to be completed */
1561*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_wait_cid_map_cleared(
1562*fa790ea9SDavid C Somayajulu p_hwfn, &p_hwfn->p_rdma_info->cid_map);
1563*fa790ea9SDavid C Somayajulu
1564*fa790ea9SDavid C Somayajulu return rc;
1565*fa790ea9SDavid C Somayajulu }
1566*fa790ea9SDavid C Somayajulu
1567*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_free_prealloc_ep(struct ecore_hwfn * p_hwfn)1568*fa790ea9SDavid C Somayajulu ecore_iwarp_free_prealloc_ep(struct ecore_hwfn *p_hwfn)
1569*fa790ea9SDavid C Somayajulu {
1570*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep;
1571*fa790ea9SDavid C Somayajulu u32 cid;
1572*fa790ea9SDavid C Somayajulu
1573*fa790ea9SDavid C Somayajulu while (!OSAL_LIST_IS_EMPTY(&p_hwfn->p_rdma_info->iwarp.ep_free_list)) {
1574*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
1575*fa790ea9SDavid C Somayajulu
1576*fa790ea9SDavid C Somayajulu ep = OSAL_LIST_FIRST_ENTRY(
1577*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->iwarp.ep_free_list,
1578*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep, list_entry);
1579*fa790ea9SDavid C Somayajulu
1580*fa790ea9SDavid C Somayajulu if (ep == OSAL_NULL) {
1581*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
1582*fa790ea9SDavid C Somayajulu break;
1583*fa790ea9SDavid C Somayajulu }
1584*fa790ea9SDavid C Somayajulu
1585*fa790ea9SDavid C Somayajulu #ifdef _NTDDK_
1586*fa790ea9SDavid C Somayajulu #pragma warning(suppress : 6011)
1587*fa790ea9SDavid C Somayajulu #endif
1588*fa790ea9SDavid C Somayajulu OSAL_LIST_REMOVE_ENTRY(
1589*fa790ea9SDavid C Somayajulu &ep->list_entry,
1590*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->iwarp.ep_free_list);
1591*fa790ea9SDavid C Somayajulu
1592*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
1593*fa790ea9SDavid C Somayajulu
1594*fa790ea9SDavid C Somayajulu if (ep->tcp_cid != ECORE_IWARP_INVALID_TCP_CID) {
1595*fa790ea9SDavid C Somayajulu cid = ep->tcp_cid - ecore_cxt_get_proto_cid_start(
1596*fa790ea9SDavid C Somayajulu p_hwfn, p_hwfn->p_rdma_info->proto);
1597*fa790ea9SDavid C Somayajulu
1598*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&p_hwfn->p_rdma_info->lock);
1599*fa790ea9SDavid C Somayajulu
1600*fa790ea9SDavid C Somayajulu ecore_bmap_release_id(p_hwfn,
1601*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->tcp_cid_map,
1602*fa790ea9SDavid C Somayajulu cid);
1603*fa790ea9SDavid C Somayajulu
1604*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&p_hwfn->p_rdma_info->lock);
1605*fa790ea9SDavid C Somayajulu }
1606*fa790ea9SDavid C Somayajulu
1607*fa790ea9SDavid C Somayajulu ecore_iwarp_destroy_ep(p_hwfn, ep, false);
1608*fa790ea9SDavid C Somayajulu }
1609*fa790ea9SDavid C Somayajulu }
1610*fa790ea9SDavid C Somayajulu
1611*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
ecore_iwarp_prealloc_ep(struct ecore_hwfn * p_hwfn,bool init)1612*fa790ea9SDavid C Somayajulu ecore_iwarp_prealloc_ep(struct ecore_hwfn *p_hwfn, bool init)
1613*fa790ea9SDavid C Somayajulu {
1614*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep;
1615*fa790ea9SDavid C Somayajulu int rc = ECORE_SUCCESS;
1616*fa790ea9SDavid C Somayajulu u32 cid;
1617*fa790ea9SDavid C Somayajulu int count;
1618*fa790ea9SDavid C Somayajulu int i;
1619*fa790ea9SDavid C Somayajulu
1620*fa790ea9SDavid C Somayajulu if (init)
1621*fa790ea9SDavid C Somayajulu count = ECORE_IWARP_PREALLOC_CNT;
1622*fa790ea9SDavid C Somayajulu else
1623*fa790ea9SDavid C Somayajulu count = 1;
1624*fa790ea9SDavid C Somayajulu
1625*fa790ea9SDavid C Somayajulu for (i = 0; i < count; i++) {
1626*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_create_ep(p_hwfn, &ep);
1627*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
1628*fa790ea9SDavid C Somayajulu return rc;
1629*fa790ea9SDavid C Somayajulu
1630*fa790ea9SDavid C Somayajulu /* During initialization we allocate from the main pool,
1631*fa790ea9SDavid C Somayajulu * afterwards we allocate only from the tcp_cid.
1632*fa790ea9SDavid C Somayajulu */
1633*fa790ea9SDavid C Somayajulu if (init) {
1634*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_alloc_cid(p_hwfn, &cid);
1635*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
1636*fa790ea9SDavid C Somayajulu goto err;
1637*fa790ea9SDavid C Somayajulu ecore_iwarp_set_tcp_cid(p_hwfn, cid);
1638*fa790ea9SDavid C Somayajulu } else {
1639*fa790ea9SDavid C Somayajulu /* We don't care about the return code, it's ok if
1640*fa790ea9SDavid C Somayajulu * tcp_cid remains invalid...in this case we'll
1641*fa790ea9SDavid C Somayajulu * defer allocation
1642*fa790ea9SDavid C Somayajulu */
1643*fa790ea9SDavid C Somayajulu ecore_iwarp_alloc_tcp_cid(p_hwfn, &cid);
1644*fa790ea9SDavid C Somayajulu }
1645*fa790ea9SDavid C Somayajulu
1646*fa790ea9SDavid C Somayajulu ep->tcp_cid = cid;
1647*fa790ea9SDavid C Somayajulu
1648*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
1649*fa790ea9SDavid C Somayajulu OSAL_LIST_PUSH_TAIL(&ep->list_entry,
1650*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->iwarp.ep_free_list);
1651*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
1652*fa790ea9SDavid C Somayajulu }
1653*fa790ea9SDavid C Somayajulu
1654*fa790ea9SDavid C Somayajulu return rc;
1655*fa790ea9SDavid C Somayajulu
1656*fa790ea9SDavid C Somayajulu err:
1657*fa790ea9SDavid C Somayajulu ecore_iwarp_destroy_ep(p_hwfn, ep, false);
1658*fa790ea9SDavid C Somayajulu
1659*fa790ea9SDavid C Somayajulu return rc;
1660*fa790ea9SDavid C Somayajulu }
1661*fa790ea9SDavid C Somayajulu
1662*fa790ea9SDavid C Somayajulu enum _ecore_status_t
ecore_iwarp_alloc(struct ecore_hwfn * p_hwfn)1663*fa790ea9SDavid C Somayajulu ecore_iwarp_alloc(struct ecore_hwfn *p_hwfn)
1664*fa790ea9SDavid C Somayajulu {
1665*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
1666*fa790ea9SDavid C Somayajulu
1667*fa790ea9SDavid C Somayajulu #ifdef CONFIG_ECORE_LOCK_ALLOC
1668*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK_ALLOC(p_hwfn, &p_hwfn->p_rdma_info->iwarp.iw_lock);
1669*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK_ALLOC(p_hwfn, &p_hwfn->p_rdma_info->iwarp.qp_lock);
1670*fa790ea9SDavid C Somayajulu #endif
1671*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK_INIT(&p_hwfn->p_rdma_info->iwarp.iw_lock);
1672*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK_INIT(&p_hwfn->p_rdma_info->iwarp.qp_lock);
1673*fa790ea9SDavid C Somayajulu
1674*fa790ea9SDavid C Somayajulu /* Allocate bitmap for tcp cid. These are used by passive side
1675*fa790ea9SDavid C Somayajulu * to ensure it can allocate a tcp cid during dpc that was
1676*fa790ea9SDavid C Somayajulu * pre-acquired and doesn't require dynamic allocation of ilt
1677*fa790ea9SDavid C Somayajulu */
1678*fa790ea9SDavid C Somayajulu rc = ecore_rdma_bmap_alloc(p_hwfn, &p_hwfn->p_rdma_info->tcp_cid_map,
1679*fa790ea9SDavid C Somayajulu ECORE_IWARP_PREALLOC_CNT,
1680*fa790ea9SDavid C Somayajulu "TCP_CID");
1681*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS) {
1682*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
1683*fa790ea9SDavid C Somayajulu "Failed to allocate tcp cid, rc = %d\n",
1684*fa790ea9SDavid C Somayajulu rc);
1685*fa790ea9SDavid C Somayajulu return rc;
1686*fa790ea9SDavid C Somayajulu }
1687*fa790ea9SDavid C Somayajulu
1688*fa790ea9SDavid C Somayajulu OSAL_LIST_INIT(&p_hwfn->p_rdma_info->iwarp.ep_free_list);
1689*fa790ea9SDavid C Somayajulu //DAVIDS OSAL_SPIN_LOCK_INIT(&p_hwfn->p_rdma_info->iwarp.iw_lock);
1690*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_prealloc_ep(p_hwfn, true);
1691*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS) {
1692*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
1693*fa790ea9SDavid C Somayajulu "ecore_iwarp_prealloc_ep failed, rc = %d\n",
1694*fa790ea9SDavid C Somayajulu rc);
1695*fa790ea9SDavid C Somayajulu return rc;
1696*fa790ea9SDavid C Somayajulu }
1697*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
1698*fa790ea9SDavid C Somayajulu "ecore_iwarp_prealloc_ep success, rc = %d\n",
1699*fa790ea9SDavid C Somayajulu rc);
1700*fa790ea9SDavid C Somayajulu
1701*fa790ea9SDavid C Somayajulu return ecore_ooo_alloc(p_hwfn);
1702*fa790ea9SDavid C Somayajulu }
1703*fa790ea9SDavid C Somayajulu
1704*fa790ea9SDavid C Somayajulu void
ecore_iwarp_resc_free(struct ecore_hwfn * p_hwfn)1705*fa790ea9SDavid C Somayajulu ecore_iwarp_resc_free(struct ecore_hwfn *p_hwfn)
1706*fa790ea9SDavid C Somayajulu {
1707*fa790ea9SDavid C Somayajulu struct ecore_iwarp_info *iwarp_info = &p_hwfn->p_rdma_info->iwarp;
1708*fa790ea9SDavid C Somayajulu
1709*fa790ea9SDavid C Somayajulu #ifdef CONFIG_ECORE_LOCK_ALLOC
1710*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK_DEALLOC(iwarp_info->iw_lock);
1711*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK_DEALLOC(iwarp_info->qp_lock);
1712*fa790ea9SDavid C Somayajulu #endif
1713*fa790ea9SDavid C Somayajulu ecore_ooo_free(p_hwfn);
1714*fa790ea9SDavid C Somayajulu if (iwarp_info->partial_fpdus)
1715*fa790ea9SDavid C Somayajulu OSAL_FREE(p_hwfn->p_dev, iwarp_info->partial_fpdus);
1716*fa790ea9SDavid C Somayajulu if (iwarp_info->mpa_bufs)
1717*fa790ea9SDavid C Somayajulu OSAL_FREE(p_hwfn->p_dev, iwarp_info->mpa_bufs);
1718*fa790ea9SDavid C Somayajulu if (iwarp_info->mpa_intermediate_buf)
1719*fa790ea9SDavid C Somayajulu OSAL_FREE(p_hwfn->p_dev, iwarp_info->mpa_intermediate_buf);
1720*fa790ea9SDavid C Somayajulu
1721*fa790ea9SDavid C Somayajulu ecore_rdma_bmap_free(p_hwfn, &p_hwfn->p_rdma_info->tcp_cid_map, 1);
1722*fa790ea9SDavid C Somayajulu }
1723*fa790ea9SDavid C Somayajulu
1724*fa790ea9SDavid C Somayajulu enum _ecore_status_t
ecore_iwarp_accept(void * rdma_cxt,struct ecore_iwarp_accept_in * iparams)1725*fa790ea9SDavid C Somayajulu ecore_iwarp_accept(void *rdma_cxt,
1726*fa790ea9SDavid C Somayajulu struct ecore_iwarp_accept_in *iparams)
1727*fa790ea9SDavid C Somayajulu {
1728*fa790ea9SDavid C Somayajulu struct ecore_hwfn *p_hwfn = (struct ecore_hwfn *)rdma_cxt;
1729*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep;
1730*fa790ea9SDavid C Somayajulu u8 mpa_data_size = 0;
1731*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
1732*fa790ea9SDavid C Somayajulu
1733*fa790ea9SDavid C Somayajulu ep = (struct ecore_iwarp_ep *)iparams->ep_context;
1734*fa790ea9SDavid C Somayajulu if (!ep) {
1735*fa790ea9SDavid C Somayajulu DP_ERR(p_hwfn, "Ep Context receive in accept is NULL\n");
1736*fa790ea9SDavid C Somayajulu return ECORE_INVAL;
1737*fa790ea9SDavid C Somayajulu }
1738*fa790ea9SDavid C Somayajulu
1739*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "QP(0x%x) EP(0x%x)\n",
1740*fa790ea9SDavid C Somayajulu iparams->qp->icid, ep->tcp_cid);
1741*fa790ea9SDavid C Somayajulu
1742*fa790ea9SDavid C Somayajulu if ((iparams->ord > ECORE_IWARP_ORD_DEFAULT) ||
1743*fa790ea9SDavid C Somayajulu (iparams->ird > ECORE_IWARP_IRD_DEFAULT)) {
1744*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
1745*fa790ea9SDavid C Somayajulu "QP(0x%x) EP(0x%x) ERROR: Invalid ord(0x%x)/ird(0x%x)\n",
1746*fa790ea9SDavid C Somayajulu iparams->qp->icid, ep->tcp_cid,
1747*fa790ea9SDavid C Somayajulu iparams->ord, iparams->ord);
1748*fa790ea9SDavid C Somayajulu return ECORE_INVAL;
1749*fa790ea9SDavid C Somayajulu }
1750*fa790ea9SDavid C Somayajulu
1751*fa790ea9SDavid C Somayajulu /* We could reach qp->ep != OSAL NULL if we do accept on the same qp */
1752*fa790ea9SDavid C Somayajulu if (iparams->qp->ep == OSAL_NULL) {
1753*fa790ea9SDavid C Somayajulu /* We need to add a replacement for the ep to the free list */
1754*fa790ea9SDavid C Somayajulu ecore_iwarp_prealloc_ep(p_hwfn, false);
1755*fa790ea9SDavid C Somayajulu } else {
1756*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
1757*fa790ea9SDavid C Somayajulu "Note re-use of QP for different connect\n");
1758*fa790ea9SDavid C Somayajulu /* Return the old ep to the free_pool */
1759*fa790ea9SDavid C Somayajulu ecore_iwarp_return_ep(p_hwfn, iparams->qp->ep);
1760*fa790ea9SDavid C Somayajulu }
1761*fa790ea9SDavid C Somayajulu
1762*fa790ea9SDavid C Somayajulu ecore_iwarp_move_to_ep_list(p_hwfn,
1763*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->iwarp.ep_list,
1764*fa790ea9SDavid C Somayajulu ep);
1765*fa790ea9SDavid C Somayajulu ep->listener = OSAL_NULL;
1766*fa790ea9SDavid C Somayajulu ep->cb_context = iparams->cb_context;
1767*fa790ea9SDavid C Somayajulu ep->qp = iparams->qp;
1768*fa790ea9SDavid C Somayajulu ep->qp->ep = ep;
1769*fa790ea9SDavid C Somayajulu
1770*fa790ea9SDavid C Somayajulu if (ep->mpa_rev == MPA_NEGOTIATION_TYPE_ENHANCED) {
1771*fa790ea9SDavid C Somayajulu /* Negotiate ord/ird: if upperlayer requested ord larger than
1772*fa790ea9SDavid C Somayajulu * ird advertised by remote, we need to decrease our ord
1773*fa790ea9SDavid C Somayajulu * to match remote ord
1774*fa790ea9SDavid C Somayajulu */
1775*fa790ea9SDavid C Somayajulu if (iparams->ord > ep->cm_info.ird) {
1776*fa790ea9SDavid C Somayajulu iparams->ord = ep->cm_info.ird;
1777*fa790ea9SDavid C Somayajulu }
1778*fa790ea9SDavid C Somayajulu
1779*fa790ea9SDavid C Somayajulu /* For chelsio compatability, if rtr_zero read is requested
1780*fa790ea9SDavid C Somayajulu * we can't set ird to zero
1781*fa790ea9SDavid C Somayajulu */
1782*fa790ea9SDavid C Somayajulu if ((ep->rtr_type & MPA_RTR_TYPE_ZERO_READ) &&
1783*fa790ea9SDavid C Somayajulu (iparams->ird == 0))
1784*fa790ea9SDavid C Somayajulu iparams->ird = 1;
1785*fa790ea9SDavid C Somayajulu }
1786*fa790ea9SDavid C Somayajulu
1787*fa790ea9SDavid C Somayajulu /* Update cm_info ord/ird to be negotiated values */
1788*fa790ea9SDavid C Somayajulu ep->cm_info.ord = iparams->ord;
1789*fa790ea9SDavid C Somayajulu ep->cm_info.ird = iparams->ird;
1790*fa790ea9SDavid C Somayajulu
1791*fa790ea9SDavid C Somayajulu ecore_iwarp_mpa_v2_set_private(p_hwfn, ep, &mpa_data_size);
1792*fa790ea9SDavid C Somayajulu
1793*fa790ea9SDavid C Somayajulu ep->cm_info.private_data = ep->ep_buffer_virt->out_pdata;
1794*fa790ea9SDavid C Somayajulu ep->cm_info.private_data_len =
1795*fa790ea9SDavid C Somayajulu iparams->private_data_len + mpa_data_size;
1796*fa790ea9SDavid C Somayajulu
1797*fa790ea9SDavid C Somayajulu OSAL_MEMCPY((u8 *)ep->ep_buffer_virt->out_pdata + mpa_data_size,
1798*fa790ea9SDavid C Somayajulu iparams->private_data,
1799*fa790ea9SDavid C Somayajulu iparams->private_data_len);
1800*fa790ea9SDavid C Somayajulu
1801*fa790ea9SDavid C Somayajulu if (ep->state == ECORE_IWARP_EP_CLOSED) {
1802*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false,
1803*fa790ea9SDavid C Somayajulu "(0x%x) Accept called on EP in CLOSED state\n",
1804*fa790ea9SDavid C Somayajulu ep->tcp_cid);
1805*fa790ea9SDavid C Somayajulu ep->tcp_cid = ECORE_IWARP_INVALID_TCP_CID;
1806*fa790ea9SDavid C Somayajulu ecore_iwarp_return_ep(p_hwfn, ep);
1807*fa790ea9SDavid C Somayajulu return ECORE_CONN_RESET;
1808*fa790ea9SDavid C Somayajulu }
1809*fa790ea9SDavid C Somayajulu
1810*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_mpa_offload(p_hwfn, ep);
1811*fa790ea9SDavid C Somayajulu if (rc) {
1812*fa790ea9SDavid C Somayajulu ecore_iwarp_modify_qp(p_hwfn,
1813*fa790ea9SDavid C Somayajulu iparams->qp,
1814*fa790ea9SDavid C Somayajulu ECORE_IWARP_QP_STATE_ERROR,
1815*fa790ea9SDavid C Somayajulu 1);
1816*fa790ea9SDavid C Somayajulu }
1817*fa790ea9SDavid C Somayajulu
1818*fa790ea9SDavid C Somayajulu return rc;
1819*fa790ea9SDavid C Somayajulu }
1820*fa790ea9SDavid C Somayajulu
1821*fa790ea9SDavid C Somayajulu enum _ecore_status_t
ecore_iwarp_reject(void * rdma_cxt,struct ecore_iwarp_reject_in * iparams)1822*fa790ea9SDavid C Somayajulu ecore_iwarp_reject(void *rdma_cxt,
1823*fa790ea9SDavid C Somayajulu struct ecore_iwarp_reject_in *iparams)
1824*fa790ea9SDavid C Somayajulu {
1825*fa790ea9SDavid C Somayajulu struct ecore_hwfn *p_hwfn = (struct ecore_hwfn *)rdma_cxt;
1826*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep;
1827*fa790ea9SDavid C Somayajulu u8 mpa_data_size = 0;
1828*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
1829*fa790ea9SDavid C Somayajulu
1830*fa790ea9SDavid C Somayajulu ep = (struct ecore_iwarp_ep *)iparams->ep_context;
1831*fa790ea9SDavid C Somayajulu if (!ep) {
1832*fa790ea9SDavid C Somayajulu DP_ERR(p_hwfn, "Ep Context receive in reject is NULL\n");
1833*fa790ea9SDavid C Somayajulu return ECORE_INVAL;
1834*fa790ea9SDavid C Somayajulu }
1835*fa790ea9SDavid C Somayajulu
1836*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "EP(0x%x)\n", ep->tcp_cid);
1837*fa790ea9SDavid C Somayajulu
1838*fa790ea9SDavid C Somayajulu ep->cb_context = iparams->cb_context;
1839*fa790ea9SDavid C Somayajulu ep->qp = OSAL_NULL;
1840*fa790ea9SDavid C Somayajulu
1841*fa790ea9SDavid C Somayajulu ecore_iwarp_mpa_v2_set_private(p_hwfn, ep, &mpa_data_size);
1842*fa790ea9SDavid C Somayajulu
1843*fa790ea9SDavid C Somayajulu ep->cm_info.private_data = ep->ep_buffer_virt->out_pdata;
1844*fa790ea9SDavid C Somayajulu ep->cm_info.private_data_len =
1845*fa790ea9SDavid C Somayajulu iparams->private_data_len + mpa_data_size;
1846*fa790ea9SDavid C Somayajulu
1847*fa790ea9SDavid C Somayajulu OSAL_MEMCPY((u8 *)ep->ep_buffer_virt->out_pdata + mpa_data_size,
1848*fa790ea9SDavid C Somayajulu iparams->private_data,
1849*fa790ea9SDavid C Somayajulu iparams->private_data_len);
1850*fa790ea9SDavid C Somayajulu
1851*fa790ea9SDavid C Somayajulu if (ep->state == ECORE_IWARP_EP_CLOSED) {
1852*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false,
1853*fa790ea9SDavid C Somayajulu "(0x%x) Reject called on EP in CLOSED state\n",
1854*fa790ea9SDavid C Somayajulu ep->tcp_cid);
1855*fa790ea9SDavid C Somayajulu ep->tcp_cid = ECORE_IWARP_INVALID_TCP_CID;
1856*fa790ea9SDavid C Somayajulu ecore_iwarp_return_ep(p_hwfn, ep);
1857*fa790ea9SDavid C Somayajulu return ECORE_CONN_RESET;
1858*fa790ea9SDavid C Somayajulu }
1859*fa790ea9SDavid C Somayajulu
1860*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_mpa_offload(p_hwfn, ep);
1861*fa790ea9SDavid C Somayajulu return rc;
1862*fa790ea9SDavid C Somayajulu }
1863*fa790ea9SDavid C Somayajulu
1864*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_print_cm_info(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_cm_info * cm_info)1865*fa790ea9SDavid C Somayajulu ecore_iwarp_print_cm_info(struct ecore_hwfn *p_hwfn,
1866*fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_info *cm_info)
1867*fa790ea9SDavid C Somayajulu {
1868*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "ip_version = %d\n",
1869*fa790ea9SDavid C Somayajulu cm_info->ip_version);
1870*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "remote_ip %x.%x.%x.%x\n",
1871*fa790ea9SDavid C Somayajulu cm_info->remote_ip[0],
1872*fa790ea9SDavid C Somayajulu cm_info->remote_ip[1],
1873*fa790ea9SDavid C Somayajulu cm_info->remote_ip[2],
1874*fa790ea9SDavid C Somayajulu cm_info->remote_ip[3]);
1875*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "local_ip %x.%x.%x.%x\n",
1876*fa790ea9SDavid C Somayajulu cm_info->local_ip[0],
1877*fa790ea9SDavid C Somayajulu cm_info->local_ip[1],
1878*fa790ea9SDavid C Somayajulu cm_info->local_ip[2],
1879*fa790ea9SDavid C Somayajulu cm_info->local_ip[3]);
1880*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "remote_port = %x\n",
1881*fa790ea9SDavid C Somayajulu cm_info->remote_port);
1882*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "local_port = %x\n",
1883*fa790ea9SDavid C Somayajulu cm_info->local_port);
1884*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "vlan = %x\n",
1885*fa790ea9SDavid C Somayajulu cm_info->vlan);
1886*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "private_data_len = %x\n",
1887*fa790ea9SDavid C Somayajulu cm_info->private_data_len);
1888*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "ord = %d\n",
1889*fa790ea9SDavid C Somayajulu cm_info->ord);
1890*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "ird = %d\n",
1891*fa790ea9SDavid C Somayajulu cm_info->ird);
1892*fa790ea9SDavid C Somayajulu }
1893*fa790ea9SDavid C Somayajulu
1894*fa790ea9SDavid C Somayajulu static int
ecore_iwarp_ll2_post_rx(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_ll2_buff * buf,u8 handle)1895*fa790ea9SDavid C Somayajulu ecore_iwarp_ll2_post_rx(struct ecore_hwfn *p_hwfn,
1896*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ll2_buff *buf,
1897*fa790ea9SDavid C Somayajulu u8 handle)
1898*fa790ea9SDavid C Somayajulu {
1899*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
1900*fa790ea9SDavid C Somayajulu
1901*fa790ea9SDavid C Somayajulu rc = ecore_ll2_post_rx_buffer(
1902*fa790ea9SDavid C Somayajulu p_hwfn,
1903*fa790ea9SDavid C Somayajulu handle,
1904*fa790ea9SDavid C Somayajulu buf->data_phys_addr,
1905*fa790ea9SDavid C Somayajulu (u16)buf->buff_size,
1906*fa790ea9SDavid C Somayajulu buf, 1);
1907*fa790ea9SDavid C Somayajulu
1908*fa790ea9SDavid C Somayajulu if (rc) {
1909*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false,
1910*fa790ea9SDavid C Somayajulu "Failed to repost rx buffer to ll2 rc = %d, handle=%d\n",
1911*fa790ea9SDavid C Somayajulu rc, handle);
1912*fa790ea9SDavid C Somayajulu OSAL_DMA_FREE_COHERENT(
1913*fa790ea9SDavid C Somayajulu p_hwfn->p_dev,
1914*fa790ea9SDavid C Somayajulu buf->data,
1915*fa790ea9SDavid C Somayajulu buf->data_phys_addr,
1916*fa790ea9SDavid C Somayajulu buf->buff_size);
1917*fa790ea9SDavid C Somayajulu OSAL_FREE(p_hwfn->p_dev, buf);
1918*fa790ea9SDavid C Somayajulu }
1919*fa790ea9SDavid C Somayajulu
1920*fa790ea9SDavid C Somayajulu return rc;
1921*fa790ea9SDavid C Somayajulu }
1922*fa790ea9SDavid C Somayajulu
1923*fa790ea9SDavid C Somayajulu static bool
ecore_iwarp_ep_exists(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_listener * listener,struct ecore_iwarp_cm_info * cm_info)1924*fa790ea9SDavid C Somayajulu ecore_iwarp_ep_exists(struct ecore_hwfn *p_hwfn,
1925*fa790ea9SDavid C Somayajulu struct ecore_iwarp_listener *listener,
1926*fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_info *cm_info)
1927*fa790ea9SDavid C Somayajulu {
1928*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep = OSAL_NULL;
1929*fa790ea9SDavid C Somayajulu bool found = false;
1930*fa790ea9SDavid C Somayajulu
1931*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&listener->lock);
1932*fa790ea9SDavid C Somayajulu OSAL_LIST_FOR_EACH_ENTRY(ep, &listener->ep_list,
1933*fa790ea9SDavid C Somayajulu list_entry, struct ecore_iwarp_ep) {
1934*fa790ea9SDavid C Somayajulu if ((ep->cm_info.local_port == cm_info->local_port) &&
1935*fa790ea9SDavid C Somayajulu (ep->cm_info.remote_port == cm_info->remote_port) &&
1936*fa790ea9SDavid C Somayajulu (ep->cm_info.vlan == cm_info->vlan) &&
1937*fa790ea9SDavid C Somayajulu !OSAL_MEMCMP(&(ep->cm_info.local_ip), cm_info->local_ip,
1938*fa790ea9SDavid C Somayajulu sizeof(cm_info->local_ip)) &&
1939*fa790ea9SDavid C Somayajulu !OSAL_MEMCMP(&(ep->cm_info.remote_ip), cm_info->remote_ip,
1940*fa790ea9SDavid C Somayajulu sizeof(cm_info->remote_ip))) {
1941*fa790ea9SDavid C Somayajulu found = true;
1942*fa790ea9SDavid C Somayajulu break;
1943*fa790ea9SDavid C Somayajulu }
1944*fa790ea9SDavid C Somayajulu }
1945*fa790ea9SDavid C Somayajulu
1946*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&listener->lock);
1947*fa790ea9SDavid C Somayajulu
1948*fa790ea9SDavid C Somayajulu if (found) {
1949*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "SYN received on active connection - dropping\n");
1950*fa790ea9SDavid C Somayajulu ecore_iwarp_print_cm_info(p_hwfn, cm_info);
1951*fa790ea9SDavid C Somayajulu
1952*fa790ea9SDavid C Somayajulu return true;
1953*fa790ea9SDavid C Somayajulu }
1954*fa790ea9SDavid C Somayajulu
1955*fa790ea9SDavid C Somayajulu return false;
1956*fa790ea9SDavid C Somayajulu }
1957*fa790ea9SDavid C Somayajulu
1958*fa790ea9SDavid C Somayajulu static struct ecore_iwarp_listener *
ecore_iwarp_get_listener(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_cm_info * cm_info)1959*fa790ea9SDavid C Somayajulu ecore_iwarp_get_listener(struct ecore_hwfn *p_hwfn,
1960*fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_info *cm_info)
1961*fa790ea9SDavid C Somayajulu {
1962*fa790ea9SDavid C Somayajulu struct ecore_iwarp_listener *listener = OSAL_NULL;
1963*fa790ea9SDavid C Somayajulu static const u32 ip_zero[4] = {0, 0, 0, 0};
1964*fa790ea9SDavid C Somayajulu bool found = false;
1965*fa790ea9SDavid C Somayajulu
1966*fa790ea9SDavid C Somayajulu ecore_iwarp_print_cm_info(p_hwfn, cm_info);
1967*fa790ea9SDavid C Somayajulu
1968*fa790ea9SDavid C Somayajulu OSAL_LIST_FOR_EACH_ENTRY(listener,
1969*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->iwarp.listen_list,
1970*fa790ea9SDavid C Somayajulu list_entry, struct ecore_iwarp_listener) {
1971*fa790ea9SDavid C Somayajulu if (listener->port == cm_info->local_port) {
1972*fa790ea9SDavid C Somayajulu /* Any IP (i.e. 0.0.0.0 ) will be treated as any vlan */
1973*fa790ea9SDavid C Somayajulu if (!OSAL_MEMCMP(listener->ip_addr,
1974*fa790ea9SDavid C Somayajulu ip_zero,
1975*fa790ea9SDavid C Somayajulu sizeof(ip_zero))) {
1976*fa790ea9SDavid C Somayajulu found = true;
1977*fa790ea9SDavid C Somayajulu break;
1978*fa790ea9SDavid C Somayajulu }
1979*fa790ea9SDavid C Somayajulu
1980*fa790ea9SDavid C Somayajulu /* If not any IP -> check vlan as well */
1981*fa790ea9SDavid C Somayajulu if (!OSAL_MEMCMP(listener->ip_addr,
1982*fa790ea9SDavid C Somayajulu cm_info->local_ip,
1983*fa790ea9SDavid C Somayajulu sizeof(cm_info->local_ip)) &&
1984*fa790ea9SDavid C Somayajulu
1985*fa790ea9SDavid C Somayajulu (listener->vlan == cm_info->vlan)) {
1986*fa790ea9SDavid C Somayajulu found = true;
1987*fa790ea9SDavid C Somayajulu break;
1988*fa790ea9SDavid C Somayajulu }
1989*fa790ea9SDavid C Somayajulu }
1990*fa790ea9SDavid C Somayajulu }
1991*fa790ea9SDavid C Somayajulu
1992*fa790ea9SDavid C Somayajulu if (found && listener->state == ECORE_IWARP_LISTENER_STATE_ACTIVE) {
1993*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "listener found = %p\n",
1994*fa790ea9SDavid C Somayajulu listener);
1995*fa790ea9SDavid C Somayajulu return listener;
1996*fa790ea9SDavid C Somayajulu }
1997*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "listener not found\n");
1998*fa790ea9SDavid C Somayajulu return OSAL_NULL;
1999*fa790ea9SDavid C Somayajulu }
2000*fa790ea9SDavid C Somayajulu
2001*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
ecore_iwarp_parse_rx_pkt(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_cm_info * cm_info,void * buf,u8 * remote_mac_addr,u8 * local_mac_addr,int * payload_len,int * tcp_start_offset)2002*fa790ea9SDavid C Somayajulu ecore_iwarp_parse_rx_pkt(struct ecore_hwfn *p_hwfn,
2003*fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_info *cm_info,
2004*fa790ea9SDavid C Somayajulu void *buf,
2005*fa790ea9SDavid C Somayajulu u8 *remote_mac_addr,
2006*fa790ea9SDavid C Somayajulu u8 *local_mac_addr,
2007*fa790ea9SDavid C Somayajulu int *payload_len,
2008*fa790ea9SDavid C Somayajulu int *tcp_start_offset)
2009*fa790ea9SDavid C Somayajulu {
2010*fa790ea9SDavid C Somayajulu struct ecore_vlan_ethhdr *vethh;
2011*fa790ea9SDavid C Somayajulu struct ecore_ethhdr *ethh;
2012*fa790ea9SDavid C Somayajulu struct ecore_iphdr *iph;
2013*fa790ea9SDavid C Somayajulu struct ecore_ipv6hdr *ip6h;
2014*fa790ea9SDavid C Somayajulu struct ecore_tcphdr *tcph;
2015*fa790ea9SDavid C Somayajulu bool vlan_valid = false;
2016*fa790ea9SDavid C Somayajulu int eth_hlen, ip_hlen;
2017*fa790ea9SDavid C Somayajulu u16 eth_type;
2018*fa790ea9SDavid C Somayajulu int i;
2019*fa790ea9SDavid C Somayajulu
2020*fa790ea9SDavid C Somayajulu ethh = (struct ecore_ethhdr *)buf;
2021*fa790ea9SDavid C Somayajulu eth_type = ntohs(ethh->h_proto);
2022*fa790ea9SDavid C Somayajulu if (eth_type == ETH_P_8021Q) {
2023*fa790ea9SDavid C Somayajulu vlan_valid = true;
2024*fa790ea9SDavid C Somayajulu vethh = (struct ecore_vlan_ethhdr *)ethh;
2025*fa790ea9SDavid C Somayajulu cm_info->vlan = ntohs(vethh->h_vlan_TCI) & VLAN_VID_MASK;
2026*fa790ea9SDavid C Somayajulu eth_type = ntohs(vethh->h_vlan_encapsulated_proto);
2027*fa790ea9SDavid C Somayajulu }
2028*fa790ea9SDavid C Somayajulu
2029*fa790ea9SDavid C Somayajulu eth_hlen = ETH_HLEN + (vlan_valid ? sizeof(u32) : 0);
2030*fa790ea9SDavid C Somayajulu
2031*fa790ea9SDavid C Somayajulu OSAL_MEMCPY(remote_mac_addr,
2032*fa790ea9SDavid C Somayajulu ethh->h_source,
2033*fa790ea9SDavid C Somayajulu ETH_ALEN);
2034*fa790ea9SDavid C Somayajulu
2035*fa790ea9SDavid C Somayajulu OSAL_MEMCPY(local_mac_addr,
2036*fa790ea9SDavid C Somayajulu ethh->h_dest,
2037*fa790ea9SDavid C Somayajulu ETH_ALEN);
2038*fa790ea9SDavid C Somayajulu
2039*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "eth_type =%d Source mac: [0x%x]:[0x%x]:[0x%x]:[0x%x]:[0x%x]:[0x%x]\n",
2040*fa790ea9SDavid C Somayajulu eth_type, ethh->h_source[0], ethh->h_source[1],
2041*fa790ea9SDavid C Somayajulu ethh->h_source[2], ethh->h_source[3],
2042*fa790ea9SDavid C Somayajulu ethh->h_source[4], ethh->h_source[5]);
2043*fa790ea9SDavid C Somayajulu
2044*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "eth_hlen=%d destination mac: [0x%x]:[0x%x]:[0x%x]:[0x%x]:[0x%x]:[0x%x]\n",
2045*fa790ea9SDavid C Somayajulu eth_hlen, ethh->h_dest[0], ethh->h_dest[1],
2046*fa790ea9SDavid C Somayajulu ethh->h_dest[2], ethh->h_dest[3],
2047*fa790ea9SDavid C Somayajulu ethh->h_dest[4], ethh->h_dest[5]);
2048*fa790ea9SDavid C Somayajulu
2049*fa790ea9SDavid C Somayajulu iph = (struct ecore_iphdr *)((u8 *)(ethh) + eth_hlen);
2050*fa790ea9SDavid C Somayajulu
2051*fa790ea9SDavid C Somayajulu if (eth_type == ETH_P_IP) {
2052*fa790ea9SDavid C Somayajulu if (iph->protocol != IPPROTO_TCP) {
2053*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false,
2054*fa790ea9SDavid C Somayajulu "Unexpected ip protocol on ll2 %x\n",
2055*fa790ea9SDavid C Somayajulu iph->protocol);
2056*fa790ea9SDavid C Somayajulu return ECORE_INVAL;
2057*fa790ea9SDavid C Somayajulu }
2058*fa790ea9SDavid C Somayajulu
2059*fa790ea9SDavid C Somayajulu cm_info->local_ip[0] = ntohl(iph->daddr);
2060*fa790ea9SDavid C Somayajulu cm_info->remote_ip[0] = ntohl(iph->saddr);
2061*fa790ea9SDavid C Somayajulu cm_info->ip_version = (enum ecore_tcp_ip_version)TCP_IPV4;
2062*fa790ea9SDavid C Somayajulu
2063*fa790ea9SDavid C Somayajulu ip_hlen = (iph->ihl)*sizeof(u32);
2064*fa790ea9SDavid C Somayajulu *payload_len = ntohs(iph->tot_len) - ip_hlen;
2065*fa790ea9SDavid C Somayajulu
2066*fa790ea9SDavid C Somayajulu } else if (eth_type == ETH_P_IPV6) {
2067*fa790ea9SDavid C Somayajulu ip6h = (struct ecore_ipv6hdr *)iph;
2068*fa790ea9SDavid C Somayajulu
2069*fa790ea9SDavid C Somayajulu if (ip6h->nexthdr != IPPROTO_TCP) {
2070*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false,
2071*fa790ea9SDavid C Somayajulu "Unexpected ip protocol on ll2 %x\n",
2072*fa790ea9SDavid C Somayajulu iph->protocol);
2073*fa790ea9SDavid C Somayajulu return ECORE_INVAL;
2074*fa790ea9SDavid C Somayajulu }
2075*fa790ea9SDavid C Somayajulu
2076*fa790ea9SDavid C Somayajulu for (i = 0; i < 4; i++) {
2077*fa790ea9SDavid C Somayajulu cm_info->local_ip[i] =
2078*fa790ea9SDavid C Somayajulu ntohl(ip6h->daddr.in6_u.u6_addr32[i]);
2079*fa790ea9SDavid C Somayajulu cm_info->remote_ip[i] =
2080*fa790ea9SDavid C Somayajulu ntohl(ip6h->saddr.in6_u.u6_addr32[i]);
2081*fa790ea9SDavid C Somayajulu }
2082*fa790ea9SDavid C Somayajulu cm_info->ip_version = (enum ecore_tcp_ip_version)TCP_IPV6;
2083*fa790ea9SDavid C Somayajulu
2084*fa790ea9SDavid C Somayajulu ip_hlen = sizeof(*ip6h);
2085*fa790ea9SDavid C Somayajulu *payload_len = ntohs(ip6h->payload_len);
2086*fa790ea9SDavid C Somayajulu } else {
2087*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false,
2088*fa790ea9SDavid C Somayajulu "Unexpected ethertype on ll2 %x\n", eth_type);
2089*fa790ea9SDavid C Somayajulu return ECORE_INVAL;
2090*fa790ea9SDavid C Somayajulu }
2091*fa790ea9SDavid C Somayajulu
2092*fa790ea9SDavid C Somayajulu tcph = (struct ecore_tcphdr *)((u8 *)iph + ip_hlen);
2093*fa790ea9SDavid C Somayajulu
2094*fa790ea9SDavid C Somayajulu if (!tcph->syn) {
2095*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false,
2096*fa790ea9SDavid C Somayajulu "Only SYN type packet expected on this ll2 conn, iph->ihl=%d source=%d dest=%d\n",
2097*fa790ea9SDavid C Somayajulu iph->ihl, tcph->source, tcph->dest);
2098*fa790ea9SDavid C Somayajulu return ECORE_INVAL;
2099*fa790ea9SDavid C Somayajulu }
2100*fa790ea9SDavid C Somayajulu
2101*fa790ea9SDavid C Somayajulu cm_info->local_port = ntohs(tcph->dest);
2102*fa790ea9SDavid C Somayajulu cm_info->remote_port = ntohs(tcph->source);
2103*fa790ea9SDavid C Somayajulu
2104*fa790ea9SDavid C Somayajulu ecore_iwarp_print_cm_info(p_hwfn, cm_info);
2105*fa790ea9SDavid C Somayajulu
2106*fa790ea9SDavid C Somayajulu *tcp_start_offset = eth_hlen + ip_hlen;
2107*fa790ea9SDavid C Somayajulu
2108*fa790ea9SDavid C Somayajulu return ECORE_SUCCESS;
2109*fa790ea9SDavid C Somayajulu }
2110*fa790ea9SDavid C Somayajulu
2111*fa790ea9SDavid C Somayajulu static struct ecore_iwarp_fpdu *
ecore_iwarp_get_curr_fpdu(struct ecore_hwfn * p_hwfn,u16 cid)2112*fa790ea9SDavid C Somayajulu ecore_iwarp_get_curr_fpdu(struct ecore_hwfn *p_hwfn, u16 cid)
2113*fa790ea9SDavid C Somayajulu {
2114*fa790ea9SDavid C Somayajulu struct ecore_iwarp_info *iwarp_info = &p_hwfn->p_rdma_info->iwarp;
2115*fa790ea9SDavid C Somayajulu struct ecore_iwarp_fpdu *partial_fpdu;
2116*fa790ea9SDavid C Somayajulu u32 idx = cid - ecore_cxt_get_proto_cid_start(p_hwfn, PROTOCOLID_IWARP);
2117*fa790ea9SDavid C Somayajulu
2118*fa790ea9SDavid C Somayajulu if (idx >= iwarp_info->max_num_partial_fpdus) {
2119*fa790ea9SDavid C Somayajulu DP_ERR(p_hwfn, "Invalid cid %x max_num_partial_fpdus=%x\n", cid,
2120*fa790ea9SDavid C Somayajulu iwarp_info->max_num_partial_fpdus);
2121*fa790ea9SDavid C Somayajulu return OSAL_NULL;
2122*fa790ea9SDavid C Somayajulu }
2123*fa790ea9SDavid C Somayajulu
2124*fa790ea9SDavid C Somayajulu partial_fpdu = &iwarp_info->partial_fpdus[idx];
2125*fa790ea9SDavid C Somayajulu
2126*fa790ea9SDavid C Somayajulu return partial_fpdu;
2127*fa790ea9SDavid C Somayajulu }
2128*fa790ea9SDavid C Somayajulu
2129*fa790ea9SDavid C Somayajulu enum ecore_iwarp_mpa_pkt_type {
2130*fa790ea9SDavid C Somayajulu ECORE_IWARP_MPA_PKT_PACKED,
2131*fa790ea9SDavid C Somayajulu ECORE_IWARP_MPA_PKT_PARTIAL,
2132*fa790ea9SDavid C Somayajulu ECORE_IWARP_MPA_PKT_UNALIGNED
2133*fa790ea9SDavid C Somayajulu };
2134*fa790ea9SDavid C Somayajulu
2135*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_INVALID_FPDU_LENGTH 0xffff
2136*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_MPA_FPDU_LENGTH_SIZE (2)
2137*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_MPA_CRC32_DIGEST_SIZE (4)
2138*fa790ea9SDavid C Somayajulu
2139*fa790ea9SDavid C Somayajulu /* Pad to multiple of 4 */
2140*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_PDU_DATA_LEN_WITH_PAD(data_len) (((data_len) + 3) & ~3)
2141*fa790ea9SDavid C Somayajulu
2142*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_FPDU_LEN_WITH_PAD(_mpa_len) \
2143*fa790ea9SDavid C Somayajulu (ECORE_IWARP_PDU_DATA_LEN_WITH_PAD(_mpa_len + \
2144*fa790ea9SDavid C Somayajulu ECORE_IWARP_MPA_FPDU_LENGTH_SIZE) + \
2145*fa790ea9SDavid C Somayajulu ECORE_IWARP_MPA_CRC32_DIGEST_SIZE)
2146*fa790ea9SDavid C Somayajulu
2147*fa790ea9SDavid C Somayajulu /* fpdu can be fragmented over maximum 3 bds: header, partial mpa, unaligned */
2148*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_MAX_BDS_PER_FPDU 3
2149*fa790ea9SDavid C Somayajulu
2150*fa790ea9SDavid C Somayajulu char *pkt_type_str[] = {
2151*fa790ea9SDavid C Somayajulu "ECORE_IWARP_MPA_PKT_PACKED",
2152*fa790ea9SDavid C Somayajulu "ECORE_IWARP_MPA_PKT_PARTIAL",
2153*fa790ea9SDavid C Somayajulu "ECORE_IWARP_MPA_PKT_UNALIGNED"
2154*fa790ea9SDavid C Somayajulu };
2155*fa790ea9SDavid C Somayajulu
2156*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
2157*fa790ea9SDavid C Somayajulu ecore_iwarp_recycle_pkt(struct ecore_hwfn *p_hwfn,
2158*fa790ea9SDavid C Somayajulu struct ecore_iwarp_fpdu *fpdu,
2159*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ll2_buff *buf);
2160*fa790ea9SDavid C Somayajulu
2161*fa790ea9SDavid C Somayajulu static enum ecore_iwarp_mpa_pkt_type
ecore_iwarp_mpa_classify(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_fpdu * fpdu,u16 tcp_payload_len,u8 * mpa_data)2162*fa790ea9SDavid C Somayajulu ecore_iwarp_mpa_classify(struct ecore_hwfn *p_hwfn,
2163*fa790ea9SDavid C Somayajulu struct ecore_iwarp_fpdu *fpdu,
2164*fa790ea9SDavid C Somayajulu u16 tcp_payload_len,
2165*fa790ea9SDavid C Somayajulu u8 *mpa_data)
2166*fa790ea9SDavid C Somayajulu
2167*fa790ea9SDavid C Somayajulu {
2168*fa790ea9SDavid C Somayajulu enum ecore_iwarp_mpa_pkt_type pkt_type;
2169*fa790ea9SDavid C Somayajulu u16 mpa_len;
2170*fa790ea9SDavid C Somayajulu
2171*fa790ea9SDavid C Somayajulu if (fpdu->incomplete_bytes) {
2172*fa790ea9SDavid C Somayajulu pkt_type = ECORE_IWARP_MPA_PKT_UNALIGNED;
2173*fa790ea9SDavid C Somayajulu goto out;
2174*fa790ea9SDavid C Somayajulu }
2175*fa790ea9SDavid C Somayajulu
2176*fa790ea9SDavid C Somayajulu /* special case of one byte remaining... */
2177*fa790ea9SDavid C Somayajulu if (tcp_payload_len == 1) {
2178*fa790ea9SDavid C Somayajulu /* lower byte will be read next packet */
2179*fa790ea9SDavid C Somayajulu fpdu->fpdu_length = *mpa_data << 8;
2180*fa790ea9SDavid C Somayajulu pkt_type = ECORE_IWARP_MPA_PKT_PARTIAL;
2181*fa790ea9SDavid C Somayajulu goto out;
2182*fa790ea9SDavid C Somayajulu }
2183*fa790ea9SDavid C Somayajulu
2184*fa790ea9SDavid C Somayajulu mpa_len = ntohs(*((u16 *)(mpa_data)));
2185*fa790ea9SDavid C Somayajulu fpdu->fpdu_length = ECORE_IWARP_FPDU_LEN_WITH_PAD(mpa_len);
2186*fa790ea9SDavid C Somayajulu
2187*fa790ea9SDavid C Somayajulu if (fpdu->fpdu_length <= tcp_payload_len)
2188*fa790ea9SDavid C Somayajulu pkt_type = ECORE_IWARP_MPA_PKT_PACKED;
2189*fa790ea9SDavid C Somayajulu else
2190*fa790ea9SDavid C Somayajulu pkt_type = ECORE_IWARP_MPA_PKT_PARTIAL;
2191*fa790ea9SDavid C Somayajulu
2192*fa790ea9SDavid C Somayajulu out:
2193*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
2194*fa790ea9SDavid C Somayajulu "MPA_ALIGN: %s: fpdu_length=0x%x tcp_payload_len:0x%x\n",
2195*fa790ea9SDavid C Somayajulu pkt_type_str[pkt_type], fpdu->fpdu_length, tcp_payload_len);
2196*fa790ea9SDavid C Somayajulu
2197*fa790ea9SDavid C Somayajulu return pkt_type;
2198*fa790ea9SDavid C Somayajulu }
2199*fa790ea9SDavid C Somayajulu
2200*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_init_fpdu(struct ecore_iwarp_ll2_buff * buf,struct ecore_iwarp_fpdu * fpdu,struct unaligned_opaque_data * pkt_data,u16 tcp_payload_size,u8 placement_offset)2201*fa790ea9SDavid C Somayajulu ecore_iwarp_init_fpdu(struct ecore_iwarp_ll2_buff *buf,
2202*fa790ea9SDavid C Somayajulu struct ecore_iwarp_fpdu *fpdu,
2203*fa790ea9SDavid C Somayajulu struct unaligned_opaque_data *pkt_data,
2204*fa790ea9SDavid C Somayajulu u16 tcp_payload_size, u8 placement_offset)
2205*fa790ea9SDavid C Somayajulu {
2206*fa790ea9SDavid C Somayajulu fpdu->mpa_buf = buf;
2207*fa790ea9SDavid C Somayajulu fpdu->pkt_hdr = buf->data_phys_addr + placement_offset;
2208*fa790ea9SDavid C Somayajulu fpdu->pkt_hdr_size = pkt_data->tcp_payload_offset;
2209*fa790ea9SDavid C Somayajulu
2210*fa790ea9SDavid C Somayajulu fpdu->mpa_frag = buf->data_phys_addr + pkt_data->first_mpa_offset;
2211*fa790ea9SDavid C Somayajulu fpdu->mpa_frag_virt = (u8 *)(buf->data) + pkt_data->first_mpa_offset;
2212*fa790ea9SDavid C Somayajulu
2213*fa790ea9SDavid C Somayajulu if (tcp_payload_size == 1)
2214*fa790ea9SDavid C Somayajulu fpdu->incomplete_bytes = ECORE_IWARP_INVALID_FPDU_LENGTH;
2215*fa790ea9SDavid C Somayajulu else if (tcp_payload_size < fpdu->fpdu_length)
2216*fa790ea9SDavid C Somayajulu fpdu->incomplete_bytes = fpdu->fpdu_length - tcp_payload_size;
2217*fa790ea9SDavid C Somayajulu else
2218*fa790ea9SDavid C Somayajulu fpdu->incomplete_bytes = 0; /* complete fpdu */
2219*fa790ea9SDavid C Somayajulu
2220*fa790ea9SDavid C Somayajulu fpdu->mpa_frag_len = fpdu->fpdu_length - fpdu->incomplete_bytes;
2221*fa790ea9SDavid C Somayajulu }
2222*fa790ea9SDavid C Somayajulu
2223*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
ecore_iwarp_copy_fpdu(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_fpdu * fpdu,struct unaligned_opaque_data * pkt_data,struct ecore_iwarp_ll2_buff * buf,u16 tcp_payload_size)2224*fa790ea9SDavid C Somayajulu ecore_iwarp_copy_fpdu(struct ecore_hwfn *p_hwfn,
2225*fa790ea9SDavid C Somayajulu struct ecore_iwarp_fpdu *fpdu,
2226*fa790ea9SDavid C Somayajulu struct unaligned_opaque_data *pkt_data,
2227*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ll2_buff *buf,
2228*fa790ea9SDavid C Somayajulu u16 tcp_payload_size)
2229*fa790ea9SDavid C Somayajulu
2230*fa790ea9SDavid C Somayajulu {
2231*fa790ea9SDavid C Somayajulu u8 *tmp_buf = p_hwfn->p_rdma_info->iwarp.mpa_intermediate_buf;
2232*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
2233*fa790ea9SDavid C Somayajulu
2234*fa790ea9SDavid C Somayajulu /* need to copy the data from the partial packet stored in fpdu
2235*fa790ea9SDavid C Somayajulu * to the new buf, for this we also need to move the data currently
2236*fa790ea9SDavid C Somayajulu * placed on the buf. The assumption is that the buffer is big enough
2237*fa790ea9SDavid C Somayajulu * since fpdu_length <= mss, we use an intermediate buffer since
2238*fa790ea9SDavid C Somayajulu * we may need to copy the new data to an overlapping location
2239*fa790ea9SDavid C Somayajulu */
2240*fa790ea9SDavid C Somayajulu if ((fpdu->mpa_frag_len + tcp_payload_size) > (u16)buf->buff_size) {
2241*fa790ea9SDavid C Somayajulu DP_ERR(p_hwfn,
2242*fa790ea9SDavid C Somayajulu "MPA ALIGN: Unexpected: buffer is not large enough for split fpdu buff_size = %d mpa_frag_len = %d, tcp_payload_size = %d, incomplete_bytes = %d\n",
2243*fa790ea9SDavid C Somayajulu buf->buff_size, fpdu->mpa_frag_len, tcp_payload_size,
2244*fa790ea9SDavid C Somayajulu fpdu->incomplete_bytes);
2245*fa790ea9SDavid C Somayajulu return ECORE_INVAL;
2246*fa790ea9SDavid C Somayajulu }
2247*fa790ea9SDavid C Somayajulu
2248*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
2249*fa790ea9SDavid C Somayajulu "MPA ALIGN Copying fpdu: [%p, %d] [%p, %d]\n",
2250*fa790ea9SDavid C Somayajulu fpdu->mpa_frag_virt, fpdu->mpa_frag_len,
2251*fa790ea9SDavid C Somayajulu (u8 *)(buf->data) + pkt_data->first_mpa_offset,
2252*fa790ea9SDavid C Somayajulu tcp_payload_size);
2253*fa790ea9SDavid C Somayajulu
2254*fa790ea9SDavid C Somayajulu OSAL_MEMCPY(tmp_buf, fpdu->mpa_frag_virt, fpdu->mpa_frag_len);
2255*fa790ea9SDavid C Somayajulu OSAL_MEMCPY(tmp_buf + fpdu->mpa_frag_len,
2256*fa790ea9SDavid C Somayajulu (u8 *)(buf->data) + pkt_data->first_mpa_offset,
2257*fa790ea9SDavid C Somayajulu tcp_payload_size);
2258*fa790ea9SDavid C Somayajulu
2259*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_recycle_pkt(p_hwfn, fpdu, fpdu->mpa_buf);
2260*fa790ea9SDavid C Somayajulu if (rc)
2261*fa790ea9SDavid C Somayajulu return rc;
2262*fa790ea9SDavid C Somayajulu
2263*fa790ea9SDavid C Somayajulu /* If we managed to post the buffer copy the data to the new buffer
2264*fa790ea9SDavid C Somayajulu * o/w this will occur in the next round...
2265*fa790ea9SDavid C Somayajulu */
2266*fa790ea9SDavid C Somayajulu OSAL_MEMCPY((u8 *)(buf->data), tmp_buf,
2267*fa790ea9SDavid C Somayajulu fpdu->mpa_frag_len + tcp_payload_size);
2268*fa790ea9SDavid C Somayajulu
2269*fa790ea9SDavid C Somayajulu fpdu->mpa_buf = buf;
2270*fa790ea9SDavid C Somayajulu /* fpdu->pkt_hdr remains as is */
2271*fa790ea9SDavid C Somayajulu /* fpdu->mpa_frag is overriden with new buf */
2272*fa790ea9SDavid C Somayajulu fpdu->mpa_frag = buf->data_phys_addr;
2273*fa790ea9SDavid C Somayajulu fpdu->mpa_frag_virt = buf->data;
2274*fa790ea9SDavid C Somayajulu fpdu->mpa_frag_len += tcp_payload_size;
2275*fa790ea9SDavid C Somayajulu
2276*fa790ea9SDavid C Somayajulu fpdu->incomplete_bytes -= tcp_payload_size;
2277*fa790ea9SDavid C Somayajulu
2278*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
2279*fa790ea9SDavid C Somayajulu "MPA ALIGN: split fpdu buff_size = %d mpa_frag_len = %d, tcp_payload_size = %d, incomplete_bytes = %d\n",
2280*fa790ea9SDavid C Somayajulu buf->buff_size, fpdu->mpa_frag_len, tcp_payload_size,
2281*fa790ea9SDavid C Somayajulu fpdu->incomplete_bytes);
2282*fa790ea9SDavid C Somayajulu
2283*fa790ea9SDavid C Somayajulu return 0;
2284*fa790ea9SDavid C Somayajulu }
2285*fa790ea9SDavid C Somayajulu
2286*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_update_fpdu_length(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_fpdu * fpdu,u8 * mpa_data)2287*fa790ea9SDavid C Somayajulu ecore_iwarp_update_fpdu_length(struct ecore_hwfn *p_hwfn,
2288*fa790ea9SDavid C Somayajulu struct ecore_iwarp_fpdu *fpdu,
2289*fa790ea9SDavid C Somayajulu u8 *mpa_data)
2290*fa790ea9SDavid C Somayajulu {
2291*fa790ea9SDavid C Somayajulu u16 mpa_len;
2292*fa790ea9SDavid C Somayajulu
2293*fa790ea9SDavid C Somayajulu /* Update incomplete packets if needed */
2294*fa790ea9SDavid C Somayajulu if (fpdu->incomplete_bytes == ECORE_IWARP_INVALID_FPDU_LENGTH) {
2295*fa790ea9SDavid C Somayajulu mpa_len = fpdu->fpdu_length | *mpa_data;
2296*fa790ea9SDavid C Somayajulu fpdu->fpdu_length = ECORE_IWARP_FPDU_LEN_WITH_PAD(mpa_len);
2297*fa790ea9SDavid C Somayajulu fpdu->mpa_frag_len = fpdu->fpdu_length;
2298*fa790ea9SDavid C Somayajulu /* one byte of hdr */
2299*fa790ea9SDavid C Somayajulu fpdu->incomplete_bytes = fpdu->fpdu_length - 1;
2300*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn,
2301*fa790ea9SDavid C Somayajulu ECORE_MSG_RDMA,
2302*fa790ea9SDavid C Somayajulu "MPA_ALIGN: Partial header mpa_len=%x fpdu_length=%x incomplete_bytes=%x\n",
2303*fa790ea9SDavid C Somayajulu mpa_len, fpdu->fpdu_length, fpdu->incomplete_bytes);
2304*fa790ea9SDavid C Somayajulu }
2305*fa790ea9SDavid C Somayajulu }
2306*fa790ea9SDavid C Somayajulu
2307*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_IS_RIGHT_EDGE(_curr_pkt) \
2308*fa790ea9SDavid C Somayajulu (GET_FIELD(_curr_pkt->flags, \
2309*fa790ea9SDavid C Somayajulu UNALIGNED_OPAQUE_DATA_PKT_REACHED_WIN_RIGHT_EDGE))
2310*fa790ea9SDavid C Somayajulu
2311*fa790ea9SDavid C Somayajulu /* This function is used to recycle a buffer using the ll2 drop option. It
2312*fa790ea9SDavid C Somayajulu * uses the mechanism to ensure that all buffers posted to tx before this one
2313*fa790ea9SDavid C Somayajulu * were completed. The buffer sent here will be sent as a cookie in the tx
2314*fa790ea9SDavid C Somayajulu * completion function and can then be reposted to rx chain when done. The flow
2315*fa790ea9SDavid C Somayajulu * that requires this is the flow where a FPDU splits over more than 3 tcp
2316*fa790ea9SDavid C Somayajulu * segments. In this case the driver needs to re-post a rx buffer instead of
2317*fa790ea9SDavid C Somayajulu * the one received, but driver can't simply repost a buffer it copied from
2318*fa790ea9SDavid C Somayajulu * as there is a case where the buffer was originally a packed FPDU, and is
2319*fa790ea9SDavid C Somayajulu * partially posted to FW. Driver needs to ensure FW is done with it.
2320*fa790ea9SDavid C Somayajulu */
2321*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
ecore_iwarp_recycle_pkt(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_fpdu * fpdu,struct ecore_iwarp_ll2_buff * buf)2322*fa790ea9SDavid C Somayajulu ecore_iwarp_recycle_pkt(struct ecore_hwfn *p_hwfn,
2323*fa790ea9SDavid C Somayajulu struct ecore_iwarp_fpdu *fpdu,
2324*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ll2_buff *buf)
2325*fa790ea9SDavid C Somayajulu {
2326*fa790ea9SDavid C Somayajulu struct ecore_ll2_tx_pkt_info tx_pkt;
2327*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
2328*fa790ea9SDavid C Somayajulu u8 ll2_handle;
2329*fa790ea9SDavid C Somayajulu
2330*fa790ea9SDavid C Somayajulu OSAL_MEM_ZERO(&tx_pkt, sizeof(tx_pkt));
2331*fa790ea9SDavid C Somayajulu tx_pkt.num_of_bds = 1;
2332*fa790ea9SDavid C Somayajulu tx_pkt.tx_dest = ECORE_LL2_TX_DEST_DROP;
2333*fa790ea9SDavid C Somayajulu tx_pkt.l4_hdr_offset_w = fpdu->pkt_hdr_size >> 2;
2334*fa790ea9SDavid C Somayajulu tx_pkt.first_frag = fpdu->pkt_hdr;
2335*fa790ea9SDavid C Somayajulu tx_pkt.first_frag_len = fpdu->pkt_hdr_size;
2336*fa790ea9SDavid C Somayajulu buf->piggy_buf = OSAL_NULL;
2337*fa790ea9SDavid C Somayajulu tx_pkt.cookie = buf;
2338*fa790ea9SDavid C Somayajulu
2339*fa790ea9SDavid C Somayajulu ll2_handle = p_hwfn->p_rdma_info->iwarp.ll2_mpa_handle;
2340*fa790ea9SDavid C Somayajulu
2341*fa790ea9SDavid C Somayajulu rc = ecore_ll2_prepare_tx_packet(p_hwfn,
2342*fa790ea9SDavid C Somayajulu ll2_handle,
2343*fa790ea9SDavid C Somayajulu &tx_pkt, true);
2344*fa790ea9SDavid C Somayajulu
2345*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
2346*fa790ea9SDavid C Somayajulu "MPA_ALIGN: send drop tx packet [%lx, 0x%x], buf=%p, rc=%d\n",
2347*fa790ea9SDavid C Somayajulu (long unsigned int)tx_pkt.first_frag,
2348*fa790ea9SDavid C Somayajulu tx_pkt.first_frag_len, buf, rc);
2349*fa790ea9SDavid C Somayajulu
2350*fa790ea9SDavid C Somayajulu if (rc)
2351*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
2352*fa790ea9SDavid C Somayajulu "Can't drop packet rc=%d\n", rc);
2353*fa790ea9SDavid C Somayajulu
2354*fa790ea9SDavid C Somayajulu return rc;
2355*fa790ea9SDavid C Somayajulu }
2356*fa790ea9SDavid C Somayajulu
2357*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
ecore_iwarp_win_right_edge(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_fpdu * fpdu)2358*fa790ea9SDavid C Somayajulu ecore_iwarp_win_right_edge(struct ecore_hwfn *p_hwfn,
2359*fa790ea9SDavid C Somayajulu struct ecore_iwarp_fpdu *fpdu)
2360*fa790ea9SDavid C Somayajulu {
2361*fa790ea9SDavid C Somayajulu struct ecore_ll2_tx_pkt_info tx_pkt;
2362*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
2363*fa790ea9SDavid C Somayajulu u8 ll2_handle;
2364*fa790ea9SDavid C Somayajulu
2365*fa790ea9SDavid C Somayajulu OSAL_MEM_ZERO(&tx_pkt, sizeof(tx_pkt));
2366*fa790ea9SDavid C Somayajulu tx_pkt.num_of_bds = 1;
2367*fa790ea9SDavid C Somayajulu tx_pkt.tx_dest = ECORE_LL2_TX_DEST_LB;
2368*fa790ea9SDavid C Somayajulu tx_pkt.l4_hdr_offset_w = fpdu->pkt_hdr_size >> 2;
2369*fa790ea9SDavid C Somayajulu
2370*fa790ea9SDavid C Somayajulu tx_pkt.first_frag = fpdu->pkt_hdr;
2371*fa790ea9SDavid C Somayajulu tx_pkt.first_frag_len = fpdu->pkt_hdr_size;
2372*fa790ea9SDavid C Somayajulu tx_pkt.enable_ip_cksum = true;
2373*fa790ea9SDavid C Somayajulu tx_pkt.enable_l4_cksum = true;
2374*fa790ea9SDavid C Somayajulu tx_pkt.calc_ip_len = true;
2375*fa790ea9SDavid C Somayajulu /* vlan overload with enum iwarp_ll2_tx_queues */
2376*fa790ea9SDavid C Somayajulu tx_pkt.vlan = IWARP_LL2_ALIGNED_RIGHT_TRIMMED_TX_QUEUE;
2377*fa790ea9SDavid C Somayajulu
2378*fa790ea9SDavid C Somayajulu ll2_handle = p_hwfn->p_rdma_info->iwarp.ll2_mpa_handle;
2379*fa790ea9SDavid C Somayajulu
2380*fa790ea9SDavid C Somayajulu rc = ecore_ll2_prepare_tx_packet(p_hwfn,
2381*fa790ea9SDavid C Somayajulu ll2_handle,
2382*fa790ea9SDavid C Somayajulu &tx_pkt, true);
2383*fa790ea9SDavid C Somayajulu
2384*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
2385*fa790ea9SDavid C Somayajulu "MPA_ALIGN: Sent right edge FPDU num_bds=%d [%lx, 0x%x], rc=%d\n",
2386*fa790ea9SDavid C Somayajulu tx_pkt.num_of_bds, (long unsigned int)tx_pkt.first_frag,
2387*fa790ea9SDavid C Somayajulu tx_pkt.first_frag_len, rc);
2388*fa790ea9SDavid C Somayajulu
2389*fa790ea9SDavid C Somayajulu if (rc)
2390*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
2391*fa790ea9SDavid C Somayajulu "Can't send right edge rc=%d\n", rc);
2392*fa790ea9SDavid C Somayajulu
2393*fa790ea9SDavid C Somayajulu return rc;
2394*fa790ea9SDavid C Somayajulu }
2395*fa790ea9SDavid C Somayajulu
2396*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
ecore_iwarp_send_fpdu(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_fpdu * fpdu,struct unaligned_opaque_data * curr_pkt,struct ecore_iwarp_ll2_buff * buf,u16 tcp_payload_size,enum ecore_iwarp_mpa_pkt_type pkt_type)2397*fa790ea9SDavid C Somayajulu ecore_iwarp_send_fpdu(struct ecore_hwfn *p_hwfn,
2398*fa790ea9SDavid C Somayajulu struct ecore_iwarp_fpdu *fpdu,
2399*fa790ea9SDavid C Somayajulu struct unaligned_opaque_data *curr_pkt,
2400*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ll2_buff *buf,
2401*fa790ea9SDavid C Somayajulu u16 tcp_payload_size,
2402*fa790ea9SDavid C Somayajulu enum ecore_iwarp_mpa_pkt_type pkt_type)
2403*fa790ea9SDavid C Somayajulu {
2404*fa790ea9SDavid C Somayajulu struct ecore_ll2_tx_pkt_info tx_pkt;
2405*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
2406*fa790ea9SDavid C Somayajulu u8 ll2_handle;
2407*fa790ea9SDavid C Somayajulu
2408*fa790ea9SDavid C Somayajulu OSAL_MEM_ZERO(&tx_pkt, sizeof(tx_pkt));
2409*fa790ea9SDavid C Somayajulu
2410*fa790ea9SDavid C Somayajulu tx_pkt.num_of_bds = (pkt_type == ECORE_IWARP_MPA_PKT_UNALIGNED) ? 3 : 2;
2411*fa790ea9SDavid C Somayajulu tx_pkt.tx_dest = ECORE_LL2_TX_DEST_LB;
2412*fa790ea9SDavid C Somayajulu tx_pkt.l4_hdr_offset_w = fpdu->pkt_hdr_size >> 2;
2413*fa790ea9SDavid C Somayajulu
2414*fa790ea9SDavid C Somayajulu /* Send the mpa_buf only with the last fpdu (in case of packed) */
2415*fa790ea9SDavid C Somayajulu if ((pkt_type == ECORE_IWARP_MPA_PKT_UNALIGNED) ||
2416*fa790ea9SDavid C Somayajulu (tcp_payload_size <= fpdu->fpdu_length))
2417*fa790ea9SDavid C Somayajulu tx_pkt.cookie = fpdu->mpa_buf;
2418*fa790ea9SDavid C Somayajulu
2419*fa790ea9SDavid C Somayajulu tx_pkt.first_frag = fpdu->pkt_hdr;
2420*fa790ea9SDavid C Somayajulu tx_pkt.first_frag_len = fpdu->pkt_hdr_size;
2421*fa790ea9SDavid C Somayajulu tx_pkt.enable_ip_cksum = true;
2422*fa790ea9SDavid C Somayajulu tx_pkt.enable_l4_cksum = true;
2423*fa790ea9SDavid C Somayajulu tx_pkt.calc_ip_len = true;
2424*fa790ea9SDavid C Somayajulu /* vlan overload with enum iwarp_ll2_tx_queues */
2425*fa790ea9SDavid C Somayajulu tx_pkt.vlan = IWARP_LL2_ALIGNED_TX_QUEUE;
2426*fa790ea9SDavid C Somayajulu
2427*fa790ea9SDavid C Somayajulu /* special case of unaligned packet and not packed, need to send
2428*fa790ea9SDavid C Somayajulu * both buffers as cookie to release.
2429*fa790ea9SDavid C Somayajulu */
2430*fa790ea9SDavid C Somayajulu if (tcp_payload_size == fpdu->incomplete_bytes) {
2431*fa790ea9SDavid C Somayajulu fpdu->mpa_buf->piggy_buf = buf;
2432*fa790ea9SDavid C Somayajulu }
2433*fa790ea9SDavid C Somayajulu
2434*fa790ea9SDavid C Somayajulu ll2_handle = p_hwfn->p_rdma_info->iwarp.ll2_mpa_handle;
2435*fa790ea9SDavid C Somayajulu
2436*fa790ea9SDavid C Somayajulu rc = ecore_ll2_prepare_tx_packet(p_hwfn,
2437*fa790ea9SDavid C Somayajulu ll2_handle,
2438*fa790ea9SDavid C Somayajulu &tx_pkt, true);
2439*fa790ea9SDavid C Somayajulu if (rc)
2440*fa790ea9SDavid C Somayajulu goto err;
2441*fa790ea9SDavid C Somayajulu
2442*fa790ea9SDavid C Somayajulu rc = ecore_ll2_set_fragment_of_tx_packet(p_hwfn, ll2_handle,
2443*fa790ea9SDavid C Somayajulu fpdu->mpa_frag,
2444*fa790ea9SDavid C Somayajulu fpdu->mpa_frag_len);
2445*fa790ea9SDavid C Somayajulu if (rc)
2446*fa790ea9SDavid C Somayajulu goto err;
2447*fa790ea9SDavid C Somayajulu
2448*fa790ea9SDavid C Somayajulu if (fpdu->incomplete_bytes) {
2449*fa790ea9SDavid C Somayajulu rc = ecore_ll2_set_fragment_of_tx_packet(
2450*fa790ea9SDavid C Somayajulu p_hwfn, ll2_handle,
2451*fa790ea9SDavid C Somayajulu buf->data_phys_addr + curr_pkt->first_mpa_offset,
2452*fa790ea9SDavid C Somayajulu fpdu->incomplete_bytes);
2453*fa790ea9SDavid C Somayajulu
2454*fa790ea9SDavid C Somayajulu if (rc)
2455*fa790ea9SDavid C Somayajulu goto err;
2456*fa790ea9SDavid C Somayajulu }
2457*fa790ea9SDavid C Somayajulu
2458*fa790ea9SDavid C Somayajulu err:
2459*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
2460*fa790ea9SDavid C Somayajulu "MPA_ALIGN: Sent FPDU num_bds=%d [%lx, 0x%x], [0x%lx, 0x%x], [0x%lx, 0x%x] (cookie %p) rc=%d\n",
2461*fa790ea9SDavid C Somayajulu tx_pkt.num_of_bds, (long unsigned int)tx_pkt.first_frag,
2462*fa790ea9SDavid C Somayajulu tx_pkt.first_frag_len, (long unsigned int)fpdu->mpa_frag,
2463*fa790ea9SDavid C Somayajulu fpdu->mpa_frag_len, (long unsigned int)buf->data_phys_addr +
2464*fa790ea9SDavid C Somayajulu curr_pkt->first_mpa_offset, fpdu->incomplete_bytes,
2465*fa790ea9SDavid C Somayajulu tx_pkt.cookie, rc);
2466*fa790ea9SDavid C Somayajulu
2467*fa790ea9SDavid C Somayajulu return rc;
2468*fa790ea9SDavid C Somayajulu }
2469*fa790ea9SDavid C Somayajulu
2470*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_mpa_get_data(struct ecore_hwfn * p_hwfn,struct unaligned_opaque_data * curr_pkt,u32 opaque_data0,u32 opaque_data1)2471*fa790ea9SDavid C Somayajulu ecore_iwarp_mpa_get_data(struct ecore_hwfn *p_hwfn,
2472*fa790ea9SDavid C Somayajulu struct unaligned_opaque_data *curr_pkt,
2473*fa790ea9SDavid C Somayajulu u32 opaque_data0, u32 opaque_data1)
2474*fa790ea9SDavid C Somayajulu {
2475*fa790ea9SDavid C Somayajulu u64 opaque_data;
2476*fa790ea9SDavid C Somayajulu
2477*fa790ea9SDavid C Somayajulu opaque_data = HILO_64(opaque_data1, opaque_data0);
2478*fa790ea9SDavid C Somayajulu *curr_pkt = *((struct unaligned_opaque_data *)&opaque_data);
2479*fa790ea9SDavid C Somayajulu
2480*fa790ea9SDavid C Somayajulu /* fix endianity */
2481*fa790ea9SDavid C Somayajulu curr_pkt->first_mpa_offset = curr_pkt->tcp_payload_offset +
2482*fa790ea9SDavid C Somayajulu OSAL_LE16_TO_CPU(curr_pkt->first_mpa_offset);
2483*fa790ea9SDavid C Somayajulu curr_pkt->cid = OSAL_LE32_TO_CPU(curr_pkt->cid);
2484*fa790ea9SDavid C Somayajulu
2485*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
2486*fa790ea9SDavid C Somayajulu "OPAQUE0=0x%x OPAQUE1=0x%x first_mpa_offset:0x%x\ttcp_payload_offset:0x%x\tflags:0x%x\tcid:0x%x\n",
2487*fa790ea9SDavid C Somayajulu opaque_data0, opaque_data1, curr_pkt->first_mpa_offset,
2488*fa790ea9SDavid C Somayajulu curr_pkt->tcp_payload_offset, curr_pkt->flags,
2489*fa790ea9SDavid C Somayajulu curr_pkt->cid);
2490*fa790ea9SDavid C Somayajulu }
2491*fa790ea9SDavid C Somayajulu
2492*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_mpa_print_tcp_seq(struct ecore_hwfn * p_hwfn,void * buf)2493*fa790ea9SDavid C Somayajulu ecore_iwarp_mpa_print_tcp_seq(struct ecore_hwfn *p_hwfn,
2494*fa790ea9SDavid C Somayajulu void *buf)
2495*fa790ea9SDavid C Somayajulu {
2496*fa790ea9SDavid C Somayajulu struct ecore_vlan_ethhdr *vethh;
2497*fa790ea9SDavid C Somayajulu struct ecore_ethhdr *ethh;
2498*fa790ea9SDavid C Somayajulu struct ecore_iphdr *iph;
2499*fa790ea9SDavid C Somayajulu struct ecore_ipv6hdr *ip6h;
2500*fa790ea9SDavid C Somayajulu struct ecore_tcphdr *tcph;
2501*fa790ea9SDavid C Somayajulu bool vlan_valid = false;
2502*fa790ea9SDavid C Somayajulu int eth_hlen, ip_hlen;
2503*fa790ea9SDavid C Somayajulu u16 eth_type;
2504*fa790ea9SDavid C Somayajulu
2505*fa790ea9SDavid C Somayajulu if ((p_hwfn->dp_level > ECORE_LEVEL_VERBOSE) ||
2506*fa790ea9SDavid C Somayajulu !(p_hwfn->dp_module & ECORE_MSG_RDMA))
2507*fa790ea9SDavid C Somayajulu return;
2508*fa790ea9SDavid C Somayajulu
2509*fa790ea9SDavid C Somayajulu ethh = (struct ecore_ethhdr *)buf;
2510*fa790ea9SDavid C Somayajulu eth_type = ntohs(ethh->h_proto);
2511*fa790ea9SDavid C Somayajulu if (eth_type == ETH_P_8021Q) {
2512*fa790ea9SDavid C Somayajulu vlan_valid = true;
2513*fa790ea9SDavid C Somayajulu vethh = (struct ecore_vlan_ethhdr *)ethh;
2514*fa790ea9SDavid C Somayajulu eth_type = ntohs(vethh->h_vlan_encapsulated_proto);
2515*fa790ea9SDavid C Somayajulu }
2516*fa790ea9SDavid C Somayajulu
2517*fa790ea9SDavid C Somayajulu eth_hlen = ETH_HLEN + (vlan_valid ? sizeof(u32) : 0);
2518*fa790ea9SDavid C Somayajulu
2519*fa790ea9SDavid C Somayajulu iph = (struct ecore_iphdr *)((u8 *)(ethh) + eth_hlen);
2520*fa790ea9SDavid C Somayajulu
2521*fa790ea9SDavid C Somayajulu if (eth_type == ETH_P_IP) {
2522*fa790ea9SDavid C Somayajulu ip_hlen = (iph->ihl)*sizeof(u32);
2523*fa790ea9SDavid C Somayajulu } else if (eth_type == ETH_P_IPV6) {
2524*fa790ea9SDavid C Somayajulu ip6h = (struct ecore_ipv6hdr *)iph;
2525*fa790ea9SDavid C Somayajulu ip_hlen = sizeof(*ip6h);
2526*fa790ea9SDavid C Somayajulu } else {
2527*fa790ea9SDavid C Somayajulu DP_ERR(p_hwfn, "Unexpected ethertype on ll2 %x\n", eth_type);
2528*fa790ea9SDavid C Somayajulu return;
2529*fa790ea9SDavid C Somayajulu }
2530*fa790ea9SDavid C Somayajulu
2531*fa790ea9SDavid C Somayajulu tcph = (struct ecore_tcphdr *)((u8 *)iph + ip_hlen);
2532*fa790ea9SDavid C Somayajulu
2533*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "Processing MPA PKT: tcp_seq=0x%x tcp_ack_seq=0x%x\n",
2534*fa790ea9SDavid C Somayajulu ntohl(tcph->seq), ntohl(tcph->ack_seq));
2535*fa790ea9SDavid C Somayajulu
2536*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "eth_type =%d Source mac: [0x%x]:[0x%x]:[0x%x]:[0x%x]:[0x%x]:[0x%x]\n",
2537*fa790ea9SDavid C Somayajulu eth_type, ethh->h_source[0], ethh->h_source[1],
2538*fa790ea9SDavid C Somayajulu ethh->h_source[2], ethh->h_source[3],
2539*fa790ea9SDavid C Somayajulu ethh->h_source[4], ethh->h_source[5]);
2540*fa790ea9SDavid C Somayajulu
2541*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "eth_hlen=%d destination mac: [0x%x]:[0x%x]:[0x%x]:[0x%x]:[0x%x]:[0x%x]\n",
2542*fa790ea9SDavid C Somayajulu eth_hlen, ethh->h_dest[0], ethh->h_dest[1],
2543*fa790ea9SDavid C Somayajulu ethh->h_dest[2], ethh->h_dest[3],
2544*fa790ea9SDavid C Somayajulu ethh->h_dest[4], ethh->h_dest[5]);
2545*fa790ea9SDavid C Somayajulu
2546*fa790ea9SDavid C Somayajulu return;
2547*fa790ea9SDavid C Somayajulu }
2548*fa790ea9SDavid C Somayajulu
2549*fa790ea9SDavid C Somayajulu /* This function is called when an unaligned or incomplete MPA packet arrives
2550*fa790ea9SDavid C Somayajulu * driver needs to align the packet, perhaps using previous data and send
2551*fa790ea9SDavid C Somayajulu * it down to FW once it is aligned.
2552*fa790ea9SDavid C Somayajulu */
2553*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
ecore_iwarp_process_mpa_pkt(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_ll2_mpa_buf * mpa_buf)2554*fa790ea9SDavid C Somayajulu ecore_iwarp_process_mpa_pkt(struct ecore_hwfn *p_hwfn,
2555*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ll2_mpa_buf *mpa_buf)
2556*fa790ea9SDavid C Somayajulu {
2557*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ll2_buff *buf = mpa_buf->ll2_buf;
2558*fa790ea9SDavid C Somayajulu enum ecore_iwarp_mpa_pkt_type pkt_type;
2559*fa790ea9SDavid C Somayajulu struct unaligned_opaque_data *curr_pkt = &mpa_buf->data;
2560*fa790ea9SDavid C Somayajulu struct ecore_iwarp_fpdu *fpdu;
2561*fa790ea9SDavid C Somayajulu u8 *mpa_data;
2562*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc = ECORE_SUCCESS;
2563*fa790ea9SDavid C Somayajulu
2564*fa790ea9SDavid C Somayajulu ecore_iwarp_mpa_print_tcp_seq(
2565*fa790ea9SDavid C Somayajulu p_hwfn, (u8 *)(buf->data) + mpa_buf->placement_offset);
2566*fa790ea9SDavid C Somayajulu
2567*fa790ea9SDavid C Somayajulu fpdu = ecore_iwarp_get_curr_fpdu(p_hwfn, curr_pkt->cid & 0xffff);
2568*fa790ea9SDavid C Somayajulu if (!fpdu) {/* something corrupt with cid, post rx back */
2569*fa790ea9SDavid C Somayajulu DP_ERR(p_hwfn, "Invalid cid, drop and post back to rx cid=%x\n",
2570*fa790ea9SDavid C Somayajulu curr_pkt->cid);
2571*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_ll2_post_rx(
2572*fa790ea9SDavid C Somayajulu p_hwfn, buf, p_hwfn->p_rdma_info->iwarp.ll2_mpa_handle);
2573*fa790ea9SDavid C Somayajulu
2574*fa790ea9SDavid C Somayajulu if (rc) { /* not much we can do here except log and free */
2575*fa790ea9SDavid C Somayajulu DP_ERR(p_hwfn, "Post rx buffer failed\n");
2576*fa790ea9SDavid C Somayajulu
2577*fa790ea9SDavid C Somayajulu /* we don't expect any failures from rx, not even
2578*fa790ea9SDavid C Somayajulu * busy since we allocate #bufs=#descs
2579*fa790ea9SDavid C Somayajulu */
2580*fa790ea9SDavid C Somayajulu rc = ECORE_UNKNOWN_ERROR;
2581*fa790ea9SDavid C Somayajulu }
2582*fa790ea9SDavid C Somayajulu return rc;
2583*fa790ea9SDavid C Somayajulu }
2584*fa790ea9SDavid C Somayajulu
2585*fa790ea9SDavid C Somayajulu do {
2586*fa790ea9SDavid C Somayajulu mpa_data = ((u8 *)(buf->data) + curr_pkt->first_mpa_offset);
2587*fa790ea9SDavid C Somayajulu
2588*fa790ea9SDavid C Somayajulu pkt_type = ecore_iwarp_mpa_classify(p_hwfn, fpdu,
2589*fa790ea9SDavid C Somayajulu mpa_buf->tcp_payload_len,
2590*fa790ea9SDavid C Somayajulu mpa_data);
2591*fa790ea9SDavid C Somayajulu
2592*fa790ea9SDavid C Somayajulu switch (pkt_type) {
2593*fa790ea9SDavid C Somayajulu case ECORE_IWARP_MPA_PKT_PARTIAL:
2594*fa790ea9SDavid C Somayajulu ecore_iwarp_init_fpdu(buf, fpdu,
2595*fa790ea9SDavid C Somayajulu curr_pkt,
2596*fa790ea9SDavid C Somayajulu mpa_buf->tcp_payload_len,
2597*fa790ea9SDavid C Somayajulu mpa_buf->placement_offset);
2598*fa790ea9SDavid C Somayajulu
2599*fa790ea9SDavid C Somayajulu if (!ECORE_IWARP_IS_RIGHT_EDGE(curr_pkt)) {
2600*fa790ea9SDavid C Somayajulu mpa_buf->tcp_payload_len = 0;
2601*fa790ea9SDavid C Somayajulu break;
2602*fa790ea9SDavid C Somayajulu }
2603*fa790ea9SDavid C Somayajulu
2604*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_win_right_edge(p_hwfn, fpdu);
2605*fa790ea9SDavid C Somayajulu
2606*fa790ea9SDavid C Somayajulu if (rc) {
2607*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
2608*fa790ea9SDavid C Somayajulu "Can't send FPDU:reset rc=%d\n", rc);
2609*fa790ea9SDavid C Somayajulu OSAL_MEM_ZERO(fpdu, sizeof(*fpdu));
2610*fa790ea9SDavid C Somayajulu break;
2611*fa790ea9SDavid C Somayajulu }
2612*fa790ea9SDavid C Somayajulu
2613*fa790ea9SDavid C Somayajulu mpa_buf->tcp_payload_len = 0;
2614*fa790ea9SDavid C Somayajulu break;
2615*fa790ea9SDavid C Somayajulu case ECORE_IWARP_MPA_PKT_PACKED:
2616*fa790ea9SDavid C Somayajulu if (fpdu->fpdu_length == 8) {
2617*fa790ea9SDavid C Somayajulu DP_ERR(p_hwfn, "SUSPICIOUS fpdu_length = 0x%x: assuming bug...aborting this packet...\n",
2618*fa790ea9SDavid C Somayajulu fpdu->fpdu_length);
2619*fa790ea9SDavid C Somayajulu mpa_buf->tcp_payload_len = 0;
2620*fa790ea9SDavid C Somayajulu break;
2621*fa790ea9SDavid C Somayajulu }
2622*fa790ea9SDavid C Somayajulu
2623*fa790ea9SDavid C Somayajulu ecore_iwarp_init_fpdu(buf, fpdu,
2624*fa790ea9SDavid C Somayajulu curr_pkt,
2625*fa790ea9SDavid C Somayajulu mpa_buf->tcp_payload_len,
2626*fa790ea9SDavid C Somayajulu mpa_buf->placement_offset);
2627*fa790ea9SDavid C Somayajulu
2628*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_send_fpdu(p_hwfn, fpdu, curr_pkt, buf,
2629*fa790ea9SDavid C Somayajulu mpa_buf->tcp_payload_len,
2630*fa790ea9SDavid C Somayajulu pkt_type);
2631*fa790ea9SDavid C Somayajulu if (rc) {
2632*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
2633*fa790ea9SDavid C Somayajulu "Can't send FPDU:reset rc=%d\n", rc);
2634*fa790ea9SDavid C Somayajulu OSAL_MEM_ZERO(fpdu, sizeof(*fpdu));
2635*fa790ea9SDavid C Somayajulu break;
2636*fa790ea9SDavid C Somayajulu }
2637*fa790ea9SDavid C Somayajulu mpa_buf->tcp_payload_len -= fpdu->fpdu_length;
2638*fa790ea9SDavid C Somayajulu curr_pkt->first_mpa_offset += fpdu->fpdu_length;
2639*fa790ea9SDavid C Somayajulu break;
2640*fa790ea9SDavid C Somayajulu case ECORE_IWARP_MPA_PKT_UNALIGNED:
2641*fa790ea9SDavid C Somayajulu ecore_iwarp_update_fpdu_length(p_hwfn, fpdu, mpa_data);
2642*fa790ea9SDavid C Somayajulu if (mpa_buf->tcp_payload_len < fpdu->incomplete_bytes) {
2643*fa790ea9SDavid C Somayajulu /* special handling of fpdu split over more
2644*fa790ea9SDavid C Somayajulu * than 2 segments
2645*fa790ea9SDavid C Somayajulu */
2646*fa790ea9SDavid C Somayajulu if (ECORE_IWARP_IS_RIGHT_EDGE(curr_pkt)) {
2647*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_win_right_edge(p_hwfn,
2648*fa790ea9SDavid C Somayajulu fpdu);
2649*fa790ea9SDavid C Somayajulu /* packet will be re-processed later */
2650*fa790ea9SDavid C Somayajulu if (rc)
2651*fa790ea9SDavid C Somayajulu return rc;
2652*fa790ea9SDavid C Somayajulu }
2653*fa790ea9SDavid C Somayajulu
2654*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_copy_fpdu(
2655*fa790ea9SDavid C Somayajulu p_hwfn, fpdu, curr_pkt,
2656*fa790ea9SDavid C Somayajulu buf, mpa_buf->tcp_payload_len);
2657*fa790ea9SDavid C Somayajulu
2658*fa790ea9SDavid C Somayajulu /* packet will be re-processed later */
2659*fa790ea9SDavid C Somayajulu if (rc)
2660*fa790ea9SDavid C Somayajulu return rc;
2661*fa790ea9SDavid C Somayajulu
2662*fa790ea9SDavid C Somayajulu mpa_buf->tcp_payload_len = 0;
2663*fa790ea9SDavid C Somayajulu
2664*fa790ea9SDavid C Somayajulu break;
2665*fa790ea9SDavid C Somayajulu }
2666*fa790ea9SDavid C Somayajulu
2667*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_send_fpdu(p_hwfn, fpdu, curr_pkt, buf,
2668*fa790ea9SDavid C Somayajulu mpa_buf->tcp_payload_len,
2669*fa790ea9SDavid C Somayajulu pkt_type);
2670*fa790ea9SDavid C Somayajulu if (rc) {
2671*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
2672*fa790ea9SDavid C Somayajulu "Can't send FPDU:delay rc=%d\n", rc);
2673*fa790ea9SDavid C Somayajulu /* don't reset fpdu -> we need it for next
2674*fa790ea9SDavid C Somayajulu * classify
2675*fa790ea9SDavid C Somayajulu */
2676*fa790ea9SDavid C Somayajulu break;
2677*fa790ea9SDavid C Somayajulu }
2678*fa790ea9SDavid C Somayajulu mpa_buf->tcp_payload_len -= fpdu->incomplete_bytes;
2679*fa790ea9SDavid C Somayajulu curr_pkt->first_mpa_offset += fpdu->incomplete_bytes;
2680*fa790ea9SDavid C Somayajulu /* The framed PDU was sent - no more incomplete bytes */
2681*fa790ea9SDavid C Somayajulu fpdu->incomplete_bytes = 0;
2682*fa790ea9SDavid C Somayajulu break;
2683*fa790ea9SDavid C Somayajulu }
2684*fa790ea9SDavid C Somayajulu
2685*fa790ea9SDavid C Somayajulu } while (mpa_buf->tcp_payload_len && !rc);
2686*fa790ea9SDavid C Somayajulu
2687*fa790ea9SDavid C Somayajulu return rc;
2688*fa790ea9SDavid C Somayajulu }
2689*fa790ea9SDavid C Somayajulu
2690*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_process_pending_pkts(struct ecore_hwfn * p_hwfn)2691*fa790ea9SDavid C Somayajulu ecore_iwarp_process_pending_pkts(struct ecore_hwfn *p_hwfn)
2692*fa790ea9SDavid C Somayajulu {
2693*fa790ea9SDavid C Somayajulu struct ecore_iwarp_info *iwarp_info = &p_hwfn->p_rdma_info->iwarp;
2694*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ll2_mpa_buf *mpa_buf = OSAL_NULL;
2695*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
2696*fa790ea9SDavid C Somayajulu
2697*fa790ea9SDavid C Somayajulu while (!OSAL_LIST_IS_EMPTY(&iwarp_info->mpa_buf_pending_list)) {
2698*fa790ea9SDavid C Somayajulu mpa_buf = OSAL_LIST_FIRST_ENTRY(
2699*fa790ea9SDavid C Somayajulu &iwarp_info->mpa_buf_pending_list,
2700*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ll2_mpa_buf,
2701*fa790ea9SDavid C Somayajulu list_entry);
2702*fa790ea9SDavid C Somayajulu
2703*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_process_mpa_pkt(p_hwfn, mpa_buf);
2704*fa790ea9SDavid C Somayajulu
2705*fa790ea9SDavid C Somayajulu /* busy means break and continue processing later, don't
2706*fa790ea9SDavid C Somayajulu * remove the buf from the pending list.
2707*fa790ea9SDavid C Somayajulu */
2708*fa790ea9SDavid C Somayajulu if (rc == ECORE_BUSY)
2709*fa790ea9SDavid C Somayajulu break;
2710*fa790ea9SDavid C Somayajulu
2711*fa790ea9SDavid C Somayajulu #ifdef _NTDDK_
2712*fa790ea9SDavid C Somayajulu #pragma warning(suppress : 6011)
2713*fa790ea9SDavid C Somayajulu #pragma warning(suppress : 28182)
2714*fa790ea9SDavid C Somayajulu #endif
2715*fa790ea9SDavid C Somayajulu OSAL_LIST_REMOVE_ENTRY(
2716*fa790ea9SDavid C Somayajulu &mpa_buf->list_entry,
2717*fa790ea9SDavid C Somayajulu &iwarp_info->mpa_buf_pending_list);
2718*fa790ea9SDavid C Somayajulu
2719*fa790ea9SDavid C Somayajulu OSAL_LIST_PUSH_TAIL(&mpa_buf->list_entry,
2720*fa790ea9SDavid C Somayajulu &iwarp_info->mpa_buf_list);
2721*fa790ea9SDavid C Somayajulu
2722*fa790ea9SDavid C Somayajulu if (rc) { /* different error, don't continue */
2723*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "process pkts failed rc=%d\n",
2724*fa790ea9SDavid C Somayajulu rc);
2725*fa790ea9SDavid C Somayajulu break;
2726*fa790ea9SDavid C Somayajulu }
2727*fa790ea9SDavid C Somayajulu }
2728*fa790ea9SDavid C Somayajulu }
2729*fa790ea9SDavid C Somayajulu
2730*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_ll2_comp_mpa_pkt(void * cxt,struct ecore_ll2_comp_rx_data * data)2731*fa790ea9SDavid C Somayajulu ecore_iwarp_ll2_comp_mpa_pkt(void *cxt,
2732*fa790ea9SDavid C Somayajulu struct ecore_ll2_comp_rx_data *data)
2733*fa790ea9SDavid C Somayajulu {
2734*fa790ea9SDavid C Somayajulu struct ecore_hwfn *p_hwfn = (struct ecore_hwfn *)cxt;
2735*fa790ea9SDavid C Somayajulu struct ecore_iwarp_info *iwarp_info = &p_hwfn->p_rdma_info->iwarp;
2736*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ll2_mpa_buf *mpa_buf;
2737*fa790ea9SDavid C Somayajulu
2738*fa790ea9SDavid C Somayajulu iwarp_info->unalign_rx_comp++;
2739*fa790ea9SDavid C Somayajulu
2740*fa790ea9SDavid C Somayajulu mpa_buf = OSAL_LIST_FIRST_ENTRY(&iwarp_info->mpa_buf_list,
2741*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ll2_mpa_buf,
2742*fa790ea9SDavid C Somayajulu list_entry);
2743*fa790ea9SDavid C Somayajulu
2744*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
2745*fa790ea9SDavid C Somayajulu "LL2 MPA CompRx buf=%p placement_offset=%d, payload_len=0x%x mpa_buf=%p\n",
2746*fa790ea9SDavid C Somayajulu data->cookie, data->u.placement_offset,
2747*fa790ea9SDavid C Somayajulu data->length.packet_length, mpa_buf);
2748*fa790ea9SDavid C Somayajulu
2749*fa790ea9SDavid C Somayajulu if (!mpa_buf) {
2750*fa790ea9SDavid C Somayajulu DP_ERR(p_hwfn, "no free mpa buf. this is a driver bug.\n");
2751*fa790ea9SDavid C Somayajulu return;
2752*fa790ea9SDavid C Somayajulu }
2753*fa790ea9SDavid C Somayajulu OSAL_LIST_REMOVE_ENTRY(&mpa_buf->list_entry, &iwarp_info->mpa_buf_list);
2754*fa790ea9SDavid C Somayajulu
2755*fa790ea9SDavid C Somayajulu ecore_iwarp_mpa_get_data(p_hwfn, &mpa_buf->data,
2756*fa790ea9SDavid C Somayajulu data->opaque_data_0, data->opaque_data_1);
2757*fa790ea9SDavid C Somayajulu
2758*fa790ea9SDavid C Somayajulu mpa_buf->tcp_payload_len = data->length.packet_length -
2759*fa790ea9SDavid C Somayajulu mpa_buf->data.first_mpa_offset;
2760*fa790ea9SDavid C Somayajulu mpa_buf->ll2_buf = (struct ecore_iwarp_ll2_buff *)data->cookie;
2761*fa790ea9SDavid C Somayajulu mpa_buf->data.first_mpa_offset += data->u.placement_offset;
2762*fa790ea9SDavid C Somayajulu mpa_buf->placement_offset = data->u.placement_offset;
2763*fa790ea9SDavid C Somayajulu
2764*fa790ea9SDavid C Somayajulu OSAL_LIST_PUSH_TAIL(&mpa_buf->list_entry,
2765*fa790ea9SDavid C Somayajulu &iwarp_info->mpa_buf_pending_list);
2766*fa790ea9SDavid C Somayajulu
2767*fa790ea9SDavid C Somayajulu ecore_iwarp_process_pending_pkts(p_hwfn);
2768*fa790ea9SDavid C Somayajulu }
2769*fa790ea9SDavid C Somayajulu
2770*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_ll2_comp_syn_pkt(void * cxt,struct ecore_ll2_comp_rx_data * data)2771*fa790ea9SDavid C Somayajulu ecore_iwarp_ll2_comp_syn_pkt(void *cxt, struct ecore_ll2_comp_rx_data *data)
2772*fa790ea9SDavid C Somayajulu {
2773*fa790ea9SDavid C Somayajulu struct ecore_hwfn *p_hwfn = (struct ecore_hwfn *)cxt;
2774*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ll2_buff *buf =
2775*fa790ea9SDavid C Somayajulu (struct ecore_iwarp_ll2_buff *)data->cookie;
2776*fa790ea9SDavid C Somayajulu struct ecore_iwarp_listener *listener;
2777*fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_info cm_info;
2778*fa790ea9SDavid C Somayajulu struct ecore_ll2_tx_pkt_info tx_pkt;
2779*fa790ea9SDavid C Somayajulu u8 remote_mac_addr[ETH_ALEN];
2780*fa790ea9SDavid C Somayajulu u8 local_mac_addr[ETH_ALEN];
2781*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep;
2782*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
2783*fa790ea9SDavid C Somayajulu int tcp_start_offset;
2784*fa790ea9SDavid C Somayajulu u8 ts_hdr_size = 0;
2785*fa790ea9SDavid C Somayajulu int payload_len;
2786*fa790ea9SDavid C Somayajulu u32 hdr_size;
2787*fa790ea9SDavid C Somayajulu
2788*fa790ea9SDavid C Somayajulu OSAL_MEM_ZERO(&cm_info, sizeof(cm_info));
2789*fa790ea9SDavid C Somayajulu
2790*fa790ea9SDavid C Somayajulu /* Check if packet was received with errors... */
2791*fa790ea9SDavid C Somayajulu if (data->err_flags != 0) {
2792*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "Error received on SYN packet: 0x%x\n",
2793*fa790ea9SDavid C Somayajulu data->err_flags);
2794*fa790ea9SDavid C Somayajulu goto err;
2795*fa790ea9SDavid C Somayajulu }
2796*fa790ea9SDavid C Somayajulu
2797*fa790ea9SDavid C Somayajulu if (GET_FIELD(data->parse_flags,
2798*fa790ea9SDavid C Somayajulu PARSING_AND_ERR_FLAGS_L4CHKSMWASCALCULATED) &&
2799*fa790ea9SDavid C Somayajulu GET_FIELD(data->parse_flags,
2800*fa790ea9SDavid C Somayajulu PARSING_AND_ERR_FLAGS_L4CHKSMERROR)) {
2801*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "Syn packet received with checksum error\n");
2802*fa790ea9SDavid C Somayajulu goto err;
2803*fa790ea9SDavid C Somayajulu }
2804*fa790ea9SDavid C Somayajulu
2805*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_parse_rx_pkt(
2806*fa790ea9SDavid C Somayajulu p_hwfn, &cm_info, (u8 *)(buf->data) + data->u.placement_offset,
2807*fa790ea9SDavid C Somayajulu remote_mac_addr, local_mac_addr, &payload_len,
2808*fa790ea9SDavid C Somayajulu &tcp_start_offset);
2809*fa790ea9SDavid C Somayajulu if (rc)
2810*fa790ea9SDavid C Somayajulu goto err;
2811*fa790ea9SDavid C Somayajulu
2812*fa790ea9SDavid C Somayajulu /* Check if there is a listener for this 4-tuple */
2813*fa790ea9SDavid C Somayajulu listener = ecore_iwarp_get_listener(p_hwfn, &cm_info);
2814*fa790ea9SDavid C Somayajulu if (!listener) {
2815*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
2816*fa790ea9SDavid C Somayajulu "SYN received on tuple not listened on parse_flags=%d packet len=%d\n",
2817*fa790ea9SDavid C Somayajulu data->parse_flags, data->length.packet_length);
2818*fa790ea9SDavid C Somayajulu
2819*fa790ea9SDavid C Somayajulu OSAL_MEMSET(&tx_pkt, 0, sizeof(tx_pkt));
2820*fa790ea9SDavid C Somayajulu tx_pkt.num_of_bds = 1;
2821*fa790ea9SDavid C Somayajulu tx_pkt.bd_flags = 0;
2822*fa790ea9SDavid C Somayajulu tx_pkt.l4_hdr_offset_w = (data->length.packet_length) >> 2;
2823*fa790ea9SDavid C Somayajulu tx_pkt.tx_dest = ECORE_LL2_TX_DEST_LB;
2824*fa790ea9SDavid C Somayajulu tx_pkt.first_frag = buf->data_phys_addr +
2825*fa790ea9SDavid C Somayajulu data->u.placement_offset;
2826*fa790ea9SDavid C Somayajulu tx_pkt.first_frag_len = data->length.packet_length;
2827*fa790ea9SDavid C Somayajulu tx_pkt.cookie = buf;
2828*fa790ea9SDavid C Somayajulu
2829*fa790ea9SDavid C Somayajulu rc = ecore_ll2_prepare_tx_packet(
2830*fa790ea9SDavid C Somayajulu p_hwfn,
2831*fa790ea9SDavid C Somayajulu p_hwfn->p_rdma_info->iwarp.ll2_syn_handle,
2832*fa790ea9SDavid C Somayajulu &tx_pkt, true);
2833*fa790ea9SDavid C Somayajulu
2834*fa790ea9SDavid C Somayajulu if (rc) {
2835*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false,
2836*fa790ea9SDavid C Somayajulu "Can't post SYN back to chip rc=%d\n", rc);
2837*fa790ea9SDavid C Somayajulu goto err;
2838*fa790ea9SDavid C Somayajulu }
2839*fa790ea9SDavid C Somayajulu return;
2840*fa790ea9SDavid C Somayajulu }
2841*fa790ea9SDavid C Somayajulu
2842*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "Received syn on listening port\n");
2843*fa790ea9SDavid C Somayajulu
2844*fa790ea9SDavid C Somayajulu /* For debugging purpose... */
2845*fa790ea9SDavid C Somayajulu if (listener->drop)
2846*fa790ea9SDavid C Somayajulu goto err;
2847*fa790ea9SDavid C Somayajulu
2848*fa790ea9SDavid C Somayajulu /* There may be an open ep on this connection if this is a syn
2849*fa790ea9SDavid C Somayajulu * retrasnmit... need to make sure there isn't...
2850*fa790ea9SDavid C Somayajulu */
2851*fa790ea9SDavid C Somayajulu if (ecore_iwarp_ep_exists(p_hwfn, listener, &cm_info))
2852*fa790ea9SDavid C Somayajulu goto err;
2853*fa790ea9SDavid C Somayajulu
2854*fa790ea9SDavid C Somayajulu ep = ecore_iwarp_get_free_ep(p_hwfn);
2855*fa790ea9SDavid C Somayajulu if (ep == OSAL_NULL)
2856*fa790ea9SDavid C Somayajulu goto err;
2857*fa790ea9SDavid C Somayajulu
2858*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&listener->lock);
2859*fa790ea9SDavid C Somayajulu OSAL_LIST_PUSH_TAIL(&ep->list_entry, &listener->ep_list);
2860*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&listener->lock);
2861*fa790ea9SDavid C Somayajulu
2862*fa790ea9SDavid C Somayajulu OSAL_MEMCPY(ep->remote_mac_addr,
2863*fa790ea9SDavid C Somayajulu remote_mac_addr,
2864*fa790ea9SDavid C Somayajulu ETH_ALEN);
2865*fa790ea9SDavid C Somayajulu OSAL_MEMCPY(ep->local_mac_addr,
2866*fa790ea9SDavid C Somayajulu local_mac_addr,
2867*fa790ea9SDavid C Somayajulu ETH_ALEN);
2868*fa790ea9SDavid C Somayajulu
2869*fa790ea9SDavid C Somayajulu OSAL_MEMCPY(&ep->cm_info, &cm_info, sizeof(ep->cm_info));
2870*fa790ea9SDavid C Somayajulu
2871*fa790ea9SDavid C Somayajulu if (p_hwfn->p_rdma_info->iwarp.tcp_flags & ECORE_IWARP_TS_EN)
2872*fa790ea9SDavid C Somayajulu ts_hdr_size = TIMESTAMP_HEADER_SIZE;
2873*fa790ea9SDavid C Somayajulu
2874*fa790ea9SDavid C Somayajulu hdr_size = ((cm_info.ip_version == ECORE_TCP_IPV4) ? 40 : 60) +
2875*fa790ea9SDavid C Somayajulu ts_hdr_size;
2876*fa790ea9SDavid C Somayajulu ep->mss = p_hwfn->p_rdma_info->iwarp.max_mtu - hdr_size;
2877*fa790ea9SDavid C Somayajulu ep->mss = OSAL_MIN_T(u16, ECORE_IWARP_MAX_FW_MSS, ep->mss);
2878*fa790ea9SDavid C Somayajulu
2879*fa790ea9SDavid C Somayajulu ep->listener = listener;
2880*fa790ea9SDavid C Somayajulu ep->event_cb = listener->event_cb;
2881*fa790ea9SDavid C Somayajulu ep->cb_context = listener->cb_context;
2882*fa790ea9SDavid C Somayajulu ep->connect_mode = TCP_CONNECT_PASSIVE;
2883*fa790ea9SDavid C Somayajulu
2884*fa790ea9SDavid C Somayajulu ep->syn = buf;
2885*fa790ea9SDavid C Somayajulu ep->syn_ip_payload_length = (u16)payload_len;
2886*fa790ea9SDavid C Somayajulu ep->syn_phy_addr = buf->data_phys_addr + data->u.placement_offset +
2887*fa790ea9SDavid C Somayajulu tcp_start_offset;
2888*fa790ea9SDavid C Somayajulu
2889*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_tcp_offload(p_hwfn, ep);
2890*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS) {
2891*fa790ea9SDavid C Somayajulu ecore_iwarp_return_ep(p_hwfn, ep);
2892*fa790ea9SDavid C Somayajulu goto err;
2893*fa790ea9SDavid C Somayajulu }
2894*fa790ea9SDavid C Somayajulu return;
2895*fa790ea9SDavid C Somayajulu
2896*fa790ea9SDavid C Somayajulu err:
2897*fa790ea9SDavid C Somayajulu ecore_iwarp_ll2_post_rx(
2898*fa790ea9SDavid C Somayajulu p_hwfn, buf, p_hwfn->p_rdma_info->iwarp.ll2_syn_handle);
2899*fa790ea9SDavid C Somayajulu }
2900*fa790ea9SDavid C Somayajulu
2901*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_ll2_rel_rx_pkt(void * cxt,u8 OSAL_UNUSED connection_handle,void * cookie,dma_addr_t OSAL_UNUSED rx_buf_addr,bool OSAL_UNUSED b_last_packet)2902*fa790ea9SDavid C Somayajulu ecore_iwarp_ll2_rel_rx_pkt(void *cxt,
2903*fa790ea9SDavid C Somayajulu u8 OSAL_UNUSED connection_handle,
2904*fa790ea9SDavid C Somayajulu void *cookie,
2905*fa790ea9SDavid C Somayajulu dma_addr_t OSAL_UNUSED rx_buf_addr,
2906*fa790ea9SDavid C Somayajulu bool OSAL_UNUSED b_last_packet)
2907*fa790ea9SDavid C Somayajulu {
2908*fa790ea9SDavid C Somayajulu struct ecore_hwfn *p_hwfn = (struct ecore_hwfn *)cxt;
2909*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ll2_buff *buffer =
2910*fa790ea9SDavid C Somayajulu (struct ecore_iwarp_ll2_buff *)cookie;
2911*fa790ea9SDavid C Somayajulu
2912*fa790ea9SDavid C Somayajulu OSAL_DMA_FREE_COHERENT(p_hwfn->p_dev,
2913*fa790ea9SDavid C Somayajulu buffer->data,
2914*fa790ea9SDavid C Somayajulu buffer->data_phys_addr,
2915*fa790ea9SDavid C Somayajulu buffer->buff_size);
2916*fa790ea9SDavid C Somayajulu
2917*fa790ea9SDavid C Somayajulu OSAL_FREE(p_hwfn->p_dev, buffer);
2918*fa790ea9SDavid C Somayajulu }
2919*fa790ea9SDavid C Somayajulu
2920*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_ll2_comp_tx_pkt(void * cxt,u8 connection_handle,void * cookie,dma_addr_t OSAL_UNUSED first_frag_addr,bool OSAL_UNUSED b_last_fragment,bool OSAL_UNUSED b_last_packet)2921*fa790ea9SDavid C Somayajulu ecore_iwarp_ll2_comp_tx_pkt(void *cxt,
2922*fa790ea9SDavid C Somayajulu u8 connection_handle,
2923*fa790ea9SDavid C Somayajulu void *cookie,
2924*fa790ea9SDavid C Somayajulu dma_addr_t OSAL_UNUSED first_frag_addr,
2925*fa790ea9SDavid C Somayajulu bool OSAL_UNUSED b_last_fragment,
2926*fa790ea9SDavid C Somayajulu bool OSAL_UNUSED b_last_packet)
2927*fa790ea9SDavid C Somayajulu {
2928*fa790ea9SDavid C Somayajulu struct ecore_hwfn *p_hwfn = (struct ecore_hwfn *)cxt;
2929*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ll2_buff *buffer =
2930*fa790ea9SDavid C Somayajulu (struct ecore_iwarp_ll2_buff *)cookie;
2931*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ll2_buff *piggy;
2932*fa790ea9SDavid C Somayajulu
2933*fa790ea9SDavid C Somayajulu if (!buffer) /* can happen in packed mpa unaligned... */
2934*fa790ea9SDavid C Somayajulu return;
2935*fa790ea9SDavid C Somayajulu
2936*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
2937*fa790ea9SDavid C Somayajulu "LL2 CompTX buf=%p piggy_buf=%p handle=%d\n",
2938*fa790ea9SDavid C Somayajulu buffer, buffer->piggy_buf, connection_handle);
2939*fa790ea9SDavid C Somayajulu
2940*fa790ea9SDavid C Somayajulu /* we got a tx packet -> this was originally a rx packet... now we
2941*fa790ea9SDavid C Somayajulu * can post it back...
2942*fa790ea9SDavid C Somayajulu */
2943*fa790ea9SDavid C Somayajulu piggy = buffer->piggy_buf;
2944*fa790ea9SDavid C Somayajulu if (piggy) {
2945*fa790ea9SDavid C Somayajulu buffer->piggy_buf = OSAL_NULL;
2946*fa790ea9SDavid C Somayajulu ecore_iwarp_ll2_post_rx(p_hwfn, piggy,
2947*fa790ea9SDavid C Somayajulu connection_handle);
2948*fa790ea9SDavid C Somayajulu }
2949*fa790ea9SDavid C Somayajulu
2950*fa790ea9SDavid C Somayajulu ecore_iwarp_ll2_post_rx(p_hwfn, buffer,
2951*fa790ea9SDavid C Somayajulu connection_handle);
2952*fa790ea9SDavid C Somayajulu
2953*fa790ea9SDavid C Somayajulu if (connection_handle == p_hwfn->p_rdma_info->iwarp.ll2_mpa_handle)
2954*fa790ea9SDavid C Somayajulu ecore_iwarp_process_pending_pkts(p_hwfn);
2955*fa790ea9SDavid C Somayajulu
2956*fa790ea9SDavid C Somayajulu return;
2957*fa790ea9SDavid C Somayajulu }
2958*fa790ea9SDavid C Somayajulu
2959*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_ll2_rel_tx_pkt(void * cxt,u8 OSAL_UNUSED connection_handle,void * cookie,dma_addr_t OSAL_UNUSED first_frag_addr,bool OSAL_UNUSED b_last_fragment,bool OSAL_UNUSED b_last_packet)2960*fa790ea9SDavid C Somayajulu ecore_iwarp_ll2_rel_tx_pkt(void *cxt,
2961*fa790ea9SDavid C Somayajulu u8 OSAL_UNUSED connection_handle,
2962*fa790ea9SDavid C Somayajulu void *cookie,
2963*fa790ea9SDavid C Somayajulu dma_addr_t OSAL_UNUSED first_frag_addr,
2964*fa790ea9SDavid C Somayajulu bool OSAL_UNUSED b_last_fragment,
2965*fa790ea9SDavid C Somayajulu bool OSAL_UNUSED b_last_packet)
2966*fa790ea9SDavid C Somayajulu {
2967*fa790ea9SDavid C Somayajulu struct ecore_hwfn *p_hwfn = (struct ecore_hwfn *)cxt;
2968*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ll2_buff *buffer =
2969*fa790ea9SDavid C Somayajulu (struct ecore_iwarp_ll2_buff *)cookie;
2970*fa790ea9SDavid C Somayajulu
2971*fa790ea9SDavid C Somayajulu if (!buffer)
2972*fa790ea9SDavid C Somayajulu return;
2973*fa790ea9SDavid C Somayajulu
2974*fa790ea9SDavid C Somayajulu if (buffer->piggy_buf) {
2975*fa790ea9SDavid C Somayajulu OSAL_DMA_FREE_COHERENT(
2976*fa790ea9SDavid C Somayajulu p_hwfn->p_dev,
2977*fa790ea9SDavid C Somayajulu buffer->piggy_buf->data,
2978*fa790ea9SDavid C Somayajulu buffer->piggy_buf->data_phys_addr,
2979*fa790ea9SDavid C Somayajulu buffer->piggy_buf->buff_size);
2980*fa790ea9SDavid C Somayajulu
2981*fa790ea9SDavid C Somayajulu OSAL_FREE(p_hwfn->p_dev, buffer->piggy_buf);
2982*fa790ea9SDavid C Somayajulu }
2983*fa790ea9SDavid C Somayajulu
2984*fa790ea9SDavid C Somayajulu OSAL_DMA_FREE_COHERENT(p_hwfn->p_dev,
2985*fa790ea9SDavid C Somayajulu buffer->data,
2986*fa790ea9SDavid C Somayajulu buffer->data_phys_addr,
2987*fa790ea9SDavid C Somayajulu buffer->buff_size);
2988*fa790ea9SDavid C Somayajulu
2989*fa790ea9SDavid C Somayajulu OSAL_FREE(p_hwfn->p_dev, buffer);
2990*fa790ea9SDavid C Somayajulu return;
2991*fa790ea9SDavid C Somayajulu }
2992*fa790ea9SDavid C Somayajulu
2993*fa790ea9SDavid C Somayajulu /* Current known slowpath for iwarp ll2 is unalign flush. When this completion
2994*fa790ea9SDavid C Somayajulu * is received, need to reset the FPDU.
2995*fa790ea9SDavid C Somayajulu */
2996*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_ll2_slowpath(void * cxt,u8 OSAL_UNUSED connection_handle,u32 opaque_data_0,u32 opaque_data_1)2997*fa790ea9SDavid C Somayajulu ecore_iwarp_ll2_slowpath(void *cxt,
2998*fa790ea9SDavid C Somayajulu u8 OSAL_UNUSED connection_handle,
2999*fa790ea9SDavid C Somayajulu u32 opaque_data_0,
3000*fa790ea9SDavid C Somayajulu u32 opaque_data_1)
3001*fa790ea9SDavid C Somayajulu {
3002*fa790ea9SDavid C Somayajulu struct ecore_hwfn *p_hwfn = (struct ecore_hwfn *)cxt;
3003*fa790ea9SDavid C Somayajulu struct unaligned_opaque_data unalign_data;
3004*fa790ea9SDavid C Somayajulu struct ecore_iwarp_fpdu *fpdu;
3005*fa790ea9SDavid C Somayajulu
3006*fa790ea9SDavid C Somayajulu ecore_iwarp_mpa_get_data(p_hwfn, &unalign_data,
3007*fa790ea9SDavid C Somayajulu opaque_data_0, opaque_data_1);
3008*fa790ea9SDavid C Somayajulu
3009*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "(0x%x) Flush fpdu\n",
3010*fa790ea9SDavid C Somayajulu unalign_data.cid);
3011*fa790ea9SDavid C Somayajulu
3012*fa790ea9SDavid C Somayajulu fpdu = ecore_iwarp_get_curr_fpdu(p_hwfn, (u16)unalign_data.cid);
3013*fa790ea9SDavid C Somayajulu if (fpdu)
3014*fa790ea9SDavid C Somayajulu OSAL_MEM_ZERO(fpdu, sizeof(*fpdu));
3015*fa790ea9SDavid C Somayajulu }
3016*fa790ea9SDavid C Somayajulu
3017*fa790ea9SDavid C Somayajulu static int
ecore_iwarp_ll2_stop(struct ecore_hwfn * p_hwfn)3018*fa790ea9SDavid C Somayajulu ecore_iwarp_ll2_stop(struct ecore_hwfn *p_hwfn)
3019*fa790ea9SDavid C Somayajulu {
3020*fa790ea9SDavid C Somayajulu struct ecore_iwarp_info *iwarp_info = &p_hwfn->p_rdma_info->iwarp;
3021*fa790ea9SDavid C Somayajulu int rc = 0;
3022*fa790ea9SDavid C Somayajulu
3023*fa790ea9SDavid C Somayajulu if (iwarp_info->ll2_syn_handle != ECORE_IWARP_HANDLE_INVAL) {
3024*fa790ea9SDavid C Somayajulu rc = ecore_ll2_terminate_connection(p_hwfn,
3025*fa790ea9SDavid C Somayajulu iwarp_info->ll2_syn_handle);
3026*fa790ea9SDavid C Somayajulu if (rc)
3027*fa790ea9SDavid C Somayajulu DP_INFO(p_hwfn, "Failed to terminate syn connection\n");
3028*fa790ea9SDavid C Somayajulu
3029*fa790ea9SDavid C Somayajulu ecore_ll2_release_connection(p_hwfn,
3030*fa790ea9SDavid C Somayajulu iwarp_info->ll2_syn_handle);
3031*fa790ea9SDavid C Somayajulu iwarp_info->ll2_syn_handle = ECORE_IWARP_HANDLE_INVAL;
3032*fa790ea9SDavid C Somayajulu }
3033*fa790ea9SDavid C Somayajulu
3034*fa790ea9SDavid C Somayajulu if (iwarp_info->ll2_ooo_handle != ECORE_IWARP_HANDLE_INVAL) {
3035*fa790ea9SDavid C Somayajulu rc = ecore_ll2_terminate_connection(p_hwfn,
3036*fa790ea9SDavid C Somayajulu iwarp_info->ll2_ooo_handle);
3037*fa790ea9SDavid C Somayajulu if (rc)
3038*fa790ea9SDavid C Somayajulu DP_INFO(p_hwfn, "Failed to terminate ooo connection\n");
3039*fa790ea9SDavid C Somayajulu
3040*fa790ea9SDavid C Somayajulu ecore_ll2_release_connection(p_hwfn,
3041*fa790ea9SDavid C Somayajulu iwarp_info->ll2_ooo_handle);
3042*fa790ea9SDavid C Somayajulu iwarp_info->ll2_ooo_handle = ECORE_IWARP_HANDLE_INVAL;
3043*fa790ea9SDavid C Somayajulu }
3044*fa790ea9SDavid C Somayajulu
3045*fa790ea9SDavid C Somayajulu if (iwarp_info->ll2_mpa_handle != ECORE_IWARP_HANDLE_INVAL) {
3046*fa790ea9SDavid C Somayajulu rc = ecore_ll2_terminate_connection(p_hwfn,
3047*fa790ea9SDavid C Somayajulu iwarp_info->ll2_mpa_handle);
3048*fa790ea9SDavid C Somayajulu if (rc)
3049*fa790ea9SDavid C Somayajulu DP_INFO(p_hwfn, "Failed to terminate mpa connection\n");
3050*fa790ea9SDavid C Somayajulu
3051*fa790ea9SDavid C Somayajulu ecore_ll2_release_connection(p_hwfn,
3052*fa790ea9SDavid C Somayajulu iwarp_info->ll2_mpa_handle);
3053*fa790ea9SDavid C Somayajulu iwarp_info->ll2_mpa_handle = ECORE_IWARP_HANDLE_INVAL;
3054*fa790ea9SDavid C Somayajulu }
3055*fa790ea9SDavid C Somayajulu
3056*fa790ea9SDavid C Somayajulu ecore_llh_remove_mac_filter(p_hwfn->p_dev, 0,
3057*fa790ea9SDavid C Somayajulu p_hwfn->p_rdma_info->iwarp.mac_addr);
3058*fa790ea9SDavid C Somayajulu
3059*fa790ea9SDavid C Somayajulu return rc;
3060*fa790ea9SDavid C Somayajulu }
3061*fa790ea9SDavid C Somayajulu
3062*fa790ea9SDavid C Somayajulu static int
ecore_iwarp_ll2_alloc_buffers(struct ecore_hwfn * p_hwfn,int num_rx_bufs,int buff_size,u8 ll2_handle)3063*fa790ea9SDavid C Somayajulu ecore_iwarp_ll2_alloc_buffers(struct ecore_hwfn *p_hwfn,
3064*fa790ea9SDavid C Somayajulu int num_rx_bufs,
3065*fa790ea9SDavid C Somayajulu int buff_size,
3066*fa790ea9SDavid C Somayajulu u8 ll2_handle)
3067*fa790ea9SDavid C Somayajulu {
3068*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ll2_buff *buffer;
3069*fa790ea9SDavid C Somayajulu int rc = 0;
3070*fa790ea9SDavid C Somayajulu int i;
3071*fa790ea9SDavid C Somayajulu
3072*fa790ea9SDavid C Somayajulu for (i = 0; i < num_rx_bufs; i++) {
3073*fa790ea9SDavid C Somayajulu buffer = OSAL_ZALLOC(p_hwfn->p_dev,
3074*fa790ea9SDavid C Somayajulu GFP_KERNEL, sizeof(*buffer));
3075*fa790ea9SDavid C Somayajulu if (!buffer) {
3076*fa790ea9SDavid C Somayajulu DP_INFO(p_hwfn, "Failed to allocate LL2 buffer desc\n");
3077*fa790ea9SDavid C Somayajulu break;
3078*fa790ea9SDavid C Somayajulu }
3079*fa790ea9SDavid C Somayajulu
3080*fa790ea9SDavid C Somayajulu buffer->data =
3081*fa790ea9SDavid C Somayajulu OSAL_DMA_ALLOC_COHERENT(p_hwfn->p_dev,
3082*fa790ea9SDavid C Somayajulu &buffer->data_phys_addr,
3083*fa790ea9SDavid C Somayajulu buff_size);
3084*fa790ea9SDavid C Somayajulu
3085*fa790ea9SDavid C Somayajulu if (!buffer->data) {
3086*fa790ea9SDavid C Somayajulu DP_INFO(p_hwfn, "Failed to allocate LL2 buffers\n");
3087*fa790ea9SDavid C Somayajulu OSAL_FREE(p_hwfn->p_dev, buffer);
3088*fa790ea9SDavid C Somayajulu rc = ECORE_NOMEM;
3089*fa790ea9SDavid C Somayajulu break;
3090*fa790ea9SDavid C Somayajulu }
3091*fa790ea9SDavid C Somayajulu
3092*fa790ea9SDavid C Somayajulu buffer->buff_size = buff_size;
3093*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_ll2_post_rx(p_hwfn, buffer, ll2_handle);
3094*fa790ea9SDavid C Somayajulu
3095*fa790ea9SDavid C Somayajulu if (rc)
3096*fa790ea9SDavid C Somayajulu break; /* buffers will be deallocated by ecore_ll2 */
3097*fa790ea9SDavid C Somayajulu }
3098*fa790ea9SDavid C Somayajulu return rc;
3099*fa790ea9SDavid C Somayajulu }
3100*fa790ea9SDavid C Somayajulu
3101*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_CACHE_PADDING(size) \
3102*fa790ea9SDavid C Somayajulu (((size) + ETH_CACHE_LINE_SIZE - 1) & ~(ETH_CACHE_LINE_SIZE - 1))
3103*fa790ea9SDavid C Somayajulu
3104*fa790ea9SDavid C Somayajulu #define ECORE_IWARP_MAX_BUF_SIZE(mtu) \
3105*fa790ea9SDavid C Somayajulu ECORE_IWARP_CACHE_PADDING(mtu + ETH_HLEN + 2*VLAN_HLEN + 2 +\
3106*fa790ea9SDavid C Somayajulu ETH_CACHE_LINE_SIZE)
3107*fa790ea9SDavid C Somayajulu
3108*fa790ea9SDavid C Somayajulu static int
ecore_iwarp_ll2_start(struct ecore_hwfn * p_hwfn,struct ecore_rdma_start_in_params * params)3109*fa790ea9SDavid C Somayajulu ecore_iwarp_ll2_start(struct ecore_hwfn *p_hwfn,
3110*fa790ea9SDavid C Somayajulu struct ecore_rdma_start_in_params *params)
3111*fa790ea9SDavid C Somayajulu {
3112*fa790ea9SDavid C Somayajulu struct ecore_iwarp_info *iwarp_info;
3113*fa790ea9SDavid C Somayajulu struct ecore_ll2_acquire_data data;
3114*fa790ea9SDavid C Somayajulu struct ecore_ll2_cbs cbs;
3115*fa790ea9SDavid C Somayajulu u32 mpa_buff_size;
3116*fa790ea9SDavid C Somayajulu int rc = ECORE_SUCCESS;
3117*fa790ea9SDavid C Somayajulu u16 n_ooo_bufs;
3118*fa790ea9SDavid C Somayajulu int i;
3119*fa790ea9SDavid C Somayajulu
3120*fa790ea9SDavid C Somayajulu iwarp_info = &p_hwfn->p_rdma_info->iwarp;
3121*fa790ea9SDavid C Somayajulu iwarp_info->ll2_syn_handle = ECORE_IWARP_HANDLE_INVAL;
3122*fa790ea9SDavid C Somayajulu iwarp_info->ll2_ooo_handle = ECORE_IWARP_HANDLE_INVAL;
3123*fa790ea9SDavid C Somayajulu iwarp_info->ll2_mpa_handle = ECORE_IWARP_HANDLE_INVAL;
3124*fa790ea9SDavid C Somayajulu
3125*fa790ea9SDavid C Somayajulu iwarp_info->max_mtu = params->max_mtu;
3126*fa790ea9SDavid C Somayajulu
3127*fa790ea9SDavid C Somayajulu OSAL_MEMCPY(p_hwfn->p_rdma_info->iwarp.mac_addr, params->mac_addr,
3128*fa790ea9SDavid C Somayajulu ETH_ALEN);
3129*fa790ea9SDavid C Somayajulu
3130*fa790ea9SDavid C Somayajulu rc = ecore_llh_add_mac_filter(p_hwfn->p_dev, 0, params->mac_addr);
3131*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
3132*fa790ea9SDavid C Somayajulu return rc;
3133*fa790ea9SDavid C Somayajulu
3134*fa790ea9SDavid C Somayajulu /* Start SYN connection */
3135*fa790ea9SDavid C Somayajulu cbs.rx_comp_cb = ecore_iwarp_ll2_comp_syn_pkt;
3136*fa790ea9SDavid C Somayajulu cbs.rx_release_cb = ecore_iwarp_ll2_rel_rx_pkt;
3137*fa790ea9SDavid C Somayajulu cbs.tx_comp_cb = ecore_iwarp_ll2_comp_tx_pkt;
3138*fa790ea9SDavid C Somayajulu cbs.tx_release_cb = ecore_iwarp_ll2_rel_tx_pkt;
3139*fa790ea9SDavid C Somayajulu cbs.cookie = p_hwfn;
3140*fa790ea9SDavid C Somayajulu
3141*fa790ea9SDavid C Somayajulu OSAL_MEMSET(&data, 0, sizeof(data));
3142*fa790ea9SDavid C Somayajulu data.input.conn_type = ECORE_LL2_TYPE_IWARP;
3143*fa790ea9SDavid C Somayajulu data.input.mtu = ECORE_IWARP_MAX_SYN_PKT_SIZE;
3144*fa790ea9SDavid C Somayajulu data.input.rx_num_desc = ECORE_IWARP_LL2_SYN_RX_SIZE;
3145*fa790ea9SDavid C Somayajulu data.input.tx_num_desc = ECORE_IWARP_LL2_SYN_TX_SIZE;
3146*fa790ea9SDavid C Somayajulu data.input.tx_max_bds_per_packet = 1; /* will never be fragmented */
3147*fa790ea9SDavid C Somayajulu data.input.tx_tc = PKT_LB_TC;
3148*fa790ea9SDavid C Somayajulu data.input.tx_dest = ECORE_LL2_TX_DEST_LB;
3149*fa790ea9SDavid C Somayajulu data.p_connection_handle = &iwarp_info->ll2_syn_handle;
3150*fa790ea9SDavid C Somayajulu data.cbs = &cbs;
3151*fa790ea9SDavid C Somayajulu
3152*fa790ea9SDavid C Somayajulu rc = ecore_ll2_acquire_connection(p_hwfn, &data);
3153*fa790ea9SDavid C Somayajulu if (rc) {
3154*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "Failed to acquire LL2 connection\n");
3155*fa790ea9SDavid C Somayajulu ecore_llh_remove_mac_filter(p_hwfn->p_dev, 0, params->mac_addr);
3156*fa790ea9SDavid C Somayajulu return rc;
3157*fa790ea9SDavid C Somayajulu }
3158*fa790ea9SDavid C Somayajulu
3159*fa790ea9SDavid C Somayajulu rc = ecore_ll2_establish_connection(p_hwfn, iwarp_info->ll2_syn_handle);
3160*fa790ea9SDavid C Somayajulu if (rc) {
3161*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false,
3162*fa790ea9SDavid C Somayajulu "Failed to establish LL2 connection\n");
3163*fa790ea9SDavid C Somayajulu goto err;
3164*fa790ea9SDavid C Somayajulu }
3165*fa790ea9SDavid C Somayajulu
3166*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_ll2_alloc_buffers(p_hwfn,
3167*fa790ea9SDavid C Somayajulu ECORE_IWARP_LL2_SYN_RX_SIZE,
3168*fa790ea9SDavid C Somayajulu ECORE_IWARP_MAX_SYN_PKT_SIZE,
3169*fa790ea9SDavid C Somayajulu iwarp_info->ll2_syn_handle);
3170*fa790ea9SDavid C Somayajulu if (rc)
3171*fa790ea9SDavid C Somayajulu goto err;
3172*fa790ea9SDavid C Somayajulu
3173*fa790ea9SDavid C Somayajulu /* Start OOO connection */
3174*fa790ea9SDavid C Somayajulu data.input.conn_type = ECORE_LL2_TYPE_OOO;
3175*fa790ea9SDavid C Somayajulu data.input.mtu = params->max_mtu;
3176*fa790ea9SDavid C Somayajulu
3177*fa790ea9SDavid C Somayajulu n_ooo_bufs = params->iwarp.ooo_num_rx_bufs;
3178*fa790ea9SDavid C Somayajulu
3179*fa790ea9SDavid C Somayajulu if (n_ooo_bufs > ECORE_IWARP_LL2_OOO_MAX_RX_SIZE)
3180*fa790ea9SDavid C Somayajulu n_ooo_bufs = ECORE_IWARP_LL2_OOO_MAX_RX_SIZE;
3181*fa790ea9SDavid C Somayajulu
3182*fa790ea9SDavid C Somayajulu data.input.rx_num_desc = n_ooo_bufs;
3183*fa790ea9SDavid C Somayajulu data.input.rx_num_ooo_buffers = n_ooo_bufs;
3184*fa790ea9SDavid C Somayajulu
3185*fa790ea9SDavid C Somayajulu p_hwfn->p_rdma_info->iwarp.num_ooo_rx_bufs = data.input.rx_num_desc;
3186*fa790ea9SDavid C Somayajulu data.input.tx_max_bds_per_packet = 1; /* will never be fragmented */
3187*fa790ea9SDavid C Somayajulu data.input.tx_num_desc = ECORE_IWARP_LL2_OOO_DEF_TX_SIZE;
3188*fa790ea9SDavid C Somayajulu data.p_connection_handle = &iwarp_info->ll2_ooo_handle;
3189*fa790ea9SDavid C Somayajulu data.input.secondary_queue = true;
3190*fa790ea9SDavid C Somayajulu
3191*fa790ea9SDavid C Somayajulu rc = ecore_ll2_acquire_connection(p_hwfn, &data);
3192*fa790ea9SDavid C Somayajulu if (rc)
3193*fa790ea9SDavid C Somayajulu goto err;
3194*fa790ea9SDavid C Somayajulu
3195*fa790ea9SDavid C Somayajulu rc = ecore_ll2_establish_connection(p_hwfn, iwarp_info->ll2_ooo_handle);
3196*fa790ea9SDavid C Somayajulu if (rc)
3197*fa790ea9SDavid C Somayajulu goto err;
3198*fa790ea9SDavid C Somayajulu
3199*fa790ea9SDavid C Somayajulu /* Start MPA connection */
3200*fa790ea9SDavid C Somayajulu cbs.rx_comp_cb = ecore_iwarp_ll2_comp_mpa_pkt;
3201*fa790ea9SDavid C Somayajulu cbs.slowpath_cb = ecore_iwarp_ll2_slowpath;
3202*fa790ea9SDavid C Somayajulu
3203*fa790ea9SDavid C Somayajulu OSAL_MEMSET(&data, 0, sizeof(data));
3204*fa790ea9SDavid C Somayajulu data.input.conn_type = ECORE_LL2_TYPE_IWARP;
3205*fa790ea9SDavid C Somayajulu data.input.mtu = params->max_mtu;
3206*fa790ea9SDavid C Somayajulu data.input.rx_num_desc = n_ooo_bufs * 2;
3207*fa790ea9SDavid C Somayajulu /* we allocate the same amount for TX to reduce the chance we
3208*fa790ea9SDavid C Somayajulu * run out of tx descriptors
3209*fa790ea9SDavid C Somayajulu */
3210*fa790ea9SDavid C Somayajulu data.input.tx_num_desc = data.input.rx_num_desc;
3211*fa790ea9SDavid C Somayajulu data.input.tx_max_bds_per_packet = ECORE_IWARP_MAX_BDS_PER_FPDU;
3212*fa790ea9SDavid C Somayajulu data.p_connection_handle = &iwarp_info->ll2_mpa_handle;
3213*fa790ea9SDavid C Somayajulu data.input.secondary_queue = true;
3214*fa790ea9SDavid C Somayajulu data.cbs = &cbs;
3215*fa790ea9SDavid C Somayajulu
3216*fa790ea9SDavid C Somayajulu rc = ecore_ll2_acquire_connection(p_hwfn, &data);
3217*fa790ea9SDavid C Somayajulu if (rc)
3218*fa790ea9SDavid C Somayajulu goto err;
3219*fa790ea9SDavid C Somayajulu
3220*fa790ea9SDavid C Somayajulu rc = ecore_ll2_establish_connection(p_hwfn, iwarp_info->ll2_mpa_handle);
3221*fa790ea9SDavid C Somayajulu if (rc)
3222*fa790ea9SDavid C Somayajulu goto err;
3223*fa790ea9SDavid C Somayajulu
3224*fa790ea9SDavid C Somayajulu mpa_buff_size = ECORE_IWARP_MAX_BUF_SIZE(params->max_mtu);
3225*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_ll2_alloc_buffers(p_hwfn,
3226*fa790ea9SDavid C Somayajulu data.input.rx_num_desc,
3227*fa790ea9SDavid C Somayajulu mpa_buff_size,
3228*fa790ea9SDavid C Somayajulu iwarp_info->ll2_mpa_handle);
3229*fa790ea9SDavid C Somayajulu if (rc)
3230*fa790ea9SDavid C Somayajulu goto err;
3231*fa790ea9SDavid C Somayajulu
3232*fa790ea9SDavid C Somayajulu iwarp_info->partial_fpdus =
3233*fa790ea9SDavid C Somayajulu OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
3234*fa790ea9SDavid C Somayajulu sizeof(*iwarp_info->partial_fpdus) *
3235*fa790ea9SDavid C Somayajulu (u16)p_hwfn->p_rdma_info->num_qps);
3236*fa790ea9SDavid C Somayajulu
3237*fa790ea9SDavid C Somayajulu if (!iwarp_info->partial_fpdus) {
3238*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false,
3239*fa790ea9SDavid C Somayajulu "Failed to allocate ecore_iwarp_info(partial_fpdus)\n");
3240*fa790ea9SDavid C Somayajulu goto err;
3241*fa790ea9SDavid C Somayajulu }
3242*fa790ea9SDavid C Somayajulu
3243*fa790ea9SDavid C Somayajulu iwarp_info->max_num_partial_fpdus = (u16)p_hwfn->p_rdma_info->num_qps;
3244*fa790ea9SDavid C Somayajulu
3245*fa790ea9SDavid C Somayajulu /* The mpa_bufs array serves for pending RX packets received on the
3246*fa790ea9SDavid C Somayajulu * mpa ll2 that don't have place on the tx ring and require later
3247*fa790ea9SDavid C Somayajulu * processing. We can't fail on allocation of such a struct therefore
3248*fa790ea9SDavid C Somayajulu * we allocate enough to take care of all rx packets
3249*fa790ea9SDavid C Somayajulu */
3250*fa790ea9SDavid C Somayajulu iwarp_info->mpa_bufs =
3251*fa790ea9SDavid C Somayajulu OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
3252*fa790ea9SDavid C Somayajulu sizeof(*iwarp_info->mpa_bufs) *
3253*fa790ea9SDavid C Somayajulu data.input.rx_num_desc);
3254*fa790ea9SDavid C Somayajulu
3255*fa790ea9SDavid C Somayajulu if (!iwarp_info->mpa_bufs) {
3256*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false,
3257*fa790ea9SDavid C Somayajulu "Failed to allocate mpa_bufs array mem_size=%d\n",
3258*fa790ea9SDavid C Somayajulu (u32)(sizeof(*iwarp_info->mpa_bufs) *
3259*fa790ea9SDavid C Somayajulu data.input.rx_num_desc));
3260*fa790ea9SDavid C Somayajulu goto err;
3261*fa790ea9SDavid C Somayajulu }
3262*fa790ea9SDavid C Somayajulu
3263*fa790ea9SDavid C Somayajulu iwarp_info->mpa_intermediate_buf =
3264*fa790ea9SDavid C Somayajulu OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL, mpa_buff_size);
3265*fa790ea9SDavid C Somayajulu if (!iwarp_info->mpa_intermediate_buf) {
3266*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false,
3267*fa790ea9SDavid C Somayajulu "Failed to allocate mpa_intermediate_buf mem_size=%d\n",
3268*fa790ea9SDavid C Somayajulu mpa_buff_size);
3269*fa790ea9SDavid C Somayajulu goto err;
3270*fa790ea9SDavid C Somayajulu }
3271*fa790ea9SDavid C Somayajulu
3272*fa790ea9SDavid C Somayajulu OSAL_LIST_INIT(&iwarp_info->mpa_buf_pending_list);
3273*fa790ea9SDavid C Somayajulu OSAL_LIST_INIT(&iwarp_info->mpa_buf_list);
3274*fa790ea9SDavid C Somayajulu for (i = 0; i < data.input.rx_num_desc; i++) {
3275*fa790ea9SDavid C Somayajulu OSAL_LIST_PUSH_TAIL(&iwarp_info->mpa_bufs[i].list_entry,
3276*fa790ea9SDavid C Somayajulu &iwarp_info->mpa_buf_list);
3277*fa790ea9SDavid C Somayajulu }
3278*fa790ea9SDavid C Somayajulu
3279*fa790ea9SDavid C Somayajulu return rc;
3280*fa790ea9SDavid C Somayajulu
3281*fa790ea9SDavid C Somayajulu err:
3282*fa790ea9SDavid C Somayajulu ecore_iwarp_ll2_stop(p_hwfn);
3283*fa790ea9SDavid C Somayajulu
3284*fa790ea9SDavid C Somayajulu return rc;
3285*fa790ea9SDavid C Somayajulu }
3286*fa790ea9SDavid C Somayajulu
3287*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_set_defaults(struct ecore_hwfn * p_hwfn,struct ecore_rdma_start_in_params * params)3288*fa790ea9SDavid C Somayajulu ecore_iwarp_set_defaults(struct ecore_hwfn *p_hwfn,
3289*fa790ea9SDavid C Somayajulu struct ecore_rdma_start_in_params *params)
3290*fa790ea9SDavid C Somayajulu {
3291*fa790ea9SDavid C Somayajulu u32 rcv_wnd_size;
3292*fa790ea9SDavid C Somayajulu u32 n_ooo_bufs;
3293*fa790ea9SDavid C Somayajulu
3294*fa790ea9SDavid C Somayajulu /* rcv_wnd_size = 0: use defaults */
3295*fa790ea9SDavid C Somayajulu rcv_wnd_size = params->iwarp.rcv_wnd_size;
3296*fa790ea9SDavid C Somayajulu if (!rcv_wnd_size) {
3297*fa790ea9SDavid C Somayajulu if (ecore_device_num_ports(p_hwfn->p_dev) == 4) {
3298*fa790ea9SDavid C Somayajulu rcv_wnd_size = ECORE_IS_AH(p_hwfn->p_dev) ?
3299*fa790ea9SDavid C Somayajulu ECORE_IWARP_RCV_WND_SIZE_AH_DEF_4_PORTS :
3300*fa790ea9SDavid C Somayajulu ECORE_IWARP_RCV_WND_SIZE_BB_DEF_4_PORTS;
3301*fa790ea9SDavid C Somayajulu } else {
3302*fa790ea9SDavid C Somayajulu rcv_wnd_size = ECORE_IS_AH(p_hwfn->p_dev) ?
3303*fa790ea9SDavid C Somayajulu ECORE_IWARP_RCV_WND_SIZE_AH_DEF_2_PORTS :
3304*fa790ea9SDavid C Somayajulu ECORE_IWARP_RCV_WND_SIZE_BB_DEF_2_PORTS;
3305*fa790ea9SDavid C Somayajulu }
3306*fa790ea9SDavid C Somayajulu params->iwarp.rcv_wnd_size = rcv_wnd_size;
3307*fa790ea9SDavid C Somayajulu }
3308*fa790ea9SDavid C Somayajulu
3309*fa790ea9SDavid C Somayajulu n_ooo_bufs = params->iwarp.ooo_num_rx_bufs;
3310*fa790ea9SDavid C Somayajulu if (!n_ooo_bufs) {
3311*fa790ea9SDavid C Somayajulu n_ooo_bufs = (u32)(((u64)ECORE_MAX_OOO *
3312*fa790ea9SDavid C Somayajulu params->iwarp.rcv_wnd_size) /
3313*fa790ea9SDavid C Somayajulu params->max_mtu);
3314*fa790ea9SDavid C Somayajulu n_ooo_bufs = OSAL_MIN_T(u32, n_ooo_bufs, USHRT_MAX);
3315*fa790ea9SDavid C Somayajulu params->iwarp.ooo_num_rx_bufs = (u16)n_ooo_bufs;
3316*fa790ea9SDavid C Somayajulu }
3317*fa790ea9SDavid C Somayajulu }
3318*fa790ea9SDavid C Somayajulu
3319*fa790ea9SDavid C Somayajulu enum _ecore_status_t
ecore_iwarp_setup(struct ecore_hwfn * p_hwfn,struct ecore_rdma_start_in_params * params)3320*fa790ea9SDavid C Somayajulu ecore_iwarp_setup(struct ecore_hwfn *p_hwfn,
3321*fa790ea9SDavid C Somayajulu struct ecore_rdma_start_in_params *params)
3322*fa790ea9SDavid C Somayajulu {
3323*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc = ECORE_SUCCESS;
3324*fa790ea9SDavid C Somayajulu struct ecore_iwarp_info *iwarp_info;
3325*fa790ea9SDavid C Somayajulu u32 rcv_wnd_size;
3326*fa790ea9SDavid C Somayajulu
3327*fa790ea9SDavid C Somayajulu iwarp_info = &(p_hwfn->p_rdma_info->iwarp);
3328*fa790ea9SDavid C Somayajulu
3329*fa790ea9SDavid C Somayajulu if (!params->iwarp.rcv_wnd_size || !params->iwarp.ooo_num_rx_bufs)
3330*fa790ea9SDavid C Somayajulu ecore_iwarp_set_defaults(p_hwfn, params);
3331*fa790ea9SDavid C Somayajulu
3332*fa790ea9SDavid C Somayajulu /* Scale 0 will set window of 0xFFFC (64K -4).
3333*fa790ea9SDavid C Somayajulu * Scale x will set window of 0xFFFC << (x)
3334*fa790ea9SDavid C Somayajulu * Therefore we subtract log2(64K) so that result is 0
3335*fa790ea9SDavid C Somayajulu */
3336*fa790ea9SDavid C Somayajulu rcv_wnd_size = params->iwarp.rcv_wnd_size;
3337*fa790ea9SDavid C Somayajulu if (rcv_wnd_size < ECORE_IWARP_RCV_WND_SIZE_MIN)
3338*fa790ea9SDavid C Somayajulu rcv_wnd_size = ECORE_IWARP_RCV_WND_SIZE_MIN;
3339*fa790ea9SDavid C Somayajulu
3340*fa790ea9SDavid C Somayajulu iwarp_info->rcv_wnd_scale = OSAL_MIN_T(u32, OSAL_LOG2(rcv_wnd_size) -
3341*fa790ea9SDavid C Somayajulu OSAL_LOG2(ECORE_IWARP_RCV_WND_SIZE_MIN), ECORE_IWARP_MAX_WND_SCALE);
3342*fa790ea9SDavid C Somayajulu iwarp_info->rcv_wnd_size = rcv_wnd_size >> iwarp_info->rcv_wnd_scale;
3343*fa790ea9SDavid C Somayajulu
3344*fa790ea9SDavid C Somayajulu iwarp_info->tcp_flags = params->iwarp.flags;
3345*fa790ea9SDavid C Somayajulu iwarp_info->crc_needed = params->iwarp.crc_needed;
3346*fa790ea9SDavid C Somayajulu switch (params->iwarp.mpa_rev) {
3347*fa790ea9SDavid C Somayajulu case ECORE_MPA_REV1:
3348*fa790ea9SDavid C Somayajulu iwarp_info->mpa_rev = MPA_NEGOTIATION_TYPE_BASIC;
3349*fa790ea9SDavid C Somayajulu break;
3350*fa790ea9SDavid C Somayajulu case ECORE_MPA_REV2:
3351*fa790ea9SDavid C Somayajulu iwarp_info->mpa_rev = MPA_NEGOTIATION_TYPE_ENHANCED;
3352*fa790ea9SDavid C Somayajulu break;
3353*fa790ea9SDavid C Somayajulu }
3354*fa790ea9SDavid C Somayajulu
3355*fa790ea9SDavid C Somayajulu iwarp_info->peer2peer = params->iwarp.mpa_peer2peer;
3356*fa790ea9SDavid C Somayajulu iwarp_info->rtr_type = MPA_RTR_TYPE_NONE;
3357*fa790ea9SDavid C Somayajulu
3358*fa790ea9SDavid C Somayajulu if (params->iwarp.mpa_rtr & ECORE_MPA_RTR_TYPE_ZERO_SEND)
3359*fa790ea9SDavid C Somayajulu iwarp_info->rtr_type |= MPA_RTR_TYPE_ZERO_SEND;
3360*fa790ea9SDavid C Somayajulu
3361*fa790ea9SDavid C Somayajulu if (params->iwarp.mpa_rtr & ECORE_MPA_RTR_TYPE_ZERO_WRITE)
3362*fa790ea9SDavid C Somayajulu iwarp_info->rtr_type |= MPA_RTR_TYPE_ZERO_WRITE;
3363*fa790ea9SDavid C Somayajulu
3364*fa790ea9SDavid C Somayajulu if (params->iwarp.mpa_rtr & ECORE_MPA_RTR_TYPE_ZERO_READ)
3365*fa790ea9SDavid C Somayajulu iwarp_info->rtr_type |= MPA_RTR_TYPE_ZERO_READ;
3366*fa790ea9SDavid C Somayajulu
3367*fa790ea9SDavid C Somayajulu //DAVIDS OSAL_SPIN_LOCK_INIT(&p_hwfn->p_rdma_info->iwarp.qp_lock);
3368*fa790ea9SDavid C Somayajulu OSAL_LIST_INIT(&p_hwfn->p_rdma_info->iwarp.ep_list);
3369*fa790ea9SDavid C Somayajulu OSAL_LIST_INIT(&p_hwfn->p_rdma_info->iwarp.listen_list);
3370*fa790ea9SDavid C Somayajulu
3371*fa790ea9SDavid C Somayajulu ecore_spq_register_async_cb(p_hwfn, PROTOCOLID_IWARP,
3372*fa790ea9SDavid C Somayajulu ecore_iwarp_async_event);
3373*fa790ea9SDavid C Somayajulu ecore_ooo_setup(p_hwfn);
3374*fa790ea9SDavid C Somayajulu
3375*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_ll2_start(p_hwfn, params);
3376*fa790ea9SDavid C Somayajulu
3377*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
3378*fa790ea9SDavid C Somayajulu "MPA_REV = %d. peer2peer=%d rtr=%x\n",
3379*fa790ea9SDavid C Somayajulu iwarp_info->mpa_rev,
3380*fa790ea9SDavid C Somayajulu iwarp_info->peer2peer,
3381*fa790ea9SDavid C Somayajulu iwarp_info->rtr_type);
3382*fa790ea9SDavid C Somayajulu
3383*fa790ea9SDavid C Somayajulu return rc;
3384*fa790ea9SDavid C Somayajulu }
3385*fa790ea9SDavid C Somayajulu
3386*fa790ea9SDavid C Somayajulu enum _ecore_status_t
ecore_iwarp_stop(struct ecore_hwfn * p_hwfn)3387*fa790ea9SDavid C Somayajulu ecore_iwarp_stop(struct ecore_hwfn *p_hwfn)
3388*fa790ea9SDavid C Somayajulu {
3389*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
3390*fa790ea9SDavid C Somayajulu
3391*fa790ea9SDavid C Somayajulu ecore_iwarp_free_prealloc_ep(p_hwfn);
3392*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_wait_for_all_cids(p_hwfn);
3393*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
3394*fa790ea9SDavid C Somayajulu return rc;
3395*fa790ea9SDavid C Somayajulu
3396*fa790ea9SDavid C Somayajulu ecore_spq_unregister_async_cb(p_hwfn, PROTOCOLID_IWARP);
3397*fa790ea9SDavid C Somayajulu
3398*fa790ea9SDavid C Somayajulu return ecore_iwarp_ll2_stop(p_hwfn);
3399*fa790ea9SDavid C Somayajulu }
3400*fa790ea9SDavid C Somayajulu
3401*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_qp_in_error(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_ep * ep,u8 fw_return_code)3402*fa790ea9SDavid C Somayajulu ecore_iwarp_qp_in_error(struct ecore_hwfn *p_hwfn,
3403*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep,
3404*fa790ea9SDavid C Somayajulu u8 fw_return_code)
3405*fa790ea9SDavid C Somayajulu {
3406*fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_event_params params;
3407*fa790ea9SDavid C Somayajulu
3408*fa790ea9SDavid C Somayajulu ecore_iwarp_modify_qp(p_hwfn, ep->qp, ECORE_IWARP_QP_STATE_ERROR, true);
3409*fa790ea9SDavid C Somayajulu
3410*fa790ea9SDavid C Somayajulu params.event = ECORE_IWARP_EVENT_CLOSE;
3411*fa790ea9SDavid C Somayajulu params.ep_context = ep;
3412*fa790ea9SDavid C Somayajulu params.cm_info = &ep->cm_info;
3413*fa790ea9SDavid C Somayajulu params.status = (fw_return_code == IWARP_QP_IN_ERROR_GOOD_CLOSE) ?
3414*fa790ea9SDavid C Somayajulu ECORE_SUCCESS : ECORE_CONN_RESET;
3415*fa790ea9SDavid C Somayajulu
3416*fa790ea9SDavid C Somayajulu ep->state = ECORE_IWARP_EP_CLOSED;
3417*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
3418*fa790ea9SDavid C Somayajulu OSAL_LIST_REMOVE_ENTRY(&ep->list_entry,
3419*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->iwarp.ep_list);
3420*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
3421*fa790ea9SDavid C Somayajulu
3422*fa790ea9SDavid C Somayajulu ep->event_cb(ep->cb_context, ¶ms);
3423*fa790ea9SDavid C Somayajulu }
3424*fa790ea9SDavid C Somayajulu
3425*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_exception_received(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_ep * ep,int fw_ret_code)3426*fa790ea9SDavid C Somayajulu ecore_iwarp_exception_received(struct ecore_hwfn *p_hwfn,
3427*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep,
3428*fa790ea9SDavid C Somayajulu int fw_ret_code)
3429*fa790ea9SDavid C Somayajulu {
3430*fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_event_params params;
3431*fa790ea9SDavid C Somayajulu bool event_cb = false;
3432*fa790ea9SDavid C Somayajulu
3433*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "EP(0x%x) fw_ret_code=%d\n",
3434*fa790ea9SDavid C Somayajulu ep->cid, fw_ret_code);
3435*fa790ea9SDavid C Somayajulu
3436*fa790ea9SDavid C Somayajulu switch (fw_ret_code) {
3437*fa790ea9SDavid C Somayajulu case IWARP_EXCEPTION_DETECTED_LLP_CLOSED:
3438*fa790ea9SDavid C Somayajulu params.status = ECORE_SUCCESS;
3439*fa790ea9SDavid C Somayajulu params.event = ECORE_IWARP_EVENT_DISCONNECT;
3440*fa790ea9SDavid C Somayajulu event_cb = true;
3441*fa790ea9SDavid C Somayajulu break;
3442*fa790ea9SDavid C Somayajulu case IWARP_EXCEPTION_DETECTED_LLP_RESET:
3443*fa790ea9SDavid C Somayajulu params.status = ECORE_CONN_RESET;
3444*fa790ea9SDavid C Somayajulu params.event = ECORE_IWARP_EVENT_DISCONNECT;
3445*fa790ea9SDavid C Somayajulu event_cb = true;
3446*fa790ea9SDavid C Somayajulu break;
3447*fa790ea9SDavid C Somayajulu case IWARP_EXCEPTION_DETECTED_RQ_EMPTY:
3448*fa790ea9SDavid C Somayajulu params.event = ECORE_IWARP_EVENT_RQ_EMPTY;
3449*fa790ea9SDavid C Somayajulu event_cb = true;
3450*fa790ea9SDavid C Somayajulu break;
3451*fa790ea9SDavid C Somayajulu case IWARP_EXCEPTION_DETECTED_IRQ_FULL:
3452*fa790ea9SDavid C Somayajulu params.event = ECORE_IWARP_EVENT_IRQ_FULL;
3453*fa790ea9SDavid C Somayajulu event_cb = true;
3454*fa790ea9SDavid C Somayajulu break;
3455*fa790ea9SDavid C Somayajulu case IWARP_EXCEPTION_DETECTED_LLP_TIMEOUT:
3456*fa790ea9SDavid C Somayajulu params.event = ECORE_IWARP_EVENT_LLP_TIMEOUT;
3457*fa790ea9SDavid C Somayajulu event_cb = true;
3458*fa790ea9SDavid C Somayajulu break;
3459*fa790ea9SDavid C Somayajulu case IWARP_EXCEPTION_DETECTED_REMOTE_PROTECTION_ERROR:
3460*fa790ea9SDavid C Somayajulu params.event = ECORE_IWARP_EVENT_REMOTE_PROTECTION_ERROR;
3461*fa790ea9SDavid C Somayajulu event_cb = true;
3462*fa790ea9SDavid C Somayajulu break;
3463*fa790ea9SDavid C Somayajulu case IWARP_EXCEPTION_DETECTED_CQ_OVERFLOW:
3464*fa790ea9SDavid C Somayajulu params.event = ECORE_IWARP_EVENT_CQ_OVERFLOW;
3465*fa790ea9SDavid C Somayajulu event_cb = true;
3466*fa790ea9SDavid C Somayajulu break;
3467*fa790ea9SDavid C Somayajulu case IWARP_EXCEPTION_DETECTED_LOCAL_CATASTROPHIC:
3468*fa790ea9SDavid C Somayajulu params.event = ECORE_IWARP_EVENT_QP_CATASTROPHIC;
3469*fa790ea9SDavid C Somayajulu event_cb = true;
3470*fa790ea9SDavid C Somayajulu break;
3471*fa790ea9SDavid C Somayajulu case IWARP_EXCEPTION_DETECTED_LOCAL_ACCESS_ERROR:
3472*fa790ea9SDavid C Somayajulu params.event = ECORE_IWARP_EVENT_LOCAL_ACCESS_ERROR;
3473*fa790ea9SDavid C Somayajulu event_cb = true;
3474*fa790ea9SDavid C Somayajulu break;
3475*fa790ea9SDavid C Somayajulu case IWARP_EXCEPTION_DETECTED_REMOTE_OPERATION_ERROR:
3476*fa790ea9SDavid C Somayajulu params.event = ECORE_IWARP_EVENT_REMOTE_OPERATION_ERROR;
3477*fa790ea9SDavid C Somayajulu event_cb = true;
3478*fa790ea9SDavid C Somayajulu break;
3479*fa790ea9SDavid C Somayajulu case IWARP_EXCEPTION_DETECTED_TERMINATE_RECEIVED:
3480*fa790ea9SDavid C Somayajulu params.event = ECORE_IWARP_EVENT_TERMINATE_RECEIVED;
3481*fa790ea9SDavid C Somayajulu event_cb = true;
3482*fa790ea9SDavid C Somayajulu break;
3483*fa790ea9SDavid C Somayajulu default:
3484*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
3485*fa790ea9SDavid C Somayajulu "Unhandled exception received...\n");
3486*fa790ea9SDavid C Somayajulu break;
3487*fa790ea9SDavid C Somayajulu }
3488*fa790ea9SDavid C Somayajulu
3489*fa790ea9SDavid C Somayajulu if (event_cb) {
3490*fa790ea9SDavid C Somayajulu params.ep_context = ep;
3491*fa790ea9SDavid C Somayajulu params.cm_info = &ep->cm_info;
3492*fa790ea9SDavid C Somayajulu ep->event_cb(ep->cb_context, ¶ms);
3493*fa790ea9SDavid C Somayajulu }
3494*fa790ea9SDavid C Somayajulu }
3495*fa790ea9SDavid C Somayajulu
3496*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_tcp_connect_unsuccessful(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_ep * ep,u8 fw_return_code)3497*fa790ea9SDavid C Somayajulu ecore_iwarp_tcp_connect_unsuccessful(struct ecore_hwfn *p_hwfn,
3498*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep,
3499*fa790ea9SDavid C Somayajulu u8 fw_return_code)
3500*fa790ea9SDavid C Somayajulu {
3501*fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_event_params params;
3502*fa790ea9SDavid C Somayajulu
3503*fa790ea9SDavid C Somayajulu OSAL_MEM_ZERO(¶ms, sizeof(params));
3504*fa790ea9SDavid C Somayajulu params.event = ECORE_IWARP_EVENT_ACTIVE_COMPLETE;
3505*fa790ea9SDavid C Somayajulu params.ep_context = ep;
3506*fa790ea9SDavid C Somayajulu params.cm_info = &ep->cm_info;
3507*fa790ea9SDavid C Somayajulu ep->state = ECORE_IWARP_EP_CLOSED;
3508*fa790ea9SDavid C Somayajulu
3509*fa790ea9SDavid C Somayajulu switch (fw_return_code) {
3510*fa790ea9SDavid C Somayajulu case IWARP_CONN_ERROR_TCP_CONNECT_INVALID_PACKET:
3511*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
3512*fa790ea9SDavid C Somayajulu "%s(0x%x) TCP connect got invalid packet\n",
3513*fa790ea9SDavid C Somayajulu ECORE_IWARP_CONNECT_MODE_STRING(ep),
3514*fa790ea9SDavid C Somayajulu ep->tcp_cid);
3515*fa790ea9SDavid C Somayajulu params.status = ECORE_CONN_RESET;
3516*fa790ea9SDavid C Somayajulu break;
3517*fa790ea9SDavid C Somayajulu case IWARP_CONN_ERROR_TCP_CONNECTION_RST:
3518*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
3519*fa790ea9SDavid C Somayajulu "%s(0x%x) TCP Connection Reset\n",
3520*fa790ea9SDavid C Somayajulu ECORE_IWARP_CONNECT_MODE_STRING(ep),
3521*fa790ea9SDavid C Somayajulu ep->tcp_cid);
3522*fa790ea9SDavid C Somayajulu params.status = ECORE_CONN_RESET;
3523*fa790ea9SDavid C Somayajulu break;
3524*fa790ea9SDavid C Somayajulu case IWARP_CONN_ERROR_TCP_CONNECT_TIMEOUT:
3525*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "%s(0x%x) TCP timeout\n",
3526*fa790ea9SDavid C Somayajulu ECORE_IWARP_CONNECT_MODE_STRING(ep),
3527*fa790ea9SDavid C Somayajulu ep->tcp_cid);
3528*fa790ea9SDavid C Somayajulu params.status = ECORE_TIMEOUT;
3529*fa790ea9SDavid C Somayajulu break;
3530*fa790ea9SDavid C Somayajulu case IWARP_CONN_ERROR_MPA_NOT_SUPPORTED_VER:
3531*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "%s(0x%x) MPA not supported VER\n",
3532*fa790ea9SDavid C Somayajulu ECORE_IWARP_CONNECT_MODE_STRING(ep),
3533*fa790ea9SDavid C Somayajulu ep->tcp_cid);
3534*fa790ea9SDavid C Somayajulu params.status = ECORE_CONN_REFUSED;
3535*fa790ea9SDavid C Somayajulu break;
3536*fa790ea9SDavid C Somayajulu case IWARP_CONN_ERROR_MPA_INVALID_PACKET:
3537*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "%s(0x%x) MPA Invalid Packet\n",
3538*fa790ea9SDavid C Somayajulu ECORE_IWARP_CONNECT_MODE_STRING(ep), ep->tcp_cid);
3539*fa790ea9SDavid C Somayajulu params.status = ECORE_CONN_RESET;
3540*fa790ea9SDavid C Somayajulu break;
3541*fa790ea9SDavid C Somayajulu default:
3542*fa790ea9SDavid C Somayajulu DP_ERR(p_hwfn, "%s(0x%x) Unexpected return code tcp connect: %d\n",
3543*fa790ea9SDavid C Somayajulu ECORE_IWARP_CONNECT_MODE_STRING(ep), ep->tcp_cid,
3544*fa790ea9SDavid C Somayajulu fw_return_code);
3545*fa790ea9SDavid C Somayajulu params.status = ECORE_CONN_RESET;
3546*fa790ea9SDavid C Somayajulu break;
3547*fa790ea9SDavid C Somayajulu }
3548*fa790ea9SDavid C Somayajulu
3549*fa790ea9SDavid C Somayajulu if (ep->connect_mode == TCP_CONNECT_PASSIVE) {
3550*fa790ea9SDavid C Somayajulu ep->tcp_cid = ECORE_IWARP_INVALID_TCP_CID;
3551*fa790ea9SDavid C Somayajulu ecore_iwarp_return_ep(p_hwfn, ep);
3552*fa790ea9SDavid C Somayajulu } else {
3553*fa790ea9SDavid C Somayajulu ep->event_cb(ep->cb_context, ¶ms);
3554*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
3555*fa790ea9SDavid C Somayajulu OSAL_LIST_REMOVE_ENTRY(&ep->list_entry,
3556*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->iwarp.ep_list);
3557*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
3558*fa790ea9SDavid C Somayajulu }
3559*fa790ea9SDavid C Somayajulu }
3560*fa790ea9SDavid C Somayajulu
3561*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_connect_complete(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_ep * ep,u8 fw_return_code)3562*fa790ea9SDavid C Somayajulu ecore_iwarp_connect_complete(struct ecore_hwfn *p_hwfn,
3563*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep,
3564*fa790ea9SDavid C Somayajulu u8 fw_return_code)
3565*fa790ea9SDavid C Somayajulu {
3566*fa790ea9SDavid C Somayajulu if (ep->connect_mode == TCP_CONNECT_PASSIVE) {
3567*fa790ea9SDavid C Somayajulu /* Done with the SYN packet, post back to ll2 rx */
3568*fa790ea9SDavid C Somayajulu ecore_iwarp_ll2_post_rx(
3569*fa790ea9SDavid C Somayajulu p_hwfn, ep->syn,
3570*fa790ea9SDavid C Somayajulu p_hwfn->p_rdma_info->iwarp.ll2_syn_handle);
3571*fa790ea9SDavid C Somayajulu
3572*fa790ea9SDavid C Somayajulu ep->syn = OSAL_NULL;
3573*fa790ea9SDavid C Somayajulu
3574*fa790ea9SDavid C Somayajulu if (ep->state == ECORE_IWARP_EP_ABORTING)
3575*fa790ea9SDavid C Somayajulu return;
3576*fa790ea9SDavid C Somayajulu
3577*fa790ea9SDavid C Somayajulu /* If connect failed - upper layer doesn't know about it */
3578*fa790ea9SDavid C Somayajulu if (fw_return_code == RDMA_RETURN_OK)
3579*fa790ea9SDavid C Somayajulu ecore_iwarp_mpa_received(p_hwfn, ep);
3580*fa790ea9SDavid C Somayajulu else
3581*fa790ea9SDavid C Somayajulu ecore_iwarp_tcp_connect_unsuccessful(p_hwfn, ep,
3582*fa790ea9SDavid C Somayajulu fw_return_code);
3583*fa790ea9SDavid C Somayajulu
3584*fa790ea9SDavid C Somayajulu } else {
3585*fa790ea9SDavid C Somayajulu if (fw_return_code == RDMA_RETURN_OK)
3586*fa790ea9SDavid C Somayajulu ecore_iwarp_mpa_offload(p_hwfn, ep);
3587*fa790ea9SDavid C Somayajulu else
3588*fa790ea9SDavid C Somayajulu ecore_iwarp_tcp_connect_unsuccessful(p_hwfn, ep,
3589*fa790ea9SDavid C Somayajulu fw_return_code);
3590*fa790ea9SDavid C Somayajulu }
3591*fa790ea9SDavid C Somayajulu }
3592*fa790ea9SDavid C Somayajulu
3593*fa790ea9SDavid C Somayajulu static OSAL_INLINE bool
ecore_iwarp_check_ep_ok(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_ep * ep)3594*fa790ea9SDavid C Somayajulu ecore_iwarp_check_ep_ok(struct ecore_hwfn *p_hwfn,
3595*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep)
3596*fa790ea9SDavid C Somayajulu {
3597*fa790ea9SDavid C Somayajulu if (ep == OSAL_NULL) {
3598*fa790ea9SDavid C Somayajulu DP_ERR(p_hwfn, "ERROR ON ASYNC ep=%p\n", ep);
3599*fa790ea9SDavid C Somayajulu return false;
3600*fa790ea9SDavid C Somayajulu }
3601*fa790ea9SDavid C Somayajulu
3602*fa790ea9SDavid C Somayajulu if (ep->sig != 0xdeadbeef) {
3603*fa790ea9SDavid C Somayajulu DP_ERR(p_hwfn, "ERROR ON ASYNC ep=%p\n", ep);
3604*fa790ea9SDavid C Somayajulu return false;
3605*fa790ea9SDavid C Somayajulu }
3606*fa790ea9SDavid C Somayajulu
3607*fa790ea9SDavid C Somayajulu return true;
3608*fa790ea9SDavid C Somayajulu }
3609*fa790ea9SDavid C Somayajulu
3610*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
ecore_iwarp_async_event(struct ecore_hwfn * p_hwfn,u8 fw_event_code,u16 OSAL_UNUSED echo,union event_ring_data * data,u8 fw_return_code)3611*fa790ea9SDavid C Somayajulu ecore_iwarp_async_event(struct ecore_hwfn *p_hwfn,
3612*fa790ea9SDavid C Somayajulu u8 fw_event_code,
3613*fa790ea9SDavid C Somayajulu u16 OSAL_UNUSED echo,
3614*fa790ea9SDavid C Somayajulu union event_ring_data *data,
3615*fa790ea9SDavid C Somayajulu u8 fw_return_code)
3616*fa790ea9SDavid C Somayajulu {
3617*fa790ea9SDavid C Somayajulu struct regpair *fw_handle = &data->rdma_data.async_handle;
3618*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep = OSAL_NULL;
3619*fa790ea9SDavid C Somayajulu u16 cid;
3620*fa790ea9SDavid C Somayajulu
3621*fa790ea9SDavid C Somayajulu ep = (struct ecore_iwarp_ep *)(osal_uintptr_t)HILO_64(fw_handle->hi,
3622*fa790ea9SDavid C Somayajulu fw_handle->lo);
3623*fa790ea9SDavid C Somayajulu
3624*fa790ea9SDavid C Somayajulu switch (fw_event_code) {
3625*fa790ea9SDavid C Somayajulu /* Async completion after TCP 3-way handshake */
3626*fa790ea9SDavid C Somayajulu case IWARP_EVENT_TYPE_ASYNC_CONNECT_COMPLETE:
3627*fa790ea9SDavid C Somayajulu if (!ecore_iwarp_check_ep_ok(p_hwfn, ep))
3628*fa790ea9SDavid C Somayajulu return ECORE_INVAL;
3629*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
3630*fa790ea9SDavid C Somayajulu "EP(0x%x) IWARP_EVENT_TYPE_ASYNC_CONNECT_COMPLETE fw_ret_code=%d\n",
3631*fa790ea9SDavid C Somayajulu ep->tcp_cid, fw_return_code);
3632*fa790ea9SDavid C Somayajulu ecore_iwarp_connect_complete(p_hwfn, ep, fw_return_code);
3633*fa790ea9SDavid C Somayajulu break;
3634*fa790ea9SDavid C Somayajulu case IWARP_EVENT_TYPE_ASYNC_EXCEPTION_DETECTED:
3635*fa790ea9SDavid C Somayajulu if (!ecore_iwarp_check_ep_ok(p_hwfn, ep))
3636*fa790ea9SDavid C Somayajulu return ECORE_INVAL;
3637*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
3638*fa790ea9SDavid C Somayajulu "QP(0x%x) IWARP_EVENT_TYPE_ASYNC_EXCEPTION_DETECTED fw_ret_code=%d\n",
3639*fa790ea9SDavid C Somayajulu ep->cid, fw_return_code);
3640*fa790ea9SDavid C Somayajulu ecore_iwarp_exception_received(p_hwfn, ep, fw_return_code);
3641*fa790ea9SDavid C Somayajulu break;
3642*fa790ea9SDavid C Somayajulu /* Async completion for Close Connection ramrod */
3643*fa790ea9SDavid C Somayajulu case IWARP_EVENT_TYPE_ASYNC_QP_IN_ERROR_STATE:
3644*fa790ea9SDavid C Somayajulu if (!ecore_iwarp_check_ep_ok(p_hwfn, ep))
3645*fa790ea9SDavid C Somayajulu return ECORE_INVAL;
3646*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
3647*fa790ea9SDavid C Somayajulu "QP(0x%x) IWARP_EVENT_TYPE_ASYNC_QP_IN_ERROR_STATE fw_ret_code=%d\n",
3648*fa790ea9SDavid C Somayajulu ep->cid, fw_return_code);
3649*fa790ea9SDavid C Somayajulu ecore_iwarp_qp_in_error(p_hwfn, ep, fw_return_code);
3650*fa790ea9SDavid C Somayajulu break;
3651*fa790ea9SDavid C Somayajulu /* Async event for active side only */
3652*fa790ea9SDavid C Somayajulu case IWARP_EVENT_TYPE_ASYNC_ENHANCED_MPA_REPLY_ARRIVED:
3653*fa790ea9SDavid C Somayajulu if (!ecore_iwarp_check_ep_ok(p_hwfn, ep))
3654*fa790ea9SDavid C Somayajulu return ECORE_INVAL;
3655*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
3656*fa790ea9SDavid C Somayajulu "QP(0x%x) IWARP_EVENT_TYPE_ASYNC_MPA_HANDSHAKE_MPA_REPLY_ARRIVED fw_ret_code=%d\n",
3657*fa790ea9SDavid C Somayajulu ep->cid, fw_return_code);
3658*fa790ea9SDavid C Somayajulu ecore_iwarp_mpa_reply_arrived(p_hwfn, ep);
3659*fa790ea9SDavid C Somayajulu break;
3660*fa790ea9SDavid C Somayajulu /* MPA Negotiations completed */
3661*fa790ea9SDavid C Somayajulu case IWARP_EVENT_TYPE_ASYNC_MPA_HANDSHAKE_COMPLETE:
3662*fa790ea9SDavid C Somayajulu if (!ecore_iwarp_check_ep_ok(p_hwfn, ep))
3663*fa790ea9SDavid C Somayajulu return ECORE_INVAL;
3664*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
3665*fa790ea9SDavid C Somayajulu "QP(0x%x) IWARP_EVENT_TYPE_ASYNC_MPA_HANDSHAKE_COMPLETE fw_ret_code=%d\n",
3666*fa790ea9SDavid C Somayajulu ep->cid, fw_return_code);
3667*fa790ea9SDavid C Somayajulu ecore_iwarp_mpa_complete(p_hwfn, ep, fw_return_code);
3668*fa790ea9SDavid C Somayajulu break;
3669*fa790ea9SDavid C Somayajulu case IWARP_EVENT_TYPE_ASYNC_CID_CLEANED:
3670*fa790ea9SDavid C Somayajulu cid = (u16)OSAL_LE32_TO_CPU(fw_handle->lo);
3671*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
3672*fa790ea9SDavid C Somayajulu "(0x%x)IWARP_EVENT_TYPE_ASYNC_CID_CLEANED\n",
3673*fa790ea9SDavid C Somayajulu cid);
3674*fa790ea9SDavid C Somayajulu ecore_iwarp_cid_cleaned(p_hwfn, cid);
3675*fa790ea9SDavid C Somayajulu
3676*fa790ea9SDavid C Somayajulu break;
3677*fa790ea9SDavid C Somayajulu case IWARP_EVENT_TYPE_ASYNC_CQ_OVERFLOW:
3678*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false,
3679*fa790ea9SDavid C Somayajulu "IWARP_EVENT_TYPE_ASYNC_CQ_OVERFLOW\n");
3680*fa790ea9SDavid C Somayajulu
3681*fa790ea9SDavid C Somayajulu p_hwfn->p_rdma_info->events.affiliated_event(
3682*fa790ea9SDavid C Somayajulu p_hwfn->p_rdma_info->events.context,
3683*fa790ea9SDavid C Somayajulu ECORE_IWARP_EVENT_CQ_OVERFLOW,
3684*fa790ea9SDavid C Somayajulu (void *)fw_handle);
3685*fa790ea9SDavid C Somayajulu break;
3686*fa790ea9SDavid C Somayajulu default:
3687*fa790ea9SDavid C Somayajulu DP_ERR(p_hwfn, "Received unexpected async iwarp event %d\n",
3688*fa790ea9SDavid C Somayajulu fw_event_code);
3689*fa790ea9SDavid C Somayajulu return ECORE_INVAL;
3690*fa790ea9SDavid C Somayajulu }
3691*fa790ea9SDavid C Somayajulu return ECORE_SUCCESS;
3692*fa790ea9SDavid C Somayajulu }
3693*fa790ea9SDavid C Somayajulu
3694*fa790ea9SDavid C Somayajulu enum _ecore_status_t
ecore_iwarp_create_listen(void * rdma_cxt,struct ecore_iwarp_listen_in * iparams,struct ecore_iwarp_listen_out * oparams)3695*fa790ea9SDavid C Somayajulu ecore_iwarp_create_listen(void *rdma_cxt,
3696*fa790ea9SDavid C Somayajulu struct ecore_iwarp_listen_in *iparams,
3697*fa790ea9SDavid C Somayajulu struct ecore_iwarp_listen_out *oparams)
3698*fa790ea9SDavid C Somayajulu {
3699*fa790ea9SDavid C Somayajulu struct ecore_hwfn *p_hwfn = (struct ecore_hwfn *)rdma_cxt;
3700*fa790ea9SDavid C Somayajulu struct ecore_iwarp_listener *listener;
3701*fa790ea9SDavid C Somayajulu
3702*fa790ea9SDavid C Somayajulu listener = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL, sizeof(*listener));
3703*fa790ea9SDavid C Somayajulu
3704*fa790ea9SDavid C Somayajulu if (!listener) {
3705*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn,
3706*fa790ea9SDavid C Somayajulu false,
3707*fa790ea9SDavid C Somayajulu "ecore iwarp create listener failed: cannot allocate memory (listener). rc = %d\n",
3708*fa790ea9SDavid C Somayajulu ECORE_NOMEM);
3709*fa790ea9SDavid C Somayajulu return ECORE_NOMEM;
3710*fa790ea9SDavid C Somayajulu }
3711*fa790ea9SDavid C Somayajulu listener->ip_version = iparams->ip_version;
3712*fa790ea9SDavid C Somayajulu OSAL_MEMCPY(listener->ip_addr,
3713*fa790ea9SDavid C Somayajulu iparams->ip_addr,
3714*fa790ea9SDavid C Somayajulu sizeof(listener->ip_addr));
3715*fa790ea9SDavid C Somayajulu listener->port = iparams->port;
3716*fa790ea9SDavid C Somayajulu listener->vlan = iparams->vlan;
3717*fa790ea9SDavid C Somayajulu
3718*fa790ea9SDavid C Somayajulu listener->event_cb = iparams->event_cb;
3719*fa790ea9SDavid C Somayajulu listener->cb_context = iparams->cb_context;
3720*fa790ea9SDavid C Somayajulu listener->max_backlog = iparams->max_backlog;
3721*fa790ea9SDavid C Somayajulu listener->state = ECORE_IWARP_LISTENER_STATE_ACTIVE;
3722*fa790ea9SDavid C Somayajulu oparams->handle = listener;
3723*fa790ea9SDavid C Somayajulu
3724*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK_INIT(&listener->lock);
3725*fa790ea9SDavid C Somayajulu OSAL_LIST_INIT(&listener->ep_list);
3726*fa790ea9SDavid C Somayajulu OSAL_SPIN_LOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
3727*fa790ea9SDavid C Somayajulu OSAL_LIST_PUSH_TAIL(&listener->list_entry,
3728*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->iwarp.listen_list);
3729*fa790ea9SDavid C Somayajulu OSAL_SPIN_UNLOCK(&p_hwfn->p_rdma_info->iwarp.iw_lock);
3730*fa790ea9SDavid C Somayajulu
3731*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "callback=%p handle=%p ip=%x:%x:%x:%x port=0x%x vlan=0x%x\n",
3732*fa790ea9SDavid C Somayajulu listener->event_cb,
3733*fa790ea9SDavid C Somayajulu listener,
3734*fa790ea9SDavid C Somayajulu listener->ip_addr[0],
3735*fa790ea9SDavid C Somayajulu listener->ip_addr[1],
3736*fa790ea9SDavid C Somayajulu listener->ip_addr[2],
3737*fa790ea9SDavid C Somayajulu listener->ip_addr[3],
3738*fa790ea9SDavid C Somayajulu listener->port,
3739*fa790ea9SDavid C Somayajulu listener->vlan);
3740*fa790ea9SDavid C Somayajulu
3741*fa790ea9SDavid C Somayajulu return ECORE_SUCCESS;
3742*fa790ea9SDavid C Somayajulu }
3743*fa790ea9SDavid C Somayajulu
3744*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_pause_complete(struct ecore_iwarp_listener * listener)3745*fa790ea9SDavid C Somayajulu ecore_iwarp_pause_complete(struct ecore_iwarp_listener *listener)
3746*fa790ea9SDavid C Somayajulu {
3747*fa790ea9SDavid C Somayajulu struct ecore_iwarp_cm_event_params params;
3748*fa790ea9SDavid C Somayajulu
3749*fa790ea9SDavid C Somayajulu if (listener->state == ECORE_IWARP_LISTENER_STATE_UNPAUSE)
3750*fa790ea9SDavid C Somayajulu listener->state = ECORE_IWARP_LISTENER_STATE_ACTIVE;
3751*fa790ea9SDavid C Somayajulu
3752*fa790ea9SDavid C Somayajulu params.event = ECORE_IWARP_EVENT_LISTEN_PAUSE_COMP;
3753*fa790ea9SDavid C Somayajulu listener->event_cb(listener->cb_context, ¶ms);
3754*fa790ea9SDavid C Somayajulu }
3755*fa790ea9SDavid C Somayajulu
3756*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_tcp_abort_comp(struct ecore_hwfn * p_hwfn,void * cookie,union event_ring_data OSAL_UNUSED * data,u8 OSAL_UNUSED fw_return_code)3757*fa790ea9SDavid C Somayajulu ecore_iwarp_tcp_abort_comp(struct ecore_hwfn *p_hwfn, void *cookie,
3758*fa790ea9SDavid C Somayajulu union event_ring_data OSAL_UNUSED *data,
3759*fa790ea9SDavid C Somayajulu u8 OSAL_UNUSED fw_return_code)
3760*fa790ea9SDavid C Somayajulu {
3761*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep = (struct ecore_iwarp_ep *)cookie;
3762*fa790ea9SDavid C Somayajulu struct ecore_iwarp_listener *listener = ep->listener;
3763*fa790ea9SDavid C Somayajulu
3764*fa790ea9SDavid C Somayajulu ecore_iwarp_return_ep(p_hwfn, ep);
3765*fa790ea9SDavid C Somayajulu
3766*fa790ea9SDavid C Somayajulu if (OSAL_LIST_IS_EMPTY(&listener->ep_list))
3767*fa790ea9SDavid C Somayajulu listener->done = true;
3768*fa790ea9SDavid C Somayajulu }
3769*fa790ea9SDavid C Somayajulu
3770*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_abort_inflight_connections(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_listener * listener)3771*fa790ea9SDavid C Somayajulu ecore_iwarp_abort_inflight_connections(struct ecore_hwfn *p_hwfn,
3772*fa790ea9SDavid C Somayajulu struct ecore_iwarp_listener *listener)
3773*fa790ea9SDavid C Somayajulu {
3774*fa790ea9SDavid C Somayajulu struct ecore_spq_entry *p_ent = OSAL_NULL;
3775*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep = OSAL_NULL;
3776*fa790ea9SDavid C Somayajulu struct ecore_sp_init_data init_data;
3777*fa790ea9SDavid C Somayajulu struct ecore_spq_comp_cb comp_data;
3778*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
3779*fa790ea9SDavid C Somayajulu
3780*fa790ea9SDavid C Somayajulu /* remove listener from list before destroying listener */
3781*fa790ea9SDavid C Somayajulu OSAL_LIST_REMOVE_ENTRY(&listener->list_entry,
3782*fa790ea9SDavid C Somayajulu &p_hwfn->p_rdma_info->iwarp.listen_list);
3783*fa790ea9SDavid C Somayajulu if (OSAL_LIST_IS_EMPTY(&listener->ep_list)) {
3784*fa790ea9SDavid C Somayajulu listener->done = true;
3785*fa790ea9SDavid C Somayajulu return;
3786*fa790ea9SDavid C Somayajulu }
3787*fa790ea9SDavid C Somayajulu OSAL_MEMSET(&init_data, 0, sizeof(init_data));
3788*fa790ea9SDavid C Somayajulu init_data.p_comp_data = &comp_data;
3789*fa790ea9SDavid C Somayajulu init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
3790*fa790ea9SDavid C Somayajulu init_data.comp_mode = ECORE_SPQ_MODE_CB;
3791*fa790ea9SDavid C Somayajulu init_data.p_comp_data->function = ecore_iwarp_tcp_abort_comp;
3792*fa790ea9SDavid C Somayajulu
3793*fa790ea9SDavid C Somayajulu OSAL_LIST_FOR_EACH_ENTRY(ep, &listener->ep_list,
3794*fa790ea9SDavid C Somayajulu list_entry, struct ecore_iwarp_ep) {
3795*fa790ea9SDavid C Somayajulu ep->state = ECORE_IWARP_EP_ABORTING;
3796*fa790ea9SDavid C Somayajulu init_data.p_comp_data->cookie = ep;
3797*fa790ea9SDavid C Somayajulu init_data.cid = ep->tcp_cid;
3798*fa790ea9SDavid C Somayajulu rc = ecore_sp_init_request(p_hwfn, &p_ent,
3799*fa790ea9SDavid C Somayajulu IWARP_RAMROD_CMD_ID_ABORT_TCP_OFFLOAD,
3800*fa790ea9SDavid C Somayajulu PROTOCOLID_IWARP,
3801*fa790ea9SDavid C Somayajulu &init_data);
3802*fa790ea9SDavid C Somayajulu if (rc == ECORE_SUCCESS)
3803*fa790ea9SDavid C Somayajulu ecore_spq_post(p_hwfn, p_ent, OSAL_NULL);
3804*fa790ea9SDavid C Somayajulu }
3805*fa790ea9SDavid C Somayajulu }
3806*fa790ea9SDavid C Somayajulu
3807*fa790ea9SDavid C Somayajulu static void
ecore_iwarp_listener_state_transition(struct ecore_hwfn * p_hwfn,void * cookie,union event_ring_data OSAL_UNUSED * data,u8 OSAL_UNUSED fw_return_code)3808*fa790ea9SDavid C Somayajulu ecore_iwarp_listener_state_transition(struct ecore_hwfn *p_hwfn, void *cookie,
3809*fa790ea9SDavid C Somayajulu union event_ring_data OSAL_UNUSED *data,
3810*fa790ea9SDavid C Somayajulu u8 OSAL_UNUSED fw_return_code)
3811*fa790ea9SDavid C Somayajulu {
3812*fa790ea9SDavid C Somayajulu struct ecore_iwarp_listener *listener = (struct ecore_iwarp_listener *)cookie;
3813*fa790ea9SDavid C Somayajulu
3814*fa790ea9SDavid C Somayajulu switch (listener->state) {
3815*fa790ea9SDavid C Somayajulu case ECORE_IWARP_LISTENER_STATE_PAUSE:
3816*fa790ea9SDavid C Somayajulu case ECORE_IWARP_LISTENER_STATE_UNPAUSE:
3817*fa790ea9SDavid C Somayajulu ecore_iwarp_pause_complete(listener);
3818*fa790ea9SDavid C Somayajulu break;
3819*fa790ea9SDavid C Somayajulu case ECORE_IWARP_LISTENER_STATE_DESTROYING:
3820*fa790ea9SDavid C Somayajulu ecore_iwarp_abort_inflight_connections(p_hwfn, listener);
3821*fa790ea9SDavid C Somayajulu break;
3822*fa790ea9SDavid C Somayajulu default:
3823*fa790ea9SDavid C Somayajulu break;
3824*fa790ea9SDavid C Somayajulu }
3825*fa790ea9SDavid C Somayajulu }
3826*fa790ea9SDavid C Somayajulu
3827*fa790ea9SDavid C Somayajulu static enum _ecore_status_t
ecore_iwarp_empty_ramrod(struct ecore_hwfn * p_hwfn,struct ecore_iwarp_listener * listener)3828*fa790ea9SDavid C Somayajulu ecore_iwarp_empty_ramrod(struct ecore_hwfn *p_hwfn,
3829*fa790ea9SDavid C Somayajulu struct ecore_iwarp_listener *listener)
3830*fa790ea9SDavid C Somayajulu {
3831*fa790ea9SDavid C Somayajulu struct ecore_spq_entry *p_ent = OSAL_NULL;
3832*fa790ea9SDavid C Somayajulu struct ecore_spq_comp_cb comp_data;
3833*fa790ea9SDavid C Somayajulu struct ecore_sp_init_data init_data;
3834*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
3835*fa790ea9SDavid C Somayajulu
3836*fa790ea9SDavid C Somayajulu OSAL_MEMSET(&init_data, 0, sizeof(init_data));
3837*fa790ea9SDavid C Somayajulu init_data.p_comp_data = &comp_data;
3838*fa790ea9SDavid C Somayajulu init_data.cid = ecore_spq_get_cid(p_hwfn);
3839*fa790ea9SDavid C Somayajulu init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
3840*fa790ea9SDavid C Somayajulu init_data.comp_mode = ECORE_SPQ_MODE_CB;
3841*fa790ea9SDavid C Somayajulu init_data.p_comp_data->function = ecore_iwarp_listener_state_transition;
3842*fa790ea9SDavid C Somayajulu init_data.p_comp_data->cookie = listener;
3843*fa790ea9SDavid C Somayajulu rc = ecore_sp_init_request(p_hwfn, &p_ent,
3844*fa790ea9SDavid C Somayajulu COMMON_RAMROD_EMPTY,
3845*fa790ea9SDavid C Somayajulu PROTOCOLID_COMMON,
3846*fa790ea9SDavid C Somayajulu &init_data);
3847*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
3848*fa790ea9SDavid C Somayajulu return rc;
3849*fa790ea9SDavid C Somayajulu
3850*fa790ea9SDavid C Somayajulu rc = ecore_spq_post(p_hwfn, p_ent, OSAL_NULL);
3851*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
3852*fa790ea9SDavid C Somayajulu return rc;
3853*fa790ea9SDavid C Somayajulu
3854*fa790ea9SDavid C Somayajulu return rc;
3855*fa790ea9SDavid C Somayajulu }
3856*fa790ea9SDavid C Somayajulu
3857*fa790ea9SDavid C Somayajulu enum _ecore_status_t
ecore_iwarp_pause_listen(void * rdma_cxt,void * handle,bool pause,bool comp)3858*fa790ea9SDavid C Somayajulu ecore_iwarp_pause_listen(void *rdma_cxt, void *handle,
3859*fa790ea9SDavid C Somayajulu bool pause, bool comp)
3860*fa790ea9SDavid C Somayajulu {
3861*fa790ea9SDavid C Somayajulu struct ecore_hwfn *p_hwfn = (struct ecore_hwfn *)rdma_cxt;
3862*fa790ea9SDavid C Somayajulu struct ecore_iwarp_listener *listener =
3863*fa790ea9SDavid C Somayajulu (struct ecore_iwarp_listener *)handle;
3864*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
3865*fa790ea9SDavid C Somayajulu
3866*fa790ea9SDavid C Somayajulu listener->state = pause ?
3867*fa790ea9SDavid C Somayajulu ECORE_IWARP_LISTENER_STATE_PAUSE :
3868*fa790ea9SDavid C Somayajulu ECORE_IWARP_LISTENER_STATE_UNPAUSE;
3869*fa790ea9SDavid C Somayajulu if (!comp)
3870*fa790ea9SDavid C Somayajulu return ECORE_SUCCESS;
3871*fa790ea9SDavid C Somayajulu
3872*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_empty_ramrod(p_hwfn, listener);
3873*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
3874*fa790ea9SDavid C Somayajulu return rc;
3875*fa790ea9SDavid C Somayajulu
3876*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "listener=%p, state=%d\n",
3877*fa790ea9SDavid C Somayajulu listener, listener->state);
3878*fa790ea9SDavid C Somayajulu
3879*fa790ea9SDavid C Somayajulu return ECORE_PENDING;
3880*fa790ea9SDavid C Somayajulu }
3881*fa790ea9SDavid C Somayajulu
3882*fa790ea9SDavid C Somayajulu enum _ecore_status_t
ecore_iwarp_destroy_listen(void * rdma_cxt,void * handle)3883*fa790ea9SDavid C Somayajulu ecore_iwarp_destroy_listen(void *rdma_cxt, void *handle)
3884*fa790ea9SDavid C Somayajulu {
3885*fa790ea9SDavid C Somayajulu struct ecore_hwfn *p_hwfn = (struct ecore_hwfn *)rdma_cxt;
3886*fa790ea9SDavid C Somayajulu struct ecore_iwarp_listener *listener =
3887*fa790ea9SDavid C Somayajulu (struct ecore_iwarp_listener *)handle;
3888*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
3889*fa790ea9SDavid C Somayajulu int wait_count = 0;
3890*fa790ea9SDavid C Somayajulu
3891*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "handle=%p\n", handle);
3892*fa790ea9SDavid C Somayajulu
3893*fa790ea9SDavid C Somayajulu listener->state = ECORE_IWARP_LISTENER_STATE_DESTROYING;
3894*fa790ea9SDavid C Somayajulu rc = ecore_iwarp_empty_ramrod(p_hwfn, listener);
3895*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
3896*fa790ea9SDavid C Somayajulu return rc;
3897*fa790ea9SDavid C Somayajulu
3898*fa790ea9SDavid C Somayajulu while (!listener->done) {
3899*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA,
3900*fa790ea9SDavid C Somayajulu "Waiting for ep list to be empty...\n");
3901*fa790ea9SDavid C Somayajulu OSAL_MSLEEP(100);
3902*fa790ea9SDavid C Somayajulu if (wait_count++ > 200) {
3903*fa790ea9SDavid C Somayajulu DP_NOTICE(p_hwfn, false, "ep list close timeout\n");
3904*fa790ea9SDavid C Somayajulu break;
3905*fa790ea9SDavid C Somayajulu }
3906*fa790ea9SDavid C Somayajulu }
3907*fa790ea9SDavid C Somayajulu
3908*fa790ea9SDavid C Somayajulu OSAL_FREE(p_hwfn->p_dev, listener);
3909*fa790ea9SDavid C Somayajulu
3910*fa790ea9SDavid C Somayajulu return ECORE_SUCCESS;
3911*fa790ea9SDavid C Somayajulu }
3912*fa790ea9SDavid C Somayajulu
3913*fa790ea9SDavid C Somayajulu enum _ecore_status_t
ecore_iwarp_send_rtr(void * rdma_cxt,struct ecore_iwarp_send_rtr_in * iparams)3914*fa790ea9SDavid C Somayajulu ecore_iwarp_send_rtr(void *rdma_cxt, struct ecore_iwarp_send_rtr_in *iparams)
3915*fa790ea9SDavid C Somayajulu {
3916*fa790ea9SDavid C Somayajulu struct ecore_hwfn *p_hwfn = (struct ecore_hwfn *)rdma_cxt;
3917*fa790ea9SDavid C Somayajulu struct ecore_sp_init_data init_data;
3918*fa790ea9SDavid C Somayajulu struct ecore_spq_entry *p_ent;
3919*fa790ea9SDavid C Somayajulu struct ecore_rdma_qp *qp;
3920*fa790ea9SDavid C Somayajulu struct ecore_iwarp_ep *ep;
3921*fa790ea9SDavid C Somayajulu enum _ecore_status_t rc;
3922*fa790ea9SDavid C Somayajulu
3923*fa790ea9SDavid C Somayajulu ep = (struct ecore_iwarp_ep *)iparams->ep_context;
3924*fa790ea9SDavid C Somayajulu if (!ep) {
3925*fa790ea9SDavid C Somayajulu DP_ERR(p_hwfn, "Ep Context receive in send_rtr is NULL\n");
3926*fa790ea9SDavid C Somayajulu return ECORE_INVAL;
3927*fa790ea9SDavid C Somayajulu }
3928*fa790ea9SDavid C Somayajulu
3929*fa790ea9SDavid C Somayajulu qp = ep->qp;
3930*fa790ea9SDavid C Somayajulu
3931*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "QP(0x%x) EP(0x%x)\n",
3932*fa790ea9SDavid C Somayajulu qp->icid, ep->tcp_cid);
3933*fa790ea9SDavid C Somayajulu
3934*fa790ea9SDavid C Somayajulu OSAL_MEMSET(&init_data, 0, sizeof(init_data));
3935*fa790ea9SDavid C Somayajulu init_data.cid = qp->icid;
3936*fa790ea9SDavid C Somayajulu init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
3937*fa790ea9SDavid C Somayajulu init_data.comp_mode = ECORE_SPQ_MODE_CB;
3938*fa790ea9SDavid C Somayajulu
3939*fa790ea9SDavid C Somayajulu rc = ecore_sp_init_request(p_hwfn, &p_ent,
3940*fa790ea9SDavid C Somayajulu IWARP_RAMROD_CMD_ID_MPA_OFFLOAD_SEND_RTR,
3941*fa790ea9SDavid C Somayajulu PROTOCOLID_IWARP, &init_data);
3942*fa790ea9SDavid C Somayajulu
3943*fa790ea9SDavid C Somayajulu if (rc != ECORE_SUCCESS)
3944*fa790ea9SDavid C Somayajulu return rc;
3945*fa790ea9SDavid C Somayajulu
3946*fa790ea9SDavid C Somayajulu rc = ecore_spq_post(p_hwfn, p_ent, OSAL_NULL);
3947*fa790ea9SDavid C Somayajulu
3948*fa790ea9SDavid C Somayajulu DP_VERBOSE(p_hwfn, ECORE_MSG_RDMA, "ecore_iwarp_send_rtr, rc = 0x%x\n",
3949*fa790ea9SDavid C Somayajulu rc);
3950*fa790ea9SDavid C Somayajulu
3951*fa790ea9SDavid C Somayajulu return rc;
3952*fa790ea9SDavid C Somayajulu }
3953*fa790ea9SDavid C Somayajulu
3954*fa790ea9SDavid C Somayajulu enum _ecore_status_t
ecore_iwarp_query_qp(struct ecore_rdma_qp * qp,struct ecore_rdma_query_qp_out_params * out_params)3955*fa790ea9SDavid C Somayajulu ecore_iwarp_query_qp(struct ecore_rdma_qp *qp,
3956*fa790ea9SDavid C Somayajulu struct ecore_rdma_query_qp_out_params *out_params)
3957*fa790ea9SDavid C Somayajulu {
3958*fa790ea9SDavid C Somayajulu out_params->state = ecore_iwarp2roce_state(qp->iwarp_state);
3959*fa790ea9SDavid C Somayajulu return ECORE_SUCCESS;
3960*fa790ea9SDavid C Somayajulu }
3961*fa790ea9SDavid C Somayajulu
3962*fa790ea9SDavid C Somayajulu #ifdef _NTDDK_
3963*fa790ea9SDavid C Somayajulu #pragma warning(pop)
3964*fa790ea9SDavid C Somayajulu #endif
3965