soc_mem_bulk.c (21151B)
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 * Implements SOC memory Bulk API. 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <sal/core/libc.h> 13 #include <soc/mem.h> 14 #include <soc/cmic.h> 15 #include <soc/error.h> 16 #include <soc/register.h> 17 #include <soc/drv.h> 18 #include <soc/scache.h> 19 #include <shared/alloc.h> 20 #include <soc/drv.h> 21 #include <soc/debug.h> 22 #include <soc/cm.h> 23 #ifdef BCM_CMICX_SUPPORT 24 #include <soc/soc_schan_fifo.h> 25 #endif 26 #include <soc/schanmsg.h> 27 #include <soc/soc_mem_bulk.h> 28 29 /*! 30 * Signature to verify bulk handle 31 */ 32 #define SOC_BULK_SIG 0xABCD 33 34 /*! 35 * Queue ID to bulk handle 36 */ 37 #define QID_TO_HANDLE(x) (((x + 1) << 16) | (SOC_BULK_SIG)) 38 39 /*! 40 * bulk handle to Queue ID 41 */ 42 #define HANDLE_TO_QID(x) (((x >> 16) & (0xffff)) - 1) 43 44 /*! 45 * Check if handle is valid 46 */ 47 #define IS_HANDLE_VALID(x) (((x) & (SOC_BULK_SIG)) == (SOC_BULK_SIG)) 48 49 /*! 50 * Default bulk handle pool 51 */ 52 #define DEF_BULK_Q_POOL_NUM 50 53 54 /*! 55 * Command buffer Size 56 */ 57 #define BULK_CMD_BUF_SIZE 352 58 59 /*! 60 * SOC bulk memory operation structure 61 */ 62 63 typedef struct soc_mem_bulk_opcache_s { 64 soc_mem_t mem; 65 int index; 66 int copyno; 67 int copyno_override; 68 void *entry_data_ptr; 69 uint32 entry_data[SOC_MAX_MEM_WORDS]; 70 uint32 con_entry_data[SOC_MAX_MEM_WORDS]; 71 uint32 cache_entry_data[SOC_MAX_MEM_WORDS]; 72 } soc_mem_bulk_opcache_t; 73 74 /*! 75 * SOC bulk memory schan command structure 76 */ 77 78 typedef struct soc_mem_bulk_cmd_s { 79 /* Status for command sequence */ 80 int status; 81 82 /* Size words occupied by commands in buffer */ 83 size_t size; 84 85 /* Number of Schan messages in data buffer */ 86 int num_data; 87 88 /* Command data */ 89 uint32 *data; 90 91 /* Number of cache opeartion */ 92 int num_cache; 93 94 /* Bulk cache op data */ 95 soc_mem_bulk_opcache_t op[BULK_CMD_BUF_SIZE/2]; 96 97 /* Next pointer */ 98 struct soc_mem_bulk_cmd_s *next; 99 } soc_mem_bulk_cmd_t; 100 101 /*! 102 * SOC bulk memory command queue structure 103 */ 104 105 typedef struct soc_mem_bulk_q_s { 106 /* Count of the command buffers */ 107 uint32 count; 108 109 /* Command queue head pointer */ 110 soc_mem_bulk_cmd_t *head; 111 112 /* Command queue tail pointer */ 113 soc_mem_bulk_cmd_t *tail; 114 115 } soc_mem_bulk_q_t; 116 117 118 /*! 119 * SOC bulk memory operation meta data 120 */ 121 typedef struct soc_mem_bulk_s { 122 /* Unit number of the command queue */ 123 int unit; 124 /* Number of command queues */ 125 int count; 126 127 /* Schan command queue */ 128 soc_mem_bulk_q_t *queue; 129 130 /* Bulk mem operation lock */ 131 sal_mutex_t op_lock; 132 133 /* Bulk mem operation complete Sync */ 134 sal_sem_t op_sync; 135 136 /* Bulk operator initialized */ 137 uint8 init; 138 } soc_mem_bulk_t; 139 140 soc_mem_bulk_t _soc_mem_bulk[SOC_MAX_NUM_DEVICES]; 141 142 /*! 143 * Allocate the bulk command. 144 */ 145 146 STATIC soc_mem_bulk_cmd_t * 147 _bulk_cmd_alloc(int unit) 148 { 149 soc_mem_bulk_cmd_t *cmd = NULL; 150 151 152 cmd = sal_alloc(sizeof(soc_mem_bulk_cmd_t), "BULK_CMD"); 153 if (cmd == NULL) { 154 LOG_ERROR(BSL_LS_SOC_SOCMEM, 155 (BSL_META_U(unit, 156 "Error: Allocating command\n"))); 157 goto error; 158 } 159 160 sal_memset(cmd, 0, sizeof(soc_mem_bulk_cmd_t)); 161 162 /* Allocate DMA able memory for bulk command */ 163 cmd->data = soc_cm_salloc(unit, sizeof(uint32) * BULK_CMD_BUF_SIZE, 164 "BULK_CMD_BUF"); 165 166 if (cmd->data == NULL) { 167 LOG_ERROR(BSL_LS_SOC_SOCMEM, 168 (BSL_META_U(unit, 169 "Error: Allocating command buff\n"))); 170 goto error; 171 } 172 173 return cmd; 174 error: 175 176 if (cmd) { 177 sal_free(cmd); 178 } 179 return NULL; 180 } 181 182 /*! 183 * Free the bulk command. 184 */ 185 186 STATIC void 187 _bulk_cmd_free(int unit, 188 soc_mem_bulk_cmd_t *cmd) 189 { 190 if (cmd) { 191 if (cmd->data) { 192 soc_cm_sfree(unit, cmd->data); 193 } 194 sal_free(cmd); 195 } 196 } 197 198 /*! 199 * Initialize the resources of command queue. 200 */ 201 STATIC int 202 _bulk_handle_create(int unit, 203 soc_mem_bulk_t *bulk, 204 soc_mem_blk_handle_t *handle) 205 { 206 int rv = SOC_E_NONE; 207 uint32 i; 208 soc_mem_bulk_q_t *queue = NULL; 209 210 /* look for empty queue */ 211 for (i = 0; i < bulk->count; i++) { 212 if (bulk->queue[i].head == NULL) { 213 break; 214 } 215 } 216 /* Unlikely: All queues are occupied , Allocate additional */ 217 if (i == bulk->count) { 218 soc_mem_bulk_q_t *q = NULL; 219 q = sal_alloc(sizeof(soc_mem_bulk_q_t) * bulk->count * 2, 220 "SOC_BULK_Q"); 221 if (q == NULL) { 222 LOG_ERROR(BSL_LS_SOC_SOCMEM, 223 (BSL_META_U(unit, 224 "Error: Allocating command queue\n"))); 225 return SOC_E_MEMORY; 226 } 227 sal_memcpy(q, bulk->queue, sizeof(soc_mem_bulk_q_t) * bulk->count); 228 bulk->count *= 2; 229 sal_free(bulk->queue); 230 bulk->queue = q; 231 } 232 233 queue = &bulk->queue[i]; 234 235 queue->head =_bulk_cmd_alloc(unit); 236 if (queue->head == NULL) { 237 *handle = 0; 238 LOG_ERROR(BSL_LS_SOC_SOCMEM, 239 (BSL_META_U(unit, 240 "Error: Memory Allocation\n"))); 241 rv = SOC_E_MEMORY; 242 } else { 243 queue->tail = queue->head; 244 /* Get handle */ 245 *handle = QID_TO_HANDLE(i); 246 queue->count++; 247 } 248 249 return rv; 250 251 } 252 253 /*! 254 * Free the resources of command queue. 255 */ 256 STATIC void 257 _bulk_handle_destroy(int unit, 258 soc_mem_bulk_t *bulk, 259 soc_mem_blk_handle_t handle) 260 { 261 uint32 i = HANDLE_TO_QID(handle); 262 soc_mem_bulk_q_t *queue = &bulk->queue[i]; 263 soc_mem_bulk_cmd_t *head = queue->head; 264 265 /* Destroy the schan command buffers */ 266 while (head) { 267 soc_mem_bulk_cmd_t *next = head->next; 268 _bulk_cmd_free(unit, head); 269 head = next; 270 } 271 sal_memset(queue, 0, sizeof(soc_mem_bulk_q_t)); 272 273 } 274 275 STATIC uint32 * 276 _bulk_cmd_buff_get(int unit, 277 soc_mem_blk_handle_t handle, 278 soc_mem_bulk_t *bulk, 279 size_t size) 280 { 281 uint32 i = HANDLE_TO_QID(handle); 282 uint32 *data = NULL; 283 284 soc_mem_bulk_q_t *queue = &bulk->queue[i]; 285 soc_mem_bulk_cmd_t *tail = queue->tail; 286 if ((tail->size + size) > BULK_CMD_BUF_SIZE) { 287 /* Not enough space need to allocate buffer */ 288 soc_mem_bulk_cmd_t *cmd = _bulk_cmd_alloc(unit); 289 if (cmd) { 290 data = cmd->data; 291 tail->next = cmd; 292 tail = queue->tail = cmd; 293 queue->count++; 294 } 295 } else { 296 /* buffer pointer at the end of data */ 297 data = tail->data + tail->size; 298 } 299 tail->num_data++; 300 /* data in words + header + address */ 301 tail->size += size + 2; 302 303 return data; 304 } 305 306 /*! 307 * Create schan message. 308 */ 309 STATIC void 310 _bulk_schan_msg_create(int unit, 311 soc_mem_t mem, 312 int index, 313 int blk, 314 size_t size, 315 uint32 *entry_data, 316 schan_msg_t *msg) 317 { 318 int dst_blk, acc_type, src_blk; 319 int data_byte_len = 0; 320 uint32 maddr; 321 uint8 at; 322 323 schan_msg_clear(msg); 324 325 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 326 maddr = soc_mem_addr_get(unit, mem, 0, blk, index, &at); 327 soc_mem_dst_blk_update(unit, blk, maddr, &dst_blk); 328 data_byte_len = size * sizeof(uint32); 329 src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit)); 330 soc_schan_header_cmd_set(unit, &msg->header, WRITE_MEMORY_CMD_MSG, 331 dst_blk, src_blk, acc_type, data_byte_len, 0, 0); 332 msg->writecmd.address = maddr; 333 /* Copy the message and update queue meta data */ 334 sal_memcpy(msg->writecmd.data , entry_data, size * sizeof(uint32)); 335 336 } 337 338 /*! 339 * Check if operation paramters are valid. 340 */ 341 STATIC int 342 _bulk_op_valid(int unit, 343 soc_mem_t mem, 344 int index, 345 int *copyno) 346 { 347 int rv = SOC_E_NONE; 348 349 if (!soc_mem_is_valid(unit, mem)) { 350 rv = SOC_E_MEMORY; 351 goto error; 352 } 353 354 if (*copyno == COPYNO_ALL) { 355 *copyno = SOC_MEM_BLOCK_ANY(unit, mem); 356 } 357 if (*copyno == COPYNO_ALL) { 358 rv = SOC_E_INTERNAL; 359 goto error; 360 } 361 362 if (!SOC_MEM_BLOCK_VALID(unit, mem, *copyno)) { 363 rv = SOC_E_PARAM; 364 goto error; 365 } 366 if (!soc_mem_index_valid(unit, mem, index)) { 367 rv = SOC_E_PARAM; 368 goto error; 369 } 370 error: 371 return rv; 372 373 } 374 375 /*! 376 * Stage the command in queue. 377 */ 378 STATIC int 379 _bulk_cmd_stage(int unit, 380 soc_mem_blk_handle_t handle, 381 soc_mem_bulk_t *bulk, 382 soc_mem_t mem, 383 int index, 384 int copyno, 385 uint32 *entry_data) 386 { 387 int rv = SOC_E_NONE; 388 389 /* Take opearation lock */ 390 sal_mutex_take(bulk->op_lock, sal_mutex_FOREVER); 391 392 if (handle == 0) { 393 /* Send command immediately using scan PIO */ 394 rv = soc_mem_write(unit, mem, copyno, index, entry_data); 395 } else { 396 schan_msg_t *msg = NULL; 397 size_t size; 398 uint32 *con_entry_data; 399 uint32 *cache_entry_data; 400 int copyno_override = 0; 401 int blk; 402 uint32 i = 0; 403 soc_mem_bulk_q_t *queue = NULL; 404 soc_mem_bulk_cmd_t *tail = NULL; 405 soc_mem_bulk_opcache_t *bulk_op = NULL; 406 407 /* Check if handle is valid */ 408 if (!IS_HANDLE_VALID(handle)) { 409 rv = SOC_E_PARAM; 410 goto error; 411 } 412 /* Go to the appropriate location */ 413 i = HANDLE_TO_QID(handle); 414 queue = &bulk->queue[i]; 415 tail = queue->tail; 416 bulk_op = &tail->op[tail->num_cache]; 417 rv = _bulk_op_valid(unit, mem, index, ©no); 418 if (SOC_FAILURE(rv)) { 419 goto error; 420 } 421 size = soc_mem_entry_words(unit, mem); 422 /* Store the bulk op data for cache update */ 423 bulk_op->mem = mem; 424 bulk_op->index = index; 425 bulk_op->copyno = copyno; 426 con_entry_data = bulk_op->con_entry_data; 427 cache_entry_data = bulk_op->cache_entry_data; 428 bulk_op->entry_data_ptr = 429 soc_mem_write_tcam_to_hw_format(unit, mem, entry_data, 430 cache_entry_data, 431 con_entry_data); 432 433 /* Store the entry data for cache update */ 434 soc_mem_write_copyno_update(unit, mem, ©no, ©no_override); 435 bulk_op->copyno_override = copyno_override; 436 sal_memcpy(bulk_op->entry_data, entry_data, sizeof(uint32) * size); 437 if (bulk_op->entry_data_ptr == con_entry_data) { 438 sal_memcpy(entry_data, bulk_op->entry_data_ptr, 439 sizeof(uint32) * size); 440 } 441 tail->num_cache++; 442 443 /* Write to one or all copies of the memory */ 444 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 445 if (copyno_override) { 446 blk = copyno = copyno_override; 447 } else if (copyno != COPYNO_ALL && copyno != blk) { 448 continue; 449 } 450 msg = (schan_msg_t *)_bulk_cmd_buff_get(unit, handle, bulk, size); 451 if (msg == NULL) { 452 LOG_ERROR(BSL_LS_SOC_SOCMEM, 453 (BSL_META_U(unit, 454 "Error: Getting data buffer\n"))); 455 rv = SOC_E_MEMORY; 456 } else { 457 _bulk_schan_msg_create(unit, mem, index, blk, 458 size, entry_data, msg); 459 /* Cache one copy of broadcast_block*/ 460 if (copyno_override) { 461 break; 462 } 463 } 464 } 465 } 466 467 error: 468 /* Release opearation lock */ 469 sal_mutex_give(bulk->op_lock); 470 471 return rv; 472 } 473 #if 0 474 STATIC void 475 _bulk_mem_cb_f(int unit, 476 void *data, 477 void *cookie, 478 int status) 479 { 480 /* Get the command sequence and populate status */ 481 482 /* Give the Semaphore */ 483 } 484 #endif 485 486 STATIC int _bulk_pio_ecc_error(int unit, 487 schan_msg_t *msg) 488 { 489 int rv = SOC_E_FAIL; 490 491 return rv; 492 } 493 494 #ifdef BCM_CMICX_SUPPORT 495 STATIC int _bulk_fifo_ecc_error(int unit, 496 soc_mem_bulk_cmd_t *cmd) 497 { 498 int rv = SOC_E_FAIL; 499 500 return rv; 501 } 502 #endif 503 504 /*! 505 * Write commands using FIFO. 506 */ 507 STATIC void 508 _bulk_cache_update(int unit, 509 soc_mem_bulk_t *bulk, 510 soc_mem_bulk_cmd_t *node) 511 { 512 int i; 513 int blk; 514 soc_mem_bulk_opcache_t *bulk_op = node->op; 515 516 for (i = 0; i < node->num_cache; i++) { 517 SOC_MEM_BLOCK_ITER(unit, bulk_op[i].mem, blk) { 518 _soc_mem_write_cache_update(unit, bulk_op[i].mem, blk, 0, 519 bulk_op[i].index, 0, 520 bulk_op[i].entry_data, 521 bulk_op[i].entry_data_ptr, 522 bulk_op[i].cache_entry_data, 523 bulk_op[i].con_entry_data); 524 } 525 } 526 } 527 528 /*! 529 * Write commands using PIO. 530 */ 531 STATIC int 532 _bulk_pio_write(int unit, 533 soc_mem_bulk_t *bulk, 534 soc_mem_bulk_q_t *cmdq) 535 { 536 int rv = SOC_E_NONE; 537 soc_mem_bulk_cmd_t *head = cmdq->head; 538 int allow_intr = SOC_IS_SAND(unit) ? 1 : 0; 539 540 /* Traverse all the message buffers in the list */ 541 while (head) { 542 int n = head->num_data; 543 uint32 *data = head->data; 544 /* Extract and send each message from buffer */ 545 while(n--) { 546 schan_msg_t * msg = (schan_msg_t *)data; 547 int dw; 548 soc_schan_header_cmd_get(unit, &msg->header, 0, 0, 0, 0, 549 &dw, 0, 0); 550 /* data in words + header + address */ 551 dw = dw / sizeof(uint32) + 2; 552 rv = soc_schan_op(unit, msg, dw, 0, allow_intr); 553 if (SOC_FAILURE(rv)) { 554 rv = _bulk_pio_ecc_error(unit, msg); 555 if (SOC_FAILURE(rv)) { 556 LOG_ERROR(BSL_LS_SOC_SOCMEM, 557 (BSL_META_U(unit, 558 "Error:Pio write = 0x%x\n"), rv)); 559 goto error; 560 } 561 } 562 data += dw; 563 } 564 /* Update the cache */ 565 _bulk_cache_update(unit, bulk, head); 566 head = head->next; 567 } 568 error: 569 return rv; 570 } 571 572 #ifdef BCM_CMICX_SUPPORT 573 /*! 574 * Write commands using FIFO. 575 */ 576 STATIC int 577 _bulk_fifo_write(int unit, 578 soc_mem_bulk_t *bulk, 579 soc_mem_bulk_q_t *cmdq) 580 { 581 int rv = SOC_E_NONE; 582 soc_mem_bulk_cmd_t *head = cmdq->head; 583 584 /* Traverse all the message buffers in the list */ 585 while (head) { 586 soc_schan_fifo_msg_t msg; 587 msg.num = head->num_data; 588 msg.size = head->size; 589 msg.cmd = (schan_fifo_cmd_t *)head->data; 590 msg.resp = NULL; 591 msg.interval = 1; 592 rv = soc_schan_fifo_msg_send(unit, &msg, head, NULL); 593 if (SOC_FAILURE(rv)) { 594 rv = _bulk_fifo_ecc_error(unit, head); 595 if (SOC_FAILURE(rv)) { 596 LOG_ERROR(BSL_LS_SOC_SOCMEM, 597 (BSL_META_U(unit, 598 "Error: Schan FIFO message send = 0x%x\n"), rv)); 599 break; 600 } 601 } else { 602 /* Update the cache */ 603 _bulk_cache_update(unit, bulk, head); 604 head = head->next; 605 } 606 } 607 608 return rv; 609 } 610 #endif 611 612 /*! 613 * Commit all the commands in queue. 614 */ 615 STATIC int 616 _bulk_cmd_commit(int unit, 617 soc_mem_bulk_t *bulk, 618 soc_mem_blk_handle_t handle) 619 { 620 int rv = SOC_E_NONE; 621 uint32 id = HANDLE_TO_QID(handle); 622 soc_control_t *soc; 623 624 soc = SOC_CONTROL(unit); 625 /* Take opearation lock */ 626 sal_mutex_take(bulk->op_lock, sal_mutex_FOREVER); 627 628 if (soc->memBulkSchanPioMode) { 629 rv = _bulk_pio_write(unit, bulk, &bulk->queue[id]); 630 } 631 #ifdef BCM_CMICX_SUPPORT 632 else { 633 if (soc_feature(unit, soc_feature_cmicx) && 634 !((SAL_BOOT_PLISIM || SAL_BOOT_BCMSIM))) { 635 rv = _bulk_fifo_write(unit, bulk, &bulk->queue[id]); 636 } else { 637 rv = SOC_E_FAIL; 638 } 639 } 640 #endif 641 642 /*Clean up the command queue */ 643 _bulk_handle_destroy(unit, bulk, handle); 644 645 /* Release opearation lock */ 646 sal_mutex_give(bulk->op_lock); 647 648 return rv; 649 } 650 651 /*! 652 * Init command queue. 653 */ 654 STATIC int 655 _bulk_cmd_init(int unit, 656 soc_mem_bulk_t *bulk, 657 soc_mem_blk_handle_t *handle) 658 { 659 660 int rv = SOC_E_NONE; 661 662 /* Take opearation lock */ 663 sal_mutex_take(bulk->op_lock, sal_mutex_FOREVER); 664 rv = _bulk_handle_create(unit, bulk, handle); 665 /* Release opearation lock */ 666 sal_mutex_give(bulk->op_lock); 667 668 return rv; 669 } 670 671 /*! 672 * SOC bulk memory opeartion 673 */ 674 int 675 soc_mem_bulk_op(int unit, 676 int flags, 677 soc_mem_blk_handle_t *handle, 678 soc_mem_t mem, 679 int index, 680 int copyno, 681 uint32 *entry_data) 682 { 683 int rv = SOC_E_NONE; 684 soc_mem_bulk_t *bulk = &_soc_mem_bulk[unit]; 685 686 if (!bulk->init) { 687 return SOC_E_INIT; 688 } 689 690 switch(flags) { 691 692 case SOC_MEM_BULK_WRITE_INIT: 693 /* Initialize bulk op queue and return the handle */ 694 rv = _bulk_cmd_init(unit, bulk, handle); 695 break; 696 697 case SOC_MEM_BULK_WRITE_STAGE: 698 if (SOC_SUCCESS(rv)) { 699 rv = _bulk_cmd_stage(unit, *handle, 700 bulk, mem, index, copyno, 701 entry_data); 702 } 703 break; 704 705 case SOC_MEM_BULK_WRITE_COMMIT: 706 /* Check if handle is valid */ 707 if (!IS_HANDLE_VALID(*handle)) { 708 rv = SOC_E_PARAM; 709 } 710 if (SOC_SUCCESS(rv)) { 711 rv = _bulk_cmd_commit(unit, bulk, *handle); 712 } 713 break; 714 715 default: 716 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 717 (BSL_META_U(unit, "Unknown flag = %d\n"), 718 flags)); 719 break; 720 } 721 722 return rv; 723 } 724 725 /*! 726 * Bulk write for memory entry array. 727 */ 728 int 729 soc_mem_bulk_write(int unit, 730 soc_mem_t *mem, 731 int *index, 732 int *copyno, 733 uint32 **entry_data, 734 int count) 735 { 736 int rv = SOC_E_NONE; 737 soc_mem_blk_handle_t handle = 0; 738 int i; 739 soc_mem_bulk_t *bulk = &_soc_mem_bulk[unit]; 740 741 if (!bulk->init) { 742 return SOC_E_INIT; 743 } 744 745 rv = _bulk_cmd_init(unit, bulk, &handle); 746 if (SOC_FAILURE(rv)) { 747 goto error; 748 } 749 /* Stage the commands in queue */ 750 for (i = 0 ; i < count; i++) { 751 rv = _bulk_cmd_stage(unit, handle, 752 bulk, mem[i], index[i], copyno[i], 753 entry_data[i]); 754 if (SOC_FAILURE(rv)) { 755 goto error; 756 } 757 } 758 /* Commit the commands in queue */ 759 rv = _bulk_cmd_commit(unit, bulk, handle); 760 if (SOC_FAILURE(rv)) { 761 goto error; 762 } 763 764 return rv; 765 error: 766 if (handle) { 767 /*Clean up the command queue */ 768 _bulk_handle_destroy(unit, bulk, handle); 769 } 770 return rv; 771 } 772 773 /*! 774 * Bulk mem module cleanup 775 */ 776 int 777 soc_mem_bulk_cleanup(int unit) 778 { 779 int rv = SOC_E_NONE; 780 soc_mem_bulk_t *bulk = &_soc_mem_bulk[unit]; 781 782 if (bulk->op_lock) { 783 sal_mutex_destroy(bulk->op_lock); 784 bulk->op_lock = NULL; 785 } 786 787 if (bulk->op_sync) { 788 sal_sem_destroy(bulk->op_sync); 789 bulk->op_sync = NULL; 790 } 791 792 if (bulk->queue) { 793 sal_free(bulk->queue); 794 bulk->queue = NULL; 795 } 796 797 return rv; 798 } 799 800 /*! 801 * Bulk mem module init 802 */ 803 int 804 soc_mem_bulk_init(int unit) 805 { 806 int rv = SOC_E_NONE; 807 soc_mem_bulk_t *bulk = &_soc_mem_bulk[unit]; 808 809 sal_memset(bulk, 0, sizeof(soc_mem_bulk_t)); 810 bulk->op_lock = sal_mutex_create("SOC_BULK"); 811 if (bulk->op_lock == NULL) { 812 LOG_ERROR(BSL_LS_SOC_SOCMEM, 813 (BSL_META_U(unit, 814 "Error: Create mutex\n"))); 815 rv = SOC_E_INIT; 816 goto error; 817 } 818 819 bulk->op_sync = sal_sem_create("SOC_BULK", sal_sem_BINARY, 0); 820 821 if (bulk->op_sync == NULL) { 822 LOG_ERROR(BSL_LS_SOC_SOCMEM, 823 (BSL_META_U(unit, 824 "Error: Create Semaphore\n"))); 825 rv = SOC_E_INIT; 826 goto error; 827 } 828 829 /* Create pool of command queues */ 830 bulk->queue = sal_alloc(sizeof(soc_mem_bulk_q_t) * DEF_BULK_Q_POOL_NUM, 831 "SOC_BULK_Q"); 832 if (bulk->queue == NULL) { 833 LOG_ERROR(BSL_LS_SOC_SOCMEM, 834 (BSL_META_U(unit, 835 "Error: Allocating command queue\n"))); 836 rv = SOC_E_MEMORY; 837 goto error; 838 } 839 840 sal_memset(bulk->queue, 0, sizeof(soc_mem_bulk_q_t) * DEF_BULK_Q_POOL_NUM); 841 bulk->count = DEF_BULK_Q_POOL_NUM; 842 bulk->init = 1; 843 844 return rv; 845 error: 846 soc_mem_bulk_cleanup(unit); 847 return rv; 848 } 849