1 2 /* 3 functions for managing Chip per-connection context 4 */ 5 #include "context.h" 6 #include "command.h" 7 #include "cdu_def.h" 8 #include "bd_chain.h" 9 10 /* returns a pionter to a connections chip context*/ 11 void * lm_get_context(struct _lm_device_t *pdev, u32_t cid){ 12 13 void * ret = NULL; 14 u32_t page,off; 15 16 DbgBreakIf(cid > pdev->params.max_func_connections); 17 DbgBreakIf(pdev->context_info->array[cid].invalid != LM_CONTEXT_VALID); 18 19 /* calculate which context page the CID is on*/ 20 page = cid / (pdev->params.num_context_in_page); 21 22 /* calculate at what offset inside the page CID is on*/ 23 off = cid % (pdev->params.num_context_in_page); 24 25 /* now goto page,off */ 26 ret = (void*)((char*)pdev->vars.context_cdu_virt_addr_table[page] + (pdev->params.context_line_size * off)); 27 /* warrning, this assumes context line size is in chars, need to check!!!*/ 28 29 return ret; 30 } 31 32 /* same as above but returns phys address in 64 bit pointer */ 33 u64_t lm_get_context_phys(struct _lm_device_t *pdev, u32_t cid){ 34 35 u64_t ret = 0; 36 u32_t page,off; 37 38 DbgBreakIf(cid > pdev->params.max_func_connections); 39 DbgBreakIf(pdev->context_info->array[cid].invalid != LM_CONTEXT_VALID); 40 41 /* calculate which context page the CID is on*/ 42 page = cid / (pdev->params.num_context_in_page); 43 44 /* calculate at what offset inside the page CID is on*/ 45 off = cid % (pdev->params.num_context_in_page); 46 47 /* now goto page,off */ 48 ret = (pdev->vars.context_cdu_phys_addr_table[page].as_u64 + (pdev->params.context_line_size * off)); 49 /* warrning, this assumes context line size is in chars, need to check!!!*/ 50 51 return ret; 52 } 53 54 extern u32_t LOG2(u32_t v); 55 static lm_status_t lm_setup_searcher_hash_info(struct _lm_device_t *pdev) 56 { 57 u32_t num_con = 0 ; 58 u32_t alloc_size = 0 ; 59 lm_context_info_t* context = NULL; 60 lm_searcher_hash_info_t* hash_info = NULL; 61 int offset = 0 ; 62 63 /* sanity */ 64 if ( CHK_NULL(pdev) || CHK_NULL( pdev->context_info ) ) 65 { 66 DbgBreakMsg("Invalid Parameters") ; 67 return LM_STATUS_INVALID_PARAMETER ; 68 } 69 context = pdev->context_info; 70 hash_info = &context->searcher_hash; 71 72 DbgBreakIf(!pdev->params.max_func_connections); 73 74 if CHK_NULL( hash_info->searcher_table) 75 { 76 DbgBreakIf(!( hash_info->searcher_table)); 77 return LM_STATUS_FAILURE; 78 } 79 num_con = pdev->params.max_func_connections; 80 alloc_size = sizeof(lm_searcher_hash_entry_t) * num_con; 81 mm_mem_zero(hash_info->searcher_table, alloc_size); 82 83 /* init value for searcher key */ 84 // TODO: for now a fixed key, need to change at runtime 85 *(u32_t *)(&hash_info->searcher_key[0]) = 0x63285672; 86 *(u32_t *)(&hash_info->searcher_key[4]) = 0x24B8F2CC; 87 *(u32_t *)(&hash_info->searcher_key[8]) = 0x223AEF9B; 88 *(u32_t *)(&hash_info->searcher_key[12]) = 0x26001E3A; 89 *(u32_t *)(&hash_info->searcher_key[16]) = 0x7AE91116; 90 *(u32_t *)(&hash_info->searcher_key[20]) = 0x5CE5230B; 91 *(u32_t *)(&hash_info->searcher_key[24]) = 0x298D8ADF; 92 *(u32_t *)(&hash_info->searcher_key[28]) = 0x6EB0FF09; 93 *(u32_t *)(&hash_info->searcher_key[32]) = 0x1830F82F; 94 *(u32_t *)(&hash_info->searcher_key[36]) = 0x1E46BE7; 95 96 /* Microsoft's example key */ 97 // *(u32_t *)(&hash_info->searcher_key[0]) = 0xda565a6d; 98 // *(u32_t *)(&hash_info->searcher_key[4]) = 0xc20e5b25; 99 // *(u32_t *)(&hash_info->searcher_key[8]) = 0x3d256741; 100 // *(u32_t *)(&hash_info->searcher_key[12]) = 0xb08fa343; 101 // *(u32_t *)(&hash_info->searcher_key[16]) = 0xcb2bcad0; 102 // *(u32_t *)(&hash_info->searcher_key[20]) = 0xb4307bae; 103 // *(u32_t *)(&hash_info->searcher_key[24]) = 0xa32dcb77; 104 // *(u32_t *)(&hash_info->searcher_key[28]) = 0x0cf23080; 105 // *(u32_t *)(&hash_info->searcher_key[32]) = 0x3bb7426a; 106 // *(u32_t *)(&hash_info->searcher_key[36]) = 0xfa01acbe; 107 108 /* init searcher_key_bits array */ 109 for (offset = 0; offset < 10; offset++) 110 { 111 int j,k; 112 u32_t bitsOffset = 32*offset; 113 u8_t _byte; 114 115 for (j= 0; j < 4; j++) 116 { 117 _byte = (u8_t)((*(u32_t *)(&hash_info->searcher_key[offset*4]) >> (j*8)) & 0xff); 118 for (k = 0; k < 8; k++) 119 { 120 hash_info->searcher_key_bits[bitsOffset+(j*8)+k] = ((_byte<<(k%8))& 0x80) ? 1 : 0; 121 } 122 } 123 } 124 125 /* init value for num hash bits */ 126 hash_info->num_hash_bits = (u8_t)LOG2(num_con); 127 128 return LM_STATUS_SUCCESS ; 129 } 130 131 static lm_status_t lm_alloc_searcher_hash_info(struct _lm_device_t *pdev) 132 { 133 u32_t num_con = 0 ; 134 u32_t alloc_size = 0 ; 135 lm_searcher_hash_info_t* hash_info = NULL ; 136 u8_t mm_cli_idx = 0 ; 137 138 if CHK_NULL(pdev) 139 { 140 return LM_STATUS_INVALID_PARAMETER ; 141 } 142 143 mm_cli_idx = LM_RESOURCE_COMMON;//!!DP mm_cli_idx_to_um_idx(LM_CLI_IDX_MAX); 144 145 /* searcher is defined with per-function #connections */ 146 num_con = pdev->params.max_func_connections; 147 alloc_size = sizeof(lm_searcher_hash_entry_t) * num_con; 148 149 hash_info = &pdev->context_info->searcher_hash; 150 151 if CHK_NULL(hash_info) 152 { 153 return LM_STATUS_INVALID_PARAMETER ; 154 } 155 156 /* allocate searcher mirror hash table */ 157 hash_info->searcher_table = mm_alloc_mem(pdev, alloc_size, mm_cli_idx); 158 159 if CHK_NULL( hash_info->searcher_table ) 160 { 161 DbgBreakIf(DBG_BREAK_ON(MEMORY_ALLOCATION_FAILURE)); 162 return LM_STATUS_RESOURCE ; 163 } 164 return LM_STATUS_SUCCESS ; 165 } 166 167 lm_status_t lm_init_cid_resc(struct _lm_device_t *pdev, u32_t cid) 168 { 169 lm_cid_resc_t *cid_resc = NULL; 170 int i = 0; 171 172 if CHK_NULL(pdev) 173 { 174 return LM_STATUS_INVALID_PARAMETER; 175 } 176 177 cid_resc = &pdev->context_info->array[cid].cid_resc; 178 if CHK_NULL(cid_resc) 179 { 180 return LM_STATUS_INVALID_PARAMETER; 181 } 182 183 for (i = 0; i < ARRSIZE(cid_resc->cookies); i++) 184 { 185 cid_resc->cookies[i] = NULL; 186 } 187 188 cid_resc->cid_pending = LM_CID_STATE_VALID; 189 lm_sp_req_manager_init(pdev, cid); 190 191 return LM_STATUS_SUCCESS; 192 } 193 194 lm_status_t lm_setup_context_pool(struct _lm_device_t *pdev) 195 { 196 u32_t num_con = 0; 197 lm_context_info_t * context = NULL ; 198 u32_t i,j; 199 struct lm_context_cookie* array = NULL ; 200 lm_searcher_hash_entry_t* searcher_table = NULL ; 201 202 if CHK_NULL(pdev) 203 { 204 DbgBreakIf(!pdev); 205 return LM_STATUS_INVALID_PARAMETER; 206 } 207 208 context = pdev->context_info; 209 210 if CHK_NULL(context) 211 { 212 DbgBreakIf( context == NULL ); 213 return LM_STATUS_INVALID_PARAMETER; 214 } 215 216 num_con = pdev->params.max_func_connections; 217 218 array = context->array ; 219 searcher_table = context->searcher_hash.searcher_table ; 220 221 mm_mem_zero( context, sizeof(lm_context_info_t) ) ; 222 223 context->array = array ; 224 context->searcher_hash.searcher_table = searcher_table ; 225 226 context->proto_start[ETH_CONNECTION_TYPE] = 0; 227 context->proto_end [ETH_CONNECTION_TYPE] = pdev->params.max_eth_including_vfs_conns - 1; 228 context->proto_start[TOE_CONNECTION_TYPE] = context->proto_end [ETH_CONNECTION_TYPE] + 1; 229 context->proto_end [TOE_CONNECTION_TYPE] = context->proto_start[TOE_CONNECTION_TYPE] + pdev->params.max_func_toe_cons - 1; 230 context->proto_start[RDMA_CONNECTION_TYPE] = context->proto_end [TOE_CONNECTION_TYPE] + 1; 231 context->proto_end [RDMA_CONNECTION_TYPE] = context->proto_start[RDMA_CONNECTION_TYPE] + pdev->params.max_func_rdma_cons - 1; 232 context->proto_start[ISCSI_CONNECTION_TYPE] = context->proto_end [RDMA_CONNECTION_TYPE] + 1; 233 context->proto_end [ISCSI_CONNECTION_TYPE] = context->proto_start[ISCSI_CONNECTION_TYPE] + pdev->params.max_func_iscsi_cons - 1; 234 context->proto_start[FCOE_CONNECTION_TYPE] = context->proto_end [ISCSI_CONNECTION_TYPE] + 1; 235 context->proto_end [FCOE_CONNECTION_TYPE] = context->proto_start[FCOE_CONNECTION_TYPE] + pdev->params.max_func_fcoe_cons - 1; 236 DbgBreakIf(context->proto_end[MAX_PROTO - 1] > pdev->params.max_func_connections -1); 237 238 if CHK_NULL(context->array) 239 { 240 DbgBreakIf(!( context->array)); 241 return LM_STATUS_INVALID_PARAMETER; 242 } 243 244 mm_mem_zero(context->array, sizeof(struct lm_context_cookie)*num_con); 245 246 ASSERT_STATIC( ARRSIZE(context->proto_start) == ARRSIZE(context->proto_end) ); 247 248 /* zero cookies and populate the free lists */ 249 for (i = 0; i < ARRSIZE(context->proto_start); i++ ) 250 { 251 for (j = context->proto_start[i]; j <= context->proto_end[i]; j++) 252 { 253 context->array[j].next = j+1; 254 context->array[j].invalid = LM_CONTEXT_VALID; 255 context->array[j].ip_type = 0; 256 context->array[j].h_val = 0; 257 lm_init_cid_resc(pdev, j); 258 } 259 /* set the first free item if max_func_XX_cons > 0 */ 260 if (context->proto_start[i] <= context->proto_end[i]) { 261 context->proto_ffree[i] = context->proto_start[i]; 262 } 263 else 264 { 265 context->proto_ffree[i] = 0; 266 } 267 context->proto_pending[i] = 0; 268 /* put 0 (end of freelist in the last entry for the proto */ 269 context->array[context->proto_end[i]].next = 0; 270 } 271 //The ETH cid doorbell space was remapped just fixing the pointers. 272 for (j = context->proto_start[ETH_CONNECTION_TYPE]; j <= context->proto_end[ETH_CONNECTION_TYPE]; j++) 273 { 274 #ifdef VF_INVOLVED 275 if (IS_CHANNEL_VFDEV(pdev)) { 276 context->array[j].cid_resc.mapped_cid_bar_addr = 277 (volatile void *)((u8_t*)pdev->vars.mapped_bar_addr[BAR_0] + j*lm_vf_get_doorbell_size(pdev) + VF_BAR0_DB_OFFSET); 278 #ifdef __SunOS 279 context->array[j].cid_resc.reg_handle = pdev->vars.reg_handle[BAR_0]; 280 #endif /* __SunOS */ 281 } else 282 #endif /* VF_INVOLVED */ 283 { 284 context->array[j].cid_resc.mapped_cid_bar_addr = 285 (volatile void *)((u8_t*)pdev->vars.mapped_bar_addr[BAR_1] + j*LM_DQ_CID_SIZE); 286 #ifdef __SunOS 287 context->array[j].cid_resc.reg_handle = pdev->vars.reg_handle[BAR_1]; 288 #endif /* __SunOS */ 289 } 290 } 291 return lm_setup_searcher_hash_info(pdev) ; 292 } 293 294 /* context pool initializer */ 295 lm_status_t lm_alloc_context_pool(struct _lm_device_t *pdev){ 296 297 u32_t num_con = 0 ; 298 lm_context_info_t * context = NULL ; 299 u8_t mm_cli_idx = 0; 300 301 if CHK_NULL(pdev) 302 { 303 DbgBreakIf(!pdev); 304 return LM_STATUS_INVALID_PARAMETER ; 305 } 306 307 /* must not be called if allready initialized */ 308 if ERR_IF( NULL != pdev->context_info ) 309 { 310 DbgBreakIf( pdev->context_info != NULL ) ; 311 return LM_STATUS_FAILURE ; 312 } 313 314 mm_cli_idx = LM_RESOURCE_COMMON;//!!DP mm_cli_idx_to_um_idx(LM_CLI_IDX_MAX); 315 316 /* number of context is per-function, the cdu has a per-port register that can be set to be higher than the max_func_connections, but 317 * the amount of memory actually allocated for the CDU matches max_func_connections. */ 318 num_con = pdev->params.max_func_connections ; 319 320 /* allocate context info and cookie array */ 321 context = mm_alloc_mem(pdev, sizeof(lm_context_info_t), mm_cli_idx); 322 if CHK_NULL(context) 323 { 324 DbgBreakIf(DBG_BREAK_ON(MEMORY_ALLOCATION_FAILURE)); 325 return LM_STATUS_RESOURCE ; 326 } 327 328 /* allocate list entries */ 329 context->array = mm_alloc_mem(pdev, sizeof(struct lm_context_cookie)*num_con, mm_cli_idx); 330 if CHK_NULL(context->array) 331 { 332 DbgBreakIf(DBG_BREAK_ON(MEMORY_ALLOCATION_FAILURE)); 333 return LM_STATUS_RESOURCE ; 334 } 335 336 /* initilize the lock */ 337 338 /* put the context where it belongs */ 339 pdev->context_info = context; 340 341 /* init searcher hash info */ 342 return lm_alloc_searcher_hash_info(pdev); 343 /* return success */ 344 } 345 346 /* context pool release function */ 347 void lm_release_context_pool(struct _lm_device_t *pdev){ 348 349 lm_context_info_t* context = NULL; 350 u32_t i, j; 351 352 /* must only be called if initialized */ 353 DbgBreakIf( pdev->context_info == NULL ); 354 355 /* first make a copy and kill the original refference */ 356 context = pdev->context_info; 357 pdev->context_info = NULL; 358 359 /* free context cookie array 360 sanity check: scan it and make sure it is empty */ 361 for (i=0; i<(pdev->params.max_func_connections); i++ ) 362 { 363 for (j = 0; j < MAX_PROTO; j++) 364 { 365 DbgBreakIf( context->array[i].cid_resc.cookies[j] != NULL ); 366 } 367 368 /* NirV: can't call from here, context_info is NULL */ 369 /*DbgBreakIf(lm_sp_req_manager_shutdown(pdev, i) != LM_STATUS_SUCCESS);*/ 370 } 371 /* mm_free_mem(context->array); */ 372 373 /* sanity check - searcher mirror hash must be empty */ 374 DbgBreakIf(context->searcher_hash.num_tuples); 375 376 /* de-initilize the lock? if in debug mode we can leave it taken to chatch errors */ 377 378 /* free context info */ 379 /* mm_free_mem(context); */ 380 381 382 /* return success */ 383 384 } 385 386 static u32_t _lm_searcher_mirror_hash_calc(lm_searcher_hash_info_t *hash_info, lm_4tuple_t *tuple) 387 { 388 u8_t in_str[MAX_SEARCHER_IN_STR] = {0}; 389 u8_t* in_str_bits = hash_info->searcher_in_str_bits; 390 u8_t* key_bits = hash_info->searcher_key_bits; 391 u32_t in_bits = 0; 392 u32_t result = 0; 393 u16_t i = 0; 394 u16_t j = 0; 395 396 /* prepare input string */ 397 if (tuple->ip_type == LM_IP_TYPE_V4) 398 { 399 *(u32_t *)(&in_str[0]) = HTON32(tuple->src_ip[0]); 400 *(u32_t *)(&in_str[4]) = HTON32(tuple->dst_ip[0]); 401 *(u16_t *)(&in_str[8]) = tuple->src_port; 402 *(u16_t *)(&in_str[10]) = tuple->dst_port; 403 in_bits = 12 * 8; 404 } 405 else 406 { 407 *(u32_t *)(&in_str[0]) = HTON32(tuple->src_ip[0]); 408 *(u32_t *)(&in_str[4]) = HTON32(tuple->src_ip[1]); 409 *(u32_t *)(&in_str[8]) = HTON32(tuple->src_ip[2]); 410 *(u32_t *)(&in_str[12]) = HTON32(tuple->src_ip[3]); 411 412 *(u32_t *)(&in_str[16]) = HTON32(tuple->dst_ip[0]); 413 *(u32_t *)(&in_str[20]) = HTON32(tuple->dst_ip[1]); 414 *(u32_t *)(&in_str[24]) = HTON32(tuple->dst_ip[2]); 415 *(u32_t *)(&in_str[28]) = HTON32(tuple->dst_ip[3]); 416 417 *(u16_t *)(&in_str[32]) = tuple->src_port; 418 *(u16_t *)(&in_str[34]) = tuple->dst_port; 419 in_bits = 36 * 8; 420 } 421 422 /* prepare searcher_in_str_bits from in_str */ 423 for (i = 0; i < in_bits; i++) 424 { 425 /* 0x80 - the leftmost bit. */ 426 in_str_bits[i] = ((in_str[i/8]<<(i%8)) & 0x80) ? 1 : 0; 427 } 428 429 /* calc ToeplitzHash */ 430 for (i = 0; i < 32; i++) 431 { 432 u8_t h = 0; 433 434 for (j = 0; j < in_bits; j++) 435 { 436 h ^= key_bits[i+j] & in_str_bits[j]; 437 } 438 439 result |= (h<<(32-i-1)); 440 } 441 442 return result; 443 } 444 445 /* assumption: CID lock NOT taken by caller */ 446 lm_status_t lm_searcher_mirror_hash_insert(struct _lm_device_t *pdev, u32_t cid, lm_4tuple_t *tuple) 447 { 448 lm_context_info_t *context = NULL; 449 lm_searcher_hash_entry_t *hash_entry = NULL; 450 u32_t h_val = 0; 451 u8_t temp_ipv6, temp_ipv4, temp_depth_ipv4, is_ipv4; 452 lm_status_t lm_status = LM_STATUS_SUCCESS; 453 #define SRC_HASH_DEPTH_TH 15 /* that is searcher's default MaxNumHops - 1 */ 454 455 /* take spinlock */ 456 MM_ACQUIRE_CID_LOCK(pdev); 457 458 context = pdev->context_info; 459 is_ipv4 = (tuple->ip_type == LM_IP_TYPE_V4 ? 1 : 0); 460 461 /* calc hash val */ 462 h_val = _lm_searcher_mirror_hash_calc(&context->searcher_hash, tuple); 463 464 /* take only num_hash_bits LSBs */ 465 h_val &= ((1 << context->searcher_hash.num_hash_bits) - 1); 466 467 /* init num_hash_bits in the searcher: if the h_val is all FFFFs - set it to 0 */ 468 if (h_val == ((1 << context->searcher_hash.num_hash_bits) - 1)) { 469 h_val = 0; 470 } 471 472 /* get the hash entry */ 473 hash_entry = &context->searcher_hash.searcher_table[h_val]; 474 475 /* start the alg. to find if there is a place available in that entry */ 476 temp_ipv6 = hash_entry->num_ipv6 + (is_ipv4 ? 0 : 1); 477 temp_ipv4 = hash_entry->num_ipv4 + is_ipv4; 478 479 /* tempDepthIpv4 = max ( depthIpv4(H), roundup(tempIpv4/2) ) */ 480 temp_depth_ipv4 = (temp_ipv4 / 2) + (temp_ipv4 % 2); 481 if (temp_depth_ipv4 < hash_entry->depth_ipv4) { 482 temp_depth_ipv4 = hash_entry->depth_ipv4; 483 } 484 485 if (temp_depth_ipv4 + temp_ipv6 > SRC_HASH_DEPTH_TH) { 486 /* each hash entry has SRC_HASH_DEPTH_TH available places. 487 * each place can contain 1 ipv6 connection or 2 ipv4 connections */ 488 DbgBreakMsg("Reached searcher hash limit\n"); 489 lm_status = LM_STATUS_FAILURE; 490 } else { 491 hash_entry->num_ipv6 = temp_ipv6; 492 hash_entry->num_ipv4 = temp_ipv4; 493 hash_entry->depth_ipv4 = temp_depth_ipv4; 494 495 /* for debug, save the max depth reached */ 496 if (context->searcher_hash.hash_depth_reached < hash_entry->depth_ipv4 + hash_entry->num_ipv6) { 497 context->searcher_hash.hash_depth_reached = hash_entry->depth_ipv4 + hash_entry->num_ipv6; 498 } 499 context->searcher_hash.num_tuples++; 500 501 /* remeber the IP type and h_val to know where and how much 502 * to decrease upon CID recycling */ 503 DbgBreakIf(context->array[cid].ip_type); /* cid can't be inserted twice */ 504 context->array[cid].ip_type = tuple->ip_type; 505 context->array[cid].h_val = h_val; 506 } 507 508 /* release spinlock */ 509 MM_RELEASE_CID_LOCK(pdev); 510 511 return lm_status; 512 } 513 514 /* assumption: CID lock NOT taken by caller */ 515 void lm_searcher_mirror_hash_remove(struct _lm_device_t *pdev, u32_t cid) 516 { 517 lm_context_info_t *context = NULL; 518 lm_searcher_hash_entry_t *hash_entry = NULL; 519 u32_t h_val = 0; 520 521 /* take spinlock */ 522 MM_ACQUIRE_CID_LOCK(pdev); 523 524 context = pdev->context_info; 525 526 if(!context->array[cid].ip_type) { 527 /* i.e lm_searcher_mirror_hash_insert was not called for this cid */ 528 DbgMessage(pdev, WARN, 529 "not removing CID %d from SRC hash (hash insert was not called for this cid)\n" 530 ,cid); 531 532 /* release spinlock */ 533 MM_RELEASE_CID_LOCK(pdev); 534 535 return; 536 } 537 538 h_val = context->array[cid].h_val; 539 hash_entry = &context->searcher_hash.searcher_table[h_val]; 540 541 if (context->array[cid].ip_type == LM_IP_TYPE_V6) { 542 DbgBreakIf(!hash_entry->num_ipv6); 543 hash_entry->num_ipv6--; 544 } 545 else 546 { 547 DbgBreakIf(!hash_entry->num_ipv4); 548 hash_entry->num_ipv4--; 549 if (hash_entry->num_ipv4 < hash_entry->depth_ipv4) 550 { 551 hash_entry->depth_ipv4 = hash_entry->num_ipv4; 552 } 553 } 554 555 /* for debug */ 556 context->searcher_hash.num_tuples--; 557 558 /* clear the entry of the context */ 559 context->array[cid].ip_type = 0; 560 context->array[cid].h_val = 0; 561 562 /* release spinlock */ 563 MM_RELEASE_CID_LOCK(pdev); 564 } 565 566 /* allocate a free context by type 567 returns CID in the out_cid param 568 return LM_STATUS_SUCCESS for available cid 569 LM_STATUS_RESOURCE if no cids are available 570 LM_STATUS_PENDING if there is a pending cfc-delete cid 571 takes the list spinlock */ 572 lm_status_t lm_allocate_cid(struct _lm_device_t *pdev, u32_t type, void * cookie, s32_t * out_cid){ 573 574 lm_context_info_t *context = NULL; 575 lm_status_t lm_status = LM_STATUS_SUCCESS; 576 u32_t cid = (u32_t)-1; 577 lm_address_t phy_addr = {{0}} ; 578 579 if ( CHK_NULL(out_cid) || 580 CHK_NULL(pdev) || 581 CHK_NULL(pdev->context_info) || 582 CHK_NULL(pdev->context_info->array) || 583 CHK_NULL(cookie) || 584 ERR_IF(type >= ARRSIZE(pdev->context_info->proto_pending)) ) 585 586 { 587 DbgBreakIf(!out_cid) ; 588 DbgBreakIf(!pdev); 589 DbgBreakIf(!pdev->context_info); 590 DbgBreakIf(!pdev->context_info->array); 591 DbgBreakIf(!cookie); 592 DbgBreakIf(type >= ARRSIZE(pdev->context_info->proto_pending)) ; 593 return LM_STATUS_INVALID_PARAMETER ; 594 } 595 596 context = pdev->context_info; 597 *out_cid = 0; 598 /* take spinlock */ 599 MM_ACQUIRE_CID_LOCK(pdev); 600 601 // if the free list is empty return error 602 if (context->proto_ffree[type]==0) { 603 if ((pdev->params.cid_allocation_mode == LM_CID_ALLOC_REGULAR) || (context->proto_pending[type] == 0)) { 604 // if the free list is empty AND the pending list is empty return error OR 605 // the free list is empty and we're in the regular allocating mode 606 lm_status = LM_STATUS_RESOURCE; 607 } 608 else 609 { 610 /* pop pendinglist entry and place cookie */ 611 /* we only use the cid to connect between the pending connection and this cid, but 612 * the connection can't know of this cid before it is acually freed, for this reason 613 * we return cid = 0, which means, 'pending' */ 614 cid = context->proto_pending[type]; 615 context->proto_pending[type] = context->array[cid].next; 616 context->array[cid].next = 0; 617 context->array[cid].cid_resc.cookies[type] = cookie; 618 context->array[cid].cid_resc.cid_pending = LM_CID_STATE_PENDING; 619 lm_sp_req_manager_init(pdev, cid); 620 *out_cid = cid; 621 622 /* make sure the first cid previous is set correctly*/ 623 cid = context->proto_pending[type]; 624 if (cid) { 625 context->array[cid].prev = 0; 626 } 627 lm_status = LM_STATUS_PENDING; 628 } 629 }else{ 630 /* pop freelist entry and place cookie*/ 631 cid = context->proto_ffree[type]; 632 context->proto_ffree[type] = context->array[cid].next; 633 context->array[cid].next = 0; 634 context->array[cid].prev = 0; 635 context->array[cid].cid_resc.cookies[type] = cookie; 636 lm_sp_req_manager_init(pdev, cid); 637 *out_cid = cid; 638 lm_status = LM_STATUS_SUCCESS; 639 } 640 641 MM_RELEASE_CID_LOCK(pdev); 642 643 if(LM_STATUS_SUCCESS == lm_status) 644 { 645 //If the function allocated a new free CID, (not pending) the function MmMapIoSpace will be called 646 //to map the specific physical cid doorbell space to a virtual address. 647 //In case of a pending CID, the map doorbell space will not be remapped. The pending CID will use 648 //the old mapping cid doorbell space. 649 phy_addr.as_u32.low = (pdev->hw_info.mem_base[BAR_1].as_u32.low) & 0xfffffff0; 650 phy_addr.as_u32.high = pdev->hw_info.mem_base[BAR_1].as_u32.high; 651 652 LM_INC64(&phy_addr,(cid*LM_DQ_CID_SIZE)); 653 654 #ifdef __SunOS 655 656 context->array[cid].cid_resc.mapped_cid_bar_addr = 657 #ifdef VF_INVOLVED 658 (volatile void *)((u8_t*)pdev->vars.mapped_bar_addr[BAR_1] + cid*LM_DQ_CID_SIZE); 659 context->array[cid].cid_resc.reg_handle = pdev->vars.reg_handle[BAR_1]; 660 #else /* !VF_INVOLVED */ 661 (volatile void *)mm_map_io_space_solaris(pdev, 662 phy_addr, 663 BAR_1, 664 (cid * LM_DQ_CID_SIZE), 665 LM_DQ_CID_SIZE, 666 &context->array[cid].cid_resc.reg_handle); 667 #endif /* VF_INVOLVED */ 668 669 #else /* !__SunOS */ 670 671 context->array[cid].cid_resc.mapped_cid_bar_addr = 672 #ifdef VF_INVOLVED 673 (volatile void *)((u8_t*)pdev->vars.mapped_bar_addr[BAR_1] + cid*LM_DQ_CID_SIZE); 674 #else /* !VF_INVOLVED */ 675 (volatile void *)mm_map_io_space(pdev, phy_addr, LM_DQ_CID_SIZE); 676 #endif /* VF_INVOLVED */ 677 678 #endif /* __SunOS */ 679 680 // If the mapping failed we will return LM_STATUS_RESOURCE and return the cid resource. 681 if CHK_NULL(context->array[cid].cid_resc.mapped_cid_bar_addr) 682 { 683 DbgMessage(pdev, FATAL, "lm_allocate_cid: mm_map_io_space failed. address low=%d address high=%d\n", phy_addr.as_u32.low,phy_addr.as_u32.high ); 684 685 /* take spinlock */ 686 MM_ACQUIRE_CID_LOCK(pdev); 687 /* return the cid to free list */ 688 context->array[cid].next = pdev->context_info->proto_ffree[type]; 689 context->proto_ffree[type] = cid; 690 context->array[cid].invalid = LM_CONTEXT_VALID; 691 MM_RELEASE_CID_LOCK(pdev); 692 693 lm_status = LM_STATUS_RESOURCE; 694 *out_cid =0; 695 } 696 } 697 return lm_status; 698 } 699 700 void lm_cfc_delete(struct _lm_device_t *pdev, void *param) 701 { 702 u32_t cid = (u32_t)(uintptr_t)param; 703 u8_t flr_in_progress = lm_fl_reset_is_inprogress(pdev); 704 705 if ( CHK_NULL(pdev) || 706 ERR_IF(cid > pdev->params.max_func_connections) || 707 ERR_IF(pdev->context_info->array[cid].invalid != LM_CONTEXT_INVALID_WAIT) ) 708 { 709 DbgBreakIf(!pdev); 710 DbgBreakIf(cid > pdev->params.max_func_connections); 711 712 if (!flr_in_progress) 713 { 714 DbgBreakIf(pdev->context_info->array[cid].invalid != LM_CONTEXT_INVALID_WAIT); 715 } 716 else 717 { 718 DbgMessage(pdev, FATAL, "lm_cfc_delete: invalid %d for cid=%d\n", pdev->context_info->array[cid].invalid,cid); 719 720 if (pdev->context_info->array[cid].invalid != LM_CONTEXT_INVALID_DELETE) 721 { 722 DbgBreakIf(1); 723 } 724 } 725 } 726 727 DbgMessage(pdev, WARN, "lm_cfc_delete: cid=0x%x\n",cid); 728 pdev->context_info->array[cid].invalid = LM_CONTEXT_INVALID_DELETE; 729 730 if (lm_fl_reset_is_inprogress(pdev)) 731 { 732 lm_recycle_cid(pdev, cid); 733 } 734 else 735 { 736 /* use common bit */ 737 lm_command_post(pdev, 738 cid, 739 RAMROD_CMD_ID_COMMON_CFC_DEL, 740 CMD_PRIORITY_NORMAL, 741 NONE_CONNECTION_TYPE, 742 0 ); 743 } 744 return; 745 } 746 747 /* free a context 748 takes the list spinlock */ 749 void lm_free_cid(struct _lm_device_t *pdev, u32_t type, u32_t cid, u8_t notify_fw){ 750 u32_t delay_time = 0; 751 u32_t curr_cid = 0; 752 u8_t recycle_now = 0; 753 u8_t proto_idx = 0; 754 755 if ( CHK_NULL(pdev) || 756 CHK_NULL(pdev->context_info) || 757 ERR_IF(type >= ARRSIZE(pdev->context_info->proto_end)) || 758 ERR_IF(cid > (pdev->context_info->proto_end[type])) || 759 ERR_IF(cid < (pdev->context_info->proto_start[type])) || 760 (!lm_fl_reset_is_inprogress(pdev) && (pdev->context_info->array[cid].invalid != LM_CONTEXT_VALID))) 761 { 762 DbgBreakIf(!pdev); 763 DbgBreakIf(!pdev->context_info); 764 DbgBreakIf(type >= ARRSIZE(pdev->context_info->proto_end)); 765 DbgBreakIf(cid > (pdev->context_info->proto_end[type])); 766 DbgBreakIf(cid < (pdev->context_info->proto_start[type])); 767 DbgBreakIf(pdev->context_info->array[cid].invalid != LM_CONTEXT_VALID); 768 return; 769 } 770 MM_ACQUIRE_CID_LOCK(pdev); 771 772 for (proto_idx = 0; proto_idx < MAX_PROTO; proto_idx++) 773 { 774 DbgBreakIf(pdev->context_info->array[cid].cid_resc.cookies[proto_idx]); 775 } 776 777 lm_sp_req_manager_shutdown(pdev, cid); 778 779 if (notify_fw) 780 { 781 /* Vladz: Added in order to optimize CID release in DOS */ 782 #if !(defined(DOS) || defined(__LINUX)) 783 delay_time = LM_FREE_CID_DELAY_TIME(pdev); 784 #else 785 delay_time = 0; 786 #endif 787 788 pdev->context_info->array[cid].invalid = LM_CONTEXT_INVALID_WAIT; 789 790 recycle_now = FALSE; 791 /* add the cid to proto-pending: it'll be freed soon when cfc-delete is done */ 792 curr_cid = pdev->context_info->proto_pending[type]; 793 pdev->context_info->array[cid].next = curr_cid; 794 pdev->context_info->array[cid].prev = 0; 795 if (curr_cid != 0) 796 { 797 pdev->context_info->array[curr_cid].prev = cid; 798 } 799 pdev->context_info->proto_pending[type] = cid; 800 } 801 else 802 { 803 pdev->context_info->array[cid].invalid = LM_CONTEXT_INVALID_DELETE; 804 recycle_now = TRUE; 805 /* If we're recylcing now, there's no point in adding it to the pending list */ 806 } 807 808 MM_RELEASE_CID_LOCK(pdev); 809 810 if (recycle_now) { 811 lm_recycle_cid(pdev, cid); 812 } 813 else 814 { 815 if (type == TOE_CONNECTION_TYPE) 816 { 817 DbgMessage(pdev, WARN, "lm_free_cid: CFC delete: cid=0x%x\n",cid); 818 lm_cfc_delete(pdev,(void *)(uintptr_t)cid); 819 } 820 else 821 { 822 DbgMessage(pdev, WARN, "lm_free_cid: schedule CFC delete: cid=0x%x\n",cid); 823 mm_schedule_task(pdev,delay_time,lm_cfc_delete, 824 (void *)(uintptr_t)cid); 825 } 826 } 827 828 } 829 830 void lm_recycle_cid(struct _lm_device_t *pdev, u32_t cid){ 831 832 u32_t type = MAX_PROTO+1; 833 u32_t prev_cid, next_cid; 834 u32_t i; 835 u8_t call_cb = TRUE; 836 837 if ( CHK_NULL(pdev) || 838 ERR_IF(pdev->context_info->array[cid].invalid != LM_CONTEXT_INVALID_DELETE) || 839 ERR_IF(cid > pdev->params.max_func_connections) ) 840 { 841 DbgBreakIf(!pdev); 842 DbgBreakIf(pdev->context_info->array[cid].invalid != LM_CONTEXT_INVALID_DELETE); 843 DbgBreakIf(cid > pdev->params.max_func_connections); 844 return; 845 } 846 847 for (i=0; i < MAX_PROTO; i++ ) { 848 if ((cid >= pdev->context_info->proto_start[i]) && (cid <= pdev->context_info->proto_end[i])) 849 { 850 type = i; 851 break; 852 } 853 } 854 if ERR_IF(type >= ARRSIZE(pdev->context_info->proto_pending)) 855 { 856 DbgBreakIf(type >= ARRSIZE(pdev->context_info->proto_pending)) ; 857 return; 858 } 859 /* take spinlock */ 860 MM_ACQUIRE_CID_LOCK(pdev); 861 #ifdef _VBD_ 862 if ((type == TOE_CONNECTION_TYPE) && (pdev->ofld_info.l4_params.ticks_per_second != 0)) 863 { 864 pdev->vars.last_recycling_timestamp = mm_get_current_time(pdev) * 1000 / pdev->ofld_info.l4_params.ticks_per_second; /*time in ms*/ 865 } 866 #endif 867 /* If no cookie is waiting on this cid extract from pending and push enrty into the freelist */ 868 if (pdev->context_info->array[cid].cid_resc.cid_pending == FALSE) { 869 /* take the cid out of the proto_pending cids if it's there */ 870 prev_cid = pdev->context_info->array[cid].prev; 871 next_cid = pdev->context_info->array[cid].next; 872 if (prev_cid) { 873 pdev->context_info->array[prev_cid].next = next_cid; 874 } 875 if (next_cid) { 876 pdev->context_info->array[next_cid].prev = prev_cid; 877 } 878 if (pdev->context_info->proto_pending[type] == cid) { 879 DbgBreakIf(prev_cid != 0); 880 pdev->context_info->proto_pending[type] = next_cid; 881 } 882 pdev->context_info->array[cid].prev = pdev->context_info->array[cid].next = 0; 883 /* add to free list */ 884 pdev->context_info->array[cid].next = pdev->context_info->proto_ffree[type]; 885 pdev->context_info->array[cid].invalid = LM_CONTEXT_VALID; 886 pdev->context_info->array[cid].cfc_delete_cnt = 0; 887 pdev->context_info->proto_ffree[type] = cid; 888 call_cb = FALSE; /* no one is waiting on this... */ 889 //free virtual memory for cids not in use. 890 #ifndef VF_INVOLVED 891 mm_unmap_io_space(pdev,(void *)pdev->context_info->array[cid].cid_resc.mapped_cid_bar_addr, LM_DQ_CID_SIZE); 892 #endif 893 } 894 else 895 { 896 /* No need to extract from pending - it's not there. */ 897 898 /* NirV: we still can't set cid_resc.cid_pending to false, */ 899 /* will be possible only in the callback */ 900 901 pdev->context_info->array[cid].invalid = LM_CONTEXT_VALID; 902 call_cb = TRUE; 903 } 904 905 /* time to clear the active bit (cdu-validation ) we can only do this after cfc-delete has completed, at this point, invalid==LM_CONTEXT_VALID */ 906 lm_set_cdu_validation_data(pdev, cid, TRUE /* Invalidate */); 907 908 909 /* rlease spinlock */ 910 MM_RELEASE_CID_LOCK(pdev); 911 912 /* call here the cid recycle callback of that 913 protocol type if such cb exists*/ 914 if (pdev->cid_recycled_callbacks[type] && call_cb) { 915 pdev->cid_recycled_callbacks[type](pdev, pdev->context_info->array[cid].cid_resc.cookies[type], cid); 916 } 917 918 return; 919 } 920 921 /* lookup the protocol cookie for a given CID 922 does not take a lock 923 will DbgBreakIf( if the CID is not allocated. */ 924 void * lm_cid_cookie(struct _lm_device_t *pdev, u32_t type, u32_t cid){ 925 926 if ( CHK_NULL(pdev) || 927 CHK_NULL(pdev->context_info) || 928 ERR_IF(type >= MAX_PROTO) || 929 ERR_IF(cid > (pdev->context_info->proto_end[MAX_PROTO - 1])) || 930 CHK_NULL(pdev->context_info->array[cid].cid_resc.cookies[type]) || 931 ERR_IF(pdev->context_info->array[cid].invalid != LM_CONTEXT_VALID) ) 932 { 933 DbgBreakIf(!pdev); 934 DbgBreakIf(!pdev->context_info); 935 DbgBreakIf(type >= MAX_PROTO); 936 DbgBreakIf(cid > (pdev->context_info->proto_end[MAX_PROTO - 1])); 937 DbgBreakIf(pdev->context_info->array[cid].invalid != LM_CONTEXT_VALID); 938 } 939 940 if (pdev->context_info->array[cid].cid_resc.cookies[type] == NULL) 941 { 942 return NULL; 943 } 944 945 946 /* if the cid is pending, return null */ 947 if (pdev->context_info->array[cid].cid_resc.cid_pending != LM_CID_STATE_VALID) 948 { 949 return NULL; 950 } 951 952 return pdev->context_info->array[cid].cid_resc.cookies[type]; 953 } 954 955 /* lookup the protocol cid_resc for a given CID 956 does not take a lock 957 will DbgBreakIf( if the CID is not allocated */ 958 lm_cid_resc_t * lm_cid_resc(struct _lm_device_t *pdev, u32_t cid){ 959 960 if ( CHK_NULL(pdev) || 961 CHK_NULL(pdev->context_info) || 962 ERR_IF(cid > (pdev->context_info->proto_end[MAX_PROTO - 1])) ) 963 { 964 DbgBreakIf(!pdev); 965 DbgBreakIf(!pdev->context_info); 966 DbgBreakIf(cid > (pdev->context_info->proto_end[MAX_PROTO - 1])); 967 } 968 969 return &pdev->context_info->array[cid].cid_resc; 970 } 971 972 u8_t lm_map_cid_to_proto(struct _lm_device_t * pdev, u32_t cid) 973 { 974 u8_t type = MAX_PROTO+1; 975 u8_t i; 976 977 if (!pdev || cid > pdev->params.max_func_connections) { 978 return type; 979 } 980 981 for (i=0; i < MAX_PROTO; i++ ) { 982 if ((cid >= pdev->context_info->proto_start[i]) && (cid <= pdev->context_info->proto_end[i])) { 983 type = i; 984 break; 985 } 986 } 987 return type; 988 } 989 990 void lm_init_connection_context(struct _lm_device_t *pdev, u32_t const sw_cid, u8_t sb_id) 991 { 992 struct eth_context * context = NULL; 993 994 if ( CHK_NULL(pdev) || 995 ERR_IF(sw_cid < PFDEV(pdev)->context_info->proto_start[ETH_CONNECTION_TYPE]) || 996 ERR_IF(sw_cid > PFDEV(pdev)->context_info->proto_end[ETH_CONNECTION_TYPE]) ) 997 { 998 DbgBreakIf(!pdev); 999 DbgBreakIf(sw_cid < PFDEV(pdev)->context_info->proto_start[ETH_CONNECTION_TYPE]); /* first legal NIC CID */ 1000 DbgBreakIf(sw_cid > PFDEV(pdev)->context_info->proto_end[ETH_CONNECTION_TYPE]); /* last legal NIC CID */ 1001 } 1002 1003 context = lm_get_context(PFDEV(pdev), VF_TO_PF_CID(pdev,sw_cid)); 1004 1005 mm_mem_zero( context, sizeof(struct eth_context) ) ; 1006 1007 /* calculate the cdu-validation value. */ 1008 lm_set_cdu_validation_data(pdev, VF_TO_PF_CID(pdev,sw_cid), FALSE /* don't invalidate */); 1009 1010 } 1011 1012 lm_status_t 1013 lm_set_cid_resc( 1014 IN struct _lm_device_t *pdev, 1015 IN u32_t type, 1016 IN void *cookie, 1017 IN u32_t cid) 1018 { 1019 lm_status_t lm_status = LM_STATUS_SUCCESS; 1020 lm_cid_resc_t *cid_resc = NULL; 1021 1022 if CHK_NULL(pdev) 1023 { 1024 return LM_STATUS_INVALID_PARAMETER; 1025 } 1026 1027 /* take spinlock */ 1028 MM_ACQUIRE_CID_LOCK(pdev); 1029 1030 cid_resc = lm_cid_resc(pdev, cid); 1031 1032 if CHK_NULL(cid_resc) 1033 { 1034 MM_RELEASE_CID_LOCK(pdev); 1035 return LM_STATUS_INVALID_PARAMETER; 1036 } 1037 1038 cid_resc->cookies[type] = cookie; 1039 1040 /* rlease spinlock */ 1041 MM_RELEASE_CID_LOCK(pdev); 1042 1043 return lm_status; 1044 } 1045 1046 lm_status_t 1047 lm_free_cid_resc( 1048 IN struct _lm_device_t *pdev, 1049 IN u32_t type, 1050 IN u32_t cid, 1051 IN u8_t notify_fw) 1052 { 1053 lm_cid_resc_t *cid_resc = NULL; 1054 u8_t proto_idx = 0; 1055 1056 1057 if (CHK_NULL(pdev) || (cid == 0)) 1058 { 1059 return LM_STATUS_INVALID_PARAMETER; 1060 } 1061 1062 /* take spinlock */ 1063 MM_ACQUIRE_CID_LOCK(pdev); 1064 1065 cid_resc = lm_cid_resc(pdev, cid); 1066 1067 if CHK_NULL(cid_resc) 1068 { 1069 MM_RELEASE_CID_LOCK(pdev); 1070 return LM_STATUS_INVALID_PARAMETER; 1071 } 1072 1073 cid_resc->cookies[type] = NULL; 1074 1075 while ((proto_idx < MAX_PROTO) && (cid_resc->cookies[proto_idx] == NULL)) 1076 { 1077 proto_idx++; 1078 } 1079 /* rlease spinlock */ 1080 MM_RELEASE_CID_LOCK(pdev); 1081 1082 if (proto_idx == MAX_PROTO) 1083 { 1084 /* We'll call lm_map_cid_to_proto() to compute the appropriate type that was associated with that CID, 1085 * this is done to avoid assert upon race scenarios in which the last cookie resource that gets freed is not from the type of the CID */ 1086 lm_free_cid(pdev, lm_map_cid_to_proto(pdev, cid), cid, notify_fw); 1087 } 1088 1089 return LM_STATUS_SUCCESS; 1090 } 1091 1092 1093 1094 lm_sp_req_manager_t * 1095 lm_cid_sp_req_mgr( 1096 IN struct _lm_device_t *pdev, 1097 IN u32_t cid 1098 ) 1099 { 1100 lm_cid_resc_t *cid_resc = NULL; 1101 1102 if CHK_NULL(pdev) 1103 { 1104 return NULL; 1105 } 1106 1107 cid_resc = lm_cid_resc(pdev, cid); 1108 1109 if CHK_NULL(cid_resc) 1110 { 1111 return NULL; 1112 } 1113 1114 return &cid_resc->sp_req_mgr; 1115 } 1116 1117 1118 1119 lm_cid_state_enum 1120 lm_cid_state( 1121 IN struct _lm_device_t *pdev, 1122 IN u32_t cid 1123 ) 1124 { 1125 lm_cid_resc_t *cid_resc = NULL; 1126 1127 if CHK_NULL(pdev) 1128 { 1129 return LM_CID_STATE_ERROR; 1130 } 1131 1132 cid_resc = lm_cid_resc(pdev, cid); 1133 1134 if CHK_NULL(cid_resc) 1135 { 1136 return LM_CID_STATE_ERROR; 1137 } 1138 1139 return (lm_cid_state_enum)cid_resc->cid_pending; 1140 } 1141 1142 1143 1144 lm_status_t 1145 lm_set_cid_state( 1146 IN struct _lm_device_t *pdev, 1147 IN u32_t cid, 1148 IN lm_cid_state_enum state 1149 ) 1150 { 1151 lm_cid_resc_t *cid_resc = NULL; 1152 1153 if CHK_NULL(pdev) 1154 { 1155 return LM_STATUS_INVALID_PARAMETER; 1156 } 1157 1158 /* take spinlock */ 1159 MM_ACQUIRE_CID_LOCK(pdev); 1160 1161 cid_resc = lm_cid_resc(pdev, cid); 1162 1163 if CHK_NULL(cid_resc) 1164 { 1165 MM_RELEASE_CID_LOCK(pdev); 1166 return LM_STATUS_INVALID_PARAMETER; 1167 } 1168 1169 cid_resc->cid_pending = state; 1170 1171 /* rlease spinlock */ 1172 MM_RELEASE_CID_LOCK(pdev); 1173 1174 return LM_STATUS_SUCCESS; 1175 } 1176 1177 /** 1178 * sets the CDU validation data to be valid for a given cid 1179 * 1180 * @param pdev - the physical device handle 1181 * @param cid - the context of this cid will be initialized with the cdu validataion data 1182 * 1183 * @return lm_status_t 1184 */ 1185 lm_status_t lm_set_cdu_validation_data(struct _lm_device_t *pdev, s32_t cid, u8_t invalidate) 1186 { 1187 lm_status_t lm_status = LM_STATUS_SUCCESS; 1188 void *context = NULL; 1189 u8_t *cdu_reserved = NULL; /* Pointer to the actual location of cdu_reserved field according to protocol */ 1190 u8_t *cdu_usage = NULL; /* Pointer to the actual location of cdu_usage field according to protocol */ 1191 u8_t proto_type = 0; 1192 1193 context = lm_get_context(PFDEV(pdev), cid); 1194 1195 if (!context) { 1196 return LM_STATUS_FAILURE; 1197 } 1198 1199 proto_type = lm_map_cid_to_proto(PFDEV(pdev), cid); 1200 1201 switch (proto_type) { 1202 case TOE_CONNECTION_TYPE: 1203 cdu_reserved = &((struct toe_context *)context)->xstorm_ag_context.cdu_reserved; 1204 cdu_usage = &(((struct toe_context *)context)->ustorm_ag_context.cdu_usage); 1205 break; 1206 case ETH_CONNECTION_TYPE: 1207 cdu_reserved = &(((struct eth_context *)context)->xstorm_ag_context.cdu_reserved); 1208 cdu_usage = &(((struct eth_context *)context)->ustorm_ag_context.cdu_usage); 1209 break; 1210 case ISCSI_CONNECTION_TYPE: 1211 cdu_reserved = &(((struct iscsi_context *)context)->xstorm_ag_context.cdu_reserved); 1212 cdu_usage = &(((struct iscsi_context *)context)->ustorm_ag_context.cdu_usage); 1213 break; 1214 case FCOE_CONNECTION_TYPE: 1215 cdu_reserved = &(((struct fcoe_context *)context)->xstorm_ag_context.cdu_reserved); 1216 cdu_usage = &(((struct fcoe_context *)context)->ustorm_ag_context.cdu_usage); 1217 break; 1218 default: 1219 lm_status = LM_STATUS_FAILURE; 1220 break; 1221 } 1222 1223 if (cdu_reserved && cdu_usage) { 1224 if (invalidate) { 1225 *cdu_reserved = CDU_RSRVD_INVALIDATE_CONTEXT_VALUE(*cdu_reserved); 1226 *cdu_usage = CDU_RSRVD_INVALIDATE_CONTEXT_VALUE(*cdu_usage); 1227 } else { 1228 *cdu_reserved = CDU_RSRVD_VALUE_TYPE_A(HW_CID(pdev, cid), CDU_REGION_NUMBER_XCM_AG, proto_type); 1229 *cdu_usage = CDU_RSRVD_VALUE_TYPE_A(HW_CID(pdev, cid), CDU_REGION_NUMBER_UCM_AG, proto_type); 1230 } 1231 } 1232 1233 return lm_status; 1234 } 1235 1236 1237 lm_status_t lm_get_context_size(struct _lm_device_t *pdev, s32_t * context_size) 1238 { 1239 *context_size = LM_CONTEXT_SIZE; 1240 return LM_STATUS_SUCCESS; 1241 } 1242 1243 lm_status_t lm_set_con_state(struct _lm_device_t *pdev, u32_t cid, u32_t state) 1244 { 1245 lm_cid_resc_t * cid_resc = lm_cid_resc(pdev, cid); 1246 1247 if CHK_NULL(cid_resc) 1248 { 1249 return LM_STATUS_INVALID_PARAMETER; 1250 } 1251 1252 cid_resc->con_state = state; 1253 1254 return LM_STATUS_SUCCESS; 1255 } 1256 1257 u32_t lm_get_con_state(struct _lm_device_t *pdev, u32_t cid) 1258 { 1259 const lm_cid_resc_t * cid_resc = lm_cid_resc(pdev, cid); 1260 1261 if CHK_NULL(cid_resc) 1262 { 1263 return LM_CON_STATE_CLOSE; 1264 } 1265 1266 return cid_resc->con_state; 1267 } 1268 1269 1270