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 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...) 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 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 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 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 */ 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 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 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 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 } 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 */ 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 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 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 */ 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. */ 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 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 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 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 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 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 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 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 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.remote_addr_3 = neigh->neigh_cached.dst_addr[3]; 2568 xtcp_st->ethernet.remote_addr_4 = neigh->neigh_cached.dst_addr[4]; 2569 xtcp_st->ethernet.remote_addr_5 = neigh->neigh_cached.dst_addr[5]; 2570 2571 if (neigh->neigh_const.vlan_tag > 0xfff) 2572 { 2573 DbgBreakIf(neigh->neigh_const.vlan_tag > 0xfff); 2574 return LM_STATUS_INVALID_PARAMETER; 2575 } 2576 xtcp_st->ethernet.vlan_params |= (neigh->neigh_const.vlan_tag << XSTORM_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT); 2577 2578 if (tcp->tcp_cached.user_priority > 0x7) 2579 { 2580 DbgBreakIf(tcp->tcp_cached.user_priority > 0x7); 2581 return LM_STATUS_INVALID_PARAMETER; 2582 } 2583 xtcp_st->ethernet.vlan_params |= (tcp->tcp_cached.user_priority << XSTORM_ETH_CONTEXT_SECTION_PRIORITY_SHIFT); 2584 2585 if ((0 != GET_FLAGS(xtcp_st->ethernet.vlan_params, XSTORM_ETH_CONTEXT_SECTION_VLAN_ID)) || 2586 (0 != GET_FLAGS(xtcp_st->ethernet.vlan_params, XSTORM_ETH_CONTEXT_SECTION_CFI)) || 2587 (0 != GET_FLAGS(xtcp_st->ethernet.vlan_params, XSTORM_ETH_CONTEXT_SECTION_PRIORITY))) 2588 { 2589 // This fields should be set to 1 whenever an inner VLAN is provided by the OS. 2590 // This flags is relevant for all function modes. 2591 SET_FLAGS( xtcp_st->flags, XSTORM_COMMON_CONTEXT_SECTION_VLAN_MODE); 2592 } 2593 2594 xtcp_st->ethernet.local_addr_0 = neigh->neigh_const.src_addr[0]; 2595 xtcp_st->ethernet.local_addr_1 = neigh->neigh_const.src_addr[1]; 2596 xtcp_st->ethernet.local_addr_2 = neigh->neigh_const.src_addr[2]; 2597 xtcp_st->ethernet.local_addr_3 = neigh->neigh_const.src_addr[3]; 2598 xtcp_st->ethernet.local_addr_4 = neigh->neigh_const.src_addr[4]; 2599 xtcp_st->ethernet.local_addr_5 = neigh->neigh_const.src_addr[5]; 2600 xtcp_st->ethernet.reserved_vlan_type = 0x8100; 2601 2602 xtcp_st->ip_version_1b = (tcp->path->path_const.ip_version == IP_VERSION_IPV4)? 0 : 1; 2603 if (tcp->path->path_const.ip_version == IP_VERSION_IPV4) { 2604 /* IPv4*/ 2605 xtcp_st->ip_union.padded_ip_v4.ip_v4.ip_remote_addr = path->path_const.u.ipv4.dst_ip; 2606 xtcp_st->ip_union.padded_ip_v4.ip_v4.ip_local_addr = path->path_const.u.ipv4.src_ip; 2607 xtcp_st->ip_union.padded_ip_v4.ip_v4.tos = tcp->tcp_cached.tos_or_traffic_class; 2608 #if DBG 2609 xtcp_st->ip_union.padded_ip_v4.ip_v4.ttl = (tcp->ulp_type == TOE_CONNECTION_TYPE) ? TOE_DBG_TTL : ISCSI_DBG_TTL; 2610 #else 2611 xtcp_st->ip_union.padded_ip_v4.ip_v4.ttl = tcp->tcp_cached.ttl_or_hop_limit; 2612 #endif 2613 src_ip[0] = HTON32(path->path_const.u.ipv4.src_ip); 2614 dst_ip[0] = HTON32(path->path_const.u.ipv4.dst_ip); 2615 pseudo_cs = lm_tcp_calc_tcp_pseudo_checksum(pdev, src_ip, dst_ip, IP_VERSION_IPV4); 2616 } else { 2617 /* IPv6*/ 2618 xtcp_st->ip_union.ip_v6.ip_remote_addr_lo_lo = path->path_const.u.ipv6.dst_ip[0]; 2619 xtcp_st->ip_union.ip_v6.ip_remote_addr_lo_hi = path->path_const.u.ipv6.dst_ip[1]; 2620 xtcp_st->ip_union.ip_v6.ip_remote_addr_hi_lo = path->path_const.u.ipv6.dst_ip[2]; 2621 xtcp_st->ip_union.ip_v6.ip_remote_addr_hi_hi = path->path_const.u.ipv6.dst_ip[3]; 2622 2623 xtcp_st->ip_union.ip_v6.ip_local_addr_lo_lo = path->path_const.u.ipv6.src_ip[0]; 2624 xtcp_st->ip_union.ip_v6.ip_local_addr_lo_hi = path->path_const.u.ipv6.src_ip[1]; 2625 xtcp_st->ip_union.ip_v6.ip_local_addr_hi_lo = path->path_const.u.ipv6.src_ip[2]; 2626 xtcp_st->ip_union.ip_v6.ip_local_addr_hi_hi = path->path_const.u.ipv6.src_ip[3]; 2627 2628 #if DBG 2629 xtcp_st->ip_union.ip_v6.hop_limit = (tcp->ulp_type == TOE_CONNECTION_TYPE) ? TOE_DBG_TTL : ISCSI_DBG_TTL; 2630 #else 2631 xtcp_st->ip_union.ip_v6.hop_limit = tcp->tcp_cached.ttl_or_hop_limit; 2632 #endif 2633 DbgBreakIf(tcp->tcp_cached.flow_label > 0xffff); 2634 xtcp_st->ip_union.ip_v6.priority_flow_label = 2635 tcp->tcp_cached.flow_label << XSTORM_IP_V6_CONTEXT_SECTION_FLOW_LABEL_SHIFT | 2636 tcp->tcp_cached.tos_or_traffic_class << XSTORM_IP_V6_CONTEXT_SECTION_TRAFFIC_CLASS_SHIFT; 2637 2638 for (i = 0; i < 4; i++) { 2639 src_ip[i] = HTON32(path->path_const.u.ipv6.src_ip[i]); 2640 dst_ip[i] = HTON32(path->path_const.u.ipv6.dst_ip[i]); 2641 } 2642 pseudo_cs = lm_tcp_calc_tcp_pseudo_checksum(pdev, src_ip, dst_ip, IP_VERSION_IPV6); 2643 } 2644 2645 xtcp_st->tcp.local_port = tcp->tcp_const.src_port; 2646 2647 2648 xtcp_st->tcp.pseudo_csum = NTOH16(pseudo_cs); 2649 xtcp_st->tcp.remote_port = tcp->tcp_const.dst_port; 2650 xtcp_st->tcp.snd_max = tcp->tcp_delegated.send_max; 2651 if(tcp->tcp_const.tcp_flags & TCP_FLAG_ENABLE_TIME_STAMP) { 2652 xtcp_st->tcp.ts_enabled = 1; 2653 } 2654 if(tcp->tcp_const.tcp_flags & TCP_FLAG_ENABLE_SACK) { 2655 xtcp_st->tcp.tcp_params |= XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED; 2656 } 2657 if ((tcp->ulp_type == TOE_CONNECTION_TYPE) && (tcp->tx_con->flags & TCP_FIN_REQ_POSTED)) { 2658 xtcp_st->tcp.tcp_params |= XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG; 2659 } 2660 xtcp_st->tcp.ts_time_diff = tcp->tcp_delegated.tstamp; /* time conversion not required */ 2661 xtcp_st->tcp.window_scaling_factor = (u16_t)tcp->tcp_const.rcv_seg_scale & 0xf; /* rcv_seg_scale is only 4b long */ 2662 2663 // Set statistics params 2664 if( TOE_CONNECTION_TYPE == tcp->ulp_type ) 2665 { 2666 // set counter id 2667 xtcp_st->tcp.statistics_counter_id = LM_STATS_CNT_ID(pdev); 2668 2669 // set enable L2 2670 SET_FLAGS( xtcp_st->tcp.statistics_params, 1<<XSTORM_TCP_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT ); 2671 2672 // set enable L4 2673 SET_FLAGS( xtcp_st->tcp.statistics_params, 1<<XSTORM_TCP_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT ); 2674 } 2675 if (tcp->ulp_type == ISCSI_CONNECTION_TYPE) 2676 { 2677 SET_FLAGS( xtcp_st->flags,(1 << XSTORM_COMMON_CONTEXT_SECTION_PHYSQ_INITIALIZED_SHIFT )); 2678 2679 SET_FLAGS( xtcp_st->flags,(PORT_ID(pdev) << XSTORM_COMMON_CONTEXT_SECTION_PBF_PORT_SHIFT)); 2680 } 2681 return LM_STATUS_SUCCESS; 2682 } 2683 2684 2685 /* init the content of the toe context */ 2686 static lm_status_t _lm_tcp_init_tcp_context( 2687 struct _lm_device_t *pdev, 2688 lm_tcp_state_t *tcp) 2689 { 2690 lm_status_t lm_status ; 2691 2692 lm_status = _lm_tcp_init_xstorm_tcp_context(pdev, tcp); 2693 if (lm_status != LM_STATUS_SUCCESS) { 2694 return lm_status; 2695 } 2696 2697 lm_status = _lm_tcp_init_tstorm_tcp_context(pdev, tcp); 2698 if (lm_status != LM_STATUS_SUCCESS) { 2699 return lm_status; 2700 } 2701 2702 return LM_STATUS_SUCCESS; 2703 } 2704 2705 static lm_status_t _lm_tcp_init_iscsi_tcp_related_context( 2706 struct _lm_device_t *pdev, 2707 lm_tcp_state_t *tcp) 2708 { 2709 struct cstorm_iscsi_ag_context * ciscsi_ag = &((struct iscsi_context *)tcp->ctx_virt)->cstorm_ag_context; 2710 struct cstorm_iscsi_st_context * ciscsi_st = &((struct iscsi_context *)tcp->ctx_virt)->cstorm_st_context; 2711 struct xstorm_iscsi_ag_context * xiscsi_ag = &((struct iscsi_context *)tcp->ctx_virt)->xstorm_ag_context; 2712 struct xstorm_iscsi_st_context * xiscsi_st = &((struct iscsi_context *)tcp->ctx_virt)->xstorm_st_context; 2713 struct tstorm_iscsi_ag_context * tiscsi_ag = &((struct iscsi_context *)tcp->ctx_virt)->tstorm_ag_context; 2714 struct tstorm_iscsi_st_context * tiscsi_st = &((struct iscsi_context *)tcp->ctx_virt)->tstorm_st_context; 2715 2716 UNREFERENCED_PARAMETER_(pdev); 2717 2718 ASSERT_STATIC(sizeof(struct cstorm_toe_ag_context) == sizeof(struct cstorm_iscsi_ag_context)); 2719 // ASSERT_STATIC(sizeof(struct cstorm_toe_st_context) == sizeof(struct cstorm_iscsi_st_context)); 2720 // ASSERT_STATIC(OFFSETOF(struct iscsi_context, cstorm_ag_context)== OFFSETOF(struct toe_context, cstorm_ag_context) ) ; 2721 // ASSERT_STATIC(OFFSETOF(struct iscsi_context, cstorm_st_context)== OFFSETOF(struct toe_context, cstorm_st_context) ) ; 2722 2723 /* cstorm */ 2724 ciscsi_ag->rel_seq = tcp->tcp_delegated.send_next; //pTcpParams->sndNext; 2725 ciscsi_ag->rel_seq_th = tcp->tcp_delegated.send_next; //pTcpParams->sndNext; 2726 ciscsi_st->hq_tcp_seq = tcp->tcp_delegated.send_next; //pTcpParams->sndNext; 2727 2728 /* xstorm */ 2729 xiscsi_ag->hq_cons_tcp_seq = tcp->tcp_delegated.send_next; //pTcpParams->sndNext; 2730 2731 /* tstorm */ 2732 /* in toe the window right edge is initialized by the doorbell */ 2733 /* recv_win_seq */ /* recv next */ 2734 tiscsi_ag->tcp.wnd_right_edge = (xiscsi_ag->tcp.local_adv_wnd << xiscsi_st->common.tcp.window_scaling_factor) + xiscsi_ag->tcp.ack_to_far_end; 2735 2736 tiscsi_ag->tcp.wnd_right_edge_local = tiscsi_ag->tcp.wnd_right_edge; 2737 2738 tiscsi_st->iscsi.process_nxt = tcp->tcp_delegated.recv_next; // same value as rcv_nxt 2739 2740 //xAgCtx->mss = pTcpParams->mss - 4; // -4 for data digest 2741 2742 return LM_STATUS_SUCCESS; 2743 } 2744 2745 /* Desciption: 2746 * Allocation of CID for a new TCP connection to be offloaded, 2747 * Initiation of connection's context line as required by FW. 2748 * Assumptions: 2749 * - lm_tcp_init_tcp_state, lm_tcp_init_rx_con/tx_con already called 2750 * - send unacked data already posted 2751 * - If the TCP is in states FinWait1, Closing or LastAck, 2752 * FIN is already posted to the tx chain 2753 * - Called under connection lock: since it can be called from either initiate-ofld 2754 * or recycle-cid (before ofld had the chance to complete) 2755 * Returns: 2756 * SUCCESS or any failure */ 2757 static lm_status_t lm_tcp_init_tcp_context( 2758 struct _lm_device_t *pdev, 2759 lm_tcp_state_t *tcp) 2760 { 2761 s32_t cid; 2762 lm_status_t lm_status; 2763 lm_4tuple_t tuple = {{0}}; 2764 u32_t expect_rwin; 2765 u8_t i; 2766 2767 DbgMessage(pdev, VERBOSEl4sp, "##lm_tcp_init_tcp_context\n"); 2768 2769 /* NirV: allocate cid is getting back here */ 2770 /* allocate cid only if cid==0: we may re-enter this function after a cid has already been allocated */ 2771 if (tcp->cid == 0) 2772 { 2773 lm_status = lm_allocate_cid(pdev, TOE_CONNECTION_TYPE, (void*)tcp, &cid); 2774 if(lm_status == LM_STATUS_RESOURCE){ 2775 DbgMessage(pdev, WARNl4sp, "lm_tcp_init_tcp_state: Failed in allocating cid\n"); 2776 return LM_STATUS_RESOURCE; 2777 } else if (lm_status == LM_STATUS_PENDING) { 2778 lm_sp_req_manager_block(pdev, (u32_t)cid); 2779 } 2780 tcp->cid = (u32_t)cid; 2781 } 2782 2783 if (lm_cid_state(pdev, tcp->cid) == LM_CID_STATE_PENDING) { 2784 return LM_STATUS_SUCCESS; /* Too soon to initialize context */ 2785 } 2786 2787 /* Validate some of the offload parameters - only relevant for TOE. */ 2788 if (tcp->ulp_type == TOE_CONNECTION_TYPE) { 2789 tcp->rx_con->u.rx.sws_info.extra_bytes = 0; 2790 if (tcp->rx_con->u.rx.gen_info.peninsula_nbytes > tcp->tcp_cached.initial_rcv_wnd) { 2791 tcp->rx_con->u.rx.sws_info.extra_bytes = tcp->rx_con->u.rx.gen_info.peninsula_nbytes - tcp->tcp_cached.initial_rcv_wnd; 2792 tcp->rx_con->u.rx.sws_info.drv_rcv_win_right_edge = tcp->tcp_delegated.recv_next; 2793 tcp->rx_con->db_data.rx->rcv_win_right_edge = tcp->tcp_delegated.recv_next; 2794 DbgMessage(pdev, INFORMl4sp, "lm_tcp_init_tcp_state: pnb:%x, irw:%x, ext:%x, rnx:%x\n",tcp->rx_con->u.rx.gen_info.peninsula_nbytes, 2795 tcp->tcp_cached.initial_rcv_wnd,tcp->rx_con->u.rx.sws_info.extra_bytes,tcp->tcp_delegated.recv_next); 2796 } else { 2797 expect_rwin = (u32_t)S32_SUB( 2798 tcp->tcp_delegated.recv_win_seq, 2799 tcp->tcp_delegated.recv_next); 2800 expect_rwin += tcp->rx_con->u.rx.gen_info.peninsula_nbytes; 2801 2802 /* WorkAround for LH: fields received at offload should match the equation below, 2803 * In LH it's not the case. TBA: add assert that we are on LH operating system */ 2804 DbgMessage(pdev, INFORMl4sp, "lm_tcp_init_tcp_state: pnb:%x, irw:%x, rws:%x, rnx:%x\n",tcp->rx_con->u.rx.gen_info.peninsula_nbytes, 2805 tcp->tcp_cached.initial_rcv_wnd, 2806 tcp->tcp_delegated.recv_win_seq, 2807 tcp->tcp_delegated.recv_next); 2808 if (ERR_IF(expect_rwin != tcp->tcp_cached.initial_rcv_wnd)) { 2809 u32_t delta; 2810 /* move tcp_delegated.recv_next accordingly */ 2811 if (expect_rwin > tcp->tcp_cached.initial_rcv_wnd) { 2812 delta = expect_rwin - tcp->tcp_cached.initial_rcv_wnd; 2813 tcp->tcp_delegated.recv_win_seq -= delta; 2814 } else { 2815 delta = tcp->tcp_cached.initial_rcv_wnd - expect_rwin; 2816 tcp->tcp_delegated.recv_win_seq += delta; 2817 } 2818 /* Need to also update the driver win right edge */ 2819 tcp->rx_con->db_data.rx->rcv_win_right_edge = tcp->tcp_delegated.recv_win_seq; 2820 tcp->rx_con->u.rx.sws_info.drv_rcv_win_right_edge = tcp->tcp_delegated.recv_win_seq; 2821 } 2822 } 2823 } 2824 /* insert 4 tuple to searcher's mirror hash */ 2825 if(tcp->path->path_const.ip_version == IP_VERSION_IPV4) { /* IPV4 */ 2826 tuple.ip_type = LM_IP_TYPE_V4; 2827 tuple.dst_ip[0] = tcp->path->path_const.u.ipv4.dst_ip; 2828 tuple.src_ip[0] = tcp->path->path_const.u.ipv4.src_ip; 2829 } else { 2830 tuple.ip_type = LM_IP_TYPE_V6; 2831 for (i = 0; i < 4; i++) { 2832 tuple.dst_ip[i] = tcp->path->path_const.u.ipv6.dst_ip[i]; 2833 tuple.src_ip[i] = tcp->path->path_const.u.ipv6.src_ip[i]; 2834 } 2835 } 2836 tuple.src_port = tcp->tcp_const.src_port; 2837 tuple.dst_port = tcp->tcp_const.dst_port; 2838 if (lm_searcher_mirror_hash_insert(pdev, tcp->cid, &tuple) != LM_STATUS_SUCCESS) { 2839 DbgMessage(pdev, WARNl4sp, "lm_tcp_init_tcp_context: Failed inserting tuple to SRC hash\n"); 2840 tcp->in_searcher = 0; 2841 return LM_STATUS_RESOURCE; 2842 } 2843 tcp->in_searcher = 1; 2844 2845 /* get context */ 2846 tcp->ctx_virt = (struct toe_context *)lm_get_context(pdev, tcp->cid); 2847 if (!tcp->ctx_virt) { 2848 DbgBreakIf(!tcp->ctx_virt); 2849 return LM_STATUS_FAILURE; 2850 } 2851 2852 tcp->ctx_phys.as_u64 = lm_get_context_phys(pdev, tcp->cid); 2853 if (!tcp->ctx_phys.as_u64) { 2854 DbgBreakIf(!tcp->ctx_phys.as_u64); 2855 return LM_STATUS_FAILURE; 2856 } 2857 DbgMessage(pdev, VERBOSEl4sp, 2858 "tcp->ctx_virt=%p, tcp->ctx_phys_high=%x, tcp->ctx_phys_low=%x\n", 2859 tcp->ctx_virt, tcp->ctx_phys.as_u32.high, tcp->ctx_phys.as_u32.low); 2860 2861 /* init the content of the context */ 2862 if (tcp->ulp_type == TOE_CONNECTION_TYPE) { 2863 lm_status = _lm_tcp_init_toe_context(pdev, tcp); 2864 if (lm_status != LM_STATUS_SUCCESS) { 2865 return lm_status; 2866 } 2867 } 2868 2869 lm_status = _lm_tcp_init_tcp_context(pdev, tcp); 2870 if (lm_status != LM_STATUS_SUCCESS) { 2871 return lm_status; 2872 } 2873 2874 /* iscsi / toe contexts are initialized separately, only the tcp section is common, HOWEVER, in iscsi 2875 * most of the context is initialized in the l5_ofld_stage, but some of the context initialization is based on tcp 2876 * params, that's why we need to complete it here... */ 2877 if (tcp->ulp_type == ISCSI_CONNECTION_TYPE) { 2878 lm_status = _lm_tcp_init_iscsi_tcp_related_context(pdev, tcp); 2879 if (lm_status != LM_STATUS_SUCCESS) { 2880 return lm_status; 2881 } 2882 } 2883 2884 return LM_STATUS_SUCCESS; 2885 } 2886 2887 /** Description 2888 * Callback function for cids being recylced 2889 */ 2890 void lm_tcp_recycle_cid_cb( 2891 struct _lm_device_t *pdev, 2892 void *cookie, 2893 s32_t cid) 2894 { 2895 lm_tcp_state_t *tcp = (lm_tcp_state_t *)cookie; 2896 lm_sp_req_common_t *sp_req = NULL; 2897 MM_ACQUIRE_TOE_LOCK(pdev); 2898 2899 /* un-block the manager... */ 2900 lm_set_cid_state(pdev, tcp->cid, LM_CID_STATE_VALID); 2901 2902 /* if the ofld flow got to the ofld workitem, only now set we can use the context, 2903 other wise, we'll get to the init_tcp_context later on */ 2904 if (tcp->hdr.status == STATE_STATUS_INIT_CONTEXT) 2905 { 2906 lm_tcp_init_tcp_context(pdev,tcp); 2907 } 2908 2909 /* we can now unblock any pending slow-paths */ 2910 lm_sp_req_manager_unblock(pdev,cid, &sp_req); 2911 2912 2913 MM_RELEASE_TOE_LOCK(pdev); 2914 } 2915 2916 /* This function needs to complete a pending slowpath toe request. Unfortunatelly it needs 2917 * to take care of all the steps done in lm_toe_service_rx_intr and lm_toe_service_tx_intr, 2918 * process the cqe, and complete slowpath... 2919 */ 2920 void lm_tcp_comp_cb(struct _lm_device_t *pdev, struct sq_pending_command *pending) 2921 { 2922 lm_tcp_state_t * tcp = NULL; 2923 lm_tcp_con_t * rx_con = NULL; 2924 lm_tcp_con_t * tx_con = NULL; 2925 struct toe_rx_cqe rx_cqe = {0}; 2926 struct toe_tx_cqe tx_cqe = {0}; 2927 u8_t i = 0; 2928 u8_t cmp_rx = FALSE; 2929 u8_t cmp_tx = FALSE; 2930 2931 MM_INIT_TCP_LOCK_HANDLE(); 2932 2933 tcp = lm_cid_cookie(pdev, TOE_CONNECTION_TYPE, pending->cid); 2934 /* Possible the tcp is NULL for ramrods that are context-less (RSS for example) */ 2935 if (tcp) 2936 { 2937 rx_con = tcp->rx_con; 2938 tx_con = tcp->tx_con; 2939 } 2940 2941 #define LM_TCP_SET_CQE(_param, _cid, _cmd) \ 2942 (_param) = (((_cid) << TOE_RX_CQE_CID_SHIFT) & TOE_RX_CQE_CID) | \ 2943 (((_cmd) << TOE_RX_CQE_COMPLETION_OPCODE_SHIFT) & TOE_RX_CQE_COMPLETION_OPCODE); 2944 2945 switch (pending->cmd) 2946 { 2947 case RAMROD_OPCODE_TOE_INIT: 2948 DbgBreakMsg("Not Supported\n"); 2949 break; 2950 case RAMROD_OPCODE_TOE_INITIATE_OFFLOAD: 2951 LM_TCP_SET_CQE(rx_cqe.params1, pending->cid, RAMROD_OPCODE_TOE_INITIATE_OFFLOAD); 2952 cmp_rx = TRUE; 2953 break; 2954 case RAMROD_OPCODE_TOE_SEARCHER_DELETE: 2955 LM_TCP_SET_CQE(rx_cqe.params1, pending->cid, RAMROD_OPCODE_TOE_SEARCHER_DELETE); 2956 cmp_rx = TRUE; 2957 break; 2958 case RAMROD_OPCODE_TOE_TERMINATE: 2959 /* Completion may have completed on tx / rx only, so whether or not to complete it depends not 2960 * only on type but on state of sp_request as well... */ 2961 LM_TCP_SET_CQE(rx_cqe.params1, pending->cid, RAMROD_OPCODE_TOE_TERMINATE); 2962 cmp_rx = (GET_FLAGS(tcp->sp_flags, SP_REQUEST_COMPLETED_RX) == 0); 2963 LM_TCP_SET_CQE(tx_cqe.params, pending->cid, RAMROD_OPCODE_TOE_TERMINATE); 2964 cmp_tx = (GET_FLAGS(tcp->sp_flags, SP_REQUEST_COMPLETED_TX) == 0);; 2965 break; 2966 case RAMROD_OPCODE_TOE_QUERY: 2967 LM_TCP_SET_CQE(rx_cqe.params1, pending->cid, RAMROD_OPCODE_TOE_QUERY); 2968 cmp_rx = TRUE; 2969 break; 2970 case RAMROD_OPCODE_TOE_RESET_SEND: 2971 LM_TCP_SET_CQE(rx_cqe.params1, pending->cid, RAMROD_OPCODE_TOE_RESET_SEND); 2972 cmp_rx = (GET_FLAGS(tcp->sp_flags, SP_REQUEST_COMPLETED_RX) == 0); 2973 LM_TCP_SET_CQE(tx_cqe.params, pending->cid, RAMROD_OPCODE_TOE_RESET_SEND); 2974 cmp_tx = (GET_FLAGS(tcp->sp_flags, SP_REQUEST_COMPLETED_TX) == 0); 2975 break; 2976 case RAMROD_OPCODE_TOE_EMPTY_RAMROD: 2977 LM_TCP_SET_CQE(rx_cqe.params1, pending->cid, RAMROD_OPCODE_TOE_EMPTY_RAMROD); 2978 cmp_rx = (GET_FLAGS(tcp->sp_flags, SP_REQUEST_COMPLETED_RX) == 0); 2979 LM_TCP_SET_CQE(tx_cqe.params, pending->cid, RAMROD_OPCODE_TOE_EMPTY_RAMROD); 2980 cmp_tx = (GET_FLAGS(tcp->sp_flags, SP_REQUEST_COMPLETED_TX) == 0); 2981 break; 2982 case RAMROD_OPCODE_TOE_INVALIDATE: 2983 LM_TCP_SET_CQE(rx_cqe.params1, pending->cid, RAMROD_OPCODE_TOE_INVALIDATE); 2984 cmp_rx = (GET_FLAGS(tcp->sp_flags, SP_REQUEST_COMPLETED_RX) == 0); 2985 LM_TCP_SET_CQE(tx_cqe.params, pending->cid, RAMROD_OPCODE_TOE_INVALIDATE); 2986 cmp_tx = (GET_FLAGS(tcp->sp_flags, SP_REQUEST_COMPLETED_TX) == 0); 2987 break; 2988 case RAMROD_OPCODE_TOE_UPDATE: 2989 LM_TCP_SET_CQE(rx_cqe.params1, pending->cid, RAMROD_OPCODE_TOE_UPDATE); 2990 cmp_rx = TRUE; 2991 break; 2992 case RAMROD_OPCODE_TOE_RSS_UPDATE: 2993 /* This one is special, its not treated as other ramrods, we return and not break 2994 * at the end of this one... */ 2995 /* a bit of a hack here... we only want to give one completion and not on all 2996 * rcq-chains, so we update the counters and decrease all l4 rss chains 2997 * except one. then we give the completion to just one chain which should take care 2998 * of completing the sq and if L2 ramrod has completed already it will also comp 2999 * back to OS */ 3000 for (i = 0; i < pdev->params.l4_rss_chain_cnt-1; i++) 3001 { 3002 mm_atomic_dec(&pdev->params.update_toe_comp_cnt); 3003 mm_atomic_dec(&pdev->params.update_comp_cnt); 3004 mm_atomic_dec(&pdev->params.update_suspend_cnt); 3005 } 3006 lm_tcp_rss_update_ramrod_comp(pdev, 3007 &pdev->toe_info.rcqs[LM_TOE_BASE_RSS_ID(pdev)], 3008 pending->cid, 3009 TOE_RSS_UPD_QUIET /* doesn't really matter*/, 3010 TRUE); 3011 3012 return; 3013 } 3014 /* process the cqes and initialize connections with all the connections that appeared 3015 * in the DPC */ 3016 if (cmp_rx) 3017 { 3018 lm_tcp_rx_process_cqe(pdev, &rx_cqe, tcp, 0 /* d/c for slpowpath */); 3019 /* FP: no need to call complete_tcp_fp since we're only completing slowpath, but we do 3020 * need to move the flags for sake of next function */ 3021 rx_con->dpc_info.snapshot_flags = rx_con->dpc_info.dpc_flags; 3022 rx_con->dpc_info.dpc_flags = 0; 3023 3024 /* we access snapshot and not dpc, since once the dpc_flags were copied 3025 * to snapshot they were zeroized */ 3026 lm_tcp_rx_complete_tcp_sp(pdev, tcp, rx_con); 3027 } 3028 3029 /* process the cqes and initialize connections with all the connections that appeared 3030 * in the DPC */ 3031 if (cmp_tx) 3032 { 3033 lm_tcp_tx_process_cqe(pdev, &tx_cqe, tcp); 3034 /* FP: no need to call complete_tcp_fp since we're only completing slowpath, but we do 3035 * need to move the flags for sake of next function */ 3036 tx_con->dpc_info.snapshot_flags = tx_con->dpc_info.dpc_flags; 3037 tx_con->dpc_info.dpc_flags = 0; 3038 3039 /* we access snapshot and not dpc, since once the dpc_flags were copied 3040 * to snapshot they were zeroized */ 3041 lm_tcp_tx_complete_tcp_sp(pdev, tcp, tx_con); 3042 } 3043 3044 } 3045 3046 /* Desciption: 3047 * - init TCP state according to its TCP state machine's state 3048 * Assumptions: 3049 * - lm_tcp_init_tcp_state, lm_tcp_init_rx_con/tx_con already called 3050 * - send unacked data already posted 3051 * Returns: 3052 * SUCCESS or any failure */ 3053 static lm_status_t lm_tcp_init_tcp_state_machine( 3054 struct _lm_device_t *pdev, 3055 lm_tcp_state_t *tcp) 3056 { 3057 lm_tcp_con_t *con = tcp->rx_con; 3058 lm_tcp_state_calculation_t *state_calc = &tcp->tcp_state_calc; 3059 u64_t curr_time = 0; 3060 lm_status_t lm_status = LM_STATUS_SUCCESS; 3061 3062 DbgMessage(pdev, VERBOSEl4sp, "##lm_tcp_init_tcp_state_machine\n"); 3063 3064 /* initiate times in the state calculation struct 3065 according to delegated.con_state */ 3066 3067 state_calc->fin_request_time = state_calc->fin_completed_time = 3068 state_calc->fin_reception_time = 0; 3069 curr_time = mm_get_current_time(pdev); 3070 3071 switch (tcp->tcp_delegated.con_state) { 3072 case L4_TCP_CON_STATE_ESTABLISHED: 3073 break; 3074 case L4_TCP_CON_STATE_FIN_WAIT1: 3075 DbgMessage(pdev, WARNl4sp, "#tcp state offloaded in state FIN_WAIT1 (tcp=%p)\n", tcp); 3076 state_calc->fin_request_time = curr_time; 3077 break; 3078 case L4_TCP_CON_STATE_FIN_WAIT2: 3079 DbgMessage(pdev, WARNl4sp, "#tcp state offloaded in state FIN_WAIT2 (tcp=%p)\n", tcp); 3080 state_calc->fin_request_time = curr_time - 1; 3081 state_calc->fin_completed_time = curr_time; 3082 break; 3083 case L4_TCP_CON_STATE_CLOSE_WAIT: 3084 DbgMessage(pdev, WARNl4sp, "#tcp state offloaded in state CLOSE_WAIT (tcp=%p)\n", tcp); 3085 state_calc->fin_reception_time = curr_time; 3086 break; 3087 case L4_TCP_CON_STATE_CLOSING: 3088 DbgMessage(pdev, WARNl4sp, "#tcp state offloaded in state CLOSING (tcp=%p)\n", tcp); 3089 state_calc->fin_request_time = curr_time - 1; 3090 state_calc->fin_reception_time = curr_time; 3091 break; 3092 case L4_TCP_CON_STATE_LAST_ACK: 3093 DbgMessage(pdev, WARNl4sp, "#tcp state offloaded in state LAST_ACK (tcp=%p)\n", tcp); 3094 state_calc->fin_reception_time = curr_time - 1; 3095 state_calc->fin_request_time = curr_time; 3096 break; 3097 default: 3098 DbgMessage(pdev, FATAL, 3099 "Initiate offload in con state=%d is not allowed by WDK!\n", 3100 tcp->tcp_delegated.con_state); 3101 DbgBreak(); 3102 return LM_STATUS_FAILURE; 3103 } 3104 3105 /* In case the the TCP state is CloseWait, Closing or LastAck, the Rx con 3106 * should be initiated as if remote FIN was already received */ 3107 3108 if (state_calc->fin_reception_time) { 3109 /* remote FIN was already received */ 3110 DbgBreakIf(con->flags & TCP_REMOTE_FIN_RECEIVED); 3111 con->flags |= TCP_REMOTE_FIN_RECEIVED; 3112 3113 if (con->flags & TCP_INDICATE_REJECTED) { 3114 /* GilR: TODO - is this case really possible [fin received+buffered data given]? If so, does NDIS really expect the fin received indication? */ 3115 /* buffered data exists, defer FIN indication */ 3116 con->u.rx.flags |= TCP_CON_FIN_IND_PENDING; 3117 } else { 3118 /* no buffered data, simulate that remote FIN already indicated */ 3119 con->flags |= TCP_REMOTE_FIN_RECEIVED_ALL_RX_INDICATED; 3120 con->flags |= TCP_BUFFERS_ABORTED; 3121 } 3122 } 3123 3124 con = tcp->tx_con; 3125 /* check if local FIN was already sent, and if it was acknowledged */ 3126 if (state_calc->fin_completed_time) { 3127 /* FIN already sent and acked */ 3128 volatile struct toe_tx_db_data *db_data = con->db_data.tx; 3129 DbgBreakIf(!state_calc->fin_request_time); 3130 DbgBreakIf(!s_list_is_empty(&con->active_tb_list)); 3131 con->flags |= (TCP_FIN_REQ_POSTED | TCP_FIN_REQ_COMPLETED); 3132 db_data->flags |= (TOE_TX_DB_DATA_FIN << TOE_TX_DB_DATA_FIN_SHIFT); 3133 db_data->bytes_prod_seq--; 3134 } else if (state_calc->fin_request_time) { 3135 /* FIN was already sent but not acked */ 3136 3137 /* GilR 11/12/2006 - TODO - we do not take the tx lock here, verify that its ok... */ 3138 /* We want to make sure we'll be able to post the tcp buffer but 3139 * NOT ring the doorbell */ 3140 DbgBreakIf(con->flags & TCP_DB_BLOCKED); 3141 con->flags |= TCP_DB_BLOCKED; 3142 DbgBreakIf(!(con->flags & TCP_POST_BLOCKED)); 3143 con->flags &= ~TCP_POST_BLOCKED; /* posting is temporary allowed */ 3144 3145 con->u.tx.flags |= TCP_CON_FIN_REQ_LM_INTERNAL; 3146 lm_status = lm_tcp_graceful_disconnect(pdev, tcp); 3147 DbgBreakIf(lm_status != LM_STATUS_SUCCESS); 3148 3149 /* retrieve initial state */ 3150 con->flags &= ~TCP_DB_BLOCKED; 3151 con->flags |= TCP_POST_BLOCKED; /* posting is no longer allowed*/ 3152 } 3153 3154 return LM_STATUS_SUCCESS; 3155 } 3156 3157 3158 /* Desciption: 3159 * - call lm_tcp_init_tcp_state_machine 3160 * - call lm_tcp_init_tcp_context 3161 * Assumptions: 3162 * - lm_tcp_init_tcp_state, lm_tcp_init_rx_con/tx_con already called 3163 * - send unacked data already posted 3164 * Returns: 3165 * SUCCESS or any failure */ 3166 lm_status_t lm_tcp_init_tcp_common( 3167 struct _lm_device_t *pdev, 3168 lm_tcp_state_t *tcp) 3169 { 3170 lm_status_t lm_status = LM_STATUS_SUCCESS; 3171 3172 DbgMessage(pdev, VERBOSEl4sp, "###lm_tcp_init_tcp_common\n"); 3173 DbgBreakIf(!(pdev && tcp)); 3174 3175 lm_status = lm_tcp_init_tcp_state_machine(pdev, tcp); 3176 if (lm_status != LM_STATUS_SUCCESS) { 3177 return lm_status; 3178 } 3179 3180 lm_status = lm_tcp_init_tcp_context(pdev, tcp); 3181 if (lm_status != LM_STATUS_SUCCESS) { 3182 return lm_status; 3183 } 3184 3185 if (tcp->ulp_type == TOE_CONNECTION_TYPE) { 3186 tcp->rx_con->u.rx.gen_info.dont_send_to_system_more_then_rwin = FALSE; //TRUE; 3187 } 3188 3189 return LM_STATUS_SUCCESS; 3190 } 3191 3192 3193 static void _lm_tcp_comp_upload_neigh_request( 3194 struct _lm_device_t * pdev, 3195 lm_neigh_state_t * neigh_state) 3196 { 3197 DbgBreakIf(neigh_state->hdr.status != STATE_STATUS_UPLOAD_PENDING); 3198 DbgBreakIf(neigh_state->hdr.state_id != STATE_ID_NEIGH); 3199 3200 DbgBreakIf(neigh_state->num_dependents); 3201 3202 neigh_state->hdr.status = STATE_STATUS_UPLOAD_DONE; 3203 mm_tcp_complete_neigh_upload_request(pdev, neigh_state); 3204 } 3205 3206 3207 /** Description 3208 * upload path state 3209 * Assumptions: 3210 * called under TOE-lock 3211 */ 3212 static void _lm_tcp_comp_upload_path_request( 3213 struct _lm_device_t * pdev, 3214 lm_path_state_t * path_state) 3215 { 3216 lm_neigh_state_t * neigh = NULL; 3217 3218 DbgBreakIf(path_state->hdr.status != STATE_STATUS_UPLOAD_PENDING); 3219 DbgBreakIf(path_state->hdr.state_id != STATE_ID_PATH); 3220 3221 path_state->hdr.status = STATE_STATUS_UPLOAD_DONE; 3222 3223 DbgBreakIf(path_state->neigh->num_dependents == 0); 3224 path_state->neigh->num_dependents--; 3225 if ((path_state->neigh->num_dependents == 0) && 3226 (path_state->neigh->hdr.status == STATE_STATUS_UPLOAD_PENDING)) { 3227 /* Time to release the neighbor resources...*/ 3228 neigh = path_state->neigh; 3229 } 3230 path_state->neigh = NULL; 3231 3232 DbgBreakIf(path_state->num_dependents); 3233 3234 mm_tcp_complete_path_upload_request(pdev, path_state); 3235 3236 if (neigh) { 3237 _lm_tcp_comp_upload_neigh_request(pdev, neigh); 3238 } 3239 } 3240 3241 3242 /* post initiate offload slow path ramrod 3243 * returns SUCCESS or any failure */ 3244 static lm_status_t lm_tcp_post_initiate_offload_request( 3245 struct _lm_device_t *pdev, 3246 lm_tcp_state_t *tcp, 3247 u8_t *command, 3248 u64_t *data) 3249 { 3250 lm_tcp_con_t *con = tcp->tx_con; 3251 int i = 0; 3252 MM_INIT_TCP_LOCK_HANDLE(); 3253 3254 DbgMessage(pdev, VERBOSEl4sp, "##lm_tcp_post_initiate_offload_request\n"); 3255 DbgBreakIf(tcp->hdr.status != STATE_STATUS_INIT_CONTEXT); 3256 tcp->hdr.status = STATE_STATUS_OFFLOAD_PENDING; 3257 3258 if (tcp->ulp_type == TOE_CONNECTION_TYPE) { 3259 con = tcp->tx_con; 3260 for (i = 0; i < 2; i++) { 3261 mm_acquire_tcp_lock(pdev, con); 3262 DbgBreakIf(!(con->flags & TCP_POST_BLOCKED)); 3263 DbgBreakIf(!(con->flags & TCP_COMP_BLOCKED)); 3264 con->flags &= ~TCP_COMP_BLOCKED; 3265 con->flags |= TCP_COMP_DEFERRED; /* completions are now allowed but deferred */ 3266 mm_release_tcp_lock(pdev, con); 3267 con = tcp->rx_con; 3268 } 3269 } 3270 3271 tcp->sp_flags |= SP_TCP_OFLD_REQ_POSTED; 3272 *command = (tcp->ulp_type == TOE_CONNECTION_TYPE)? RAMROD_OPCODE_TOE_INITIATE_OFFLOAD : L5CM_RAMROD_CMD_ID_ADD_NEW_CONNECTION; 3273 *data = tcp->ctx_phys.as_u64; 3274 3275 return LM_STATUS_PENDING; 3276 } 3277 3278 3279 static lm_status_t lm_tcp_post_terminate_tcp_request ( 3280 IN struct _lm_device_t * pdev, 3281 IN lm_tcp_state_t * tcp, 3282 OUT u8_t * command, 3283 OUT u64_t * data 3284 ) 3285 { 3286 DbgMessage(pdev, VERBOSEl4sp, "## lm_tcp_post_terminate_tcp_request\n"); 3287 3288 DbgBreakIf(tcp->hdr.status != STATE_STATUS_UPLOAD_PENDING); 3289 3290 lm_tcp_flush_db(pdev,tcp); 3291 3292 SET_FLAGS(tcp->sp_flags, SP_TCP_TRM_REQ_POSTED ); 3293 3294 *command = (tcp->ulp_type == TOE_CONNECTION_TYPE)? RAMROD_OPCODE_TOE_TERMINATE : L5CM_RAMROD_CMD_ID_TERMINATE_OFFLOAD; 3295 *data = 0; 3296 3297 return LM_STATUS_PENDING; 3298 } 3299 3300 /** 3301 Description: 3302 * Posts RST request. 3303 * 3304 * Assumptions: 3305 * - Global TOE lock is already taken by the caller. 3306 * 3307 * Returns: 3308 * SUCCESS or any failure 3309 * 3310 */ 3311 static lm_status_t lm_tcp_post_abortive_disconnect_request ( 3312 IN struct _lm_device_t * pdev, 3313 IN lm_tcp_state_t * tcp, 3314 OUT u8_t * command, 3315 OUT u64_t * data 3316 ) 3317 { 3318 /* Get Rx and Tx connections */ 3319 lm_tcp_con_t *rx_con = tcp->rx_con; 3320 lm_tcp_con_t *tx_con = tcp->tx_con; 3321 3322 MM_INIT_TCP_LOCK_HANDLE(); 3323 3324 DbgMessage(pdev, VERBOSEl4sp, "## lm_tcp_post_abortive_disconnect_request\n"); 3325 DbgBreakIf( (tcp->hdr.status != STATE_STATUS_NORMAL ) && 3326 (tcp->hdr.status != STATE_STATUS_ABORTED) ); 3327 3328 /*********************** Tx **********************/ 3329 /* Take Tx lock */ 3330 mm_acquire_tcp_lock(pdev, tx_con); 3331 3332 /* This will imply Tx POST_BLOCKED */ 3333 tx_con->flags |= TCP_RST_REQ_POSTED; 3334 3335 /* Release Tx lock */ 3336 mm_release_tcp_lock(pdev, tx_con); 3337 3338 /*********************** Rx **********************/ 3339 /* Take Rx lock */ 3340 mm_acquire_tcp_lock(pdev, rx_con); 3341 3342 /* This will imply Rx POST_BLOCKED and IND_BLOCKED */ 3343 rx_con->flags |= TCP_RST_REQ_POSTED; 3344 3345 /* Release Rx lock */ 3346 mm_release_tcp_lock(pdev, rx_con); 3347 /**************Post the ramrod *******************/ 3348 *command = RAMROD_OPCODE_TOE_RESET_SEND; 3349 *data = 0; 3350 3351 return LM_STATUS_PENDING; 3352 } 3353 3354 3355 /** 3356 Description: 3357 * Initiates the TCP connection upload process. 3358 * Posts a Searcher ramrod to the chip. 3359 * 3360 * Assumptions: 3361 * - Global TOE lock is already taken by the caller. 3362 * - UM caller has allocated "struct toe_context" phys. cont. buffer 3363 * and put its address to "data.phys_addr". 3364 * Returns: 3365 * SUCCESS or any failure 3366 * 3367 */ 3368 static lm_status_t lm_tcp_post_upload_tcp_request ( 3369 IN struct _lm_device_t * pdev, 3370 IN lm_tcp_state_t * tcp, 3371 OUT u8_t * command, 3372 OUT u64_t * data 3373 ) 3374 { 3375 lm_tcp_con_t *rx_con, *tx_con = NULL; 3376 struct toe_spe spe = {{0}}; 3377 MM_INIT_TCP_LOCK_HANDLE(); 3378 3379 DbgMessage(pdev, VERBOSEl4sp, "## lm_tcp_post_upload_tcp_request\n"); 3380 DbgBreakIf(tcp->hdr.status < STATE_STATUS_NORMAL); 3381 DbgBreakIf(tcp->hdr.status >= STATE_STATUS_UPLOAD_PENDING); 3382 DbgBreakIf(tcp->hdr.state_id != STATE_ID_TCP); 3383 3384 3385 /* Set the status of the connection to UPLOAD_PENDING */ 3386 tcp->hdr.status = STATE_STATUS_UPLOAD_PENDING; 3387 3388 if (tcp->ulp_type == TOE_CONNECTION_TYPE) { 3389 /* Get Rx and Tx connections */ 3390 rx_con = tcp->rx_con; 3391 tx_con = tcp->tx_con; 3392 3393 /* Set the flags for the connections (Rx and Tx) */ 3394 /* Tx */ 3395 mm_acquire_tcp_lock(pdev, tx_con); 3396 DbgBreakIf(tx_con->flags & TCP_TRM_REQ_POSTED); 3397 tx_con->flags |= TCP_TRM_REQ_POSTED; 3398 mm_release_tcp_lock(pdev, tx_con); 3399 /* Rx */ 3400 mm_acquire_tcp_lock(pdev, rx_con); 3401 DbgBreakIf(rx_con->flags & TCP_TRM_REQ_POSTED); 3402 rx_con->flags |= TCP_TRM_REQ_POSTED; 3403 mm_release_tcp_lock(pdev, rx_con); 3404 } 3405 3406 tcp->sp_flags |= SP_TCP_SRC_REQ_POSTED; 3407 3408 *command = (tcp->ulp_type == TOE_CONNECTION_TYPE)? RAMROD_OPCODE_TOE_SEARCHER_DELETE : L5CM_RAMROD_CMD_ID_SEARCHER_DELETE; 3409 spe.toe_data.rx_completion.hash_value = (u16_t)(tcp->tcp_const.hash_value); 3410 *data = *((u64_t*)(&(spe.toe_data.rx_completion))); 3411 3412 return LM_STATUS_PENDING; 3413 } 3414 3415 static lm_status_t lm_tcp_post_query_request ( 3416 IN struct _lm_device_t * pdev, 3417 IN lm_tcp_state_t * tcp, 3418 OUT u8_t * command, 3419 OUT u64_t * data, 3420 IN lm_tcp_slow_path_request_t * request 3421 ) 3422 { 3423 struct toe_spe spe = {{0}}; 3424 3425 UNREFERENCED_PARAMETER_(request); 3426 3427 DbgMessage(pdev, VERBOSEl4sp, "## lm_tcp_post_query_request\n"); 3428 3429 tcp->sp_flags |= SP_TCP_QRY_REQ_POSTED; 3430 *command = (tcp->ulp_type == TOE_CONNECTION_TYPE)? RAMROD_OPCODE_TOE_QUERY : L5CM_RAMROD_CMD_ID_QUERY; 3431 3432 mm_memset(tcp->sp_req_data.virt_addr, 0, TOE_SP_PHYS_DATA_SIZE); 3433 3434 spe.toe_data.phys_addr.hi = tcp->sp_req_data.phys_addr.as_u32.high; 3435 spe.toe_data.phys_addr.lo = tcp->sp_req_data.phys_addr.as_u32.low; 3436 *data = *((u64_t*)(&(spe.toe_data.phys_addr))); 3437 3438 return LM_STATUS_PENDING; 3439 } 3440 3441 lm_status_t lm_tcp_post_upload_path_request ( 3442 struct _lm_device_t * pdev, 3443 lm_path_state_t * path_state, 3444 l4_path_delegated_state_t * ret_delegated) 3445 { 3446 3447 DbgBreakIf(path_state->hdr.status != STATE_STATUS_NORMAL); 3448 DbgBreakIf(path_state->hdr.state_id != STATE_ID_PATH); 3449 3450 /* MichalS TBA: do we need this? (also in spec ('ipv4_current_ip_id' unclear)) */ 3451 *ret_delegated = path_state->path_delegated; 3452 3453 DbgMessage(pdev, INFORMl4sp, "lm_tcp_post_upload_path_request: num_dependents=%d\n", path_state->num_dependents); 3454 3455 if (path_state->num_dependents == 0) { 3456 path_state->hdr.status = STATE_STATUS_UPLOAD_DONE; 3457 return LM_STATUS_SUCCESS; 3458 } 3459 path_state->hdr.status = STATE_STATUS_UPLOAD_PENDING; 3460 return LM_STATUS_PENDING; 3461 3462 } 3463 3464 lm_status_t lm_tcp_post_upload_neigh_request( 3465 struct _lm_device_t * pdev, 3466 lm_neigh_state_t * neigh_state 3467 ) 3468 { 3469 DbgBreakIf(neigh_state->hdr.status != STATE_STATUS_NORMAL); 3470 DbgBreakIf(neigh_state->hdr.state_id != STATE_ID_NEIGH); 3471 3472 DbgMessage(pdev, INFORMl4sp, "lm_tcp_post_upload_neigh_request: num_dependents=%d\n", neigh_state->num_dependents); 3473 3474 #if DBG 3475 { 3476 /* NirV: multi client todo */ 3477 lm_path_state_t * path = (lm_path_state_t *) d_list_peek_head(&pdev->toe_info.state_blk.path_list); 3478 while(path) { 3479 if(path->neigh == neigh_state) { 3480 DbgBreakIf(path->hdr.status == STATE_STATUS_NORMAL); 3481 } 3482 path = (lm_path_state_t *) d_list_next_entry(&path->hdr.link); 3483 } 3484 } 3485 #endif 3486 3487 if (neigh_state->num_dependents == 0) { 3488 neigh_state->hdr.status = STATE_STATUS_UPLOAD_DONE; 3489 return LM_STATUS_SUCCESS; 3490 } 3491 neigh_state->hdr.status = STATE_STATUS_UPLOAD_PENDING; 3492 return LM_STATUS_PENDING; 3493 3494 } 3495 3496 /* sets the cached parameters of tcp/path/neigh and initializes a toe_context (which is initially all zeros) */ 3497 static lm_status_t lm_tcp_set_tcp_cached( 3498 struct _lm_device_t * pdev, 3499 lm_tcp_state_t * tcp, 3500 l4_tcp_cached_state_t * tcp_cached, 3501 void * mem_virt /* firmware context */ 3502 ) 3503 { 3504 struct toe_update_ramrod_cached_params * ctx = mem_virt; 3505 l4_ofld_params_t * l4_params = &(pdev->ofld_info.l4_params); 3506 3507 MM_INIT_TCP_LOCK_HANDLE(); 3508 3509 /* tcp-flags */ 3510 DbgMessage(pdev, INFORMl4sp, "## lm_tcp_set_tcp_cached cid=%d\n", tcp->cid); 3511 3512 if ((tcp->tcp_cached.tcp_flags & TCP_FLAG_ENABLE_KEEP_ALIVE) != 3513 (tcp_cached->tcp_flags & TCP_FLAG_ENABLE_KEEP_ALIVE)) { 3514 if (tcp_cached->tcp_flags & TCP_FLAG_ENABLE_KEEP_ALIVE) { 3515 ctx->enable_keepalive = 1; 3516 } else { 3517 ctx->enable_keepalive = 0; 3518 } 3519 ctx->changed_fields |= TOE_UPDATE_RAMROD_CACHED_PARAMS_ENABLE_KEEPALIVE_CHANGED; 3520 DbgMessage(pdev, INFORMl4sp, "## tcp_cached: [cid=%d] update : flag TCP_FLAG_ENABLE_KEEP_ALIVE changed to %d\n", 3521 tcp->cid, ctx->enable_keepalive); 3522 } 3523 if ((tcp->tcp_cached.tcp_flags & TCP_FLAG_ENABLE_NAGLING) != 3524 (tcp_cached->tcp_flags & TCP_FLAG_ENABLE_NAGLING)) { 3525 if (tcp_cached->tcp_flags & TCP_FLAG_ENABLE_NAGLING) { 3526 ctx->enable_nagle = 1; 3527 } else { 3528 ctx->enable_nagle = 0; 3529 } 3530 ctx->changed_fields |= TOE_UPDATE_RAMROD_CACHED_PARAMS_ENABLE_NAGLE_CHANGED; 3531 DbgMessage(pdev, INFORMl4sp, "## tcp_cached [cid=%d] update : flag TCP_FLAG_ENABLE_NAGLING changed to %d\n", 3532 tcp->cid, ctx->enable_nagle); 3533 } 3534 if (tcp_cached->tcp_flags & TCP_FLAG_RESTART_KEEP_ALIVE) { 3535 ctx->ka_restart = 1; 3536 DbgMessage(pdev, INFORMl4sp, "## tcp_cached [cid=%d] update : flag TCP_FLAG_RESTART_KEEP_ALIVE set\n", 3537 tcp->cid); 3538 } else { 3539 ctx->ka_restart = 0; 3540 } 3541 if (tcp_cached->tcp_flags & TCP_FLAG_RESTART_MAX_RT) { 3542 ctx->retransmit_restart = 1; 3543 DbgMessage(pdev, INFORMl4sp, "## tcp_cached [cid=%d] update : flag TOE_CACHED_RESTART_MAX_RT set\n", 3544 tcp->cid); 3545 } else { 3546 ctx->retransmit_restart = 0; 3547 } 3548 if (tcp_cached->tcp_flags & TCP_FLAG_UPDATE_RCV_WINDOW) { 3549 /* for debugging purposes */ 3550 DbgMessage(pdev, INFORMl4sp, "## tcp_cached [cid=%d] update : flag TCP_FLAG_UPDATE_RCV_WINDOW set\n", 3551 tcp->cid); 3552 } 3553 3554 tcp->tcp_cached.tcp_flags = tcp_cached->tcp_flags; 3555 3556 /* flow label ipv6 only */ 3557 if (tcp->path->path_const.ip_version == IP_VERSION_IPV6) { 3558 if (tcp->tcp_cached.flow_label != tcp_cached->flow_label) { 3559 DbgMessage(pdev, INFORMl4sp, "## tcp_cached [cid=%d] update : flow_label changed from %d to %d\n", 3560 tcp->cid, tcp->tcp_cached.flow_label, tcp_cached->flow_label); 3561 tcp->tcp_cached.flow_label = tcp_cached->flow_label; 3562 ctx->flow_label= tcp->tcp_cached.flow_label; 3563 ctx->changed_fields |= TOE_UPDATE_RAMROD_CACHED_PARAMS_FLOW_LABEL_CHANGED; 3564 } 3565 } 3566 3567 /* initial_rcv_wnd */ 3568 if (tcp->tcp_cached.initial_rcv_wnd != tcp_cached->initial_rcv_wnd) { 3569 DbgMessage(pdev, INFORMl4sp, "## tcp_cached [cid=%d] update : initial_rcv_wnd changed from %d to %d\n", 3570 tcp->cid, tcp->tcp_cached.initial_rcv_wnd, tcp_cached->initial_rcv_wnd); 3571 /* no change to firmware */ 3572 mm_tcp_update_required_gen_bufs(pdev, 3573 tcp->rx_con->u.rx.sws_info.mss, /* new-mss(no change)*/ 3574 tcp->rx_con->u.rx.sws_info.mss, /* old-mss*/ 3575 tcp_cached->initial_rcv_wnd, /* new initial receive window */ 3576 tcp->tcp_cached.initial_rcv_wnd); /* old initial receive window */ 3577 3578 /* In VISTA and higher, window CAN decrease! */ 3579 if ERR_IF(tcp_cached->initial_rcv_wnd > MAX_INITIAL_RCV_WND) { 3580 /* TBD: Miniport doesn't handle any parameter other than SUCCESS / PENDING... */ 3581 /* TODO: return LM_STATUS_INVALID_PARAMETER; */ 3582 DbgBreakIfAll(tcp_cached->initial_rcv_wnd > MAX_INITIAL_RCV_WND); 3583 } 3584 /* update the sws_bytea accordingly */ 3585 mm_acquire_tcp_lock(pdev,tcp->rx_con); 3586 /* it's now time to give the window doorbell in-case there was a window update - could be negative, in which case, special handling is required... */ 3587 if (tcp->tcp_cached.initial_rcv_wnd < tcp_cached->initial_rcv_wnd) { 3588 /* regular window update */ 3589 lm_tcp_rx_post_sws(pdev, tcp, tcp->rx_con, tcp_cached->initial_rcv_wnd - tcp->tcp_cached.initial_rcv_wnd, TCP_RX_POST_SWS_INC); 3590 } else { 3591 lm_tcp_rx_post_sws(pdev, tcp, tcp->rx_con, tcp->tcp_cached.initial_rcv_wnd - tcp_cached->initial_rcv_wnd, TCP_RX_POST_SWS_DEC); 3592 pdev->toe_info.toe_events |= LM_TOE_EVENT_WINDOW_DECREASE; 3593 } 3594 mm_release_tcp_lock(pdev, tcp->rx_con); 3595 tcp->tcp_cached.initial_rcv_wnd = tcp_cached->initial_rcv_wnd; 3596 ctx->initial_rcv_wnd = tcp->tcp_cached.initial_rcv_wnd; 3597 ctx->changed_fields |= TOE_UPDATE_RAMROD_CACHED_PARAMS_INITIAL_RCV_WND_CHANGED; 3598 } 3599 3600 /*ttl_or_hop_limit*/ 3601 if (tcp->tcp_cached.ttl_or_hop_limit != tcp_cached->ttl_or_hop_limit) { 3602 DbgMessage(pdev, INFORMl4sp, "## tcp_cached [cid=%d] update : ttl_or_hop_limit changed from %d to %d\n", 3603 tcp->cid, tcp->tcp_cached.ttl_or_hop_limit, tcp_cached->ttl_or_hop_limit); 3604 tcp->tcp_cached.ttl_or_hop_limit = tcp_cached->ttl_or_hop_limit; 3605 if (tcp->path->path_const.ip_version == IP_VERSION_IPV4) { 3606 ctx->ttl= tcp->tcp_cached.ttl_or_hop_limit; 3607 ctx->changed_fields |= TOE_UPDATE_RAMROD_CACHED_PARAMS_TTL_CHANGED; 3608 } else { 3609 ctx->hop_limit = tcp->tcp_cached.ttl_or_hop_limit; 3610 ctx->changed_fields |= TOE_UPDATE_RAMROD_CACHED_PARAMS_HOP_LIMIT_CHANGED; 3611 } 3612 } 3613 3614 /* tos_or_traffic_class */ 3615 if (tcp->tcp_cached.tos_or_traffic_class != tcp_cached->tos_or_traffic_class) { 3616 DbgMessage(pdev, INFORMl4sp, "## tcp_cached [cid=%d] update : tos_or_traffic_class changed from %d to %d\n", 3617 tcp->cid, tcp->tcp_cached.tos_or_traffic_class, tcp_cached->tos_or_traffic_class); 3618 tcp->tcp_cached.tos_or_traffic_class = tcp_cached->tos_or_traffic_class; 3619 3620 if (tcp->path->path_const.ip_version == IP_VERSION_IPV4) { 3621 ctx->tos = tcp_cached->tos_or_traffic_class; 3622 ctx->changed_fields |= TOE_UPDATE_RAMROD_CACHED_PARAMS_TOS_CHANGED; 3623 } else { 3624 ctx->traffic_class = tcp_cached->tos_or_traffic_class; 3625 ctx->changed_fields |= TOE_UPDATE_RAMROD_CACHED_PARAMS_TRAFFIC_CLASS_CHANGED; 3626 } 3627 } 3628 3629 /* ka_probe_cnt */ 3630 if (tcp->tcp_cached.ka_probe_cnt != tcp_cached->ka_probe_cnt) { 3631 DbgMessage(pdev, INFORMl4sp, "## tcp_cached [cid=%d] update : ka_probe_cnt changed from %d to %d\n", 3632 tcp->cid, tcp->tcp_cached.ka_probe_cnt, tcp_cached->ka_probe_cnt); 3633 tcp->tcp_cached.ka_probe_cnt = tcp_cached->ka_probe_cnt; 3634 ctx->ka_max_probe_count = tcp_cached->ka_probe_cnt; 3635 ctx->changed_fields |= TOE_UPDATE_RAMROD_CACHED_PARAMS_KA_MAX_PROBE_COUNT_CHANGED; 3636 } 3637 3638 /* user_priority */ 3639 if (tcp->tcp_cached.user_priority != tcp_cached->user_priority) { 3640 DbgMessage(pdev, INFORMl4sp, "## tcp_cached [cid=%d] update : user_priority changed from %d to %d\n", 3641 tcp->cid, tcp->tcp_cached.user_priority, tcp_cached->user_priority); 3642 DbgBreakIf(tcp_cached->user_priority > 0x7); 3643 tcp->tcp_cached.user_priority = tcp_cached->user_priority; 3644 ctx->user_priority = tcp_cached->user_priority; 3645 ctx->changed_fields |= TOE_UPDATE_RAMROD_CACHED_PARAMS_USER_PRIORITY_CHANGED; 3646 } 3647 3648 /* rcv_indication_size */ 3649 DbgBreakIf(tcp_cached->rcv_indication_size != 0); 3650 if (tcp->tcp_cached.rcv_indication_size != tcp_cached->rcv_indication_size) { 3651 DbgMessage(pdev, INFORMl4sp, "## tcp_cached [cid=%d] update : rcv_indication_size changed from %d to %d\n", 3652 tcp->cid, tcp->tcp_cached.rcv_indication_size, tcp_cached->rcv_indication_size); 3653 DbgBreakIf(tcp->tcp_cached.rcv_indication_size > 0xffff); 3654 tcp->tcp_cached.rcv_indication_size = tcp_cached->rcv_indication_size; 3655 ctx->rcv_indication_size = (u16_t)tcp_cached->rcv_indication_size; 3656 ctx->changed_fields |= TOE_UPDATE_RAMROD_CACHED_PARAMS_RCV_INDICATION_SIZE_CHANGED; 3657 } 3658 3659 /* ka_time_out */ 3660 if (tcp->tcp_cached.ka_time_out != tcp_cached->ka_time_out) { 3661 DbgMessage(pdev, INFORMl4sp, "## tcp_cached [cid=%d] update : ka_time_out changed from %d to %d\n", 3662 tcp->cid, tcp->tcp_cached.ka_time_out, tcp_cached->ka_time_out); 3663 tcp->tcp_cached.ka_time_out = tcp_cached->ka_time_out; 3664 ctx->ka_timeout = 3665 lm_time_resolution(pdev, tcp->tcp_cached.ka_time_out, l4_params->ticks_per_second, TIMERS_TICKS_PER_SEC); 3666 ctx->changed_fields |= TOE_UPDATE_RAMROD_CACHED_PARAMS_KA_TIMEOUT_CHANGED; 3667 } 3668 3669 /* ka_interval */ 3670 if (tcp->tcp_cached.ka_interval != tcp_cached->ka_interval) { 3671 DbgMessage(pdev, INFORMl4sp, "## tcp_cached [cid=%d] update : ka_interval changed from %d to %d\n", 3672 tcp->cid, tcp->tcp_cached.ka_interval, tcp_cached->ka_interval); 3673 tcp->tcp_cached.ka_interval = tcp_cached->ka_interval; 3674 ctx->ka_interval = 3675 lm_time_resolution(pdev, tcp->tcp_cached.ka_interval, l4_params->ticks_per_second, TIMERS_TICKS_PER_SEC); 3676 ctx->changed_fields |= TOE_UPDATE_RAMROD_CACHED_PARAMS_KA_INTERVAL_CHANGED; 3677 } 3678 3679 /* max_rt */ 3680 if (tcp->tcp_cached.max_rt != tcp_cached->max_rt) { 3681 DbgMessage(pdev, INFORMl4sp, "## tcp_cached [cid=%d] update : max_rt changed from %d to %d\n", 3682 tcp->cid, tcp->tcp_cached.max_rt, tcp_cached->max_rt); 3683 tcp->tcp_cached.max_rt = tcp_cached->max_rt; 3684 ctx->max_rt = 3685 lm_time_resolution(pdev, tcp->tcp_cached.max_rt, l4_params->ticks_per_second, TSEMI_CLK1_TICKS_PER_SEC); 3686 ctx->changed_fields |= TOE_UPDATE_RAMROD_CACHED_PARAMS_MAX_RT_CHANGED; 3687 } 3688 3689 if (!ctx->changed_fields && !ctx->ka_restart && !ctx->retransmit_restart) { 3690 DbgMessage(pdev, INFORMl4sp, "## tcp_cached [cid=%d] update : nothing changed, completing synchronously\n", tcp->cid); 3691 return LM_STATUS_SUCCESS; /* synchronous complete */ 3692 } 3693 //DbgMessage(pdev, WARNl4sp, "## lm_tcp_set_tcp_cached cid=%d DONE!\n", tcp->cid); 3694 return LM_STATUS_PENDING; 3695 } 3696 3697 /* sets the cached parameters of tcp/path/neigh and initializes a toe_context (which is initially all zeros) */ 3698 static lm_status_t lm_tcp_set_path_cached( 3699 struct _lm_device_t * pdev, 3700 lm_tcp_state_t * tcp, 3701 l4_path_cached_state_t * path_cached, 3702 void * mem_virt /* firmware context */ 3703 ) 3704 { 3705 struct toe_update_ramrod_cached_params * ctx = mem_virt; 3706 u32_t new_mss = 0; 3707 3708 new_mss = _lm_tcp_calc_mss(path_cached->path_mtu, 3709 tcp->tcp_const.remote_mss, 3710 (tcp->path->path_const.ip_version == IP_VERSION_IPV6), 3711 tcp->tcp_const.tcp_flags & TCP_FLAG_ENABLE_TIME_STAMP, 3712 pdev->ofld_info.l4_params.flags & OFLD_PARAM_FLAG_SNAP_ENCAP, 3713 tcp->path->neigh->neigh_const.vlan_tag != 0); 3714 3715 if (new_mss != tcp->rx_con->u.rx.sws_info.mss) { 3716 /* also need to notify um, since this may affect the number of generic buffers 3717 * required. */ 3718 DbgMessage(pdev, INFORMl4sp, "## path_cached: tcp [cid=%d] update : mss (as a result of pathMtu) from %d to %d\n", 3719 tcp->cid, tcp->rx_con->u.rx.sws_info.mss, new_mss); 3720 mm_tcp_update_required_gen_bufs(pdev, 3721 new_mss, 3722 tcp->rx_con->u.rx.sws_info.mss, /* old-mss*/ 3723 tcp->tcp_cached.initial_rcv_wnd, /* new initial receive window */ 3724 tcp->tcp_cached.initial_rcv_wnd); /* old initial receive window */ 3725 3726 tcp->rx_con->u.rx.sws_info.mss = new_mss; 3727 DbgBreakIf(new_mss > 0xffff); 3728 ctx->mss = (u16_t)new_mss; 3729 ctx->changed_fields |= TOE_UPDATE_RAMROD_CACHED_PARAMS_MSS_CHANGED; 3730 } 3731 3732 if (ctx->changed_fields == 0) { 3733 return LM_STATUS_SUCCESS; /* synchronous complete */ 3734 } 3735 3736 return LM_STATUS_PENDING; 3737 } 3738 3739 /* sets the cached parameters of tcp/path/neigh and initializes a toe_context (which is initially all zeros) 3740 * Assumption: this function is only called if in-fact, the destination address changed. 3741 */ 3742 static lm_status_t lm_tcp_set_neigh_cached( 3743 struct _lm_device_t * pdev, 3744 lm_tcp_state_t * tcp, 3745 l4_neigh_cached_state_t * neigh_cached, 3746 void * mem_virt /* firmware context */ 3747 ) 3748 { 3749 struct toe_update_ramrod_cached_params * ctx = mem_virt; 3750 int i = 0; 3751 3752 DbgMessage(pdev, INFORMl4sp, "## neigh_cached: tcp [cid=%d] update : neighbor dst_addr\n", tcp->cid); 3753 3754 for (i = 0; i < 6; i++) { 3755 ctx->dest_addr[i] = (u8_t)neigh_cached->dst_addr[i]; /* TBA Michals : is this init correct? order of assignment*/ 3756 } 3757 ctx->changed_fields |= TOE_UPDATE_RAMROD_CACHED_PARAMS_DEST_ADDR_CHANGED; 3758 3759 return LM_STATUS_PENDING; 3760 } 3761 3762 static lm_status_t lm_tcp_post_update_request ( 3763 IN struct _lm_device_t * pdev, 3764 IN lm_tcp_state_t * tcp, 3765 OUT u8_t * command, 3766 OUT u64_t * data, 3767 IN lm_tcp_slow_path_request_t * request 3768 ) 3769 { 3770 struct toe_spe spe = {{0}}; 3771 lm_status_t lm_status = LM_STATUS_FAILURE ; 3772 3773 DbgBreakIf(tcp->hdr.state_id != STATE_ID_TCP); 3774 3775 *command = RAMROD_OPCODE_TOE_UPDATE; 3776 spe.toe_data.phys_addr.hi = tcp->sp_req_data.phys_addr.as_u32.high; 3777 spe.toe_data.phys_addr.lo = tcp->sp_req_data.phys_addr.as_u32.low; 3778 *data = *((u64_t*)(&(spe.toe_data.phys_addr))); 3779 mm_memset(tcp->sp_req_data.virt_addr, 0, sizeof(struct toe_update_ramrod_cached_params)); 3780 3781 DbgBreakIf((tcp->hdr.status != STATE_STATUS_NORMAL) && 3782 (tcp->hdr.status != STATE_STATUS_ABORTED)); 3783 3784 /* we need to initialize the data for firmware */ 3785 switch(request->type) { 3786 case SP_REQUEST_UPDATE_TCP: 3787 lm_status = lm_tcp_set_tcp_cached(pdev, tcp, 3788 request->sent_data.tcp_update_data.data, 3789 tcp->sp_req_data.virt_addr); 3790 break; 3791 case SP_REQUEST_UPDATE_PATH: 3792 DbgBreakIf(tcp->path->hdr.status != STATE_STATUS_NORMAL); 3793 DbgBreakIf(tcp->path->neigh->hdr.status != STATE_STATUS_NORMAL); 3794 lm_status = lm_tcp_set_path_cached(pdev, tcp, 3795 request->sent_data.tcp_update_data.data, 3796 tcp->sp_req_data.virt_addr); 3797 break; 3798 case SP_REQUEST_UPDATE_NEIGH: 3799 DbgBreakIf(tcp->path->neigh->hdr.status != STATE_STATUS_NORMAL); 3800 3801 lm_status = lm_tcp_set_neigh_cached(pdev, tcp, 3802 request->sent_data.tcp_update_data.data, 3803 tcp->sp_req_data.virt_addr); 3804 break; 3805 case SP_REQUEST_UPDATE_PATH_RELINK: 3806 /* we will always return PENDING status */ 3807 DbgBreakIf(tcp->path->neigh->hdr.status != STATE_STATUS_NORMAL); 3808 lm_status = lm_tcp_set_neigh_cached(pdev, tcp, 3809 &((lm_tcp_path_relink_cached_t *)request->sent_data.tcp_update_data.data)->neigh_cached, 3810 tcp->sp_req_data.virt_addr); 3811 3812 DbgBreakIf(tcp->path->hdr.status != STATE_STATUS_NORMAL); 3813 DbgBreakIf(tcp->path->neigh->hdr.status != STATE_STATUS_NORMAL); 3814 lm_tcp_set_path_cached(pdev, tcp, &((lm_tcp_path_relink_cached_t *)request->sent_data.tcp_update_data.data)->path_cached, 3815 tcp->sp_req_data.virt_addr); 3816 break; 3817 } 3818 3819 return lm_status; 3820 } 3821 3822 static lm_status_t lm_tcp_post_empty_ramrod_request( 3823 IN struct _lm_device_t * pdev, 3824 IN lm_tcp_state_t * tcp, 3825 OUT u8_t * command, 3826 OUT u64_t * data) 3827 { 3828 struct toe_spe spe = {{0}}; 3829 3830 DbgMessage(pdev, VERBOSEl4sp, "## lm_tcp_post_empty_ramrod_request\n"); 3831 3832 *command = RAMROD_OPCODE_TOE_EMPTY_RAMROD; 3833 spe.toe_data.rx_completion.hash_value = (u16_t)(tcp->tcp_const.hash_value); 3834 *data = *((u64_t*)(&(spe.toe_data.rx_completion))); 3835 3836 return LM_STATUS_PENDING; 3837 } 3838 3839 static lm_status_t lm_tcp_post_invalidate_request( 3840 IN struct _lm_device_t * pdev, 3841 IN lm_tcp_state_t * tcp, 3842 OUT u8_t * command, 3843 OUT u64_t * data) 3844 { 3845 /* Get Rx and Tx connections */ 3846 lm_tcp_con_t * rx_con = tcp->rx_con; 3847 lm_tcp_con_t * tx_con = tcp->tx_con; 3848 MM_INIT_TCP_LOCK_HANDLE(); 3849 3850 DbgMessage(pdev, INFORMl4sp, "## lm_tcp_post_invalidate_request cid=%d\n", tcp->cid); 3851 3852 DbgBreakIf(tcp->hdr.status != STATE_STATUS_NORMAL && 3853 tcp->hdr.status != STATE_STATUS_ABORTED); 3854 3855 /* Set the flags for the connections (Rx and Tx) */ 3856 /* Tx */ 3857 mm_acquire_tcp_lock(pdev, tx_con); 3858 DbgBreakIf(tx_con->flags & TCP_INV_REQ_POSTED); 3859 tx_con->flags |= TCP_INV_REQ_POSTED; 3860 mm_release_tcp_lock(pdev, tx_con); 3861 /* Rx */ 3862 mm_acquire_tcp_lock(pdev, rx_con); 3863 DbgBreakIf(rx_con->flags & TCP_INV_REQ_POSTED); 3864 rx_con->flags |= TCP_INV_REQ_POSTED; 3865 mm_release_tcp_lock(pdev, rx_con); 3866 3867 3868 *command = RAMROD_OPCODE_TOE_INVALIDATE; 3869 *data = 0; 3870 3871 return LM_STATUS_PENDING; 3872 } 3873 3874 3875 /* Desciption: 3876 * post slow path request of given type for given tcp state 3877 * Assumptions: 3878 * - caller initialized request->type according to his specific request 3879 * - caller allocated space for request->data, according to the specific request type 3880 * - all previous slow path requests for given tcp state are already completed 3881 * Returns: 3882 * PENDING, SUCCESS or any failure */ 3883 lm_status_t lm_tcp_post_slow_path_request( 3884 struct _lm_device_t *pdev, 3885 lm_tcp_state_t *tcp, 3886 lm_tcp_slow_path_request_t *request) 3887 { 3888 lm_status_t lm_status = LM_STATUS_INVALID_PARAMETER; 3889 u64_t data = 0; 3890 u8_t command = 0; 3891 3892 DbgBreakIf(!(pdev && tcp && request)); 3893 DbgBreakIf(tcp->sp_request); /* lm supports only one pending slow path request per connection */ 3894 DbgMessage(pdev, VERBOSEl4sp, "### lm_tcp_post_slow_path_request cid=%d, type=%d\n", tcp->cid, request->type); 3895 DbgBreakIf(tcp->cid && (tcp != lm_cid_cookie(pdev, TOE_CONNECTION_TYPE, tcp->cid))); 3896 tcp->sp_request = request; 3897 3898 switch(request->type) { 3899 /* call the type specific post function that: 3900 execute any actions required for the specific sp request (possibly take tx/rx locks for that) 3901 according to state, possibly set the request status and complete the request synchronously 3902 fill the appropriate content in the lm information structure of the request */ 3903 case SP_REQUEST_INITIATE_OFFLOAD: 3904 lm_status = lm_tcp_post_initiate_offload_request(pdev, tcp, &command, &data); 3905 break; 3906 case SP_REQUEST_TERMINATE1_OFFLOAD: 3907 lm_status = lm_tcp_post_terminate_tcp_request(pdev, tcp, &command, &data); 3908 break; 3909 case SP_REQUEST_TERMINATE_OFFLOAD: 3910 lm_status = lm_tcp_post_upload_tcp_request(pdev, tcp, &command, &data); 3911 break; 3912 case SP_REQUEST_QUERY: 3913 lm_status = lm_tcp_post_query_request(pdev, tcp, &command, &data, request); 3914 break; 3915 case SP_REQUEST_UPDATE_TCP: 3916 case SP_REQUEST_UPDATE_PATH: 3917 case SP_REQUEST_UPDATE_NEIGH: 3918 case SP_REQUEST_UPDATE_PATH_RELINK: 3919 lm_status = lm_tcp_post_update_request(pdev, tcp, &command, &data, request); 3920 break; 3921 case SP_REQUEST_INVALIDATE: 3922 lm_status = lm_tcp_post_invalidate_request(pdev, tcp, &command, &data); 3923 break; 3924 case SP_REQUEST_ABORTIVE_DISCONNECT: 3925 lm_status = lm_tcp_post_abortive_disconnect_request(pdev,tcp, &command, &data); 3926 break; 3927 case SP_REQUEST_PENDING_LOCAL_FIN_DISCONNECT: 3928 case SP_REQUEST_PENDING_REMOTE_DISCONNECT: 3929 case SP_REQUEST_PENDING_TX_RST: 3930 lm_status = lm_tcp_post_empty_ramrod_request(pdev, tcp, &command, &data); 3931 break; 3932 default: 3933 DbgBreakMsg("Illegal slow path request type!\n"); 3934 } 3935 if(lm_status == LM_STATUS_PENDING) { 3936 DbgMessage(pdev, VERBOSEl4sp, 3937 "calling lm_command_post, cid=%d, command=%d, con_type=%d, data=%lx\n", 3938 tcp->cid, command, tcp->ulp_type, data); 3939 if (tcp->hdr.status == STATE_STATUS_UPLOAD_DONE) 3940 { 3941 /* no slow path request can be posted after connection is uploaded */ 3942 DbgBreakIf(tcp->hdr.status == STATE_STATUS_UPLOAD_DONE); 3943 tcp->sp_request = NULL; 3944 lm_status = LM_STATUS_INVALID_PARAMETER; 3945 } else 3946 { 3947 lm_command_post(pdev, tcp->cid, command, CMD_PRIORITY_NORMAL, tcp->ulp_type, data); 3948 } 3949 } else { 3950 tcp->sp_request = NULL; 3951 } 3952 3953 request->status = lm_status; 3954 return lm_status; 3955 } 3956 3957 /* slow path request completion template */ 3958 // lm_status_t lm_tcp_comp_XXX_slow_path_request(struct _lm_device_t *pdev, 3959 // lm_tcp_state_t *tcp, 3960 // ...cqe...) 3961 // { 3962 // lm_tcp_slow_path_request_t *sp_request; 3963 // 3964 // DbgMessage(pdev, VERBOSEl4sp, "###lm_tcp_comp_XXX_slow_path_request\n"); 3965 // MM_ACQUIRE_TOE_LOCK(pdev); 3966 // DbgBreakIf(tcp->hdr.status != STATE_STATUS_YYY); 3967 // tcp->hdr.status = STATE_STATUS_ZZZ; 3968 // execute lm state actions if required 3969 // lm_sp_ring_command_completed (*) [not here, automatically in 'process CQ'] 3970 // MM_RELEASE_TOE_LOCK(pdev); 3971 // under tx lock, execute any Tx actions required (possibly call mm_*) 3972 // under rx lock, execute any Rx actions required (possibly call mm_*) 3973 // MM_ACQUIRE_TOE_LOCK(pdev); 3974 // tcp->sp_flags ~= (SP_REQ_COMPLETED_RX | SP_REQ_COMPLETED_TX) 3975 // tcp->sp_request->status = completion status; 3976 // sp_request = tcp->sp_request; 3977 // tcp->sp_request = NULL 3978 // mm_tcp_comp_slow_path_request(tcp, sp_request) 3979 // MM_RELEASE_TOE_LOCK(pdev); 3980 // } 3981 void lm_tcp_service_deferred_cqes(lm_device_t * pdev, lm_tcp_state_t * tcp) 3982 { 3983 lm_tcp_con_t * con = tcp->tx_con; 3984 u8_t idx = 0, dead=FALSE; 3985 MM_INIT_TCP_LOCK_HANDLE(); 3986 3987 DbgMessage(pdev, INFORMl4sp, "### lm_tcp_service_deferred_cqes cid=%d\n", tcp->cid); 3988 3989 3990 3991 for (idx = 0; idx < 2; idx++) { 3992 mm_acquire_tcp_lock(pdev, con); 3993 while(con->flags & TCP_DEFERRED_PROCESSING) { 3994 /* consistent state. at this stage, since we have the lock and deferred cqes need the lock 3995 * for processing, it's as if we have just processed X cqes and are about to complete the fp 3996 * of these cqes... During the complete of fp and sp, the lock may be released, in this case 3997 * more cqes may be processed, in which case TCP_DEFERRED_PROCESSING will be switched back on. */ 3998 con->flags &= ~TCP_DEFERRED_PROCESSING; 3999 DbgMessage(pdev, INFORMl4sp, "### deferred cid=%d\n", tcp->cid); 4000 4001 if (con->type == TCP_CON_TYPE_RX) { 4002 lm_tcp_rx_complete_tcp_fp(pdev, con->tcp_state, con); 4003 } else { 4004 lm_tcp_tx_complete_tcp_fp(pdev, con->tcp_state, con); 4005 } 4006 4007 if (con->dpc_info.snapshot_flags) { 4008 mm_release_tcp_lock(pdev, con); 4009 4010 if (con->type == TCP_CON_TYPE_RX) { 4011 lm_tcp_rx_complete_tcp_sp(pdev,tcp, con); 4012 } else { 4013 lm_tcp_tx_complete_tcp_sp(pdev,tcp, con); 4014 } 4015 4016 mm_acquire_tcp_lock(pdev, con); 4017 } 4018 } 4019 4020 con->flags &= ~TCP_COMP_DEFERRED; /* completions are no longer deferred */ 4021 4022 /* it's possible, that while processing the deferred cqes - the connection was uploaded, 4023 * since the TCP_COMP_DEFERRED flag was still on - we didn't delete it yet, now is the time 4024 * to delete it... note, that this can only happen while we're handling the deferred cqes of 4025 * Rx_con - since query will only complete on RX and not TX, that's why it's safe to check and 4026 * after handling rx we won't access this connection anymore....*/ 4027 dead = lm_tcp_is_tcp_dead(pdev, tcp, TCP_IS_DEAD_OP_OFLD_COMP_DFRD); 4028 4029 4030 mm_release_tcp_lock(pdev, con); 4031 4032 con = tcp->rx_con; 4033 4034 if (dead) { 4035 mm_tcp_del_tcp_state(pdev, tcp); 4036 } 4037 4038 } 4039 } 4040 4041 /* initiate offload request completion */ 4042 void lm_tcp_comp_initiate_offload_request( 4043 struct _lm_device_t *pdev, 4044 lm_tcp_state_t *tcp, 4045 u32_t comp_status) 4046 { 4047 lm_tcp_slow_path_request_t *sp_request; 4048 lm_tcp_con_t *con; 4049 lm_status_t lm_status = LM_STATUS_SUCCESS; 4050 int i; 4051 MM_INIT_TCP_LOCK_HANDLE(); 4052 4053 DbgMessage(pdev, VERBOSEl4sp, "##lm_tcp_comp_initiate_offload_request\n"); 4054 4055 MM_ACQUIRE_TOE_LOCK(pdev); 4056 4057 DbgBreakIf(tcp->hdr.status != STATE_STATUS_OFFLOAD_PENDING); 4058 4059 if(!comp_status) 4060 { /* successful completion */ 4061 tcp->hdr.status = STATE_STATUS_NORMAL; 4062 4063 if (tcp->ulp_type == TOE_CONNECTION_TYPE) 4064 { 4065 con = tcp->tx_con; 4066 for (i = 0; i < 2; i++) 4067 { 4068 mm_acquire_tcp_lock(pdev, con); 4069 DbgBreakIf(!(con->flags & TCP_COMP_DEFERRED)); 4070 DbgBreakIf(!(con->flags & TCP_POST_BLOCKED)); 4071 con->flags &= ~TCP_POST_BLOCKED; /* posting is now allowed */ 4072 mm_release_tcp_lock(pdev, con); 4073 con = tcp->rx_con; 4074 } 4075 4076 // update stats counters if TOE 4077 if( IP_VERSION_IPV4 == tcp->path->path_const.ip_version ) 4078 { 4079 ++pdev->vars.stats.stats_mirror.stats_drv.drv_toe.ipv[STATS_IP_4_IDX].currently_established; 4080 } 4081 else if( IP_VERSION_IPV6 == tcp->path->path_const.ip_version ) 4082 { 4083 ++pdev->vars.stats.stats_mirror.stats_drv.drv_toe.ipv[STATS_IP_6_IDX].currently_established; 4084 } 4085 } 4086 } 4087 else 4088 { 4089 #ifndef _VBD_CMD_ 4090 DbgMessage(pdev, FATAL, "initiate offload failed. err=%x\n", comp_status); 4091 #endif // _VBD_CMD_ 4092 tcp->hdr.status = STATE_STATUS_INIT_OFFLOAD_ERR; 4093 4094 if (tcp->ulp_type == TOE_CONNECTION_TYPE) 4095 { 4096 con = tcp->tx_con; 4097 for (i = 0; i < 2; i++) 4098 { 4099 mm_acquire_tcp_lock(pdev, con); 4100 DbgBreakIf((con->flags & ~TCP_INDICATE_REJECTED) != (TCP_POST_BLOCKED | TCP_COMP_DEFERRED)); 4101 con->flags &= ~TCP_COMP_DEFERRED; 4102 con->flags |= TCP_COMP_BLOCKED; /* completions are blocked */ 4103 mm_release_tcp_lock(pdev, con); 4104 con = tcp->rx_con; 4105 } 4106 } 4107 4108 lm_status = LM_STATUS_FAILURE; 4109 } 4110 4111 DbgBreakIf(tcp->sp_flags & (SP_REQUEST_COMPLETED_RX | SP_REQUEST_COMPLETED_TX)); 4112 tcp->sp_request->status = lm_status; 4113 // DbgMessage(pdev, FATAL, "#lm_tcp_comp_initiate_offload_request cid=%d, sp_request->status=%d\n", tcp->cid, tcp->sp_request->status); 4114 sp_request = tcp->sp_request; 4115 tcp->sp_request = NULL; 4116 4117 DbgBreakIf(!(tcp->sp_flags & SP_TCP_OFLD_REQ_POSTED)); 4118 tcp->sp_flags |= SP_TCP_OFLD_REQ_COMP; 4119 mm_tcp_comp_slow_path_request(pdev, tcp, sp_request); 4120 4121 MM_RELEASE_TOE_LOCK(pdev); 4122 4123 /* handle deferred CQEs */ 4124 if(!comp_status && (tcp->ulp_type == TOE_CONNECTION_TYPE)) { 4125 lm_tcp_service_deferred_cqes(pdev, tcp); 4126 } 4127 } 4128 4129 void lm_tcp_collect_stats( 4130 struct _lm_device_t *pdev, 4131 lm_tcp_state_t *tcp) 4132 { 4133 4134 if (tcp->tx_con && tcp->rx_con) { 4135 pdev->toe_info.stats.tx_bytes_posted_total += tcp->tx_con->bytes_post_cnt; 4136 pdev->toe_info.stats.tx_rq_complete_calls += tcp->tx_con->rq_completion_calls; 4137 pdev->toe_info.stats.tx_bytes_completed_total += tcp->tx_con->bytes_comp_cnt; 4138 pdev->toe_info.stats.tx_rq_bufs_completed += tcp->tx_con->buffer_completed_cnt; 4139 pdev->toe_info.stats.total_tx_abortion_under_flr += tcp->tx_con->abortion_under_flr; 4140 4141 pdev->toe_info.stats.rx_rq_complete_calls += tcp->rx_con->rq_completion_calls; 4142 pdev->toe_info.stats.rx_rq_bufs_completed += tcp->rx_con->buffer_completed_cnt; 4143 pdev->toe_info.stats.rx_bytes_completed_total += tcp->rx_con->bytes_comp_cnt; 4144 4145 pdev->toe_info.stats.rx_accepted_indications += tcp->rx_con->u.rx.gen_info.num_success_indicates; 4146 pdev->toe_info.stats.rx_bufs_indicated_accepted += tcp->rx_con->u.rx.gen_info.num_buffers_indicated; 4147 pdev->toe_info.stats.rx_bytes_indicated_accepted += tcp->rx_con->u.rx.gen_info.bytes_indicated_accepted; 4148 4149 pdev->toe_info.stats.rx_rejected_indications += tcp->rx_con->u.rx.gen_info.num_failed_indicates; 4150 pdev->toe_info.stats.rx_bufs_indicated_rejected += tcp->rx_con->u.rx.gen_info.bufs_indicated_rejected; 4151 pdev->toe_info.stats.rx_bytes_indicated_rejected += tcp->rx_con->u.rx.gen_info.bytes_indicated_rejected; 4152 pdev->toe_info.stats.total_num_non_full_indications += tcp->rx_con->u.rx.gen_info.num_non_full_indications; 4153 4154 pdev->toe_info.stats.rx_zero_byte_recv_reqs += tcp->rx_con->u.rx.rx_zero_byte_recv_reqs; 4155 pdev->toe_info.stats.rx_bufs_copied_grq += tcp->rx_con->u.rx.gen_info.num_buffers_copied_grq; 4156 pdev->toe_info.stats.rx_bufs_copied_rq += tcp->rx_con->u.rx.gen_info.num_buffers_copied_rq; 4157 pdev->toe_info.stats.rx_bytes_copied_in_comp += tcp->rx_con->u.rx.gen_info.bytes_copied_cnt_in_comp; 4158 pdev->toe_info.stats.rx_bytes_copied_in_post += tcp->rx_con->u.rx.gen_info.bytes_copied_cnt_in_post; 4159 pdev->toe_info.stats.rx_bytes_copied_in_process += tcp->rx_con->u.rx.gen_info.bytes_copied_cnt_in_process; 4160 if (pdev->toe_info.stats.max_number_of_isles_in_single_con < tcp->rx_con->u.rx.gen_info.max_number_of_isles) { 4161 pdev->toe_info.stats.max_number_of_isles_in_single_con = tcp->rx_con->u.rx.gen_info.max_number_of_isles; 4162 } 4163 pdev->toe_info.stats.rx_bufs_posted_total += tcp->rx_con->buffer_post_cnt; 4164 pdev->toe_info.stats.rx_bytes_posted_total += tcp->rx_con->bytes_post_cnt; 4165 pdev->toe_info.stats.rx_bufs_skipped_post += tcp->rx_con->buffer_skip_post_cnt; 4166 pdev->toe_info.stats.rx_bytes_skipped_post += tcp->rx_con->bytes_skip_post_cnt; 4167 4168 pdev->toe_info.stats.rx_bytes_skipped_push += tcp->rx_con->bytes_push_skip_cnt; 4169 pdev->toe_info.stats.rx_partially_completed_buf_cnt += tcp->rx_con->partially_completed_buf_cnt; 4170 pdev->toe_info.stats.total_droped_empty_isles += tcp->rx_con->droped_empty_isles; 4171 pdev->toe_info.stats.total_droped_non_empty_isles += tcp->rx_con->droped_non_empty_isles; 4172 pdev->toe_info.stats.total_rx_post_blocked += tcp->rx_con->rx_post_blocked; 4173 pdev->toe_info.stats.total_zb_rx_post_blocked += tcp->rx_con->zb_rx_post_blocked; 4174 if (tcp->aux_mem_flag & TCP_CON_AUX_RT_MEM_SUCCSESS_ALLOCATION) { 4175 pdev->toe_info.stats.total_aux_mem_success_allocations++; 4176 } else if (tcp->aux_mem_flag & TCP_CON_AUX_RT_MEM_FAILED_ALLOCATION) { 4177 pdev->toe_info.stats.total_aux_mem_failed_allocations++; 4178 } 4179 pdev->toe_info.stats.total_rx_abortion_under_flr += tcp->rx_con->abortion_under_flr; 4180 } 4181 } 4182 4183 4184 4185 /* Desciption: 4186 * delete tcp state from lm _except_ from actual freeing of memory. 4187 * the task of freeing of memory is done in lm_tcp_free_tcp_state() 4188 * Assumptions: 4189 * global toe lock is taken by the caller 4190 */ 4191 void lm_tcp_del_tcp_state( 4192 struct _lm_device_t *pdev, 4193 lm_tcp_state_t *tcp) 4194 { 4195 DbgMessage(pdev, VERBOSEl4sp, "###lm_tcp_del_tcp_state\n"); 4196 DbgBreakIf(!(pdev && tcp)); 4197 4198 if (!lm_fl_reset_is_inprogress(pdev)) 4199 { 4200 DbgBreakIf(tcp->hdr.status >= STATE_STATUS_OFFLOAD_PENDING && 4201 tcp->hdr.status < STATE_STATUS_UPLOAD_DONE); 4202 } 4203 else 4204 { 4205 DbgMessage(pdev, FATAL, "###lm_tcp_del_tcp_state under FLR\n"); 4206 } 4207 4208 /* just a moment before we delete this connection, lets take it's info... */ 4209 lm_tcp_collect_stats(pdev, tcp); 4210 4211 d_list_remove_entry( 4212 &tcp->hdr.state_blk->tcp_list, 4213 &tcp->hdr.link); 4214 4215 if (tcp->ulp_type == TOE_CONNECTION_TYPE) 4216 { 4217 pdev->toe_info.stats.total_upld++; 4218 } 4219 else if (tcp->ulp_type == ISCSI_CONNECTION_TYPE) 4220 { 4221 pdev->iscsi_info.run_time.stats.total_upld++; 4222 } 4223 4224 if (!lm_fl_reset_is_inprogress(pdev) && (tcp->path != NULL)) { 4225 /* This is called as a result of a failured offload and not an upload..., 4226 * if connection is uploaded it means that path must have been taken care of 4227 * already. */ 4228 DbgBreakIf((tcp->hdr.status != STATE_STATUS_INIT_OFFLOAD_ERR) && 4229 (tcp->hdr.status != STATE_STATUS_INIT) && 4230 (tcp->hdr.status != STATE_STATUS_INIT_CONTEXT)); 4231 DbgBreakIf(tcp->path->hdr.status != STATE_STATUS_NORMAL); 4232 tcp->path->num_dependents--; 4233 tcp->path = NULL; 4234 } 4235 4236 if (tcp->in_searcher) { 4237 /* remove 4tuple from searcher */ 4238 lm_searcher_mirror_hash_remove(pdev, tcp->cid); 4239 tcp->in_searcher = 0; 4240 } 4241 4242 if (tcp->cid != 0) { 4243 u8_t notify_fw = 0; 4244 4245 /* we only notify FW if this delete is a result of upload, otherwise 4246 * (err_offload / error in init stage) we don't*/ 4247 if (!lm_fl_reset_is_inprogress(pdev) && (tcp->hdr.status == STATE_STATUS_UPLOAD_DONE)) { 4248 notify_fw = 1; 4249 } 4250 lm_free_cid_resc(pdev, TOE_CONNECTION_TYPE, tcp->cid, notify_fw); 4251 } 4252 4253 tcp->hdr.state_blk = NULL; 4254 tcp->cid = 0; 4255 tcp->ctx_virt = NULL; 4256 tcp->ctx_phys.as_u64 = 0; 4257 if (tcp->aux_memory != NULL) { 4258 switch (tcp->type_of_aux_memory) { 4259 case TCP_CON_AUX_RT_MEM: 4260 DbgMessage(pdev, WARNl4sp, 4261 "###lm_tcp_del_tcp_state: delete aux_mem (%d)\n", 4262 tcp->aux_mem_size); 4263 tcp->type_of_aux_memory = 0; 4264 mm_rt_free_mem(pdev,tcp->aux_memory,tcp->aux_mem_size,LM_RESOURCE_NDIS); 4265 break; 4266 default: 4267 break; 4268 } 4269 } 4270 } /* lm_tcp_del_tcp_state */ 4271 4272 /* Desciption: 4273 * delete path state from lm 4274 * Assumptions: 4275 * global toe lock is taken by the caller 4276 */ 4277 void lm_tcp_del_path_state( 4278 struct _lm_device_t *pdev, 4279 lm_path_state_t *path) 4280 { 4281 UNREFERENCED_PARAMETER_(pdev); 4282 4283 if (path->neigh != NULL) { 4284 4285 DbgBreakIf(path->neigh->hdr.status != STATE_STATUS_NORMAL); 4286 /* This is called as a result of a synchronous path upload */ 4287 path->neigh->num_dependents--; 4288 path->neigh = NULL; 4289 } 4290 4291 DbgBreakIf(!lm_fl_reset_is_inprogress(pdev) && (path->hdr.status != STATE_STATUS_UPLOAD_DONE)); 4292 d_list_remove_entry(&path->hdr.state_blk->path_list, &path->hdr.link); 4293 } 4294 4295 /* Desciption: 4296 * delete neigh state from lm 4297 * Assumptions: 4298 * global toe lock is taken by the caller 4299 */ 4300 void lm_tcp_del_neigh_state( 4301 struct _lm_device_t *pdev, 4302 lm_neigh_state_t *neigh) 4303 { 4304 UNREFERENCED_PARAMETER_(pdev); 4305 4306 DbgBreakIf(!lm_fl_reset_is_inprogress(pdev) && (neigh->hdr.status != STATE_STATUS_UPLOAD_DONE)); 4307 d_list_remove_entry(&neigh->hdr.state_blk->neigh_list, &neigh->hdr.link); 4308 } 4309 4310 /* Desciption: 4311 * free lm tcp state resources 4312 * Assumptions: 4313 * lm_tcp_del_tcp_state() already called */ 4314 void lm_tcp_free_tcp_resc( 4315 struct _lm_device_t *pdev, 4316 lm_tcp_state_t *tcp) 4317 { 4318 lm_tcp_con_t *tcp_con; 4319 d_list_t released_list_of_gen_bufs; 4320 u8_t reset_in_progress = lm_reset_is_inprogress(pdev); 4321 u32_t num_isles = 0; 4322 u32_t num_bytes_in_isles = 0; 4323 u32_t num_gen_bufs_in_isles = 0; 4324 4325 DbgMessage(pdev, VERBOSEl4sp, "###lm_tcp_free_tcp_resc tcp=%p\n", tcp); 4326 DbgBreakIf(!(pdev && tcp)); 4327 DbgBreakIf(!reset_in_progress && tcp->hdr.status >= STATE_STATUS_OFFLOAD_PENDING && 4328 tcp->hdr.status < STATE_STATUS_UPLOAD_DONE); 4329 DbgBreakIf(tcp->cid); /* i.e lm_tcp_del_tcp_state wasn't called */ 4330 4331 tcp_con = tcp->rx_con; 4332 if (tcp_con) { 4333 /* need to return the generic buffers of the isle list to the pool */ 4334 d_list_init(&released_list_of_gen_bufs, NULL, NULL, 0); 4335 num_isles = d_list_entry_cnt(&tcp_con->u.rx.gen_info.isles_list); 4336 num_bytes_in_isles = tcp_con->u.rx.gen_info.isle_nbytes; 4337 lm_tcp_rx_clear_isles(pdev, tcp, &released_list_of_gen_bufs); 4338 num_gen_bufs_in_isles = d_list_entry_cnt(&released_list_of_gen_bufs); 4339 if(!d_list_is_empty(&tcp_con->u.rx.gen_info.dpc_peninsula_list)) { 4340 if (!reset_in_progress) { 4341 DbgBreak(); 4342 } 4343 d_list_add_tail(&released_list_of_gen_bufs,&tcp_con->u.rx.gen_info.dpc_peninsula_list); 4344 d_list_init(&tcp->rx_con->u.rx.gen_info.dpc_peninsula_list, NULL, NULL, 0); 4345 } 4346 if (!d_list_is_empty(&tcp_con->u.rx.gen_info.peninsula_list)) { 4347 d_list_add_tail(&released_list_of_gen_bufs,&tcp_con->u.rx.gen_info.peninsula_list); 4348 d_list_init(&tcp->rx_con->u.rx.gen_info.peninsula_list, NULL, NULL, 0); 4349 if (!reset_in_progress) { 4350 /* we can only have data in the peninsula if we didn't go via the upload flow (i.e. offload failure of some sort...)*/ 4351 DbgBreakIf(tcp->hdr.status == STATE_STATUS_UPLOAD_DONE); 4352 if (tcp->hdr.status == STATE_STATUS_UPLOAD_DONE) { 4353 pdev->toe_info.stats.total_bytes_lost_on_upload += tcp_con->u.rx.gen_info.peninsula_nbytes; 4354 } 4355 } 4356 } 4357 4358 if (!d_list_is_empty(&released_list_of_gen_bufs)) { 4359 mm_tcp_return_list_of_gen_bufs(pdev, &released_list_of_gen_bufs, 0, NON_EXISTENT_SB_IDX); 4360 if (!reset_in_progress && num_isles) { 4361 s32_t delta = -(s32_t)num_gen_bufs_in_isles; 4362 MM_ACQUIRE_ISLES_CONTROL_LOCK(pdev); 4363 lm_tcp_update_isles_cnts(pdev, -(s32_t)num_isles, delta); 4364 MM_RELEASE_ISLES_CONTROL_LOCK(pdev); 4365 } 4366 } 4367 } 4368 4369 } /* lm_tcp_free_tcp_resc */ 4370 4371 /* Desciption: 4372 * update chip internal memory and hw with given offload params 4373 * Assumptions: 4374 * - lm_tcp_init was already called 4375 * Returns: 4376 * SUCCESS or any failure */ 4377 lm_status_t 4378 lm_tcp_set_ofld_params( 4379 lm_device_t *pdev, 4380 lm_state_block_t *state_blk, 4381 l4_ofld_params_t *params) 4382 { 4383 l4_ofld_params_t *curr_params = &pdev->ofld_info.l4_params; 4384 4385 UNREFERENCED_PARAMETER_(state_blk); 4386 4387 DbgMessage(pdev, VERBOSE, "###lm_tcp_set_ofld_params\n"); 4388 4389 /* we assume all timers periods can't be 0 */ 4390 DbgBreakIf(!(params->delayed_ack_ticks && 4391 params->nce_stale_ticks && 4392 params->push_ticks && 4393 params->sws_prevention_ticks && 4394 params->ticks_per_second)); 4395 4396 /* <MichalK> Here we override the ofld info. This in theory effects iscsi as well, however, since ftsk 4397 * does not really use timers, and passes '0' for ka / rt in delegate/cached params its ok that 4398 * we're overriding the parameters here. The correct solution is to maintain this per cli-idx, 4399 * but that will require major changes in l4 context initialization and not worth the effort. 4400 */ 4401 *curr_params = *params; 4402 4403 /* update internal memory/hw for each storm both with 4404 * toe/rdma/iscsi common params and with toe private params (where applicable) */ 4405 4406 _lm_set_ofld_params_xstorm_common(pdev, curr_params); 4407 4408 _lm_set_ofld_params_tstorm_common(pdev, curr_params); 4409 4410 _lm_set_ofld_params_tstorm_toe(pdev, curr_params); 4411 4412 _lm_set_ofld_params_ustorm_toe(pdev, curr_params); 4413 4414 _lm_set_ofld_params_xstorm_toe(pdev, curr_params); 4415 4416 /* GilR 6/7/2006 - TBD - usage of params->starting_ip_id is not clear. currenlty we ignore it */ 4417 4418 return LM_STATUS_SUCCESS; 4419 } /* lm_tcp_set_ofld_params */ 4420 4421 4422 /** Description 4423 * indicates that a rst request was received. Called from several 4424 * functions. Could also be called as a result of a delayed rst. 4425 * Assumptions: 4426 */ 4427 void lm_tcp_indicate_rst_received( 4428 struct _lm_device_t * pdev, 4429 lm_tcp_state_t * tcp 4430 ) 4431 { 4432 lm_tcp_con_t *rx_con, *tx_con; 4433 u8_t ip_version; 4434 MM_INIT_TCP_LOCK_HANDLE(); 4435 4436 //DbgMessage(pdev, WARNl4rx , "##lm_tcp_indicate_rst_received cid=%d\n", tcp->cid); 4437 4438 /* Update the Reset Received statistic*/ 4439 ip_version = (tcp->path->path_const.ip_version == IP_VERSION_IPV4)? STATS_IP_4_IDX : STATS_IP_6_IDX; 4440 LM_COMMON_DRV_STATS_ATOMIC_INC_TOE(pdev, ipv[ip_version].in_reset); 4441 4442 rx_con = tcp->rx_con; 4443 tx_con = tcp->tx_con; 4444 4445 DbgBreakIf( ! (pdev && tcp) ); 4446 /* The state may only be NORMAL or UPLOAD_PENDING */ 4447 DbgBreakIf( (tcp->hdr.status != STATE_STATUS_NORMAL) && 4448 (tcp->hdr.status != STATE_STATUS_UPLOAD_PENDING) ); 4449 4450 /* Get the global TOE lock */ 4451 MM_ACQUIRE_TOE_LOCK(pdev); 4452 4453 /* Change the state status if needed: NORMAL->ABORTED */ 4454 if ( tcp->hdr.status == STATE_STATUS_NORMAL ) { 4455 tcp->hdr.status = STATE_STATUS_ABORTED; 4456 } 4457 4458 /* Release the global TOE lock */ 4459 MM_RELEASE_TOE_LOCK(pdev); 4460 /*********************** Tx **********************/ 4461 /* Take Tx lock */ 4462 mm_acquire_tcp_lock(pdev, tx_con); 4463 4464 /* Implies POST Tx blocked */ 4465 DbgBreakIf(tx_con->flags & TCP_REMOTE_RST_RECEIVED_ALL_RX_INDICATED); 4466 tx_con->flags |= TCP_REMOTE_RST_RECEIVED_ALL_RX_INDICATED; 4467 4468 /* Abort Tx buffers */ 4469 lm_tcp_abort_bufs(pdev, tcp, tx_con, LM_STATUS_CONNECTION_RESET); 4470 4471 /* Clear delayed RST flag */ 4472 tx_con->u.tx.flags &= ~ TCP_CON_RST_IND_NOT_SAFE; 4473 4474 /* Release Tx lock */ 4475 mm_release_tcp_lock(pdev, tx_con); 4476 /*********************** Rx **********************/ 4477 /* Take Rx lock */ 4478 mm_acquire_tcp_lock(pdev, rx_con); 4479 4480 /* Clear delayed FIN and RST */ 4481 rx_con->u.rx.flags &= ~ (TCP_CON_RST_IND_PENDING | TCP_CON_FIN_IND_PENDING); 4482 4483 /* Implies POST Rx blocked */ 4484 DbgBreakIf(rx_con->flags & TCP_REMOTE_RST_RECEIVED_ALL_RX_INDICATED); 4485 rx_con->flags |= TCP_REMOTE_RST_RECEIVED_ALL_RX_INDICATED; 4486 4487 /* Abort Rx buffers */ 4488 lm_tcp_abort_bufs(pdev, tcp, rx_con, LM_STATUS_CONNECTION_RESET); 4489 4490 /* Release Rx lock */ 4491 mm_release_tcp_lock(pdev, rx_con); 4492 4493 /* Indicate the Remote Abortive Disconnect to the Client */ 4494 mm_tcp_indicate_rst_received(pdev, tcp); 4495 } 4496 4497 void lm_tcp_searcher_ramrod_complete( 4498 IN struct _lm_device_t * pdev, 4499 IN lm_tcp_state_t * tcp 4500 ) 4501 { 4502 lm_tcp_slow_path_request_t * request = tcp->sp_request; 4503 4504 DbgMessage(pdev, VERBOSEl4, "## lm_tcp_searcher_ramrod_comp\n"); 4505 4506 DbgBreakIf(tcp->hdr.status != STATE_STATUS_UPLOAD_PENDING); 4507 DbgBreakIf(request->type != SP_REQUEST_TERMINATE_OFFLOAD); 4508 4509 tcp->sp_request = NULL; 4510 request->type = SP_REQUEST_TERMINATE1_OFFLOAD; 4511 4512 4513 MM_ACQUIRE_TOE_LOCK(pdev); 4514 /* remove 4tuple from searcher */ 4515 DbgBreakIf(!tcp->in_searcher); 4516 lm_searcher_mirror_hash_remove(pdev, tcp->cid); 4517 tcp->in_searcher = 0; 4518 DbgBreakIf(!(tcp->sp_flags & SP_TCP_SRC_REQ_POSTED)); 4519 tcp->sp_flags |= SP_TCP_SRC_REQ_COMP; 4520 lm_tcp_post_slow_path_request(pdev, tcp, request); 4521 MM_RELEASE_TOE_LOCK(pdev); 4522 } 4523 4524 void lm_tcp_terminate_ramrod_complete( 4525 IN struct _lm_device_t * pdev, 4526 IN lm_tcp_state_t * tcp) 4527 { 4528 lm_tcp_slow_path_request_t * request = tcp->sp_request; 4529 MM_ACQUIRE_TOE_LOCK(pdev); 4530 tcp->sp_request = NULL; 4531 request->type = SP_REQUEST_QUERY; 4532 /* Clear the flags */ 4533 DbgBreakIf(tcp->sp_flags & ( SP_REQUEST_COMPLETED_TX | SP_REQUEST_COMPLETED_RX )); 4534 4535 DbgBreakIf(!(tcp->sp_flags & SP_TCP_TRM_REQ_POSTED)); 4536 tcp->sp_flags |= SP_TCP_TRM_REQ_COMP; 4537 4538 /* Part of the fast-terminate flow is to zeroize the timers context: turn of num of active timers */ 4539 if (tcp->ulp_type == TOE_CONNECTION_TYPE) { 4540 RESET_FLAGS(((struct toe_context *)tcp->ctx_virt)->timers_context.flags, __TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS); 4541 } 4542 4543 lm_tcp_post_slow_path_request(pdev, tcp, request); 4544 4545 MM_RELEASE_TOE_LOCK(pdev); 4546 } 4547 4548 static void lm_tcp_rx_terminate_ramrod_complete( 4549 IN struct _lm_device_t * pdev, 4550 IN lm_tcp_state_t * tcp) 4551 { 4552 lm_tcp_con_t * rx_con = tcp->rx_con; 4553 MM_INIT_TCP_LOCK_HANDLE(); 4554 4555 DbgMessage(pdev, VERBOSEl4rx, "## lm_tcp_terminate_ramrod_comp_rx\n"); 4556 4557 DbgBreakIf(tcp->hdr.status != STATE_STATUS_UPLOAD_PENDING); 4558 4559 mm_acquire_tcp_lock(pdev, rx_con); 4560 DbgBreakIf( mm_tcp_indicating_bufs(rx_con) ); 4561 DbgBreakIf(rx_con->flags & TCP_TRM_REQ_COMPLETED); 4562 rx_con->flags |= TCP_TRM_REQ_COMPLETED; 4563 mm_release_tcp_lock(pdev, rx_con); 4564 } 4565 4566 static void lm_tcp_tx_terminate_ramrod_complete( 4567 IN struct _lm_device_t * pdev, 4568 IN lm_tcp_state_t * tcp) 4569 { 4570 lm_tcp_con_t * tx_con = tcp->tx_con; 4571 MM_INIT_TCP_LOCK_HANDLE(); 4572 4573 DbgMessage(pdev, VERBOSEl4tx, "## lm_tcp_terminate_ramrod_comp_tx\n"); 4574 4575 DbgBreakIf(tcp->hdr.status != STATE_STATUS_UPLOAD_PENDING); 4576 4577 mm_acquire_tcp_lock(pdev, tx_con); 4578 DbgBreakIf(tx_con->flags & TCP_TRM_REQ_COMPLETED); 4579 tx_con->flags |= TCP_TRM_REQ_COMPLETED; 4580 mm_release_tcp_lock(pdev, tx_con); 4581 4582 } 4583 4584 /** Description 4585 * indicates that a fin request was received. Called from several 4586 * functions. Could also be called as a result of a delayed fin 4587 * Assumptions: called without any lock taken 4588 */ 4589 static void lm_tcp_indicate_fin_received( 4590 struct _lm_device_t * pdev, 4591 lm_tcp_state_t * tcp 4592 ) 4593 { 4594 lm_tcp_con_t * rx_con; 4595 u8_t ip_version; 4596 MM_INIT_TCP_LOCK_HANDLE(); 4597 4598 DbgMessage(pdev, INFORMl4rx , "##lm_tcp_indicate_fin_received cid=%d\n", tcp->cid); 4599 DbgBreakIf( ! ( pdev && tcp ) ); 4600 4601 ip_version = (tcp->path->path_const.ip_version == IP_VERSION_IPV4)? STATS_IP_4_IDX : STATS_IP_6_IDX; 4602 LM_COMMON_DRV_STATS_ATOMIC_INC_TOE(pdev, ipv[ip_version].in_fin); 4603 4604 rx_con = tcp->rx_con; 4605 4606 mm_acquire_tcp_lock(pdev, rx_con); 4607 4608 rx_con->u.rx.flags &= ~TCP_CON_FIN_IND_PENDING; 4609 4610 /* Mark the connection as POST_BLOCKED due to Remote FIN Received */ 4611 DbgBreakIf(rx_con->flags & TCP_REMOTE_FIN_RECEIVED_ALL_RX_INDICATED); 4612 rx_con->flags |= TCP_REMOTE_FIN_RECEIVED_ALL_RX_INDICATED; 4613 /* Abort pending Rx buffers */ 4614 lm_tcp_abort_bufs(pdev, tcp, rx_con, LM_STATUS_SUCCESS); 4615 4616 mm_release_tcp_lock(pdev, rx_con); 4617 4618 /* Indicate the Remote FIN up to the client */ 4619 mm_tcp_indicate_fin_received(pdev, tcp); 4620 } 4621 4622 void lm_tcp_process_retrieve_indication_cqe( 4623 struct _lm_device_t * pdev, 4624 lm_tcp_state_t * tcp, 4625 l4_upload_reason_t upload_reason) 4626 { 4627 u32_t rx_flags = 0; 4628 u32_t tx_flags = 0; 4629 DbgMessage(pdev, INFORMl4, "###lm_tcp_process_retrieve_indication_cqe cid=%d upload_reason=%d\n", tcp->cid, upload_reason); 4630 4631 /* assert that this CQE is allowed */ 4632 /* we could receive this cqe after a RST / UPL, in which cases we will not notify about it. */ 4633 SET_FLAGS(rx_flags, TCP_RX_COMP_BLOCKED | TCP_UPLOAD_REQUESTED); 4634 SET_FLAGS(tx_flags, TCP_TX_COMP_BLOCKED); 4635 4636 /* we do need to notify about it even if it's after a FIN... */ 4637 RESET_FLAGS(rx_flags, TCP_REMOTE_FIN_RECEIVED); 4638 RESET_FLAGS(tx_flags, TCP_FIN_REQ_COMPLETED); 4639 4640 if (!GET_FLAGS(tcp->rx_con->flags, rx_flags) && !GET_FLAGS(tcp->tx_con->flags,tx_flags)) { 4641 SET_FLAGS(tcp->rx_con->flags, TCP_UPLOAD_REQUESTED); 4642 DbgMessage(pdev, INFORMl4, "###Indicating UP: cid=%d upload_reason=%d\n", tcp->cid, upload_reason); 4643 mm_tcp_indicate_retrieve_indication(pdev, tcp, upload_reason); 4644 } 4645 } 4646 4647 /* Assumption: called without any lock taken */ 4648 static void lm_tcp_rx_fin_received_complete( 4649 struct _lm_device_t * pdev, 4650 lm_tcp_state_t * tcp, 4651 u8_t upload 4652 ) 4653 { 4654 lm_tcp_con_t * rx_con; 4655 u8_t indicate = 1; 4656 u8_t is_empty_peninsula; 4657 MM_INIT_TCP_LOCK_HANDLE(); 4658 4659 DbgMessage(pdev, INFORMl4rx, "###lm_tcp_rx_fin_received_complete cid=%d\n", tcp->cid); 4660 DbgBreakIf( ! (pdev && tcp) ); 4661 DbgBreakIf( tcp->hdr.status != STATE_STATUS_NORMAL && tcp->hdr.status != STATE_STATUS_UPLOAD_PENDING); 4662 4663 rx_con = tcp->rx_con; 4664 4665 mm_acquire_tcp_lock(pdev, rx_con); 4666 4667 /* break if we received a fin on the cqe and we still have an 'unreleased' generic buffer in our peninsula */ 4668 DbgBreakIf( !d_list_is_empty(&tcp->rx_con->u.rx.gen_info.dpc_peninsula_list) ); 4669 4670 /* Mark the connection as 'COMP_BLOCKED' and 'DB BLOCKED' */ 4671 DbgBreakIf(rx_con->flags & TCP_REMOTE_FIN_RECEIVED); 4672 rx_con->flags |= TCP_REMOTE_FIN_RECEIVED; 4673 is_empty_peninsula = (rx_con->u.rx.gen_info.peninsula_nbytes > 0 ? 0 : 1); 4674 if (!is_empty_peninsula || mm_tcp_indicating_bufs(rx_con) ) { 4675 DbgMessage(pdev, INFORMl4, "lm_tcp_process_fin_received_cqe - postponing fin indication cid=%d\n", tcp->cid); 4676 rx_con->u.rx.flags |= TCP_CON_FIN_IND_PENDING; 4677 indicate = 0; 4678 } 4679 4680 tcp->tcp_state_calc.fin_reception_time = mm_get_current_time(pdev); 4681 if (tcp->tcp_state_calc.fin_reception_time == tcp->tcp_state_calc.fin_request_time) { 4682 tcp->tcp_state_calc.fin_request_time -= 1; 4683 } 4684 4685 mm_release_tcp_lock(pdev, rx_con); 4686 4687 if (indicate) 4688 { 4689 lm_tcp_indicate_fin_received(pdev, tcp); 4690 } else if(upload && !is_empty_peninsula) 4691 { 4692 /* we did not indicate the received fin, AND we got upload request from FW, AND peninsula is not empty, 4693 i.e. we _may_ be waiting for RQ buffers to be posted before we indicate the fin. 4694 Thus, we _may_ need to request for upload: */ 4695 4696 /* imitate as if FW has sent an upload request CQE: */ 4697 lm_tcp_process_retrieve_indication_cqe(pdev, tcp, L4_UPLOAD_REASON_UPLOAD_REQUESTED); 4698 pdev->toe_info.stats.total_fin_upld_requested++; 4699 } 4700 } 4701 4702 4703 static void lm_tcp_comp_empty_ramrod_request( 4704 IN struct _lm_device_t * pdev, 4705 IN lm_tcp_state_t * tcp) 4706 { 4707 lm_tcp_slow_path_request_t * sp_req = tcp->sp_request; 4708 4709 MM_ACQUIRE_TOE_LOCK(pdev); 4710 4711 DbgBreakIf(tcp->sp_flags & ( SP_REQUEST_COMPLETED_TX | SP_REQUEST_COMPLETED_RX )); 4712 sp_req->status = LM_STATUS_SUCCESS; 4713 tcp->sp_request = NULL; 4714 mm_tcp_comp_slow_path_request(pdev, tcp, sp_req); 4715 4716 MM_RELEASE_TOE_LOCK(pdev); 4717 } 4718 4719 static void lm_tcp_rx_empty_ramrod_complete( 4720 IN struct _lm_device_t * pdev, 4721 IN lm_tcp_state_t * tcp, 4722 IN u32_t sp_type) 4723 { 4724 u8_t indicate = 0; 4725 4726 DbgBreakIf(!tcp); 4727 4728 DbgMessage(pdev, INFORMl4rx | INFORMl4sp, 4729 "###lm_tcp_process_empty_slow_path_rcqe cid=%d, request->type=%d\n", 4730 tcp->cid, sp_type); 4731 4732 switch (sp_type) { 4733 case SP_REQUEST_PENDING_LOCAL_FIN_DISCONNECT: 4734 case SP_REQUEST_PENDING_TX_RST: 4735 break; /* relevant to scqe only */ 4736 case SP_REQUEST_PENDING_REMOTE_DISCONNECT: 4737 if ( tcp->rx_con->u.rx.flags & TCP_CON_RST_IND_PENDING ) { 4738 /* process it */ 4739 MM_ACQUIRE_TOE_LOCK(pdev); 4740 4741 /* Mark Rx ready for RST indication - before it was marked as 'delayed' */ 4742 tcp->sp_flags |= REMOTE_RST_INDICATED_RX; 4743 4744 if ( (tcp->sp_flags & REMOTE_RST_INDICATED_RX) && (tcp->sp_flags & REMOTE_RST_INDICATED_TX) ) { 4745 indicate = 1; 4746 } 4747 4748 /* Release global TOE lock */ 4749 MM_RELEASE_TOE_LOCK(pdev); 4750 if (indicate) { 4751 lm_tcp_indicate_rst_received(pdev, tcp); 4752 } /* o/w we haven't seen the TX yet... */ 4753 } 4754 else if ( tcp->rx_con->u.rx.flags & TCP_CON_FIN_IND_PENDING ) { 4755 /* process it */ 4756 lm_tcp_indicate_fin_received(pdev, tcp); 4757 } 4758 break; 4759 default: 4760 { 4761 DbgMessage(pdev, FATAL, 4762 "'empty ramrod' opcode in cqe doesn't fit with sp_request->type %d\n", 4763 sp_type); 4764 DbgBreak(); 4765 } 4766 } 4767 } 4768 4769 static void lm_tcp_tx_empty_ramrod_complete( 4770 IN struct _lm_device_t * pdev, 4771 IN lm_tcp_state_t * tcp, 4772 IN u32_t sp_type) 4773 { 4774 u8_t indicate = 0; 4775 MM_INIT_TCP_LOCK_HANDLE(); 4776 4777 DbgBreakIf(!tcp); 4778 4779 DbgMessage(pdev, INFORMl4tx | INFORMl4sp, 4780 "###lm_tcp_process_empty_slow_path_scqe cid=%d, request->type=%d\n", 4781 tcp->cid, sp_type); 4782 4783 switch (sp_type) { 4784 case SP_REQUEST_PENDING_LOCAL_FIN_DISCONNECT: 4785 /* process it */ 4786 mm_acquire_tcp_lock(pdev, tcp->tx_con); 4787 lm_tcp_abort_bufs(pdev,tcp,tcp->tx_con,LM_STATUS_ABORTED); 4788 mm_release_tcp_lock(pdev, tcp->tx_con); 4789 break; 4790 case SP_REQUEST_PENDING_REMOTE_DISCONNECT: 4791 break; /* rcqe only */ 4792 case SP_REQUEST_PENDING_TX_RST: 4793 /* safe to abort buffers at this stage - we know none are pending on pbf */ 4794 if (tcp->tx_con->u.tx.flags & TCP_CON_RST_IND_NOT_SAFE ) { 4795 /* process it */ 4796 MM_ACQUIRE_TOE_LOCK(pdev); 4797 4798 /* Mark Rx ready for RST indication - before it was marked as 'delayed' */ 4799 tcp->sp_flags |= REMOTE_RST_INDICATED_TX; 4800 4801 if ( (tcp->sp_flags & REMOTE_RST_INDICATED_RX) && (tcp->sp_flags & REMOTE_RST_INDICATED_TX) ) { 4802 indicate = 1; 4803 } 4804 4805 mm_acquire_tcp_lock(pdev, tcp->tx_con); 4806 tcp->tx_con->u.tx.flags &= ~TCP_CON_RST_IND_NOT_SAFE; 4807 mm_release_tcp_lock(pdev, tcp->tx_con); 4808 4809 /* Release global TOE lock */ 4810 MM_RELEASE_TOE_LOCK(pdev); 4811 if (indicate) { 4812 lm_tcp_indicate_rst_received(pdev, tcp); 4813 } /* o/w we haven't seen the RX yet... */ 4814 } 4815 break; 4816 default: 4817 { 4818 DbgMessage(pdev, FATAL, 4819 "'empty ramrod' opcode in cqe doesn't fit with sp_request->type %d\n", 4820 sp_type); 4821 DbgBreak(); 4822 } 4823 } 4824 } 4825 4826 static void lm_tcp_comp_abortive_disconnect_request( 4827 struct _lm_device_t * pdev, 4828 lm_tcp_state_t * tcp, 4829 lm_tcp_slow_path_request_t * request 4830 ) 4831 { 4832 lm_tcp_con_t *rx_con, *tx_con; 4833 u8_t delayed_rst = 0; 4834 u8_t ip_version; 4835 u8_t complete_sp_request = TRUE; 4836 MM_INIT_TCP_LOCK_HANDLE(); 4837 4838 DbgBreakIf( ! (pdev && tcp && request) ); 4839 4840 /* Update the statistics */ 4841 ip_version = (tcp->path->path_const.ip_version == IP_VERSION_IPV4)? STATS_IP_4_IDX : STATS_IP_6_IDX; 4842 LM_COMMON_DRV_STATS_ATOMIC_INC_TOE(pdev, ipv[ip_version].out_resets); 4843 4844 rx_con = tcp->rx_con; 4845 tx_con = tcp->tx_con; 4846 4847 /* Get global TOE lock */ 4848 MM_ACQUIRE_TOE_LOCK(pdev); 4849 4850 /* The state may only be NORMAL or ABORTED (due to remote RST) */ 4851 DbgBreakIf( ( tcp->hdr.status != STATE_STATUS_NORMAL ) && ( tcp->hdr.status != STATE_STATUS_ABORTED ) ); 4852 /* the FW will always post a RST packet no matter if 4853 remote RST was already received, therefore, the 4854 completion status of the request is always SUCCESS */ 4855 request->status = LM_STATUS_SUCCESS; 4856 4857 tcp->hdr.status = STATE_STATUS_ABORTED; 4858 4859 tcp->tcp_state_calc.con_rst_flag = TRUE; 4860 4861 /* Release global TOE lock */ 4862 MM_RELEASE_TOE_LOCK(pdev); 4863 4864 /***************** Tx ********************/ 4865 /* Get Tx lock */ 4866 mm_acquire_tcp_lock(pdev, tx_con); 4867 4868 /* Clear delayed RST flag */ 4869 tx_con->u.tx.flags &= ~ TCP_CON_RST_IND_NOT_SAFE; 4870 /* safe to abort buffers anyway, even if we have a non-safe tx abort, since this means that a ramrod has been sent so queues are clear */ 4871 lm_tcp_abort_bufs(pdev,tcp,tx_con, LM_STATUS_ABORTED); 4872 4873 /* Release Tx lock */ 4874 mm_release_tcp_lock(pdev, tx_con); 4875 4876 /***************** Rx ********************/ 4877 /* Get Rx lock */ 4878 mm_acquire_tcp_lock(pdev, rx_con); 4879 4880 /* 'POST/IND BLOCKED' in the request. Even a post was in the middle it must be done by now */ 4881 if (mm_tcp_indicating_bufs(rx_con)) { 4882 if (pdev->params.l4_support_pending_sp_req_complete) { 4883 DbgBreakIf(DBG_BREAK_ON(ABORTIVE_DISCONNECT_DURING_IND)); 4884 complete_sp_request = FALSE; 4885 tcp->sp_request_pending_completion = TRUE; 4886 tcp->pending_abortive_disconnect++; 4887 mm_atomic_inc(&pdev->toe_info.stats.total_aborive_disconnect_during_completion); 4888 DbgMessage(pdev, INFORMl4sp, "Abortive disconnect completion during indication(%d)\n", tcp->cid); 4889 } else { 4890 DbgBreak(); 4891 } 4892 } 4893 4894 if ( rx_con->u.rx.flags & TCP_CON_RST_IND_PENDING ) { 4895 delayed_rst = 1; 4896 } 4897 4898 /* Clear delayed RST and FIN flags */ 4899 rx_con->u.rx.flags &= ~ (TCP_CON_RST_IND_PENDING | TCP_CON_FIN_IND_PENDING); 4900 4901 lm_tcp_abort_bufs(pdev,tcp, rx_con, LM_STATUS_ABORTED); 4902 4903 /* Release Rx lock */ 4904 mm_release_tcp_lock(pdev, rx_con); 4905 /*****************************************/ 4906 4907 if ( delayed_rst ) { 4908 /* GilR 10/15/2006 - TBD - since anyway we complete the request 4909 with status SUCCESS, we do not need to indicate a remote RST 4910 that was delayed. therefore the following call to 4911 mm_tcp_indicate_rst_received is canceled */ 4912 //mm_tcp_indicate_rst_received(pdev, tcp); 4913 } 4914 4915 if (complete_sp_request) { 4916 /* Get global TOE lock */ 4917 MM_ACQUIRE_TOE_LOCK(pdev); 4918 4919 DbgBreakIf(tcp->sp_flags & ( SP_REQUEST_COMPLETED_TX | SP_REQUEST_COMPLETED_RX )); 4920 4921 tcp->sp_request = NULL; 4922 4923 mm_tcp_comp_slow_path_request(pdev, tcp, request); 4924 4925 /* Release global TOE lock */ 4926 MM_RELEASE_TOE_LOCK(pdev); 4927 } 4928 } 4929 4930 static void lm_tcp_rx_rst_received_complete ( 4931 struct _lm_device_t * pdev, 4932 lm_tcp_state_t * tcp 4933 ) 4934 { 4935 lm_tcp_con_t * rx_con; 4936 u8_t indicate = 0; 4937 MM_INIT_TCP_LOCK_HANDLE(); 4938 4939 DbgMessage(pdev, INFORMl4rx , "###lm_tcp_process_rst_received_rcqe cid=%d\n", tcp->cid); 4940 DbgBreakIf( ! (pdev && tcp) ); 4941 /* The state may only be NORMAL or UPLOAD_PENDING */ 4942 DbgBreakIf( (tcp->hdr.status != STATE_STATUS_NORMAL) && 4943 (tcp->hdr.status != STATE_STATUS_UPLOAD_PENDING) ); 4944 4945 rx_con = tcp->rx_con; 4946 4947 /* Get global TOE lock */ 4948 MM_ACQUIRE_TOE_LOCK(pdev); 4949 4950 /* Take the Rx lock */ 4951 mm_acquire_tcp_lock(pdev, rx_con); 4952 4953 /* break if we received a rst on the cqe and we still have an 'unreleased' generic buffer in our peninsula */ 4954 DbgBreakIf( !d_list_is_empty(&tcp->rx_con->u.rx.gen_info.dpc_peninsula_list) ); 4955 4956 4957 /* This will imply RX_COMP_LOCKED and RX_DB_BLOCKED */ 4958 DbgBreakIf(rx_con->flags & TCP_REMOTE_RST_RECEIVED); 4959 rx_con->flags |= TCP_REMOTE_RST_RECEIVED; 4960 4961 /* Clear pending FIN */ 4962 rx_con->u.rx.flags &= ~ TCP_CON_FIN_IND_PENDING; 4963 4964 /* Check if all received data has been completed towards the Client */ 4965 if (rx_con->u.rx.gen_info.peninsula_nbytes || mm_tcp_indicating_bufs(rx_con) ) { 4966 DbgMessage(pdev, INFORMl4rx , "lm_tcp_process_rst_received_cqe - postponing rst indication cid=%d\n", tcp->cid); 4967 rx_con->u.rx.flags |= TCP_CON_RST_IND_PENDING; 4968 } else { 4969 /* Mark Rx ready for RST indication */ 4970 tcp->sp_flags |= REMOTE_RST_INDICATED_RX; 4971 } 4972 4973 /* Release the Rx lock */ 4974 mm_release_tcp_lock(pdev, rx_con); 4975 4976 if ( (tcp->sp_flags & REMOTE_RST_INDICATED_RX) && (tcp->sp_flags & REMOTE_RST_INDICATED_TX) ) { 4977 indicate = 1; 4978 tcp->tcp_state_calc.con_rst_flag = TRUE; 4979 } 4980 4981 /* Release global TOE lock */ 4982 MM_RELEASE_TOE_LOCK(pdev); 4983 4984 /* Indicate the RST to the Client if it was the second completion */ 4985 if ( indicate ) { 4986 lm_tcp_indicate_rst_received(pdev,tcp); 4987 } 4988 } 4989 4990 static void lm_tcp_tx_rst_received_complete ( 4991 struct _lm_device_t * pdev, 4992 lm_tcp_state_t * tcp 4993 ) 4994 { 4995 lm_tcp_con_t * tx_con; 4996 lm_status_t lm_status; 4997 u8_t indicate = 0; 4998 u8_t send_empty_ramrod = 0; 4999 u8_t upload_on_fail = 0; 5000 5001 MM_INIT_TCP_LOCK_HANDLE(); 5002 5003 DbgMessage(pdev, INFORMl4tx, "###lm_tcp_tx_rst_received_complete cid=%d\n", tcp->cid); 5004 DbgBreakIf( ! (pdev && tcp) ); 5005 /* The state may only be NORMAL or UPLOAD_PENDING */ 5006 DbgBreakIf( (tcp->hdr.status != STATE_STATUS_NORMAL) && 5007 (tcp->hdr.status != STATE_STATUS_UPLOAD_PENDING) ); 5008 5009 tx_con = tcp->tx_con; 5010 5011 /* Get global TOE lock */ 5012 MM_ACQUIRE_TOE_LOCK(pdev); 5013 5014 /* Take the Tx lock */ 5015 mm_acquire_tcp_lock(pdev, tx_con); 5016 5017 /* This will imply TX_COMP_LOCKED and TX_DB_BLOCKED */ 5018 DbgBreakIf(tx_con->flags & TCP_REMOTE_RST_RECEIVED); 5019 tx_con->flags |= TCP_REMOTE_RST_RECEIVED; 5020 5021 /* There is a potential race between receiving a reset to aborting buffers, once reset is received from te CSTORM it doesn't mean that 5022 * the pbf isn't trying to transmit any other buffers, to make sure that it flushes remaining buffers we need to pass a ramrod - any ramrod, 5023 * if the active_tb_list is not empty, if the tx post is blocked already, it means its too late, rst / fin / trm / inv were posted, so we don't 5024 * abort the buffers - they will be aborted later on... to make sure buffers aren't aborted we turn on the TCP_CON_RST_IND_NOT_SAFE flag. they'll 5025 * be aborted in terminate later on. we won't send the indication as well, we'll send it when completing terminate / empty ramrod later on. 5026 */ 5027 /* Check if all received data has been completed towards the Client + terminate ramrod has not been posted yet */ 5028 if ( s_list_entry_cnt(&tx_con->active_tb_list) > 0 ) { 5029 DbgMessage(pdev, INFORMl4rx, "TX lm_tcp_process_rst_received_cqe - postponing rst indication cid=%d sending empty ramrod\n", tcp->cid); 5030 tx_con->u.tx.flags |= TCP_CON_RST_IND_NOT_SAFE; 5031 /* send the empty ramrod only if we're not blocked already. 5032 * TCP_TX_POST_BLOCKED includes FIN_REQ_POSTED case in which we should send the empty ramrod, 5033 * and REMOTE_RST_RECEIVED_ALL_RX_INDICATED, TCP_POST_BLOCKED that shouldn't be set when reaching this point, 5034 * so we'll check all other the relevant flags. 5035 * here we determine whether to send the ramrod according to the lm flags, it is possible that the ramrod will be dropped later 5036 * in the mm_tcp_post_empty_slow_path_request() due upload request pending in the um */ 5037 if (!(tx_con->flags & (TCP_RST_REQ_POSTED | TCP_INV_REQ_POSTED | TCP_TRM_REQ_POSTED))) { 5038 send_empty_ramrod = TRUE; 5039 } 5040 } else { 5041 /* Mark Tx ready for RST indication */ 5042 tcp->sp_flags |= REMOTE_RST_INDICATED_TX; 5043 } 5044 5045 /* Release the Tx lock */ 5046 mm_release_tcp_lock(pdev, tx_con); 5047 5048 if ( (tcp->sp_flags & REMOTE_RST_INDICATED_RX) && (tcp->sp_flags & REMOTE_RST_INDICATED_TX) ) { 5049 indicate = 1; 5050 tcp->tcp_state_calc.con_rst_flag = TRUE; 5051 } else if ( tcp->sp_flags & REMOTE_RST_INDICATED_RX ) { 5052 upload_on_fail = 1; /* RX is done, the only reason that TX isn't is because it has buffers to abort, if we can't postpone tx, indicate anyway. */ 5053 tcp->tcp_state_calc.con_rst_flag = TRUE; 5054 } 5055 5056 /* Indicate the RST to the Client if it was the second completion */ 5057 if ( indicate ) { 5058 /* Release global TOE lock */ 5059 MM_RELEASE_TOE_LOCK(pdev); 5060 5061 lm_tcp_indicate_rst_received(pdev,tcp); 5062 } else if (send_empty_ramrod) { 5063 /* Send empty ramrod, only when it is complete we can complete the reset i.e. tx reset received. 5064 * it is possible that the ramrod will be dropped due upload request pending in the um */ 5065 DbgMessage(pdev, INFORMl4tx, "Sending Empty Ramrod TX\n"); 5066 lm_status = mm_tcp_post_empty_slow_path_request(pdev, tcp, SP_REQUEST_PENDING_TX_RST); 5067 5068 /* Release global TOE lock */ 5069 MM_RELEASE_TOE_LOCK(pdev); 5070 5071 if ((lm_status != LM_STATUS_PENDING) && (lm_status != LM_STATUS_UPLOAD_IN_PROGRESS)) { /* we expect the posting of an empty ramrod to be pending... */ 5072 /* This is a bit of a problem here...we don't want to risk the pbf accessing released data, so instead 5073 * we risk the application turning an error, we delay the abort of buffers till the terminate stage. 5074 * we don't remove the RST_IND_PENDING... we'll look at that before aborting buffers... */ 5075 if (upload_on_fail) { 5076 DbgMessage(pdev, WARNl4sp, "Couldn't send empty ramrod on TX when we needed\n"); 5077 5078 /* instead of indicating the rst, which is NOT possible at this stage, ask for connection upload */ 5079 mm_tcp_indicate_retrieve_indication(pdev, tcp, L4_UPLOAD_REASON_UPLOAD_REQUESTED); 5080 pdev->toe_info.stats.total_rst_upld_requested++; 5081 } 5082 } 5083 } 5084 else 5085 { 5086 /* Release global TOE lock */ 5087 MM_RELEASE_TOE_LOCK(pdev); 5088 } 5089 } 5090 5091 5092 static void lm_tcp_rx_abortive_disconnect_ramrod_complete ( 5093 struct _lm_device_t * pdev, 5094 lm_tcp_state_t * tcp) 5095 { 5096 lm_tcp_con_t * rx_con; 5097 MM_INIT_TCP_LOCK_HANDLE(); 5098 5099 DbgMessage(pdev, INFORMl4rx, "###lm_tcp_process_abortive_disconnect_request_rcqe cid=%d\n", tcp->cid); 5100 DbgBreakIf( ! (pdev && tcp) ); 5101 5102 rx_con = tcp->rx_con; 5103 5104 /* Take the Rx lock */ 5105 mm_acquire_tcp_lock(pdev, rx_con); 5106 5107 /* break if we received a rst on the cqe and we still have an 'unreleased' generic buffer in our peninsula */ 5108 DbgBreakIf( !d_list_is_empty(&tcp->rx_con->u.rx.gen_info.peninsula_list) && 5109 (((lm_tcp_gen_buf_t *)(d_list_peek_tail(&tcp->rx_con->u.rx.gen_info.peninsula_list)))->placed_bytes == 0)); 5110 5111 /* This implies COMP_BLOCKED */ 5112 rx_con->flags |= TCP_RST_REQ_COMPLETED; 5113 5114 /* Release the Tx lock */ 5115 mm_release_tcp_lock(pdev, rx_con); 5116 } 5117 5118 static void lm_tcp_tx_abortive_disconnect_ramrod_complete ( 5119 struct _lm_device_t * pdev, 5120 lm_tcp_state_t * tcp) 5121 { 5122 lm_tcp_con_t * tx_con; 5123 MM_INIT_TCP_LOCK_HANDLE(); 5124 5125 DbgMessage(pdev, INFORMl4tx, "###lm_tcp_tx_abortive_disconnect_request_complete cid=%d\n", tcp->cid); 5126 DbgBreakIf( ! (pdev && tcp) ); 5127 5128 tx_con = tcp->tx_con; 5129 5130 /* Take the Tx lock */ 5131 mm_acquire_tcp_lock(pdev, tx_con); 5132 5133 /* This implies COMP_BLOCKED */ 5134 tx_con->flags |= TCP_RST_REQ_COMPLETED; 5135 5136 /* Release the Tx lock */ 5137 mm_release_tcp_lock(pdev, tx_con); 5138 } 5139 5140 5141 5142 static void lm_tcp_comp_invalidate_request( 5143 struct _lm_device_t * pdev, 5144 lm_tcp_state_t * tcp, 5145 lm_tcp_slow_path_request_t * request) 5146 { 5147 DbgMessage(pdev, INFORMl4sp, "### Completing invalidate request cid=%d\n", tcp->cid); 5148 5149 MM_ACQUIRE_TOE_LOCK(pdev); 5150 5151 DbgBreakIf(!pdev || !tcp); 5152 DbgBreakIf(tcp->hdr.status != STATE_STATUS_NORMAL && tcp->hdr.status != STATE_STATUS_ABORTED); 5153 5154 tcp->hdr.status = STATE_STATUS_INVALIDATED; 5155 5156 tcp->sp_request = NULL; 5157 5158 request->status = LM_STATUS_SUCCESS; 5159 5160 DbgBreakIf(tcp->sp_flags & ( SP_REQUEST_COMPLETED_TX | SP_REQUEST_COMPLETED_RX )); 5161 5162 mm_tcp_comp_slow_path_request(pdev, tcp, request); 5163 5164 MM_RELEASE_TOE_LOCK(pdev); 5165 } 5166 5167 5168 static void lm_tcp_tx_invalidate_ramrod_complete ( 5169 struct _lm_device_t * pdev, 5170 lm_tcp_state_t * tcp) 5171 { 5172 lm_tcp_con_t * tx_con; 5173 MM_INIT_TCP_LOCK_HANDLE(); 5174 5175 DbgMessage(pdev, INFORMl4tx, "###lm_tcp_tx_invalidate_request_complete cid=%d\n", tcp->cid); 5176 5177 DbgBreakIf( ! (pdev && tcp) ); 5178 5179 tx_con = tcp->tx_con; 5180 5181 /* Take the Tx lock */ 5182 mm_acquire_tcp_lock(pdev, tx_con); 5183 5184 /* This implies COMP_BLOCKED */ 5185 DbgBreakIf(tx_con->flags & TCP_INV_REQ_COMPLETED); 5186 tx_con->flags |= TCP_INV_REQ_COMPLETED; 5187 5188 /* Release the Tx lock */ 5189 mm_release_tcp_lock(pdev, tx_con); 5190 } 5191 5192 5193 static void lm_tcp_rx_invalidate_ramrod_complete ( 5194 struct _lm_device_t * pdev, 5195 lm_tcp_state_t * tcp) 5196 { 5197 lm_tcp_con_t * rx_con; 5198 MM_INIT_TCP_LOCK_HANDLE(); 5199 5200 DbgMessage(pdev, INFORMl4rx, "###lm_tcp_process_invalidate_request_rcqe cid=%d\n", tcp->cid); 5201 DbgBreakIf( ! (pdev && tcp) ); 5202 5203 rx_con = tcp->rx_con; 5204 5205 5206 /* Take the Rx lock */ 5207 mm_acquire_tcp_lock(pdev, rx_con); 5208 /* 'POST/IND BLOCKED' in the request. 5209 Even a post was in the middle it must be done by now 5210 */ 5211 DbgBreakIf( mm_tcp_indicating_bufs(rx_con) ); 5212 5213 /* break if we received an invalidate on the cqe and we still have an 'unreleased' generic buffer in our peninsula */ 5214 DbgBreakIf( !d_list_is_empty(&tcp->rx_con->u.rx.gen_info.peninsula_list) && 5215 (((lm_tcp_gen_buf_t *)(d_list_peek_tail(&tcp->rx_con->u.rx.gen_info.peninsula_list)))->placed_bytes == 0)); 5216 5217 /* This implies COMP_BLOCKED */ 5218 DbgBreakIf(rx_con->flags & TCP_INV_REQ_COMPLETED); 5219 rx_con->flags |= TCP_INV_REQ_COMPLETED; 5220 5221 /* Release the Rx lock */ 5222 mm_release_tcp_lock(pdev, rx_con); 5223 } 5224 5225 5226 static void lm_tcp_get_delegated( 5227 IN struct _lm_device_t * pdev, 5228 IN lm_tcp_state_t * tcp, 5229 IN void * ctx_p /* context with updated data */ 5230 ) 5231 { 5232 struct xstorm_toe_tcp_ag_context_section * xag_tcp = NULL; 5233 struct tstorm_tcp_st_context_section * tst_tcp = NULL; 5234 struct xstorm_tcp_context_section * xst_tcp = NULL; 5235 struct tstorm_toe_tcp_ag_context_section * tag_tcp = NULL; 5236 5237 struct ustorm_toe_st_context * ust_toe = NULL; 5238 struct cstorm_toe_st_context * cst_toe = NULL; 5239 struct xstorm_toe_ag_context * xag_toe = NULL; 5240 struct xstorm_toe_context_section * xst_toe = NULL; 5241 5242 u32_t send_wnd; 5243 u8_t sanity_check; 5244 5245 ASSERT_STATIC(sizeof(struct xstorm_toe_tcp_ag_context_section) == sizeof(struct xstorm_tcp_tcp_ag_context_section)); 5246 ASSERT_STATIC(sizeof(struct tstorm_toe_tcp_ag_context_section) == sizeof(struct tstorm_tcp_tcp_ag_context_section)); 5247 5248 sanity_check = FALSE; 5249 5250 /* Set shortcuts... and take care of driver delegated params. */ 5251 if (tcp->ulp_type == TOE_CONNECTION_TYPE) 5252 { 5253 xst_tcp = &((struct toe_context *)ctx_p)->xstorm_st_context.context.common.tcp; 5254 xag_tcp = &((struct toe_context *)ctx_p)->xstorm_ag_context.tcp; 5255 tst_tcp = &((struct toe_context *)ctx_p)->tstorm_st_context.context.tcp; 5256 tag_tcp = &((struct toe_context *)ctx_p)->tstorm_ag_context.tcp; 5257 5258 xst_toe = &((struct toe_context *)ctx_p)->xstorm_st_context.context.toe; 5259 xag_toe = &((struct toe_context *)ctx_p)->xstorm_ag_context; 5260 cst_toe = &((struct toe_context *)ctx_p)->cstorm_st_context.context; 5261 ust_toe = &((struct toe_context *)ctx_p)->ustorm_st_context.context; 5262 5263 if (S32_SUB(tcp->rx_con->u.rx.sws_info.drv_rcv_win_right_edge, tcp->rx_con->db_data.rx->rcv_win_right_edge) < 0) { 5264 /* due to window decrease issues... */ 5265 tcp->rx_con->u.rx.sws_info.drv_rcv_win_right_edge = tcp->rx_con->db_data.rx->rcv_win_right_edge; 5266 } 5267 5268 /* RcvWnd = WndRightEgde - RcvNext */ 5269 /* recv_win_seq is determined by the driver, and therefore is the most up-to-date value, 5270 * we also have to add any pending indicated bytes to this value, and this is because we don't 5271 * add them immediatel, only when the buffer is returned to help limit our GRQ pool. */ 5272 tcp->tcp_delegated.recv_win_seq = tcp->rx_con->u.rx.sws_info.drv_rcv_win_right_edge + 5273 tcp->rx_con->u.rx.gen_info.pending_indicated_bytes; 5274 5275 if (!lm_reset_is_inprogress(pdev)) 5276 { 5277 sanity_check = TRUE; 5278 } 5279 5280 } 5281 else if (tcp->ulp_type == ISCSI_CONNECTION_TYPE) 5282 { 5283 xst_tcp = &((struct iscsi_context *)ctx_p)->xstorm_st_context.common.tcp; 5284 xag_tcp = (struct xstorm_toe_tcp_ag_context_section *)&((struct iscsi_context *)ctx_p)->xstorm_ag_context.tcp; 5285 tst_tcp = &((struct iscsi_context *)ctx_p)->tstorm_st_context.tcp; 5286 tag_tcp = (struct tstorm_toe_tcp_ag_context_section *)&((struct toe_context *)ctx_p)->tstorm_ag_context.tcp; 5287 5288 /* RcvWnd = WndRightEgde - RcvNext */ 5289 tcp->tcp_delegated.recv_win_seq = tag_tcp->wnd_right_edge - tst_tcp->rcv_nxt; 5290 } 5291 else 5292 { 5293 DbgBreakMsg("lm_tcp_get_delegated: Unsupported protocol type \n") ; 5294 return; 5295 } 5296 5297 /* Sanity Checks: (block below) 5298 * the purpose for sanity checks below, under debug only is to find a problem in FW delegated params before 5299 * we send them to OS in which case it may assert later on, or worse after several offloads. 5300 * Perform sanity checks only if chip isn't under reset... In case of error recovery for example, these delegated 5301 * params may be rubbish, it's ok since in the same case we'll also send a LM_STATUS_FAILURE in the upload completion. 5302 */ 5303 if (sanity_check) 5304 { 5305 5306 /* context sanity checks */ 5307 #if !defined(_VBD_CMD_) 5308 /* check that DMA write towards host is done */ 5309 DbgBreakIf(((struct toe_context *)ctx_p)->ustorm_ag_context.__state == 0); 5310 DbgBreakIf(((struct toe_context *)ctx_p)->tstorm_ag_context.__state == 0); 5311 DbgBreakIf(((struct toe_context *)ctx_p)->xstorm_ag_context.__state == 0); 5312 /* needs to be: t <= x <= u <= drv */ 5313 /* driver window right edge >= ust.prev_rcv_win_right_edge >= xag.local_adv_wnd >= tag.wnd_right_edge (cyclic)*/ 5314 // apply in w2k3 5315 // DbgBreakIf(S32_SUB(xag_tcp->local_adv_wnd, tag_tcp->wnd_right_edge) < 0); 5316 // DbgBreakIf(S32_SUB(ust_toe->prev_rcv_win_right_edge, xag_tcp->local_adv_wnd) < 0); 5317 // DbgBreakIf(S32_SUB(tcp->rx_con->u.rx.sws_info.drv_rcv_win_right_edge, ust_toe->prev_rcv_win_right_edge) < 0); 5318 /* xag.snd_nxt <= xst.snd_max */ 5319 DbgBreakIf(S32_SUB(xag_tcp->snd_nxt, xst_tcp->snd_max) > 0); 5320 /* xag.snd_una <= tag.snd_una <= tag.snd_max <= xst.snd_max */ 5321 DbgBreakIf(S32_SUB(xag_tcp->snd_una, tag_tcp->snd_una) != 0); 5322 DbgBreakIf(S32_SUB(tag_tcp->snd_una, tag_tcp->snd_max) > 0); 5323 // TBD: the assert is not valid, discuess with FW regarding a change. DbgBreakIf(S32_SUB(tag_tcp->snd_max, xst_tcp->snd_max) > 0); 5324 /* xag.cmp_bd_start_seq <= c.cmp_bd_start_seq <= tag.snd_una */ 5325 DbgBreakIf(S32_SUB(xag_toe->cmp_bd_start_seq, tag_tcp->snd_una) > 0); 5326 /* tst.rcv_nxt >= xag.ack_to_far_end */ 5327 DbgBreakIf(S32_SUB(tst_tcp->rcv_nxt, xag_tcp->ack_to_far_end) != 0); 5328 /* tst.rcv_nxt >= tst.prev_seg_seq */ 5329 //DbgBreakIf(S32_SUB(tst_tcp->rcv_nxt, tst_tcp->prev_seg_seq) < 0); 5330 /* xag.cmp_bd_cons <= cst.bd_cons <= xst.tx_bd_cons <= xst.bd_prod <= Driver bd prod (16 bit cyclic) */ 5331 DbgBreakIf(S16_SUB(xag_toe->cmp_bd_cons, cst_toe->bd_cons) > 0); 5332 DbgBreakIf(S16_SUB(xst_toe->tx_bd_cons, xst_toe->bd_prod) > 0); 5333 DbgBreakIf(S16_SUB(xst_toe->bd_prod, tcp->tx_con->db_data.tx->bds_prod) > 0); 5334 DbgBreakIf(S32_SUB(tag_tcp->snd_una, xag_tcp->snd_nxt) > 0); 5335 /* timestamp: */ 5336 /* tst.timestamp_exists == xst.ts_enable -- ? can't find fields in fw*/ 5337 5338 /* tst.timestamp_recent >= xag.ts_to_echo (cyclic) */ 5339 DbgBreakIf(S32_SUB(tst_tcp->timestamp_recent, xag_tcp->ts_to_echo) < 0); 5340 5341 /* fin: ?? can't find fields in fw */ 5342 /* if (xst.fin_sent_flag) then bds should contain bd with fin // driver flag 'sent-fin' */ 5343 /* if (tag.fin_sent_flag) then xst.fin_sent_flag */ 5344 5345 5346 /* check that rcv nxt has the expected value compared to bytes that were completed on rx application buffers and generic buffers */ 5347 /* rx_bytes_recv = tcp->rx_con->bytes_comp_cnt + 5348 tcp->rx_con->u.rx.gen_info.bytes_indicated_accepted + 5349 (tcp->sp_request->ret_data.tcp_upload_data.frag_list ? tcp->sp_request->ret_data.tcp_upload_data.frag_list->size : 0) - 5350 tcp->rx_con->bytes_push_skip_cnt - 5351 if (tcp->rx_con->flags & TCP_REMOTE_FIN_RECEIVED) 5352 { 5353 DbgBreakIf(((u32_t)(tcp->tcp_delegated.recv_next + (u32_t)rx_bytes_recv + 1) != tst_tcp->rcv_nxt)); 5354 } else 5355 { 5356 DbgBreakIf(((u32_t)(tcp->tcp_delegated.recv_next + (u32_t)rx_bytes_recv) != tst_tcp->rcv_nxt)); 5357 } 5358 */ 5359 /* check that cstrom rel seq is equal to tstorm snd una */ 5360 DbgBreakIf(((struct toe_context *)ctx_p)->cstorm_ag_context.rel_seq != tag_tcp->snd_una); 5361 5362 /* check that snd una has the expected value compared to bytes that were completed on tx application buffers */ 5363 DbgBreakIf((u32_t)(tcp->tcp_delegated.send_una + (u32_t)tcp->tx_con->bytes_comp_cnt + (u32_t)tcp->tx_con->bytes_trm_aborted_cnt - (u32_t)tcp->tx_con->bytes_aborted_cnt) != tag_tcp->snd_una); 5364 #endif 5365 5366 } 5367 5368 /* Set the updated delegated parameters */ 5369 tcp->tcp_delegated.recv_next = tst_tcp->rcv_nxt; 5370 5371 tcp->tcp_delegated.send_una = tag_tcp->snd_una; 5372 tcp->tcp_delegated.send_next = xag_tcp->snd_nxt; 5373 tcp->tcp_delegated.send_max = xst_tcp->snd_max; 5374 /* recent_seg_wnd is the value received in the last packet from the other side. This means this value is scaled, 5375 * therefore we need to get the absolute value by 'unscaling' it */ 5376 tcp->tcp_delegated.send_win = (tst_tcp->recent_seg_wnd << tcp->tcp_const.snd_seg_scale) 5377 + tcp->tcp_delegated.send_una; 5378 send_wnd = tst_tcp->recent_seg_wnd << tcp->tcp_const.snd_seg_scale; 5379 5380 /* Does not come from chip! Driver uses what the chip returned for SndWnd, 5381 and takes the maximum between that, all past query results for this paramter, 5382 and 2 * MSS. 5383 */ 5384 if ( tcp->tcp_delegated.max_send_win < tcp->tcp_delegated.send_win - tcp->tcp_delegated.send_una) { 5385 tcp->tcp_delegated.max_send_win = tcp->tcp_delegated.send_win - tcp->tcp_delegated.send_una; 5386 } 5387 5388 tcp->tcp_delegated.send_wl1 = tst_tcp->prev_seg_seq; 5389 tcp->tcp_delegated.send_cwin = tst_tcp->cwnd + tcp->tcp_delegated.send_una; 5390 tcp->tcp_delegated.ss_thresh = tst_tcp->ss_thresh; 5391 5392 tcp->tcp_delegated.sm_rtt = (tst_tcp->flags1 & TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT) 5393 >> TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT_SHIFT; 5394 tcp->tcp_delegated.sm_delta = (tst_tcp->flags2 & TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION) 5395 >> TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION_SHIFT; 5396 /* convert ms to ticks. */ 5397 //16/09/2008 NirV: Assert removed, return upon fw fix 5398 //DbgBreakIf(tcp->tcp_delegated.sm_rtt > (35*TIMERS_TICKS_PER_SEC)); 5399 //DbgBreakIf(tcp->tcp_delegated.sm_delta > (35*TIMERS_TICKS_PER_SEC)); 5400 5401 tcp->tcp_delegated.sm_rtt = 5402 lm_time_resolution(pdev, tcp->tcp_delegated.sm_rtt, TIMERS_TICKS_PER_SEC, pdev->ofld_info.l4_params.ticks_per_second)*8; 5403 tcp->tcp_delegated.sm_delta = 5404 lm_time_resolution(pdev, tcp->tcp_delegated.sm_delta, TIMERS_TICKS_PER_SEC, pdev->ofld_info.l4_params.ticks_per_second)*4; 5405 5406 tcp->tcp_delegated.ts_recent = tst_tcp->timestamp_recent; 5407 /* convert ms to ticks. */ 5408 tcp->tcp_delegated.ts_recent_age = 5409 lm_time_resolution(pdev, tst_tcp->timestamp_recent_time, TSEMI_CLK1_TICKS_PER_SEC, pdev->ofld_info.l4_params.ticks_per_second); 5410 5411 tcp->tcp_delegated.tstamp = xst_tcp->ts_time_diff; 5412 /* convert ms to ticks. */ 5413 tcp->tcp_delegated.total_rt = 5414 lm_time_resolution(pdev, tst_tcp->retransmit_start_time, TIMERS_TICKS_PER_SEC, pdev->ofld_info.l4_params.ticks_per_second); 5415 5416 tcp->tcp_delegated.dup_ack_count = tst_tcp->dup_ack_count; 5417 tcp->tcp_delegated.snd_wnd_probe_count = tst_tcp->persist_probe_count; 5418 5419 if(tcp->tcp_delegated.send_una == tcp->tcp_delegated.send_max && (send_wnd > 0)) { /* KA is running (?) */ 5420 if ( (tcp->tcp_cached.tcp_flags & TCP_FLAG_ENABLE_KEEP_ALIVE)) { 5421 5422 tcp->tcp_delegated.u.keep_alive.probe_cnt = tst_tcp->ka_probe_count; 5423 5424 /* convert ms to ticks. */ 5425 tcp->tcp_delegated.u.keep_alive.timeout_delta = 5426 lm_time_resolution(pdev, xag_tcp->ka_timer, TIMERS_TICKS_PER_SEC, pdev->ofld_info.l4_params.ticks_per_second); 5427 5428 /* ka timeout may be negative in cases that it expired and timer was armed for other purposes. In this case - we write 0 to the 5429 * timeout delta - OS will treat this as if timer has just expired */ 5430 /* bugbug, for some reason, we get a 28 bit value from FW, so a value such as 0xffffff9 is actually negative... so instead of checking (the reason is that timer's block bus width is 28 bit - ariel) 5431 * negative - we just check if it's larger than 0x8000000*/ 5432 if ((tcp->tcp_delegated.u.keep_alive.timeout_delta != 0xffffffff) && 5433 (tcp->tcp_delegated.u.keep_alive.timeout_delta > 0x8000000)) { 5434 tcp->tcp_delegated.u.keep_alive.timeout_delta = 0; 5435 } 5436 } else { //ka disabled 5437 tcp->tcp_delegated.u.keep_alive.probe_cnt = 0; 5438 tcp->tcp_delegated.u.keep_alive.timeout_delta = 0xffffffff; 5439 } 5440 } else { 5441 tcp->tcp_delegated.u.retransmit.num_retx = tst_tcp->retransmit_count; 5442 //TBD: Ariel, why it comes from the same place as TotalRT? 5443 /* TODO: we need to convert retx_ms to clock ticks in VBD instead of 5444 * doing this conversion in NDIS (same as Teton) */ 5445 5446 /* rto_timer may be negative in cases that it expired and timer was armed for other purposes. In this case - we write 0 to the 5447 * retx_ms - OS will treat this as if timer has just expired and immediately retransmit. */ 5448 /* bugbug, for some reason, we get a 28 bit value from FW, so a value such as 0xffffff9 is actually negative... so instead of checking 5449 * negative - we just check if it's larger than 0xf000000*/ 5450 if ((xag_tcp->rto_timer != 0xffffffff) && (xag_tcp->rto_timer > 0x8000000)) { 5451 tcp->tcp_delegated.u.retransmit.retx_ms = 0; 5452 } else { 5453 tcp->tcp_delegated.u.retransmit.retx_ms = xag_tcp->rto_timer; 5454 } 5455 } 5456 5457 /* Calculate the TCP connection state */ 5458 tcp->tcp_delegated.con_state = lm_tcp_calc_state(pdev, tcp, 5459 xst_tcp->tcp_params & XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG ? 1 : 0); 5460 pdev->toe_info.stats.con_state_on_upload[tcp->tcp_delegated.con_state]++; 5461 } 5462 5463 5464 void lm_init_sp_req_type( 5465 struct _lm_device_t * pdev, 5466 lm_tcp_state_t * tcp, 5467 lm_tcp_slow_path_request_t * lm_req, 5468 void * req_input_data) 5469 { 5470 5471 UNREFERENCED_PARAMETER_(pdev); 5472 5473 switch(lm_req->type) { 5474 case SP_REQUEST_INITIATE_OFFLOAD: 5475 case SP_REQUEST_TERMINATE_OFFLOAD: 5476 case SP_REQUEST_PENDING_LOCAL_FIN_DISCONNECT: 5477 case SP_REQUEST_PENDING_REMOTE_DISCONNECT: 5478 case SP_REQUEST_PENDING_TX_RST: 5479 case SP_REQUEST_ABORTIVE_DISCONNECT: 5480 case SP_REQUEST_INVALIDATE: 5481 break; 5482 case SP_REQUEST_UPDATE_TCP: 5483 case SP_REQUEST_UPDATE_PATH: 5484 case SP_REQUEST_UPDATE_NEIGH: 5485 case SP_REQUEST_UPDATE_PATH_RELINK: 5486 lm_req->sent_data.tcp_update_data.data = req_input_data; 5487 break; 5488 case SP_REQUEST_QUERY: 5489 DbgBreakMsg("GilR - NOT IMPLEMENTED!\n"); 5490 break; 5491 default: 5492 DbgBreakMsg("Illegal slow path request type!\n"); 5493 } 5494 5495 /* initialize common section of the sp request */ 5496 lm_req->sp_req_common.req_post_func = (void *)lm_tcp_post_slow_path_request; 5497 lm_req->sp_req_common.req_post_ctx = tcp; 5498 } 5499 5500 5501 5502 static void _lm_tcp_comp_upload_tcp_request ( 5503 IN struct _lm_device_t * pdev, 5504 IN lm_tcp_state_t * tcp 5505 ) 5506 { 5507 lm_tcp_con_t * rx_con = tcp->rx_con; 5508 lm_tcp_con_t * tx_con = tcp->tx_con; 5509 u8_t has_fin = 0; 5510 u8_t has_rst = 0; 5511 lm_tcp_slow_path_request_t * sp_req = tcp->sp_request; 5512 lm_path_state_t * path = NULL; 5513 lm_status_t lm_status = LM_STATUS_SUCCESS; 5514 #if 0 // TODO: add WINDOW_DEC validation check in w2k3, implement upon os type identification in the lm 5515 #if (DBG && !defined(_VBD_CMD_) && !defined(__USER_MODE_DEBUG)) 5516 u32_t expect_rwin; 5517 #endif 5518 #endif 5519 MM_INIT_TCP_LOCK_HANDLE(); 5520 5521 /* status will be changed only after upload completion returns from the client */ 5522 5523 if (tcp->ulp_type == TOE_CONNECTION_TYPE) { 5524 /* Abort Tx buffers and pending graceful disconnect request if any */ 5525 mm_acquire_tcp_lock(pdev, tx_con); 5526 lm_tcp_abort_bufs(pdev, tcp, tx_con, (tx_con->flags & TCP_CON_RST_IND_NOT_SAFE)? LM_STATUS_CONNECTION_RESET : LM_STATUS_UPLOAD_IN_PROGRESS); 5527 5528 /* Remember pending RST if any */ 5529 has_rst |= (tx_con->u.tx.flags & TCP_CON_RST_IND_NOT_SAFE) ? 1 : 0; 5530 5531 /* Clear pending RST */ 5532 tx_con->u.tx.flags &= ~(TCP_CON_RST_IND_NOT_SAFE); 5533 5534 mm_release_tcp_lock(pdev, tx_con); 5535 5536 /* Rx abortive part... */ 5537 mm_acquire_tcp_lock(pdev, rx_con); 5538 /* Abort pending buffers */ 5539 lm_tcp_abort_bufs(pdev, tcp, rx_con, LM_STATUS_UPLOAD_IN_PROGRESS); 5540 5541 /* Remember pending FIN if any */ 5542 has_fin = rx_con->u.rx.flags & TCP_CON_FIN_IND_PENDING ? 1 : 0; 5543 5544 /* Remember pending RST if any */ 5545 has_rst |= (rx_con->u.rx.flags & TCP_CON_RST_IND_PENDING) ? 1 : 0; 5546 5547 /* Clear pending FIN and RST */ 5548 rx_con->u.rx.flags &= ~(TCP_CON_FIN_IND_PENDING | TCP_CON_RST_IND_PENDING); 5549 5550 /* Get generic data that hasn't been indicated so far */ 5551 lm_status = lm_tcp_rx_get_buffered_data_from_terminate(pdev, tcp, 5552 &(tcp->sp_request->ret_data.tcp_upload_data.frag_list), 5553 &(tcp->sp_request->ret_data.tcp_upload_data.ret_buf_ctx) 5554 ); 5555 mm_release_tcp_lock(pdev, rx_con); 5556 5557 /* check if we have a delayed fin */ 5558 /* assumption: if we have a delayed-fin, it means we have buffered data*/ 5559 /* OS can't handle fin indiaction followed by buffered data */ 5560 /* DbgBreakIf(has_fin && !sp_req->ret_data.tcp_upload_data.frag_list); */ 5561 /* DbgBreakIf(has_rst && !sp_req->ret_data.tcp_upload_data.frag_list); */ 5562 5563 /* check if we have a delayed rst (rst is sp so no locks) */ 5564 if ( has_rst ) { 5565 mm_tcp_indicate_rst_received(pdev, tcp); 5566 } 5567 } 5568 5569 /* Indication part */ 5570 MM_ACQUIRE_TOE_LOCK(pdev); 5571 5572 DbgBreakIf(!(tcp->sp_flags & SP_TCP_QRY_REQ_POSTED)); 5573 tcp->sp_flags |= SP_TCP_QRY_REQ_COMP; 5574 5575 /* Update delegated parameters */ 5576 lm_tcp_get_delegated(pdev, tcp, &tcp->sp_req_data.virt_addr->toe_ctx); 5577 5578 tcp->sp_request = NULL; 5579 sp_req->status = lm_status; 5580 5581 /* Indicate SP request completion up to the client */ 5582 /* Set the request type to TERMINATE_OFFLOAD as it was set by UM during the post */ 5583 sp_req->type = SP_REQUEST_TERMINATE_OFFLOAD; 5584 5585 DbgBreakIf(tcp->path->num_dependents == 0); 5586 tcp->path->num_dependents--; 5587 5588 // update stats counters if TOE 5589 if (TOE_CONNECTION_TYPE == tcp->ulp_type ) 5590 { 5591 if( IP_VERSION_IPV4 == tcp->path->path_const.ip_version ) 5592 { 5593 --pdev->vars.stats.stats_mirror.stats_drv.drv_toe.ipv[STATS_IP_4_IDX].currently_established; 5594 } 5595 else if( IP_VERSION_IPV6 == tcp->path->path_const.ip_version ) 5596 { 5597 --pdev->vars.stats.stats_mirror.stats_drv.drv_toe.ipv[STATS_IP_6_IDX].currently_established; 5598 } 5599 } 5600 5601 if (tcp->path->hdr.status == STATE_STATUS_UPLOAD_PENDING && 5602 tcp->path->num_dependents == 0) { 5603 /* last pendind-upload-path dependent... */ 5604 path = tcp->path; 5605 } 5606 tcp->path = NULL; 5607 5608 #if 0 // TODO: add WINDOW_DEC validation check in w2k3, implement upon os type identification in the lm 5609 if (tcp->ulp_type == TOE_CONNECTION_TYPE) { 5610 #if (DBG && !defined(_VBD_CMD_) && !defined(__USER_MODE_DEBUG)) 5611 expect_rwin = (u32_t) S32_SUB( 5612 tcp->tcp_delegated.recv_win_seq, 5613 tcp->tcp_delegated.recv_next); 5614 /* These asserts are not valid for WSD connections. */ 5615 if(sp_req->ret_data.tcp_upload_data.frag_list) 5616 { 5617 expect_rwin += (u32_t)sp_req->ret_data.tcp_upload_data.frag_list->size; 5618 } 5619 5620 /* If we received a fin / rst we may be down by one on the initial_rcv_wnd... */ 5621 if((tcp->rx_con->flags & TCP_REMOTE_FIN_RECEIVED) || 5622 (tcp->rx_con->flags & TCP_REMOTE_RST_RECEIVED)) 5623 { 5624 DbgBreakIf( 5625 (expect_rwin != tcp->tcp_cached.initial_rcv_wnd) && 5626 (expect_rwin != tcp->tcp_cached.initial_rcv_wnd - 1)); 5627 } 5628 else 5629 { 5630 DbgBreakIf(expect_rwin != tcp->tcp_cached.initial_rcv_wnd); 5631 } 5632 #endif 5633 } 5634 #endif 5635 5636 mm_tcp_comp_slow_path_request(pdev, tcp, sp_req); 5637 5638 if (path) { 5639 DbgMessage(pdev, INFORMl4sp, "_lm_tcp_comp_upload_request: last tcp dependent of pending path %p\n", path); 5640 _lm_tcp_comp_upload_path_request(pdev, path); 5641 } 5642 5643 MM_RELEASE_TOE_LOCK(pdev); 5644 5645 5646 } 5647 5648 lm_tcp_state_t * lm_tcp_get_next_path_dependent( 5649 struct _lm_device_t *pdev, 5650 void *path_state, 5651 lm_tcp_state_t * tcp_state) 5652 { 5653 if (tcp_state == NULL) { 5654 tcp_state = (lm_tcp_state_t *) d_list_peek_head(&pdev->toe_info.state_blk.tcp_list); 5655 } else { 5656 tcp_state = (lm_tcp_state_t *) d_list_next_entry(&tcp_state->hdr.link); 5657 } 5658 5659 while(tcp_state) { 5660 /* Update the tcp state only if it is a dependent and is not being offloaded, 5661 * invalidated, or uploaded. */ 5662 if (tcp_state->path == (lm_path_state_t*)path_state) { 5663 return tcp_state; 5664 } 5665 tcp_state = (lm_tcp_state_t *) d_list_next_entry(&tcp_state->hdr.link); 5666 } 5667 return NULL; 5668 5669 } 5670 5671 5672 lm_tcp_state_t * lm_tcp_get_next_neigh_dependent( 5673 struct _lm_device_t *pdev, 5674 void * neigh_state, 5675 lm_tcp_state_t * tcp_state) 5676 { 5677 if (tcp_state == NULL) { 5678 tcp_state = (lm_tcp_state_t *) d_list_peek_head(&pdev->toe_info.state_blk.tcp_list); 5679 } else { 5680 tcp_state = (lm_tcp_state_t *) d_list_next_entry(&tcp_state->hdr.link); 5681 } 5682 5683 while(tcp_state) { 5684 /* Update the tcp state only if it is a dependent and is not being offloaded, 5685 * invalidated, or uploaded. */ 5686 if (tcp_state->path && (tcp_state->path->neigh == (lm_neigh_state_t*)neigh_state)) { 5687 return tcp_state; 5688 } 5689 tcp_state = (lm_tcp_state_t *) d_list_next_entry(&tcp_state->hdr.link); 5690 } 5691 return NULL; 5692 } 5693 5694 5695 void lm_tcp_update_ramrod_complete(lm_device_t * pdev, lm_tcp_state_t * tcp) 5696 { 5697 lm_tcp_slow_path_request_t *sp_req; 5698 MM_INIT_TCP_LOCK_HANDLE(); 5699 5700 DbgMessage(pdev, INFORMl4sp, "###lm_tcp_update_ramrod_complete cid=%d \n", tcp->cid); 5701 5702 MM_ACQUIRE_TOE_LOCK(pdev); 5703 5704 /* assert state status is NORMAL */ 5705 DbgBreakIf( (tcp->hdr.status != STATE_STATUS_NORMAL) && 5706 (tcp->hdr.status != STATE_STATUS_ABORTED)); 5707 DbgBreakIf(tcp->sp_request == NULL); 5708 DbgBreakIf((tcp->sp_request->type != SP_REQUEST_UPDATE_NEIGH) && 5709 (tcp->sp_request->type != SP_REQUEST_UPDATE_PATH) && 5710 (tcp->sp_request->type != SP_REQUEST_UPDATE_TCP) && 5711 (tcp->sp_request->type != SP_REQUEST_UPDATE_PATH_RELINK)); 5712 5713 sp_req = tcp->sp_request; 5714 DbgBreakIf(tcp->sp_flags & ( SP_REQUEST_COMPLETED_TX | SP_REQUEST_COMPLETED_RX )); 5715 sp_req->status = LM_STATUS_SUCCESS; 5716 tcp->sp_request = NULL; 5717 5718 /* Take the Rx lock */ 5719 mm_acquire_tcp_lock(pdev, tcp->rx_con); 5720 if ((sp_req->type == SP_REQUEST_UPDATE_TCP) && (GET_FLAGS(tcp->rx_con->db_data.rx->flags, TOE_RX_DB_DATA_IGNORE_WND_UPDATES))) 5721 { 5722 lm_tcp_rx_post_sws(pdev, tcp, tcp->rx_con, tcp->rx_con->dpc_info.dpc_fw_wnd_after_dec, TCP_RX_POST_SWS_SET); 5723 } 5724 /* Release the Rx lock */ 5725 mm_release_tcp_lock(pdev, tcp->rx_con); 5726 5727 mm_tcp_comp_slow_path_request(pdev, tcp, sp_req); 5728 5729 MM_RELEASE_TOE_LOCK(pdev); 5730 } 5731 5732 5733 void lm_tcp_query_ramrod_complete( 5734 IN struct _lm_device_t * pdev, 5735 IN lm_tcp_state_t * tcp 5736 ) 5737 { 5738 DbgMessage(pdev, VERBOSEl4, "## lm_tcp_query_ramrod_comp\n"); 5739 DbgBreakIf(! tcp->sp_request ); 5740 DbgBreakIf(tcp->sp_request->type != SP_REQUEST_QUERY); 5741 5742 if (tcp->hdr.status == STATE_STATUS_UPLOAD_PENDING) { 5743 _lm_tcp_comp_upload_tcp_request(pdev, tcp); 5744 } else { 5745 DbgBreakMsg("Vladz: Not implemented yet!\n"); 5746 } 5747 } 5748 5749 /* TOE lock should be taken by hte caller */ 5750 void lm_tcp_internal_query( 5751 IN struct _lm_device_t * pdev) 5752 { 5753 lm_tcp_state_t *tcp_state; 5754 u32_t status_arr[STATE_STATUS_ERR+1] = {0}; 5755 u32_t status, num_tcps, i; 5756 5757 DbgMessage(pdev, FATAL, "## lm_tcp_debug_query START version %d.%d.%d\n", 5758 LM_DRIVER_MAJOR_VER, LM_DRIVER_MINOR_VER, LM_DRIVER_FIX_NUM); 5759 5760 num_tcps = d_list_entry_cnt(&pdev->toe_info.state_blk.tcp_list); 5761 tcp_state = (lm_tcp_state_t *)d_list_peek_head(&pdev->toe_info.state_blk.tcp_list); 5762 i = 0; 5763 while (tcp_state) { 5764 status = tcp_state->hdr.status; 5765 status_arr[status]++; 5766 5767 /* check state's status */ 5768 if(status != STATE_STATUS_NORMAL) { 5769 DbgMessage(pdev, FATAL, "# tcp ptr 0x%p (cid %d), has status=%d (!= normal)\n", 5770 tcp_state, tcp_state->cid, status); 5771 } 5772 5773 /* verify the is no pending slow path request */ 5774 if(tcp_state->sp_request) { 5775 DbgMessage(pdev, FATAL, "# tcp ptr 0x%p (cid %d), has slow path request of type %d, not completed by FW (sp comp flags=0x%x\n", 5776 tcp_state, tcp_state->cid, tcp_state->sp_request->type, tcp_state->sp_flags); 5777 } 5778 5779 /* verify the is no bytes pending completion */ 5780 if(tcp_state->tx_con->bytes_post_cnt != tcp_state->tx_con->bytes_comp_cnt) { 5781 DbgMessage(pdev, FATAL, "# tcp ptr 0x%p (cid %d), has TX pending bytes (%d). (con->flags=0x%x)\n", 5782 tcp_state, tcp_state->cid, 5783 S64_SUB(tcp_state->tx_con->bytes_post_cnt, tcp_state->tx_con->bytes_comp_cnt), 5784 tcp_state->tx_con->flags); 5785 } 5786 if(tcp_state->rx_con->bytes_post_cnt != tcp_state->rx_con->bytes_comp_cnt) { 5787 DbgMessage(pdev, FATAL, "# tcp ptr 0x%p (cid %d), has RX pending bytes (%d). (con->flags=0x%x)\n", 5788 tcp_state, tcp_state->cid, 5789 S64_SUB(tcp_state->rx_con->bytes_post_cnt, tcp_state->rx_con->bytes_comp_cnt), 5790 tcp_state->rx_con->flags); 5791 } 5792 5793 tcp_state = (lm_tcp_state_t *)d_list_next_entry((d_list_entry_t*)tcp_state); 5794 } 5795 5796 /* print statistics */ 5797 DbgMessage(pdev, FATAL, "# num offloaded connections=%d\n", num_tcps); 5798 for (i = 0; i < STATE_STATUS_ERR+1; i++) { 5799 if (status_arr[i]) { 5800 DbgMessage(pdev, FATAL, "# num connections in status %d=%d\n", i, status_arr[i]); 5801 } 5802 } 5803 5804 DbgMessage(pdev, FATAL, "## lm_tcp_debug_query END\n"); 5805 } 5806 5807 5808 void lm_tcp_upld_close_received_complete( 5809 struct _lm_device_t * pdev, 5810 lm_tcp_state_t * tcp, 5811 l4_upload_reason_t upload_reason) 5812 { 5813 DbgMessage(pdev, INFORMl4sp , "###lm_tcp_drv_upl_received_complete cid=%d \n", tcp->cid); 5814 5815 MM_ACQUIRE_TOE_LOCK(pdev); 5816 5817 tcp->tcp_state_calc.con_upld_close_flag = TRUE; 5818 5819 MM_RELEASE_TOE_LOCK(pdev); 5820 5821 lm_tcp_process_retrieve_indication_cqe(pdev, tcp, upload_reason); 5822 pdev->toe_info.stats.total_close_upld_requested++; 5823 } 5824 5825 5826 /** Description 5827 * completes the slow-path part of a connection 5828 */ 5829 void lm_tcp_tx_complete_tcp_sp( 5830 IN struct _lm_device_t * pdev, 5831 IN lm_tcp_state_t * tcp, 5832 IN lm_tcp_con_t * con) 5833 { 5834 u8_t complete_ramrod; 5835 u32_t sp_type,sp_flags,flags,snapshot_flags; 5836 lm_tcp_slow_path_request_t * request = NULL; 5837 5838 snapshot_flags = con->dpc_info.snapshot_flags; 5839 if (con->dpc_info.snapshot_flags & LM_TCP_DPC_RESET_RECV) { 5840 con->dpc_info.snapshot_flags &= ~LM_TCP_DPC_RESET_RECV; 5841 lm_tcp_tx_rst_received_complete(pdev, con->tcp_state); 5842 } 5843 if (con->dpc_info.snapshot_flags & LM_TCP_DPC_RAMROD_CMP) { 5844 /* clean the dpc_info: we're done with it */ 5845 con->dpc_info.snapshot_flags = 0; 5846 5847 /* all ramrod on SCQ also complete on RCQ*/ 5848 complete_ramrod = FALSE; 5849 /* Get global TOE lock */ 5850 MM_ACQUIRE_TOE_LOCK(pdev); 5851 5852 /* save the type under the lock because the next ramrod will change this type ???*/ 5853 sp_type = tcp->sp_request->type; 5854 MM_RELEASE_TOE_LOCK(pdev); 5855 5856 switch(sp_type) { 5857 case SP_REQUEST_ABORTIVE_DISCONNECT: 5858 lm_tcp_tx_abortive_disconnect_ramrod_complete(pdev, tcp); 5859 break; 5860 case SP_REQUEST_INVALIDATE: 5861 lm_tcp_tx_invalidate_ramrod_complete(pdev, tcp); 5862 break; 5863 case SP_REQUEST_TERMINATE1_OFFLOAD: 5864 lm_tcp_tx_terminate_ramrod_complete(pdev, tcp); 5865 break; 5866 case SP_REQUEST_PENDING_LOCAL_FIN_DISCONNECT: 5867 case SP_REQUEST_PENDING_REMOTE_DISCONNECT: 5868 case SP_REQUEST_PENDING_TX_RST: 5869 lm_tcp_tx_empty_ramrod_complete(pdev, tcp, sp_type); 5870 break; 5871 default: 5872 DbgMessage(pdev, FATAL, "unexpected sp completion type=%d\n", tcp->sp_request->type); 5873 DbgBreak(); 5874 } 5875 /* Get global TOE lock */ 5876 MM_ACQUIRE_TOE_LOCK(pdev); 5877 5878 /* save the type under the lock because the next ramrod will change this type */ 5879 DbgBreakIf(sp_type != tcp->sp_request->type); 5880 5881 tcp->sp_flags |= SP_REQUEST_COMPLETED_TX; 5882 5883 /* If it's a second comletion, post the query ramrod */ 5884 if ( tcp->sp_flags & SP_REQUEST_COMPLETED_RX ) { 5885 complete_ramrod = TRUE; 5886 tcp->sp_flags &= ~ ( SP_REQUEST_COMPLETED_TX | SP_REQUEST_COMPLETED_RX ); 5887 } 5888 sp_flags = tcp->sp_flags; 5889 flags = tcp->tx_con->flags; 5890 MM_RELEASE_TOE_LOCK(pdev); 5891 if (complete_ramrod) { 5892 request = tcp->sp_request; 5893 DbgBreakIf(request == NULL); 5894 switch(sp_type) { 5895 case SP_REQUEST_ABORTIVE_DISCONNECT: 5896 DbgBreakIf(request->type != SP_REQUEST_ABORTIVE_DISCONNECT); 5897 lm_tcp_comp_abortive_disconnect_request(pdev, tcp, request); 5898 lm_sq_complete(pdev, CMD_PRIORITY_NORMAL, RAMROD_OPCODE_TOE_RESET_SEND, tcp->ulp_type, tcp->cid); 5899 break; 5900 case SP_REQUEST_INVALIDATE: 5901 DbgBreakIf(request->type != SP_REQUEST_INVALIDATE); 5902 lm_tcp_comp_invalidate_request(pdev, tcp, request); 5903 lm_sq_complete(pdev, CMD_PRIORITY_NORMAL, RAMROD_OPCODE_TOE_INVALIDATE, tcp->ulp_type, tcp->cid); 5904 break; 5905 case SP_REQUEST_TERMINATE1_OFFLOAD: 5906 DbgBreakIf(request->type != SP_REQUEST_TERMINATE1_OFFLOAD); 5907 lm_tcp_terminate_ramrod_complete(pdev, tcp); 5908 lm_sq_complete(pdev, CMD_PRIORITY_NORMAL, RAMROD_OPCODE_TOE_TERMINATE, tcp->ulp_type, tcp->cid); 5909 break; 5910 case SP_REQUEST_PENDING_LOCAL_FIN_DISCONNECT: 5911 case SP_REQUEST_PENDING_REMOTE_DISCONNECT: 5912 case SP_REQUEST_PENDING_TX_RST: 5913 lm_tcp_comp_empty_ramrod_request(pdev, tcp); 5914 lm_sq_complete(pdev, CMD_PRIORITY_NORMAL, RAMROD_OPCODE_TOE_EMPTY_RAMROD, tcp->ulp_type, tcp->cid); 5915 break; 5916 default: 5917 DbgMessage(pdev, FATAL, "unexpected sp completion type=%d\n", tcp->sp_request->type); 5918 DbgBreak(); 5919 } 5920 } 5921 } 5922 } 5923 5924 /** Description 5925 * completes the slow-path part of a connection 5926 * completes ramrods if ramrod is completed. 5927 * function logic: every stage 'turns' of it's flag, if at the end of the check the flags is zero 5928 * it means there is nothing left to do and we can return. Usually, we will rarely have a case of more 5929 * than one/two flags on, therefore it seems useless to check all the cases (too many if/jumps) 5930 */ 5931 void lm_tcp_rx_complete_tcp_sp( 5932 IN struct _lm_device_t * pdev, 5933 IN lm_tcp_state_t * tcp, 5934 IN lm_tcp_con_t * con 5935 ) 5936 { 5937 u8_t complete_ramrod; 5938 u32_t sp_type,sp_flags,flags,snapshot_flags; 5939 lm_tcp_slow_path_request_t * request = NULL; 5940 u32_t cid; 5941 u8_t ulp_type; 5942 5943 /* handle fin recv */ 5944 snapshot_flags = con->dpc_info.snapshot_flags; 5945 if (con->dpc_info.snapshot_flags & LM_TCP_DPC_FIN_RECV) { 5946 lm_tcp_rx_fin_received_complete(pdev, tcp, 0); 5947 con->dpc_info.snapshot_flags &= ~LM_TCP_DPC_FIN_RECV; 5948 } 5949 if (con->dpc_info.snapshot_flags & LM_TCP_DPC_FIN_RECV_UPL) { 5950 lm_tcp_rx_fin_received_complete(pdev, tcp, 1); 5951 con->dpc_info.snapshot_flags &= ~LM_TCP_DPC_FIN_RECV_UPL; 5952 } 5953 5954 DbgMessage(pdev, INFORMl4rx, "lm_tcp_rx_complete_tcp_sp tcp=%p cid=%d \n", tcp, tcp->cid); 5955 /* reset recv needs to be checked first */ 5956 if (con->dpc_info.snapshot_flags & LM_TCP_DPC_RESET_RECV) { 5957 con->dpc_info.snapshot_flags &= ~LM_TCP_DPC_RESET_RECV; 5958 lm_tcp_rx_rst_received_complete(pdev, tcp); 5959 } 5960 5961 /* check if we have some sort of retrieve indication. we sort of check twice */ 5962 /* Rx completions (from ustorm) will not arrive after the following indications, 5963 * therefore, we can assume, they were received before 5964 * can't assume the same for ramrods */ 5965 if (con->dpc_info.snapshot_flags & (LM_TCP_DPC_URG | LM_TCP_DPC_RT_TO | LM_TCP_DPC_KA_TO | LM_TCP_DPC_DBT_RE | LM_TCP_DPC_OPT_ERR | LM_TCP_DPC_UPLD_CLOSE)) { 5966 con->dpc_info.snapshot_flags &= ~(LM_TCP_DPC_TOO_BIG_ISLE | LM_TCP_DPC_TOO_MANY_ISLES); 5967 if (con->dpc_info.snapshot_flags & LM_TCP_DPC_URG) { 5968 con->dpc_info.snapshot_flags &= ~LM_TCP_DPC_URG; 5969 lm_tcp_process_retrieve_indication_cqe(pdev, tcp, L4_UPLOAD_REASON_URG); 5970 } 5971 5972 if (con->dpc_info.snapshot_flags & LM_TCP_DPC_RT_TO) { 5973 con->dpc_info.snapshot_flags &= ~LM_TCP_DPC_RT_TO; 5974 lm_tcp_process_retrieve_indication_cqe(pdev, tcp, L4_UPLOAD_REASON_RETRANSMIT_TIMEOUT); 5975 } 5976 5977 if (con->dpc_info.snapshot_flags & LM_TCP_DPC_KA_TO) { 5978 con->dpc_info.snapshot_flags &= ~LM_TCP_DPC_KA_TO; 5979 lm_tcp_upld_close_received_complete(pdev, tcp, L4_UPLOAD_REASON_KEEP_ALIVE_TIMEOUT); 5980 } 5981 5982 if (con->dpc_info.snapshot_flags & LM_TCP_DPC_DBT_RE) { 5983 con->dpc_info.snapshot_flags &= ~LM_TCP_DPC_DBT_RE; 5984 lm_tcp_process_retrieve_indication_cqe(pdev, tcp, L4_UPLOAD_REASON_UPLOAD_REQUESTED); 5985 pdev->toe_info.stats.total_dbt_upld_requested++; 5986 } 5987 5988 if (con->dpc_info.snapshot_flags & LM_TCP_DPC_OPT_ERR) { 5989 con->dpc_info.snapshot_flags &= ~LM_TCP_DPC_OPT_ERR; 5990 lm_tcp_process_retrieve_indication_cqe(pdev, tcp, L4_UPLOAD_REASON_UPLOAD_REQUESTED); 5991 pdev->toe_info.stats.total_opt_upld_requested++; 5992 } 5993 5994 if (con->dpc_info.snapshot_flags & LM_TCP_DPC_UPLD_CLOSE) { 5995 con->dpc_info.snapshot_flags &= ~LM_TCP_DPC_UPLD_CLOSE; 5996 lm_tcp_upld_close_received_complete(pdev, tcp, L4_UPLOAD_REASON_UPLOAD_REQUESTED); 5997 } 5998 } else if (con->dpc_info.snapshot_flags & LM_TCP_DPC_TOO_BIG_ISLE) { 5999 con->dpc_info.snapshot_flags &= ~(LM_TCP_DPC_TOO_BIG_ISLE | LM_TCP_DPC_TOO_MANY_ISLES); 6000 lm_tcp_process_retrieve_indication_cqe(pdev, tcp, L4_UPLOAD_REASON_UPLOAD_REQUESTED); 6001 pdev->toe_info.stats.total_big_isle_upld_requesed++; 6002 } else if (con->dpc_info.snapshot_flags & LM_TCP_DPC_TOO_MANY_ISLES) { 6003 con->dpc_info.snapshot_flags &= ~LM_TCP_DPC_TOO_MANY_ISLES; 6004 lm_tcp_process_retrieve_indication_cqe(pdev, tcp, L4_UPLOAD_REASON_UPLOAD_REQUESTED); 6005 pdev->toe_info.stats.total_many_isles_upld_requesed++; 6006 } 6007 6008 6009 if (con->dpc_info.snapshot_flags & LM_TCP_DPC_RAMROD_CMP) { 6010 con->dpc_info.snapshot_flags &= ~LM_TCP_DPC_RAMROD_CMP; 6011 DbgBreakIf(con->dpc_info.snapshot_flags != 0); 6012 /* Keep these before completing as the completion calls themselves can cause tcp state to be 6013 * deleted... */ 6014 cid = tcp->cid; 6015 ulp_type = tcp->ulp_type; 6016 switch (tcp->sp_request->type) { 6017 case SP_REQUEST_UPDATE_NEIGH: 6018 case SP_REQUEST_UPDATE_PATH: 6019 case SP_REQUEST_UPDATE_TCP: 6020 case SP_REQUEST_UPDATE_PATH_RELINK: 6021 lm_tcp_update_ramrod_complete(pdev, tcp); 6022 lm_sq_complete(pdev, CMD_PRIORITY_NORMAL, RAMROD_OPCODE_TOE_UPDATE, ulp_type, cid); 6023 return; 6024 case SP_REQUEST_QUERY: 6025 lm_tcp_query_ramrod_complete(pdev, tcp); /* this may delete tcp !! */ 6026 lm_sq_complete(pdev, CMD_PRIORITY_NORMAL, RAMROD_OPCODE_TOE_QUERY, ulp_type, cid); 6027 return; 6028 case SP_REQUEST_TERMINATE_OFFLOAD: 6029 lm_tcp_searcher_ramrod_complete(pdev, tcp); 6030 lm_sq_complete(pdev, CMD_PRIORITY_NORMAL, RAMROD_OPCODE_TOE_SEARCHER_DELETE, ulp_type, cid); 6031 return; 6032 case SP_REQUEST_INITIATE_OFFLOAD: 6033 /* Completion of initiate offload request can reach this point only if there was a license error, */ 6034 /* otherwise its being completed earlier during 'process' stage */ 6035 lm_tcp_comp_initiate_offload_request(pdev, tcp, TOE_INITIATE_OFFLOAD_RAMROD_DATA_LICENSE_FAILURE); 6036 lm_sq_complete(pdev, CMD_PRIORITY_NORMAL, RAMROD_OPCODE_TOE_INITIATE_OFFLOAD, tcp->ulp_type, cid); 6037 return; 6038 } 6039 6040 /* The rest of the ramrods on RCQ also complete on SCQ */ 6041 complete_ramrod = FALSE; 6042 MM_ACQUIRE_TOE_LOCK(pdev); 6043 6044 /* save the type under the lock because the next ramrod will change this type ????*/ 6045 sp_type = tcp->sp_request->type; 6046 MM_RELEASE_TOE_LOCK(pdev); 6047 6048 switch(sp_type) { 6049 case SP_REQUEST_ABORTIVE_DISCONNECT: 6050 lm_tcp_rx_abortive_disconnect_ramrod_complete(pdev, tcp); 6051 break; 6052 case SP_REQUEST_INVALIDATE: 6053 lm_tcp_rx_invalidate_ramrod_complete(pdev, tcp); 6054 break; 6055 case SP_REQUEST_TERMINATE1_OFFLOAD: 6056 lm_tcp_rx_terminate_ramrod_complete(pdev, tcp); 6057 break; 6058 case SP_REQUEST_PENDING_LOCAL_FIN_DISCONNECT: 6059 case SP_REQUEST_PENDING_REMOTE_DISCONNECT: 6060 case SP_REQUEST_PENDING_TX_RST: 6061 lm_tcp_rx_empty_ramrod_complete(pdev,tcp, sp_type); 6062 break; 6063 default: 6064 DbgMessage(pdev, FATAL, "unexpected sp completion type=%d\n", tcp->sp_request->type); 6065 DbgBreak(); 6066 } 6067 /* Get global TOE lock */ 6068 MM_ACQUIRE_TOE_LOCK(pdev); 6069 6070 DbgBreakIf(sp_type != tcp->sp_request->type); 6071 6072 tcp->sp_flags |= SP_REQUEST_COMPLETED_RX; 6073 6074 /* If it's a second comletion, post the query ramrod */ 6075 if ( tcp->sp_flags & SP_REQUEST_COMPLETED_TX ) { 6076 complete_ramrod = TRUE; 6077 tcp->sp_flags &= ~ ( SP_REQUEST_COMPLETED_TX | SP_REQUEST_COMPLETED_RX ); 6078 } 6079 sp_flags = tcp->sp_flags; 6080 flags = tcp->rx_con->flags; 6081 MM_RELEASE_TOE_LOCK(pdev); 6082 if (complete_ramrod) { 6083 request = tcp->sp_request; 6084 DbgBreakIf(request == NULL); 6085 switch(sp_type) { 6086 case SP_REQUEST_ABORTIVE_DISCONNECT: 6087 DbgBreakIf(request->type != SP_REQUEST_ABORTIVE_DISCONNECT); 6088 lm_tcp_comp_abortive_disconnect_request(pdev, tcp, request); 6089 lm_sq_complete(pdev, CMD_PRIORITY_NORMAL, RAMROD_OPCODE_TOE_RESET_SEND, tcp->ulp_type, tcp->cid); 6090 break; 6091 case SP_REQUEST_INVALIDATE: 6092 DbgBreakIf(request->type != SP_REQUEST_INVALIDATE); 6093 lm_tcp_comp_invalidate_request(pdev, tcp, request); 6094 lm_sq_complete(pdev, CMD_PRIORITY_NORMAL, RAMROD_OPCODE_TOE_INVALIDATE, tcp->ulp_type, tcp->cid); 6095 break; 6096 case SP_REQUEST_TERMINATE1_OFFLOAD: 6097 DbgBreakIf(request->type != SP_REQUEST_TERMINATE1_OFFLOAD); 6098 lm_tcp_terminate_ramrod_complete(pdev, tcp); 6099 lm_sq_complete(pdev, CMD_PRIORITY_NORMAL, RAMROD_OPCODE_TOE_TERMINATE, tcp->ulp_type, tcp->cid); 6100 break; 6101 case SP_REQUEST_PENDING_LOCAL_FIN_DISCONNECT: 6102 case SP_REQUEST_PENDING_REMOTE_DISCONNECT: 6103 case SP_REQUEST_PENDING_TX_RST: 6104 lm_tcp_comp_empty_ramrod_request(pdev, tcp); 6105 lm_sq_complete(pdev, CMD_PRIORITY_NORMAL, RAMROD_OPCODE_TOE_EMPTY_RAMROD, tcp->ulp_type, tcp->cid); 6106 break; 6107 default: 6108 DbgMessage(pdev, FATAL, "unexpected sp completion type=%d\n", tcp->sp_request->type); 6109 DbgBreak(); 6110 } 6111 } 6112 } 6113 } 6114 6115 #define MSL 4 /* 4 seconds */ 6116 6117 l4_tcp_con_state_t lm_tcp_calc_state ( 6118 lm_device_t * pdev, 6119 lm_tcp_state_t * tcp, 6120 u8_t fin_was_sent 6121 ) 6122 { 6123 enum { 6124 NO_CLOSE = 0, 6125 ACTIVE_CLOSE, 6126 PASSIVE_CLOSE, 6127 PASSIVE_BY_ACTIVE_CLOSE 6128 } closing_type; 6129 6130 u32_t snd_max = tcp->tcp_delegated.send_max; 6131 u32_t snd_una = tcp->tcp_delegated.send_una; 6132 u8_t con_rst = tcp->tcp_state_calc.con_rst_flag; 6133 u8_t con_upld_close = tcp->tcp_state_calc.con_upld_close_flag; 6134 u64_t fin_completed_time = tcp->tcp_state_calc.fin_completed_time; 6135 u64_t fin_reception_time = tcp->tcp_state_calc.fin_reception_time; 6136 u64_t fin_request_time = tcp->tcp_state_calc.fin_request_time; 6137 u64_t time_wait_state_entering_time = fin_completed_time > fin_reception_time ? 6138 fin_completed_time : fin_reception_time; 6139 l4_tcp_con_state_t tcp_state; 6140 6141 /* Set closing type */ 6142 closing_type = NO_CLOSE; 6143 if ( fin_reception_time == 0 ) { 6144 if ( fin_request_time > 0 ) { 6145 closing_type = ACTIVE_CLOSE; 6146 } 6147 } else if ( ( fin_reception_time < fin_request_time ) || (fin_request_time == 0) ) { 6148 closing_type = PASSIVE_CLOSE; 6149 } else if ( ( fin_reception_time >= fin_request_time ) && (fin_request_time > 0) ){ 6150 closing_type = PASSIVE_BY_ACTIVE_CLOSE; 6151 } 6152 6153 if ((con_rst) || (con_upld_close)) { 6154 tcp_state = L4_TCP_CON_STATE_CLOSED; 6155 } else if ( closing_type == NO_CLOSE ) { 6156 tcp_state = L4_TCP_CON_STATE_ESTABLISHED; 6157 } else if ( ( closing_type == ACTIVE_CLOSE ) && fin_was_sent ) { 6158 if ( snd_una == snd_max ){ 6159 tcp_state = L4_TCP_CON_STATE_FIN_WAIT2; 6160 } else { 6161 tcp_state = L4_TCP_CON_STATE_FIN_WAIT1; 6162 } 6163 } else if ( ( closing_type == PASSIVE_BY_ACTIVE_CLOSE ) && (! fin_was_sent ) ) { 6164 tcp_state = L4_TCP_CON_STATE_CLOSE_WAIT; 6165 } else if (closing_type == PASSIVE_BY_ACTIVE_CLOSE ) { 6166 if (snd_una == snd_max) { 6167 if ( mm_get_current_time(pdev) - time_wait_state_entering_time > 2*pdev->ofld_info.l4_params.ticks_per_second *MSL ) { 6168 tcp_state = L4_TCP_CON_STATE_CLOSED; 6169 } else { 6170 tcp_state = L4_TCP_CON_STATE_TIME_WAIT; 6171 } 6172 } else { 6173 tcp_state = L4_TCP_CON_STATE_CLOSING; 6174 } 6175 } else if (closing_type == PASSIVE_CLOSE ) { 6176 if ( ! fin_was_sent ) { 6177 tcp_state = L4_TCP_CON_STATE_CLOSE_WAIT; 6178 } else if ( snd_una == snd_max ) { 6179 tcp_state = L4_TCP_CON_STATE_CLOSED; 6180 } else { 6181 tcp_state = L4_TCP_CON_STATE_LAST_ACK; 6182 } 6183 } else { 6184 tcp_state = L4_TCP_CON_STATE_ESTABLISHED; 6185 } 6186 6187 return tcp_state; 6188 } 6189 6190 void lm_tcp_clear_grqs(lm_device_t * pdev) 6191 { 6192 lm_tcp_grq_t * grq; 6193 // lm_tcp_gen_buf_t * gen_buf; 6194 u8_t idx; 6195 6196 DbgBreakIf(!(pdev->params.ofld_cap & LM_OFFLOAD_CHIMNEY)); 6197 6198 /* shutdown bug - BSOD only if shutdown is not in progress */ 6199 if (!lm_reset_is_inprogress(pdev)){ 6200 DbgBreakIf(!d_list_is_empty(&pdev->toe_info.state_blk.tcp_list)); 6201 DbgBreakIf(!d_list_is_empty(&pdev->toe_info.state_blk.path_list)); 6202 DbgBreakIf(!d_list_is_empty(&pdev->toe_info.state_blk.neigh_list)); 6203 } 6204 6205 /* we need to go over all the buffers in the GRQs and return them to the pool. We also need 6206 * to clear the consumer- of the grq in the FWto make sure this grq isn't treated in the xon test. */ 6207 /* This function is called after all work - items have finished, and the driver 6208 * state is no longer running, therefore there is no risk at accessing the grqs without 6209 * a lock */ 6210 6211 if (IS_PFDEV(pdev)) { 6212 DbgBreakIf(USTORM_TOE_GRQ_CONS_PTR_LO_SIZE != 4); 6213 DbgBreakIf(USTORM_TOE_GRQ_CONS_PTR_HI_SIZE != 4); 6214 } 6215 6216 LM_TOE_FOREACH_RSS_IDX(pdev, idx) 6217 { 6218 grq = &pdev->toe_info.grqs[idx]; 6219 MM_ACQUIRE_TOE_GRQ_LOCK(pdev, idx); 6220 grq->grq_compensate_on_alloc = FALSE; 6221 MM_RELEASE_TOE_GRQ_LOCK(pdev, idx); 6222 } 6223 6224 LM_TOE_FOREACH_RSS_IDX(pdev, idx) 6225 { 6226 if (IS_PFDEV(pdev)) { 6227 /* nullify consumer pointer of all inactive GRQs (required by FW) (will override with active ones) */ 6228 LM_INTMEM_WRITE32(pdev, USTORM_TOE_GRQ_CONS_PTR_LO_OFFSET(LM_TOE_FW_RSS_ID(pdev,idx), PORT_ID(pdev)), 0, BAR_USTRORM_INTMEM); 6229 LM_INTMEM_WRITE32(pdev, USTORM_TOE_GRQ_CONS_PTR_HI_OFFSET(LM_TOE_FW_RSS_ID(pdev,idx), PORT_ID(pdev)), 0, BAR_USTRORM_INTMEM); 6230 } 6231 6232 grq = &pdev->toe_info.grqs[idx]; 6233 if (!d_list_is_empty(&grq->aux_gen_list)) { 6234 mm_tcp_return_list_of_gen_bufs(pdev, &grq->aux_gen_list, 0, NON_EXISTENT_SB_IDX); 6235 d_list_clear(&grq->aux_gen_list); 6236 } 6237 if (!d_list_is_empty(&grq->active_gen_list)) { 6238 mm_tcp_return_list_of_gen_bufs(pdev, &grq->active_gen_list, 0, NON_EXISTENT_SB_IDX); 6239 d_list_clear(&grq->active_gen_list); 6240 lm_bd_chain_reset(pdev, &grq->bd_chain); 6241 } 6242 } 6243 } 6244 6245 /** 6246 * @Description: Update TOE RSS. The origin of this call is when getting 6247 * an OS RSS update. It's actually by L2 interface and not 6248 * L4. However, the ramrods are separate for L4 + L2 due to the 6249 * assumptions by the different protocols of what the data is 6250 * in the indirection table. 6251 * 6252 * @Assumptions: Called BEFORE calling L2 6253 * enable-rss!! 6254 * 6255 * @param pdev 6256 * @param chain_indirection_table - table of TOE RCQ chain values 6257 * @param table_size - size of table above 6258 * @param enable - is this enable/disable rss if it's disable, the 6259 * table will all point to the same entry 6260 * 6261 * @return lm_status_t - PENDING is completion will arrive asyncrounoulsy 6262 * - SUCCESS if no ramrod is sent (for example table didn't change) 6263 * - FAILURE o/w 6264 */ 6265 lm_status_t lm_tcp_update_rss(struct _lm_device_t * pdev, u8_t * chain_indirection_table, 6266 u32_t table_size, u8_t enable) 6267 { 6268 struct toe_rss_update_ramrod_data *data = pdev->toe_info.rss_update_data; 6269 lm_status_t lm_status = LM_STATUS_SUCCESS; 6270 u8_t value = 0; 6271 u8_t send_ramrod = 0; 6272 u8_t rss_idx = 0; 6273 u16_t bitmap = 0; 6274 u8_t i,j; 6275 6276 /* If data is NULL (allocation failed...) we don't want to fail this operation for L2 */ 6277 if (pdev->params.l4_enable_rss == L4_RSS_DISABLED || data == NULL) 6278 { 6279 return LM_STATUS_SUCCESS; 6280 } 6281 6282 DbgBreakIf(pdev->params.l4_enable_rss != L4_RSS_DYNAMIC); 6283 6284 if (enable) 6285 { 6286 if (pdev->params.l4_grq_page_cnt > 2) 6287 { 6288 LM_TOE_FOREACH_RSS_IDX(pdev, rss_idx) 6289 { 6290 pdev->toe_info.grqs[rss_idx].high_bds_threshold = 2 * 512; 6291 } 6292 } 6293 } 6294 else 6295 { 6296 pdev->toe_info.grqs[LM_TOE_BASE_RSS_ID(pdev)].high_bds_threshold = 0; 6297 } 6298 6299 6300 for (j = 0; j < TOE_INDIRECTION_TABLE_SIZE/table_size; j++) 6301 { 6302 for (i = 0; i < table_size; i++) 6303 { 6304 value = LM_TOE_FW_RSS_ID(pdev,chain_indirection_table[i]); 6305 6306 if (pdev->toe_info.indirection_table[(j*table_size)+i] != value) { 6307 pdev->toe_info.indirection_table[(j*table_size)+i] = value; 6308 send_ramrod = TRUE; 6309 } 6310 } 6311 } 6312 6313 /* send update ramrod */ 6314 if (send_ramrod) 6315 { 6316 pdev->params.update_comp_cnt = 0; 6317 pdev->params.update_suspend_cnt = 0; 6318 pdev->params.update_toe_comp_cnt = 0; /* We need a separate one for TOE to determine when to update sq credit */ 6319 6320 /* 2 global update counters : 6321 * update_comp_cnt - Set initialy to the number of expected completions, decrmented every time an update completion is processed. 6322 * The processing for all chains is suspended until this counter gets to 0. 6323 * update_suspend_cnt - Set initialy to the number of potentially suspended chains. Decremented when each chain resumes processing. The ramrod completion 6324 * is indicated back only when this counter gets to 0. 6325 * 6326 * The update ramrod is 1 pending so we can access the completion and suspend counters here and below without grabbing a lock 6327 */ 6328 6329 /* Update once for Eth... */ 6330 pdev->params.update_comp_cnt++; 6331 pdev->params.update_suspend_cnt++; 6332 6333 6334 /* TODO: Enhancment, send only on the chains that take part, and the ones removed... */ 6335 LM_TOE_FOREACH_RSS_IDX(pdev, rss_idx) 6336 { 6337 bitmap |= (1<<LM_TOE_FW_RSS_ID(pdev,rss_idx)); 6338 } 6339 6340 mm_memcpy(data->indirection_table, pdev->toe_info.indirection_table, sizeof(data->indirection_table)); 6341 data->toe_rss_bitmap = bitmap; 6342 6343 pdev->params.update_comp_cnt += pdev->params.l4_rss_chain_cnt; 6344 pdev->params.update_suspend_cnt += pdev->params.l4_rss_chain_cnt; 6345 pdev->params.update_toe_comp_cnt = pdev->params.l4_rss_chain_cnt; /* TOE only! */ 6346 6347 lm_status = lm_command_post(pdev, 6348 LM_TOE_FW_RSS_ID(pdev, LM_TOE_BASE_RSS_ID(pdev)), 6349 RAMROD_OPCODE_TOE_RSS_UPDATE, 6350 CMD_PRIORITY_MEDIUM, 6351 TOE_CONNECTION_TYPE, 6352 pdev->toe_info.rss_update_data_phys.as_u64); 6353 6354 if (lm_status == LM_STATUS_SUCCESS) 6355 { 6356 lm_status = LM_STATUS_PENDING; 6357 } 6358 } 6359 6360 return lm_status; 6361 } 6362 6363 6364 /** Description 6365 * function is called whenever the UM allocates more generic buffers 6366 */ 6367 void lm_tcp_rx_gen_bufs_alloc_cb(lm_device_t * pdev) 6368 { 6369 u8_t i; 6370 6371 LM_TOE_FOREACH_RSS_IDX(pdev, i) 6372 { 6373 6374 lm_tcp_grq_t *grq = &pdev->toe_info.grqs[i]; 6375 MM_ACQUIRE_TOE_GRQ_LOCK(pdev, i); 6376 if (grq->grq_compensate_on_alloc) { 6377 /* fill GRQ */ 6378 if (lm_tcp_rx_fill_grq(pdev, i, NULL, FILL_GRQ_LOW_THRESHOLD)) { 6379 DbgMessage(pdev, INFORMl4rx, "lm_toe_service_rx_intr: Updating GRQ producer\n"); 6380 /* notify the fw of the prod of the GRQ */ 6381 LM_INTMEM_WRITE16(pdev, USTORM_TOE_GRQ_PROD_OFFSET(LM_TOE_FW_RSS_ID(pdev,i), PORT_ID(pdev)), 6382 lm_bd_chain_prod_idx(&pdev->toe_info.grqs[i].bd_chain), BAR_USTRORM_INTMEM); 6383 } 6384 } 6385 MM_RELEASE_TOE_GRQ_LOCK(pdev, i); 6386 } 6387 } 6388 6389 void lm_tcp_update_isles_cnts(struct _lm_device_t * pdev, s16_t number_of_isles, s32_t number_of_gen_bufs) 6390 { 6391 lm_toe_isles_t *archipelago = &pdev->toe_info.archipelago; 6392 6393 pdev->toe_info.archipelago.number_of_isles += number_of_isles; 6394 pdev->toe_info.archipelago.gen_bufs_in_isles += number_of_gen_bufs; 6395 if (archipelago->number_of_isles > archipelago->max_number_of_isles) { 6396 archipelago->max_number_of_isles = archipelago->number_of_isles; 6397 } 6398 6399 if (archipelago->gen_bufs_in_isles > archipelago->max_gen_bufs_in_isles) { 6400 archipelago->max_gen_bufs_in_isles = archipelago->gen_bufs_in_isles; 6401 } 6402 if (pdev->params.l4_max_gen_bufs_in_archipelago 6403 && (archipelago->gen_bufs_in_isles > (s32_t)pdev->params.l4_max_gen_bufs_in_archipelago)) { 6404 if (pdev->params.l4_limit_isles & L4_LI_NOTIFY) { 6405 DbgBreak(); 6406 } 6407 if (pdev->params.l4_limit_isles & L4_LI_MAX_GEN_BUFS_IN_ARCHIPELAGO) { 6408 pdev->toe_info.archipelago.l4_decrease_archipelago = TRUE; 6409 } 6410 } else if (pdev->toe_info.archipelago.l4_decrease_archipelago) { 6411 if (archipelago->gen_bufs_in_isles <= (s32_t)pdev->params.l4_valid_gen_bufs_in_archipelago) { 6412 pdev->toe_info.archipelago.l4_decrease_archipelago = FALSE; 6413 } 6414 } 6415 6416 } 6417 6418 void lm_tcp_init_num_of_blocks_per_connection( 6419 struct _lm_device_t *pdev, 6420 u8_t num) 6421 { 6422 pdev->params.l4_num_of_blocks_per_connection = num; 6423 } 6424 6425 u8_t lm_tcp_get_num_of_blocks_per_connection( 6426 struct _lm_device_t *pdev) 6427 { 6428 return pdev->params.l4_num_of_blocks_per_connection; 6429 } 6430 6431 lm_neigh_state_t * lm_tcp_get_next_neigh( 6432 struct _lm_device_t *pdev, 6433 lm_neigh_state_t * neigh_state) 6434 { 6435 if (neigh_state == NULL) { 6436 neigh_state = (lm_neigh_state_t *) d_list_peek_head(&pdev->toe_info.state_blk.neigh_list); 6437 } else { 6438 neigh_state = (lm_neigh_state_t *) d_list_next_entry(&neigh_state->hdr.link); 6439 } 6440 return neigh_state; 6441 } 6442 6443 lm_path_state_t * lm_tcp_get_next_path( 6444 struct _lm_device_t *pdev, 6445 lm_neigh_state_t * neigh_state, 6446 lm_path_state_t * path_state) 6447 { 6448 if (path_state == NULL) { 6449 path_state = (lm_path_state_t *) d_list_peek_head(&pdev->toe_info.state_blk.path_list); 6450 } else { 6451 path_state = (lm_path_state_t *) d_list_next_entry(&path_state->hdr.link); 6452 } 6453 6454 if (neigh_state != NULL) { 6455 while(path_state) { 6456 if (path_state->neigh == neigh_state) { 6457 return path_state; 6458 } 6459 path_state = (lm_path_state_t *) d_list_next_entry(&path_state->hdr.link); 6460 } 6461 } 6462 return path_state; 6463 } 6464 6465 lm_tcp_state_t * lm_tcp_get_next_tcp( 6466 struct _lm_device_t *pdev, 6467 lm_tcp_state_t * tcp_state) 6468 { 6469 if (tcp_state == NULL) { 6470 tcp_state = (lm_tcp_state_t *) d_list_peek_head(&pdev->toe_info.state_blk.tcp_list); 6471 } else { 6472 tcp_state = (lm_tcp_state_t *) d_list_next_entry(&tcp_state->hdr.link); 6473 } 6474 return tcp_state; 6475 } 6476 6477 u8_t lm_tcp_get_src_ip_cam_byte( 6478 IN struct _lm_device_t * pdev, 6479 IN lm_path_state_t * path) 6480 { 6481 u8_t src_ip_byte; 6482 6483 DbgBreakIf(!(pdev && path)); 6484 6485 if (path->path_const.ip_version == IP_VERSION_IPV4) { 6486 src_ip_byte = path->path_const.u.ipv4.src_ip & 0x000000FF; 6487 } else { 6488 src_ip_byte = path->path_const.u.ipv6.src_ip[0] & 0x000000FF; 6489 } 6490 return src_ip_byte; 6491 } 6492 6493 lm_tcp_state_t* lm_tcp_find_offloaded_tcp_tuple(struct _lm_device_t * pdev, u8_t src_ip_byte, u8_t src_tcp_b, u8_t dst_tcp_b, lm_tcp_state_t * prev_tcp) 6494 { 6495 lm_tcp_state_t *connection_found = NULL; 6496 lm_tcp_state_t *current_tcp = NULL; 6497 6498 while ((current_tcp = lm_tcp_get_next_tcp(pdev, prev_tcp))) { 6499 u8_t c_src_tcp_b; 6500 u8_t c_dst_tcp_b; 6501 prev_tcp = current_tcp; 6502 c_src_tcp_b = current_tcp->tcp_const.src_port & 0x00FF; 6503 c_dst_tcp_b = current_tcp->tcp_const.dst_port & 0x00FF; 6504 if ((c_src_tcp_b == src_tcp_b) && (c_dst_tcp_b == dst_tcp_b)) { 6505 if ((current_tcp->path == NULL) || (lm_tcp_get_src_ip_cam_byte(pdev,current_tcp->path) == src_ip_byte)) { 6506 connection_found = current_tcp; 6507 break; 6508 } 6509 } 6510 } 6511 6512 return connection_found; 6513 } 6514 6515 u8_t * lm_tcp_get_pattern(struct _lm_device_t * pdev, 6516 lm_tcp_state_t * tcp, 6517 u8_t pattern_idx, 6518 u32_t offset, 6519 u32_t * pattern_size) 6520 { 6521 offset = tcp->integrity_info.current_offset_in_pattern_buf[pattern_idx] + offset; 6522 offset = offset % pdev->toe_info.integrity_info.pattern_size; 6523 if (*pattern_size > (pdev->toe_info.integrity_info.pattern_buf_size - pdev->toe_info.integrity_info.pattern_size)) { 6524 *pattern_size = pdev->toe_info.integrity_info.pattern_buf_size - pdev->toe_info.integrity_info.pattern_size; 6525 } 6526 return (pdev->toe_info.integrity_info.pattern_buf + offset); 6527 } 6528 6529 void lm_tcp_set_pattern_offset(struct _lm_device_t * pdev, 6530 lm_tcp_state_t * tcp, 6531 u8_t pattern_idx, 6532 u32_t offset) 6533 { 6534 tcp->integrity_info.current_offset_in_pattern_buf[pattern_idx] += offset; 6535 tcp->integrity_info.current_offset_in_pattern_buf[pattern_idx] = 6536 tcp->integrity_info.current_offset_in_pattern_buf[pattern_idx] % pdev->toe_info.integrity_info.pattern_size; 6537 6538 return; 6539 } 6540 6541 u32_t lm_tcp_find_pattern_offset(struct _lm_device_t * pdev, u8_t * sub_buf, u32_t sub_buf_size) 6542 { 6543 u32_t i,j; 6544 for (j = 0; j < pdev->toe_info.integrity_info.pattern_size; j++) { 6545 for (i = 0; i < sub_buf_size; i++) { 6546 if (sub_buf[i] != pdev->toe_info.integrity_info.pattern_buf[j+i]) { 6547 break; 6548 } 6549 } 6550 if (i == sub_buf_size) { 6551 return j; 6552 } 6553 } 6554 return 0xFFFFFFFF; 6555 } 6556