1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019-2021 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <rte_common.h> 7 #include <rte_cycles.h> 8 #include <rte_malloc.h> 9 #include <rte_log.h> 10 #include <rte_alarm.h> 11 #include "bnxt.h" 12 #include "bnxt_ulp.h" 13 #include "bnxt_tf_common.h" 14 #include "ulp_ha_mgr.h" 15 #include "ulp_flow_db.h" 16 17 /* Local only MACROs and defines that aren't exported */ 18 #define ULP_HA_TIMER_THREAD (1 << 0) 19 #define ULP_HA_TIMER_IS_RUNNING(info) (!!((info)->flags & ULP_HA_TIMER_THREAD)) 20 #define ULP_HA_TIMER_SEC 1 21 #define ULP_HA_WAIT_TIME (MS_PER_S / 10) 22 #define ULP_HA_WAIT_TIMEOUT (MS_PER_S * 2) 23 24 #define ULP_HA_IF_TBL_DIR TF_DIR_RX 25 #define ULP_HA_IF_TBL_TYPE TF_IF_TBL_TYPE_PROF_PARIF_ERR_ACT_REC_PTR 26 #define ULP_HA_IF_TBL_IDX 10 27 #define ULP_HA_CLIENT_CNT_IF_TBL_IDX 9 28 29 static void ulp_ha_mgr_timer_cancel(struct bnxt_ulp_context *ulp_ctx); 30 static int32_t ulp_ha_mgr_timer_start(void *arg); 31 static void ulp_ha_mgr_timer_cb(void *arg); 32 static int32_t ulp_ha_mgr_app_type_set(struct bnxt_ulp_context *ulp_ctx, 33 enum ulp_ha_mgr_app_type app_type); 34 static int32_t 35 ulp_ha_mgr_region_set(struct bnxt_ulp_context *ulp_ctx, 36 enum ulp_ha_mgr_region region); 37 static int32_t 38 ulp_ha_mgr_state_set(struct bnxt_ulp_context *ulp_ctx, 39 enum ulp_ha_mgr_state state); 40 41 static int32_t 42 ulp_ha_mgr_tf_client_num_get(struct bnxt_ulp_context *ulp_ctx, uint32_t *cnt); 43 44 static int32_t 45 ulp_ha_mgr_state_set(struct bnxt_ulp_context *ulp_ctx, 46 enum ulp_ha_mgr_state state) 47 { 48 struct tf_set_if_tbl_entry_parms set_parms = { 0 }; 49 struct tf *tfp; 50 uint32_t val = 0; 51 int32_t rc = 0; 52 53 if (ulp_ctx == NULL) { 54 BNXT_TF_DBG(ERR, "Invalid parms in state get.\n"); 55 return -EINVAL; 56 } 57 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO); 58 if (tfp == NULL) { 59 BNXT_TF_DBG(ERR, "Unable to get the TFP.\n"); 60 return -EINVAL; 61 } 62 63 val = (uint32_t)state; 64 65 set_parms.dir = ULP_HA_IF_TBL_DIR; 66 set_parms.type = ULP_HA_IF_TBL_TYPE; 67 set_parms.data = (uint8_t *)&val; 68 set_parms.data_sz_in_bytes = sizeof(val); 69 set_parms.idx = ULP_HA_IF_TBL_IDX; 70 71 rc = tf_set_if_tbl_entry(tfp, &set_parms); 72 if (rc) 73 BNXT_TF_DBG(ERR, "Failed to write the HA state\n"); 74 75 return rc; 76 } 77 78 static int32_t 79 ulp_ha_mgr_tf_client_num_get(struct bnxt_ulp_context *ulp_ctx, 80 uint32_t *cnt) 81 { 82 struct tf_get_if_tbl_entry_parms get_parms = { 0 }; 83 struct tf *tfp; 84 uint32_t val = 0; 85 int32_t rc = 0; 86 87 if (ulp_ctx == NULL || cnt == NULL) { 88 BNXT_TF_DBG(ERR, "Invalid parms in client num get.\n"); 89 return -EINVAL; 90 } 91 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO); 92 if (tfp == NULL) { 93 BNXT_TF_DBG(ERR, "Unable to get the TFP.\n"); 94 return -EINVAL; 95 } 96 97 get_parms.dir = ULP_HA_IF_TBL_DIR; 98 get_parms.type = ULP_HA_IF_TBL_TYPE; 99 get_parms.idx = ULP_HA_CLIENT_CNT_IF_TBL_IDX; 100 get_parms.data = (uint8_t *)&val; 101 get_parms.data_sz_in_bytes = sizeof(val); 102 103 rc = tf_get_if_tbl_entry(tfp, &get_parms); 104 if (rc) 105 BNXT_TF_DBG(ERR, "Failed to read the number of HA clients\n"); 106 107 *cnt = val; 108 return rc; 109 } 110 111 static int32_t 112 ulp_ha_mgr_region_set(struct bnxt_ulp_context *ulp_ctx, 113 enum ulp_ha_mgr_region region) 114 { 115 struct bnxt_ulp_ha_mgr_info *ha_info; 116 117 if (ulp_ctx == NULL) { 118 BNXT_TF_DBG(ERR, "Invalid params in ha region get.\n"); 119 return -EINVAL; 120 } 121 122 ha_info = bnxt_ulp_cntxt_ptr2_ha_info_get(ulp_ctx); 123 if (ha_info == NULL) { 124 BNXT_TF_DBG(ERR, "Unable to get ha info\n"); 125 return -EINVAL; 126 } 127 ha_info->region = region; 128 129 return 0; 130 } 131 132 static int32_t 133 ulp_ha_mgr_app_type_set(struct bnxt_ulp_context *ulp_ctx, 134 enum ulp_ha_mgr_app_type app_type) 135 { 136 struct bnxt_ulp_ha_mgr_info *ha_info; 137 138 if (ulp_ctx == NULL) { 139 BNXT_TF_DBG(ERR, "Invalid Parms.\n"); 140 return -EINVAL; 141 } 142 143 ha_info = bnxt_ulp_cntxt_ptr2_ha_info_get(ulp_ctx); 144 if (ha_info == NULL) { 145 BNXT_TF_DBG(ERR, "Unable to get the ha info.\n"); 146 return -EINVAL; 147 } 148 ha_info->app_type = app_type; 149 150 return 0; 151 } 152 153 static void 154 ulp_ha_mgr_timer_cb(void *arg) 155 { 156 struct tf_move_tcam_shared_entries_parms mparms = { 0 }; 157 struct tf_clear_tcam_shared_entries_parms cparms = { 0 }; 158 struct bnxt_ulp_context *ulp_ctx; 159 enum ulp_ha_mgr_state curr_state; 160 enum ulp_ha_mgr_app_type app_type; 161 uint8_t myclient_cnt = 0; 162 uint32_t client_cnt = 0; 163 struct tf *tfp; 164 int32_t rc; 165 166 ulp_ctx = bnxt_ulp_cntxt_entry_acquire(arg); 167 if (ulp_ctx == NULL) { 168 ulp_ha_mgr_timer_start(arg); 169 return; 170 } 171 172 myclient_cnt = bnxt_ulp_cntxt_num_shared_clients_get(ulp_ctx); 173 if (myclient_cnt == 0) { 174 BNXT_TF_DBG(ERR, 175 "PANIC Client Count is zero kill timer\n."); 176 return; 177 } 178 179 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_YES); 180 if (tfp == NULL) { 181 BNXT_TF_DBG(ERR, "Unable to get the TFP.\n"); 182 goto cb_restart; 183 } 184 185 rc = ulp_ha_mgr_state_get(ulp_ctx, &curr_state); 186 if (rc) { 187 /* 188 * This shouldn't happen, if it does, reset the timer 189 * and try again next time. 190 */ 191 BNXT_TF_DBG(ERR, "Failed(%d) to get state.\n", 192 rc); 193 goto cb_restart; 194 } 195 196 rc = ulp_ha_mgr_tf_client_num_get(ulp_ctx, &client_cnt); 197 if (rc) { 198 BNXT_TF_DBG(ERR, "Failed(%d) to get cnt.\n", 199 rc); 200 goto cb_restart; 201 } 202 203 rc = ulp_ha_mgr_app_type_get(ulp_ctx, &app_type); 204 if (rc) { 205 BNXT_TF_DBG(ERR, "Failed(%d) to get type.\n", 206 rc); 207 goto cb_restart; 208 } 209 210 /* Handle the Cleanup if an app went away */ 211 if (client_cnt == myclient_cnt) { 212 if (curr_state == ULP_HA_STATE_PRIM_SEC_RUN && 213 app_type == ULP_HA_APP_TYPE_PRIM) { 214 /* 215 * The SECONDARY went away: 216 * 1. Set the state to PRIM_RUN 217 * 2. Clear the High region so our TCAM will hit. 218 */ 219 rc = ulp_ha_mgr_state_set(ulp_ctx, 220 ULP_HA_STATE_PRIM_RUN); 221 if (rc) { 222 BNXT_TF_DBG(ERR, 223 "On HA CB:Failed(%d) to set state\n", 224 rc); 225 goto cb_restart; 226 } 227 228 cparms.dir = TF_DIR_RX; 229 cparms.tcam_tbl_type = 230 TF_TCAM_TBL_TYPE_WC_TCAM_HIGH; 231 rc = tf_clear_tcam_shared_entries(tfp, &cparms); 232 if (rc) { 233 BNXT_TF_DBG(ERR, 234 "On HA CB:Failed(%d) clear tcam\n", 235 rc); 236 goto cb_restart; 237 } 238 } else if (curr_state == ULP_HA_STATE_PRIM_SEC_RUN && 239 app_type == ULP_HA_APP_TYPE_SEC) { 240 /* 241 * The PRIMARY went away: 242 * 1. Set the state to SEC_COPY 243 * 2. Clear the Low Region for the next copy 244 */ 245 rc = ulp_ha_mgr_state_set(ulp_ctx, 246 ULP_HA_STATE_SEC_TIMER_COPY); 247 if (rc) { 248 BNXT_TF_DBG(ERR, 249 "On HA CB:Failed(%d) to set state\n", 250 rc); 251 goto cb_restart; 252 } 253 curr_state = ULP_HA_STATE_SEC_TIMER_COPY; 254 } 255 } 256 257 /* Only the Secondary has work to on SEC_TIMER_COPY */ 258 if (curr_state != ULP_HA_STATE_SEC_TIMER_COPY || 259 app_type != ULP_HA_APP_TYPE_SEC) 260 goto cb_restart; 261 262 /* Protect the flow database during the copy */ 263 if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) { 264 /* Should not fail, if we do, restart timer and try again */ 265 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n"); 266 goto cb_restart; 267 } 268 /* All paths after this point must release the fdb lock */ 269 270 /* The Primary has issued a close and we are in the timer copy 271 * phase. Become the new Primary, Set state to Primary Run and 272 * move WC entries to Low Region. 273 */ 274 BNXT_TF_DBG(INFO, "On HA CB: Moving entries HI to LOW\n"); 275 276 cparms.dir = TF_DIR_RX; 277 cparms.tcam_tbl_type = TF_TCAM_TBL_TYPE_WC_TCAM_LOW; 278 rc = tf_clear_tcam_shared_entries(tfp, &cparms); 279 if (rc) { 280 BNXT_TF_DBG(ERR, 281 "On HA CB:Failed(%d) clear tcam low\n", 282 rc); 283 goto unlock; 284 } 285 286 mparms.dir = TF_DIR_RX; 287 mparms.tcam_tbl_type = TF_TCAM_TBL_TYPE_WC_TCAM_HIGH; 288 rc = tf_move_tcam_shared_entries(tfp, &mparms); 289 if (rc) { 290 BNXT_TF_DBG(ERR, "On HA_CB: Failed to move entries\n"); 291 goto unlock; 292 } 293 294 ulp_ha_mgr_region_set(ulp_ctx, ULP_HA_REGION_LOW); 295 ulp_ha_mgr_app_type_set(ulp_ctx, ULP_HA_APP_TYPE_PRIM); 296 ulp_ha_mgr_state_set(ulp_ctx, ULP_HA_STATE_PRIM_RUN); 297 BNXT_TF_DBG(INFO, "On HA CB: SEC[SEC_TIMER_COPY] => PRIM[PRIM_RUN]\n"); 298 unlock: 299 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx); 300 cb_restart: 301 bnxt_ulp_cntxt_entry_release(); 302 ulp_ha_mgr_timer_start(arg); 303 } 304 305 static int32_t 306 ulp_ha_mgr_timer_start(void *arg) 307 { 308 rte_eal_alarm_set(US_PER_S * ULP_HA_TIMER_SEC, 309 ulp_ha_mgr_timer_cb, arg); 310 return 0; 311 } 312 313 static void 314 ulp_ha_mgr_timer_cancel(struct bnxt_ulp_context *ulp_ctx) 315 { 316 rte_eal_alarm_cancel(ulp_ha_mgr_timer_cb, ulp_ctx->cfg_data); 317 } 318 319 int32_t 320 ulp_ha_mgr_init(struct bnxt_ulp_context *ulp_ctx) 321 { 322 struct bnxt_ulp_ha_mgr_info *ha_info; 323 int32_t rc; 324 ha_info = rte_zmalloc("ulp_ha_mgr_info", sizeof(*ha_info), 0); 325 if (!ha_info) 326 return -ENOMEM; 327 328 /* Add the HA info tbl to the ulp context. */ 329 bnxt_ulp_cntxt_ptr2_ha_info_set(ulp_ctx, ha_info); 330 331 rc = pthread_mutex_init(&ha_info->ha_lock, NULL); 332 if (rc) { 333 PMD_DRV_LOG(ERR, "Failed to initialize ha mutex\n"); 334 goto cleanup; 335 } 336 rc = ulp_ha_mgr_timer_start(ulp_ctx->cfg_data); 337 if (rc) { 338 BNXT_TF_DBG(ERR, "Unable to start timer CB.\n"); 339 goto cleanup; 340 } 341 342 return 0; 343 cleanup: 344 if (ha_info != NULL) 345 ulp_ha_mgr_deinit(ulp_ctx); 346 return -ENOMEM; 347 } 348 349 void 350 ulp_ha_mgr_deinit(struct bnxt_ulp_context *ulp_ctx) 351 { 352 struct bnxt_ulp_ha_mgr_info *ha_info; 353 354 ulp_ha_mgr_timer_cancel(ulp_ctx); 355 356 ha_info = bnxt_ulp_cntxt_ptr2_ha_info_get(ulp_ctx); 357 if (ha_info == NULL) { 358 BNXT_TF_DBG(ERR, "Unable to get HA Info for deinit.\n"); 359 return; 360 } 361 362 pthread_mutex_destroy(&ha_info->ha_lock); 363 rte_free(ha_info); 364 365 bnxt_ulp_cntxt_ptr2_ha_info_set(ulp_ctx, NULL); 366 } 367 368 int32_t 369 ulp_ha_mgr_app_type_get(struct bnxt_ulp_context *ulp_ctx, 370 enum ulp_ha_mgr_app_type *app_type) 371 { 372 struct bnxt_ulp_ha_mgr_info *ha_info; 373 374 if (ulp_ctx == NULL || app_type == NULL) { 375 BNXT_TF_DBG(ERR, "Invalid Parms.\n"); 376 return -EINVAL; 377 } 378 379 ha_info = bnxt_ulp_cntxt_ptr2_ha_info_get(ulp_ctx); 380 if (ha_info == NULL) { 381 BNXT_TF_DBG(ERR, "Unable to get the HA info.\n"); 382 return -EINVAL; 383 } 384 *app_type = ha_info->app_type; 385 386 return 0; 387 } 388 389 int32_t 390 ulp_ha_mgr_state_get(struct bnxt_ulp_context *ulp_ctx, 391 enum ulp_ha_mgr_state *state) 392 { 393 struct tf_get_if_tbl_entry_parms get_parms = { 0 }; 394 struct tf *tfp; 395 uint32_t val = 0; 396 int32_t rc = 0; 397 398 if (ulp_ctx == NULL || state == NULL) { 399 BNXT_TF_DBG(ERR, "Invalid parms in state get.\n"); 400 return -EINVAL; 401 } 402 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO); 403 if (tfp == NULL) { 404 BNXT_TF_DBG(ERR, "Unable to get the TFP.\n"); 405 return -EINVAL; 406 } 407 408 get_parms.dir = ULP_HA_IF_TBL_DIR; 409 get_parms.type = ULP_HA_IF_TBL_TYPE; 410 get_parms.idx = ULP_HA_IF_TBL_IDX; 411 get_parms.data = (uint8_t *)&val; 412 get_parms.data_sz_in_bytes = sizeof(val); 413 414 rc = tf_get_if_tbl_entry(tfp, &get_parms); 415 if (rc) 416 BNXT_TF_DBG(ERR, "Failed to read the HA state\n"); 417 418 *state = val; 419 return rc; 420 } 421 422 int32_t 423 ulp_ha_mgr_open(struct bnxt_ulp_context *ulp_ctx) 424 { 425 enum ulp_ha_mgr_state curr_state; 426 int32_t rc; 427 428 rc = ulp_ha_mgr_state_get(ulp_ctx, &curr_state); 429 if (rc) { 430 BNXT_TF_DBG(ERR, "Failed to get HA state on Open (%d)\n", rc); 431 return -EINVAL; 432 } 433 434 /* 435 * An Open can only occur during the Init and Primary Run states. During 436 * Init, the system attempting to Open will become the only system 437 * running. During Primary Run, the system attempting to Open will 438 * become the secondary system temporarily, and should eventually be 439 * transitioned to the primary system. 440 */ 441 switch (curr_state) { 442 case ULP_HA_STATE_INIT: 443 /* 444 * No system is running, as we are the primary. Since no other 445 * system is running, we start writing into the low region. By 446 * writing into the low region, we save room for the secondary 447 * system to override our entries by using the high region. 448 */ 449 ulp_ha_mgr_app_type_set(ulp_ctx, ULP_HA_APP_TYPE_PRIM); 450 ulp_ha_mgr_region_set(ulp_ctx, ULP_HA_REGION_LOW); 451 rc = ulp_ha_mgr_state_set(ulp_ctx, ULP_HA_STATE_PRIM_RUN); 452 if (rc) { 453 BNXT_TF_DBG(ERR, "On Open: Failed to set PRIM_RUN.\n"); 454 return -EINVAL; 455 } 456 457 BNXT_TF_DBG(INFO, "On Open: [INIT] => PRIM[PRIM_RUN]\n"); 458 break; 459 case ULP_HA_STATE_PRIM_RUN: 460 /* 461 * The secondary system is starting in order to take over. 462 * The current primary is expected to eventually close and pass 463 * full control to this system;however, until the primary closes 464 * both are operational. 465 */ 466 ulp_ha_mgr_app_type_set(ulp_ctx, ULP_HA_APP_TYPE_SEC); 467 ulp_ha_mgr_region_set(ulp_ctx, ULP_HA_REGION_HI); 468 469 rc = ulp_ha_mgr_state_set(ulp_ctx, ULP_HA_STATE_PRIM_SEC_RUN); 470 if (rc) { 471 BNXT_TF_DBG(ERR, "On Open: Failed to set PRIM_SEC_RUN\n"); 472 return -EINVAL; 473 } 474 BNXT_TF_DBG(INFO, "On Open: [PRIM_RUN] => [PRIM_SEC_RUN]\n"); 475 break; 476 default: 477 BNXT_TF_DBG(ERR, "On Open: Unknown state 0x%x\n", curr_state); 478 return -EINVAL; 479 } 480 481 return 0; 482 } 483 484 int32_t 485 ulp_ha_mgr_close(struct bnxt_ulp_context *ulp_ctx) 486 { 487 enum ulp_ha_mgr_state curr_state, next_state, poll_state; 488 enum ulp_ha_mgr_app_type app_type; 489 int32_t timeout; 490 int32_t rc; 491 492 curr_state = ULP_HA_STATE_INIT; 493 app_type = ULP_HA_APP_TYPE_NONE; 494 rc = ulp_ha_mgr_state_get(ulp_ctx, &curr_state); 495 if (rc) { 496 BNXT_TF_DBG(ERR, "On Close: Failed(%d) to get HA state\n", rc); 497 return -EINVAL; 498 } 499 500 rc = ulp_ha_mgr_app_type_get(ulp_ctx, &app_type); 501 if (rc) { 502 BNXT_TF_DBG(ERR, "On Close: Failed to get the app type.\n"); 503 return -EINVAL; 504 } 505 506 if (curr_state == ULP_HA_STATE_PRIM_RUN && 507 app_type == ULP_HA_APP_TYPE_PRIM) { 508 /* 509 * Only the primary is running, so a close effectively moves the 510 * system back to INIT. 511 */ 512 next_state = ULP_HA_STATE_INIT; 513 ulp_ha_mgr_state_set(ulp_ctx, next_state); 514 BNXT_TF_DBG(INFO, "On Close: PRIM[PRIM_RUN] => [INIT]\n"); 515 } else if (curr_state == ULP_HA_STATE_PRIM_SEC_RUN && 516 app_type == ULP_HA_APP_TYPE_PRIM) { 517 /* 518 * While both are running, the primary received a close. 519 * Cleanup the flows, set the COPY state, and wait for the 520 * secondary to become the Primary. 521 */ 522 BNXT_TF_DBG(INFO, 523 "On Close: PRIM[PRIM_SEC_RUN] flushing flows.\n"); 524 525 ulp_flow_db_flush_flows(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR); 526 ulp_ha_mgr_state_set(ulp_ctx, ULP_HA_STATE_SEC_TIMER_COPY); 527 528 /* 529 * TODO: This needs to be bounded in case the other system does 530 * not move to PRIM_RUN. 531 */ 532 BNXT_TF_DBG(INFO, 533 "On Close: PRIM[PRIM_SEC_RUN] => [Copy], enter wait.\n"); 534 timeout = ULP_HA_WAIT_TIMEOUT; 535 do { 536 rte_delay_ms(ULP_HA_WAIT_TIME); 537 rc = ulp_ha_mgr_state_get(ulp_ctx, &poll_state); 538 if (rc) { 539 BNXT_TF_DBG(ERR, 540 "Failed to get HA state on Close (%d)\n", 541 rc); 542 goto cleanup; 543 } 544 timeout -= ULP_HA_WAIT_TIME; 545 BNXT_TF_DBG(INFO, 546 "On Close: Waiting %d ms for PRIM_RUN\n", 547 timeout); 548 } while (poll_state != ULP_HA_STATE_PRIM_RUN && timeout > 0); 549 550 if (timeout <= 0) { 551 BNXT_TF_DBG(ERR, "On Close: SEC[COPY] Timed out\n"); 552 goto cleanup; 553 } 554 555 BNXT_TF_DBG(INFO, "On Close: PRIM[PRIM_SEC_RUN] => [COPY]\n"); 556 } else if (curr_state == ULP_HA_STATE_PRIM_SEC_RUN && 557 app_type == ULP_HA_APP_TYPE_SEC) { 558 /* 559 * While both are running, the secondary unexpectedly received a 560 * close. 561 */ 562 ulp_ha_mgr_state_set(ulp_ctx, ULP_HA_STATE_PRIM_RUN); 563 564 BNXT_TF_DBG(INFO, "On Close: SEC[PRIM_SEC_RUN] => [PRIM_RUN]\n"); 565 } else if (curr_state == ULP_HA_STATE_SEC_TIMER_COPY && 566 app_type == ULP_HA_APP_TYPE_SEC) { 567 /* 568 * While both were running and the Secondary went into copy, 569 * secondary received a close. Wait until the former Primary 570 * clears the copy stage, close, and set to INIT. 571 */ 572 BNXT_TF_DBG(INFO, "On Close: SEC[COPY] wait for PRIM_RUN\n"); 573 574 timeout = ULP_HA_WAIT_TIMEOUT; 575 do { 576 rte_delay_ms(ULP_HA_WAIT_TIME); 577 rc = ulp_ha_mgr_state_get(ulp_ctx, &poll_state); 578 if (rc) { 579 BNXT_TF_DBG(ERR, 580 "Failed to get HA state on Close (%d)\n", 581 rc); 582 goto cleanup; 583 } 584 585 timeout -= ULP_HA_WAIT_TIME; 586 BNXT_TF_DBG(INFO, 587 "On Close: Waiting %d ms for PRIM_RUN\n", 588 timeout); 589 } while (poll_state != ULP_HA_STATE_PRIM_RUN && 590 timeout >= 0); 591 592 if (timeout <= 0) { 593 BNXT_TF_DBG(ERR, 594 "On Close: SEC[COPY] Timed out\n"); 595 goto cleanup; 596 } 597 598 next_state = ULP_HA_STATE_INIT; 599 rc = ulp_ha_mgr_state_set(ulp_ctx, next_state); 600 if (rc) { 601 BNXT_TF_DBG(ERR, 602 "On Close: Failed to set state to INIT(%x)\n", 603 rc); 604 goto cleanup; 605 } 606 607 BNXT_TF_DBG(INFO, 608 "On Close: SEC[COPY] => [INIT] after %d ms\n", 609 ULP_HA_WAIT_TIMEOUT - timeout); 610 } else { 611 BNXT_TF_DBG(ERR, "On Close: Invalid type/state %d/%d\n", 612 curr_state, app_type); 613 } 614 cleanup: 615 return rc; 616 } 617 618 int32_t 619 ulp_ha_mgr_region_get(struct bnxt_ulp_context *ulp_ctx, 620 enum ulp_ha_mgr_region *region) 621 { 622 struct bnxt_ulp_ha_mgr_info *ha_info; 623 624 if (ulp_ctx == NULL || region == NULL) { 625 BNXT_TF_DBG(ERR, "Invalid params in ha region get.\n"); 626 return -EINVAL; 627 } 628 629 ha_info = bnxt_ulp_cntxt_ptr2_ha_info_get(ulp_ctx); 630 if (ha_info == NULL) { 631 BNXT_TF_DBG(ERR, "Unable to get ha info\n"); 632 return -EINVAL; 633 } 634 *region = ha_info->region; 635 636 return 0; 637 } 638