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

rx.c (10340B)


      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:        rx.c
      8  * Purpose:     BCMX RX API implementation
      9  * Requires:
     10  */
     11 
     12 #include <shared/bsl.h>
     13 
     14 #include <shared/alloc.h>
     15 #include <sal/core/libc.h>
     16 #include <bcm/pkt.h>
     17 #include <bcm/rx.h>
     18 #include <bcm/error.h>
     19 
     20 
     21 #include <bcm_int/control.h>
     22 #include <bcm_int/common/rx.h>
     23 
     24 #include <bcmx/rx.h>
     25 #include <bcmx/bcmx.h>
     26 
     27 #include "bcmx_int.h"
     28 
     29 #define BCMX_RX_INIT_CHECK    BCMX_READY_CHECK
     30 
     31 #define BCMX_RX_SET_ERROR_CHECK(_unit, _check, _rv)    \
     32     BCMX_SET_ERROR_CHECK(_unit, _check, _rv)
     33 
     34 #define BCMX_RX_DELETE_ERROR_CHECK(_unit, _check, _rv)    \
     35     BCMX_DELETE_ERROR_CHECK(_unit, _check, _rv)
     36 
     37 #define BCMX_RX_GET_IS_VALID(_unit, _rv)    \
     38     BCMX_ERROR_IS_VALID(_unit, _rv)
     39 
     40 
     41 /* Exposed to BCMX internals */
     42 
     43 int _bcmx_rx_running = FALSE;
     44 
     45 static rx_callout_t *bcmx_rco;
     46 
     47 
     48 /*
     49  * Function:
     50  *      bcmx_rx_running
     51  * Purpose:
     52  *      Return status of whether BCMX RX is running
     53  * Returns:
     54  *      TRUE if BCMX RX is running
     55  * Notes:
     56  *      The _bcmx_rx_running variable is exported and visible.  That
     57  *      can be checked as easily.
     58  */
     59 
     60 int
     61 bcmx_rx_running(void) {
     62     return _bcmx_rx_running;
     63 }
     64 
     65 static INLINE rx_callout_t *
     66 bcmx_rco_find(bcm_rx_cb_f fn, int priority, rx_callout_t **prev)
     67 {
     68     rx_callout_t *rco = bcmx_rco;
     69 
     70     *prev = NULL;
     71     while (rco != NULL) {
     72         if (rco->rco_function == fn && rco->rco_priority == priority) {
     73             return rco;
     74         }
     75         if (rco->rco_priority < priority) {
     76             return NULL;
     77         }
     78         *prev = rco;
     79         rco = (rx_callout_t *)rco->rco_next;
     80     }
     81 
     82     return NULL;
     83 }
     84 
     85 
     86 /*
     87  * Function:
     88  *      bcmx_rx_register
     89  * Purpose:
     90  *      Register with all BCM units to receive packets
     91  * Parameters:
     92  *      name         - char string identifier of callout
     93  *      fn           - Callout function
     94  *      priority     - Of callout
     95  *      cookie       - Passed on callback
     96  *      flags        - See BCM_RCO_F_...
     97  * Returns:
     98  *      BCM_E_XXX
     99  * Notes:
    100  *      Handlers registering in interrupt context will not receive
    101  *      tunnelled packets.
    102  *
    103  *      The callback is registered with each available unit.
    104  *
    105  *      The callbacks have to be maintained locally since addition/
    106  *      removal of units results in making subsequent BCM layer
    107  *      register/unregister calls.
    108  */
    109 
    110 int
    111 bcmx_rx_register(const char *name,
    112                  bcm_rx_cb_f fn,
    113                  int priority,
    114                  void *cookie,
    115                  uint32 flags)
    116 {
    117     int unit, i;
    118     int rv = BCM_E_NONE, tmp_rv;
    119     rx_callout_t *rco, *prev, *next;
    120 
    121     BCMX_RX_INIT_CHECK;
    122 
    123 #if defined(BROADCOM_DEBUG)
    124     if (flags & BCM_RCO_F_INTR) {
    125         LOG_WARN(BSL_LS_BCMX_COMMON,
    126                  (BSL_META("BCMX RX: Intr RX handler will "
    127                            "not receive tunnelled pkts: %s\n"),
    128                   name));
    129     }
    130 #endif  /* BROADCOM_DEBUG */
    131 
    132     BCMX_CONFIG_LOCK;
    133     rco = bcmx_rco_find(fn, priority, &prev);
    134     if (rco != NULL) {
    135         BCMX_CONFIG_UNLOCK;
    136         return BCM_E_NONE;
    137     }
    138 
    139     rco = sal_alloc(sizeof(rx_callout_t), "bcmx_rx_reg");
    140     if (rco == NULL) {
    141         BCMX_CONFIG_UNLOCK;
    142         return BCM_E_MEMORY;
    143     }
    144 
    145     if (prev == NULL) {
    146         next = bcmx_rco;
    147         bcmx_rco = rco;
    148     } else {
    149         next = (rx_callout_t *)prev->rco_next;
    150         prev->rco_next = rco;
    151     }
    152     SETUP_RCO(rco, name, fn, priority, cookie, next, flags);
    153     for (i = 0; i < 16; i++) {
    154         if ((flags & BCM_RCO_F_COS_ACCEPT_MASK) & BCM_RCO_F_COS_ACCEPT(i)) {
    155             SETUP_RCO_COS_SET(rco, i);
    156         }
    157     }
    158     BCMX_CONFIG_UNLOCK;
    159 
    160     if (_bcmx_rx_running) {
    161         rv = BCM_E_UNAVAIL;
    162         BCMX_UNIT_ITER(unit, i) {
    163             tmp_rv = bcm_rx_register(unit, name, fn, priority, cookie, flags);
    164             BCM_IF_ERROR_RETURN(BCMX_RX_SET_ERROR_CHECK(unit, tmp_rv, &rv));
    165         }
    166     }
    167 
    168     return rv;
    169 }
    170 
    171 
    172 /*
    173  * Function:
    174  *      bcmx_rx_unregister
    175  * Purpose:
    176  *      Unregister the RX callback from all BCM units
    177  * Parameters:
    178  *      fn           - Callout function
    179  *      priority     - Of callout
    180  * Returns:
    181  *      BCM_E_XXX
    182  */
    183 
    184 int
    185 bcmx_rx_unregister(bcm_rx_cb_f fn, int priority)
    186 {
    187     int unit, i;
    188     int rv = BCM_E_UNAVAIL, tmp_rv;
    189     rx_callout_t *rco, *prev;
    190 
    191     BCMX_RX_INIT_CHECK;
    192 
    193     BCMX_CONFIG_LOCK;
    194     rco = bcmx_rco_find(fn, priority, &prev);
    195     if (rco == NULL) {
    196         BCMX_CONFIG_UNLOCK;
    197         return BCM_E_NONE;
    198     }
    199 
    200     if (prev == NULL) {
    201         bcmx_rco = (rx_callout_t *)rco->rco_next;
    202     } else {
    203         prev->rco_next = rco->rco_next;
    204     }
    205 
    206     sal_free(rco);
    207     BCMX_CONFIG_UNLOCK;
    208 
    209     /* Now take care of any known remote units */
    210     BCMX_UNIT_ITER(unit, i) {
    211         tmp_rv = bcm_rx_unregister(unit, fn, priority);
    212         BCM_IF_ERROR_RETURN(BCMX_RX_DELETE_ERROR_CHECK(unit, tmp_rv, &rv));
    213     }
    214 
    215     return rv;
    216 }
    217 
    218 
    219 
    220 /*
    221  * Function:
    222  *      bcmx_rx_start
    223  * Purpose:
    224  *      Start BCMX RX packet handling
    225  * Returns:
    226  *      BCM_E_XXX
    227  * Notes:
    228  *      Calls "add" on all the current units.
    229  */
    230 
    231 int
    232 bcmx_rx_start(void)
    233 {
    234     int unit, i;
    235     int rv = BCM_E_UNAVAIL, tmp_rv;
    236 
    237     BCMX_RX_INIT_CHECK;
    238 
    239     if (_bcmx_rx_running) {
    240         return BCM_E_NONE;
    241     }
    242 
    243     _bcmx_rx_running = TRUE;
    244 
    245     BCMX_UNIT_ITER(unit, i) {
    246         tmp_rv = bcmx_rx_device_add(unit);
    247         if (BCM_FAILURE(BCMX_RX_SET_ERROR_CHECK(unit, tmp_rv, &rv))) {
    248             LOG_WARN(BSL_LS_BCMX_COMMON,
    249                      (BSL_META_U(unit,
    250                                  "BCMX RX: Unit %d add failed: %s\n"),
    251                       unit, bcm_errmsg(tmp_rv)));
    252             break;
    253         }
    254     }
    255 
    256     return rv;
    257 }
    258 
    259 
    260 
    261 /*
    262  * Function:
    263  *      bcmx_rx_stop
    264  * Purpose:
    265  *      Stop BCMX RX packet handling
    266  * Returns:
    267  *      BCM_E_XXX
    268  */
    269 
    270 int
    271 bcmx_rx_stop(void)
    272 {
    273     int unit, i;
    274     int rv = BCM_E_UNAVAIL, tmp_rv;
    275 
    276     BCMX_RX_INIT_CHECK;
    277 
    278     if (!_bcmx_rx_running) {
    279         return BCM_E_NONE;
    280     }
    281 
    282     _bcmx_rx_running = FALSE;
    283 
    284     BCMX_UNIT_ITER(unit, i) {
    285         tmp_rv = bcmx_rx_device_remove(unit);
    286         if (BCM_FAILURE(BCMX_RX_DELETE_ERROR_CHECK(unit, tmp_rv, &rv))) {
    287             LOG_WARN(BSL_LS_BCMX_COMMON,
    288                      (BSL_META_U(unit,
    289                                  "BCMX RX: Unit %d remove failed: %s\n"),
    290                       unit, bcm_errmsg(tmp_rv)));
    291             break;
    292         }
    293     }
    294 
    295     return rv;
    296 }
    297 
    298 
    299 /*
    300  * Function:
    301  *      bcmx_rx_unit_add
    302  * Purpose:
    303  *      Add a BCM unit to BCMX RX registration.
    304  * Parameters:
    305  *      unit         - The unit to add
    306  * Returns:
    307  *      BCM_E_XXX
    308  * Notes:
    309  *      May be called when a new BCM unit is added
    310  */
    311 
    312 int
    313 bcmx_rx_device_add(int unit)
    314 {
    315     rx_callout_t *rco = bcmx_rco;
    316     int rv = BCM_E_NONE, tmp_rv;
    317 
    318     BCMX_RX_INIT_CHECK;
    319 
    320     if (!BCM_UNIT_VALID(unit)) {
    321         return BCM_E_PARAM;
    322     }
    323 
    324     if (_bcmx_rx_running) {
    325         rv = BCM_E_UNAVAIL;
    326         while (rco != NULL) {
    327             tmp_rv = bcm_rx_register(unit,
    328                                      rco->rco_name,
    329                                      rco->rco_function,
    330                                      rco->rco_priority,
    331                                      rco->rco_cookie,
    332                                      rco->rco_flags);
    333             if (BCM_FAILURE(BCMX_RX_SET_ERROR_CHECK(unit, tmp_rv, &rv))) {
    334                 LOG_WARN(BSL_LS_BCMX_COMMON,
    335                          (BSL_META_U(unit,
    336                                      "BCMX RX: Unit %d register failed: %s\n"),
    337                           unit, bcm_errmsg(tmp_rv)));
    338             }
    339             rco = (rx_callout_t *)rco->rco_next;
    340         }
    341 
    342         /* Start RX */
    343         tmp_rv = bcm_rx_start(unit, NULL);
    344         if (tmp_rv == BCM_E_BUSY) {
    345             tmp_rv = BCM_E_NONE;
    346         }
    347         (void) BCMX_RX_SET_ERROR_CHECK(unit, tmp_rv, &rv);
    348     }
    349 
    350     return rv;
    351 }
    352 
    353 
    354 /*
    355  * Function:
    356  *      bcmx_rx_unit_remove
    357  * Purpose:
    358  *      Remove a BCM unit to BCMX RX registration.
    359  * Parameters:
    360  *      unit         - The unit to add
    361  * Returns:
    362  *      BCM_E_XXX
    363  * Notes:
    364  *      May be called when a BCM unit is removed
    365  */
    366 
    367 int
    368 bcmx_rx_device_remove(int unit)
    369 {
    370     rx_callout_t *rco = bcmx_rco;
    371     int rv = BCM_E_NONE, tmp_rv;
    372 
    373     BCMX_RX_INIT_CHECK;
    374 
    375     if (!BCM_UNIT_VALID(unit)) {
    376         return BCM_E_PARAM;
    377     }
    378 
    379     while (rco != NULL) {
    380         tmp_rv = bcm_rx_unregister(unit,
    381                                    rco->rco_function,
    382                                    rco->rco_priority);
    383         if (BCM_FAILURE(BCMX_RX_DELETE_ERROR_CHECK(unit, tmp_rv, &rv))) {
    384             LOG_WARN(BSL_LS_BCMX_COMMON,
    385                      (BSL_META_U(unit,
    386                                  "BCMX RX: Unit %d unregister failed: %s\n"),
    387                       unit, bcm_errmsg(tmp_rv)));
    388         }
    389 
    390         rco = (rx_callout_t *)rco->rco_next;
    391     }
    392 
    393     return rv;
    394 }
    395 
    396 /*
    397  * Function:
    398  *      bcmx_rx_control_set(bcm_rx_control_t type, int value)
    399  * Description:
    400  *      Enable/Disable specified RX feature.
    401  * Parameters:
    402  *      type - RX control parameter
    403  *      value - new value of control parameter
    404  * Return Value:
    405  *      BCM_E_NONE
    406  *      BCM_E_UNAVAIL - Functionality not available
    407  */
    408 
    409 int
    410 bcmx_rx_control_set(bcm_rx_control_t type, int arg)
    411 {
    412     int rv = BCM_E_UNAVAIL, tmp_rv;
    413     int i, bcm_unit;
    414 
    415     BCMX_RX_INIT_CHECK;
    416 
    417     BCMX_UNIT_ITER(bcm_unit, i) {
    418         tmp_rv = bcm_rx_control_set(bcm_unit, type, arg);
    419         BCM_IF_ERROR_RETURN(BCMX_RX_SET_ERROR_CHECK(bcm_unit, tmp_rv, &rv));
    420     }
    421 
    422     return rv;
    423 }
    424 
    425 /*
    426  * Function:
    427  *      bcmx_rx_control_get(bcm_rx_control_t type, int *value)
    428  * Description:
    429  *      Get the status of specified RX feature.
    430  * Parameters:
    431  *      type - RX control parameter
    432  *      value - (OUT) Current value of control parameter
    433  * Return Value:
    434  *      BCM_E_NONE
    435  *      BCM_E_UNAVAIL - Functionality not available
    436  */
    437 
    438 int
    439 bcmx_rx_control_get(bcm_rx_control_t type, int *arg)
    440 {
    441     int rv;
    442     int i, bcm_unit;
    443 
    444     BCMX_RX_INIT_CHECK;
    445 
    446     BCMX_PARAM_NULL_CHECK(arg);
    447 
    448     BCMX_UNIT_ITER(bcm_unit, i) {
    449         rv = bcm_rx_control_get(bcm_unit, type, arg);
    450         if (BCMX_RX_GET_IS_VALID(bcm_unit, rv)) {
    451             return rv;
    452         }
    453     }
    454 
    455     return BCM_E_UNAVAIL;
    456 }
    457