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

meter.c (26424B)


      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: 	meter.c
      8  * Purpose: 	Firebolt placeholder for metering, FP metering.
      9  */
     10 
     11 #include <sal/types.h>
     12 #include <sal/core/libc.h>
     13 
     14 #include <shared/bitop.h>
     15 
     16 #include <soc/mem.h>
     17 #include <soc/debug.h>
     18 #include <soc/cm.h>
     19 #include <soc/counter.h>
     20 #include <soc/drv.h>
     21 #include <soc/register.h>
     22 #include <soc/memory.h>
     23 
     24 #include <bcm/error.h>
     25 
     26 #include <bcm_int/esw/mbcm.h>
     27 #include <bcm_int/esw/firebolt.h>
     28 
     29 
     30 #define FB_NUM_BUCKET_SIZES       16
     31 #define FB_NUM_VALID_BUCKET_SIZES 14
     32 
     33 /* For Firebolt, every token in the bucket is worth one bit. */
     34 /* For metering purposes, kbits means 1000 bits.             */
     35 static uint32 fb_bucket_settings[FB_NUM_BUCKET_SIZES] = {
     36   0,                /*  Disabled   */
     37   0x00008000/1000,  /*  32K tokens */
     38   0x00010000/1000,  /*  64K tokens */
     39   0x00020000/1000,  /* 128K tokens */
     40   0x00040000/1000,  /* 256K tokens */
     41   0x00080000/1000,  /* 512K tokens */
     42   0x00100000/1000,  /*   1M tokens */
     43   0x00200000/1000,  /*   2M tokens */
     44   0x00400000/1000,  /*   4M tokens */
     45   0x00800000/1000,  /*   8M tokens */
     46   0x01000000/1000,  /*  16M tokens */
     47   0x02000000/1000,  /*  32M tokens */
     48   0x04000000/1000,  /*  64M tokens */
     49   0x08000000/1000,  /* 128M tokens */
     50   0,                /*     N/A     */
     51   0                 /*     N/A     */
     52 };
     53 
     54 /*
     55  * Function:
     56  *	_bcm_fb_kbits_to_bucketsize
     57  * Description:
     58  *      Routine that converts desired burst size into Firebolt style
     59  *      leaky bucketsize register value.
     60  * Parameters:
     61  *      kbits_burst - Desired size of maximum burst traffic
     62  * Returns:
     63  *	Register bits for BUCKETSIZEf field. 
     64  * Notes:
     65  *	None.
     66  */
     67 
     68 uint8
     69 _bcm_fb_kbits_to_bucketsize(uint32 kbits_burst)
     70 {
     71     uint8 i;
     72     for (i=0; i< FB_NUM_VALID_BUCKET_SIZES; i++) {
     73         if (kbits_burst <= fb_bucket_settings[i])
     74 	    break; 
     75     }
     76     if (i == FB_NUM_VALID_BUCKET_SIZES)
     77         i--;
     78     return i;
     79 }
     80 
     81 /*
     82  * Function:
     83  *	_bcm_fb_bucketsize_to_kbits
     84  * Description:
     85  *      Routine that converts Firebolt style leaky bucketsize 
     86  *      register value into its associated burst size.
     87  * Parameters:
     88  *      reg_val - BUCKETSIZEf field value
     89  * Returns:
     90  *	Max size burst traffic in kbits. 
     91  * Notes:
     92  *	None.
     93  */
     94 
     95 uint32
     96 _bcm_fb_bucketsize_to_kbits(uint8 reg_val)
     97 {
     98     return fb_bucket_settings[reg_val & 0x0F];
     99 }
    100 
    101 #if defined (BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) || \
    102     defined (BCM_TRX_SUPPORT)
    103 #define FB2_NUM_BUCKET_RANGES           16
    104 #define FB2_BUCKET_MIN_BITS             (4 * 1024 * 8) /* 4K bytes */
    105 #define FB2_BUCKET_SEGMENT_GRANULARITY  256
    106 #define FB2_BUCKET_SEGMENT_MASK         0xff
    107 #define FB2_BUCKET_POWER_SHIFT          8
    108 #define FB2_BUCKET_POWER_MASK           0xf
    109 #define FB2_BUCKET_ENCODED_MAX          0xfff
    110 
    111 /*
    112  * Function:
    113  *	_bcm_fb2_kbits_to_bucketsize
    114  * Description:
    115  *      Routine that converts desired burst size into Firebolt2 style
    116  *      leaky bucketsize register value.
    117  * Parameters:
    118  *      kbits_burst - Desired size of maximum burst traffic
    119  * Returns:
    120  *	Register bits for BUCKETSIZEf field. 
    121  * Notes:
    122  *	None.
    123  */
    124 
    125 uint32
    126 _bcm_fb2_kbits_to_bucket_encoding(uint32 kbits_burst, int linear_mode)
    127 {
    128     uint32 i;
    129     uint32 bits, encoding, bucketsize, bucket_segment_size;
    130 
    131     if (linear_mode) {
    132         encoding = (((kbits_burst * 1000) + (FB2_BUCKET_MIN_BITS - 1)) /
    133                 FB2_BUCKET_MIN_BITS);
    134         if (encoding > FB2_BUCKET_ENCODED_MAX) {
    135             encoding = FB2_BUCKET_ENCODED_MAX;
    136         }
    137         return encoding;
    138     } else {
    139         encoding = kbits_burst ? 1 : 0; /* 0 kbits means disable */
    140         bucketsize = FB2_BUCKET_MIN_BITS;
    141         bits = kbits_burst * 1000;
    142 
    143         for (i=0; i<= FB2_NUM_BUCKET_RANGES; i++, bucketsize *= 2) {
    144             if (bits <= bucketsize) {
    145                 if (i > 0) {
    146                     bucket_segment_size =
    147                         (1 << (i - 1)) * FB2_BUCKET_MIN_BITS /
    148                         FB2_BUCKET_SEGMENT_GRANULARITY;
    149                     encoding =
    150                         (bits - (bucketsize / 2) +
    151                          (bucket_segment_size - 1)) / bucket_segment_size;
    152                     encoding |= (i - 1) << FB2_BUCKET_POWER_SHIFT;
    153                 }
    154                 break;
    155             }
    156         }
    157 
    158         return (i < FB2_NUM_BUCKET_RANGES) ? encoding :
    159             FB2_BUCKET_ENCODED_MAX;
    160     }
    161 }
    162 
    163 /*
    164  * Function:
    165  *	_bcm_fb2_bucketsize_to_kbits
    166  * Description:
    167  *      Routine that converts Firebolt2 style leaky bucketsize 
    168  *      register value into its associated burst size.
    169  * Parameters:
    170  *      reg_val - BUCKETSIZEf field value
    171  * Returns:
    172  *	Max size burst traffic in kbits. 
    173  * Notes:
    174  *	None.
    175  */
    176 
    177 uint32
    178 _bcm_fb2_bucket_encoding_to_kbits(uint32 reg_val, int linear_mode)
    179 {
    180     uint32 power, segment, bucketsize;
    181 
    182     if (linear_mode) {
    183         return ((reg_val * FB2_BUCKET_MIN_BITS) / 1000);
    184     } else {
    185         segment = reg_val & FB2_BUCKET_SEGMENT_MASK;
    186         power = (reg_val >> FB2_BUCKET_POWER_SHIFT) & FB2_BUCKET_POWER_MASK;
    187 
    188         /* Calculate raw bits */
    189         bucketsize = (1 << power) *
    190             (FB2_BUCKET_MIN_BITS / FB2_BUCKET_SEGMENT_GRANULARITY) *
    191             (FB2_BUCKET_SEGMENT_GRANULARITY + segment);
    192 
    193     
    194         /* bits to kbits */
    195         return (bucketsize + (1000 - 1)) / 1000;
    196     }
    197 }
    198 
    199 #define METER_GRANULARITY_DEFAULT       3
    200 #define METER_GRANULARITY_NUM           8
    201 #define METER_KBITS_SEC_QUANTUM_MIN     8       /* 8000 bits/second */
    202 #define METER_BITS_BURST_MIN           (1024 * 8 / 2) /* 1/2 Kbytes */
    203 #define METER_PACKET_SEC_QUANTUM_MIN    1
    204 #define METER_PACKET_MAX_GRAN_FP_EXTRA_MULTIPLE   4 /* 2 extra steps */
    205 #define METER_PACKET_MAX_GRAN_MMU_EXTRA_MULTIPLE  2 /* 1 extra step */
    206 #define METER_PACKET_BURST_MIN          512     /* 0.512 packet, use 1000x */
    207 #define METER_PACKET_BURST_DIVISOR      1000    /* use 1000x for calculation */
    208 #define METER_NL_SEGMENT_GRANULARITY    256
    209 #define METER_NL_BUCKET_POWER_SHIFT     8
    210 #define METER_NL_BUCKET_RANGE_NUM       16
    211 #define METER_NL_BUCKET_SEGMENT_MASK    0xff
    212 #define METER_NL_BUCKET_POWER_MASK      0xf
    213 #define METER_NL_BUCKET_MAC_ENCODE_MAX  0xff80
    214 
    215 STATIC void
    216 _bcm_xgs_granularity_params(int granularity, uint32 flags,
    217                              uint32 *rate_quantum, uint32 *burst_quantum)
    218 {
    219     int ix;
    220     uint32 gran_multiple = 1;
    221 
    222     for (ix = 0; ix < granularity; ix++) {
    223         gran_multiple *= 2;
    224     }
    225 
    226     if (flags & _BCM_XGS_METER_FLAG_PACKET_MODE) {
    227         if (granularity == (METER_GRANULARITY_NUM - 1)) {
    228             if (flags &_BCM_XGS_METER_FLAG_FP_POLICER) {
    229                 if (!(flags & _BCM_XGS_METER_FLAG_FP_TD2_POLICER)) {
    230                    gran_multiple *= METER_PACKET_MAX_GRAN_FP_EXTRA_MULTIPLE;
    231                 }
    232             } else {
    233                 gran_multiple *= METER_PACKET_MAX_GRAN_MMU_EXTRA_MULTIPLE;
    234             }
    235         }
    236         if ((flags & _BCM_XGS_METER_FLAG_FP_TD2_POLICER)
    237              && (flags & _BCM_XGS_METER_FLAG_FP_POLICER)) {
    238             if ((granularity >= 5)  && (granularity <=7)) {
    239                 for (ix = 0; ix <= (granularity - 5); ix++) {
    240                      gran_multiple = gran_multiple * 2;
    241                 }
    242             }
    243         }
    244         *rate_quantum = METER_PACKET_SEC_QUANTUM_MIN * gran_multiple;
    245         *burst_quantum = METER_PACKET_BURST_MIN * gran_multiple;
    246 
    247     } else {
    248         *rate_quantum = METER_KBITS_SEC_QUANTUM_MIN * gran_multiple;
    249         *burst_quantum = METER_BITS_BURST_MIN * gran_multiple;
    250     }
    251 
    252     /*
    253      * On device with double refresh frequency (double the number of refresh
    254      * per second), granularity is half for burst and (per refresh) rate.
    255      */
    256     if (flags & _BCM_XGS_METER_FLAG_DOUBLE_REFRESH_FREQ) {
    257         *burst_quantum /= 2;
    258     }
    259 
    260     if (flags & _BCM_XGS_METER_FLAG_BUCKET_IN_8KB) { 
    261         if (granularity == 5) {
    262             *burst_quantum /= 2;
    263         }
    264     }
    265     /* With Refresh rate of 15.625us,
    266      * Minimum Quantum (g=0) | Byte Mode |   Pkt Mode |
    267      *   Rate                |  4 kbps   |    0.5 pps |
    268      *   Burst               | 512 bytes | 0.512 pkts |
    269      * So, calculated rate and burst quantum needs to be adjusted
    270      */
    271     if (flags & _BCM_XGS_METER_FLAG_REFRESH_RATE_15p625) {
    272         *rate_quantum /= 2;
    273         *burst_quantum /= 8;
    274     }
    275 }
    276 
    277 /*
    278  * Function:
    279  *	_bcm_xgs_kbits_to_bucket_encoding
    280  * Description:
    281  *      Routine that converts desired burst size into Firebolt2 style
    282  *      leaky bucketsize register value.
    283  * Parameters:
    284  *      kbits_sec - Desired rate of ongoing traffic
    285  *      kbits_burst - Desired size of maximum burst traffic
    286  *      flags - paramters indicating capabilities and configuration of meter
    287  *      refresh_bitsize - number of bits for the refresh rate field
    288  *      bucket_max_bitsize - number of bits for the bucket max field
    289  *      refresh_rate - (OUT) calculated value for the refresh rate field
    290  *      bucket_max - (OUT) calculated value for the bucket max field
    291  *      granularity - (OUT) calculated value for the granularity field
    292  * Returns:
    293  *	BCM_E_*
    294  * Notes:
    295  *
    296  * bandwidth-shaping mode
    297  * gran  refresh      refresh            bucket-size-granularity
    298  *       byte/refresh kbit/second        bits
    299  *                     min <-> max         base <-> max
    300  *                                                  (linear)   / (ITU mode)
    301  * 0     1/128           8 <-> 0x1ffff8    4096 <-> 0xfff000   / 0xff80000
    302  * 1     1/64           16 <-> 0x3ffff0    8192 <-> 0x1ffe000  / 0x1ff00000
    303  * 2     1/32           32 <-> 0x7fffe0   16384 <-> 0x3ffc000  / 0x3fe00000
    304  * 3     1/16           64 <-> 0xffffc0   32768 <-> 0x7ff8000  / 0x7fc00000
    305  * 4     1/8           128 <-> 0x1ffff80  65536 <-> 0xfff0000  / 0xff800000
    306  * 5     1/4           256 <-> 0x3ffff00 131072 <-> 0x1ffe0000 / 0x1ff000000
    307  * 6     1/2           512 <-> 0x7fffe00 262144 <-> 0x3ffc0000 / 0x3fe000000
    308  * 7     1            1024 <-> 0xffffc00 524288 <-> 0x7ff80000 / 0x7fc000000
    309  * (max value is based on 18-bit refresh setting and 12-bit burst setting)
    310  *
    311  * packet-shaping mode (for mmu)
    312  * gran  refresh        refresh           bucket-size-granularity
    313  *       packet/refresh packet/second     packet
    314  *                      min <-> max          base <-> max
    315  *                                                    (linear) / (ITU mode)
    316  * 0     1/128000         1 <-> 0x3ffff     0.512 <-> 0x830    / 0x82d0
    317  * 1     1/64000          2 <-> 0x7fffe     1.024 <-> 0x1061   / 0x105a1
    318  * 2     1/32000          4 <-> 0xffffc     2.048 <-> 0x20c2   / 0x20b43
    319  * 3     1/16000          8 <-> 0x1ffff8    4.096 <-> 0x4185   / 0x41687
    320  * 4     1/8000          16 <-> 0x3ffff0    8.192 <-> 0x830a   / 0x82d0e
    321  * 5     1/4000          32 <-> 0x7fffe0   16.384 <-> 0x10614  / 0x105a1c
    322  * 6     1/2000          64 <-> 0xffffc0   32.768 <-> 0x20c28  / 0x20b439
    323  * 7     1/500          256 <-> 0x3ffff00 131.072 <-> 0x830a3  / 0x82d0e5
    324  *
    325  * packet-shaping mode (for fp)
    326  * gran  refresh        refresh           bucket-size-granularity
    327  *       packet/refresh packet/second     packet
    328  *                      min <-> max          base <-> max
    329  *                                                    (linear) / (ITU mode)
    330  * 0     1/128000         1 <-> 0x7ffff     0.512 <-> 0x830    / 0x82d0
    331  * 1     1/64000          2 <-> 0xffffe     1.024 <-> 0x1061   / 0x105a1
    332  * 2     1/32000          4 <-> 0x1ffffc    2.048 <-> 0x20c2   / 0x20b43
    333  * 3     1/16000          8 <-> 0x3ffff8    4.096 <-> 0x4185   / 0x41687
    334  * 4     1/8000          16 <-> 0x7ffff0    8.192 <-> 0x830a   / 0x82d0e
    335  * 5     1/4000          32 <-> 0xffffe0   16.384 <-> 0x10614  / 0x105a1c
    336  * 6     1/2000          64 <-> 0x1ffffc0  32.768 <-> 0x20c28  / 0x20b439
    337  * 7     1/250          512 <-> 0xffffe00 262.144 <-> 0x106147 / 0x105a1ca
    338  */
    339 
    340 int
    341 _bcm_xgs_kbits_to_bucket_encoding(uint32 kbits_sec, uint32 kbits_burst,
    342                                   uint32 flags,
    343                                   int refresh_bitsize,
    344                                   int bucket_max_bitsize,
    345                                   uint32 *refresh_rate, uint32 *bucketsize,
    346                                   uint32 *granularity)
    347 {
    348     int gran, gran_min, gran_max;
    349     uint32 i;
    350     uint32 burst, encoding, buckettop, bucket_segment_size;
    351     uint32 refresh_mask = 0;
    352     uint32 bucket_mask = 0;
    353     uint32 refresh_max = 0; 
    354     uint32 bucket_max = 0;
    355     uint32 rate_quantum = 0;
    356     uint32 burst_quantum = 0;
    357     uint32 gran_select = 0;
    358 
    359     if ((refresh_rate == NULL) || (bucketsize == NULL)) {
    360         return BCM_E_INTERNAL;
    361     }
    362 
    363     if ((kbits_burst == 0) &&
    364         (!(flags & _BCM_XGS_METER_FLAG_FP_POLICER) && (kbits_sec == 0))) {
    365         /* Disabled */
    366         *refresh_rate = 0;
    367         *bucketsize = 0;
    368         *granularity = METER_GRANULARITY_DEFAULT;
    369         return BCM_E_NONE;
    370     }
    371 
    372     refresh_mask = 0xffffffff >> (32 - refresh_bitsize);
    373     bucket_mask = 0xffffffff >> (32 - bucket_max_bitsize);
    374     if (flags & _BCM_XGS_METER_FLAG_PACKET_MODE) {
    375         /* Minimum packet burst is .512 packet.  We'll work in integers. */
    376         burst = kbits_burst * METER_PACKET_BURST_DIVISOR;
    377     } else {
    378         if (kbits_burst > (0xffffffff / 1000)) {
    379             burst = 0xffffffff;
    380         } else {
    381             burst = kbits_burst * 1000;
    382         }
    383     }
    384 
    385     if (flags & _BCM_XGS_METER_FLAG_GRANULARITY) {
    386         gran_min = 0;
    387         gran_max = METER_GRANULARITY_NUM - 1;
    388     } else if  (flags & _BCM_XGS_METER_FLAG_GRANULARITY_SELECTIVE) {
    389         gran_select = (flags & _BCM_XGS_METER_FLAG_GRANULARITY_SELECT_MASK);
    390         gran_select >>= _BCM_XGS_METER_FLAG_GRANULARITY_SELECT_SHIFT;
    391         
    392         gran_min = gran_max = -1;
    393         for (i = 0; i < METER_GRANULARITY_NUM; i++) {
    394             if ((gran_select & 0x1) && (gran_min < 0)) {
    395                 gran_min = i;
    396             }
    397             if (gran_select & 0x1) {
    398                 gran_max = i;
    399             }
    400             gran_select >>= 1;
    401         }
    402         
    403         /* Can't get min ang max gran, set to default */
    404         if ((gran_min < 0) || (gran_max < 0)) {
    405             gran_min = gran_max = METER_GRANULARITY_DEFAULT;
    406         }
    407     } else {
    408         gran_min = gran_max = METER_GRANULARITY_DEFAULT;
    409     }
    410 
    411     for (gran = gran_min; gran <= gran_max; gran++) {
    412         if	(flags & _BCM_XGS_METER_FLAG_GRANULARITY_SELECTIVE) {
    413             gran_select = (flags & _BCM_XGS_METER_FLAG_GRANULARITY_SELECT_MASK);
    414             gran_select >>= _BCM_XGS_METER_FLAG_GRANULARITY_SELECT_SHIFT;
    415             if (!((1 << gran) & gran_select)) {
    416                 continue;
    417             }
    418         }
    419 
    420         _bcm_xgs_granularity_params(gran, flags,
    421                                      &rate_quantum, &burst_quantum);
    422         refresh_max = refresh_mask * rate_quantum;
    423         if (flags & _BCM_XGS_METER_FLAG_NON_LINEAR) {
    424             bucket_max = METER_NL_BUCKET_MAC_ENCODE_MAX * burst_quantum;
    425         } else {
    426             bucket_max = bucket_mask * burst_quantum;
    427         }
    428 
    429         if ((kbits_sec <= refresh_max) && (burst <= bucket_max)) {
    430             break;
    431         }
    432     }
    433 
    434     if (gran > gran_max) {
    435         /* Saturate! */
    436         gran = gran_max;
    437         if (kbits_sec > refresh_max) {
    438             kbits_sec = refresh_max;
    439         }
    440         if (burst > bucket_max) {
    441             burst = bucket_max;
    442         }
    443     }
    444 
    445     *granularity = gran;
    446 
    447     if (kbits_sec > (0xffffffff - (rate_quantum - 1))) {
    448         kbits_sec = 0xffffffff - (rate_quantum - 1);
    449     }
    450 
    451     if (!rate_quantum) {
    452         /* avoid un-expected rate_quantum */
    453         return BCM_E_INTERNAL;
    454     }
    455 
    456     *refresh_rate = (kbits_sec + (rate_quantum - 1)) / rate_quantum;
    457     if (*refresh_rate > refresh_mask) {
    458         *refresh_rate = refresh_mask;
    459     }        
    460 
    461     if (flags & _BCM_XGS_METER_FLAG_NON_LINEAR) {
    462         if (burst <= burst_quantum) {
    463             *bucketsize = burst ? 1 : 0; /* 0 kbits means disable */
    464         } else {
    465             encoding = bucket_mask;
    466             buckettop = burst_quantum;
    467             for (i = 0; i < METER_NL_BUCKET_RANGE_NUM; i++, buckettop *= 2) {
    468                 bucket_segment_size =
    469                     buckettop / METER_NL_SEGMENT_GRANULARITY;
    470                 if (burst <= (buckettop * 2 - bucket_segment_size) ||
    471                     (buckettop == 0)) {
    472                     if (buckettop == 0) {
    473                         /* Saturate */
    474                         buckettop = 0xffffffff;
    475                     }
    476                     encoding =
    477                         (burst - buckettop + (bucket_segment_size - 1)) /
    478                         bucket_segment_size;
    479                     encoding |= i << METER_NL_BUCKET_POWER_SHIFT;
    480                     break;
    481                 }
    482             }
    483             *bucketsize = (i < METER_NL_BUCKET_RANGE_NUM) ? encoding :
    484                 bucket_mask;
    485         }
    486     } else {
    487         encoding = (burst + (burst_quantum - 1)) / burst_quantum;
    488         if (encoding > bucket_mask) {
    489             encoding = bucket_mask;
    490         }
    491         *bucketsize = encoding;
    492     }
    493     return BCM_E_NONE;
    494 }
    495 
    496 /*
    497  * Function:
    498  *	_bcm_xgs_bucket_encoding_to_kbits
    499  * Description:
    500  *      Routine that converts Firebolt2 style leaky bucketsize 
    501  *      register value into its associated burst size.
    502  * Parameters:
    503  *      refresh_rate - refresh rate field
    504  *      bucket_max - bucket max field
    505  *      granularity - granularity field
    506  *      flags - paramters indicating capabilities and configuration of meter
    507  *      kbits_sec - (OUT) Configured rate of ongoing traffic
    508  *      kbits_burst - (OUT) Configured size of maximum burst traffic
    509  * Returns:
    510  *	Max size burst traffic in kbits. 
    511  * Notes:
    512  *      None.
    513  */
    514 
    515 uint32
    516 _bcm_xgs_bucket_encoding_to_kbits(uint32 refresh_rate, uint32 bucket_max,
    517                                   uint32 granularity, uint32 flags,
    518                                   uint32 *kbits_sec, uint32 *kbits_burst)
    519 {
    520     int gran;
    521     uint32 power, segment, bucketsize;
    522     uint32 rate_quantum, burst_quantum;
    523 
    524     if ((kbits_sec == NULL) || (kbits_burst == NULL)) {
    525         return BCM_E_INTERNAL;
    526     }
    527 
    528     gran = (flags & _BCM_XGS_METER_FLAG_GRANULARITY) ? granularity :
    529         METER_GRANULARITY_DEFAULT;
    530     _bcm_xgs_granularity_params(gran, flags,
    531                                  &rate_quantum, &burst_quantum);
    532 
    533     *kbits_sec = refresh_rate * rate_quantum;
    534 
    535     if (flags & _BCM_XGS_METER_FLAG_NON_LINEAR) {
    536         if (bucket_max == 0) { /* 0 means disabled */
    537             bucketsize = 0;
    538         } else {
    539             segment = bucket_max & METER_NL_BUCKET_SEGMENT_MASK;
    540             power = (bucket_max >> METER_NL_BUCKET_POWER_SHIFT) &
    541                 METER_NL_BUCKET_POWER_MASK;
    542 
    543             /* Calculate raw bits */
    544             bucketsize = (1 << power) *
    545                 (burst_quantum / METER_NL_SEGMENT_GRANULARITY) *
    546                 (METER_NL_SEGMENT_GRANULARITY + segment);
    547         }
    548     } else {
    549         bucketsize = bucket_max * burst_quantum;
    550     }
    551 
    552     if (flags & _BCM_XGS_METER_FLAG_PACKET_MODE) {
    553         *kbits_burst = bucketsize / METER_PACKET_BURST_DIVISOR;
    554     } else {
    555         *kbits_burst = bucketsize / 1000;
    556     }
    557 
    558     return BCM_E_NONE;
    559 }
    560 
    561 /*
    562  * Function:
    563  *	_bcm_xgs_kbits_to_dual_bucket_encoding
    564  * Description:
    565  *      Routine that converts desired burst size into TRX style
    566  *      leaky bucketsize register value for dual token bucket policer.
    567  * Parameters:
    568  *      kbits_sec - Desired rate of ongoing traffic
    569  *      kbits_burst - Desired size of maximum burst traffic
    570  *      flags - paramters indicating capabilities and configuration of meter
    571  *      refresh_bitsize - number of bits for the refresh rate field
    572  *      bucket_max_bitsize - number of bits for the bucket max field
    573  *      granularity_start - granularity start value to be used for computation
    574  *      refresh_rate - (OUT) calculated value for the refresh rate field
    575  *      bucket_max - (OUT) calculated value for the bucket max field
    576  *      granularity - (OUT) calculated value for the granularity field
    577  * Returns:
    578  *	BCM_E_*
    579  */
    580 int
    581 _bcm_xgs_kbits_to_dual_bucket_encoding(uint32 kbits_sec, uint32 kbits_burst,
    582                                        uint32 flags,
    583                                        int refresh_bitsize,
    584                                        int bucket_max_bitsize,
    585                                        int granularity_start,
    586                                        uint32 *refresh_rate, uint32 *bucketsize,
    587                                        uint32 *granularity)
    588 {
    589     int gran, gran_min = 0, gran_max;
    590     uint32 burst, encoding;
    591     uint32 refresh_mask = 0;
    592     uint32 bucket_mask = 0;
    593     uint32 refresh_max = 0; 
    594     uint32 bucket_max = 0;
    595     uint32 rate_quantum = 0;
    596     uint32 burst_quantum = METER_PACKET_BURST_MIN;
    597 
    598     if ((refresh_rate == NULL) || (bucketsize == NULL)) {
    599         return BCM_E_INTERNAL;
    600     }
    601 
    602     if ((kbits_burst == 0) &&
    603         (!(flags & _BCM_XGS_METER_FLAG_FP_POLICER) && (kbits_sec == 0))) {
    604         /* Disabled */
    605         *refresh_rate = 0;
    606         *bucketsize = 0;
    607         *granularity = METER_GRANULARITY_DEFAULT;
    608         return BCM_E_NONE;
    609     }
    610 
    611     refresh_mask = 0xffffffff >> (32 - refresh_bitsize);
    612     bucket_mask = 0xffffffff >> (32 - bucket_max_bitsize);
    613     if (flags & _BCM_XGS_METER_FLAG_PACKET_MODE) {
    614         /* Minimum packet burst is .512 packet.  We'll work in integers. */
    615         burst = kbits_burst * METER_PACKET_BURST_DIVISOR;
    616     } else {
    617         if (kbits_burst > (0xffffffff / 1000)) {
    618             burst = 0xffffffff;
    619         } else {
    620             burst = kbits_burst * 1000;
    621         }
    622     }
    623 
    624     gran_min = granularity_start;
    625     gran_max = METER_GRANULARITY_NUM - 1;
    626 
    627     for (gran = gran_min; gran <= gran_max; gran++) {
    628         _bcm_xgs_granularity_params(gran, flags,
    629                                      &rate_quantum, &burst_quantum);
    630         refresh_max = refresh_mask * rate_quantum;
    631         bucket_max = bucket_mask * burst_quantum;
    632 
    633         if ((kbits_sec <= refresh_max) && (burst <= bucket_max)) {
    634             break;
    635         }
    636     }
    637 
    638     if (gran > gran_max) {
    639         /* Saturate! */
    640         gran = gran_max;
    641         if (kbits_sec > refresh_max) {
    642             kbits_sec = refresh_max;
    643         }
    644         if (burst > bucket_max) {
    645             burst = bucket_max;
    646         }
    647     }
    648 
    649     *granularity = gran;
    650 
    651     if (kbits_sec > (0xffffffff - (rate_quantum - 1))) {
    652         kbits_sec = 0xffffffff - (rate_quantum - 1);
    653     }
    654 
    655     /* Coverity fix : Making sure rate_quantum is above zero in order
    656     to avoid divide by zero coverity error */
    657     if (rate_quantum > 0) {
    658         *refresh_rate = (kbits_sec + (rate_quantum - 1)) / rate_quantum;
    659     }
    660     if (*refresh_rate > refresh_mask) {
    661         *refresh_rate = refresh_mask;
    662     }        
    663 
    664     encoding = (burst + (burst_quantum - 1)) / burst_quantum;
    665     if (encoding > bucket_mask) {
    666         encoding = bucket_mask;
    667     }
    668     *bucketsize = encoding;
    669     return BCM_E_NONE;
    670 }
    671 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAPTOR_SUPPORT || BCM_TRIUMPH_SUPPORT */
    672 
    673 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
    674     defined(BCM_GREYHOUND2_SUPPORT)
    675 int
    676 _bcm_xgs_kbits_to_bucket_encoding_with_granularity(uint32 kbits_sec, 
    677                                   uint32 kbits_burst,
    678                                   uint32 flags,
    679                                   int refresh_bitsize,
    680                                   int bucket_max_bitsize,
    681                                   uint32 *refresh_rate, uint32 *bucketsize,
    682                                   uint32 *granularity)
    683 {
    684     uint32 i;
    685     uint32 burst, encoding, buckettop, bucket_segment_size;
    686     uint32 refresh_mask = 0;
    687     uint32 bucket_mask = 0;
    688     uint32 rate_quantum = 0;
    689     uint32 burst_quantum = 0;
    690 
    691     if ((refresh_rate == NULL) || (bucketsize == NULL)) {
    692         return BCM_E_INTERNAL;
    693     }
    694 
    695     if ((kbits_burst == 0) &&
    696         (!(flags & _BCM_XGS_METER_FLAG_FP_POLICER) && (kbits_sec == 0))) {
    697         /* Disabled */
    698         *refresh_rate = 0;
    699         *bucketsize = 0;
    700         *granularity = METER_GRANULARITY_DEFAULT;
    701         return BCM_E_NONE;
    702     }
    703 
    704     refresh_mask = 0xffffffff >> (32 - refresh_bitsize);
    705     bucket_mask = 0xffffffff >> (32 - bucket_max_bitsize);
    706     if (flags & _BCM_XGS_METER_FLAG_PACKET_MODE) {
    707         /* Minimum packet burst is .512 packet.  We'll work in integers. */
    708         burst = kbits_burst * METER_PACKET_BURST_DIVISOR;
    709     } else {
    710         if (kbits_burst > (0xffffffff / 1000)) {
    711             burst = 0xffffffff;
    712         } else {
    713             burst = kbits_burst * 1000;
    714         }
    715     }
    716 
    717     _bcm_xgs_granularity_params(*granularity, flags,
    718                                      &rate_quantum, &burst_quantum);
    719 
    720     if (kbits_sec > (0xffffffff - (rate_quantum - 1))) {
    721         kbits_sec = 0xffffffff - (rate_quantum - 1);
    722     }
    723 
    724     *refresh_rate = (kbits_sec + (rate_quantum - 1)) / rate_quantum;
    725     if (*refresh_rate > refresh_mask) {
    726         *refresh_rate = refresh_mask;
    727     }        
    728 
    729     if (flags & _BCM_XGS_METER_FLAG_NON_LINEAR) {
    730         if (burst <= burst_quantum) {
    731             *bucketsize = burst ? 1 : 0; /* 0 kbits means disable */
    732         } else {
    733             encoding = bucket_mask;
    734             buckettop = burst_quantum;
    735             for (i = 0; i < METER_NL_BUCKET_RANGE_NUM; i++, buckettop *= 2) {
    736                 bucket_segment_size =
    737                     buckettop / METER_NL_SEGMENT_GRANULARITY;
    738                 if (burst <= (buckettop * 2 - bucket_segment_size) ||
    739                     (buckettop == 0)) {
    740                     if (buckettop == 0) {
    741                         /* Saturate */
    742                         buckettop = 0xffffffff;
    743                     }
    744                     encoding =
    745                         (burst - buckettop + (bucket_segment_size - 1)) /
    746                         bucket_segment_size;
    747                     encoding |= i << METER_NL_BUCKET_POWER_SHIFT;
    748                     break;
    749                 }
    750             }
    751             *bucketsize = (i < METER_NL_BUCKET_RANGE_NUM) ? encoding :
    752                 bucket_mask;
    753         }
    754     } else {
    755         encoding = (burst + (burst_quantum - 1)) / burst_quantum;
    756         if (encoding > bucket_mask) {
    757             encoding = bucket_mask;
    758         }
    759         *bucketsize = encoding;
    760     }
    761     return BCM_E_NONE;
    762 }
    763 #endif /* BCM_KATANA_SUPPORT || BCM_TRIUMPH3_SUPPORT ||
    764           BCM_GREYHOUND2_SUPPORT */