failover.c (13485B)
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 * Saber2 failover API 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <soc/defs.h> 13 #include <sal/core/libc.h> 14 15 #if defined(BCM_SABER2_SUPPORT) && defined(INCLUDE_L3) 16 17 #include <soc/drv.h> 18 #include <soc/mem.h> 19 #include <soc/util.h> 20 #include <soc/debug.h> 21 #include <bcm/types.h> 22 #include <bcm/error.h> 23 #include <bcm/failover.h> 24 #include <bcm_int/esw_dispatch.h> 25 #include <bcm_int/esw/katana2.h> 26 #include <bcm_int/esw/katana.h> 27 #include <bcm_int/common/multicast.h> 28 #include <bcm_int/esw/failover.h> 29 #include <bcm_int/esw/triumph2.h> 30 #ifdef BCM_WARM_BOOT_SUPPORT 31 #include <bcm_int/esw/switch.h> 32 #include <soc/scache.h> 33 #endif /* BCM_WARM_BOOT_SUPPORT */ 34 35 36 typedef struct _bcm_failover_keeper_s { 37 int primary_nhi; 38 int secondary_nhi; 39 } _bcm_failover_keeper_t; 40 STATIC _bcm_failover_keeper_t *failover_keeper[SOC_MAX_NUM_DEVICES]; 41 42 43 #ifdef BCM_WARM_BOOT_SUPPORT 44 45 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 46 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_0 47 48 STATIC int 49 _bcm_sb2_failover_wb_alloc(int unit) 50 { 51 soc_scache_handle_t scache_handle; 52 uint8 *scache_ptr; 53 int rv, alloc_size; 54 55 56 alloc_size = 3 * sizeof(uint32) * 2 * soc_mem_index_count(unit,MMU_INITIAL_NHOP_TBLm); 57 58 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FAILOVER, 0); 59 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size, 60 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL); 61 if (rv == BCM_E_NOT_FOUND) { 62 rv = BCM_E_NONE; 63 } 64 65 return rv; 66 } 67 68 int 69 bcm_sb2_failover_sync(int unit) 70 { 71 soc_scache_handle_t scache_handle; 72 uint8 *scache_ptr, *ptr; 73 uint32 index; 74 75 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FAILOVER, 0); 76 BCM_IF_ERROR_RETURN 77 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, 78 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL)); 79 80 ptr = scache_ptr; 81 for (index = 0; index < (2 * soc_mem_index_count (unit, MMU_INITIAL_NHOP_TBLm)); 82 index++) 83 { 84 *(((uint32 *)ptr)) = failover_keeper[unit][index].primary_nhi; 85 ptr += sizeof(uint32); 86 *(((uint32 *)ptr)) = failover_keeper[unit][index].secondary_nhi; 87 ptr += sizeof(uint32); 88 if (_BCM_FAILOVER_MMU_PROT_GROUP_MAP_USED_GET(unit, index)) { 89 *(((uint32 *)ptr)) = 0x1; 90 } else { 91 *(((uint32 *)ptr)) = 0x0; 92 } 93 ptr += sizeof(uint32); 94 } 95 return BCM_E_NONE; 96 } 97 98 int 99 bcm_sb2_failover_reinit(int unit) 100 { 101 soc_scache_handle_t scache_handle; 102 uint8 *scache_ptr, *ptr; 103 int stable_size, rv; 104 uint16 recovered_ver; 105 int index; 106 107 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 108 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 109 /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/ 110 return BCM_E_NONE; 111 } 112 113 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FAILOVER, 0); 114 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &scache_ptr, 115 BCM_WB_DEFAULT_VERSION, &recovered_ver); 116 if (BCM_E_NOT_FOUND == rv) { 117 /* Upgrading from SDK release that does not have warmboot state */ 118 BCM_IF_ERROR_RETURN(_bcm_sb2_failover_wb_alloc(unit)); 119 return BCM_E_NONE; 120 } else if (BCM_FAILURE(rv)) { 121 return rv; 122 } 123 124 ptr = scache_ptr; 125 126 for (index = 0; index < (2 * soc_mem_index_count (unit, MMU_INITIAL_NHOP_TBLm)); 127 index++) { 128 failover_keeper[unit][index].primary_nhi = *(((uint32 *)ptr)); 129 ptr += sizeof(uint32); 130 failover_keeper[unit][index].secondary_nhi = *(((uint32 *)ptr)); 131 ptr += sizeof(uint32); 132 if (*(((uint32 *)ptr)) == 1) { 133 _BCM_FAILOVER_MMU_PROT_GROUP_MAP_USED_SET(unit, index); 134 } 135 ptr += sizeof(uint32); 136 } 137 return BCM_E_NONE; 138 } 139 #endif 140 141 int 142 bcm_sb2_failover_init(int unit) 143 { 144 int index; 145 if (failover_keeper[unit] == NULL) { 146 failover_keeper[unit] = 147 sal_alloc((sizeof(_bcm_failover_keeper_t) * 148 2 * soc_mem_index_count(unit,MMU_INITIAL_NHOP_TBLm )), 149 "failover_keeper"); 150 } 151 for (index = 0; index < (2 * soc_mem_index_count(unit,MMU_INITIAL_NHOP_TBLm )); 152 index++) { 153 failover_keeper[unit][index].primary_nhi = -1; 154 failover_keeper[unit][index].secondary_nhi = -1; 155 } 156 #ifdef BCM_WARM_BOOT_SUPPORT 157 if (SOC_WARM_BOOT(unit)) { 158 return bcm_sb2_failover_reinit(unit); 159 } else { 160 BCM_IF_ERROR_RETURN(_bcm_sb2_failover_wb_alloc(unit)); 161 } 162 #endif /* BCM_WARM_BOOT_SUPPORT */ 163 164 165 return BCM_E_NONE; 166 } 167 168 int 169 bcm_sb2_failover_cleanup(int unit) 170 { 171 if (failover_keeper[unit]) { 172 sal_free(failover_keeper[unit]); 173 failover_keeper[unit] = NULL; 174 } 175 176 return BCM_E_NONE; 177 178 } 179 180 int 181 bcm_sb2_failover_destroy(int unit, int failover_id) 182 { 183 mmu_initial_nhop_tbl_entry_t mmu_prot_nhi_entry; 184 soc_field_t field[4] = 185 { 186 PROT_DROP_STATUS0f, 187 PROT_DROP_STATUS1f, 188 PROT_DROP_STATUS2f, 189 PROT_DROP_STATUS3f 190 }; 191 if (failover_keeper[unit][failover_id].primary_nhi != -1) { 192 193 BCM_IF_ERROR_RETURN (soc_mem_read(unit, MMU_INITIAL_NHOP_TBLm, 194 MEM_BLOCK_ANY, 195 failover_keeper[unit][failover_id].primary_nhi / 4, 196 &mmu_prot_nhi_entry)); 197 198 soc_mem_field32_set(unit, MMU_INITIAL_NHOP_TBLm, 199 &mmu_prot_nhi_entry, 200 field[failover_keeper[unit][failover_id].primary_nhi % 4] , 0); 201 202 BCM_IF_ERROR_RETURN (soc_mem_write(unit, MMU_INITIAL_NHOP_TBLm, 203 MEM_BLOCK_ALL, failover_keeper[unit][failover_id].primary_nhi / 4 , 204 &mmu_prot_nhi_entry)); 205 206 BCM_IF_ERROR_RETURN (soc_mem_read(unit, MMU_INITIAL_NHOP_TBLm, 207 MEM_BLOCK_ANY, 208 failover_keeper[unit][failover_id].secondary_nhi / 4, 209 &mmu_prot_nhi_entry)); 210 211 soc_mem_field32_set(unit, MMU_INITIAL_NHOP_TBLm, 212 &mmu_prot_nhi_entry, 213 field[failover_keeper[unit][failover_id].secondary_nhi % 4] , 0); 214 215 BCM_IF_ERROR_RETURN (soc_mem_write(unit, MMU_INITIAL_NHOP_TBLm, 216 MEM_BLOCK_ALL, failover_keeper[unit][failover_id].secondary_nhi / 4 , 217 &mmu_prot_nhi_entry)); 218 219 failover_keeper[unit][failover_id].primary_nhi = -1; 220 failover_keeper[unit][failover_id].secondary_nhi = -1; 221 } 222 return BCM_E_NONE; 223 } 224 /* 225 * Function: 226 * bcm_sb2_failover_prot_nhi_set 227 * Purpose: 228 * Set the parameters for PROT_NHI 229 * Parameters: 230 * IN : unit 231 * IN : Primary Next Hop Index 232 * IN : Protection Next Hop Index 233 * IN : Failover Group Index 234 * Returns: 235 * BCM_E_XXX 236 */ 237 238 int 239 bcm_sb2_failover_prot_nhi_set(int unit, uint32 flags, int nh_index, uint32 prot_nh_index, 240 bcm_multicast_t mc_group, bcm_failover_t failover_id) 241 { 242 _BCM_GET_FAILOVER_ID(failover_id); 243 if (failover_keeper[unit][failover_id].primary_nhi != -1) { 244 return BCM_E_PARAM; 245 } 246 failover_keeper[unit][failover_id].primary_nhi = nh_index; 247 failover_keeper[unit][failover_id].secondary_nhi = prot_nh_index; 248 249 return BCM_E_NONE; 250 251 } 252 253 254 /* 255 * Function: bcm_sb2_failover_prot_nhi_get 256 * Purpose: 257 * Get the parameters for PROT_NHI 258 * Parameters: 259 * IN : unit 260 * IN : primary Next Hop Index 261 * OUT : Failover Group Index 262 * OUT : Protection Next Hop Index 263 * Returns: 264 * BCM_E_XXX 265 */ 266 267 268 int 269 bcm_sb2_failover_prot_nhi_get(int unit, int nh_index, 270 bcm_failover_t *failover_id, int *prot_nh_index, bcm_multicast_t *mc_group) 271 { 272 273 _BCM_GET_FAILOVER_ID(*failover_id); 274 275 *prot_nh_index = failover_keeper[unit][*failover_id].secondary_nhi; 276 277 return BCM_E_NONE; 278 279 } 280 281 282 /* 283 * Function: 284 * bcm_sb2_failover_status_set 285 * Purpose: 286 * Set the parameters for a failover object 287 * Parameters: 288 * IN : unit 289 * IN : failover_id 290 * IN : value 291 * Returns: 292 * BCM_E_XXX 293 */ 294 295 int 296 bcm_sb2_failover_status_set(int unit, 297 bcm_failover_element_t *failover, 298 int value) 299 { 300 int rv = BCM_E_UNAVAIL; 301 mmu_initial_nhop_tbl_entry_t mmu_prot_nhi_entry; 302 soc_field_t field[4] = 303 { 304 PROT_DROP_STATUS0f, 305 PROT_DROP_STATUS1f, 306 PROT_DROP_STATUS2f, 307 PROT_DROP_STATUS3f 308 }; 309 310 if ((value < 0) || (value > 1)) { 311 return BCM_E_PARAM; 312 } 313 _BCM_GET_FAILOVER_ID(failover->failover_id); 314 if ((failover_keeper[unit][failover->failover_id].secondary_nhi == -1) || 315 (failover_keeper[unit][failover->failover_id].primary_nhi == -1)) { 316 return BCM_E_INTERNAL; 317 } 318 if (failover->failover_id != BCM_FAILOVER_INVALID) { 319 /* Group protection for Port and Tunnel: Egress and Ingress */ 320 BCM_IF_ERROR_RETURN( 321 bcm_tr2_failover_mmu_id_validate ( unit, failover->failover_id )); 322 323 if (value) { 324 BCM_IF_ERROR_RETURN (soc_mem_read(unit, MMU_INITIAL_NHOP_TBLm, 325 MEM_BLOCK_ANY, 326 failover_keeper[unit][failover->failover_id].secondary_nhi / 4, 327 &mmu_prot_nhi_entry)); 328 329 soc_mem_field32_set(unit, MMU_INITIAL_NHOP_TBLm, 330 &mmu_prot_nhi_entry, 331 field[failover_keeper[unit][failover->failover_id].secondary_nhi % 4] , 0); 332 333 rv = soc_mem_write(unit, MMU_INITIAL_NHOP_TBLm, 334 MEM_BLOCK_ALL, failover_keeper[unit][failover->failover_id].secondary_nhi / 4 , 335 &mmu_prot_nhi_entry); 336 337 BCM_IF_ERROR_RETURN (soc_mem_read(unit, MMU_INITIAL_NHOP_TBLm, 338 MEM_BLOCK_ANY, 339 failover_keeper[unit][failover->failover_id].primary_nhi / 4, 340 &mmu_prot_nhi_entry)); 341 342 soc_mem_field32_set(unit, MMU_INITIAL_NHOP_TBLm, 343 &mmu_prot_nhi_entry, 344 field[failover_keeper[unit][failover->failover_id].primary_nhi % 4] , 1); 345 346 rv = soc_mem_write(unit, MMU_INITIAL_NHOP_TBLm, 347 MEM_BLOCK_ALL, failover_keeper[unit][failover->failover_id].primary_nhi / 4 , 348 &mmu_prot_nhi_entry); 349 } else { 350 BCM_IF_ERROR_RETURN (soc_mem_read(unit, MMU_INITIAL_NHOP_TBLm, 351 MEM_BLOCK_ANY, 352 failover_keeper[unit][failover->failover_id].primary_nhi / 4, 353 &mmu_prot_nhi_entry)); 354 355 soc_mem_field32_set(unit, MMU_INITIAL_NHOP_TBLm, 356 &mmu_prot_nhi_entry, 357 field[failover_keeper[unit][failover->failover_id].primary_nhi % 4] , 0); 358 359 rv = soc_mem_write(unit, MMU_INITIAL_NHOP_TBLm, 360 MEM_BLOCK_ALL, failover_keeper[unit][failover->failover_id].primary_nhi / 4 , 361 &mmu_prot_nhi_entry); 362 363 BCM_IF_ERROR_RETURN (soc_mem_read(unit, MMU_INITIAL_NHOP_TBLm, 364 MEM_BLOCK_ANY, 365 failover_keeper[unit][failover->failover_id].secondary_nhi / 4, 366 &mmu_prot_nhi_entry)); 367 368 soc_mem_field32_set(unit, MMU_INITIAL_NHOP_TBLm, 369 &mmu_prot_nhi_entry, 370 field[failover_keeper[unit][failover->failover_id].secondary_nhi % 4] , 1); 371 372 rv = soc_mem_write(unit, MMU_INITIAL_NHOP_TBLm, 373 MEM_BLOCK_ALL, failover_keeper[unit][failover->failover_id].secondary_nhi / 4 , 374 &mmu_prot_nhi_entry); 375 376 } 377 } else { 378 return BCM_E_PARAM; 379 } 380 return rv; 381 } 382 383 384 /* 385 * Function: 386 * bcm_sb2_failover_status_get 387 * Purpose: 388 * Get the parameters for a failover object 389 * Parameters: 390 * IN : unit 391 * IN : failover_id 392 * OUT : value 393 * Returns: 394 * BCM_E_XXX 395 */ 396 397 int 398 bcm_sb2_failover_status_get(int unit, 399 bcm_failover_element_t *failover, 400 int *value) 401 { 402 mmu_initial_nhop_tbl_entry_t prot_nhi_entry; 403 soc_field_t field[4] = 404 { 405 PROT_DROP_STATUS0f, 406 PROT_DROP_STATUS1f, 407 PROT_DROP_STATUS2f, 408 PROT_DROP_STATUS3f 409 }; 410 411 _BCM_GET_FAILOVER_ID(failover->failover_id); 412 if (failover->failover_id != BCM_FAILOVER_INVALID) { 413 414 BCM_IF_ERROR_RETURN( 415 bcm_tr2_failover_mmu_id_validate ( unit, failover->failover_id )); 416 417 BCM_IF_ERROR_RETURN (soc_mem_read(unit, MMU_INITIAL_NHOP_TBLm, 418 MEM_BLOCK_ANY, 419 failover_keeper[unit][failover->failover_id].secondary_nhi / 4, 420 &prot_nhi_entry)); 421 422 *value = soc_mem_field32_get(unit, MMU_INITIAL_NHOP_TBLm, 423 &prot_nhi_entry, 424 field[failover_keeper[unit][failover->failover_id].secondary_nhi % 4]); 425 *value = *value ? 0 : 1 ; 426 } else { 427 return BCM_E_PARAM; 428 } 429 return BCM_E_NONE; 430 } 431 432 #endif /* defined(BCM_SABER2_SUPPORT) && defined(INCLUDE_L3) */