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

cmicm_sbusdma_reg.c (39488B)


      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  * Purpose: CMICM Register Based SBUS DMA Driver
      8  */
      9 
     10 #include <shared/bsl.h>
     11 #include <shared/alloc.h>
     12 #include <soc/drv.h>
     13 #include <soc/debug.h>
     14 #include <soc/cm.h>
     15 #include <soc/sbusdma_internal.h>
     16 
     17 #if defined(BCM_CMICM_SUPPORT) && defined(BCM_SBUSDMA_SUPPORT)
     18 #include <soc/cmicm.h>
     19 #endif
     20 
     21 #ifdef BCM_TRIUMPH3_SUPPORT
     22 #include <soc/er_tcam.h>
     23 #include <soc/triumph3.h>
     24 #endif
     25 
     26 #ifdef BCM_KATANA2_SUPPORT
     27 #include <soc/katana2.h>
     28 #include <soc/katana.h>
     29 #endif
     30 
     31 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT)
     32 #if defined(BCM_CMICM_SUPPORT) && defined(BCM_SBUSDMA_SUPPORT)
     33 
     34 #ifdef BCM_KATANA2_SUPPORT
     35 #define RD_DMA_CFG_REG                   0
     36 #define RD_DMA_HOTMEM_THRESHOLD_REG      1
     37 #define RD_DMA_STAT                      2
     38 #define RD_DMA_STAT_CLR                  3
     39 #endif
     40 
     41 #define SOC_SBUSDMA_FP_RETRIES 200
     42 
     43 #undef PRINT_DMA_TIME
     44 
     45 STATIC uint32 _soc_irq_sbusdma_ch[] = {
     46     IRQ_SBUSDMA_CH0_DONE,
     47     IRQ_SBUSDMA_CH1_DONE,
     48     IRQ_SBUSDMA_CH2_DONE
     49 };
     50 
     51 STATIC int _soc_multi_cmc = 0;
     52 
     53 /*******************************************
     54 * @function _cmicm_sbusdma_reg_array_read
     55 * purpose DMA acceleration for soc_mem_read_range() on FB/ER
     56 *
     57 * @param unit [in] unit
     58 * @param drv [in] soc_sbusdma_reg_param_t pointer
     59 *
     60 * @returns SOC_E_NONE
     61 * @returns SOC_E_XXX
     62 *
     63 * @end
     64  */
     65 STATIC int
     66 _cmicm_sbusdma_reg_array_read(int unit, soc_sbusdma_reg_param_t  *param)
     67 {
     68     soc_control_t *soc = SOC_CONTROL(unit);
     69     uint32        start_addr;
     70     uint32        count;
     71     uint32        data_beats;
     72     uint32        spacing;
     73     int           rv = SOC_E_NONE;
     74     uint32        ctrl, rval;
     75     uint8         at;
     76     int           ch;
     77     int           cmc = SOC_PCI_CMC(unit);
     78     schan_msg_t   msg;
     79     int           dst_blk, acc_type, dma;
     80 #ifdef PRINT_DMA_TIME
     81     sal_usecs_t   start_time;
     82     int           diff_time;
     83 #endif
     84 #if defined(BCM_TRIUMPH3_SUPPORT)
     85     uint32        wa_rval, wa_val = 0;
     86 #endif
     87 
     88     LOG_VERBOSE(BSL_LS_SOC_DMA,
     89              (BSL_META_U(unit,
     90                          "unit %d"
     91                          " mem %s.%s[%u] index %d-%d SER flags 0x%08x buffer %p\n"),
     92               unit, SOC_MEM_UFNAME(unit, param->mem), SOC_BLOCK_NAME(unit,
     93               param->copyno), param->array_id_start, param->index_begin,
     94               param->index_end, param->flags, param->buffer));
     95 
     96    if (param->copyno == COPYNO_ALL) {
     97         return SOC_E_INTERNAL;
     98     }
     99 
    100     data_beats = soc_mem_entry_words(unit, param->mem);
    101 
    102     /* muticmc with grab all the channels and release one to grab */
    103     if (_soc_multi_cmc) {
    104         SOC_IF_ERROR_RETURN(cmicm_sbusdma_ch_get(unit, &cmc, &ch));
    105         assert((ch >= 0) && (ch < CMIC_CMCx_SBUSDMA_CHAN_MAX));
    106     } else {
    107         ch = soc->tdma_ch;
    108     }
    109 
    110     assert((ch >= 0) && (ch < soc->max_sbusdma_channels));
    111     count = param->index_end - param->index_begin + 1;
    112     if (count < 1) {
    113         if (_soc_multi_cmc) {
    114             cmicm_sbusdma_ch_put(unit, cmc, ch);
    115         }
    116         return SOC_E_NONE;
    117     }
    118     schan_msg_clear(&msg);
    119     acc_type = SOC_MEM_ACC_TYPE(unit, param->mem);
    120     dst_blk = SOC_BLOCK2SCH(unit, param->copyno);
    121 
    122 #if defined(BCM_XGS3_SWITCH_SUPPORT)
    123     if (0 != (param->flags & _SOC_SER_FLAG_MULTI_PIPE)) {
    124         if ((param->flags & _SOC_SER_FLAG_ACC_TYPE_MASK) ||
    125             (soc_feature(unit, soc_feature_unique_acc_type_access))) {
    126 
    127             /* Override ACC_TYPE in opcode */
    128             acc_type = param->flags & _SOC_SER_FLAG_ACC_TYPE_MASK;
    129         }
    130     }
    131 #endif /* BCM_XGS3_SWITCH_SUPPORT */
    132 
    133     if (SOC_IS_ARAD(unit)) {
    134         /* DMA transaction indicator on SBUS */
    135         dma = 1;
    136     } else {
    137         dma = 0;
    138     }
    139     soc_schan_header_cmd_set(unit, &msg.header, READ_MEMORY_CMD_MSG,
    140                              dst_blk, 0, acc_type, 4, dma, 0);
    141     start_addr = soc_mem_addr_get(unit, param->mem, param->array_id_start,
    142                                   param->copyno, param->index_begin, &at);
    143 
    144     if (_soc_multi_cmc) {
    145         SBUS_DMA_LOCK(unit, cmc, ch);
    146     } else {
    147         TABLE_DMA_LOCK(unit);
    148     }
    149 
    150     LOG_VERBOSE(BSL_LS_SOC_DMA,
    151                 (BSL_META_U(unit,
    152                  "unit=%d %s.acc_type = %0x, idx[%0d-%0d], cmc= %d, ch = %d\n"),
    153                  unit, SOC_MEM_NAME(unit, param->mem), acc_type,
    154                  param->index_begin, param->index_end, cmc, ch));
    155 
    156 #if defined(BCM_TRIUMPH3_SUPPORT)
    157     if (soc_feature(unit, soc_feature_esm_correction) &&
    158         ((SOC_BLOCK_TYPE(unit, param->copyno) == SOC_BLK_ESM) ||
    159          (SOC_BLOCK_TYPE(unit, param->copyno) == SOC_BLK_ETU))) {
    160         SOC_ESM_LOCK(unit);
    161     }
    162 #endif
    163 
    164     ctrl = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch));
    165     /* Set mode, clear abort, start (clears status and errors) */
    166     soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_CONTROLr, &ctrl,
    167                       MODEf, 0);
    168     soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_CONTROLr, &ctrl,
    169                       ABORTf, 0);
    170     soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_CONTROLr, &ctrl,
    171                       STARTf, 0);
    172     soc_pci_write(unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch), ctrl);
    173     /* Set 1st schan ctrl word as opcode */
    174     soc_pci_write(unit, CMIC_CMCx_SBUSDMA_CHy_OPCODE(cmc, ch), msg.dwords[0]);
    175     soc_pci_write(unit, CMIC_CMCx_SBUSDMA_CHy_HOSTADDR(cmc, ch),
    176                   soc_cm_l2p(unit, param->buffer));
    177     soc_pci_write(unit, CMIC_CMCx_SBUSDMA_CHy_ADDRESS(cmc, ch), start_addr);
    178     soc_pci_write(unit, CMIC_CMCx_SBUSDMA_CHy_COUNT(cmc, ch), count);
    179 
    180     /* Program beats, increment etc */
    181     rval = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_REQUEST(cmc, ch));
    182     soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &rval,
    183                       REP_WORDSf, data_beats);
    184     soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &rval,
    185                       REQ_WORDSf, 0);
    186 
    187 #if defined(BCM_TRIUMPH3_SUPPORT)
    188     if (soc_feature(unit, soc_feature_etu_support)) {
    189         if (SOC_BLOCK_TYPE(unit, param->copyno) == SOC_BLK_ETU) {
    190             int index0, index1, increment;
    191             soc_mem_t real_mem;
    192 
    193             soc_tcam_mem_index_to_raw_index(unit, param->mem, 0,
    194                                             &real_mem, &index0);
    195             soc_tcam_mem_index_to_raw_index(unit, param->mem, 1,
    196                                             &real_mem, &index1);
    197             increment = _shr_popcount(index1 - index0 - 1);
    198             soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &rval,
    199                               INCR_SHIFTf, increment);
    200             SOC_IF_ERROR_RETURN(READ_ETU_TX_REQ_FIFO_CTLr(unit, &wa_rval));
    201             wa_val = soc_reg_field_get(unit, ETU_TX_REQ_FIFO_CTLr, wa_rval,
    202                                        CP_ACC_THRf);
    203             soc_reg_field_set(unit, ETU_TX_REQ_FIFO_CTLr, &wa_rval,
    204                               CP_ACC_THRf, 0);
    205             SOC_IF_ERROR_RETURN(WRITE_ETU_TX_REQ_FIFO_CTLr(unit, wa_rval));
    206         } else {
    207             soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &rval,
    208                               INCR_SHIFTf, 0);
    209             if ((param->mem == EXT_L2_ENTRY_1m) ||
    210                  (param->mem == EXT_L2_ENTRY_2m)) {
    211                 SOC_IF_ERROR_RETURN(READ_ETU_TX_REQ_FIFO_CTLr(unit, &wa_rval));
    212                 wa_val = soc_reg_field_get(unit, ETU_TX_REQ_FIFO_CTLr, wa_rval,
    213                                            CP_ACC_THRf);
    214                 soc_reg_field_set(unit, ETU_TX_REQ_FIFO_CTLr, &wa_rval,
    215                                   CP_ACC_THRf, 0);
    216                 SOC_IF_ERROR_RETURN(WRITE_ETU_TX_REQ_FIFO_CTLr(unit, wa_rval));
    217             }
    218         }
    219     } else
    220 #endif /* BCM_TRIUMPH3_SUPPORT */
    221 #if defined(BCM_SAND_SUPPORT)
    222     if (SOC_IS_SAND(unit)) {
    223         soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &rval,
    224                           INCR_SHIFTf, 0);
    225     } else
    226 #endif
    227     {
    228         soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &rval,
    229                           INCR_SHIFTf, 0);
    230     }
    231     if (soc_feature(unit, soc_feature_multi_sbus_cmds)) {
    232         
    233         if (soc->sbusCmdSpacing < 0) {
    234             spacing = data_beats > 7 ? data_beats + 1 : 8;
    235         } else {
    236             spacing = soc->sbusCmdSpacing;
    237         }
    238         if (!((SOC_BLOCK_TYPE(unit, param->copyno) == SOC_BLK_IPIPE) ||
    239              (SOC_BLOCK_TYPE(unit, param->copyno) == SOC_BLK_EPIPE))) {
    240             spacing = 0;
    241         }
    242         soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &rval,
    243                           PEND_CLOCKSf, spacing);
    244     }
    245     soc_pci_write(unit, CMIC_CMCx_SBUSDMA_CHy_REQUEST(cmc, ch), rval);
    246     soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_CONTROLr, &ctrl, STARTf, 1);
    247     /* Start DMA */
    248 #ifdef PRINT_DMA_TIME
    249     start_time = sal_time_usecs();
    250 #endif
    251     /* On BCMSIM, this interrupt just be reported one time. 
    252     If we enable this interrupt after starting table DMA, the interrupt may be lost.
    253     But on chip, the interrupt will be reported continually until we clear STARTf of
    254     CMIC_CMC0_SBUSDMA_CH0_CONTROLr */
    255     if (soc->tableDmaIntrEnb) {
    256         soc_cmicm_cmcx_intr0_enable(unit, cmc, _soc_irq_sbusdma_ch[ch]);
    257     }
    258 
    259     soc_pci_write(unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch), ctrl);
    260 
    261     LOG_VERBOSE(BSL_LS_SOC_DMA,
    262              (BSL_META_U(unit,
    263                          "%d entries %d beats "
    264                          "addr 0x%x (index %d-%d) Interrupt-Mode(%d)\n"),
    265               count, data_beats, start_addr, param->index_begin,
    266               param->index_end, soc->tableDmaIntrEnb));
    267 
    268     rv = SOC_E_TIMEOUT;
    269     if (soc->tableDmaIntrEnb) {
    270         if (SBUSDMA_DMA_INTR_WAIT(unit, cmc, ch, soc->tableDmaTimeout) < 0) {
    271             rv = SOC_E_TIMEOUT;
    272             LOG_VERBOSE(BSL_LS_SOC_COMMON,
    273                        (BSL_META_U(unit,
    274                                   "%s.%s interrupt timeout\n"),
    275                        SOC_MEM_UFNAME(unit, param->mem),
    276                        SOC_BLOCK_NAME(unit, param->copyno)));
    277         }
    278 #ifdef PRINT_DMA_TIME
    279         diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time);
    280         LOG_VERBOSE(BSL_LS_SOC_DMA,
    281                     (BSL_META_U(unit,
    282                      "(%s)HW dma read time[count=%u, beats=%u]: %d usecs, [%d nsecs per op]\n"),
    283                      SOC_MEM_UFNAME(unit, param->mem),count,data_beats,
    284                      diff_time, diff_time*1000/count));
    285 #endif
    286         soc_cmicm_cmcx_intr0_disable(unit, cmc, _soc_irq_sbusdma_ch[ch]);
    287 
    288         rval = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc, ch));
    289         if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    290                               rval, DONEf)) {
    291             rv = SOC_E_NONE;
    292             if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    293                                   rval, ERRORf)) {
    294                 rv = SOC_E_FAIL;
    295                 cmicm_sbusdma_curr_op_details(unit, cmc, ch);
    296             }
    297         }
    298     } else {
    299         soc_timeout_t to;
    300         soc_timeout_init(&to, soc->tableDmaTimeout, 0);
    301         do {
    302             rval = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc, ch));
    303             if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    304                                   rval, DONEf)) {
    305                 rv = SOC_E_NONE;
    306 #ifdef PRINT_DMA_TIME
    307                 diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time);
    308                 LOG_VERBOSE(BSL_LS_SOC_DMA,
    309                             (BSL_META_U(unit,
    310                              "(%s)HW dma read poll time[count=%u, beats=%u]: %d usecs, [%d nsecs per op]\n"),
    311                              SOC_MEM_UFNAME(unit, param->mem),count,
    312                              data_beats, diff_time, diff_time*1000/count));
    313 #endif
    314                 if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    315                                       rval, ERRORf)) {
    316                     rv = SOC_E_FAIL;
    317                     cmicm_sbusdma_curr_op_details(unit, cmc, ch);
    318                 }
    319                 break;
    320             }
    321         } while(!(soc_timeout_check(&to)));
    322     }
    323 
    324 #if defined(BCM_TRIUMPH3_SUPPORT)
    325     if (soc_feature(unit, soc_feature_etu_support)) {
    326         if ((SOC_BLOCK_TYPE(unit, param->copyno) == SOC_BLK_ETU) ||
    327             ((param->mem == EXT_L2_ENTRY_1m) ||
    328              (param->mem == EXT_L2_ENTRY_2m))) {
    329             SOC_IF_ERROR_RETURN
    330                 (soc_reg_field32_modify(unit, ETU_TX_REQ_FIFO_CTLr,
    331                                         REG_PORT_ANY,
    332                                         CP_ACC_THRf, wa_val));
    333         }
    334     }
    335 #endif
    336 
    337     if (rv != SOC_E_NONE) {
    338         if (rv != SOC_E_TIMEOUT) {
    339             LOG_ERROR(BSL_LS_SOC_COMMON,
    340                       (BSL_META_U(unit,
    341                                   "%s.%s failed(ERR)\n"),
    342                        SOC_MEM_UFNAME(unit, param->mem),
    343                        SOC_BLOCK_NAME(unit, param->copyno)));
    344             cmicm_sbusdma_error_details(unit,
    345                 soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc, ch)));
    346         } else { /* Timeout cleanup */
    347             soc_timeout_t to;
    348 
    349             LOG_ERROR(BSL_LS_SOC_COMMON,
    350                       (BSL_META_U(unit,
    351                                   "%s.%s %s timeout\n"),
    352                        SOC_MEM_UFNAME(unit, param->mem),
    353                        SOC_BLOCK_NAME(unit, param->copyno),
    354                        soc->tableDmaIntrEnb ? "interrupt" : "polling"));
    355 #ifdef BCM_PETRA_SUPPORT
    356             if (SOC_IS_ARAD(unit)) {
    357                 LOG_ERROR(BSL_LS_SOC_COMMON,
    358                           (BSL_META_U(unit,
    359                            "This DMA failure may be due to wrong PCI configuration. "
    360                            "Timeout configured to %dus.\n"),
    361                            soc->tableDmaTimeout));
    362             }
    363 #endif /* BCM_PETRA_SUPPORT */
    364 
    365             /* Abort Table DMA */
    366             ctrl = soc_pci_read(unit,
    367                                 CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch));
    368             soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_CONTROLr, &ctrl,
    369                               ABORTf, 1);
    370             soc_pci_write(unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch), ctrl);
    371 
    372             /* Check the done bit to confirm */
    373             soc_timeout_init(&to, soc->tableDmaTimeout, 0);
    374             while (1) {
    375                 rval = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc, ch));
    376                 if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    377                     rval, DONEf)) {
    378                     break;
    379                 }
    380                 if (soc_timeout_check(&to)) {
    381                     LOG_ERROR(BSL_LS_SOC_COMMON,
    382                               (BSL_META_U(unit,
    383                                "_cmicm_sbusdma_reg_read: Abort Failed\n")));
    384                     break;
    385                 }
    386             }
    387         }
    388     }
    389 
    390     soc_cm_sinval(unit, (void *)param->buffer, WORDS2BYTES(data_beats) * count);
    391 #if defined(BCM_TRIUMPH3_SUPPORT)
    392     if (soc_feature(unit, soc_feature_esm_correction) &&
    393                     ((SOC_BLOCK_TYPE(unit, param->copyno) == SOC_BLK_ESM) ||
    394                     (SOC_BLOCK_TYPE(unit, param->copyno) == SOC_BLK_ETU))) {
    395                     SOC_ESM_UNLOCK(unit);
    396     }
    397 #endif
    398     if (_soc_multi_cmc) {
    399         SBUS_DMA_UNLOCK(unit, cmc, ch);
    400         cmicm_sbusdma_ch_put(unit, cmc, ch);
    401     } else {
    402         TABLE_DMA_UNLOCK(unit);
    403     }
    404 
    405     return rv;
    406 }
    407 
    408 /*******************************************
    409 * @function _cmicm_sbusdma_reg_array_write
    410 * purpose DMA acceleration for soc_mem_write_range() on FB/ER
    411 *
    412 * @param unit [in] unit
    413 * @param drv [in] soc_sbusdma_reg_param_t pointer
    414 * @param mem_clear [in] flag to clear the memory
    415 * @param clear_buf_ent [in] clear_buf_ent is not used as
    416 *        SLAM DMA only supports a one entry buffer
    417 *
    418 * @returns SOC_E_NONE
    419 * @returns SOC_E_XXX
    420 *
    421 * @end
    422  */
    423 
    424 STATIC int
    425 _cmicm_sbusdma_reg_array_write(int unit, soc_sbusdma_reg_param_t  *param)
    426 {
    427     soc_control_t *soc = SOC_CONTROL(unit);
    428     uint32        start_addr;
    429     uint32        count = 0;
    430     uint32        data_beats;
    431     uint32        spacing;
    432     int           rv = SOC_E_NONE;
    433     uint32        ctrl, rval;
    434     uint8         at, rev_slam = 0;
    435     int           ch;
    436     int           cmc = SOC_PCI_CMC(unit);
    437     schan_msg_t   msg;
    438     int           dst_blk, acc_type, data_byte_len, dma;
    439     unsigned      array_index;
    440     int           dma_retries=0;
    441     int           max_retries=0;
    442 
    443 #ifdef PRINT_DMA_TIME
    444     sal_usecs_t   start_time;
    445     int           diff_time;
    446 #endif
    447 #if defined(BCM_TRIUMPH3_SUPPORT)
    448     uint32        wa_rval, wa_val = 0;
    449 #endif
    450 #if defined(BCM_PETRA_SUPPORT)
    451     uint32        *cache;
    452     uint8         *vmap;
    453     int           index = 0;
    454     int           mem_array_vmap_offset;
    455     int           mem_array_cache_offset;
    456     int           blk, copyno_override, cache_copyno = param->copyno;
    457 #endif
    458 
    459     LOG_VERBOSE(BSL_LS_SOC_DMA,
    460              (BSL_META_U(unit,
    461                          "unit %d"
    462                          " mem %s[%u-%u].%s index %d-%d buffer %p\n"),
    463               unit, SOC_MEM_UFNAME(unit, param->mem), param->array_id_start,
    464               param->array_id_end, SOC_BLOCK_NAME(unit, param->copyno),
    465               param->index_begin, param->index_end, param->buffer));
    466 
    467     data_beats = soc_mem_entry_words(unit, param->mem);
    468 
    469     /* muticmc with grab all the channels and release one to grab */
    470     if (_soc_multi_cmc) {
    471         SOC_IF_ERROR_RETURN(cmicm_sbusdma_ch_get(unit, &cmc, &ch));
    472         assert((ch >= 0) && (ch < CMIC_CMCx_SBUSDMA_CHAN_MAX));
    473     } else {
    474         ch = soc->tslam_ch;
    475     }
    476 
    477     assert((ch >= 0) && (ch < soc->max_sbusdma_channels));
    478 
    479     if (param->index_begin > param->index_end) {
    480         count = param->index_begin - param->index_end + 1;
    481         rev_slam = 1;
    482     } else {
    483         count = param->index_end - param->index_begin + 1;
    484     }
    485     if (count < 1) {
    486         if (_soc_multi_cmc) {
    487             cmicm_sbusdma_ch_put(unit, cmc, ch);
    488         }
    489         return SOC_E_NONE;
    490     }
    491 
    492     schan_msg_clear(&msg);
    493     acc_type = SOC_MEM_ACC_TYPE(unit, param->mem);
    494     dst_blk = SOC_BLOCK2SCH(unit, param->copyno);
    495     data_byte_len = data_beats * sizeof(uint32);
    496 
    497 #ifdef FW_BCAST_DOWNLOAD
    498     if (SOC_IS_TOMAHAWK2(unit)) {
    499         if (param->flags & SOC_MEM_WRITE_BCAST_OP) {
    500             int bcast_id = 0;
    501 
    502             rv = SOC_E_FAIL;
    503             if ((SOC_PORTCTRL_FUNCTIONS(unit) != NULL)
    504                 && (SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_sbus_bcast_id_get != NULL)) {
    505                 rv = SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_sbus_bcast_id_get(unit, dst_blk, &bcast_id);
    506                 if (SOC_SUCCESS(rv)) {
    507                     dst_blk = bcast_id;
    508                 }
    509             }
    510 
    511             param->flags &= ~SOC_MEM_WRITE_BCAST_OP;
    512         }
    513     }
    514 #endif
    515 
    516     if (SOC_IS_ARAD(unit)) {
    517         dma = 1;
    518     } else {
    519         dma = 0;
    520     }
    521 
    522     soc_schan_header_cmd_set(unit, &msg.header, WRITE_MEMORY_CMD_MSG,
    523                              dst_blk, 0, acc_type, data_byte_len, dma, 0);
    524 
    525     if (_soc_multi_cmc) {
    526         SBUS_DMA_LOCK(unit, cmc, ch);
    527     } else {
    528         TSLAM_DMA_LOCK(unit);
    529     }
    530 
    531     LOG_VERBOSE(BSL_LS_SOC_DMA,
    532                 (BSL_META_U(unit,
    533                  "unit=%d %s.acc_type = %0x, idx[%0d-%0d], cmc= %d, ch = %d\n"),
    534                  unit, SOC_MEM_NAME(unit, param->mem), acc_type,
    535                  param->index_begin, param->index_end, cmc, ch));
    536 
    537 #if defined(BCM_TRIUMPH3_SUPPORT)
    538     if (soc_feature(unit, soc_feature_esm_correction) &&
    539                     ((SOC_BLOCK_TYPE(unit, param->copyno) == SOC_BLK_ESM) ||
    540                     (SOC_BLOCK_TYPE(unit, param->copyno) == SOC_BLK_ETU))) {
    541                     SOC_ESM_LOCK(unit);
    542     }
    543 #endif
    544 
    545     for (array_index = param->array_id_start;
    546                            array_index <= param->array_id_end; ++array_index) {
    547         if (!param->flags || (param->flags & SOC_MEM_WRITE_SET_ONLY)) {
    548             start_addr = soc_mem_addr_get(unit, param->mem, array_index,
    549                                           param->copyno, param->index_begin, &at);
    550 
    551             ctrl = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch));
    552             /* Set mode, clear abort, start (clears status and errors) */
    553             soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_CONTROLr, &ctrl,
    554                               MODEf, 0);
    555             soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_CONTROLr, &ctrl,
    556                               ABORTf, 0);
    557             soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_CONTROLr, &ctrl,
    558                               STARTf, 0);
    559             soc_pci_write(unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch), ctrl);
    560             /* Set 1st schan ctrl word as opcode */
    561             soc_pci_write(unit, CMIC_CMCx_SBUSDMA_CHy_OPCODE(cmc, ch),
    562                           msg.dwords[0]);
    563             soc_pci_write(unit, CMIC_CMCx_SBUSDMA_CHy_HOSTADDR(cmc, ch),
    564                           soc_cm_l2p(unit, param->buffer));
    565             soc_pci_write(unit, CMIC_CMCx_SBUSDMA_CHy_ADDRESS(cmc, ch),
    566                           start_addr);
    567             soc_pci_write(unit, CMIC_CMCx_SBUSDMA_CHy_COUNT(cmc, ch), count);
    568 
    569             /* Program beats, increment/decrement, single etc */
    570             rval = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_REQUEST(cmc, ch));
    571             soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &rval,
    572                               REQ_WORDSf, data_beats);
    573             soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &rval,
    574                               REP_WORDSf, 0);
    575 
    576 #if defined(BCM_TRIUMPH3_SUPPORT)
    577             if (soc_feature(unit, soc_feature_etu_support)) {
    578                 if (SOC_BLOCK_TYPE(unit, param->copyno) == SOC_BLK_ETU) {
    579                     int index0, index1, increment;
    580                     soc_mem_t real_mem;
    581 
    582                     soc_tcam_mem_index_to_raw_index(unit, param->mem, 0,
    583                                                     &real_mem, &index0);
    584                     soc_tcam_mem_index_to_raw_index(unit, param->mem, 1,
    585                                                     &real_mem, &index1);
    586                     increment = _shr_popcount(index1 - index0 - 1);
    587                     soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &rval,
    588                                     INCR_SHIFTf, increment);
    589                     SOC_IF_ERROR_RETURN(READ_ETU_TX_REQ_FIFO_CTLr(unit, &wa_rval));
    590                     wa_val = soc_reg_field_get(unit, ETU_TX_REQ_FIFO_CTLr, wa_rval,
    591                                                CP_ACC_THRf);
    592                     soc_reg_field_set(unit, ETU_TX_REQ_FIFO_CTLr, &wa_rval,
    593                                       CP_ACC_THRf, 0);
    594                     SOC_IF_ERROR_RETURN(WRITE_ETU_TX_REQ_FIFO_CTLr(unit, wa_rval));
    595                 } else {
    596                     soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &rval,
    597                                       INCR_SHIFTf, 0);
    598                     if ((param->mem == EXT_L2_ENTRY_1m) ||
    599                                        (param->mem == EXT_L2_ENTRY_2m)) {
    600                         SOC_IF_ERROR_RETURN(READ_ETU_TX_REQ_FIFO_CTLr(unit, &wa_rval));
    601                         wa_val = soc_reg_field_get(unit, ETU_TX_REQ_FIFO_CTLr, wa_rval,
    602                                                    CP_ACC_THRf);
    603                         soc_reg_field_set(unit, ETU_TX_REQ_FIFO_CTLr, &wa_rval,
    604                                           CP_ACC_THRf, 0);
    605                         SOC_IF_ERROR_RETURN(WRITE_ETU_TX_REQ_FIFO_CTLr(unit, wa_rval));
    606                     }
    607                 }
    608             } else
    609 #endif /* BCM_TRIUMPH3_SUPPORT */
    610 #if defined(BCM_SAND_SUPPORT)
    611             if (SOC_IS_SAND(unit)) {
    612                 soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &rval,
    613                               INCR_SHIFTf, 0);
    614             } else
    615 #endif
    616             {
    617                 soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &rval,
    618                                   INCR_SHIFTf, 0);
    619             }
    620             if (param->mem_clear) {
    621                 soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &rval,
    622                                   REQ_SINGLEf, 1);
    623             } else {
    624                 soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &rval,
    625                                   REQ_SINGLEf, 0);
    626             }
    627             if (rev_slam) {
    628                 soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &rval,
    629                                   DECRf, 1);
    630             } else {
    631                 soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &rval,
    632                                   DECRf, 0);
    633             }
    634             if (soc_feature(unit, soc_feature_multi_sbus_cmds)) {
    635                 
    636                 if (soc->sbusCmdSpacing < 0) {
    637                     spacing = data_beats > 7 ? data_beats + 1 : 8;
    638                 } else {
    639                     spacing = soc->sbusCmdSpacing;
    640                 }
    641                 if (!((SOC_BLOCK_TYPE(unit, param->copyno) == SOC_BLK_IPIPE) ||
    642                      (SOC_BLOCK_TYPE(unit, param->copyno) == SOC_BLK_EPIPE))) {
    643                     spacing = 0;
    644                 }
    645                 soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_REQUESTr, &rval,
    646                                   PEND_CLOCKSf, spacing);
    647             }
    648             soc_pci_write(unit, CMIC_CMCx_SBUSDMA_CHy_REQUEST(cmc, ch), rval);
    649 
    650             if (param->mem_clear) {
    651                 soc_cm_sflush(unit, param->buffer, WORDS2BYTES(data_beats));
    652             } else {
    653                 soc_cm_sflush(unit, param->buffer, WORDS2BYTES(data_beats) * count);
    654             }
    655 
    656             LOG_VERBOSE(BSL_LS_SOC_DMA,
    657                      (BSL_META_U(unit,
    658                                  "_soc_mem_sbusdma_write: %d entries %d beats "
    659                                  "addr 0x%x (index %d-%d) Interrupt-Mode(%d)\n"),
    660                       count, data_beats, start_addr,
    661                       param->index_begin, param->index_end,
    662                       soc->tslamDmaIntrEnb));
    663         }
    664 
    665         if (!param->flags || (param->flags & SOC_MEM_WRITE_COMMIT_ONLY)) {
    666             ctrl = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch));
    667             soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_CONTROLr, &ctrl, STARTf, 1);
    668             /* On BCMSIM, this interrupt just be reported one time. 
    669             If we enable this interrupt after starting table DMA, the interrupt may be lost.
    670             But on chip, the interrupt will be reported continually until we clear STARTf of
    671             CMIC_CMC0_SBUSDMA_CH0_CONTROLr */
    672             if (soc->tslamDmaIntrEnb) {
    673                 soc_cmicm_cmcx_intr0_enable(unit, cmc, _soc_irq_sbusdma_ch[ch]);
    674             }
    675 
    676             /* Start DMA */
    677             soc_pci_write(unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch), ctrl);
    678         }
    679 
    680         if (!param->flags || (param->flags & SOC_MEM_WRITE_STATUS_ONLY)) {
    681 #ifdef PRINT_DMA_TIME
    682             start_time = sal_time_usecs();
    683 #endif
    684             rv = SOC_E_TIMEOUT;
    685             if (soc->tslamDmaIntrEnb) {
    686                 if (SBUSDMA_DMA_INTR_WAIT(unit, cmc, ch, soc->tslamDmaTimeout) < 0) {
    687                         rv = SOC_E_TIMEOUT;
    688                         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    689                                    (BSL_META_U(unit,
    690                                               "%s.%s interrupt timeout\n"),
    691                                    SOC_MEM_UFNAME(unit, param->mem),
    692                                    SOC_BLOCK_NAME(unit, param->copyno)));
    693                 }
    694 #ifdef PRINT_DMA_TIME
    695                 diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time);
    696                 LOG_VERBOSE(BSL_LS_SOC_DMA,
    697                             (BSL_META_U(unit,
    698                              "(%s)HW dma write time[count=%u, beats=%u]: %d usecs, [%d nsecs per op]\n"),
    699                              SOC_MEM_UFNAME(unit, param->mem),count,data_beats,
    700                              diff_time, diff_time*1000/count));
    701 #endif
    702                 soc_cmicm_cmcx_intr0_disable(unit, cmc, _soc_irq_sbusdma_ch[ch]);
    703 
    704                 rval = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc, ch));
    705                 if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    706                                       rval, DONEf)) {
    707                     rv = SOC_E_NONE;
    708                     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    709                                           rval, ERRORf)) {
    710                         rv = SOC_E_FAIL;
    711                         cmicm_sbusdma_curr_op_details(unit, cmc, ch);
    712                     }
    713                 }
    714             } else {
    715                 soc_timeout_t to;
    716                 soc_timeout_init(&to, soc->tslamDmaTimeout, 0);
    717                 /* Accessing the memory location prior to read loop improves performance */
    718                 rval=soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc, ch));
    719                 do {
    720                     rval = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc, ch));
    721                     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    722                                           rval, DONEf)) {
    723 #ifdef PRINT_DMA_TIME
    724                         diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time);
    725                         LOG_VERBOSE(BSL_LS_SOC_DMA,
    726                                     (BSL_META_U(unit,
    727                                     "(%s)HW dma write poll time[count=%u, beats=%u]: %d usecs, [%d nsecs per op]\n"),
    728                                     SOC_MEM_UFNAME(unit, param->mem),count, data_beats,
    729                                     diff_time, diff_time*1000/count));
    730 #endif
    731                         rv = SOC_E_NONE;
    732                         if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    733                                               rval, ERRORf)) {
    734                             rv = SOC_E_FAIL;
    735                             cmicm_sbusdma_curr_op_details(unit, cmc, ch);
    736                         }
    737                         break;
    738                     }
    739                 } while(dma_retries++ < max_retries || !(soc_timeout_check(&to)));
    740             }
    741 
    742 #if defined(BCM_TRIUMPH3_SUPPORT)
    743             if (soc_feature(unit, soc_feature_etu_support)) {
    744                 if ((SOC_BLOCK_TYPE(unit, param->copyno) == SOC_BLK_ETU) ||
    745                     ((param->mem == EXT_L2_ENTRY_1m) ||
    746                                (param->mem == EXT_L2_ENTRY_2m))) {
    747                     SOC_IF_ERROR_RETURN
    748                         (soc_reg_field32_modify(unit, ETU_TX_REQ_FIFO_CTLr,
    749                           REG_PORT_ANY, CP_ACC_THRf, wa_val));
    750                 }
    751             }
    752 #endif
    753 
    754             if (rv < 0) {
    755                 if (rv != SOC_E_TIMEOUT) {
    756                     LOG_ERROR(BSL_LS_SOC_COMMON,
    757                               (BSL_META_U(unit,
    758                                           "%s[%u].%s failed(ERR)\n"),
    759                                SOC_MEM_UFNAME(unit, param->mem), array_index,
    760                                SOC_BLOCK_NAME(unit, param->copyno)));
    761                     cmicm_sbusdma_error_details(unit,
    762                         soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc, ch)));
    763                 } else { /* Timeout cleanup */
    764                     soc_timeout_t to;
    765 
    766                     LOG_ERROR(BSL_LS_SOC_COMMON,
    767                               (BSL_META_U(unit,
    768                                           "%s[%u].%s %s timeout\n"),
    769                                SOC_MEM_UFNAME(unit, param->mem), array_index,
    770                                SOC_BLOCK_NAME(unit, param->copyno),
    771                                soc->tslamDmaIntrEnb ? "interrupt" : "polling"));
    772 
    773                     /* Abort Table DMA */
    774                     ctrl = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch));
    775                     soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_CONTROLr, &ctrl, ABORTf, 1);
    776                     soc_pci_write(unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch), ctrl);
    777 
    778                     /* Check the done bit to confirm */
    779                     soc_timeout_init(&to, soc->tslamDmaTimeout, 0);
    780                     while (1) {
    781                         rval = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc, ch));
    782                         if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    783                             rval, DONEf)) {
    784                             break;
    785                         }
    786                         if (soc_timeout_check(&to)) {
    787                             LOG_ERROR(BSL_LS_SOC_COMMON,
    788                                       (BSL_META_U(unit,
    789                                        "_soc_mem_sbusdma_write: Abort Failed\n")));
    790                             break;
    791                         }
    792                     }
    793                 }
    794             }
    795         }
    796 #if defined(BCM_PETRA_SUPPORT)
    797         /* update cache, for broadcast block loop each block */
    798         copyno_override = soc_mem_broadcast_block_get(unit,param->mem);
    799         if (cache_copyno == copyno_override) {
    800             cache_copyno = COPYNO_ALL;
    801         }
    802         SOC_MEM_BLOCK_ITER(unit, param->mem, blk) {
    803             if ((cache_copyno != COPYNO_ALL) && (cache_copyno != blk)) {
    804                 continue;
    805             }
    806             /* It will not go into this API if param->copyno = -1. */
    807             /* coverity[negative_returns] */
    808             cache = SOC_MEM_STATE(unit, param->mem).cache[blk];
    809             vmap = SOC_MEM_STATE(unit, param->mem).vmap[blk];
    810             mem_array_vmap_offset = array_index * soc_mem_index_count(unit, param->mem);
    811             mem_array_cache_offset = mem_array_vmap_offset * data_beats;
    812             if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) {
    813                 for (index = param->index_begin; index <= param->index_end; index ++) {
    814                     if ((param->mem_clear) &&
    815                         !(CACHE_VMAP_TST(vmap, index + mem_array_vmap_offset))) {
    816                         continue;
    817                     }
    818                     sal_memcpy(cache + mem_array_cache_offset + index * data_beats,
    819                                param->buffer, data_beats * 4);
    820                     /* update vmap */
    821                     CACHE_VMAP_SET(vmap, mem_array_vmap_offset + index);
    822                 }
    823             }
    824         }
    825 #endif
    826     } /* end of loop over array indices */
    827 
    828 #if defined(BCM_TRIUMPH3_SUPPORT)
    829     if (soc_feature(unit, soc_feature_esm_correction) &&
    830                     ((SOC_BLOCK_TYPE(unit, param->copyno) == SOC_BLK_ESM) ||
    831                     (SOC_BLOCK_TYPE(unit, param->copyno) == SOC_BLK_ETU))) {
    832                     SOC_ESM_UNLOCK(unit);
    833     }
    834 #endif
    835     if (_soc_multi_cmc) {
    836         SBUS_DMA_UNLOCK(unit, cmc, ch);
    837         cmicm_sbusdma_ch_put(unit, cmc, ch);
    838     } else {
    839         TSLAM_DMA_UNLOCK(unit);
    840     }
    841 
    842     return rv;
    843 }
    844 
    845 /*******************************************
    846 * @function _cmicm_sbusdma_reg_clear_specific
    847 * purpose clear a specific memory/table region using
    848 *          DMA write (slam) acceleration.
    849 *
    850 * @param unit [in] unit
    851 * @param param [in] soc_sbusdma_reg_param_t pointer
    852 *
    853 * @returns SOC_E_NONE
    854 * @returns SOC_E_XXX
    855 *
    856 * @end
    857  */
    858 STATIC int
    859 _cmicm_sbusdma_reg_clear_specific(int unit, soc_sbusdma_reg_param_t  *param)
    860 {
    861     int    rv = 0, chunk_size, chunk_entries, mem_size, entry_words;
    862     int    index, blk, tmp, copyno;
    863     uint32 *buf;
    864 
    865     if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)) {
    866         return SOC_E_NONE;
    867     }
    868     chunk_size = SOC_MEM_CLEAR_CHUNK_SIZE_GET(unit);
    869     /* get legal values for indices, if too
    870      * small/big use the memory's boundaries
    871      */
    872     tmp = soc_mem_index_min(unit, param->mem);
    873     if (param->index_begin < soc_mem_index_min(unit, param->mem)) {
    874       param->index_begin = tmp;
    875     }
    876     if (param->index_end < param->index_begin) {
    877         param->index_end = param->index_begin;
    878     } else {
    879          tmp = soc_mem_index_max(unit, param->mem);
    880          if (param->index_end > tmp) {
    881              param->index_end = tmp;
    882          }
    883     }
    884 
    885     entry_words = soc_mem_entry_words(unit, param->mem);
    886     mem_size = (param->index_end - param->index_begin + 1) * entry_words * 4;
    887     if (mem_size < chunk_size) {
    888         chunk_size = mem_size;
    889     }
    890 #ifdef BCM_PETRA_SUPPORT
    891     if (SOC_IS_ARAD(unit) && (entry_words * 4 > chunk_size)) {
    892         /* The default is to use a one table entry buffer,
    893          * if not given a bigger chunk size
    894          * make sure the buffer size holds at least one table entry
    895          */
    896         chunk_size = entry_words * 4;
    897     }
    898 #endif
    899 
    900     buf = soc_cm_salloc(unit, chunk_size, "mem_clear_buf");
    901     if (buf == NULL) {
    902         return SOC_E_MEMORY;
    903     }
    904     chunk_entries = chunk_size / (entry_words * 4);
    905     for (index = 0; index < chunk_entries; index++) {
    906         sal_memcpy(buf + (index * entry_words),
    907                    param->buffer, entry_words * 4);
    908     }
    909 
    910     /* get legal values for memory array indices */
    911     if (SOC_MEM_IS_ARRAY(unit, param->mem)) {
    912         soc_mem_array_info_t *maip = SOC_MEM_ARRAY_INFOP(unit, param->mem);
    913         if (maip) {
    914             if (param->array_id_end >= (maip->numels + maip->first_array_index)) {
    915                 param->array_id_end = (maip->numels - 1) + maip->first_array_index;
    916             } else if (param->array_id_start < maip->first_array_index) {
    917                 param->array_id_start = maip->first_array_index;
    918             }
    919         }
    920     } else {
    921         param->array_id_start = param->array_id_end = 0;
    922     }
    923     copyno = param->copyno;
    924     MEM_LOCK(unit, param->mem);
    925     SOC_MEM_BLOCK_ITER(unit, param->mem, blk) {
    926         if (copyno != COPYNO_ALL && copyno != blk) {
    927             continue;
    928         }
    929         param->buffer = buf;
    930         param->flags = 0;
    931         param->mem_clear = TRUE;
    932         param->copyno = blk;
    933         rv = _cmicm_sbusdma_reg_array_write(unit, param);
    934         if (rv < 0) {
    935             LOG_ERROR(BSL_LS_SOC_COMMON,
    936                       (BSL_META_U(unit,
    937                                   "soc_mem_sbusdma_clear: %s.%s[%d-%d] failed: %s\n"),
    938                                   SOC_MEM_UFNAME(unit, param->mem),
    939                                   SOC_BLOCK_NAME(unit, blk),
    940                                   param->index_begin, param->index_end,
    941                                   soc_errmsg(rv)));
    942         }
    943     }
    944     MEM_UNLOCK(unit, param->mem);
    945     /* restoring the copy number since it is modified */
    946     param->copyno = copyno;
    947     soc_cm_sfree(unit, buf);
    948     return rv;
    949 }
    950 
    951 /*******************************************
    952 * @function _cmicm_sbusdma_cmc_max_num_ch_get
    953 * @Returns number of SBUSDMA channels in cmc
    954 *
    955 * @end
    956  */
    957 STATIC uint32
    958 _cmicm_sbusdma_cmc_max_num_ch_get(int unit)
    959 {
    960     return CMIC_CMCx_SBUSDMA_CHAN_MAX;
    961 }
    962 
    963 
    964 /*******************************************
    965 * @function cmicm_sbusdma_reg_init
    966 * purpose API to Initialize cmicm Register DMA
    967 *
    968 * @param unit [in] unit
    969 * @param drv [out] soc_sbusdma_desc_drv_t pointer
    970 *
    971 * @returns SOC_E_NONE
    972 * @returns SOC_E_XXX
    973 *
    974 * @end
    975  */
    976 int cmicm_sbusdma_reg_init(int unit, soc_sbusdma_reg_drv_t *drv)
    977 {
    978     /* Cache multi CMC flag */
    979     if (SOC_CHECK_MULTI_CMC(unit)) {
    980         _soc_multi_cmc = 1;
    981     }
    982     drv->soc_mem_sbusdma_read  = _cmicm_sbusdma_reg_array_read;
    983     drv->soc_mem_sbusdma_write = _cmicm_sbusdma_reg_array_write;
    984     drv->soc_mem_sbusdma_clear = _cmicm_sbusdma_reg_clear_specific;
    985     drv->soc_sbusdma_cmc_max_num_ch_get = _cmicm_sbusdma_cmc_max_num_ch_get;
    986 
    987     return SOC_E_NONE;
    988 }
    989 
    990 #endif /* BCM_SBUSDMA_SUPPORT */
    991 #endif /* defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) */
    992