fcoe.c (220978B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: fcoe.c 8 * Purpose: Trident2 FCoE functions 9 */ 10 #include <soc/defs.h> 11 12 #if defined(BCM_TRIDENT2_SUPPORT) 13 14 #include <assert.h> 15 #include <shared/bsl.h> 16 #include <sal/core/libc.h> 17 18 #include <soc/mem.h> 19 #include <soc/debug.h> 20 #include <soc/cm.h> 21 #include <soc/drv.h> 22 #include <soc/register.h> 23 #include <soc/memory.h> 24 #include <soc/hash.h> 25 #include <soc/l2x.h> 26 #include <soc/l3x.h> 27 #include <soc/lpm.h> 28 #include <soc/trident2.h> 29 #include <bcm/l2.h> 30 #include <bcm/l3.h> 31 #include <bcm/error.h> 32 #include <bcm/fcoe.h> 33 #include <bcm/switch.h> 34 #include <bcm_int/esw/trx.h> 35 #include <bcm_int/esw/l2.h> 36 #include <bcm_int/esw/l3.h> 37 #include <bcm_int/esw/fcoe.h> 38 #include <bcm_int/esw/trident.h> 39 #include <bcm_int/esw/trident2.h> 40 #include <bcm_int/esw/qos.h> 41 #include <bcm_int/esw/vlan.h> 42 #include <bcm_int/esw/trx.h> 43 #include <shared/idxres_fl.h> 44 #include <soc/scache.h> 45 46 #ifdef BCM_TRIDENT3_SUPPORT 47 #include <soc/trident3.h> 48 #endif /* BCM_TRIDENT3_SUPPORT */ 49 typedef uint32 L2_ENTRY_T[SOC_MAX_MEM_FIELD_WORDS]; 50 51 /* VSAN resource manager */ 52 STATIC shr_idxres_list_handle_t vsan_id_list[BCM_MAX_NUM_UNITS] = {NULL}; 53 54 #define FCOE_MAX_VSAN_ID 0xfff 55 #define FCOE_MAX_SRC_DEST_ID 0xffffff 56 #define FCOE_ZONE_MAX_CLASS_ID 0x3f 57 58 #ifdef BCM_WARM_BOOT_SUPPORT 59 /* VSAN ID reserve state */ 60 #define FCOE_VSAN_ID_BYTES 512 /* 4096 IDs, 1 bits per id = 512 bytes */ 61 typedef struct { 62 uint8 state[FCOE_VSAN_ID_BYTES]; /* 1 bits per VSAN ID */ 63 } _vsan_id_reserve_state; 64 65 STATIC _vsan_id_reserve_state _vsan_id_state[BCM_MAX_NUM_UNITS]; 66 67 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 68 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 69 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_1 70 71 #endif 72 73 typedef int (*fcoe_traverse_cb_f)(int unit, soc_mem_t mem, uint32 *buf, 74 bcm_fcoe_route_t *route); 75 76 #define VFT_NUM_ENTRIES 1 /* 1 entry per set in EGR_VFT_FIELDS_PROFILE */ 77 #define VFT_NUM_PROFILES 8 /* 8 profiles available in EGR_VFT_FIELDS_PROFILE */ 78 79 /* Hardware values for FC_HDR_ENCODE field defined in architecture spec */ 80 #define FC_HEADER_TYPE_NOT_PRESENT 0 81 #define FC_HEADER_TYPE_STANDARD 1 82 #define FC_HEADER_TYPE_VFT 2 83 #define FC_HEADER_TYPE_ENCAPSULATION 3 84 #define FC_HEADER_TYPE_IFR 4 85 #define FC_HEADER_TYPE_UNKNOWN 6 86 87 /* Values for EGR_L3_INTF.FCOE_VFT_ACTION */ 88 #define FCOE_VFT_ACTION_DO_NOT_MODIFY 0 89 #define FCOE_VFT_ACTION_ADD_REPLACE 1 90 #define FCOE_VFT_ACTION_DELETE 2 91 92 /* Values for EGR_L3_INTF.FCOE_FABRIC_ID_SEL */ 93 #define FCOE_FABRIC_ID_SEL_SET 0 94 #define FCOE_FABRIC_ID_SEL_INTERNAL 1 95 #define FCOE_FABRIC_ID_SEL_INNER_VLAN 2 96 #define FCOE_FABRIC_ID_SEL_OUTER_VLAN 3 97 98 /* Values for EGR_L3_INTF.FCOE_FABRIC_PRI_SEL */ 99 #define FCOE_FABRIC_PRI_SEL_SET 0 100 #define FCOE_FABRIC_PRI_SEL_INTERNAL 1 101 #define FCOE_FABRIC_PRI_SEL_REMARK 2 102 #define FCOE_ROUTE_READ_RETURN_L3_INTF 0 103 #define FCOE_ROUTE_READ_RETURN_NHID 1 104 105 #define CHECK_FLAGS_NOT_SET(flags, values) \ 106 if (((flags) & (values)) != 0) { \ 107 return BCM_E_PARAM; \ 108 } 109 110 typedef struct _bcm_td2_fcoe_bookkeeping_s { 111 uint8 profile_use_refcnt[VFT_NUM_PROFILES]; 112 } _bcm_td2_fcoe_bookkeeping_t; 113 114 static _bcm_td2_fcoe_bookkeeping_t _bcm_td2_fcoe_bk_info[BCM_MAX_NUM_UNITS]; 115 116 /* 117 * Function: bcm_td2_fcoe_init 118 * Purpose: Initialize the FCOE module. 119 * Parameters: unit - SOC unit number. 120 * Returns: BCM_E_XXX 121 */ 122 int 123 bcm_td2_fcoe_init(int unit) 124 { 125 #ifdef BCM_WARM_BOOT_SUPPORT 126 int fcoe_scache_size; 127 soc_scache_handle_t scache_handle; 128 uint8 *fcoe_scache_ptr; 129 #endif 130 int rv = BCM_E_NONE; 131 132 #ifdef BCM_WARM_BOOT_SUPPORT 133 if (SOC_WARM_BOOT(unit)) { 134 return _bcm_td2_fcoe_reinit(unit); 135 } 136 #endif 137 138 /* create vsan id list manager */ 139 rv = shr_idxres_list_create(&vsan_id_list[unit], 0, FCOE_MAX_VSAN_ID, 140 0, FCOE_MAX_VSAN_ID, "VSAN ID"); 141 if (rv != BCM_E_NONE) { 142 return rv; 143 } 144 145 #ifdef BCM_WARM_BOOT_SUPPORT 146 147 memset(&_vsan_id_state[unit], 0, sizeof(_vsan_id_reserve_state)); 148 149 fcoe_scache_size = sizeof(_vsan_id_reserve_state) * BCM_MAX_NUM_UNITS; 150 151 fcoe_scache_size += sizeof(_bcm_td2_fcoe_bookkeeping_t); 152 153 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FCOE, 0); 154 155 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 156 fcoe_scache_size, &fcoe_scache_ptr, 157 BCM_WB_DEFAULT_VERSION, NULL); 158 159 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 160 return rv; 161 } 162 163 #endif 164 165 memset(&_bcm_td2_fcoe_bk_info[unit].profile_use_refcnt, 0, 166 sizeof _bcm_td2_fcoe_bk_info[unit].profile_use_refcnt); 167 168 return BCM_E_NONE; 169 } 170 171 #ifdef BCM_WARM_BOOT_SUPPORT 172 173 STATIC int 174 _bcm_td2_vsan_id_creation_state_get(int unit, int vsan_id) 175 { 176 uint32 byte_index; 177 uint32 bit_index; 178 uint8 state_val; 179 uint8 tmp = 0; 180 181 /* find corresponding bit for vsan id */ 182 byte_index = vsan_id / 8; 183 bit_index = vsan_id % 8; 184 tmp = 1 << bit_index; 185 state_val = _vsan_id_state[unit].state[byte_index]; 186 187 if ((state_val & tmp) != 0) { /* state bit is 1 */ 188 return 1; 189 } else { 190 return 0; 191 } 192 } 193 194 STATIC void 195 _bcm_td2_vsan_id_creation_state_set(int unit, int vsan_id, int state) 196 { 197 uint32 byte_index; 198 uint32 bit_index; 199 uint8 state_val; 200 uint8 tmp = 0; 201 202 /* find corresponding bit for vsan id */ 203 byte_index = vsan_id / 8; 204 bit_index = vsan_id % 8; 205 tmp = 1 << bit_index; 206 state_val = _vsan_id_state[unit].state[byte_index]; 207 208 if (state == 0) { 209 /* clear state */ 210 state_val = state_val & ~tmp; 211 212 } else { 213 /* set state */ 214 state_val = state_val | tmp; 215 } 216 /* update table */ 217 _vsan_id_state[unit].state[byte_index] = state_val; 218 } 219 220 STATIC int 221 _bcm_td2_recreate_reserved_entries(int unit) 222 { 223 uint32 vsan_id; 224 int rv; 225 int index; 226 soc_mem_t mem = ING_VSANm; 227 ing_vsan_entry_t vsan_entry; 228 229 /* release VSAN list manager */ 230 if (vsan_id_list[unit] != NULL) { 231 /* the following can be failed if we have stale pointer. Igonre it */ 232 (void)shr_idxres_list_destroy(vsan_id_list[unit]); 233 vsan_id_list[unit] = NULL; 234 } 235 236 /* re-create vsan id list manager */ 237 rv = shr_idxres_list_create(&vsan_id_list[unit], 0, FCOE_MAX_VSAN_ID, 238 0, FCOE_MAX_VSAN_ID, "VSAN ID"); 239 if (rv != BCM_E_NONE) { 240 return rv; 241 } 242 243 for (vsan_id = 0; vsan_id <= FCOE_MAX_VSAN_ID; vsan_id++) { 244 if (_bcm_td2_vsan_id_creation_state_get(unit, vsan_id) != 0) { 245 /*reserve entry */ 246 BCM_IF_ERROR_RETURN( 247 shr_idxres_list_reserve(vsan_id_list[unit], vsan_id, vsan_id)); 248 249 /* Recover FC_MAP_PROFILE references */ 250 BCM_IF_ERROR_RETURN( 251 soc_mem_read(unit, mem, MEM_BLOCK_ANY, vsan_id, &vsan_entry)); 252 index = soc_mem_field32_get(unit,mem, &vsan_entry, 253 FCOE_FC_MAP_INDEXf); 254 BCM_IF_ERROR_RETURN( 255 _bcm_fc_map_profile_entry_reference(unit, index, 1)); 256 } 257 } 258 return BCM_E_NONE; 259 } 260 261 int 262 _bcm_td2_fcoe_sync(int unit) 263 { 264 soc_scache_handle_t scache_handle; 265 uint8 *fcoe_scache_ptr; 266 int rv; 267 268 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FCOE, 0); 269 270 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, 271 &fcoe_scache_ptr, 272 BCM_WB_DEFAULT_VERSION, NULL); 273 274 /* Note : If no storage is configured, the above function will return 275 * with BCM_E_NOT_FOUND. This is the correct behavior for 276 * UNSYNCHRONIZED mode. 277 */ 278 279 if (rv == BCM_E_NONE) { 280 /* copy data to cache */ 281 sal_memcpy(fcoe_scache_ptr, &_vsan_id_state[unit], 282 sizeof(_vsan_id_reserve_state)); 283 fcoe_scache_ptr += sizeof(_vsan_id_reserve_state) * BCM_MAX_NUM_UNITS; 284 285 /* BCM_WB_VERSION_1_1 */ 286 sal_memcpy(fcoe_scache_ptr, &_bcm_td2_fcoe_bk_info[unit], 287 sizeof(_bcm_td2_fcoe_bookkeeping_t)); 288 fcoe_scache_ptr += sizeof(_bcm_td2_fcoe_bookkeeping_t); 289 } 290 291 return BCM_E_NONE; 292 } 293 294 int 295 _bcm_td2_fcoe_reinit(int unit) 296 { 297 int rv; 298 soc_scache_handle_t scache_handle; 299 uint8 *fcoe_scache_ptr; 300 uint16 recovered_ver = 0; 301 uint32 additional_scache_size = 0; 302 int index; 303 int refcnt = 0; 304 305 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FCOE, 0); 306 307 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, 308 &fcoe_scache_ptr, 309 BCM_WB_DEFAULT_VERSION, &recovered_ver); 310 if (rv == BCM_E_NOT_FOUND) { 311 fcoe_scache_ptr = NULL; 312 313 } else if (SOC_FAILURE(rv)) { 314 return rv; 315 } else { 316 /* success, recover data (copy data from cache) */ 317 sal_memcpy(&_vsan_id_state[unit], fcoe_scache_ptr, 318 sizeof(_vsan_id_reserve_state)); 319 fcoe_scache_ptr += sizeof(_vsan_id_reserve_state) * BCM_MAX_NUM_UNITS; 320 if (recovered_ver >= BCM_WB_VERSION_1_1) { 321 sal_memcpy(&_bcm_td2_fcoe_bk_info[unit], fcoe_scache_ptr, 322 sizeof(_bcm_td2_fcoe_bookkeeping_t)); 323 fcoe_scache_ptr += sizeof(_bcm_td2_fcoe_bookkeeping_t); 324 for (index = 0; index < VFT_NUM_PROFILES; index++) { 325 if (_bcm_td2_fcoe_bk_info[unit].profile_use_refcnt[index]) { 326 refcnt = _bcm_td2_fcoe_bk_info[unit].profile_use_refcnt[index]; 327 while (refcnt--) { 328 _bcm_egr_vft_fields_entry_reference(unit, index, 1); 329 } 330 } 331 } 332 } else { 333 additional_scache_size += sizeof(_bcm_td2_fcoe_bookkeeping_t); 334 } 335 if (additional_scache_size > 0) { 336 SOC_IF_ERROR_RETURN 337 (soc_scache_realloc(unit, scache_handle, additional_scache_size)); 338 } 339 340 BCM_IF_ERROR_RETURN(_bcm_td2_recreate_reserved_entries(unit)); 341 } 342 343 return BCM_E_NONE; 344 } 345 346 #endif 347 348 /* 349 * Function: bcm_td2_fcoe_cleanup 350 * Purpose: Cleanup the FCOE module. 351 * Parameters: unit - SOC unit number. 352 * Returns: BCM_E_XXX 353 */ 354 int 355 bcm_td2_fcoe_cleanup(int unit) 356 { 357 int rv = BCM_E_NONE; 358 359 /* free vsan id list manager */ 360 if (vsan_id_list[unit] != NULL) { 361 rv = shr_idxres_list_destroy(vsan_id_list[unit]); 362 363 if (rv != BCM_E_NONE) { 364 return rv; 365 } else { 366 vsan_id_list[unit] = NULL; 367 } 368 } 369 370 371 372 return rv; 373 } 374 375 /* mark vsan ID as Reserved */ 376 STATIC int 377 _bcm_fcoe_reserve_vsan_id (int unit, uint32 vsan_id) 378 { 379 #ifdef BCM_WARM_BOOT_SUPPORT 380 SOC_CONTROL_LOCK(unit); 381 SOC_CONTROL(unit)->scache_dirty = 1; 382 SOC_CONTROL_UNLOCK(unit); 383 384 /* mark as created */ 385 _bcm_td2_vsan_id_creation_state_set(unit, vsan_id, 1); 386 #endif 387 388 return shr_idxres_list_reserve(vsan_id_list[unit], vsan_id, vsan_id); 389 } 390 391 /* unreserve vsan ID */ 392 STATIC int 393 _bcm_fcoe_unreserve_vsan_id (int unit, uint32 vsan_id) 394 { 395 #ifdef BCM_WARM_BOOT_SUPPORT 396 SOC_CONTROL_LOCK(unit); 397 SOC_CONTROL(unit)->scache_dirty = 1; 398 SOC_CONTROL_UNLOCK(unit); 399 400 _bcm_td2_vsan_id_creation_state_set(unit, vsan_id, 0); 401 #endif 402 403 return shr_idxres_list_free(vsan_id_list[unit], vsan_id); 404 } 405 406 STATIC int 407 _bcm_fcoe_zone_validate(bcm_fcoe_zone_entry_t *zone) 408 { 409 if ((zone->vsan_id > FCOE_MAX_VSAN_ID) || /* 12 bits */ 410 (zone->d_id > FCOE_MAX_SRC_DEST_ID) || /* 24 bits */ 411 (zone->s_id > FCOE_MAX_SRC_DEST_ID) || /* 24 bits */ 412 (zone->class_id < 0) || 413 (zone->class_id > FCOE_ZONE_MAX_CLASS_ID) || /* 6 bits */ 414 (zone->action > bcmFcoeZoneActionRedirect)) { 415 return BCM_E_PARAM; 416 } 417 return BCM_E_NONE; 418 } 419 420 /* 421 * Purpose: 422 * Add FCoE zoning entry 423 * Parameters: 424 * unit - Device unit number 425 * zone - zone entry 426 * Returns: 427 * BCM_E_NONE - Success. 428 * BCM_E_XXX 429 */ 430 int 431 bcm_td2_fcoe_zone_add(int unit, bcm_fcoe_zone_entry_t *zone) 432 { 433 L2_ENTRY_T l2_entry; 434 L2_ENTRY_T l2_lookup; 435 soc_mem_t mem; 436 soc_field_t field_key; 437 int rv = BCM_E_NONE; 438 int l2_index = 0, valid_f; 439 440 if (_bcm_fcoe_zone_validate(zone) != BCM_E_NONE) { 441 return BCM_E_PARAM; 442 } 443 444 sal_memset(&l2_entry, 0, sizeof (l2_entry)); 445 sal_memset(&l2_lookup, 0, sizeof (l2_lookup)); 446 447 mem = L2Xm; 448 valid_f = VALIDf; 449 450 #ifdef BCM_TRIDENT3_SUPPORT 451 if (SOC_IS_TRIDENT3X(unit)) 452 valid_f = BASE_VALIDf; 453 #endif 454 455 field_key = TD2_L2_HASH_KEY_TYPE_FCOE_ZONE; 456 457 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 458 valid_f, 1); /* [1] */ 459 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 460 KEY_TYPEf, field_key); /* fcoe type */ 461 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 462 FCOE_ZONE__VSAN_IDf, zone->vsan_id); /* vsan ID */ 463 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 464 FCOE_ZONE__D_IDf, zone->d_id); /* D_ID */ 465 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 466 FCOE_ZONE__S_IDf, zone->s_id); /* S_ID */ 467 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 468 FCOE_ZONE__CLASS_IDf, zone->class_id); /* CLASS_ID */ 469 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 470 FCOE_ZONE__STATIC_BITf, 1); 471 472 /* 473 * set action field & copy_to_cpu field 474 */ 475 switch (zone->action) { 476 case bcmFcoeZoneActionAllow: 477 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 478 FCOE_ZONE__ACTIONf, 1); 479 break; 480 case bcmFcoeZoneActionDeny: 481 /* action field is already 0 */ 482 break; 483 case bcmFcoeZoneActionCopyToCpu: 484 #ifdef BCM_TRIDENT3_SUPPORT 485 if (SOC_IS_TRIDENT3X(unit)) { 486 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 487 FCOE_ZONE__CPUf, 1); 488 } else 489 #endif /* BCM_TRIDENT3_SUPPORT */ 490 { 491 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 492 FCOE_ZONE__COPY_TO_CPUf, 1); 493 } 494 break; 495 case bcmFcoeZoneActionRedirect: 496 /* fallthru */ 497 default: 498 return BCM_E_UNAVAIL; 499 break; 500 } 501 502 /* See if the entry already exists */ 503 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l2_index, 504 (void *)&l2_entry, (void *)&l2_lookup, 0); 505 506 if (rv == SOC_E_NONE) { 507 /* 508 * entry already exist. (l2_index gets the location) 509 * rewrite using new data 510 */ 511 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, l2_index, &l2_entry); 512 } else if (rv == SOC_E_NOT_FOUND) { 513 /* Not found, add entry */ 514 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ANY, (void *)&l2_entry); 515 } else { 516 return rv; 517 } 518 return rv; 519 } 520 521 522 /* 523 * Purpose: 524 * Delete Zone check entry 525 * Parameters: 526 * unit - Device unit number 527 * zone - zone entry to be deleted 528 * Returns: 529 * BCM_E_NONE - Success. 530 * BCM_E_XXX 531 */ 532 int 533 bcm_td2_fcoe_zone_delete(int unit, bcm_fcoe_zone_entry_t *zone) 534 { 535 L2_ENTRY_T l2_entry; 536 L2_ENTRY_T l2_lookup; 537 soc_mem_t mem; 538 soc_field_t field_key; 539 int rv = BCM_E_NONE; 540 int l2_index = 0; 541 542 sal_memset(&l2_entry, 0, sizeof (l2_entry)); 543 sal_memset(&l2_lookup, 0, sizeof (l2_lookup)); 544 545 mem = L2Xm; 546 547 field_key = TD2_L2_HASH_KEY_TYPE_FCOE_ZONE; 548 549 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 550 KEY_TYPEf, field_key); /* fcoe type */ 551 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 552 FCOE_ZONE__VSAN_IDf, zone->vsan_id); /* vsan ID */ 553 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 554 FCOE_ZONE__D_IDf, zone->d_id); /* D_ID */ 555 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 556 FCOE_ZONE__S_IDf, zone->s_id); /* S_ID */ 557 558 559 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l2_index, 560 (void *)&l2_entry, (void *)&l2_lookup, 0); 561 562 if ((rv < 0) && (rv != BCM_E_NOT_FOUND)) { 563 return rv; 564 } 565 566 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, (void *)&l2_entry); 567 return rv; 568 } 569 570 571 /* 572 * Description: 573 * Delete all zone check entries 574 * Parameters: 575 * unit - device number 576 * Return: 577 * BCM_E_XXX 578 */ 579 int 580 bcm_td2_fcoe_zone_delete_all (int unit) 581 { 582 int ix; 583 int key_type; 584 int chnk_end; 585 int chunksize; 586 int chunk; 587 int chunk_max; 588 int mem_idx_max; 589 L2_ENTRY_T *l2e; 590 L2_ENTRY_T *l2ep; 591 soc_control_t *soc = SOC_CONTROL(unit); 592 soc_mem_t mem; 593 int rv = BCM_E_NONE, valid_f; 594 595 chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS, 596 L2_MEM_CHUNKS_DEFAULT); 597 598 mem = L2Xm; 599 valid_f = VALIDf; 600 601 #ifdef BCM_TRIDENT3_SUPPORT 602 if (SOC_IS_TRIDENT3X(unit)) 603 valid_f = BASE_VALIDf; 604 #endif 605 606 l2e = soc_cm_salloc(unit, chunksize * sizeof(*l2e), "l2entrydel_chunk"); 607 608 if (l2e == NULL) { 609 return BCM_E_MEMORY; 610 } 611 612 mem_idx_max = soc_mem_index_max(unit, mem); 613 614 soc_mem_lock(unit, mem); 615 616 for (chunk = soc_mem_index_min(unit, mem); chunk <= mem_idx_max; 617 chunk += chunksize) { 618 619 chunk_max = chunk + chunksize - 1; 620 621 if (chunk_max > mem_idx_max) { 622 chunk_max = mem_idx_max; 623 } 624 625 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 626 chunk, chunk_max, l2e); 627 if (rv < 0) { 628 break; 629 } 630 631 chnk_end = (chunk_max - chunk); 632 633 for (ix = 0; ix <= chnk_end; ix++) { 634 l2ep = soc_mem_table_idx_to_pointer(unit, mem, 635 L2_ENTRY_T *, l2e, ix); 636 if (!soc_mem_field32_get(unit, mem, l2ep, valid_f)) { 637 continue; 638 } 639 640 /* we won't check set/check FCOE_ZONE__STATIC_BITf for now... 641 if (soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__STATIC_BITf)) { 642 continue; 643 }*/ 644 645 /* Match the Key Type to FCOE */ 646 key_type = soc_mem_field32_get(unit, mem, l2ep, KEY_TYPEf); 647 648 if (key_type != TD2_L2_HASH_KEY_TYPE_FCOE_ZONE) { 649 continue; 650 } 651 652 if (SOC_L2_DEL_SYNC_LOCK(soc) < 0) { 653 rv = BCM_E_RESOURCE; 654 break; 655 } 656 657 if (((rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, l2ep)) < 0) || 658 ((rv = soc_l2x_sync_delete(unit, (uint32 *) l2ep, 659 (chunk + ix), 0)) < 0)) { 660 SOC_L2_DEL_SYNC_UNLOCK(soc); 661 break; 662 } 663 664 SOC_L2_DEL_SYNC_UNLOCK(soc); 665 } 666 667 if (rv < 0) { 668 break; 669 } 670 } 671 672 soc_mem_unlock(unit, mem); 673 soc_cm_sfree(unit, l2e); 674 675 return rv; 676 } 677 678 679 /* 680 * Description: 681 * Delete all zone check entries matching VSAN ID 682 * Parameters: 683 * unit - device number 684 * zone - zone entry with VSAN ID to be deleted 685 * Return: 686 * BCM_E_XXX 687 */ 688 int 689 bcm_td2_fcoe_zone_delete_by_vsan (int unit, bcm_fcoe_zone_entry_t *zone) 690 { 691 int ix; 692 int key_type; 693 int chnk_end; 694 int chunksize; 695 int chunk; 696 int chunk_max; 697 int mem_idx_max; 698 L2_ENTRY_T *l2e; 699 L2_ENTRY_T *l2ep; 700 soc_control_t *soc = SOC_CONTROL(unit); 701 soc_mem_t mem; 702 int rv = BCM_E_NONE, valid_f; 703 uint32 vsan_id; 704 705 chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS, 706 L2_MEM_CHUNKS_DEFAULT); 707 708 mem = L2Xm; 709 valid_f = VALIDf; 710 711 #ifdef BCM_TRIDENT3_SUPPORT 712 if (SOC_IS_TRIDENT3X(unit)) 713 valid_f = BASE_VALIDf; 714 #endif 715 716 l2e = soc_cm_salloc(unit, chunksize * sizeof(*l2e), "l2entrydel_chunk"); 717 718 if (l2e == NULL) { 719 return BCM_E_MEMORY; 720 } 721 722 mem_idx_max = soc_mem_index_max(unit, mem); 723 724 soc_mem_lock(unit, mem); 725 726 for (chunk = soc_mem_index_min(unit, mem); chunk <= mem_idx_max; 727 chunk += chunksize) { 728 729 chunk_max = chunk + chunksize - 1; 730 731 if (chunk_max > mem_idx_max) { 732 chunk_max = mem_idx_max; 733 } 734 735 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 736 chunk, chunk_max, l2e); 737 if (rv < 0) { 738 break; 739 } 740 741 chnk_end = (chunk_max - chunk); 742 743 for (ix = 0; ix <= chnk_end; ix++) { 744 l2ep = soc_mem_table_idx_to_pointer(unit, mem, 745 L2_ENTRY_T *, l2e, ix); 746 if (!soc_mem_field32_get(unit, mem, l2ep, valid_f)) { 747 continue; 748 } 749 750 /* we won't check set/check FCOE_ZONE__STATIC_BITf for now... 751 if (soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__STATIC_BITf)) { 752 continue; 753 }*/ 754 755 /* Match the Key Type to FCOE */ 756 key_type = soc_mem_field32_get(unit, mem, l2ep, KEY_TYPEf); 757 758 if (key_type != TD2_L2_HASH_KEY_TYPE_FCOE_ZONE) { 759 continue; 760 } 761 762 /* match vsan id */ 763 vsan_id = soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__VSAN_IDf); 764 765 if (vsan_id != zone->vsan_id) { 766 continue; 767 } 768 769 if (SOC_L2_DEL_SYNC_LOCK(soc) < 0) { 770 rv = BCM_E_RESOURCE; 771 break; 772 } 773 774 if (((rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, l2ep)) < 0) || 775 ((rv = soc_l2x_sync_delete(unit, (uint32 *) l2ep, 776 (chunk + ix), 0)) < 0)) { 777 SOC_L2_DEL_SYNC_UNLOCK(soc); 778 break; 779 } 780 781 SOC_L2_DEL_SYNC_UNLOCK(soc); 782 } 783 784 if (rv < 0) { 785 break; 786 } 787 } 788 789 soc_mem_unlock(unit, mem); 790 soc_cm_sfree(unit, l2e); 791 792 return rv; 793 } 794 795 796 /* 797 * Description: 798 * Delete all zone check entries matching Source ID 799 * Parameters: 800 * unit - device number 801 * zone - zone entry with S_ID to be deleted 802 * Return: 803 * BCM_E_XXX 804 */ 805 int 806 bcm_td2_fcoe_zone_delete_by_sid (int unit, bcm_fcoe_zone_entry_t *zone) 807 { 808 int ix; 809 int key_type; 810 int chnk_end; 811 int chunksize; 812 int chunk; 813 int chunk_max; 814 int mem_idx_max; 815 L2_ENTRY_T *l2e; 816 L2_ENTRY_T *l2ep; 817 soc_control_t *soc = SOC_CONTROL(unit); 818 soc_mem_t mem; 819 int rv = BCM_E_NONE, valid_f; 820 uint32 s_id; 821 822 chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS, 823 L2_MEM_CHUNKS_DEFAULT); 824 825 mem = L2Xm; 826 valid_f = VALIDf; 827 828 #ifdef BCM_TRIDENT3_SUPPORT 829 if (SOC_IS_TRIDENT3X(unit)) 830 valid_f = BASE_VALIDf; 831 #endif 832 833 l2e = soc_cm_salloc(unit, chunksize * sizeof(*l2e), "l2entrydel_chunk"); 834 835 if (l2e == NULL) { 836 return BCM_E_MEMORY; 837 } 838 839 mem_idx_max = soc_mem_index_max(unit, mem); 840 841 soc_mem_lock(unit, mem); 842 843 for (chunk = soc_mem_index_min(unit, mem); chunk <= mem_idx_max; 844 chunk += chunksize) { 845 846 chunk_max = chunk + chunksize - 1; 847 848 if (chunk_max > mem_idx_max) { 849 chunk_max = mem_idx_max; 850 } 851 852 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 853 chunk, chunk_max, l2e); 854 if (rv < 0) { 855 break; 856 } 857 858 chnk_end = (chunk_max - chunk); 859 860 for (ix = 0; ix <= chnk_end; ix++) { 861 l2ep = soc_mem_table_idx_to_pointer(unit, mem, 862 L2_ENTRY_T *, l2e, ix); 863 if (!soc_mem_field32_get(unit, mem, l2ep, valid_f)) { 864 continue; 865 } 866 867 /* we won't check set/check FCOE_ZONE__STATIC_BITf for now... 868 if (soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__STATIC_BITf)) { 869 continue; 870 }*/ 871 872 /* Match the Key Type to FCOE */ 873 key_type = soc_mem_field32_get(unit, mem, l2ep, KEY_TYPEf); 874 875 if (key_type != TD2_L2_HASH_KEY_TYPE_FCOE_ZONE) { 876 continue; 877 } 878 879 /* match s_id */ 880 s_id = soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__S_IDf); 881 882 if (s_id != zone->s_id) { 883 continue; 884 } 885 886 if (SOC_L2_DEL_SYNC_LOCK(soc) < 0) { 887 rv = BCM_E_RESOURCE; 888 break; 889 } 890 891 if (((rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, l2ep)) < 0) || 892 ((rv = soc_l2x_sync_delete(unit, (uint32 *) l2ep, 893 (chunk + ix), 0)) < 0)) { 894 SOC_L2_DEL_SYNC_UNLOCK(soc); 895 break; 896 } 897 898 SOC_L2_DEL_SYNC_UNLOCK(soc); 899 } 900 901 if (rv < 0) { 902 break; 903 } 904 } 905 906 soc_mem_unlock(unit, mem); 907 soc_cm_sfree(unit, l2e); 908 909 return rv; 910 } 911 912 913 /* 914 * Description: 915 * Delete all zone check entries matching Destination ID 916 * Parameters: 917 * unit - device number 918 * zone - zone entry with D_ID to be deleted 919 * Return: 920 * BCM_E_XXX 921 */ 922 int 923 bcm_td2_fcoe_zone_delete_by_did (int unit, bcm_fcoe_zone_entry_t *zone) 924 { 925 int ix; 926 int key_type; 927 int chnk_end; 928 int chunksize; 929 int chunk; 930 int chunk_max; 931 int mem_idx_max; 932 L2_ENTRY_T *l2e; 933 L2_ENTRY_T *l2ep; 934 soc_control_t *soc = SOC_CONTROL(unit); 935 soc_mem_t mem; 936 int rv = BCM_E_NONE, valid_f; 937 uint32 d_id; 938 939 chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS, 940 L2_MEM_CHUNKS_DEFAULT); 941 942 mem = L2Xm; 943 valid_f = VALIDf; 944 945 #ifdef BCM_TRIDENT3_SUPPORT 946 if (SOC_IS_TRIDENT3X(unit)) 947 valid_f = BASE_VALIDf; 948 #endif 949 950 l2e = soc_cm_salloc(unit, chunksize * sizeof(*l2e), "l2entrydel_chunk"); 951 952 if (l2e == NULL) { 953 return BCM_E_MEMORY; 954 } 955 956 mem_idx_max = soc_mem_index_max(unit, mem); 957 958 soc_mem_lock(unit, mem); 959 960 for (chunk = soc_mem_index_min(unit, mem); chunk <= mem_idx_max; 961 chunk += chunksize) { 962 963 chunk_max = chunk + chunksize - 1; 964 965 if (chunk_max > mem_idx_max) { 966 chunk_max = mem_idx_max; 967 } 968 969 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 970 chunk, chunk_max, l2e); 971 if (rv < 0) { 972 break; 973 } 974 975 chnk_end = (chunk_max - chunk); 976 977 for (ix = 0; ix <= chnk_end; ix++) { 978 l2ep = soc_mem_table_idx_to_pointer(unit, mem, 979 L2_ENTRY_T *, l2e, ix); 980 if (!soc_mem_field32_get(unit, mem, l2ep, valid_f)) { 981 continue; 982 } 983 984 /* we won't check set/check FCOE_ZONE__STATIC_BITf for now... 985 if (soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__STATIC_BITf)) { 986 continue; 987 }*/ 988 989 /* Match the Key Type to FCOE */ 990 key_type = soc_mem_field32_get(unit, mem, l2ep, KEY_TYPEf); 991 992 if (key_type != TD2_L2_HASH_KEY_TYPE_FCOE_ZONE) { 993 continue; 994 } 995 996 /* match d_id */ 997 d_id = soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__D_IDf); 998 999 if (d_id != zone->d_id) { 1000 continue; 1001 } 1002 1003 if (SOC_L2_DEL_SYNC_LOCK(soc) < 0) { 1004 rv = BCM_E_RESOURCE; 1005 break; 1006 } 1007 1008 if (((rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, l2ep)) < 0) || 1009 ((rv = soc_l2x_sync_delete(unit, (uint32 *) l2ep, 1010 (chunk + ix), 0)) < 0)) { 1011 SOC_L2_DEL_SYNC_UNLOCK(soc); 1012 break; 1013 } 1014 1015 SOC_L2_DEL_SYNC_UNLOCK(soc); 1016 } 1017 1018 if (rv < 0) { 1019 break; 1020 } 1021 } 1022 1023 soc_mem_unlock(unit, mem); 1024 soc_cm_sfree(unit, l2e); 1025 1026 return rv; 1027 } 1028 1029 1030 /* 1031 * Description: 1032 * Retrieve Zone info 1033 * Parameters: 1034 * unit - device number 1035 * zone - zone entry 1036 * Return: 1037 * BCM_E_XXX 1038 */ 1039 int 1040 bcm_td2_fcoe_zone_get (int unit, bcm_fcoe_zone_entry_t *zone) 1041 { 1042 L2_ENTRY_T l2_entry; 1043 L2_ENTRY_T l2_lookup; 1044 soc_mem_t mem; 1045 soc_field_t field_key; 1046 int rv = BCM_E_NONE; 1047 int l2_index = 0; 1048 uint32 action; 1049 uint32 copy_to_cpu; 1050 1051 sal_memset(&l2_entry, 0, sizeof (l2_entry)); 1052 sal_memset(&l2_lookup, 0, sizeof (l2_lookup)); 1053 1054 mem = L2Xm; 1055 1056 field_key = TD2_L2_HASH_KEY_TYPE_FCOE_ZONE; 1057 1058 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 1059 KEY_TYPEf, field_key); /* fcoe type */ 1060 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 1061 FCOE_ZONE__VSAN_IDf, zone->vsan_id); /* vsan ID */ 1062 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 1063 FCOE_ZONE__D_IDf, zone->d_id); /* D_ID */ 1064 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 1065 FCOE_ZONE__S_IDf, zone->s_id); /* S_ID */ 1066 1067 1068 /* See if the entry exists */ 1069 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l2_index, 1070 (void *)&l2_entry, (void *)&l2_lookup, 0); 1071 1072 if (rv == SOC_E_NONE) { 1073 /* entry found */ 1074 zone->class_id = (int)soc_mem_field32_get(unit, mem, 1075 (void *)&l2_lookup, 1076 FCOE_ZONE__CLASS_IDf); 1077 action = soc_mem_field32_get(unit, mem, (void *)&l2_lookup, 1078 FCOE_ZONE__ACTIONf); 1079 #ifdef BCM_TRIDENT3_SUPPORT 1080 if (SOC_IS_TRIDENT3X(unit)) { 1081 copy_to_cpu = soc_mem_field32_get(unit, mem, (void *)&l2_lookup, 1082 FCOE_ZONE__CPUf); 1083 } else 1084 #endif /* BCM_TRIDENT3_SUPPORT */ 1085 { 1086 copy_to_cpu = soc_mem_field32_get(unit, mem, (void *)&l2_lookup, 1087 FCOE_ZONE__COPY_TO_CPUf); 1088 } 1089 1090 /* 1091 * now, combine action & copy_to_cpu and generate a 1092 * bcm_fcoe_zone_action_t. 1093 * It means bcmFcoeZoneActionAllow and bcmFcoeZoneActionCopyToCpu are 1094 * mutually exclusive. If not, zone action API definition need to be 1095 * changed. BTW, 'redirect' action is not defined in register spec... 1096 */ 1097 if (action == 1) { 1098 zone->action = bcmFcoeZoneActionAllow; 1099 } else { /* action is 0 (deny) */ 1100 zone->action = bcmFcoeZoneActionDeny; 1101 if (copy_to_cpu == 1) { 1102 zone->action = bcmFcoeZoneActionCopyToCpu; 1103 } 1104 } 1105 } 1106 1107 return rv; 1108 } 1109 1110 #ifdef INCLUDE_L3 1111 1112 /* 1113 * Description: 1114 * Allocate a next hop if needed or if incoming route->intf is an l3 egress 1115 * object then retrieve the HW nh index 1116 * Parameters: 1117 * unit - (IN) device number 1118 * route - (IN) route information to be used 1119 * index - (OUT) Index of nexthop info added 1120 * Returns: 1121 * BCM_E_XXX 1122 */ 1123 STATIC int 1124 _bcm_fcoe_add_nh_entry(int unit, bcm_fcoe_route_t *route, bcm_if_t *index) 1125 { 1126 _bcm_l3_cfg_t l3cfg; 1127 int rv = BCM_E_NONE; 1128 1129 memset(&l3cfg, 0, sizeof l3cfg); 1130 1131 if (route->flags & BCM_FCOE_COPY_TO_CPU) { 1132 l3cfg.l3c_flags |= BCM_L3_L2TOCPU; 1133 } 1134 if (route->flags & BCM_FCOE_DST_DISCARD) { 1135 l3cfg.l3c_flags |= BCM_L3_DST_DISCARD; 1136 } 1137 if (route->flags & BCM_FCOE_SRC_DISCARD) { 1138 l3cfg.l3c_flags |= BCM_L3_SRC_DISCARD; 1139 } 1140 if (route->flags & BCM_FCOE_NO_HOP_COUNT_CHANGE) { 1141 l3cfg.l3c_flags |= BCM_L3_KEEP_TTL; 1142 } 1143 if (route->flags & BCM_FCOE_MULTIPATH) { 1144 l3cfg.l3c_ecmp = 1; 1145 } 1146 1147 l3cfg.l3c_vrf = route->vrf; 1148 l3cfg.l3c_port_tgid = BCM_GPORT_MODPORT_PORT_GET(route->port); 1149 l3cfg.l3c_modid = BCM_GPORT_MODPORT_MODID_GET(route->port); 1150 l3cfg.l3c_prio = route->pri; 1151 l3cfg.l3c_lookup_class = route->lookup_class; 1152 l3cfg.l3c_intf = route->intf; 1153 1154 #ifdef BCM_TRIDENT3_SUPPORT 1155 if (SOC_IS_TRIDENT3X(unit)) { 1156 l3cfg.l3c_flags2 |= BCM_L3_FLAGS2_FCOE_ONLY; 1157 } 1158 #endif /* BCM_TRIDENT3_SUPPORT */ 1159 memcpy(&l3cfg.l3c_mac_addr, route->nexthop_mac, sizeof route->nexthop_mac); 1160 rv = _bcm_xgs3_nh_init_add(unit, &l3cfg, NULL, index); 1161 1162 return rv; 1163 } 1164 1165 /* 1166 * Description: 1167 * Create a key for the L3 table (FCOE_EXT view) based on the incoming 1168 * route structure 1169 * Parameters: 1170 * unit - (IN) device number 1171 * mem - (IN) memory to be used 1172 * table_row - (OUT) buffer containing a table row to modify 1173 * route - (IN) route information to be used 1174 * Returns: 1175 * BCM_E_XXX 1176 */ 1177 STATIC int 1178 _bcm_fcoe_route_construct_key_ext(int unit, soc_mem_t mem, uint32 *table_row, 1179 bcm_fcoe_route_t *route) 1180 { 1181 int key_type; 1182 int key_field; 1183 int key_value; 1184 1185 if (route->vrf >= SOC_VRF_MAX(unit) || route->vrf == 0) 1186 return BCM_E_PARAM; 1187 1188 soc_mem_field32_set(unit, mem, table_row, FCOE_EXT__VRF_IDf, route->vrf); 1189 1190 #ifdef BCM_TRIDENT3_SUPPORT 1191 if (SOC_IS_TRIDENT3X(unit)) { 1192 int data_type; 1193 if (route->flags & BCM_FCOE_HOST_ROUTE) { 1194 key_type = (int)TD3_L3_HASH_KEY_TYPE_FCOE_HOST_EXT; 1195 data_type = (int)TD3_L3_HASH_DATA_TYPE_FCOE_HOST_EXT; 1196 key_field = FCOE_EXT__D_IDf; 1197 key_value = route->nport_id; 1198 } else if (route->flags & BCM_FCOE_SOURCE_ROUTE) { 1199 key_type = (int)TD3_L3_HASH_KEY_TYPE_FCOE_SOURCE_MAP_EXT; 1200 data_type = (int)TD3_L3_HASH_DATA_TYPE_FCOE_SOURCE_MAP_EXT; 1201 key_field = FCOE_EXT__S_IDf; 1202 key_value = route->nport_id; 1203 } else if (route->flags & BCM_FCOE_DOMAIN_ROUTE) { 1204 key_type = (int)TD3_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT; 1205 data_type = (int)TD3_L3_HASH_DATA_TYPE_FCOE_DOMAIN_EXT; 1206 key_field = FCOE_EXT__MASKED_D_IDf; 1207 key_value = route->nport_id & route->nport_id_mask; 1208 } else { 1209 /* route must be either host, source, or domain */ 1210 return BCM_E_PARAM; 1211 } 1212 1213 soc_mem_field32_set(unit, mem, table_row, KEY_TYPEf, key_type); 1214 soc_mem_field32_set(unit, mem, table_row, DATA_TYPEf, data_type); 1215 soc_mem_field32_set(unit, mem, table_row, key_field, key_value); 1216 soc_mem_field32_set(unit, mem, table_row, BASE_VALID_0f, 1); 1217 soc_mem_field32_set(unit, mem, table_row, BASE_VALID_1f, 7); 1218 } else 1219 #endif 1220 { 1221 if (route->flags & BCM_FCOE_HOST_ROUTE) { 1222 key_type = (int)TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT; 1223 key_field = FCOE_EXT__D_IDf; 1224 key_value = route->nport_id; 1225 } else if (route->flags & BCM_FCOE_SOURCE_ROUTE) { 1226 key_type = (int)TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT; 1227 key_field = FCOE_EXT__S_IDf; 1228 key_value = route->nport_id; 1229 } else if (route->flags & BCM_FCOE_DOMAIN_ROUTE) { 1230 key_type = (int)TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT; 1231 key_field = FCOE_EXT__MASKED_D_IDf; 1232 key_value = route->nport_id & route->nport_id_mask; 1233 } else { 1234 /* route must be either host, source, or domain */ 1235 return BCM_E_PARAM; 1236 } 1237 1238 soc_mem_field32_set(unit, mem, table_row, KEY_TYPE_0f, key_type); 1239 soc_mem_field32_set(unit, mem, table_row, KEY_TYPE_1f, key_type); 1240 soc_mem_field32_set(unit, mem, table_row, key_field, key_value); 1241 soc_mem_field32_set(unit, mem, table_row, VALID_0f, 1); 1242 soc_mem_field32_set(unit, mem, table_row, VALID_1f, 1); 1243 } 1244 1245 return BCM_E_NONE; 1246 } 1247 1248 /* 1249 * Description: 1250 * Construct an L3 table key (FCOE view) from the given route 1251 * Parameters: 1252 * unit - (IN) device number 1253 * mem - (IN) memory (table) used 1254 * table_row - (OUT) buffer holding a table row 1255 * index - (IN) Index of nexthop info added 1256 * Returns: 1257 * BCM_E_XXX 1258 */ 1259 STATIC int 1260 _bcm_fcoe_route_construct_key_normal(int unit, soc_mem_t mem, uint32 *table_row, 1261 bcm_fcoe_route_t *route) 1262 { 1263 if (route->vrf >= SOC_VRF_MAX(unit) || route->vrf == 0) 1264 return BCM_E_PARAM; 1265 1266 soc_mem_field32_set(unit, mem, table_row, FCOE__VRF_IDf, route->vrf); 1267 1268 #ifdef BCM_TRIDENT3_SUPPORT 1269 if (SOC_IS_TRIDENT3X(unit)) { 1270 if (route->flags & BCM_FCOE_HOST_ROUTE) { 1271 soc_mem_field32_set(unit, mem, table_row, DATA_TYPEf, 1272 TD3_L3_HASH_DATA_TYPE_FCOE_HOST); 1273 soc_mem_field32_set(unit, mem, table_row, KEY_TYPEf, 1274 TD3_L3_HASH_KEY_TYPE_FCOE_HOST); 1275 soc_mem_field32_set(unit, mem, table_row, FCOE__D_IDf, 1276 route->nport_id); 1277 } else if (route->flags & BCM_FCOE_SOURCE_ROUTE) { 1278 soc_mem_field32_set(unit, mem, table_row, DATA_TYPEf, 1279 TD3_L3_HASH_DATA_TYPE_FCOE_SOURCE_MAP); 1280 soc_mem_field32_set(unit, mem, table_row, KEY_TYPEf, 1281 TD3_L3_HASH_KEY_TYPE_FCOE_SOURCE_MAP); 1282 soc_mem_field32_set(unit, mem, table_row, FCOE__S_IDf, 1283 route->nport_id); 1284 } else if (route->flags & BCM_FCOE_DOMAIN_ROUTE) { 1285 soc_mem_field32_set(unit, mem, table_row, DATA_TYPEf, 1286 TD3_L3_HASH_DATA_TYPE_FCOE_DOMAIN); 1287 soc_mem_field32_set(unit, mem, table_row, KEY_TYPEf, 1288 TD3_L3_HASH_KEY_TYPE_FCOE_DOMAIN); 1289 soc_mem_field32_set(unit, mem, table_row, FCOE__MASKED_D_IDf, 1290 route->nport_id & route->nport_id_mask); 1291 } else { 1292 /* route must be either host, source, or domain */ 1293 return BCM_E_PARAM; 1294 } 1295 } else 1296 #endif /* BCM_TRIDENT3_SUPPORT */ 1297 { 1298 if (route->flags & BCM_FCOE_HOST_ROUTE) { 1299 soc_mem_field32_set(unit, mem, table_row, KEY_TYPEf, 1300 TD2_L3_HASH_KEY_TYPE_FCOE_HOST); 1301 soc_mem_field32_set(unit, mem, table_row, FCOE__D_IDf, 1302 route->nport_id); 1303 } else if (route->flags & BCM_FCOE_SOURCE_ROUTE) { 1304 soc_mem_field32_set(unit, mem, table_row, KEY_TYPEf, 1305 TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP); 1306 soc_mem_field32_set(unit, mem, table_row, FCOE__S_IDf, 1307 route->nport_id); 1308 } else if (route->flags & BCM_FCOE_DOMAIN_ROUTE) { 1309 soc_mem_field32_set(unit, mem, table_row, KEY_TYPEf, 1310 TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN); 1311 soc_mem_field32_set(unit, mem, table_row, FCOE__MASKED_D_IDf, 1312 route->nport_id & route->nport_id_mask); 1313 } else { 1314 /* route must be either host, source, or domain */ 1315 return BCM_E_PARAM; 1316 } 1317 } 1318 1319 #ifdef BCM_TRIDENT3_SUPPORT 1320 if (SOC_IS_TRIDENT3X(unit)) { 1321 soc_mem_field32_set(unit, mem, table_row, BASE_VALIDf, 1); 1322 } else 1323 #endif 1324 { 1325 soc_mem_field32_set(unit, mem, table_row, VALIDf, 1); 1326 } 1327 1328 return BCM_E_NONE; 1329 } 1330 1331 1332 /* 1333 * _bcm_td2_fcoe_number_bits_set 1334 * Return the number of bits set in the input parameter i. It works, trust me. 1335 */ 1336 STATIC int 1337 _bcm_td2_fcoe_number_bits_set(uint32 i) 1338 { 1339 i = i - ((i >> 1) & 0x55555555); 1340 i = (i & 0x33333333) + ((i >> 2) & 0x33333333); 1341 return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; 1342 } 1343 1344 /* 1345 * _bcm_td2_fcoe_route_is_prefix: 1346 * Return TRUE for domain prefix routes, and FALSE for all other routes 1347 */ 1348 STATIC int 1349 _bcm_td2_fcoe_route_is_prefix(int unit, bcm_fcoe_route_t *route) 1350 { 1351 int domainPrefixLength = 0; 1352 int routeBitsSet = 0; 1353 int rv = bcm_esw_switch_control_get(unit, 1354 bcmSwitchFcoeDomainRoutePrefixLength, 1355 &domainPrefixLength); 1356 1357 if (BCM_FAILURE(rv)) { 1358 return FALSE; 1359 } 1360 1361 routeBitsSet = _bcm_td2_fcoe_number_bits_set(route->nport_id_mask); 1362 1363 return (route->flags & BCM_FCOE_DOMAIN_ROUTE) 1364 && (domainPrefixLength == routeBitsSet); 1365 } 1366 1367 /* 1368 * Description: 1369 * Convert modport-gport into the hardware specific global logical port 1370 * Parameters: 1371 * port - (IN) port 1372 * glp - (OUT) resulting global logical port 1373 * Returns: 1374 * BCM_E_XXX 1375 */ 1376 STATIC int 1377 _bcm_fcoe_port_to_glp(bcm_gport_t port, int *glp) 1378 { 1379 int base_port = BCM_GPORT_MODPORT_PORT_GET(port); 1380 int base_modid = BCM_GPORT_MODPORT_MODID_GET(port); 1381 1382 int port_id = (_BCM_TD2_L3_PORT_MASK & base_port); 1383 int modid = (_BCM_TD2_L3_MODID_MASK & base_modid) 1384 << _BCM_TD2_L3_MODID_SHIFT; 1385 1386 if (!BCM_GPORT_IS_MODPORT(port)) { 1387 return BCM_E_PARAM; 1388 } 1389 1390 *glp = (modid | port_id); 1391 return BCM_E_NONE; 1392 } 1393 1394 /* 1395 * Description: 1396 * Convert modport-gport into the hardware specific global logical port 1397 * Parameters: 1398 * port - (IN) port 1399 * glp - (OUT) resulting global logical port 1400 * Returns: 1401 * BCM_E_XXX 1402 */ 1403 STATIC int 1404 _bcm_fcoe_glp_to_port(int glp, bcm_gport_t *port) 1405 { 1406 int glp_port_id = (_BCM_TD2_L3_PORT_MASK & glp); 1407 int glp_modid = (glp >> _BCM_TD2_L3_MODID_SHIFT) & _BCM_TD2_L3_MODID_MASK; 1408 1409 BCM_GPORT_MODPORT_SET(*port, glp_modid, glp_port_id); 1410 1411 return BCM_E_NONE; 1412 } 1413 1414 /* 1415 * Description: 1416 * Validate elements of the route bcm_fcoe_route_t structure when adding 1417 * a route 1418 * Parameters: 1419 * unit - (IN) unit number 1420 * route - (IN) route to be validated 1421 * Returns: 1422 * BCM_E_XXX 1423 */ 1424 STATIC int 1425 _bcm_fcoe_validate_route(int unit, bcm_fcoe_route_t *route) 1426 { 1427 if ((route->flags & (BCM_FCOE_HOST_ROUTE 1428 | BCM_FCOE_DOMAIN_ROUTE 1429 | BCM_FCOE_SOURCE_ROUTE)) == 0) { 1430 return BCM_E_PARAM; 1431 } 1432 1433 if (BCM_XGS3_L3_EGRESS_MODE_ISSET(unit) == 0) { 1434 bcm_l3_intf_t find_if; 1435 1436 bcm_l3_intf_t_init(&find_if); 1437 find_if.l3a_intf_id = route->intf; 1438 BCM_IF_ERROR_RETURN(bcm_esw_l3_intf_get(unit, &find_if)); 1439 1440 if (BCM_MAC_IS_ZERO(route->nexthop_mac)) 1441 return BCM_E_PARAM; 1442 1443 if (!BCM_GPORT_IS_MODPORT(route->port)) 1444 return BCM_E_PARAM; 1445 } 1446 1447 if (route->vrf >= SOC_VRF_MAX(unit) || route->vrf < BCM_L3_VRF_DEFAULT) 1448 return BCM_E_PARAM; 1449 1450 if (route->nport_id == 0) 1451 return BCM_E_PARAM; 1452 1453 if (route->nport_id > FCOE_MAX_SRC_DEST_ID) 1454 return BCM_E_PARAM; 1455 1456 if (route->lookup_class < 0 || route->lookup_class > FCOE_ZONE_MAX_CLASS_ID) 1457 return BCM_E_PARAM; 1458 1459 return BCM_E_NONE; 1460 } 1461 1462 STATIC int _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(int unit) 1463 { 1464 #ifdef BCM_TRIDENT3_SUPPORT 1465 if (SOC_IS_TRIDENT3X(unit)) { 1466 return (L3_ENTRY_SINGLEm); 1467 } 1468 #endif 1469 return (L3_ENTRY_IPV4_UNICASTm); 1470 } 1471 1472 STATIC int _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(int unit) 1473 { 1474 #ifdef BCM_TRIDENT3_SUPPORT 1475 if (SOC_IS_TRIDENT3X(unit)) { 1476 return (L3_ENTRY_DOUBLEm); 1477 } 1478 #endif 1479 return (L3_ENTRY_IPV4_MULTICASTm); 1480 } 1481 /* 1482 * Description: 1483 * Add a route to the L3 table (FCOE view) 1484 * Parameters: 1485 * unit - (IN) unit number 1486 * route - (IN) route to be added 1487 * Returns: 1488 * BCM_E_XXX 1489 */ 1490 STATIC int 1491 _bcm_td2_fcoe_route_add_normal(int unit, bcm_fcoe_route_t *route, 1492 bcm_if_t nh_idx) 1493 { 1494 l3_entry_ipv4_unicast_entry_t l3_entry[2]; 1495 1496 soc_mem_t mem = _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit); 1497 uint32 *buf = (uint32 *)&l3_entry[0]; 1498 uint32 *lookup = (uint32 *)&l3_entry[1]; 1499 int existing_index = 0; 1500 int rv; 1501 1502 if (route->flags & BCM_FCOE_NO_HOP_COUNT_CHANGE) { 1503 return BCM_E_PARAM; 1504 } 1505 1506 memset(&l3_entry, 0, sizeof l3_entry); 1507 1508 BCM_IF_ERROR_RETURN(_bcm_fcoe_validate_route(unit, route)); 1509 BCM_IF_ERROR_RETURN(_bcm_fcoe_route_construct_key_normal(unit, mem, buf, 1510 route)); 1511 1512 soc_mem_field32_set(unit, mem, buf, FCOE__DST_DISCARDf, 1513 (route->flags & BCM_FCOE_DST_DISCARD) ? 1 : 0); 1514 soc_mem_field32_set(unit, mem, buf, FCOE__PRIf, route->pri); 1515 soc_mem_field32_set(unit, mem, buf, FCOE__RPEf, 1516 (route->flags & BCM_FCOE_RPE) ? 1 : 0); 1517 soc_mem_field32_set(unit, mem, buf, FCOE__CLASS_IDf, route->lookup_class); 1518 1519 /* BCM_FCOE_LOCAL_ADDRESS is only valid in host route mode */ 1520 if ((route->flags & BCM_FCOE_HOST_ROUTE) 1521 && (route->flags & BCM_FCOE_LOCAL_ADDRESS)) { 1522 soc_mem_field32_set(unit, mem, buf, FCOE__LOCAL_ADDRESSf, 1); 1523 } 1524 1525 if (route->flags & BCM_FCOE_MULTIPATH) { 1526 #ifdef BCM_TRIDENT3_SUPPORT 1527 if (SOC_IS_TRIDENT3X(unit)) { 1528 soc_mem_field32_dest_set(unit, mem, buf, FCOE__DESTINATIONf, 1529 SOC_MEM_FIF_DEST_ECMP, nh_idx); 1530 1531 } else 1532 #endif 1533 { 1534 soc_mem_field32_set(unit, mem, buf, FCOE__ECMP_PTR0f, nh_idx); 1535 soc_mem_field32_set(unit, mem, buf, FCOE__ECMPf, 1); 1536 } 1537 } else { 1538 #ifdef BCM_TRIDENT3_SUPPORT 1539 if (SOC_IS_TRIDENT3X(unit)) { 1540 soc_mem_field32_dest_set(unit, mem, buf, FCOE__DESTINATIONf, 1541 SOC_MEM_FIF_DEST_NEXTHOP, nh_idx); 1542 } else 1543 #endif 1544 { 1545 soc_mem_field32_set(unit, mem, buf, FCOE__NEXT_HOP_INDEXf, nh_idx); 1546 } 1547 } 1548 1549 /* Search for this key in the existing database */ 1550 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &existing_index, buf, 1551 (void *)lookup, 0); 1552 1553 /* 1554 * If the entry exists, overwrite it with the new data, otherwise insert 1555 * a new entry 1556 */ 1557 if (rv == SOC_E_NONE) { 1558 /* 1559 * Route exists, and the reference count of old nhi should be adjusted. 1560 * The current route will be updated to new nhi. 1561 */ 1562 bcm_if_t old_nh_idx = 0; 1563 #ifdef BCM_TRIDENT3_SUPPORT 1564 if (SOC_IS_TRIDENT3X(unit)) { 1565 uint32 dest_type = SOC_MEM_FIF_DEST_INVALID; 1566 1567 old_nh_idx = soc_mem_field32_dest_get(unit, mem, lookup, 1568 DESTINATIONf, &dest_type); 1569 if (dest_type == SOC_MEM_FIF_DEST_ECMP) { 1570 BCM_IF_ERROR_RETURN(bcm_xgs3_ecmp_group_del(unit, old_nh_idx, 0)); 1571 } else { 1572 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, old_nh_idx)); 1573 } 1574 } else 1575 #endif 1576 { 1577 if (soc_mem_field32_get(unit, mem, lookup, FCOE__ECMPf)) { 1578 old_nh_idx = soc_mem_field32_get(unit, mem, 1579 lookup, FCOE__ECMP_PTR0f); 1580 BCM_IF_ERROR_RETURN(bcm_xgs3_ecmp_group_del(unit, old_nh_idx, 0)); 1581 } else { 1582 old_nh_idx= soc_mem_field32_get(unit, mem, lookup, 1583 FCOE__NEXT_HOP_INDEXf); 1584 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, old_nh_idx)); 1585 } 1586 } 1587 } 1588 1589 L3_LOCK(unit); 1590 if (rv == SOC_E_NONE) { 1591 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, existing_index, buf); 1592 } else if (rv == SOC_E_NOT_FOUND) { 1593 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ANY, buf); 1594 } 1595 L3_UNLOCK(unit); 1596 1597 return rv; 1598 } 1599 1600 /* 1601 * Description: 1602 * Add a route to the L3 table (FCOE_EXT view) 1603 * Parameters: 1604 * unit - (IN) unit number 1605 * route - (IN) route to be added 1606 * Returns: 1607 * BCM_E_XXX 1608 */ 1609 STATIC int 1610 _bcm_td2_fcoe_route_add_ext(int unit, bcm_fcoe_route_t *route) 1611 { 1612 l3_entry_ipv4_multicast_entry_t l3_ext_entry[2]; 1613 1614 soc_mem_t mem = _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit); 1615 uint32 *buf = (uint32 *)&l3_ext_entry[0]; 1616 uint32 *lookup = (uint32 *)&l3_ext_entry[1]; 1617 int existing_index = 0; 1618 int rv; 1619 int glp; 1620 1621 memset(&l3_ext_entry, 0, sizeof l3_ext_entry); 1622 1623 BCM_IF_ERROR_RETURN(_bcm_fcoe_validate_route(unit, route)); 1624 BCM_IF_ERROR_RETURN(_bcm_fcoe_route_construct_key_ext(unit, mem, buf, 1625 route)); 1626 1627 soc_mem_field32_set(unit, mem, buf, FCOE_EXT__DST_DISCARDf, 1628 (route->flags & BCM_FCOE_DST_DISCARD) ? 1 : 0); 1629 soc_mem_field32_set(unit, mem, buf, FCOE_EXT__PRIf, route->pri); 1630 soc_mem_field32_set(unit, mem, buf, FCOE_EXT__RPEf, 1631 (route->flags & BCM_FCOE_RPE) ? 1 : 0); 1632 soc_mem_field32_set(unit, mem, buf, FCOE_EXT__CLASS_IDf, 1633 route->lookup_class); 1634 1635 /* BCM_FCOE_LOCAL_ADDRESS is only valid in host route mode */ 1636 if ((route->flags & BCM_FCOE_HOST_ROUTE) 1637 && (route->flags & BCM_FCOE_LOCAL_ADDRESS)) { 1638 1639 soc_mem_field32_set(unit, mem, buf, FCOE_EXT__LOCAL_ADDRESSf, 1); 1640 } 1641 1642 BCM_IF_ERROR_RETURN(_bcm_fcoe_port_to_glp(route->port, &glp)); 1643 1644 soc_mem_field32_set(unit, mem, buf, FCOE_EXT__L3_INTF_NUMf, 1645 route->intf); 1646 soc_mem_mac_addr_set(unit, mem, buf, FCOE_EXT__MAC_ADDRf, 1647 route->nexthop_mac); 1648 soc_mem_field32_set(unit, mem, buf, FCOE_EXT__COPY_TO_CPUf, 1649 (route->flags & BCM_FCOE_COPY_TO_CPU) ? 1 : 0); 1650 #ifdef BCM_TRIDENT3_SUPPORT 1651 if (SOC_IS_TRIDENT3X(unit)) { 1652 uint32 physical_port; 1653 soc_mem_field32_set(unit, mem, buf, FCOE_EXT__DO_NOT_DECREMENT_TTLf, 1654 (route->flags & BCM_FCOE_NO_HOP_COUNT_CHANGE) 1655 ? 1 : 0); 1656 1657 physical_port = (BCM_GPORT_MODPORT_MODID_GET(route->port) << 1658 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS) | 1659 BCM_GPORT_MODPORT_PORT_GET(route->port); 1660 1661 soc_mem_field32_dest_set(unit, mem, buf, FCOE_EXT__DESTINATIONf, 1662 SOC_MEM_FIF_DEST_DGPP, physical_port); 1663 } else 1664 #endif 1665 { 1666 soc_mem_field32_set(unit, mem, buf, FCOE_EXT__DO_NOT_CHANGE_TTLf, 1667 (route->flags & BCM_FCOE_NO_HOP_COUNT_CHANGE) 1668 ? 1 : 0); 1669 soc_mem_field32_set(unit, mem, buf, FCOE_EXT__GLPf, glp); 1670 } 1671 1672 /* Search for this key in the existing database */ 1673 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &existing_index, buf, 1674 (void *)lookup, 0); 1675 1676 /* 1677 * If the entry exists, overwrite it with the new data, otherwise insert 1678 * a new entry 1679 */ 1680 L3_LOCK(unit); 1681 if (rv == SOC_E_NONE) { 1682 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, existing_index, buf); 1683 } else if (rv == SOC_E_NOT_FOUND) { 1684 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ANY, buf); 1685 } 1686 L3_UNLOCK(unit); 1687 1688 return rv; 1689 } 1690 1691 STATIC int 1692 _bcm_fcoe_route_to_defip(int unit, bcm_fcoe_route_t *route, 1693 _bcm_defip_cfg_t *lpm_cfg) 1694 { 1695 int rv = BCM_E_NONE; 1696 _bcm_defip_cfg_t entry; 1697 int nh_ecmp_index; 1698 1699 sal_memset(lpm_cfg, 0, sizeof *lpm_cfg); 1700 1701 if (route->flags & BCM_FCOE_COPY_TO_CPU) { 1702 lpm_cfg->defip_flags |= BCM_L3_L2TOCPU; 1703 } 1704 if (route->flags & BCM_FCOE_DST_DISCARD) { 1705 lpm_cfg->defip_flags |= BCM_L3_DST_DISCARD; 1706 } 1707 if (route->flags & BCM_FCOE_SRC_DISCARD) { 1708 lpm_cfg->defip_flags |= BCM_L3_SRC_DISCARD; 1709 } 1710 if (route->flags & BCM_FCOE_NO_HOP_COUNT_CHANGE) { 1711 lpm_cfg->defip_flags |= BCM_L3_KEEP_TTL; 1712 } 1713 if (route->flags & BCM_FCOE_MULTIPATH) { 1714 lpm_cfg->defip_ecmp = 1; 1715 lpm_cfg->defip_flags |= BCM_L3_MULTIPATH; 1716 } 1717 1718 lpm_cfg->defip_vrf = route->vrf; 1719 lpm_cfg->defip_port_tgid = BCM_GPORT_MODPORT_PORT_GET(route->port); 1720 lpm_cfg->defip_modid = BCM_GPORT_MODPORT_MODID_GET(route->port); 1721 lpm_cfg->defip_prio = route->pri; 1722 lpm_cfg->defip_lookup_class = route->lookup_class; 1723 lpm_cfg->defip_intf = route->intf; 1724 lpm_cfg->defip_entry_type = bcmDefipEntryTypeFcoe; 1725 lpm_cfg->defip_fcoe_d_id = route->nport_id & route->nport_id_mask; 1726 lpm_cfg->defip_fcoe_d_id_mask = route->nport_id_mask; 1727 1728 memcpy(&lpm_cfg->defip_mac_addr, route->nexthop_mac, 1729 sizeof route->nexthop_mac); 1730 entry = *lpm_cfg; 1731 rv = _bcm_fb_lpm_get(unit, &entry, &nh_ecmp_index); 1732 if (BCM_SUCCESS(rv)) { 1733 /* Save route entry index in hw to indicate */ 1734 lpm_cfg->defip_index = entry.defip_index; 1735 } else if (rv == BCM_E_NOT_FOUND){ 1736 /* New route. */ 1737 lpm_cfg->defip_index = BCM_XGS3_L3_INVALID_INDEX; 1738 rv = BCM_E_NONE; 1739 } 1740 1741 return rv; 1742 } 1743 1744 STATIC int 1745 _bcm_fcoe_defip_to_route(int unit, _bcm_defip_cfg_t *lpm_cfg, 1746 bcm_fcoe_route_t *route) 1747 { 1748 int rv = BCM_E_NONE; 1749 1750 sal_memset(route, 0, sizeof *route); 1751 1752 route->flags = BCM_FCOE_DOMAIN_ROUTE; 1753 1754 if (lpm_cfg->defip_flags & BCM_L3_L2TOCPU) { 1755 route->flags |= BCM_FCOE_COPY_TO_CPU; 1756 } 1757 1758 if (lpm_cfg->defip_flags & BCM_L3_DST_DISCARD) { 1759 route->flags |= BCM_FCOE_DST_DISCARD; 1760 } 1761 1762 if (lpm_cfg->defip_flags & BCM_L3_SRC_DISCARD) { 1763 route->flags |= BCM_FCOE_SRC_DISCARD; 1764 } 1765 1766 if (lpm_cfg->defip_flags & BCM_L3_KEEP_TTL) { 1767 route->flags |= BCM_FCOE_NO_HOP_COUNT_CHANGE; 1768 } 1769 1770 if (lpm_cfg->defip_ecmp == 1) { 1771 route->flags |= BCM_FCOE_MULTIPATH; 1772 } 1773 1774 route->vrf = lpm_cfg->defip_vrf; 1775 BCM_GPORT_MODPORT_SET(route->port, lpm_cfg->defip_modid, 1776 lpm_cfg->defip_port_tgid); 1777 1778 route->pri = lpm_cfg->defip_prio; 1779 route->lookup_class = lpm_cfg->defip_lookup_class; 1780 route->intf = lpm_cfg->defip_intf; 1781 route->nport_id = lpm_cfg->defip_fcoe_d_id; 1782 route->nport_id_mask = lpm_cfg->defip_fcoe_d_id_mask; 1783 1784 memcpy(route->nexthop_mac, &lpm_cfg->defip_mac_addr, 1785 sizeof route->nexthop_mac); 1786 1787 return rv; 1788 } 1789 1790 STATIC int 1791 _bcm_td2_fcoe_route_add_prefix(int unit, bcm_fcoe_route_t *route) 1792 { 1793 _bcm_defip_cfg_t lpm_cfg; 1794 int nh_idx = 0; 1795 int rv = BCM_E_NONE; 1796 int old_nh_idx = 0; 1797 _bcm_defip_cfg_t old_lpm_cfg; 1798 1799 sal_memset(&lpm_cfg, 0, sizeof lpm_cfg); 1800 1801 BCM_IF_ERROR_RETURN(_bcm_fcoe_validate_route(unit, route)); 1802 BCM_IF_ERROR_RETURN(_bcm_fcoe_route_to_defip(unit, route, &lpm_cfg)); 1803 sal_memcpy(&old_lpm_cfg, &lpm_cfg, sizeof(_bcm_defip_cfg_t)); 1804 rv = _bcm_fb_lpm_get(unit, &old_lpm_cfg, &old_nh_idx); 1805 if (BCM_SUCCESS(rv)) { 1806 /* 1807 * Route exists, and the reference count of old nhi should be adjusted. 1808 * The current route is updated to new nhi. 1809 */ 1810 if (old_lpm_cfg.defip_flags & BCM_L3_MULTIPATH) { 1811 BCM_IF_ERROR_RETURN(bcm_xgs3_ecmp_group_del(unit, old_nh_idx, 0)); 1812 } else { 1813 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, old_nh_idx)); 1814 } 1815 } 1816 BCM_IF_ERROR_RETURN(_bcm_xgs3_nh_init_add(unit, NULL, &lpm_cfg, &nh_idx)); 1817 1818 rv = _bcm_fb_lpm_add(unit, &lpm_cfg, nh_idx); 1819 if (BCM_FAILURE(rv)) { 1820 if (route->flags & BCM_FCOE_MULTIPATH) { 1821 (void) bcm_xgs3_ecmp_group_del(unit, nh_idx, 0); 1822 } else { 1823 (void) bcm_xgs3_nh_del(unit, 0, nh_idx); 1824 } 1825 return rv; 1826 } 1827 1828 return BCM_E_NONE; 1829 } 1830 1831 /* 1832 * Description: 1833 * Add an entry into FCOE host routing table. Supports add for both 1834 * normal (with next-hop) and extended views (embedded nh) 1835 * Parameters: 1836 * unit - device number 1837 * route - route information to be added 1838 * Returns: 1839 * BCM_E_XXX 1840 */ 1841 STATIC int 1842 _bcm_td2_fcoe_route_add_host(int unit, bcm_fcoe_route_t *route) 1843 { 1844 int rv = BCM_E_NONE; 1845 bcm_if_t nh_idx; 1846 1847 BCM_IF_ERROR_RETURN(_bcm_fcoe_add_nh_entry(unit, route, &nh_idx)); 1848 1849 if (BCM_TD2_L3_USE_EMBEDDED_NEXT_HOP(unit, route->intf, nh_idx)) { 1850 rv = _bcm_td2_fcoe_route_add_ext(unit, route); 1851 } else { 1852 rv = _bcm_td2_fcoe_route_add_normal(unit, route, nh_idx); 1853 } 1854 1855 if (BCM_FAILURE(rv) && (nh_idx != BCM_XGS3_L3_INVALID_INDEX) && 1856 !(route->flags & BCM_FCOE_MULTIPATH)) { 1857 (void)bcm_xgs3_nh_del(unit, 0, nh_idx); 1858 } 1859 1860 return rv; 1861 } 1862 1863 #endif 1864 1865 /* 1866 * Description: 1867 * Add an entry into the FCOE routing table. This API supports all 1868 * three routes: 1869 * - Host, source-map, Domain (goes in L3_ENTRY table) 1870 * - Prefix (goes in DEFIP table) 1871 * Parameters: 1872 * unit - device number 1873 * route - route information to be added 1874 * Returns: 1875 * BCM_E_XXX 1876 */ 1877 int 1878 bcm_td2_fcoe_route_add(int unit, bcm_fcoe_route_t *route) 1879 { 1880 #ifdef INCLUDE_L3 1881 if (_bcm_td2_fcoe_route_is_prefix(unit, route)) { 1882 return _bcm_td2_fcoe_route_add_prefix(unit, route); 1883 } else { 1884 return _bcm_td2_fcoe_route_add_host(unit, route); 1885 } 1886 #else 1887 return BCM_E_UNAVAIL; 1888 #endif 1889 } 1890 1891 #ifdef INCLUDE_L3 1892 1893 /* 1894 * Description: 1895 * Delete a route from the DEFIP table 1896 * Parameters: 1897 * unit - (IN) unit number 1898 * route - (IN) route to be deleted 1899 * Returns: 1900 * BCM_E_XXX 1901 */ 1902 STATIC int 1903 _bcm_td2_fcoe_route_delete_prefix(int unit, uint32 *lookup) 1904 { 1905 int nh_idx = 0; 1906 _bcm_defip_cfg_t lpm_cfg; 1907 1908 sal_memset(&lpm_cfg, 0, sizeof lpm_cfg); 1909 1910 #ifdef BCM_TRIDENT3_SUPPORT 1911 if (SOC_IS_TRIDENT3X(unit)) { 1912 uint32 dest_type; 1913 1914 /* delete the left half if it's a valid FCOE entry */ 1915 if (soc_L3_DEFIPm_field32_get(unit, lookup, VALID0f) 1916 && (soc_L3_DEFIPm_field32_get(unit, lookup, DATA_TYPE0f) == 3)) { 1917 1918 BCM_IF_ERROR_RETURN( 1919 _bcm_fb_lpm_ent_parse(unit, &lpm_cfg, &nh_idx, 1920 (uint32 *)lookup, NULL)); 1921 lpm_cfg.defip_index = BCM_XGS3_L3_INVALID_INDEX; 1922 BCM_IF_ERROR_RETURN(_bcm_fb_lpm_del(unit, &lpm_cfg)); 1923 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, nh_idx)); 1924 } 1925 1926 /* 1927 * if the right half is a valid FCOE entry, copy it to the left half and 1928 * then delete 1929 */ 1930 if (soc_L3_DEFIPm_field32_get(unit, lookup, VALID1f) 1931 && (soc_L3_DEFIPm_field32_get(unit, lookup, DATA_TYPE1f) == 3)) { 1932 nh_idx = soc_mem_field32_dest_get(unit, L3_DEFIPm, lookup, 1933 DESTINATIONf, &dest_type); 1934 BCM_IF_ERROR_RETURN(soc_fb_lpm_ip4entry1_to_0(unit, lookup, lookup, 0)); 1935 BCM_IF_ERROR_RETURN(soc_fb_lpm_delete(unit, lookup)); 1936 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, nh_idx)); 1937 } 1938 } else 1939 #endif 1940 { 1941 /* delete the left half if it's a valid FCOE entry */ 1942 if (soc_L3_DEFIPm_field32_get(unit, lookup, VALID0f) 1943 && (soc_L3_DEFIPm_field32_get(unit, lookup, ENTRY_TYPE0f) == 1)) { 1944 1945 BCM_IF_ERROR_RETURN( 1946 _bcm_fb_lpm_ent_parse(unit, &lpm_cfg, &nh_idx, 1947 (uint32 *)lookup, NULL)); 1948 1949 lpm_cfg.defip_index = BCM_XGS3_L3_INVALID_INDEX; 1950 BCM_IF_ERROR_RETURN(_bcm_fb_lpm_del(unit, &lpm_cfg)); 1951 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, nh_idx)); 1952 } 1953 1954 /* 1955 * if the right half is a valid FCOE entry, copy it to the left half and 1956 * then delete 1957 */ 1958 if (soc_L3_DEFIPm_field32_get(unit, lookup, VALID1f) 1959 && (soc_L3_DEFIPm_field32_get(unit, lookup, ENTRY_TYPE1f) == 1)) { 1960 1961 nh_idx = soc_L3_DEFIPm_field32_get(unit, lookup, NEXT_HOP_INDEX1f); 1962 BCM_IF_ERROR_RETURN(soc_fb_lpm_ip4entry1_to_0(unit, lookup, lookup, 0)); 1963 BCM_IF_ERROR_RETURN(soc_fb_lpm_delete(unit, lookup)); 1964 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, nh_idx)); 1965 } 1966 } 1967 1968 return BCM_E_NONE; 1969 } 1970 1971 /* 1972 * Description: 1973 * Delete a route from hardware. If the route has a corresponding nexthop 1974 * index, delete that too (or decrement refcount). 1975 * Parameters: 1976 * unit - (IN) unit number 1977 * mem - (IN) memory to be deleted from 1978 * lookup - (IN) table lookup result to be deleted 1979 * Returns: 1980 * BCM_E_XXX 1981 */ 1982 STATIC int 1983 _bcm_td2_fcoe_internal_delete_route(int unit, bcm_fcoe_route_t *route, 1984 soc_mem_t mem, uint32 *lookup) 1985 { 1986 int rv = BCM_E_NONE; 1987 int next_hop_index = 0; 1988 int nh_field = FCOE__NEXT_HOP_INDEXf; 1989 1990 if (mem == L3_DEFIPm) { 1991 return _bcm_td2_fcoe_route_delete_prefix(unit, lookup); 1992 } 1993 1994 #ifdef BCM_TRIDENT3_SUPPORT 1995 if (SOC_IS_TRIDENT3X(unit)) { 1996 nh_field = DESTINATIONf; 1997 } 1998 #endif 1999 2000 if (SOC_MEM_FIELD_VALID(unit, mem, nh_field)) { 2001 #ifdef BCM_TRIDENT3_SUPPORT 2002 if (SOC_IS_TRIDENT3X(unit)) { 2003 uint32 dest_type; 2004 next_hop_index = soc_mem_field32_dest_get(unit, mem, lookup, 2005 nh_field, &dest_type); 2006 if (dest_type == SOC_MEM_FIF_DEST_ECMP){ 2007 if ((route != NULL) && !(route->flags & BCM_FCOE_MULTIPATH)) { 2008 return BCM_E_PARAM; 2009 } 2010 rv = bcm_xgs3_ecmp_group_del(unit, next_hop_index, 0); 2011 } else { 2012 rv = bcm_xgs3_nh_del(unit, 0, next_hop_index); 2013 } 2014 } else 2015 #endif 2016 { 2017 next_hop_index = soc_mem_field32_get(unit, mem, lookup, nh_field); 2018 if (SOC_MEM_FIELD_VALID(unit, mem, FCOE__ECMPf) && 2019 soc_mem_field32_get(unit, mem, lookup, FCOE__ECMPf)) { 2020 if ((route != NULL) && !(route->flags & BCM_FCOE_MULTIPATH)) { 2021 return BCM_E_PARAM; 2022 } 2023 rv = bcm_xgs3_ecmp_group_del(unit, next_hop_index, 0); 2024 } else { 2025 rv = bcm_xgs3_nh_del(unit, 0, next_hop_index); 2026 } 2027 } 2028 } 2029 2030 if (BCM_SUCCESS(rv)) { 2031 L3_LOCK(unit); 2032 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, (void *)lookup); 2033 L3_UNLOCK(unit); 2034 } 2035 2036 return rv; 2037 } 2038 2039 /* 2040 * Description: 2041 * Delete a route from the L3 table (FCOE view) 2042 * Parameters: 2043 * unit - (IN) unit number 2044 * route - (IN) route to be deleted 2045 * Returns: 2046 * BCM_E_XXX 2047 */ 2048 STATIC int 2049 _bcm_td2_fcoe_route_delete_normal(int unit, bcm_fcoe_route_t *route) 2050 { 2051 l3_entry_ipv4_unicast_entry_t l3_entry[2]; 2052 2053 soc_mem_t mem = _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit); 2054 uint32 *buf = (uint32 *)&l3_entry[0]; 2055 uint32 *lookup = (uint32 *)&l3_entry[1]; 2056 int existing_index = 0; 2057 int rv; 2058 2059 memset(&l3_entry, 0, sizeof l3_entry); 2060 2061 BCM_IF_ERROR_RETURN(_bcm_fcoe_route_construct_key_normal(unit, mem, buf, 2062 route)); 2063 2064 /* Search for this key in the existing database */ 2065 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &existing_index, buf, 2066 (void *)lookup, 0); 2067 switch (rv) { 2068 case SOC_E_NOT_FOUND: return BCM_E_NOT_FOUND; 2069 case SOC_E_NONE: break; 2070 default: return BCM_E_PARAM; 2071 } 2072 2073 return _bcm_td2_fcoe_internal_delete_route(unit, route, mem, lookup); 2074 } 2075 2076 /* 2077 * Description: 2078 * Delete a route from the L3 table (FCOE_EXT view) 2079 * Parameters: 2080 * unit - (IN) unit number 2081 * route - (IN) route to be deleted 2082 * Returns: 2083 * BCM_E_XXX 2084 */ 2085 STATIC int 2086 _bcm_td2_fcoe_route_delete_ext(int unit, bcm_fcoe_route_t *route) 2087 { 2088 l3_entry_ipv4_multicast_entry_t l3_ext_entry[2]; 2089 2090 soc_mem_t mem = _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit); 2091 uint32 *buf = (uint32 *)&l3_ext_entry[0]; 2092 uint32 *lookup = (uint32 *)&l3_ext_entry[1]; 2093 int existing_index = 0; 2094 int rv; 2095 2096 memset(&l3_ext_entry, 0, sizeof l3_ext_entry); 2097 2098 BCM_IF_ERROR_RETURN(_bcm_fcoe_route_construct_key_ext(unit, mem, buf, 2099 route)); 2100 2101 /* Search for this key in the existing database */ 2102 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &existing_index, buf, 2103 (void *)lookup, 0); 2104 switch (rv) { 2105 case SOC_E_NOT_FOUND: return BCM_E_NOT_FOUND; 2106 case SOC_E_NONE: break; 2107 default: return BCM_E_PARAM; 2108 } 2109 2110 return _bcm_td2_fcoe_internal_delete_route(unit, route, mem, lookup); 2111 } 2112 2113 STATIC int 2114 _bcm_td2_find_and_delete_defip(int unit, bcm_fcoe_route_t *route) 2115 { 2116 _bcm_defip_cfg_t lpm_cfg; 2117 int nh_idx; 2118 2119 sal_memset(&lpm_cfg, 0, sizeof lpm_cfg); 2120 2121 BCM_IF_ERROR_RETURN(_bcm_fcoe_route_to_defip(unit, route, &lpm_cfg)); 2122 BCM_IF_ERROR_RETURN(_bcm_fb_lpm_get(unit, &lpm_cfg, &nh_idx)); 2123 BCM_IF_ERROR_RETURN(_bcm_fb_lpm_del(unit, &lpm_cfg)); 2124 if (route->flags & BCM_FCOE_MULTIPATH) { 2125 BCM_IF_ERROR_RETURN( 2126 bcm_xgs3_ecmp_group_del(unit, nh_idx, 0)); 2127 } else { 2128 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, nh_idx)); 2129 } 2130 2131 return BCM_E_NONE; 2132 } 2133 2134 #endif 2135 2136 /* 2137 * Description: 2138 * Delete a route from the L3 table 2139 * Parameters: 2140 * unit - (IN) unit number 2141 * route - (IN) route to be added 2142 * Returns: 2143 * BCM_E_XXX 2144 */ 2145 int 2146 bcm_td2_fcoe_route_delete(int unit, bcm_fcoe_route_t *route) 2147 { 2148 int rv = BCM_E_UNAVAIL; 2149 2150 #ifdef INCLUDE_L3 2151 if (route == NULL) { 2152 return BCM_E_NONE; 2153 } 2154 2155 if (_bcm_td2_fcoe_route_is_prefix(unit, route)) { 2156 return _bcm_td2_find_and_delete_defip(unit, route); 2157 } else { 2158 rv = _bcm_td2_fcoe_route_delete_ext(unit, route); 2159 if (rv == BCM_E_NOT_FOUND) { 2160 rv = _bcm_td2_fcoe_route_delete_normal(unit, route); 2161 } 2162 } 2163 #endif 2164 2165 return rv; 2166 } 2167 2168 #ifdef INCLUDE_L3 2169 2170 /* 2171 * Description: 2172 * Given a buffer holding a table row, retrieve the VRF 2173 * Parameters: 2174 * unit - (IN) unit number 2175 * mem - (IN) table type 2176 * buf - (IN) buffer holding table data 2177 * vrf - (OUT) VRF from table 2178 * Returns: 2179 * BCM_E_XXX 2180 */ 2181 STATIC int 2182 _bcm_td2_mem_get_vrf(int unit, soc_mem_t mem, uint32 *buf, int *vrf) 2183 { 2184 if (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) { 2185 *vrf = soc_mem_field32_get(unit, mem, buf, FCOE_EXT__VRF_IDf); 2186 } else if (mem == _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit)) { 2187 *vrf = soc_mem_field32_get(unit, mem, buf, FCOE__VRF_IDf); 2188 } else if (mem == L3_DEFIPm) { 2189 int entry_type = soc_mem_field32_get(unit, mem, buf, ENTRY_TYPE0f); 2190 if (entry_type == 1) { 2191 *vrf = soc_mem_field32_get(unit, mem, buf, VRF_ID_0f); 2192 } else { 2193 *vrf = soc_mem_field32_get(unit, mem, buf, VRF_ID_1f); 2194 } 2195 } else { 2196 return BCM_E_FAIL; 2197 } 2198 2199 return BCM_E_NONE; 2200 } 2201 2202 /* 2203 * Description: 2204 * Given a buffer holding a table row, retrieve the L3 interface number 2205 * Parameters: 2206 * unit - (IN) unit number 2207 * mem - (IN) table type 2208 * buf - (IN) buffer holding table data 2209 * intf - (OUT) L3_INTF_NUM from table 2210 * Returns: 2211 * BCM_E_XXX 2212 */ 2213 STATIC int 2214 _bcm_td2_mem_get_intf(int unit, soc_mem_t mem, uint32 *buf, int *intf) 2215 { 2216 if (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) { 2217 *intf = soc_mem_field32_get(unit, mem, buf, FCOE_EXT__L3_INTF_NUMf); 2218 return BCM_E_NONE; 2219 } else { 2220 return BCM_E_FAIL; 2221 } 2222 } 2223 2224 /* 2225 * Description: 2226 * Given a buffer holding a table row, retrieve the key type 2227 * Parameters: 2228 * unit - (IN) unit number 2229 * mem - (IN) table type 2230 * buf - (IN) buffer holding table data 2231 * key_type - (OUT) KEY_TYPE from table 2232 * Returns: 2233 * BCM_E_XXX 2234 */ 2235 STATIC int 2236 _bcm_td2_mem_get_key_type(int unit, soc_mem_t mem, uint32 *buf, int *key_type) 2237 { 2238 if (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) { 2239 #ifdef BCM_TRIDENT3_SUPPORT 2240 if (SOC_IS_TRIDENT3X(unit)) { 2241 *key_type = soc_mem_field32_get(unit, mem, buf, KEY_TYPEf); 2242 } else 2243 #endif 2244 { 2245 *key_type = soc_mem_field32_get(unit, mem, buf, KEY_TYPE_0f); 2246 } 2247 } else if (mem == _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit)) { 2248 *key_type = soc_mem_field32_get(unit, mem, buf, KEY_TYPEf); 2249 } else if (mem == L3_DEFIPm) { 2250 *key_type = TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN; 2251 } else { 2252 return BCM_E_FAIL; 2253 } 2254 2255 return BCM_E_NONE; 2256 } 2257 2258 /* 2259 * Description: 2260 * Given a buffer holding a table row, retrieve the nport_id 2261 * Parameters: 2262 * unit - (IN) unit number 2263 * mem - (IN) table type 2264 * buf - (IN) buffer holding table data 2265 * id - (OUT) D_ID or S_ID from table 2266 * Returns: 2267 * BCM_E_XXX 2268 */ 2269 STATIC int 2270 _bcm_td2_mem_get_id(int unit, soc_mem_t mem, uint32 *buf, uint32 *id) 2271 { 2272 int key_type; 2273 int id_key; 2274 2275 BCM_IF_ERROR_RETURN(_bcm_td2_mem_get_key_type(unit, mem, buf, &key_type)); 2276 2277 if (mem == L3_DEFIPm) { 2278 int entry_type = soc_mem_field32_get(unit, mem, buf, ENTRY_TYPE0f); 2279 if (entry_type == 1) { 2280 id_key = D_ID0f; 2281 } else { 2282 id_key = D_ID1f; 2283 } 2284 } else { 2285 switch (key_type) { 2286 2287 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST: 2288 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT: 2289 id_key = (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) 2290 ? FCOE_EXT__D_IDf : FCOE__D_IDf; 2291 break; 2292 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN: 2293 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT: 2294 id_key = (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) 2295 ? FCOE_EXT__MASKED_D_IDf : FCOE__MASKED_D_IDf; 2296 break; 2297 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP: 2298 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT: 2299 id_key = (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) 2300 ? FCOE_EXT__S_IDf : FCOE__S_IDf; 2301 break; 2302 default: 2303 return BCM_E_PARAM; 2304 } 2305 } 2306 2307 *id = soc_mem_field32_get(unit, mem, buf, id_key); 2308 2309 return BCM_E_NONE; 2310 } 2311 /* 2312 * Description: 2313 * Determine if the given key type is an FCOE key for the given table. 2314 * Parameters: 2315 * mem - (IN) table type 2316 * key_type - (IN) key type field from the table row 2317 * Returns: 2318 * 0 indicates "not an FCOE key" 2319 * 1 indicates "is an FCOE key" 2320 */ 2321 #ifdef BCM_TRIDENT3_SUPPORT 2322 STATIC int 2323 _bcm_td3_key_type_is_fcoe(int unit, soc_mem_t mem, int key_type_0, int key_type_1) 2324 { 2325 if (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) { 2326 if ((key_type_0 == (int)TD3_L3_HASH_KEY_TYPE_FCOE_HOST) && 2327 (key_type_1 == (int)TD3_L3_HASH_DATA_TYPE_FCOE_HOST_EXT)) 2328 return (1); 2329 2330 if ((key_type_0 == (int)TD3_L3_HASH_KEY_TYPE_FCOE_DOMAIN) && 2331 (key_type_1 == (int)TD3_L3_HASH_DATA_TYPE_FCOE_DOMAIN_EXT)) 2332 return (1); 2333 2334 if ((key_type_0 == (int)TD3_L3_HASH_KEY_TYPE_FCOE_SOURCE_MAP) && 2335 (key_type_1 == (int)TD3_L3_HASH_DATA_TYPE_FCOE_SOURCE_MAP_EXT)) 2336 return (1); 2337 } else if (mem == _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit)) { 2338 if ((key_type_0 == (int)TD3_L3_HASH_KEY_TYPE_FCOE_HOST) && 2339 (key_type_1 == (int)TD3_L3_HASH_KEY_TYPE_FCOE_HOST_EXT)) 2340 return (1); 2341 2342 if ((key_type_0 == (int)TD3_L3_HASH_KEY_TYPE_FCOE_DOMAIN) && 2343 (key_type_1 == (int)TD3_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT)) 2344 return (1); 2345 2346 if ((key_type_0 == (int)TD3_L3_HASH_KEY_TYPE_FCOE_SOURCE_MAP) && 2347 (key_type_1 == (int)TD3_L3_HASH_KEY_TYPE_FCOE_SOURCE_MAP_EXT)) 2348 return (1); 2349 } 2350 2351 return 0; 2352 } 2353 #endif 2354 2355 /* 2356 * Description: 2357 * Determine if the given key type is an FCOE key for the given table. 2358 * Parameters: 2359 * mem - (IN) table type 2360 * key_type - (IN) key type field from the table row 2361 * Returns: 2362 * 0 indicates "not an FCOE key" 2363 * 1 indicates "is an FCOE key" 2364 */ 2365 STATIC int 2366 _bcm_td2_key_type_is_fcoe(int unit, soc_mem_t mem, int key_type) 2367 { 2368 if (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) { 2369 return (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT) 2370 || (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT) 2371 || (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT); 2372 } else if (mem == _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit)) { 2373 return (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_HOST) 2374 || (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN) 2375 || (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP); 2376 } else { 2377 return 0; 2378 } 2379 } 2380 2381 /* 2382 * Description: 2383 * Traverse the contents of a given memory (either L3 unicast or L3 mcast). 2384 * For each row, call the given function and supply the given route 2385 * as a parameter. 2386 * Parameters: 2387 * unit - (IN) unit number 2388 * mem - (IN) table type 2389 * traverse_func - (IN) callback function 2390 * route - (IN) route to be passed to callback 2391 * Returns: 2392 * BCM_E_XXX 2393 */ 2394 STATIC int 2395 _bcm_td2_fcoe_traverse_table(int unit, soc_mem_t mem, 2396 fcoe_traverse_cb_f traverse_func, 2397 bcm_fcoe_route_t *route) 2398 { 2399 l3_entry_ipv4_multicast_entry_t l3_ext_entry; 2400 2401 uint32 *buf = (uint32 *)&l3_ext_entry; 2402 int idx; 2403 int idx_max; 2404 int key_type_0; 2405 int key_type_1; 2406 int rv = BCM_E_NONE; 2407 2408 idx_max = soc_mem_index_max(unit, mem); 2409 2410 soc_mem_lock(unit, mem); 2411 2412 for (idx = 0; idx < idx_max; idx++) { 2413 sal_memset(buf, 0, sizeof l3_ext_entry); 2414 2415 rv = BCM_XGS3_MEM_READ(unit, mem, idx, buf); 2416 if (BCM_FAILURE(rv)) { 2417 break; 2418 } 2419 2420 if (mem == _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit)) { 2421 #ifdef BCM_TRIDENT3_SUPPORT 2422 if (SOC_IS_TRIDENT3X(unit)) { 2423 if (!soc_mem_field32_get(unit, mem, buf, BASE_VALIDf)) { 2424 continue; 2425 } 2426 key_type_0 = soc_mem_field32_get(unit, mem, buf, 2427 KEY_TYPEf); 2428 key_type_1 = soc_mem_field32_get(unit, mem, buf, 2429 DATA_TYPEf); 2430 } else 2431 #endif 2432 { 2433 if (!soc_mem_field32_get(unit, mem, buf, VALIDf)) { 2434 continue; 2435 } 2436 key_type_0 = soc_mem_field32_get(unit, mem, buf, 2437 KEY_TYPEf); 2438 key_type_1 = key_type_0; 2439 } 2440 } else { 2441 #ifdef BCM_TRIDENT3_SUPPORT 2442 if (SOC_IS_TRIDENT3X(unit)) { 2443 if (!soc_mem_field32_get(unit, mem, buf, BASE_VALID_0f) 2444 || !soc_mem_field32_get(unit, mem, buf, BASE_VALID_1f)) { 2445 continue; 2446 } 2447 key_type_0 = soc_mem_field32_get(unit, mem, buf, 2448 KEY_TYPEf); 2449 key_type_1 = soc_mem_field32_get(unit, mem, buf, 2450 DATA_TYPEf); 2451 } else 2452 #endif 2453 { 2454 if (!soc_mem_field32_get(unit, mem, buf, VALID_0f) 2455 || !soc_mem_field32_get(unit, mem, buf, VALID_1f)) { 2456 continue; 2457 } 2458 key_type_0 = soc_mem_field32_get(unit, mem, buf, 2459 KEY_TYPE_0f); 2460 key_type_1 = soc_mem_field32_get(unit, mem, buf, 2461 KEY_TYPE_1f); 2462 } 2463 } 2464 #ifdef BCM_TRIDENT3_SUPPORT 2465 if (SOC_IS_TRIDENT3X(unit)) { 2466 if (!_bcm_td3_key_type_is_fcoe(unit, mem, key_type_0, key_type_1)) { 2467 continue; 2468 } 2469 } else 2470 #endif 2471 { 2472 if (!_bcm_td2_key_type_is_fcoe(unit, mem, key_type_0) 2473 || (key_type_0 != key_type_1)) { 2474 continue; 2475 } 2476 } 2477 2478 rv = traverse_func(unit, mem, buf, route); 2479 if (rv != BCM_E_NONE) { 2480 break; 2481 } 2482 } 2483 2484 /* coverity[overrun-local] */ 2485 soc_mem_unlock(unit, mem); 2486 2487 return rv; 2488 } 2489 2490 STATIC int 2491 _bcm_td2_fcoe_traverse_defip(int unit, fcoe_traverse_cb_f traverse_func, 2492 bcm_fcoe_route_t *route) 2493 { 2494 soc_mem_t mem = L3_DEFIPm; 2495 int idx; 2496 int rv = BCM_E_NONE; 2497 char *defip_tbl_ptr = NULL; 2498 int defip_table_size = 0; 2499 defip_entry_t *lpm_entry; 2500 2501 soc_mem_lock(unit, mem); 2502 2503 rv = bcm_xgs3_l3_tbl_dma(unit, mem, BCM_XGS3_L3_ENT_SZ(unit, defip), 2504 "lpm_tbl", &defip_tbl_ptr, &defip_table_size); 2505 if (BCM_FAILURE(rv)) { 2506 soc_mem_unlock(unit, mem); 2507 return rv; 2508 } 2509 2510 for (idx = 0; idx < defip_table_size; idx++) { 2511 lpm_entry = soc_mem_table_idx_to_pointer(unit, mem, 2512 defip_entry_t *, 2513 defip_tbl_ptr, idx); 2514 2515 if ((soc_mem_field32_get(unit, mem, (uint32 *)lpm_entry, VALID0f) && 2516 soc_mem_field32_get(unit, mem, (uint32 *)lpm_entry, ENTRY_TYPE0f)) 2517 || (soc_mem_field32_get(unit, mem, (uint32 *)lpm_entry, VALID1f) && 2518 soc_mem_field32_get(unit, mem, (uint32 *)lpm_entry, ENTRY_TYPE1f)) 2519 ) { 2520 rv = traverse_func(unit, mem, (uint32 *)lpm_entry, route); 2521 if (rv != BCM_E_NONE) { 2522 break; 2523 } 2524 } 2525 } 2526 soc_cm_sfree(unit, defip_tbl_ptr); 2527 soc_mem_unlock(unit, mem); 2528 2529 return rv; 2530 } 2531 2532 /* 2533 * Description: 2534 * Traverse the contents of the L3 unicast and L3 mcast memories. 2535 * For each row, call the given function and supply the given route 2536 * as a parameter. 2537 * Parameters: 2538 * unit - (IN) unit number 2539 * traverse_func - (IN) callback function 2540 * route - (IN) route to be passed to callback 2541 * Returns: 2542 * BCM_E_XXX 2543 */ 2544 STATIC int 2545 _bcm_td2_fcoe_traverse_tables(int unit, fcoe_traverse_cb_f traverse_func, 2546 bcm_fcoe_route_t *route) 2547 { 2548 int rv = _bcm_td2_fcoe_traverse_table(unit, _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit), 2549 traverse_func, route); 2550 if (BCM_SUCCESS(rv)) { 2551 rv = _bcm_td2_fcoe_traverse_table(unit, _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit), 2552 traverse_func, route); 2553 } 2554 2555 if (BCM_SUCCESS(rv)) { 2556 rv = _bcm_td2_fcoe_traverse_defip(unit, traverse_func, route); 2557 } 2558 return rv; 2559 } 2560 2561 /* 2562 * Description: 2563 * Callback function used in bcm_td2_fcoe_route_delete_by_prefix for each 2564 * table row 2565 * Parameters: 2566 * unit - device number 2567 * mem - memory being accessed 2568 * buf - buffer holding table data 2569 * route - route information to be checked 2570 * Returns: 2571 * BCM_E_XXX 2572 */ 2573 STATIC int 2574 _bcm_td2_fcoe_route_delete_by_prefix_cb(int unit, soc_mem_t mem, uint32 *buf, 2575 bcm_fcoe_route_t *route) 2576 { 2577 int searching_prefix = route->nport_id & route->nport_id_mask; 2578 int vrf; 2579 uint32 id; 2580 int rv = BCM_E_NONE; 2581 2582 BCM_IF_ERROR_RETURN(_bcm_td2_mem_get_id(unit, mem, buf, &id)); 2583 BCM_IF_ERROR_RETURN(_bcm_td2_mem_get_vrf(unit, mem, buf, &vrf)); 2584 2585 if (route->vrf != vrf) { 2586 return BCM_E_NONE; 2587 } 2588 2589 if ((id & route->nport_id_mask) == searching_prefix) { 2590 rv = _bcm_td2_fcoe_internal_delete_route(unit, route, mem, buf); 2591 2592 if (rv != SOC_E_NONE) { 2593 return BCM_E_FAIL; 2594 } 2595 } 2596 2597 return BCM_E_NONE; 2598 } 2599 2600 #endif 2601 2602 /* 2603 * Description: 2604 * Delete FCOE entries based on Masked Domain prefix (network) 2605 * Parameters: 2606 * unit - device number 2607 * route - route information to be deleted 2608 * Returns: 2609 * BCM_E_XXX 2610 */ 2611 int 2612 bcm_td2_fcoe_route_delete_by_prefix(int unit, bcm_fcoe_route_t *route) 2613 { 2614 #ifdef INCLUDE_L3 2615 return _bcm_td2_fcoe_traverse_tables(unit, 2616 &_bcm_td2_fcoe_route_delete_by_prefix_cb, 2617 route); 2618 #else 2619 return BCM_E_UNAVAIL; 2620 #endif 2621 } 2622 2623 #ifdef INCLUDE_L3 2624 2625 STATIC int 2626 _bcm_fcoe_read_nexthop_into_route(int unit, int nexthop, 2627 bcm_fcoe_route_t *route, int flag); 2628 2629 /* 2630 * Description: 2631 * Callback function used in bcm_td2_fcoe_route_delete_by_interface for each 2632 * table row 2633 * Parameters: 2634 * unit - device number 2635 * mem - memory being accessed 2636 * buf - buffer holding table data 2637 * route - route information to be checked 2638 * Returns: 2639 * BCM_E_XXX 2640 */ 2641 STATIC int 2642 _bcm_td2_fcoe_route_delete_by_intf_cb(int unit, soc_mem_t mem, uint32 *buf, 2643 bcm_fcoe_route_t *route) 2644 { 2645 int vrf; 2646 int intf; 2647 int nexthop; 2648 bcm_fcoe_route_t tbl_route; 2649 int rv = BCM_E_NONE; 2650 2651 if (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) { 2652 BCM_IF_ERROR_RETURN(_bcm_td2_mem_get_vrf(unit, mem, buf, &vrf)); 2653 BCM_IF_ERROR_RETURN(_bcm_td2_mem_get_intf(unit, mem, buf, &intf)); 2654 2655 if (route->vrf == vrf && route->intf == intf) { 2656 rv = _bcm_td2_fcoe_internal_delete_route(unit, route, mem, buf); 2657 2658 if (rv != SOC_E_NONE) { 2659 return BCM_E_FAIL; 2660 } 2661 } 2662 } else { 2663 BCM_IF_ERROR_RETURN(_bcm_td2_mem_get_vrf(unit, mem, buf, &vrf)); 2664 #ifdef BCM_TRIDENT3_SUPPORT 2665 if (SOC_IS_TRIDENT3X(unit)) { 2666 uint32 dest_type; 2667 nexthop = soc_mem_field32_dest_get(unit, mem, buf, 2668 DESTINATIONf, &dest_type); 2669 } else 2670 #endif 2671 { 2672 nexthop = soc_mem_field32_get(unit, mem, buf, FCOE__NEXT_HOP_INDEXf); 2673 } 2674 2675 2676 sal_memset(&tbl_route, 0x0, sizeof(tbl_route)); 2677 2678 BCM_IF_ERROR_RETURN( 2679 _bcm_fcoe_read_nexthop_into_route(unit, nexthop, &tbl_route, 2680 FCOE_ROUTE_READ_RETURN_L3_INTF)); 2681 2682 if (route->vrf == vrf && route->intf == tbl_route.intf) { 2683 rv = _bcm_td2_fcoe_internal_delete_route(unit, route, mem, buf); 2684 2685 if (rv != SOC_E_NONE) { 2686 return BCM_E_FAIL; 2687 } 2688 } 2689 } 2690 2691 return rv; 2692 } 2693 2694 #endif 2695 2696 /* 2697 * Description: 2698 * Delete FCOE entries that do/don't match a specified L3 interface 2699 * Parameters: 2700 * unit - device number 2701 * route - route information to be deleted 2702 * Returns: 2703 * BCM_E_XXX 2704 */ 2705 int 2706 bcm_td2_fcoe_route_delete_by_interface(int unit, bcm_fcoe_route_t *route) 2707 { 2708 #ifdef INCLUDE_L3 2709 return _bcm_td2_fcoe_traverse_tables(unit, 2710 &_bcm_td2_fcoe_route_delete_by_intf_cb, 2711 route); 2712 #else 2713 return BCM_E_UNAVAIL; 2714 #endif 2715 } 2716 2717 #ifdef INCLUDE_L3 2718 /* 2719 * Description: 2720 * Callback function used in bcm_td2_fcoe_route_delete_all for each 2721 * table row 2722 * Parameters: 2723 * unit - device number 2724 * mem - memory being accessed 2725 * buf - buffer holding table data 2726 * route - route information to be checked 2727 * Returns: 2728 * BCM_E_XXX 2729 */ 2730 STATIC int 2731 _bcm_td2_fcoe_route_delete_all_cb(int unit, soc_mem_t mem, uint32 *buf, 2732 bcm_fcoe_route_t *route) 2733 { 2734 int rv = _bcm_td2_fcoe_internal_delete_route(unit, route, mem, buf); 2735 2736 if (rv != SOC_E_NONE) { 2737 return BCM_E_FAIL; 2738 } 2739 2740 return BCM_E_NONE; 2741 } 2742 #endif 2743 2744 /* 2745 * Description: 2746 * Deletes all FCOE routing table entries 2747 * Parameters: 2748 * unit - device number 2749 * Returns: 2750 * BCM_E_XXX 2751 */ 2752 int 2753 bcm_td2_fcoe_route_delete_all(int unit) 2754 { 2755 #ifdef INCLUDE_L3 2756 return _bcm_td2_fcoe_traverse_tables(unit, 2757 &_bcm_td2_fcoe_route_delete_all_cb, 2758 NULL); 2759 #else 2760 return BCM_E_UNAVAIL; 2761 #endif 2762 } 2763 2764 #ifdef INCLUDE_L3 2765 /* 2766 * Description: 2767 * Read the nexthop table and convert relevant info into the fcoe route 2768 * structure 2769 * Parameters: 2770 * unit - device number 2771 * nexthop - table index 2772 * route - route information to be filled in 2773 * flag - internal flag indicates return l3 intf or nexthop index 2774 * Returns: 2775 * BCM_E_XXX 2776 */ 2777 STATIC int 2778 _bcm_fcoe_read_nexthop_into_route(int unit, int nexthop, 2779 bcm_fcoe_route_t *route, int flag) 2780 { 2781 bcm_l3_egress_t nh_entry; 2782 int rv; 2783 2784 if (BCM_XGS3_L3_HWCALL_CHECK(unit, nh_get)) { 2785 rv = BCM_XGS3_L3_HWCALL_EXEC(unit, nh_get) (unit, nexthop, &nh_entry); 2786 } else { 2787 rv = BCM_E_FAIL; 2788 } 2789 2790 BCM_IF_ERROR_RETURN(rv); 2791 2792 if (nh_entry.flags & BCM_L3_L2TOCPU) { 2793 route->flags |= BCM_FCOE_COPY_TO_CPU; 2794 } 2795 2796 if (nh_entry.flags & BCM_L3_DST_DISCARD) { 2797 route->flags |= BCM_FCOE_DST_DISCARD; 2798 } 2799 2800 if (nh_entry.flags & BCM_L3_SRC_DISCARD) { 2801 route->flags |= BCM_FCOE_SRC_DISCARD; 2802 } 2803 2804 if (nh_entry.flags & BCM_L3_KEEP_TTL) { 2805 route->flags |= BCM_FCOE_NO_HOP_COUNT_CHANGE; 2806 } 2807 2808 BCM_IF_ERROR_RETURN(_bcm_fcoe_glp_to_port(nh_entry.port, &route->port)); 2809 if (flag == FCOE_ROUTE_READ_RETURN_NHID) { 2810 if (BCM_XGS3_L3_EGRESS_MODE_ISSET(unit)) { 2811 if (route->flags & BCM_FCOE_MULTIPATH) { 2812 route->intf = nexthop + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 2813 } else { 2814 route->intf = nexthop + BCM_XGS3_EGRESS_IDX_MIN(unit); 2815 } 2816 return BCM_E_NONE; 2817 } 2818 } 2819 if (flag != FCOE_ROUTE_READ_RETURN_L3_INTF) { 2820 return BCM_E_INTERNAL; 2821 } 2822 route->intf = nh_entry.intf; 2823 2824 return BCM_E_NONE; 2825 } 2826 2827 /* 2828 * Description: 2829 * Read a buffer from the L3 hardware table into a fcoe route structure 2830 * Parameters: 2831 * unit - device number 2832 * mem - table to be used 2833 * buf - buffer holding the table row 2834 * route - route information to be created 2835 * Returns: 2836 * BCM_E_XXX 2837 */ 2838 STATIC int 2839 _bcm_fcoe_read_mem_into_route(int unit, soc_mem_t mem, uint32 *buf, 2840 bcm_fcoe_route_t *route) 2841 { 2842 int key_type; 2843 #ifdef BCM_TRIDENT3_SUPPORT 2844 uint32 dest_type = 0; 2845 #endif 2846 2847 BCM_IF_ERROR_RETURN(_bcm_td2_mem_get_key_type(unit, mem, buf, &key_type)); 2848 BCM_IF_ERROR_RETURN(_bcm_td2_mem_get_id(unit, mem, buf, 2849 &route->nport_id)); 2850 2851 switch (key_type) { 2852 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST: 2853 case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT: 2854 route->flags = BCM_FCOE_HOST_ROUTE; 2855 break; 2856 2857 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP: 2858 case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT: 2859 route->flags = BCM_FCOE_SOURCE_ROUTE; 2860 break; 2861 2862 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN: 2863 case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT: 2864 route->flags = BCM_FCOE_DOMAIN_ROUTE; 2865 break; 2866 2867 default: 2868 return BCM_E_FAIL; 2869 } 2870 2871 if (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) { 2872 int port; 2873 2874 if (soc_mem_field32_get(unit, mem, buf, FCOE_EXT__DST_DISCARDf)) { 2875 route->flags |= BCM_FCOE_DST_DISCARD; 2876 } 2877 if (soc_mem_field32_get(unit, mem, buf, FCOE_EXT__RPEf)) { 2878 route->flags |= BCM_FCOE_RPE; 2879 } 2880 2881 route->pri = soc_mem_field32_get(unit, mem, buf, FCOE_EXT__PRIf); 2882 route->lookup_class = soc_mem_field32_get(unit, mem, buf, 2883 FCOE_EXT__CLASS_IDf); 2884 2885 if ((route->flags & BCM_FCOE_HOST_ROUTE) 2886 && soc_mem_field32_get(unit, mem, buf, FCOE_EXT__LOCAL_ADDRESSf)) { 2887 route->flags |= BCM_FCOE_LOCAL_ADDRESS; 2888 } 2889 2890 BCM_IF_ERROR_RETURN(_bcm_td2_mem_get_intf(unit, mem, buf, 2891 &route->intf)); 2892 2893 soc_mem_mac_addr_get(unit, mem, buf, FCOE_EXT__MAC_ADDRf, 2894 route->nexthop_mac); 2895 2896 if (soc_mem_field32_get(unit, mem, buf, FCOE_EXT__COPY_TO_CPUf)) { 2897 route->flags |= BCM_FCOE_COPY_TO_CPU; 2898 } 2899 2900 2901 #ifdef BCM_TRIDENT3_SUPPORT 2902 if (SOC_IS_TRIDENT3X(unit)) { 2903 uint32 dest; 2904 if (soc_mem_field32_get(unit, mem, buf, FCOE_EXT__DO_NOT_DECREMENT_TTLf)) { 2905 route->flags |= BCM_FCOE_NO_HOP_COUNT_CHANGE; 2906 } 2907 dest = soc_mem_field32_dest_get(unit, mem, buf, FCOE_EXT__DESTINATIONf, 2908 &dest_type); 2909 if (dest_type == SOC_MEM_FIF_DEST_DGPP) { 2910 port = BCM_GPORT_MODPORT_PORT_GET(dest); 2911 } else { 2912 return BCM_E_INTERNAL; 2913 } 2914 } else 2915 #endif /* BCM_TRIDENT3_SUPPORT */ 2916 { 2917 if (soc_mem_field32_get(unit, mem, buf, FCOE_EXT__DO_NOT_CHANGE_TTLf)) { 2918 route->flags |= BCM_FCOE_NO_HOP_COUNT_CHANGE; 2919 } 2920 2921 port = soc_mem_field32_get(unit, mem, buf, FCOE_EXT__GLPf); 2922 BCM_IF_ERROR_RETURN(_bcm_fcoe_glp_to_port(port, &route->port)); 2923 } 2924 } else { 2925 int nexthop; 2926 2927 #ifdef BCM_TRIDENT3_SUPPORT 2928 if (SOC_IS_TRIDENT3X(unit)) { 2929 nexthop = soc_mem_field32_dest_get(unit, mem, buf, DESTINATIONf, &dest_type); 2930 } else 2931 #endif 2932 { 2933 nexthop = soc_mem_field32_get(unit, mem, buf, FCOE__NEXT_HOP_INDEXf); 2934 } 2935 2936 route->pri = soc_mem_field32_get(unit, mem, buf, FCOE__PRIf); 2937 route->lookup_class = soc_mem_field32_get(unit, mem, buf, 2938 FCOE__CLASS_IDf); 2939 2940 if ((route->flags & BCM_FCOE_HOST_ROUTE) 2941 && soc_mem_field32_get(unit, mem, buf, FCOE__LOCAL_ADDRESSf)) { 2942 route->flags |= BCM_FCOE_LOCAL_ADDRESS; 2943 } 2944 2945 if (soc_mem_field32_get(unit, mem, buf, FCOE__DST_DISCARDf)) { 2946 route->flags |= BCM_FCOE_DST_DISCARD; 2947 } 2948 if (soc_mem_field32_get(unit, mem, buf, FCOE__RPEf)) { 2949 route->flags |= BCM_FCOE_RPE; 2950 } 2951 #ifdef BCM_TRIDENT3_SUPPORT 2952 if (SOC_IS_TRIDENT3X(unit)) { 2953 if (dest_type == SOC_MEM_FIF_DEST_ECMP){ 2954 route->flags |= BCM_FCOE_MULTIPATH; 2955 } 2956 } else 2957 #endif 2958 { 2959 if (soc_mem_field32_get(unit, mem, buf, FCOE__ECMPf)) { 2960 route->flags |= BCM_FCOE_MULTIPATH; 2961 } 2962 } 2963 2964 BCM_IF_ERROR_RETURN( 2965 _bcm_fcoe_read_nexthop_into_route(unit, nexthop, route, 2966 FCOE_ROUTE_READ_RETURN_NHID)); 2967 } 2968 2969 return BCM_E_NONE; 2970 } 2971 2972 /* 2973 * Description: 2974 * Look up an FCOE routing table entry based on nport id 2975 * Parameters: 2976 * unit - device number 2977 * route - route information to be deleted 2978 * Returns: 2979 * BCM_E_XXX 2980 */ 2981 STATIC int 2982 _bcm_td2_fcoe_route_find_ext(int unit, bcm_fcoe_route_t *route) 2983 { 2984 l3_entry_ipv4_multicast_entry_t l3_ext_entry[2]; 2985 2986 soc_mem_t mem = _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit); 2987 uint32 *buf = (uint32 *)&l3_ext_entry[0]; 2988 uint32 *lookup = (uint32 *)&l3_ext_entry[1]; 2989 int existing_index = 0; 2990 int rv; 2991 2992 memset(&l3_ext_entry, 0, sizeof l3_ext_entry); 2993 2994 BCM_IF_ERROR_RETURN(_bcm_fcoe_route_construct_key_ext(unit, mem, buf, 2995 route)); 2996 2997 /* Search for this key in the existing database */ 2998 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &existing_index, buf, 2999 (void *)lookup, 0); 3000 if (rv == SOC_E_NOT_FOUND) { 3001 return BCM_E_NOT_FOUND; 3002 } 3003 3004 _bcm_fcoe_read_mem_into_route(unit, mem, lookup, route); 3005 3006 return BCM_E_NONE; 3007 } 3008 3009 /* 3010 * Description: 3011 * Look up an FCOE routing table entry based on nport id 3012 * Parameters: 3013 * unit - device number 3014 * route - route information to be deleted 3015 * Returns: 3016 * BCM_E_XXX 3017 */ 3018 STATIC int 3019 _bcm_td2_fcoe_route_find_normal(int unit, bcm_fcoe_route_t *route) 3020 { 3021 l3_entry_ipv4_unicast_entry_t l3_entry[2]; 3022 3023 soc_mem_t mem = _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit); 3024 uint32 *buf = (uint32 *)&l3_entry[0]; 3025 uint32 *lookup = (uint32 *)&l3_entry[1]; 3026 int existing_index = 0; 3027 int rv; 3028 3029 memset(&l3_entry, 0, sizeof l3_entry); 3030 3031 BCM_IF_ERROR_RETURN(_bcm_fcoe_route_construct_key_normal(unit, mem, buf, 3032 route)); 3033 3034 /* Search for this key in the existing database */ 3035 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &existing_index, buf, 3036 (void *)lookup, 0); 3037 if (rv == SOC_E_NOT_FOUND) { 3038 return BCM_E_NOT_FOUND; 3039 } 3040 3041 _bcm_fcoe_read_mem_into_route(unit, mem, lookup, route); 3042 3043 return BCM_E_NONE; 3044 } 3045 3046 /* 3047 * Description: 3048 * Look up an FCOE route in the L3_DEFIP table 3049 * Parameters: 3050 * unit - device number 3051 * route - route information to be deleted 3052 * Returns: 3053 * BCM_E_XXX 3054 */ 3055 STATIC int 3056 _bcm_td2_fcoe_route_find_defip(int unit, bcm_fcoe_route_t *route) 3057 { 3058 _bcm_defip_cfg_t lpm_cfg; 3059 int nh_idx = 0; 3060 3061 sal_memset(&lpm_cfg, 0, sizeof lpm_cfg); 3062 3063 BCM_IF_ERROR_RETURN(_bcm_fcoe_route_to_defip(unit, route, &lpm_cfg)); 3064 BCM_IF_ERROR_RETURN(_bcm_fb_lpm_get(unit, &lpm_cfg, &nh_idx)); 3065 BCM_IF_ERROR_RETURN(_bcm_fcoe_defip_to_route(unit, &lpm_cfg, route)); 3066 if (BCM_XGS3_L3_EGRESS_MODE_ISSET(unit)) { 3067 if (route->flags & BCM_FCOE_MULTIPATH) { 3068 route->intf = nh_idx + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 3069 } else { 3070 route->intf = nh_idx + BCM_XGS3_EGRESS_IDX_MIN(unit); 3071 } 3072 } 3073 return BCM_E_NONE; 3074 } 3075 #endif 3076 3077 /* 3078 * Description: 3079 * Look up an FCOE routing table entry based on nport id 3080 * Parameters: 3081 * unit - device number 3082 * route - route information to be deleted 3083 * Returns: 3084 * BCM_E_XXX 3085 */ 3086 int 3087 bcm_td2_fcoe_route_find(int unit, bcm_fcoe_route_t *route) 3088 { 3089 #ifdef INCLUDE_L3 3090 int rv = _bcm_td2_fcoe_route_find_normal(unit, route); 3091 3092 if (rv != BCM_E_NONE) { 3093 rv = _bcm_td2_fcoe_route_find_ext(unit, route); 3094 } 3095 3096 if (rv != BCM_E_NONE) { 3097 rv = _bcm_td2_fcoe_route_find_defip(unit, route); 3098 } 3099 #else 3100 int rv = BCM_E_UNAVAIL; 3101 #endif 3102 3103 return rv; 3104 } 3105 3106 /* validate vsan entry input */ 3107 STATIC int 3108 _bcm_fcoe_vsan_param_validate (bcm_fcoe_vsan_t *vsan, bcm_fcoe_vsan_id_t vsan_id) 3109 { 3110 if ((vsan_id > FCOE_MAX_VSAN_ID) || 3111 (vsan->fcmap > 0xffffff)) { /* fcmap is 24 bits */ 3112 return BCM_E_PARAM; 3113 } 3114 return BCM_E_NONE; 3115 } 3116 3117 /* return fcmap value for given index */ 3118 STATIC int 3119 _bcm_fcoe_fc_profile_map_value_get (int unit, int index, 3120 bcm_fcoe_fcmap_t *fcmap) 3121 { 3122 int rv; 3123 uint32 entry[SOC_MAX_MEM_FIELD_WORDS]; 3124 void *entries[1]; 3125 3126 entries[0] = entry; 3127 rv = _bcm_fc_map_profile_entry_get(unit, index, 1, entries); 3128 3129 if (rv == BCM_E_NONE) { 3130 *fcmap = entry[0]; 3131 } 3132 3133 return rv; 3134 } 3135 3136 /* Allocate and configure a VSAN */ 3137 int 3138 bcm_td2_fcoe_vsan_create (int unit, uint32 options, bcm_fcoe_vsan_t *vsan, 3139 bcm_fcoe_vsan_id_t *vsan_id) 3140 { 3141 ing_vsan_entry_t vsan_entry; 3142 soc_mem_t mem = ING_VSANm; 3143 int rv = BCM_E_NONE; 3144 int index = *vsan_id; 3145 uint32 fcmap_index = 0; 3146 void *entries[1]; 3147 uint32 fcmap_to_set; 3148 3149 rv = _bcm_fcoe_vsan_param_validate(vsan, *vsan_id); 3150 if (rv != BCM_E_NONE) { 3151 return rv; 3152 } 3153 3154 /* check if vsan id is already created */ 3155 if (shr_idxres_list_elem_state(vsan_id_list[unit], *vsan_id) != 3156 BCM_E_NOT_FOUND) { 3157 /* exception : if intention is to replace existing ID, overwrite 3158 * existing entry */ 3159 if ((options & BCM_FCOE_VSAN_OPTION_REPLACE) == 0) { 3160 return BCM_E_EXISTS; 3161 } 3162 } 3163 3164 fcmap_to_set = vsan->fcmap; 3165 entries[0] = &fcmap_to_set; 3166 3167 rv = _bcm_fc_map_profile_entry_add(unit, entries, 1, &fcmap_index); 3168 3169 if (rv != SOC_E_NONE) { 3170 return rv; 3171 } 3172 3173 /* read table entry */ 3174 soc_mem_lock(unit, mem); 3175 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &vsan_entry); 3176 if (rv != BCM_E_NONE) { 3177 soc_mem_unlock(unit, mem); 3178 return rv; 3179 } 3180 3181 if (vsan->config_flags & BCM_FCOE_VSAN_CONFIG_NORMALIZED_ZONE_CHECK) { 3182 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3183 ZONE_CHECK_NORMALIZEDf, 1); 3184 } else { 3185 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3186 ZONE_CHECK_NORMALIZEDf, 0); 3187 } 3188 if (vsan->config_flags & BCM_FCOE_VSAN_CONFIG_FCOE_ROUTE_ENABLE) { 3189 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3190 FCOE_ROUTE_ENABLEf, 1); 3191 } else { 3192 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3193 FCOE_ROUTE_ENABLEf, 0); 3194 } 3195 3196 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3197 L3_IIFf, vsan->l3_intf_id); 3198 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3199 FCOE_FC_MAP_INDEXf, fcmap_index); 3200 3201 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &vsan_entry); 3202 3203 soc_mem_unlock(unit, mem); 3204 3205 if (rv == BCM_E_NONE) { 3206 /* mark this vsan id as "created" */ 3207 if (shr_idxres_list_elem_state(vsan_id_list[unit], *vsan_id) == 3208 BCM_E_NOT_FOUND) { 3209 return _bcm_fcoe_reserve_vsan_id(unit, *vsan_id); 3210 } 3211 } 3212 return rv; 3213 } 3214 3215 /* Destroy a VSAN */ 3216 int 3217 bcm_td2_fcoe_vsan_destroy (int unit, bcm_fcoe_vsan_id_t vsan_id) 3218 { 3219 ing_vsan_entry_t vsan_entry; 3220 soc_mem_t mem = ING_VSANm; 3221 int rv = BCM_E_NONE; 3222 int index = vsan_id; 3223 int fcmap_index; 3224 3225 /* check if vsan id is existing */ 3226 if (shr_idxres_list_elem_state(vsan_id_list[unit], vsan_id) != 3227 BCM_E_EXISTS) { 3228 return BCM_E_NOT_FOUND; 3229 } 3230 3231 /* read table entry */ 3232 soc_mem_lock(unit, mem); 3233 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &vsan_entry); 3234 if (rv != BCM_E_NONE) { 3235 soc_mem_unlock(unit, mem); 3236 return rv; 3237 } 3238 3239 /* delete fc map entry */ 3240 fcmap_index = soc_mem_field32_get(unit,mem, &vsan_entry, FCOE_FC_MAP_INDEXf); 3241 rv = _bcm_fc_map_profile_entry_delete(unit, fcmap_index); 3242 if (rv != BCM_E_NONE) { 3243 soc_mem_unlock(unit, mem); 3244 return rv; 3245 } 3246 3247 /* NOTE : zero out all fields (including flex counter fields) 3248 */ 3249 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3250 FLEX_CTR_OFFSET_MODEf, 0); 3251 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3252 FLEX_CTR_POOL_NUMBERf, 0); 3253 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3254 FLEX_CTR_BASE_COUNTER_IDXf, 0); 3255 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3256 FCOE_ROUTE_ENABLEf, 0); 3257 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3258 ZONE_CHECK_NORMALIZEDf, 0); 3259 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, L3_IIFf, 0); 3260 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3261 FCOE_FC_MAP_INDEXf, 0); 3262 3263 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &vsan_entry); 3264 3265 soc_mem_unlock(unit, mem); 3266 3267 if (rv == BCM_E_NONE) { 3268 /* unreserve this vsan id */ 3269 return _bcm_fcoe_unreserve_vsan_id(unit, vsan_id); 3270 } 3271 return rv; 3272 } 3273 3274 /* Destroy all VSANs */ 3275 int 3276 bcm_td2_fcoe_vsan_destroy_all (int unit) 3277 { 3278 ing_vsan_entry_t vsan_entry; 3279 soc_mem_t mem = ING_VSANm; 3280 int rv = BCM_E_NONE; 3281 int index; 3282 int fcmap_index; 3283 3284 soc_mem_lock(unit, mem); 3285 for (index = 0; index <= FCOE_MAX_VSAN_ID; index++) { 3286 3287 /* check if vsan id is existing */ 3288 if (shr_idxres_list_elem_state(vsan_id_list[unit], index) != 3289 BCM_E_EXISTS) { 3290 continue; 3291 } 3292 3293 /* read table entry */ 3294 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &vsan_entry); 3295 if (rv != BCM_E_NONE) { 3296 break; 3297 } 3298 3299 /* delete fc map entry */ 3300 fcmap_index = soc_mem_field32_get(unit,mem, &vsan_entry, 3301 FCOE_FC_MAP_INDEXf); 3302 rv = _bcm_fc_map_profile_entry_delete(unit, fcmap_index); 3303 if (rv != BCM_E_NONE) { 3304 soc_mem_unlock(unit, mem); 3305 return rv; 3306 } 3307 3308 /* NOTE : zero out all fields (including flex counter fields) 3309 */ 3310 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3311 FLEX_CTR_OFFSET_MODEf, 0); 3312 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3313 FLEX_CTR_POOL_NUMBERf, 0); 3314 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3315 FLEX_CTR_BASE_COUNTER_IDXf, 0); 3316 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3317 FCOE_ROUTE_ENABLEf, 0); 3318 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3319 ZONE_CHECK_NORMALIZEDf, 0); 3320 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, L3_IIFf, 0); 3321 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3322 FCOE_FC_MAP_INDEXf, 0); 3323 3324 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &vsan_entry); 3325 3326 if (rv == BCM_E_NONE) { 3327 /* unreserve this vsan id */ 3328 rv = _bcm_fcoe_unreserve_vsan_id(unit, index); 3329 if (rv != BCM_E_NONE) { 3330 break; 3331 } 3332 } else { 3333 break; 3334 } 3335 } 3336 3337 soc_mem_unlock(unit, mem); 3338 return rv; 3339 } 3340 3341 /* Get VSAN controls */ 3342 int 3343 bcm_td2_fcoe_control_vsan_get (int unit, 3344 bcm_fcoe_vsan_id_t vsan_id, 3345 bcm_fcoe_vsan_control_t type, 3346 int *arg) 3347 { 3348 ing_vsan_entry_t vsan_entry; 3349 soc_mem_t mem = ING_VSANm; 3350 int rv = BCM_E_NONE; 3351 int index = vsan_id; 3352 3353 if (vsan_id > FCOE_MAX_VSAN_ID) { 3354 return BCM_E_PARAM; 3355 } 3356 3357 /* read table entry */ 3358 soc_mem_lock(unit, mem); 3359 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &vsan_entry); 3360 if (rv != BCM_E_NONE) { 3361 soc_mem_unlock(unit, mem); 3362 return rv; 3363 } 3364 soc_mem_unlock(unit, mem); 3365 3366 switch (type) { 3367 case bcmFcoeVsanNormalizedZoneCheck: 3368 *arg = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry, 3369 ZONE_CHECK_NORMALIZEDf); 3370 break; 3371 3372 case bcmFcoeVsanRouteEnable: 3373 *arg = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry, 3374 FCOE_ROUTE_ENABLEf); 3375 break; 3376 3377 default: 3378 rv = BCM_E_PARAM; 3379 break; 3380 } 3381 3382 return rv; 3383 } 3384 3385 /* Set VSAN controls */ 3386 int 3387 bcm_td2_fcoe_control_vsan_set (int unit, 3388 bcm_fcoe_vsan_id_t vsan_id, 3389 bcm_fcoe_vsan_control_t type, 3390 int arg) 3391 { 3392 ing_vsan_entry_t vsan_entry; 3393 soc_mem_t mem = ING_VSANm; 3394 int rv = BCM_E_NONE; 3395 int index = vsan_id; 3396 3397 if (vsan_id > FCOE_MAX_VSAN_ID) { 3398 return BCM_E_PARAM; 3399 } 3400 3401 /* read table entry */ 3402 soc_mem_lock(unit, mem); 3403 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &vsan_entry); 3404 if (rv != BCM_E_NONE) { 3405 soc_mem_unlock(unit, mem); 3406 return rv; 3407 } 3408 3409 switch (type) { 3410 case bcmFcoeVsanNormalizedZoneCheck: 3411 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3412 ZONE_CHECK_NORMALIZEDf, (arg != 0) ? 1 : 0); 3413 break; 3414 3415 case bcmFcoeVsanRouteEnable: 3416 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3417 FCOE_ROUTE_ENABLEf, (arg != 0) ? 1 : 0); 3418 break; 3419 3420 default: 3421 rv = BCM_E_PARAM; 3422 break; 3423 } 3424 3425 if (rv == BCM_E_NONE) { 3426 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &vsan_entry); 3427 } 3428 soc_mem_unlock(unit, mem); 3429 return rv; 3430 } 3431 3432 /* Get VSAN properties associated with a VSAN ID */ 3433 int 3434 bcm_td2_fcoe_vsan_get (int unit, bcm_fcoe_vsan_id_t vsan_id, 3435 bcm_fcoe_vsan_t *vsan) 3436 { 3437 ing_vsan_entry_t vsan_entry; 3438 soc_mem_t mem = ING_VSANm; 3439 int rv = BCM_E_NONE; 3440 int index = vsan_id; 3441 int flag = 0; 3442 int fcmap_index = 0; 3443 bcm_fcoe_fcmap_t fcmap; 3444 3445 if (vsan_id > FCOE_MAX_VSAN_ID) { 3446 return BCM_E_PARAM; 3447 } 3448 3449 /* NOTE : for now, reading a not-initialized(not created) entry is not 3450 * allowed. we may change this behavior.... 3451 */ 3452 if (shr_idxres_list_elem_state(vsan_id_list[unit], vsan_id) != 3453 BCM_E_EXISTS) { 3454 return BCM_E_NOT_FOUND; 3455 } 3456 3457 /* read table entry */ 3458 soc_mem_lock(unit, mem); 3459 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &vsan_entry); 3460 soc_mem_unlock(unit, mem); 3461 if (rv != BCM_E_NONE) { 3462 return rv; 3463 } 3464 3465 fcmap_index = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry, 3466 FCOE_FC_MAP_INDEXf); 3467 /* get fcmap value for fcmap index */ 3468 rv = _bcm_fcoe_fc_profile_map_value_get (unit, fcmap_index, &fcmap); 3469 if (rv != BCM_E_NONE) { 3470 return rv; 3471 } 3472 vsan->fcmap = fcmap; 3473 3474 vsan->config_flags = 0; 3475 flag = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry, 3476 ZONE_CHECK_NORMALIZEDf); 3477 if (flag) { 3478 vsan->config_flags |= BCM_FCOE_VSAN_CONFIG_NORMALIZED_ZONE_CHECK; 3479 } 3480 flag = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry, 3481 FCOE_ROUTE_ENABLEf); 3482 if (flag) { 3483 vsan->config_flags |= BCM_FCOE_VSAN_CONFIG_FCOE_ROUTE_ENABLE; 3484 } 3485 3486 vsan->l3_intf_id = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry, 3487 L3_IIFf); 3488 vsan->fcmap = fcmap; 3489 3490 return rv; 3491 } 3492 3493 /* Update VSAN properties associated with a VSAN ID */ 3494 int 3495 bcm_td2_fcoe_vsan_set (int unit, bcm_fcoe_vsan_id_t vsan_id, 3496 bcm_fcoe_vsan_t *vsan) 3497 { 3498 ing_vsan_entry_t vsan_entry; 3499 soc_mem_t mem = ING_VSANm; 3500 int rv = BCM_E_NONE; 3501 int index = vsan_id; 3502 uint32 fcmap_index = 0; 3503 int old_fcmap_index; 3504 void *entries[1]; 3505 uint32 fcmap_to_set; 3506 3507 if (vsan_id > FCOE_MAX_VSAN_ID) { 3508 return BCM_E_PARAM; 3509 } 3510 3511 /* check if vsan id is already created */ 3512 if (shr_idxres_list_elem_state(vsan_id_list[unit], vsan_id) != 3513 BCM_E_EXISTS) { 3514 return BCM_E_NOT_FOUND; 3515 } 3516 3517 /* read table entry */ 3518 soc_mem_lock(unit, mem); 3519 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &vsan_entry); 3520 if (rv != BCM_E_NONE) { 3521 soc_mem_unlock(unit, mem); 3522 return rv; 3523 } 3524 3525 old_fcmap_index = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry, 3526 FCOE_FC_MAP_INDEXf); 3527 fcmap_to_set = vsan->fcmap; 3528 entries[0] = &fcmap_to_set; 3529 3530 rv = _bcm_fc_map_profile_entry_add(unit, entries, 1, &fcmap_index); 3531 3532 if (rv != SOC_E_NONE) { 3533 soc_mem_unlock(unit, mem); 3534 return rv; 3535 } 3536 3537 if (vsan->config_flags & BCM_FCOE_VSAN_CONFIG_NORMALIZED_ZONE_CHECK) { 3538 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3539 ZONE_CHECK_NORMALIZEDf, 1); 3540 } else { 3541 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3542 ZONE_CHECK_NORMALIZEDf, 0); 3543 } 3544 if (vsan->config_flags & BCM_FCOE_VSAN_CONFIG_FCOE_ROUTE_ENABLE) { 3545 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3546 FCOE_ROUTE_ENABLEf, 1); 3547 } else { 3548 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3549 FCOE_ROUTE_ENABLEf, 0); 3550 } 3551 3552 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3553 L3_IIFf, vsan->l3_intf_id); 3554 soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 3555 FCOE_FC_MAP_INDEXf, fcmap_index); 3556 3557 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &vsan_entry); 3558 3559 if (rv == BCM_E_NONE) { 3560 rv = _bcm_fc_map_profile_entry_delete(unit, old_fcmap_index); 3561 } 3562 3563 soc_mem_unlock(unit, mem); 3564 3565 return rv; 3566 } 3567 3568 /* 3569 * Description: 3570 * Check that parameters sent to bcm_td2_fcoe_fc_header_type_* functions 3571 * are valid. 3572 * Parameters: 3573 * flags - (IN) BCM_FCOE_FC_HEADER_TYPE_INGRESS/EGRESS 3574 * hdr_type - (IN) Header type to force this value of r_ctl to use 3575 * Returns: 3576 * BCM_E_XXX 3577 */ 3578 STATIC int 3579 _bcm_td2_fcoe_fc_header_sanity_check(uint32 flags, 3580 bcm_fcoe_fc_header_type_t hdr_type) 3581 { 3582 int rv = BCM_E_NONE; 3583 3584 if (hdr_type > bcmFcoeFcHeaderTypeCount 3585 || hdr_type < bcmFcoeFcHeaderTypeNone) { 3586 rv = BCM_E_PARAM; 3587 } 3588 3589 if (!(flags & BCM_FCOE_FC_HEADER_TYPE_INGRESS) 3590 && !(flags & BCM_FCOE_FC_HEADER_TYPE_EGRESS)) { 3591 rv = BCM_E_PARAM; 3592 } 3593 3594 return rv; 3595 } 3596 3597 /* 3598 * Description: 3599 * Convert a hardware value of header type to the corresponding 3600 * bcm_fcoe_fc_header_type_t enum 3601 * Parameters: 3602 * encoded_value - (IN) hardware value to convert 3603 * hdr_type - (OUT) resulting header type enum 3604 * Returns: 3605 * BCM_E_XXX 3606 */ 3607 STATIC int 3608 _bcm_td2_fcoe_hdr_encode_to_hdr_type(uint32 encoded_value, 3609 bcm_fcoe_fc_header_type_t *hdr_type) 3610 { 3611 int rv = BCM_E_NONE; 3612 3613 switch (encoded_value) { 3614 case FC_HEADER_TYPE_NOT_PRESENT: 3615 *hdr_type = bcmFcoeFcHeaderTypeNone; 3616 break; 3617 3618 case FC_HEADER_TYPE_STANDARD: 3619 *hdr_type = bcmFcoeFcHeaderTypeStd; 3620 break; 3621 3622 case FC_HEADER_TYPE_ENCAPSULATION: 3623 *hdr_type = bcmFcoeFcHeaderTypeEncap; 3624 break; 3625 3626 case FC_HEADER_TYPE_VFT: 3627 *hdr_type = bcmFcoeFcHeaderTypeVft; 3628 break; 3629 3630 case FC_HEADER_TYPE_IFR: 3631 *hdr_type = bcmFcoeFcHeaderTypeIfr; 3632 break; 3633 3634 case FC_HEADER_TYPE_UNKNOWN: 3635 *hdr_type = bcmFcoeFcHeaderTypeUnknown; 3636 break; 3637 3638 default: 3639 rv = BCM_E_PARAM; 3640 break; 3641 } 3642 3643 return rv; 3644 } 3645 3646 /* 3647 * Description: 3648 * Convert a bcm_fcoe_fc_header_type_t enum to the corresponding value that 3649 * should be programmed to hardware 3650 * Parameters: 3651 * hdr_type - (IN) header type enum to convert 3652 * encoded_value - (OUT) resulting hardware value 3653 * Returns: 3654 * BCM_E_XXX 3655 */ 3656 STATIC int 3657 _bcm_td2_fcoe_hdr_type_to_hdr_encode(bcm_fcoe_fc_header_type_t hdr_type, 3658 uint32 *encoded_value) 3659 { 3660 int rv = BCM_E_NONE; 3661 3662 switch (hdr_type) { 3663 case bcmFcoeFcHeaderTypeNone: 3664 *encoded_value = FC_HEADER_TYPE_NOT_PRESENT; 3665 break; 3666 3667 case bcmFcoeFcHeaderTypeStd: 3668 *encoded_value = FC_HEADER_TYPE_STANDARD; 3669 break; 3670 3671 case bcmFcoeFcHeaderTypeEncap: 3672 *encoded_value = FC_HEADER_TYPE_ENCAPSULATION; 3673 break; 3674 3675 case bcmFcoeFcHeaderTypeVft: 3676 *encoded_value = FC_HEADER_TYPE_VFT; 3677 break; 3678 3679 case bcmFcoeFcHeaderTypeIfr: 3680 *encoded_value = FC_HEADER_TYPE_IFR; 3681 break; 3682 3683 case bcmFcoeFcHeaderTypeUnknown: 3684 *encoded_value = FC_HEADER_TYPE_UNKNOWN; 3685 break; 3686 3687 default: 3688 rv = BCM_E_PARAM; 3689 break; 3690 } 3691 3692 return rv; 3693 } 3694 3695 /* 3696 * Description: 3697 * Write header type to hardware 3698 * Parameters: 3699 * unit - (IN) device number 3700 * mem - (IN) device memory to write 3701 * r_ctl - (IN) [0-255] value of r_ctl to write 3702 * hdr_encode - (IN) Header type to store at this r_ctl value 3703 * Return: 3704 * BCM_E_XXX 3705 */ 3706 STATIC int 3707 _bcm_td2_fcoe_fc_program_header(int unit, soc_mem_t mem, uint8 r_ctl, 3708 uint32 hdr_encode) 3709 { 3710 ing_fc_header_type_entry_t ing_entry; 3711 egr_fc_header_type_entry_t egr_entry; 3712 uint32 *buf = NULL; 3713 int rv = BCM_E_NONE; 3714 3715 sal_memset(&ing_entry, 0, sizeof ing_entry); 3716 sal_memset(&egr_entry, 0, sizeof egr_entry); 3717 3718 if ((mem == ING_FC_HEADER_TYPEm) || 3719 (mem == PARSER1_ING_FC_HEADER_TYPEm) || 3720 (mem == PARSER2_ING_FC_HEADER_TYPEm)) { 3721 buf = (uint32 *)&ing_entry; 3722 } else if (mem == EGR_FC_HEADER_TYPEm) { 3723 buf = (uint32 *)&egr_entry; 3724 } else { 3725 rv = BCM_E_PARAM; 3726 } 3727 3728 if (rv == BCM_E_NONE) { 3729 soc_mem_field32_set(unit, mem, buf, FC_HDR_ENCODEf, hdr_encode); 3730 } 3731 3732 if (rv == BCM_E_NONE) { 3733 soc_mem_lock(unit, mem); 3734 rv = BCM_XGS3_MEM_WRITE(unit, mem, r_ctl, buf); 3735 soc_mem_unlock(unit, mem); 3736 } 3737 3738 return rv; 3739 } 3740 3741 /* 3742 * Description: 3743 * Read header type from hardware and return it 3744 * Parameters: 3745 * unit - (IN) device number 3746 * mem - (IN) device memory to read 3747 * r_ctl - (IN) [0-255] value of r_ctl to read 3748 * hdr_encode - (OUT) Header type stored at this r_ctl value 3749 * Return: 3750 * BCM_E_XXX 3751 */ 3752 STATIC int 3753 _bcm_td2_fcoe_fc_read_header(int unit, soc_mem_t mem, uint8 r_ctl, 3754 uint32 *hdr_encode) 3755 { 3756 ing_fc_header_type_entry_t ing_entry; 3757 egr_fc_header_type_entry_t egr_entry; 3758 uint32 *buf = NULL; 3759 int rv = BCM_E_NONE; 3760 3761 if ((mem == ING_FC_HEADER_TYPEm) || 3762 (mem == PARSER1_ING_FC_HEADER_TYPEm) || 3763 (mem == PARSER2_ING_FC_HEADER_TYPEm)) { 3764 buf = (uint32 *)&ing_entry; 3765 } else if (mem == EGR_FC_HEADER_TYPEm) { 3766 buf = (uint32 *)&egr_entry; 3767 } else { 3768 rv = BCM_E_PARAM; 3769 } 3770 3771 if (rv == BCM_E_NONE) { 3772 soc_mem_lock(unit, mem); 3773 rv = BCM_XGS3_MEM_READ(unit, mem, r_ctl, buf); 3774 soc_mem_unlock(unit, mem); 3775 } 3776 3777 if (rv == BCM_E_NONE) { 3778 *hdr_encode = soc_mem_field32_get(unit, mem, buf, FC_HDR_ENCODEf); 3779 } 3780 3781 return rv; 3782 } 3783 3784 /* 3785 * Description: 3786 * Set FC header type 3787 * Parameters: 3788 * unit - (IN) device number 3789 * flags - (IN) BCM_FCOE_FC_HEADER_TYPE_INGRESS/EGRESS 3790 * r_ctl - (IN) [0-255] value of r_ctl to modify 3791 * hdr_type - (IN) Header type to force this value of r_ctl to use 3792 * Return: 3793 * BCM_E_XXX 3794 */ 3795 int 3796 bcm_td2_fcoe_fc_header_type_set(int unit, uint32 flags, uint8 r_ctl, 3797 bcm_fcoe_fc_header_type_t hdr_type) 3798 { 3799 int rv = BCM_E_NONE; 3800 uint32 encoded_value = 0; 3801 3802 rv = _bcm_td2_fcoe_fc_header_sanity_check(flags, hdr_type); 3803 3804 if (rv == BCM_E_NONE) { 3805 rv = _bcm_td2_fcoe_hdr_type_to_hdr_encode(hdr_type, &encoded_value); 3806 } 3807 3808 if ((rv == BCM_E_NONE) && (flags & BCM_FCOE_FC_HEADER_TYPE_INGRESS)) { 3809 #ifdef BCM_TRIDENT3_SUPPORT 3810 if (SOC_IS_TRIDENT3X(unit)) { 3811 rv = _bcm_td2_fcoe_fc_program_header(unit, PARSER1_ING_FC_HEADER_TYPEm, 3812 r_ctl, encoded_value); 3813 if (rv == BCM_E_NONE) { 3814 rv = _bcm_td2_fcoe_fc_program_header(unit, PARSER2_ING_FC_HEADER_TYPEm, 3815 r_ctl, encoded_value); 3816 } 3817 } else 3818 #endif /* BCM_TRIDENT3_SUPPORT */ 3819 { 3820 rv = _bcm_td2_fcoe_fc_program_header(unit, ING_FC_HEADER_TYPEm, 3821 r_ctl, encoded_value); 3822 } 3823 } 3824 3825 if ((rv == BCM_E_NONE) && (flags & BCM_FCOE_FC_HEADER_TYPE_EGRESS)) { 3826 #ifdef BCM_TRIDENT3_SUPPORT 3827 if (!(SOC_IS_TRIDENT3X(unit))) 3828 #endif /* BCM_TRIDENT3_SUPPORT */ 3829 { 3830 rv = _bcm_td2_fcoe_fc_program_header(unit, EGR_FC_HEADER_TYPEm, 3831 r_ctl, encoded_value); 3832 } 3833 } 3834 3835 return rv; 3836 } 3837 3838 /* 3839 * Description: 3840 * Retrieve FC header type 3841 * Parameters: 3842 * unit - (IN) device number 3843 * flags - (IN) BCM_FCOE_FC_HEADER_TYPE_INGRESS/EGRESS 3844 * r_ctl - (IN) [0-255] value of r_ctl to retrieve 3845 * hdr_type - (OUT) Header type that this value of r_ctl is forced to 3846 * Return: 3847 * BCM_E_XXX 3848 */ 3849 int 3850 bcm_td2_fcoe_fc_header_type_get(int unit, uint32 flags, uint8 r_ctl, 3851 bcm_fcoe_fc_header_type_t *hdr_type) 3852 { 3853 int rv = BCM_E_NONE, mem; 3854 uint32 encoded_value = 0; 3855 3856 if ((flags & BCM_FCOE_FC_HEADER_TYPE_INGRESS) 3857 && (flags & BCM_FCOE_FC_HEADER_TYPE_EGRESS)) { 3858 return (BCM_E_PARAM); 3859 } 3860 3861 if (flags & BCM_FCOE_FC_HEADER_TYPE_INGRESS) { 3862 mem = (SOC_IS_TRIDENT3X(unit)) ? PARSER1_ING_FC_HEADER_TYPEm : 3863 ING_FC_HEADER_TYPEm; 3864 } else if (flags & BCM_FCOE_FC_HEADER_TYPE_EGRESS) { 3865 mem = (SOC_IS_TRIDENT3X(unit)) ? PARSER2_ING_FC_HEADER_TYPEm : 3866 EGR_FC_HEADER_TYPEm; 3867 } else { 3868 return (BCM_E_PARAM); 3869 } 3870 rv = _bcm_td2_fcoe_fc_read_header(unit, mem, r_ctl, &encoded_value); 3871 3872 if (rv == BCM_E_NONE) { 3873 rv = _bcm_td2_fcoe_hdr_encode_to_hdr_type(encoded_value, hdr_type); 3874 } 3875 3876 return rv; 3877 } 3878 3879 /* 3880 * Provides relevant flex table information(table-name,index with 3881 * direction) for given VSAN ID. 3882 */ 3883 STATIC bcm_error_t 3884 _bcm_td2_vsan_stat_get_table_info (int unit, 3885 bcm_fcoe_vsan_id_t vsan, 3886 uint32 *num_of_tables, 3887 bcm_stat_flex_table_info_t *table_info) 3888 { 3889 int index = 0; 3890 3891 if (!soc_feature(unit,soc_feature_advanced_flex_counter)) { 3892 return BCM_E_UNAVAIL; 3893 } 3894 3895 /* Get index into ING_VSAN table. VSAN ID is index (12 bits). */ 3896 if (vsan > 0xfff) { 3897 return BCM_E_PARAM; 3898 } 3899 index = (int)vsan; 3900 3901 /* Ingress VSAN */ 3902 table_info[*num_of_tables].table=ING_VSANm; 3903 table_info[*num_of_tables].index=index; 3904 table_info[*num_of_tables].direction=bcmStatFlexDirectionIngress; 3905 (*num_of_tables)++; 3906 3907 return BCM_E_NONE; 3908 } 3909 3910 /* Allocate flex counter and assign counter index/offset for 3911 * FCOE VSAN ID 3912 */ 3913 int 3914 bcm_td2_fcoe_vsan_stat_attach (int unit, 3915 bcm_fcoe_vsan_id_t vsan, 3916 uint32 stat_counter_id) 3917 { 3918 int rv = BCM_E_NONE; 3919 int counter_flag = 0; 3920 soc_mem_t table = 0; 3921 bcm_stat_flex_direction_t direction = bcmStatFlexDirectionIngress; 3922 uint32 pool_number = 0; 3923 uint32 base_index = 0; 3924 bcm_stat_flex_mode_t offset_mode = 0; 3925 bcm_stat_object_t object = bcmStatObjectIngPort; 3926 bcm_stat_group_mode_t group_mode = bcmStatGroupModeSingle; 3927 uint32 count = 0; 3928 uint32 actual_num_tables = 0; 3929 uint32 num_of_tables = 0; 3930 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 3931 3932 3933 /* Get pool, base index group mode and offset modes from stat counter id */ 3934 _bcm_esw_stat_get_counter_id_info( 3935 unit, stat_counter_id, 3936 &group_mode, &object, &offset_mode, &pool_number, 3937 &base_index); 3938 3939 /* Validate object and group mode */ 3940 BCM_IF_ERROR_RETURN( 3941 _bcm_esw_stat_validate_object(unit, object, &direction)); 3942 BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_group(unit, group_mode)); 3943 3944 /* Get Table index to attach flexible counter */ 3945 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_table_info( 3946 unit, object, 1, &actual_num_tables, &table, 3947 &direction)); 3948 BCM_IF_ERROR_RETURN(_bcm_td2_vsan_stat_get_table_info( 3949 unit, vsan, &num_of_tables, &table_info[0])); 3950 3951 for (count = 0; count < num_of_tables; count++) { 3952 if ((table_info[count].direction == direction) && 3953 (table_info[count].table == table) ) { 3954 if (direction == bcmStatFlexDirectionIngress) { 3955 counter_flag = 1; 3956 rv = _bcm_esw_stat_flex_attach_ingress_table_counters( 3957 unit, 3958 table_info[count].table, 3959 table_info[count].index, 3960 offset_mode, 3961 base_index, 3962 pool_number); 3963 3964 if(BCM_FAILURE(rv)) { 3965 break; 3966 } 3967 3968 } else { 3969 /* no egress table...*/ 3970 } 3971 } 3972 } 3973 3974 if (counter_flag == 0) { 3975 rv = BCM_E_NOT_FOUND; 3976 } 3977 3978 return rv; 3979 } 3980 3981 /* Detach flex counter for FCOE VSAN ID */ 3982 int 3983 bcm_td2_fcoe_vsan_stat_detach (int unit, bcm_fcoe_vsan_id_t vsan) 3984 { 3985 int counter_flag = 0; 3986 uint32 count = 0; 3987 uint32 num_of_tables = 0; 3988 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 3989 int rv = BCM_E_NONE; 3990 3991 3992 /* Get the table index to be detached */ 3993 BCM_IF_ERROR_RETURN(_bcm_td2_vsan_stat_get_table_info( 3994 unit, vsan, &num_of_tables, &table_info[0])); 3995 3996 for (count = 0; count < num_of_tables; count++) { 3997 if (table_info[count].direction == bcmStatFlexDirectionIngress) { 3998 counter_flag = 1; 3999 rv = _bcm_esw_stat_flex_detach_ingress_table_counters( 4000 unit, table_info[count].table, table_info[count].index); 4001 } else { 4002 /* no egress table...*/ 4003 } 4004 } 4005 4006 if (counter_flag == 0) { 4007 return BCM_E_NOT_FOUND; 4008 } 4009 4010 return rv; 4011 } 4012 4013 /* Get flex counter for FCOE VSAN ID */ 4014 int 4015 bcm_td2_fcoe_vsan_stat_counter_get (int unit, 4016 int sync_mode, 4017 bcm_fcoe_vsan_id_t vsan, 4018 bcm_fcoe_vsan_stat_t stat, 4019 uint32 num_entries, 4020 uint32 *counter_indexes, 4021 bcm_stat_value_t *counter_values) 4022 { 4023 uint32 table_count = 0; 4024 uint32 index_count = 0; 4025 uint32 num_of_tables = 0; 4026 bcm_stat_flex_direction_t direction = bcmStatFlexDirectionIngress; 4027 uint32 byte_flag = 0; 4028 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4029 4030 if ((stat == bcmFcoeVsanInPackets) || 4031 (stat == bcmFcoeVsanInBytes)) { 4032 direction = bcmStatFlexDirectionIngress; 4033 } else { 4034 return BCM_E_PARAM; 4035 } 4036 if (stat == bcmFcoeVsanInBytes) { 4037 byte_flag = 1; 4038 } 4039 4040 /* Get Table index to read the flex counter */ 4041 BCM_IF_ERROR_RETURN(_bcm_td2_vsan_stat_get_table_info( 4042 unit, vsan, &num_of_tables, &table_info[0])); 4043 4044 /* Get the flex counter for the attached table index */ 4045 for (table_count = 0; table_count < num_of_tables ; table_count++) { 4046 if (table_info[table_count].direction == direction) { 4047 for (index_count = 0; index_count < num_entries ; index_count++) { 4048 BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_get( 4049 unit, sync_mode, 4050 table_info[table_count].index, 4051 table_info[table_count].table, 4052 0, 4053 byte_flag, 4054 counter_indexes[index_count], 4055 &counter_values[index_count])); 4056 } 4057 } 4058 } 4059 4060 return BCM_E_NONE; 4061 } 4062 4063 /* Set flex counter for FCOE VSAN ID */ 4064 int 4065 bcm_td2_fcoe_vsan_stat_counter_set (int unit, 4066 bcm_fcoe_vsan_id_t vsan, 4067 bcm_fcoe_vsan_stat_t stat, 4068 uint32 num_entries, 4069 uint32 *counter_indexes, 4070 bcm_stat_value_t *counter_values) 4071 { 4072 uint32 table_count = 0; 4073 uint32 index_count = 0; 4074 uint32 num_of_tables = 0; 4075 bcm_stat_flex_direction_t direction = bcmStatFlexDirectionIngress; 4076 uint32 byte_flag = 0; 4077 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4078 4079 if ((stat == bcmFcoeVsanInPackets) || 4080 (stat == bcmFcoeVsanInBytes)) { 4081 direction = bcmStatFlexDirectionIngress; 4082 } else { 4083 return BCM_E_PARAM; 4084 } 4085 if (stat == bcmFcoeVsanInBytes) { 4086 byte_flag = 1; 4087 } 4088 4089 /* Get Table index to read the flex counter */ 4090 BCM_IF_ERROR_RETURN(_bcm_td2_vsan_stat_get_table_info( 4091 unit, vsan, &num_of_tables, &table_info[0])); 4092 4093 /* Set the flex counter for the attached table index */ 4094 for (table_count = 0; table_count < num_of_tables ; table_count++) { 4095 if (table_info[table_count].direction == direction) { 4096 for (index_count = 0; index_count < num_entries; index_count++) { 4097 BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_set( 4098 unit, 4099 table_info[table_count].index, 4100 table_info[table_count].table, 4101 0, 4102 byte_flag, 4103 counter_indexes[index_count], 4104 &counter_values[index_count])); 4105 } 4106 } 4107 } 4108 return BCM_E_NONE; 4109 } 4110 4111 /* Get stat counter ID for FCOE VSAN ID */ 4112 int 4113 bcm_td2_fcoe_vsan_stat_id_get (int unit, 4114 bcm_fcoe_vsan_id_t vsan, 4115 bcm_fcoe_vsan_stat_t stat, 4116 uint32 *stat_counter_id) 4117 { 4118 bcm_stat_flex_direction_t direction = bcmStatFlexDirectionIngress; 4119 uint32 num_of_tables = 0; 4120 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4121 uint32 index = 0; 4122 uint32 num_stat_counter_ids = 0; 4123 4124 if ((stat == bcmFcoeVsanInPackets) || 4125 (stat == bcmFcoeVsanInBytes)) { 4126 direction = bcmStatFlexDirectionIngress; 4127 } else { 4128 return BCM_E_PARAM; 4129 } 4130 4131 /* Get Tables, for which flex counter are attached */ 4132 BCM_IF_ERROR_RETURN( 4133 _bcm_td2_vsan_stat_get_table_info(unit, vsan, &num_of_tables, 4134 &table_info[0])); 4135 4136 /* Retrieve stat counter id */ 4137 for (index = 0; index < num_of_tables ; index++) { 4138 if (table_info[index].direction == direction) { 4139 return _bcm_esw_stat_flex_get_counter_id( 4140 unit, 1, &table_info[index], 4141 &num_stat_counter_ids, stat_counter_id); 4142 } 4143 } 4144 return BCM_E_NOT_FOUND; 4145 } 4146 4147 #if defined (INCLUDE_L3) 4148 4149 STATIC int 4150 _bcm_td2_fcoe_route_index_get_ext(int unit, bcm_fcoe_route_t *route, int *index) 4151 { 4152 l3_entry_ipv4_multicast_entry_t l3_ext_entry[2]; 4153 4154 soc_mem_t mem = _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit); 4155 uint32 *buf = (uint32 *)&l3_ext_entry[0]; 4156 uint32 *lookup = (uint32 *)&l3_ext_entry[1]; 4157 4158 memset(&l3_ext_entry, 0, sizeof l3_ext_entry); 4159 4160 BCM_IF_ERROR_RETURN(_bcm_fcoe_route_construct_key_ext(unit, mem, buf, 4161 route)); 4162 4163 /* Search for this key in the existing database */ 4164 return soc_mem_search(unit, mem, MEM_BLOCK_ANY, index, buf, 4165 (void *)lookup, 0); 4166 } 4167 4168 4169 STATIC int 4170 _bcm_td2_fcoe_route_index_get_normal(int unit, bcm_fcoe_route_t *route, int *index) 4171 { 4172 l3_entry_ipv4_unicast_entry_t l3_entry[2]; 4173 4174 soc_mem_t mem = _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit); 4175 uint32 *buf = (uint32 *)&l3_entry[0]; 4176 uint32 *lookup = (uint32 *)&l3_entry[1]; 4177 4178 memset(&l3_entry, 0, sizeof l3_entry); 4179 4180 BCM_IF_ERROR_RETURN(_bcm_fcoe_route_construct_key_normal(unit, mem, buf, 4181 route)); 4182 4183 /* Search for this key in the existing database */ 4184 return soc_mem_search(unit, mem, MEM_BLOCK_ANY, index, buf, 4185 (void *)lookup, 0); 4186 } 4187 4188 4189 STATIC int 4190 _bcm_td2_fcoe_route_index_get(int unit, bcm_fcoe_route_t *route, int *index) 4191 { 4192 int rv; 4193 4194 rv = _bcm_td2_fcoe_route_index_get_normal(unit, route, index); 4195 4196 if (rv != BCM_E_NONE) { 4197 rv = _bcm_td2_fcoe_route_index_get_ext(unit, route, index); 4198 } 4199 4200 return rv; 4201 } 4202 4203 /* 4204 * Provides relevant flex table information(table-name,index with 4205 * direction) for given route info. 4206 */ 4207 STATIC bcm_error_t 4208 _bcm_td2_fcoe_route_stat_get_table_info ( 4209 int unit, 4210 bcm_fcoe_route_t *route, 4211 uint32 *num_of_tables, 4212 bcm_stat_flex_table_info_t *table_info) 4213 { 4214 int index = 0; 4215 4216 if (!soc_feature(unit,soc_feature_advanced_flex_counter)) { 4217 return BCM_E_UNAVAIL; 4218 } 4219 4220 /* Get unique index for the route info. 4221 * Support all fcoe types: FCOE_DOMAIN_EXT, FCOE_HOST_EXT, 4222 * FCOE_SOURCE_MAP_EXT 4223 */ 4224 if (_bcm_td2_fcoe_route_index_get(unit, route, &index) != BCM_E_NONE) { 4225 return BCM_E_NOT_FOUND; 4226 } 4227 4228 /* Ingress FCOE */ 4229 table_info[*num_of_tables].table = _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit); 4230 table_info[*num_of_tables].index = (uint32)index; 4231 table_info[*num_of_tables].direction = bcmStatFlexDirectionIngress; 4232 (*num_of_tables)++; 4233 4234 return BCM_E_NONE; 4235 } 4236 #endif /* INCLUDE_L3*/ 4237 4238 /* Allocate flex counter and assign counter index/offset for 4239 * FCOE Route 4240 */ 4241 int 4242 bcm_td2_fcoe_route_stat_attach (int unit, 4243 bcm_fcoe_route_t *route, 4244 uint32 stat_counter_id) 4245 { 4246 #if defined(INCLUDE_L3) 4247 4248 int rv = BCM_E_NONE; 4249 int counter_flag = 0; 4250 soc_mem_t table = 0; 4251 bcm_stat_flex_direction_t direction = bcmStatFlexDirectionIngress; 4252 uint32 pool_number = 0; 4253 uint32 base_index = 0; 4254 bcm_stat_flex_mode_t offset_mode = 0; 4255 bcm_stat_object_t object = bcmStatObjectIngPort; 4256 bcm_stat_group_mode_t group_mode = bcmStatGroupModeSingle; 4257 uint32 count = 0; 4258 uint32 actual_num_tables = 0; 4259 uint32 num_of_tables = 0; 4260 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4261 4262 if (!BCM_XGS3_L3_EGRESS_MODE_ISSET(unit) || 4263 (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, route->intf)) || 4264 (BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, route->intf)) || 4265 (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, route->intf)) || 4266 (BCM_XGS3_PROXY_EGRESS_IDX_VALID(unit, route->intf))) { 4267 return BCM_E_PARAM; 4268 } 4269 4270 /* Get pool, base index group mode and offset modes from stat counter id */ 4271 _bcm_esw_stat_get_counter_id_info(unit, stat_counter_id, &group_mode, &object, 4272 &offset_mode, &pool_number, &base_index); 4273 4274 /* Validate object and group mode */ 4275 BCM_IF_ERROR_RETURN( 4276 _bcm_esw_stat_validate_object(unit, object, &direction)); 4277 BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_group(unit, group_mode)); 4278 4279 /* Get Table index to attach flexible counter */ 4280 BCM_IF_ERROR_RETURN( 4281 _bcm_esw_stat_flex_get_table_info(unit, object, 1, &actual_num_tables, 4282 &table, &direction)); 4283 BCM_IF_ERROR_RETURN( 4284 _bcm_td2_fcoe_route_stat_get_table_info(unit, route, &num_of_tables, 4285 &table_info[0])); 4286 4287 for (count = 0; count < num_of_tables; count++) { 4288 if ((table_info[count].direction == direction) && 4289 (table_info[count].table == table) ) { 4290 if (direction == bcmStatFlexDirectionIngress) { 4291 counter_flag = 1; 4292 rv = _bcm_esw_stat_flex_attach_ingress_table_counters( 4293 unit, 4294 table_info[count].table, 4295 table_info[count].index, 4296 offset_mode, 4297 base_index, 4298 pool_number); 4299 if(BCM_FAILURE(rv)) { 4300 break; 4301 } 4302 } else { 4303 /* shouldn't reach here, only ingress is supported */ 4304 } 4305 } 4306 } 4307 4308 if (counter_flag == 0) { 4309 rv = BCM_E_NOT_FOUND; 4310 } 4311 4312 return rv; 4313 #else 4314 return BCM_E_UNAVAIL; 4315 #endif /* INCLUDE_L3 */ 4316 } 4317 4318 /* Detach flex counter for FCOE Route */ 4319 int 4320 bcm_td2_fcoe_route_stat_detach (int unit, bcm_fcoe_route_t *route) 4321 { 4322 #if defined(INCLUDE_L3) 4323 int counter_flag = 0; 4324 uint32 count = 0; 4325 uint32 num_of_tables = 0; 4326 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4327 int rv = BCM_E_NONE; 4328 4329 /* Get the table index to be detached */ 4330 BCM_IF_ERROR_RETURN(_bcm_td2_fcoe_route_stat_get_table_info( 4331 unit, route, &num_of_tables, &table_info[0])); 4332 4333 for (count = 0; count < num_of_tables; count++) { 4334 if (table_info[count].direction == bcmStatFlexDirectionIngress) { 4335 counter_flag = 1; 4336 rv = _bcm_esw_stat_flex_detach_ingress_table_counters( 4337 unit, table_info[count].table, table_info[count].index); 4338 } else { 4339 /* no egress support */ 4340 } 4341 } 4342 4343 if (counter_flag == 0) { 4344 return BCM_E_NOT_FOUND; 4345 } 4346 4347 return rv; 4348 #else 4349 return BCM_E_UNAVAIL; 4350 #endif /* INCLUDE_L3 */ 4351 } 4352 4353 /* Get flex counter for FCOE Route */ 4354 int 4355 bcm_td2_fcoe_route_stat_counter_get (int unit, 4356 int sync_mode, 4357 bcm_fcoe_route_t *route, 4358 bcm_fcoe_route_stat_t stat, 4359 uint32 num_entries, 4360 uint32 *counter_indexes, 4361 bcm_stat_value_t *counter_values) 4362 { 4363 #if defined(INCLUDE_L3) 4364 uint32 table_count = 0; 4365 uint32 index_count = 0; 4366 uint32 num_of_tables = 0; 4367 bcm_stat_flex_direction_t direction = bcmStatFlexDirectionIngress; 4368 uint32 byte_flag = 0; 4369 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4370 4371 if ((stat != bcmFcoeRouteInPackets) && (stat != bcmFcoeRouteInBytes)) { 4372 return BCM_E_PARAM; 4373 } 4374 4375 if (stat == bcmFcoeRouteInBytes) { 4376 byte_flag = 1; 4377 } 4378 4379 /* Get Table index to read the flex counter */ 4380 BCM_IF_ERROR_RETURN( 4381 _bcm_td2_fcoe_route_stat_get_table_info(unit, route, &num_of_tables, 4382 &table_info[0])); 4383 4384 /* Get the flex counter for the attached table index */ 4385 for (table_count = 0; table_count < num_of_tables ; table_count++) { 4386 if (table_info[table_count].direction == direction) { 4387 for (index_count = 0; index_count < num_entries ; index_count++) { 4388 BCM_IF_ERROR_RETURN( 4389 _bcm_esw_stat_counter_get(unit, sync_mode, 4390 table_info[table_count].index, 4391 table_info[table_count].table, 4392 0, 4393 byte_flag, 4394 counter_indexes[index_count], 4395 &counter_values[index_count])); 4396 } 4397 } 4398 } 4399 4400 return BCM_E_NONE; 4401 #else 4402 return BCM_E_UNAVAIL; 4403 #endif /* INCLUDE_L3 */ 4404 } 4405 4406 /* Set flex counter for FCOE Route */ 4407 int 4408 bcm_td2_fcoe_route_stat_counter_set (int unit, 4409 bcm_fcoe_route_t *route, 4410 bcm_fcoe_route_stat_t stat, 4411 uint32 num_entries, 4412 uint32 *counter_indexes, 4413 bcm_stat_value_t *counter_values) 4414 { 4415 #if defined(INCLUDE_L3) 4416 uint32 table_count = 0; 4417 uint32 index_count = 0; 4418 uint32 num_of_tables = 0; 4419 bcm_stat_flex_direction_t direction = bcmStatFlexDirectionIngress; 4420 uint32 byte_flag = 0; 4421 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4422 4423 if ((stat != bcmFcoeRouteInPackets) && (stat != bcmFcoeRouteInBytes)) { 4424 return BCM_E_PARAM; 4425 } 4426 4427 if (stat == bcmFcoeRouteInBytes) { 4428 byte_flag = 1; 4429 } 4430 4431 /* Get Table index to read the flex counter */ 4432 BCM_IF_ERROR_RETURN( 4433 _bcm_td2_fcoe_route_stat_get_table_info(unit, route, &num_of_tables, 4434 &table_info[0])); 4435 4436 /* Get the flex counter for the attached table index */ 4437 for (table_count = 0; table_count < num_of_tables ; table_count++) { 4438 if (table_info[table_count].direction == direction) { 4439 for (index_count = 0; index_count < num_entries; index_count++) { 4440 BCM_IF_ERROR_RETURN( 4441 _bcm_esw_stat_counter_set(unit, 4442 table_info[table_count].index, 4443 table_info[table_count].table, 4444 0, 4445 byte_flag, 4446 counter_indexes[index_count], 4447 &counter_values[index_count])); 4448 } 4449 } 4450 } 4451 return BCM_E_NONE; 4452 #else 4453 return BCM_E_UNAVAIL; 4454 #endif /* INCLUDE_L3 */ 4455 } 4456 4457 /* Get stat counter ID for FCOE Route */ 4458 int 4459 bcm_td2_fcoe_route_stat_id_get (int unit, 4460 bcm_fcoe_route_t *route, 4461 bcm_fcoe_route_stat_t stat, 4462 uint32 *stat_counter_id) 4463 { 4464 #if defined(INCLUDE_L3) 4465 bcm_stat_flex_direction_t direction = bcmStatFlexDirectionIngress; 4466 uint32 num_of_tables = 0; 4467 bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]; 4468 uint32 index = 0; 4469 uint32 num_stat_counter_ids = 0; 4470 4471 if ((stat != bcmFcoeRouteInPackets) && (stat != bcmFcoeRouteInBytes)) { 4472 return BCM_E_PARAM; 4473 } 4474 4475 /* Get Tables, for which flex counter are attached */ 4476 BCM_IF_ERROR_RETURN( 4477 _bcm_td2_fcoe_route_stat_get_table_info(unit, route, &num_of_tables, 4478 &table_info[0])); 4479 4480 /* Retrieve stat counter id */ 4481 for (index = 0; index < num_of_tables ; index++) { 4482 if (table_info[index].direction == direction) 4483 return _bcm_esw_stat_flex_get_counter_id(unit, 4484 1, 4485 &table_info[index], 4486 &num_stat_counter_ids, 4487 stat_counter_id); 4488 } 4489 return BCM_E_NOT_FOUND; 4490 #else 4491 return BCM_E_UNAVAIL; 4492 #endif /* INCLUDE_L3 */ 4493 } 4494 4495 #ifdef INCLUDE_L3 4496 4497 /* 4498 * Purpose: 4499 * Require exactly 1 of the following 3 flags: 4500 * BCM_FCOE_INTF_VFT_DO_NOT_MODIFY 4501 * BCM_FCOE_INTF_VFT_ADD_REPLACE 4502 * BCM_FCOE_INTF_VFT_DELETE 4503 * 4504 * Parameters: 4505 * flags - (IN) flags given by the application 4506 * vft_action - (OUT) the option that was chosen 4507 * 4508 * Returns: 4509 * BCM_E_XXX 4510 */ 4511 STATIC int 4512 _bcm_td2_vft_action_from_flags(uint32 flags, int *vft_action) 4513 { 4514 if (flags & BCM_FCOE_INTF_VFT_DO_NOT_MODIFY) { 4515 CHECK_FLAGS_NOT_SET(flags, BCM_FCOE_INTF_VFT_ADD_REPLACE 4516 | BCM_FCOE_INTF_VFT_DELETE); 4517 *vft_action = FCOE_VFT_ACTION_DO_NOT_MODIFY; 4518 } else if (flags & BCM_FCOE_INTF_VFT_ADD_REPLACE) { 4519 CHECK_FLAGS_NOT_SET(flags, BCM_FCOE_INTF_VFT_DO_NOT_MODIFY 4520 | BCM_FCOE_INTF_VFT_DELETE); 4521 *vft_action = FCOE_VFT_ACTION_ADD_REPLACE; 4522 } else if (flags & BCM_FCOE_INTF_VFT_DELETE) { 4523 CHECK_FLAGS_NOT_SET(flags, BCM_FCOE_INTF_VFT_DO_NOT_MODIFY 4524 | BCM_FCOE_INTF_VFT_ADD_REPLACE); 4525 *vft_action = FCOE_VFT_ACTION_DELETE; 4526 } else { 4527 return BCM_E_PARAM; 4528 } 4529 4530 return BCM_E_NONE; 4531 } 4532 4533 STATIC int 4534 _bcm_td2_fcoe_vsan_id_sel_check(bcm_fcoe_intf_vsan_id_source_t src, 4535 int *fabric_id_sel) 4536 { 4537 if (src == bcmFcoeIntfVsanSet) { 4538 *fabric_id_sel = FCOE_FABRIC_ID_SEL_SET; 4539 } else if (src == bcmFcoeIntfVsanInternal) { 4540 *fabric_id_sel = FCOE_FABRIC_ID_SEL_INTERNAL; 4541 } else if (src == bcmFcoeIntfVsanInnerVlan) { 4542 *fabric_id_sel = FCOE_FABRIC_ID_SEL_INNER_VLAN; 4543 } else if (src == bcmFcoeIntfVsanOuterVlan) { 4544 *fabric_id_sel = FCOE_FABRIC_ID_SEL_OUTER_VLAN; 4545 } else { 4546 return BCM_E_PARAM; 4547 } 4548 4549 return BCM_E_NONE; 4550 } 4551 4552 STATIC int 4553 _bcm_td2_fcoe_vsan_pri_sel_check(bcm_fcoe_intf_vsan_pri_source_t src, 4554 int *fabric_pri_sel) 4555 { 4556 if (src == bcmFcoeIntfVsanPriSet) { 4557 *fabric_pri_sel = FCOE_FABRIC_PRI_SEL_SET; 4558 } else if (src == bcmFcoeIntfVsanPriInternal) { 4559 *fabric_pri_sel = FCOE_FABRIC_PRI_SEL_INTERNAL; 4560 } else if (src == bcmFcoeIntfVsanPriRemark) { 4561 *fabric_pri_sel = FCOE_FABRIC_PRI_SEL_REMARK; 4562 } else { 4563 return BCM_E_PARAM; 4564 } 4565 4566 return BCM_E_NONE; 4567 } 4568 4569 #endif 4570 4571 /* 4572 * _bcm_td2_add_vft_fields_profile 4573 * Add data in *cfg to EGR_VFT_FIELDS_PROFILE and store the index used into 4574 * vft_fields_idx 4575 */ 4576 STATIC int 4577 _bcm_td2_add_vft_fields_profile(int unit, bcm_fcoe_vsan_vft_t *cfg, 4578 uint32 *vft_fields_idx) 4579 { 4580 int rv; 4581 soc_mem_t mem = EGR_VFT_FIELDS_PROFILEm; 4582 egr_vft_fields_profile_entry_t entry; 4583 void *entries = (void *)&entry; 4584 4585 sal_memset(&entry, 0, sizeof entry); 4586 4587 soc_mem_field32_set(unit, mem, (uint32 *)&entry, FCOE_VFT_R_CTLf, 4588 cfg->r_ctl); 4589 soc_mem_field32_set(unit, mem, (uint32 *)&entry, FCOE_VFT_VERSIONf, 4590 cfg->version); 4591 soc_mem_field32_set(unit, mem, (uint32 *)&entry, FCOE_VFT_TYPEf, 4592 cfg->type); 4593 soc_mem_field32_set(unit, mem, (uint32 *)&entry, FCOE_VFT_HOP_COUNTf, 4594 cfg->hop_count); 4595 4596 soc_mem_field32_set(unit, mem, (uint32 *)&entry, FCOE_VFT_R1f, 0); 4597 soc_mem_field32_set(unit, mem, (uint32 *)&entry, FCOE_VFT_R2f, 0); 4598 soc_mem_field32_set(unit, mem, (uint32 *)&entry, FCOE_VFT_Ef, 0); 4599 4600 rv = _bcm_egr_vft_fields_entry_add(unit, &entries, VFT_NUM_ENTRIES, 4601 vft_fields_idx); 4602 return rv; 4603 } 4604 4605 /* 4606 * _bcm_td2_inc_vft_profile_refcnt 4607 * Increment the reference count for the given vft fields index 4608 */ 4609 STATIC int 4610 _bcm_td2_inc_vft_profile_refcnt(int unit, uint32 index) 4611 { 4612 _bcm_td2_fcoe_bk_info[unit].profile_use_refcnt[index]++; 4613 return BCM_E_NONE; 4614 } 4615 4616 /* 4617 * _bcm_td2_dec_vft_profile_refcnt 4618 * Decrement the reference count for the given vft fields index. Delete the 4619 * table entry if the counter reaches zero. 4620 */ 4621 STATIC int 4622 _bcm_td2_dec_vft_profile_refcnt(int unit, uint32 index) 4623 { 4624 _bcm_td2_fcoe_bk_info[unit].profile_use_refcnt[index]--; 4625 4626 if (_bcm_td2_fcoe_bk_info[unit].profile_use_refcnt[index] == 0) { 4627 return _bcm_egr_vft_fields_entry_del(unit, index); 4628 } 4629 4630 return BCM_E_NONE; 4631 } 4632 4633 #ifdef INCLUDE_L3 4634 4635 /* 4636 * _bcm_td2_vft_fields_profile_sanity 4637 * Sanity check for the values in a bcm_fcoe_vsan_vft_t structure. They're 4638 * all uint8s, so only check the 2 values that don't allow all 8 bits to be 4639 * used. 4640 */ 4641 STATIC int 4642 _bcm_td2_vft_fields_profile_sanity(bcm_fcoe_vsan_vft_t *cfg) 4643 { 4644 if ((cfg->version > 3) || (cfg->type > 15)) { 4645 return BCM_E_PARAM; 4646 } 4647 4648 return BCM_E_NONE; 4649 } 4650 4651 /* 4652 * _bcm_td2_set_intf_config 4653 * Store values into the EGR_L3_INTF table 4654 */ 4655 STATIC int 4656 _bcm_td2_set_intf_config(int unit, bcm_if_t intf, bcm_fcoe_intf_config_t *cfg, 4657 uint32 vft_fields_idx, int vft_action, 4658 int fabric_id_sel, int fabric_pri_sel) 4659 { 4660 egr_l3_intf_entry_t intf_entry; 4661 uint32 *buf = (uint32 *)&intf_entry; 4662 int rv = BCM_E_NONE; 4663 soc_mem_t mem = EGR_L3_INTFm; 4664 int old_fields_idx; 4665 int qos_map_hwidx; 4666 4667 if (intf >= soc_mem_index_max(unit, mem)) { 4668 return BCM_E_PARAM; 4669 } 4670 4671 if (fabric_pri_sel == FCOE_FABRIC_PRI_SEL_REMARK) { 4672 BCM_IF_ERROR_RETURN(bcm_td2_qos_get_egr_vsan_hw_idx(unit, cfg->qos_map_id, 4673 &qos_map_hwidx)); 4674 4675 } 4676 4677 sal_memset(buf, 0, sizeof intf_entry); 4678 4679 soc_mem_lock(unit, mem); 4680 rv = BCM_XGS3_MEM_READ(unit, mem, intf, buf); 4681 if (BCM_FAILURE(rv)) { 4682 soc_mem_unlock(unit, mem); 4683 return rv; 4684 } 4685 4686 old_fields_idx = soc_mem_field32_get(unit, mem, buf, 4687 FCOE_VFT_FIELDS_PROFILE_INDEXf); 4688 if ((old_fields_idx != vft_fields_idx) && (old_fields_idx != 0)) { 4689 rv = _bcm_td2_dec_vft_profile_refcnt(unit, old_fields_idx); 4690 if (BCM_FAILURE(rv)) { 4691 soc_mem_unlock(unit, mem); 4692 return rv; 4693 } 4694 } 4695 4696 soc_mem_field32_set(unit, mem, buf, FCOE_VFT_ACTIONf, vft_action); 4697 soc_mem_field32_set(unit, mem, buf, FCOE_FABRIC_ID_SELf, fabric_id_sel); 4698 soc_mem_field32_set(unit, mem, buf, FCOE_FABRIC_PRI_SELf, fabric_pri_sel); 4699 soc_mem_field32_set(unit, mem, buf, FCOE_VSAN_IDf, cfg->vsan); 4700 if (fabric_pri_sel == FCOE_FABRIC_PRI_SEL_SET) { 4701 soc_mem_field32_set(unit, mem, buf, FCOE_VSAN_PRIf, cfg->vsan_pri); 4702 } else if (fabric_pri_sel == FCOE_FABRIC_PRI_SEL_REMARK) { 4703 soc_mem_field32_set(unit, mem, buf, FCOE_VSAN_PRI_MAPPING_PROFILEf, 4704 qos_map_hwidx); 4705 } 4706 soc_mem_field32_set(unit, mem, buf, FCOE_VFT_FIELDS_PROFILE_INDEXf, 4707 vft_fields_idx); 4708 4709 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, intf, buf); 4710 4711 soc_mem_unlock(unit, mem); 4712 4713 return rv; 4714 } 4715 4716 4717 /* Set parameters for FCOE L3 interface */ 4718 int 4719 bcm_td2_fcoe_intf_config_set(int unit, uint32 flags, bcm_if_t intf, 4720 bcm_fcoe_intf_config_t *cfg) 4721 { 4722 int rv = BCM_E_NONE; 4723 int vft_action = 0; 4724 int fabric_id_sel = 0; 4725 int fabric_pri_sel = 0; 4726 uint32 vft_fields_idx = 0; 4727 4728 /* Translate flags into hardware values and test validity */ 4729 BCM_IF_ERROR_RETURN(_bcm_td2_vft_action_from_flags(cfg->flags, 4730 &vft_action)); 4731 BCM_IF_ERROR_RETURN(_bcm_td2_fcoe_vsan_pri_sel_check(cfg->vsan_pri_source, 4732 &fabric_pri_sel)); 4733 BCM_IF_ERROR_RETURN(_bcm_td2_fcoe_vsan_id_sel_check(cfg->vsan_source, 4734 &fabric_id_sel)); 4735 4736 /* Check that the VFT profile is valid, and add it */ 4737 BCM_IF_ERROR_RETURN(_bcm_td2_vft_fields_profile_sanity(&cfg->vft)); 4738 BCM_IF_ERROR_RETURN(_bcm_td2_add_vft_fields_profile(unit, &cfg->vft, 4739 &vft_fields_idx)); 4740 BCM_IF_ERROR_RETURN(_bcm_td2_inc_vft_profile_refcnt(unit, vft_fields_idx)); 4741 4742 /* Set interface properties */ 4743 rv = _bcm_td2_set_intf_config(unit, intf, cfg, vft_fields_idx, vft_action, 4744 fabric_id_sel, fabric_pri_sel); 4745 if (BCM_FAILURE(rv)) { 4746 BCM_IF_ERROR_RETURN(_bcm_td2_dec_vft_profile_refcnt(unit, 4747 vft_fields_idx)); 4748 return rv; 4749 } 4750 4751 return rv; 4752 } 4753 4754 #endif 4755 4756 /* Read data out of the EGR_VFT_FIELDS_PROFILE table and store it in a 4757 * bcm_fcoe_vsan_vft_t structure */ 4758 STATIC int 4759 _bcm_td2_get_fields_profile(int unit, int vft_fields_idx, 4760 bcm_fcoe_vsan_vft_t *vft) 4761 { 4762 soc_mem_t mem = EGR_VFT_FIELDS_PROFILEm; 4763 egr_vft_fields_profile_entry_t entry; 4764 void *entries = (void *)&entry; 4765 4766 sal_memset(&entry, 0, sizeof entry); 4767 BCM_IF_ERROR_RETURN(_bcm_egr_vft_fields_entry_get(unit, vft_fields_idx, 4768 VFT_NUM_ENTRIES, 4769 &entries)); 4770 4771 vft->r_ctl = soc_mem_field32_get(unit, mem, &entry, FCOE_VFT_R_CTLf); 4772 vft->version = soc_mem_field32_get(unit, mem, &entry, FCOE_VFT_VERSIONf); 4773 vft->type = soc_mem_field32_get(unit, mem, &entry, FCOE_VFT_TYPEf); 4774 vft->hop_count = soc_mem_field32_get(unit, mem, &entry, FCOE_VFT_HOP_COUNTf); 4775 4776 return BCM_E_NONE; 4777 } 4778 4779 #ifdef INCLUDE_L3 4780 4781 /* Get parameters for FCOE L3 interface */ 4782 int 4783 bcm_td2_fcoe_intf_config_get(int unit, uint32 flags, bcm_if_t intf, 4784 bcm_fcoe_intf_config_t *cfg) 4785 { 4786 egr_l3_intf_entry_t intf_entry; 4787 uint32 *buf = (uint32 *)&intf_entry; 4788 int rv = BCM_E_NONE; 4789 soc_mem_t mem = EGR_L3_INTFm; 4790 int vft_fields_idx = 0; 4791 int qos_map_hwidx = 0; 4792 4793 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, mem, intf, buf)); 4794 4795 vft_fields_idx = soc_mem_field32_get(unit, mem, buf, 4796 FCOE_VFT_FIELDS_PROFILE_INDEXf); 4797 4798 switch (soc_mem_field32_get(unit, mem, buf, FCOE_VFT_ACTIONf)) { 4799 case FCOE_VFT_ACTION_DO_NOT_MODIFY: 4800 cfg->flags |= BCM_FCOE_INTF_VFT_DO_NOT_MODIFY; 4801 break; 4802 4803 case FCOE_VFT_ACTION_ADD_REPLACE: 4804 cfg->flags |= BCM_FCOE_INTF_VFT_ADD_REPLACE; 4805 break; 4806 4807 case FCOE_VFT_ACTION_DELETE: 4808 cfg->flags |= BCM_FCOE_INTF_VFT_DELETE; 4809 break; 4810 4811 default: 4812 return BCM_E_FAIL; 4813 } 4814 4815 switch (soc_mem_field32_get(unit, mem, buf, FCOE_FABRIC_ID_SELf)) { 4816 case FCOE_FABRIC_ID_SEL_SET: 4817 cfg->vsan_source = bcmFcoeIntfVsanSet; 4818 break; 4819 4820 case FCOE_FABRIC_ID_SEL_INTERNAL: 4821 cfg->vsan_source = bcmFcoeIntfVsanInternal; 4822 break; 4823 4824 case FCOE_FABRIC_ID_SEL_INNER_VLAN: 4825 cfg->vsan_source = bcmFcoeIntfVsanInnerVlan; 4826 break; 4827 4828 case FCOE_FABRIC_ID_SEL_OUTER_VLAN: 4829 cfg->vsan_source = bcmFcoeIntfVsanOuterVlan; 4830 break; 4831 4832 default: 4833 return BCM_E_FAIL; 4834 } 4835 4836 switch (soc_mem_field32_get(unit, mem, buf, FCOE_FABRIC_PRI_SELf)) { 4837 case FCOE_FABRIC_PRI_SEL_SET: 4838 cfg->vsan_pri_source = bcmFcoeIntfVsanPriSet; 4839 break; 4840 4841 case FCOE_FABRIC_PRI_SEL_INTERNAL: 4842 cfg->vsan_pri_source = bcmFcoeIntfVsanPriInternal; 4843 break; 4844 4845 case FCOE_FABRIC_PRI_SEL_REMARK: 4846 cfg->vsan_pri_source = bcmFcoeIntfVsanPriRemark; 4847 break; 4848 4849 default: 4850 return BCM_E_FAIL; 4851 } 4852 4853 cfg->vsan = soc_mem_field32_get(unit, mem, buf, FCOE_VSAN_IDf); 4854 vft_fields_idx = soc_mem_field32_get(unit, mem, buf, 4855 FCOE_VFT_FIELDS_PROFILE_INDEXf); 4856 if (cfg->vsan_pri_source == bcmFcoeIntfVsanPriSet) { 4857 cfg->vsan_pri = soc_mem_field32_get(unit, mem, buf, FCOE_VSAN_PRIf); 4858 } else if (cfg->vsan_pri_source == bcmFcoeIntfVsanPriRemark) { 4859 qos_map_hwidx = soc_mem_field32_get(unit, mem, buf, 4860 FCOE_VSAN_PRI_MAPPING_PROFILEf); 4861 BCM_IF_ERROR_RETURN(bcm_td2_vsan_profile_to_qos_id(unit, qos_map_hwidx, 4862 &cfg->qos_map_id)); 4863 } 4864 4865 BCM_IF_ERROR_RETURN(_bcm_td2_get_fields_profile(unit, vft_fields_idx, 4866 &cfg->vft)); 4867 4868 return rv; 4869 } 4870 4871 #endif /* INCLUDE_L3 */ 4872 4873 4874 /* construct a key for VLAN_XLATE table search */ 4875 STATIC int 4876 _bcm_td2_fcoe_ing_vlan_translate_entry_assemble( 4877 int unit, 4878 void *vent, 4879 bcm_fcoe_vsan_translate_key_config_t *key) 4880 { 4881 if (soc_feature(unit, soc_feature_fcoe)) { 4882 bcm_module_t mod_out; 4883 bcm_port_t port_out; 4884 bcm_trunk_t trunk_out; 4885 int tmp_id; 4886 int key_type_value; 4887 int key_type; 4888 int use_glp = 1; 4889 int mem = VLAN_XLATEm; 4890 4891 if (SOC_MEM_IS_VALID(unit, VLAN_XLATE_1_DOUBLEm)) { 4892 mem = VLAN_XLATE_1_DOUBLEm; 4893 } 4894 4895 switch (key->key_type) { 4896 case bcmFcoeVsanTranslateKeyDouble: 4897 use_glp = 0; 4898 key_type = VLXLT_HASH_KEY_TYPE_IVID_OVID; 4899 soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf, 4900 key->outer_vlan); 4901 soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf, 4902 key->inner_vlan); 4903 break; 4904 4905 case bcmFcoeVsanTranslateKeyOuter: 4906 use_glp = 0; 4907 key_type = VLXLT_HASH_KEY_TYPE_OVID; 4908 soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf, 4909 key->outer_vlan); 4910 break; 4911 4912 case bcmFcoeVsanTranslateKeyInner: 4913 use_glp = 0; 4914 key_type = VLXLT_HASH_KEY_TYPE_IVID; 4915 soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf, 4916 key->inner_vlan); 4917 break; 4918 4919 case bcmFcoeVsanTranslateKeyOuterTag: 4920 use_glp = 0; 4921 key_type = VLXLT_HASH_KEY_TYPE_OTAG; 4922 4923 /* vlan id should also have PRI/CFI bits */ 4924 soc_mem_field32_set(unit, mem, vent, XLATE__OTAGf, 4925 key->outer_vlan); 4926 break; 4927 4928 case bcmFcoeVsanTranslateKeyInnerTag: 4929 use_glp = 0; 4930 key_type = VLXLT_HASH_KEY_TYPE_ITAG; 4931 /* vlan id should also have PRI/CFI bits */ 4932 soc_mem_field32_set(unit, mem, vent, XLATE__ITAGf, 4933 key->inner_vlan); 4934 break; 4935 4936 case bcmFcoeVsanTranslateKeyOuterPri: 4937 use_glp = 0; 4938 key_type = VLXLT_HASH_KEY_TYPE_PRI_CFI; 4939 4940 /* vlan id should have PRI/CFI bits */ 4941 soc_mem_field32_set(unit, mem, vent, XLATE__OTAGf, 4942 key->outer_vlan); 4943 break; 4944 4945 case bcmFcoeVsanTranslateKeyPortDouble: 4946 key_type = VLXLT_HASH_KEY_TYPE_IVID_OVID; 4947 soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf, 4948 key->outer_vlan); 4949 soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf, 4950 key->inner_vlan); 4951 break; 4952 4953 case bcmFcoeVsanTranslateKeyPortOuter: 4954 key_type = VLXLT_HASH_KEY_TYPE_OVID; 4955 soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf, 4956 key->outer_vlan); 4957 break; 4958 4959 case bcmFcoeVsanTranslateKeyPortInner: 4960 key_type = VLXLT_HASH_KEY_TYPE_IVID; 4961 soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf, 4962 key->inner_vlan); 4963 break; 4964 4965 case bcmFcoeVsanTranslateKeyPortOuterTag: 4966 key_type = VLXLT_HASH_KEY_TYPE_OTAG; 4967 /* vlan id should also have PRI/CFI bits */ 4968 soc_mem_field32_set(unit, mem, vent, XLATE__OTAGf, 4969 key->outer_vlan); 4970 break; 4971 4972 case bcmFcoeVsanTranslateKeyPortInnerTag: 4973 key_type = VLXLT_HASH_KEY_TYPE_ITAG; 4974 /* vlan id should also have PRI/CFI bits */ 4975 soc_mem_field32_set(unit, mem, vent, XLATE__ITAGf, 4976 key->inner_vlan); 4977 break; 4978 4979 case bcmFcoeVsanTranslateKeyPortOuterPri: 4980 key_type = VLXLT_HASH_KEY_TYPE_PRI_CFI; 4981 /* vlan id should have PRI/CFI bits */ 4982 soc_mem_field32_set(unit, mem, vent, XLATE__OTAGf, 4983 key->outer_vlan); 4984 break; 4985 4986 case bcmFcoeVsanTranslateKeyDoubleVsan: 4987 use_glp = 0; 4988 key_type = VLXLT_HASH_KEY_TYPE_IVID_OVID_VSAN; 4989 soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf, 4990 key->outer_vlan); 4991 soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf, 4992 key->inner_vlan); 4993 soc_mem_field32_set(unit, mem, vent, XLATE__VSAN_IDf, 4994 key->vsan); 4995 break; 4996 4997 case bcmFcoeVsanTranslateKeyInnerVsan: 4998 use_glp = 0; 4999 key_type = VLXLT_HASH_KEY_TYPE_IVID_VSAN; 5000 soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf, 5001 key->inner_vlan); 5002 soc_mem_field32_set(unit, mem, vent, XLATE__VSAN_IDf, 5003 key->vsan); 5004 break; 5005 5006 case bcmFcoeVsanTranslateKeyOuterVsan: 5007 use_glp = 0; 5008 key_type = VLXLT_HASH_KEY_TYPE_OVID_VSAN; 5009 soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf, 5010 key->outer_vlan); 5011 soc_mem_field32_set(unit, mem, vent, XLATE__VSAN_IDf, 5012 key->vsan); 5013 break; 5014 5015 case bcmFcoeVsanTranslateKeyPortDoubleVsan: 5016 key_type = VLXLT_HASH_KEY_TYPE_IVID_OVID_VSAN; 5017 soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf, 5018 key->outer_vlan); 5019 soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf, 5020 key->inner_vlan); 5021 soc_mem_field32_set(unit, mem, vent, XLATE__VSAN_IDf, 5022 key->vsan); 5023 break; 5024 5025 case bcmFcoeVsanTranslateKeyPortInnerVsan: 5026 key_type = VLXLT_HASH_KEY_TYPE_IVID_VSAN; 5027 soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf, 5028 key->inner_vlan); 5029 soc_mem_field32_set(unit, mem, vent, XLATE__VSAN_IDf, 5030 key->vsan); 5031 break; 5032 5033 case bcmFcoeVsanTranslateKeyPortOuterVsan: 5034 key_type = VLXLT_HASH_KEY_TYPE_OVID_VSAN; 5035 soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf, 5036 key->outer_vlan); 5037 soc_mem_field32_set(unit, mem, vent, XLATE__VSAN_IDf, 5038 key->vsan); 5039 break; 5040 5041 default: 5042 return BCM_E_PARAM; 5043 } 5044 5045 BCM_IF_ERROR_RETURN( 5046 _bcm_esw_vlan_xlate_key_type_value_get(unit, key_type, 5047 &key_type_value)); 5048 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, key_type_value); 5049 5050 5051 if (use_glp) { 5052 /* SGLP - Use SGLP {trunk, ModId(7,0), Port(6,0)} as the Source 5053 Field */ 5054 if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) { 5055 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1); 5056 } 5057 5058 BCM_IF_ERROR_RETURN( 5059 _bcm_esw_gport_resolve(unit, key->port, &mod_out, &port_out, 5060 &trunk_out, &tmp_id)); 5061 if (BCM_GPORT_IS_TRUNK(key->port)) { 5062 soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 1); 5063 soc_mem_field32_set(unit, mem, vent, XLATE__TGIDf, 5064 trunk_out); 5065 } else { 5066 soc_mem_field32_set(unit, mem, vent, XLATE__MODULE_IDf, 5067 mod_out); 5068 soc_mem_field32_set(unit, mem, vent, XLATE__PORT_NUMf, 5069 port_out); 5070 } 5071 } else { 5072 if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) { 5073 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 0); 5074 } 5075 /* incoming port not used in lookup key, set field to all 1's */ 5076 soc_mem_field32_set(unit, mem, vent, GLPf, 5077 SOC_VLAN_XLATE_GLP_WILDCARD(unit)); 5078 } 5079 5080 return BCM_E_NONE; 5081 } 5082 return BCM_E_UNAVAIL; 5083 } 5084 5085 uint32 5086 _bcm_td2_fcoe_ing_vft_pri_action_encode(bcm_fcoe_vsan_action_t action) 5087 { 5088 switch (action) { 5089 case bcmFcoeVsanActionNone: 5090 return _BCM_TD2_ING_VFT_PRI_ACTION_NONE; 5091 case bcmFcoeVsanActionInnerVlan: 5092 return _BCM_TD2_ING_VFT_PRI_ACTION_USE_INNER_PRI; 5093 case bcmFcoeVsanActionOuterVlan: 5094 return _BCM_TD2_ING_VFT_PRI_ACTION_USE_OUTER_PRI; 5095 case bcmFcoeVsanActionReplace: 5096 return _BCM_TD2_ING_VFT_PRI_ACTION_REPLACE; 5097 case bcmFcoeVsanActionDelete: 5098 case bcmFcoeVsanActionInternal: 5099 default: 5100 return _BCM_TD2_ING_VFT_PRI_ACTION_NONE; 5101 } 5102 } 5103 5104 /* 5105 * add a new entry to vlan action profile table -- ingress 5106 */ 5107 STATIC int 5108 _bcm_td2_ing_vlan_action_profile_entry_add( 5109 int unit, 5110 bcm_fcoe_vsan_action_set_t *action, 5111 uint32 *index) 5112 { 5113 5114 ing_vlan_tag_action_profile_entry_t ing_profile; 5115 ing_vlan_tag_action_profile_2_entry_t ing_profile_2; 5116 void *entry; 5117 soc_mem_t mem; 5118 int ent_sz; 5119 5120 if (SOC_MEM_IS_VALID(unit, ING_VLAN_TAG_ACTION_PROFILE_2m)) { 5121 mem = ING_VLAN_TAG_ACTION_PROFILE_2m; 5122 ent_sz = sizeof(ing_vlan_tag_action_profile_2_entry_t); 5123 entry = &ing_profile_2; 5124 } else { 5125 mem = ING_VLAN_TAG_ACTION_PROFILEm; 5126 ent_sz = sizeof(ing_vlan_tag_action_profile_entry_t); 5127 entry = &ing_profile; 5128 } 5129 5130 5131 /* Note : on ingress, no VFT Tag manipulation will happen. Only Pri 5132 * manipulation is allowed. 5133 * So, mark all Tag actions to None (it is done by above sal_memset) 5134 */ 5135 5136 sal_memset(entry, 0, ent_sz); 5137 /* 3 new PRI actions */ 5138 soc_mem_field32_set(unit, mem, entry, 5139 DT_VT_VPRI_ACTIONf, 5140 _bcm_td2_fcoe_ing_vft_pri_action_encode( 5141 action->dt_vsan_pri)); 5142 soc_mem_field32_set(unit, mem, entry, 5143 SOT_VT_VPRI_ACTIONf, 5144 _bcm_td2_fcoe_ing_vft_pri_action_encode( 5145 action->ot_vsan_pri)); 5146 soc_mem_field32_set(unit, mem, entry, 5147 SIT_VT_VPRI_ACTIONf, 5148 _bcm_td2_fcoe_ing_vft_pri_action_encode( 5149 action->it_vsan_pri)); 5150 5151 soc_mem_field32_set( 5152 unit, mem, entry, DT_OTAG_ACTIONf, 5153 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.dt_outer)); 5154 soc_mem_field32_set( 5155 unit, mem, entry, DT_POTAG_ACTIONf, 5156 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.dt_outer_prio)); 5157 soc_mem_field32_set( 5158 unit, mem, entry, DT_ITAG_ACTIONf, 5159 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.dt_inner)); 5160 soc_mem_field32_set( 5161 unit, mem, entry, DT_PITAG_ACTIONf, 5162 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.dt_inner_prio)); 5163 soc_mem_field32_set( 5164 unit, mem, entry, SOT_OTAG_ACTIONf, 5165 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ot_outer)); 5166 soc_mem_field32_set( 5167 unit, mem, entry, SOT_POTAG_ACTIONf, 5168 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ot_outer_prio)); 5169 soc_mem_field32_set( 5170 unit, mem, entry, SOT_ITAG_ACTIONf, 5171 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ot_inner)); 5172 soc_mem_field32_set( 5173 unit, mem, entry, SIT_OTAG_ACTIONf, 5174 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.it_outer)); 5175 soc_mem_field32_set( 5176 unit, mem, entry, SIT_ITAG_ACTIONf, 5177 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.it_inner)); 5178 soc_mem_field32_set( 5179 unit, mem, entry, SIT_PITAG_ACTIONf, 5180 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.it_inner_prio)); 5181 soc_mem_field32_set( 5182 unit, mem, entry, UT_OTAG_ACTIONf, 5183 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ut_outer)); 5184 soc_mem_field32_set( 5185 unit, mem, entry, UT_ITAG_ACTIONf, 5186 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ut_inner)); 5187 5188 if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) { 5189 soc_mem_field32_set( 5190 unit, mem, entry, DT_OPRI_ACTIONf, 5191 _BCM_TRX_PRI_CFI_ACTION_ENCODE( 5192 action->vlan_action.dt_outer_pkt_prio)); 5193 soc_mem_field32_set( 5194 unit, mem, entry, DT_OCFI_ACTIONf, 5195 _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.dt_outer_cfi)); 5196 soc_mem_field32_set( 5197 unit, mem, entry, DT_IPRI_ACTIONf, 5198 _BCM_TRX_PRI_CFI_ACTION_ENCODE( 5199 action->vlan_action.dt_inner_pkt_prio)); 5200 soc_mem_field32_set( 5201 unit, mem, entry, DT_ICFI_ACTIONf, 5202 _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.dt_inner_cfi)); 5203 soc_mem_field32_set( 5204 unit, mem, entry, SOT_OPRI_ACTIONf, 5205 _BCM_TRX_PRI_CFI_ACTION_ENCODE( 5206 action->vlan_action.ot_outer_pkt_prio)); 5207 soc_mem_field32_set( 5208 unit, mem, entry, SOT_OCFI_ACTIONf, 5209 _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.ot_outer_cfi)); 5210 soc_mem_field32_set( 5211 unit, mem, entry, SOT_IPRI_ACTIONf, 5212 _BCM_TRX_PRI_CFI_ACTION_ENCODE( 5213 action->vlan_action.ot_inner_pkt_prio)); 5214 soc_mem_field32_set( 5215 unit, mem, entry, SOT_ICFI_ACTIONf, 5216 _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.ot_inner_cfi)); 5217 soc_mem_field32_set( 5218 unit, mem, entry, SIT_OPRI_ACTIONf, 5219 _BCM_TRX_PRI_CFI_ACTION_ENCODE( 5220 action->vlan_action.it_outer_pkt_prio)); 5221 soc_mem_field32_set( 5222 unit, mem, entry, SIT_OCFI_ACTIONf, 5223 _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.it_outer_cfi)); 5224 soc_mem_field32_set( 5225 unit, mem, entry, SIT_IPRI_ACTIONf, 5226 _BCM_TRX_PRI_CFI_ACTION_ENCODE( 5227 action->vlan_action.it_inner_pkt_prio)); 5228 soc_mem_field32_set( 5229 unit, mem, entry, SIT_ICFI_ACTIONf, 5230 _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.it_inner_cfi)); 5231 soc_mem_field32_set( 5232 unit, mem, entry, UT_OPRI_ACTIONf, 5233 _BCM_TRX_PRI_CFI_ACTION_ENCODE( 5234 action->vlan_action.ut_outer_pkt_prio)); 5235 soc_mem_field32_set( 5236 unit, mem, entry, UT_OCFI_ACTIONf, 5237 _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.ut_outer_cfi)); 5238 soc_mem_field32_set( 5239 unit, mem, entry, UT_IPRI_ACTIONf, 5240 _BCM_TRX_PRI_CFI_ACTION_ENCODE( 5241 action->vlan_action.ut_inner_pkt_prio)); 5242 soc_mem_field32_set( 5243 unit, mem, entry, UT_ICFI_ACTIONf, 5244 _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.ut_inner_cfi)); 5245 } 5246 5247 return _bcm_trx_ing_vlan_action_profile_entry_no_mod_add(unit, entry, 5248 index); 5249 } 5250 5251 STATIC int 5252 _bcm_td2_fcoe_egr_vlan_translate_entry_assemble( 5253 int unit, 5254 int port_class, 5255 void *vent, 5256 bcm_fcoe_vsan_translate_key_config_t *key) 5257 { 5258 int dvp_id = BCM_GPORT_INVALID; 5259 soc_mem_t mem = EGR_VLAN_XLATEm; 5260 soc_field_t ef = ENTRY_TYPEf; 5261 5262 if (SOC_MEM_IS_VALID(unit, EGR_VLAN_XLATE_1_DOUBLEm)) { 5263 mem = EGR_VLAN_XLATE_1_DOUBLEm; 5264 sal_memset(vent, 0, sizeof(egr_vlan_xlate_1_double_entry_t)); 5265 ef = DATA_TYPEf; 5266 } else { 5267 sal_memset(vent, 0, sizeof(egr_vlan_xlate_entry_t)); 5268 } 5269 5270 VLAN_CHK_ID(unit, key->outer_vlan); 5271 VLAN_CHK_ID(unit, key->inner_vlan); 5272 5273 if (BCM_GPORT_IS_SUBPORT_PORT(port_class)) { 5274 if (soc_feature(unit, soc_feature_subport)) { 5275 dvp_id = BCM_GPORT_SUBPORT_PORT_GET(port_class); 5276 } else { 5277 return BCM_E_PORT; 5278 } 5279 } else if (BCM_GPORT_IS_MIM_PORT(port_class)) { 5280 if (soc_feature(unit, soc_feature_mim)) { 5281 dvp_id = BCM_GPORT_MIM_PORT_ID_GET(port_class); 5282 } else { 5283 return BCM_E_PORT; 5284 } 5285 5286 } else if (BCM_GPORT_IS_WLAN_PORT(port_class)) { 5287 if (soc_feature(unit, soc_feature_wlan)) { 5288 dvp_id = BCM_GPORT_WLAN_PORT_ID_GET(port_class); 5289 } else { 5290 return BCM_E_PORT; 5291 } 5292 } else if (BCM_GPORT_IS_VLAN_PORT(port_class)) { 5293 if (soc_feature(unit, soc_feature_vlan_vp)) { 5294 dvp_id = BCM_GPORT_VLAN_PORT_ID_GET(port_class); 5295 } else { 5296 return BCM_E_PORT; 5297 } 5298 } else if (BCM_GPORT_IS_MPLS_PORT(port_class)) { 5299 if (soc_feature(unit, soc_feature_mpls)) { 5300 dvp_id = BCM_GPORT_MPLS_PORT_ID_GET(port_class); 5301 } else { 5302 return BCM_E_PORT; 5303 } 5304 } 5305 5306 soc_mem_field32_set(unit, mem, vent, OVIDf, key->outer_vlan); 5307 soc_mem_field32_set(unit, mem, vent, IVIDf, key->inner_vlan); 5308 soc_mem_field32_set(unit, mem, vent, VSAN_IDf, key->vsan); 5309 5310 5311 if (BCM_GPORT_INVALID != dvp_id) { 5312 soc_mem_field32_set(unit, mem, vent, ef, 5313 TD2_EVLXLT_HASH_KEY_TYPE_FCOE_XLATE_DVP); 5314 soc_mem_field32_set(unit, mem, vent, DVPf, dvp_id); 5315 } else { 5316 soc_mem_field32_set(unit, mem, vent, PORT_GROUP_IDf, port_class); 5317 soc_mem_field32_set(unit, mem, vent, ef, 5318 TD2_EVLXLT_HASH_KEY_TYPE_FCOE_XLATE); 5319 } 5320 5321 return BCM_E_NONE; 5322 } 5323 5324 uint32 5325 _bcm_td2_fcoe_egr_vft_pri_action_encode(bcm_fcoe_vsan_action_t action) 5326 { 5327 switch (action) { 5328 case bcmFcoeVsanActionNone: 5329 return _BCM_TD2_EGR_VFT_PRI_ACTION_NONE; 5330 case bcmFcoeVsanActionInnerVlan: 5331 return _BCM_TD2_EGR_VFT_PRI_ACTION_USE_INTERNAL_IPRI; 5332 case bcmFcoeVsanActionOuterVlan: 5333 return _BCM_TD2_EGR_VFT_PRI_ACTION_USE_INTERNAL_OPRI; 5334 case bcmFcoeVsanActionReplace: 5335 return _BCM_TD2_EGR_VFT_PRI_ACTION_REPLACE; 5336 case bcmFcoeVsanActionDelete: 5337 case bcmFcoeVsanActionInternal: 5338 default: 5339 return _BCM_TD2_EGR_VFT_PRI_ACTION_NONE; 5340 } 5341 } 5342 5343 uint32 5344 _bcm_td2_fcoe_egr_vft_tag_action_encode(bcm_fcoe_vsan_action_t action) 5345 { 5346 switch (action) { 5347 case bcmFcoeVsanActionNone: 5348 return _BCM_TD2_EGR_VFT_TAG_ACTION_NONE; 5349 case bcmFcoeVsanActionInnerVlan: 5350 return _BCM_TD2_EGR_VFT_TAG_ACTION_USE_INTERNAL_IVID; 5351 case bcmFcoeVsanActionOuterVlan: 5352 return _BCM_TD2_EGR_VFT_TAG_ACTION_USE_INTERNAL_OVID; 5353 case bcmFcoeVsanActionDelete: 5354 return _BCM_TD2_EGR_VFT_TAG_ACTION_DELETE; 5355 case bcmFcoeVsanActionInternal: 5356 return _BCM_TD2_EGR_VFT_TAG_ACTION_USE_INTERNAL_VSAN; 5357 case bcmFcoeVsanActionReplace: 5358 return _BCM_TD2_EGR_VFT_TAG_ACTION_REPLACE; 5359 default: 5360 return _BCM_TD2_EGR_VFT_TAG_ACTION_NONE; 5361 } 5362 } 5363 5364 /* 5365 * add a new entry to egress vlan action profile table 5366 */ 5367 int 5368 _bcm_td2_fcoe_egr_vlan_action_profile_entry_add( 5369 int unit, 5370 bcm_fcoe_vsan_action_set_t *action, 5371 uint32 *index) 5372 { 5373 egr_vlan_tag_action_profile_entry_t entry; 5374 5375 sal_memset(&entry, 0, sizeof(egr_vlan_tag_action_profile_entry_t)); 5376 5377 /* Note : 5378 * Above sal_memset() will set all tag/pri/cfi actions to 5379 * none. We only need to set new FCOE actions. 5380 */ 5381 soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, 5382 DT_VT_VPRI_ACTIONf, 5383 _bcm_td2_fcoe_egr_vft_pri_action_encode( 5384 action->dt_vsan_pri)); 5385 soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, 5386 SOT_VT_VPRI_ACTIONf, 5387 _bcm_td2_fcoe_egr_vft_pri_action_encode( 5388 action->ot_vsan_pri)); 5389 soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, 5390 SIT_VT_VPRI_ACTIONf, 5391 _bcm_td2_fcoe_egr_vft_pri_action_encode( 5392 action->it_vsan_pri)); 5393 soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, 5394 UT_VT_VPRI_ACTIONf, 5395 _bcm_td2_fcoe_egr_vft_pri_action_encode( 5396 action->ut_vsan_pri)); 5397 soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, 5398 DT_VT_VTAG_ACTIONf, 5399 _bcm_td2_fcoe_egr_vft_pri_action_encode( 5400 action->dt_vsan)); 5401 soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, 5402 SOT_VT_VTAG_ACTIONf, 5403 _bcm_td2_fcoe_egr_vft_pri_action_encode( 5404 action->ot_vsan)); 5405 soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, 5406 SIT_VT_VTAG_ACTIONf, 5407 _bcm_td2_fcoe_egr_vft_pri_action_encode( 5408 action->it_vsan)); 5409 soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, 5410 UT_VT_VTAG_ACTIONf, 5411 _bcm_td2_fcoe_egr_vft_pri_action_encode( 5412 action->ut_vsan)); 5413 5414 /* actions for no VFT header */ 5415 if (action->flags & BCM_FCOE_VSAN_ACTION_VFT_NONE) { 5416 soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, 5417 DT_NOVT_VPRI_ACTIONf, 5418 _bcm_td2_fcoe_egr_vft_pri_action_encode( 5419 action->dt_vsan_pri)); 5420 soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, 5421 SOT_NOVT_VPRI_ACTIONf, 5422 _bcm_td2_fcoe_egr_vft_pri_action_encode( 5423 action->ot_vsan_pri)); 5424 soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, 5425 SIT_NOVT_VPRI_ACTIONf, 5426 _bcm_td2_fcoe_egr_vft_pri_action_encode( 5427 action->it_vsan_pri)); 5428 soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, 5429 UT_NOVT_VPRI_ACTIONf, 5430 _bcm_td2_fcoe_egr_vft_pri_action_encode( 5431 action->ut_vsan_pri)); 5432 soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, 5433 DT_NOVT_VTAG_ACTIONf, 5434 _bcm_td2_fcoe_egr_vft_pri_action_encode( 5435 action->dt_vsan)); 5436 soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, 5437 SOT_NOVT_VTAG_ACTIONf, 5438 _bcm_td2_fcoe_egr_vft_pri_action_encode( 5439 action->ot_vsan)); 5440 soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, 5441 SIT_NOVT_VTAG_ACTIONf, 5442 _bcm_td2_fcoe_egr_vft_pri_action_encode( 5443 action->it_vsan)); 5444 soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, 5445 UT_NOVT_VTAG_ACTIONf, 5446 _bcm_td2_fcoe_egr_vft_pri_action_encode( 5447 action->ut_vsan)); 5448 } 5449 5450 soc_mem_field32_set( 5451 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, DT_OTAG_ACTIONf, 5452 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.dt_outer)); 5453 soc_mem_field32_set( 5454 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, DT_POTAG_ACTIONf, 5455 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.dt_outer_prio)); 5456 soc_mem_field32_set( 5457 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, DT_ITAG_ACTIONf, 5458 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.dt_inner)); 5459 soc_mem_field32_set( 5460 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, DT_PITAG_ACTIONf, 5461 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.dt_inner_prio)); 5462 soc_mem_field32_set( 5463 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SOT_OTAG_ACTIONf, 5464 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ot_outer)); 5465 soc_mem_field32_set( 5466 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SOT_POTAG_ACTIONf, 5467 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ot_outer_prio)); 5468 soc_mem_field32_set( 5469 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SOT_ITAG_ACTIONf, 5470 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ot_inner)); 5471 soc_mem_field32_set( 5472 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SIT_OTAG_ACTIONf, 5473 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.it_outer)); 5474 soc_mem_field32_set( 5475 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SIT_ITAG_ACTIONf, 5476 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.it_inner)); 5477 soc_mem_field32_set( 5478 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SIT_PITAG_ACTIONf, 5479 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.it_inner_prio)); 5480 soc_mem_field32_set( 5481 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, UT_OTAG_ACTIONf, 5482 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ut_outer)); 5483 soc_mem_field32_set( 5484 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, UT_ITAG_ACTIONf, 5485 _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ut_inner)); 5486 5487 if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) { 5488 soc_mem_field32_set( 5489 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, DT_OPRI_ACTIONf, 5490 _BCM_TRX_PRI_CFI_ACTION_ENCODE( 5491 action->vlan_action.dt_outer_pkt_prio)); 5492 soc_mem_field32_set( 5493 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, DT_OCFI_ACTIONf, 5494 _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.dt_outer_cfi)); 5495 soc_mem_field32_set( 5496 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, DT_IPRI_ACTIONf, 5497 _BCM_TRX_PRI_CFI_ACTION_ENCODE( 5498 action->vlan_action.dt_inner_pkt_prio)); 5499 soc_mem_field32_set( 5500 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, DT_ICFI_ACTIONf, 5501 _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.dt_inner_cfi)); 5502 soc_mem_field32_set( 5503 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SOT_OPRI_ACTIONf, 5504 _BCM_TRX_PRI_CFI_ACTION_ENCODE( 5505 action->vlan_action.ot_outer_pkt_prio)); 5506 soc_mem_field32_set( 5507 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SOT_OCFI_ACTIONf, 5508 _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.ot_outer_cfi)); 5509 soc_mem_field32_set( 5510 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SOT_IPRI_ACTIONf, 5511 _BCM_TRX_PRI_CFI_ACTION_ENCODE( 5512 action->vlan_action.ot_inner_pkt_prio)); 5513 soc_mem_field32_set( 5514 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SOT_ICFI_ACTIONf, 5515 _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.ot_inner_cfi)); 5516 soc_mem_field32_set( 5517 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SIT_OPRI_ACTIONf, 5518 _BCM_TRX_PRI_CFI_ACTION_ENCODE( 5519 action->vlan_action.it_outer_pkt_prio)); 5520 soc_mem_field32_set( 5521 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SIT_OCFI_ACTIONf, 5522 _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.it_outer_cfi)); 5523 soc_mem_field32_set( 5524 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SIT_IPRI_ACTIONf, 5525 _BCM_TRX_PRI_CFI_ACTION_ENCODE( 5526 action->vlan_action.it_inner_pkt_prio)); 5527 soc_mem_field32_set( 5528 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SIT_ICFI_ACTIONf, 5529 _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.it_inner_cfi)); 5530 soc_mem_field32_set( 5531 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, UT_OPRI_ACTIONf, 5532 _BCM_TRX_PRI_CFI_ACTION_ENCODE( 5533 action->vlan_action.ut_outer_pkt_prio)); 5534 soc_mem_field32_set( 5535 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, UT_OCFI_ACTIONf, 5536 _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.ut_outer_cfi)); 5537 soc_mem_field32_set( 5538 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, UT_IPRI_ACTIONf, 5539 _BCM_TRX_PRI_CFI_ACTION_ENCODE( 5540 action->vlan_action.ut_inner_pkt_prio)); 5541 soc_mem_field32_set( 5542 unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, UT_ICFI_ACTIONf, 5543 _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.ut_inner_cfi)); 5544 } 5545 5546 return _bcm_trx_egr_vlan_action_profile_entry_no_mod_add(unit, &entry, 5547 index); 5548 } 5549 5550 5551 /* Add VSAN translate action */ 5552 int 5553 bcm_td2_fcoe_vsan_translate_action_add ( 5554 int unit, 5555 bcm_fcoe_vsan_translate_key_config_t *key, 5556 bcm_fcoe_vsan_action_set_t *action) 5557 { 5558 int rv = BCM_E_NONE; 5559 int mem = VLAN_XLATEm; 5560 int vf = VALIDf; 5561 int ent_sz = sizeof(vlan_xlate_entry_t); 5562 5563 if (SOC_MEM_IS_VALID(unit, VLAN_XLATE_1_DOUBLEm)) { 5564 mem = VLAN_XLATE_1_DOUBLEm; 5565 vf = BASE_VALID_0f; /* TD3TBD */ 5566 ent_sz = sizeof(vlan_xlate_1_double_entry_t); 5567 } 5568 5569 if (action->flags & BCM_FCOE_VSAN_ACTION_INGRESS) { 5570 5571 uint32 profile_idx; 5572 int search_rv; 5573 int old_profile_idx = 0; 5574 int index; 5575 void *vent, *search_vent; 5576 vlan_xlate_entry_t vx_ent; 5577 vlan_xlate_entry_t search_vx_ent; 5578 5579 #ifdef BCM_TRIDENT3_SUPPORT 5580 vlan_xlate_1_double_entry_t vx1d_ent; 5581 vlan_xlate_1_double_entry_t search_vx1d_ent; 5582 5583 if (SOC_IS_TRIDENT3X(unit)) { 5584 vent = &vx1d_ent; 5585 search_vent= &search_vx1d_ent; 5586 ent_sz = sizeof(vx1d_ent); 5587 } else 5588 #endif 5589 { 5590 vent = &vx_ent; 5591 search_vent= &search_vx_ent; 5592 ent_sz = sizeof(vx_ent); 5593 } 5594 5595 sal_memset(vent, 0, ent_sz); 5596 5597 /* first, search VLAN_XLATE table using provided key */ 5598 BCM_IF_ERROR_RETURN( 5599 _bcm_td2_fcoe_ing_vlan_translate_entry_assemble(unit, vent, 5600 key)); 5601 5602 sal_memcpy(search_vent, vent, ent_sz); 5603 5604 search_rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, 5605 search_vent, vent, 0); 5606 5607 if (search_rv == SOC_E_NONE) { /* already exist */ 5608 old_profile_idx = soc_mem_field32_get(unit, mem, vent, 5609 XLATE__TAG_ACTION_PROFILE_PTRf); 5610 } 5611 5612 soc_mem_field32_set(unit, mem, vent, NEW_IVIDf, 5613 action->vlan_action.new_inner_vlan); 5614 soc_mem_field32_set(unit, mem, vent, NEW_OVIDf, 5615 action->vlan_action.new_outer_vlan); 5616 if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) { 5617 if (action->vlan_action.priority >= BCM_PRIO_MIN && 5618 action->vlan_action.priority <= BCM_PRIO_MAX) { 5619 soc_mem_field32_set(unit, mem, vent, NEW_OPRIf, 5620 action->vlan_action.priority); 5621 } 5622 soc_mem_field32_set(unit, mem, vent, NEW_OCFIf, 5623 action->vlan_action.new_outer_cfi); 5624 soc_mem_field32_set(unit, mem, vent, NEW_IPRIf, 5625 action->vlan_action.new_inner_pkt_prio); 5626 soc_mem_field32_set(unit, mem, vent, NEW_ICFIf, 5627 action->vlan_action.new_inner_cfi); 5628 } 5629 5630 /* update or fill in the vlan xlate entry*/ 5631 BCM_IF_ERROR_RETURN( 5632 _bcm_td2_ing_vlan_action_profile_entry_add(unit, action, 5633 &profile_idx)); 5634 5635 /* update table index */ 5636 soc_mem_field32_set(unit, mem, vent, XLATE__TAG_ACTION_PROFILE_PTRf, 5637 profile_idx); 5638 5639 /* mark action is valid */ 5640 if (SOC_MEM_FIELD_VALID(unit, mem, XLATE__VLAN_ACTION_VALIDf)) { 5641 soc_mem_field32_set(unit, mem, vent, 5642 XLATE__VLAN_ACTION_VALIDf, 1); 5643 } 5644 5645 /* VSAN ID & Pri. VSAN ID is not used for ingress VSAN translation...*/ 5646 soc_mem_field32_set(unit, mem, vent, XLATE__FCOE_VSAN_IDf, 5647 action->new_vsan); 5648 soc_mem_field32_set(unit, mem, vent, XLATE__FCOE_VSAN_PRIf, 5649 action->new_vsan_pri); 5650 5651 /* mark this entry(VLAN_XLATE) is valid */ 5652 if (mem == VLAN_XLATEm) { 5653 soc_mem_field32_set(unit, mem, vent, vf, 1); 5654 } else { 5655 soc_mem_field32_set(unit, mem, vent, vf, 3); 5656 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7); 5657 } 5658 5659 /* NOTE : action->vft (remaining field of VFT header) is not used 5660 * on ingress side. 5661 */ 5662 5663 /* write entry into table */ 5664 if (search_rv == SOC_E_NONE) { 5665 /* overrides existing one */ 5666 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, vent); 5667 } else { /* case search_rv == SOC_E_NOT_FOUND */ 5668 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, vent); 5669 } 5670 5671 if (BCM_FAILURE(rv)) { 5672 /* Delete the allocated vlan translate profile entry */ 5673 profile_idx = soc_mem_field32_get(unit, mem, vent, 5674 XLATE__TAG_ACTION_PROFILE_PTRf); 5675 (void) _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx); 5676 } else { 5677 /* delete the old profile entry */ 5678 if (search_rv == SOC_E_NONE) { 5679 rv = _bcm_trx_vlan_action_profile_entry_delete(unit, 5680 old_profile_idx); 5681 } 5682 } 5683 5684 if (rv != BCM_E_NONE) { 5685 return rv; 5686 } 5687 } 5688 5689 5690 if (action->flags & BCM_FCOE_VSAN_ACTION_EGRESS) { 5691 uint32 profile_idx; 5692 uint32 old_profile_idx = 0; 5693 uint32 vent[SOC_MAX_MEM_FIELD_WORDS]; 5694 uint32 vent_old[SOC_MAX_MEM_FIELD_WORDS]; 5695 uint32 *vent_ptr; 5696 int index; 5697 uint32 vft_profile_index = 0; 5698 uint32 old_vft_profile_index = 0; 5699 uint32 port_class; 5700 int search_rv, vf = VALIDf; 5701 soc_mem_t egr_mem = EGR_VLAN_XLATEm; 5702 5703 if (SOC_MEM_IS_VALID(unit, EGR_VLAN_XLATE_1_DOUBLEm)) { 5704 egr_mem = EGR_VLAN_XLATE_1_DOUBLEm; 5705 vf = BASE_VALID_0f; 5706 } 5707 5708 BCM_IF_ERROR_RETURN( 5709 bcm_esw_port_class_get(unit, key->port, 5710 bcmPortClassVlanTranslateEgress, &port_class)); 5711 5712 vent_ptr = vent; 5713 BCM_IF_ERROR_RETURN( 5714 _bcm_td2_fcoe_egr_vlan_translate_entry_assemble(unit, port_class, 5715 vent_ptr, key)); 5716 5717 soc_mem_lock(unit, egr_mem); 5718 /* check if the entry with same key already exists */ 5719 search_rv = soc_mem_search(unit, egr_mem, MEM_BLOCK_ANY, &index, 5720 vent_ptr, vent_old, 0); 5721 5722 if (search_rv == SOC_E_NONE) { 5723 /* alredy exists, update on the existing one, so the flex 5724 * counter related fields in TR3/Katana can be preserved. 5725 */ 5726 vent_ptr = vent_old; 5727 old_profile_idx = soc_mem_field32_get(unit, egr_mem, vent_ptr, 5728 TAG_ACTION_PROFILE_PTRf); 5729 old_vft_profile_index = 5730 soc_mem_field32_get(unit, egr_mem, vent_ptr, 5731 FCOE_VFT_FIELDS_PROFILE_INDEXf); 5732 } else if (search_rv != SOC_E_NOT_FOUND) { 5733 soc_mem_unlock(unit, egr_mem); 5734 return rv; /* error condition */ 5735 } else { 5736 /* doesn't exist, update the new entry */ 5737 vent_ptr = vent; 5738 } 5739 5740 /* new VSAN & PRI */ 5741 soc_mem_field32_set(unit, egr_mem, vent_ptr, FCOE_VSAN_IDf, 5742 action->new_vsan); 5743 soc_mem_field32_set(unit, egr_mem, vent_ptr, FCOE_VSAN_PRIf, 5744 action->new_vsan_pri); 5745 5746 5747 soc_mem_field32_set(unit, egr_mem, vent_ptr, NEW_IVIDf, 5748 action->vlan_action.new_inner_vlan); 5749 soc_mem_field32_set(unit, egr_mem, vent_ptr, NEW_OVIDf, 5750 action->vlan_action.new_outer_vlan); 5751 if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) { 5752 if (action->vlan_action.priority >= BCM_PRIO_MIN && 5753 action->vlan_action.priority <= BCM_PRIO_MAX) { 5754 soc_mem_field32_set(unit, egr_mem, vent_ptr, NEW_OPRIf, 5755 action->vlan_action.priority); 5756 } 5757 soc_mem_field32_set(unit, egr_mem, vent_ptr, NEW_OCFIf, 5758 action->vlan_action.new_outer_cfi); 5759 soc_mem_field32_set(unit, egr_mem, vent_ptr, NEW_IPRIf, 5760 action->vlan_action.new_inner_pkt_prio); 5761 soc_mem_field32_set(unit, egr_mem, vent_ptr, NEW_ICFIf, 5762 action->vlan_action.new_inner_cfi); 5763 } 5764 /* action profile index */ 5765 rv = _bcm_td2_fcoe_egr_vlan_action_profile_entry_add(unit, action, 5766 &profile_idx); 5767 if (rv != SOC_E_NONE) { 5768 soc_mem_unlock(unit, egr_mem); 5769 return rv; 5770 } 5771 soc_mem_field32_set(unit, egr_mem, vent_ptr, TAG_ACTION_PROFILE_PTRf, 5772 profile_idx); 5773 5774 /* new FCOE_VFT_FIELDS_PROFILE_INDEX, creaate one if not exist */ 5775 rv = _bcm_td2_add_vft_fields_profile(unit, &action->vft, 5776 &vft_profile_index); 5777 if (rv != SOC_E_NONE) { 5778 soc_mem_unlock(unit, egr_mem); 5779 return rv; 5780 } 5781 5782 rv = _bcm_td2_inc_vft_profile_refcnt(unit, vft_profile_index); 5783 if (rv != SOC_E_NONE) { 5784 soc_mem_unlock(unit, egr_mem); 5785 return rv; 5786 } 5787 5788 soc_mem_field32_set(unit, egr_mem, vent_ptr, NEW_OTAG_VPTAG_SELf, 0); 5789 if (vf == VALIDf) { 5790 soc_mem_field32_set(unit, egr_mem, vent_ptr, vf, 1); 5791 } else { 5792 soc_mem_field32_set(unit, egr_mem, vent_ptr, vf, 3); 5793 soc_mem_field32_set(unit, egr_mem, vent_ptr, BASE_VALID_1f, 7); 5794 } 5795 5796 if (search_rv == SOC_E_NONE) { 5797 /* write back the existing one */ 5798 rv = soc_mem_write(unit, egr_mem, 5799 MEM_BLOCK_ALL, index, vent_ptr); 5800 if (rv == SOC_E_NONE) { 5801 /* write was succeful */ 5802 rv = _bcm_trx_egr_vlan_action_profile_entry_delete(unit, 5803 old_profile_idx); 5804 if (old_vft_profile_index != vft_profile_index) { 5805 rv += _bcm_td2_dec_vft_profile_refcnt(unit, 5806 old_vft_profile_index); 5807 } 5808 } 5809 } else { 5810 /* insert new one */ 5811 rv = soc_mem_insert(unit, egr_mem, MEM_BLOCK_ALL, vent_ptr); 5812 } 5813 5814 soc_mem_unlock(unit, egr_mem); 5815 5816 return rv; 5817 } 5818 5819 return BCM_E_NONE; 5820 } 5821 5822 /* Delete VSAN translate action */ 5823 int 5824 bcm_td2_fcoe_vsan_translate_action_delete ( 5825 int unit, 5826 bcm_fcoe_vsan_translate_key_config_t *key) 5827 { 5828 int rv = BCM_E_NONE; 5829 int search_rv; 5830 int index; 5831 uint32 port_class; 5832 vlan_xlate_entry_t ing_vent; 5833 uint32 ing_profile_idx; 5834 uint32 egr_profile_idx; 5835 uint32 egr_vft_profile_idx; 5836 soc_mem_t mem = VLAN_XLATEm; 5837 soc_mem_t egr_mem = EGR_VLAN_XLATEm; 5838 int ent_sz, vf = VALIDf; 5839 vlan_xlate_1_double_entry_t ing_1d_vent; 5840 void *in_vent; 5841 uint32 egr_vent[SOC_MAX_MEM_FIELD_WORDS]; 5842 5843 in_vent = &ing_vent; 5844 ent_sz = sizeof(ing_vent); 5845 5846 if (SOC_MEM_IS_VALID(unit, VLAN_XLATE_1_DOUBLEm)) { 5847 mem = VLAN_XLATE_1_DOUBLEm; 5848 egr_mem = EGR_VLAN_XLATE_1_DOUBLEm; 5849 vf = BASE_VALID_0f; 5850 in_vent = &ing_1d_vent; 5851 ent_sz = sizeof(ing_1d_vent); 5852 } 5853 5854 /* ingress */ 5855 sal_memset(in_vent, 0, ent_sz); 5856 BCM_IF_ERROR_RETURN( 5857 _bcm_td2_fcoe_ing_vlan_translate_entry_assemble(unit, in_vent, 5858 key)); 5859 5860 search_rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, 5861 in_vent, in_vent, 0); 5862 5863 if (search_rv == SOC_E_NONE) { /* exist */ 5864 ing_profile_idx = soc_mem_field32_get(unit, mem, in_vent, 5865 XLATE__TAG_ACTION_PROFILE_PTRf); 5866 /* mark entry as invalid */ 5867 if (mem == VLAN_XLATEm) { 5868 soc_mem_field32_set(unit, mem, in_vent, vf, 0); 5869 } else { 5870 soc_mem_field32_set(unit, mem, in_vent, vf, 0); 5871 soc_mem_field32_set(unit, mem, in_vent, BASE_VALID_1f, 0); 5872 } 5873 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, in_vent); 5874 5875 if (rv == BCM_E_NONE) { 5876 /* Delete the old vlan action profile entry */ 5877 rv = _bcm_trx_vlan_action_profile_entry_delete(unit, 5878 ing_profile_idx); 5879 } 5880 } else if (search_rv == BCM_E_NOT_FOUND) { 5881 rv = BCM_E_NONE; /* if INGRESS flag was not used when adding action, 5882 * this is an expected return 5883 */ 5884 } 5885 5886 if (rv != BCM_E_NONE) { 5887 return rv; 5888 } 5889 5890 /* egress */ 5891 5892 BCM_IF_ERROR_RETURN( 5893 bcm_esw_port_class_get(unit, key->port, bcmPortClassVlanTranslateEgress, 5894 &port_class)); 5895 5896 sal_memset(egr_vent, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 5897 BCM_IF_ERROR_RETURN( 5898 _bcm_td2_fcoe_egr_vlan_translate_entry_assemble(unit, port_class, 5899 egr_vent, key)); 5900 5901 soc_mem_lock(unit, egr_mem); 5902 5903 /* check if the entry with same key already exists */ 5904 rv = soc_mem_search(unit, egr_mem, MEM_BLOCK_ANY, &index, 5905 egr_vent, egr_vent, 0); 5906 5907 if (rv == SOC_E_NONE) { 5908 /* exists */ 5909 egr_profile_idx = soc_mem_field32_get(unit, egr_mem, egr_vent, 5910 TAG_ACTION_PROFILE_PTRf); 5911 egr_vft_profile_idx = soc_mem_field32_get(unit, egr_mem, egr_vent, 5912 FCOE_VFT_FIELDS_PROFILE_INDEXf); 5913 5914 /* mark entry as invalid */ 5915 if (egr_mem == EGR_VLAN_XLATEm) { 5916 soc_mem_field32_set(unit, egr_mem, egr_vent, vf, 0); 5917 } else { 5918 soc_mem_field32_set(unit, egr_mem, egr_vent, vf, 0); 5919 soc_mem_field32_set(unit, egr_mem, egr_vent, BASE_VALID_1f, 0); 5920 } 5921 rv = soc_mem_write(unit, egr_mem, MEM_BLOCK_ALL, index, egr_vent); 5922 5923 if (rv == BCM_E_NONE) { 5924 5925 /* Delete vlan action profile entry */ 5926 rv = _bcm_trx_egr_vlan_action_profile_entry_delete(unit, 5927 egr_profile_idx); 5928 /* delete vft profile entry */ 5929 rv += _bcm_td2_dec_vft_profile_refcnt(unit, egr_vft_profile_idx); 5930 } 5931 } else if (rv == BCM_E_NOT_FOUND) { 5932 rv = BCM_E_NONE; /* if EGRESS flag was not used when adding action, 5933 * this is an expected return 5934 */ 5935 } 5936 soc_mem_unlock(unit, egr_mem); 5937 return rv; 5938 } 5939 5940 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 5941 void 5942 _bcm_td2_fcoe_sw_dump(int unit) 5943 { 5944 uint32 vsan_id; 5945 int valid = 0; 5946 int count = 0; 5947 5948 LOG_CLI((BSL_META_U(unit, 5949 "\nSW Information FCOE - Unit %d\n"), unit)); 5950 5951 LOG_CLI((BSL_META_U(unit, 5952 "VSAN ID Creation State : \n"))); 5953 for (vsan_id = 0; vsan_id <= FCOE_MAX_VSAN_ID; vsan_id++) { 5954 valid = _bcm_td2_vsan_id_creation_state_get(unit, vsan_id); 5955 if (valid) { 5956 count++; 5957 LOG_CLI((BSL_META_U(unit, "%4d "), vsan_id)); 5958 if (count == 16) { 5959 count = 0; 5960 LOG_CLI((BSL_META_U(unit, "\n"))); 5961 } 5962 } 5963 } 5964 LOG_CLI((BSL_META_U(unit, "\n"))); 5965 } 5966 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */ 5967 5968 /* traverse zone entries and call user callback function */ 5969 int 5970 bcm_td2_fcoe_zone_traverse(int unit, 5971 uint32 flags, 5972 bcm_fcoe_zone_traverse_cb trav_fn, 5973 void *user_data) 5974 { 5975 int ix; 5976 int key_type; 5977 int chnk_end; 5978 int chunksize; 5979 int chunk; 5980 int chunk_max; 5981 int mem_idx_max; 5982 L2_ENTRY_T *l2e; 5983 L2_ENTRY_T *l2ep; 5984 soc_mem_t mem; 5985 uint32 action; 5986 uint32 copy_to_cpu; 5987 int rv = BCM_E_NONE; 5988 bcm_fcoe_zone_entry_t zone; 5989 5990 /* note : flags parameter is not used at the moment */ 5991 5992 chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS, 5993 L2_MEM_CHUNKS_DEFAULT); 5994 5995 mem = L2Xm; 5996 5997 l2e = soc_cm_salloc(unit, chunksize * sizeof(*l2e), "l2entrydel_chunk"); 5998 5999 if (l2e == NULL) { 6000 return BCM_E_MEMORY; 6001 } 6002 6003 mem_idx_max = soc_mem_index_max(unit, mem); 6004 6005 soc_mem_lock(unit, mem); 6006 6007 for (chunk = soc_mem_index_min(unit, mem); chunk <= mem_idx_max; 6008 chunk += chunksize) { 6009 6010 chunk_max = chunk + chunksize - 1; 6011 6012 if (chunk_max > mem_idx_max) { 6013 chunk_max = mem_idx_max; 6014 } 6015 6016 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 6017 chunk, chunk_max, l2e); 6018 if (rv < 0) { 6019 break; 6020 } 6021 6022 chnk_end = (chunk_max - chunk); 6023 6024 for (ix = 0; ix <= chnk_end; ix++) { 6025 l2ep = soc_mem_table_idx_to_pointer(unit, mem, 6026 L2_ENTRY_T *, l2e, ix); 6027 #ifdef BCM_TRIDENT3_SUPPORT 6028 if (SOC_IS_TRIDENT3X(unit)) { 6029 if (!soc_mem_field32_get(unit, mem, l2ep, BASE_VALIDf)) { 6030 continue; 6031 } 6032 } else 6033 #endif 6034 { 6035 if (!soc_mem_field32_get(unit, mem, l2ep, VALIDf)) { 6036 continue; 6037 } 6038 } 6039 6040 /* Match the Key Type to FCOE */ 6041 key_type = soc_mem_field32_get(unit, mem, l2ep, KEY_TYPEf); 6042 6043 if (key_type != TD2_L2_HASH_KEY_TYPE_FCOE_ZONE) { 6044 continue; 6045 } 6046 6047 /* found zone entry */ 6048 sal_memset(&zone, 0, sizeof(bcm_fcoe_zone_entry_t)); 6049 zone.vsan_id = soc_mem_field32_get(unit, mem, l2ep, 6050 FCOE_ZONE__VSAN_IDf); 6051 zone.d_id = soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__D_IDf); 6052 zone.s_id = soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__S_IDf); 6053 zone.class_id = (int)soc_mem_field32_get(unit, mem, l2ep, 6054 FCOE_ZONE__CLASS_IDf); 6055 action = soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__ACTIONf); 6056 #ifdef BCM_TRIDENT3_SUPPORT 6057 if (SOC_IS_TRIDENT3X(unit)) { 6058 copy_to_cpu = soc_mem_field32_get(unit, mem, l2ep, 6059 FCOE_ZONE__CPUf); 6060 } else 6061 #endif /* BCM_TRIDENT3_SUPPORT */ 6062 { 6063 copy_to_cpu = soc_mem_field32_get(unit, mem, l2ep, 6064 FCOE_ZONE__COPY_TO_CPUf); 6065 } 6066 6067 if (action == 1) { 6068 zone.action = bcmFcoeZoneActionAllow; 6069 } else { /* action is 0 (deny) */ 6070 zone.action = bcmFcoeZoneActionDeny; 6071 if (copy_to_cpu == 1) { 6072 zone.action = bcmFcoeZoneActionCopyToCpu; 6073 } 6074 } 6075 6076 /* call user callback function with a zone entry */ 6077 rv = (trav_fn)(unit, &zone, user_data); 6078 6079 if (rv < 0) { 6080 break; 6081 } 6082 } 6083 6084 if (rv < 0) { 6085 break; 6086 } 6087 } 6088 6089 soc_mem_unlock(unit, mem); 6090 soc_cm_sfree(unit, l2e); 6091 6092 return rv; 6093 } 6094 6095 /* traverse vsan entries and call user callback function */ 6096 int 6097 bcm_td2_fcoe_vsan_traverse(int unit, 6098 uint32 flags, 6099 bcm_fcoe_vsan_traverse_cb trav_fn, 6100 void *user_data) 6101 { 6102 ing_vsan_entry_t vsan_entry; 6103 soc_mem_t mem = ING_VSANm; 6104 int rv = BCM_E_NONE; 6105 int index; 6106 bcm_fcoe_vsan_t vsan; 6107 int flag = 0; 6108 int fcmap_index = 0; 6109 bcm_fcoe_fcmap_t fcmap; 6110 6111 /* note : flags parameter is not used at the moment */ 6112 6113 soc_mem_lock(unit, mem); 6114 for (index = 0; index <= FCOE_MAX_VSAN_ID; index++) { 6115 6116 /* check if vsan id is existing */ 6117 if (shr_idxres_list_elem_state(vsan_id_list[unit], index) != 6118 BCM_E_EXISTS) { 6119 continue; 6120 } 6121 6122 /* read table entry */ 6123 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &vsan_entry); 6124 if (rv != BCM_E_NONE) { 6125 break; 6126 } 6127 6128 sal_memset(&vsan, 0, sizeof(bcm_fcoe_vsan_t)); 6129 6130 /* get FC MAP */ 6131 fcmap_index = soc_mem_field32_get(unit,mem, (uint32 *)&vsan_entry, 6132 FCOE_FC_MAP_INDEXf); 6133 6134 rv = _bcm_fcoe_fc_profile_map_value_get (unit, fcmap_index, &fcmap); 6135 if (rv != BCM_E_NONE) { 6136 break; 6137 } 6138 vsan.fcmap = fcmap; 6139 6140 flag = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry, 6141 ZONE_CHECK_NORMALIZEDf); 6142 if (flag) { 6143 vsan.config_flags |= BCM_FCOE_VSAN_CONFIG_NORMALIZED_ZONE_CHECK; 6144 } 6145 6146 flag = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry, 6147 FCOE_ROUTE_ENABLEf); 6148 if (flag) { 6149 vsan.config_flags |= BCM_FCOE_VSAN_CONFIG_FCOE_ROUTE_ENABLE; 6150 } 6151 6152 vsan.l3_intf_id = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry, 6153 L3_IIFf); 6154 6155 /* call user callback function with a vsan entry. index is vsan_id */ 6156 rv = (trav_fn)(unit, index, &vsan, user_data); 6157 6158 if (rv < 0) { 6159 break; 6160 } 6161 } 6162 6163 soc_mem_unlock(unit, mem); 6164 return rv; 6165 } 6166 6167 #ifdef INCLUDE_L3 6168 #ifdef BCM_TRIDENT3_SUPPORT 6169 STATIC int 6170 _bcm_td3_fcoe_correct_key_type_for_flags(int unit, uint32 flags, 6171 soc_mem_t mem, 6172 int key_type, 6173 int data_type) 6174 { 6175 int rv = BCM_E_NONE; 6176 6177 if (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) { 6178 if ((key_type == (int)TD3_L3_HASH_KEY_TYPE_FCOE_HOST) || 6179 (data_type == (int)TD3_L3_HASH_DATA_TYPE_FCOE_HOST_EXT)) { 6180 if ((flags & BCM_FCOE_HOST_ROUTE) == 0) { 6181 rv = BCM_E_NOT_FOUND; 6182 } 6183 } else if ((key_type == (int)TD3_L3_HASH_KEY_TYPE_FCOE_DOMAIN) || 6184 (data_type == (int)TD3_L3_HASH_DATA_TYPE_FCOE_DOMAIN_EXT)) { 6185 if ((flags & BCM_FCOE_DOMAIN_ROUTE) == 0) { 6186 rv = BCM_E_NOT_FOUND; 6187 } 6188 } else if ((key_type == (int)TD3_L3_HASH_KEY_TYPE_FCOE_SOURCE_MAP) || 6189 (data_type == (int)TD3_L3_HASH_DATA_TYPE_FCOE_SOURCE_MAP_EXT)) { 6190 if ((flags & BCM_FCOE_SOURCE_ROUTE) == 0) { 6191 rv = BCM_E_NOT_FOUND; 6192 } 6193 } else { 6194 rv = BCM_E_NOT_FOUND; 6195 } 6196 } else if (mem == _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit)) { 6197 if ((key_type == (int)TD3_L3_HASH_KEY_TYPE_FCOE_HOST) || 6198 (data_type == (int)TD3_L3_HASH_DATA_TYPE_FCOE_HOST)) { 6199 if ((flags & BCM_FCOE_HOST_ROUTE) == 0) { 6200 rv = BCM_E_NOT_FOUND; 6201 } 6202 } else if ((key_type == (int)TD3_L3_HASH_KEY_TYPE_FCOE_DOMAIN) || 6203 (data_type == (int)TD3_L3_HASH_DATA_TYPE_FCOE_DOMAIN)) { 6204 if ((flags & BCM_FCOE_DOMAIN_ROUTE) == 0) { 6205 rv = BCM_E_NOT_FOUND; 6206 } 6207 } else if ((key_type == (int)TD3_L3_HASH_KEY_TYPE_FCOE_SOURCE_MAP) || 6208 (data_type == (int)TD3_L3_HASH_DATA_TYPE_FCOE_SOURCE_MAP)) { 6209 if ((flags & BCM_FCOE_SOURCE_ROUTE) == 0) { 6210 rv = BCM_E_NOT_FOUND; 6211 } 6212 } else { 6213 rv = BCM_E_NOT_FOUND; 6214 } 6215 } else { 6216 rv = BCM_E_NOT_FOUND; 6217 } 6218 6219 return rv; 6220 } 6221 #endif /* BCM_TRIDENT3_SUPPORT */ 6222 STATIC int 6223 _bcm_td2_fcoe_correct_key_type_for_flags(int unit, uint32 flags, 6224 soc_mem_t mem, 6225 int key_type) 6226 { 6227 int rv = BCM_E_NONE; 6228 6229 if (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) { 6230 if (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT) { 6231 if ((flags & BCM_FCOE_HOST_ROUTE) == 0) { 6232 rv = BCM_E_NOT_FOUND; 6233 } 6234 } else if (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT) { 6235 if ((flags & BCM_FCOE_DOMAIN_ROUTE) == 0) { 6236 rv = BCM_E_NOT_FOUND; 6237 } 6238 } else if (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT) { 6239 if ((flags & BCM_FCOE_SOURCE_ROUTE) == 0) { 6240 rv = BCM_E_NOT_FOUND; 6241 } 6242 } else { 6243 rv = BCM_E_NOT_FOUND; 6244 } 6245 } else if (mem == _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit)) { 6246 if (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_HOST) { 6247 if ((flags & BCM_FCOE_HOST_ROUTE) == 0) { 6248 rv = BCM_E_NOT_FOUND; 6249 } 6250 } else if (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN) { 6251 if ((flags & BCM_FCOE_DOMAIN_ROUTE) == 0) { 6252 rv = BCM_E_NOT_FOUND; 6253 } 6254 } else if (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP) { 6255 if ((flags & BCM_FCOE_SOURCE_ROUTE) == 0) { 6256 rv = BCM_E_NOT_FOUND; 6257 } 6258 } else { 6259 rv = BCM_E_NOT_FOUND; 6260 } 6261 } else { 6262 rv = BCM_E_NOT_FOUND; 6263 } 6264 6265 return rv; 6266 } 6267 6268 STATIC int 6269 _bcm_fcoe_route_tbl_traverse_normal(int unit, 6270 uint32 flags, 6271 bcm_fcoe_route_traverse_cb trav_fn, 6272 void *user_data) 6273 { 6274 l3_entry_ipv4_multicast_entry_t l3_ext_entry; 6275 6276 soc_mem_t mem = _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit); 6277 uint32 *buf = (uint32 *)&l3_ext_entry; 6278 int idx; 6279 int idx_max; 6280 int key_type_0; 6281 int rv = BCM_E_NONE; 6282 bcm_fcoe_route_t route; 6283 6284 idx_max = soc_mem_index_max(unit, mem); 6285 6286 soc_mem_lock(unit, mem); 6287 6288 for (idx = 0; idx < idx_max; idx++) { 6289 sal_memset(buf, 0, sizeof l3_ext_entry); 6290 6291 rv = BCM_XGS3_MEM_READ(unit, mem, idx, buf); 6292 if (BCM_FAILURE(rv)) { 6293 break; 6294 } 6295 6296 #ifdef BCM_TRIDENT3_SUPPORT 6297 if (SOC_IS_TRIDENT3X(unit)) { 6298 int key_type_1; 6299 if (!soc_mem_field32_get(unit, mem, buf, BASE_VALIDf)) { 6300 continue; 6301 } 6302 key_type_0 = soc_mem_field32_get(unit, mem, buf, 6303 KEY_TYPEf); 6304 key_type_1 = soc_mem_field32_get(unit, mem, buf, 6305 DATA_TYPEf); 6306 6307 if (!_bcm_td3_key_type_is_fcoe(unit, mem, key_type_0, key_type_1)) { 6308 continue; 6309 } 6310 6311 if (_bcm_td3_fcoe_correct_key_type_for_flags(unit, flags, mem, key_type_0, key_type_1) != 6312 BCM_E_NONE) { 6313 continue; 6314 } 6315 } else 6316 #endif 6317 { 6318 if (!soc_mem_field32_get(unit, mem, buf, VALIDf)) { 6319 continue; 6320 } 6321 6322 key_type_0 = soc_mem_field32_get(unit, mem, buf, 6323 KEY_TYPEf); 6324 6325 if (!_bcm_td2_key_type_is_fcoe(unit, mem, key_type_0)) { 6326 continue; 6327 } 6328 6329 if (_bcm_td2_fcoe_correct_key_type_for_flags(unit, flags, mem, key_type_0) != 6330 BCM_E_NONE) { 6331 continue; 6332 } 6333 } 6334 6335 /* build route entry */ 6336 sal_memset(&route, 0, sizeof(bcm_fcoe_route_t)); 6337 6338 _bcm_fcoe_read_mem_into_route(unit, mem, buf, &route); 6339 6340 /* call user callback function */ 6341 rv = (trav_fn)(unit, &route, user_data); 6342 if (rv != BCM_E_NONE) { 6343 break; 6344 } 6345 } 6346 6347 soc_mem_unlock(unit, mem); 6348 6349 return rv; 6350 } 6351 6352 6353 STATIC int 6354 _bcm_fcoe_route_tbl_traverse_ext(int unit, 6355 uint32 flags, 6356 bcm_fcoe_route_traverse_cb trav_fn, 6357 void *user_data) 6358 { 6359 l3_entry_ipv4_multicast_entry_t l3_ext_entry; 6360 6361 soc_mem_t mem = _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit); 6362 uint32 *buf = (uint32 *)&l3_ext_entry; 6363 int idx; 6364 int idx_max; 6365 int key_type_0, key_type_0f = KEY_TYPE_0f; 6366 int key_type_1, key_type_1f = KEY_TYPE_1f; 6367 int valid_0f = VALID_0f; 6368 int valid_1f = VALID_1f; 6369 int rv = BCM_E_NONE; 6370 bcm_fcoe_route_t route; 6371 6372 idx_max = soc_mem_index_max(unit, mem); 6373 6374 soc_mem_lock(unit, mem); 6375 6376 #ifdef BCM_TRIDENT3_SUPPORT 6377 if (SOC_IS_TRIDENT3X(unit)) { 6378 valid_0f = BASE_VALID_0f; 6379 valid_1f = BASE_VALID_1f; 6380 key_type_0f = KEY_TYPEf; 6381 key_type_1f = DATA_TYPEf; 6382 } 6383 #endif 6384 for (idx = 0; idx < idx_max; idx++) { 6385 sal_memset(buf, 0, sizeof l3_ext_entry); 6386 6387 rv = BCM_XGS3_MEM_READ(unit, mem, idx, buf); 6388 if (BCM_FAILURE(rv)) { 6389 break; 6390 } 6391 6392 if (!soc_mem_field32_get(unit, mem, buf, valid_0f) || 6393 !soc_mem_field32_get(unit, mem, buf, valid_1f)) { 6394 continue; 6395 } 6396 6397 key_type_0 = soc_mem_field32_get(unit, mem, buf, key_type_0f); 6398 key_type_1 = soc_mem_field32_get(unit, mem, buf, key_type_1f); 6399 6400 #ifdef BCM_TRIDENT3_SUPPORT 6401 if (SOC_IS_TRIDENT3X(unit)) { 6402 if (!_bcm_td3_key_type_is_fcoe(unit, mem, key_type_0, key_type_1)) { 6403 continue; 6404 } 6405 if (_bcm_td3_fcoe_correct_key_type_for_flags(unit, flags, mem, key_type_0, key_type_1) != 6406 BCM_E_NONE) { 6407 continue; 6408 } 6409 } else 6410 #endif 6411 { 6412 if (!_bcm_td2_key_type_is_fcoe(unit, mem, key_type_0) || 6413 (key_type_0 != key_type_1)) { 6414 continue; 6415 } 6416 6417 if (_bcm_td2_fcoe_correct_key_type_for_flags(unit, flags, mem, key_type_0) != 6418 BCM_E_NONE) { 6419 continue; 6420 } 6421 } 6422 6423 /* build route entry */ 6424 sal_memset(&route, 0, sizeof(bcm_fcoe_route_t)); 6425 6426 _bcm_fcoe_read_mem_into_route(unit, mem, buf, &route); 6427 6428 /* call user callback function */ 6429 rv = (trav_fn)(unit, &route, user_data); 6430 if (rv != BCM_E_NONE) { 6431 break; 6432 } 6433 } 6434 6435 soc_mem_unlock(unit, mem); 6436 6437 return rv; 6438 } 6439 6440 STATIC int 6441 _bcm_fcoe_route_tbl_traverse_prefix(int unit, 6442 bcm_fcoe_route_traverse_cb trav_fn, 6443 void *user_data) 6444 { 6445 uint32 entry[SOC_MAX_MEM_WORDS]; 6446 uint32 *buf = entry; 6447 soc_mem_t mem = L3_DEFIPm; 6448 int idx; 6449 int idx_max; 6450 int rv = BCM_E_NONE; 6451 bcm_fcoe_route_t route; 6452 int nh_idx = 0; 6453 _bcm_defip_cfg_t lpm_cfg; 6454 6455 idx_max = soc_mem_index_max(unit, mem); 6456 6457 soc_mem_lock(unit, mem); 6458 6459 for (idx = 0; idx < idx_max; idx++) { 6460 sal_memset(buf, 0, sizeof entry); 6461 6462 rv = BCM_XGS3_MEM_READ(unit, mem, idx, buf); 6463 if (BCM_FAILURE(rv)) { 6464 break; 6465 } 6466 6467 /* first entry */ 6468 if (soc_mem_field32_get(unit, mem, buf, VALID0f) && 6469 soc_mem_field32_get(unit, mem, buf, ENTRY_TYPE0f)) { 6470 6471 /* build route entry */ 6472 sal_memset(&route, 0, sizeof(bcm_fcoe_route_t)); 6473 sal_memset(&lpm_cfg , 0, sizeof(_bcm_defip_cfg_t)); 6474 6475 BCM_IF_ERROR_RETURN( 6476 _bcm_fb_lpm_ent_parse(unit, &lpm_cfg, &nh_idx, 6477 buf, NULL)); 6478 6479 rv = _bcm_fcoe_defip_to_route(unit, &lpm_cfg, &route); 6480 6481 if (rv != BCM_E_NONE) { 6482 break; 6483 } 6484 6485 if (BCM_XGS3_L3_EGRESS_MODE_ISSET(unit)) { 6486 if (route.flags & BCM_FCOE_MULTIPATH) { 6487 route.intf = nh_idx + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 6488 } else { 6489 route.intf = nh_idx + BCM_XGS3_EGRESS_IDX_MIN(unit); 6490 } 6491 } 6492 6493 /* call user callback function */ 6494 rv = (trav_fn)(unit, &route, user_data); 6495 6496 if (rv != BCM_E_NONE) { 6497 break; 6498 } 6499 } 6500 6501 /* second entry */ 6502 if (soc_mem_field32_get(unit, mem, buf, VALID1f) && 6503 soc_mem_field32_get(unit, mem, buf, ENTRY_TYPE1f)) { 6504 6505 /* build route entry */ 6506 sal_memset(&route, 0, sizeof(bcm_fcoe_route_t)); 6507 sal_memset(&lpm_cfg , 0, sizeof(_bcm_defip_cfg_t)); 6508 6509 rv = soc_fb_lpm_ip4entry1_to_0(unit, buf, buf, 0); 6510 6511 if (rv != BCM_E_NONE) { 6512 break; 6513 } 6514 6515 BCM_IF_ERROR_RETURN( 6516 _bcm_fb_lpm_ent_parse(unit, &lpm_cfg, &nh_idx, 6517 buf, NULL)); 6518 6519 rv = _bcm_fcoe_defip_to_route(unit, &lpm_cfg, &route); 6520 6521 if (rv != BCM_E_NONE) { 6522 break; 6523 } 6524 6525 if (BCM_XGS3_L3_EGRESS_MODE_ISSET(unit)) { 6526 if (route.flags & BCM_FCOE_MULTIPATH) { 6527 route.intf = nh_idx + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 6528 } else { 6529 route.intf = nh_idx + BCM_XGS3_EGRESS_IDX_MIN(unit); 6530 } 6531 } 6532 6533 /* call user callback function */ 6534 rv = (trav_fn)(unit, &route, user_data); 6535 6536 if (rv != BCM_E_NONE) { 6537 break; 6538 } 6539 } 6540 } 6541 6542 soc_mem_unlock(unit, mem); 6543 6544 return rv; 6545 } 6546 6547 #endif /* INCLUDE_L3 */ 6548 6549 /* traverse routing entries and call user callback function */ 6550 int 6551 bcm_td2_fcoe_route_traverse(int unit, 6552 uint32 flags, 6553 bcm_fcoe_route_traverse_cb trav_fn, 6554 void *user_data) 6555 { 6556 #ifdef INCLUDE_L3 6557 int rv = BCM_E_NONE; 6558 6559 if (BCM_XGS3_L3_EGRESS_MODE_ISSET(unit)) { 6560 /* search L3_ENTRY_IPV4_UNICAST table */ 6561 rv = _bcm_fcoe_route_tbl_traverse_normal(unit, flags, trav_fn, 6562 user_data); 6563 if (rv == BCM_E_NONE) { 6564 /* search L3_ENTRY_IPV4_MULTICAST table */ 6565 rv = _bcm_fcoe_route_tbl_traverse_ext(unit, flags, trav_fn, 6566 user_data); 6567 } 6568 } else { 6569 /* search L3_ENTRY_IPV4_MULTICAST table */ 6570 rv = _bcm_fcoe_route_tbl_traverse_ext(unit, flags, trav_fn, user_data); 6571 } 6572 6573 if (rv != BCM_E_NONE) { 6574 return rv; 6575 } 6576 6577 if (flags & BCM_FCOE_DOMAIN_ROUTE) { 6578 /* L3_DEFIP table for prefix route */ 6579 rv = _bcm_fcoe_route_tbl_traverse_prefix(unit, trav_fn, user_data); 6580 } 6581 6582 return rv; 6583 #else 6584 return BCM_E_UNAVAIL; 6585 #endif 6586 } 6587 6588 6589 #endif /* BCM_TRIDENT2_SUPORT */