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_utils.c (6281B)


      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_utils.c
      8  * Purpose:
      9  * Requires:
     10  */
     11 
     12 
     13 #include <shared/bsl.h>
     14 
     15 #include <sal/core/boot.h>
     16 #include <sal/core/dpc.h>
     17 #include <shared/bsl.h>
     18 
     19 #include <soc/drv.h>
     20 #include <soc/error.h>
     21 #include <soc/debug.h>
     22 #include <soc/mem.h>
     23 #include <soc/dma.h>
     24 
     25 #include <soc/rx.h>
     26 
     27 #if defined(BCM_CMICM_SUPPORT)
     28 #include <soc/cmicm.h>
     29 #endif
     30 
     31 int
     32 soc_rx_queue_channel_set(int unit, int queue_id,
     33                          int chan_id)
     34 {
     35 #ifdef BCM_KATANA_SUPPORT
     36     uint32 i = 0;
     37 #endif
     38 #if defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT)
     39     uint32 ix;
     40     uint32 chan_id_max = SOC_RX_CHANNELS;
     41     uint32 soc_rx_channels = SOC_RX_CHANNELS;
     42     uint32 reg_addr = 0, reg_val;
     43     int cmc;
     44     int pci_cmc = SOC_PCI_CMC(unit);
     45     uint32 chan_off = 0;
     46     int startq = 0;
     47     int numq, endq, countq;
     48     int start_chan_id;
     49 
     50     soc_dma_max_rx_channels_get(unit, &chan_id_max);
     51     soc_rx_channels = chan_id_max;
     52 
     53     if (0 != SOC_CMCS_NUM(unit)) {
     54         chan_id_max *= SOC_CMCS_NUM(unit);
     55     }
     56 
     57     if (SOC_WARM_BOOT(unit)) {
     58         return SOC_E_NONE;
     59     }
     60     if ((chan_id < 0) || (chan_id >= chan_id_max)) {
     61         /* Verify the chan id */
     62         return SOC_E_PARAM;
     63     } else if (queue_id >= NUM_CPU_COSQ(unit)) {
     64         return SOC_E_PARAM;
     65     }
     66 
     67     if(soc_feature(unit, soc_feature_cmicm) ||
     68         soc_feature(unit, soc_feature_cmicx)) {
     69         /* We institute the normalizing assumption that the
     70          * channels are numbered first in the PCI CMC, then in order of the
     71          * ARM CMCs.  This is why we have the shuffling steps below.
     72          */
     73         if (chan_id < soc_rx_channels) {
     74             cmc = pci_cmc;
     75         } else {
     76             cmc = SOC_ARM_CMC(unit, ((chan_id / soc_rx_channels) - 1));
     77             /* compute start queue number for any CMC */
     78             startq = NUM_CPU_ARM_COSQ(unit, pci_cmc);
     79             for (ix = 0; ix < cmc; ix++) {
     80                 startq += (ix != pci_cmc) ? NUM_CPU_ARM_COSQ(unit, ix) : 0;
     81             }
     82         }
     83 
     84         numq = NUM_CPU_ARM_COSQ(unit, cmc);
     85         start_chan_id = (cmc != pci_cmc) ? cmc * soc_rx_channels : 0;
     86 
     87         if (queue_id < 0) { /* All COS Queues */
     88             /* validate the queue range of CMC is in the valid range
     89              * for this CMC
     90              */
     91             SHR_BITCOUNT_RANGE(CPU_ARM_QUEUE_BITMAP(unit, cmc),
     92                     countq, startq, numq);
     93             if (numq != countq) {
     94                 return SOC_E_PARAM;
     95             }
     96 
     97             /* We know chan_id != -1 from the parameter check at the
     98              * start of the function */
     99             endq = startq + NUM_CPU_ARM_COSQ(unit, cmc);
    100             for (ix = start_chan_id; ix < (start_chan_id + soc_rx_channels); ix++) {
    101                 /* set CMIC_CMCx_CHy_COS_CTRL_RX_0/1 based on CMC's start
    102                  * and end queue number
    103                  */
    104                 chan_off = ix % soc_rx_channels;
    105                 reg_val = 0;
    106                 if (ix == (uint32)chan_id) {
    107                     reg_val |= (endq < 32) ?
    108                         ((uint32)1 << endq) - 1 : 0xffffffff;
    109                     reg_val &= (startq < 32) ?
    110                         ~(((uint32)1 << startq) - 1) : 0;
    111                 }
    112 
    113                 /*
    114                  * Hard Code queue_id to 0 to ensure we get back COS_CTRL_RX_0
    115                  * register address.
    116                  */
    117                 soc_dma_cos_ctrl_reg_addr_get(unit, cmc, chan_off,
    118                                               0, &reg_addr);
    119 
    120                 /* Incoporate the reserved queues (if any on this device)
    121                  * into the CMIC programming,  */
    122                 reg_val |= CPU_ARM_RSVD_QUEUE_BITMAP(unit,cmc)[0];
    123                 soc_pci_write(unit, reg_addr, reg_val);
    124 
    125                 /*
    126                  * Hard Code queue_id to 32 to ensure we get back COS_CTRL_RX_1
    127                  * register address.
    128                  */
    129                 soc_dma_cos_ctrl_reg_addr_get(unit, cmc, chan_off,
    130                                               32, &reg_addr);
    131 
    132 #if defined(BCM_KATANA_SUPPORT)
    133                 if (SOC_IS_KATANAX(unit)) {
    134                     /*
    135                      * Katana queues have been disabled to prevent packets
    136                      * that cannot egress from reaching the CMIC. At this
    137                      * point those queues can be enabled.
    138                      */
    139                     for (i = startq; i < endq; i++) {
    140                         reg_val = 0;
    141                         soc_reg_field_set(unit,
    142                                 THDO_QUEUE_DISABLE_CFG2r, &reg_val, QUEUE_NUMf, i);
    143                         SOC_IF_ERROR_RETURN(
    144                                 WRITE_THDO_QUEUE_DISABLE_CFG2r(unit, reg_val));
    145                         reg_val = 0;
    146                         soc_reg_field_set(unit,
    147                                 THDO_QUEUE_DISABLE_CFG1r, &reg_val, QUEUE_WRf, 1);
    148                         SOC_IF_ERROR_RETURN(
    149                                 WRITE_THDO_QUEUE_DISABLE_CFG1r(unit, reg_val));
    150                     }
    151                 }
    152 #endif /*BCM_KATANA_SUPPORT */
    153                 reg_val = 0;
    154                 /* Incoporate the reserved queues (if any on this device)
    155                  * into the CMIC programming,  */
    156                 reg_val |= CPU_ARM_RSVD_QUEUE_BITMAP(unit,cmc)[1];
    157 
    158                 if (ix == (uint32)chan_id) {
    159                     reg_val |= ((endq >= 32) && (endq < 64)) ?
    160                         (((uint32)1 << (endq % 32)) - 1) :
    161                         ((endq < 32) ? 0 : 0xffffffff);
    162                     reg_val &= (startq >= 32) ?
    163                         ~(((uint32)1 << (startq % 32)) - 1) : 0xffffffff;
    164                     if (SOC_IS_TD2P_TT2P(unit)) {
    165                         soc_pci_write(unit, reg_addr, reg_val);
    166                     }
    167 
    168                 }
    169                 if (!SOC_IS_TD2P_TT2P(unit)) {
    170                     soc_pci_write(unit, reg_addr, reg_val);
    171                 }
    172             }
    173         } else {
    174             return SOC_E_PARAM;
    175         }
    176     } else
    177 #endif
    178     {
    179         return SOC_E_PARAM;
    180     }
    181     return SOC_E_NONE;
    182 }
    183