qos.c (104518B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: qos.c 8 * Purpose: Trident2 QoS functions 9 */ 10 11 #include <soc/mem.h> 12 #include <soc/debug.h> 13 #include <soc/cm.h> 14 #include <soc/drv.h> 15 #include <soc/register.h> 16 #include <soc/memory.h> 17 #include <soc/hash.h> 18 #include <soc/l2x.h> 19 #include <soc/trident2.h> 20 #include <bcm/l2.h> 21 #include <bcm/error.h> 22 #include <bcm/stat.h> 23 #include <bcm/fcoe.h> 24 #include <bcm_int/esw/trx.h> 25 #include <bcm_int/esw/l2.h> 26 #include <bcm_int/esw/qos.h> 27 #include <bcm_int/esw/fcoe.h> 28 #include <bcm_int/esw/trident.h> 29 #include <bcm_int/esw/trident2.h> 30 #include <bcm_int/esw/triumph2.h> 31 #include <bcm_int/esw/xgs3.h> 32 #ifdef BCM_TRIDENT3_SUPPORT 33 #include <bcm_int/esw/trident3.h> 34 #endif 35 36 #ifdef BCM_TRIDENT2_SUPPORT 37 38 #define _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP 8 39 #define _BCM_QOS_MAP_CHUNK_VSAN_PRI_MAP 64 40 #define _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP 16 41 #define _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP 64 42 43 #define _BCM_QOS_MAX_VFT_PRIORITIES 8 44 #define _BCM_QOS_MAX_VSAN_PRIORITIES 16 45 #define _BCM_QOS_MAX_PKT_PRIORITIES 8 46 #define _BCM_QOS_MAX_INT_PRIORITIES 16 47 #define _BCM_QOS_MAX_PKT_DES 2 48 #define _BCM_QOS_PRI_BIT_SHIFT 2 49 50 #define _BCM_QOS_MAX_VFT_PRI_MAPS \ 51 ((SOC_MEM_IS_VALID(unit, ING_VFT_PRI_MAPm)) ? \ 52 (soc_mem_index_count(unit, ING_VFT_PRI_MAPm)/ \ 53 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP) : 0) 54 55 #define _BCM_QOS_MAX_VSAN_PRI_MAPS \ 56 (soc_mem_index_count(unit, EGR_VSAN_INTPRI_MAPm)/ \ 57 _BCM_QOS_MAP_CHUNK_VSAN_PRI_MAP) 58 59 #define _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS \ 60 (soc_mem_index_count(unit, ING_ETAG_PCP_MAPPINGm)/ \ 61 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP) 62 63 #define _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS \ 64 (soc_mem_is_valid(unit, VFT_QOS_INFO(unit)->egr_etag_mem) ? \ 65 (soc_mem_index_count(unit, VFT_QOS_INFO(unit)->egr_etag_mem)/ \ 66 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP) : 0) 67 68 #define _BCM_QOS_MAX_VFT_PRI_MAP_IDS ((_BCM_QOS_MAX_VFT_PRI_MAPS) * 8) 69 #define _BCM_QOS_MAX_VSAN_PRI_MAP_IDS ((_BCM_QOS_MAX_VSAN_PRI_MAPS) * 8) 70 #define _BCM_QOS_MAX_L2_VLAN_ETAG_MAP_IDS ((_BCM_QOS_MAX_L2_VLAN_ETAG_MAPS)\ 71 * _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP) 72 #define _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAP_IDS ((_BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS)\ 73 * _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP) 74 75 76 #define _BCM_QOS_MAP_TYPE_MASK 0x7ff 77 #define _BCM_QOS_MAP_SHIFT 11 78 79 #define _BCM_QOS_NO_MAP -1 80 81 typedef struct _bcm_td2_qos_bookkeeping_s { 82 SHR_BITDCL *ing_vft_pri_map; 83 uint32 *ing_vft_pri_map_hwidx; 84 SHR_BITDCL *ing_l2_vlan_etag_map; 85 uint32 *ing_l2_vlan_etag_map_hwidx; 86 SHR_BITDCL *egr_vft_pri_map; 87 uint32 *egr_vft_pri_map_hwidx; 88 SHR_BITDCL *egr_vsan_intpri_map; 89 uint32 *egr_vsan_intpri_map_hwidx; 90 SHR_BITDCL *egr_l2_vlan_etag_map; 91 uint32 *egr_l2_vlan_etag_map_hwidx; 92 sal_mutex_t qos_mutex; 93 soc_mem_t egr_etag_mem; 94 } _bcm_td2_qos_bookkeeping_t; 95 96 static _bcm_td2_qos_bookkeeping_t _bcm_td2_qos_bk_info[BCM_MAX_NUM_UNITS]; 97 static int _bcm_td2_qos_initialized[BCM_MAX_NUM_UNITS] = { 0 }; 98 99 #define VFT_QOS_INFO(_unit_) (&_bcm_td2_qos_bk_info[_unit_]) 100 101 #define _BCM_QOS_ING_VFT_PRI_MAP_TABLE_USED_GET(_u_, _identifier_) \ 102 SHR_BITGET(VFT_QOS_INFO(_u_)->ing_vft_pri_map, (_identifier_)) 103 #define _BCM_QOS_ING_VFT_PRI_MAP_TABLE_USED_SET(_u_, _identifier_) \ 104 SHR_BITSET(VFT_QOS_INFO((_u_))->ing_vft_pri_map, (_identifier_)) 105 #define _BCM_QOS_ING_VFT_PRI_MAP_TABLE_USED_CLR(_u_, _identifier_) \ 106 SHR_BITCLR(VFT_QOS_INFO((_u_))->ing_vft_pri_map, (_identifier_)) 107 108 #define _BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(_u_, _identifier_) \ 109 SHR_BITGET(VFT_QOS_INFO(_u_)->ing_l2_vlan_etag_map, (_identifier_)) 110 #define _BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_SET(_u_, _identifier_) \ 111 SHR_BITSET(VFT_QOS_INFO((_u_))->ing_l2_vlan_etag_map, (_identifier_)) 112 #define _BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_CLR(_u_, _identifier_) \ 113 SHR_BITCLR(VFT_QOS_INFO((_u_))->ing_l2_vlan_etag_map, (_identifier_)) 114 115 #define _BCM_QOS_EGR_VFT_PRI_MAP_TABLE_USED_GET(_u_, _identifier_) \ 116 SHR_BITGET(VFT_QOS_INFO(_u_)->egr_vft_pri_map, (_identifier_)) 117 #define _BCM_QOS_EGR_VFT_PRI_MAP_TABLE_USED_SET(_u_, _identifier_) \ 118 SHR_BITSET(VFT_QOS_INFO((_u_))->egr_vft_pri_map, (_identifier_)) 119 #define _BCM_QOS_EGR_VFT_PRI_MAP_TABLE_USED_CLR(_u_, _identifier_) \ 120 SHR_BITCLR(VFT_QOS_INFO((_u_))->egr_vft_pri_map, (_identifier_)) 121 122 #define _BCM_QOS_EGR_VSAN_PRI_MAP_TABLE_USED_GET(_u_, _identifier_) \ 123 SHR_BITGET(VFT_QOS_INFO(_u_)->egr_vsan_intpri_map, (_identifier_)) 124 #define _BCM_QOS_EGR_VSAN_PRI_MAP_TABLE_USED_SET(_u_, _identifier_) \ 125 SHR_BITSET(VFT_QOS_INFO((_u_))->egr_vsan_intpri_map, (_identifier_)) 126 #define _BCM_QOS_EGR_VSAN_PRI_MAP_TABLE_USED_CLR(_u_, _identifier_) \ 127 SHR_BITCLR(VFT_QOS_INFO((_u_))->egr_vsan_intpri_map, (_identifier_)) 128 129 #define _BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(_u_, _identifier_) \ 130 SHR_BITGET(VFT_QOS_INFO(_u_)->egr_l2_vlan_etag_map, (_identifier_)) 131 #define _BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_SET(_u_, _identifier_) \ 132 SHR_BITSET(VFT_QOS_INFO((_u_))->egr_l2_vlan_etag_map, (_identifier_)) 133 #define _BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_CLR(_u_, _identifier_) \ 134 SHR_BITCLR(VFT_QOS_INFO((_u_))->egr_l2_vlan_etag_map, (_identifier_)) 135 136 137 #define QOS_LOCK(unit) \ 138 sal_mutex_take(VFT_QOS_INFO(unit)->qos_mutex, sal_mutex_FOREVER); 139 #define QOS_UNLOCK(unit) \ 140 sal_mutex_give(VFT_QOS_INFO(unit)->qos_mutex); 141 142 #define QOS_INIT(unit) \ 143 do { \ 144 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { \ 145 return BCM_E_UNIT; \ 146 } \ 147 if (!_bcm_td2_qos_initialized[unit]) { \ 148 return BCM_E_INIT; \ 149 } \ 150 } while (0) 151 152 153 #define TD2_HW_COLOR_GREEN 0 154 #define TD2_HW_COLOR_YELLOW 3 155 #define TD2_HW_COLOR_RED 1 156 #define TD2_HW_COLOR_ERROR -1 157 158 159 /* 160 * Function: 161 * _bcm_td2_qos_map_id_alloc 162 * Purpose: 163 * Allocate a new QOS map ID. The bitmap given contains bits set for 164 * existing IDs, so find the first empty one, set it, and return it. 165 * Parameters: 166 * unit - (IN) Unit to be operated on 167 * bitmap - (IN/OUT) 168 * id - (OUT) 169 * Returns: 170 * BCM_E_XXX 171 */ 172 STATIC int 173 _bcm_td2_qos_map_id_alloc(int unit, SHR_BITDCL *bitmap, int *id, 174 int map_size) 175 { 176 int i; 177 178 for (i = 0; i < map_size; i++) { 179 if (!SHR_BITGET(bitmap, i)) { 180 SHR_BITSET(bitmap, i); 181 *id = i; 182 return BCM_E_NONE; 183 } 184 } 185 186 return BCM_E_RESOURCE; 187 } 188 189 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 190 /* 191 * Function: 192 * _bcm_td2_qos_sw_dump 193 * Purpose: 194 * Displays QOS software state info 195 * Parameters: 196 * unit : (IN) Device Unit Number 197 * Returns: 198 * NONE 199 */ 200 void 201 _bcm_td2_qos_sw_dump(int unit) 202 { 203 int i; 204 if (!_bcm_td2_qos_initialized[unit]) { 205 LOG_CLI((BSL_META_U(unit, 206 "ERROR: QOS module not initialized on Unit:%d \n"), unit)); 207 return; 208 } 209 210 LOG_CLI((BSL_META_U(unit, 211 "QOS: ING_L2_VLAN_ETAG_MAP info \n"))); 212 for (i = 0; i < _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; i++) { 213 if (_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, i)) { 214 LOG_CLI((BSL_META_U(unit, 215 " map id:%4d HW index:%4d\n"), i, 216 VFT_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[i])); 217 } 218 } 219 220 LOG_CLI((BSL_META_U(unit, 221 "QOS: EGR_L2_VLAN_ETAG_MAP info \n"))); 222 for (i = 0; i < _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; i++) { 223 if (_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, i)) { 224 LOG_CLI((BSL_META_U(unit, 225 " map id:%4d HW index:%4d\n"), i, 226 VFT_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[i])); 227 } 228 } 229 230 LOG_CLI((BSL_META_U(unit, 231 "QOS: ING_VFT_PRI_MAP info \n"))); 232 for (i = 0; i < _BCM_QOS_MAX_VFT_PRI_MAPS; i++) { 233 if (_BCM_QOS_ING_VFT_PRI_MAP_TABLE_USED_GET(unit, i)) { 234 LOG_CLI((BSL_META_U(unit, 235 " map id:%4d HW index:%4d\n"), i, 236 VFT_QOS_INFO(unit)->ing_vft_pri_map_hwidx[i])); 237 } 238 } 239 240 LOG_CLI((BSL_META_U(unit, 241 "QOS: EGR_VFT_PRI_MAP info \n"))); 242 for (i = 0; i < _BCM_QOS_MAX_VFT_PRI_MAPS; i++) { 243 if (_BCM_QOS_EGR_VFT_PRI_MAP_TABLE_USED_GET(unit, i)) { 244 LOG_CLI((BSL_META_U(unit, 245 " map id:%4d HW index:%4d\n"), i, 246 VFT_QOS_INFO(unit)->egr_vft_pri_map_hwidx[i])); 247 } 248 } 249 250 LOG_CLI((BSL_META_U(unit, 251 "QOS: EGR_VSAN_PRI_MAP info \n"))); 252 for (i = 0; i < _BCM_QOS_MAX_VSAN_PRI_MAPS; i++) { 253 if (_BCM_QOS_EGR_VSAN_PRI_MAP_TABLE_USED_GET(unit, i)) { 254 LOG_CLI((BSL_META_U(unit, 255 " map id:%4d HW index:%4d\n"), i, 256 VFT_QOS_INFO(unit)->egr_vsan_intpri_map_hwidx[i])); 257 } 258 } 259 } 260 261 #endif 262 #ifdef BCM_WARM_BOOT_SUPPORT 263 264 #define _BCM_TD2_REINIT_INVALID_HW_IDX 0xff /* used as an invalid hw idx */ 265 266 /* 267 * Function: 268 * _bcm_td2_qos_reinit_scache_len_get 269 * Purpose: 270 * Helper utility to determine scache details. 271 * Parameters: 272 * unit : (IN) Device Unit Number 273 * scache_len : (OUT) Total required scache length 274 * Returns: 275 * BCM_E_XXX 276 */ 277 int 278 _bcm_td2_qos_reinit_scache_len_get(int unit, uint32 *scache_len) 279 { 280 if (scache_len == NULL) { 281 return BCM_E_PARAM; 282 } 283 284 /* TD2 wb will store bookeeping data as 4 bytes per hw_index */ 285 *scache_len += _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS * sizeof(uint32); 286 *scache_len += _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS * sizeof(uint32); 287 *scache_len += _BCM_QOS_MAX_VFT_PRI_MAPS * 2 * sizeof(uint32); 288 *scache_len += _BCM_QOS_MAX_VSAN_PRI_MAPS * sizeof(uint32); 289 290 return BCM_E_NONE; 291 } 292 293 int 294 _bcm_td2_qos_reinit_from_hw_state(int unit, soc_mem_t mem, soc_field_t field, 295 uint8 map_type, SHR_BITDCL *hw_idx_bmp, 296 int hw_idx_bmp_len) 297 { 298 int rv = BCM_E_NONE; 299 int idx, min_idx, max_idx, map_size, map_id, hw_prof_idx; 300 uint32 buf[SOC_MAX_MEM_FIELD_WORDS]; 301 uint32 *hw_idx_table; 302 SHR_BITDCL *map_bmp; 303 304 switch (map_type) { 305 case _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP: 306 map_bmp = VFT_QOS_INFO(unit)->ing_l2_vlan_etag_map; 307 hw_idx_table = VFT_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx; 308 map_size = _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; 309 break; 310 case _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP: 311 map_bmp = VFT_QOS_INFO(unit)->egr_l2_vlan_etag_map; 312 hw_idx_table = VFT_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx; 313 map_size = _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; 314 break; 315 case _BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP: 316 map_bmp = VFT_QOS_INFO(unit)->ing_vft_pri_map; 317 hw_idx_table = VFT_QOS_INFO(unit)->ing_vft_pri_map_hwidx; 318 map_size = _BCM_QOS_MAX_VFT_PRI_MAPS; 319 break; 320 case _BCM_QOS_MAP_TYPE_EGR_VFT_PRI_MAP: 321 map_bmp = VFT_QOS_INFO(unit)->egr_vft_pri_map; 322 hw_idx_table = VFT_QOS_INFO(unit)->egr_vft_pri_map_hwidx; 323 map_size = _BCM_QOS_MAX_VFT_PRI_MAPS; 324 break; 325 case _BCM_QOS_MAP_TYPE_EGR_VSAN_PRI_MAP: 326 map_bmp = VFT_QOS_INFO(unit)->egr_vsan_intpri_map; 327 hw_idx_table = VFT_QOS_INFO(unit)->egr_vsan_intpri_map_hwidx; 328 map_size = _BCM_QOS_MAX_VSAN_PRI_MAPS; 329 break; 330 default: 331 return BCM_E_PARAM; 332 } 333 334 min_idx = soc_mem_index_min(unit, mem); 335 max_idx = soc_mem_index_max(unit, mem); 336 337 for (idx = min_idx; idx <= max_idx; idx++) { 338 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, &buf); 339 if (SOC_FAILURE(rv)) { 340 LOG_ERROR(BSL_LS_BCM_QOS, 341 (BSL_META_U(unit, 342 "Error(%s) reading mem(%d) at " 343 "index:%d \n"), soc_errmsg(rv), mem, idx)); 344 return rv; 345 } 346 347 hw_prof_idx = soc_mem_field32_get(unit, mem, &buf, field); 348 349 if (hw_prof_idx > (hw_idx_bmp_len - 1)) { 350 LOG_ERROR(BSL_LS_BCM_QOS, 351 (BSL_META_U(unit, 352 "Invalid profile(%d) in mem(%d) " 353 "at index:%d\n"), hw_prof_idx, mem, idx)); 354 return BCM_E_INTERNAL; 355 } 356 if (hw_prof_idx && (!SHR_BITGET(hw_idx_bmp, hw_prof_idx))) { 357 /* non-zero profile id and not stored previously */ 358 BCM_IF_ERROR_RETURN(_bcm_td2_qos_map_id_alloc(unit, map_bmp, &map_id, 359 map_size)); 360 if (map_id < 0) { 361 LOG_ERROR(BSL_LS_BCM_QOS, 362 (BSL_META_U(unit, 363 "Invalid profile(%d) in mem" 364 "(%d) at index:%d\n"), hw_prof_idx, mem, idx)); 365 return BCM_E_RESOURCE; 366 } 367 hw_idx_table[map_id] = hw_prof_idx; 368 SHR_BITSET(hw_idx_bmp, hw_prof_idx); 369 SHR_BITSET(map_bmp, map_id); 370 } 371 } 372 373 return rv; 374 } 375 376 /* 377 * Function: 378 * _bcm_td2_qos_unsynchronized_reinit 379 * Purpose: 380 * This routine handles Level 1 Warmboot init. In this style of reinit, the 381 * map-ids allocated previously are not guaranteed to be the same. 382 * Cold-boot: Does nothing 383 * Warm-boot: The data-structures are populated by reading the HW tables. 384 * Parameters: 385 * unit : (IN) Device Unit Number 386 * Returns: 387 * BCM_E_XXX 388 */ 389 int 390 _bcm_td2_qos_unsynchronized_reinit(int unit) 391 { 392 int rv = BCM_E_NONE; 393 int bmp_len; 394 SHR_BITDCL *temp_bmp; 395 396 if (SOC_IS_TRIDENT3X(unit)) { 397 VFT_QOS_INFO(unit)->egr_etag_mem = EGR_ZONE_3_DOT1P_MAPPING_TABLE_2m; 398 } else { 399 VFT_QOS_INFO(unit)->egr_etag_mem = EGR_ETAG_PCP_MAPPINGm; 400 } 401 402 /* read hw tables and populate the state */ 403 bmp_len = _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; 404 temp_bmp = NULL; 405 temp_bmp = sal_alloc(SHR_BITALLOCSIZE(bmp_len), "temp_bmp"); 406 if (temp_bmp == NULL) { 407 return BCM_E_MEMORY; 408 } 409 sal_memset(temp_bmp, 0x0, SHR_BITALLOCSIZE(bmp_len)); 410 411 if (SOC_IS_TRIDENT3X(unit)) { 412 rv = _bcm_td2_qos_reinit_from_hw_state(unit, LPORT_TABm, 413 ETAG_PCP_DE_MAPPING_PTRf, 414 _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP, 415 temp_bmp, bmp_len); 416 } else { 417 if (soc_mem_is_valid(unit, PORT_TABm)) { 418 rv = _bcm_td2_qos_reinit_from_hw_state(unit, PORT_TABm, 419 ETAG_PCP_DE_MAPPING_PTRf, 420 _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP, 421 temp_bmp, bmp_len); 422 } 423 } 424 sal_free(temp_bmp); 425 426 /* now extract EGR_MPLS_PRI_MAPPING state */ 427 if (BCM_SUCCESS(rv)) { 428 bmp_len = _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; 429 temp_bmp = NULL; 430 temp_bmp = sal_alloc(SHR_BITALLOCSIZE(bmp_len), "temp_bmp"); 431 if (temp_bmp == NULL) { 432 return BCM_E_MEMORY; 433 } 434 sal_memset(temp_bmp, 0x0, SHR_BITALLOCSIZE(bmp_len)); 435 if (SOC_IS_TRIDENT3X(unit)) { 436 rv = _bcm_td2_qos_reinit_from_hw_state(unit, LPORT_TABm, 437 ETAG_DOT1P_MAPPING_PTRf, 438 _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP, 439 temp_bmp, bmp_len); 440 } else { 441 if (soc_mem_field_valid(unit, PORT_TABm, 442 ETAG_DOT1P_MAPPING_PTRf)) { 443 rv = _bcm_td2_qos_reinit_from_hw_state(unit, PORT_TABm, 444 ETAG_DOT1P_MAPPING_PTRf, 445 _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP, 446 temp_bmp, bmp_len); 447 } 448 } 449 sal_free(temp_bmp); 450 } 451 452 /* now extract ING_VFT_PRI_MAPPING state */ 453 if (BCM_SUCCESS(rv)) { 454 bmp_len = _BCM_QOS_MAX_VFT_PRI_MAPS; 455 temp_bmp = NULL; 456 temp_bmp = sal_alloc(SHR_BITALLOCSIZE(bmp_len), "temp_bmp"); 457 if (temp_bmp == NULL) { 458 return BCM_E_MEMORY; 459 } 460 sal_memset(temp_bmp, 0x0, SHR_BITALLOCSIZE(bmp_len)); 461 if (SOC_IS_TRIDENT3X(unit)) { 462 rv = _bcm_td2_qos_reinit_from_hw_state(unit, LPORT_TABm, 463 FCOE_VFT_PRI_MAP_PROFILEf, 464 _BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP, 465 temp_bmp, bmp_len); 466 } else { 467 if (soc_mem_field_valid(unit, PORT_TABm, 468 FCOE_VFT_PRI_MAP_PROFILEf)) { 469 rv = _bcm_td2_qos_reinit_from_hw_state(unit, PORT_TABm, 470 FCOE_VFT_PRI_MAP_PROFILEf, 471 _BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP, 472 temp_bmp, bmp_len); 473 } 474 } 475 sal_free(temp_bmp); 476 } 477 478 /* now extract EGR_VFT_PRI_MAPPING state */ 479 if (BCM_SUCCESS(rv)) { 480 bmp_len = _BCM_QOS_MAX_VFT_PRI_MAPS; 481 temp_bmp = NULL; 482 temp_bmp = sal_alloc(SHR_BITALLOCSIZE(bmp_len), "temp_bmp"); 483 if (temp_bmp == NULL) { 484 return BCM_E_MEMORY; 485 } 486 sal_memset(temp_bmp, 0x0, SHR_BITALLOCSIZE(bmp_len)); 487 488 if (SOC_IS_TRIDENT3X(unit)) { 489 rv = _bcm_td2_qos_reinit_from_hw_state(unit, EGR_LPORT_PROFILEm, 490 FCOE_VFT_PRI_MAP_PROFILEf, 491 _BCM_QOS_MAP_TYPE_EGR_VFT_PRI_MAP, 492 temp_bmp, bmp_len); 493 } else { 494 if (soc_mem_field_valid(unit, EGR_PORTm, 495 FCOE_VFT_PRI_MAP_PROFILEf)) { 496 rv = _bcm_td2_qos_reinit_from_hw_state(unit, EGR_PORTm, 497 FCOE_VFT_PRI_MAP_PROFILEf, 498 _BCM_QOS_MAP_TYPE_EGR_VFT_PRI_MAP, 499 temp_bmp, bmp_len); 500 } 501 } 502 sal_free(temp_bmp); 503 } 504 505 /* now extract EGR_VSAN_PRI_MAPPING state */ 506 if (BCM_SUCCESS(rv)) { 507 bmp_len = _BCM_QOS_MAX_VSAN_PRI_MAPS; 508 temp_bmp = NULL; 509 temp_bmp = sal_alloc(SHR_BITALLOCSIZE(bmp_len), "temp_bmp"); 510 if (temp_bmp == NULL) { 511 return BCM_E_MEMORY; 512 } 513 sal_memset(temp_bmp, 0x0, SHR_BITALLOCSIZE(bmp_len)); 514 if (soc_mem_field_valid(unit, EGR_L3_INTFm, 515 FCOE_VSAN_PRI_MAPPING_PROFILEf)) { 516 rv = _bcm_td2_qos_reinit_from_hw_state(unit, EGR_L3_INTFm, 517 FCOE_VSAN_PRI_MAPPING_PROFILEf, 518 _BCM_QOS_MAP_TYPE_EGR_VSAN_PRI_MAP, 519 temp_bmp, bmp_len); 520 } 521 sal_free(temp_bmp); 522 } 523 524 return rv; 525 } 526 527 /* 528 * Function: 529 * _bcm_td2_qos_extended_reinit 530 * Purpose: 531 * This routine handles Level 2 Warmboot init. 532 * Cold-boot: scache location is allocated. 533 * Warm-boot: The data-structs are populated from recovered scache state 534 * Parameters: 535 * unit : (IN) Device Unit Number 536 * Returns: 537 * BCM_E_XXX 538 */ 539 int 540 _bcm_td2_qos_extended_reinit(int unit, uint8 **scache_ptr) 541 { 542 uint32 hw_idx; 543 int idx; 544 545 for (idx = 0; idx < _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; idx++) { 546 sal_memcpy(&hw_idx, (*scache_ptr), sizeof(uint32)); 547 (*scache_ptr) += sizeof(hw_idx); 548 if (hw_idx != _BCM_TD2_REINIT_INVALID_HW_IDX) { 549 _BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_SET(unit, idx); 550 VFT_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[idx] = hw_idx; 551 } 552 } 553 for (idx = 0; idx < _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; idx++) { 554 sal_memcpy(&hw_idx, (*scache_ptr), sizeof(uint32)); 555 (*scache_ptr) += sizeof(hw_idx); 556 if (hw_idx != _BCM_TD2_REINIT_INVALID_HW_IDX) { 557 _BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_SET(unit, idx); 558 VFT_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[idx] = hw_idx; 559 } 560 } 561 for (idx = 0; idx < _BCM_QOS_MAX_VFT_PRI_MAPS; idx++) { 562 sal_memcpy(&hw_idx, (*scache_ptr), sizeof(uint32)); 563 (*scache_ptr) += sizeof(hw_idx); 564 if (hw_idx != _BCM_TD2_REINIT_INVALID_HW_IDX) { 565 _BCM_QOS_ING_VFT_PRI_MAP_TABLE_USED_SET(unit, idx); 566 VFT_QOS_INFO(unit)->ing_vft_pri_map_hwidx[idx] = hw_idx; 567 } 568 } 569 for (idx = 0; idx < _BCM_QOS_MAX_VFT_PRI_MAPS; idx++) { 570 sal_memcpy(&hw_idx, (*scache_ptr), sizeof(uint32)); 571 (*scache_ptr) += sizeof(hw_idx); 572 if (hw_idx != _BCM_TD2_REINIT_INVALID_HW_IDX) { 573 _BCM_QOS_EGR_VFT_PRI_MAP_TABLE_USED_SET(unit, idx); 574 VFT_QOS_INFO(unit)->egr_vft_pri_map_hwidx[idx] = hw_idx; 575 } 576 } 577 for (idx = 0; idx < _BCM_QOS_MAX_VSAN_PRI_MAPS; idx++) { 578 sal_memcpy(&hw_idx, (*scache_ptr), sizeof(uint32)); 579 (*scache_ptr) += sizeof(hw_idx); 580 if (hw_idx != _BCM_TD2_REINIT_INVALID_HW_IDX) { 581 _BCM_QOS_EGR_VSAN_PRI_MAP_TABLE_USED_SET(unit, idx); 582 VFT_QOS_INFO(unit)->egr_vsan_intpri_map_hwidx[idx] = hw_idx; 583 } 584 } 585 586 return BCM_E_NONE; 587 } 588 589 590 /* 591 * Function: 592 * _bcm_td2_qos_reinit_hw_profiles_update 593 * Purpose: 594 * Updates the shared memory profile tables reference counts 595 * Parameters: 596 * unit : (IN) Device Unit Number 597 * Returns: 598 * BCM_E_XXX 599 */ 600 int 601 _bcm_td2_qos_reinit_hw_profiles_update(int unit) 602 { 603 int i; 604 605 for (i = 0; i < _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; i++) { 606 if (_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, i)) { 607 BCM_IF_ERROR_RETURN(_bcm_ing_l2_vlan_etag_map_entry_reference(unit, 608 ((VFT_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[i]) * 609 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP), 610 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP)); 611 } 612 } 613 for (i = 0; i < _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; i++) { 614 if (_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, i)) { 615 BCM_IF_ERROR_RETURN(_bcm_egr_l2_vlan_etag_map_entry_reference(unit, 616 ((VFT_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[i]) * 617 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP), 618 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP)); 619 } 620 } 621 for (i = 0; i < _BCM_QOS_MAX_VFT_PRI_MAPS; i++) { 622 if (_BCM_QOS_ING_VFT_PRI_MAP_TABLE_USED_GET(unit, i)) { 623 BCM_IF_ERROR_RETURN(_bcm_ing_vft_pri_map_entry_reference(unit, 624 ((VFT_QOS_INFO(unit)->ing_vft_pri_map_hwidx[i]) * 625 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP), 626 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP)); 627 } 628 } 629 for (i = 0; i < _BCM_QOS_MAX_VFT_PRI_MAPS; i++) { 630 if (_BCM_QOS_EGR_VFT_PRI_MAP_TABLE_USED_GET(unit, i)) { 631 BCM_IF_ERROR_RETURN(_bcm_egr_vft_pri_map_entry_reference(unit, 632 ((VFT_QOS_INFO(unit)->egr_vft_pri_map_hwidx[i]) * 633 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP), 634 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP)); 635 } 636 } 637 for (i = 0; i < _BCM_QOS_MAX_VSAN_PRI_MAPS; i++) { 638 if (_BCM_QOS_EGR_VSAN_PRI_MAP_TABLE_USED_GET(unit, i)) { 639 BCM_IF_ERROR_RETURN(_bcm_egr_vsan_intpri_map_entry_reference(unit, 640 ((VFT_QOS_INFO(unit)->egr_vsan_intpri_map_hwidx[i]) * 641 _BCM_QOS_MAP_CHUNK_VSAN_PRI_MAP), 642 _BCM_QOS_MAP_CHUNK_VSAN_PRI_MAP)); 643 } 644 } 645 646 return BCM_E_NONE; 647 } 648 649 650 /* 651 * Function: 652 * bcm_td2_qos_sync 653 * Purpose: 654 * This routine extracts the state that needs to be stored from the 655 * book-keeping structs and stores it in the allocated scache location 656 * Compression format: 0 - A l2_vlan_etag table 657 * A+1 - B egr_l2_vlan_etag table 658 * Parameters: 659 * unit : (IN) Device Unit Number 660 * Returns: 661 * BCM_E_XXX 662 */ 663 int 664 _bcm_td2_qos_sync(int unit, uint8 **scache_ptr) 665 { 666 uint32 hw_idx; 667 int idx; 668 669 /* now store the state into the compressed format */ 670 for (idx = 0; idx < _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; idx++) { 671 if (_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, idx)) { 672 hw_idx = VFT_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[idx]; 673 } else { 674 hw_idx = _BCM_TD2_REINIT_INVALID_HW_IDX; 675 } 676 sal_memcpy((*scache_ptr), &hw_idx, sizeof(uint32)); 677 (*scache_ptr) += sizeof(hw_idx); 678 } 679 for (idx = 0; idx < _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; idx++) { 680 if (_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, idx)) { 681 hw_idx = VFT_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[idx]; 682 } else { 683 hw_idx = _BCM_TD2_REINIT_INVALID_HW_IDX; 684 } 685 sal_memcpy((*scache_ptr), &hw_idx, sizeof(uint32)); 686 (*scache_ptr) += sizeof(hw_idx); 687 } 688 for (idx = 0; idx < _BCM_QOS_MAX_VFT_PRI_MAPS; idx++) { 689 if (_BCM_QOS_ING_VFT_PRI_MAP_TABLE_USED_GET(unit, idx)) { 690 hw_idx = VFT_QOS_INFO(unit)->ing_vft_pri_map_hwidx[idx]; 691 } else { 692 hw_idx = _BCM_TD2_REINIT_INVALID_HW_IDX; 693 } 694 sal_memcpy((*scache_ptr), &hw_idx, sizeof(uint32)); 695 (*scache_ptr) += sizeof(hw_idx); 696 } 697 for (idx = 0; idx < _BCM_QOS_MAX_VFT_PRI_MAPS; idx++) { 698 if (_BCM_QOS_EGR_VFT_PRI_MAP_TABLE_USED_GET(unit, idx)) { 699 hw_idx = VFT_QOS_INFO(unit)->egr_vft_pri_map_hwidx[idx]; 700 } else { 701 hw_idx = _BCM_TD2_REINIT_INVALID_HW_IDX; 702 } 703 sal_memcpy((*scache_ptr), &hw_idx, sizeof(uint32)); 704 (*scache_ptr) += sizeof(hw_idx); 705 } 706 for (idx = 0; idx < _BCM_QOS_MAX_VSAN_PRI_MAPS; idx++) { 707 if (_BCM_QOS_EGR_VSAN_PRI_MAP_TABLE_USED_GET(unit, idx)) { 708 hw_idx = VFT_QOS_INFO(unit)->egr_vsan_intpri_map_hwidx[idx]; 709 } else { 710 hw_idx = _BCM_TD2_REINIT_INVALID_HW_IDX; 711 } 712 sal_memcpy((*scache_ptr), &hw_idx, sizeof(uint32)); 713 (*scache_ptr) += sizeof(hw_idx); 714 } 715 716 return BCM_E_NONE; 717 } 718 719 #endif /* BCM_WARM_BOOT_SUPPORT */ 720 721 /* 722 * Function: 723 * _bcm_td2_qos_free_resources 724 * Purpose: 725 * Free TD2 QOS bookkeeping resources associated with a given unit. This 726 * happens either during an error initializing or during a detach operation. 727 * Parameters: 728 * unit - (IN) Unit to free resources of 729 * Returns: 730 * BCM_E_XXX 731 */ 732 STATIC void 733 _bcm_td2_qos_free_resources(int unit) 734 { 735 _bcm_td2_qos_bookkeeping_t *qos_info = VFT_QOS_INFO(unit); 736 737 if (!qos_info) { 738 /* 739 * Coverity 740 * This is defencive statement. 741 */ 742 /* coverity[dead_error_line] */ 743 return; 744 } 745 746 if (qos_info->ing_vft_pri_map) { 747 sal_free(qos_info->ing_vft_pri_map); 748 qos_info->ing_vft_pri_map = NULL; 749 } 750 751 if (qos_info->ing_vft_pri_map_hwidx) { 752 sal_free(qos_info->ing_vft_pri_map_hwidx); 753 qos_info->ing_vft_pri_map_hwidx = NULL; 754 } 755 756 if (qos_info->ing_l2_vlan_etag_map) { 757 sal_free(qos_info->ing_l2_vlan_etag_map); 758 qos_info->ing_l2_vlan_etag_map = NULL; 759 } 760 761 if (qos_info->ing_l2_vlan_etag_map_hwidx) { 762 sal_free(qos_info->ing_l2_vlan_etag_map_hwidx); 763 qos_info->ing_l2_vlan_etag_map_hwidx = NULL; 764 } 765 766 if (qos_info->egr_vft_pri_map) { 767 sal_free(qos_info->egr_vft_pri_map); 768 qos_info->egr_vft_pri_map = NULL; 769 } 770 771 if (qos_info->egr_vft_pri_map_hwidx) { 772 sal_free(qos_info->egr_vft_pri_map_hwidx); 773 qos_info->egr_vft_pri_map_hwidx = NULL; 774 } 775 776 if (qos_info->egr_vsan_intpri_map) { 777 sal_free(qos_info->egr_vsan_intpri_map); 778 qos_info->egr_vsan_intpri_map = NULL; 779 } 780 781 if (qos_info->egr_vft_pri_map_hwidx) { 782 sal_free(qos_info->egr_vft_pri_map_hwidx); 783 qos_info->egr_vft_pri_map_hwidx = NULL; 784 } 785 786 if (qos_info->egr_l2_vlan_etag_map) { 787 sal_free(qos_info->egr_l2_vlan_etag_map); 788 qos_info->egr_l2_vlan_etag_map = NULL; 789 } 790 791 if (qos_info->egr_l2_vlan_etag_map_hwidx) { 792 sal_free(qos_info->egr_l2_vlan_etag_map_hwidx); 793 qos_info->egr_l2_vlan_etag_map_hwidx = NULL; 794 } 795 796 if (qos_info->egr_vsan_intpri_map_hwidx) { 797 sal_free(qos_info->egr_vsan_intpri_map_hwidx); 798 qos_info->egr_vsan_intpri_map_hwidx = NULL; 799 } 800 801 if (qos_info->qos_mutex) { 802 sal_mutex_destroy(qos_info->qos_mutex); 803 qos_info->qos_mutex = NULL; 804 } 805 806 } 807 808 /* 809 * Function: 810 * bcm_td2_qos_detach 811 * Purpose: 812 * Detach the QOS module. Called when the module should de-initialize. 813 * Parameters: 814 * unit - (IN) Unit being detached. 815 * Returns: 816 * BCM_E_XXX 817 */ 818 int 819 bcm_td2_qos_detach(int unit) 820 { 821 if (_bcm_td2_qos_initialized[unit]) { 822 _bcm_td2_qos_initialized[unit] = 0; 823 _bcm_td2_qos_free_resources(unit); 824 } 825 826 return BCM_E_NONE; 827 } 828 829 /* 830 * Function: 831 * bcm_td2_qos_init 832 * Purpose: 833 * Initialize the TD2 QOS module. Allocate bookkeeping information. 834 * Parameters: 835 * unit - (IN) Unit being initialized 836 * Returns: 837 * BCM_E_XXX 838 */ 839 int 840 bcm_td2_qos_init(int unit) 841 { 842 _bcm_td2_qos_bookkeeping_t *qos_info = VFT_QOS_INFO(unit); 843 int vft_map_size = 0; 844 int vsan_map_size = _BCM_QOS_MAX_VSAN_PRI_MAPS; 845 int l2_vlan_tag_map_size = _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; 846 int egr_l2_vlan_tag_map_size; 847 848 if (_bcm_td2_qos_initialized[unit]) { 849 BCM_IF_ERROR_RETURN(bcm_td2_qos_detach(unit)); 850 } 851 852 memset(qos_info, 0, sizeof *qos_info); 853 854 if (SOC_IS_TRIDENT3X(unit)) { 855 qos_info->egr_etag_mem = EGR_ZONE_3_DOT1P_MAPPING_TABLE_2m; 856 } else { 857 qos_info->egr_etag_mem = EGR_ETAG_PCP_MAPPINGm; 858 } 859 /* Macro relies on above code to enable */ 860 egr_l2_vlan_tag_map_size = _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; 861 862 /* ingress priority map bitmap */ 863 if (soc_mem_is_valid(unit, ING_VFT_PRI_MAPm)) { 864 vft_map_size = _BCM_QOS_MAX_VFT_PRI_MAPS; 865 qos_info->ing_vft_pri_map = sal_alloc(SHR_BITALLOCSIZE(vft_map_size), 866 "ing_vft_pri_map"); 867 if (qos_info->ing_vft_pri_map == NULL) { 868 _bcm_td2_qos_free_resources(unit); 869 return BCM_E_MEMORY; 870 } 871 sal_memset(qos_info->ing_vft_pri_map, 0, SHR_BITALLOCSIZE(vft_map_size)); 872 873 /* ingress priority map hardware indexes */ 874 qos_info->ing_vft_pri_map_hwidx = sal_alloc(sizeof(uint32) * vft_map_size, 875 "ing_vft_pri_map_hwidx"); 876 if (qos_info->ing_vft_pri_map_hwidx == NULL) { 877 _bcm_td2_qos_free_resources(unit); 878 return BCM_E_MEMORY; 879 } 880 sal_memset(qos_info->ing_vft_pri_map_hwidx, 0, 881 sizeof(uint32) * vft_map_size); 882 } 883 /* ingress l2 vlan etag map bitmap */ 884 qos_info->ing_l2_vlan_etag_map = 885 sal_alloc(SHR_BITALLOCSIZE(l2_vlan_tag_map_size), 886 "ing_l2_vlan_etag_map"); 887 if (qos_info->ing_l2_vlan_etag_map == NULL) { 888 _bcm_td2_qos_free_resources(unit); 889 return BCM_E_MEMORY; 890 } 891 sal_memset(qos_info->ing_l2_vlan_etag_map, 0, 892 SHR_BITALLOCSIZE(l2_vlan_tag_map_size)); 893 894 /* ingress l2 vlan etag map hardware indexes */ 895 qos_info->ing_l2_vlan_etag_map_hwidx = 896 sal_alloc(sizeof(uint32) * l2_vlan_tag_map_size, 897 "ing_l2_vlan_etag_map_hwidx"); 898 if (qos_info->ing_l2_vlan_etag_map_hwidx == NULL) { 899 _bcm_td2_qos_free_resources(unit); 900 return BCM_E_MEMORY; 901 } 902 sal_memset(qos_info->ing_l2_vlan_etag_map_hwidx, 0, 903 sizeof(uint32) * l2_vlan_tag_map_size); 904 905 /* egress priority map bitmap */ 906 if (soc_mem_is_valid(unit, ING_VFT_PRI_MAPm)) { 907 qos_info->egr_vft_pri_map = sal_alloc(SHR_BITALLOCSIZE(vft_map_size), 908 "egr_vft_pri_map"); 909 if (qos_info->egr_vft_pri_map == NULL) { 910 _bcm_td2_qos_free_resources(unit); 911 return BCM_E_MEMORY; 912 } 913 sal_memset(qos_info->egr_vft_pri_map, 0, SHR_BITALLOCSIZE(vft_map_size)); 914 915 /* egress priority map hardware indexes */ 916 qos_info->egr_vft_pri_map_hwidx = sal_alloc(sizeof(uint32) * vft_map_size, 917 "egr_vft_pri_map_hwidx"); 918 if (qos_info->egr_vft_pri_map_hwidx == NULL) { 919 _bcm_td2_qos_free_resources(unit); 920 return BCM_E_MEMORY; 921 } 922 sal_memset(qos_info->egr_vft_pri_map_hwidx, 0, 923 sizeof(uint32) * vft_map_size); 924 } 925 /* egress vsan priority map bitmap */ 926 qos_info->egr_vsan_intpri_map = sal_alloc(SHR_BITALLOCSIZE(vsan_map_size), 927 "egr_vsan_intpri_map"); 928 if (qos_info->egr_vsan_intpri_map == NULL) { 929 _bcm_td2_qos_free_resources(unit); 930 return BCM_E_MEMORY; 931 } 932 sal_memset(qos_info->egr_vsan_intpri_map, 0, 933 SHR_BITALLOCSIZE(vsan_map_size)); 934 935 /* egress vsan priority map hardware indexes */ 936 qos_info->egr_vsan_intpri_map_hwidx = 937 sal_alloc(sizeof(uint32) * vsan_map_size, "egr_vsan_intpri_map_hwidx"); 938 if (qos_info->egr_vsan_intpri_map_hwidx == NULL) { 939 _bcm_td2_qos_free_resources(unit); 940 return BCM_E_MEMORY; 941 } 942 sal_memset(qos_info->egr_vsan_intpri_map_hwidx, 0, 943 sizeof(uint32) * vsan_map_size); 944 945 /* egress l2 vlan etag priority map bitmap */ 946 qos_info->egr_l2_vlan_etag_map = sal_alloc(SHR_BITALLOCSIZE(egr_l2_vlan_tag_map_size), 947 "egr_l2_vlan_etag_map"); 948 if (qos_info->egr_l2_vlan_etag_map == NULL) { 949 _bcm_td2_qos_free_resources(unit); 950 return BCM_E_MEMORY; 951 } 952 sal_memset(qos_info->egr_l2_vlan_etag_map, 0, 953 SHR_BITALLOCSIZE(egr_l2_vlan_tag_map_size)); 954 955 /* egress l2 vlan etag map hardware indexes */ 956 qos_info->egr_l2_vlan_etag_map_hwidx = 957 sal_alloc(sizeof(uint32) * egr_l2_vlan_tag_map_size, 958 "egr_l2_vlan_etag_map_hwidx"); 959 if (qos_info->egr_l2_vlan_etag_map_hwidx == NULL) { 960 _bcm_td2_qos_free_resources(unit); 961 return BCM_E_MEMORY; 962 } 963 sal_memset(qos_info->egr_l2_vlan_etag_map_hwidx, 0, 964 sizeof(uint32) * egr_l2_vlan_tag_map_size); 965 966 /* accessor mutex */ 967 qos_info->qos_mutex = sal_mutex_create("vft qos_mutex"); 968 if (qos_info->qos_mutex == NULL) { 969 _bcm_td2_qos_free_resources(unit); 970 return BCM_E_MEMORY; 971 } 972 973 #if defined(BCM_TRIDENT3_SUPPORT) 974 if (SOC_WARM_BOOT(unit)) { 975 if (SOC_IS_TRIDENT3X(unit)) { 976 BCM_IF_ERROR_RETURN(bcm_td3_qos_reinit(unit)); 977 } 978 } 979 #endif 980 981 _bcm_td2_qos_initialized[unit] = 1; 982 return BCM_E_NONE; 983 } 984 985 /* 986 * Function: 987 * _bcm_td2_qos_map_create_with_id 988 * Purpose: 989 * Allocate a new QOS map ID where the app has specified the ID. So just 990 * check that the requested ID is available, and mark it as used. 991 * Parameters: 992 * unit - (IN) Unit to be operated on 993 * flags - (IN) Used only to test if BCM_QOS_MAP_REPLACE is set 994 * bitmap - (IN/OUT) Bitmap containing the set of used IDs 995 * map_id - (IN) The ID requested by the application 996 * is_ingress - (IN) 1=ingress map, 0=egress map 997 * Returns: 998 * BCM_E_XXX 999 */ 1000 STATIC int 1001 _bcm_td2_qos_map_create_with_id(int unit, int flags, SHR_BITDCL *bitmap, 1002 int *map_id, int is_ingress, int max_ids) 1003 { 1004 int id = 0, map_type = 0, rv = BCM_E_NONE; 1005 1006 id = *map_id & _BCM_QOS_MAP_TYPE_MASK; 1007 map_type = *map_id >> _BCM_QOS_MAP_SHIFT; 1008 1009 if (id < 0 || id >= max_ids) { 1010 return BCM_E_BADID; 1011 } 1012 1013 if ((map_type == _BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP && is_ingress) 1014 || (map_type == _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP && is_ingress) 1015 || (map_type == _BCM_QOS_MAP_TYPE_EGR_VFT_PRI_MAP && !is_ingress) 1016 || (map_type == _BCM_QOS_MAP_TYPE_EGR_VSAN_PRI_MAP && !is_ingress) 1017 || (map_type == _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP && !is_ingress)) { 1018 1019 if (SHR_BITGET(bitmap, id) == 1) { 1020 if (!(flags & BCM_QOS_MAP_REPLACE)) { 1021 rv = BCM_E_EXISTS; 1022 } 1023 } 1024 1025 if (BCM_SUCCESS(rv)) { 1026 SHR_BITSET(bitmap, id); 1027 } 1028 } else { 1029 rv = BCM_E_PARAM; 1030 } 1031 1032 return rv; 1033 } 1034 1035 /* 1036 * Function: 1037 * _bcm_td2_qos_count_used_maps 1038 * Purpose: 1039 * Count the number maps currently used in hardware. Since IDs in app-space 1040 * can point to the same hardware index, count how many hardware indexes are 1041 * used, ignoring duplicates. 1042 * Parameters: 1043 * unit - (IN) Unit to be operated on 1044 * bitmap - (IN) Bitmap of used map IDs 1045 * hwmap - (IN) Array that maps userspace IDs to hardware IDs 1046 * Returns: 1047 * integer containing the number of used hardware indexes 1048 */ 1049 STATIC int 1050 _bcm_td2_qos_count_used_maps(int unit, SHR_BITDCL *bitmap, uint32 *hwmap, 1051 int map_size, int max_maps) 1052 { 1053 uint8 *hw_used = sal_alloc(map_size, "td2_qos_used_maps"); 1054 int total_used = 0; 1055 int i = 0; 1056 1057 if (hw_used == NULL) { 1058 return max_maps; 1059 } 1060 1061 memset(hw_used, 0, map_size); 1062 1063 for (i = 0; i < map_size; i++) { 1064 if (SHR_BITGET(bitmap, i) && hw_used[hwmap[i]] == 0) { 1065 hw_used[hwmap[i]] = 1; 1066 total_used++; 1067 } 1068 } 1069 1070 sal_free(hw_used); 1071 return total_used; 1072 } 1073 1074 /* 1075 * Function: 1076 * _bcm_td2_qos_flags_sanity_check 1077 * Purpose: 1078 * Check that the combination of flags specified is valid. 1079 * Parameters: 1080 * flags - (IN) BCM_QOS_MAP_* flags (eg. ingress/egress/with_id/replace) 1081 * Returns: 1082 * BCM_E_XXX 1083 */ 1084 STATIC int 1085 _bcm_td2_qos_flags_sanity_check(uint32 flags) 1086 { 1087 int rv = BCM_E_NONE; 1088 1089 /* must be ingress or egress, not both */ 1090 if ((flags & BCM_QOS_MAP_INGRESS) && (flags & BCM_QOS_MAP_EGRESS)) { 1091 rv = BCM_E_PARAM; 1092 } 1093 1094 /* must be ingress or egress, not neither */ 1095 if (!(flags & BCM_QOS_MAP_INGRESS) && !(flags & BCM_QOS_MAP_EGRESS)) { 1096 rv = BCM_E_PARAM; 1097 } 1098 1099 /* must be VFT or VSAN, not both */ 1100 if ((flags & BCM_QOS_MAP_VFT) && (flags & BCM_QOS_MAP_VSAN)) { 1101 rv = BCM_E_PARAM; 1102 } 1103 1104 /* must be VFT or VSAN, not neither */ 1105 if (!(flags & BCM_QOS_MAP_VFT) && !(flags & BCM_QOS_MAP_VSAN) 1106 && !(flags & BCM_QOS_MAP_L2_VLAN_ETAG)) { 1107 rv = BCM_E_PARAM; 1108 } 1109 1110 /* VSAN maps can only be egress */ 1111 if ((flags & BCM_QOS_MAP_INGRESS) && (flags & BCM_QOS_MAP_VSAN)) { 1112 rv = BCM_E_PARAM; 1113 } 1114 1115 return rv; 1116 } 1117 1118 /* 1119 * Function: 1120 * _bcm_td2_qos_assign_creation_table_vars 1121 * Purpose: 1122 * Assign the various pointers to tables and table sizes and bitmaps used 1123 * for the bcm_td2_qos_map_create so that it can create the different types 1124 * of maps with common logic. 1125 * 1126 * Assumes "flags" has already been validated. 1127 * Parameters: 1128 * unit - (IN) Unit to be operated on 1129 * flags - (IN) BCM_QOS_MAP_* flags (eg. ingress/egress/with_id/etc) 1130 * is_ingress - (OUT) 1 for ingress, 0 for egress map 1131 * bitmap - (OUT) pointer to priority map's bitmap 1132 * hwmap - (OUT) pointer to priority map's hwidx mapping 1133 * map_type - (OUT) _BCM_QOS_MAP_TYPE_* 1134 * map_size - (OUT) size of the selected map 1135 * max_maps - (OUT) maximum number of maps available for the selected type 1136 * Returns: 1137 * None 1138 */ 1139 STATIC void 1140 _bcm_td2_qos_assign_creation_table_vars(int unit, int flags, int *is_ingress, 1141 SHR_BITDCL **bitmap, 1142 uint32 **hwmap, int *map_type, 1143 int *map_size, int *max_maps) 1144 { 1145 if (flags & BCM_QOS_MAP_INGRESS) { 1146 *is_ingress = 1; 1147 if (flags & BCM_QOS_MAP_VFT) { 1148 *bitmap = VFT_QOS_INFO(unit)->ing_vft_pri_map; 1149 *hwmap = VFT_QOS_INFO(unit)->ing_vft_pri_map_hwidx; 1150 *map_type = _BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP; 1151 *map_size = _BCM_QOS_MAX_VFT_PRI_MAPS; 1152 *max_maps = _BCM_QOS_MAX_VFT_PRI_MAPS; 1153 } else if (flags & BCM_QOS_MAP_L2_VLAN_ETAG) { 1154 *bitmap = VFT_QOS_INFO(unit)->ing_l2_vlan_etag_map; 1155 *hwmap = VFT_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx; 1156 *map_type = _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP; 1157 *map_size = _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; 1158 *max_maps = _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; 1159 } 1160 } else if (flags & BCM_QOS_MAP_EGRESS) { 1161 *is_ingress = 0; 1162 1163 if (flags & BCM_QOS_MAP_VFT) { 1164 *bitmap = VFT_QOS_INFO(unit)->egr_vft_pri_map; 1165 *hwmap = VFT_QOS_INFO(unit)->egr_vft_pri_map_hwidx; 1166 *map_type = _BCM_QOS_MAP_TYPE_EGR_VFT_PRI_MAP; 1167 *map_size = _BCM_QOS_MAX_VFT_PRI_MAPS; 1168 *max_maps = _BCM_QOS_MAX_VFT_PRI_MAPS; 1169 } else if (flags & BCM_QOS_MAP_VSAN) { 1170 *bitmap = VFT_QOS_INFO(unit)->egr_vsan_intpri_map; 1171 *hwmap = VFT_QOS_INFO(unit)->egr_vsan_intpri_map_hwidx; 1172 *map_type = _BCM_QOS_MAP_TYPE_EGR_VSAN_PRI_MAP; 1173 *map_size = _BCM_QOS_MAX_VSAN_PRI_MAPS; 1174 *max_maps = _BCM_QOS_MAX_VSAN_PRI_MAPS; 1175 } else if (flags & BCM_QOS_MAP_L2_VLAN_ETAG) { 1176 *bitmap = VFT_QOS_INFO(unit)->egr_l2_vlan_etag_map; 1177 *hwmap = VFT_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx; 1178 *map_type = _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP; 1179 *map_size = _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; 1180 *max_maps = _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; 1181 } 1182 } 1183 1184 } 1185 1186 /* 1187 * Function: 1188 * bcm_td2_qos_map_create 1189 * Purpose: 1190 * Create a new QOS map. 1191 * Parameters: 1192 * unit - (IN) Unit to be operated on 1193 * flags - (IN) BCM_QOS_MAP_* flags (eg. ingress/egress/with_id/replace) 1194 * map_id - (IN/OUT) If BCM_QOS_MAP_WITH_ID is set, then this is the ID 1195 * being requested. Otherwise, it's assigned as the ID 1196 * allocated. 1197 * Returns: 1198 * BCM_E_XXX 1199 */ 1200 int 1201 bcm_td2_qos_map_create(int unit, uint32 flags, int *map_id) 1202 { 1203 int is_ingress = 0; 1204 int map_type = 0; 1205 SHR_BITDCL *bitmap = NULL; 1206 uint32 index = 0; 1207 int rv = BCM_E_NONE; 1208 int id = 0; 1209 void *entries[2] = {NULL}; 1210 uint32 *hwmap = NULL; 1211 int map_size = 0; 1212 int max_maps = 0; 1213 1214 QOS_INIT(unit); 1215 QOS_LOCK(unit); 1216 1217 rv = _bcm_td2_qos_flags_sanity_check(flags); 1218 1219 if (BCM_SUCCESS(rv)) { 1220 _bcm_td2_qos_assign_creation_table_vars(unit, flags, &is_ingress, 1221 &bitmap, &hwmap, &map_type, 1222 &map_size, &max_maps); 1223 } 1224 1225 if (BCM_SUCCESS(rv)) { 1226 if (_bcm_td2_qos_count_used_maps(unit, bitmap, hwmap, map_size, 1227 max_maps) >= max_maps) { 1228 rv = BCM_E_MEMORY; 1229 } 1230 } 1231 1232 if (BCM_SUCCESS(rv)) { 1233 if (flags & BCM_QOS_MAP_WITH_ID) { 1234 rv = _bcm_td2_qos_map_create_with_id(unit, flags, bitmap, map_id, 1235 is_ingress, map_size); 1236 id = *map_id & _BCM_QOS_MAP_TYPE_MASK; 1237 } else { 1238 rv = _bcm_td2_qos_map_id_alloc(unit, bitmap, &id, map_size); 1239 if (BCM_SUCCESS(rv)) { 1240 *map_id = id | (map_type << _BCM_QOS_MAP_SHIFT); 1241 } 1242 } 1243 } 1244 1245 if (BCM_SUCCESS(rv)) { 1246 if (flags & BCM_QOS_MAP_VSAN) { 1247 egr_vsan_intpri_map_entry_t table[_BCM_QOS_MAP_CHUNK_VSAN_PRI_MAP]; 1248 memset(&table, 0, sizeof table); 1249 entries[0] = &table; 1250 1251 rv = _bcm_egr_vsan_intpri_map_entry_add(unit, entries, 1252 _BCM_QOS_MAP_CHUNK_VSAN_PRI_MAP, 1253 &index); 1254 1255 if (BCM_SUCCESS(rv)) { 1256 VFT_QOS_INFO(unit)->egr_vsan_intpri_map_hwidx[id] = index / 1257 _BCM_QOS_MAP_CHUNK_VSAN_PRI_MAP; 1258 } 1259 } 1260 else if ((flags & BCM_QOS_MAP_INGRESS) && (flags & BCM_QOS_MAP_VFT)) { 1261 ing_vft_pri_map_entry_t table[_BCM_QOS_MAP_CHUNK_VFT_PRI_MAP]; 1262 memset(&table, 0, sizeof table); 1263 entries[0] = &table; 1264 1265 rv = _bcm_ing_vft_pri_map_entry_add(unit, entries, 1266 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP, 1267 &index); 1268 1269 if (BCM_SUCCESS(rv)) { 1270 VFT_QOS_INFO(unit)->ing_vft_pri_map_hwidx[id] = index / 1271 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP; 1272 } 1273 } else if ((flags & BCM_QOS_MAP_EGRESS) && (flags & BCM_QOS_MAP_VFT)){ 1274 egr_vft_pri_map_entry_t table[_BCM_QOS_MAP_CHUNK_VFT_PRI_MAP]; 1275 memset(&table, 0, sizeof table); 1276 entries[0] = &table; 1277 1278 rv = _bcm_egr_vft_pri_map_entry_add(unit, entries, 1279 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP, 1280 &index); 1281 1282 if (BCM_SUCCESS(rv)) { 1283 VFT_QOS_INFO(unit)->egr_vft_pri_map_hwidx[id] = index / 1284 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP; 1285 } 1286 } 1287 else if ((flags & BCM_QOS_MAP_INGRESS) 1288 && (flags & BCM_QOS_MAP_L2_VLAN_ETAG)) { 1289 ing_etag_pcp_mapping_entry_t 1290 table[_BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP]; 1291 memset(&table, 0, sizeof table); 1292 entries[0] = &table; 1293 1294 rv = _bcm_ing_l2_vlan_etag_map_entry_add(unit, entries, 1295 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP, 1296 &index); 1297 1298 if (BCM_SUCCESS(rv)) { 1299 VFT_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[id] = index / 1300 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP; 1301 } 1302 } else if ((flags & BCM_QOS_MAP_EGRESS) 1303 && (flags & BCM_QOS_MAP_L2_VLAN_ETAG)) { 1304 egr_zone_3_dot1p_mapping_table_2_entry_t 1305 td3_etag_table[2][_BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP]; 1306 egr_etag_pcp_mapping_entry_t 1307 table[_BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP]; 1308 1309 if (SOC_IS_TRIDENT3X(unit)) { 1310 memset(&td3_etag_table, 0, sizeof(td3_etag_table)); 1311 entries[0] = &td3_etag_table[0]; 1312 entries[1] = &td3_etag_table[1]; 1313 } else { 1314 memset(&table, 0, sizeof table); 1315 entries[0] = &table; 1316 } 1317 1318 rv = _bcm_egr_l2_vlan_etag_map_entry_add(unit, entries, 1319 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP, 1320 &index); 1321 1322 if (BCM_SUCCESS(rv)) { 1323 VFT_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[id] = index / 1324 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP; 1325 } 1326 } 1327 } 1328 1329 QOS_UNLOCK(unit); 1330 1331 return rv; 1332 } 1333 1334 /* 1335 * Function: 1336 * _bcm_td2_qos_map_destroy 1337 * Purpose: 1338 * Destroy a map ID by removing it from hardware. 1339 * Parameters: 1340 * unit - (IN) The unit being operated on 1341 * table - (IN) Indicates either ingress or egress 1342 * id - (IN) The map ID being destroyed 1343 * Returns: 1344 * BCM_E_XXX 1345 */ 1346 STATIC int 1347 _bcm_td2_qos_map_destroy(int unit, int table, int id) 1348 { 1349 int rv = BCM_E_NONE; 1350 _bcm_td2_qos_bookkeeping_t *qos_info = VFT_QOS_INFO(unit); 1351 1352 if (table == _BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP) { 1353 rv = _bcm_ing_vft_pri_map_entry_del(unit, 1354 qos_info->ing_vft_pri_map_hwidx[id] * 1355 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP); 1356 } else if (table == _BCM_QOS_MAP_TYPE_EGR_VFT_PRI_MAP) { 1357 rv = _bcm_egr_vft_pri_map_entry_del(unit, 1358 qos_info->egr_vft_pri_map_hwidx[id] * 1359 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP); 1360 } else if (table == _BCM_QOS_MAP_TYPE_EGR_VSAN_PRI_MAP) { 1361 rv = _bcm_egr_vsan_intpri_map_entry_del(unit, 1362 qos_info->egr_vsan_intpri_map_hwidx[id] * 1363 _BCM_QOS_MAP_CHUNK_VSAN_PRI_MAP); 1364 } else if (table == _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP) { 1365 rv = _bcm_ing_l2_vlan_etag_map_entry_del(unit, 1366 qos_info->ing_l2_vlan_etag_map_hwidx[id] * 1367 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP); 1368 } else if (table == _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP) { 1369 rv = _bcm_egr_l2_vlan_etag_map_entry_del(unit, 1370 qos_info->egr_l2_vlan_etag_map_hwidx[id] * 1371 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP); 1372 } 1373 1374 return rv; 1375 } 1376 1377 /* 1378 * Function: 1379 * bcm_td2_qos_map_destroy 1380 * Purpose: 1381 * Destroy a VFT QOS map ID by removing it from hardware and deleting the 1382 * associated software state info. 1383 * Parameters: 1384 * unit - (IN) Unit being operated on 1385 * map_id - (IN) QOS map ID to be destroyed 1386 * Returns: 1387 * BCM_E_XXX 1388 */ 1389 int 1390 bcm_td2_qos_map_destroy(int unit, int map_id) 1391 { 1392 int id = map_id & _BCM_QOS_MAP_TYPE_MASK; 1393 int rv = BCM_E_UNAVAIL; 1394 1395 QOS_INIT(unit); 1396 QOS_LOCK(unit); 1397 1398 switch (map_id >> _BCM_QOS_MAP_SHIFT) { 1399 case _BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP: 1400 if (!_BCM_QOS_ING_VFT_PRI_MAP_TABLE_USED_GET(unit, id)) { 1401 rv = BCM_E_NOT_FOUND; 1402 } else { 1403 rv = _bcm_td2_qos_map_destroy(unit, 1404 _BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP, id); 1405 1406 if (BCM_SUCCESS(rv)) { 1407 _BCM_QOS_ING_VFT_PRI_MAP_TABLE_USED_CLR(unit, id); 1408 } 1409 } 1410 break; 1411 1412 case _BCM_QOS_MAP_TYPE_EGR_VFT_PRI_MAP: 1413 if (!_BCM_QOS_EGR_VFT_PRI_MAP_TABLE_USED_GET(unit, id)) { 1414 rv = BCM_E_NOT_FOUND; 1415 } else { 1416 rv = _bcm_td2_qos_map_destroy(unit, 1417 _BCM_QOS_MAP_TYPE_EGR_VFT_PRI_MAP, id); 1418 1419 if (BCM_SUCCESS(rv)) { 1420 _BCM_QOS_EGR_VFT_PRI_MAP_TABLE_USED_CLR(unit, id); 1421 } 1422 } 1423 break; 1424 1425 case _BCM_QOS_MAP_TYPE_EGR_VSAN_PRI_MAP: 1426 if (!_BCM_QOS_EGR_VSAN_PRI_MAP_TABLE_USED_GET(unit, id)) { 1427 rv = BCM_E_NOT_FOUND; 1428 } else { 1429 rv = _bcm_td2_qos_map_destroy(unit, 1430 _BCM_QOS_MAP_TYPE_EGR_VSAN_PRI_MAP, id); 1431 1432 if (BCM_SUCCESS(rv)) { 1433 _BCM_QOS_EGR_VSAN_PRI_MAP_TABLE_USED_CLR(unit, id); 1434 } 1435 } 1436 break; 1437 case _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP: 1438 if (!_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id)) { 1439 rv = BCM_E_NOT_FOUND; 1440 } else { 1441 rv = _bcm_td2_qos_map_destroy(unit, 1442 _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP, id); 1443 1444 if (BCM_SUCCESS(rv)) { 1445 _BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_CLR(unit, id); 1446 } 1447 } 1448 break; 1449 case _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP: 1450 if (!_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id)) { 1451 rv = BCM_E_NOT_FOUND; 1452 } else { 1453 rv = _bcm_td2_qos_map_destroy(unit, 1454 _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP, id); 1455 1456 if (BCM_SUCCESS(rv)) { 1457 _BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_CLR(unit, id); 1458 } 1459 } 1460 break; 1461 default: 1462 rv = BCM_E_PARAM; 1463 } 1464 1465 QOS_UNLOCK(unit); 1466 1467 return rv; 1468 } 1469 1470 /* 1471 * Function: 1472 * _bcm_td2_qos_map_add_sanity_check 1473 * Purpose: 1474 * Check that all the paramters given to the bcm_qos_map_add() function make 1475 * sense and are internally consistent. 1476 * Parameters: 1477 * unit - (IN) The unit being operated on 1478 * flags - (IN) BCM_QOS_MAP_* flags sent in by the app 1479 * map - (IN) The map structure sent in by the app 1480 * map_id - (IN) The map ID sent in by the app 1481 * Returns: 1482 * BCM_E_XXX 1483 */ 1484 STATIC int 1485 _bcm_td2_qos_map_add_sanity_check(int unit, uint32 flags, bcm_qos_map_t *map, 1486 int map_id) 1487 { 1488 int map_type = map_id >> _BCM_QOS_MAP_SHIFT; 1489 int id = map_id & _BCM_QOS_MAP_TYPE_MASK; 1490 int rv; 1491 1492 rv = _bcm_td2_qos_flags_sanity_check(flags); 1493 if (BCM_FAILURE(rv)) { 1494 return rv; 1495 } 1496 1497 if ((flags & BCM_QOS_MAP_INGRESS) 1498 && ((map_type != _BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP) 1499 && (map_type != _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP))) { 1500 return BCM_E_PARAM; 1501 } 1502 1503 if ((flags & BCM_QOS_MAP_EGRESS) 1504 && ((map_type != _BCM_QOS_MAP_TYPE_EGR_VFT_PRI_MAP) 1505 && (map_type != _BCM_QOS_MAP_TYPE_EGR_VSAN_PRI_MAP) 1506 && (map_type != _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP)) 1507 ) { 1508 return BCM_E_PARAM; 1509 } 1510 1511 if ((flags & BCM_QOS_MAP_INGRESS) 1512 && (map_type == _BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP) 1513 && (_BCM_QOS_ING_VFT_PRI_MAP_TABLE_USED_GET(unit, id) == 0)) { 1514 return BCM_E_BADID; 1515 } 1516 1517 if ((flags & BCM_QOS_MAP_INGRESS) 1518 && (map_type == _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP) 1519 && (_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id) == 0)) { 1520 return BCM_E_BADID; 1521 } 1522 1523 if ((flags & BCM_QOS_MAP_EGRESS) 1524 && (map_type == _BCM_QOS_MAP_TYPE_EGR_VFT_PRI_MAP) 1525 && (_BCM_QOS_EGR_VFT_PRI_MAP_TABLE_USED_GET(unit, id) == 0)) { 1526 return BCM_E_BADID; 1527 } 1528 1529 if ((flags & BCM_QOS_MAP_EGRESS) 1530 && (map_type == _BCM_QOS_MAP_TYPE_EGR_VSAN_PRI_MAP) 1531 && (_BCM_QOS_EGR_VSAN_PRI_MAP_TABLE_USED_GET(unit, id) == 0)) { 1532 return BCM_E_BADID; 1533 } 1534 1535 if ((flags & BCM_QOS_MAP_EGRESS) 1536 && (map_type == _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP) 1537 && (_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id) == 0)) { 1538 return BCM_E_BADID; 1539 } 1540 1541 if (!(flags & BCM_QOS_MAP_L2_VLAN_ETAG)) { 1542 if (map->int_pri < 0) { 1543 return BCM_E_PARAM; 1544 } 1545 } 1546 1547 if (flags & BCM_QOS_MAP_VFT) { 1548 if (map->int_pri >= _BCM_QOS_MAX_VFT_PRIORITIES) { 1549 return BCM_E_PARAM; 1550 } 1551 } else if (flags & BCM_QOS_MAP_VSAN) { 1552 if (map->int_pri >= _BCM_QOS_MAX_VSAN_PRIORITIES) { 1553 return BCM_E_PARAM; 1554 } 1555 } 1556 1557 if (map->pkt_pri >= _BCM_QOS_MAX_PKT_PRIORITIES) { 1558 return BCM_E_PARAM; 1559 } 1560 1561 if (flags & BCM_QOS_MAP_VSAN) { 1562 if (map->color != bcmColorGreen && map->color != bcmColorYellow 1563 && map->color != bcmColorRed) { 1564 return BCM_E_PARAM; 1565 } 1566 } 1567 1568 if (flags & BCM_QOS_MAP_L2_VLAN_ETAG) { 1569 if ((map->etag_pcp >= _BCM_QOS_MAX_PKT_PRIORITIES) 1570 || (map->etag_de >= _BCM_QOS_MAX_PKT_DES) 1571 || (map->pkt_cfi >= _BCM_QOS_MAX_PKT_DES)) { 1572 return BCM_E_PARAM; 1573 } 1574 } 1575 1576 if ((flags & BCM_QOS_MAP_L2_VLAN_ETAG) 1577 && (flags & BCM_QOS_MAP_EGRESS)) { 1578 if (map->color != bcmColorGreen && map->color != bcmColorYellow 1579 && map->color != bcmColorRed) { 1580 return BCM_E_PARAM; 1581 } 1582 if (map->int_pri >= _BCM_QOS_MAX_INT_PRIORITIES) { 1583 return BCM_E_PARAM; 1584 } 1585 } 1586 1587 return BCM_E_NONE; 1588 } 1589 1590 /* 1591 * Function: 1592 * _bcm_td2_ing_qos_map_update_index 1593 * Purpose: 1594 * Update an existing profile (or a newly created one) in the hardware's 1595 * table with a new mapping. 1596 * 1597 * The structure is: (1) get existing profile for this map from hardware, 1598 * (2) update the profile in RAM, (3) delete the old profile from hardware, 1599 * and (4) push the updated profile in RAM to hardware. 1600 * Parameters: 1601 * unit - (IN) The unit being operated on 1602 * map - (IN) Map structure sent in by app to be applied to hardware 1603 * map_id - (IN) Map ID sent in by app to be applied to hardware 1604 * Returns: 1605 * BCM_E_XXX 1606 */ 1607 STATIC int 1608 _bcm_td2_ing_qos_map_update_index(int unit, bcm_qos_map_t *map, int map_id) 1609 { 1610 void *entries[1]; 1611 int rv = 0; 1612 uint32 index; 1613 int id = map_id & _BCM_QOS_MAP_TYPE_MASK; 1614 1615 if (QOS_MAP_IS_L2_VLAN_ETAG(map_id)) { 1616 ing_etag_pcp_mapping_entry_t table[_BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP]; 1617 index = VFT_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[id] * 1618 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP; 1619 1620 entries[0] = &table; 1621 rv = _bcm_ing_l2_vlan_etag_map_entry_get(unit, index, 1622 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP, 1623 entries); 1624 1625 if (BCM_SUCCESS(rv)) { 1626 ing_etag_pcp_mapping_entry_t *entry = 1627 &table[(map->pkt_pri << 1) | map->pkt_cfi]; 1628 1629 soc_mem_field32_set(unit, ING_ETAG_PCP_MAPPINGm, 1630 entry, PCPf, map->etag_pcp); 1631 soc_mem_field32_set(unit, ING_ETAG_PCP_MAPPINGm, 1632 entry, DEf, map->etag_de); 1633 1634 rv = _bcm_ing_l2_vlan_etag_map_entry_del(unit, (int)index); 1635 } 1636 1637 if (BCM_SUCCESS(rv)) { 1638 rv = _bcm_ing_l2_vlan_etag_map_entry_add(unit, entries, 1639 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP, 1640 &index); 1641 VFT_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[id] = index / 1642 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP; 1643 } 1644 } else if (soc_mem_is_valid(unit, ING_VFT_PRI_MAPm)) { 1645 ing_vft_pri_map_entry_t table[_BCM_QOS_MAP_CHUNK_VFT_PRI_MAP]; 1646 index = VFT_QOS_INFO(unit)->ing_vft_pri_map_hwidx[id] * 1647 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP; 1648 1649 entries[0] = &table; 1650 rv = _bcm_ing_vft_pri_map_entry_get(unit, index, 1651 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP, 1652 entries); 1653 1654 if (BCM_SUCCESS(rv)) { 1655 ing_vft_pri_map_entry_t *entry = &table[map->pkt_pri]; 1656 1657 soc_mem_field32_set(unit, ING_VFT_PRI_MAPm, entry, FCOE_VFT_PRIf, 1658 map->int_pri); 1659 1660 rv = _bcm_ing_vft_pri_map_entry_del(unit, (int)index); 1661 } 1662 1663 if (BCM_SUCCESS(rv)) { 1664 rv = _bcm_ing_vft_pri_map_entry_add(unit, entries, 1665 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP, 1666 &index); 1667 VFT_QOS_INFO(unit)->ing_vft_pri_map_hwidx[id] = index / 1668 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP; 1669 } 1670 } 1671 return rv; 1672 } 1673 1674 /* 1675 * Function: 1676 * _bcm_td2_egr_qos_map_update_index 1677 * Purpose: 1678 * Update an existing profile (or a newly created one) in the hardware's 1679 * table with a new mapping. 1680 * 1681 * The structure is: (1) get existing profile for this map from hardware, 1682 * (2) update the profile in RAM, (3) delete the old profile from hardware, 1683 * and (4) push the updated profile in RAM to hardware. 1684 * Parameters: 1685 * unit - (IN) The unit being operated on 1686 * map - (IN) Map structure sent in by app to be applied to hardware 1687 * map_id - (IN) Map ID sent in by app to be applied to hardware 1688 * Returns: 1689 * BCM_E_XXX 1690 */ 1691 STATIC int 1692 _bcm_td2_egr_qos_map_update_index(int unit, bcm_qos_map_t *map, int map_id) 1693 { 1694 void *entries[2]; 1695 int rv = 0, cng; 1696 uint32 index; 1697 int id = map_id & _BCM_QOS_MAP_TYPE_MASK; 1698 egr_zone_3_dot1p_mapping_table_2_entry_t td3_etag_table[2][_BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP]; 1699 egr_etag_pcp_mapping_entry_t table[_BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP]; 1700 egr_etag_pcp_mapping_entry_t *entry; 1701 egr_zone_3_dot1p_mapping_table_2_entry_t *td3_entry; 1702 1703 if (QOS_MAP_IS_L2_VLAN_ETAG(map_id)) { 1704 index = VFT_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[id] * 1705 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP; 1706 if (SOC_IS_TRIDENT3X(unit)) { 1707 entries[0] = td3_etag_table[0]; 1708 entries[1] = td3_etag_table[1]; 1709 } else { 1710 entries[0] = &table; 1711 } 1712 rv = _bcm_egr_l2_vlan_etag_map_entry_get(unit, index, 1713 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP, 1714 entries); 1715 if (BCM_SUCCESS(rv)) { 1716 cng = _BCM_COLOR_ENCODING(unit, map->color); 1717 if (SOC_IS_TRIDENT3X(unit)) { 1718 /* Outer Tag */ 1719 td3_entry = &td3_etag_table[0][(map->int_pri << 2) | cng]; 1720 soc_mem_field32_set(unit, EGR_ZONE_3_DOT1P_MAPPING_TABLE_2m, 1721 td3_entry, PRIf, map->etag_pcp); 1722 soc_mem_field32_set(unit, EGR_ZONE_3_DOT1P_MAPPING_TABLE_2m, 1723 td3_entry, CFIf, map->etag_de); 1724 /* Inner Tag */ 1725 td3_entry = &td3_etag_table[1][(map->int_pri << 2) | cng]; 1726 soc_mem_field32_set(unit, EGR_ZONE_1_DOT1P_MAPPING_TABLE_2m, 1727 td3_entry, PRIf, map->etag_pcp); 1728 soc_mem_field32_set(unit, EGR_ZONE_1_DOT1P_MAPPING_TABLE_2m, 1729 td3_entry, CFIf, map->etag_de); 1730 1731 } else { 1732 cng = _BCM_COLOR_ENCODING(unit, map->color); 1733 entry = &table[(map->int_pri << 2) | cng]; 1734 1735 soc_mem_field32_set(unit, EGR_ETAG_PCP_MAPPINGm, 1736 entry, PCPf, map->etag_pcp); 1737 soc_mem_field32_set(unit, EGR_ETAG_PCP_MAPPINGm, 1738 entry, DEf, map->etag_de); 1739 } 1740 rv = _bcm_egr_l2_vlan_etag_map_entry_del(unit, (int)index); 1741 } 1742 1743 if (BCM_SUCCESS(rv)) { 1744 rv = _bcm_egr_l2_vlan_etag_map_entry_add(unit, entries, 1745 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP, 1746 &index); 1747 VFT_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[id] = index / 1748 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP; 1749 } 1750 } else if (soc_mem_is_valid(unit, ING_VFT_PRI_MAPm)) { 1751 egr_vft_pri_map_entry_t table[_BCM_QOS_MAP_CHUNK_VFT_PRI_MAP]; 1752 index = VFT_QOS_INFO(unit)->egr_vft_pri_map_hwidx[id] * 1753 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP; 1754 1755 entries[0] = &table; 1756 rv = _bcm_egr_vft_pri_map_entry_get(unit, index, 1757 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP, 1758 entries); 1759 1760 if (BCM_SUCCESS(rv)) { 1761 egr_vft_pri_map_entry_t *entry = &table[map->int_pri]; 1762 1763 soc_mem_field32_set(unit, EGR_VFT_PRI_MAPm, entry, FCOE_VFT_PRIf, 1764 map->pkt_pri); 1765 1766 rv = _bcm_egr_vft_pri_map_entry_del(unit, index); 1767 } 1768 1769 if (BCM_SUCCESS(rv)) { 1770 rv = _bcm_egr_vft_pri_map_entry_add(unit, entries, 1771 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP, 1772 &index); 1773 VFT_QOS_INFO(unit)->egr_vft_pri_map_hwidx[id] = index / 1774 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP; 1775 } 1776 } 1777 1778 return rv; 1779 } 1780 1781 /* 1782 * Function: 1783 * _bcm_td2_color_to_hw_color 1784 * Purpose: 1785 * Convert from bcm_color_t enum to hardware color values for VSAN QOS 1786 * mapping 1787 * Parameters: 1788 * color - (IN) Value to convert from 1789 * hw_color - (OUT) Converted hardware color value 1790 * Returns: 1791 * BCM_E_XXX 1792 */ 1793 STATIC int 1794 _bcm_td2_color_to_hw_color(bcm_color_t color, int *hw_color) 1795 { 1796 int rv = BCM_E_NONE; 1797 1798 switch (color) { 1799 case bcmColorRed: *hw_color = TD2_HW_COLOR_RED; break; 1800 case bcmColorYellow: *hw_color = TD2_HW_COLOR_YELLOW; break; 1801 case bcmColorGreen: *hw_color = TD2_HW_COLOR_GREEN; break; 1802 default: 1803 rv = BCM_E_PARAM; 1804 break; 1805 } 1806 1807 return rv; 1808 } 1809 1810 /* 1811 * Function: 1812 * _bcm_td2_egr_vsan_map_update_index 1813 * Purpose: 1814 * Update an existing profile (or a newly created one) in the hardware's 1815 * EGR_VSAN_INTPRI_MAP table with a new mapping. 1816 * 1817 * The structure is: (1) get existing profile for this map from hardware, 1818 * (2) update the profile in RAM, (3) delete the old profile from hardware, 1819 * and (4) push the updated profile in RAM to hardware. 1820 * Parameters: 1821 * unit - (IN) The unit being operated on 1822 * map - (IN) Map structure sent in by app to be applied to hardware 1823 * map_id - (IN) Map ID sent in by app to be applied to hardware 1824 * Returns: 1825 * BCM_E_XXX 1826 */ 1827 STATIC int 1828 _bcm_td2_egr_vsan_map_update_index(int unit, bcm_qos_map_t *map, int map_id) 1829 { 1830 void *entries[1]; 1831 int rv; 1832 uint32 index; 1833 int id = map_id & _BCM_QOS_MAP_TYPE_MASK; 1834 egr_vsan_intpri_map_entry_t table[_BCM_QOS_MAP_CHUNK_VSAN_PRI_MAP]; 1835 1836 index = VFT_QOS_INFO(unit)->egr_vsan_intpri_map_hwidx[id] * 1837 _BCM_QOS_MAP_CHUNK_VSAN_PRI_MAP; 1838 1839 entries[0] = &table; 1840 rv = _bcm_egr_vsan_intpri_map_entry_get(unit, index, 1841 _BCM_QOS_MAP_CHUNK_VSAN_PRI_MAP, 1842 entries); 1843 1844 if (BCM_SUCCESS(rv)) { 1845 int hw_color = TD2_HW_COLOR_ERROR; 1846 egr_vsan_intpri_map_entry_t *entry = NULL; 1847 1848 rv = _bcm_td2_color_to_hw_color(map->color, &hw_color); 1849 if (BCM_SUCCESS(rv)) { 1850 entry = &table[(map->int_pri << _BCM_QOS_PRI_BIT_SHIFT) | hw_color]; 1851 1852 soc_mem_field32_set(unit, EGR_VSAN_INTPRI_MAPm, entry, PRIf, 1853 map->pkt_pri); 1854 1855 rv = _bcm_egr_vsan_intpri_map_entry_del(unit, index); 1856 } 1857 } 1858 1859 if (BCM_SUCCESS(rv)) { 1860 rv = _bcm_egr_vsan_intpri_map_entry_add(unit, entries, 1861 _BCM_QOS_MAP_CHUNK_VSAN_PRI_MAP, 1862 &index); 1863 VFT_QOS_INFO(unit)->egr_vsan_intpri_map_hwidx[id] = index / 1864 _BCM_QOS_MAP_CHUNK_VSAN_PRI_MAP; 1865 } 1866 1867 return rv; 1868 } 1869 /* 1870 * Function: 1871 * bcm_td2_qos_map_add 1872 * Purpose: 1873 * Add a new QOS mapping to hardware. 1874 * Parameters: 1875 * unit - (IN) The unit being operated on 1876 * flags - (IN) BCM_QOS_MAP_* flags 1877 * map - (IN) Structure containing the priorities to be mapped 1878 * map_id - (IN) The ID of the map to add the new information to 1879 * Returns: 1880 * BCM_E_XXX 1881 */ 1882 int 1883 bcm_td2_qos_map_add(int unit, uint32 flags, bcm_qos_map_t *map, int map_id) 1884 { 1885 int rv = BCM_E_NONE; 1886 1887 QOS_INIT(unit); 1888 QOS_LOCK(unit); 1889 1890 rv = _bcm_td2_qos_map_add_sanity_check(unit, flags, map, map_id); 1891 if (BCM_SUCCESS(rv)) { 1892 if (flags & BCM_QOS_MAP_VSAN) { 1893 rv = _bcm_td2_egr_vsan_map_update_index(unit, map, map_id); 1894 } else if ((flags & BCM_QOS_MAP_INGRESS) 1895 && ((flags & BCM_QOS_MAP_L2_VLAN_ETAG) 1896 || (flags & BCM_QOS_MAP_VFT))) { 1897 rv = _bcm_td2_ing_qos_map_update_index(unit, map, map_id); 1898 } else { 1899 rv = _bcm_td2_egr_qos_map_update_index(unit, map, map_id); 1900 } 1901 } 1902 1903 QOS_UNLOCK(unit); 1904 1905 return rv; 1906 } 1907 1908 /* 1909 * Function: 1910 * bcm_td2_qos_map_delete 1911 * Purpose: 1912 * Delete a mapping (for example, the map from 7 to 3). This is equivalent 1913 * to changing it to a map from 7 to 0, so this function maps the call into 1914 * bcm_td2_qos_map_add(). 1915 * Parameters: 1916 * unit - (IN) The unit being operated on 1917 * flags - (IN) BCM_QOS_MAP_* flags 1918 * map - (IN) Structure containing the priorities to be mapped 1919 * map_id - (IN) The ID of the map to add the new information to 1920 * Returns: 1921 * BCM_E_XXX 1922 */ 1923 int 1924 bcm_td2_qos_map_delete(int unit, uint32 flags, bcm_qos_map_t *map, int map_id) 1925 { 1926 int rv = BCM_E_NONE; 1927 bcm_qos_map_t clr_map; 1928 1929 QOS_INIT(unit); 1930 1931 sal_memcpy(&clr_map, map, sizeof clr_map); 1932 1933 rv = _bcm_td2_qos_flags_sanity_check(flags); 1934 if (BCM_SUCCESS(rv)) { 1935 if (flags & BCM_QOS_MAP_INGRESS) { 1936 if (flags & BCM_QOS_MAP_VFT) { 1937 clr_map.int_pri = 0; 1938 } else if (flags & BCM_QOS_MAP_L2_VLAN_ETAG) { 1939 clr_map.etag_pcp = 0; 1940 clr_map.etag_de = 0; 1941 } 1942 } else { 1943 if(flags & BCM_QOS_MAP_L2_VLAN_ETAG) { 1944 clr_map.etag_pcp = 0; 1945 clr_map.etag_de = 0; 1946 } else { 1947 clr_map.pkt_pri = 0; 1948 } 1949 } 1950 } 1951 1952 if (BCM_SUCCESS(rv)) { 1953 rv = bcm_td2_qos_map_add(unit, flags, &clr_map, map_id); 1954 } 1955 1956 return rv; 1957 } 1958 1959 /* 1960 * Function: 1961 * _bcm_td2_qos_apply_ing_map_to_port 1962 * Purpose: 1963 * Apply a fully created ingress map to a hardware port. This is the final 1964 * step in the process, where the mapping becomes operational. 1965 * Parameters: 1966 * unit - (IN) Unit being operated on 1967 * ing_map - (IN) ID of the map to be applied 1968 * local_port - (IN) Local port number to apply map to 1969 * Returns: 1970 * BCM_E_XXX 1971 */ 1972 STATIC int 1973 _bcm_td2_qos_apply_ing_map_to_port(int unit, int ing_map, bcm_port_t local_port) 1974 { 1975 int rv = BCM_E_PARAM; 1976 int id = ing_map & _BCM_QOS_MAP_TYPE_MASK; 1977 1978 soc_mem_lock(unit, PORT_TABm); 1979 1980 if ((ing_map >> _BCM_QOS_MAP_SHIFT) == _BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP) { 1981 if (SOC_IS_TRIDENT3X(unit)) { 1982 rv = _bcm_esw_port_tab_set(unit, local_port, _BCM_CPU_TABS_BOTH, 1983 FCOE_VFT_PRI_MAP_PROFILEf, 1984 VFT_QOS_INFO(unit)->ing_vft_pri_map_hwidx[id]); 1985 } else { 1986 rv = _bcm_tr2_port_tab_set(unit, local_port, FCOE_VFT_PRI_MAP_PROFILEf, 1987 VFT_QOS_INFO(unit)->ing_vft_pri_map_hwidx[id]); 1988 } 1989 } else if ((ing_map >> _BCM_QOS_MAP_SHIFT) == 1990 _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP) { 1991 if (SOC_IS_TRIDENT3X(unit)) { 1992 rv = _bcm_esw_port_tab_set(unit, local_port, _BCM_CPU_TABS_BOTH, 1993 ETAG_PCP_DE_MAPPING_PTRf, 1994 VFT_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[id]); 1995 } else { 1996 rv = _bcm_tr2_port_tab_set(unit, local_port, ETAG_PCP_DE_MAPPING_PTRf, 1997 VFT_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[id]); 1998 } 1999 } 2000 2001 soc_mem_unlock(unit, PORT_TABm); 2002 2003 return rv; 2004 } 2005 2006 /* 2007 * Function: 2008 * _bcm_td2_qos_apply_egr_map_to_port 2009 * Purpose: 2010 * Apply a fully created egress map to a hardware port. This is the final 2011 * step in the process, where the mapping becomes operational. 2012 * Parameters: 2013 * unit - (IN) Unit being operated on 2014 * id - (IN) ID of the map to be applied 2015 * local_port - (IN) Local port number to apply map to 2016 * Returns: 2017 * BCM_E_XXX 2018 */ 2019 STATIC int 2020 _bcm_td2_qos_apply_egr_map_to_port(int unit, int id, bcm_port_t local_port) 2021 { 2022 int rv; 2023 2024 soc_mem_lock(unit, PORT_TABm); 2025 2026 if (SOC_IS_TRIDENT3X(unit)) { 2027 rv = _bcm_esw_egr_port_tab_set(unit, local_port, FCOE_VFT_PRI_MAP_PROFILEf, 2028 VFT_QOS_INFO(unit)->egr_vft_pri_map_hwidx[id]); 2029 } else { 2030 rv = _bcm_td2_egr_port_set(unit, local_port, FCOE_VFT_PRI_MAP_PROFILEf, 2031 VFT_QOS_INFO(unit)->egr_vft_pri_map_hwidx[id]); 2032 } 2033 2034 soc_mem_unlock(unit, PORT_TABm); 2035 2036 return rv; 2037 } 2038 2039 /* 2040 * Function: 2041 * _bcm_td2_qos_port_ing_profile_get 2042 * Purpose: 2043 * Retrieve a specific ingress QoS map index from given port. 2044 * Parameters: 2045 * unit - (IN) Unit being operated on 2046 * local_port - (IN) Local port number to apply map to 2047 * ing_map_type - (IN) type of the map to be retrieved 2048 * profile_idx - (OUT) Hardware index 2049 * Returns: 2050 * BCM_E_XXX 2051 */ 2052 STATIC int 2053 _bcm_td2_qos_port_ing_profile_get(int unit, bcm_port_t local_port, 2054 int ing_map_type, int *profile_idx) 2055 { 2056 int rv = BCM_E_PARAM; 2057 2058 if (profile_idx == NULL) { 2059 return BCM_E_PARAM; 2060 } 2061 2062 if (ing_map_type == _BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP) { 2063 if (SOC_IS_TRIDENT3X(unit)) { 2064 rv = _bcm_esw_port_tab_get(unit, local_port, FCOE_VFT_PRI_MAP_PROFILEf, 2065 profile_idx); 2066 } else { 2067 rv = _bcm_tr2_port_tab_get(unit, local_port, FCOE_VFT_PRI_MAP_PROFILEf, 2068 profile_idx); 2069 2070 } 2071 } else if (ing_map_type == _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP) { 2072 if (SOC_IS_TRIDENT3X(unit)) { 2073 rv = _bcm_esw_port_tab_get(unit, local_port, ETAG_PCP_DE_MAPPING_PTRf, 2074 profile_idx); 2075 } else { 2076 rv = _bcm_tr2_port_tab_get(unit, local_port, ETAG_PCP_DE_MAPPING_PTRf, 2077 profile_idx); 2078 } 2079 } 2080 2081 return rv; 2082 } 2083 2084 /* 2085 * Function: 2086 * _bcm_td2_qos_port_egr_profile_get 2087 * Purpose: 2088 * Retrieve a specific egress QoS map index from given port. 2089 * Parameters: 2090 * unit - (IN) Unit being operated on 2091 * local_port - (IN) Local port number to apply map to 2092 * egr_map_type - (IN) type of the map to be retrieved 2093 * profile_idx - (OUT) Hardware index 2094 * Returns: 2095 * BCM_E_XXX 2096 */ 2097 STATIC int 2098 _bcm_td2_qos_port_egr_profile_get(int unit, bcm_port_t local_port, 2099 int egr_map_type, int *profile_idx) 2100 { 2101 int rv = BCM_E_PARAM; 2102 2103 if (profile_idx == NULL) { 2104 return BCM_E_PARAM; 2105 } 2106 2107 if (egr_map_type == _BCM_QOS_MAP_TYPE_EGR_VFT_PRI_MAP) { 2108 if (SOC_IS_TRIDENT3X(unit)) { 2109 rv = _bcm_esw_egr_port_tab_get(unit, local_port, FCOE_VFT_PRI_MAP_PROFILEf, 2110 profile_idx); 2111 } else { 2112 rv = _bcm_td2_egr_port_get(unit, local_port, FCOE_VFT_PRI_MAP_PROFILEf, 2113 profile_idx); 2114 } 2115 } 2116 2117 return rv; 2118 } 2119 2120 /* 2121 * Function: 2122 * bcm_td2_qos_get_egr_vsan_hw_idx 2123 * Purpose: 2124 * Given a QOS map ID for a VSAN mapping profile, return the hardware index 2125 * into the EGR_VSAN_INTPRI_MAP table. 2126 * Parameters: 2127 * unit - (IN) Unit being operated on 2128 * egr_map_id - (IN) ID of the map to be retrieved 2129 * hw_index - (OUT) Hardware index that egr_map_id maps to 2130 * Returns: 2131 * BCM_E_XXX 2132 */ 2133 int 2134 bcm_td2_qos_get_egr_vsan_hw_idx(int unit, int egr_map_id, int *hw_index) 2135 { 2136 int map_type = egr_map_id >> _BCM_QOS_MAP_SHIFT; 2137 int id = egr_map_id & _BCM_QOS_MAP_TYPE_MASK; 2138 2139 if ((map_type != _BCM_QOS_MAP_TYPE_EGR_VSAN_PRI_MAP) 2140 || (_BCM_QOS_EGR_VSAN_PRI_MAP_TABLE_USED_GET(unit, id) == 0)) { 2141 return BCM_E_BADID; 2142 } 2143 2144 *hw_index = VFT_QOS_INFO(unit)->egr_vsan_intpri_map_hwidx[id]; 2145 2146 return BCM_E_NONE; 2147 } 2148 2149 /* 2150 * Function: 2151 * bcm_td2_vsan_profile_to_qos_id 2152 * Purpose: 2153 * Given a hardware profile number index, find the QOS map ID which maps to it 2154 * Parameters: 2155 * unit - (IN) Unit being operated on 2156 * profile_num - (IN) profile number of the map to be retrieved 2157 * egr_map - (OUT) Map ID that points to profile_num 2158 * Returns: 2159 * BCM_E_XXX 2160 */ 2161 int 2162 bcm_td2_vsan_profile_to_qos_id(int unit, int profile_num, int *egr_map) 2163 { 2164 int i; 2165 2166 for (i = 0; i < _BCM_QOS_MAX_VSAN_PRI_MAP_IDS; i++) { 2167 if (VFT_QOS_INFO(unit)->egr_vsan_intpri_map_hwidx[i] == profile_num) { 2168 *egr_map = (_BCM_QOS_MAP_TYPE_EGR_VSAN_PRI_MAP << _BCM_QOS_MAP_SHIFT) 2169 | i; 2170 return BCM_E_NONE; 2171 } 2172 } 2173 2174 return BCM_E_BADID; 2175 } 2176 2177 /* 2178 * Function: 2179 * bcm_td2_qos_port_map_set 2180 * Purpose: 2181 * Apply a fully created ingress and/or egress map to a given port. If 2182 * either map is given as -1 (_BCM_QOS_NO_MAP), then the parameter should be 2183 * ignored. 2184 * Parameters: 2185 * unit - (IN) The unit to be operated on 2186 * port - (IN) The port number for the map to be applied to 2187 * ing_map - (IN) The ID of an ingress map to be applied 2188 * egr_map - (IN) The ID of an egress map to be applied 2189 * Returns: 2190 * BCM_E_XXX 2191 */ 2192 int 2193 bcm_td2_qos_port_map_set(int unit, bcm_gport_t port, int ing_map, int egr_map) 2194 { 2195 int rv = BCM_E_NONE; 2196 bcm_port_t local_port; 2197 2198 QOS_INIT(unit); 2199 QOS_LOCK(unit); 2200 2201 if (!BCM_GPORT_IS_SET(port)) { 2202 rv = BCM_E_PARAM; 2203 } 2204 2205 if (BCM_SUCCESS(rv)) { 2206 rv = bcm_esw_port_local_get(unit, port, &local_port); 2207 } 2208 2209 if (BCM_SUCCESS(rv) && !SOC_PORT_VALID(unit, local_port)) { 2210 rv = BCM_E_PARAM; 2211 } 2212 2213 if (BCM_SUCCESS(rv) && ing_map != _BCM_QOS_NO_MAP) { 2214 int id = ing_map & _BCM_QOS_MAP_TYPE_MASK; 2215 2216 if (((ing_map >> _BCM_QOS_MAP_SHIFT) != 2217 _BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP) 2218 && ((ing_map >> _BCM_QOS_MAP_SHIFT) != 2219 _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP)){ 2220 rv = BCM_E_PARAM; 2221 } 2222 2223 if (BCM_SUCCESS(rv) 2224 && ((((ing_map >> _BCM_QOS_MAP_SHIFT) == 2225 _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP) 2226 && (_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id) == 0)) 2227 || (((ing_map >> _BCM_QOS_MAP_SHIFT) == 2228 _BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP) 2229 && (_BCM_QOS_ING_VFT_PRI_MAP_TABLE_USED_GET(unit, id) == 0)))) { 2230 rv = BCM_E_PARAM; 2231 } 2232 2233 if (BCM_SUCCESS(rv)) { 2234 rv = _bcm_td2_qos_apply_ing_map_to_port(unit, ing_map, local_port); 2235 } 2236 } 2237 2238 if (BCM_SUCCESS(rv) && egr_map != _BCM_QOS_NO_MAP) { 2239 int id = egr_map & _BCM_QOS_MAP_TYPE_MASK; 2240 2241 if ((egr_map >> _BCM_QOS_MAP_SHIFT) == 2242 _BCM_QOS_MAP_TYPE_EGR_VFT_PRI_MAP) { 2243 if (_BCM_QOS_EGR_VFT_PRI_MAP_TABLE_USED_GET(unit, id) != 0) { 2244 rv = _bcm_td2_qos_apply_egr_map_to_port(unit, id, 2245 local_port); 2246 } else { 2247 rv = BCM_E_PARAM; 2248 } 2249 } else if ((egr_map >> _BCM_QOS_MAP_SHIFT) == 2250 _BCM_QOS_MAP_TYPE_EGR_VSAN_PRI_MAP) { 2251 rv = BCM_E_PARAM; /* should use bcm_td2_fcoe_intf_config_set */ 2252 } 2253 } 2254 2255 QOS_UNLOCK(unit); 2256 2257 return rv; 2258 } 2259 2260 2261 /* 2262 * Function: 2263 * bcm_td2_qos_port_map_type_get 2264 * Purpose: 2265 * Retrieve ingress or egress map from a given port. 2266 * Parameters: 2267 * unit - (IN) The unit to be operated on 2268 * port - (IN) The port number for the map to be retrieved from 2269 * flags - (IN) type of the map which is of interest 2270 * map_id - (OUT) The ID of map returned 2271 * Returns: 2272 * BCM_E_XXX 2273 */ 2274 int 2275 bcm_td2_qos_port_map_type_get(int unit, bcm_gport_t port, uint32 flags, 2276 int *map_id) 2277 { 2278 int rv = BCM_E_NONE; 2279 bcm_port_t local_port; 2280 int map_type; 2281 int profile_idx; 2282 2283 QOS_INIT(unit); 2284 2285 if (map_id == NULL) { 2286 rv = BCM_E_PARAM; 2287 } 2288 if (!BCM_GPORT_IS_SET(port)) { 2289 rv = BCM_E_PARAM; 2290 } 2291 2292 if (BCM_SUCCESS(rv)) { 2293 rv = bcm_esw_port_local_get(unit, port, &local_port); 2294 } 2295 2296 if (BCM_SUCCESS(rv) && !SOC_PORT_VALID(unit, local_port)) { 2297 rv = BCM_E_PARAM; 2298 } 2299 2300 BCM_IF_ERROR_RETURN(rv); 2301 2302 if (flags & BCM_QOS_MAP_INGRESS) { 2303 if (flags & BCM_QOS_MAP_VFT) { 2304 map_type = _BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP; 2305 } else if (flags & BCM_QOS_MAP_L2_VLAN_ETAG) { 2306 map_type = _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP; 2307 } else { 2308 rv = BCM_E_PARAM; 2309 BCM_IF_ERROR_RETURN(rv); 2310 } 2311 rv = _bcm_td2_qos_port_ing_profile_get(unit, local_port, map_type, 2312 &profile_idx); 2313 } else if (flags & BCM_QOS_MAP_EGRESS) { 2314 if (flags & BCM_QOS_MAP_VFT) { 2315 map_type = _BCM_QOS_MAP_TYPE_EGR_VFT_PRI_MAP; 2316 } else if (flags & BCM_QOS_MAP_VSAN) { 2317 map_type = _BCM_QOS_MAP_TYPE_EGR_VSAN_PRI_MAP; 2318 } else if (flags & BCM_QOS_MAP_L2_VLAN_ETAG) { 2319 map_type = _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP; 2320 } else { 2321 rv = BCM_E_PARAM; 2322 BCM_IF_ERROR_RETURN(rv); 2323 } 2324 rv = _bcm_td2_qos_port_egr_profile_get(unit, local_port, map_type, 2325 &profile_idx); 2326 } else { 2327 rv = BCM_E_PARAM; 2328 BCM_IF_ERROR_RETURN(rv); 2329 } 2330 2331 if(BCM_SUCCESS(rv)) { 2332 /* map H/W profile ID to API QoS map ID */ 2333 rv = _bcm_td2_qos_idx2id(unit, profile_idx, map_type, map_id); 2334 } 2335 2336 return rv; 2337 } 2338 2339 2340 /* bcm_td2_qos_map_multi_get */ 2341 int 2342 bcm_td2_qos_map_multi_get(int unit, uint32 flags, 2343 int map_id, int array_size, 2344 bcm_qos_map_t *array, int *array_count) 2345 { 2346 int rv = BCM_E_NONE; 2347 int num_entries, idx, id, hw_id, alloc_size, entry_size, count; 2348 uint8 *dma_buf; 2349 void *entry; 2350 soc_mem_t mem; 2351 bcm_qos_map_t *map; 2352 int cng = 0; 2353 int hw_color = TD2_HW_COLOR_ERROR; 2354 2355 /* ignore with_id & replace flags */ 2356 flags &= (~(BCM_QOS_MAP_WITH_ID | BCM_QOS_MAP_REPLACE)); 2357 id = map_id & _BCM_QOS_MAP_TYPE_MASK; 2358 mem = INVALIDm; 2359 hw_id = 0; 2360 num_entries = 0; 2361 entry_size = 0; 2362 QOS_LOCK(unit); 2363 switch (map_id >> _BCM_QOS_MAP_SHIFT) { 2364 case _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP: 2365 if ((flags != (BCM_QOS_MAP_L2_VLAN_ETAG | BCM_QOS_MAP_INGRESS)) || 2366 (!_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id))) { 2367 rv = BCM_E_PARAM; 2368 } 2369 num_entries = _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP; 2370 entry_size = sizeof(ing_etag_pcp_mapping_entry_t); 2371 hw_id = VFT_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[id] * 2372 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP; 2373 mem = ING_ETAG_PCP_MAPPINGm; 2374 break; 2375 2376 case _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP: 2377 if ((flags != (BCM_QOS_MAP_L2_VLAN_ETAG | BCM_QOS_MAP_EGRESS)) || 2378 (!_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id))) { 2379 rv = BCM_E_PARAM; 2380 break; 2381 } 2382 num_entries = _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP; 2383 if (SOC_IS_TRIDENT3X(unit)) { 2384 entry_size = sizeof(egr_zone_3_dot1p_mapping_table_2_entry_t); 2385 mem = EGR_ZONE_3_DOT1P_MAPPING_TABLE_2m; 2386 } else { 2387 entry_size = sizeof(egr_etag_pcp_mapping_entry_t); 2388 mem = EGR_ETAG_PCP_MAPPINGm; 2389 } 2390 hw_id = VFT_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[id] * 2391 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP; 2392 break; 2393 2394 case _BCM_QOS_MAP_TYPE_EGR_VSAN_PRI_MAP: 2395 if ((flags != (BCM_QOS_MAP_VSAN | BCM_QOS_MAP_EGRESS)) || 2396 (!_BCM_QOS_EGR_VSAN_PRI_MAP_TABLE_USED_GET(unit, id))) { 2397 rv = BCM_E_PARAM; 2398 break; 2399 } 2400 num_entries = _BCM_QOS_MAP_CHUNK_VSAN_PRI_MAP; 2401 entry_size = sizeof(egr_vsan_intpri_map_entry_t); 2402 hw_id = VFT_QOS_INFO(unit)->egr_vsan_intpri_map_hwidx[id] * 2403 _BCM_QOS_MAP_CHUNK_VSAN_PRI_MAP; 2404 mem = EGR_VSAN_INTPRI_MAPm; 2405 break; 2406 2407 case _BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP: 2408 if ((flags != (BCM_QOS_MAP_VFT | BCM_QOS_MAP_INGRESS)) || 2409 (!_BCM_QOS_ING_VFT_PRI_MAP_TABLE_USED_GET(unit, id))) { 2410 rv = BCM_E_PARAM; 2411 break; 2412 } 2413 num_entries = _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP; 2414 entry_size = sizeof(ing_vft_pri_map_entry_t); 2415 hw_id = VFT_QOS_INFO(unit)->ing_vft_pri_map_hwidx[id] * 2416 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP; 2417 mem = ING_VFT_PRI_MAPm; 2418 break; 2419 2420 case _BCM_QOS_MAP_TYPE_EGR_VFT_PRI_MAP: 2421 if ((flags != (BCM_QOS_MAP_VFT | BCM_QOS_MAP_EGRESS)) || 2422 (!_BCM_QOS_EGR_VFT_PRI_MAP_TABLE_USED_GET(unit, id))) { 2423 rv = BCM_E_PARAM; 2424 } 2425 num_entries = _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP; 2426 entry_size = sizeof(egr_vft_pri_map_entry_t); 2427 hw_id = VFT_QOS_INFO(unit)->egr_vft_pri_map_hwidx[id] * 2428 _BCM_QOS_MAP_CHUNK_VFT_PRI_MAP; 2429 mem = EGR_VFT_PRI_MAPm; 2430 break; 2431 2432 default: 2433 rv = BCM_E_PARAM; 2434 } 2435 QOS_UNLOCK(unit); 2436 BCM_IF_ERROR_RETURN(rv); 2437 2438 if (array_size == 0) { /* querying the size of map-chunk */ 2439 *array_count = num_entries; 2440 return BCM_E_NONE; 2441 } 2442 if (!array || !array_count) { 2443 return BCM_E_PARAM; 2444 } 2445 2446 /* Allocate memory for DMA & regular */ 2447 alloc_size = num_entries * entry_size; 2448 dma_buf = soc_cm_salloc(unit, alloc_size, "TD2 qos multi get DMA buf"); 2449 if (!dma_buf) { 2450 return BCM_E_MEMORY; 2451 } 2452 sal_memset(dma_buf, 0, alloc_size); 2453 2454 /* Read the profile chunk */ 2455 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, hw_id, 2456 (hw_id + num_entries - 1), dma_buf); 2457 if (BCM_FAILURE(rv)) { 2458 soc_cm_sfree(unit, dma_buf); 2459 return rv; 2460 } 2461 2462 count = 0; 2463 QOS_LOCK(unit); 2464 switch (map_id >> _BCM_QOS_MAP_SHIFT) { 2465 case _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP: 2466 for (idx=0; ((idx<num_entries) && (count < array_size)); idx++) { 2467 map = &array[idx]; 2468 sal_memset(map, 0x0, sizeof(bcm_qos_map_t)); 2469 map->pkt_pri = ((idx & 0xe) >> 1); 2470 map->pkt_cfi = (idx & 0x1); 2471 entry = soc_mem_table_idx_to_pointer(unit, mem, void *, 2472 dma_buf, idx); 2473 map->etag_pcp = soc_mem_field32_get(unit, mem, entry, PCPf); 2474 map->etag_de = soc_mem_field32_get(unit, mem, entry, DEf); 2475 count++; 2476 } 2477 break; 2478 2479 case _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP: 2480 for (idx = 0; ((idx < num_entries) && (count < array_size)); idx++) { 2481 map = &array[idx]; 2482 sal_memset(map, 0x0, sizeof(bcm_qos_map_t)); 2483 map->int_pri = (idx >> 2) & 0xf; 2484 cng = idx & 0x3; 2485 map->color = _BCM_COLOR_DECODING(unit, cng); 2486 entry = soc_mem_table_idx_to_pointer(unit, mem, void *, 2487 dma_buf, idx); 2488 if (SOC_IS_TRIDENT3X(unit)) { 2489 map->etag_pcp = soc_mem_field32_get(unit, mem, entry, PRIf); 2490 map->etag_de = soc_mem_field32_get(unit, mem, entry, CFIf); 2491 } else { 2492 map->etag_pcp = soc_mem_field32_get(unit, mem, entry, PCPf); 2493 map->etag_de = soc_mem_field32_get(unit, mem, entry, DEf); 2494 } 2495 count++; 2496 } 2497 break; 2498 2499 case _BCM_QOS_MAP_TYPE_EGR_VSAN_PRI_MAP: 2500 for (idx = 0; ((idx < num_entries) && (count < array_size)); idx++) { 2501 map = &array[idx]; 2502 sal_memset(map, 0x0, sizeof(bcm_qos_map_t)); 2503 map->int_pri = ((idx & 0x3c) >> 2); 2504 hw_color = (idx & 0x3); 2505 map->color = _BCM_COLOR_DECODING(unit, hw_color); 2506 entry = soc_mem_table_idx_to_pointer(unit, mem, void *, 2507 dma_buf, idx); 2508 map->pkt_pri = soc_mem_field32_get(unit, mem, entry, PRIf); 2509 count++; 2510 } 2511 break; 2512 2513 case _BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP: 2514 for (idx=0; ((idx<num_entries) && (count < array_size)); idx++) { 2515 map = &array[idx]; 2516 sal_memset(map, 0x0, sizeof(bcm_qos_map_t)); 2517 map->pkt_pri = idx; 2518 entry = soc_mem_table_idx_to_pointer(unit, mem, void *, 2519 dma_buf, idx); 2520 map->int_pri = soc_mem_field32_get(unit, mem, entry, FCOE_VFT_PRIf); 2521 count++; 2522 } 2523 break; 2524 2525 case _BCM_QOS_MAP_TYPE_EGR_VFT_PRI_MAP: 2526 for (idx = 0; ((idx < num_entries) && (count < array_size)); idx++) { 2527 map = &array[idx]; 2528 sal_memset(map, 0x0, sizeof(bcm_qos_map_t)); 2529 map->int_pri = idx; 2530 entry = soc_mem_table_idx_to_pointer(unit, mem, void *, 2531 dma_buf, idx); 2532 map->pkt_pri = soc_mem_field32_get(unit, mem, entry, FCOE_VFT_PRIf); 2533 count++; 2534 } 2535 break; 2536 2537 default: 2538 rv = BCM_E_INTERNAL; /* should not hit this */ 2539 } 2540 QOS_UNLOCK(unit); 2541 soc_cm_sfree(unit, dma_buf); 2542 2543 BCM_IF_ERROR_RETURN(rv); 2544 2545 *array_count = count; 2546 return BCM_E_NONE; 2547 } 2548 2549 #undef DSCP_CODE_POINT_CNT 2550 #define DSCP_CODE_POINT_CNT 64 2551 #undef DSCP_CODE_POINT_MAX 2552 #define DSCP_CODE_POINT_MAX (DSCP_CODE_POINT_CNT - 1) 2553 #define _BCM_QOS_MAP_CHUNK_DSCP 64 2554 2555 /* Function: 2556 * bcm_td2_port_dscp_map_set 2557 * Purpose: 2558 * Internal implementation for bcm_td2_port_dscp_map_set 2559 * Parameters: 2560 * unit - switch device 2561 * port - switch port or -1 for global table 2562 * srccp - src code point or -1 2563 * mapcp - mapped code point or -1 2564 * prio - priority value for mapped code point 2565 * -1 to use port default untagged priority 2566 * BCM_PRIO_RED can be or'ed into the priority 2567 * BCM_PRIO_YELLOW can be or'ed into the priority 2568 * Returns: 2569 * BCM_E_XXX 2570 */ 2571 2572 int 2573 bcm_td2_port_dscp_map_set(int unit, bcm_port_t port, int srccp, 2574 int mapcp, int prio, int cng) 2575 { 2576 port_tab_entry_t pent; 2577 void *entries[2]; 2578 uint32 old_profile_index = 0; 2579 int index = 0; 2580 int rv = BCM_E_NONE; 2581 dscp_table_entry_t dscp_table[64]; 2582 phb_mapping_tbl_2_entry_t phb_map_tbl[64]; 2583 int offset = 0, i = 0; 2584 void *entry = NULL; 2585 soc_mem_t dscpm = DSCP_TABLEm; 2586 soc_field_t prifd = PRIf; 2587 int port_count = 0, ref_count = 0; 2588 /* Lock the port table */ 2589 PORT_LOCK(unit); 2590 2591 if (SOC_IS_TRIDENT3X(unit)) { 2592 rv = _bcm_esw_port_tab_get(unit, port, TRUST_DSCP_PTRf, 2593 (void *)&old_profile_index); 2594 if (BCM_FAILURE(rv)) { 2595 goto cleanup_bcm_td2_port_dscp_map_set; 2596 } 2597 old_profile_index = old_profile_index * DSCP_CODE_POINT_CNT; 2598 } else { 2599 /* Get profile index from port table. */ 2600 rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, port, &pent); 2601 if (BCM_FAILURE(rv)) { 2602 goto cleanup_bcm_td2_port_dscp_map_set; 2603 } 2604 old_profile_index = 2605 soc_mem_field32_get(unit, PORT_TABm, &pent, TRUST_DSCP_PTRf) * \ 2606 DSCP_CODE_POINT_CNT; 2607 } 2608 2609 sal_memset(dscp_table, 0, sizeof(dscp_table)); 2610 sal_memset(phb_map_tbl, 0, sizeof(phb_map_tbl)); 2611 2612 /* Base index of table in hardware */ 2613 if (SOC_MEM_IS_VALID(unit, PHB_MAPPING_TBL_2m)) { 2614 entries[0] = &phb_map_tbl; 2615 dscpm = PHB_MAPPING_TBL_2m; 2616 prifd = INT_PRIf; 2617 } else { 2618 entries[0] = &dscp_table; 2619 } 2620 2621 rv = _bcm_dscp_table_entry_get(unit, old_profile_index, 64, entries); 2622 if (BCM_FAILURE(rv)) { 2623 goto cleanup_bcm_td2_port_dscp_map_set; 2624 } 2625 offset = srccp; 2626 /* Modify what's needed */ 2627 2628 if (offset < 0) { 2629 for (i = 0; i <= DSCP_CODE_POINT_MAX; i++) { 2630 if (dscpm == DSCP_TABLEm) { 2631 entry = &dscp_table[i]; 2632 } else { 2633 entry = &phb_map_tbl[i]; 2634 soc_mem_field32_set(unit, dscpm, entry, DSCP_VALIDf, 1); 2635 } 2636 soc_mem_field32_set(unit, dscpm, entry, DSCPf, mapcp); 2637 soc_mem_field32_set(unit, dscpm, entry, prifd, prio); 2638 soc_mem_field32_set(unit, dscpm, entry, CNGf, cng); 2639 } 2640 } else { 2641 if (dscpm == DSCP_TABLEm) { 2642 entry = &dscp_table[offset]; 2643 } else { 2644 entry = &phb_map_tbl[offset]; 2645 soc_mem_field32_set(unit, dscpm, entry, DSCP_VALIDf, 1); 2646 } 2647 soc_mem_field32_set(unit, dscpm, entry, DSCPf, mapcp); 2648 soc_mem_field32_set(unit, dscpm, entry, prifd, prio); 2649 soc_mem_field32_set(unit, dscpm, entry, CNGf, cng); 2650 } 2651 2652 /* Add new chunk and store new HW index */ 2653 rv = _bcm_dscp_table_entry_add(unit, entries, _BCM_QOS_MAP_CHUNK_DSCP, 2654 (uint32 *)&index); 2655 if (BCM_FAILURE(rv)) { 2656 goto cleanup_bcm_td2_port_dscp_map_set; 2657 } 2658 2659 if (index != old_profile_index) { 2660 if (SOC_IS_TRIDENT3X(unit)) { 2661 rv = _bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_BOTH, 2662 TRUST_DSCP_PTRf, index / _BCM_QOS_MAP_CHUNK_DSCP); 2663 if (BCM_FAILURE(rv)) { 2664 goto cleanup_bcm_td2_port_dscp_map_set; 2665 } 2666 } else { 2667 soc_mem_field32_set(unit, PORT_TABm, &pent, TRUST_DSCP_PTRf, 2668 index / _BCM_QOS_MAP_CHUNK_DSCP); 2669 rv = soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL, port, 2670 &pent); 2671 if (BCM_FAILURE(rv)) { 2672 goto cleanup_bcm_td2_port_dscp_map_set; 2673 } 2674 } 2675 } 2676 if (!old_profile_index) { 2677 BCM_PBMP_COUNT(PBMP_ALL(unit), port_count); 2678 rv = _bcm_dscp_table_entry_ref_count_get(unit, old_profile_index, 2679 &ref_count); 2680 if (BCM_FAILURE(rv)) { 2681 goto cleanup_bcm_td2_port_dscp_map_set; 2682 } 2683 /* DSCP_TABLE default profile index 0 is referenced by all active 2684 * ports in the cosq init time. Reference count for profile index 0 2685 * should be decremented only when it is greater than active port 2686 * count. 2687 */ 2688 if (ref_count > port_count) { 2689 rv = _bcm_dscp_table_entry_delete(unit, old_profile_index); 2690 } 2691 } else { 2692 rv = _bcm_dscp_table_entry_delete(unit, old_profile_index); 2693 } 2694 2695 cleanup_bcm_td2_port_dscp_map_set: 2696 /* Release port table lock */ 2697 PORT_UNLOCK(unit); 2698 return rv; 2699 } 2700 2701 /* Function: 2702 * bcm_td2_qos_egr_etag_id2profile 2703 * Purpose: 2704 * Given a QOS map ID for a egress etag mapping profile, return the profile number 2705 * into the EGR_ETAG_PCP_MAPPING table. 2706 * Parameters: 2707 * unit - (IN) Unit being operated on 2708 * map_id - (IN) ID of the map to be retrieved 2709 * profile_num - (OUT) Hardware profile number that map_id maps to 2710 * Returns: 2711 * BCM_E_XXX 2712 */ 2713 int 2714 bcm_td2_qos_egr_etag_id2profile(int unit, int map_id, int *profile_num) 2715 { 2716 int id; 2717 2718 QOS_INIT(unit); 2719 id = map_id & _BCM_QOS_MAP_TYPE_MASK; 2720 2721 QOS_LOCK(unit); 2722 if (!_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id)) { 2723 QOS_UNLOCK(unit); 2724 return BCM_E_NOT_FOUND; 2725 } else { 2726 *profile_num = VFT_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[id]; 2727 } 2728 2729 QOS_UNLOCK(unit); 2730 return BCM_E_NONE; 2731 } 2732 2733 /* Function: 2734 * bcm_td2_qos_egr_etag_profile2id 2735 * Purpose: 2736 * Given a EGR_ETAG_PCP_MAPPING table profile number, find the QOS map ID which maps to it. 2737 * Parameters: 2738 * unit - (IN) Unit being operated on 2739 * profile_num - (IN) profile number of the map to be retrieved 2740 * map_id - (OUT) Map ID that points to profile_num 2741 * Returns: 2742 * BCM_E_XXX 2743 */ 2744 int 2745 bcm_td2_qos_egr_etag_profile2id(int unit, int profile_num, int *map_id) 2746 { 2747 int i; 2748 2749 QOS_INIT(unit); 2750 2751 QOS_LOCK(unit); 2752 for (i = 0; i < _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAP_IDS; i++) { 2753 if (VFT_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[i] == profile_num) { 2754 *map_id = (_BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP << _BCM_QOS_MAP_SHIFT) | i; 2755 QOS_UNLOCK(unit); 2756 return BCM_E_NONE; 2757 } 2758 } 2759 2760 QOS_UNLOCK(unit); 2761 return BCM_E_BADID; 2762 } 2763 2764 /* Function: 2765 * _bcm_td2_qos_id2idx 2766 * Purpose: 2767 * Translate hardware table index into map ID used by API 2768 * Parameters: 2769 * Returns: 2770 * BCM_E_XXX 2771 */ 2772 int 2773 _bcm_td2_qos_idx2id(int unit, int hw_idx, int type, int *map_id) 2774 { 2775 int idx; 2776 int rv = BCM_E_NOT_FOUND; 2777 2778 if (map_id == NULL) { 2779 return BCM_E_PARAM; 2780 } 2781 2782 QOS_INIT(unit); 2783 2784 QOS_LOCK(unit); 2785 2786 switch (type) { 2787 case _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP: 2788 for (idx = 0; idx < _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; idx++) { 2789 if (_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, idx)) { 2790 if (VFT_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[idx] 2791 == hw_idx) { 2792 *map_id = idx | (_BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP 2793 << _BCM_QOS_MAP_SHIFT); 2794 rv = BCM_E_NONE; 2795 break; 2796 } 2797 } 2798 } 2799 2800 break; 2801 2802 case _BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP: 2803 for (idx = 0; idx < _BCM_QOS_MAX_VFT_PRI_MAPS; idx++) { 2804 if (_BCM_QOS_ING_VFT_PRI_MAP_TABLE_USED_GET(unit, idx)) { 2805 if (VFT_QOS_INFO(unit)->ing_vft_pri_map_hwidx[idx] == hw_idx) { 2806 *map_id = idx | (_BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP 2807 << _BCM_QOS_MAP_SHIFT); 2808 rv = BCM_E_NONE; 2809 break; 2810 } 2811 } 2812 } 2813 2814 break; 2815 2816 case _BCM_QOS_MAP_TYPE_EGR_VFT_PRI_MAP: 2817 for (idx = 0; idx < _BCM_QOS_MAX_VFT_PRI_MAPS; idx++) { 2818 if (_BCM_QOS_EGR_VFT_PRI_MAP_TABLE_USED_GET(unit, idx)) { 2819 if (VFT_QOS_INFO(unit)->egr_vft_pri_map_hwidx[idx] == hw_idx) { 2820 *map_id = idx | (_BCM_QOS_MAP_TYPE_EGR_VFT_PRI_MAP 2821 << _BCM_QOS_MAP_SHIFT); 2822 rv = BCM_E_NONE; 2823 break; 2824 } 2825 } 2826 } 2827 2828 break; 2829 2830 default: 2831 rv = BCM_E_NOT_FOUND; 2832 } 2833 2834 QOS_UNLOCK(unit); 2835 2836 return rv; 2837 } 2838 2839 /* Get the list of all created fcoe Map-ids along with corresponding flags */ 2840 void 2841 _bcm_td2_qos_fcoe_get(int unit, int array_size, int *map_ids_array, 2842 int *flags_array, int *array_count) 2843 { 2844 int idx, count; 2845 2846 if (array_size == 0) { 2847 *array_count = 0; 2848 count = 0; 2849 SHR_BITCOUNT_RANGE(VFT_QOS_INFO(unit)->egr_vsan_intpri_map, count, 2850 0, _BCM_QOS_MAX_VSAN_PRI_MAPS); 2851 *array_count += count; 2852 SHR_BITCOUNT_RANGE(VFT_QOS_INFO(unit)->ing_vft_pri_map, count, 2853 0, _BCM_QOS_MAX_VFT_PRI_MAPS); 2854 *array_count += count; 2855 SHR_BITCOUNT_RANGE(VFT_QOS_INFO(unit)->egr_vft_pri_map, count, 2856 0, _BCM_QOS_MAX_VFT_PRI_MAPS); 2857 *array_count += count; 2858 } else { 2859 for (idx = 0; ((idx < _BCM_QOS_MAX_VSAN_PRI_MAPS) && 2860 (*array_count < array_size)); idx++) { 2861 if (_BCM_QOS_EGR_VSAN_PRI_MAP_TABLE_USED_GET(unit, idx)) { 2862 *(map_ids_array + *array_count) = 2863 idx | (_BCM_QOS_MAP_TYPE_EGR_VSAN_PRI_MAP << 2864 _BCM_QOS_MAP_SHIFT); 2865 *(flags_array + *array_count) = BCM_QOS_MAP_VSAN | BCM_QOS_MAP_EGRESS; 2866 (*array_count)++; 2867 } 2868 } 2869 for (idx = 0; ((idx < _BCM_QOS_MAX_VFT_PRI_MAPS) && 2870 (*array_count < array_size)); idx++) { 2871 if (_BCM_QOS_ING_VFT_PRI_MAP_TABLE_USED_GET(unit, idx)) { 2872 *(map_ids_array + *array_count) = 2873 idx | (_BCM_QOS_MAP_TYPE_ING_VFT_PRI_MAP << 2874 _BCM_QOS_MAP_SHIFT); 2875 *(flags_array + *array_count) = BCM_QOS_MAP_VFT | BCM_QOS_MAP_INGRESS; 2876 (*array_count)++; 2877 } 2878 } 2879 for (idx = 0; ((idx < _BCM_QOS_MAX_VFT_PRI_MAPS) && 2880 (*array_count < array_size)); idx++) { 2881 if (_BCM_QOS_EGR_VFT_PRI_MAP_TABLE_USED_GET(unit, idx)) { 2882 *(map_ids_array + *array_count) = 2883 idx | (_BCM_QOS_MAP_TYPE_EGR_VFT_PRI_MAP << 2884 _BCM_QOS_MAP_SHIFT); 2885 *(flags_array + *array_count) = BCM_QOS_MAP_VFT | BCM_QOS_MAP_EGRESS; 2886 (*array_count)++; 2887 } 2888 } 2889 } 2890 return; 2891 } 2892 2893 /* Get the list of all created L2 VLAN ETAG Map-ids along with corresponding flags */ 2894 int 2895 _bcm_td2_qos_multi_get(int unit, int array_size, int *map_ids_array, 2896 int *flags_array, int *array_count) 2897 { 2898 /* Assume that QoS lock has been taken */ 2899 2900 int idx, count; 2901 int rv = BCM_E_NONE; 2902 2903 if (array_size == 0) { 2904 if (array_count == NULL) { 2905 rv = BCM_E_PARAM; 2906 } 2907 2908 if (BCM_SUCCESS(rv)) { 2909 *array_count = 0; 2910 count = 0; 2911 SHR_BITCOUNT_RANGE(VFT_QOS_INFO(unit)->ing_l2_vlan_etag_map, count, 2912 0, _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS); 2913 *array_count += count; 2914 count = 0; 2915 SHR_BITCOUNT_RANGE(VFT_QOS_INFO(unit)->egr_l2_vlan_etag_map, count, 2916 0, _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS); 2917 *array_count += count; 2918 } 2919 } else { 2920 if ((map_ids_array == NULL) || (flags_array == NULL) || 2921 (array_count == NULL)) { 2922 rv = BCM_E_PARAM; 2923 } 2924 2925 if (BCM_SUCCESS(rv)) { 2926 count = 0; 2927 for (idx = 0; ((idx < _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS) && 2928 (count < array_size)); idx++) { 2929 if (_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, idx)) { 2930 *(map_ids_array + count) = 2931 idx | (_BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP << 2932 _BCM_QOS_MAP_SHIFT); 2933 *(flags_array + count) = BCM_QOS_MAP_L2_VLAN_ETAG | BCM_QOS_MAP_INGRESS; 2934 count++; 2935 } 2936 } 2937 for (idx = 0; ((idx < _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS) && 2938 (count < array_size)); idx++) { 2939 if (_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, idx)) { 2940 *(map_ids_array + count) = 2941 idx | (_BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP << 2942 _BCM_QOS_MAP_SHIFT); 2943 *(flags_array + count) = BCM_QOS_MAP_L2_VLAN_ETAG | BCM_QOS_MAP_EGRESS; 2944 count++; 2945 } 2946 } 2947 2948 *array_count = count; 2949 } 2950 2951 } 2952 2953 return rv; 2954 } 2955 2956 #endif /* BCM_TRIDENT2_SUPPORT */