Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 1999 - 2018 Intel Corporation. */
0003 
0004 #include "ixgbe.h"
0005 #include "ixgbe_type.h"
0006 #include "ixgbe_dcb.h"
0007 #include "ixgbe_dcb_82598.h"
0008 #include "ixgbe_dcb_82599.h"
0009 
0010 /**
0011  * ixgbe_ieee_credits - This calculates the ieee traffic class
0012  * credits from the configured bandwidth percentages. Credits
0013  * are the smallest unit programmable into the underlying
0014  * hardware. The IEEE 802.1Qaz specification do not use bandwidth
0015  * groups so this is much simplified from the CEE case.
0016  * @bw: bandwidth index by traffic class
0017  * @refill: refill credits index by traffic class
0018  * @max: max credits by traffic class
0019  * @max_frame: maximum frame size
0020  */
0021 static s32 ixgbe_ieee_credits(__u8 *bw, __u16 *refill,
0022                   __u16 *max, int max_frame)
0023 {
0024     int min_percent = 100;
0025     int min_credit, multiplier;
0026     int i;
0027 
0028     min_credit = ((max_frame / 2) + DCB_CREDIT_QUANTUM - 1) /
0029             DCB_CREDIT_QUANTUM;
0030 
0031     for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
0032         if (bw[i] < min_percent && bw[i])
0033             min_percent = bw[i];
0034     }
0035 
0036     multiplier = (min_credit / min_percent) + 1;
0037 
0038     /* Find out the hw credits for each TC */
0039     for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
0040         int val = min(bw[i] * multiplier, MAX_CREDIT_REFILL);
0041 
0042         if (val < min_credit)
0043             val = min_credit;
0044         refill[i] = val;
0045 
0046         max[i] = bw[i] ? (bw[i] * MAX_CREDIT)/100 : min_credit;
0047     }
0048     return 0;
0049 }
0050 
0051 /**
0052  * ixgbe_dcb_calculate_tc_credits - Calculates traffic class credits
0053  * @hw: pointer to hardware structure
0054  * @dcb_config: Struct containing DCB settings
0055  * @max_frame: Maximum frame size
0056  * @direction: Configuring either Tx or Rx
0057  *
0058  * This function calculates the credits allocated to each traffic class.
0059  * It should be called only after the rules are checked by
0060  * ixgbe_dcb_check_config().
0061  */
0062 s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_hw *hw,
0063                    struct ixgbe_dcb_config *dcb_config,
0064                    int max_frame, u8 direction)
0065 {
0066     struct tc_bw_alloc *p;
0067     int min_credit;
0068     int min_multiplier;
0069     int min_percent = 100;
0070     /* Initialization values default for Tx settings */
0071     u32 credit_refill       = 0;
0072     u32 credit_max          = 0;
0073     u16 link_percentage     = 0;
0074     u8  bw_percent          = 0;
0075     u8  i;
0076 
0077     if (!dcb_config)
0078         return DCB_ERR_CONFIG;
0079 
0080     min_credit = ((max_frame / 2) + DCB_CREDIT_QUANTUM - 1) /
0081             DCB_CREDIT_QUANTUM;
0082 
0083     /* Find smallest link percentage */
0084     for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
0085         p = &dcb_config->tc_config[i].path[direction];
0086         bw_percent = dcb_config->bw_percentage[direction][p->bwg_id];
0087         link_percentage = p->bwg_percent;
0088 
0089         link_percentage = (link_percentage * bw_percent) / 100;
0090 
0091         if (link_percentage && link_percentage < min_percent)
0092             min_percent = link_percentage;
0093     }
0094 
0095     /*
0096      * The ratio between traffic classes will control the bandwidth
0097      * percentages seen on the wire. To calculate this ratio we use
0098      * a multiplier. It is required that the refill credits must be
0099      * larger than the max frame size so here we find the smallest
0100      * multiplier that will allow all bandwidth percentages to be
0101      * greater than the max frame size.
0102      */
0103     min_multiplier = (min_credit / min_percent) + 1;
0104 
0105     /* Find out the link percentage for each TC first */
0106     for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
0107         p = &dcb_config->tc_config[i].path[direction];
0108         bw_percent = dcb_config->bw_percentage[direction][p->bwg_id];
0109 
0110         link_percentage = p->bwg_percent;
0111         /* Must be careful of integer division for very small nums */
0112         link_percentage = (link_percentage * bw_percent) / 100;
0113         if (p->bwg_percent > 0 && link_percentage == 0)
0114             link_percentage = 1;
0115 
0116         /* Save link_percentage for reference */
0117         p->link_percent = (u8)link_percentage;
0118 
0119         /* Calculate credit refill ratio using multiplier */
0120         credit_refill = min(link_percentage * min_multiplier,
0121                     MAX_CREDIT_REFILL);
0122 
0123         /* Refill at least minimum credit */
0124         if (credit_refill < min_credit)
0125             credit_refill = min_credit;
0126 
0127         p->data_credits_refill = (u16)credit_refill;
0128 
0129         /* Calculate maximum credit for the TC */
0130         credit_max = (link_percentage * MAX_CREDIT) / 100;
0131 
0132         /*
0133          * Adjustment based on rule checking, if the percentage
0134          * of a TC is too small, the maximum credit may not be
0135          * enough to send out a jumbo frame in data plane arbitration.
0136          */
0137         if (credit_max < min_credit)
0138             credit_max = min_credit;
0139 
0140         if (direction == DCB_TX_CONFIG) {
0141             /*
0142              * Adjustment based on rule checking, if the
0143              * percentage of a TC is too small, the maximum
0144              * credit may not be enough to send out a TSO
0145              * packet in descriptor plane arbitration.
0146              */
0147             if ((hw->mac.type == ixgbe_mac_82598EB) &&
0148                 credit_max &&
0149                 (credit_max < MINIMUM_CREDIT_FOR_TSO))
0150                 credit_max = MINIMUM_CREDIT_FOR_TSO;
0151 
0152             dcb_config->tc_config[i].desc_credits_max =
0153                 (u16)credit_max;
0154         }
0155 
0156         p->data_credits_max = (u16)credit_max;
0157     }
0158 
0159     return 0;
0160 }
0161 
0162 void ixgbe_dcb_unpack_pfc(struct ixgbe_dcb_config *cfg, u8 *pfc_en)
0163 {
0164     struct tc_configuration *tc_config = &cfg->tc_config[0];
0165     int tc;
0166 
0167     for (*pfc_en = 0, tc = 0; tc < MAX_TRAFFIC_CLASS; tc++) {
0168         if (tc_config[tc].dcb_pfc != pfc_disabled)
0169             *pfc_en |= BIT(tc);
0170     }
0171 }
0172 
0173 void ixgbe_dcb_unpack_refill(struct ixgbe_dcb_config *cfg, int direction,
0174                  u16 *refill)
0175 {
0176     struct tc_configuration *tc_config = &cfg->tc_config[0];
0177     int tc;
0178 
0179     for (tc = 0; tc < MAX_TRAFFIC_CLASS; tc++)
0180         refill[tc] = tc_config[tc].path[direction].data_credits_refill;
0181 }
0182 
0183 void ixgbe_dcb_unpack_max(struct ixgbe_dcb_config *cfg, u16 *max)
0184 {
0185     struct tc_configuration *tc_config = &cfg->tc_config[0];
0186     int tc;
0187 
0188     for (tc = 0; tc < MAX_TRAFFIC_CLASS; tc++)
0189         max[tc] = tc_config[tc].desc_credits_max;
0190 }
0191 
0192 void ixgbe_dcb_unpack_bwgid(struct ixgbe_dcb_config *cfg, int direction,
0193                 u8 *bwgid)
0194 {
0195     struct tc_configuration *tc_config = &cfg->tc_config[0];
0196     int tc;
0197 
0198     for (tc = 0; tc < MAX_TRAFFIC_CLASS; tc++)
0199         bwgid[tc] = tc_config[tc].path[direction].bwg_id;
0200 }
0201 
0202 void ixgbe_dcb_unpack_prio(struct ixgbe_dcb_config *cfg, int direction,
0203                 u8 *ptype)
0204 {
0205     struct tc_configuration *tc_config = &cfg->tc_config[0];
0206     int tc;
0207 
0208     for (tc = 0; tc < MAX_TRAFFIC_CLASS; tc++)
0209         ptype[tc] = tc_config[tc].path[direction].prio_type;
0210 }
0211 
0212 u8 ixgbe_dcb_get_tc_from_up(struct ixgbe_dcb_config *cfg, int direction, u8 up)
0213 {
0214     struct tc_configuration *tc_config = &cfg->tc_config[0];
0215     u8 prio_mask = BIT(up);
0216     u8 tc = cfg->num_tcs.pg_tcs;
0217 
0218     /* If tc is 0 then DCB is likely not enabled or supported */
0219     if (!tc)
0220         return 0;
0221 
0222     /*
0223      * Test from maximum TC to 1 and report the first match we find.  If
0224      * we find no match we can assume that the TC is 0 since the TC must
0225      * be set for all user priorities
0226      */
0227     for (tc--; tc; tc--) {
0228         if (prio_mask & tc_config[tc].path[direction].up_to_tc_bitmap)
0229             break;
0230     }
0231 
0232     return tc;
0233 }
0234 
0235 void ixgbe_dcb_unpack_map(struct ixgbe_dcb_config *cfg, int direction, u8 *map)
0236 {
0237     u8 up;
0238 
0239     for (up = 0; up < MAX_USER_PRIORITY; up++)
0240         map[up] = ixgbe_dcb_get_tc_from_up(cfg, direction, up);
0241 }
0242 
0243 /**
0244  * ixgbe_dcb_hw_config - Config and enable DCB
0245  * @hw: pointer to hardware structure
0246  * @dcb_config: pointer to ixgbe_dcb_config structure
0247  *
0248  * Configure dcb settings and enable dcb mode.
0249  */
0250 s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw,
0251             struct ixgbe_dcb_config *dcb_config)
0252 {
0253     u8 pfc_en;
0254     u8 ptype[MAX_TRAFFIC_CLASS];
0255     u8 bwgid[MAX_TRAFFIC_CLASS];
0256     u8 prio_tc[MAX_TRAFFIC_CLASS];
0257     u16 refill[MAX_TRAFFIC_CLASS];
0258     u16 max[MAX_TRAFFIC_CLASS];
0259 
0260     /* Unpack CEE standard containers */
0261     ixgbe_dcb_unpack_pfc(dcb_config, &pfc_en);
0262     ixgbe_dcb_unpack_refill(dcb_config, DCB_TX_CONFIG, refill);
0263     ixgbe_dcb_unpack_max(dcb_config, max);
0264     ixgbe_dcb_unpack_bwgid(dcb_config, DCB_TX_CONFIG, bwgid);
0265     ixgbe_dcb_unpack_prio(dcb_config, DCB_TX_CONFIG, ptype);
0266     ixgbe_dcb_unpack_map(dcb_config, DCB_TX_CONFIG, prio_tc);
0267 
0268     switch (hw->mac.type) {
0269     case ixgbe_mac_82598EB:
0270         return ixgbe_dcb_hw_config_82598(hw, pfc_en, refill, max,
0271                          bwgid, ptype);
0272     case ixgbe_mac_82599EB:
0273     case ixgbe_mac_X540:
0274     case ixgbe_mac_X550:
0275     case ixgbe_mac_X550EM_x:
0276     case ixgbe_mac_x550em_a:
0277         return ixgbe_dcb_hw_config_82599(hw, pfc_en, refill, max,
0278                          bwgid, ptype, prio_tc);
0279     default:
0280         break;
0281     }
0282     return 0;
0283 }
0284 
0285 /* Helper routines to abstract HW specifics from DCB netlink ops */
0286 s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc)
0287 {
0288     switch (hw->mac.type) {
0289     case ixgbe_mac_82598EB:
0290         return ixgbe_dcb_config_pfc_82598(hw, pfc_en);
0291     case ixgbe_mac_82599EB:
0292     case ixgbe_mac_X540:
0293     case ixgbe_mac_X550:
0294     case ixgbe_mac_X550EM_x:
0295     case ixgbe_mac_x550em_a:
0296         return ixgbe_dcb_config_pfc_82599(hw, pfc_en, prio_tc);
0297     default:
0298         break;
0299     }
0300     return -EINVAL;
0301 }
0302 
0303 s32 ixgbe_dcb_hw_ets(struct ixgbe_hw *hw, struct ieee_ets *ets, int max_frame)
0304 {
0305     __u16 refill[IEEE_8021QAZ_MAX_TCS], max[IEEE_8021QAZ_MAX_TCS];
0306     __u8 prio_type[IEEE_8021QAZ_MAX_TCS];
0307     int i;
0308 
0309     /* naively give each TC a bwg to map onto CEE hardware */
0310     __u8 bwg_id[IEEE_8021QAZ_MAX_TCS] = {0, 1, 2, 3, 4, 5, 6, 7};
0311 
0312     /* Map TSA onto CEE prio type */
0313     for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
0314         switch (ets->tc_tsa[i]) {
0315         case IEEE_8021QAZ_TSA_STRICT:
0316             prio_type[i] = 2;
0317             break;
0318         case IEEE_8021QAZ_TSA_ETS:
0319             prio_type[i] = 0;
0320             break;
0321         default:
0322             /* Hardware only supports priority strict or
0323              * ETS transmission selection algorithms if
0324              * we receive some other value from dcbnl
0325              * throw an error
0326              */
0327             return -EINVAL;
0328         }
0329     }
0330 
0331     ixgbe_ieee_credits(ets->tc_tx_bw, refill, max, max_frame);
0332     return ixgbe_dcb_hw_ets_config(hw, refill, max,
0333                        bwg_id, prio_type, ets->prio_tc);
0334 }
0335 
0336 s32 ixgbe_dcb_hw_ets_config(struct ixgbe_hw *hw,
0337                 u16 *refill, u16 *max, u8 *bwg_id,
0338                 u8 *prio_type, u8 *prio_tc)
0339 {
0340     switch (hw->mac.type) {
0341     case ixgbe_mac_82598EB:
0342         ixgbe_dcb_config_rx_arbiter_82598(hw, refill, max,
0343                             prio_type);
0344         ixgbe_dcb_config_tx_desc_arbiter_82598(hw, refill, max,
0345                                  bwg_id, prio_type);
0346         ixgbe_dcb_config_tx_data_arbiter_82598(hw, refill, max,
0347                                  bwg_id, prio_type);
0348         break;
0349     case ixgbe_mac_82599EB:
0350     case ixgbe_mac_X540:
0351     case ixgbe_mac_X550:
0352     case ixgbe_mac_X550EM_x:
0353     case ixgbe_mac_x550em_a:
0354         ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max,
0355                           bwg_id, prio_type, prio_tc);
0356         ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max,
0357                                bwg_id, prio_type);
0358         ixgbe_dcb_config_tx_data_arbiter_82599(hw, refill, max, bwg_id,
0359                                prio_type, prio_tc);
0360         break;
0361     default:
0362         break;
0363     }
0364     return 0;
0365 }
0366 
0367 static void ixgbe_dcb_read_rtrup2tc_82599(struct ixgbe_hw *hw, u8 *map)
0368 {
0369     u32 reg, i;
0370 
0371     reg = IXGBE_READ_REG(hw, IXGBE_RTRUP2TC);
0372     for (i = 0; i < MAX_USER_PRIORITY; i++)
0373         map[i] = IXGBE_RTRUP2TC_UP_MASK &
0374             (reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT));
0375 }
0376 
0377 void ixgbe_dcb_read_rtrup2tc(struct ixgbe_hw *hw, u8 *map)
0378 {
0379     switch (hw->mac.type) {
0380     case ixgbe_mac_82599EB:
0381     case ixgbe_mac_X540:
0382     case ixgbe_mac_X550:
0383     case ixgbe_mac_X550EM_x:
0384     case ixgbe_mac_x550em_a:
0385         ixgbe_dcb_read_rtrup2tc_82599(hw, map);
0386         break;
0387     default:
0388         break;
0389     }
0390 }