switch.c (125602B)
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 * Module : Switch 8 * 9 * Purpose: 10 * This file has the flexible hashing apis and its accessory functions to configure 11 * field match data and relative hash offsets for bucket 2 and 3. 12 * 13 * The below shows the configurations of flexible hashing mechanism in UDF and Flex 14 * tables. Data qualifier apis are used to configure the UDF table with relative 15 * packet offsets from L4 header. UDF chunk4 - 7 is being used to configure hash 16 * bucket 2 and 3. Flexible hashing offset mapping is done with functions 17 * implemented in this file. 18 * 19 * 20 * 21 * FLEXIBLE HASHING PACKET PARSER (with UDF) 22 * 23 * Packet L4 24 * +--------+--------+------------+---------+ 25 * | | | L4 header | Payload | 26 * +--------+--------+-+-+--------+---------+ 27 * offset 2 2 .... 28 * || -----+ 29 * || | 30 * +----Chunk4----+ PKT.field1(16b)| 31 * PKT.offset1 --> | +--Chunk5-----+ | 32 * | | +-Chunk6------+ ==> PKT.field2(16b)| 33 * + PKT.offset2 --> | | | +-Chunk7------+ -+ 34 * +-| | | | PKT.field3(16b)| 35 * PKT.offset3 ----> +-| |UDF_TCAM/OFF | | 36 * +-| (4 x 16bit)| PKT.field4(16b)| 37 * PKT.offset4 ------> +-------------+ | 38 * -----+ 39 * 40 * 41 * FLEXIBLE HASHING OFFSET MAPPING 42 * * 43 * (64bx8) [UDF_CONDITIONAL_CHECK_TABLE_CAMm] 44 * -----+ +--0-------------+ 45 * PKT.field1(16b)| +-|+-2--------------+ 46 * | +-|+-3--------------+ 47 * PKT.field2(16b)| 64bit +| +-4--------------+ ==> offset 2 48 * -+---- Key +-| +-5--------------+ 49 * PKT.field3(16b)| +-| +-6--------------+ 50 * | +-| +-7--------------+ 51 * PKT.field4(16b)| +-| | 52 * | +----------------+ 53 * -----+ [UDF_CONDITIONAL_CHECK_TABLE_RAMm] 54 */ 55 56 #include <soc/defs.h> 57 58 #if defined(BCM_TRIDENT2_SUPPORT) 59 #include <soc/mem.h> 60 #include <soc/mcm/memregs.h> 61 #include <soc/debug.h> 62 #include <soc/field.h> 63 #include <bcm/switch.h> 64 65 #include <bcm_int/esw/xgs4.h> 66 #include <bcm_int/esw/field.h> 67 #include <bcm_int/esw/switch.h> 68 #include <bcm_int/esw/trident2.h> 69 #include <soc/soc_ser_log.h> 70 71 72 73 /* Flex enable regmem and fields */ 74 static soc_reg_t _bcm_td2_flex_hash_control = RTAG7_HASH_CONTROL_3r; 75 static soc_field_t _bcm_td2_flex_hash_enable_fields[] = { 76 ENABLE_FLEX_FIELD_1_Af, 77 ENABLE_FLEX_FIELD_1_Bf, 78 ENABLE_FLEX_FIELD_2_Af, 79 ENABLE_FLEX_FIELD_2_Bf 80 }; 81 82 #ifdef BCM_TOMAHAWK2_SUPPORT 83 static soc_reg_t _bcm_th2_flex_hash_control = RTAG7_HASH_CONTROL_3_64r; 84 static soc_field_t _bcm_th2_flex_hash_enable_fields[] = { 85 ENABLE_FLEX_FIELD_1_Af, 86 ENABLE_FLEX_FIELD_1_Bf, 87 ENABLE_FLEX_FIELD_2_Af, 88 ENABLE_FLEX_FIELD_2_Bf, 89 ENABLE_FLEX_FIELD_3_Af, 90 ENABLE_FLEX_FIELD_3_Bf, 91 ENABLE_FLEX_FIELD_4_Af, 92 ENABLE_FLEX_FIELD_4_Bf, 93 ENABLE_FLEX_FIELD_5_Af, 94 ENABLE_FLEX_FIELD_5_Bf, 95 ENABLE_FLEX_FIELD_6_Af, 96 ENABLE_FLEX_FIELD_6_Bf, 97 ENABLE_FLEX_FIELD_7_Af, 98 ENABLE_FLEX_FIELD_7_Bf, 99 ENABLE_FLEX_FIELD_8_Af, 100 ENABLE_FLEX_FIELD_8_Bf, 101 ENABLE_FLEX_FIELD_9_Af, 102 ENABLE_FLEX_FIELD_9_Bf, 103 ENABLE_FLEX_FIELD_10_Af, 104 ENABLE_FLEX_FIELD_10_Bf, 105 ENABLE_FLEX_FIELD_11_Af, 106 ENABLE_FLEX_FIELD_11_Bf, 107 ENABLE_FLEX_FIELD_12_Af, 108 ENABLE_FLEX_FIELD_12_Bf, 109 ENABLE_FLEX_FIELD_13_Af, 110 ENABLE_FLEX_FIELD_13_Bf 111 }; 112 #endif /*BCM_TOMAHAWK2_SUPPORT*/ 113 114 /* register to enable flex hasing scheme */ 115 static soc_reg_t _bcm_td2_ing_hash_config = ING_HASH_CONFIG_0r; 116 static soc_field_t _bcm_td2_ing_hash_config_fields[] = { 117 ENABLE_FLEX_HASHINGf 118 }; 119 /* 120 * TCAM: FIELD_1_MASK, FIELD_2_MASK 121 * FIELD_1_DATA, FIELD_2_DATA 122 123 * RAM: FIELD_1_MASK, FIELD_2_MASK 124 * FIELD_1_OFFSET, FIELD_2_OFFSET 125 */ 126 127 static soc_field_t _bcm_td2_flex_hash_data[] = { 128 FIELD_2_DATAf, 129 FIELD_1_DATAf 130 }; 131 132 static soc_field_t _bcm_td2_flex_hash_mask[] = { 133 FIELD_2_MASKf, 134 FIELD_1_MASKf, 135 FIELD_3_MASKf, 136 FIELD_4_MASKf, 137 FIELD_5_MASKf, 138 FIELD_6_MASKf, 139 FIELD_7_MASKf, 140 FIELD_8_MASKf, 141 FIELD_9_MASKf, 142 FIELD_10_MASKf, 143 FIELD_11_MASKf, 144 FIELD_12_MASKf, 145 FIELD_13_MASKf 146 }; 147 148 static soc_field_t _bcm_td2_flex_hash_offset[] = { 149 FIELD_2_OFFSETf, 150 FIELD_1_OFFSETf 151 }; 152 #if defined(BCM_TOMAHAWK_SUPPORT) 153 static soc_field_t _bcm_th_flex_hash_offset_udf[] = { 154 UDF_SEL_2f, 155 UDF_CHUNK_ID_2f, 156 UDF_SEL_1f, 157 UDF_CHUNK_ID_1f, 158 UDF_SEL_3f, 159 UDF_CHUNK_ID_3f, 160 UDF_SEL_4f, 161 UDF_CHUNK_ID_4f, 162 UDF_SEL_5f, 163 UDF_CHUNK_ID_5f, 164 UDF_SEL_6f, 165 UDF_CHUNK_ID_6f, 166 UDF_SEL_7f, 167 UDF_CHUNK_ID_7f, 168 UDF_SEL_8f, 169 UDF_CHUNK_ID_8f, 170 UDF_SEL_9f, 171 UDF_CHUNK_ID_9f, 172 UDF_SEL_10f, 173 UDF_CHUNK_ID_10f, 174 UDF_SEL_11f, 175 UDF_CHUNK_ID_11f, 176 UDF_SEL_12f, 177 UDF_CHUNK_ID_12f, 178 UDF_SEL_13f, 179 UDF_CHUNK_ID_13f 180 }; 181 static soc_field_t _bcm_th_flex_hash_offset_type[] = { 182 FIELD_2_TYPEf, 183 FIELD_1_TYPEf, 184 FIELD_3_TYPEf, 185 FIELD_4_TYPEf, 186 FIELD_5_TYPEf, 187 FIELD_6_TYPEf, 188 FIELD_7_TYPEf, 189 FIELD_8_TYPEf, 190 FIELD_9_TYPEf, 191 FIELD_10_TYPEf, 192 FIELD_11_TYPEf, 193 FIELD_12_TYPEf, 194 FIELD_13_TYPEf 195 }; 196 #endif /*BCM_TOMAHAWK_SUPPORT*/ 197 static soc_mem_t _bcm_td2_flex_hash_table[] = { 198 UDF_CONDITIONAL_CHECK_TABLE_CAMm, 199 UDF_CONDITIONAL_CHECK_TABLE_RAMm 200 }; 201 202 #define FLEX_HASH_TCAM (_bcm_td2_flex_hash_table[0]) 203 #define FLEX_HASH_OFFSET (_bcm_td2_flex_hash_table[1]) 204 #define FLEX_HASH_TCAM_ENTRY_T udf_conditional_check_table_cam_entry_t 205 #define FLEX_HASH_OFFSET_ENTRY_T udf_conditional_check_table_ram_entry_t 206 #define FLEX_HASH_OFFSET_MASK(_u_) (((SOC_IS_TOMAHAWK2(_u_)) \ 207 || (SOC_IS_TOMAHAWK3(_u_))) ? \ 208 UDF_CONDITIONAL_CHECK_TABLE_RAM_1m : UDF_CONDITIONAL_CHECK_TABLE_RAMm) 209 #define FLEX_HASH_OFFSET_MASK_ENTRY_T udf_conditional_check_table_ram_1_entry_t 210 211 /* 212 * Flex Index usage bitmap operations. The 8 indexes of flex tcam table are 213 * being managed with index bitmap operations. 214 */ 215 #define _BCM_SWITCH_FLEX_IDX_USED_GET(_u_, _idx_) \ 216 SHR_BITGET(SWITCH_HASH_INFO(_u_)->hash_idx_bitmap, (_idx_)) 217 218 #define _BCM_SWITCH_FLEX_IDX_USED_SET(_u_, _idx_) \ 219 SHR_BITSET(SWITCH_HASH_INFO((_u_))->hash_idx_bitmap, (_idx_)) 220 221 #define _BCM_SWITCH_FLEX_IDX_USED_CLR(_u_, _idx_) \ 222 SHR_BITCLR(SWITCH_HASH_INFO((_u_))->hash_idx_bitmap, (_idx_)) 223 224 225 #define FLEX_HASH_MAX_FIELDS 4 226 #define FLEX_HASH_MAX_OFFSET 13 227 #define FLEX_QUAL_BIT_PER_SIZE 8 228 #define FLEX_HASH_OFFSET_NUM(_u_) (((SOC_IS_TOMAHAWK2(_u_)) \ 229 || (SOC_IS_TOMAHAWK3(_u_))) ? 13 : 2) 230 #define FLEX_HASH_CHECK_FIELDS_NUM 2 231 typedef struct _bcm_flex_hash_match_arr_s { 232 int qual_id; /* Data Qualifier Id */ 233 int qual_size; /* Data qualifier size: xbytes, 2byte max */ 234 uint32 qual_match; /* Qualifier match data */ 235 uint32 qual_mask; /* Qualifier mask */ 236 } _bcm_flex_hash_match_arr_t; 237 238 typedef struct _bcm_flex_hash_entry_s { 239 int entry_id; /* Logical eid for flex hash entry */ 240 int hw_idx; /* Associated flex table index */ 241 int entry_count; /* Reference count of the entry */ 242 int offset_bitmap; /* Flex hash offset bitmap */ 243 int offset_count; /* Flex hash offset count */ 244 int hash_offset[FLEX_HASH_MAX_OFFSET]; /* Flex hash offset */ 245 int hash_mask[FLEX_HASH_MAX_OFFSET]; /* Flex hash mask */ 246 _bcm_flex_hash_match_arr_t match_arr[FLEX_HASH_MAX_FIELDS]; 247 struct _bcm_flex_hash_entry_s *next; /* Next in flex hash list */ 248 int type[FLEX_HASH_MAX_OFFSET]; /* field type, 249 currently there are two field types in flex hash ram table. 0: offset, 1: udf chunk */ 250 bcm_udf_id_t udf_id[FLEX_HASH_MAX_OFFSET]; /*udf id when field type is udf*/ 251 } flex_hash_entry_t, *flex_hash_entry_p; 252 253 /* Switch flex hash bookkeeping structure */ 254 typedef struct _bcm_td2_switch_hash_bookeeping_s { 255 int init; 256 int api_ver; 257 flex_hash_entry_p hash_entry_list; 258 SHR_BITDCL *hash_idx_bitmap; 259 uint32 last_hash_entry_id; 260 } _bcm_td2_switch_hash_bookeeping_t; 261 262 STATIC _bcm_td2_switch_hash_bookeeping_t 263 _bcm_td2_switch_hash_bk_info[BCM_MAX_NUM_UNITS]; 264 265 #define SWITCH_HASH_INFO(_unit_) (&_bcm_td2_switch_hash_bk_info[_unit_]) 266 #define SWITCH_HASH_INIT(_unit_) \ 267 (_bcm_td2_switch_hash_bk_info[_unit_].init) 268 #define SWITCH_HASH_ENTRY_LIST(_unit_) \ 269 (_bcm_td2_switch_hash_bk_info[_unit_].hash_entry_list) 270 #define SWITCH_HASH_IDX_BITMAP(_unit_) \ 271 (_bcm_td2_switch_hash_bk_info[_unit_].hash_idx_bitmap) 272 #define SWITCH_HASH_LAST_ENTRY_ID(_unit_) \ 273 (_bcm_td2_switch_hash_bk_info[_unit_].last_hash_entry_id) 274 275 #if defined (BCM_WARM_BOOT_SUPPORT) 276 /* warmboot entry */ 277 typedef struct wb_hash_entry_match_arr_s { 278 uint32 qual_id; 279 uint32 qual_size; 280 } wb_hash_entry_match_arr_t; 281 282 typedef struct bcmi_xgs4_td2_switch_wb_hash_entry_s { 283 uint32 entry_id; 284 uint32 hw_idx; 285 uint32 offset_bitmap; 286 wb_hash_entry_match_arr_t match_arr[FLEX_HASH_MAX_FIELDS]; 287 bcm_udf_id_t udf_id[FLEX_HASH_MAX_OFFSET]; 288 } bcmi_xgs4_td2_switch_wb_hash_entry_t; 289 #endif 290 291 292 293 typedef struct _bcm_td2_gtp_port_match_s { 294 uint8 match_criteria; 295 uint16 dst_port; 296 uint16 src_port; 297 } _bcm_td2_gtp_port_match_t; 298 /* 299 * Software book keeping for Switch Match related information 300 */ 301 typedef struct _bcm_td2_switch_match_bookkeeping_s { 302 _bcm_td2_gtp_port_match_t **gtp_ptr_array; /* Array of pointers to gtp port table */ 303 sal_mutex_t match_mutex; 304 } _bcm_td2_switch_match_bookkeeping_t; 305 306 STATIC _bcm_td2_switch_match_bookkeeping_t 307 _bcm_td2_switch_match_bk_info[BCM_MAX_NUM_UNITS]; 308 309 STATIC int _bcm_td2_match_initialized[BCM_MAX_NUM_UNITS] = { 0 }; 310 311 #define TD2_MATCH_INFO(_u_) (&_bcm_td2_switch_match_bk_info[_u_]) 312 313 #define TD2_GTP_PORT_MATCH(_u_, id) \ 314 (TD2_MATCH_INFO(_u_)->gtp_ptr_array[id]) 315 316 #define TD2_GTP_PORT_MATCH_IS_USED(_u_, id) \ 317 (TD2_MATCH_INFO(_u_)->gtp_ptr_array[id] != NULL) 318 319 320 /* Switch Match related definitions */ 321 #define _BCM_TD2_SWITCH_MATCH_ID_MASK (0xffff) 322 #define _BCM_TD2_SWITCH_MATCH_TYPE_SHIFT (28) 323 324 #define TD2_MATCH_TYPE_GET(_id_) \ 325 (_id_ >> _BCM_TD2_SWITCH_MATCH_TYPE_SHIFT) 326 #define TD2_MATCH_ID_SET(_id_, _service_type_) \ 327 (_id_ | _service_type_ << _BCM_TD2_SWITCH_MATCH_TYPE_SHIFT) 328 #define TD2_MATCH_HW_ID_GET(_id_) \ 329 (_id_ & _BCM_TD2_SWITCH_MATCH_ID_MASK) 330 331 #define TD2_MATCH_LOCK(_u_) \ 332 sal_mutex_take(TD2_MATCH_INFO(_u_)->match_mutex, sal_mutex_FOREVER); 333 #define TD2_MATCH_UNLOCK(_u_) \ 334 sal_mutex_give(TD2_MATCH_INFO(_u_)->match_mutex); 335 336 #define TD2_MATCH_INIT(_u_) \ 337 do { \ 338 if ((_u_ < 0) || (_u_ >= BCM_MAX_NUM_UNITS)) { \ 339 return BCM_E_UNIT; \ 340 } \ 341 if (!_bcm_td2_match_initialized[_u_]) { \ 342 return BCM_E_INIT; \ 343 } \ 344 } while (0) 345 346 347 /* forward declarations */ 348 349 STATIC int _flex_hash_entry_get(int unit, bcm_hash_entry_t hash_entry_id, 350 flex_hash_entry_t ** hash_entry); 351 352 STATIC int _bcm_hash_entry_delete(int unit, bcm_hash_entry_t entry_id); 353 STATIC int _bcm_hash_entry_remove(int unit, bcm_hash_entry_t entry_id); 354 355 STATIC int _flex_hash_entry_destroy(int unit, flex_hash_entry_t * entry); 356 357 358 #if defined (BCM_WARM_BOOT_SUPPORT) 359 STATIC int _bcm_flex_hash_table_wb_read(int unit, 360 flex_hash_entry_t * hash_entry, 361 bcmi_xgs4_td2_switch_wb_hash_entry_t * wb_hash_entry); 362 #endif 363 364 /* 365 * The below listed flexible hashing support routines are modularized for table 366 * and list management routines. 367 * 1. Flex hash TCAM table read/write routines 368 * _bcm_flex_hash_table_write 369 * _bcm_flex_hash_table_read 370 * _bcm_flex_hash_control_enable 371 * _bcm_flex_hash_control_disable 372 * 373 * 2. Flex hash Entry list management routines 374 * _flex_hash_entry_get 375 * _flex_hash_entry_destroy 376 * _flex_hash_entry_destroy_all 377 * _flex_hash_entry_alloc 378 * _flex_hash_entry_add 379 * _flex_hash_entry_delete 380 * 381 * 3. Flex hash management routines 382 * _bcm_hash_entry_create 383 * _bcm_hash_entry_delete 384 * _bcm_hash_entry_qual_set 385 * _bcm_hash_entry_qual_get 386 * _bcm_hash_entry_qual_data_set 387 * _bcm_hash_entry_qual_data_get 388 * 389 * 390 * 4. Flexible hash Switch API support routines 391 * bcm_td2_switch_hash_entry_init 392 * bcm_td2_switch_hash_entry_detach 393 * bcm_td2_switch_hash_entry_create 394 * bcm_td2_switch_hash_entry_destroy 395 * bcm_td2_switch_hash_qualify_data 396 * 397 * bcm_td2_switch_hash_entry_install 398 * bcm_td2_switch_hash_entry_reinstall 399 * bcm_td2_switch_hash_entry_remove 400 */ 401 402 /* 403 * 404 * Flex hash TCAM table read/write routines 405 */ 406 #if defined(BCM_TOMAHAWK2_SUPPORT) 407 STATIC int 408 _bcm_th2_flex_hash_table_write(int unit, flex_hash_entry_t * hash_entry, uint8 delete) 409 { 410 int fld, rv = BCM_E_NONE; 411 FLEX_HASH_TCAM_ENTRY_T flex_tcam_entry; 412 FLEX_HASH_OFFSET_ENTRY_T flex_offset_entry; 413 FLEX_HASH_OFFSET_MASK_ENTRY_T flex_offset_mask_entry; 414 uint32 data[2] = { 0, 0 }; 415 uint32 mask[2] = { 0, 0 }; 416 417 if (NULL == hash_entry) { 418 return BCM_E_FAIL; 419 } 420 421 /* 422 note :qual_size_range is 0~2. maximum 4 match field data in a flexkey. 423 it is required to create a flexkey in a such order 424 field_data2: 1st qual_data, 2nd qual_data 425 field_data1: 3rd qual_data, 4th qual_data; thus 426 first and third match field data is shifed to left for 16 bits insdie field data. 427 in addition, if qual_size is 1, qual_data is shifed to left for 8 bits inside field data 428 if qual_size is 0 or 2, there won't be any shift inside field data 429 */ 430 data[0] = (hash_entry->match_arr[0].qual_match << 431 ((hash_entry->match_arr[0].qual_size & 1) * FLEX_QUAL_BIT_PER_SIZE)) << 16; 432 data[0] |= (hash_entry->match_arr[1].qual_match << 433 ((hash_entry->match_arr[1].qual_size & 1) * FLEX_QUAL_BIT_PER_SIZE)) << 0; 434 data[1] = (hash_entry->match_arr[2].qual_match << 435 ((hash_entry->match_arr[2].qual_size & 1) * FLEX_QUAL_BIT_PER_SIZE)) << 16; 436 data[1] |= (hash_entry->match_arr[3].qual_match << 437 ((hash_entry->match_arr[3].qual_size & 1) * FLEX_QUAL_BIT_PER_SIZE)) << 0; 438 439 mask[0] = (hash_entry->match_arr[0].qual_mask << 440 ((hash_entry->match_arr[0].qual_size & 1) * FLEX_QUAL_BIT_PER_SIZE)) << 16; 441 mask[0] |= (hash_entry->match_arr[1].qual_mask << 442 ((hash_entry->match_arr[1].qual_size & 1) * FLEX_QUAL_BIT_PER_SIZE)) << 0; 443 mask[1] = (hash_entry->match_arr[2].qual_mask << 444 ((hash_entry->match_arr[2].qual_size & 1) * FLEX_QUAL_BIT_PER_SIZE)) << 16; 445 mask[1] |= (hash_entry->match_arr[3].qual_mask << 446 ((hash_entry->match_arr[3].qual_size & 1) * FLEX_QUAL_BIT_PER_SIZE)) << 0; 447 448 sal_memset(&flex_tcam_entry, 0, sizeof(flex_tcam_entry)); 449 sal_memset(&flex_offset_entry, 0, sizeof(flex_offset_entry)); 450 sal_memset(&flex_offset_mask_entry, 0, sizeof(flex_offset_mask_entry)); 451 452 rv = soc_mem_read(unit, FLEX_HASH_TCAM, MEM_BLOCK_ANY, 453 hash_entry->hw_idx, &flex_tcam_entry); 454 if (BCM_FAILURE(rv)) { 455 return BCM_E_FAIL; 456 } 457 rv = soc_mem_read(unit, FLEX_HASH_OFFSET, MEM_BLOCK_ANY, 458 hash_entry->hw_idx, &flex_offset_entry); 459 if (BCM_FAILURE(rv)) { 460 return BCM_E_FAIL; 461 } 462 463 rv = soc_mem_read(unit, FLEX_HASH_OFFSET_MASK(unit), MEM_BLOCK_ANY, 464 hash_entry->hw_idx, &flex_offset_mask_entry); 465 if (BCM_FAILURE(rv)) { 466 return BCM_E_FAIL; 467 } 468 469 if (soc_mem_field_valid(unit, FLEX_HASH_TCAM, VALIDf)) { 470 if (delete && !soc_mem_field32_get(unit, FLEX_HASH_TCAM, 471 &flex_tcam_entry, VALIDf)) { 472 return BCM_E_NOT_FOUND; 473 } 474 soc_mem_field32_set(unit, FLEX_HASH_TCAM, &flex_tcam_entry, 475 VALIDf, delete? 0:1); 476 } 477 478 for (fld = 0; fld < FLEX_HASH_CHECK_FIELDS_NUM; fld++) { 479 soc_mem_field32_set(unit, FLEX_HASH_TCAM, &flex_tcam_entry, 480 _bcm_td2_flex_hash_data[fld], delete ? 0 : data[fld]); 481 soc_mem_field32_set(unit, FLEX_HASH_TCAM, &flex_tcam_entry, 482 _bcm_td2_flex_hash_mask[fld], delete ? 0 : mask[fld]); 483 } 484 485 for (fld = 0; fld < FLEX_HASH_OFFSET_NUM(unit); fld++) { 486 if (hash_entry->type[fld] & BCM_SWITCH_HASH_FIELD_TYPE_UDF) { 487 if (hash_entry->offset_bitmap & (0x1 << fld)) { 488 if (hash_entry->hash_offset[fld] >= MAX_UDF_OFFSET_CHUNKS) { 489 return BCM_E_PARAM; 490 } 491 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 492 &flex_offset_entry, 493 _bcm_th_flex_hash_offset_udf[fld*2], 494 delete ? 0 : hash_entry->hash_offset[fld] / 8); 495 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 496 &flex_offset_entry, 497 _bcm_th_flex_hash_offset_udf[fld*2 + 1], 498 delete ? 0 : (7 - hash_entry->hash_offset[fld] % 8)); 499 soc_mem_field32_set(unit, FLEX_HASH_OFFSET_MASK(unit), 500 &flex_offset_mask_entry, 501 _bcm_td2_flex_hash_mask[fld], 502 delete ? 0 : hash_entry->hash_mask[fld]); 503 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 504 &flex_offset_entry, 505 _bcm_th_flex_hash_offset_type[fld], 506 delete ? 0 : 1); 507 } else { 508 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 509 &flex_offset_entry, 510 _bcm_th_flex_hash_offset_udf[fld*2], 0); 511 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 512 &flex_offset_entry, 513 _bcm_th_flex_hash_offset_udf[fld*2 + 1], 0); 514 soc_mem_field32_set(unit, FLEX_HASH_OFFSET_MASK(unit), 515 &flex_offset_mask_entry, 516 _bcm_td2_flex_hash_mask[fld], 0); 517 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 518 &flex_offset_entry, 519 _bcm_th_flex_hash_offset_type[fld], 0); 520 break; 521 } 522 } else { 523 if (fld > bcmSwitchFlexHashField1) { 524 continue; 525 } 526 if (hash_entry->offset_bitmap & (0x1 << fld)) { 527 if (hash_entry->hash_offset[fld] >= 528 (FLEX_QUAL_BIT_PER_SIZE * FLEX_HASH_CHECK_FIELDS_NUM)) { 529 return BCM_E_PARAM; 530 } 531 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 532 &flex_offset_entry, 533 _bcm_td2_flex_hash_offset[fld], 534 delete ? 0 : hash_entry->hash_offset[fld]); 535 soc_mem_field32_set(unit, FLEX_HASH_OFFSET_MASK(unit), 536 &flex_offset_mask_entry, 537 _bcm_td2_flex_hash_mask[fld], 538 delete ? 0 : hash_entry->hash_mask[fld]); 539 } else { 540 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 541 &flex_offset_entry, 542 _bcm_td2_flex_hash_offset[fld], 0); 543 soc_mem_field32_set(unit, FLEX_HASH_OFFSET_MASK(unit), 544 &flex_offset_mask_entry, 545 _bcm_td2_flex_hash_mask[fld], 0); 546 } 547 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 548 &flex_offset_entry, 549 _bcm_th_flex_hash_offset_type[fld], 0); 550 } 551 } 552 553 rv = soc_mem_write(unit, FLEX_HASH_OFFSET, MEM_BLOCK_ANY, 554 hash_entry->hw_idx, &flex_offset_entry); 555 if (BCM_FAILURE(rv)) { 556 return BCM_E_FAIL; 557 } 558 rv = soc_mem_write(unit, FLEX_HASH_OFFSET_MASK(unit), MEM_BLOCK_ANY, 559 hash_entry->hw_idx, &flex_offset_mask_entry); 560 if (BCM_FAILURE(rv)) { 561 return BCM_E_FAIL; 562 } 563 rv = soc_mem_write(unit, FLEX_HASH_TCAM, MEM_BLOCK_ALL, 564 hash_entry->hw_idx, &flex_tcam_entry); 565 566 if (BCM_FAILURE(rv)) { 567 return BCM_E_FAIL; 568 } 569 return BCM_E_NONE; 570 } 571 #endif /*BCM_TOMAHAWK2_SUPPORT*/ 572 573 STATIC int 574 _bcm_flex_hash_table_write(int unit, flex_hash_entry_t * hash_entry, uint8 delete) 575 { 576 int fld, rv = BCM_E_NONE; 577 FLEX_HASH_TCAM_ENTRY_T flex_tcam_entry; 578 FLEX_HASH_OFFSET_ENTRY_T flex_offset_entry; 579 uint32 data[2] = { 0, 0 }; 580 uint32 mask[2] = { 0, 0 }; 581 582 if (NULL == hash_entry) { 583 return BCM_E_FAIL; 584 } 585 586 /* 587 note :qual_size_range is 0~2. maximum 4 match field data in a flexkey. 588 it is required to create a flexkey in a such order 589 field_data2: 1st qual_data, 2nd qual_data 590 field_data1: 3rd qual_data, 4th qual_data; thus 591 first and third match field data is shifed to left for 16 bits insdie field data. 592 in addition, if qual_size is 1, qual_data is shifed to left for 8 bits inside field data 593 if qual_size is 0 or 2, there won't be any shift inside field data 594 */ 595 data[0] = (hash_entry->match_arr[0].qual_match << 596 ((hash_entry->match_arr[0].qual_size & 1) * FLEX_QUAL_BIT_PER_SIZE)) << 16; 597 data[0] |= (hash_entry->match_arr[1].qual_match << 598 ((hash_entry->match_arr[1].qual_size & 1) * FLEX_QUAL_BIT_PER_SIZE)) << 0; 599 data[1] = (hash_entry->match_arr[2].qual_match << 600 ((hash_entry->match_arr[2].qual_size & 1) * FLEX_QUAL_BIT_PER_SIZE)) << 16; 601 data[1] |= (hash_entry->match_arr[3].qual_match << 602 ((hash_entry->match_arr[3].qual_size & 1) * FLEX_QUAL_BIT_PER_SIZE)) << 0; 603 604 mask[0] = (hash_entry->match_arr[0].qual_mask << 605 ((hash_entry->match_arr[0].qual_size & 1) * FLEX_QUAL_BIT_PER_SIZE)) << 16; 606 mask[0] |= (hash_entry->match_arr[1].qual_mask << 607 ((hash_entry->match_arr[1].qual_size & 1) * FLEX_QUAL_BIT_PER_SIZE)) << 0; 608 mask[1] = (hash_entry->match_arr[2].qual_mask << 609 ((hash_entry->match_arr[2].qual_size & 1) * FLEX_QUAL_BIT_PER_SIZE)) << 16; 610 mask[1] |= (hash_entry->match_arr[3].qual_mask << 611 ((hash_entry->match_arr[3].qual_size & 1) * FLEX_QUAL_BIT_PER_SIZE)) << 0; 612 613 sal_memset(&flex_tcam_entry, 0, sizeof(flex_tcam_entry)); 614 sal_memset(&flex_offset_entry, 0, sizeof(flex_offset_entry)); 615 616 rv = soc_mem_read(unit, FLEX_HASH_TCAM, MEM_BLOCK_ANY, 617 hash_entry->hw_idx, &flex_tcam_entry); 618 if (BCM_FAILURE(rv)) { 619 return BCM_E_FAIL; 620 } 621 rv = soc_mem_read(unit, FLEX_HASH_OFFSET, MEM_BLOCK_ANY, 622 hash_entry->hw_idx, &flex_offset_entry); 623 if (BCM_FAILURE(rv)) { 624 return BCM_E_FAIL; 625 } 626 627 if (soc_mem_field_valid(unit, FLEX_HASH_TCAM, VALIDf)) { 628 if (delete && !soc_mem_field32_get(unit, FLEX_HASH_TCAM, 629 &flex_tcam_entry, VALIDf)) { 630 return BCM_E_NOT_FOUND; 631 } 632 soc_mem_field32_set(unit, FLEX_HASH_TCAM, &flex_tcam_entry, 633 VALIDf, delete? 0:1); 634 } 635 636 for (fld = 0; fld < FLEX_HASH_CHECK_FIELDS_NUM; fld++) { 637 soc_mem_field32_set(unit, FLEX_HASH_TCAM, &flex_tcam_entry, 638 _bcm_td2_flex_hash_data[fld], delete ? 0 : data[fld]); 639 soc_mem_field32_set(unit, FLEX_HASH_TCAM, &flex_tcam_entry, 640 _bcm_td2_flex_hash_mask[fld], delete ? 0 : mask[fld]); 641 } 642 643 for (fld = 0; fld < FLEX_HASH_OFFSET_NUM(unit); fld++) { 644 #if defined(BCM_TOMAHAWK_SUPPORT) 645 if (hash_entry->type[fld] & BCM_SWITCH_HASH_FIELD_TYPE_UDF) { 646 if (hash_entry->offset_bitmap & (0x1 << fld)) { 647 if (hash_entry->hash_offset[fld] >= MAX_UDF_OFFSET_CHUNKS) { 648 return BCM_E_PARAM; 649 } 650 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 651 &flex_offset_entry, 652 _bcm_th_flex_hash_offset_udf[fld*2], 653 delete ? 0 : hash_entry->hash_offset[fld] / 8); 654 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 655 &flex_offset_entry, 656 _bcm_th_flex_hash_offset_udf[fld*2 + 1], 657 delete ? 0 : (7 - hash_entry->hash_offset[fld] % 8)); 658 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 659 &flex_offset_entry, 660 _bcm_td2_flex_hash_mask[fld], 661 delete ? 0 : hash_entry->hash_mask[fld]); 662 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 663 &flex_offset_entry, 664 _bcm_th_flex_hash_offset_type[fld], 665 delete ? 0 : 1); 666 } else { 667 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 668 &flex_offset_entry, 669 _bcm_th_flex_hash_offset_udf[fld*2], 0); 670 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 671 &flex_offset_entry, 672 _bcm_th_flex_hash_offset_udf[fld*2 + 1], 0); 673 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 674 &flex_offset_entry, 675 _bcm_td2_flex_hash_mask[fld], 0); 676 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 677 &flex_offset_entry, 678 _bcm_th_flex_hash_offset_type[fld], 0); 679 break; 680 } 681 } else 682 #endif /*BCM_TOMAHAWK_SUPPORT*/ 683 { 684 if (fld > bcmSwitchFlexHashField1) { 685 continue; 686 } 687 if (hash_entry->offset_bitmap & (0x1 << fld)) { 688 if (hash_entry->hash_offset[fld] >= 689 (FLEX_QUAL_BIT_PER_SIZE * FLEX_HASH_CHECK_FIELDS_NUM)) { 690 return BCM_E_PARAM; 691 } 692 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 693 &flex_offset_entry, 694 _bcm_td2_flex_hash_offset[fld], 695 delete ? 0 : hash_entry->hash_offset[fld]); 696 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 697 &flex_offset_entry, 698 _bcm_td2_flex_hash_mask[fld], 699 delete ? 0 : hash_entry->hash_mask[fld]); 700 } else { 701 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 702 &flex_offset_entry, 703 _bcm_td2_flex_hash_offset[fld], 0); 704 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 705 &flex_offset_entry, 706 _bcm_td2_flex_hash_mask[fld], 0); 707 } 708 #if defined(BCM_TOMAHAWK_SUPPORT) 709 if (SOC_IS_TOMAHAWK(unit)) { 710 soc_mem_field32_set(unit, FLEX_HASH_OFFSET, 711 &flex_offset_entry, 712 _bcm_th_flex_hash_offset_type[fld], 0); 713 } 714 #endif /*BCM_TOMAHAWK_SUPPORT*/ 715 } 716 } 717 718 rv = soc_mem_write(unit, FLEX_HASH_OFFSET, MEM_BLOCK_ANY, 719 hash_entry->hw_idx, &flex_offset_entry); 720 if (BCM_FAILURE(rv)) { 721 return BCM_E_FAIL; 722 } 723 rv = soc_mem_write(unit, FLEX_HASH_TCAM, MEM_BLOCK_ALL, 724 hash_entry->hw_idx, &flex_tcam_entry); 725 726 if (BCM_FAILURE(rv)) { 727 return BCM_E_FAIL; 728 } 729 730 return BCM_E_NONE; 731 } 732 733 #if defined (BCM_WARM_BOOT_SUPPORT) 734 STATIC int 735 _bcm_flex_hash_table_wb_read(int unit, 736 flex_hash_entry_t * hash_entry, 737 bcmi_xgs4_td2_switch_wb_hash_entry_t * wb_hash_entry) 738 { 739 int fld, rv = BCM_E_NONE; 740 uint32 data[2], mask[2]; 741 FLEX_HASH_TCAM_ENTRY_T flex_tcam_entry; 742 FLEX_HASH_OFFSET_ENTRY_T flex_offset_entry; 743 744 #if defined(BCM_TOMAHAWK_SUPPORT) 745 int udf_chunk_id, udf_sel; 746 #endif /*BCM_TOMAHAWK_SUPPORT*/ 747 748 #ifdef BCM_TOMAHAWK2_SUPPORT 749 FLEX_HASH_OFFSET_MASK_ENTRY_T flex_offset_mask_entry; 750 #endif /*BCM_TOMAHAWK2_SUPPORT*/ 751 752 sal_memset(&flex_tcam_entry, 0, sizeof(flex_tcam_entry)); 753 sal_memset(&flex_offset_entry, 0, sizeof(flex_offset_entry)); 754 755 hash_entry->offset_count = 0; 756 757 rv = soc_mem_read(unit, FLEX_HASH_TCAM, MEM_BLOCK_ANY, 758 hash_entry->hw_idx, &flex_tcam_entry); 759 if (BCM_FAILURE(rv)) { 760 return BCM_E_FAIL; 761 } 762 763 rv = soc_mem_read(unit, FLEX_HASH_OFFSET, MEM_BLOCK_ANY, 764 hash_entry->hw_idx, &flex_offset_entry); 765 if (BCM_FAILURE(rv)) { 766 return BCM_E_FAIL; 767 } 768 #ifdef BCM_TOMAHAWK2_SUPPORT 769 if ((SOC_IS_TOMAHAWK2(unit)) || (SOC_IS_TOMAHAWK3(unit))) { 770 sal_memset(&flex_offset_mask_entry, 0, sizeof(flex_offset_mask_entry)); 771 rv = soc_mem_read(unit, FLEX_HASH_OFFSET_MASK(unit), MEM_BLOCK_ANY, 772 hash_entry->hw_idx, &flex_offset_mask_entry); 773 if (BCM_FAILURE(rv)) { 774 return BCM_E_FAIL; 775 } 776 } 777 #endif 778 779 for (fld = 0; fld < FLEX_HASH_CHECK_FIELDS_NUM; fld++) { 780 data[fld] = 781 soc_mem_field32_get(unit, FLEX_HASH_TCAM, &flex_tcam_entry, 782 _bcm_td2_flex_hash_data[fld]); 783 mask[fld] = 784 soc_mem_field32_get(unit, FLEX_HASH_TCAM, &flex_tcam_entry, 785 _bcm_td2_flex_hash_mask[fld]); 786 } 787 788 for (fld = 0; fld < FLEX_HASH_OFFSET_NUM(unit); fld++) { 789 #if defined(BCM_TOMAHAWK_SUPPORT) 790 if (SOC_IS_TOMAHAWKX(unit)) { 791 hash_entry->type[fld] = 792 soc_mem_field32_get(unit, FLEX_HASH_OFFSET, 793 &flex_offset_entry, 794 _bcm_th_flex_hash_offset_type[fld]); 795 } 796 if (hash_entry->type[fld] & BCM_SWITCH_HASH_FIELD_TYPE_UDF) { 797 udf_sel = soc_mem_field32_get(unit, FLEX_HASH_OFFSET, 798 &flex_offset_entry, 799 _bcm_th_flex_hash_offset_udf[fld*2]); 800 udf_chunk_id= soc_mem_field32_get(unit, FLEX_HASH_OFFSET, 801 &flex_offset_entry, 802 _bcm_th_flex_hash_offset_udf[fld*2 + 1]); 803 hash_entry->hash_offset[fld] = udf_sel * 8 + (7 - udf_chunk_id); 804 } else 805 #endif /*BCM_TOMAHAWK_SUPPORT*/ 806 { 807 if (fld > bcmSwitchFlexHashField1) { 808 continue; 809 } 810 hash_entry->hash_offset[fld] = 811 soc_mem_field32_get(unit, FLEX_HASH_OFFSET, 812 &flex_offset_entry, 813 _bcm_td2_flex_hash_offset[fld]); 814 } 815 816 #ifdef BCM_TOMAHAWK2_SUPPORT 817 if ((SOC_IS_TOMAHAWK2(unit)) || (SOC_IS_TOMAHAWK3(unit))) { 818 hash_entry->hash_mask[fld] = 819 soc_mem_field32_get(unit, FLEX_HASH_OFFSET_MASK(unit), 820 &flex_offset_mask_entry, 821 _bcm_td2_flex_hash_mask[fld]); 822 } else 823 #endif 824 { 825 hash_entry->hash_mask[fld] = 826 soc_mem_field32_get(unit, FLEX_HASH_OFFSET, 827 &flex_offset_entry, 828 _bcm_td2_flex_hash_mask[fld]); 829 } 830 831 if (hash_entry->hash_offset[fld] > 0) { 832 hash_entry->offset_count++; 833 } 834 } 835 836 for (fld = 0; fld < FLEX_HASH_MAX_FIELDS; fld++) { 837 hash_entry->match_arr[fld].qual_id= wb_hash_entry->match_arr[fld].qual_id; 838 if (hash_entry->match_arr[fld].qual_id >= 0) 839 { 840 hash_entry->match_arr[fld].qual_size = wb_hash_entry->match_arr[fld].qual_size; 841 842 hash_entry->match_arr[fld].qual_match = (data[fld / 2] >>((fld % 2) ? 0:16)) >> 843 ((hash_entry->match_arr[0].qual_size & 1) * FLEX_QUAL_BIT_PER_SIZE); 844 hash_entry->match_arr[fld].qual_mask = (mask[fld / 2] >> ((fld % 2) ? 0:16)) >> 845 ((hash_entry->match_arr[0].qual_size & 1) * FLEX_QUAL_BIT_PER_SIZE); 846 847 } 848 } 849 #if defined(BCM_TOMAHAWK_SUPPORT) 850 for (fld = 0; fld < FLEX_HASH_OFFSET_NUM(unit); fld++) { 851 if (hash_entry->type[fld]) { 852 hash_entry->udf_id[fld] = wb_hash_entry->udf_id[fld]; 853 } 854 } 855 #endif /*BCM_TOMAHAWK_SUPPORT*/ 856 857 return BCM_E_NONE; 858 } 859 #endif 860 861 /* 862 enable RTAG7_HASH_CONTROL and ING_HASH_CONFIG_0 registers 863 */ 864 STATIC int 865 _bcm_flex_hash_control_enable(int unit) 866 { 867 868 int cnt; 869 soc_reg_t reg; 870 uint32 hash_control, hash_config; 871 #ifdef BCM_TOMAHAWK2_SUPPORT 872 uint64 hash_control_64; 873 #endif 874 875 /* 876 * Enable Flexible/UDF controls 877 * Flex hash controls are enabled for Hash A and Hash B, which has 878 * high precedence over Flex UDF controls. 879 */ 880 #ifdef BCM_TOMAHAWK2_SUPPORT 881 if ((SOC_IS_TOMAHAWK2(unit)) || (SOC_IS_TOMAHAWK3(unit))) { 882 reg = _bcm_th2_flex_hash_control; 883 BCM_IF_ERROR_RETURN(soc_reg64_get 884 (unit, reg, REG_PORT_ANY, 0, &hash_control_64)); 885 for (cnt = 0; 886 cnt < 887 (sizeof(_bcm_th2_flex_hash_enable_fields) / 888 sizeof(_bcm_th2_flex_hash_enable_fields[0])); cnt++) { 889 if (SOC_REG_FIELD_VALID 890 (unit, reg, _bcm_th2_flex_hash_enable_fields[cnt])) { 891 soc_reg64_field32_set(unit, reg, &hash_control_64, 892 _bcm_th2_flex_hash_enable_fields[cnt], 1); 893 } 894 } 895 BCM_IF_ERROR_RETURN(soc_reg64_set 896 (unit, reg, REG_PORT_ANY, 0, hash_control_64)); 897 } else 898 #endif 899 { 900 reg = _bcm_td2_flex_hash_control; 901 BCM_IF_ERROR_RETURN(soc_reg32_get 902 (unit, reg, REG_PORT_ANY, 0, &hash_control)); 903 for (cnt = 0; 904 cnt < 905 (sizeof(_bcm_td2_flex_hash_enable_fields) / 906 sizeof(_bcm_td2_flex_hash_enable_fields[0])); cnt++) { 907 if (SOC_REG_FIELD_VALID 908 (unit, reg, _bcm_td2_flex_hash_enable_fields[cnt])) { 909 soc_reg_field_set(unit, reg, &hash_control, 910 _bcm_td2_flex_hash_enable_fields[cnt], 911 1); 912 } 913 } 914 BCM_IF_ERROR_RETURN(soc_reg32_set 915 (unit, reg, REG_PORT_ANY, 0, hash_control)); 916 } 917 918 /* Enable Actual TCAM lookup using flex key*/ 919 reg = _bcm_td2_ing_hash_config; 920 BCM_IF_ERROR_RETURN(READ_ING_HASH_CONFIG_0r(unit, &hash_config)); 921 922 if (SOC_REG_FIELD_VALID 923 (unit, reg, _bcm_td2_ing_hash_config_fields[0])) { 924 soc_reg_field_set(unit, reg, &hash_config, 925 _bcm_td2_ing_hash_config_fields[0], 1); 926 } 927 928 BCM_IF_ERROR_RETURN(WRITE_ING_HASH_CONFIG_0r(unit, hash_config)); 929 930 return BCM_E_NONE; 931 } 932 933 STATIC int 934 _bcm_flex_hash_control_disable(int unit) 935 { 936 937 int cnt; 938 soc_reg_t reg; 939 uint32 hash_control, hash_config; 940 #ifdef BCM_TOMAHAWK2_SUPPORT 941 uint64 hash_control_64; 942 #endif 943 944 /* 945 * Disable Flexible/UDF controls 946 * Flex hash controls are enabled for Hash A and Hash B, which has 947 * high precedence over Flex UDF controls. 948 */ 949 #ifdef BCM_TOMAHAWK2_SUPPORT 950 if ((SOC_IS_TOMAHAWK2(unit)) || (SOC_IS_TOMAHAWK3(unit))) { 951 reg = _bcm_th2_flex_hash_control; 952 BCM_IF_ERROR_RETURN(soc_reg64_get 953 (unit, reg, REG_PORT_ANY, 0, &hash_control_64)); 954 for (cnt = 0; 955 cnt < 956 (sizeof(_bcm_th2_flex_hash_enable_fields) / 957 _bcm_th2_flex_hash_enable_fields[0]); cnt++) { 958 if (SOC_REG_FIELD_VALID 959 (unit, reg, _bcm_th2_flex_hash_enable_fields[cnt])) { 960 soc_reg64_field32_set(unit, reg, &hash_control_64, 961 _bcm_th2_flex_hash_enable_fields[cnt], 0); 962 } 963 } 964 BCM_IF_ERROR_RETURN(soc_reg64_set 965 (unit, reg, REG_PORT_ANY, 0, hash_control_64)); 966 } else 967 #endif 968 { 969 reg = _bcm_td2_flex_hash_control; 970 BCM_IF_ERROR_RETURN(soc_reg32_get 971 (unit, reg, REG_PORT_ANY, 0, &hash_control)); 972 for (cnt = 0; 973 cnt < 974 (sizeof(_bcm_td2_flex_hash_enable_fields) / 975 _bcm_td2_flex_hash_enable_fields[0]); cnt++) { 976 if (SOC_REG_FIELD_VALID 977 (unit, reg, _bcm_td2_flex_hash_enable_fields[cnt])) { 978 soc_reg_field_set(unit, reg, &hash_control, 979 _bcm_td2_flex_hash_enable_fields[cnt], 980 0); 981 } 982 } 983 BCM_IF_ERROR_RETURN(soc_reg32_set 984 (unit, reg, REG_PORT_ANY, 0, hash_control)); 985 } 986 987 /* Disable TCAM lookup using flex key*/ 988 reg = _bcm_td2_ing_hash_config; 989 BCM_IF_ERROR_RETURN(READ_ING_HASH_CONFIG_0r(unit, &hash_config)); 990 991 if (SOC_REG_FIELD_VALID 992 (unit, reg, _bcm_td2_ing_hash_config_fields[0])) { 993 994 soc_reg_field_set(unit, reg, &hash_config, 995 _bcm_td2_ing_hash_config_fields[0], 0); 996 } 997 998 BCM_IF_ERROR_RETURN(WRITE_ING_HASH_CONFIG_0r(unit, hash_config)); 999 return BCM_E_NONE; 1000 } 1001 1002 /* 1003 * 1004 * Flex hash Entry list management routines 1005 */ 1006 1007 STATIC int 1008 _flex_hash_entry_get(int unit, bcm_hash_entry_t hash_entry_id, 1009 flex_hash_entry_t ** hash_entry) 1010 { 1011 *hash_entry = SWITCH_HASH_ENTRY_LIST(unit); 1012 while (*hash_entry != NULL) { 1013 if ((*hash_entry)->entry_id == hash_entry_id) { 1014 return BCM_E_NONE; 1015 } 1016 *hash_entry = (*hash_entry)->next; 1017 } 1018 return BCM_E_NOT_FOUND; 1019 } 1020 1021 STATIC int 1022 _flex_hash_entry_destroy(int unit, flex_hash_entry_t * entry) 1023 { 1024 1025 if (NULL == entry) { 1026 return BCM_E_NOT_FOUND; 1027 } 1028 1029 if (entry->entry_count == 0) { 1030 sal_free(entry); 1031 } 1032 return BCM_E_NONE; 1033 } 1034 1035 STATIC int 1036 _flex_hash_entry_destroy_all(int unit) 1037 { 1038 1039 flex_hash_entry_t *hash_entry = NULL; 1040 flex_hash_entry_t *hash_curr = NULL; 1041 1042 hash_entry = SWITCH_HASH_ENTRY_LIST(unit); 1043 1044 SWITCH_HASH_ENTRY_LIST(unit) = NULL; 1045 if (NULL != hash_entry) { 1046 while (hash_entry != NULL) { 1047 hash_curr = hash_entry; 1048 hash_entry = hash_curr->next; 1049 _BCM_SWITCH_FLEX_IDX_USED_CLR(unit, hash_curr->hw_idx); 1050 sal_free(hash_curr); 1051 } 1052 } 1053 BCM_IF_ERROR_RETURN(_bcm_flex_hash_control_disable(unit)); 1054 return BCM_E_NONE; 1055 } 1056 1057 STATIC int 1058 _flex_hash_entry_alloc(int unit, flex_hash_entry_t ** entry) 1059 { 1060 int entry_size; 1061 int entry_wrap = 0; 1062 flex_hash_entry_p hash_entry = NULL; 1063 1064 if (NULL == entry) { 1065 return BCM_E_FAIL; 1066 } 1067 1068 entry_size = sizeof(flex_hash_entry_t); 1069 *entry = sal_alloc(entry_size, "flex hash entry"); 1070 if (*entry == NULL) { 1071 return BCM_E_MEMORY; 1072 } 1073 sal_memset(*entry, 0, entry_size); 1074 1075 while (BCM_SUCCESS 1076 (_flex_hash_entry_get(unit, SWITCH_HASH_LAST_ENTRY_ID(unit), 1077 &hash_entry))) { 1078 if (SWITCH_HASH_LAST_ENTRY_ID(unit)++ == 0) { 1079 if (entry_wrap++ >= 2) { 1080 sal_free(*entry); 1081 return BCM_E_RESOURCE; 1082 } 1083 } 1084 } 1085 (*entry)->entry_id = SWITCH_HASH_LAST_ENTRY_ID(unit); 1086 (*entry)->next = NULL; 1087 1088 return BCM_E_NONE; 1089 } 1090 1091 1092 STATIC int 1093 _flex_hash_entry_add(int unit, flex_hash_entry_t * entry, int hw_index) 1094 { 1095 flex_hash_entry_t *hash_entry = NULL; 1096 flex_hash_entry_t *hash_prev = NULL; 1097 1098 if (NULL == entry) { 1099 return BCM_E_FAIL; 1100 } 1101 1102 hash_entry = SWITCH_HASH_ENTRY_LIST(unit); 1103 if (NULL == hash_entry) { 1104 entry->hw_idx = hw_index; 1105 SWITCH_HASH_ENTRY_LIST(unit) = entry; 1106 if (!SOC_WARM_BOOT(unit)) { 1107 BCM_IF_ERROR_RETURN(_bcm_flex_hash_control_enable(unit)); 1108 } 1109 } else { 1110 while (hash_entry != NULL) { 1111 if (hash_entry->entry_id == entry->entry_id) { 1112 entry->hw_idx = hw_index; 1113 /* Increment entry count */ 1114 entry->entry_count++; 1115 } else if (hash_entry->entry_id < entry->entry_id) { 1116 if (NULL == hash_prev) { 1117 SWITCH_HASH_ENTRY_LIST(unit) = entry; 1118 } else { 1119 hash_prev->next = entry; 1120 } 1121 entry->next = hash_entry; 1122 entry->hw_idx = hw_index; 1123 /* Increment entry count */ 1124 entry->entry_count++; 1125 break; 1126 } 1127 hash_prev = hash_entry; 1128 hash_entry = hash_entry->next; 1129 } 1130 if (hash_entry == NULL) { 1131 hash_prev->next = entry; 1132 entry->next = hash_entry; 1133 entry->hw_idx = hw_index; 1134 /* Increment entry count */ 1135 entry->entry_count++; 1136 } 1137 } 1138 return BCM_E_NONE; 1139 } 1140 1141 STATIC int 1142 _flex_hash_entry_delete(int unit, flex_hash_entry_t * entry) 1143 { 1144 flex_hash_entry_t *hash_entry = NULL; 1145 flex_hash_entry_t *hash_prev = NULL; 1146 1147 if (NULL == entry) { 1148 return BCM_E_FAIL; 1149 } 1150 1151 hash_entry = SWITCH_HASH_ENTRY_LIST(unit); 1152 if (NULL != hash_entry) { 1153 1154 while (hash_entry != NULL) { 1155 if (hash_entry->entry_id == entry->entry_id) { 1156 if (NULL == hash_prev) { 1157 SWITCH_HASH_ENTRY_LIST(unit) = hash_entry->next; 1158 } else { 1159 hash_prev->next = hash_entry->next; 1160 } 1161 if (SWITCH_HASH_ENTRY_LIST(unit) == NULL) { 1162 BCM_IF_ERROR_RETURN 1163 (_bcm_flex_hash_control_disable(unit)); 1164 1165 } 1166 break; 1167 } 1168 hash_prev = hash_entry; 1169 hash_entry = hash_entry->next; 1170 } 1171 } 1172 return BCM_E_NONE; 1173 } 1174 1175 /* 1176 * 1177 * Flexible Hashing management routines 1178 */ 1179 1180 STATIC int 1181 _bcm_hash_entry_create(int unit, bcm_hash_entry_t * entry) 1182 { 1183 int num_indexes, idx_cnt; 1184 int hw_index = -1; 1185 flex_hash_entry_p hash_entry = NULL; 1186 int rv = BCM_E_NONE; 1187 1188 /* Allocate hardware index into flex tcam table. */ 1189 num_indexes = soc_mem_index_count(unit, FLEX_HASH_TCAM); 1190 for (idx_cnt = 0; idx_cnt < num_indexes; idx_cnt++) { 1191 if (!_BCM_SWITCH_FLEX_IDX_USED_GET(unit, idx_cnt)) { 1192 hw_index = idx_cnt; /* free index */ 1193 break; 1194 } 1195 } 1196 if (hw_index == -1) { 1197 return BCM_E_FULL; 1198 } 1199 _BCM_SWITCH_FLEX_IDX_USED_SET(unit, hw_index); 1200 1201 /* Allocate entry id and associate with hardware index. */ 1202 rv = _flex_hash_entry_alloc(unit, &hash_entry); 1203 if (BCM_FAILURE(rv)) { 1204 return rv; 1205 } 1206 1207 /* Add in hash entry list. 1208 If RTAG7_HASH_CONTROL and ING_HASH_CONFIG_0 are not set, 1209 the registers will be programemed in this routine */ 1210 rv = _flex_hash_entry_add(unit, hash_entry, hw_index); 1211 if (BCM_FAILURE(rv)) { 1212 _flex_hash_entry_destroy(unit, hash_entry); 1213 return rv; 1214 } 1215 1216 /* return entry id */ 1217 *entry = hash_entry->entry_id; 1218 return rv; 1219 } 1220 1221 STATIC int 1222 _bcm_hash_entry_delete(int unit, bcm_hash_entry_t entry_id) 1223 { 1224 int rv = BCM_E_NONE; 1225 flex_hash_entry_t *hash_entry; 1226 1227 rv = _flex_hash_entry_get(unit, entry_id, &hash_entry); 1228 if (BCM_FAILURE(rv)) { 1229 return rv; 1230 } 1231 1232 _BCM_SWITCH_FLEX_IDX_USED_CLR(unit, hash_entry->hw_idx); 1233 1234 rv = _flex_hash_entry_delete(unit, hash_entry); 1235 if (BCM_FAILURE(rv)) { 1236 return rv; 1237 } 1238 #ifdef BCM_TOMAHAWK2_SUPPORT 1239 if ((SOC_IS_TOMAHAWK2(unit)) || (SOC_IS_TOMAHAWK3(unit))) { 1240 rv = _bcm_th2_flex_hash_table_write(unit, hash_entry, TRUE); 1241 } else 1242 #endif 1243 { 1244 rv = _bcm_flex_hash_table_write(unit, hash_entry, TRUE); 1245 } 1246 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1247 return rv; 1248 } 1249 1250 rv = _flex_hash_entry_destroy(unit, hash_entry); 1251 if (BCM_FAILURE(rv)) { 1252 return rv; 1253 } 1254 1255 1256 return rv; 1257 } 1258 1259 STATIC int 1260 _bcm_hash_entry_remove(int unit, bcm_hash_entry_t entry_id) 1261 { 1262 int rv = BCM_E_NONE; 1263 flex_hash_entry_t *hash_entry; 1264 1265 rv = _flex_hash_entry_get(unit, entry_id, &hash_entry); 1266 if (BCM_FAILURE(rv)) { 1267 return rv; 1268 } 1269 #ifdef BCM_TOMAHAWK2_SUPPORT 1270 if ((SOC_IS_TOMAHAWK2(unit)) || (SOC_IS_TOMAHAWK3(unit))) { 1271 return _bcm_th2_flex_hash_table_write(unit, hash_entry, TRUE); 1272 } else 1273 #endif 1274 { 1275 return _bcm_flex_hash_table_write(unit, hash_entry, TRUE); 1276 } 1277 } 1278 1279 STATIC int 1280 _bcm_hash_entry_udf_set(int unit, bcm_hash_entry_t entry_id, 1281 int qual_count, int *qual_array) 1282 { 1283 int id = 0; 1284 int rv = BCM_E_NONE; 1285 int idx, chunk_id, chunk_base, chunk_max; 1286 flex_hash_entry_t *hash_entry; 1287 bcmi_xgs4_udf_offset_info_t *offset_info; 1288 1289 rv = _flex_hash_entry_get(unit, entry_id, &hash_entry); 1290 if (BCM_FAILURE(rv)) { 1291 return rv; 1292 } 1293 1294 if (qual_count > FLEX_HASH_MAX_FIELDS) { 1295 /* reset outbound size */ 1296 qual_count = FLEX_HASH_MAX_FIELDS; 1297 } 1298 1299 chunk_base = 12; /* UDF2.4 */ 1300 chunk_max = chunk_base + FLEX_HASH_MAX_FIELDS - 1; 1301 1302 for (id = 0; id < qual_count; id++) { 1303 /* Get data qualifier info. */ 1304 rv = bcmi_xgs4_udf_offset_node_get(unit, qual_array[id], 1305 &offset_info); 1306 BCM_IF_ERROR_RETURN(rv); 1307 1308 if (!(BCMI_XGS4_UDF_OFFSET_FLEXHASH & offset_info->flags) || 1309 !(offset_info->hw_bmap & (0xf << chunk_base))) { 1310 return BCM_E_PARAM; 1311 } 1312 1313 for (chunk_id = chunk_base; chunk_id <= chunk_max; chunk_id++) { 1314 if (offset_info->hw_bmap & (0x1 << chunk_id)) { 1315 idx = chunk_id - chunk_base; 1316 hash_entry->match_arr[idx].qual_id = qual_array[id]; 1317 hash_entry->match_arr[idx].qual_size = offset_info->width; 1318 break; 1319 } 1320 } 1321 } 1322 1323 return BCM_E_NONE; 1324 } 1325 1326 STATIC int 1327 _bcm_hash_entry_qual_set(int unit, bcm_hash_entry_t entry_id, 1328 int qual_count, int *qual_array) 1329 { 1330 int id = 0; 1331 int rv = BCM_E_NONE; 1332 int idx, chunk_id, chunk_base, chunk_max; 1333 flex_hash_entry_t *hash_entry; 1334 _field_data_qualifier_t data_qual; 1335 1336 rv = _flex_hash_entry_get(unit, entry_id, &hash_entry); 1337 if (BCM_FAILURE(rv)) { 1338 return rv; 1339 } 1340 1341 if (qual_count > FLEX_HASH_MAX_FIELDS) { 1342 /* reset outbound size */ 1343 qual_count = FLEX_HASH_MAX_FIELDS; 1344 } 1345 1346 chunk_base = 12; /* UDF2.4 */ 1347 chunk_max = chunk_base + FLEX_HASH_MAX_FIELDS - 1; 1348 1349 for (id = 0; id < qual_count; id++) { 1350 /* Get data qualifier info. */ 1351 rv = _field_data_qualifier_get(unit, qual_array[id], 1352 &data_qual); 1353 if (BCM_FAILURE(rv)) { 1354 return (rv); 1355 } 1356 if (! 1357 (BCM_FIELD_DATA_QUALIFIER_OFFSET_FLEX_HASH == 1358 data_qual.flags) || 1359 !(data_qual.hw_bmap & (0xf << chunk_base))) { 1360 return BCM_E_FAIL; 1361 } 1362 1363 for (chunk_id = chunk_base; chunk_id <= chunk_max; chunk_id++) { 1364 if (data_qual.hw_bmap & (0x1 << chunk_id)) { 1365 idx = chunk_id - chunk_base; 1366 hash_entry->match_arr[idx].qual_id = qual_array[id]; 1367 hash_entry->match_arr[idx].qual_size = data_qual.length; 1368 break; 1369 } 1370 } 1371 } 1372 1373 return BCM_E_NONE; 1374 } 1375 1376 #if 0 /* Code required for warmboot when implemented */ 1377 STATIC int 1378 _bcm_hash_entry_qual_get(int unit, bcm_hash_entry_t entry_id, 1379 int *qual_array, int *qual_count) 1380 { 1381 int id = 0; 1382 int rv = BCM_E_NONE; 1383 flex_hash_entry_t *hash_entry; 1384 bcm_field_data_qualifier_t data_qual; 1385 1386 *qual_count = 0; 1387 rv = _flex_hash_entry_get(unit, entry_id, &hash_entry); 1388 if (BCM_FAILURE(rv)) { 1389 return rv; 1390 } 1391 1392 for (id = 0; id < FLEX_HASH_MAX_FIELDS; id++) { 1393 if (bcm_esw_field_data_qualifier_get(unit, 1394 hash_entry->match_arr[id]. 1395 qual_id, &data_qual)) { 1396 qual_array[id] = hash_entry->match_arr[id].qual_id; 1397 *qual_count += 1; 1398 return BCM_E_NONE; 1399 } 1400 } 1401 return BCM_E_NOT_FOUND; 1402 } 1403 #endif 1404 1405 STATIC int 1406 _bcm_hash_entry_qual_data_set(int unit, bcm_hash_entry_t entry_id, int qual_id, 1407 uint32 data, uint32 mask) 1408 { 1409 int id = 0; 1410 int rv = BCM_E_NONE; 1411 flex_hash_entry_t *hash_entry; 1412 1413 rv = _flex_hash_entry_get(unit, entry_id, &hash_entry); 1414 if (BCM_FAILURE(rv)) { 1415 return rv; 1416 } 1417 1418 for (id = 0; id < FLEX_HASH_MAX_FIELDS; id++) { 1419 if (hash_entry->match_arr[id].qual_id == qual_id) { 1420 hash_entry->match_arr[id].qual_match = data; 1421 hash_entry->match_arr[id].qual_mask = mask; 1422 1423 return BCM_E_NONE; 1424 } 1425 } 1426 return BCM_E_NOT_FOUND; 1427 } 1428 1429 #if 0 /* Code required for warmboot when implemented */ 1430 STATIC int 1431 _bcm_hash_entry_qual_data_get(int unit, bcm_hash_entry_t entry_id, int qual_id, 1432 uint32 * data, uint32 * mask) 1433 { 1434 int id = 0; 1435 int rv = BCM_E_NONE; 1436 flex_hash_entry_t *hash_entry; 1437 1438 rv = _flex_hash_entry_get(unit, entry_id, &hash_entry); 1439 if (BCM_FAILURE(rv)) { 1440 return rv; 1441 } 1442 1443 for (id = 0; id < FLEX_HASH_MAX_FIELDS; id++) { 1444 if (hash_entry->match_arr[id].qual_id == qual_id) { 1445 *data = hash_entry->match_arr[id].qual_match; 1446 *mask = hash_entry->match_arr[id].qual_mask; 1447 } 1448 } 1449 1450 if (FLEX_HASH_MAX_FIELDS == id) { 1451 return BCM_E_NOT_FOUND; 1452 } 1453 1454 return BCM_E_NONE; 1455 } 1456 #endif 1457 1458 #if defined (BCM_WARM_BOOT_SUPPORT) 1459 int 1460 bcmi_td2_switch_wb_hash_entry_reinit(int unit, uint8 **scache_ptr) 1461 { 1462 int rv; 1463 int i; 1464 int num_hash_entry; 1465 int hw_index; 1466 int wb_last_hash_entry_id; 1467 bcmi_xgs4_td2_switch_wb_hash_entry_t *hash_entry_scache_p; 1468 uint32 *u32_scache_p; 1469 flex_hash_entry_p hash_entry = NULL; 1470 BCM_IF_ERROR_RETURN(bcm_td2_switch_hash_entry_init(unit)); 1471 1472 u32_scache_p = (uint32 *)(*scache_ptr); 1473 1474 /* Number of UDFs created */ 1475 num_hash_entry = *u32_scache_p; 1476 u32_scache_p++; 1477 1478 _bcm_td2_switch_hash_bk_info[unit].api_ver = *u32_scache_p; 1479 u32_scache_p++; 1480 1481 wb_last_hash_entry_id = *u32_scache_p; 1482 u32_scache_p++; 1483 1484 hash_entry_scache_p = 1485 (bcmi_xgs4_td2_switch_wb_hash_entry_t *)u32_scache_p; 1486 1487 for (i = 0; i < num_hash_entry; i++) { 1488 hw_index = hash_entry_scache_p->hw_idx; 1489 1490 rv = _flex_hash_entry_alloc(unit, &hash_entry); 1491 if (BCM_FAILURE(rv)) { 1492 return rv; 1493 } 1494 hash_entry->entry_id = hash_entry_scache_p->entry_id; 1495 hash_entry->hw_idx = hash_entry_scache_p->hw_idx; 1496 hash_entry->offset_bitmap = hash_entry_scache_p->offset_bitmap; 1497 _bcm_flex_hash_table_wb_read(unit, hash_entry, hash_entry_scache_p); 1498 1499 _BCM_SWITCH_FLEX_IDX_USED_SET(unit, hw_index); 1500 1501 rv = _flex_hash_entry_add(unit, hash_entry, hw_index); 1502 if (BCM_FAILURE(rv)) { 1503 _flex_hash_entry_destroy(unit, hash_entry); 1504 return rv; 1505 } 1506 1507 hash_entry_scache_p++; 1508 } 1509 SWITCH_HASH_LAST_ENTRY_ID(unit) = wb_last_hash_entry_id; 1510 *scache_ptr = (uint8 *)hash_entry_scache_p; 1511 1512 return BCM_E_NONE; 1513 } 1514 #if defined(BCM_TOMAHAWK_SUPPORT) 1515 int 1516 bcmi_th_switch_wb_hash_entry_reinit(int unit, uint8 **scache_ptr) 1517 { 1518 flex_hash_entry_t *hash_entry = NULL; 1519 int fld; 1520 bcm_udf_id_t *udf_id_p = NULL; 1521 1522 hash_entry = SWITCH_HASH_ENTRY_LIST(unit); 1523 udf_id_p = (bcm_udf_id_t *)(*scache_ptr); 1524 1525 while (hash_entry != NULL) { 1526 for (fld = 0; fld < FLEX_HASH_MAX_OFFSET; fld++) { 1527 hash_entry->udf_id[fld] = *udf_id_p; 1528 udf_id_p++; 1529 } 1530 hash_entry = hash_entry->next; 1531 } 1532 1533 return BCM_E_NONE; 1534 } 1535 #endif /*BCM_TOMAHAWK_SUPPORT*/ 1536 1537 1538 STATIC int 1539 _flex_hash_entry_num(int unit) 1540 { 1541 int num_hash_entry = 0; 1542 1543 flex_hash_entry_t *hash_entry = SWITCH_HASH_ENTRY_LIST(unit); 1544 1545 while (hash_entry != NULL) { 1546 hash_entry = hash_entry->next; 1547 num_hash_entry++; 1548 } 1549 return num_hash_entry; 1550 } 1551 1552 1553 int 1554 bcmi_td2_switch_wb_hash_entry_sync(int unit, uint8 **scache_ptr) 1555 { 1556 int fld; 1557 bcmi_xgs4_td2_switch_wb_hash_entry_t *hash_entry_scache_p; 1558 uint32 *u32_scache_p; 1559 flex_hash_entry_p hash_entry = NULL; 1560 int num_hash_entry = 0; 1561 #if defined(BCM_TOMAHAWK_SUPPORT) 1562 bcm_udf_id_t *udf_id_p = NULL; 1563 #endif 1564 1565 num_hash_entry = _flex_hash_entry_num(unit); 1566 hash_entry = SWITCH_HASH_ENTRY_LIST(unit); 1567 1568 u32_scache_p = (uint32 *)(*scache_ptr); 1569 1570 /* Number of hash entry created */ 1571 *u32_scache_p = num_hash_entry; 1572 u32_scache_p++; 1573 1574 *u32_scache_p = _bcm_td2_switch_hash_bk_info[unit].api_ver; 1575 u32_scache_p++; 1576 1577 *u32_scache_p = SWITCH_HASH_LAST_ENTRY_ID(unit); 1578 u32_scache_p++; 1579 1580 hash_entry_scache_p = 1581 (bcmi_xgs4_td2_switch_wb_hash_entry_t *)u32_scache_p; 1582 1583 while (hash_entry != NULL) { 1584 hash_entry_scache_p->entry_id = hash_entry->entry_id; 1585 hash_entry_scache_p->hw_idx = hash_entry->hw_idx; 1586 hash_entry_scache_p->offset_bitmap = hash_entry->offset_bitmap; 1587 for (fld = 0; fld < FLEX_HASH_MAX_FIELDS; fld++) { 1588 hash_entry_scache_p->match_arr[fld].qual_id= hash_entry->match_arr[fld].qual_id; 1589 hash_entry_scache_p->match_arr[fld].qual_size= hash_entry->match_arr[fld].qual_size; 1590 } 1591 hash_entry_scache_p++; 1592 1593 hash_entry = hash_entry->next; 1594 } 1595 *scache_ptr = (uint8 *)u32_scache_p; 1596 1597 #if defined(BCM_TOMAHAWK_SUPPORT) 1598 if (SOC_IS_TOMAHAWKX(unit)) { 1599 udf_id_p = (bcm_udf_id_t *)hash_entry_scache_p; 1600 hash_entry = SWITCH_HASH_ENTRY_LIST(unit); 1601 while (hash_entry != NULL) { 1602 for (fld = 0; fld < FLEX_HASH_MAX_OFFSET; fld++) { 1603 *udf_id_p = hash_entry->udf_id[fld]; 1604 udf_id_p++; 1605 } 1606 hash_entry = hash_entry->next; 1607 } 1608 /* overwrite scache_ptr*/ 1609 *scache_ptr = (uint8 *)udf_id_p; 1610 } 1611 #endif /*BCM_TOMAHAWK_SUPPORT*/ 1612 1613 return BCM_E_NONE; 1614 } 1615 1616 /* If this size be changed, please don't forget to change udf wb version simultaneously */ 1617 int 1618 bcmi_td2_switch_wb_hash_entry_scache_size_get(int unit, int *req_scache_size) 1619 { 1620 int alloc_size = 0; 1621 int hash_entries = 0; 1622 1623 alloc_size += sizeof(hash_entries); 1624 alloc_size += sizeof(_bcm_td2_switch_hash_bk_info[unit].api_ver); 1625 alloc_size += sizeof(SWITCH_HASH_LAST_ENTRY_ID(unit)); 1626 /* Number of hash entries*/ 1627 if (SOC_IS_TRIDENT3X(unit)) { 1628 /* TD3TBD */ 1629 hash_entries = 128; 1630 } else { 1631 hash_entries = soc_mem_index_count(unit, FLEX_HASH_TCAM); 1632 } 1633 1634 alloc_size += (hash_entries * 1635 sizeof(bcmi_xgs4_td2_switch_wb_hash_entry_t)); 1636 1637 #if defined(BCM_TOMAHAWK_SUPPORT) 1638 if (SOC_IS_TOMAHAWKX(unit)) { 1639 alloc_size += sizeof(bcm_udf_id_t) * hash_entries * FLEX_HASH_MAX_OFFSET; 1640 } 1641 #endif /*BCM_TOMAHAWK_SUPPORT*/ 1642 1643 *req_scache_size += alloc_size; 1644 1645 return BCM_E_NONE; 1646 } 1647 #endif 1648 1649 /* 1650 * 1651 * Flexible hash Switch API support routines 1652 */ 1653 int 1654 bcm_td2_switch_hash_entry_detach(int unit) 1655 { 1656 1657 if (SWITCH_HASH_ENTRY_LIST(unit)) { 1658 _flex_hash_entry_destroy_all(unit); 1659 } 1660 1661 if (SWITCH_HASH_IDX_BITMAP(unit)) { 1662 sal_free(SWITCH_HASH_IDX_BITMAP(unit)); 1663 SWITCH_HASH_IDX_BITMAP(unit) = NULL; 1664 } 1665 1666 SWITCH_HASH_INIT(unit) = FALSE; 1667 1668 return BCM_E_NONE; 1669 } 1670 1671 int 1672 bcm_td2_switch_hash_entry_init(int unit) 1673 { 1674 int hash_entries; 1675 1676 if (SWITCH_HASH_INIT(unit) == TRUE ) { 1677 bcm_td2_switch_hash_entry_detach(unit); 1678 } 1679 1680 if (SWITCH_HASH_IDX_BITMAP(unit)) { 1681 1682 } 1683 /* Initialize bookeeping */ 1684 sal_memset(SWITCH_HASH_INFO(unit), 0, sizeof(*SWITCH_HASH_INFO(unit))); 1685 1686 /* Initialize the hash entry list */ 1687 SWITCH_HASH_ENTRY_LIST(unit) = NULL; 1688 1689 if (SOC_IS_TRIDENT3X(unit)) { 1690 /* Flex Hashing is not supported for TD3X */ 1691 hash_entries = 0; 1692 } else { 1693 hash_entries = soc_mem_index_count(unit, FLEX_HASH_TCAM); 1694 } 1695 1696 SWITCH_HASH_IDX_BITMAP(unit) = sal_alloc(SHR_BITALLOCSIZE(hash_entries), 1697 "hash index bitmap"); 1698 if (NULL == SWITCH_HASH_IDX_BITMAP(unit)) { 1699 bcm_td2_switch_hash_entry_detach(unit); 1700 return BCM_E_FAIL; 1701 } 1702 sal_memset(SWITCH_HASH_IDX_BITMAP(unit), 0, SHR_BITALLOCSIZE(hash_entries)); 1703 1704 SWITCH_HASH_INIT(unit) = TRUE; 1705 1706 return BCM_E_NONE; 1707 } 1708 1709 1710 /* 1711 * Function: 1712 * bcm_td2_switch_hash_entry_create 1713 * Purpose: 1714 * Create a blank flex hash entry. 1715 * Parameters: 1716 * unit - (IN) bcm device 1717 * group - (IN) BCM field group 1718 * *entry - (OUT) BCM hash entry 1719 * 1720 * Returns: 1721 * BCM_E_NONE - Success 1722 * BCM_E_XXX 1723 * Notes: 1724 */ 1725 int 1726 bcm_td2_switch_hash_entry_create(int unit, 1727 bcm_field_group_t group, 1728 bcm_hash_entry_t * entry_id) 1729 { 1730 int rv = BCM_E_NONE; 1731 bcm_field_qset_t qset; 1732 int qual_array[FLEX_HASH_MAX_FIELDS]; 1733 int qual_count; 1734 1735 1736 /* Validate unit, group of qualifier Ids */ 1737 if (!SOC_UNIT_VALID(unit)) { 1738 return BCM_E_UNIT; 1739 } 1740 1741 rv = bcm_esw_field_group_get(unit, group, &qset); 1742 if (BCM_FAILURE(rv)) { 1743 return BCM_E_BADID; 1744 } 1745 1746 /* Either this API or the create_qset should be used 1747 * Users should not intermix the APIs. 1748 */ 1749 if (SWITCH_HASH_INFO(unit)->api_ver == 0) { 1750 SWITCH_HASH_INFO(unit)->api_ver = 1; 1751 } else if (SWITCH_HASH_INFO(unit)->api_ver == 2) { 1752 return BCM_E_CONFIG; 1753 } 1754 1755 /* 1756 * Check for the required qualifier fields, the assumption is qual_array 1757 * has the same sequence of offsets from UDF2.4 .. UDF2.7 for flex hash 1758 */ 1759 rv = bcm_esw_field_qset_data_qualifier_get(unit, qset, 1760 FLEX_HASH_MAX_FIELDS, 1761 qual_array, &qual_count); 1762 if (BCM_FAILURE(rv)) { 1763 return BCM_E_FAIL; 1764 } 1765 1766 if (0 == qual_count) { 1767 return BCM_E_FAIL; 1768 } 1769 1770 /* Create flexible hash entry */ 1771 /* Get free index from the flex hash tcam */ 1772 BCM_IF_ERROR_RETURN(_bcm_hash_entry_create(unit, entry_id)); 1773 1774 /* Add qualifier ids in the hash entry */ 1775 BCM_IF_ERROR_RETURN(_bcm_hash_entry_qual_set 1776 (unit, *entry_id, qual_count, qual_array)); 1777 return rv; 1778 } 1779 1780 /* 1781 * Function: 1782 * bcm_td2_switch_hash_entry_create_qset 1783 * Purpose: 1784 * Create a blank flex hash entry. 1785 * Parameters: 1786 * unit - (IN) bcm device 1787 * qset - (IN) Qset 1788 * *entry - (OUT) BCM hash entry 1789 * 1790 * Returns: 1791 * BCM_E_NONE - Success 1792 * BCM_E_XXX 1793 * Notes: 1794 */ 1795 int 1796 bcm_td2_switch_hash_entry_create_qset(int unit, 1797 bcm_field_qset_t qset, 1798 bcm_hash_entry_t * entry_id) 1799 { 1800 int rv = BCM_E_NONE; 1801 int qual_array[FLEX_HASH_MAX_FIELDS]; 1802 int qual_count; 1803 1804 /* Either this API or the create_qset should be used 1805 * Users should not intermix the APIs. 1806 */ 1807 if (SWITCH_HASH_INFO(unit)->api_ver == 0) { 1808 SWITCH_HASH_INFO(unit)->api_ver = 2; 1809 } else if (SWITCH_HASH_INFO(unit)->api_ver == 1) { 1810 return BCM_E_CONFIG; 1811 } 1812 1813 /* 1814 * Check for the required qualifier fields, the assumption is qual_array 1815 * has the same sequence of offsets from UDF2.4 .. UDF2.7 for flex hash 1816 */ 1817 rv = bcm_esw_field_qset_id_multi_get(unit, qset, bcmFieldQualifyUdf, 1818 FLEX_HASH_MAX_FIELDS, 1819 qual_array, &qual_count); 1820 BCM_IF_ERROR_RETURN(rv); 1821 1822 if (0 == qual_count) { 1823 return BCM_E_PARAM; 1824 } 1825 1826 /* Create flexible hash entry */ 1827 /* Get free index from the flex hash tcam */ 1828 BCM_IF_ERROR_RETURN(_bcm_hash_entry_create(unit, entry_id)); 1829 1830 /* Add qualifier ids in the hash entry */ 1831 BCM_IF_ERROR_RETURN(_bcm_hash_entry_udf_set 1832 (unit, *entry_id, qual_count, qual_array)); 1833 1834 return rv; 1835 } 1836 1837 1838 /* 1839 * Function: 1840 * bcm_td2_switch_hash_entry_destroy 1841 * Purpose: 1842 * Destroy a flex hash entry. 1843 * Parameters: 1844 * unit - (IN) bcm device 1845 * entry_id - (IN) BCM hash entry 1846 * 1847 * Returns: 1848 * BCM_E_NONE - Success 1849 * BCM_E_XXX 1850 * Notes: 1851 */ 1852 int 1853 bcm_td2_switch_hash_entry_destroy(int unit, bcm_hash_entry_t entry_id) 1854 { 1855 1856 return _bcm_hash_entry_delete(unit, entry_id); 1857 } 1858 1859 /* 1860 * Function: 1861 * bcm_td2_switch_hash_entry_set 1862 * Purpose: 1863 * Set a flex hash entry configuration information. 1864 * Parameters: 1865 * unit - (IN) BCM device 1866 * entry - (IN) BCM hash entry 1867 * config - (IN) BCM hash configure information 1868 * 1869 * Returns: 1870 * BCM_E_NONE - Success 1871 * BCM_E_XXX 1872 * Notes: 1873 */ 1874 int 1875 bcm_td2_switch_hash_entry_set(int unit, 1876 bcm_hash_entry_t entry, 1877 bcm_switch_hash_entry_config_t *config) 1878 { 1879 int mask_bit_max; 1880 uint32 mask; 1881 #ifdef LE_HOST 1882 uint32 mask_swap; 1883 #endif /* LE_HOST */ 1884 flex_hash_entry_t *hash_entry; 1885 uint8 *p; 1886 #if defined(BCM_TOMAHAWK_SUPPORT) 1887 bcmi_xgs4_udf_offset_info_t *offset_info = NULL; 1888 int i, gran, pos, chunk_pos = 0; 1889 #endif 1890 1891 if (config == NULL) { 1892 return BCM_E_PARAM; 1893 } 1894 1895 BCM_IF_ERROR_RETURN( 1896 _flex_hash_entry_get(unit, entry, &hash_entry)); 1897 1898 #ifdef BCM_TOMAHAWK2_SUPPORT 1899 if ((SOC_IS_TOMAHAWK2(unit)) || (SOC_IS_TOMAHAWK3(unit))) { 1900 /* In TH2 bcmSwitchFlexHashField2~12 only support udf type. */ 1901 if ((config->field >= bcmSwitchFlexHashFieldCount) || 1902 ((config->field > bcmSwitchFlexHashField1) && 1903 !(config->flags & BCM_SWITCH_HASH_FIELD_TYPE_UDF))) { 1904 return BCM_E_PARAM; 1905 } 1906 } else 1907 #endif /*BCM_TOMAHAWK2_SUPPORT*/ 1908 { 1909 /* In TH and TD2 only first two fields are supported. */ 1910 if (config->field > bcmSwitchFlexHashField1) { 1911 return BCM_E_PARAM; 1912 } 1913 } 1914 1915 /*Only TH series support UDF type flex Hash*/ 1916 if (!SOC_IS_TOMAHAWKX(unit) && 1917 config->flags & BCM_SWITCH_HASH_FIELD_TYPE_UDF) { 1918 return BCM_E_UNAVAIL; 1919 } 1920 mask_bit_max = soc_mem_field_length(unit, FLEX_HASH_OFFSET_MASK(unit), 1921 _bcm_td2_flex_hash_mask[config->field]); 1922 1923 if (config->mask_length > BITS2BYTES(mask_bit_max) 1924 || config->mask_length > sizeof(mask)) { 1925 return BCM_E_PARAM; 1926 } 1927 1928 mask = 0; 1929 if (config->mask_length) { 1930 p = (uint8 *)&mask; 1931 p += sizeof(mask) - config->mask_length; 1932 sal_memcpy(p, config->mask, config->mask_length); 1933 } 1934 1935 #ifdef LE_HOST 1936 mask_swap = _shr_swap32(mask); 1937 mask = mask_swap; 1938 #endif /* LE_HOST */ 1939 1940 #if defined(BCM_TOMAHAWK_SUPPORT) 1941 /*Extract udf chunk id from udf_id*/ 1942 if (config->flags & BCM_SWITCH_HASH_FIELD_TYPE_UDF) { 1943 if ((config->udf_id < BCMI_XGS4_UDF_ID_MIN) || 1944 (config->udf_id > BCMI_XGS4_UDF_ID_MAX)) { 1945 return BCM_E_PARAM; 1946 } 1947 hash_entry->type[config->field] |= BCM_SWITCH_HASH_FIELD_TYPE_UDF; 1948 hash_entry->udf_id[config->field] = config->udf_id; 1949 gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit); 1950 BCM_IF_ERROR_RETURN 1951 (bcmi_xgs4_udf_offset_node_get(unit, config->udf_id, &offset_info)); 1952 /*Sanity check, the offset should start at even boundary of a packet */ 1953 if ((offset_info->width < config->offset / 8 + gran) || 1954 (offset_info->start + config->offset / 8) % gran) { 1955 return BCM_E_PARAM; 1956 } 1957 /*get the chunk id which the offset points to*/ 1958 chunk_pos = 0; 1959 pos = offset_info->start % gran + (config->offset / 8) / gran; 1960 for (i = 0, chunk_pos = 0; i < MAX_UDF_OFFSET_CHUNKS; i++) { 1961 if (offset_info->hw_bmap & (1 << i)) { 1962 if (chunk_pos == pos) { 1963 break; 1964 } 1965 chunk_pos++; 1966 } 1967 } 1968 hash_entry->hash_offset[config->field] = i; 1969 } else 1970 #endif 1971 { 1972 hash_entry->hash_offset[config->field] = config->offset & 0xf; 1973 } 1974 hash_entry->hash_mask[config->field] = (int)mask; 1975 if (mask) { 1976 hash_entry->offset_bitmap |= (0x1 << config->field); 1977 } else { 1978 hash_entry->offset_bitmap &= ~(0x1 << config->field); 1979 } 1980 hash_entry->offset_count = _shr_popcount(hash_entry->offset_bitmap); 1981 1982 return BCM_E_NONE; 1983 } 1984 1985 /* 1986 * Function: 1987 * bcm_td2_switch_hash_entry_get 1988 * Purpose: 1989 * Get a flex hash entry configure information. 1990 * Parameters: 1991 * unit - (IN) BCM device 1992 * entry - (IN) BCM hash entry 1993 * config - (IN/OUT) BCM hash configure information 1994 * 1995 * Returns: 1996 * BCM_E_NONE - Success 1997 * BCM_E_XXX 1998 * Notes: 1999 */ 2000 int 2001 bcm_td2_switch_hash_entry_get(int unit, 2002 bcm_hash_entry_t entry, 2003 bcm_switch_hash_entry_config_t *config) 2004 { 2005 int i, mask_len; 2006 uint32 mask; 2007 #ifdef LE_HOST 2008 uint32 mask_swap; 2009 #endif /* LE_HOST */ 2010 flex_hash_entry_t *hash_entry; 2011 #if defined(BCM_TOMAHAWK_SUPPORT) 2012 int gran, position = 0; 2013 bcmi_xgs4_udf_offset_info_t *offset_info = NULL; 2014 #endif /*BCM_TOMAHAWK_SUPPORT*/ 2015 2016 if (config == NULL) { 2017 return BCM_E_PARAM; 2018 } 2019 2020 BCM_IF_ERROR_RETURN( 2021 _flex_hash_entry_get(unit, entry, &hash_entry)); 2022 2023 #if defined(BCM_TOMAHAWK2_SUPPORT) 2024 if ((SOC_IS_TOMAHAWK2(unit)) || (SOC_IS_TOMAHAWK3(unit))) { 2025 if (config->field >= bcmSwitchFlexHashFieldCount) { 2026 return BCM_E_PARAM; 2027 } 2028 } else 2029 #endif 2030 { 2031 if (config->field > bcmSwitchFlexHashField1) { 2032 return BCM_E_PARAM; 2033 } 2034 } 2035 2036 mask_len = 0; 2037 mask = (uint32)hash_entry->hash_mask[config->field]; 2038 for (i = 0; i < sizeof(mask); i++) { 2039 if (mask & 0xff000000) { 2040 mask_len = sizeof(mask) - i; 2041 break; 2042 } 2043 mask <<= 8; 2044 } 2045 2046 if (mask_len == 0) { 2047 return BCM_E_NOT_FOUND; 2048 } 2049 2050 #ifdef LE_HOST 2051 mask_swap = _shr_swap32(mask); 2052 mask = mask_swap; 2053 #endif /* LE_HOST */ 2054 2055 #if defined(BCM_TOMAHAWK_SUPPORT) 2056 /*Extract udf chunk id from udf_id*/ 2057 if (hash_entry->type[config->field] & BCM_SWITCH_HASH_FIELD_TYPE_UDF) { 2058 config->udf_id = hash_entry->udf_id[config->field]; 2059 gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit); 2060 BCM_IF_ERROR_RETURN 2061 (bcmi_xgs4_udf_offset_node_get(unit, config->udf_id, &offset_info)); 2062 position = 0; 2063 for (i = 0; i < hash_entry->hash_offset[config->field]; i++) { 2064 if (SHR_BITGET(&(offset_info->hw_bmap), i)) { 2065 position++; 2066 } 2067 } 2068 /* offset gran is in bit, not byte. */ 2069 config->offset = (position * gran - offset_info->start % gran) * 8; 2070 } else 2071 2072 #endif 2073 { 2074 config->offset = hash_entry->hash_offset[config->field]; 2075 } 2076 config->flags = hash_entry->type[config->field]; 2077 config->mask_length = mask_len; 2078 if (config->mask_length > 0) { 2079 sal_memcpy(config->mask, &mask, mask_len); 2080 } 2081 2082 return BCM_E_NONE; 2083 } 2084 2085 /* 2086 * Function: 2087 * bcm_td2_switch_hash_entry_traverse 2088 * Purpose: 2089 * Traverse flex hash entry tables. 2090 * Parameters: 2091 * unit - (IN) BCM device 2092 * cb_fn - (IN) BCM traverse call back function 2093 * user_data - (IN) BCM user data 2094 * 2095 * Returns: 2096 * BCM_E_NONE - Success 2097 * BCM_E_XXX 2098 * Notes: 2099 */ 2100 int 2101 bcm_td2_switch_hash_entry_traverse(int unit, int flags, 2102 bcm_switch_hash_entry_traverse_cb cb_fn, 2103 void *user_data) 2104 { 2105 int rv; 2106 flex_hash_entry_t *hash_entry = SWITCH_HASH_ENTRY_LIST(unit); 2107 2108 if (cb_fn == NULL) { 2109 return BCM_E_PARAM; 2110 } 2111 2112 while (hash_entry != NULL) { 2113 rv = cb_fn(unit, flags, hash_entry->entry_id, user_data); 2114 if (BCM_FAILURE(rv)) { 2115 return rv; 2116 } 2117 hash_entry = hash_entry->next; 2118 } 2119 2120 return BCM_E_NONE; 2121 } 2122 2123 /* 2124 * Function: 2125 * bcm_td2_switch_hash_entry_install 2126 * Purpose: 2127 * Install a flex hash entry into hardware tables. 2128 * Parameters: 2129 * unit - (IN) bcm device 2130 * entry - (IN) BCM hash entry 2131 * 2132 * Returns: 2133 * BCM_E_NONE - Success 2134 * BCM_E_XXX 2135 * Notes: 2136 */ 2137 int 2138 bcm_td2_switch_hash_entry_install(int unit, bcm_hash_entry_t entry_id, 2139 uint32 offset, uint32 mask) 2140 { 2141 int rv = BCM_E_NONE; 2142 flex_hash_entry_t *hash_entry; 2143 2144 rv = _flex_hash_entry_get(unit, entry_id, &hash_entry); 2145 if (BCM_FAILURE(rv)) { 2146 return rv; 2147 } 2148 2149 if (offset != BCM_SWITCH_HASH_USE_CONFIG) { 2150 if (++hash_entry->offset_count > FLEX_HASH_OFFSET_NUM(unit)) { 2151 return BCM_E_RESOURCE; 2152 } 2153 hash_entry->hash_offset[hash_entry->offset_count - 1] = offset & 0xf; 2154 hash_entry->hash_mask[hash_entry->offset_count - 1] = mask & 0xffff; 2155 hash_entry->offset_bitmap |= 0x1 << (hash_entry->offset_count - 1); 2156 } 2157 2158 #ifdef BCM_TOMAHAWK2_SUPPORT 2159 if ((SOC_IS_TOMAHAWK2(unit)) || (SOC_IS_TOMAHAWK3(unit))) { 2160 rv = _bcm_th2_flex_hash_table_write(unit, hash_entry, FALSE); 2161 } else 2162 #endif 2163 { 2164 rv = _bcm_flex_hash_table_write(unit, hash_entry, FALSE); 2165 } 2166 2167 if (BCM_FAILURE(rv)) { 2168 return rv; 2169 } 2170 2171 return rv; 2172 } 2173 2174 /* 2175 * Function: 2176 * bcm_td2_switch_hash_entry_reinstall 2177 * Purpose: 2178 * Re-install a flex hash entry into hardware tables. 2179 * Parameters: 2180 * unit - (IN) bcm device 2181 * entry - (IN) BCM hash entry 2182 * offset - (IN) BCM hash offset 2183 * 2184 * Returns: 2185 * BCM_E_NONE - Success 2186 * BCM_E_XXX 2187 * Notes: 2188 */ 2189 int 2190 bcm_td2_switch_hash_entry_reinstall(int unit, 2191 bcm_hash_entry_t entry_id, uint32 offset, uint32 mask) 2192 { 2193 int cnt, rv = BCM_E_NONE, reinstall; 2194 flex_hash_entry_t *hash_entry; 2195 2196 if (offset != BCM_SWITCH_HASH_USE_CONFIG) { 2197 rv = _flex_hash_entry_get(unit, entry_id, &hash_entry); 2198 if (BCM_FAILURE(rv)) { 2199 return rv; 2200 } 2201 2202 reinstall = 1; 2203 for (cnt = 0; cnt < FLEX_HASH_OFFSET_NUM(unit); cnt++) { 2204 if (hash_entry->hash_offset[cnt] == -1) { 2205 reinstall = 0; 2206 } 2207 } 2208 if ((reinstall == 1) && (cnt == FLEX_HASH_OFFSET_NUM(unit))) { 2209 for (cnt = 0; cnt < FLEX_HASH_OFFSET_NUM(unit); cnt++) { 2210 hash_entry->hash_offset[cnt] = -1; 2211 hash_entry->offset_count = 0; 2212 hash_entry->offset_bitmap = 0; 2213 } 2214 } 2215 } 2216 2217 return bcm_td2_switch_hash_entry_install(unit, entry_id, offset, mask); 2218 } 2219 2220 /* 2221 * Function: 2222 * bcm_td2_switch_hash_entry_remove 2223 * Purpose: 2224 * Remove a flex hash entry from hardware tables. 2225 * Parameters: 2226 * unit - (IN) bcm device 2227 * entry - (IN) BCM hash entry 2228 * 2229 * Returns: 2230 * BCM_E_NONE - Success 2231 * BCM_E_XXX 2232 * Notes: 2233 */ 2234 int 2235 bcm_td2_switch_hash_entry_remove(int unit, bcm_hash_entry_t entry_id) 2236 { 2237 return _bcm_hash_entry_remove(unit, entry_id);; 2238 } 2239 2240 /* 2241 * Function: 2242 * bcm_td2_switch_hash_qualify_data 2243 * Purpose: 2244 * Add flex hash field qualifiers into hardware tables. 2245 * Parameters: 2246 * unit - (IN) bcm device 2247 * entry - (IN) BCM hash entry 2248 * qual_id - (IN) BCM qualifier id 2249 * data - (IN) BCM hash field qualifier 2250 * mask - (IN) BCM hash field mask 2251 * Returns: 2252 * BCM_E_NONE - Success 2253 * BCM_E_XXX 2254 * Notes: 2255 */ 2256 2257 int 2258 bcm_td2_switch_hash_qualify_data(int unit, bcm_hash_entry_t entry_id, 2259 int qual_id, uint32 data, uint32 mask) 2260 { 2261 int rv = BCM_E_NONE; 2262 2263 rv = _bcm_hash_entry_qual_data_set(unit, entry_id, qual_id, data, mask); 2264 if (BCM_FAILURE(rv)) { 2265 return rv; 2266 } 2267 2268 return rv; 2269 } 2270 2271 /* 2272 * Function: 2273 * bcm_td2_switch_hash_qualify_udf 2274 * Purpose: 2275 * Add flex hash udf qualifiers into hardware tables. 2276 * Parameters: 2277 * unit - (IN) bcm device 2278 * entry - (IN) BCM hash entry 2279 * udf_id - (IN) BCM qualifier id 2280 * length - (IN) BCM qualifier id 2281 * data - (IN) BCM hash field qualifier 2282 * mask - (IN) BCM hash field mask 2283 * Returns: 2284 * BCM_E_NONE - Success 2285 * BCM_E_XXX 2286 * Notes: 2287 */ 2288 int 2289 bcm_td2_switch_hash_qualify_udf(int unit, 2290 bcm_hash_entry_t entry, 2291 bcm_udf_id_t udf_id, 2292 int length, 2293 uint8 *data, uint8 *mask) 2294 { 2295 int i, idx, len; 2296 int id, chunk_base, chunk_size, chunk_cnt; 2297 flex_hash_entry_t *hash_entry; 2298 bcmi_xgs4_udf_offset_info_t *offset_info; 2299 uint8 *p; 2300 uint32 qual_match, qual_mask; 2301 #ifdef LE_HOST 2302 uint32 qual_match_swap, qual_mask_swap; 2303 #endif /* LE_HOST */ 2304 2305 if (data == NULL || mask == NULL) { 2306 return BCM_E_PARAM; 2307 } 2308 BCM_IF_ERROR_RETURN( 2309 _flex_hash_entry_get(unit, entry, &hash_entry)); 2310 chunk_base = 12; /* UDF2.4 */ 2311 chunk_size = 2; 2312 /* Get data qualifier info. */ 2313 BCM_IF_ERROR_RETURN( 2314 bcmi_xgs4_udf_offset_node_get(unit, udf_id, &offset_info)); 2315 2316 if (!(offset_info->flags & BCMI_XGS4_UDF_OFFSET_FLEXHASH) || 2317 !(offset_info->hw_bmap & (0xf << chunk_base)) || 2318 !(offset_info->width > 0)) { 2319 return BCM_E_PARAM; 2320 } 2321 if (length > offset_info->width) { 2322 return BCM_E_PARAM; 2323 } 2324 for (id = 0; id < FLEX_HASH_MAX_FIELDS; id++) { 2325 if (hash_entry->match_arr[id].qual_id == udf_id) { 2326 hash_entry->match_arr[id].qual_size = 0; 2327 break; 2328 } 2329 } 2330 if (id == FLEX_HASH_MAX_FIELDS) { 2331 return BCM_E_PARAM; 2332 } 2333 chunk_cnt = (offset_info->width + chunk_size - 1) / chunk_size; 2334 if ((id + chunk_cnt) > FLEX_HASH_MAX_FIELDS) { 2335 return BCM_E_PARAM; 2336 } 2337 2338 for (i = 0; i < length; i += chunk_size) { 2339 idx = id + i / chunk_size; 2340 len = ((length - i) >= chunk_size) ? chunk_size : (length - i); 2341 qual_match = qual_mask = 0; 2342 2343 p = (uint8 *)&qual_match; 2344 p += sizeof(uint32) - len; 2345 sal_memcpy(p, &data[i], len); 2346 p = (uint8 *)&qual_mask; 2347 p += sizeof(uint32) - len; 2348 sal_memcpy(p, &mask[i], len); 2349 2350 #ifdef LE_HOST 2351 qual_match_swap = _shr_swap32(qual_match); 2352 qual_match = qual_match_swap; 2353 qual_mask_swap = _shr_swap32(qual_mask); 2354 qual_mask = qual_mask_swap; 2355 #endif /* LE_HOST */ 2356 2357 hash_entry->match_arr[idx].qual_match = qual_match; 2358 hash_entry->match_arr[idx].qual_mask = qual_mask; 2359 hash_entry->match_arr[idx].qual_size = len; 2360 } 2361 2362 return BCM_E_NONE; 2363 } 2364 2365 /* 2366 * Function: 2367 * bcm_td2_switch_hash_qualify_udf_get 2368 * Purpose: 2369 * Get flex hash udf qualifiers' length, data and mask. 2370 * Parameters: 2371 * unit - (IN) bcm device 2372 * entry - (IN) BCM hash entry 2373 * udf_id - (IN) BCM qualifier id 2374 * length - (OUT) BCM qualifier id 2375 * data - (OUT) BCM hash field qualifier 2376 * mask - (OUT) BCM hash field mask 2377 * Returns: 2378 * BCM_E_NONE - Success 2379 * BCM_E_XXX 2380 * Notes: 2381 */ 2382 int 2383 bcm_td2_switch_hash_qualify_udf_get(int unit, 2384 bcm_hash_entry_t entry, 2385 bcm_udf_id_t udf_id, 2386 int max_length, 2387 uint8 *data, uint8 *mask, 2388 int *actual_length) 2389 { 2390 int i, idx, len, len_tmp = 0; 2391 int id, chunk_base, chunk_size, chunk_cnt; 2392 flex_hash_entry_t *hash_entry; 2393 bcmi_xgs4_udf_offset_info_t *offset_info; 2394 uint8 *p; 2395 uint32 qual_match, qual_mask; 2396 #ifdef LE_HOST 2397 uint32 qual_match_swap, qual_mask_swap; 2398 #endif /* LE_HOST */ 2399 2400 if (data == NULL || mask == NULL || actual_length == NULL) { 2401 return BCM_E_PARAM; 2402 } 2403 2404 BCM_IF_ERROR_RETURN( 2405 _flex_hash_entry_get(unit, entry, &hash_entry)); 2406 2407 chunk_base = 12; /* UDF2.4 */ 2408 chunk_size = 2; 2409 /* Get data qualifier info. */ 2410 BCM_IF_ERROR_RETURN( 2411 bcmi_xgs4_udf_offset_node_get(unit, udf_id, &offset_info)); 2412 if (!(offset_info->flags & BCMI_XGS4_UDF_OFFSET_FLEXHASH) || 2413 !(offset_info->hw_bmap & (0xf << chunk_base))) { 2414 return BCM_E_PARAM; 2415 } 2416 2417 if (max_length < offset_info->width) { 2418 return BCM_E_PARAM; 2419 } 2420 2421 for (id = 0; id < FLEX_HASH_MAX_FIELDS; id++) { 2422 if (hash_entry->match_arr[id].qual_id == udf_id) { 2423 break; 2424 } 2425 } 2426 if (id >= FLEX_HASH_MAX_FIELDS) { 2427 return BCM_E_NOT_FOUND; 2428 } 2429 2430 chunk_cnt = (offset_info->width + chunk_size - 1) / chunk_size; 2431 if ((id + chunk_cnt) > FLEX_HASH_MAX_FIELDS) { 2432 return BCM_E_INTERNAL; 2433 } 2434 2435 for (i = 0; i < offset_info->width; i += chunk_size) { 2436 idx = id + i / chunk_size; 2437 len = hash_entry->match_arr[idx].qual_size; 2438 if (len) { 2439 qual_match = hash_entry->match_arr[idx].qual_match; 2440 qual_mask = hash_entry->match_arr[idx].qual_mask; 2441 2442 #ifdef LE_HOST 2443 qual_match_swap = _shr_swap32(qual_match); 2444 qual_match = qual_match_swap; 2445 qual_mask_swap = _shr_swap32(qual_mask); 2446 qual_mask = qual_mask_swap; 2447 #endif /* LE_HOST */ 2448 2449 p = (uint8 *)&qual_match; 2450 p += sizeof(uint32) - len; 2451 sal_memcpy(&data[i], p, len); 2452 p = (uint8 *)&qual_mask; 2453 p += sizeof(uint32) - len; 2454 sal_memcpy(&mask[i], p, len); 2455 len_tmp += len; 2456 } 2457 } 2458 2459 *actual_length = len_tmp; 2460 2461 return BCM_E_NONE; 2462 } 2463 2464 /* 2465 * Function: 2466 * _bcm_td2_switch_match_free_resources 2467 * Purpose: 2468 * Free match bookkeeping resources associated with a given unit. This 2469 * happens either during an error initializing or during a detach operation. 2470 * Parameters: 2471 * unit - (IN) Unit number 2472 * Returns: 2473 * BCM_E_XXX 2474 */ 2475 STATIC void 2476 _bcm_td2_switch_match_free_resources(int unit) 2477 { 2478 _bcm_td2_switch_match_bookkeeping_t *match_info = TD2_MATCH_INFO(unit); 2479 int i; 2480 2481 if (match_info->gtp_ptr_array) { 2482 for (i = 0; i < soc_mem_index_count(unit, GTP_PORT_TABLEm); i++) { 2483 if (match_info->gtp_ptr_array[i]) { 2484 sal_free(match_info->gtp_ptr_array[i]); 2485 } 2486 } 2487 sal_free(match_info->gtp_ptr_array); 2488 match_info->gtp_ptr_array = NULL; 2489 } 2490 2491 if (match_info->match_mutex) { 2492 sal_mutex_destroy(match_info->match_mutex); 2493 match_info->match_mutex = NULL; 2494 } 2495 } 2496 2497 /* 2498 * Function: 2499 * bcm_td2_switch_match_detach 2500 * Purpose: 2501 * Detach the TD2 match resource. Called when the module should de-initialize. 2502 * Parameters: 2503 * unit - (IN) Unit being detached. 2504 * Returns: 2505 * BCM_E_XXX 2506 */ 2507 int 2508 bcm_td2_switch_match_detach(int unit) 2509 { 2510 if (_bcm_td2_match_initialized[unit]) { 2511 _bcm_td2_switch_match_free_resources(unit); 2512 _bcm_td2_match_initialized[unit] = 0; 2513 } 2514 2515 return BCM_E_NONE; 2516 } 2517 2518 #ifdef BCM_WARM_BOOT_SUPPORT 2519 2520 /* 2521 * Function: 2522 * _bcmi_td2_gtp_match_reinit 2523 * Purpose: 2524 * Restore GTP match entries 2525 * Parameters: 2526 * unit - (IN) Unit being initialized 2527 * Returns: 2528 * BCM_E_XXX 2529 */ 2530 STATIC int 2531 _bcm_td2_gtp_port_match_reinit(int unit) 2532 { 2533 int hw_id, table_size; 2534 gtp_port_table_entry_t gtp_port_table_entry; 2535 int match_type; 2536 _bcm_td2_gtp_port_match_t *gtp_port_match; 2537 2538 table_size = soc_mem_index_count(unit, GTP_PORT_TABLEm); 2539 2540 for (hw_id = 0; hw_id < table_size; hw_id++) { 2541 sal_memset(>p_port_table_entry, 0, sizeof(gtp_port_table_entry_t)); 2542 BCM_IF_ERROR_RETURN( 2543 soc_mem_read(unit, GTP_PORT_TABLEm, MEM_BLOCK_ANY, 2544 hw_id, >p_port_table_entry)); 2545 2546 match_type = soc_mem_field32_get(unit, GTP_PORT_TABLEm, 2547 >p_port_table_entry, MATCH_ENABLEf); 2548 if (match_type == 0) { 2549 continue; 2550 } 2551 2552 gtp_port_match = sal_alloc(sizeof(_bcm_td2_gtp_port_match_t), 2553 "gtp_port_match"); 2554 if (gtp_port_match == NULL) { 2555 return BCM_E_MEMORY; 2556 } 2557 2558 gtp_port_match->match_criteria = match_type; 2559 gtp_port_match->src_port = soc_mem_field32_get(unit, GTP_PORT_TABLEm, 2560 >p_port_table_entry, 2561 SRC_PORTf); 2562 gtp_port_match->dst_port = soc_mem_field32_get(unit, GTP_PORT_TABLEm, 2563 >p_port_table_entry, 2564 DST_PORTf); 2565 2566 TD2_GTP_PORT_MATCH(unit, hw_id) = gtp_port_match; 2567 } 2568 2569 return BCM_E_NONE; 2570 } 2571 2572 /* 2573 * Function: 2574 * bcm_td2_switch_match_reinit 2575 * Purpose: 2576 * Re-initialize the TD2 match resourse. Restore bookkeeping information. 2577 * Parameters: 2578 * unit - (IN) Unit being initialized 2579 * Returns: 2580 * BCM_E_XXX 2581 */ 2582 STATIC int 2583 _bcm_td2_switch_match_reinit(int unit) 2584 { 2585 BCM_IF_ERROR_RETURN(_bcm_td2_gtp_port_match_reinit(unit)); 2586 2587 return BCM_E_NONE; 2588 } 2589 #endif /* BCM_WARM_BOOT_SUPPORT */ 2590 2591 /* 2592 * Function: 2593 * bcmi_td2_switch_match_init 2594 * Purpose: 2595 * Initialize the TD2 match resourse. Allocate bookkeeping information. 2596 * Parameters: 2597 * unit - (IN) Unit being initialized 2598 * Returns: 2599 * BCM_E_XXX 2600 */ 2601 int 2602 bcm_td2_switch_match_init(int unit) 2603 { 2604 _bcm_td2_switch_match_bookkeeping_t *match_info = TD2_MATCH_INFO(unit); 2605 int gtp_port_table_size; 2606 #ifdef BCM_WARM_BOOT_SUPPORT 2607 int rv; 2608 #endif /* BCM_WARM_BOOT_SUPPORT */ 2609 2610 if (_bcm_td2_match_initialized[unit]) { 2611 BCM_IF_ERROR_RETURN(bcm_td2_switch_match_detach(unit)); 2612 } 2613 2614 sal_memset(match_info, 0, sizeof(_bcm_td2_switch_match_bookkeeping_t)); 2615 gtp_port_table_size = soc_mem_index_count(unit, GTP_PORT_TABLEm); 2616 2617 match_info->gtp_ptr_array = 2618 sal_alloc(sizeof(_bcm_td2_gtp_port_match_t *) * gtp_port_table_size, 2619 "gtp_ptr_array"); 2620 if (match_info->gtp_ptr_array == NULL) { 2621 _bcm_td2_switch_match_free_resources(unit); 2622 return BCM_E_MEMORY; 2623 } 2624 sal_memset(match_info->gtp_ptr_array, 0, 2625 sizeof(_bcm_td2_gtp_port_match_t *) * gtp_port_table_size); 2626 2627 /* Create mutex */ 2628 match_info->match_mutex = sal_mutex_create("match_mutex"); 2629 if (match_info->match_mutex == NULL) { 2630 _bcm_td2_switch_match_free_resources(unit); 2631 return BCM_E_MEMORY; 2632 } 2633 2634 #ifdef BCM_WARM_BOOT_SUPPORT 2635 if (SOC_WARM_BOOT(unit)) { 2636 /* Warm Boot recovery */ 2637 rv = _bcm_td2_switch_match_reinit(unit); 2638 if (BCM_FAILURE(rv)) { 2639 _bcm_td2_switch_match_free_resources(unit); 2640 return rv; 2641 } 2642 } 2643 #endif /* BCM_WARM_BOOT_SUPPORT */ 2644 2645 _bcm_td2_match_initialized[unit] = 1; 2646 2647 return BCM_E_NONE; 2648 } 2649 2650 /* 2651 * Function: 2652 * _bcm_td2_switch_match_id_check 2653 * Purpose: 2654 * Check match_id is valid 2655 * Parameters: 2656 * unit - (IN) Unit number 2657 * match_service - (IN) Match service type 2658 * match_id - (IN) Match ID 2659 * Returns: 2660 * BCM_E_xxx 2661 */ 2662 STATIC int 2663 _bcm_td2_switch_match_id_check( 2664 int unit, 2665 bcm_switch_match_service_t match_service, 2666 int match_id) 2667 { 2668 int match_type, table_size; 2669 uint32 hw_id = TD2_MATCH_HW_ID_GET(match_id); 2670 2671 if (match_service != bcmSwitchMatchServiceGtp) { 2672 return BCM_E_PARAM; 2673 } 2674 table_size = soc_mem_index_count(unit, GTP_PORT_TABLEm); 2675 match_type = TD2_MATCH_TYPE_GET(match_id); 2676 2677 if ((match_type <= BCM_SWITCH_GTP_MATCH_DST_PORT) || 2678 (match_type > BCM_SWITCH_GTP_MATCH_SRC_AND_DST_PORT)) { 2679 return BCM_E_PARAM; 2680 } 2681 2682 if (hw_id >= table_size) { 2683 return BCM_E_PARAM; 2684 } 2685 2686 return BCM_E_NONE; 2687 } 2688 2689 STATIC int 2690 _bcm_td2_gtp_port_match_config_find( 2691 int unit, 2692 bcm_switch_match_service_t match_service, 2693 bcm_switch_match_config_info_t config_info, 2694 int *match_id) 2695 { 2696 int rv = BCM_E_NOT_FOUND; 2697 int i, table_size; 2698 2699 table_size = soc_mem_index_count(unit, GTP_PORT_TABLEm); 2700 2701 for (i = 0; i < table_size; i++) { 2702 if (!TD2_GTP_PORT_MATCH_IS_USED(unit, i)) { 2703 continue; 2704 } 2705 if (config_info.match_criteria != 2706 TD2_GTP_PORT_MATCH(unit, i)->match_criteria) { 2707 continue; 2708 } 2709 switch (config_info.match_criteria) { 2710 case BCM_SWITCH_GTP_MATCH_DST_PORT: 2711 if (config_info.dst_port == 2712 TD2_GTP_PORT_MATCH(unit, i)->dst_port) { 2713 *match_id = TD2_MATCH_ID_SET(i, bcmSwitchMatchServiceGtp); 2714 return BCM_E_NONE; 2715 } 2716 break; 2717 case BCM_SWITCH_GTP_MATCH_SRC_PORT: 2718 if (config_info.src_port == 2719 TD2_GTP_PORT_MATCH(unit, i)->src_port) { 2720 *match_id = TD2_MATCH_ID_SET(i, bcmSwitchMatchServiceGtp); 2721 return BCM_E_NONE; 2722 } 2723 break; 2724 case BCM_SWITCH_GTP_MATCH_SRC_AND_DST_PORT: 2725 case BCM_SWITCH_GTP_MATCH_SRC_OR_DST_PORT: 2726 if ((config_info.dst_port == 2727 TD2_GTP_PORT_MATCH(unit, i)->dst_port) && 2728 (config_info.src_port == 2729 TD2_GTP_PORT_MATCH(unit, i)->src_port)) { 2730 *match_id = TD2_MATCH_ID_SET(i, bcmSwitchMatchServiceGtp); 2731 return BCM_E_NONE; 2732 } 2733 break; 2734 default: 2735 return BCM_E_PARAM; 2736 break; 2737 } 2738 } 2739 2740 return rv; 2741 } 2742 2743 2744 /* 2745 * Function: 2746 * _bcm_td2_custom_hdr_match_config_add 2747 * Purpose: 2748 * Add a match config, match_id will be returned after match 2749 * config created. 2750 * Parameters: 2751 * unit - (IN) Unit number 2752 * match_service - (IN) Match service type 2753 * config_info - (IN) Match configuration 2754 * match_id - (OUT) Match ID 2755 * Returns: 2756 * BCM_E_xxx 2757 */ 2758 STATIC int 2759 _bcm_td2_gtp_port_match_config_add( 2760 int unit, 2761 bcm_switch_match_service_t match_service, 2762 bcm_switch_match_config_info_t *config_info, 2763 int *match_id) 2764 { 2765 int rv = BCM_E_NONE; 2766 int i, table_size; 2767 int exist_match_id; 2768 int src_port = 0, dst_port = 0; 2769 gtp_port_table_entry_t gtp_port_entry; 2770 2771 if ((config_info->match_criteria < BCM_SWITCH_GTP_MATCH_DST_PORT) || 2772 (config_info->match_criteria > BCM_SWITCH_GTP_MATCH_SRC_AND_DST_PORT)) { 2773 return BCM_E_PARAM; 2774 } 2775 2776 rv = _bcm_td2_gtp_port_match_config_find(unit, bcmSwitchMatchServiceGtp, 2777 *config_info, &exist_match_id); 2778 if (rv == BCM_E_NONE) { 2779 return BCM_E_EXISTS; 2780 } 2781 2782 table_size = soc_mem_index_count(unit, GTP_PORT_TABLEm); 2783 for (i = 0; i < table_size; i++) { 2784 if (!TD2_GTP_PORT_MATCH_IS_USED(unit, i)) { 2785 break; 2786 } 2787 } 2788 2789 if (i == table_size) { 2790 return BCM_E_FULL; 2791 } 2792 2793 switch (config_info->match_criteria) { 2794 case BCM_SWITCH_GTP_MATCH_DST_PORT: 2795 dst_port = config_info->dst_port; 2796 src_port = 0; 2797 break; 2798 case BCM_SWITCH_GTP_MATCH_SRC_PORT: 2799 src_port = config_info->src_port; 2800 dst_port = 0; 2801 break; 2802 case BCM_SWITCH_GTP_MATCH_SRC_AND_DST_PORT: 2803 case BCM_SWITCH_GTP_MATCH_SRC_OR_DST_PORT: 2804 src_port = config_info->src_port; 2805 dst_port = config_info->dst_port; 2806 break; 2807 default: 2808 return BCM_E_PARAM; 2809 break; 2810 } 2811 2812 sal_memset(>p_port_entry, 0, sizeof(gtp_port_table_entry_t)); 2813 soc_mem_field32_set(unit, GTP_PORT_TABLEm, >p_port_entry, 2814 MATCH_ENABLEf, config_info->match_criteria); 2815 soc_mem_field32_set(unit, GTP_PORT_TABLEm, >p_port_entry, 2816 SRC_PORTf, src_port); 2817 soc_mem_field32_set(unit, GTP_PORT_TABLEm, >p_port_entry, 2818 DST_PORTf, dst_port); 2819 SOC_IF_ERROR_RETURN( 2820 soc_mem_write(unit, GTP_PORT_TABLEm, MEM_BLOCK_ALL, i, >p_port_entry)); 2821 2822 TD2_GTP_PORT_MATCH(unit, i) = 2823 sal_alloc(sizeof(_bcm_td2_gtp_port_match_t), "gtp_port_match"); 2824 if (TD2_GTP_PORT_MATCH(unit, i) == NULL) { 2825 return BCM_E_MEMORY; 2826 } 2827 TD2_GTP_PORT_MATCH(unit, i)->match_criteria = config_info->match_criteria; 2828 TD2_GTP_PORT_MATCH(unit, i)->dst_port = dst_port; 2829 TD2_GTP_PORT_MATCH(unit, i)->src_port = src_port; 2830 *match_id = TD2_MATCH_ID_SET(i, bcmSwitchMatchServiceGtp); 2831 return BCM_E_NONE; 2832 } 2833 2834 /* 2835 * Function: 2836 * bcm_td2_switch_match_config_add 2837 * Purpose: 2838 * Add a match config to hardware. 2839 * Parameters: 2840 * unit - (IN) Unit number 2841 * match_service - (IN) Match service type 2842 * config_info - (IN) Match configuration 2843 * match_id - (OUT) Match ID 2844 * Returns: 2845 * BCM_E_xxx 2846 */ 2847 int 2848 bcm_td2_switch_match_config_add( 2849 int unit, 2850 bcm_switch_match_service_t match_service, 2851 bcm_switch_match_config_info_t *config_info, 2852 int *match_id) 2853 { 2854 int rv = BCM_E_NONE; 2855 2856 TD2_MATCH_INIT(unit); 2857 TD2_MATCH_LOCK(unit); 2858 2859 if (match_service == bcmSwitchMatchServiceGtp) { 2860 rv = _bcm_td2_gtp_port_match_config_add(unit, match_service, 2861 config_info, match_id); 2862 } 2863 2864 TD2_MATCH_UNLOCK(unit); 2865 2866 return rv; 2867 } 2868 2869 /* 2870 * Function: 2871 * _bcm_td2_custom_hdr_match_config_delete 2872 * Purpose: 2873 * Destroy a match ID by removing it from hardware. 2874 * Parameters: 2875 * unit - (IN) Unit number 2876 * match_service - (IN) Match service type 2877 * match_id - (IN) Match ID 2878 * Returns: 2879 * BCM_E_XXX 2880 */ 2881 STATIC int 2882 _bcm_td2_gtp_port_match_config_delete( 2883 int unit, 2884 bcm_switch_match_service_t match_service, 2885 int match_id) 2886 { 2887 int hw_id; 2888 gtp_port_table_entry_t gtp_port_entry; 2889 2890 BCM_IF_ERROR_RETURN( 2891 _bcm_td2_switch_match_id_check(unit, match_service, match_id)); 2892 2893 hw_id = TD2_MATCH_HW_ID_GET(match_id); 2894 if (!TD2_GTP_PORT_MATCH_IS_USED(unit, hw_id)) { 2895 return BCM_E_NOT_FOUND; 2896 } 2897 2898 sal_memset(>p_port_entry, 0, sizeof(gtp_port_table_entry_t)); 2899 soc_mem_field32_set(unit, GTP_PORT_TABLEm, >p_port_entry, 2900 MATCH_ENABLEf, 0); 2901 soc_mem_field32_set(unit, GTP_PORT_TABLEm, >p_port_entry, 2902 SRC_PORTf, 0); 2903 soc_mem_field32_set(unit, GTP_PORT_TABLEm, >p_port_entry, 2904 DST_PORTf, 0); 2905 SOC_IF_ERROR_RETURN( 2906 soc_mem_write(unit, GTP_PORT_TABLEm, MEM_BLOCK_ALL, hw_id, 2907 >p_port_entry)); 2908 2909 sal_free(TD2_GTP_PORT_MATCH(unit, hw_id)); 2910 TD2_GTP_PORT_MATCH(unit, hw_id) = NULL; 2911 2912 return BCM_E_NONE; 2913 } 2914 2915 /* 2916 * Function: 2917 * bcm_td2_switch_match_config_delete 2918 * Purpose: 2919 * Delete a match config with the given match_id by removing it from 2920 * hardware and deleting the associated software state info. 2921 * Parameters: 2922 * unit - (IN) Unit number 2923 * match_service - (IN) Match service type 2924 * match_id - (IN) Match ID 2925 * Returns: 2926 * BCM_E_xxx 2927 */ 2928 int 2929 bcm_td2_switch_match_config_delete( 2930 int unit, 2931 bcm_switch_match_service_t match_service, 2932 int match_id) 2933 { 2934 int rv = BCM_E_NONE; 2935 2936 BCM_IF_ERROR_RETURN( 2937 _bcm_td2_switch_match_id_check(unit, match_service, match_id)); 2938 2939 TD2_MATCH_INIT(unit); 2940 TD2_MATCH_LOCK(unit); 2941 2942 if (match_service == bcmSwitchMatchServiceGtp) { 2943 rv = _bcm_td2_gtp_port_match_config_delete( 2944 unit, match_service, match_id); 2945 } 2946 2947 TD2_MATCH_UNLOCK(unit); 2948 2949 return rv; 2950 } 2951 2952 /* 2953 * Function: 2954 * bcm_td2_switch_match_config_delete_all 2955 * Purpose: 2956 * Delete all match config with the given match_service. 2957 * Parameters: 2958 * unit - (IN) Unit number 2959 * match_service - (IN) Match service type 2960 * Returns: 2961 * BCM_E_xxx 2962 */ 2963 int 2964 bcm_td2_switch_match_config_delete_all( 2965 int unit, 2966 bcm_switch_match_service_t match_service) 2967 { 2968 int rv = BCM_E_NONE; 2969 int i, table_size; 2970 2971 TD2_MATCH_INIT(unit); 2972 TD2_MATCH_LOCK(unit); 2973 2974 if (match_service == bcmSwitchMatchServiceGtp) { 2975 table_size = soc_mem_index_count(unit, GTP_PORT_TABLEm); 2976 rv = soc_mem_clear(unit, GTP_PORT_TABLEm, MEM_BLOCK_ANY, TRUE); 2977 if (SOC_FAILURE(rv)) { 2978 TD2_MATCH_UNLOCK(unit); 2979 return rv; 2980 } 2981 for (i = 0; i < table_size; i++) { 2982 if (TD2_GTP_PORT_MATCH_IS_USED(unit,i)) { 2983 sal_free(TD2_GTP_PORT_MATCH(unit,i)); 2984 TD2_GTP_PORT_MATCH(unit,i) = NULL; 2985 } 2986 } 2987 } 2988 2989 TD2_MATCH_UNLOCK(unit); 2990 return rv; 2991 } 2992 2993 /* 2994 * Function: 2995 * _bcm_td2_gtp_port_match_config_get 2996 * Purpose: 2997 * Get the match configuration from hardware 2998 * Parameters: 2999 * unit - (IN) Unit number 3000 * match_service - (IN) Match service type 3001 * match_id - (IN) Match ID 3002 * config_info - (OUT) Match configuration 3003 * Returns: 3004 * BCM_E_xxx 3005 */ 3006 STATIC int 3007 _bcm_td2_gtp_port_match_config_get( 3008 int unit, 3009 bcm_switch_match_service_t match_service, 3010 int match_id, 3011 bcm_switch_match_config_info_t *config_info) 3012 { 3013 uint32 hw_id; 3014 3015 hw_id = TD2_MATCH_HW_ID_GET(match_id); 3016 3017 if (!TD2_GTP_PORT_MATCH_IS_USED(unit, hw_id)) { 3018 return BCM_E_NOT_FOUND; 3019 } 3020 3021 bcm_switch_match_config_info_t_init(config_info); 3022 config_info->match_criteria = TD2_GTP_PORT_MATCH(unit, hw_id)->match_criteria; 3023 config_info->dst_port = TD2_GTP_PORT_MATCH(unit, hw_id)->dst_port; 3024 config_info->src_port = TD2_GTP_PORT_MATCH(unit, hw_id)->src_port; 3025 3026 return BCM_E_NONE; 3027 } 3028 3029 3030 /* 3031 * Function: 3032 * bcm_td2_switch_match_config_get 3033 * Purpose: 3034 * Get the configuration of the match with the given match_id. 3035 * Parameters: 3036 * unit - (IN) Unit number 3037 * match_service - (IN) Match service type 3038 * match_id - (IN) Match ID 3039 * config_info - (OUT) Match configuration 3040 * Returns: 3041 * BCM_E_xxx 3042 */ 3043 int 3044 bcm_td2_switch_match_config_get( 3045 int unit, 3046 bcm_switch_match_service_t match_service, 3047 int match_id, 3048 bcm_switch_match_config_info_t *config_info) 3049 { 3050 int rv = BCM_E_NONE; 3051 3052 BCM_IF_ERROR_RETURN( 3053 _bcm_td2_switch_match_id_check(unit, match_service, match_id)); 3054 3055 TD2_MATCH_INIT(unit); 3056 TD2_MATCH_LOCK(unit); 3057 3058 if (match_service == bcmSwitchMatchServiceGtp) { 3059 rv = _bcm_td2_gtp_port_match_config_get( 3060 unit, match_service, match_id, config_info); 3061 } 3062 3063 TD2_MATCH_UNLOCK(unit); 3064 3065 return rv; 3066 } 3067 3068 /* 3069 * Function: 3070 * _bcm_td2_gtp_port_match_config_set 3071 * Purpose: 3072 * Set the match configuration from hardware 3073 * Parameters: 3074 * unit - (IN) Unit number 3075 * match_service - (IN) Match service type 3076 * match_id - (IN) Match ID 3077 * config_info - (IN) Match configuration 3078 * Returns: 3079 * BCM_E_xxx 3080 */ 3081 STATIC int 3082 _bcm_td2_gtp_port_match_config_set( 3083 int unit, 3084 bcm_switch_match_service_t match_service, 3085 int match_id, 3086 bcm_switch_match_config_info_t *config_info) 3087 { 3088 int rv; 3089 uint32 hw_id; 3090 int exist_match_id; 3091 int src_port = 0, dst_port = 0; 3092 gtp_port_table_entry_t gtp_port_entry; 3093 3094 hw_id = TD2_MATCH_HW_ID_GET(match_id); 3095 3096 rv = _bcm_td2_gtp_port_match_config_find(unit, bcmSwitchMatchServiceGtp, 3097 *config_info, &exist_match_id); 3098 if (rv != BCM_E_NOT_FOUND) { 3099 if (rv == BCM_E_NONE) { 3100 if (exist_match_id != match_id) { 3101 return BCM_E_EXISTS; 3102 } else { 3103 return BCM_E_NONE; 3104 } 3105 } else { 3106 return rv; 3107 } 3108 } 3109 3110 switch (config_info->match_criteria) { 3111 case BCM_SWITCH_GTP_MATCH_DST_PORT: 3112 dst_port = config_info->dst_port; 3113 src_port = 0; 3114 break; 3115 case BCM_SWITCH_GTP_MATCH_SRC_PORT: 3116 src_port = config_info->src_port; 3117 dst_port = 0; 3118 break; 3119 case BCM_SWITCH_GTP_MATCH_SRC_AND_DST_PORT: 3120 case BCM_SWITCH_GTP_MATCH_SRC_OR_DST_PORT: 3121 src_port = config_info->src_port; 3122 dst_port = config_info->dst_port; 3123 break; 3124 default: 3125 return BCM_E_PARAM; 3126 break; 3127 } 3128 3129 sal_memset(>p_port_entry, 0, sizeof(gtp_port_table_entry_t)); 3130 soc_mem_field32_set(unit, GTP_PORT_TABLEm, >p_port_entry, 3131 MATCH_ENABLEf, config_info->match_criteria); 3132 soc_mem_field32_set(unit, GTP_PORT_TABLEm, >p_port_entry, 3133 SRC_PORTf, src_port); 3134 soc_mem_field32_set(unit, GTP_PORT_TABLEm, >p_port_entry, 3135 DST_PORTf, dst_port); 3136 SOC_IF_ERROR_RETURN( 3137 soc_mem_write(unit, GTP_PORT_TABLEm, MEM_BLOCK_ALL, 3138 hw_id, >p_port_entry)); 3139 3140 if (!TD2_GTP_PORT_MATCH_IS_USED(unit, hw_id)) { 3141 TD2_GTP_PORT_MATCH(unit, hw_id) = 3142 sal_alloc(sizeof(_bcm_td2_gtp_port_match_t), "gtp_port_match"); 3143 if (TD2_GTP_PORT_MATCH(unit, hw_id) == NULL) { 3144 return BCM_E_MEMORY; 3145 } 3146 } 3147 3148 TD2_GTP_PORT_MATCH(unit, hw_id)->match_criteria = config_info->match_criteria; 3149 TD2_GTP_PORT_MATCH(unit, hw_id)->dst_port = dst_port; 3150 TD2_GTP_PORT_MATCH(unit, hw_id)->src_port = src_port; 3151 3152 return BCM_E_NONE; 3153 } 3154 3155 /* 3156 * Function: 3157 * bcm_td2_switch_match_config_set 3158 * Purpose: 3159 * Set the configuration of the match with the given match_id. 3160 * Parameters: 3161 * unit - (IN) Unit number 3162 * match_service - (IN) Match service type 3163 * match_id - (IN) Match ID 3164 * config_info - (IN) Match configuration 3165 * Returns: 3166 * BCM_E_xxx 3167 */ 3168 int 3169 bcm_td2_switch_match_config_set( 3170 int unit, 3171 bcm_switch_match_service_t match_service, 3172 int match_id, 3173 bcm_switch_match_config_info_t *config_info) 3174 { 3175 int rv = BCM_E_NONE; 3176 3177 if ((config_info->match_criteria < BCM_SWITCH_GTP_MATCH_DST_PORT) || 3178 (config_info->match_criteria > BCM_SWITCH_GTP_MATCH_SRC_AND_DST_PORT)) { 3179 return BCM_E_PARAM; 3180 } 3181 BCM_IF_ERROR_RETURN( 3182 _bcm_td2_switch_match_id_check(unit, match_service, match_id)); 3183 3184 TD2_MATCH_INIT(unit); 3185 TD2_MATCH_LOCK(unit); 3186 3187 if (match_service == bcmSwitchMatchServiceGtp) { 3188 rv = _bcm_td2_gtp_port_match_config_set( 3189 unit, match_service, match_id, config_info); 3190 } 3191 3192 TD2_MATCH_UNLOCK(unit); 3193 3194 return rv; 3195 } 3196 3197 /* 3198 * Function: 3199 * bcm_td2_switch_match_config_traverse 3200 * Purpose: 3201 * Traverse the created match config. 3202 * Parameters: 3203 * unit - (IN) Unit number 3204 * match_service - (IN) Match service type 3205 * cb_fn - (IN) Traverse call back function 3206 * user_data - (IN) User data 3207 * Returns: 3208 * BCM_E_xxx 3209 */ 3210 int 3211 bcm_td2_switch_match_config_traverse( 3212 int unit, 3213 bcm_switch_match_service_t match_service, 3214 bcm_switch_match_config_traverse_cb cb_fn, 3215 void *user_data) 3216 { 3217 uint32 match_id; 3218 int table_size = 0, i = 0; 3219 bcm_switch_match_config_info_t match_config; 3220 int rv = BCM_E_NONE; 3221 3222 if (cb_fn == NULL) { 3223 return BCM_E_PARAM; 3224 } 3225 3226 TD2_MATCH_INIT(unit); 3227 TD2_MATCH_LOCK(unit); 3228 3229 table_size = soc_mem_index_count(unit, GTP_PORT_TABLEm); 3230 3231 for (i = 0; i < table_size; i++) { 3232 if (TD2_GTP_PORT_MATCH_IS_USED(unit, i)) { 3233 match_id = TD2_MATCH_ID_SET(i, bcmSwitchMatchServiceGtp); 3234 rv = bcm_td2_switch_match_config_get( 3235 unit, match_service, match_id, &match_config); 3236 if (BCM_FAILURE(rv)) { 3237 TD2_MATCH_UNLOCK(unit); 3238 return rv; 3239 } 3240 3241 rv = cb_fn(unit, match_id, &match_config, user_data); 3242 if (BCM_FAILURE(rv)) { 3243 TD2_MATCH_UNLOCK(unit); 3244 return rv; 3245 } 3246 } 3247 } 3248 3249 TD2_MATCH_UNLOCK(unit); 3250 return BCM_E_NONE; 3251 } 3252 3253 /* 3254 * Function: 3255 * bcmi_td2_l2x_freeze_mode_map_bcm2soc 3256 * Description: 3257 * Conver freeze mode from BCM layer value to SOC layer value. 3258 * Parameters: 3259 * bcm_mode - (IN) BCM layer value 3260 * soc_mode - (OUT) SOC layer value 3261 * Return Value: 3262 * BCM_E_XXX 3263 */ 3264 STATIC int 3265 bcmi_td2_l2x_freeze_mode_map_bcm2soc(int bcm_mode, int *soc_mode) 3266 { 3267 if (soc_mode == NULL) { 3268 return BCM_E_PARAM; 3269 } 3270 switch(bcm_mode) { 3271 case BCM_SWITCH_L2_FREEZE_MODE_PORT: 3272 *soc_mode = SOC_L2X_FREEZE_MODE_PORT_RECONFIGURE; 3273 break; 3274 case BCM_SWITCH_L2_FREEZE_MODE_GLOBAL: 3275 *soc_mode = SOC_L2X_FREEZE_MODE_GLOBAL_OVERRIDE; 3276 break; 3277 default: 3278 LOG_ERROR(BSL_LS_BCM_COMMON, 3279 (BSL_META("Unknown freeze mode: %d\n"), bcm_mode)); 3280 return BCM_E_PARAM; 3281 } 3282 return BCM_E_NONE; 3283 } 3284 3285 /* 3286 * Function: 3287 * bcmi_td2_l2x_freeze_mode_map_soc2bcm 3288 * Description: 3289 * Conver freeze mode from SOC layer value to BCM layer value. 3290 * Parameters: 3291 * soc_mode - (IN) SOC layer value 3292 * bcm_mode - (OUT) BCM layer value 3293 * Return Value: 3294 * BCM_E_XXX 3295 */ 3296 STATIC int 3297 bcmi_td2_l2x_freeze_mode_map_soc2bcm(int soc_mode, int *bcm_mode) 3298 { 3299 if (bcm_mode == NULL) { 3300 return BCM_E_PARAM; 3301 } 3302 switch(soc_mode) { 3303 case SOC_L2X_FREEZE_MODE_PORT_RECONFIGURE: 3304 *bcm_mode = BCM_SWITCH_L2_FREEZE_MODE_PORT; 3305 break; 3306 case SOC_L2X_FREEZE_MODE_GLOBAL_OVERRIDE: 3307 *bcm_mode = BCM_SWITCH_L2_FREEZE_MODE_GLOBAL; 3308 break; 3309 default: 3310 LOG_ERROR(BSL_LS_BCM_COMMON, 3311 (BSL_META("Unknown soc freeze mode: %d\n"), soc_mode)); 3312 return BCM_E_INTERNAL; 3313 } 3314 return BCM_E_NONE; 3315 } 3316 3317 int 3318 bcm_td2_l2x_freeze_mode_set(int unit, int arg) 3319 { 3320 int mode = 0; 3321 3322 BCM_IF_ERROR_RETURN(bcmi_td2_l2x_freeze_mode_map_bcm2soc(arg, &mode)); 3323 SOC_IF_ERROR_RETURN(soc_l2x_freeze_mode_set(unit, mode)); 3324 3325 return BCM_E_NONE; 3326 } 3327 3328 int 3329 bcm_td2_l2x_freeze_mode_get(int unit, int *arg) 3330 { 3331 int mode = 0; 3332 3333 if (arg == NULL) { 3334 return BCM_E_PARAM; 3335 } 3336 SOC_IF_ERROR_RETURN(soc_l2x_freeze_mode_get(unit, &mode)); 3337 BCM_IF_ERROR_RETURN(bcmi_td2_l2x_freeze_mode_map_soc2bcm(mode, arg)); 3338 3339 return BCM_E_NONE; 3340 } 3341 3342 /* 3343 * Function: 3344 * bcm_td2_switch_l2_freeze_mode_init 3345 * Description: 3346 * Set default L2 freeze mode to global override mode. 3347 * Global override mode is less time consuming. 3348 * Parameters: 3349 * unit - (IN) Device number 3350 * Return Value: 3351 * BCM_E_XXX 3352 */ 3353 int 3354 bcm_td2_switch_l2_freeze_mode_init(int unit) 3355 { 3356 BCM_IF_ERROR_RETURN( 3357 bcm_td2_l2x_freeze_mode_set(unit, 3358 BCM_SWITCH_L2_FREEZE_MODE_GLOBAL)); 3359 return BCM_E_NONE; 3360 } 3361 3362 STATIC void 3363 bcm_td2_ser_log_tlv2info(int unit, 3364 void *buffer, bcm_switch_ser_log_info_t *info) 3365 { 3366 soc_ser_log_tlv_hdr_t *tlv_hdr = buffer; 3367 char *data = (char*)buffer + sizeof(soc_ser_log_tlv_hdr_t); 3368 soc_ser_log_tlv_memory_t *tlv_mem; 3369 soc_ser_log_tlv_register_t *tlv_reg; 3370 soc_ser_log_tlv_generic_t *tlv_generic; 3371 soc_ser_log_flag_t flags; 3372 soc_mem_t mem = INVALIDm; 3373 int entry_dw = 0; 3374 3375 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3376 (BSL_META("type: %d\n"), tlv_hdr->type)); 3377 3378 switch (tlv_hdr->type) { 3379 case SOC_SER_LOG_TLV_MEMORY: 3380 tlv_mem = (soc_ser_log_tlv_memory_t*)data; 3381 info->flags |= BCM_SWITCH_SER_LOG_MEM; 3382 info->mem_reg = tlv_mem->memory; 3383 info->index = tlv_mem->index; 3384 if (SOC_MEM_IS_VALID(unit, info->mem_reg)) { 3385 sal_memcpy(info->name, SOC_MEM_NAME(unit, info->mem_reg), 3386 strlen(SOC_MEM_NAME(unit, info->mem_reg)) + 1); 3387 } 3388 break; 3389 case SOC_SER_LOG_TLV_REGISTER: 3390 tlv_reg = (soc_ser_log_tlv_register_t*)data; 3391 info->flags |= BCM_SWITCH_SER_LOG_REG; 3392 info->mem_reg = tlv_reg->reg; 3393 info->index = tlv_reg->index; 3394 info->port = tlv_reg->port; 3395 if (SOC_REG_IS_VALID(unit, info->mem_reg)) { 3396 sal_memcpy(info->name, SOC_REG_NAME(unit, info->mem_reg), 3397 strlen(SOC_REG_NAME(unit, info->mem_reg)) + 1); 3398 } 3399 break; 3400 case SOC_SER_LOG_TLV_CONTENTS: 3401 mem = info->mem_reg; 3402 if (SOC_MEM_IS_VALID(unit, mem)) { 3403 entry_dw = soc_mem_entry_words(unit, mem); 3404 } 3405 if (entry_dw != 0) { 3406 info->flags |= BCM_SWITCH_SER_LOG_ENTRY; 3407 sal_memcpy(info->entry_data, data, entry_dw * 4); 3408 } 3409 break; 3410 case SOC_SER_LOG_TLV_CACHE: 3411 mem = info->mem_reg; 3412 if (SOC_MEM_IS_VALID(unit, mem)) { 3413 entry_dw = soc_mem_entry_words(unit, mem); 3414 } 3415 if (entry_dw != 0) { 3416 info->flags |= BCM_SWITCH_SER_LOG_CACHE; 3417 sal_memcpy(info->cache_data, data, entry_dw * 4); 3418 } 3419 break; 3420 case SOC_SER_LOG_TLV_GENERIC: 3421 tlv_generic = (soc_ser_log_tlv_generic_t*)data; 3422 flags = tlv_generic->flags; 3423 3424 info->flags |= (flags & SOC_SER_LOG_FLAG_MULTIBIT) ? 3425 BCM_SWITCH_SER_LOG_MULTI:0; 3426 info->time = tlv_generic->time; 3427 info->addr = tlv_generic->address; 3428 info->instance = tlv_generic->inst; 3429 info->pipe = tlv_generic->pipe_num; 3430 switch(tlv_generic->block_type) { 3431 case SOC_BLK_MMU: 3432 info->block_type = bcmSwitchBlockTypeMmu; 3433 break; 3434 case SOC_BLK_MMU_GLB: 3435 info->block_type = bcmSwitchBlockTypeMmuGlb; 3436 break; 3437 case SOC_BLK_MMU_XPE: 3438 info->block_type = bcmSwitchBlockTypeMmuXpe; 3439 break; 3440 case SOC_BLK_MMU_SC: 3441 info->block_type = bcmSwitchBlockTypeMmuSc; 3442 break; 3443 case SOC_BLK_MMU_SED: 3444 info->block_type = bcmSwitchBlockTypeMmuSed; 3445 break; 3446 case SOC_BLK_IPIPE: 3447 info->block_type = bcmSwitchBlockTypeIpipe; 3448 break; 3449 case SOC_BLK_EPIPE: 3450 info->block_type = bcmSwitchBlockTypeEpipe; 3451 break; 3452 case SOC_BLK_PGW_CL: 3453 info->block_type = bcmSwitchBlockTypePgw; 3454 break; 3455 case SOC_BLK_CLPORT: 3456 info->block_type = bcmSwitchBlockTypeClport; 3457 break; 3458 case SOC_BLK_XLPORT: 3459 info->block_type = bcmSwitchBlockTypeXlport; 3460 break; 3461 case SOC_BLK_MACSEC: 3462 info->block_type = bcmSwitchBlockTypeMacsec; 3463 break; 3464 default: 3465 LOG_CLI((BSL_META_U(unit, "\tUnknown block type\n"))); 3466 break; 3467 } 3468 3469 switch (tlv_generic->parity_type) { 3470 case SOC_PARITY_TYPE_PARITY: 3471 info->error_type = bcmSwitchErrorTypeParity; 3472 break; 3473 case SOC_PARITY_TYPE_ECC: 3474 if (flags & SOC_SER_LOG_FLAG_DOUBLEBIT) { 3475 info->error_type = bcmSwitchErrorTypeEccDoubleBit; 3476 } else { 3477 info->error_type = bcmSwitchErrorTypeEccSingleBit; 3478 } 3479 break; 3480 default: 3481 info->error_type = bcmSwitchErrorTypeUnknown; 3482 break; 3483 } 3484 3485 info->flags |= tlv_generic->corrected ? BCM_SWITCH_SER_LOG_CORRECTED:0; 3486 3487 switch (tlv_generic->ser_response_flag) { 3488 case SOC_MEM_FLAG_SER_ENTRY_CLEAR: 3489 info->correction_type = bcmSwitchCorrectTypeEntryClear; 3490 break; 3491 case SOC_MEM_FLAG_SER_ECC_CORRECTABLE: 3492 case SOC_MEM_FLAG_SER_CACHE_RESTORE: 3493 case SOC_MEM_FLAG_SER_WRITE_CACHE_RESTORE: 3494 info->correction_type = bcmSwitchCorrectTypeCacheRestore; 3495 break; 3496 case SOC_MEM_FLAG_SER_SPECIAL: 3497 info->correction_type = bcmSwitchCorrectTypeSpecial; 3498 break; 3499 default: 3500 info->correction_type = bcmSwitchCorrectTypeNoAction; 3501 break; 3502 } 3503 if (TRUE == tlv_generic->hw_cache) { 3504 info->correction_type = bcmSwitchCorrectTypeHwCacheRestore; 3505 } 3506 break; 3507 default: 3508 LOG_CLI((BSL_META_U(unit, "\tUnknown type\n"))); 3509 break; 3510 } 3511 3512 return; 3513 } 3514 3515 3516 STATIC int 3517 bcm_td2_ser_log_entry2info(int unit, 3518 void *buffer, bcm_switch_ser_log_info_t *info) 3519 { 3520 soc_ser_log_tlv_hdr_t *tlv_hdr = buffer; 3521 3522 while (tlv_hdr->type != 0) { 3523 bcm_td2_ser_log_tlv2info(unit, (char*)tlv_hdr, info); 3524 tlv_hdr = (soc_ser_log_tlv_hdr_t*)((char*)tlv_hdr + 3525 tlv_hdr->length + sizeof(soc_ser_log_tlv_hdr_t)); 3526 } 3527 3528 return BCM_E_NONE; 3529 } 3530 3531 /* 3532 * Function: 3533 * bcm_td2_switch_ser_log_info_get 3534 * Purpose: 3535 * To get ser log info. 3536 * Parameters: 3537 * unit - (IN) Unit number. 3538 * id - (IN) log id. 3539 * info - (OUT) ser log info. 3540 * Returns: 3541 * BCM_E_xxx 3542 * Notes: 3543 */ 3544 int 3545 bcm_td2_switch_ser_log_info_get(int unit, 3546 int id, bcm_switch_ser_log_info_t *info) 3547 { 3548 int rv = BCM_E_NONE; 3549 int size; 3550 char *buffer; 3551 3552 if (NULL == info) { 3553 return (BCM_E_PARAM); 3554 } 3555 3556 buffer = sal_alloc(_SOC_SER_LOG_BUFFER_SIZE, "ser log info"); 3557 if (NULL == buffer) { 3558 return (BCM_E_MEMORY); 3559 } 3560 3561 rv = soc_ser_log_get_entry_size(unit, id, &size); 3562 if ((size <= 0) || (size > _SOC_SER_LOG_BUFFER_SIZE) 3563 || (BCM_E_NONE != rv)) { 3564 LOG_ERROR(BSL_LS_BCM_COMMON, 3565 (BSL_META("Log %d not found!\n"), id)); 3566 rv = BCM_E_NOT_FOUND; 3567 goto error; 3568 } 3569 3570 rv = soc_ser_log_get_entry(unit, id, size, buffer); 3571 if (BCM_FAILURE(rv)) { 3572 goto error; 3573 } 3574 3575 rv = bcm_td2_ser_log_entry2info(unit, buffer, info); 3576 error: 3577 if (NULL != buffer) { 3578 sal_free(buffer); 3579 } 3580 return rv; 3581 } 3582 3583 /* 3584 * Map BCM layer block type, SER error type, SER error correction type to SOC layer ones 3585 */ 3586 STATIC int 3587 bcm_td2_ser_error_stat_type_mapping(int unit, 3588 bcm_switch_ser_error_stat_type_t stat_type, 3589 soc_ser_block_type_t *btype, 3590 soc_ser_error_type_t *etype, 3591 soc_ser_correction_type_t *ctype) 3592 { 3593 soc_ser_block_type_t btype_tmp; 3594 soc_ser_error_type_t etype_tmp; 3595 soc_ser_correction_type_t ctype_tmp; 3596 3597 switch (stat_type.block_type) { 3598 case bcmSwitchBlockTypeAll: 3599 btype_tmp = SocSerBlockTypeAll; 3600 break; 3601 case bcmSwitchBlockTypeMmu: 3602 btype_tmp = SocSerBlockTypeMMU; 3603 break; 3604 case bcmSwitchBlockTypeMmuGlb: 3605 btype_tmp = SocSerBlockTypeMMU_GLB; 3606 break; 3607 case bcmSwitchBlockTypeMmuXpe: 3608 btype_tmp = SocSerBlockTypeMMU_XPE; 3609 break; 3610 case bcmSwitchBlockTypeMmuSc: 3611 btype_tmp = SocSerBlockTypeMMU_SC; 3612 break; 3613 case bcmSwitchBlockTypeMmuSed: 3614 btype_tmp = SocSerBlockTypeMMU_SED; 3615 break; 3616 case bcmSwitchBlockTypeIpipe: 3617 btype_tmp = SocSerBlockTypeIPIPE; 3618 break; 3619 case bcmSwitchBlockTypeEpipe: 3620 btype_tmp = SocSerBlockTypeEPIPE; 3621 break; 3622 case bcmSwitchBlockTypePgw: 3623 btype_tmp = SocSerBlockTypePGW; 3624 break; 3625 case bcmSwitchBlockTypeClport: 3626 btype_tmp = SocSerBlockTypeCLPORT; 3627 break; 3628 case bcmSwitchBlockTypeXlport: 3629 btype_tmp = SocSerBlockTypeXLPORT; 3630 break; 3631 case bcmSwitchBlockTypeMacsec: 3632 btype_tmp = SocSerBlockTypeMACSEC; 3633 break; 3634 case bcmSwitchBlockTypeCount: 3635 btype_tmp = SocSerBlockTypeCount; 3636 break; 3637 default: 3638 return (BCM_E_PARAM); 3639 } 3640 3641 switch (stat_type.error_type) { 3642 case bcmSwitchErrorTypeAll: 3643 etype_tmp = SocSerErrorTypeAll; 3644 break; 3645 case bcmSwitchErrorTypeUnknown: 3646 etype_tmp = SocSerErrorTypeUnknown; 3647 break; 3648 case bcmSwitchErrorTypeParity: 3649 etype_tmp = SocSerErrorTypeParity; 3650 break; 3651 case bcmSwitchErrorTypeEccSingleBit: 3652 etype_tmp = SocSerErrorTypeEccSingleBit; 3653 break; 3654 case bcmSwitchErrorTypeEccDoubleBit: 3655 etype_tmp = SocSerErrorTypeEccDoubleBit; 3656 break; 3657 case bcmSwitchErrorTypeCount: 3658 etype_tmp = SocSerErrorTypeCount; 3659 break; 3660 default: 3661 return (BCM_E_PARAM); 3662 } 3663 3664 switch (stat_type.correction_type) { 3665 case bcmSwitchCorrectTypeAll: 3666 ctype_tmp = SocSerCorrectTypeAll; 3667 break; 3668 case bcmSwitchCorrectTypeNoAction: 3669 ctype_tmp = SocSerCorrectTypeNoAction; 3670 break; 3671 case bcmSwitchCorrectTypeFailToCorrect: 3672 ctype_tmp = SocSerCorrectTypeFailedToCorrect; 3673 break; 3674 case bcmSwitchCorrectTypeEntryClear: 3675 ctype_tmp = SocSerCorrectTypeEntryClear; 3676 break; 3677 case bcmSwitchCorrectTypeCacheRestore: 3678 ctype_tmp = SocSerCorrectTypeCacheRestore; 3679 break; 3680 case bcmSwitchCorrectTypeHwCacheRestore: 3681 ctype_tmp = socSerCorrectTypeHwCacheRestore; 3682 break; 3683 case bcmSwitchCorrectTypeSpecial: 3684 ctype_tmp = SocSerCorrectTypeSpecial; 3685 break; 3686 case bcmSwitchCorrectTypeCount: 3687 ctype_tmp = SocSerCorrectTypeCount; 3688 break; 3689 default: 3690 return (BCM_E_PARAM); 3691 } 3692 3693 *btype = btype_tmp; 3694 *etype = etype_tmp; 3695 *ctype = ctype_tmp; 3696 return (BCM_E_NONE); 3697 } 3698 3699 STATIC int 3700 bcm_td2_ser_error_count_sum(int unit, 3701 uint32 flags, 3702 soc_ser_block_type_t btype, 3703 soc_ser_error_type_t etype, 3704 soc_ser_correction_type_t ctype, 3705 uint32 *value) 3706 { 3707 int rv = BCM_E_NONE; 3708 uint32 value_tmp = 0; 3709 3710 /* All block types */ 3711 if (btype == SocSerBlockTypeAll && 3712 etype != SocSerErrorTypeAll && 3713 ctype != SocSerCorrectTypeAll) { 3714 if (BCM_SWITCH_SER_STAT_TCAM & flags) { 3715 SOC_SER_TCAM_ERROR_STAT_ALL_BTYPE_SUM(unit, etype, ctype, value_tmp); 3716 } else { 3717 SOC_SER_ERROR_STAT_ALL_BTYPE_SUM(unit, etype, ctype, value_tmp); 3718 } 3719 } /* All error types */ 3720 else if (btype != SocSerBlockTypeAll && 3721 etype == SocSerErrorTypeAll && 3722 ctype != SocSerCorrectTypeAll) { 3723 if (BCM_SWITCH_SER_STAT_TCAM & flags) { 3724 SOC_SER_TCAM_ERROR_STAT_ALL_ETYPE_SUM(unit, btype, ctype, value_tmp); 3725 } else { 3726 SOC_SER_ERROR_STAT_ALL_ETYPE_SUM(unit, btype, ctype, value_tmp); 3727 } 3728 } /* All correction types */ 3729 else if (btype != SocSerBlockTypeAll && 3730 etype != SocSerErrorTypeAll && 3731 ctype == SocSerCorrectTypeAll) { 3732 if (BCM_SWITCH_SER_STAT_TCAM & flags) { 3733 SOC_SER_TCAM_ERROR_STAT_ALL_CTYPE_SUM(unit, btype, etype, value_tmp); 3734 } else { 3735 SOC_SER_ERROR_STAT_ALL_CTYPE_SUM(unit, btype, etype, value_tmp); 3736 } 3737 } /* All block and error types*/ 3738 else if (btype == SocSerBlockTypeAll && 3739 etype == SocSerErrorTypeAll && 3740 ctype != SocSerCorrectTypeAll) { 3741 if (BCM_SWITCH_SER_STAT_TCAM & flags) { 3742 SOC_SER_TCAM_ERROR_STAT_ALL_BTYPE_ETYPE_SUM(unit, ctype, value_tmp); 3743 } else { 3744 SOC_SER_ERROR_STAT_ALL_BTYPE_ETYPE_SUM(unit, ctype, value_tmp); 3745 } 3746 } /* All block and correction types */ 3747 else if (btype == SocSerBlockTypeAll && 3748 etype != SocSerErrorTypeAll && 3749 ctype == SocSerCorrectTypeAll) { 3750 if (BCM_SWITCH_SER_STAT_TCAM & flags) { 3751 SOC_SER_TCAM_ERROR_STAT_ALL_BTYPE_CTYPE_SUM(unit, etype, value_tmp); 3752 } else { 3753 SOC_SER_ERROR_STAT_ALL_BTYPE_CTYPE_SUM(unit, etype, value_tmp); 3754 } 3755 } /* All error and correction types */ 3756 else if (btype != SocSerBlockTypeAll && 3757 etype == SocSerErrorTypeAll && 3758 ctype == SocSerCorrectTypeAll) { 3759 if (BCM_SWITCH_SER_STAT_TCAM & flags) { 3760 SOC_SER_TCAM_ERROR_STAT_ALL_ETYPE_CTYPE_SUM(unit, btype, value_tmp); 3761 } else { 3762 SOC_SER_ERROR_STAT_ALL_ETYPE_CTYPE_SUM(unit, btype, value_tmp); 3763 } 3764 } /* All block, error and correction types */ 3765 else if (btype == SocSerBlockTypeAll && 3766 etype == SocSerErrorTypeAll && 3767 ctype == SocSerCorrectTypeAll) { 3768 if (BCM_SWITCH_SER_STAT_TCAM & flags) { 3769 SOC_SER_TCAM_ERROR_STAT_ALL_BTYPE_ETYPE_CTYPE_SUM(unit, value_tmp); 3770 } else { 3771 SOC_SER_ERROR_STAT_ALL_BTYPE_ETYPE_CTYPE_SUM(unit, value_tmp); 3772 } 3773 } else { 3774 return (BCM_E_PARAM); 3775 } 3776 3777 *value = value_tmp; 3778 return rv; 3779 } 3780 3781 /* 3782 * Function: 3783 * bcm_td2_switch_ser_error_stat_get 3784 * Purpose: 3785 * Get SER error statistics for specified statistics type. 3786 * Parameters: 3787 * unit - (IN) Unit number. 3788 * type - (IN) SER error statistics type. 3789 * value - (OUT) Number of errors 3790 * Returns: 3791 * BCM_E_xxx 3792 * Notes: 3793 */ 3794 int 3795 bcm_td2_switch_ser_error_stat_get(int unit, 3796 bcm_switch_ser_error_stat_type_t stat_type, 3797 uint32 *value) 3798 { 3799 int rv = BCM_E_NONE; 3800 soc_ser_block_type_t btype; 3801 soc_ser_error_type_t etype; 3802 soc_ser_correction_type_t ctype; 3803 3804 /* Parameter boundary check */ 3805 if (stat_type.block_type >= bcmSwitchBlockTypeCount || 3806 stat_type.error_type >= bcmSwitchErrorTypeCount || 3807 stat_type.correction_type >= bcmSwitchCorrectTypeCount || 3808 stat_type.block_type < bcmSwitchBlockTypeAll || 3809 stat_type.error_type < bcmSwitchErrorTypeAll || 3810 stat_type.correction_type < bcmSwitchCorrectTypeAll) { 3811 return (BCM_E_PARAM); 3812 } 3813 3814 BCM_IF_ERROR_RETURN 3815 (bcm_td2_ser_error_stat_type_mapping(unit, stat_type, &btype, 3816 &etype, &ctype)); 3817 if (btype == SocSerBlockTypeAll || 3818 etype == SocSerErrorTypeAll || 3819 ctype == SocSerCorrectTypeAll) { 3820 /* Sum error count based on type */ 3821 rv = bcm_td2_ser_error_count_sum(unit, stat_type.flags, 3822 btype, etype, ctype, value); 3823 return rv; 3824 } 3825 3826 if (BCM_SWITCH_SER_STAT_TCAM & stat_type.flags) { 3827 *value = SOC_SER_TCAM_ERROR_STAT(unit, btype, etype, ctype); 3828 } else { 3829 *value = SOC_SER_ERROR_STAT(unit, btype, etype, ctype); 3830 } 3831 3832 return rv; 3833 } 3834 3835 STATIC int 3836 bcm_td2_ser_error_clear_by_type(int unit, 3837 uint32 flags, 3838 soc_ser_block_type_t btype, 3839 soc_ser_error_type_t etype, 3840 soc_ser_correction_type_t ctype) 3841 { 3842 int rv = BCM_E_NONE; 3843 3844 /* All block types */ 3845 if (btype == SocSerBlockTypeAll && 3846 etype != SocSerErrorTypeAll && 3847 ctype != SocSerCorrectTypeAll) { 3848 if (BCM_SWITCH_SER_STAT_TCAM & flags) { 3849 SOC_SER_TCAM_ERROR_STAT_ALL_BTYPE_CLEAR(unit, etype, ctype); 3850 } else { 3851 SOC_SER_ERROR_STAT_ALL_BTYPE_CLEAR(unit, etype, ctype); 3852 } 3853 } /* All error types */ 3854 else if (btype != SocSerBlockTypeAll && 3855 etype == SocSerErrorTypeAll && 3856 ctype != SocSerCorrectTypeAll) { 3857 if (BCM_SWITCH_SER_STAT_TCAM & flags) { 3858 SOC_SER_TCAM_ERROR_STAT_ALL_ETYPE_CLEAR(unit, btype, ctype); 3859 } else { 3860 SOC_SER_ERROR_STAT_ALL_ETYPE_CLEAR(unit, btype, ctype); 3861 } 3862 } /* All correction types */ 3863 else if (btype != SocSerBlockTypeAll && 3864 etype != SocSerErrorTypeAll && 3865 ctype == SocSerCorrectTypeAll) { 3866 if (BCM_SWITCH_SER_STAT_TCAM & flags) { 3867 SOC_SER_TCAM_ERROR_STAT_ALL_CTYPE_CLEAR(unit, btype, etype); 3868 } else { 3869 SOC_SER_ERROR_STAT_ALL_CTYPE_CLEAR(unit, btype, etype); 3870 } 3871 } /* All block and error types*/ 3872 else if (btype == SocSerBlockTypeAll && 3873 etype == SocSerErrorTypeAll && 3874 ctype != SocSerCorrectTypeAll) { 3875 if (BCM_SWITCH_SER_STAT_TCAM & flags) { 3876 SOC_SER_TCAM_ERROR_STAT_ALL_BTYPE_ETYPE_CLEAR(unit, ctype); 3877 } else { 3878 SOC_SER_ERROR_STAT_ALL_BTYPE_ETYPE_CLEAR(unit, ctype); 3879 } 3880 } /* All block and correction types */ 3881 else if (btype == SocSerBlockTypeAll && 3882 etype != SocSerErrorTypeAll && 3883 ctype == SocSerCorrectTypeAll) { 3884 if (BCM_SWITCH_SER_STAT_TCAM & flags) { 3885 SOC_SER_TCAM_ERROR_STAT_ALL_BTYPE_CTYPE_CLEAR(unit, etype); 3886 } else { 3887 SOC_SER_ERROR_STAT_ALL_BTYPE_CTYPE_CLEAR(unit, etype); 3888 } 3889 } /* All error and correction types */ 3890 else if (btype != SocSerBlockTypeAll && 3891 etype == SocSerErrorTypeAll && 3892 ctype == SocSerCorrectTypeAll) { 3893 if (BCM_SWITCH_SER_STAT_TCAM & flags) { 3894 SOC_SER_TCAM_ERROR_STAT_ALL_ETYPE_CTYPE_CLEAR(unit, btype); 3895 } else { 3896 SOC_SER_ERROR_STAT_ALL_ETYPE_CTYPE_CLEAR(unit, btype); 3897 } 3898 } /* All block, error and correction types */ 3899 else if (btype == SocSerBlockTypeAll && 3900 etype == SocSerErrorTypeAll && 3901 ctype == SocSerCorrectTypeAll) { 3902 if (BCM_SWITCH_SER_STAT_TCAM & flags) { 3903 SOC_SER_TCAM_ERROR_STAT_ALL_BTYPE_ETYPE_CTYPE_CLEAR(unit); 3904 } else { 3905 SOC_SER_ERROR_STAT_ALL_BTYPE_ETYPE_CTYPE_CLEAR(unit); 3906 } 3907 } else { 3908 return (BCM_E_PARAM); 3909 } 3910 return rv; 3911 } 3912 3913 /* 3914 * Function: 3915 * bcm_td2_switch_ser_error_stat_clear 3916 * Purpose: 3917 * Clear SER error statistics for specified statistics type. 3918 * Parameters: 3919 * unit - (IN) Unit number. 3920 * type - (IN) SER error statistics type. 3921 * Returns: 3922 * BCM_E_xxx 3923 * Notes: 3924 */ 3925 int 3926 bcm_td2_switch_ser_error_stat_clear(int unit, 3927 bcm_switch_ser_error_stat_type_t stat_type) 3928 { 3929 int rv = BCM_E_NONE; 3930 soc_ser_block_type_t btype; 3931 soc_ser_error_type_t etype; 3932 soc_ser_correction_type_t ctype; 3933 3934 /* Parameter boundary check */ 3935 if (stat_type.block_type >= bcmSwitchBlockTypeCount || 3936 stat_type.error_type >= bcmSwitchErrorTypeCount || 3937 stat_type.correction_type >= bcmSwitchCorrectTypeCount || 3938 stat_type.block_type < bcmSwitchBlockTypeAll || 3939 stat_type.error_type < bcmSwitchErrorTypeAll || 3940 stat_type.correction_type < bcmSwitchCorrectTypeAll) { 3941 return (BCM_E_PARAM); 3942 } 3943 3944 BCM_IF_ERROR_RETURN 3945 (bcm_td2_ser_error_stat_type_mapping(unit, stat_type, &btype, 3946 &etype, &ctype)); 3947 3948 if (btype == SocSerBlockTypeAll || 3949 etype == SocSerErrorTypeAll || 3950 ctype == SocSerCorrectTypeAll) { 3951 /* Clear error count based on type */ 3952 SOC_SER_ERR_STAT_LOCK(unit); 3953 rv = bcm_td2_ser_error_clear_by_type(unit, stat_type.flags, btype, 3954 etype, ctype); 3955 SOC_SER_ERR_STAT_UNLOCK(unit); 3956 return rv; 3957 } 3958 3959 SOC_SER_ERR_STAT_LOCK(unit); 3960 if (BCM_SWITCH_SER_STAT_TCAM & stat_type.flags) { 3961 SOC_SER_TCAM_ERROR_STAT_CLEAR(unit, btype, etype, ctype); 3962 } else { 3963 SOC_SER_ERROR_STAT_CLEAR(unit, btype, etype, ctype); 3964 } 3965 SOC_SER_ERR_STAT_UNLOCK(unit); 3966 3967 return rv; 3968 } 3969 3970 #endif /* defined(BCM_TRIDENT2_SUPPORT) */