openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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, &copyno);
    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, &copyno, &copyno_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