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

sbusdma.c (35402B)


      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: SOC SBUS-DMA and FIFO DMA driver.
      8  */
      9 
     10 #include <shared/bsl.h>
     11 
     12 #include <sal/core/boot.h>
     13 #include <sal/core/libc.h>
     14 #include <shared/alloc.h>
     15 
     16 #include <soc/drv.h>
     17 #include <soc/debug.h>
     18 #include <soc/cm.h>
     19 #include <soc/sbusdma_internal.h>
     20 #include <soc/l2x.h>
     21 #ifdef BCM_SAND_SUPPORT
     22 #include <soc/sand/sand_aux_access.h>
     23 #endif
     24 
     25 #ifdef CRASH_RECOVERY_SUPPORT
     26 #include <soc/hwstate/hw_log.h>
     27 #include <soc/dcmn/dcmn_crash_recovery.h>
     28 #endif
     29 
     30 #ifdef BCM_DNX_SUPPORT
     31 #include <soc/dnx/dnx_err_recovery_manager_utils.h>
     32 #endif
     33 
     34 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT)
     35 #ifdef BCM_SBUSDMA_SUPPORT
     36 
     37 #if (!defined(_LIMITS_H)) && !defined(_LIBC_LIMITS_H_)
     38 
     39 #if (!defined(INT_MIN)) && !defined(INT_MAX)
     40 #define INT_MIN (((int)1)<<(sizeof(int)*8-1))
     41 #define INT_MAX (~INT_MIN)
     42 #endif
     43 
     44 #ifndef UINT_MAX
     45 #define UINT_MAX ((unsigned)-1)
     46 #endif
     47 
     48 #endif
     49 
     50 #ifdef BCM_KATANA2_SUPPORT
     51 #define RD_DMA_CFG_REG                   0
     52 #define RD_DMA_HOTMEM_THRESHOLD_REG      1
     53 #define RD_DMA_STAT                      2
     54 #define RD_DMA_STAT_CLR                  3
     55 #endif 
     56 
     57 typedef struct soc_sbusdma_reg_s {
     58     soc_sbusdma_reg_drv_t drv;
     59     soc_sbusdma_cmic_ch_t  ch;
     60 } soc_sbusdma_reg_t;
     61 
     62 STATIC soc_sbusdma_desc_drv_t _sbusdma_desc_drv[SOC_MAX_NUM_DEVICES];
     63 STATIC soc_sbusdma_reg_t _sbusdma_reg_drv[SOC_MAX_NUM_DEVICES];
     64 
     65 /*
     66  * Function:
     67  *     _soc_mem_sbusdma_read
     68  * Purpose:
     69  *     DMA acceleration for soc_mem_read_range()
     70  * Parameters:
     71  *     buffer -- must be pointer to sufficiently large
     72  *               DMA-able block of memory
     73  */
     74 int
     75 _soc_mem_sbusdma_read(int unit, soc_mem_t mem, int copyno,
     76                       int index_min, int index_max,
     77                       uint32 ser_flags, void *buffer)
     78 {
     79     return _soc_mem_array_sbusdma_read(unit, mem, 0, copyno,
     80                                        index_min, index_max,
     81                                        ser_flags, buffer, -1);
     82 }
     83 
     84 int
     85 _soc_mem_array_sbusdma_read(int unit, soc_mem_t mem, unsigned array_index,
     86                             int copyno, int index_min, int index_max,
     87                             uint32 ser_flags, void *buffer, int vchan)
     88 {
     89     int rv = SOC_E_MEMORY;
     90 #ifdef CRASH_RECOVERY_SUPPORT
     91     int rv_cr = SOC_E_NONE;
     92 #endif
     93     soc_sbusdma_reg_param_t  param;
     94 
     95     param.mem = mem;
     96     param.array_id_start = array_index;
     97     param.index_begin = index_min;
     98     param.index_end = index_max;
     99     param.copyno = copyno;
    100 
    101 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_MONTEREY_SUPPORT) || defined(BCM_APACHE_SUPPORT)
    102     if (SOC_IS_TRIDENT2X(unit)) {
    103         /* The ser and access flags use different macros, using the same bits.
    104          They were not designed to be specified by the same values.
    105          The argument contains a flags field supporting
    106          SOC_MEM_WRITE_* values, and does not support any _SOC_SER_FLAG_* flags.
    107          TD2X device seem to have code specifying SOC_MEM_WRITE_* flags in serflags arguments. */
    108         param.flags = ser_flags;
    109     }
    110     else
    111 #endif
    112     {
    113         param.flags = 0;
    114     }
    115     param.buffer = buffer;
    116     param.vchan = vchan;
    117 
    118 #ifdef CRASH_RECOVERY_SUPPORT
    119     soc_hw_set_immediate_hw_access(unit);
    120 #endif
    121     if (_sbusdma_reg_drv[unit].drv.soc_mem_sbusdma_read != NULL) {
    122         rv = _sbusdma_reg_drv[unit].drv.soc_mem_sbusdma_read(unit, &param);
    123     }
    124 #ifdef CRASH_RECOVERY_SUPPORT
    125     soc_hw_restore_immediate_hw_access(unit);
    126 
    127     /* check the log if we have any updated values */
    128     if (BCM_UNIT_DO_HW_READ_WRITE(unit)) {
    129         if(Hw_Log_List[unit].Access_cb.soc_sbusdma_read) {
    130             rv_cr = Hw_Log_List[unit].Access_cb.soc_sbusdma_read(unit, mem, array_index, copyno, index_min, index_max, ser_flags, buffer, vchan);
    131             if(rv_cr != SOC_E_NONE) {
    132                 soc_dcmn_cr_suppress(unit, dcmn_cr_no_support_dma);
    133                 /* Might have to re-read the entry from hardware after the suppression */
    134                 _soc_mem_array_sbusdma_read(unit, mem, array_index, copyno, index_min, index_max, ser_flags, buffer, vchan);
    135             }
    136         }
    137     }
    138 #endif
    139 
    140     return rv;
    141 }
    142 
    143 /*
    144  * Function:
    145  *     _soc_mem_array_sbusdma_write
    146  * Purpose:
    147  *      DMA acceleration for soc_mem_write_range() on FB/ER
    148  * Parameters:
    149  *      buffer -- must be pointer to sufficiently large
    150  *                DMA-able block of memory
    151  *      index_begin <= index_end - Forward direction
    152  *      index_begin >  index_end - Reverse direction
    153  *      mem_clear -- if TRUE: simply clear memory using one
    154  *                   mem chunk from the supplied buffer
    155  *      clear_buf_ent is not used as SLAM DMA only supports
    156  *                   a one entry buffer
    157  */
    158 
    159 int
    160 _soc_mem_array_sbusdma_write(int unit, int flags, soc_mem_t mem,
    161                              unsigned array_index_start,
    162                              unsigned array_index_end, int copyno,
    163                              int index_begin, int index_end, 
    164                              void *buffer, uint8 mem_clear, 
    165                              int clear_buf_ent, int vchan)
    166 {
    167     int rv = SOC_E_MEMORY;
    168 
    169     soc_sbusdma_reg_param_t  param;
    170 
    171 
    172 #ifdef CRASH_RECOVERY_SUPPORT
    173     if (BCM_UNIT_DO_HW_READ_WRITE(unit)) {
    174         if(Hw_Log_List[unit].Access_cb.soc_sbusdma_write) {
    175             return Hw_Log_List[unit].Access_cb.soc_sbusdma_write(
    176                     unit, flags, mem,
    177                     array_index_start,
    178                     array_index_end, copyno,
    179                     index_begin, index_end,
    180                     buffer, mem_clear,
    181                     clear_buf_ent, vchan);
    182         }
    183     }
    184 #endif
    185 
    186     param.mem = mem;
    187     param.array_id_start = array_index_start;
    188     param.array_id_end = array_index_end;
    189     param.index_begin = index_begin;
    190     param.index_end = index_end;
    191     param.copyno = copyno;
    192     param.flags= flags;
    193     param.mem_clear = mem_clear;
    194     param.buffer = buffer;
    195     param.vchan = vchan;
    196 
    197     if (_sbusdma_reg_drv[unit].drv.soc_mem_sbusdma_write != NULL) {
    198         rv = _sbusdma_reg_drv[unit].drv.soc_mem_sbusdma_write(unit,
    199                                                       &param);
    200     }
    201 
    202     return rv;
    203 }
    204 
    205 /*
    206  * Function:
    207  *     _soc_mem_sbusdma_write
    208  * Purpose:
    209  *      DMA acceleration for soc_mem_write_range() on FB/ER
    210  * Parameters:
    211  *      buffer -- must be pointer to sufficiently large
    212  *                DMA-able block of memory
    213  *      index_begin <= index_end - Forward direction
    214  *      index_begin >  index_end - Reverse direction
    215  *      mem_clear -- if TRUE: simply clear memory using one
    216  *                   mem chunk from the supplied buffer 
    217  */
    218 
    219 int
    220 _soc_mem_sbusdma_write(int unit, soc_mem_t mem, int copyno,
    221                        int index_begin, int index_end, 
    222                        void *buffer, uint8 mem_clear, 
    223                        int clear_buf_ent)
    224 {
    225     return _soc_mem_array_sbusdma_write(unit, 0, mem, 0, 0, copyno, index_begin,
    226                                         index_end, buffer, mem_clear,
    227                                         clear_buf_ent, -1);
    228 }
    229 
    230 /*
    231  * Function:
    232  *     _soc_mem_sbusdma_clear_specific
    233  * Purpose:
    234  *     clear a specific memory/table region using DMA
    235  *     write (slam) acceleration.
    236  */
    237 int
    238 _soc_mem_sbusdma_clear_specific(int unit, soc_mem_t mem,
    239                                 unsigned array_index_min,
    240                                 unsigned array_index_max,
    241                                 int copyno,
    242                                 int index_min, int index_max,
    243                                 void *null_entry)
    244 {
    245     int    rv = SOC_E_MEMORY;
    246 
    247     soc_sbusdma_reg_param_t  param;
    248 
    249     param.mem = mem;
    250     param.array_id_start = array_index_min;
    251     param.array_id_end = array_index_max;
    252     param.index_begin = index_min;
    253     param.index_end = index_max;
    254     param.copyno = copyno;
    255     param.buffer = null_entry;
    256     param.vchan = -1;
    257 
    258     if (_sbusdma_reg_drv[unit].drv.soc_mem_sbusdma_clear != NULL) {
    259         rv = _sbusdma_reg_drv[unit].drv.soc_mem_sbusdma_clear(unit, &param);
    260     }
    261 
    262 
    263     return rv;
    264 }
    265 
    266 
    267 /*
    268  * Function:
    269  *     _soc_mem_sbusdma_clear
    270  * Purpose:
    271  *     soc_mem_clear acceleration using table DMA write (slam)
    272  */
    273 int
    274 _soc_mem_sbusdma_clear(int unit, soc_mem_t mem, int copyno, void *null_entry)
    275 {
    276     return _soc_mem_sbusdma_clear_specific(unit, mem, 0, UINT_MAX, copyno,
    277                                            INT_MIN, INT_MAX, null_entry);
    278 }
    279 
    280 /*
    281  ****************************************************************
    282  * SBUSDMA descriptor mode
    283  */
    284 
    285 STATIC int
    286 _soc_sbusdma_desc_abort(int unit)
    287 {
    288     soc_timeout_t to;
    289     /* signal abort */
    290     SOC_SBUSDMA_DM_TO(unit) = 0;
    291     if (SOC_SBUSDMA_DM_PID(unit) != SAL_THREAD_ERROR) {
    292         /* Wake up thread so it will check the exit flag */
    293         sal_sem_give(SOC_SBUSDMA_DM_INTR(unit));
    294 
    295         /* Give thread a few seconds to wake up and exit */
    296         if (SAL_BOOT_SIMULATION) {
    297             soc_timeout_init(&to, 50 * 1000000, 0);
    298         } else {
    299             soc_timeout_init(&to, 10 * 1000000, 0);
    300         }
    301 
    302         while (SOC_SBUSDMA_DM_PID(unit) != SAL_THREAD_ERROR) {
    303             if (soc_timeout_check(&to)) {
    304                 LOG_ERROR(BSL_LS_SOC_COMMON,
    305                           (BSL_META_U(unit,
    306                                       "soc_sbusdma_desc_detach: SBUDMA Desc Mode thread will not exit\n")));
    307                 return SOC_E_INTERNAL;
    308             }
    309         }
    310     }
    311     return SOC_E_NONE;
    312 }
    313 
    314 
    315 int
    316 soc_sbusdma_desc_abort(int unit)
    317 {
    318     int rv = SOC_E_NONE;
    319 
    320     if (!SOC_SBUSDMA_DM_INFO(unit)) {
    321         return rv;
    322     }
    323 
    324     rv = _soc_sbusdma_desc_abort(unit);
    325 
    326     return rv;
    327 }
    328 
    329 int
    330 soc_sbusdma_desc_detach(int unit)
    331 {
    332 
    333     int i, rv = SOC_E_NONE;
    334     _soc_sbusdma_state_t *swd; 
    335     
    336     if (!SOC_SBUSDMA_DM_INFO(unit)) {
    337         return rv;
    338     }
    339     SOC_SBUSDMA_DM_INIT(unit) = 2;
    340     /* Check if something is running and wait for it to complete
    341      * (or issue an abort ?) */
    342     if (soc_sbusdma_desc_abort(unit)) {
    343         return SOC_E_INTERNAL;
    344     }
    345     if (_sbusdma_desc_drv[unit].soc_sbusdma_desc_detach) {
    346         rv = _sbusdma_desc_drv[unit].soc_sbusdma_desc_detach(unit);
    347     }
    348 
    349     for (i=1; i<SOC_SBUSDMA_MAX_DESC; i++) {
    350         if (SOC_SBUSDMA_DM_HANDLES(unit)[i]) {
    351             swd = SOC_SBUSDMA_DM_HANDLES(unit)[i];
    352             sal_free(swd->cfg);
    353             if (!(swd->ctrl.flags & SOC_SBUSDMA_CFG_USE_SUPPLIED_DESC)) {
    354                 soc_cm_sfree(unit, swd->desc);
    355             }
    356             sal_free(swd);
    357             SOC_SBUSDMA_DM_HANDLES(unit)[i] = 0;
    358             SOC_SBUSDMA_DM_COUNT(unit)--;
    359         }
    360     }
    361     
    362     if (SOC_SBUSDMA_DM_MUTEX(unit)) {
    363         sal_mutex_destroy(SOC_SBUSDMA_DM_MUTEX(unit));
    364         SOC_SBUSDMA_DM_MUTEX(unit) = NULL;
    365     }
    366     if (SOC_SBUSDMA_DM_INTR(unit)) {
    367         sal_sem_destroy(SOC_SBUSDMA_DM_INTR(unit));
    368         SOC_SBUSDMA_DM_INTR(unit) = NULL;
    369     }
    370     SOC_SBUSDMA_DM_INIT(unit) = 0;
    371     sal_free(SOC_SBUSDMA_DM_INFO(unit));
    372     SOC_SBUSDMA_DM_INFO(unit) = NULL;
    373 
    374     return rv;
    375 }
    376 
    377 STATIC void
    378 _soc_sbusdma_desc(void *unit_vp)
    379 {
    380     int rv;
    381     int unit = PTR_TO_INT(unit_vp);
    382     soc_control_t *soc = SOC_CONTROL(unit);
    383     sal_usecs_t interval;
    384     sal_usecs_t stime, etime;
    385     int cmc = SOC_PCI_CMC(unit);
    386     int ch = soc->desc_ch;
    387     _soc_sbusdma_state_t *swd;
    388 
    389     assert((ch >= 0) && (ch < soc->max_sbusdma_channels));
    390 
    391 #ifdef BCM_DNX_SUPPORT
    392     if(SOC_IS_DNX(unit))
    393     {
    394         DNX_ERR_RECOVERY_UTILS_EXCLUDED_THREAD_ADD(unit);
    395     }
    396 #endif
    397 
    398     while((interval = SOC_SBUSDMA_DM_TO(unit)) != 0) {
    399         /* wait for run indication */
    400         (void)sal_sem_take(SOC_SBUSDMA_DM_INTR(unit), sal_sem_FOREVER);
    401         if (!SOC_SBUSDMA_DM_TO(unit)) {
    402             goto cleanup_exit;
    403         }
    404         if (!SOC_SBUSDMA_DM_ACTIVE(unit) || !SOC_SBUSDMA_DM_WORKING(unit)) {
    405             continue;
    406         }
    407 
    408         LOG_VERBOSE(BSL_LS_SOC_DMA,
    409                     (BSL_META_U(unit,
    410                                 "soc_sbusdma_desc: Process \n")));
    411         stime = sal_time_usecs();
    412         SOC_SBUSDMA_DM_LOCK(unit);
    413         swd = SOC_SBUSDMA_DM_WORKING(unit);
    414 
    415         /* execute preconfig */
    416         if (swd->ctrl.pc) {
    417             swd->ctrl.pc(unit, swd->handle, swd->ctrl.pc_data);
    418         }
    419 
    420         rv = _sbusdma_desc_drv[unit].soc_sbusdma_program(unit, &cmc, swd, &ch);
    421 
    422         if (rv == SOC_E_NONE) {
    423             rv = _sbusdma_desc_drv[unit].soc_sbusdma_wait(unit, cmc, ch,
    424                                                           SOC_SBUSDMA_DM_TO(unit),
    425                                                           SOC_SBUSDMA_DM_INTRENB(unit));
    426         }
    427 
    428         if (rv == SOC_E_NONE) {
    429             etime = sal_time_usecs();
    430             LOG_VERBOSE(BSL_LS_SOC_DMA,
    431                         (BSL_META_U(unit,
    432                                     "soc_sbusdma_desc: unit=%d mode(%s) done in %d usec\n"),
    433                          unit, SOC_SBUSDMA_DM_INTRENB(unit) ? "interrupt" : "polling",
    434                          SAL_USECS_SUB(etime, stime)));
    435         } else {
    436             LOG_ERROR(BSL_LS_SOC_COMMON,
    437                       (BSL_META_U(unit,
    438                                   "soc_sbusdma_desc:%s Error\n"),
    439                        swd->ctrl.name));
    440         }
    441 
    442         /* execute callback */
    443         swd->status = 0;
    444         swd->ctrl.cb(unit, rv, swd->handle, swd->ctrl.data);
    445 
    446         SOC_SBUSDMA_DM_ACTIVE(unit) = 0;
    447         SOC_SBUSDMA_DM_UNLOCK(unit);
    448     }
    449 cleanup_exit:
    450 
    451     /* cleanup the any pending/aborted descriptor */
    452     if (SOC_SBUSDMA_DM_ACTIVE(unit) && SOC_SBUSDMA_DM_WORKING(unit)) {
    453         SOC_SBUSDMA_DM_LOCK(unit);
    454         swd = SOC_SBUSDMA_DM_WORKING(unit);
    455         swd->status = 0;
    456         SOC_SBUSDMA_DM_ACTIVE(unit) = 0;
    457         SOC_SBUSDMA_DM_UNLOCK(unit);
    458     }
    459 
    460 #ifdef BCM_DNX_SUPPORT
    461     if(SOC_IS_DNX(unit))
    462     {
    463         DNX_ERR_RECOVERY_UTILS_EXCLUDED_THREAD_REMOVE(unit);
    464     }
    465 #endif
    466 
    467     LOG_INFO(BSL_LS_SOC_DMA,
    468              (BSL_META_U(unit,
    469                          "_soc_sbusdma_desc: exiting\n")));
    470     SOC_SBUSDMA_DM_PID(unit) = SAL_THREAD_ERROR;
    471     sal_thread_exit(0);
    472 }
    473 
    474 
    475 STATIC int
    476 _soc_sbusdma_desc_init(int unit, int interval, uint8 intrEnb)
    477 {
    478     int rv;
    479     if (SOC_SBUSDMA_DM_INFO(unit) && (SOC_SBUSDMA_DM_INIT(unit) == 2)) {
    480         return SOC_E_BUSY;
    481     }
    482     if (SOC_SBUSDMA_DM_INFO(unit)) {
    483         SOC_SBUSDMA_DM_INIT(unit) = 2;
    484         if ((rv = soc_sbusdma_desc_detach(unit)) != SOC_E_NONE) {
    485             return rv;
    486         }
    487     }    
    488     SOC_SBUSDMA_DM_INFO(unit) = sal_alloc(sizeof(soc_sbusdma_desc_info_t),
    489                                           "sbusdma dm info");
    490     if (SOC_SBUSDMA_DM_INFO(unit) == NULL) {
    491         return SOC_E_MEMORY;
    492     }
    493     sal_memset(SOC_SBUSDMA_DM_INFO(unit), 0, sizeof(soc_sbusdma_desc_info_t));
    494     SOC_SBUSDMA_DM_INIT(unit) = 2;
    495 
    496     if ((SOC_SBUSDMA_DM_MUTEX(unit) = 
    497            sal_mutex_create("sbusdma dm lock")) == NULL) {
    498         (void)soc_sbusdma_desc_detach(unit);
    499         return SOC_E_MEMORY;
    500     }
    501     if ((SOC_SBUSDMA_DM_INTR(unit) = 
    502            sal_sem_create("Desc DMA interrupt", sal_sem_BINARY, 0)) == NULL) {
    503         (void)soc_sbusdma_desc_detach(unit);
    504         return SOC_E_MEMORY;
    505     }
    506     if (intrEnb) {
    507         SOC_SBUSDMA_DM_INTRENB(unit) = 1;
    508     } else {
    509         SOC_SBUSDMA_DM_INTRENB(unit) = 0;
    510     }
    511     SOC_SBUSDMA_DM_TO(unit) = interval ? interval : SAL_BOOT_QUICKTURN ? 
    512                                   30000000 : 10000000;
    513     sal_snprintf(SOC_SBUSDMA_DM_NAME(unit), sizeof(SOC_SBUSDMA_DM_NAME(unit)),
    514                  "socdmadesc.%d", unit);
    515     SOC_SBUSDMA_DM_PID(unit) = sal_thread_create(SOC_SBUSDMA_DM_NAME(unit),
    516                                                  SAL_THREAD_STKSZ,
    517                                                  soc_property_get(unit, spn_SBUS_DMA_DESC_THREAD_PRI, 50),
    518                                                  _soc_sbusdma_desc,
    519                                                  INT_TO_PTR(unit));
    520     if (SOC_SBUSDMA_DM_PID(unit) == SAL_THREAD_ERROR) {
    521         LOG_ERROR(BSL_LS_SOC_COMMON,
    522                   (BSL_META_U(unit,
    523                               "soc_sbusdma_desc_init: Could not start SBUDMA Desc Mode thread.\n")));
    524         (void)soc_sbusdma_desc_detach(unit);
    525         return SOC_E_MEMORY;
    526     }
    527 
    528     SOC_SBUSDMA_DM_COUNT(unit) = 0;
    529     SOC_SBUSDMA_DM_INIT(unit) = 1;
    530     return SOC_E_NONE;
    531 }
    532 
    533 
    534 int
    535 soc_sbusdma_desc_create(int unit, soc_sbusdma_desc_ctrl_t *ctrl, 
    536                         soc_sbusdma_desc_cfg_t *cfg, 
    537                         sbusdma_desc_handle_t *desc_handle)
    538 {
    539     uint32 i;
    540     _soc_sbusdma_state_t *swd = NULL;
    541     int rv;
    542 
    543     if ((SOC_SBUSDMA_DM_INFO(unit) == NULL) || !SOC_SBUSDMA_DM_INIT(unit)) {
    544         return SOC_E_INIT;
    545     }
    546     if (!ctrl || !cfg || !ctrl->cb || !ctrl->cfg_count) {
    547         return SOC_E_PARAM;
    548     }
    549 
    550     SOC_SBUSDMA_DM_LOCK(unit);
    551     
    552     swd = sal_alloc(sizeof(_soc_sbusdma_state_t), "_soc_sbusdma_state_t");
    553     if (swd == NULL) {
    554         SOC_SBUSDMA_DM_UNLOCK(unit);
    555         return SOC_E_MEMORY;
    556     }
    557     sal_memset(swd, 0, sizeof(_soc_sbusdma_state_t));
    558     /* save s/w ctrl and config */
    559     sal_memcpy(&swd->ctrl, ctrl, sizeof(soc_sbusdma_desc_ctrl_t));
    560     if (ctrl->cfg_count == 1) { /* single mode */
    561         swd->cfg = sal_alloc(sizeof(soc_sbusdma_desc_cfg_t),
    562                                     "soc_sbusdma_desc_cfg_t");
    563         if (swd->cfg == NULL) {
    564             sal_free(swd);
    565             SOC_SBUSDMA_DM_UNLOCK(unit);
    566             return SOC_E_MEMORY;
    567         }
    568         sal_memcpy(swd->cfg, cfg, sizeof(soc_sbusdma_desc_cfg_t));
    569         if (swd->ctrl.buff) { /* ctrl buff over-rides cfg buff */
    570             swd->cfg->buff = swd->ctrl.buff;
    571         }
    572         assert(swd->cfg->buff);
    573         if (!(ctrl->flags & SOC_SBUSDMA_CFG_USE_SUPPLIED_DESC) ||
    574               !ctrl->hw_desc) {
    575 
    576             /* Prepare h/w desc */
    577             rv =  _sbusdma_desc_drv[unit].soc_sbusdma_desc_create(
    578                                                          unit, ctrl,
    579                                                          swd->cfg,
    580                                                          &swd->desc);
    581             if (SOC_FAILURE(rv)) {
    582                 sal_free(swd->cfg);
    583                 sal_free(swd);
    584                 SOC_SBUSDMA_DM_UNLOCK(unit);
    585                 return rv;
    586             }
    587         }
    588     } else { /* chain mode */
    589 
    590         swd->cfg = sal_alloc(sizeof(soc_sbusdma_desc_cfg_t) * ctrl->cfg_count, 
    591                              "soc_sbusdma_desc_cfg_t");
    592         if (swd->cfg == NULL) {
    593             sal_free(swd);
    594             SOC_SBUSDMA_DM_UNLOCK(unit);
    595             return SOC_E_MEMORY;
    596         }
    597         sal_memcpy(swd->cfg, cfg, sizeof(soc_sbusdma_desc_cfg_t) * 
    598                    ctrl->cfg_count);
    599         if (!(ctrl->flags & SOC_SBUSDMA_CFG_USE_SUPPLIED_DESC) ||
    600                            !ctrl->hw_desc) {
    601 
    602             /* Prepare h/w desc */
    603             rv =  _sbusdma_desc_drv[unit].soc_sbusdma_desc_create(
    604                                                          unit, ctrl,
    605                                                          swd->cfg,
    606                                                          &swd->desc);
    607             if (SOC_FAILURE(rv)) {
    608                 sal_free(swd->cfg);
    609                 sal_free(swd);
    610                 SOC_SBUSDMA_DM_UNLOCK(unit);
    611                 return rv;
    612             }
    613         }
    614     }
    615     /* find a free handle */
    616     for (i=1; i<SOC_SBUSDMA_MAX_DESC;) {
    617         if (SOC_SBUSDMA_DM_HANDLES(unit)[i] == 0) {
    618             break;
    619         }
    620         i++;
    621     }
    622     if(i >= SOC_SBUSDMA_MAX_DESC) {
    623         LOG_WARN(BSL_LS_SOC_DMA,
    624             (BSL_META_U(unit,
    625                         "No free DMA descriptors. All %d are used. \n"), i));
    626         if (!(swd->ctrl.flags & SOC_SBUSDMA_CFG_USE_SUPPLIED_DESC)) {
    627             soc_cm_sfree(unit, swd->desc);
    628         }
    629         sal_free(swd->cfg);
    630         sal_free(swd);
    631         SOC_SBUSDMA_DM_UNLOCK(unit);
    632         return SOC_E_RESOURCE;
    633     }
    634 
    635     *desc_handle = i; 
    636     swd->handle = *desc_handle;
    637     SOC_SBUSDMA_DM_HANDLES(unit)[i] = swd;
    638     SOC_SBUSDMA_DM_COUNT(unit)++;
    639     SOC_SBUSDMA_DM_UNLOCK(unit);
    640     if (ctrl->cfg_count == 1) {
    641         LOG_INFO(BSL_LS_SOC_DMA,
    642                  (BSL_META_U(unit,
    643                              "Create Single:: Handle: %d,"
    644                              "opcount: %d, buff: %p\n"),
    645                   swd->handle, swd->ctrl.cfg_count, swd->cfg->buff));
    646     } else {
    647         LOG_INFO(BSL_LS_SOC_DMA,
    648                  (BSL_META_U(unit,
    649                              "Create Chain:: Handle: %d, desc count: %d\n"), 
    650                   swd->handle, swd->ctrl.cfg_count));
    651     }
    652     
    653     LOG_INFO(BSL_LS_SOC_DMA,
    654              (BSL_META_U(unit,
    655                          "SBD DM count: %d\n"), SOC_SBUSDMA_DM_COUNT(unit)));
    656     return SOC_E_NONE;
    657 }
    658 
    659 int
    660 soc_sbusdma_desc_get(int unit, sbusdma_desc_handle_t desc_handle,
    661                      soc_sbusdma_desc_ctrl_t *ctrl,
    662                      soc_sbusdma_desc_cfg_t *cfg)
    663 {
    664     _soc_sbusdma_state_t *swd;
    665 
    666     if ((SOC_SBUSDMA_DM_INFO(unit) == NULL) || !SOC_SBUSDMA_DM_INIT(unit) ||
    667         !SOC_SBUSDMA_DM_COUNT(unit)) {
    668         return SOC_E_INIT;
    669     }
    670 
    671     if (!ctrl || !cfg) {
    672         return SOC_E_PARAM;
    673     }
    674 
    675     SOC_SBUSDMA_DM_LOCK(unit);
    676     if ((desc_handle > 0) && (desc_handle <= SOC_SBUSDMA_MAX_DESC)
    677         && SOC_SBUSDMA_DM_HANDLES(unit)[desc_handle]) {
    678         swd = SOC_SBUSDMA_DM_HANDLES(unit)[desc_handle];
    679     } else {
    680         SOC_SBUSDMA_DM_UNLOCK(unit);
    681         LOG_ERROR(BSL_LS_SOC_COMMON,
    682                   (BSL_META_U(unit,
    683                               "Get request for invalid or non-existing descriptor handle: %d\n"),
    684                    desc_handle));
    685         return SOC_E_PARAM;
    686     }
    687     if (swd->handle != desc_handle) {
    688         SOC_SBUSDMA_DM_UNLOCK(unit);
    689         LOG_ERROR(BSL_LS_SOC_COMMON,
    690                   (BSL_META_U(unit,
    691                               "Handle mismatch found: %d<=>%d\n"), swd->handle,
    692                    desc_handle));
    693         return SOC_E_INTERNAL;
    694     }
    695     sal_memcpy(ctrl, &swd->ctrl, sizeof(soc_sbusdma_desc_ctrl_t));
    696     sal_memcpy(cfg, swd->cfg, sizeof(soc_sbusdma_desc_cfg_t) * ctrl->cfg_count);
    697     SOC_SBUSDMA_DM_UNLOCK(unit);
    698     return SOC_E_NONE;
    699 }
    700 
    701 int
    702 soc_sbusdma_desc_get_state(int unit, sbusdma_desc_handle_t desc_handle,
    703                            uint8 *state)
    704 {
    705     _soc_sbusdma_state_t *swd;
    706 
    707     if ((SOC_SBUSDMA_DM_INFO(unit) == NULL) || !SOC_SBUSDMA_DM_INIT(unit) ||
    708         !SOC_SBUSDMA_DM_COUNT(unit)) {
    709         return SOC_E_INIT;
    710     }
    711     SOC_SBUSDMA_DM_LOCK(unit);
    712     if ((desc_handle > 0) && (desc_handle <= SOC_SBUSDMA_MAX_DESC) 
    713         && SOC_SBUSDMA_DM_HANDLES(unit)[desc_handle]) {
    714         swd = SOC_SBUSDMA_DM_HANDLES(unit)[desc_handle];
    715     } else {
    716         SOC_SBUSDMA_DM_UNLOCK(unit);
    717         LOG_ERROR(BSL_LS_SOC_COMMON,
    718                   (BSL_META_U(unit,
    719                               "Get state request for invalid or non-existing descriptor handle: %d\n"), 
    720                    desc_handle));
    721         return SOC_E_PARAM;
    722     }
    723     if (swd->handle != desc_handle) {
    724         SOC_SBUSDMA_DM_UNLOCK(unit);
    725         LOG_ERROR(BSL_LS_SOC_COMMON,
    726                   (BSL_META_U(unit,
    727                               "Handle mismatch found: %d<=>%d\n"), swd->handle,
    728                    desc_handle));
    729         return SOC_E_INTERNAL;
    730     }
    731     *state = swd->status;
    732     SOC_SBUSDMA_DM_UNLOCK(unit);
    733     return SOC_E_NONE;
    734 }
    735 
    736 int
    737 soc_sbusdma_desc_run(int unit, sbusdma_desc_handle_t desc_handle)
    738 {
    739     _soc_sbusdma_state_t *swd;
    740 
    741     if ((SOC_SBUSDMA_DM_INFO(unit) == NULL) || !SOC_SBUSDMA_DM_INIT(unit) ||
    742         !SOC_SBUSDMA_DM_COUNT(unit)) {
    743         return SOC_E_INIT;
    744     }
    745     SOC_SBUSDMA_DM_LOCK(unit);
    746     if (SOC_SBUSDMA_DM_ACTIVE(unit)) {
    747         SOC_SBUSDMA_DM_UNLOCK(unit);
    748         return SOC_E_BUSY;
    749     }
    750     if ((desc_handle > 0) && (desc_handle <= SOC_SBUSDMA_MAX_DESC)
    751         && SOC_SBUSDMA_DM_HANDLES(unit)[desc_handle]) {
    752         swd = SOC_SBUSDMA_DM_HANDLES(unit)[desc_handle];
    753     } else {
    754         SOC_SBUSDMA_DM_UNLOCK(unit);
    755         LOG_ERROR(BSL_LS_SOC_COMMON,
    756                   (BSL_META_U(unit,
    757                               "Run request for invalid or non-existing descriptor handle: %d\n"),
    758                    desc_handle));
    759         return SOC_E_PARAM;
    760     }
    761     if (swd->handle != desc_handle) {
    762         SOC_SBUSDMA_DM_UNLOCK(unit);
    763         LOG_ERROR(BSL_LS_SOC_COMMON,
    764                   (BSL_META_U(unit,
    765                               "Handle mismatch found: %d<=>%d\n"),
    766                    swd->handle, desc_handle));
    767         return SOC_E_INTERNAL;
    768     }
    769 
    770     /* process swd->desc */
    771     swd->status = 1;
    772     SOC_SBUSDMA_DM_ACTIVE(unit) = 1;
    773     SOC_SBUSDMA_DM_WORKING(unit) = swd;
    774     
    775     if (swd->ctrl.cfg_count == 1) {
    776         LOG_INFO(BSL_LS_SOC_DMA,
    777                  (BSL_META_U(unit,
    778                              "Run Single:: Handle: %d, desc count: %d,"
    779                              "buff: %p\n"),
    780                   swd->handle, swd->ctrl.cfg_count, swd->cfg->buff));
    781     } else {
    782         LOG_INFO(BSL_LS_SOC_DMA,
    783                  (BSL_META_U(unit,
    784                              "Run Chain:: Handle: %d, desc count: %d\n"),
    785                   swd->handle, swd->ctrl.cfg_count));
    786     }
    787     sal_sem_give(SOC_SBUSDMA_DM_INTR(unit));
    788 
    789     SOC_SBUSDMA_DM_UNLOCK(unit);
    790 
    791     return SOC_E_NONE;
    792 }
    793 
    794 int
    795 soc_sbusdma_desc_start(int unit, sbusdma_desc_handle_t desc_handle)
    796 {
    797     soc_control_t *soc = SOC_CONTROL(unit);
    798     _soc_sbusdma_state_t *swd;
    799     sal_usecs_t stime, etime;
    800     int cmc = SOC_PCI_CMC(unit);
    801     int ch = soc->desc_ch;
    802     int rv;
    803 
    804     if (!SOC_CHECK_MULTI_CMC(unit)) {
    805         return soc_sbusdma_desc_run(unit, desc_handle);
    806     }
    807 
    808     if ((SOC_SBUSDMA_DM_INFO(unit) == NULL) || !SOC_SBUSDMA_DM_INIT(unit) ||
    809         !SOC_SBUSDMA_DM_COUNT(unit)) {
    810         return SOC_E_INIT;
    811     }
    812     SOC_SBUSDMA_DM_LOCK(unit);
    813     if ((desc_handle > 0) && (desc_handle <= SOC_SBUSDMA_MAX_DESC)
    814         && SOC_SBUSDMA_DM_HANDLES(unit)[desc_handle]) {
    815         swd = SOC_SBUSDMA_DM_HANDLES(unit)[desc_handle];
    816     } else {
    817         SOC_SBUSDMA_DM_UNLOCK(unit);
    818         LOG_ERROR(BSL_LS_SOC_COMMON,
    819                   (BSL_META_U(unit,
    820                               "Start request for invalid or non-existing descriptor handle: %d\n"),
    821                    desc_handle));
    822         return SOC_E_PARAM;
    823     }
    824     if (swd->handle != desc_handle) {
    825         SOC_SBUSDMA_DM_UNLOCK(unit);
    826         LOG_ERROR(BSL_LS_SOC_COMMON,
    827                   (BSL_META_U(unit,
    828                               "Handle mismatch found: %d<=>%d\n"),
    829                    swd->handle, desc_handle));
    830         return SOC_E_INTERNAL;
    831     }
    832     if (swd->status) {
    833         SOC_SBUSDMA_DM_UNLOCK(unit);
    834         return SOC_E_BUSY;
    835     }
    836     swd->status = 1;
    837     SOC_SBUSDMA_DM_UNLOCK(unit);
    838 
    839     if (swd->ctrl.cfg_count == 1) {
    840         LOG_INFO(BSL_LS_SOC_DMA,
    841                  (BSL_META_U(unit,
    842                              "Start Single:: Handle: %d, desc count: %d,"
    843                              "buff: %p\n"),
    844                   swd->handle, swd->ctrl.cfg_count, swd->cfg->buff));
    845     } else {
    846         LOG_INFO(BSL_LS_SOC_DMA,
    847                  (BSL_META_U(unit,
    848                              "Start Chain:: Handle: %d, desc count: %d\n"),
    849                   swd->handle, swd->ctrl.cfg_count));
    850     }
    851 
    852     stime = sal_time_usecs();
    853 
    854     /* execute preconfig */
    855     if (swd->ctrl.pc) {
    856         swd->ctrl.pc(unit, swd->handle, swd->ctrl.pc_data);
    857     }
    858 
    859     rv = _sbusdma_desc_drv[unit].soc_sbusdma_program(unit, &cmc, swd, &ch);
    860 
    861     if (rv == SOC_E_NONE) {
    862         rv = _sbusdma_desc_drv[unit].soc_sbusdma_wait(unit, cmc, ch,
    863                                                       SOC_SBUSDMA_DM_TO(unit),
    864                                                       SOC_SBUSDMA_DM_INTRENB(unit));
    865     }
    866 
    867     if (rv == SOC_E_NONE) {
    868         etime = sal_time_usecs();
    869         LOG_VERBOSE(BSL_LS_SOC_DMA,
    870                     (BSL_META_U(unit,
    871                                 "soc_sbusdma_desc: unit=%d mode(%s) done in %d usec\n"),
    872                      unit, SOC_SBUSDMA_DM_INTRENB(unit) ? "interrupt" : "polling",
    873                      SAL_USECS_SUB(etime, stime)));
    874     } else {
    875         LOG_ERROR(BSL_LS_SOC_COMMON,
    876                   (BSL_META_U(unit,
    877                               "soc_sbusdma_desc:%s Error\n"),
    878                    swd->ctrl.name));
    879     }
    880 
    881     /* execute callback */
    882     swd->ctrl.cb(unit, rv, swd->handle, swd->ctrl.data);
    883 
    884     SOC_SBUSDMA_DM_LOCK(unit);
    885     swd->status = 0;
    886     SOC_SBUSDMA_DM_UNLOCK(unit);
    887 
    888     return rv;
    889 }
    890 
    891 int
    892 soc_sbusdma_desc_delete(int unit, sbusdma_desc_handle_t handle)
    893 {
    894     _soc_sbusdma_state_t *swd;
    895 
    896     if ((SOC_SBUSDMA_DM_INFO(unit) == NULL) || !SOC_SBUSDMA_DM_INIT(unit) ||
    897         !SOC_SBUSDMA_DM_COUNT(unit)) {
    898         return SOC_E_INIT;
    899     }
    900     SOC_SBUSDMA_DM_LOCK(unit);
    901     if ((handle > 0) && (handle <= SOC_SBUSDMA_MAX_DESC)
    902         && SOC_SBUSDMA_DM_HANDLES(unit)[handle]) {
    903         swd = SOC_SBUSDMA_DM_HANDLES(unit)[handle];
    904         if (swd->handle != handle) {
    905             SOC_SBUSDMA_DM_UNLOCK(unit);
    906             LOG_ERROR(BSL_LS_SOC_COMMON,
    907                       (BSL_META_U(unit,
    908                                   "Handle mismatch found: %d<=>%d\n"),
    909                        swd->handle, handle));
    910             return SOC_E_INTERNAL;
    911         }
    912         if (swd->ctrl.cfg_count == 1) {
    913             LOG_INFO(BSL_LS_SOC_DMA,
    914                      (BSL_META_U(unit,
    915                                  "Delete Single:: Handle: %d, desc count: %d,"
    916                                  "buff: %p\n"),
    917                       swd->handle, swd->ctrl.cfg_count, swd->cfg->buff));
    918         } else {
    919             LOG_INFO(BSL_LS_SOC_DMA,
    920                      (BSL_META_U(unit,
    921                                  "Delete Chain:: Handle: %d, desc count: %d\n"),
    922                       swd->handle, swd->ctrl.cfg_count));
    923         }
    924         sal_free(swd->cfg);
    925         if (!(swd->ctrl.flags & SOC_SBUSDMA_CFG_USE_SUPPLIED_DESC)) {
    926             soc_cm_sfree(unit, swd->desc);
    927         }
    928         sal_free(swd);
    929         SOC_SBUSDMA_DM_HANDLES(unit)[handle] = 0;
    930         SOC_SBUSDMA_DM_COUNT(unit)--;
    931         LOG_INFO(BSL_LS_SOC_DMA,
    932                  (BSL_META_U(unit,
    933                              "SBD DM count: %d\n"),
    934                   SOC_SBUSDMA_DM_COUNT(unit)));
    935     } else {
    936         SOC_SBUSDMA_DM_UNLOCK(unit);
    937         LOG_ERROR(BSL_LS_SOC_COMMON,
    938                   (BSL_META_U(unit,
    939                               "Del request for invalid or non-existing descriptor handle: %d\n"),
    940                    handle));
    941         return SOC_E_PARAM;
    942     }
    943     SOC_SBUSDMA_DM_UNLOCK(unit);
    944     return SOC_E_NONE;
    945 }
    946 
    947 /*******************************************
    948 * @function soc_sbusdma_ch_try_get
    949 * purpose get idle channel on cmc
    950 *
    951 * @param unit [in] unit #
    952 * @param cmc [out] cmc number
    953 * @param ch [out] channel number
    954 *
    955 * @returns SOC_E_BUSY
    956 * @returns SOC_E_NONE
    957 *
    958 * @end
    959  */
    960 int soc_sbusdma_ch_try_get(int unit, int cmc, int ch)
    961 {
    962     int rv = SOC_E_NONE;
    963 
    964     if (_sbusdma_reg_drv[unit].ch.soc_sbusdma_ch_try_get != NULL) {
    965         rv =
    966          _sbusdma_reg_drv[unit].ch.soc_sbusdma_ch_try_get(unit, cmc, ch);
    967     } else {
    968         rv = SOC_E_INIT;
    969     }
    970 
    971     return rv;
    972 }
    973 
    974 /*******************************************
    975 * @function soc_sbusdma_ch_put
    976 * purpose put back the freed channel on cmc
    977 *
    978 * @param cmc [in] cmc number
    979 * @param ch [in] channel number
    980 *
    981 * @returns SOC_E_PARAM
    982 * @returns SOC_E_NONE
    983 *
    984 * @end
    985  */
    986 int soc_sbusdma_ch_put(int unit, int cmc, int ch)
    987 {
    988    int rv;
    989 
    990    if (_sbusdma_reg_drv[unit].ch.soc_sbusdma_ch_put != NULL) {
    991         rv =
    992          _sbusdma_reg_drv[unit].ch.soc_sbusdma_ch_put(unit, cmc, ch);
    993    } else {
    994        rv = SOC_E_INIT;
    995    }
    996 
    997    return rv;
    998 }
    999 
   1000 /*******************************************
   1001 * @function soc_sbusdma_ch_endian_set
   1002 * set the endianess value
   1003 *
   1004 * @param cmc [in] cmc number
   1005 * @param ch [in] channel number
   1006 * @param ch [in] big_endian
   1007 *
   1008 * @returns SOC_E_PARAM
   1009 * @returns SOC_E_NONE
   1010 *
   1011 * @end
   1012  */
   1013 int soc_sbusdma_ch_endian_set(int unit, int cmc, int ch, int be)
   1014 {
   1015 #ifdef BCM_CMICX_SUPPORT
   1016     if (soc_feature(unit, soc_feature_cmicx)) {
   1017         return cmicx_sbusdma_ch_endian_set(unit, cmc, ch, be);
   1018     }
   1019 #endif
   1020 
   1021     return SOC_E_NONE;
   1022 }
   1023 
   1024 /*******************************************
   1025 * @function soc_sbusdma_cmc_max_num_ch_get
   1026 * @Returns number of SBUSDMA channels in cmc
   1027 *
   1028 * @end
   1029  */
   1030 uint32 soc_sbusdma_cmc_max_num_ch_get(int unit)
   1031 {
   1032     if(_sbusdma_reg_drv[unit].drv.soc_sbusdma_cmc_max_num_ch_get == NULL) {
   1033         /* driver is not attached yet, so return zero */
   1034         return 0;
   1035     }
   1036     return _sbusdma_reg_drv[unit].drv.soc_sbusdma_cmc_max_num_ch_get(unit);
   1037 }
   1038 
   1039 /*******************************************
   1040 * @function soc_sbusdma_reg_init
   1041 * purpose API to Initialize cmicx/cmicm Register DMA
   1042 *
   1043 * @param unit [in] unit
   1044 *
   1045 * @returns SOC_E_NONE
   1046 * @returns SOC_E_XXX
   1047 *
   1048 * @end
   1049  */
   1050 int soc_sbusdma_reg_init(int unit)
   1051 {
   1052 #ifdef BCM_CMICX_SUPPORT
   1053     if (soc_feature(unit, soc_feature_cmicx)) {
   1054         SOC_IF_ERROR_RETURN(cmicx_sbusdma_reg_init(unit,
   1055                             &_sbusdma_reg_drv[unit].drv));
   1056     }
   1057 #endif
   1058 
   1059 #ifdef BCM_CMICM_SUPPORT
   1060     if (soc_feature(unit, soc_feature_cmicm)) {
   1061         SOC_IF_ERROR_RETURN(cmicm_sbusdma_reg_init(unit,
   1062                             &_sbusdma_reg_drv[unit].drv));
   1063     }
   1064 #endif
   1065 
   1066     return SOC_E_NONE;
   1067 }
   1068 
   1069 
   1070 /*******************************************
   1071 * @function soc_sbusdma_init
   1072 * purpose API to Initialize SBUS DMA
   1073 *
   1074 * @param unit [in] unit
   1075 *
   1076 * @returns SOC_E_NONE
   1077 * @returns SOC_E_XXX
   1078 *
   1079 * @end
   1080  */
   1081 int soc_sbusdma_init(int unit, int interval, uint8 intrEnb)
   1082 {
   1083     int rv;
   1084 
   1085 #ifdef BCM_CMICX_SUPPORT
   1086     if (soc_feature(unit, soc_feature_cmicx)) {
   1087         soc_control_t *soc = SOC_CONTROL(unit);
   1088         SOC_IF_ERROR_RETURN(cmicx_sbusdma_reg_init(unit,
   1089                             &_sbusdma_reg_drv[unit].drv));
   1090         SOC_IF_ERROR_RETURN(cmicx_sbusdma_ch_init(unit,
   1091                         soc->sbusDmaTimeout + CMIC_CMCx_SBUSDMA_CHSELECT_TIMEOUT,
   1092                         &_sbusdma_reg_drv[unit].ch));
   1093 
   1094         if ((soc->sbusDmaIntrEnb) || (soc->tslamDmaIntrEnb) ||
   1095                (soc->tableDmaIntrEnb)) {
   1096             SOC_IF_ERROR_RETURN(cmicx_sbusdma_intr_init(unit));
   1097         }
   1098 
   1099         SOC_IF_ERROR_RETURN(_soc_sbusdma_desc_init(unit, interval, intrEnb));
   1100 
   1101         rv = cmicx_sbusdma_desc_init(unit, &_sbusdma_desc_drv[unit]);
   1102         if (rv != SOC_E_NONE) {
   1103             (void)soc_sbusdma_desc_detach(unit);
   1104             return rv;
   1105         }
   1106 
   1107         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1108                   (BSL_META_U(unit,":SUCCESS\n")));
   1109     }
   1110 #endif
   1111 
   1112 
   1113 #ifdef BCM_CMICM_SUPPORT
   1114     if (soc_feature(unit, soc_feature_cmicm)) {
   1115 
   1116         SOC_IF_ERROR_RETURN(cmicm_sbusdma_reg_init(unit,
   1117                             &_sbusdma_reg_drv[unit].drv));
   1118         SOC_IF_ERROR_RETURN(cmicm_sbusdma_ch_init(unit,
   1119                         CMIC_CMCx_SBUSDMA_CHSELECT_TIMEOUT,
   1120                         &_sbusdma_reg_drv[unit].ch));
   1121 
   1122         SOC_IF_ERROR_RETURN(_soc_sbusdma_desc_init(unit, interval, intrEnb));
   1123 
   1124         rv = cmicm_sbusdma_desc_init(unit, &_sbusdma_desc_drv[unit]);
   1125         if (rv != SOC_E_NONE) {
   1126           (void)soc_sbusdma_desc_detach(unit);
   1127            return rv;
   1128         }
   1129     }
   1130 #endif
   1131 
   1132     return SOC_E_NONE;
   1133 }
   1134 
   1135 #endif /* BCM_SBUSDMA_SUPPORT */
   1136 #endif /* defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) */