pscan.c (21452B)
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: pscan.c 8 * Purpose: uKernel based port scan common driver. 9 * 10 * Notes: PSCAN functions will return SOC_E_UAVAIL unless these conditions 11 * are true: 12 * - BCM_CMICM_SUPPORT 13 * - soc_feature_cmicm 14 */ 15 16 #include <shared/bsl.h> 17 18 #include <soc/defs.h> 19 20 #include <sal/types.h> 21 #include <sal/core/alloc.h> 22 #include <sal/core/boot.h> 23 #include <sal/core/libc.h> 24 #include <sal/core/sync.h> 25 #include <sal/core/thread.h> 26 #include <sal/core/time.h> 27 28 #include <bcm/types.h> 29 #include <soc/types.h> 30 #include <soc/debug.h> 31 #include <soc/drv.h> 32 #include <soc/error.h> 33 #include <soc/feature.h> 34 #include <soc/uc_msg.h> 35 #include <soc/shared/mos_msg_common.h> 36 #include <soc/pscan.h> 37 38 #ifdef BCM_CMICM_SUPPORT 39 40 #define BCM_ESW_PSCAN_THREAD_PRI_DFLT 200 41 42 #define PSCAN_PORT_BITMAP_BYTE_LEN 32 43 #define PSCAN_DMA_BUFFER_LEN PSCAN_PORT_BITMAP_BYTE_LEN 44 45 /* 46 * PSCAN Information SW Data 47 */ 48 49 /* PSCAN Information SW Data Structure */ 50 typedef struct pscan_info_s { 51 int unit; /* Unit number */ 52 int initialized; /* If set, PSCAN has been initialized */ 53 int uc_num; /* uController number running PSCAN appl */ 54 sal_thread_t event_thread_id; /* Event handler thread id */ 55 int event_thread_kill; /* Signal Event thread exit */ 56 uint8 bitmap[PSCAN_PORT_BITMAP_BYTE_LEN]; 57 int dma_buffer_len; /* DMA max buffer size */ 58 uint8 *dma_buffer; /* DMA buffer */ 59 } pscan_info_t; 60 61 static pscan_info_t *soc_pscan_info[BCM_MAX_NUM_UNITS] = {0}; 62 63 #define PSCAN_INFO(u_) (soc_pscan_info[(u_)]) 64 65 /* 66 * Utility macros 67 */ 68 /* True if PSCAN module has been initialized */ 69 #define PSCAN_INIT(u_) \ 70 ((PSCAN_INFO(u_) != NULL) && (PSCAN_INFO(u_)->initialized)) 71 72 /* Checks for 'null' argument */ 73 #define PARAM_NULL_CHECK(arg_) \ 74 if ((arg_) == NULL) { \ 75 return SOC_E_PARAM; \ 76 } 77 78 /* Checks that required feature(s) is available */ 79 #define FEATURE_CHECK(u_) \ 80 if (!soc_feature((u_), soc_feature_cmicm)) { \ 81 return SOC_E_UNAVAIL; \ 82 } 83 84 /* Checks that PSCAN module has been initialized */ 85 #define PSCAN_INIT_CHECK(u_) \ 86 if ((PSCAN_INFO(u_) == NULL) || (!PSCAN_INFO(u_)->initialized)) { \ 87 return SOC_E_INIT; \ 88 } 89 90 /* Checks that required feature(s) is available and PSCAN has been initialized */ 91 #define PSCAN_FEATURE_INIT_CHECK(u_) \ 92 do { \ 93 FEATURE_CHECK(u_); \ 94 PSCAN_INIT_CHECK(u_); \ 95 } while (0) 96 97 98 #undef PSCAN_DEBUG_DUMP 99 100 #define PSCAN_SDK_VERSION 0 101 #define PSCAN_UC_MIN_VERSION 0 102 103 /* Timeout for Host <--> uC message */ 104 #define PSCAN_UC_MSG_TIMEOUT_USECS 2000000 /* 2 secs */ 105 #define PSCAN_UC_MSG_TIMEOUT_USECS_QUICKTURN 300000000 /* 5 mins */ 106 107 static sal_usecs_t pscan_uc_msg_timeout_usecs = PSCAN_UC_MSG_TIMEOUT_USECS; 108 109 /* 110 * Function: 111 * soc_pscan_alloc_clear 112 * Purpose: 113 * Allocate memory block and set memory content to zeros. 114 * Parameters: 115 * size - (IN) Size of memory to allocate. 116 * description - (IN) Description of memory block. 117 * Returns: 118 * Pointer to memory block. 119 */ 120 STATIC void * 121 soc_pscan_alloc_clear(unsigned int size, char *description) 122 { 123 void *block = NULL; 124 125 if (size) { 126 block = sal_alloc(size, description); 127 if (block != NULL) { 128 sal_memset(block, 0, size); 129 } 130 } 131 132 return block; 133 } 134 135 /* 136 * Function: 137 * soc_pscan_free_resource 138 * Purpose: 139 * Free memory resources allocated for given unit. 140 * Parameters: 141 * unit - (IN) Unit number. 142 * Returns: 143 * None 144 */ 145 STATIC void 146 soc_pscan_free_resource(int unit) 147 { 148 pscan_info_t *info; 149 150 if (soc_pscan_info[unit] != NULL) { 151 info = soc_pscan_info[unit]; 152 if (info->dma_buffer != NULL) { 153 soc_cm_sfree(unit, info->dma_buffer); 154 } 155 156 sal_free(soc_pscan_info[unit]); 157 soc_pscan_info[unit] = NULL; 158 } 159 160 return; 161 } 162 163 /* 164 * Function: 165 * soc_pscan_alloc_resource 166 * Purpose: 167 * Allocate memory resources allocated for given unit. 168 * Parameters: 169 * unit - (IN) Unit number. 170 * Returns: 171 * None 172 */ 173 STATIC int 174 soc_pscan_alloc_resource(int unit) 175 { 176 pscan_info_t *pscan_info; 177 178 if (soc_pscan_info[unit] != NULL) { 179 soc_pscan_free_resource(unit); 180 } 181 182 /* Allocate memory for PSCAN Information Data Structure */ 183 if ((soc_pscan_info[unit] = 184 soc_pscan_alloc_clear(sizeof(pscan_info_t), 185 "PSCAN info")) == NULL) { 186 return SOC_E_MEMORY; 187 } 188 189 pscan_info = PSCAN_INFO(unit); 190 191 /* 192 * Allocate DMA buffer 193 * 194 * DMA buffer will be used to send and receive 'long' messages 195 * between SDK Host and uController (BTE). 196 */ 197 pscan_info->dma_buffer_len = PSCAN_DMA_BUFFER_LEN; 198 pscan_info->dma_buffer = soc_cm_salloc(unit, pscan_info->dma_buffer_len, 199 "PSCAN DMA buffer"); 200 if (!pscan_info->dma_buffer) { 201 return SOC_E_MEMORY; 202 } 203 sal_memset(pscan_info->dma_buffer, 0, pscan_info->dma_buffer_len); 204 205 return SOC_E_NONE; 206 } 207 208 /* 209 * Function: 210 * soc_pscan_msg_send_receive 211 * Purpose: 212 * Sends given PSCAN control message to the uController. 213 * Receives and verifies expected reply. 214 * Parameters: 215 * unit - (IN) Unit number. 216 * s_subclass - (IN) PSCAN message subclass. 217 * s_len - (IN) Value for 'len' field in message struct. 218 * Length of buffer to flush if DMA send is required. 219 * s_data - (IN) Value for 'data' field in message struct. 220 * Ignored if message requires a DMA send/receive 221 * operation. 222 * r_subclass - (IN) Expected reply message subclass. 223 * r_len - (OUT) Returns value in 'len' reply message field. 224 * r_data - (OUT) Returns value in 'data' reply message field. 225 * Returns: 226 * SOC_E_XXX 227 * Notes: 228 * - The uc_msg 'len' and 'data' fields of mos_msg_data_t 229 * can take any arbitrary data. 230 */ 231 STATIC int 232 soc_pscan_msg_send_receive(int unit, uint8 s_subclass, 233 uint16 s_len, uint32 s_data, 234 uint8 r_subclass, 235 uint16 *r_len, uint32 *r_data) 236 { 237 int rv; 238 sal_paddr_t paddr; 239 pscan_info_t *pscan_info = PSCAN_INFO(unit); 240 mos_msg_data_t send, reply; 241 uint8 *dma_buffer; 242 uint32 dma_buffer_len; 243 244 sal_memset(&send, 0, sizeof(send)); 245 sal_memset(&reply, 0, sizeof(reply)); 246 send.s.mclass = MOS_MSG_CLASS_PSCAN; 247 send.s.subclass = s_subclass; 248 send.s.len = soc_htons(s_len); 249 250 /* 251 * Set 'data' to DMA buffer address if a DMA operation is 252 * required for send or receive. 253 */ 254 dma_buffer = pscan_info->dma_buffer; 255 dma_buffer_len = pscan_info->dma_buffer_len; 256 if (MOS_MSG_DMA_MSG(s_subclass) || MOS_MSG_DMA_MSG(r_subclass)) { 257 paddr = soc_cm_l2p(unit, dma_buffer); 258 send.s.data = soc_htonl((uint32)paddr); 259 } else { 260 send.s.data = soc_htonl(s_data); 261 } 262 263 /* Flush DMA memory */ 264 if (MOS_MSG_DMA_MSG(s_subclass)) { 265 soc_cm_sflush(unit, dma_buffer, s_len); 266 } 267 268 /* Invalidate DMA memory to read */ 269 if (MOS_MSG_DMA_MSG(r_subclass)) { 270 soc_cm_sinval(unit, dma_buffer, dma_buffer_len); 271 } 272 273 rv = soc_cmic_uc_msg_send_receive(unit, pscan_info->uc_num, 274 &send, &reply, 275 pscan_uc_msg_timeout_usecs); 276 277 /* Check reply class, subclass */ 278 if ((rv != SOC_E_NONE) || 279 (reply.s.mclass != MOS_MSG_CLASS_PSCAN) || 280 (reply.s.subclass != r_subclass)) { 281 return SOC_E_INTERNAL; 282 } 283 284 if (r_data != NULL) { 285 *r_data = soc_ntohl(reply.s.data); 286 } 287 if (r_len != NULL) { 288 *r_len = soc_ntohs(reply.s.len); 289 } 290 291 return rv; 292 } 293 294 /* 295 * Function: 296 * soc_pscan_delay 297 * Purpose: 298 * Set the scan delay for the given unit 299 * Parameters: 300 * unit - (IN) Unit number. 301 * delay - (IN) delay in usec. 302 * Returns: 303 * SOC_E_NONE or error 304 */ 305 int 306 soc_pscan_delay(int unit, int delay) 307 { 308 int rv = SOC_E_NONE; 309 uint16 reply_len; 310 pscan_info_t *pscan_info; 311 312 FEATURE_CHECK(unit); 313 314 /* check if already initialized */ 315 if (!PSCAN_INIT(unit)) { 316 LOG_WARN(BSL_LS_SOC_COMMON, 317 (BSL_META_U(unit, 318 "PSCAN not initialized\n"))); 319 return SOC_E_NONE; 320 } 321 322 pscan_info = PSCAN_INFO(unit); 323 if (soc_cmic_uc_msg_active_wait(unit, pscan_info->uc_num) != SOC_E_NONE) { 324 LOG_WARN(BSL_LS_SOC_COMMON, 325 (BSL_META_U(unit, 326 "uKernel not Ready, PSCAN not started\n"))); 327 return SOC_E_NONE; 328 } 329 330 /* Send PSCAN delay message to uC */ 331 rv = soc_pscan_msg_send_receive(unit, 332 MOS_MSG_SUBCLASS_PSCAN_SCAN_DELAY, 333 0, delay, 334 MOS_MSG_SUBCLASS_PSCAN_SCAN_DELAY, 335 &reply_len, NULL); 336 337 if (SOC_FAILURE(rv) || (reply_len != 0)) { 338 if (SOC_SUCCESS(rv)) { 339 rv = SOC_E_INTERNAL; 340 } 341 return rv; 342 } 343 344 return SOC_E_NONE; 345 } 346 347 /* 348 * Function: 349 * soc_pscan_port_config 350 * Purpose: 351 * Set the flags for a given <unit, port> 352 * Parameters: 353 * unit - (IN) Unit number. 354 * port - (IN) Port to configure. 355 * flags - (IN) flag bitmask 356 * Returns: 357 * SOC_E_NONE or error 358 */ 359 int 360 soc_pscan_port_config(int unit, uint32 port, uint32 flags) 361 { 362 int rv = SOC_E_NONE; 363 uint16 reply_len; 364 pscan_info_t *pscan_info; 365 366 FEATURE_CHECK(unit); 367 368 /* check if already initialized */ 369 if (!PSCAN_INIT(unit)) { 370 LOG_WARN(BSL_LS_SOC_COMMON, 371 (BSL_META_U(unit, 372 "PSCAN not initialized\n"))); 373 return SOC_E_NONE; 374 } 375 376 pscan_info = PSCAN_INFO(unit); 377 if (soc_cmic_uc_msg_active_wait(unit, pscan_info->uc_num) != SOC_E_NONE) { 378 LOG_WARN(BSL_LS_SOC_COMMON, 379 (BSL_META_U(unit, 380 "uKernel not Ready, PSCAN not started\n"))); 381 return SOC_E_NONE; 382 } 383 384 /* Send PSCAN delay message to uC */ 385 rv = soc_pscan_msg_send_receive(unit, 386 MOS_MSG_SUBCLASS_PSCAN_PORT_CONFIG, 387 port, flags, 388 MOS_MSG_SUBCLASS_PSCAN_PORT_CONFIG, 389 &reply_len, NULL); 390 391 if (SOC_FAILURE(rv) || (reply_len != 0)) { 392 if (SOC_SUCCESS(rv)) { 393 rv = SOC_E_INTERNAL; 394 } 395 return rv; 396 } 397 398 return SOC_E_NONE; 399 } 400 401 /* 402 * Function: 403 * soc_pscan_port_enable 404 * Purpose: 405 * Enable/disable scanning on the specified port 406 * Parameters: 407 * unit - (IN) Unit number. 408 * port - (IN) Port to configure. 409 * enable - (IN) enable flag 410 * Returns: 411 * SOC_E_NONE or error 412 */ 413 int 414 soc_pscan_port_enable(int unit, uint32 port, int enable) 415 { 416 pscan_info_t *pscan_info; 417 418 FEATURE_CHECK(unit); 419 420 /* check if already initialized */ 421 if (!PSCAN_INIT(unit)) { 422 LOG_WARN(BSL_LS_SOC_COMMON, 423 (BSL_META_U(unit, 424 "PSCAN not initialized\n"))); 425 return SOC_E_NONE; 426 } 427 428 if (port > PSCAN_PORT_BITMAP_BYTE_LEN*8) { 429 LOG_WARN(BSL_LS_SOC_COMMON, 430 (BSL_META_U(unit, 431 "PSCAN invalid port %d\n"), port)); 432 return SOC_E_INTERNAL; 433 } 434 435 pscan_info = PSCAN_INFO(unit); 436 if (enable) { 437 pscan_info->bitmap[port >> 3] |= 1 << (port & 0x07); 438 } 439 else { 440 pscan_info->bitmap[port >> 3] &= ~(1 << (port & 0x07)); 441 } 442 return SOC_E_NONE; 443 } 444 445 /* 446 * Function: 447 * soc_pscan_update 448 * Purpose: 449 * Push the port scan bitmap to the uKernel 450 * Parameters: 451 * unit - (IN) Unit number. 452 * Returns: 453 * SOC_E_NONE or error 454 */ 455 int 456 soc_pscan_update(int unit) 457 { 458 int rv = SOC_E_NONE; 459 uint16 reply_len; 460 pscan_info_t *pscan_info = PSCAN_INFO(unit); 461 462 FEATURE_CHECK(unit); 463 464 /* check if already initialized */ 465 if (!PSCAN_INIT(unit)) { 466 LOG_WARN(BSL_LS_SOC_COMMON, 467 (BSL_META_U(unit, 468 "PSCAN not initialized\n"))); 469 return SOC_E_NONE; 470 } 471 if (soc_cmic_uc_msg_active_wait(unit, pscan_info->uc_num) != SOC_E_NONE) { 472 LOG_WARN(BSL_LS_SOC_COMMON, 473 (BSL_META_U(unit, 474 "uKernel not Ready, PSCAN not started\n"))); 475 return SOC_E_NONE; 476 } 477 478 /* Copy bitmap to dma buffer */ 479 sal_memcpy(pscan_info->dma_buffer, pscan_info->bitmap, 480 PSCAN_PORT_BITMAP_BYTE_LEN); 481 482 /* Send PSCAN delay message to uC */ 483 rv = soc_pscan_msg_send_receive(unit, 484 MOS_MSG_SUBCLASS_PSCAN_PORT_BITMAP, 485 PSCAN_PORT_BITMAP_BYTE_LEN, 486 0, 487 MOS_MSG_SUBCLASS_PSCAN_PORT_BITMAP_REPLY, 488 &reply_len, NULL); 489 490 if (SOC_FAILURE(rv) || (reply_len != 0)) { 491 if (SOC_SUCCESS(rv)) { 492 rv = SOC_E_INTERNAL; 493 } 494 return rv; 495 } 496 497 return SOC_E_NONE; 498 } 499 500 /* 501 * Function: 502 * soc_pscan_callback_thread 503 * Purpose: 504 * Thread to listen for event messages from uController. 505 * Parameters: 506 * param - Pointer to PSCAN info structure. 507 * Returns: 508 * None 509 */ 510 STATIC void 511 soc_pscan_callback_thread(int unit) 512 { 513 int rv; 514 pscan_info_t *pscan_info = PSCAN_INFO(unit); 515 mos_msg_data_t event_msg; 516 uint16 port; 517 uint32 code; 518 519 LOG_VERBOSE(BSL_LS_SOC_COMMON, 520 (BSL_META_U(unit, 521 "PSCAN callback thread starting\n"))); 522 523 pscan_info->event_thread_id = sal_thread_self(); 524 pscan_info->event_thread_kill = 0; 525 526 while (1) { 527 /* Wait on notifications from uController */ 528 rv = soc_cmic_uc_msg_receive(pscan_info->unit, pscan_info->uc_num, 529 MOS_MSG_CLASS_PSCAN_EVENT, &event_msg, 530 sal_sem_FOREVER); 531 532 if (SOC_FAILURE(rv) || (pscan_info->event_thread_kill)) { 533 break; /* Thread exit */ 534 } 535 536 /* Get data from event message */ 537 port = soc_ntohs(event_msg.s.len); 538 code = soc_ntohl(event_msg.s.data); 539 540 LOG_CLI((BSL_META_U(unit, 541 "PSCAN port %d alert 0x%08x\n"), port, code)); 542 } 543 544 pscan_info->event_thread_kill = 0; 545 pscan_info->event_thread_id = NULL; 546 LOG_VERBOSE(BSL_LS_SOC_COMMON, 547 (BSL_META_U(unit, 548 "PSCAN callback thread stopped\n"))); 549 sal_thread_exit(0); 550 } 551 552 /* 553 * Function: 554 * soc_pscan_init 555 * Purpose: 556 * Initialize the PSCAN subsystem 557 * Parameters: 558 * unit - (IN) Unit number. 559 * Returns: 560 * SOC_E_NONE Operation completed successfully 561 * SOC_E_MEMORY Unable to allocate memory for internal control structures 562 * SOC_E_INTERNAL Failed to initialize 563 * Notes: 564 * PSCAN initialization will return SOC_E_NONE for the following 565 * error conditions (i.e. feature not supported): 566 * - uKernel is not loaded 567 * - PSCAN application is not found in any of the uC uKernel 568 */ 569 int 570 soc_pscan_init(int unit) 571 { 572 int uc; 573 int rv = SOC_E_NONE; 574 pscan_info_t *pscan_info; 575 int priority; 576 577 FEATURE_CHECK(unit); 578 579 if (SAL_BOOT_QUICKTURN) { 580 pscan_uc_msg_timeout_usecs = PSCAN_UC_MSG_TIMEOUT_USECS_QUICKTURN; 581 } else { 582 pscan_uc_msg_timeout_usecs = PSCAN_UC_MSG_TIMEOUT_USECS; 583 } 584 585 /* Check if uKernel is loaded */ 586 for (uc = 0; uc < SOC_INFO(unit).num_ucs; uc++) { 587 if (soc_cmic_uc_msg_active_wait(unit, uc) == SOC_E_NONE) { 588 break; 589 } 590 } 591 /* Return silently if there is no active CMICm */ 592 if (uc >= SOC_INFO(unit).num_ucs) { 593 LOG_WARN(BSL_LS_SOC_COMMON, 594 (BSL_META_U(unit, 595 "uKernel not Ready, PSCAN not started\n"))); 596 return SOC_E_NONE; 597 } 598 599 /* Detach if already initialized */ 600 if (PSCAN_INIT(unit)) { 601 SOC_IF_ERROR_RETURN(soc_pscan_detach(unit)); 602 } 603 604 /* 605 * Initialize HOST side 606 */ 607 rv = soc_pscan_alloc_resource(unit); 608 if (SOC_FAILURE(rv)) { 609 soc_pscan_free_resource(unit); 610 return rv; 611 } 612 613 pscan_info = PSCAN_INFO(unit); 614 pscan_info->unit = unit; 615 616 /* 617 * Initialize uController side 618 */ 619 620 /* 621 * Start PSCAN application in BTE (Broadcom Task Engine) uController. 622 * Determine which uController is running PSCAN by choosing the first 623 * uC that returns successfully. 624 */ 625 for (uc = 0; uc < SOC_INFO(unit).num_ucs; uc++) { 626 rv = soc_cmic_uc_appl_init(unit, uc, MOS_MSG_CLASS_PSCAN, 627 pscan_uc_msg_timeout_usecs, 628 PSCAN_SDK_VERSION, 629 PSCAN_UC_MIN_VERSION, 630 NULL, 631 NULL); 632 if (SOC_E_NONE == rv) { 633 /* PSCAN started successfully */ 634 pscan_info->uc_num = uc; 635 break; 636 } 637 } 638 639 if (uc >= SOC_INFO(unit).num_ucs) { 640 /* Could not find or start PSCAN appl */ 641 soc_pscan_free_resource(unit); 642 LOG_WARN(BSL_LS_SOC_COMMON, 643 (BSL_META_U(unit, 644 "uKernel PSCAN application not available\n"))); 645 return SOC_E_NONE; 646 } 647 648 /* 649 * Initialize Event handler 650 */ 651 /* Start event thread handler */ 652 priority = soc_property_get(unit, spn_BCM_ESW_PSCAN_THREAD_PRI, BCM_ESW_PSCAN_THREAD_PRI_DFLT); 653 if (pscan_info->event_thread_id == NULL) { 654 if (sal_thread_create("bcmPSCAN", SAL_THREAD_STKSZ, 655 priority, 656 (void (*)(void*))soc_pscan_callback_thread, 657 INT_TO_PTR(unit)) == SAL_THREAD_ERROR) { 658 if (SAL_BOOT_QUICKTURN) { 659 /* If emulation, then wait */ 660 sal_usleep(1000000); 661 } 662 663 if (pscan_info->event_thread_id == NULL) { 664 SOC_IF_ERROR_RETURN(soc_pscan_detach(unit)); 665 return SOC_E_MEMORY; 666 } 667 } 668 } 669 pscan_info->event_thread_kill = 0; 670 671 /* Module has been initialized */ 672 pscan_info->initialized = 1; 673 674 return SOC_E_NONE; 675 } 676 677 /* 678 * Function: 679 * soc_pscan_detach 680 * Purpose: 681 * Shut down the PSCAN subsystem 682 * Parameters: 683 * unit - (IN) Unit number. 684 * Returns: 685 * SOC_E_NONE Operation completed successfully 686 * Notes: 687 * In progress... 688 */ 689 int 690 soc_pscan_detach(int unit) 691 { 692 pscan_info_t *pscan_info = PSCAN_INFO(unit); 693 #if 0 694 int rv; 695 uint16 reply_len; 696 #endif 697 sal_usecs_t timeout = 0; 698 699 FEATURE_CHECK(unit); 700 701 if (!PSCAN_INIT(unit)) { 702 return SOC_E_NONE; 703 } 704 705 /* Event Handler thread exit signal */ 706 if (pscan_info->event_thread_id) { 707 pscan_info->event_thread_kill = 1; 708 soc_cmic_uc_msg_receive_cancel(unit, pscan_info->uc_num, 709 MOS_MSG_CLASS_PSCAN_EVENT); 710 711 /* 712 * Ensure here itself that the callback thread exists as we are going 713 * to free soc_pscan_info below and we will loose reference 714 * to the thread 715 */ 716 timeout = sal_time_usecs() + 1000000; 717 while (pscan_info->event_thread_id != NULL) { 718 if (sal_time_usecs() < timeout) { 719 /*give some time to already running pscan thread to schedule and exit*/ 720 sal_usleep(1000); 721 } else { 722 /*timeout*/ 723 LOG_ERROR(BSL_LS_SOC_COMMON, 724 (BSL_META_U(unit, 725 "PSCAN event thread did not exit.\n"))); 726 return SOC_E_INTERNAL; 727 } 728 } 729 } 730 731 #if 0 732 /* 733 * Send PSCAN Uninit message to uC 734 * Ignore error since that may indicate uKernel was reloaded. 735 */ 736 rv = soc_pscan_msg_send_receive(unit, 737 MOS_MSG_SUBCLASS_PSCAN_UNINIT, 738 0, 0, 739 MOS_MSG_SUBCLASS_PSCAN_UNINIT_REPLY, 740 &reply_len, NULL); 741 if (BCM_SUCCESS(rv) && (reply_len != 0)) { 742 return SOC_E_INTERNAL; 743 } 744 #endif 745 746 /* Free resources */ 747 soc_pscan_free_resource(unit); 748 soc_pscan_info[unit] = NULL; 749 750 return SOC_E_NONE; 751 } 752 753 #endif /* BCM_CMICM_SUPPORT */