1 
2 #include "lm5710.h"
3 #include "lm.h"
4 #include "lm_l4sp.h"
5 #include "command.h"
6 #include "context.h"
7 #include "bd_chain.h"
8 #include "mm.h"
9 #include "mm_l4if.h"
10 #include "lm_l4fp.h"
11 #include "lm_l4sp.h"
12 #include "everest_l5cm_constants.h"
13 #include "l4debug.h"
14 
15 /* Sizes of objects that need to be allocated in physical memory */
16 #define TOE_SP_PHYS_DATA_SIZE ((sizeof(lm_tcp_slow_path_phys_data_t) + CACHE_LINE_SIZE_MASK) & ~CACHE_LINE_SIZE_MASK)
17 #define TOE_DB_RX_DATA_SIZE   ((sizeof(struct toe_rx_db_data) + CACHE_LINE_SIZE_MASK) & ~CACHE_LINE_SIZE_MASK)
18 #define TOE_DB_TX_DATA_SIZE   ((sizeof(struct toe_tx_db_data) + CACHE_LINE_SIZE_MASK) & ~CACHE_LINE_SIZE_MASK)
19 
20 #define TCP_XCM_DEFAULT_DEL_ACK_MAX_CNT 2
21 
22 l4_tcp_con_state_t lm_tcp_calc_state (
23     lm_device_t    * pdev,
24     lm_tcp_state_t * tcp,
25     u8_t             fin_was_sent
26     );
27 
28 /** Description Callback function for spe being completed
29  *  internally in vbd driver (not via FW)
30  */
31 void lm_tcp_comp_cb(
32     struct _lm_device_t *pdev,
33     struct sq_pending_command *pending);
34 
35 
36 /* GilR 11/13/2006 - TODO - ttl is temporarily overloaded for ethearel capture L4/L2 debugging */
37 #define TOE_DBG_TTL 200
38 #define ISCSI_DBG_TTL 222
39 
40 #define TIMERS_TICKS_PER_SEC        (u32_t)(1000)//(1 / TIMERS_TICK_SIZE_CHIP)
41 #define TSEMI_CLK1_TICKS_PER_SEC    (u32_t)(1000)//(1 / TSEMI_CLK1_RESUL_CHIP)
42 
lm_get_num_of_cashed_grq_bds(struct _lm_device_t * pdev)43 u32_t lm_get_num_of_cashed_grq_bds(struct _lm_device_t *pdev)
44 {
45     return USTORM_TOE_GRQ_CACHE_NUM_BDS;
46 }
47 
48 // this function is used only to verify that the defines above are correct (on compile time - save the runtime checkings...)
_fake_func_verify_defines(void)49 static void _fake_func_verify_defines(void)
50 {
51     ASSERT_STATIC( TIMERS_TICKS_PER_SEC     == (1 / TIMERS_TICK_SIZE_CHIP) ) ;
52     ASSERT_STATIC( TSEMI_CLK1_TICKS_PER_SEC == (1 / TSEMI_CLK1_RESUL_CHIP) ) ;
53 }
54 
lm_time_resolution(lm_device_t * pdev,u32_t src_time,u32_t src_ticks_per_sec,u32_t trg_ticks_per_sec)55 static __inline u32_t lm_time_resolution(
56     lm_device_t *pdev,
57     u32_t src_time,
58     u32_t src_ticks_per_sec,
59     u32_t trg_ticks_per_sec)
60 {
61     u64_t result;
62     u64_t tmp_result;
63     u32_t dev_factor;
64 
65     DbgBreakIf(!(src_ticks_per_sec && trg_ticks_per_sec));
66 
67     if (trg_ticks_per_sec > src_ticks_per_sec){
68         dev_factor =  trg_ticks_per_sec / src_ticks_per_sec;
69         result = src_time * dev_factor;
70     } else {
71         tmp_result = src_time * trg_ticks_per_sec;
72 
73 #if defined(_VBD_)
74         result = CEIL_DIV(tmp_result, src_ticks_per_sec);
75 #else
76         /* Here we try a avoid 64-bit division operation */
77         if (tmp_result < 0xffffffff) {
78             result = (u32_t)tmp_result / src_ticks_per_sec;
79         } else {
80             /* src_ticks_per_sec and trg_ticks_per_sec parameters come
81                from NDIS and so far the values observed were 100 or 1000,
82                depending on Windows version. These parameters define
83                TCP timers resolution and are unlikely to change significantly
84                in the future.
85                So, here we assume that if (src_time * trg_ticks_per_sec) product
86                is out of 32-bit range it is because src_time value.
87             */
88             DbgBreakIf(src_time < src_ticks_per_sec);
89             result = ((u64_t)(src_time / src_ticks_per_sec)) * trg_ticks_per_sec;
90         }
91 #endif
92     }
93 
94     if(src_time && !result) {
95         result = 1;
96     }
97     DbgMessage(pdev, VERBOSEl4sp,
98                 "lm_time_resulition: src_time=%d, src_ticks_per_sec=%d, trg_ticks_per_sec=%d, result=%d\n",
99                 src_time, src_ticks_per_sec, trg_ticks_per_sec, result);
100 
101     DbgBreakIf(result > 0xffffffff);
102     return (u32_t)result;
103 }
104 
lm_tcp_erase_connection(IN struct _lm_device_t * pdev,IN lm_tcp_state_t * tcp)105 lm_status_t lm_tcp_erase_connection(
106     IN    struct _lm_device_t   * pdev,
107     IN    lm_tcp_state_t        * tcp)
108 {
109     lm_status_t status = LM_STATUS_SUCCESS;
110     lm_tcp_con_t *rx_con;
111     lm_tcp_con_t *tx_con;
112     MM_INIT_TCP_LOCK_HANDLE();
113     if (!lm_fl_reset_is_inprogress(pdev)) {
114         return LM_STATUS_FAILURE;
115     }
116 
117     DbgMessage(pdev, FATAL, "##lm_tcp_erase_connection(0x%x)\n",tcp->cid);
118     if (tcp->ulp_type == TOE_CONNECTION_TYPE) {
119         rx_con = tcp->rx_con;
120         tx_con = tcp->tx_con;
121         mm_acquire_tcp_lock(pdev, tx_con);
122         tx_con->flags |= TCP_POST_BLOCKED;
123         lm_tcp_abort_bufs(pdev, tcp, tx_con, LM_STATUS_CONNECTION_CLOSED);
124         if (tx_con->abortion_under_flr) {
125             DbgMessage(pdev, FATAL, "##lm_tcp_erase_connection(0x%x): Tx aborted\n",tcp->cid);
126         }
127         mm_release_tcp_lock(pdev, tx_con);
128 
129         /* Rx abortive part... */
130 
131         mm_acquire_tcp_lock(pdev, rx_con);
132         /* Abort pending buffers */
133         rx_con->flags |= TCP_POST_BLOCKED;
134         if (mm_tcp_indicating_bufs(rx_con)) {
135             DbgMessage(pdev, FATAL, "##lm_tcp_erase_connection(0x%x): under indication\n",tcp->cid);
136             DbgBreak();
137             mm_release_tcp_lock(pdev, rx_con);
138             return LM_STATUS_FAILURE;
139         }
140         lm_tcp_abort_bufs(pdev, tcp, rx_con, LM_STATUS_CONNECTION_CLOSED);
141         if (rx_con->abortion_under_flr) {
142             DbgMessage(pdev, FATAL, "##lm_tcp_erase_connection(0x%x): Rx aborted\n",tcp->cid);
143         }
144 
145         mm_release_tcp_lock(pdev, rx_con);
146     }
147     mm_tcp_del_tcp_state(pdev,tcp);
148     return status;
149 }
150 
lm_tcp_flush_db(struct _lm_device_t * pdev,lm_tcp_state_t * tcp)151 void lm_tcp_flush_db(
152     struct _lm_device_t * pdev,
153     lm_tcp_state_t *tcp)
154 {
155     struct toe_tx_doorbell  dq_flush_msg;
156     lm_tcp_con_t *rx_con, *tx_con;
157     MM_INIT_TCP_LOCK_HANDLE();
158 
159     DbgBreakIf(!(pdev && tcp));
160 
161     if (tcp->ulp_type != TOE_CONNECTION_TYPE) {
162         DbgMessage(pdev, WARNl4sp, "##lm_tcp_flush_db is not sent for connection(0x%x) of type %d\n",tcp->cid, tcp->ulp_type);
163         return;
164     }
165 
166     DbgMessage(pdev, INFORMl4sp, "##lm_tcp_flush_db (cid=0x%x)\n",tcp->cid);
167     rx_con = tcp->rx_con;
168     tx_con = tcp->tx_con;
169 
170     dq_flush_msg.hdr.data = (TOE_CONNECTION_TYPE << DOORBELL_HDR_T_CONN_TYPE_SHIFT);
171     dq_flush_msg.params = TOE_TX_DOORBELL_FLUSH;
172     dq_flush_msg.nbytes = 0;
173 
174 
175     mm_acquire_tcp_lock(pdev, tx_con);
176     tx_con->flags |= TCP_DB_BLOCKED;
177     mm_release_tcp_lock(pdev, tx_con);
178 
179     mm_acquire_tcp_lock(pdev, rx_con);
180     rx_con->flags |= TCP_DB_BLOCKED;
181     mm_release_tcp_lock(pdev, rx_con);
182 
183     DOORBELL(pdev, tcp->cid, *((u32_t *)&dq_flush_msg));
184 }
185 
186 /* Desciption:
187  *  allocate l4 resources
188  * Assumptions:
189  *  - lm_init_params was already called
190  * Returns:
191  *  SUCCESS or any failure */
lm_tcp_alloc_resc(lm_device_t * pdev)192 static lm_status_t lm_tcp_alloc_resc(lm_device_t *pdev)
193 {
194     lm_toe_info_t *toe_info;
195     lm_bd_chain_t *bd_chain;
196     u32_t mem_size;
197     long i;
198     u8_t mm_cli_idx       = 0;
199 
200     DbgMessage(pdev, VERBOSEl4sp, "##lm_tcp_alloc_resc\n");
201 
202     // NOP, call this function only to prevent compile warning.
203     _fake_func_verify_defines();
204 
205     mm_cli_idx = LM_RESOURCE_NDIS;//!!DP mm_cli_idx_to_um_idx(LM_CLI_IDX_NDIS);
206 
207     toe_info = &pdev->toe_info;
208     LM_TOE_FOREACH_TSS_IDX(pdev, i)
209     {
210         /* allocate SCQs */
211         bd_chain = &toe_info->scqs[i].bd_chain;
212         mem_size = pdev->params.l4_scq_page_cnt * LM_PAGE_SIZE;
213         bd_chain->bd_chain_virt = mm_alloc_phys_mem(pdev, mem_size, &bd_chain->bd_chain_phy, 0, mm_cli_idx);
214         if (!bd_chain->bd_chain_virt) {
215             DbgBreakIf(DBG_BREAK_ON(MEMORY_ALLOCATION_FAILURE));
216             return LM_STATUS_RESOURCE;
217         }
218         mm_memset(bd_chain->bd_chain_virt, 0, mem_size);
219     }
220 
221     LM_TOE_FOREACH_RSS_IDX(pdev, i)
222     {
223         /* allocate RCQs */
224         bd_chain = &toe_info->rcqs[i].bd_chain;
225         mem_size = pdev->params.l4_rcq_page_cnt * LM_PAGE_SIZE;
226         bd_chain->bd_chain_virt = mm_alloc_phys_mem(pdev, mem_size, &bd_chain->bd_chain_phy, 0, mm_cli_idx);
227         if (!bd_chain->bd_chain_virt) {
228             DbgBreakIf(DBG_BREAK_ON(MEMORY_ALLOCATION_FAILURE));
229             return LM_STATUS_RESOURCE;
230         }
231         mm_memset(bd_chain->bd_chain_virt, 0, mem_size);
232 
233         /* allocate GRQs */
234         bd_chain = &toe_info->grqs[i].bd_chain;
235         mem_size = pdev->params.l4_grq_page_cnt * LM_PAGE_SIZE;
236         bd_chain->bd_chain_virt = mm_alloc_phys_mem(pdev, mem_size, &bd_chain->bd_chain_phy, 0, mm_cli_idx);
237         if (!bd_chain->bd_chain_virt) {
238             DbgBreakIf(DBG_BREAK_ON(MEMORY_ALLOCATION_FAILURE));
239             return LM_STATUS_RESOURCE;
240         }
241         mm_memset(bd_chain->bd_chain_virt, 0, mem_size);
242 
243         DbgBreakIf(toe_info->grqs[i].isles_pool);
244         if (!pdev->params.l4_isles_pool_size) {
245             pdev->params.l4_isles_pool_size = 2 * T_TCP_ISLE_ARRAY_SIZE;
246         } else if (pdev->params.l4_isles_pool_size < T_TCP_ISLE_ARRAY_SIZE) {
247             pdev->params.l4_isles_pool_size = T_TCP_ISLE_ARRAY_SIZE;
248         }
249         mem_size = pdev->params.l4_isles_pool_size * sizeof(lm_isle_t);
250         toe_info->grqs[i].isles_pool = (lm_isle_t*)mm_alloc_mem(pdev, mem_size, mm_cli_idx);
251         if (!toe_info->grqs[i].isles_pool) {
252             DbgBreakIf(DBG_BREAK_ON(MEMORY_ALLOCATION_FAILURE));
253             return LM_STATUS_RESOURCE;
254         }
255         mm_memset(toe_info->grqs[i].isles_pool, 0, mem_size);
256     }
257     if (pdev->params.l4_data_integrity) {
258         u32_t pb_idx;
259         pdev->toe_info.integrity_info.pattern_size = 256;
260         pdev->toe_info.integrity_info.pattern_buf_size = 0x10000 + pdev->toe_info.integrity_info.pattern_size;
261         pdev->toe_info.integrity_info.pattern_buf = mm_alloc_mem(pdev, pdev->toe_info.integrity_info.pattern_buf_size, mm_cli_idx);
262         if (!pdev->toe_info.integrity_info.pattern_buf) {
263             DbgBreakIf(DBG_BREAK_ON(MEMORY_ALLOCATION_FAILURE));
264             return LM_STATUS_RESOURCE;
265         }
266         for (pb_idx = 0; pb_idx < pdev->toe_info.integrity_info.pattern_buf_size; pb_idx++) {
267             pdev->toe_info.integrity_info.pattern_buf[pb_idx] = pb_idx %  pdev->toe_info.integrity_info.pattern_size;
268         }
269     }
270 
271     /* Allocate rss-update physical data */
272     pdev->toe_info.rss_update_data = (struct toe_rss_update_ramrod_data *)
273                                       mm_alloc_phys_mem(pdev, sizeof(*pdev->toe_info.rss_update_data),
274                                                         &pdev->toe_info.rss_update_data_phys,
275                                                         0,0);
276 
277     if (pdev->toe_info.rss_update_data == NULL)
278     {
279         DbgBreakIf(DBG_BREAK_ON(MEMORY_ALLOCATION_FAILURE));
280         return LM_STATUS_RESOURCE;
281     }
282 
283     return LM_STATUS_SUCCESS;
284 }
285 
_lm_get_default_l4cli_params(lm_device_t * pdev,l4_ofld_params_t * l4_params)286 static void _lm_get_default_l4cli_params(lm_device_t *pdev, l4_ofld_params_t *l4_params)
287 {
288     lm_params_t *def_params = &pdev->params;
289 
290     DbgBreakIf(def_params->l4cli_ack_frequency > 0xff);
291     l4_params->ack_frequency = def_params->l4cli_ack_frequency & 0xff;
292 
293     DbgBreakIf(def_params->l4cli_delayed_ack_ticks > 0xff);
294     l4_params->delayed_ack_ticks = def_params->l4cli_delayed_ack_ticks & 0xff;
295 
296     DbgBreakIf(def_params->l4cli_doubt_reachability_retx > 0xff);
297     l4_params->doubt_reachability_retx = def_params->l4cli_doubt_reachability_retx & 0xff;
298 
299     l4_params->dup_ack_threshold = def_params->l4cli_dup_ack_threshold;
300 
301     DbgBreakIf((def_params->l4cli_flags != 0) &&
302                (def_params->l4cli_flags != OFLD_PARAM_FLAG_SNAP_ENCAP));
303     l4_params->flags = def_params->l4cli_flags;
304 
305     DbgBreakIf(def_params->l4cli_max_retx > 0xff);
306     l4_params->max_retx = def_params->l4cli_max_retx & 0xff;
307 
308     l4_params->nce_stale_ticks = def_params->l4cli_nce_stale_ticks;
309     l4_params->push_ticks = def_params->l4cli_push_ticks;
310 
311     DbgBreakIf(def_params->l4cli_starting_ip_id > 0xffff);
312     l4_params->starting_ip_id = def_params->l4cli_starting_ip_id & 0xffff;
313 
314     l4_params->sws_prevention_ticks = def_params->l4cli_sws_prevention_ticks;
315     l4_params->ticks_per_second = def_params->l4cli_ticks_per_second;
316 
317 }
318 
319 /** Description
320  *  requests generic buffers from the generic buffer pool and attaches the generic buffers
321  *  to the grq-bd chain. It attaches the amount of buffers received, no matter if they were
322  *  less than requested. Function always tries to fill bd-chain (i.e. requests bd_chain->bd_left)
323  * Assumptions:
324  *  - called after the generic buffer pool is ready to deliver generic buffers
325  *  - who ever will call this function will handle checking if a work item for allocating more
326  *    buffers is needed.
327  * Returns:
328  *  - TRUE: buffers were written
329  *  - FALSE: o/w
330  */
lm_tcp_rx_fill_grq(struct _lm_device_t * pdev,u8_t sb_idx,d_list_t * bypass_gen_pool_list,u8_t filling_mode)331 u8_t lm_tcp_rx_fill_grq(struct _lm_device_t * pdev, u8_t sb_idx, d_list_t * bypass_gen_pool_list, u8_t filling_mode)
332 {
333     lm_toe_info_t        * toe_info;
334     lm_tcp_grq_t         * grq;
335     struct toe_rx_grq_bd * grq_bd;
336     lm_tcp_gen_buf_t     * curr_gen_buf;
337     lm_bd_chain_t        * bd_chain;
338     d_list_t               tmp_gen_buf_list;
339     d_list_t               free_gen_buf_list;
340     u16_t                  num_bufs; /* limited by bd_chain->bd_left */
341     u16_t                  num_bufs_threshold;
342     u32_t                  num_bypass_buffs;
343     u32_t                  avg_dpc_cnt;
344 
345     toe_info = &pdev->toe_info;
346     grq      = &toe_info->grqs[sb_idx];
347     bd_chain = &grq->bd_chain;
348     num_bufs = bd_chain->bd_left; /* required number of bufs from grq pool */
349 
350     DbgMessage(pdev, VERBOSEl4rx, "###lm_tcp_rx_fill_grq bd_left (to be filled)= %d\n", bd_chain->bd_left);
351 
352     if (!pdev->params.l4_grq_filling_threshold_divider) {
353         num_bufs_threshold = 1;
354     } else {
355         if (pdev->params.l4_grq_filling_threshold_divider < 2) {
356             pdev->params.l4_grq_filling_threshold_divider = 2;
357         }
358         num_bufs_threshold = bd_chain->capacity / pdev->params.l4_grq_filling_threshold_divider;
359     }
360 
361     d_list_init(&tmp_gen_buf_list, NULL, NULL, 0);
362     d_list_init(&free_gen_buf_list, NULL, NULL, 0);
363     if (bypass_gen_pool_list != NULL) {
364         num_bypass_buffs = d_list_entry_cnt(bypass_gen_pool_list);
365     } else {
366         num_bypass_buffs = 0;
367     }
368 
369     if (filling_mode == FILL_GRQ_MIN_CASHED_BDS) {
370         u16_t bufs_in_chain = bd_chain->capacity - num_bufs;
371         if (bufs_in_chain >= USTORM_TOE_GRQ_CACHE_NUM_BDS) {
372             return 0;
373         } else {
374             num_bufs = USTORM_TOE_GRQ_CACHE_NUM_BDS - bufs_in_chain;
375         }
376     } else if (filling_mode == FILL_GRQ_LOW_THRESHOLD) {
377         u16_t bufs_in_chain = bd_chain->capacity - num_bufs;
378         DbgBreakIf(grq->low_bds_threshold < USTORM_TOE_GRQ_CACHE_NUM_BDS);
379         if (grq->low_bds_threshold < USTORM_TOE_GRQ_CACHE_NUM_BDS) {
380             grq->low_bds_threshold = 3*GRQ_XOFF_TH;
381         }
382         if (bufs_in_chain >= grq->low_bds_threshold) {
383             return 0;
384         } else {
385             num_bufs = grq->low_bds_threshold - bufs_in_chain;
386         }
387     } else {
388         if (grq->high_bds_threshold) {
389             u16_t bufs_in_chain = bd_chain->capacity - num_bufs;
390             if (bufs_in_chain >= grq->high_bds_threshold) {
391                 return 0;
392             } else {
393                 num_bufs = grq->high_bds_threshold - bufs_in_chain;
394             }
395         }
396         if (num_bufs < num_bufs_threshold) {
397             if (num_bufs > num_bypass_buffs) {
398                 num_bufs = (u16_t)num_bypass_buffs; /* Partly fill grq from bypass only*/
399                 grq->gen_bufs_compensated_from_bypass_only += num_bypass_buffs;
400             }
401             if (!num_bufs) {
402                 return 0; /* nothing to fill or to fill later and more
403                             to avoid abundant GEN_POOL_LOCK acquiring*/
404             }
405         }
406     }
407 
408     if (num_bypass_buffs < num_bufs) {
409         /* we can safely cast the returned value since we know we ask for max 2^16 */
410         u16_t num_required_buffs = num_bufs - num_bypass_buffs;
411         mm_tcp_get_gen_bufs(pdev, &tmp_gen_buf_list, num_required_buffs, sb_idx);
412     }
413     while ((d_list_entry_cnt(&tmp_gen_buf_list) < num_bufs) && num_bypass_buffs) {
414 		lm_tcp_gen_buf_t * tmp_buf = NULL;
415         d_list_entry_t * curr_entry = d_list_pop_head(bypass_gen_pool_list);
416 		tmp_buf = (lm_tcp_gen_buf_t *)curr_entry;
417         DbgBreakIf(!curr_entry);
418 		if (tmp_buf->flags & GEN_FLAG_FREE_WHEN_DONE)
419 		{
420 			d_list_push_head(&free_gen_buf_list, curr_entry);
421 		}
422 		else
423 		{
424             d_list_push_head(&tmp_gen_buf_list, curr_entry);
425 		}
426         num_bypass_buffs--;
427     }
428     num_bufs = (u16_t)d_list_entry_cnt(&tmp_gen_buf_list);
429 	if ((bypass_gen_pool_list != NULL) && d_list_entry_cnt(&free_gen_buf_list))
430 	{
431 		d_list_add_tail(bypass_gen_pool_list, &free_gen_buf_list);
432 	}
433     /* stats... */
434     grq->num_grqs_last_dpc = num_bufs;
435     if (grq->num_grqs_last_dpc) {  /* Exclude zeroed value from statistics*/
436         if (grq->num_grqs_last_dpc > grq->max_grqs_per_dpc) {
437             grq->max_grqs_per_dpc = grq->num_grqs_last_dpc;
438         }
439         /* we don't want to wrap around...*/
440         if ((grq->sum_grqs_last_x_dpcs + grq->num_grqs_last_dpc) < grq->sum_grqs_last_x_dpcs) {
441             grq->avg_dpc_cnt = 0;
442             grq->sum_grqs_last_x_dpcs = 0;
443         }
444         grq->sum_grqs_last_x_dpcs += grq->num_grqs_last_dpc;
445         grq->avg_dpc_cnt++;
446         avg_dpc_cnt = grq->avg_dpc_cnt;
447         if (avg_dpc_cnt) { /*Prevent division by 0*/
448             grq->avg_grqs_per_dpc = grq->sum_grqs_last_x_dpcs / avg_dpc_cnt;
449         } else {
450             grq->sum_grqs_last_x_dpcs = 0;
451         }
452     }
453 
454     DbgBreakIf(num_bufs != tmp_gen_buf_list.cnt);
455 
456     if (num_bufs < bd_chain->bd_left) {
457         grq->num_deficient++;
458     }
459 
460     if (!num_bufs) {
461         DbgMessage(pdev, WARNl4rx, "no buffers returned from generic pool\n");
462         return 0; /* nothing to do */
463     }
464     curr_gen_buf = (lm_tcp_gen_buf_t *)d_list_peek_head(&tmp_gen_buf_list);
465 
466     if (filling_mode == FILL_GRQ_LOW_THRESHOLD) {
467         grq->gen_bufs_compensated_till_low_threshold += num_bufs;
468     }
469     while (num_bufs--) {
470         DbgBreakIf(SIG(curr_gen_buf->buf_virt) != L4GEN_BUFFER_SIG);
471         DbgMessage(pdev, VERBOSEl4rx, "curr_gen_buf->buf_virt=0x%p, END_SIG=0x%x\n", curr_gen_buf->buf_virt,
472                     END_SIG(curr_gen_buf->buf_virt, LM_TCP_GEN_BUF_SIZE(pdev)));
473         DbgBreakIf(END_SIG(curr_gen_buf->buf_virt, LM_TCP_GEN_BUF_SIZE(pdev)) != L4GEN_BUFFER_SIG_END);
474 
475         /* initialize curr_gen_buf */
476         curr_gen_buf->ind_bytes    = 0;
477         curr_gen_buf->ind_nbufs    = 0;
478         curr_gen_buf->placed_bytes = 0;
479         curr_gen_buf->refcnt       = 0;
480         curr_gen_buf->tcp          = NULL;
481 
482         grq_bd = (struct toe_rx_grq_bd *)lm_toe_bd_chain_produce_bd(bd_chain);
483         DbgBreakIf(!grq_bd);
484         /* attach gen buf to grq */
485 		DbgBreakIf(!curr_gen_buf || !curr_gen_buf->buf_phys.as_u64);
486         grq_bd->addr_hi = curr_gen_buf->buf_phys.as_u32.high;
487         grq_bd->addr_lo = curr_gen_buf->buf_phys.as_u32.low;
488 
489         curr_gen_buf = (lm_tcp_gen_buf_t *)d_list_next_entry(&curr_gen_buf->link);
490         /* enlist gen buf to active list will be done at the end of the loop (more efficient) */
491     }
492 
493     if (bd_chain->bd_left) {
494         DbgMessage(pdev, INFORMl4rx, "GRQ bd-chain wasn't filled completely\n");
495     }
496 	if (d_list_entry_cnt(&tmp_gen_buf_list))
497 	{
498         d_list_add_tail(&grq->active_gen_list, &tmp_gen_buf_list);
499 	}
500     return (tmp_gen_buf_list.cnt != 0); /* how many buffers were actually placed */
501 }
502 
503 /* Desciption:
504  *  initialize l4 VBD resources
505  * Assumptions:
506  *  - lm_init_params was already called
507  *  - lm_tcp_alloc_resc was already called
508  *  - um GRQ pool is ready to supply buffers to lm (?)
509  * Returns:
510  *  SUCCESS or any failure */
lm_tcp_init_resc(struct _lm_device_t * pdev,u8_t b_is_init)511 lm_status_t lm_tcp_init_resc(struct _lm_device_t *pdev, u8_t b_is_init )
512 {
513     lm_toe_info_t *toe_info;
514     lm_bd_chain_t *bd_chain;
515     long i;
516     u16_t volatile * sb_indexes;
517     u32_t sb_id;
518 
519     DbgMessage(pdev, VERBOSEl4sp, "##lm_tcp_init_resc\n");
520     toe_info = &pdev->toe_info;
521     toe_info->state = LM_TOE_STATE_INIT;
522 
523     /* init rest of toe_info fields */
524     toe_info->rss_update_cnt = 0;
525     toe_info->gen_buf_size = lm_tcp_calc_gen_buf_size(pdev);
526     LM_TCP_SET_UPDATE_WINDOW_MODE(pdev, LM_TOE_UPDATE_MODE_SHORT_LOOP);
527 
528     if( b_is_init )
529     {
530         d_list_init(&toe_info->state_blk.neigh_list, NULL, NULL, 0);
531         d_list_init(&toe_info->state_blk.path_list, NULL, NULL, 0);
532         d_list_init(&toe_info->state_blk.tcp_list, NULL, NULL, 0);
533     }
534 
535     /* TODO: consider enabling the assertion */
536     //DbgBreakIf(pdev->ofld_info.state_blks[STATE_BLOCK_TOE]);
537     pdev->ofld_info.state_blks[STATE_BLOCK_TOE] = &toe_info->state_blk;
538 
539     LM_TOE_FOREACH_TSS_IDX(pdev, i)
540     {
541         /* init SCQs */
542         lm_tcp_scq_t *scq = &toe_info->scqs[i];
543         bd_chain = &scq->bd_chain;
544         lm_bd_chain_setup(pdev, bd_chain, bd_chain->bd_chain_virt,
545                           bd_chain->bd_chain_phy, (u16_t)pdev->params.l4_scq_page_cnt, sizeof(struct toe_tx_cqe), 1, TRUE);
546         /* Assign the SCQ chain consumer pointer to the consumer index in the status block. */
547         sb_id = RSS_ID_TO_SB_ID(i);
548 #ifdef _VBD_
549 	if (!CHIP_IS_E1x(pdev) && (pdev->params.l4_enable_rss == L4_RSS_DISABLED))
550 	{
551             sb_id = LM_NON_RSS_SB(pdev);
552 	}
553 #endif
554         sb_indexes = lm_get_sb_indexes(pdev, (u8_t)sb_id);
555         sb_indexes[HC_INDEX_TOE_TX_CQ_CONS] = 0;
556         scq->hw_con_idx_ptr = sb_indexes + HC_INDEX_TOE_TX_CQ_CONS;
557         scq->hc_sb_info.hc_sb = STATUS_BLOCK_NORMAL_TYPE;
558         scq->hc_sb_info.hc_index_value = HC_INDEX_TOE_TX_CQ_CONS;
559     }
560 
561 
562     /* Before initializing GRQs, we need to check if there are left-overs from before (incase this isn't the iniitiali 'init', for that we need to clear
563      * them - but outside the loop... */
564     if ( !b_is_init ) {
565         /* we need to return what ever buffers are still on the grq back to the pool before
566          * the new initialization... */
567          lm_tcp_clear_grqs(pdev);
568     }
569 
570     LM_TOE_FOREACH_RSS_IDX(pdev, i)
571     {
572         lm_tcp_rcq_t *rcq = &toe_info->rcqs[i];
573         lm_tcp_grq_t *grq = &toe_info->grqs[i];
574 	u8_t byte_counter_id;
575 
576 	sb_id = RSS_ID_TO_SB_ID(i);
577 #ifdef _VBD_
578 	if (!CHIP_IS_E1x(pdev) && (pdev->params.l4_enable_rss == L4_RSS_DISABLED))
579 	{
580 	    sb_id = LM_NON_RSS_SB(pdev);
581 	}
582 #endif
583 	byte_counter_id = CHIP_IS_E1x(pdev)? LM_FW_SB_ID(pdev, sb_id) : LM_FW_DHC_QZONE_ID(pdev, sb_id);
584 
585         /* init RCQs */
586         bd_chain = &rcq->bd_chain;
587         lm_bd_chain_setup(pdev, bd_chain, bd_chain->bd_chain_virt,
588                           bd_chain->bd_chain_phy, (u16_t)pdev->params.l4_rcq_page_cnt, sizeof(struct toe_rx_cqe), 1, TRUE);
589         rcq->rss_update_pending = 0;
590         rcq->suspend_processing = FALSE;
591         rcq->update_cid = 0;
592 
593         /* Assign the RCQ chain consumer pointer to the consumer index in the status block. */
594         sb_indexes = lm_get_sb_indexes(pdev, (u8_t)sb_id);
595         sb_indexes[HC_INDEX_TOE_RX_CQ_CONS] = 0;
596         rcq->hw_con_idx_ptr = sb_indexes + HC_INDEX_TOE_RX_CQ_CONS;
597         rcq->hc_sb_info.hc_sb = STATUS_BLOCK_NORMAL_SL_TYPE;
598         rcq->hc_sb_info.hc_index_value = HC_INDEX_TOE_RX_CQ_CONS;
599         if (IS_PFDEV(pdev))
600         {
601             rcq->hc_sb_info.iro_dhc_offset = CSTORM_BYTE_COUNTER_OFFSET(byte_counter_id, HC_INDEX_TOE_RX_CQ_CONS);
602         }
603         else
604         {
605             DbgMessage(pdev, FATAL, "Dhc not implemented for VF yet\n");
606         }
607 
608         /* init GRQs */
609         if( b_is_init )
610         {
611             d_list_init(&grq->active_gen_list, NULL, NULL, 0);
612             d_list_init(&grq->aux_gen_list, NULL, NULL, 0);
613             if ((u8_t)i != LM_TOE_BASE_RSS_ID(pdev)  ) {
614                 grq->grq_compensate_on_alloc = TRUE;
615                 pdev->toe_info.grqs[i].high_bds_threshold = 3*GRQ_XOFF_TH + 1;
616             } else {
617                 grq->grq_compensate_on_alloc = FALSE;
618                 pdev->toe_info.grqs[i].high_bds_threshold = 0;
619             }
620             grq->low_bds_threshold = 3*GRQ_XOFF_TH;
621         }
622 
623         bd_chain = &grq->bd_chain;
624         lm_bd_chain_setup(pdev, bd_chain, bd_chain->bd_chain_virt,
625                           bd_chain->bd_chain_phy, (u16_t)pdev->params.l4_grq_page_cnt, sizeof(struct toe_rx_grq_bd), 0, TRUE);
626         /* fill GRQ (minimum mode)*/
627         lm_tcp_rx_fill_grq(pdev, (u8_t)i, NULL, FILL_GRQ_MIN_CASHED_BDS);
628     }
629 
630 
631     LM_TOE_FOREACH_RSS_IDX(pdev, i)
632     {
633         // lm_tcp_grq_t *grq = &toe_info->grqs[i];
634         lm_tcp_rx_fill_grq(pdev, (u8_t)i, NULL, FILL_GRQ_FULL);
635     }
636 
637     return LM_STATUS_SUCCESS;
638 }
639 
640 
641 /* init cstorm internal memory for toe
642  * assumption - strom's common intmem (if any) already initiated */
_lm_tcp_init_cstorm_intmem(lm_device_t * pdev)643 static void _lm_tcp_init_cstorm_intmem(lm_device_t *pdev)
644 {
645     lm_toe_info_t *toe_info;
646     lm_address_t phys_addr;
647     lm_tcp_scq_t *scq;
648     u16_t idx;
649     u8_t drv_toe_rss_id;
650     u8_t port;
651     u8_t fw_sb_id;
652 
653     toe_info = &pdev->toe_info;
654     port = PORT_ID(pdev);
655 
656     LM_TOE_FOREACH_TSS_IDX(pdev, drv_toe_rss_id)
657     {
658         scq = &toe_info->scqs[drv_toe_rss_id];
659 
660         /* SCQ consumer ptr - scq first page addr */
661         phys_addr = lm_bd_chain_phys_addr(&scq->bd_chain, 0);
662         DbgBreakIf(CSTORM_TOE_CQ_CONS_PTR_LO_SIZE != 4);
663 
664         LM_INTMEM_WRITE32(pdev, CSTORM_TOE_CQ_CONS_PTR_LO_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), phys_addr.as_u32.low, BAR_CSTRORM_INTMEM);
665 
666         DbgBreakIf (CSTORM_TOE_CQ_CONS_PTR_HI_SIZE != 4);
667         LM_INTMEM_WRITE32(pdev, CSTORM_TOE_CQ_CONS_PTR_HI_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), phys_addr.as_u32.high, BAR_CSTRORM_INTMEM);
668 
669         /* SCQ producer idx */
670         idx = lm_bd_chain_prod_idx(&scq->bd_chain);
671 
672         DbgBreakIf(CSTORM_TOE_CQ_PROD_SIZE != 2);
673         LM_INTMEM_WRITE16(pdev, CSTORM_TOE_CQ_PROD_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), idx, BAR_CSTRORM_INTMEM);
674 
675         /* SCQ consumer idx */
676         idx = lm_bd_chain_cons_idx(&scq->bd_chain);
677         DbgBreakIf(idx != 0);
678 
679         DbgBreakIf(CSTORM_TOE_CQ_CONS_SIZE != 2);
680         LM_INTMEM_WRITE16(pdev, CSTORM_TOE_CQ_CONS_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), idx, BAR_CSTRORM_INTMEM);
681 
682         /* SCQ second page addr */
683         phys_addr = lm_bd_chain_phys_addr(&scq->bd_chain, 1);
684 
685         DbgBreakIf(CSTORM_TOE_CQ_NEXT_PAGE_BASE_ADDR_LO_SIZE != 4);
686         LM_INTMEM_WRITE32(pdev, CSTORM_TOE_CQ_NEXT_PAGE_BASE_ADDR_LO_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), phys_addr.as_u32.low, BAR_CSTRORM_INTMEM);
687 
688         DbgBreakIf(CSTORM_TOE_CQ_NEXT_PAGE_BASE_ADDR_HI_SIZE != 4);
689         LM_INTMEM_WRITE32(pdev, CSTORM_TOE_CQ_NEXT_PAGE_BASE_ADDR_HI_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), phys_addr.as_u32.high, BAR_CSTRORM_INTMEM);
690 
691         DbgBreakIf(CSTORM_TOE_CQ_NXT_PAGE_ADDR_VALID_SIZE != 1);
692 
693         LM_INTMEM_WRITE8(pdev, CSTORM_TOE_CQ_NXT_PAGE_ADDR_VALID_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), 1, BAR_CSTRORM_INTMEM);
694 
695         //LM_INTMEM_WRITE8(pdev, CSTORM_TOE_STATUS_BLOCK_ID_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), BAR_CSTRORM_INTMEM);
696 	fw_sb_id = LM_FW_SB_ID(pdev, RSS_ID_TO_SB_ID(drv_toe_rss_id));
697 #ifdef _VBD_
698 	if (!CHIP_IS_E1x(pdev) && (pdev->params.l4_enable_rss == L4_RSS_DISABLED))
699 	{
700 		fw_sb_id = LM_FW_SB_ID(pdev, RSS_ID_TO_SB_ID(LM_NON_RSS_SB(pdev)));
701 		if (drv_toe_rss_id != LM_NON_RSS_CHAIN(pdev))
702 		{
703 			DbgBreak();
704 		}
705 	}
706 #endif
707         LM_INTMEM_WRITE8(pdev, CSTORM_TOE_STATUS_BLOCK_ID_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), fw_sb_id, BAR_CSTRORM_INTMEM);
708         LM_INTMEM_WRITE8(pdev, CSTORM_TOE_STATUS_BLOCK_INDEX_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), HC_INDEX_TOE_TX_CQ_CONS, BAR_CSTRORM_INTMEM);
709     }
710 }
711 
712 /* init ustorm offload params private to TOE */
_lm_set_ofld_params_ustorm_toe(lm_device_t * pdev,l4_ofld_params_t * l4_params)713 static void _lm_set_ofld_params_ustorm_toe(lm_device_t *pdev, l4_ofld_params_t *l4_params)
714 {
715     u8_t func;
716     u32_t val32;
717 
718     func = FUNC_ID(pdev);
719 
720     /* global push timer ticks */
721     /* This value is in milliseconds instead of ticks in SNP
722      * and Longhorn.  In the future microsoft will change these
723      * values to ticks. TBA : When fix takes place, uncomment first line and remove second line */
724     /* val32 = lm_time_resolution(pdev, l4_params->push_ticks, l4_params->ticks_per_second, 1000); */
725     val32 = lm_time_resolution(pdev, l4_params->push_ticks, 1000, 1000);
726 
727     DbgBreakIf (USTORM_TOE_TCP_PUSH_TIMER_TICKS_SIZE != 4);
728     LM_INTMEM_WRITE32(pdev, USTORM_TOE_TCP_PUSH_TIMER_TICKS_OFFSET(func), val32, BAR_USTRORM_INTMEM);
729 }
730 
731 /* init ustorm internal memory for toe
732  * assumption - strom's common intmem (if any) already initiated */
_lm_tcp_init_ustorm_intmem(lm_device_t * pdev)733 static void _lm_tcp_init_ustorm_intmem(lm_device_t *pdev)
734 {
735     lm_toe_info_t *toe_info;
736     lm_address_t phys_addr;
737     lm_tcp_rcq_t *rcq;
738     lm_tcp_grq_t *grq;
739     struct toe_rx_grq_bd *grq_bd;
740     u16_t idx;
741     u8_t drv_toe_rss_id, grq_bd_idx;
742     u8_t port;
743     u8_t fw_sb_id;
744     u8_t sw_sb_id;
745 
746     toe_info = &pdev->toe_info;
747     port = PORT_ID(pdev);
748 
749     _lm_set_ofld_params_ustorm_toe(pdev, &(pdev->ofld_info.l4_params));
750 
751     LM_TOE_FOREACH_RSS_IDX(pdev,drv_toe_rss_id)
752     {
753 
754         rcq = &toe_info->rcqs[drv_toe_rss_id];
755         grq = &toe_info->grqs[drv_toe_rss_id];
756 
757         /* GRQ cache bds */
758         grq_bd = (struct toe_rx_grq_bd *)grq->bd_chain.bd_chain_virt;
759 
760         DbgBreakIf( USTORM_TOE_GRQ_CACHE_NUM_BDS > lm_bd_chain_usable_bds_per_page(&grq->bd_chain));
761 
762         for(grq_bd_idx = 0; grq_bd_idx < USTORM_TOE_GRQ_CACHE_NUM_BDS; grq_bd_idx++) {
763             LM_INTMEM_WRITE32(pdev, USTORM_GRQ_CACHE_BD_LO_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id) ,port,grq_bd_idx), grq_bd->addr_lo, BAR_USTRORM_INTMEM);
764             LM_INTMEM_WRITE32(pdev, USTORM_GRQ_CACHE_BD_HI_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id),port,grq_bd_idx), grq_bd->addr_hi, BAR_USTRORM_INTMEM);
765             grq_bd++;
766         }
767 
768         /* GRQ cache prod idx */
769         DbgBreakIf (USTORM_TOE_GRQ_LOCAL_PROD_SIZE != 1);
770         LM_INTMEM_WRITE8(pdev, USTORM_TOE_GRQ_LOCAL_PROD_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port),  (u8_t)USTORM_TOE_GRQ_CACHE_NUM_BDS, BAR_USTRORM_INTMEM);
771 
772         /* GRQ cache cons idx */
773         DbgBreakIf (USTORM_TOE_GRQ_LOCAL_CONS_SIZE != 1);
774         LM_INTMEM_WRITE8(pdev, USTORM_TOE_GRQ_LOCAL_CONS_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port),  0, BAR_USTRORM_INTMEM);
775 
776         /* GRQ producer idx */
777         idx = lm_bd_chain_prod_idx(&grq->bd_chain);
778         DbgBreakIf (USTORM_TOE_GRQ_PROD_SIZE != 2);
779         LM_INTMEM_WRITE16(pdev, USTORM_TOE_GRQ_PROD_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), idx, BAR_USTRORM_INTMEM);
780 
781         /* GRQ consumer idx */
782         DbgBreakIf (USTORM_TOE_GRQ_CONS_SIZE != 2);
783         LM_INTMEM_WRITE16(pdev, USTORM_TOE_GRQ_CONS_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), (u8_t)USTORM_TOE_GRQ_CACHE_NUM_BDS, BAR_USTRORM_INTMEM);
784 
785         /* GRQ consumer ptr */
786         phys_addr = lm_bd_chain_phys_addr(&grq->bd_chain, 0);
787         LM_INC64(&phys_addr, sizeof(struct toe_rx_grq_bd) * USTORM_TOE_GRQ_CACHE_NUM_BDS);
788 
789         DbgBreakIf (USTORM_TOE_GRQ_CONS_PTR_LO_SIZE != 4);
790         LM_INTMEM_WRITE32(pdev, USTORM_TOE_GRQ_CONS_PTR_LO_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), phys_addr.as_u32.low, BAR_USTRORM_INTMEM);
791 
792         DbgBreakIf (USTORM_TOE_GRQ_CONS_PTR_HI_SIZE != 4);
793         LM_INTMEM_WRITE32(pdev, USTORM_TOE_GRQ_CONS_PTR_HI_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), phys_addr.as_u32.high, BAR_USTRORM_INTMEM);
794 
795         /* Generic buffer size */
796         DbgBreakIf (USTORM_TOE_GRQ_BUF_SIZE_SIZE != 2);
797 
798         DbgBreakIf(LM_TCP_GEN_BUF_SIZE(pdev) > 0xffff); /* the size available in ustorm */
799         LM_INTMEM_WRITE16(pdev, USTORM_TOE_GRQ_BUF_SIZE_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), (u16_t)LM_TCP_GEN_BUF_SIZE(pdev), BAR_USTRORM_INTMEM);
800 
801         /* RCQ consumer ptr - rcq first page addr */
802         phys_addr = lm_bd_chain_phys_addr(&rcq->bd_chain, 0);
803 
804         DbgBreakIf (USTORM_TOE_CQ_CONS_PTR_LO_SIZE != 4);
805         LM_INTMEM_WRITE32(pdev, USTORM_TOE_CQ_CONS_PTR_LO_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), phys_addr.as_u32.low, BAR_USTRORM_INTMEM);
806 
807         DbgBreakIf (USTORM_TOE_CQ_CONS_PTR_HI_SIZE != 4);
808         LM_INTMEM_WRITE32(pdev, USTORM_TOE_CQ_CONS_PTR_HI_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), phys_addr.as_u32.high, BAR_USTRORM_INTMEM);
809 
810         /* RCQ second page addr */
811         phys_addr = lm_bd_chain_phys_addr(&rcq->bd_chain, 1);
812 
813         DbgBreakIf (USTORM_TOE_CQ_NEXT_PAGE_BASE_ADDR_LO_SIZE != 4);
814         LM_INTMEM_WRITE32(pdev, USTORM_TOE_CQ_NEXT_PAGE_BASE_ADDR_LO_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), phys_addr.as_u32.low, BAR_USTRORM_INTMEM);
815 
816         DbgBreakIf (USTORM_TOE_CQ_NEXT_PAGE_BASE_ADDR_HI_SIZE != 4);
817         LM_INTMEM_WRITE32(pdev, USTORM_TOE_CQ_NEXT_PAGE_BASE_ADDR_HI_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), phys_addr.as_u32.high, BAR_USTRORM_INTMEM);
818 
819         DbgBreakIf (USTORM_TOE_CQ_NXT_PAGE_ADDR_VALID_SIZE != 1);
820         LM_INTMEM_WRITE8(pdev, USTORM_TOE_CQ_NXT_PAGE_ADDR_VALID_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), 1, BAR_USTRORM_INTMEM);
821 
822         /* RCQ producer idx */
823         idx = lm_bd_chain_prod_idx(&rcq->bd_chain);
824 
825         DbgBreakIf (USTORM_TOE_CQ_PROD_SIZE != 2);
826         LM_INTMEM_WRITE16(pdev, USTORM_TOE_CQ_PROD_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), idx, BAR_USTRORM_INTMEM);
827         if (pdev->params.enable_dynamic_hc[HC_INDEX_TOE_RX_CQ_CONS]) {
828             u32_t l4_quasi_byte_counter;
829             u16_t prod_idx_diff = lm_bd_chain_prod_idx(&rcq->bd_chain) - rcq->bd_chain.bds_per_page * rcq->bd_chain.page_cnt;
830             l4_quasi_byte_counter = prod_idx_diff;
831             l4_quasi_byte_counter <<= 16;
832 //            LM_INTMEM_WRITE32(pdev, CSTORM_BYTE_COUNTER_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), HC_INDEX_TOE_RX_CQ_CONS), l4_quasi_byte_counter, BAR_CSTRORM_INTMEM);
833             LM_INTMEM_WRITE32(pdev, rcq->hc_sb_info.iro_dhc_offset, l4_quasi_byte_counter, BAR_CSTRORM_INTMEM);
834         }
835         /* RCQ consumer idx */
836         idx = lm_bd_chain_cons_idx(&rcq->bd_chain);
837         DbgBreakIf(idx != 0);
838 
839         DbgBreakIf (USTORM_TOE_CQ_CONS_SIZE != 2);
840         LM_INTMEM_WRITE16(pdev, USTORM_TOE_CQ_CONS_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), idx, BAR_USTRORM_INTMEM);
841 
842         fw_sb_id = LM_FW_SB_ID(pdev, RSS_ID_TO_SB_ID(drv_toe_rss_id));
843 	sw_sb_id = RSS_ID_TO_SB_ID(drv_toe_rss_id);
844         if (RSS_ID_TO_SB_ID(drv_toe_rss_id) >= MAX_NDSB) { //To suppress Prefast warning
845             DbgBreak();
846             break;
847         }
848 #ifdef _VBD_
849 	if (!CHIP_IS_E1x(pdev) && (pdev->params.l4_enable_rss == L4_RSS_DISABLED))
850 	{
851 		fw_sb_id = LM_FW_SB_ID(pdev, RSS_ID_TO_SB_ID(LM_NON_RSS_SB(pdev)));
852 		sw_sb_id = LM_NON_RSS_SB(pdev);
853 		if (drv_toe_rss_id != LM_NON_RSS_CHAIN(pdev))
854 		{
855 			DbgBreak();
856 		}
857 	}
858 #endif
859         if (CHIP_IS_E1x(pdev)) {
860 
861             if (pdev->params.enable_dynamic_hc[HC_INDEX_TOE_RX_CQ_CONS]) {
862                 pdev->vars.status_blocks_arr[RSS_ID_TO_SB_ID(drv_toe_rss_id)].hc_status_block_data.e1x_sb_data.index_data[HC_INDEX_TOE_RX_CQ_CONS].flags |= HC_INDEX_DATA_DYNAMIC_HC_ENABLED;
863             } else {
864                 pdev->vars.status_blocks_arr[RSS_ID_TO_SB_ID(drv_toe_rss_id)].hc_status_block_data.e1x_sb_data.index_data[HC_INDEX_TOE_RX_CQ_CONS].flags &= ~HC_INDEX_DATA_DYNAMIC_HC_ENABLED;
865             }
866             LM_INTMEM_WRITE8(PFDEV(pdev), CSTORM_STATUS_BLOCK_DATA_OFFSET(fw_sb_id)
867                               + OFFSETOF(struct hc_status_block_data_e1x, index_data)
868                               + sizeof(struct hc_index_data)*HC_INDEX_TOE_RX_CQ_CONS
869                               + OFFSETOF(struct hc_index_data,flags),
870                               pdev->vars.status_blocks_arr[RSS_ID_TO_SB_ID(drv_toe_rss_id)].hc_status_block_data.e1x_sb_data.index_data[HC_INDEX_ETH_RX_CQ_CONS].flags, BAR_CSTRORM_INTMEM);
871         } else {
872 
873             if (pdev->params.enable_dynamic_hc[HC_INDEX_TOE_RX_CQ_CONS]) {
874                 pdev->vars.status_blocks_arr[sw_sb_id].hc_status_block_data.e2_sb_data.index_data[HC_INDEX_TOE_RX_CQ_CONS].flags |= HC_INDEX_DATA_DYNAMIC_HC_ENABLED;
875             } else {
876                 pdev->vars.status_blocks_arr[sw_sb_id].hc_status_block_data.e2_sb_data.index_data[HC_INDEX_TOE_RX_CQ_CONS].flags &= ~HC_INDEX_DATA_DYNAMIC_HC_ENABLED;
877             }
878             LM_INTMEM_WRITE8(PFDEV(pdev), CSTORM_STATUS_BLOCK_DATA_OFFSET(fw_sb_id)
879                               + OFFSETOF(struct hc_status_block_data_e2, index_data)
880                               + sizeof(struct hc_index_data)*HC_INDEX_TOE_RX_CQ_CONS
881                               + OFFSETOF(struct hc_index_data,flags),
882                               pdev->vars.status_blocks_arr[sw_sb_id].hc_status_block_data.e2_sb_data.index_data[HC_INDEX_ETH_RX_CQ_CONS].flags, BAR_CSTRORM_INTMEM);
883 
884         }
885 
886 //        LM_INTMEM_WRITE8(pdev, USTORM_TOE_STATUS_BLOCK_ID_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port),LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), BAR_USTRORM_INTMEM);
887         LM_INTMEM_WRITE8(pdev, USTORM_TOE_STATUS_BLOCK_ID_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port),fw_sb_id, BAR_USTRORM_INTMEM);
888         LM_INTMEM_WRITE8(pdev, USTORM_TOE_STATUS_BLOCK_INDEX_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id), port), HC_INDEX_TOE_RX_CQ_CONS, BAR_USTRORM_INTMEM);
889     }
890 
891     /* Initialize Indirection Table : Only in entries that match status - blocks : L4 base--> L4 base + cnt */
892     DbgBreakIf (USTORM_INDIRECTION_TABLE_ENTRY_SIZE != 1);
893 
894     if (pdev->params.l4_enable_rss == L4_RSS_DISABLED) {
895         LM_TOE_FOREACH_RSS_IDX(pdev, idx)
896         {
897             LM_INTMEM_WRITE8(pdev, USTORM_INDIRECTION_TABLE_OFFSET(port) + LM_TOE_FW_RSS_ID(pdev,idx), LM_TOE_FW_RSS_ID(pdev,(u8_t)idx), BAR_USTRORM_INTMEM);
898         }
899     } else {
900         for (idx = 0; idx < RSS_INDIRECTION_TABLE_SIZE; idx++) {
901             LM_INTMEM_WRITE8(pdev,USTORM_INDIRECTION_TABLE_OFFSET(port) + idx, pdev->toe_info.indirection_table[idx], BAR_USTRORM_INTMEM);
902         }
903     }
904 }
905 
906 /* init tstorm offload params common to TOE/RDMA/ISCSI */
_lm_set_ofld_params_tstorm_common(lm_device_t * pdev,l4_ofld_params_t * l4_params)907 static void _lm_set_ofld_params_tstorm_common(lm_device_t *pdev, l4_ofld_params_t *l4_params)
908 {
909     u8_t func;
910     u32_t dup_ack_threshold;
911 
912     func = FUNC_ID(pdev);
913 
914     dup_ack_threshold = l4_params->dup_ack_threshold;
915     if(dup_ack_threshold > TCP_TSTORM_MAX_DUP_ACK_TH) {
916         DbgMessage(pdev, WARNl4sp,
917                    "given dup_ack_threshold (=%d) too high. setting it to maximum allowed (=%d)\n",
918                    dup_ack_threshold, TCP_TSTORM_MAX_DUP_ACK_TH);
919         dup_ack_threshold = TCP_TSTORM_MAX_DUP_ACK_TH;
920     }
921 
922     DbgBreakIf (TSTORM_TCP_DUPLICATE_ACK_THRESHOLD_SIZE != 4);
923     LM_INTMEM_WRITE32(pdev, TSTORM_TCP_DUPLICATE_ACK_THRESHOLD_OFFSET(func), dup_ack_threshold, BAR_TSTRORM_INTMEM);
924 
925     /* MaxCwnd  */
926     DbgBreakIf (TSTORM_TCP_MAX_CWND_SIZE != 4);
927     if(pdev->params.network_type == LM_NETOWRK_TYPE_WAN) {
928         LM_INTMEM_WRITE32(pdev, TSTORM_TCP_MAX_CWND_OFFSET(func), pdev->params.max_cwnd_wan, BAR_TSTRORM_INTMEM);
929     } else {
930         DbgBreakIf(pdev->params.network_type != LM_NETOWRK_TYPE_LAN);
931         LM_INTMEM_WRITE32(pdev, TSTORM_TCP_MAX_CWND_OFFSET(func), pdev->params.max_cwnd_lan, BAR_TSTRORM_INTMEM);
932     }
933 }
934 
935 /* init tstorm offload params private to TOE */
_lm_set_ofld_params_tstorm_toe(lm_device_t * pdev,l4_ofld_params_t * l4_params)936 static void _lm_set_ofld_params_tstorm_toe(lm_device_t *pdev, l4_ofld_params_t *l4_params)
937 {
938     u8_t func;
939 
940     func = FUNC_ID(pdev);
941 
942     /* max retransmit (TOE param only) */
943     DbgBreakIf (TSTORM_TOE_MAX_SEG_RETRANSMIT_SIZE != 4);
944     LM_INTMEM_WRITE32(pdev, TSTORM_TOE_MAX_SEG_RETRANSMIT_OFFSET(func), l4_params->max_retx, BAR_TSTRORM_INTMEM);
945 
946     /* TcpDoubtReachability (TOE param only) */
947     DbgBreakIf (TSTORM_TOE_DOUBT_REACHABILITY_SIZE != 1);
948     LM_INTMEM_WRITE8(pdev, TSTORM_TOE_DOUBT_REACHABILITY_OFFSET(func), l4_params->doubt_reachability_retx, BAR_TSTRORM_INTMEM);
949 
950 }
951 
952 /* init tstorm internal memory for toe
953  * assumption - strom's common intmem already initiated */
_lm_tcp_init_tstorm_intmem(lm_device_t * pdev)954 static void _lm_tcp_init_tstorm_intmem(lm_device_t *pdev)
955 {
956     _lm_set_ofld_params_tstorm_toe(pdev, &(pdev->ofld_info.l4_params));
957 
958     DbgBreakIf (TSTORM_TOE_MAX_DOMINANCE_VALUE_SIZE != 1);
959     LM_INTMEM_WRITE8(pdev, TSTORM_TOE_MAX_DOMINANCE_VALUE_OFFSET, (u8_t)pdev->params.l4_max_dominance_value, BAR_TSTRORM_INTMEM);
960     DbgBreakIf (TSTORM_TOE_DOMINANCE_THRESHOLD_SIZE != 1);
961     LM_INTMEM_WRITE8(pdev, TSTORM_TOE_DOMINANCE_THRESHOLD_OFFSET, (u8_t)pdev->params.l4_dominance_threshold, BAR_TSTRORM_INTMEM);
962 
963 }
964 
965 
966 /* init xstorm offload params common to TOE/RDMA/ISCSI */
_lm_set_ofld_params_xstorm_common(lm_device_t * pdev,l4_ofld_params_t * l4_params)967 static void _lm_set_ofld_params_xstorm_common(lm_device_t *pdev, l4_ofld_params_t *l4_params)
968 {
969     u8_t func, ack_frequency;
970     u32_t val32, max_reg, tmr_reg, delayed_ack_ticks;
971 
972     func = FUNC_ID(pdev);
973     if (PORT_ID(pdev)) {
974         max_reg = XCM_REG_GLB_DEL_ACK_MAX_CNT_1;
975         tmr_reg = XCM_REG_GLB_DEL_ACK_TMR_VAL_1;
976     } else {
977         max_reg = XCM_REG_GLB_DEL_ACK_MAX_CNT_0;
978         tmr_reg = XCM_REG_GLB_DEL_ACK_TMR_VAL_0;
979     }
980     /* if ack_frequency is 0, it means use default value of 2. */
981     /* delayed max ack count, (both in internal ram and in XCM!!!) */
982     ack_frequency = l4_params->ack_frequency;
983     if(ack_frequency < TCP_XCM_MIN_GLB_DEL_ACK_MAX_CNT) {
984         DbgMessage(pdev, WARNl4sp,
985                    "given ack_frequency (=%d) too low. setting it to minimum allowed (=%d)\n",
986                    ack_frequency, TCP_XCM_DEFAULT_DEL_ACK_MAX_CNT);
987         ack_frequency = TCP_XCM_DEFAULT_DEL_ACK_MAX_CNT;
988     }
989 
990 
991     DbgBreakIf (XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_MAX_COUNT_SIZE != 1);
992     LM_INTMEM_WRITE8(pdev, XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_MAX_COUNT_OFFSET(func), ack_frequency, BAR_XSTRORM_INTMEM);
993     REG_WR(pdev,  max_reg, ack_frequency);
994 
995     /* This value is in milliseconds instead of ticks in SNP
996      * and Longhorn.  In the future microsoft will change these
997      * values to ticks. TBA : When fix takes place, uncomment first line and remove second line */
998     /* delayed_ack_ticks = lm_time_resolution(pdev, l4_params->delayed_ack_ticks, l4_params->ticks_per_second, 1000); */
999     delayed_ack_ticks = lm_time_resolution(pdev, l4_params->delayed_ack_ticks, 1000, TIMERS_TICKS_PER_SEC);
1000 
1001     /* delayed ack timer */
1002     REG_WR(pdev,   tmr_reg, delayed_ack_ticks);
1003 
1004     /* sws timer */
1005     /* This value (sws_prevention_ticks) is in milliseconds instead of ticks in SNP
1006      * and Longhorn.  In the future microsoft will change these
1007      * values to ticks. TBA : When fix takes place, uncomment first line and remove second line */
1008     /* val32 = lm_time_resolution(pdev, l4_params->sws_prevention_ticks, l4_params->ticks_per_second, TIMERS_TICKS_PER_SEC); */
1009     val32 = lm_time_resolution(pdev, l4_params->sws_prevention_ticks, 1000 , TIMERS_TICKS_PER_SEC);
1010 
1011     DbgBreakIf (XSTORM_TCP_TX_SWS_TIMER_VAL_SIZE != 4);
1012     LM_INTMEM_WRITE32(pdev, XSTORM_TCP_TX_SWS_TIMER_VAL_OFFSET(func), val32, BAR_XSTRORM_INTMEM);
1013 
1014     DbgBreakIf (XSTORM_COMMON_RTC_RESOLUTION_SIZE != 2);
1015     LM_INTMEM_WRITE16(pdev, XSTORM_COMMON_RTC_RESOLUTION_OFFSET, 1000 / l4_params->ticks_per_second , BAR_XSTRORM_INTMEM);
1016 }
1017 
1018 /* init xstorm offload params private to TOE */
_lm_set_ofld_params_xstorm_toe(lm_device_t * pdev,l4_ofld_params_t * l4_params)1019 static void _lm_set_ofld_params_xstorm_toe(lm_device_t *pdev, l4_ofld_params_t *l4_params)
1020 {
1021     u8_t func;
1022 
1023     func = FUNC_ID(pdev);
1024 
1025     DbgBreakIf (XSTORM_TOE_LLC_SNAP_ENABLED_SIZE != 1);
1026     if(l4_params->flags & OFLD_PARAM_FLAG_SNAP_ENCAP) {
1027         LM_INTMEM_WRITE8(pdev, XSTORM_TOE_LLC_SNAP_ENABLED_OFFSET(func), 1, BAR_XSTRORM_INTMEM);
1028     } else {
1029         LM_INTMEM_WRITE8(pdev, XSTORM_TOE_LLC_SNAP_ENABLED_OFFSET(func), 0, BAR_XSTRORM_INTMEM);
1030     }
1031 }
1032 
1033 /* init xstorm internal memory for toe
1034  * assumption - strom's common intmem already initiated */
_lm_tcp_init_xstorm_intmem(lm_device_t * pdev)1035 static void _lm_tcp_init_xstorm_intmem(lm_device_t *pdev)
1036 {
1037     _lm_set_ofld_params_xstorm_toe(pdev, &(pdev->ofld_info.l4_params));
1038 }
1039 
1040 /* Desciption:
1041  *  init chip internal memory and hw that is common for TOE, ISCSI and RDMA
1042  * Assumptions:
1043  *  - lm_init_params was already called
1044  * Returns:
1045  *  SUCCESS or any failure  */
lm_tcp_init_chip_common(lm_device_t * pdev)1046 lm_status_t lm_tcp_init_chip_common(lm_device_t *pdev)
1047 {
1048     l4_ofld_params_t l4_params;
1049     u8_t func;
1050 
1051     DbgMessage(pdev, VERBOSEl4sp, "###lm_tcp_init_chip_common\n");
1052     DbgBreakIf(!pdev);
1053 
1054     func = FUNC_ID(pdev);
1055 
1056     _lm_get_default_l4cli_params(pdev, &l4_params);
1057 
1058     pdev->ofld_info.l4_params = l4_params;
1059 
1060     /* init common internal memory/hw for each storm
1061      * (c+u storms do not have common offload params) */
1062     _lm_set_ofld_params_xstorm_common(pdev, &l4_params);
1063     _lm_set_ofld_params_tstorm_common(pdev, &l4_params);
1064 
1065 
1066     /* init internal memory constatns (non-dependant on l4_params)*/
1067 
1068     /* enable delayed acks */
1069     DbgBreakIf (XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_ENABLED_SIZE != 1);
1070     LM_INTMEM_WRITE8(pdev, XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_ENABLED_OFFSET(func), 1 /* always enabled */, BAR_XSTRORM_INTMEM);
1071 
1072     /* ip id (init value currently constant: 0x8000) */
1073     DbgBreakIf (XSTORM_TCP_IPID_SIZE != 2);
1074     LM_INTMEM_WRITE16(pdev, XSTORM_TCP_IPID_OFFSET(func), TOE_XSTORM_IP_ID_INIT_HI, BAR_XSTRORM_INTMEM);
1075 
1076     return LM_STATUS_SUCCESS;
1077 }
1078 
1079 /* Desciption:
1080  *  init chip internal memory for L4
1081  * Returns:
1082  *  SUCCESS or any failure  */
lm_tcp_init_chip(lm_device_t * pdev)1083 lm_status_t lm_tcp_init_chip(lm_device_t *pdev)
1084 {
1085     DbgMessage(pdev, VERBOSEl4sp, "##lm_tcp_init_chip\n");
1086 
1087     /* GilR 4/9/2006 - TODO - Assaf - RSS indirection table default initialization, done in L2? */
1088 
1089     /* init XSTORM internal RAM */
1090     _lm_tcp_init_xstorm_intmem(pdev);
1091 
1092     /* init CSTORM internal RAM */
1093     _lm_tcp_init_cstorm_intmem(pdev);
1094 
1095     /* init TSTORM internal RAM */
1096     _lm_tcp_init_tstorm_intmem(pdev);
1097 
1098     /* init USTORM internal RAM */
1099     _lm_tcp_init_ustorm_intmem(pdev);
1100 
1101     return LM_STATUS_SUCCESS;
1102 }
1103 
1104 /* Desciption:
1105  *  send TOE START ramrod wait for completion and return
1106  * Assumptions:
1107  *  - there is no pending slow path request for the leading connection (cid=0)
1108  *  - interrupts are already enabled
1109  * Returns:
1110  *  SUCCESS or any failure  */
lm_tcp_start_chip(lm_device_t * pdev)1111 lm_status_t lm_tcp_start_chip(lm_device_t *pdev)
1112 {
1113     lm_toe_info_t *toe_info;
1114     u32_t to_cnt = 100000; /* GilR 4/9/2006 - TBA - 'to_cnt' in lm_tcp_init_chip need to be removed? */
1115     u64_t data;
1116     struct toe_init_ramrod_data toe_init_data;
1117 
1118     DbgMessage(pdev, VERBOSEl4sp, "##lm_tcp_start_chip\n");
1119 
1120     toe_info = &pdev->toe_info;
1121 
1122     /* send TOE INIT ramrod and wait for completion */
1123     DbgBreakIf(toe_info->state != LM_TOE_STATE_INIT);
1124 
1125     toe_init_data.rss_num = LM_TOE_FW_RSS_ID(pdev,LM_TOE_BASE_RSS_ID(pdev));
1126     data = *((u64_t*)(&toe_init_data));
1127     lm_command_post(pdev, LM_SW_LEADING_RSS_CID(pdev), RAMROD_OPCODE_TOE_INIT, CMD_PRIORITY_NORMAL, TOE_CONNECTION_TYPE, data);
1128     while (toe_info->state != LM_TOE_STATE_NORMAL && to_cnt) {
1129         mm_wait(pdev,100);
1130         to_cnt--;
1131     }
1132     /* GilR 5/16/2006 - TODO - DbgBreakIf(toe_info->state != LM_TOE_STATE_NORMAL); commented out for windows user mode */
1133     if(toe_info->state != LM_TOE_STATE_NORMAL) {
1134 #ifndef _VBD_CMD_
1135         DbgMessage(pdev, FATAL, "TOE init ramrod did not complete\n");
1136 #else
1137         toe_info->state = LM_TOE_STATE_NORMAL;
1138         lm_sq_complete(pdev, CMD_PRIORITY_NORMAL, RAMROD_OPCODE_TOE_INIT, TOE_CONNECTION_TYPE, LM_SW_LEADING_RSS_CID(pdev));
1139 #endif
1140 
1141         #if defined(_VBD_)
1142         DbgBreak();
1143         #endif
1144     }
1145 
1146     /* cid recycled cb registration  */
1147     lm_cid_recycled_cb_register(pdev, TOE_CONNECTION_TYPE, lm_tcp_recycle_cid_cb);
1148 
1149     /* Sq-completion cb registration (sq that get completed internally in driver */
1150     lm_sq_comp_cb_register(pdev, TOE_CONNECTION_TYPE, lm_tcp_comp_cb);
1151 
1152     return LM_STATUS_SUCCESS;
1153 }
1154 
1155 /* Desciption:
1156  *  allocate and initiate l4 (lm driver and chip)
1157  * Assumptions:
1158  *  - lm_init_params was already called
1159  *  - um GRQ pool is ready to supply buffers to lm (?)
1160  *  - there is no pending slow path request for the leading connection (cid=0)
1161  *  - interrupts are already enabled
1162  * Returns:
1163  *  SUCCESS or any failure */
lm_tcp_init(lm_device_t * pdev)1164 lm_status_t lm_tcp_init(lm_device_t *pdev)
1165 {
1166     lm_toe_info_t *toe_info;
1167     lm_status_t lm_status;
1168 
1169     DbgMessage(pdev, VERBOSEl4sp, "###lm_tcp_init\n");
1170     if (IS_VFDEV(pdev)) {
1171         DbgMessage(pdev, FATAL, "###lm_tcp_init is not supported for VF\n");
1172         return LM_STATUS_SUCCESS;
1173     }
1174 
1175     toe_info = &pdev->toe_info;
1176     mm_memset(toe_info, 0 , sizeof(lm_toe_info_t));
1177     toe_info->pdev = pdev;
1178 
1179     /* allocate resources */
1180     lm_status = lm_tcp_alloc_resc(pdev);
1181     DbgBreakIf((lm_status!=LM_STATUS_SUCCESS) && DBG_BREAK_ON(MEMORY_ALLOCATION_FAILURE));
1182     if (lm_status != LM_STATUS_SUCCESS) {
1183         return lm_status;
1184     }
1185 
1186     /* initialize resources */
1187     lm_status = lm_tcp_init_resc(pdev, TRUE);
1188     DbgBreakIf(lm_status!=LM_STATUS_SUCCESS);
1189     if (lm_status != LM_STATUS_SUCCESS) {
1190         return lm_status;
1191     }
1192 
1193     /* initialize chip resources */
1194     lm_status = lm_tcp_init_chip(pdev);
1195     DbgBreakIf(lm_status!=LM_STATUS_SUCCESS);
1196     if (lm_status != LM_STATUS_SUCCESS) {
1197         return lm_status;
1198     }
1199 
1200     /* activate chip for tcp */
1201     lm_status = lm_tcp_start_chip(pdev);
1202     DbgBreakIf(lm_status!=LM_STATUS_SUCCESS);
1203     if (lm_status != LM_STATUS_SUCCESS) {
1204         return lm_status;
1205     }
1206 
1207     return lm_status;
1208 }
1209 
1210 /* Desciption:
1211  *  handle TOE init protocol ramrod completion */
lm_tcp_init_ramrod_comp(lm_device_t * pdev)1212 void lm_tcp_init_ramrod_comp(lm_device_t *pdev)
1213 {
1214     lm_toe_info_t *toe_info;
1215 
1216     DbgMessage(pdev, VERBOSEl4sp, "##lm_tcp_init_ramrod_comp\n");
1217     DbgBreakIf(!pdev);
1218 
1219     toe_info = &pdev->toe_info;
1220     DbgBreakIf(toe_info->state != LM_TOE_STATE_INIT);
1221     toe_info->state = LM_TOE_STATE_NORMAL;
1222 }
1223 
1224 /* Desciption:
1225  *  handle TOE RSS-update ramrod completion
1226  * Assumptions:
1227  * - called once for each RCQ
1228  */
lm_tcp_rss_update_ramrod_comp(struct _lm_device_t * pdev,lm_tcp_rcq_t * rcq,u32_t cid,u32_t update_stats_type,u8_t update_suspend_rcq)1229 void lm_tcp_rss_update_ramrod_comp(
1230     struct _lm_device_t *pdev,
1231     lm_tcp_rcq_t *rcq,
1232     u32_t cid,
1233     u32_t update_stats_type,
1234     u8_t update_suspend_rcq)
1235 {
1236 
1237    /* decrement the completion count and check if we need to suspend processing */
1238    DbgBreakIf(rcq->suspend_processing == TRUE);
1239 
1240    /* Update update statistics - These statistics indicate which FW flow was taken and also count the overall number of updates */
1241     DbgMessage(pdev, INFORMl4sp, "lm_tcp_rss_update_ramrod_comp(): %d\n",update_stats_type);
1242     switch (update_stats_type) {
1243     case TOE_RSS_UPD_QUIET:
1244         rcq->rss_update_stats_quiet++;
1245         break;
1246     case TOE_RSS_UPD_SLEEPING:
1247         rcq->rss_update_stats_sleeping++;
1248         break;
1249     case TOE_RSS_UPD_DELAYED:
1250         rcq->rss_update_stats_delayed++;
1251         break;
1252     default:
1253         DbgBreak();
1254         break;
1255     }
1256 
1257     /* This is a hack due to the fact the FW has a hard time providing the cid on which the ramrod was sent on */
1258     /* I know that I sent the ramrod on the leading connection so I use it here instead of the cid on the cqe (update cid) */
1259     /* If the driver ever changes the cid on which the rmarod is snt on this line will have to be changed as well - UGLY, UGLY */
1260     rcq->update_cid = LM_SW_LEADING_RSS_CID(pdev);
1261 
1262     /* This is what should have been if the FW alwys put the ramrod cid on these completions
1263     rcq->update_cid = cid;
1264     */
1265     if (update_suspend_rcq) {
1266         lm_tcp_rss_update_suspend_rcq(pdev, rcq);
1267     } else {
1268         rcq->rss_update_processing_delayed++;
1269     }
1270 }
1271 
1272 /* Desciption:
1273  *  Checks whether the rcq processing should be suspended as a result of an rss update
1274  */
lm_tcp_rss_update_suspend_rcq(IN struct _lm_device_t * pdev,IN lm_tcp_rcq_t * rcq)1275 void lm_tcp_rss_update_suspend_rcq(
1276     IN    struct _lm_device_t * pdev,
1277     IN    lm_tcp_rcq_t        * rcq)
1278 {
1279     void * cookie = NULL;
1280     /*  This function is called once when an update completion is encountered and the rcq porcessing is not suspended yet.
1281      *  At all other times it is called only if the rcq processing is already suspended. */
1282     if (rcq->suspend_processing == FALSE)
1283     {
1284         /* decrment the expected completion counter */
1285         mm_atomic_dec(&pdev->params.update_comp_cnt);
1286         /* Toe specific... to determine who completes the ramrod. */
1287         if (mm_atomic_dec(&pdev->params.update_toe_comp_cnt) == 0)
1288         {
1289             /* Everyone is done. Time to return credit to the slowpath ring... */
1290             lm_sq_complete(pdev, CMD_PRIORITY_NORMAL, RAMROD_OPCODE_TOE_RSS_UPDATE,
1291                            TOE_CONNECTION_TYPE, LM_TOE_FW_RSS_ID(pdev, LM_TOE_BASE_RSS_ID(pdev)));
1292         }
1293     }
1294     rcq->suspend_processing = pdev->params.update_toe_comp_cnt ? TRUE : FALSE;
1295 
1296     if (rcq->suspend_processing == FALSE)
1297     {
1298         /* processing was suspended and can now be resumed, try to complete the update ramrod */
1299         DbgMessage(pdev, INFORMl4sp, "lm_tcp_rss_update_suspend_rcq(): calling lm_eth_update_ramrod_comp\n");
1300         if (mm_atomic_dec(&pdev->params.update_suspend_cnt) == 0)
1301         {
1302             if (pdev->slowpath_info.set_rss_cookie)
1303             {
1304                 cookie = (void *)pdev->slowpath_info.set_rss_cookie;
1305                 pdev->slowpath_info.set_rss_cookie = NULL;
1306                 mm_set_done(pdev, rcq->update_cid, cookie);
1307             }
1308         }
1309     }
1310 }
1311 
1312 
1313 
1314 /* Desciption:
1315  *  initiate a caller allocated lm neighbor state
1316  * Assumptions:
1317  *  - caller already zeroed given neigh state
1318  * Returns:
1319  *  SUCCESS or any failure */
lm_tcp_init_neigh_state(struct _lm_device_t * pdev,lm_state_block_t * state_blk,lm_neigh_state_t * neigh,l4_neigh_const_state_t * neigh_const,l4_neigh_cached_state_t * neigh_cached,l4_neigh_delegated_state_t * neigh_delegated)1320 lm_status_t lm_tcp_init_neigh_state(
1321     struct _lm_device_t *pdev,
1322     lm_state_block_t *state_blk,
1323     lm_neigh_state_t *neigh,
1324     l4_neigh_const_state_t *neigh_const,
1325     l4_neigh_cached_state_t *neigh_cached,
1326     l4_neigh_delegated_state_t *neigh_delegated)
1327 {
1328     DbgMessage(pdev, VERBOSEl4sp, "###lm_tcp_init_neigh_state\n");
1329     DbgBreakIf(!(pdev && state_blk && neigh && neigh_const && neigh_cached && neigh_delegated));
1330 
1331     neigh->hdr.state_blk    = state_blk;
1332     neigh->hdr.state_id     = STATE_ID_NEIGH;
1333     neigh->hdr.status       = STATE_STATUS_NORMAL;
1334     d_list_push_tail(&state_blk->neigh_list, &neigh->hdr.link);
1335     neigh->num_dependents   = 0;
1336 
1337     mm_memcpy(&neigh->neigh_cached, neigh_cached, sizeof(neigh->neigh_cached));
1338     mm_memcpy(&neigh->neigh_const, neigh_const, sizeof(neigh->neigh_const));
1339     mm_memcpy(&neigh->neigh_delegated, neigh_delegated, sizeof(neigh->neigh_delegated));
1340 
1341     neigh->host_reachability_time   = 0; /* SHOULD BE: (mm_get_current_time() - neigh_cached->host_reachability_delta)   */
1342     neigh->nic_reachability_time    = 0; /* SHOULD BE: (mm_get_current_time() - neigh_delegated->nic_reachability_delta) */
1343     neigh->stale                    = 0;
1344 
1345     return LM_STATUS_SUCCESS;
1346 }
1347 
1348 /* Desciption:
1349  *  initiate a caller allocated lm path state
1350  * Assumptions:
1351  *  - caller already zeroed given path state
1352  * Returns:
1353  *  SUCCESS or any failure */
lm_tcp_init_path_state(struct _lm_device_t * pdev,lm_state_block_t * state_blk,lm_path_state_t * path,lm_neigh_state_t * neigh,l4_path_const_state_t * path_const,l4_path_cached_state_t * path_cached,l4_path_delegated_state_t * path_delegated)1354 lm_status_t lm_tcp_init_path_state(
1355     struct _lm_device_t *pdev,
1356     lm_state_block_t *state_blk,
1357     lm_path_state_t *path,
1358     lm_neigh_state_t *neigh,
1359     l4_path_const_state_t *path_const,
1360     l4_path_cached_state_t *path_cached,
1361     l4_path_delegated_state_t *path_delegated)
1362 {
1363     DbgMessage(pdev, VERBOSEl4sp, "###lm_tcp_init_path_state\n");
1364     DbgBreakIf(!(pdev && state_blk && path && neigh && path_const && path_cached && path_delegated));
1365     DbgBreakIf(neigh->hdr.state_id != STATE_ID_NEIGH || neigh->hdr.status != STATE_STATUS_NORMAL);
1366 
1367     path->hdr.state_blk     = state_blk;
1368     path->hdr.state_id      = STATE_ID_PATH;
1369     path->hdr.status        = STATE_STATUS_NORMAL;
1370     d_list_push_tail(&state_blk->path_list, &path->hdr.link);
1371     path->neigh             = neigh;
1372     neigh->num_dependents++;
1373     path->num_dependents    = 0;
1374 
1375     mm_memcpy(&path->path_cached, path_cached, sizeof(path->path_cached));
1376     mm_memcpy(&path->path_const, path_const, sizeof(path->path_const));
1377     mm_memcpy(&path->path_delegated, path_delegated, sizeof(path->path_delegated));
1378 
1379    return LM_STATUS_SUCCESS;
1380 }
1381 
1382 /* Desciption:
1383  *  initiate a caller allocated lm tcp state
1384  * Assumptions:
1385  *  - caller already zeroed given tcp state
1386  *  - caller already set the tx/rx_con pointers of the given
1387  *    tcp state to pre-allocated tx/rx cons
1388  * Returns:
1389  *  SUCCESS or any failure */
lm_tcp_init_tcp_state(struct _lm_device_t * pdev,lm_state_block_t * state_blk,lm_tcp_state_t * tcp,lm_path_state_t * path,l4_tcp_const_state_t * tcp_const,l4_tcp_cached_state_t * tcp_cached,l4_tcp_delegated_state_t * tcp_delegated,u32_t tcp_cid_addr)1390 lm_status_t lm_tcp_init_tcp_state(
1391     struct _lm_device_t *pdev,
1392     lm_state_block_t *state_blk,
1393     lm_tcp_state_t *tcp,
1394     lm_path_state_t *path,
1395     l4_tcp_const_state_t *tcp_const,
1396     l4_tcp_cached_state_t *tcp_cached,
1397     l4_tcp_delegated_state_t *tcp_delegated,
1398     u32_t tcp_cid_addr)
1399 {
1400     DbgMessage(pdev, VERBOSEl4sp, "###lm_tcp_init_tcp_state, ptr=%p, src_port=%d\n", tcp, tcp_const->src_port);
1401     DbgBreakIf(!(pdev && state_blk && tcp && path && tcp_const && tcp_cached && tcp_delegated));
1402     DbgBreakIf(path->hdr.state_id != STATE_ID_PATH || path->hdr.status != STATE_STATUS_NORMAL);
1403 
1404     /* We need to determine the ULP_TYPE and get ourselves a cid if one doesn't already exist */
1405     if (!tcp_cid_addr)
1406     {
1407         tcp->ulp_type = TOE_CONNECTION_TYPE;
1408     }
1409     else
1410     {
1411         tcp->ulp_type = lm_map_cid_to_proto(pdev, tcp_cid_addr);
1412         tcp->cid = tcp_cid_addr;
1413         lm_set_cid_resc(pdev, TOE_CONNECTION_TYPE, tcp, tcp_cid_addr);
1414     }
1415 
1416     tcp->hdr.state_blk     = state_blk;
1417     tcp->hdr.state_id      = STATE_ID_TCP;
1418     tcp->hdr.status        = STATE_STATUS_INIT;
1419     d_list_push_tail(&state_blk->tcp_list, &tcp->hdr.link);
1420     tcp->path = path;
1421     path->num_dependents++;
1422 
1423     if (tcp->ulp_type == TOE_CONNECTION_TYPE)
1424     {
1425         pdev->toe_info.stats.total_ofld++;
1426     }
1427     else if (tcp->ulp_type == ISCSI_CONNECTION_TYPE)
1428     {
1429         pdev->iscsi_info.run_time.stats.total_ofld++;
1430     }
1431 
1432     mm_memcpy(&tcp->tcp_cached, tcp_cached, sizeof(tcp->tcp_cached));
1433     mm_memcpy(&tcp->tcp_const, tcp_const, sizeof(tcp->tcp_const));
1434     mm_memcpy(&tcp->tcp_delegated, tcp_delegated, sizeof(tcp->tcp_delegated));
1435 
1436     /* the rest of the tcp state's fields that require initialization value other than 0,
1437      * will be initialized later (when lm_tcp_init_tx_con/lm_tcp_init_rx_con/lm_tcp_init_tcp_context are called) */
1438 
1439     return LM_STATUS_SUCCESS;
1440 }
1441 
1442 /* calc connection's mss according to path_mtu and remote MSS */
_lm_tcp_calc_mss(u32_t path_mtu,u16_t remote_mss,u8_t is_ipv6,u8_t ts_enabled,u8_t llc_snap_enabled,u8_t vlan_enabled)1443 static u32_t _lm_tcp_calc_mss(u32_t path_mtu, u16_t remote_mss, u8_t is_ipv6, u8_t ts_enabled,
1444                               u8_t llc_snap_enabled, u8_t vlan_enabled)
1445 {
1446 #define MIN_MTU         576 /* rfc 793 */
1447 #define IPV4_HDR_LEN    20
1448 #define IPV6_HDR_LEN    40
1449 #define TCP_HDR_LEN     20
1450 #define TCP_OPTION_LEN  12
1451 #define LLC_SNAP_LEN     8
1452 #define VLAN_LEN         4
1453 
1454     u32_t mss  = 0;
1455     u32_t hdrs = TCP_HDR_LEN;
1456 
1457     UNREFERENCED_PARAMETER_(vlan_enabled);
1458     UNREFERENCED_PARAMETER_(llc_snap_enabled);
1459 
1460     if(is_ipv6) {
1461         hdrs += IPV6_HDR_LEN;
1462     } else {
1463         hdrs += IPV4_HDR_LEN;
1464     }
1465 #ifdef LLC_SNAP_HEADER_ROOMS_WITH_PAYLOAD
1466 /*
1467     LLC_SNAP_HEADER_ROOMS_WITH_PAYLOAD never was defined. Nobody remembers when LLC/SNAP protocol was tested but
1468     in any case don't use payload to room LLC/SNAP header
1469 */
1470     if (llc_snap_enabled) {
1471         hdrs += LLC_SNAP_LEN;
1472     }
1473 #endif
1474 #ifdef VLAN_HEADER_ROOMS_WITH_PAYLOAD
1475 /*
1476     VLAN_HEADER_ROOMS_WITH_PAYLOAD never was defined and below strings is reminder that once there was problem of
1477     decreasing (-4) data payload size because of VLAN header rooming with payload CQ39709
1478 */
1479     if (vlan_enabled) {
1480         hdrs += VLAN_LEN;
1481     }
1482 #endif
1483     DbgBreakIf(path_mtu < MIN_MTU);
1484     mss = path_mtu - hdrs;
1485 
1486     if(mss > remote_mss) {
1487         mss = remote_mss;
1488     }
1489     if(ts_enabled) {
1490         mss -= TCP_OPTION_LEN;
1491     }
1492     if (!mss) {
1493         DbgBreakIf(!mss);
1494         mss = 1; /*mss may be used as divider, so let's prevent division by zero*/
1495     }
1496     return mss;
1497 }
1498 
1499 /** Description
1500  *  calculate the fragment count for a given initial receive window and mss
1501  *  The fragment count is based on the maximum size we will need to do for a single
1502  *  indication
1503  */
_lm_tcp_calc_frag_cnt(lm_device_t * pdev,u32_t initial_rcv_wnd,u32_t mss)1504 static u32_t _lm_tcp_calc_frag_cnt(lm_device_t * pdev, u32_t initial_rcv_wnd, u32_t mss)
1505 {
1506     u32_t frag_cnt;
1507 
1508     frag_cnt = initial_rcv_wnd / mss;
1509     if (frag_cnt < (0x10000 / mss)) {
1510         frag_cnt = 0x10000 / mss;
1511     }
1512 
1513     if ((pdev->params.l4_max_rcv_wnd_size > 0x10000) && (frag_cnt > (pdev->params.l4_max_rcv_wnd_size / mss))) {
1514         frag_cnt = pdev->params.l4_max_rcv_wnd_size / mss;
1515     }
1516     frag_cnt = frag_cnt * 2 + 1;
1517 
1518     if (pdev->params.l4_max_gen_buf_cnt && (frag_cnt > pdev->params.l4_max_gen_buf_cnt)) {
1519         frag_cnt = pdev->params.l4_max_gen_buf_cnt;
1520     }
1521     return frag_cnt;
1522 }
1523 
lm_tcp_calc_frag_cnt(lm_device_t * pdev,lm_tcp_state_t * tcp)1524 u32_t lm_tcp_calc_frag_cnt(
1525         lm_device_t * pdev,
1526         lm_tcp_state_t * tcp
1527     )
1528 {
1529     u32_t mss, frag_cnt;
1530     DbgBreakIf(!(pdev && tcp));
1531     mss = _lm_tcp_calc_mss(tcp->path->path_cached.path_mtu,
1532                            tcp->tcp_const.remote_mss,
1533                            (tcp->path->path_const.ip_version == IP_VERSION_IPV6),
1534                            tcp->tcp_const.tcp_flags & TCP_FLAG_ENABLE_TIME_STAMP,
1535                            FALSE,
1536                            tcp->path->neigh->neigh_const.vlan_tag != 0);
1537 
1538     frag_cnt = _lm_tcp_calc_frag_cnt(pdev, tcp->tcp_cached.initial_rcv_wnd, mss);
1539 
1540     return frag_cnt;
1541 }
1542 
1543 
1544 
_lm_tcp_init_qe_buffer(struct _lm_device_t * pdev,lm_tcp_qe_buffer_t * qe_buffer,u8_t * mem_virt,u32_t cnt,u8_t cqe_size)1545 static void _lm_tcp_init_qe_buffer(
1546     struct _lm_device_t * pdev,
1547     lm_tcp_qe_buffer_t  * qe_buffer,
1548     u8_t                * mem_virt,
1549     u32_t                 cnt,
1550     u8_t                  cqe_size)
1551 {
1552     UNREFERENCED_PARAMETER_(pdev);
1553 
1554     qe_buffer->left    = cnt;
1555     qe_buffer->first   = (char *)mem_virt;
1556     qe_buffer->head    = qe_buffer->first;
1557     qe_buffer->tail    = qe_buffer->first;
1558     qe_buffer->last    = qe_buffer->first;
1559     qe_buffer->last   += (qe_buffer->left-1)*cqe_size;
1560     qe_buffer->qe_size = cqe_size;
1561 }
1562 
1563 /** Description
1564  *  function calculates the amount of virtual memory required for the RX connection
1565  * Return
1566  *  amount of virtual memory required
1567  */
lm_tcp_rx_con_get_virt_size(struct _lm_device_t * pdev,lm_tcp_state_t * tcp)1568 u32_t lm_tcp_rx_con_get_virt_size(struct _lm_device_t * pdev, lm_tcp_state_t * tcp)
1569 {
1570     u32_t frag_cnt;
1571     u32_t mem_size;
1572     u32_t mss;
1573 
1574     /* The calculation for frag_cnt is based on the calculation from Teton's init_rx_tcp_resc()
1575      * also the assertion is taken from Teton */
1576     DbgBreakIf(tcp->tcp_cached.initial_rcv_wnd == 0);
1577     /* the rx_con may not be initialized at this state, therefore we can't rely on the mss being initialized. */
1578     mss = _lm_tcp_calc_mss(tcp->path->path_cached.path_mtu,
1579                            tcp->tcp_const.remote_mss,
1580                            (tcp->path->path_const.ip_version == IP_VERSION_IPV6),
1581                            tcp->tcp_const.tcp_flags & TCP_FLAG_ENABLE_TIME_STAMP,
1582                            pdev->ofld_info.l4_params.flags & OFLD_PARAM_FLAG_SNAP_ENCAP,
1583                            tcp->path->neigh->neigh_const.vlan_tag  != 0);
1584 
1585     frag_cnt = _lm_tcp_calc_frag_cnt(pdev, tcp->tcp_cached.initial_rcv_wnd, mss);
1586 
1587 
1588     DbgMessage(pdev, INFORMl4rx, "Calc #frags for rx-con initial_rcv_wnd: %d frag_cnt: %d\n", tcp->tcp_cached.initial_rcv_wnd, frag_cnt);
1589 
1590     mem_size = sizeof(lm_frag_list_t) + (frag_cnt - 1)*sizeof(lm_frag_t);
1591 
1592     return mem_size;
1593 }
1594 
lm_tcp_init_tcp_sp_data_mem(struct _lm_device_t * pdev,lm_tcp_state_t * tcp)1595 void lm_tcp_init_tcp_sp_data_mem(
1596     struct _lm_device_t *pdev,
1597     lm_tcp_state_t *tcp
1598     )
1599 {
1600     /* slow-path physical memory */
1601     /* allocation of physical area for sp request */
1602     lm_sp_req_manager_t *sp_req_mgr = NULL;
1603 
1604     sp_req_mgr = lm_cid_sp_req_mgr(pdev, tcp->cid);
1605     if CHK_NULL(sp_req_mgr)
1606     {
1607         DbgBreakIf(!sp_req_mgr);
1608         return;
1609     }
1610     DbgBreakIf(sp_req_mgr->sp_data_phys_addr.as_u32.low & CACHE_LINE_SIZE_MASK);
1611     tcp->sp_req_data.phys_addr = sp_req_mgr->sp_data_phys_addr;
1612     tcp->sp_req_data.virt_addr = sp_req_mgr->sp_data_virt_addr;
1613 }
1614 
1615 
lm_tcp_init_tcp_phys_mem(struct _lm_device_t * pdev,lm_tcp_state_t * tcp,lm_tcp_phy_mem_block_t * phy_mblk)1616 void lm_tcp_init_tcp_phys_mem(
1617     struct _lm_device_t *pdev,
1618     lm_tcp_state_t *tcp,
1619     lm_tcp_phy_mem_block_t * phy_mblk)
1620 {
1621     lm_tcp_con_t * con;
1622     u32_t mem_size;
1623     u16_t page_cnt,page_idx;
1624     u32_t idx = 0;
1625     u8_t  bd_size;
1626     u8_t  block_idx;
1627 
1628     #if (LM_PAGE_SIZE != 4096)
1629     #error (LM_PAGE_SIZE != 4096) /* currently FW assumes a tx chain page is 4KB */
1630     #endif
1631 
1632     /* Init physical memory */
1633     /* bd-chains */
1634     con = tcp->tx_con;
1635     page_cnt = (u16_t)pdev->params.l4_tx_chain_page_cnt;
1636     bd_size = sizeof(struct toe_tx_bd);
1637     block_idx = 0;
1638     for (idx = 0 ; idx < 2; idx++) {
1639         mem_size = LM_PAGE_SIZE;
1640         for (page_idx = 0; page_idx < page_cnt; page_idx++) {
1641             if (phy_mblk[block_idx].left < mem_size) {
1642                 block_idx++;
1643                 DbgBreakIf(block_idx == pdev->params.l4_num_of_blocks_per_connection);
1644             }
1645             DbgBreakIf(phy_mblk[block_idx].left < mem_size);
1646             lm_bd_chain_add_page(pdev,&con->bd_chain,phy_mblk[block_idx].free, phy_mblk[block_idx].free_phy, bd_size, TRUE);
1647             phy_mblk[block_idx].free += mem_size;
1648             phy_mblk[block_idx].left -= mem_size;
1649             LM_INC64(&phy_mblk[block_idx].free_phy, mem_size);
1650         }
1651         /* rx-con */
1652         con = tcp->rx_con;
1653         page_cnt = (u16_t)pdev->params.l4_rx_chain_page_cnt;
1654         bd_size = sizeof(struct toe_rx_bd);
1655     }
1656 
1657     /* slow-path physical memory */
1658     /* allocation of physical area for sp request */
1659     mem_size = TOE_SP_PHYS_DATA_SIZE;
1660 
1661     if (phy_mblk[block_idx].left < mem_size) {
1662         block_idx++;
1663         DbgBreakIf(block_idx == pdev->params.l4_num_of_blocks_per_connection);
1664     }
1665     DbgBreakIf(mem_size > phy_mblk[block_idx].left);
1666     DbgBreakIf(phy_mblk[block_idx].free_phy.as_u32.low & CACHE_LINE_SIZE_MASK);
1667     tcp->sp_req_data.phys_addr = phy_mblk[block_idx].free_phy;
1668     tcp->sp_req_data.virt_addr = (lm_tcp_slow_path_phys_data_t *)phy_mblk[block_idx].free;
1669     mm_memset(tcp->sp_req_data.virt_addr, 0, mem_size);
1670     phy_mblk[block_idx].free += mem_size;
1671     phy_mblk[block_idx].left -= mem_size;
1672     LM_INC64(&phy_mblk[block_idx].free_phy, mem_size);
1673 
1674     /* doorbell data */
1675     /* init tx part */
1676     mem_size = TOE_DB_TX_DATA_SIZE;
1677     if (phy_mblk[block_idx].left < mem_size) {
1678         block_idx++;
1679         DbgBreakIf(block_idx == pdev->params.l4_num_of_blocks_per_connection);
1680     }
1681     DbgBreakIf(mem_size > phy_mblk[block_idx].left);
1682     DbgBreakIf(phy_mblk[block_idx].free_phy.as_u32.low & CACHE_LINE_SIZE_MASK);
1683     tcp->tx_con->phys_db_data = phy_mblk[block_idx].free_phy;
1684     tcp->tx_con->db_data.tx = (volatile struct toe_tx_db_data *)phy_mblk[block_idx].free;
1685     tcp->tx_con->db_data.tx->flags = 0;
1686     tcp->tx_con->db_data.tx->bds_prod = 0;
1687     /* init tx db data to snd.una (+ sizeof sent unacked data that will
1688      * be initiated when sent unacked data is posted): */
1689     tcp->tx_con->db_data.tx->bytes_prod_seq = tcp->tcp_delegated.send_una;
1690     phy_mblk[block_idx].free += mem_size;
1691     phy_mblk[block_idx].left -= mem_size;
1692     LM_INC64(&phy_mblk[block_idx].free_phy, mem_size);
1693 
1694 
1695     /* init rx part */
1696     if (phy_mblk[block_idx].left < mem_size) {
1697         block_idx++;
1698         DbgBreakIf(block_idx == pdev->params.l4_num_of_blocks_per_connection);
1699     }
1700     mem_size = TOE_DB_RX_DATA_SIZE;
1701     DbgBreakIf(mem_size > phy_mblk[block_idx].left);
1702     DbgBreakIf(phy_mblk[block_idx].free_phy.as_u32.low & CACHE_LINE_SIZE_MASK);
1703     tcp->rx_con->phys_db_data = phy_mblk[block_idx].free_phy;
1704     tcp->rx_con->db_data.rx = (volatile struct toe_rx_db_data *)phy_mblk[block_idx].free;
1705     phy_mblk[block_idx].free += mem_size;
1706     phy_mblk[block_idx].left -= mem_size;
1707     LM_INC64(&phy_mblk[block_idx].free_phy, mem_size);
1708     tcp->rx_con->db_data.rx->rcv_win_right_edge = tcp->tcp_delegated.recv_win_seq;
1709     /* we also need to initialize the driver copy of the rcv_win_right_edge */
1710     tcp->rx_con->u.rx.sws_info.drv_rcv_win_right_edge = tcp->tcp_delegated.recv_win_seq;
1711     tcp->rx_con->db_data.rx->bds_prod = 0;
1712     tcp->rx_con->db_data.rx->bytes_prod = 0;
1713     tcp->rx_con->db_data.rx->consumed_grq_bytes = 0;
1714     tcp->rx_con->db_data.rx->flags = 0;
1715     tcp->rx_con->db_data.rx->reserved1 = 0;
1716 }
1717 
lm_tcp_init_tcp_virt_mem(struct _lm_device_t * pdev,lm_tcp_state_t * tcp,lm_tcp_mem_block_t * mblk)1718 void lm_tcp_init_tcp_virt_mem(
1719     struct _lm_device_t *pdev,
1720     lm_tcp_state_t *tcp,
1721     lm_tcp_mem_block_t * mblk)
1722 {
1723     lm_tcp_con_t * con;
1724     u32_t mem_size;
1725 
1726     u32_t idx = 0;
1727     u8_t  cqe_size;
1728 
1729     con = tcp->tx_con;
1730     cqe_size = sizeof(struct toe_tx_cqe);
1731     for (idx = 0; idx < 2; idx++) {
1732         /* allocation of buffers for history CQEs */
1733         if (pdev->params.l4_history_cqe_cnt) {
1734             mem_size = pdev->params.l4_history_cqe_cnt*cqe_size;
1735             DbgBreakIf(mblk->left < mem_size);
1736             _lm_tcp_init_qe_buffer(pdev, &con->history_cqes, mblk->free, pdev->params.l4_history_cqe_cnt, cqe_size);
1737             mblk->free += mem_size;
1738             mblk->left -= mem_size;
1739         } else {
1740             DbgBreakMsg("MichalS: Currently History Count = 0 is not SUPPORTED\n");
1741         }
1742         con = tcp->rx_con;
1743         cqe_size = sizeof(struct toe_rx_cqe);
1744     }
1745 
1746     /* rx frag list */
1747     mem_size = lm_tcp_rx_con_get_virt_size(pdev, tcp);
1748     DbgBreakIf(mblk->left < mem_size);
1749 
1750     tcp->rx_con->u.rx.gen_info.frag_list = (lm_frag_list_t *)mblk->free;
1751     mblk->free += mem_size;
1752     mblk->left -= mem_size;
1753 
1754 }
lm_tcp_init_tcp_resc(struct _lm_device_t * pdev,lm_tcp_state_t * tcp,lm_tcp_mem_block_t * mblk,lm_tcp_phy_mem_block_t * phy_mblk)1755 lm_status_t lm_tcp_init_tcp_resc(
1756     struct _lm_device_t *pdev,
1757     lm_tcp_state_t *tcp,
1758     lm_tcp_mem_block_t * mblk,
1759     lm_tcp_phy_mem_block_t * phy_mblk)
1760 {
1761     DbgMessage(pdev, VERBOSEl4sp, "###lm_tcp_init_tx_con\n");
1762     DbgBreakIf(!(pdev && tcp));
1763 
1764     /* tx-specific */
1765     tcp->tx_con->type = TCP_CON_TYPE_TX;
1766     mm_memset(&tcp->tx_con->u.tx, 0, sizeof(lm_tcp_con_tx_t));
1767 
1768     tcp->tx_con->flags = (TCP_POST_BLOCKED | TCP_COMP_BLOCKED);
1769     tcp->tx_con->tcp_state = tcp;
1770     s_list_init(&tcp->tx_con->active_tb_list, NULL, NULL, 0);
1771 
1772     /* rx-specific */
1773     tcp->rx_con->type = TCP_CON_TYPE_RX;
1774     mm_memset(&tcp->rx_con->u.rx, 0, sizeof(lm_tcp_con_rx_t));
1775 
1776     tcp->rx_con->flags = (TCP_POST_BLOCKED | TCP_COMP_BLOCKED);
1777     tcp->rx_con->tcp_state = tcp;
1778     s_list_init(&tcp->rx_con->active_tb_list, NULL, NULL, 0);
1779 
1780     lm_tcp_init_tcp_phys_mem(pdev,tcp,phy_mblk);
1781 
1782     lm_tcp_init_tcp_virt_mem(pdev,tcp,mblk);
1783 
1784 
1785     tcp->rx_con->u.rx.sws_info.mss = tcp->tx_con->u.tx.mss =
1786         _lm_tcp_calc_mss(tcp->path->path_cached.path_mtu,
1787                          tcp->tcp_const.remote_mss,
1788                          (tcp->path->path_const.ip_version == IP_VERSION_IPV6),
1789                          tcp->tcp_const.tcp_flags & TCP_FLAG_ENABLE_TIME_STAMP,
1790                          pdev->ofld_info.l4_params.flags & OFLD_PARAM_FLAG_SNAP_ENCAP,
1791                          tcp->path->neigh->neigh_const.vlan_tag  != 0);
1792 
1793 
1794 
1795     tcp->rx_con->u.rx.gen_info.max_frag_count  = _lm_tcp_calc_frag_cnt(pdev, tcp->tcp_cached.initial_rcv_wnd, tcp->rx_con->u.rx.sws_info.mss);
1796     return LM_STATUS_SUCCESS;
1797 }
1798 
1799 /* Function returns the required size for a virtual connection. If tcp_state is given,
1800  * the size is calculated for the specific connection given, o/w the default size is given.
1801  */
lm_tcp_get_virt_size(struct _lm_device_t * pdev,lm_tcp_state_t * tcp_state)1802 u32_t lm_tcp_get_virt_size(
1803     struct _lm_device_t * pdev,
1804     lm_tcp_state_t * tcp_state)
1805 {
1806     u32_t       virt_size = 0;
1807     u32_t       mss       = 0;
1808     u32_t const chain_idx = LM_SW_LEADING_RSS_CID(pdev);
1809 
1810     virt_size =
1811         pdev->params.l4_history_cqe_cnt*sizeof(struct toe_tx_cqe)   +
1812         pdev->params.l4_history_cqe_cnt*sizeof(struct toe_rx_cqe);
1813 
1814     if (tcp_state)
1815     {
1816         virt_size += lm_tcp_rx_con_get_virt_size(pdev,tcp_state);
1817     }
1818     else
1819     {
1820         #define LM_TCP_DEFAULT_WINDOW_SIZE 0x10000
1821 
1822         if(CHK_NULL(pdev) ||
1823         ERR_IF((ARRSIZE(pdev->params.l2_cli_con_params) <= chain_idx) ||
1824                 (CHIP_IS_E1H(pdev) && (chain_idx >= ETH_MAX_RX_CLIENTS_E1H)) || /* TODO E2 add IS_E2*/
1825                 (CHIP_IS_E1(pdev) && (chain_idx >= ETH_MAX_RX_CLIENTS_E1)) ))
1826         {
1827             DbgBreakIf(1);
1828             return 0;
1829         }
1830 
1831         mss = _lm_tcp_calc_mss(pdev->params.l2_cli_con_params[chain_idx].mtu, 0xffff, FALSE, FALSE, FALSE, FALSE);
1832         virt_size += sizeof(lm_frag_list_t) +
1833             (_lm_tcp_calc_frag_cnt(pdev, LM_TCP_DEFAULT_WINDOW_SIZE, mss) - 1)*sizeof(lm_frag_t);
1834     }
1835     return virt_size;
1836 }
1837 
lm_tcp_get_phys_size(struct _lm_device_t * pdev)1838 u32_t lm_tcp_get_phys_size(
1839     struct _lm_device_t * pdev)
1840 {
1841     u32_t mem_size = TOE_SP_PHYS_DATA_SIZE + TOE_DB_TX_DATA_SIZE + TOE_DB_RX_DATA_SIZE;
1842 
1843     mem_size = ((mem_size / LM_PAGE_SIZE) + 1) * LM_PAGE_SIZE;
1844 
1845     mem_size += pdev->params.l4_rx_chain_page_cnt*LM_PAGE_SIZE + /* rx bd-chain */
1846             pdev->params.l4_tx_chain_page_cnt*LM_PAGE_SIZE; /* tx bd-chain */
1847 
1848     return mem_size;
1849 }
1850 
lm_tcp_post_buffered_data(struct _lm_device_t * pdev,lm_tcp_state_t * tcp,d_list_t * buffered_data)1851 lm_status_t lm_tcp_post_buffered_data(
1852     struct _lm_device_t *pdev,
1853     lm_tcp_state_t *tcp,
1854     d_list_t *buffered_data)
1855 {
1856     lm_tcp_con_rx_gen_info_t * gen_info     = NULL;
1857     lm_tcp_gen_buf_t         * curr_gen_buf = NULL;
1858 
1859     DbgBreakIf(!buffered_data);
1860     if(!d_list_is_empty(buffered_data)) {
1861         gen_info = &tcp->rx_con->u.rx.gen_info;
1862         curr_gen_buf = (lm_tcp_gen_buf_t *)d_list_peek_head(buffered_data);
1863         DbgBreakIf(!d_list_is_empty(&gen_info->peninsula_list));
1864         d_list_add_head(&gen_info->peninsula_list, buffered_data);
1865         /* initialize peninsula_nbytes */
1866         while (curr_gen_buf) {
1867             gen_info->peninsula_nbytes += curr_gen_buf->placed_bytes;
1868             curr_gen_buf = (lm_tcp_gen_buf_t *)d_list_next_entry(&curr_gen_buf->link);
1869         }
1870 
1871         DbgBreakIf(tcp->rx_con->flags & TCP_INDICATE_REJECTED);
1872         tcp->rx_con->flags |= TCP_RX_COMP_DEFERRED; /* TCP_INDICATE_REJECTED was here to wait rx buffers from OS.
1873                                                        With TCP_RX_COMP_DEFERRED flag processing of completion
1874                                                        SP_REQUEST_INITIATE_OFFLOAD will indicate the buffered data
1875                                                        if it needed */
1876     }
1877 
1878 
1879     return LM_STATUS_SUCCESS;
1880 }
1881 
1882 /* calculate tcp pseudo check sum.
1883  * input and retured value in _network_ order */
lm_tcp_calc_tcp_pseudo_checksum(struct _lm_device_t * pdev,u32_t n_src_ip[4],u32_t n_dst_ip[4],u8_t ip_type)1884 static u16_t lm_tcp_calc_tcp_pseudo_checksum(
1885     struct _lm_device_t *pdev,
1886     u32_t n_src_ip[4],
1887     u32_t n_dst_ip[4],
1888     u8_t ip_type)
1889 {
1890 #define D_IP_PROTOCOL_TCP 6
1891     u32_t sum = 0;
1892     int i;
1893 
1894     if(ip_type == IP_VERSION_IPV4) { /* IPV4 */
1895         sum += n_src_ip[0] & 0xffff;
1896         sum += (n_src_ip[0]>>16) & 0xffff;
1897 
1898         sum += n_dst_ip[0] & 0xffff;
1899         sum += (n_dst_ip[0]>>16) & 0xffff;
1900     } else {
1901         for (i = 0; i < 4; i++) {
1902             sum += n_src_ip[i] & 0xffff;
1903             sum += (n_src_ip[i]>>16) & 0xffff;
1904         }
1905         for (i = 0; i < 4; i++) {
1906             sum += n_dst_ip[i] & 0xffff;
1907             sum += (n_dst_ip[i]>>16) & 0xffff;
1908         }
1909     }
1910 
1911     sum +=  HTON16((u16_t)(D_IP_PROTOCOL_TCP));
1912 
1913    /* Fold 32-bit sum to 16 bits */
1914    while( sum >> 16 ) {
1915        sum = (sum & 0xffff) + (sum >> 16);
1916    }
1917 
1918    DbgMessage(pdev, VERBOSEl4sp,
1919                "_lm_tcp_calc_tcp_pseudo_checksum: n_src_ip=%x, n_dst_ip=%x, (u16_t)sum=%x\n",
1920                n_src_ip[0], n_dst_ip[0], (u16_t)sum);
1921 
1922    return (u16_t)sum;
1923 }
1924 
1925 /* find the bd in the bd chain that contains snd_nxt, the offset of snd_nxt
1926  * within this bd, and the base address of the page that contains this bd. */
lm_locate_snd_next_info(lm_tcp_con_t * tx_con,u32_t snd_nxt,u32_t snd_una,u16_t * bd_idx,u16_t * bd_offset,lm_address_t * page_addr)1927 static lm_status_t lm_locate_snd_next_info(
1928     lm_tcp_con_t * tx_con,
1929     u32_t          snd_nxt,
1930     u32_t          snd_una,
1931     u16_t        * bd_idx,
1932     u16_t        * bd_offset,
1933     lm_address_t * page_addr)
1934 {
1935     u32_t              cur_seq   = 0;
1936     struct toe_tx_bd * cur_tx_bd = NULL;
1937 
1938     /* we assume that the first byte of the first application buffer equals SND.UNA
1939      * we need to find SND.NXT relative to this */
1940     DbgMessage(NULL, VERBOSEl4sp, "### lm_locate_snd_next_info\n");
1941 
1942     /* want to make sure the consumer is still zero ... */
1943     if ((tx_con->bd_chain.cons_idx != 0) ||
1944         (S32_SUB(tx_con->bytes_post_cnt ,S32_SUB(snd_nxt, snd_una)) < 0) ||
1945         (tx_con->bytes_comp_cnt))
1946     {
1947         DbgBreakIf(tx_con->bd_chain.cons_idx != 0);
1948         DbgBreakIf(S32_SUB(tx_con->bytes_post_cnt ,S32_SUB(snd_nxt, snd_una)) < 0);
1949         DbgBreakIf(tx_con->bytes_comp_cnt); /* nothing should be completed yet */
1950         return LM_STATUS_INVALID_PARAMETER;
1951     }
1952 
1953     *bd_idx = 0;
1954     *bd_offset = 0;
1955     *page_addr = tx_con->bd_chain.bd_chain_phy;
1956 
1957     if (lm_bd_chain_prod_idx(&tx_con->bd_chain) == 0) {
1958         /* If the producer is '0', chain is empty. bd_idx/offset are 0 */
1959         if ((tx_con->bytes_post_cnt > 0) ||
1960             (snd_nxt != snd_una))
1961         {
1962             DbgBreakIf(tx_con->bytes_post_cnt > 0);
1963             /* Notice: This case was seen and its a bug in the MS stack: delegated: snd_nxt > snd_una but WITHOUT unacked data */
1964             DbgBreakIf(snd_nxt != snd_una);
1965             return LM_STATUS_INVALID_PARAMETER;
1966         }
1967         return LM_STATUS_SUCCESS;
1968     }
1969 
1970     cur_seq    = snd_una;
1971     cur_tx_bd  = (struct toe_tx_bd *)tx_con->bd_chain.bd_chain_virt;
1972 
1973     while ((*bd_idx < lm_bd_chain_prod_idx(&tx_con->bd_chain))
1974         && S32_SUB(snd_nxt, cur_seq + cur_tx_bd->size) >= 0) {
1975         /* Advance to the next bd. */
1976         cur_seq += cur_tx_bd->size;
1977         lm_bd_chain_incr_bd(&tx_con->bd_chain, page_addr, (void**)&cur_tx_bd, bd_idx);
1978     }
1979 
1980     /* make sure assignment is legit. */
1981     if ((S32_SUB(snd_nxt, cur_seq) < 0) ||
1982         (S32_SUB(snd_nxt, cur_seq) > 0xffff))
1983     {
1984         DbgBreakIf(S32_SUB(snd_nxt, cur_seq) < 0 );
1985         DbgBreakIf(S32_SUB(snd_nxt, cur_seq) > 0xffff );
1986         return LM_STATUS_INVALID_PARAMETER;
1987     }
1988 
1989     *bd_offset = S32_SUB(snd_nxt, cur_seq);
1990     return LM_STATUS_SUCCESS;
1991 }
1992 
_lm_tcp_init_xstorm_toe_context(struct _lm_device_t * pdev,lm_tcp_state_t * tcp)1993 static lm_status_t _lm_tcp_init_xstorm_toe_context(
1994     struct _lm_device_t *pdev,
1995     lm_tcp_state_t * tcp)
1996 {
1997     struct toe_context * ctx                = (struct toe_context *)tcp->ctx_virt;
1998     struct xstorm_toe_ag_context * xctx_ag  = &ctx->xstorm_ag_context;
1999     struct xstorm_toe_st_context * xctx_st  = &ctx->xstorm_st_context.context;
2000     lm_address_t                  mem_phys  = {{0}};
2001     u16_t                         bd_idx    = 0;
2002     u16_t                         bd_offset = 0;
2003     lm_status_t                   lm_status = LM_STATUS_SUCCESS;
2004 
2005     /* xstorm ag context */
2006     mm_memset(xctx_ag, 0, sizeof(struct xstorm_toe_ag_context));
2007 
2008     if(tcp->tcp_cached.tcp_flags & TCP_FLAG_ENABLE_NAGLING)
2009     {
2010         xctx_ag->agg_vars1 |= XSTORM_TOE_AG_CONTEXT_NAGLE_EN;
2011     }
2012     /* Initialize Send-Una info */
2013     mem_phys = lm_bd_chain_phys_addr(&tcp->tx_con->bd_chain, 0);
2014     xctx_ag->cmp_bd_cons           = 0;                           /* idx of bd with snd.una - always 0 */
2015     xctx_ag->cmp_bd_page_0_to_31   = mem_phys.as_u32.low;         /* page that includes the snd.una */
2016     xctx_ag->cmp_bd_page_32_to_63  = mem_phys.as_u32.high;        /* page that includes the snd.una */
2017     xctx_ag->cmp_bd_start_seq      = tcp->tcp_delegated.send_una; /* the sequence number of the first byte in the bd which holds SndUna */
2018 
2019     /* more_to_send: The difference between SndNxt and the last byte in the bd pointed by bd prod */
2020     if (tcp->tx_con->bytes_comp_cnt)
2021     {
2022         DbgBreakIf(tcp->tx_con->bytes_comp_cnt);
2023         return LM_STATUS_INVALID_PARAMETER;
2024     }
2025     xctx_ag->more_to_send = S32_SUB(tcp->tx_con->bytes_post_cnt,(S32_SUB(tcp->tcp_delegated.send_next,tcp->tcp_delegated.send_una)));
2026     if ((tcp->tx_con->flags & TCP_FIN_REQ_POSTED) && !(tcp->tx_con->flags & TCP_FIN_REQ_COMPLETED)) {
2027         xctx_ag->more_to_send--; /* the fin byte on the bd chain is not counted */
2028     }
2029 
2030     /* xstorm st context */
2031     mm_memset(xctx_st, 0, sizeof(struct xstorm_toe_st_context));
2032     lm_status = lm_locate_snd_next_info(tcp->tx_con, tcp->tcp_delegated.send_next, tcp->tcp_delegated.send_una,
2033                             &bd_idx, &bd_offset, &mem_phys);
2034     if (lm_status != LM_STATUS_SUCCESS)
2035     {
2036         return lm_status;
2037     }
2038     xctx_st->toe.tx_bd_cons                   = bd_idx;    /* index of bd that includes snd_nxt */
2039     xctx_st->toe.tx_bd_offset                 = bd_offset; /* offset of snd_nxt within its bd */
2040     xctx_st->toe.tx_bd_page_base_hi           = mem_phys.as_u32.high;
2041     xctx_st->toe.tx_bd_page_base_lo           = mem_phys.as_u32.low;
2042 
2043     xctx_st->toe.bd_prod                      = lm_bd_chain_prod_idx(&tcp->tx_con->bd_chain); /* Bd containing the last byte the application wishes to trasnmit */
2044     xctx_st->toe.driver_doorbell_info_ptr_lo  = tcp->tx_con->phys_db_data.as_u32.low;
2045     xctx_st->toe.driver_doorbell_info_ptr_hi  = tcp->tx_con->phys_db_data.as_u32.high;
2046 
2047     return LM_STATUS_SUCCESS;
2048 }
2049 
2050 
_lm_tcp_init_ustorm_toe_context(struct _lm_device_t * pdev,lm_tcp_state_t * tcp)2051 static lm_status_t _lm_tcp_init_ustorm_toe_context(
2052     struct _lm_device_t *pdev,
2053     lm_tcp_state_t *tcp)
2054 {
2055     struct toe_context *          ctx      = (struct toe_context *)tcp->ctx_virt;
2056     struct ustorm_toe_ag_context *uctx_ag  = &ctx->ustorm_ag_context;
2057     struct ustorm_toe_st_context *uctx_st  = &ctx->ustorm_st_context.context;
2058     lm_address_t                  mem_phys = {{0}};
2059 
2060     /* Calculate the crc8 for CDU Validation */
2061     mm_memset(uctx_ag, 0, sizeof(struct ustorm_toe_ag_context));
2062 
2063     /* ustorm_ag_context */
2064     uctx_ag->rq_prod                     = 0;
2065     uctx_ag->driver_doorbell_info_ptr_hi = tcp->rx_con->phys_db_data.as_u32.high;
2066     uctx_ag->driver_doorbell_info_ptr_lo = tcp->rx_con->phys_db_data.as_u32.low;
2067 
2068     /* ustorm_st_context */
2069     mm_memset(uctx_st, 0, sizeof(struct ustorm_toe_st_context));
2070     uctx_st->indirection_ram_offset   = (u16_t)tcp->tcp_const.hash_value;
2071     uctx_st->pen_grq_placed_bytes     = tcp->rx_con->u.rx.gen_info.peninsula_nbytes;
2072     DbgMessage(pdev, INFORMl4sp, "_lm_tcp_init_ustorm_toe_context: IRO is 0x%x, IS is %d\n",
2073                 uctx_st->indirection_ram_offset, uctx_st->__indirection_shift);
2074     if ((tcp->tcp_cached.rcv_indication_size > 0xffff) ||
2075         (tcp->tcp_cached.rcv_indication_size != 0))
2076     {
2077         DbgBreakIf(tcp->tcp_cached.rcv_indication_size > 0xffff);
2078         DbgBreakIf(tcp->tcp_cached.rcv_indication_size != 0); /* TBA receive_indication_size != 0 not supported : if it is we need to change initialization below */
2079         return LM_STATUS_INVALID_PARAMETER;
2080     }
2081     /* We set the ustorm context to rcv_indication_size = 1 byte, this means that the first packet that is placed on GRQ,
2082      * that exceeds or equals 1 byte is indicated immediately, without arming the push timer, the first packet is identified by
2083      * a packet that is placed while there are no GRQ placed bytes, every time that the driver advertises 'consumedGRQ', GRQ placed bytes
2084      * is decreased by the number, bringing it back to '0' will bring us back to the state where the next packet with 1 byte will be indicated.
2085      * We added this feature due to a sparta test called ReceiveIndication, which sends a fairly small packet and expects it to be indicated straight
2086      * awat, for some reason the small RQ buffer doesn't make it's way to the VBD... */
2087     uctx_st->rcv_indication_size      = 1;
2088     mem_phys = lm_bd_chain_phys_addr(&tcp->rx_con->bd_chain, 0);
2089     uctx_st->pen_ring_params.rq_cons  = 0;
2090     uctx_st->pen_ring_params.rq_cons_addr_hi = mem_phys.as_u32.high;
2091     uctx_st->pen_ring_params.rq_cons_addr_lo = mem_phys.as_u32.low;
2092 
2093     uctx_st->prev_rcv_win_right_edge = tcp->rx_con->db_data.rx->rcv_win_right_edge;
2094 
2095     if (pdev->params.l4_ignore_grq_push_enabled)
2096     {
2097         SET_FLAGS(uctx_st->flags2, USTORM_TOE_ST_CONTEXT_IGNORE_GRQ_PUSH);
2098     }
2099 
2100     if (pdev->params.l4_enable_rss == L4_RSS_DYNAMIC)
2101     {
2102         SET_FLAGS( uctx_st->flags2, USTORM_TOE_ST_CONTEXT_RSS_UPDATE_ENABLED );
2103     }
2104     /*DbgMessage(pdev, FATAL, "_lm_tcp_init_ustorm_toe_context(): uctx_st->initial_rcv_wnd=%d\n", tcp->tcp_cached.initial_rcv_wnd);*/
2105     uctx_st->initial_rcv_wnd = tcp->tcp_cached.initial_rcv_wnd;
2106     uctx_st->rcv_nxt         = tcp->tcp_delegated.recv_next;
2107 
2108     return LM_STATUS_SUCCESS;
2109 }
2110 
_lm_tcp_init_cstorm_toe_context(struct _lm_device_t * pdev,lm_tcp_state_t * tcp)2111 static lm_status_t _lm_tcp_init_cstorm_toe_context(
2112     struct _lm_device_t *pdev,
2113     lm_tcp_state_t *tcp)
2114 {
2115     struct toe_context           *ctx      = (struct toe_context *)tcp->ctx_virt;
2116     struct cstorm_toe_ag_context *cctx_ag  = &ctx->cstorm_ag_context;
2117     struct cstorm_toe_st_context *cctx_st  = &ctx->cstorm_st_context.context;
2118     lm_address_t                  mem_phys = {{0}};
2119 
2120     mm_memset(cctx_ag, 0, sizeof(struct cstorm_toe_ag_context));
2121 
2122     if (tcp->tcp_cached.initial_rcv_wnd > MAX_INITIAL_RCV_WND)
2123     {
2124         /* we can't support more than the maximum receive window due to cyclic counters we use for
2125          * recv_next, recv_win_seq, updates, window increase */
2126         DbgBreakIfAll(tcp->tcp_cached.initial_rcv_wnd > MAX_INITIAL_RCV_WND);
2127         return LM_STATUS_INVALID_PARAMETER;
2128     }
2129 
2130     /* cstorm_ag_context */
2131     cctx_ag->bd_prod = lm_bd_chain_prod_idx(&tcp->tx_con->bd_chain); /* Bd containing the last byte the application wishes to trasnmit */
2132     cctx_ag->rel_seq = tcp->tcp_delegated.send_una;
2133     cctx_ag->snd_max = tcp->tcp_delegated.send_max;
2134 
2135     /* cstorm_st_context */
2136     mm_memset(cctx_st, 0, sizeof(struct cstorm_toe_st_context));
2137     mem_phys = lm_bd_chain_phys_addr(&tcp->tx_con->bd_chain, 0);
2138     cctx_st->bds_ring_page_base_addr_hi = mem_phys.as_u32.high; /* page that includes the snd.una */
2139     cctx_st->bds_ring_page_base_addr_lo = mem_phys.as_u32.low;  /* page that includes the snd.una */
2140     cctx_st->bd_cons          = 0; /* idx of bd with snd.una - always 0 */
2141     if (ERR_IF(tcp->tcp_const.hash_value >= (u8_t)USTORM_INDIRECTION_TABLE_SIZE)) {
2142         if (tcp->tcp_const.hash_value >= (u8_t)USTORM_INDIRECTION_TABLE_SIZE)
2143         {
2144             DbgBreakIfAll(tcp->tcp_const.hash_value >= (u8_t)USTORM_INDIRECTION_TABLE_SIZE);
2145             return LM_STATUS_INVALID_PARAMETER;
2146         }
2147         tcp->tcp_const.hash_value = LM_TOE_FW_RSS_ID(pdev,LM_TOE_BASE_RSS_ID(pdev));
2148     }
2149 
2150     cctx_st->prev_snd_max = tcp->tcp_delegated.send_una;
2151 
2152 
2153 
2154 
2155     /* For TOE RSS the values in the USTORM (RSS) must differ from the one in CSTORM (TSS)
2156        2 options:
2157         a. base chain.
2158         b. value of most up-to-date indirection table.
2159     */
2160     if (pdev->params.l4_enable_rss == L4_RSS_DISABLED)
2161     {
2162         cctx_st->cpu_id = LM_TOE_FW_RSS_ID(pdev,LM_TOE_BASE_RSS_ID(pdev));
2163     }
2164     else
2165     {
2166         cctx_st->cpu_id = pdev->toe_info.indirection_table[tcp->tcp_const.hash_value];
2167     }
2168 
2169     cctx_st->free_seq = tcp->tcp_delegated.send_una - 1; /* (snd.una - 1 - offset of snd.una byte in its buffer (which is always 0)) */
2170 
2171     return LM_STATUS_SUCCESS;
2172 }
2173 
_lm_tcp_init_tstorm_toe_context(struct _lm_device_t * pdev,lm_tcp_state_t * tcp)2174 static lm_status_t _lm_tcp_init_tstorm_toe_context(
2175     struct _lm_device_t *pdev,
2176     lm_tcp_state_t * tcp)
2177 {
2178     struct toe_context * ctx = (struct toe_context *)tcp->ctx_virt;
2179     struct tstorm_toe_ag_context * tctx_ag = &ctx->tstorm_ag_context;
2180     struct tstorm_toe_st_context * tctx_st = &ctx->tstorm_st_context.context;
2181 
2182     UNREFERENCED_PARAMETER_(pdev);
2183 
2184     /* tstorm ag context */
2185     mm_mem_zero(tctx_ag, sizeof(struct tstorm_toe_ag_context));
2186 
2187     /* tstorm st context */
2188     mm_mem_zero(tctx_st, sizeof(struct tstorm_toe_st_context));
2189 
2190     return LM_STATUS_SUCCESS;
2191 }
2192 
_lm_tcp_init_timers_context(struct _lm_device_t * pdev,lm_tcp_state_t * tcp)2193 static lm_status_t _lm_tcp_init_timers_context(
2194     struct _lm_device_t *pdev,
2195     lm_tcp_state_t *tcp)
2196 {
2197     struct toe_context * ctx = (struct toe_context *)tcp->ctx_virt;
2198     /* timers_context */
2199     SET_FLAGS(ctx->timers_context.flags, TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG);
2200 
2201     UNREFERENCED_PARAMETER_(pdev);
2202 
2203     return LM_STATUS_SUCCESS;
2204 }
2205 
_lm_tcp_init_toe_context(struct _lm_device_t * pdev,lm_tcp_state_t * tcp)2206 static lm_status_t _lm_tcp_init_toe_context(
2207     struct _lm_device_t *pdev,
2208     lm_tcp_state_t *tcp)
2209 {
2210     lm_status_t lm_status = LM_STATUS_SUCCESS;
2211 
2212     lm_status = _lm_tcp_init_xstorm_toe_context(pdev, tcp);
2213     if (lm_status != LM_STATUS_SUCCESS) {
2214         return lm_status;
2215     }
2216     lm_status = _lm_tcp_init_ustorm_toe_context(pdev, tcp);
2217     if (lm_status != LM_STATUS_SUCCESS) {
2218         return lm_status;
2219     }
2220     lm_status = _lm_tcp_init_cstorm_toe_context(pdev, tcp);
2221     if (lm_status != LM_STATUS_SUCCESS) {
2222         return lm_status;
2223     }
2224     lm_status = _lm_tcp_init_tstorm_toe_context(pdev, tcp);
2225     if (lm_status != LM_STATUS_SUCCESS) {
2226         return lm_status;
2227     }
2228     lm_status = _lm_tcp_init_timers_context(pdev, tcp);
2229     if (lm_status != LM_STATUS_SUCCESS) {
2230         return lm_status;
2231     }
2232 
2233     /* now we need to configure the cdu-validation data */
2234     lm_set_cdu_validation_data(pdev, tcp->cid, FALSE /* don't invalidate */);
2235     return LM_STATUS_SUCCESS;
2236 }
2237 
2238 
_lm_tcp_init_tstorm_tcp_context(struct _lm_device_t * pdev,lm_tcp_state_t * tcp)2239 static lm_status_t _lm_tcp_init_tstorm_tcp_context(
2240     struct _lm_device_t *pdev,
2241     lm_tcp_state_t *tcp
2242     )
2243 {
2244     /* TODO: unify iscsi + toe structure name */
2245     struct tstorm_toe_tcp_ag_context_section *ttcp_ag;
2246     struct tstorm_tcp_st_context_section *ttcp_st;
2247     l4_ofld_params_t *l4_params = &pdev->ofld_info.l4_params;
2248     lm_path_state_t *path = tcp->path;
2249     lm_neigh_state_t *neigh = path->neigh;
2250     u32_t sm_rtt, sm_delta;
2251     u32_t snd_wnd;
2252 
2253     ASSERT_STATIC(sizeof(struct tstorm_toe_tcp_ag_context_section) == sizeof(struct tstorm_tcp_tcp_ag_context_section) );
2254     if (tcp->ulp_type == TOE_CONNECTION_TYPE)
2255     {
2256         ttcp_ag = &((struct toe_context *)tcp->ctx_virt)->tstorm_ag_context.tcp;
2257         ttcp_st = &((struct toe_context *)tcp->ctx_virt)->tstorm_st_context.context.tcp;
2258     }
2259     else
2260     {
2261         ttcp_ag = (struct tstorm_toe_tcp_ag_context_section *)&((struct iscsi_context *)tcp->ctx_virt)->tstorm_ag_context.tcp;
2262         ttcp_st = &((struct iscsi_context *)tcp->ctx_virt)->tstorm_st_context.tcp;
2263     }
2264     mm_mem_zero(ttcp_ag, sizeof(struct tstorm_toe_tcp_ag_context_section));
2265     mm_mem_zero(ttcp_st, sizeof(struct tstorm_tcp_st_context_section));
2266 
2267     /* tstorm_ag_context */
2268     ttcp_ag->snd_max      = tcp->tcp_delegated.send_max;
2269     ttcp_ag->snd_nxt      = tcp->tcp_delegated.send_next;
2270     ttcp_ag->snd_una      = tcp->tcp_delegated.send_una;
2271 
2272     /* tstorm_st_context*/
2273     // starting FW 7.6.5, the DA_EN is a "don't care" for iSCSI as it is set in pf init to FW
2274     // iSCSI FW overrides this flag according to pf init value regardless context init here.
2275     ttcp_st->flags2 |= TSTORM_TCP_ST_CONTEXT_SECTION_DA_EN;         /* DA timer always on */
2276 
2277     // DA_COUNTER_EN should stay always on since FW will not use it in case DA_EN is off.
2278     ttcp_st->flags2 |= TSTORM_TCP_ST_CONTEXT_SECTION_DA_COUNTER_EN; /* DA counter always on */
2279     ttcp_st->dup_ack_count = tcp->tcp_delegated.dup_ack_count;
2280 
2281     if(tcp->tcp_const.tcp_flags & TCP_FLAG_ENABLE_TIME_STAMP) {
2282         ttcp_st->flags1 |= TSTORM_TCP_ST_CONTEXT_SECTION_TIMESTAMP_EXISTS;
2283     }
2284     if(tcp->tcp_cached.tcp_flags & TCP_FLAG_ENABLE_KEEP_ALIVE) {
2285         ttcp_st->flags1 |= TSTORM_TCP_ST_CONTEXT_SECTION_KA_ENABLED;
2286         if ((tcp->tcp_cached.ka_time_out == 0) ||
2287             (tcp->tcp_cached.ka_interval == 0))
2288         {
2289             DbgBreakIf(tcp->tcp_cached.ka_time_out == 0);
2290             DbgBreakIf(tcp->tcp_cached.ka_interval == 0);
2291             return LM_STATUS_INVALID_PARAMETER;
2292         }
2293     }
2294     if(tcp->tcp_const.tcp_flags & TCP_FLAG_ENABLE_WIN_SCALING) {
2295         ttcp_st->snd_wnd_scale = tcp->tcp_const.snd_seg_scale;
2296     }
2297 
2298     ttcp_st->cwnd                 = tcp->tcp_delegated.send_cwin - tcp->tcp_delegated.send_una; /* i.e. ndis_tcp_delegated->CWnd */
2299     /* bugbug: driver workaround - wnd may be 0xffffffff, in this case we change it to 2^30 - since FW has an assumption this value
2300      * doesn't wrap-around, configuring it to 0xffffffff may cause it to wrap around and then change from a very large cwnd to a ver
2301      * small one - we give 2^30 which is the largest cwnd that can be advertised.  */
2302     if (ttcp_st->cwnd == 0xffffffff) {
2303         ttcp_st->cwnd = 0x40000000;
2304     }
2305 
2306     ttcp_st->ka_interval          =
2307         lm_time_resolution(pdev, tcp->tcp_cached.ka_interval, l4_params->ticks_per_second, TIMERS_TICKS_PER_SEC);
2308     ttcp_st->ka_max_probe_count   = tcp->tcp_cached.ka_probe_cnt;
2309     if(tcp->tcp_delegated.send_una == tcp->tcp_delegated.send_max) { /* KA is running (?) */
2310         ttcp_st->ka_probe_count   = tcp->tcp_delegated.u.keep_alive.probe_cnt;
2311     } else {   /* retransmit is running (?) */
2312         ttcp_st->ka_probe_count   = 0;
2313     }
2314     ttcp_st->ka_timeout           =
2315         lm_time_resolution(pdev, tcp->tcp_cached.ka_time_out, l4_params->ticks_per_second, TIMERS_TICKS_PER_SEC);
2316 
2317     /* Set the src mac addr in tstorm context:
2318      * In both big and little endian architectures, the mac addr is given from the client in an array of
2319      * 6 chars. Therefore, regardless the endian architectue, we need to swap this array into the little endian
2320      * convention of the tstorm context. */
2321     ttcp_st->msb_mac_address = mm_cpu_to_le16(NTOH16(*(u16 *)(&neigh->neigh_const.src_addr[0])));
2322     ttcp_st->mid_mac_address = mm_cpu_to_le16(NTOH16(*(u16 *)(&neigh->neigh_const.src_addr[2])));
2323     ttcp_st->lsb_mac_address = mm_cpu_to_le16(NTOH16(*(u16 *)(&neigh->neigh_const.src_addr[4])));
2324 
2325     ttcp_st->max_rt_time          =
2326         lm_time_resolution(pdev, tcp->tcp_cached.max_rt, l4_params->ticks_per_second, TSEMI_CLK1_TICKS_PER_SEC);
2327     /* GilR: place holder, to be enabled in v0_18_1 when proper FW support is included */
2328     //ttcp_st->max_seg_retransmit_en = 0;
2329     if (ttcp_st->max_rt_time == 0) { /* GilR 9/19/2006 - TBD - currently FW does not handle the '0' case correctly. */
2330         ttcp_st->max_rt_time = 0xffffffff;
2331         ttcp_st->flags1 |= TSTORM_TCP_ST_CONTEXT_SECTION_MAX_SEG_RETRANSMIT_EN;
2332         //ctx->tstorm_st_context.tcp.max_seg_retransmit_en = 1;
2333     }
2334 
2335     if (tcp->ulp_type == TOE_CONNECTION_TYPE) {
2336         if (tcp->rx_con->u.rx.sws_info.mss > 0xffff)
2337         {
2338             DbgBreakIf(tcp->rx_con->u.rx.sws_info.mss > 0xffff);
2339             return LM_STATUS_INVALID_PARAMETER;
2340         }
2341         ttcp_st->mss = tcp->rx_con->u.rx.sws_info.mss & 0xffff;
2342     } else {
2343         /* we must calc mss here since it is possible that we don't have rx_con (iscsi) */
2344         ttcp_st->mss = _lm_tcp_calc_mss(tcp->path->path_cached.path_mtu,
2345                                     tcp->tcp_const.remote_mss,
2346                                     (tcp->path->path_const.ip_version == IP_VERSION_IPV6),
2347                                     tcp->tcp_const.tcp_flags & TCP_FLAG_ENABLE_TIME_STAMP,
2348                                     pdev->ofld_info.l4_params.flags & OFLD_PARAM_FLAG_SNAP_ENCAP,
2349                                     tcp->path->neigh->neigh_const.vlan_tag  != 0) & 0xffff;
2350 
2351         /* NirV: set expected release sequance parameter that's being set in the toe fw but not in the iscsi fw */
2352         /* should be done in the iscsi initiate offload handler in the fw as in toe */
2353         ttcp_st->expected_rel_seq = tcp->tcp_delegated.send_una;
2354     }
2355 
2356     DbgMessage(pdev, INFORMl4sp, "offload num_retx=%d, snd_wnd_probe_cnt=%d\n",tcp->tcp_delegated.u.retransmit.num_retx,tcp->tcp_delegated.snd_wnd_probe_count);
2357 
2358     ttcp_st->persist_probe_count  = tcp->tcp_delegated.snd_wnd_probe_count;
2359     ttcp_st->prev_seg_seq         = tcp->tcp_delegated.send_wl1;
2360     ttcp_st->rcv_nxt              = tcp->tcp_delegated.recv_next;
2361     /*ttcp_st->reserved_slowpath    = 0;  This value is the 7 LSBs of the toeplitz hash result for this connection's 4 tuple.
2362                                                                     required in order to give the L2-completion on the correct RSS ring
2363                                                                     TBD - toeplitz hash calc not implemented for this yet, but no harm done */
2364 
2365     //calculate snd window
2366     snd_wnd = (S32_SUB(tcp->tcp_delegated.send_cwin, tcp->tcp_delegated.send_win) > 0) ?
2367         (tcp->tcp_delegated.send_win - tcp->tcp_delegated.send_una) : /* i.e. ndis_tcp_delegated->SndWnd */
2368         (tcp->tcp_delegated.send_cwin - tcp->tcp_delegated.send_una); /* i.e. ndis_tcp_delegated->CWnd */
2369 
2370     if(tcp->tcp_delegated.send_una == tcp->tcp_delegated.send_max && snd_wnd > 0) { /* KA is running (?) */
2371         ttcp_st->rto_exp = 0;
2372         ttcp_st->retransmit_count = 0;
2373     } else {   /* retransmit is running (?) */
2374         ttcp_st->retransmit_count = tcp->tcp_delegated.u.retransmit.num_retx;
2375         ttcp_st->rto_exp = tcp->tcp_delegated.u.retransmit.num_retx;
2376     }
2377     ttcp_st->retransmit_start_time =
2378         lm_time_resolution(pdev, tcp->tcp_delegated.total_rt, l4_params->ticks_per_second, TSEMI_CLK1_TICKS_PER_SEC);
2379 
2380     /* convert to ms.
2381      * the /8 and /4 are a result of some shifts that MSFT does, these number were received from MSFT through emails and are
2382      * done the same in Teton. */
2383     sm_rtt = lm_time_resolution(pdev, tcp->tcp_delegated.sm_rtt, l4_params->ticks_per_second, TIMERS_TICKS_PER_SEC)/8;
2384     if (sm_rtt > 30000) {   /* reduce to 30sec */
2385         sm_rtt = 30000;
2386     }
2387     sm_delta = lm_time_resolution(pdev, tcp->tcp_delegated.sm_delta, l4_params->ticks_per_second, TIMERS_TICKS_PER_SEC)/4;
2388     if (sm_delta > 30000) {   /* reduce to 30sec */
2389         sm_delta = 30000;
2390     }
2391 
2392     ttcp_st->flags1 |= (sm_rtt << TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT_SHIFT);  /* given in ticks, no conversion is required */
2393     ttcp_st->flags2 |= (sm_delta << TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION_SHIFT); /* given in ticks, no conversion is required */
2394     if ((tcp->ulp_type == TOE_CONNECTION_TYPE) && (tcp->rx_con->flags & TCP_REMOTE_FIN_RECEIVED)) {
2395         ttcp_st->flags1 |= TSTORM_TCP_ST_CONTEXT_SECTION_STOP_RX_PAYLOAD;
2396     }
2397 
2398     ttcp_st->ss_thresh            = tcp->tcp_delegated.ss_thresh;
2399     ttcp_st->timestamp_recent     = tcp->tcp_delegated.ts_recent;
2400     ttcp_st->timestamp_recent_time =
2401         lm_time_resolution(pdev, tcp->tcp_delegated.ts_recent_age, l4_params->ticks_per_second, TSEMI_CLK1_TICKS_PER_SEC);
2402     ttcp_st->vlan_id              = neigh->neigh_const.vlan_tag;
2403     ttcp_st->recent_seg_wnd       = tcp->tcp_delegated.send_win - tcp->tcp_delegated.send_una;
2404     ttcp_st->ooo_support_mode      = (tcp->ulp_type == TOE_CONNECTION_TYPE)? TCP_TSTORM_OOO_SUPPORTED : TCP_TSTORM_OOO_DROP_AND_PROC_ACK;
2405     ttcp_st->statistics_counter_id = (tcp->ulp_type == TOE_CONNECTION_TYPE)? LM_STATS_CNT_ID(pdev) : LM_CLI_IDX_ISCSI;
2406 
2407     // Set statistics params
2408     if( TOE_CONNECTION_TYPE == tcp->ulp_type )
2409     {
2410         // set enable L2
2411         SET_FLAGS( ttcp_st->flags2, 1<<TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT );
2412 
2413         // set enable L4
2414         SET_FLAGS( ttcp_st->flags2, 1<<TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT );
2415     }
2416 
2417     return LM_STATUS_SUCCESS;
2418 }
2419 
2420 
_lm_tcp_init_xstorm_tcp_context(struct _lm_device_t * pdev,lm_tcp_state_t * tcp)2421 static lm_status_t _lm_tcp_init_xstorm_tcp_context(
2422     struct _lm_device_t *pdev,
2423     lm_tcp_state_t *tcp)
2424 {
2425     /* TODO: unify iscsi + toe structure name */
2426     struct xstorm_toe_tcp_ag_context_section * xtcp_ag;
2427     struct xstorm_common_context_section     * xtcp_st;
2428     lm_path_state_t  * path  = tcp->path;
2429     lm_neigh_state_t * neigh = path->neigh;
2430     l4_ofld_params_t * l4_params = &(pdev->ofld_info.l4_params);
2431     u32_t src_ip[4], dst_ip[4];
2432     u16_t pseudo_cs, i;
2433     u32_t sm_rtt, sm_delta;
2434 
2435     ASSERT_STATIC(sizeof(struct xstorm_toe_tcp_ag_context_section) == sizeof(struct xstorm_tcp_tcp_ag_context_section));
2436     if (tcp->ulp_type == TOE_CONNECTION_TYPE) {
2437         xtcp_ag = &((struct toe_context *)tcp->ctx_virt)->xstorm_ag_context.tcp;
2438         xtcp_st = &((struct toe_context *)tcp->ctx_virt)->xstorm_st_context.context.common;
2439     } else {
2440         xtcp_ag = (struct xstorm_toe_tcp_ag_context_section *)&((struct iscsi_context *)tcp->ctx_virt)->xstorm_ag_context.tcp;
2441         xtcp_st = &((struct iscsi_context *)tcp->ctx_virt)->xstorm_st_context.common;
2442     }
2443 
2444     mm_mem_zero(xtcp_ag, sizeof(struct xstorm_toe_tcp_ag_context_section));
2445     mm_mem_zero(xtcp_st, sizeof(struct xstorm_common_context_section));
2446 
2447     xtcp_ag->ack_to_far_end       = tcp->tcp_delegated.recv_next;
2448     if(tcp->tcp_delegated.send_una == tcp->tcp_delegated.send_max) { /* KA is running (?) */
2449         if ((tcp->tcp_cached.ka_probe_cnt > 0) && (tcp->tcp_delegated.u.keep_alive.timeout_delta == 0)) {
2450             xtcp_ag->ka_timer = 1;
2451         } else if ((tcp->tcp_cached.ka_probe_cnt == 0) && (tcp->tcp_delegated.u.keep_alive.timeout_delta == 0)) {
2452             if (tcp->tcp_cached.ka_time_out == 0) {/* KA disabled */
2453                 xtcp_ag->ka_timer = 0xffffffff;
2454             } else {
2455                 if (tcp->tcp_cached.ka_time_out == 0xffffffff) {
2456                     xtcp_ag->ka_timer  = 0xffffffff;
2457                 } else {
2458                     xtcp_ag->ka_timer =
2459                         tcp->tcp_cached.ka_time_out ?
2460                         lm_time_resolution(pdev, tcp->tcp_cached.ka_time_out, l4_params->ticks_per_second, TIMERS_TICKS_PER_SEC) :
2461                         1 /* value of 0 is not allowed by FW */;
2462                 }
2463             }
2464         } else {
2465             if (tcp->tcp_delegated.u.keep_alive.timeout_delta == 0xffffffff) {
2466                 xtcp_ag->ka_timer  = 0xffffffff;
2467             } else {
2468                 xtcp_ag->ka_timer = lm_time_resolution(pdev, tcp->tcp_delegated.u.keep_alive.timeout_delta, l4_params->ticks_per_second, TIMERS_TICKS_PER_SEC);
2469             }
2470         }
2471     } else {   /* retransmit is running (?) */
2472         xtcp_ag->ka_timer         = 0xffffffff;
2473     }
2474 
2475     if (tcp->ulp_type == TOE_CONNECTION_TYPE) {
2476         xtcp_ag->local_adv_wnd        = tcp->tcp_delegated.recv_win_seq;
2477     } else if (tcp->ulp_type == ISCSI_CONNECTION_TYPE) {
2478         /* NirV: Add define to the iscsi HSI */
2479         xtcp_ag->local_adv_wnd        = 0xFFFF << ((u16_t)tcp->tcp_const.rcv_seg_scale & 0xf); /* rcv_seg_scale is only 4b long */
2480     }
2481 
2482     if (tcp->ulp_type == TOE_CONNECTION_TYPE) {
2483         if (tcp->rx_con->u.rx.sws_info.mss > 0xffff)
2484         {
2485             DbgBreakIf(tcp->rx_con->u.rx.sws_info.mss > 0xffff);
2486             return LM_STATUS_INVALID_PARAMETER;
2487         }
2488         xtcp_ag->mss = tcp->rx_con->u.rx.sws_info.mss & 0xffff;
2489     } else {
2490         /* we must calc mss here since it is possible that we don't have rx_con (iscsi) */
2491         xtcp_ag->mss = _lm_tcp_calc_mss(tcp->path->path_cached.path_mtu,
2492                                     tcp->tcp_const.remote_mss,
2493                                     (tcp->path->path_const.ip_version == IP_VERSION_IPV6),
2494                                     tcp->tcp_const.tcp_flags & TCP_FLAG_ENABLE_TIME_STAMP,
2495                                     pdev->ofld_info.l4_params.flags & OFLD_PARAM_FLAG_SNAP_ENCAP,
2496                                     tcp->path->neigh->neigh_const.vlan_tag  != 0) & 0xfffc;     /* MSS value set in the XStorm should be multiple of 4 */
2497 
2498         if (tcp->ulp_type == ISCSI_CONNECTION_TYPE)
2499         {
2500             if (xtcp_ag->mss < 4)
2501             {
2502                 DbgBreakIf(xtcp_ag->mss < 4);
2503                 return LM_STATUS_INVALID_PARAMETER;
2504             }
2505             xtcp_ag->mss -= 4;  // -4 for data digest
2506         }
2507     }
2508 
2509     if (tcp->ulp_type == TOE_CONNECTION_TYPE) {
2510         /*if persist probes were sent xstorm should be blocked*/
2511         if (tcp->tcp_delegated.snd_wnd_probe_count == 0) {
2512             xtcp_ag->tcp_agg_vars2 |= __XSTORM_TOE_TCP_AG_CONTEXT_SECTION_TX_UNBLOCKED;
2513         }
2514     }
2515 
2516     /* calculate transmission window */
2517     xtcp_ag->tx_wnd               =
2518         (S32_SUB(tcp->tcp_delegated.send_cwin, tcp->tcp_delegated.send_win) > 0) ?
2519         (tcp->tcp_delegated.send_win - tcp->tcp_delegated.send_una) : /* i.e. ndis_tcp_delegated->SndWnd */
2520         (tcp->tcp_delegated.send_cwin - tcp->tcp_delegated.send_una); /* i.e. ndis_tcp_delegated->CWnd */
2521 
2522     /* bugbug: driver workaround - wnd may be 0xffffffff, in this case we change it to 2^30 - since FW has an assumption this value
2523      * doesn't wrap-around, configuring it to 0xffffffff may cause it to wrap around and then change from a very large cwnd to a ver
2524      * small one - we give 2^30 which is the largest cwnd that can be advertised.  */
2525     if (xtcp_ag->tx_wnd == 0xffffffff) {
2526         xtcp_ag->tx_wnd = 0x40000000;
2527     }
2528 
2529     /* check if we are in keepalive. */
2530     if ((tcp->tcp_delegated.send_una == tcp->tcp_delegated.send_max) && ((xtcp_ag->tx_wnd > 0) || (tcp->tcp_delegated.u.retransmit.retx_ms == 0xffffffff))) { /* KA is enabled (?) */
2531        /* convert to ms.
2532         * the /8 and /4 are a result of some shifts that MSFT does, these number were received from MSFT through emails and are
2533         * done the same in Teton. */
2534         sm_rtt = lm_time_resolution(pdev, tcp->tcp_delegated.sm_rtt, l4_params->ticks_per_second, TIMERS_TICKS_PER_SEC)/8;
2535         if (sm_rtt > 30000) {   /* reduce to 30sec */
2536             sm_rtt = 30000;
2537         }
2538         sm_delta = lm_time_resolution(pdev, tcp->tcp_delegated.sm_delta, l4_params->ticks_per_second, TIMERS_TICKS_PER_SEC)/4;
2539         if (sm_delta > 30000) { /* reduce to 30sec */
2540             sm_delta = 30000;
2541         }
2542         xtcp_ag->rto_timer  = (sm_rtt + (sm_delta << 2));
2543     } else {   /* retransmit is running (?) */
2544         if (tcp->tcp_delegated.u.retransmit.retx_ms == 0xffffffff) {
2545             xtcp_ag->rto_timer       = 0xffffffff;
2546         } else {
2547             xtcp_ag->rto_timer        = tcp->tcp_delegated.u.retransmit.retx_ms ? tcp->tcp_delegated.u.retransmit.retx_ms : 1 /* value of 0 is not allowed by FW*/;
2548                 /* TODO: retx_ms is already converted in Miniport
2549                  * we need to convert retx_ms to clock ticks in VBD instead of
2550                  * doing this conversion in NDIS (same as Teton) */
2551                 /*tcp->tcp_delegated.u.retransmit.retx_ms ?
2552                 lm_time_resolution(pdev, tcp->tcp_delegated.u.retransmit.retx_ms,
2553                                    1000, TIMERS_TICKS_PER_SEC) :
2554                 1 *//* value of 0 is not allowed by FW*/;
2555         }
2556     }
2557     xtcp_ag->snd_nxt              = tcp->tcp_delegated.send_next;
2558     xtcp_ag->snd_una              = tcp->tcp_delegated.send_una;
2559     xtcp_ag->tcp_agg_vars2        |= XSTORM_TOE_TCP_AG_CONTEXT_SECTION_DA_ENABLE; /* Delayed Acks always on */
2560     xtcp_ag->ts_to_echo           = tcp->tcp_delegated.ts_recent;
2561 
2562 
2563     /* xstorm_st_context */
2564     xtcp_st->ethernet.remote_addr_0      = neigh->neigh_cached.dst_addr[0];
2565     xtcp_st->ethernet.remote_addr_1      = neigh->neigh_cached.dst_addr[1];
2566     xtcp_st->ethernet.remote_addr_2      = neigh->neigh_cached.dst_addr[2];
2567     xtcp_st->ethernet.