openbcm

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

soc_async_sbusdma.c (13702B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        soc_async_sbusdma.c
      8  * Purpose:     SOC SBUS-DMA driver, supports both sync and async modes.
      9  */
     10 
     11 #include <shared/bsl.h>
     12 #include <shared/alloc.h>
     13 #include <soc/drv.h>
     14 #include <soc/debug.h>
     15 #include <soc/cm.h>
     16 #include <soc/sbusdma_internal.h>
     17 #include <soc/soc_async_sbusdma.h>
     18 
     19 #if defined(BCM_SBUSDMA_SUPPORT) && defined(BCM_SOC_ASYNC_SUPPORT)
     20 
     21 #if (!defined(_LIMITS_H)) && !defined(_LIBC_LIMITS_H_)
     22 
     23 #if (!defined(INT_MIN)) && !defined(INT_MAX)
     24 #define INT_MIN (((int)1)<<(sizeof(int)*8-1))
     25 #define INT_MAX (~INT_MIN)
     26 #endif
     27 
     28 #ifndef UINT_MAX
     29 #define UINT_MAX ((unsigned)-1)
     30 #endif
     31 
     32 #endif
     33 
     34 typedef struct soc_async_sbusdma_reg_s {
     35     soc_sbusdma_reg_drv_t drv;
     36     soc_sbusdma_cmic_ch_t  ch;
     37     soc_async_handle_t handle;
     38 } soc_async_sbusdma_reg_t;
     39 
     40 STATIC soc_async_sbusdma_reg_t _async_sbusdma_reg[SOC_MAX_NUM_DEVICES];
     41 
     42 /*******************************************
     43 * @function _soc_async_sbusdma_cb_f
     44 * purpose this function calls used defined callback
     45 *
     46 * @param unit [in] unit #
     47 * @param data [in] User parameter
     48 * @param cookie [in] user/driver data
     49 * @param cookie [in] status
     50 *
     51 * @end
     52  */
     53 STATIC void
     54 _soc_async_sbusdma_cb_f(int unit,
     55                     void *data, void *cookie, int status)
     56 {
     57     cmic_sbusdma_wparam_t *wparam;
     58 
     59     wparam = (cmic_sbusdma_wparam_t *)cookie;
     60     if (wparam) {
     61         wparam->cb_f(unit, data, wparam->cookie, status);
     62         sal_free(wparam);
     63     }
     64 }
     65 
     66 /*******************************************
     67 * @function _soc_async_sbusdma_msg_alloc
     68 * purpose this function to initialize sbus message
     69 *
     70 * @param unit [in] unit #
     71 * @param msg [in, out] pointer to pointer soc_async_msg_t
     72 * @param param [in] user data pointer
     73 * @param cbf [in] user call back function
     74 *
     75 * @returns SOC_E_BUSY
     76 * @returns SOC_E_MEMORY
     77 * @end
     78  */
     79 STATIC int
     80 _soc_async_sbusdma_msg_alloc(int unit,
     81                      soc_async_msg_t  **msg,
     82                      soc_sbusdma_reg_param_t *param,
     83                      soc_async_cb_f   cbf)
     84 {
     85     cmic_sbusdma_wparam_t *wparam;
     86 
     87     wparam = sal_alloc(sizeof(cmic_sbusdma_wparam_t), "cmicx_sbusdma_wparam");
     88 
     89     if(!wparam) {
     90         return SOC_E_MEMORY;
     91     }
     92 
     93     if (SOC_FAILURE(soc_async_msg_alloc(_async_sbusdma_reg[unit].handle, msg))) {
     94         sal_free(wparam);
     95         return SOC_E_MEMORY;
     96     }
     97     (*msg)->unit = unit;
     98     (*msg)->type = p_sbus_dma;
     99     (*msg)->data = param;
    100     (*msg)->cookie = wparam;
    101     (*msg)->wait_f = _async_sbusdma_reg[unit].drv.soc_sbusdma_reg_complete;
    102     (*msg)->cb_f = _soc_async_sbusdma_cb_f;
    103     wparam->cb_f = cbf;
    104     wparam->cookie = NULL;
    105 
    106     return SOC_E_NONE;
    107 }
    108 
    109 /*******************************************
    110 * @function _soc_async_sbusdma_msg_free
    111 * purpose this function to initialize sbus message
    112 *
    113 * @param unit [in] unit #
    114 * @param msg [in] pointer to soc_async_msg_t
    115 *
    116 * @returns SOC_E_BUSY
    117 * @returns SOC_E_MEMORY
    118 * @end
    119  */
    120 STATIC int
    121 _soc_async_sbusdma_msg_free(int unit,
    122                      soc_async_msg_t  *msg)
    123 {
    124    cmic_sbusdma_wparam_t *wparam = NULL;
    125 
    126    if (msg == NULL)
    127        return SOC_E_PARAM;
    128 
    129    wparam = (cmic_sbusdma_wparam_t *)msg->cookie;
    130 
    131    if (wparam) {
    132        sal_free(wparam);
    133    }
    134 
    135    soc_async_msg_free(_async_sbusdma_reg[unit].handle, msg);
    136 
    137    return SOC_E_NONE;
    138 }
    139 
    140 /*******************************************
    141 * @function soc_async_mem_array_sbusdma_write
    142 * purpose DMA acceleration for soc_mem_write_range()
    143 * If callback function is NULL then the call
    144 * will behave as synchronous/Blocked.
    145 *
    146 * @param unit [in] unit #
    147 * @param param [in] soc_sbusdma_reg_param_t pointer
    148 * @param cbf [out] soc_async_cb_f, call back function pointer
    149 *
    150 * @returns SOC_E_BUSY
    151 * @returns SOC_E_NONE
    152 *
    153 * @end
    154  */
    155 int
    156 soc_async_mem_array_sbusdma_write(int unit,
    157         soc_sbusdma_reg_param_t *param, soc_async_cb_f   cbf)
    158 {
    159     soc_control_t *soc = SOC_CONTROL(unit);
    160     int rv = SOC_E_NONE;
    161     soc_async_msg_t  *msg;
    162     soc_timeout_t to;
    163     cmic_sbusdma_wait_t  *wait;
    164 
    165     /* If callback is defined it is async call */
    166     if (cbf != NULL) {
    167         rv = _soc_async_sbusdma_msg_alloc(unit, &msg, param, cbf);
    168         if (rv == SOC_E_NONE) {
    169             wait = &((cmic_sbusdma_wparam_t *)(msg->cookie))->wait;
    170             wait->intr_enb = soc->tslamDmaIntrEnb;
    171             wait->timeout = soc->tslamDmaTimeout;
    172             msg->proc_f = _async_sbusdma_reg[unit].drv.soc_sbusdma_write_prog;
    173             soc_timeout_init(&to, wait->timeout, 100);
    174             do {
    175                 rv = soc_async_msg_queue(_async_sbusdma_reg[unit].handle, msg);
    176                 if (rv == SOC_E_NONE) {
    177                     break;
    178                 }
    179             } while(!soc_timeout_check(&to));
    180 
    181             if (SOC_FAILURE(rv)) {
    182                (void)_soc_async_sbusdma_msg_free(unit, msg);
    183             }
    184         }
    185 
    186     } else {
    187         if (_async_sbusdma_reg[unit].drv.soc_mem_sbusdma_write != NULL) {
    188             rv = _async_sbusdma_reg[unit].drv.soc_mem_sbusdma_write(unit,
    189                                                       param);
    190         } else {
    191             rv = SOC_E_INIT;
    192         }
    193     }
    194 
    195     return rv;
    196 }
    197 
    198 /*******************************************
    199 * @function soc_async_mem_sbusdma_write
    200 * purpose DMA acceleration for soc_mem_write_range()
    201 * This calls 'soc_mem_array_sbusdma_async_write'
    202 *
    203 * @param unit [in] unit #
    204 * @param param [in] soc_sbusdma_reg_param_t pointer
    205 * @param cbf [out] soc_async_cb_f, call back function pointer
    206 *
    207 * @returns SOC_E_BUSY
    208 * @returns SOC_E_NONE
    209 *
    210 * @end
    211  */
    212 int
    213 soc_async_mem_sbusdma_write(int unit,
    214         soc_sbusdma_reg_param_t *param, soc_async_cb_f   cbf)
    215 {
    216     param->array_id_start = 0;
    217     param->array_id_end = 0;
    218     param->flags= 0;
    219 
    220     return soc_async_mem_array_sbusdma_write(unit, param, cbf);
    221 }
    222 
    223 /*******************************************
    224 * @function soc_async_mem_array_sbusdma_read
    225 * purpose DMA acceleration for soc_mem_read_range()
    226 * If callback function is NULL then the call
    227 * will behave as synchronous/Blocked.
    228 *
    229 * @param unit [in] unit #
    230 * @param param [in] soc_sbusdma_reg_param_t pointer
    231 * @param cbf [out] soc_async_cb_f, call back function pointer
    232 *
    233 * @returns SOC_E_BUSY
    234 * @returns SOC_E_NONE
    235 *
    236 * @end
    237  */
    238 int
    239 soc_async_mem_array_sbusdma_read(int unit,
    240         soc_sbusdma_reg_param_t *param, soc_async_cb_f   cbf)
    241 {
    242     soc_control_t *soc = SOC_CONTROL(unit);
    243     int rv = SOC_E_NONE;
    244     soc_async_msg_t  *msg;
    245     soc_timeout_t to;
    246     cmic_sbusdma_wait_t  *wait;
    247 
    248     /* If callback is defined it is async call */
    249     if (cbf != NULL) {
    250         rv = _soc_async_sbusdma_msg_alloc(unit, &msg, param, cbf);
    251         if (rv == SOC_E_NONE) {
    252             wait = &((cmic_sbusdma_wparam_t *)(msg->cookie))->wait;
    253             wait->intr_enb = soc->tableDmaIntrEnb;
    254             wait->timeout = soc->tableDmaTimeout;
    255             msg->proc_f = _async_sbusdma_reg[unit].drv.soc_sbusdma_read_prog;
    256             soc_timeout_init(&to, wait->timeout, 100);
    257 
    258             do {
    259                 rv = soc_async_msg_queue(_async_sbusdma_reg[unit].handle, msg);
    260                 if (rv == SOC_E_NONE) {
    261                     break;
    262                 }
    263             } while(!soc_timeout_check(&to));
    264 
    265             if (SOC_FAILURE(rv)) {
    266                 (void)_soc_async_sbusdma_msg_free(unit, msg);
    267             }
    268         }
    269 
    270     } else {
    271         if (_async_sbusdma_reg[unit].drv.soc_mem_sbusdma_read != NULL) {
    272             rv = _async_sbusdma_reg[unit].drv.soc_mem_sbusdma_read(unit,
    273                                                       param);
    274         }  else {
    275             rv = SOC_E_INIT;
    276         }
    277     }
    278     return rv;
    279 }
    280 
    281 /*******************************************
    282 * @function soc_async_mem_sbusdma_read
    283 * purpose DMA acceleration for soc_mem_read_range()
    284 * This calls 'soc_mem_array_sbusdma_async_read'
    285 *
    286 * @param unit [in] unit #
    287 * @param param [in] soc_sbusdma_reg_param_t pointer
    288 * @param cbf [out] soc_async_cb_f, call back function pointer
    289 *
    290 * @returns SOC_E_BUSY
    291 * @returns SOC_E_NONE
    292 *
    293 * @end
    294  */
    295 int
    296 soc_async_mem_sbusdma_read(int unit,
    297         soc_sbusdma_reg_param_t *param, soc_async_cb_f   cbf)
    298 {
    299      param->array_id_start = 0;
    300 
    301      return soc_async_mem_array_sbusdma_read(unit, param, cbf);
    302 }
    303 
    304 /*******************************************
    305 * @function soc_async_mem_sbusdma_clear_specific
    306 * purpose Clear a specific memory/table region using
    307 * DMA write (slam) acceleration.
    308 * If callback function is NULL then the call
    309 * will behave as synchronous/Blocked.
    310 *
    311 * @param unit [in] unit #
    312 * @param param [in] soc_sbusdma_reg_param_t pointer
    313 * @param cbf [out] soc_async_cb_f, call back function pointer
    314 *
    315 * @returns SOC_E_BUSY
    316 * @returns SOC_E_NONE
    317 *
    318 * @end
    319  */
    320 int
    321 soc_async_mem_sbusdma_clear_specific(int unit,
    322         soc_sbusdma_reg_param_t *param, soc_async_cb_f   cbf)
    323 {
    324     soc_control_t *soc = SOC_CONTROL(unit);
    325     int rv = SOC_E_NONE;
    326     soc_async_msg_t  *msg;
    327     soc_timeout_t to;
    328 
    329     /* If callback is defined it is async call */
    330     if (cbf != NULL) {
    331          rv = _soc_async_sbusdma_msg_alloc(unit, &msg, param, cbf);
    332         if (rv == SOC_E_NONE) {
    333             msg->proc_f = _async_sbusdma_reg[unit].drv.soc_sbusdma_clear_prog;
    334             msg->wait_f = NULL;
    335             soc_timeout_init(&to, soc->tslamDmaTimeout, 100);
    336             do {
    337                 rv = soc_async_msg_queue(_async_sbusdma_reg[unit].handle, msg);
    338                 if (rv == SOC_E_NONE) {
    339                     break;
    340                 }
    341             } while(!soc_timeout_check(&to));
    342 
    343             if (SOC_FAILURE(rv)) {
    344                 (void)_soc_async_sbusdma_msg_free(unit, msg);
    345             }
    346         }
    347 
    348     } else {
    349         if (_async_sbusdma_reg[unit].drv.soc_mem_sbusdma_clear != NULL) {
    350             rv = _async_sbusdma_reg[unit].drv.soc_mem_sbusdma_clear(unit,
    351                                                       param);
    352         }  else {
    353             rv = SOC_E_INIT;
    354         }
    355     }
    356 
    357     return rv;
    358 }
    359 
    360 /*******************************************
    361 * @function soc_async_mem_sbusdma_clear
    362 * This function calls 'soc_mem_sbusdma_async_clear_specific'
    363 * This calls 'soc_async_mem_sbusdma_clear_specific'
    364 *
    365 * @param unit [in] unit #
    366 * @param param [in] soc_sbusdma_reg_param_t pointer
    367 * @param cbf [out] soc_async_cb_f, call back function pointer
    368 *
    369 * @returns SOC_E_BUSY
    370 * @returns SOC_E_NONE
    371 *
    372 * @end
    373  */
    374 int
    375 soc_async_mem_sbusdma_clear(int unit,
    376         soc_sbusdma_reg_param_t *param, soc_async_cb_f   cbf)
    377 {
    378 
    379     param->array_id_start = 0;
    380     param->array_id_end = UINT_MAX;
    381     param->index_begin = INT_MIN;
    382     param->index_end = INT_MAX;
    383 
    384     return soc_async_mem_sbusdma_clear_specific(unit, param, cbf);
    385 }
    386 
    387 /*******************************************
    388 * @function soc_async_sbusdma_ch_try_get
    389 * purpose get idle channel on cmc
    390 *
    391 * @param unit [in] unit #
    392 * @param cmc [out] cmc number 0-1
    393 * @param ch [out] channel number 0-2
    394 *
    395 * @returns SOC_E_BUSY
    396 * @returns SOC_E_NONE
    397 *
    398 * @end
    399  */
    400 int soc_async_sbusdma_ch_try_get(int unit, int cmc, int ch)
    401 {
    402     int rv = SOC_E_NONE;
    403 
    404     if (_async_sbusdma_reg[unit].ch.soc_sbusdma_ch_try_get != NULL) {
    405         rv =
    406          _async_sbusdma_reg[unit].ch.soc_sbusdma_ch_try_get(unit, cmc, ch);
    407     } else {
    408         rv = SOC_E_INIT;
    409     }
    410 
    411     return rv;
    412 }
    413 
    414 /*******************************************
    415 * @function soc_async_sbusdma_ch_put
    416 * purpose put back the freed channel on cmc
    417 *
    418 * @param cmc [in] cmc number
    419 * @param ch [in] channel number
    420 *
    421 * @returns SOC_E_PARAM
    422 * @returns SOC_E_NONE
    423 *
    424 * @end
    425  */
    426 int soc_async_sbusdma_ch_put(int unit, int cmc, int ch)
    427 {
    428    int rv;
    429 
    430    if (_async_sbusdma_reg[unit].ch.soc_sbusdma_ch_put != NULL) {
    431         rv =
    432          _async_sbusdma_reg[unit].ch.soc_sbusdma_ch_put(unit, cmc, ch);
    433    } else {
    434        rv = SOC_E_INIT;
    435    }
    436 
    437    return rv;
    438 }
    439 /*******************************************
    440 * @function soc_async_sbusdma_deinit
    441 * purpose API to DeInitialize ASYNC SBUS DMA
    442 *
    443 * @param unit [in] unit
    444 *
    445 * @returns SOC_E_NONE
    446 * @returns SOC_E_XXX
    447 *
    448 * @end
    449  */
    450 int
    451 soc_async_sbusdma_deinit(int unit)
    452 {
    453 #ifdef BCM_CMICX_SUPPORT
    454    if (soc_feature(unit, soc_feature_cmicx)) {
    455        (void)cmicx_sbusdma_ch_deinit(unit);
    456 
    457        if (_async_sbusdma_reg[unit].handle) {
    458            (void)soc_async_proc_deinit(_async_sbusdma_reg[unit].handle);
    459            _async_sbusdma_reg[unit].handle = NULL;
    460        }
    461 
    462    }
    463 #endif
    464    return SOC_E_NONE;
    465 }
    466 
    467 /*******************************************
    468 * @function soc_async_sbusdma_init
    469 * purpose API to Initialize ASYNC SBUS DMA
    470 *
    471 * @param unit [in] unit
    472 * @param prop [in] soc_async_prop_t pointer
    473 *
    474 * @returns SOC_E_NONE
    475 * @returns SOC_E_XXX
    476 *
    477 * @end
    478  */
    479 int
    480 soc_async_sbusdma_init(int unit, soc_async_prop_t  *prop)
    481 {
    482     int rv = SOC_E_NONE;
    483 
    484 #ifdef BCM_CMICX_SUPPORT
    485     if (soc_feature(unit, soc_feature_cmicx)) {
    486         SOC_IF_ERROR_RETURN(cmicx_sbusdma_reg_init(unit,
    487             &_async_sbusdma_reg[unit].drv));
    488 
    489         SOC_IF_ERROR_RETURN(cmicx_sbusdma_ch_init(unit,
    490             CMIC_CMCx_SBUSDMA_CHSELECT_TIMEOUT,
    491             &_async_sbusdma_reg[unit].ch));
    492 
    493         SOC_IF_ERROR_RETURN(cmicx_sbusdma_intr_init(unit));
    494     }
    495 
    496     rv = soc_async_proc_init(
    497                   unit,
    498                   prop,
    499                   &_async_sbusdma_reg[unit].handle);
    500 
    501     if (rv != SOC_E_NONE) {
    502         LOG_ERROR(BSL_LS_SOC_DMA,
    503               (BSL_META_U(unit,
    504                  "Failed to initialize Async Proc =%d\n"), rv));
    505         (void)soc_async_sbusdma_deinit(unit);
    506         return rv;
    507     }
    508     LOG_VERBOSE(BSL_LS_SOC_DMA,
    509               (BSL_META_U(unit,":SUCCESS\n")));
    510 #endif
    511     return rv;
    512 }
    513 
    514 #endif /* defined(BCM_SBUSDMA_SUPPORT) && defined(BCM_SOC_ASYNC_SUPPORT)  */
    515