LCOV - code coverage report
Current view: top level - drivers/net/txgbe/base - txgbe_dcb.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 122 0.0 %
Date: 2025-01-02 22:41:34 Functions: 0 10 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 65 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2015-2020 Beijing WangXun Technology Co., Ltd.
       3                 :            :  * Copyright(c) 2010-2017 Intel Corporation
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "txgbe_type.h"
       7                 :            : #include "txgbe_hw.h"
       8                 :            : #include "txgbe_dcb.h"
       9                 :            : #include "txgbe_dcb_hw.h"
      10                 :            : 
      11                 :            : /**
      12                 :            :  *  txgbe_pfc_enable - Enable flow control
      13                 :            :  *  @hw: pointer to hardware structure
      14                 :            :  *  @tc_num: traffic class number
      15                 :            :  *  Enable flow control according to the current settings.
      16                 :            :  */
      17                 :            : int
      18                 :          0 : txgbe_dcb_pfc_enable(struct txgbe_hw *hw, uint8_t tc_num)
      19                 :            : {
      20                 :            :         int ret_val = 0;
      21                 :            :         uint32_t mflcn_reg, fccfg_reg;
      22                 :            :         uint32_t pause_time;
      23                 :            :         uint32_t fcrtl, fcrth;
      24                 :            :         uint8_t i;
      25                 :            :         uint8_t nb_rx_en;
      26                 :            : 
      27                 :            :         /* Validate the water mark configuration */
      28         [ #  # ]:          0 :         if (!hw->fc.pause_time) {
      29                 :            :                 ret_val = TXGBE_ERR_INVALID_LINK_SETTINGS;
      30                 :          0 :                 goto out;
      31                 :            :         }
      32                 :            : 
      33                 :            :         /* Low water mark of zero causes XOFF floods */
      34         [ #  # ]:          0 :         if (hw->fc.current_mode & txgbe_fc_tx_pause) {
      35                 :            :                  /* High/Low water can not be 0 */
      36         [ #  # ]:          0 :                 if (!hw->fc.high_water[tc_num] ||
      37         [ #  # ]:          0 :                     !hw->fc.low_water[tc_num]) {
      38                 :          0 :                         PMD_INIT_LOG(ERR, "Invalid water mark configuration");
      39                 :            :                         ret_val = TXGBE_ERR_INVALID_LINK_SETTINGS;
      40                 :          0 :                         goto out;
      41                 :            :                 }
      42                 :            : 
      43         [ #  # ]:          0 :                 if (hw->fc.low_water[tc_num] >= hw->fc.high_water[tc_num]) {
      44                 :          0 :                         PMD_INIT_LOG(ERR, "Invalid water mark configuration");
      45                 :            :                         ret_val = TXGBE_ERR_INVALID_LINK_SETTINGS;
      46                 :          0 :                         goto out;
      47                 :            :                 }
      48                 :            :         }
      49                 :            :         /* Negotiate the fc mode to use */
      50                 :          0 :         txgbe_fc_autoneg(hw);
      51                 :            : 
      52                 :            :         /* Disable any previous flow control settings */
      53                 :            :         mflcn_reg = rd32(hw, TXGBE_RXFCCFG);
      54                 :          0 :         mflcn_reg &= ~(TXGBE_RXFCCFG_FC | TXGBE_RXFCCFG_PFC);
      55                 :            : 
      56                 :            :         fccfg_reg = rd32(hw, TXGBE_TXFCCFG);
      57                 :          0 :         fccfg_reg &= ~(TXGBE_TXFCCFG_FC | TXGBE_TXFCCFG_PFC);
      58                 :            : 
      59   [ #  #  #  #  :          0 :         switch (hw->fc.current_mode) {
                      # ]
      60                 :            :         case txgbe_fc_none:
      61                 :            :                 /*
      62                 :            :                  * If the count of enabled RX Priority Flow control > 1,
      63                 :            :                  * and the TX pause can not be disabled
      64                 :            :                  */
      65                 :            :                 nb_rx_en = 0;
      66         [ #  # ]:          0 :                 for (i = 0; i < TXGBE_DCB_TC_MAX; i++) {
      67                 :          0 :                         uint32_t reg = rd32(hw, TXGBE_FCWTRHI(i));
      68         [ #  # ]:          0 :                         if (reg & TXGBE_FCWTRHI_XOFF)
      69                 :          0 :                                 nb_rx_en++;
      70                 :            :                 }
      71         [ #  # ]:          0 :                 if (nb_rx_en > 1)
      72                 :          0 :                         fccfg_reg |= TXGBE_TXFCCFG_PFC;
      73                 :            :                 break;
      74                 :          0 :         case txgbe_fc_rx_pause:
      75                 :            :                 /*
      76                 :            :                  * Rx Flow control is enabled and Tx Flow control is
      77                 :            :                  * disabled by software override. Since there really
      78                 :            :                  * isn't a way to advertise that we are capable of RX
      79                 :            :                  * Pause ONLY, we will advertise that we support both
      80                 :            :                  * symmetric and asymmetric Rx PAUSE.  Later, we will
      81                 :            :                  * disable the adapter's ability to send PAUSE frames.
      82                 :            :                  */
      83                 :          0 :                 mflcn_reg |= TXGBE_RXFCCFG_PFC;
      84                 :            :                 /*
      85                 :            :                  * If the count of enabled RX Priority Flow control > 1,
      86                 :            :                  * and the TX pause can not be disabled
      87                 :            :                  */
      88                 :            :                 nb_rx_en = 0;
      89         [ #  # ]:          0 :                 for (i = 0; i < TXGBE_DCB_TC_MAX; i++) {
      90                 :          0 :                         uint32_t reg = rd32(hw, TXGBE_FCWTRHI(i));
      91         [ #  # ]:          0 :                         if (reg & TXGBE_FCWTRHI_XOFF)
      92                 :          0 :                                 nb_rx_en++;
      93                 :            :                 }
      94         [ #  # ]:          0 :                 if (nb_rx_en > 1)
      95                 :          0 :                         fccfg_reg |= TXGBE_TXFCCFG_PFC;
      96                 :            :                 break;
      97                 :          0 :         case txgbe_fc_tx_pause:
      98                 :            :                 /*
      99                 :            :                  * Tx Flow control is enabled, and Rx Flow control is
     100                 :            :                  * disabled by software override.
     101                 :            :                  */
     102                 :          0 :                 fccfg_reg |= TXGBE_TXFCCFG_PFC;
     103                 :          0 :                 break;
     104                 :          0 :         case txgbe_fc_full:
     105                 :            :                 /* Flow control (both Rx and Tx) is enabled by SW override. */
     106                 :          0 :                 mflcn_reg |= TXGBE_RXFCCFG_PFC;
     107                 :          0 :                 fccfg_reg |= TXGBE_TXFCCFG_PFC;
     108                 :          0 :                 break;
     109                 :          0 :         default:
     110                 :          0 :                 PMD_DRV_LOG(DEBUG, "Flow control param set incorrectly");
     111                 :            :                 ret_val = TXGBE_ERR_CONFIG;
     112                 :          0 :                 goto out;
     113                 :            :         }
     114                 :            : 
     115                 :            :         /* Set 802.3x based flow control settings. */
     116                 :            :         wr32(hw, TXGBE_RXFCCFG, mflcn_reg);
     117                 :            :         wr32(hw, TXGBE_TXFCCFG, fccfg_reg);
     118                 :            : 
     119                 :            :         /* Set up and enable Rx high/low water mark thresholds, enable XON. */
     120         [ #  # ]:          0 :         if ((hw->fc.current_mode & txgbe_fc_tx_pause) &&
     121         [ #  # ]:          0 :                 hw->fc.high_water[tc_num]) {
     122                 :          0 :                 fcrtl = TXGBE_FCWTRLO_TH(hw->fc.low_water[tc_num]) |
     123                 :            :                         TXGBE_FCWTRLO_XON;
     124                 :          0 :                 fcrth = TXGBE_FCWTRHI_TH(hw->fc.high_water[tc_num]) |
     125                 :            :                         TXGBE_FCWTRHI_XOFF;
     126                 :            :         } else {
     127                 :            :                 /*
     128                 :            :                  * In order to prevent Tx hangs when the internal Tx
     129                 :            :                  * switch is enabled we must set the high water mark
     130                 :            :                  * to the maximum FCRTH value.  This allows the Tx
     131                 :            :                  * switch to function even under heavy Rx workloads.
     132                 :            :                  */
     133                 :            :                 fcrtl = 0;
     134                 :          0 :                 fcrth = rd32(hw, TXGBE_PBRXSIZE(tc_num)) - 32;
     135                 :            :         }
     136                 :          0 :         wr32(hw, TXGBE_FCWTRLO(tc_num), fcrtl);
     137                 :          0 :         wr32(hw, TXGBE_FCWTRHI(tc_num), fcrth);
     138                 :            : 
     139                 :            :         /* Configure pause time (2 TCs per register) */
     140                 :          0 :         pause_time = TXGBE_RXFCFSH_TIME(hw->fc.pause_time);
     141         [ #  # ]:          0 :         for (i = 0; i < (TXGBE_DCB_TC_MAX / 2); i++)
     142                 :          0 :                 wr32(hw, TXGBE_FCXOFFTM(i), pause_time * 0x00010001);
     143                 :            : 
     144                 :            :         /* Configure flow control refresh threshold value */
     145                 :          0 :         wr32(hw, TXGBE_RXFCRFSH, pause_time / 2);
     146                 :            : 
     147                 :          0 : out:
     148                 :          0 :         return ret_val;
     149                 :            : }
     150                 :            : 
     151                 :            : /**
     152                 :            :  * txgbe_dcb_calculate_tc_credits_cee - Calculates traffic class credits
     153                 :            :  * @hw: pointer to hardware structure
     154                 :            :  * @dcb_config: Struct containing DCB settings
     155                 :            :  * @max_frame_size: Maximum frame size
     156                 :            :  * @direction: Configuring either Tx or Rx
     157                 :            :  *
     158                 :            :  * This function calculates the credits allocated to each traffic class.
     159                 :            :  * It should be called only after the rules are checked by
     160                 :            :  * txgbe_dcb_check_config_cee().
     161                 :            :  */
     162                 :          0 : s32 txgbe_dcb_calculate_tc_credits_cee(struct txgbe_hw *hw,
     163                 :            :                                    struct txgbe_dcb_config *dcb_config,
     164                 :            :                                    u32 max_frame_size, u8 direction)
     165                 :            : {
     166                 :            :         struct txgbe_dcb_tc_path *p;
     167                 :            :         u32 min_multiplier      = 0;
     168                 :            :         u16 min_percent         = 100;
     169                 :            :         s32 ret_val =           0;
     170                 :            :         /* Initialization values default for Tx settings */
     171                 :            :         u32 min_credit          = 0;
     172                 :            :         u32 credit_refill       = 0;
     173                 :            :         u32 credit_max          = 0;
     174                 :            :         u16 link_percentage     = 0;
     175                 :            :         u8  bw_percent          = 0;
     176                 :            :         u8  i;
     177                 :            : 
     178                 :            :         UNREFERENCED_PARAMETER(hw);
     179                 :            : 
     180         [ #  # ]:          0 :         if (dcb_config == NULL) {
     181                 :            :                 ret_val = TXGBE_ERR_CONFIG;
     182                 :          0 :                 goto out;
     183                 :            :         }
     184                 :            : 
     185                 :          0 :         min_credit = ((max_frame_size / 2) + TXGBE_DCB_CREDIT_QUANTUM - 1) /
     186                 :            :                      TXGBE_DCB_CREDIT_QUANTUM;
     187                 :            : 
     188                 :            :         /* Find smallest link percentage */
     189         [ #  # ]:          0 :         for (i = 0; i < TXGBE_DCB_TC_MAX; i++) {
     190                 :          0 :                 p = &dcb_config->tc_config[i].path[direction];
     191                 :          0 :                 bw_percent = dcb_config->bw_percentage[p->bwg_id][direction];
     192                 :          0 :                 link_percentage = p->bwg_percent;
     193                 :            : 
     194                 :          0 :                 link_percentage = (link_percentage * bw_percent) / 100;
     195                 :            : 
     196         [ #  # ]:          0 :                 if (link_percentage && link_percentage < min_percent)
     197                 :            :                         min_percent = link_percentage;
     198                 :            :         }
     199                 :            : 
     200                 :            :         /*
     201                 :            :          * The ratio between traffic classes will control the bandwidth
     202                 :            :          * percentages seen on the wire. To calculate this ratio we use
     203                 :            :          * a multiplier. It is required that the refill credits must be
     204                 :            :          * larger than the max frame size so here we find the smallest
     205                 :            :          * multiplier that will allow all bandwidth percentages to be
     206                 :            :          * greater than the max frame size.
     207                 :            :          */
     208                 :          0 :         min_multiplier = (min_credit / min_percent) + 1;
     209                 :            : 
     210                 :            :         /* Find out the link percentage for each TC first */
     211         [ #  # ]:          0 :         for (i = 0; i < TXGBE_DCB_TC_MAX; i++) {
     212                 :          0 :                 p = &dcb_config->tc_config[i].path[direction];
     213                 :          0 :                 bw_percent = dcb_config->bw_percentage[p->bwg_id][direction];
     214                 :            : 
     215                 :          0 :                 link_percentage = p->bwg_percent;
     216                 :            :                 /* Must be careful of integer division for very small nums */
     217                 :          0 :                 link_percentage = (link_percentage * bw_percent) / 100;
     218         [ #  # ]:          0 :                 if (p->bwg_percent > 0 && link_percentage == 0)
     219                 :            :                         link_percentage = 1;
     220                 :            : 
     221                 :            :                 /* Save link_percentage for reference */
     222                 :          0 :                 p->link_percent = (u8)link_percentage;
     223                 :            : 
     224                 :            :                 /* Calculate credit refill ratio using multiplier */
     225                 :          0 :                 credit_refill = min(link_percentage * min_multiplier,
     226                 :            :                                     (u32)TXGBE_DCB_MAX_CREDIT_REFILL);
     227                 :            : 
     228                 :            :                 /* Refill at least minimum credit */
     229                 :            :                 if (credit_refill < min_credit)
     230                 :            :                         credit_refill = min_credit;
     231                 :            : 
     232                 :          0 :                 p->data_credits_refill = (u16)credit_refill;
     233                 :            : 
     234                 :            :                 /* Calculate maximum credit for the TC */
     235                 :          0 :                 credit_max = (link_percentage * TXGBE_DCB_MAX_CREDIT) / 100;
     236                 :            : 
     237                 :            :                 /*
     238                 :            :                  * Adjustment based on rule checking, if the percentage
     239                 :            :                  * of a TC is too small, the maximum credit may not be
     240                 :            :                  * enough to send out a jumbo frame in data plane arbitration.
     241                 :            :                  */
     242                 :            :                 if (credit_max < min_credit)
     243                 :            :                         credit_max = min_credit;
     244                 :            : 
     245         [ #  # ]:          0 :                 if (direction == TXGBE_DCB_TX_CONFIG) {
     246                 :          0 :                         dcb_config->tc_config[i].desc_credits_max =
     247                 :          0 :                                                                 (u16)credit_max;
     248                 :            :                 }
     249                 :            : 
     250                 :          0 :                 p->data_credits_max = (u16)credit_max;
     251                 :            :         }
     252                 :            : 
     253                 :          0 : out:
     254                 :          0 :         return ret_val;
     255                 :            : }
     256                 :            : 
     257                 :            : /**
     258                 :            :  * txgbe_dcb_unpack_pfc_cee - Unpack dcb_config PFC info
     259                 :            :  * @cfg: dcb configuration to unpack into hardware consumable fields
     260                 :            :  * @map: user priority to traffic class map
     261                 :            :  * @pfc_up: u8 to store user priority PFC bitmask
     262                 :            :  *
     263                 :            :  * This unpacks the dcb configuration PFC info which is stored per
     264                 :            :  * traffic class into a 8bit user priority bitmask that can be
     265                 :            :  * consumed by hardware routines. The priority to tc map must be
     266                 :            :  * updated before calling this routine to use current up-to maps.
     267                 :            :  */
     268                 :          0 : void txgbe_dcb_unpack_pfc_cee(struct txgbe_dcb_config *cfg, u8 *map, u8 *pfc_up)
     269                 :            : {
     270                 :          0 :         struct txgbe_dcb_tc_config *tc_config = &cfg->tc_config[0];
     271                 :            :         int up;
     272                 :            : 
     273                 :            :         /*
     274                 :            :          * If the TC for this user priority has PFC enabled then set the
     275                 :            :          * matching bit in 'pfc_up' to reflect that PFC is enabled.
     276                 :            :          */
     277         [ #  # ]:          0 :         for (*pfc_up = 0, up = 0; up < TXGBE_DCB_UP_MAX; up++) {
     278         [ #  # ]:          0 :                 if (tc_config[map[up]].pfc != txgbe_dcb_pfc_disabled)
     279                 :          0 :                         *pfc_up |= 1 << up;
     280                 :            :         }
     281                 :          0 : }
     282                 :            : 
     283                 :          0 : void txgbe_dcb_unpack_refill_cee(struct txgbe_dcb_config *cfg, int direction,
     284                 :            :                              u16 *refill)
     285                 :            : {
     286                 :          0 :         struct txgbe_dcb_tc_config *tc_config = &cfg->tc_config[0];
     287                 :            :         int tc;
     288                 :            : 
     289         [ #  # ]:          0 :         for (tc = 0; tc < TXGBE_DCB_TC_MAX; tc++)
     290                 :          0 :                 refill[tc] = tc_config[tc].path[direction].data_credits_refill;
     291                 :          0 : }
     292                 :            : 
     293                 :          0 : void txgbe_dcb_unpack_max_cee(struct txgbe_dcb_config *cfg, u16 *max)
     294                 :            : {
     295                 :          0 :         struct txgbe_dcb_tc_config *tc_config = &cfg->tc_config[0];
     296                 :            :         int tc;
     297                 :            : 
     298         [ #  # ]:          0 :         for (tc = 0; tc < TXGBE_DCB_TC_MAX; tc++)
     299                 :          0 :                 max[tc] = tc_config[tc].desc_credits_max;
     300                 :          0 : }
     301                 :            : 
     302                 :          0 : void txgbe_dcb_unpack_bwgid_cee(struct txgbe_dcb_config *cfg, int direction,
     303                 :            :                             u8 *bwgid)
     304                 :            : {
     305                 :          0 :         struct txgbe_dcb_tc_config *tc_config = &cfg->tc_config[0];
     306                 :            :         int tc;
     307                 :            : 
     308         [ #  # ]:          0 :         for (tc = 0; tc < TXGBE_DCB_TC_MAX; tc++)
     309                 :          0 :                 bwgid[tc] = tc_config[tc].path[direction].bwg_id;
     310                 :          0 : }
     311                 :            : 
     312                 :          0 : void txgbe_dcb_unpack_tsa_cee(struct txgbe_dcb_config *cfg, int direction,
     313                 :            :                            u8 *tsa)
     314                 :            : {
     315                 :          0 :         struct txgbe_dcb_tc_config *tc_config = &cfg->tc_config[0];
     316                 :            :         int tc;
     317                 :            : 
     318         [ #  # ]:          0 :         for (tc = 0; tc < TXGBE_DCB_TC_MAX; tc++)
     319                 :          0 :                 tsa[tc] = tc_config[tc].path[direction].tsa;
     320                 :          0 : }
     321                 :            : 
     322                 :          0 : u8 txgbe_dcb_get_tc_from_up(struct txgbe_dcb_config *cfg, int direction, u8 up)
     323                 :            : {
     324                 :          0 :         struct txgbe_dcb_tc_config *tc_config = &cfg->tc_config[0];
     325                 :          0 :         u8 prio_mask = 1 << up;
     326                 :          0 :         u8 tc = cfg->num_tcs.pg_tcs;
     327                 :            : 
     328                 :            :         /* If tc is 0 then DCB is likely not enabled or supported */
     329         [ #  # ]:          0 :         if (!tc)
     330                 :          0 :                 goto out;
     331                 :            : 
     332                 :            :         /*
     333                 :            :          * Test from maximum TC to 1 and report the first match we find.  If
     334                 :            :          * we find no match we can assume that the TC is 0 since the TC must
     335                 :            :          * be set for all user priorities
     336                 :            :          */
     337         [ #  # ]:          0 :         for (tc--; tc; tc--) {
     338         [ #  # ]:          0 :                 if (prio_mask & tc_config[tc].path[direction].up_to_tc_bitmap)
     339                 :            :                         break;
     340                 :            :         }
     341                 :          0 : out:
     342                 :          0 :         return tc;
     343                 :            : }
     344                 :            : 
     345                 :          0 : void txgbe_dcb_unpack_map_cee(struct txgbe_dcb_config *cfg, int direction,
     346                 :            :                               u8 *map)
     347                 :            : {
     348                 :            :         u8 up;
     349                 :            : 
     350         [ #  # ]:          0 :         for (up = 0; up < TXGBE_DCB_UP_MAX; up++)
     351                 :          0 :                 map[up] = txgbe_dcb_get_tc_from_up(cfg, direction, up);
     352                 :          0 : }
     353                 :            : 
     354                 :            : /* Helper routines to abstract HW specifics from DCB netlink ops */
     355                 :          0 : s32 txgbe_dcb_config_pfc(struct txgbe_hw *hw, u8 pfc_en, u8 *map)
     356                 :            : {
     357                 :            :         int ret = TXGBE_ERR_PARAM;
     358                 :          0 :         ret = txgbe_dcb_config_pfc_raptor(hw, pfc_en, map);
     359                 :          0 :         return ret;
     360                 :            : }
     361                 :            : 

Generated by: LCOV version 1.14