linux/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright(c) 1999 - 2018 Intel Corporation. */
   3
   4#include "ixgbe.h"
   5#include "ixgbe_type.h"
   6#include "ixgbe_dcb.h"
   7#include "ixgbe_dcb_82598.h"
   8#include "ixgbe_dcb_82599.h"
   9
  10/**
  11 * ixgbe_ieee_credits - This calculates the ieee traffic class
  12 * credits from the configured bandwidth percentages. Credits
  13 * are the smallest unit programmable into the underlying
  14 * hardware. The IEEE 802.1Qaz specification do not use bandwidth
  15 * groups so this is much simplified from the CEE case.
  16 * @bw: bandwidth index by traffic class
  17 * @refill: refill credits index by traffic class
  18 * @max: max credits by traffic class
  19 * @max_frame: maximum frame size
  20 */
  21static s32 ixgbe_ieee_credits(__u8 *bw, __u16 *refill,
  22                              __u16 *max, int max_frame)
  23{
  24        int min_percent = 100;
  25        int min_credit, multiplier;
  26        int i;
  27
  28        min_credit = ((max_frame / 2) + DCB_CREDIT_QUANTUM - 1) /
  29                        DCB_CREDIT_QUANTUM;
  30
  31        for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
  32                if (bw[i] < min_percent && bw[i])
  33                        min_percent = bw[i];
  34        }
  35
  36        multiplier = (min_credit / min_percent) + 1;
  37
  38        /* Find out the hw credits for each TC */
  39        for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
  40                int val = min(bw[i] * multiplier, MAX_CREDIT_REFILL);
  41
  42                if (val < min_credit)
  43                        val = min_credit;
  44                refill[i] = val;
  45
  46                max[i] = bw[i] ? (bw[i] * MAX_CREDIT)/100 : min_credit;
  47        }
  48        return 0;
  49}
  50
  51/**
  52 * ixgbe_dcb_calculate_tc_credits - Calculates traffic class credits
  53 * @hw: pointer to hardware structure
  54 * @dcb_config: Struct containing DCB settings
  55 * @max_frame: Maximum frame size
  56 * @direction: Configuring either Tx or Rx
  57 *
  58 * This function calculates the credits allocated to each traffic class.
  59 * It should be called only after the rules are checked by
  60 * ixgbe_dcb_check_config().
  61 */
  62s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_hw *hw,
  63                                   struct ixgbe_dcb_config *dcb_config,
  64                                   int max_frame, u8 direction)
  65{
  66        struct tc_bw_alloc *p;
  67        int min_credit;
  68        int min_multiplier;
  69        int min_percent = 100;
  70        /* Initialization values default for Tx settings */
  71        u32 credit_refill       = 0;
  72        u32 credit_max          = 0;
  73        u16 link_percentage     = 0;
  74        u8  bw_percent          = 0;
  75        u8  i;
  76
  77        if (!dcb_config)
  78                return DCB_ERR_CONFIG;
  79
  80        min_credit = ((max_frame / 2) + DCB_CREDIT_QUANTUM - 1) /
  81                        DCB_CREDIT_QUANTUM;
  82
  83        /* Find smallest link percentage */
  84        for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
  85                p = &dcb_config->tc_config[i].path[direction];
  86                bw_percent = dcb_config->bw_percentage[direction][p->bwg_id];
  87                link_percentage = p->bwg_percent;
  88
  89                link_percentage = (link_percentage * bw_percent) / 100;
  90
  91                if (link_percentage && link_percentage < min_percent)
  92                        min_percent = link_percentage;
  93        }
  94
  95        /*
  96         * The ratio between traffic classes will control the bandwidth
  97         * percentages seen on the wire. To calculate this ratio we use
  98         * a multiplier. It is required that the refill credits must be
  99         * larger than the max frame size so here we find the smallest
 100         * multiplier that will allow all bandwidth percentages to be
 101         * greater than the max frame size.
 102         */
 103        min_multiplier = (min_credit / min_percent) + 1;
 104
 105        /* Find out the link percentage for each TC first */
 106        for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
 107                p = &dcb_config->tc_config[i].path[direction];
 108                bw_percent = dcb_config->bw_percentage[direction][p->bwg_id];
 109
 110                link_percentage = p->bwg_percent;
 111                /* Must be careful of integer division for very small nums */
 112                link_percentage = (link_percentage * bw_percent) / 100;
 113                if (p->bwg_percent > 0 && link_percentage == 0)
 114                        link_percentage = 1;
 115
 116                /* Save link_percentage for reference */
 117                p->link_percent = (u8)link_percentage;
 118
 119                /* Calculate credit refill ratio using multiplier */
 120                credit_refill = min(link_percentage * min_multiplier,
 121                                    MAX_CREDIT_REFILL);
 122
 123                /* Refill at least minimum credit */
 124                if (credit_refill < min_credit)
 125                        credit_refill = min_credit;
 126
 127                p->data_credits_refill = (u16)credit_refill;
 128
 129                /* Calculate maximum credit for the TC */
 130                credit_max = (link_percentage * MAX_CREDIT) / 100;
 131
 132                /*
 133                 * Adjustment based on rule checking, if the percentage
 134                 * of a TC is too small, the maximum credit may not be
 135                 * enough to send out a jumbo frame in data plane arbitration.
 136                 */
 137                if (credit_max < min_credit)
 138                        credit_max = min_credit;
 139
 140                if (direction == DCB_TX_CONFIG) {
 141                        /*
 142                         * Adjustment based on rule checking, if the
 143                         * percentage of a TC is too small, the maximum
 144                         * credit may not be enough to send out a TSO
 145                         * packet in descriptor plane arbitration.
 146                         */
 147                        if ((hw->mac.type == ixgbe_mac_82598EB) &&
 148                            credit_max &&
 149                            (credit_max < MINIMUM_CREDIT_FOR_TSO))
 150                                credit_max = MINIMUM_CREDIT_FOR_TSO;
 151
 152                        dcb_config->tc_config[i].desc_credits_max =
 153                                (u16)credit_max;
 154                }
 155
 156                p->data_credits_max = (u16)credit_max;
 157        }
 158
 159        return 0;
 160}
 161
 162void ixgbe_dcb_unpack_pfc(struct ixgbe_dcb_config *cfg, u8 *pfc_en)
 163{
 164        struct tc_configuration *tc_config = &cfg->tc_config[0];
 165        int tc;
 166
 167        for (*pfc_en = 0, tc = 0; tc < MAX_TRAFFIC_CLASS; tc++) {
 168                if (tc_config[tc].dcb_pfc != pfc_disabled)
 169                        *pfc_en |= BIT(tc);
 170        }
 171}
 172
 173void ixgbe_dcb_unpack_refill(struct ixgbe_dcb_config *cfg, int direction,
 174                             u16 *refill)
 175{
 176        struct tc_configuration *tc_config = &cfg->tc_config[0];
 177        int tc;
 178
 179        for (tc = 0; tc < MAX_TRAFFIC_CLASS; tc++)
 180                refill[tc] = tc_config[tc].path[direction].data_credits_refill;
 181}
 182
 183void ixgbe_dcb_unpack_max(struct ixgbe_dcb_config *cfg, u16 *max)
 184{
 185        struct tc_configuration *tc_config = &cfg->tc_config[0];
 186        int tc;
 187
 188        for (tc = 0; tc < MAX_TRAFFIC_CLASS; tc++)
 189                max[tc] = tc_config[tc].desc_credits_max;
 190}
 191
 192void ixgbe_dcb_unpack_bwgid(struct ixgbe_dcb_config *cfg, int direction,
 193                            u8 *bwgid)
 194{
 195        struct tc_configuration *tc_config = &cfg->tc_config[0];
 196        int tc;
 197
 198        for (tc = 0; tc < MAX_TRAFFIC_CLASS; tc++)
 199                bwgid[tc] = tc_config[tc].path[direction].bwg_id;
 200}
 201
 202void ixgbe_dcb_unpack_prio(struct ixgbe_dcb_config *cfg, int direction,
 203                            u8 *ptype)
 204{
 205        struct tc_configuration *tc_config = &cfg->tc_config[0];
 206        int tc;
 207
 208        for (tc = 0; tc < MAX_TRAFFIC_CLASS; tc++)
 209                ptype[tc] = tc_config[tc].path[direction].prio_type;
 210}
 211
 212u8 ixgbe_dcb_get_tc_from_up(struct ixgbe_dcb_config *cfg, int direction, u8 up)
 213{
 214        struct tc_configuration *tc_config = &cfg->tc_config[0];
 215        u8 prio_mask = BIT(up);
 216        u8 tc = cfg->num_tcs.pg_tcs;
 217
 218        /* If tc is 0 then DCB is likely not enabled or supported */
 219        if (!tc)
 220                return 0;
 221
 222        /*
 223         * Test from maximum TC to 1 and report the first match we find.  If
 224         * we find no match we can assume that the TC is 0 since the TC must
 225         * be set for all user priorities
 226         */
 227        for (tc--; tc; tc--) {
 228                if (prio_mask & tc_config[tc].path[direction].up_to_tc_bitmap)
 229                        break;
 230        }
 231
 232        return tc;
 233}
 234
 235void ixgbe_dcb_unpack_map(struct ixgbe_dcb_config *cfg, int direction, u8 *map)
 236{
 237        u8 up;
 238
 239        for (up = 0; up < MAX_USER_PRIORITY; up++)
 240                map[up] = ixgbe_dcb_get_tc_from_up(cfg, direction, up);
 241}
 242
 243/**
 244 * ixgbe_dcb_hw_config - Config and enable DCB
 245 * @hw: pointer to hardware structure
 246 * @dcb_config: pointer to ixgbe_dcb_config structure
 247 *
 248 * Configure dcb settings and enable dcb mode.
 249 */
 250s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw,
 251                        struct ixgbe_dcb_config *dcb_config)
 252{
 253        u8 pfc_en;
 254        u8 ptype[MAX_TRAFFIC_CLASS];
 255        u8 bwgid[MAX_TRAFFIC_CLASS];
 256        u8 prio_tc[MAX_TRAFFIC_CLASS];
 257        u16 refill[MAX_TRAFFIC_CLASS];
 258        u16 max[MAX_TRAFFIC_CLASS];
 259
 260        /* Unpack CEE standard containers */
 261        ixgbe_dcb_unpack_pfc(dcb_config, &pfc_en);
 262        ixgbe_dcb_unpack_refill(dcb_config, DCB_TX_CONFIG, refill);
 263        ixgbe_dcb_unpack_max(dcb_config, max);
 264        ixgbe_dcb_unpack_bwgid(dcb_config, DCB_TX_CONFIG, bwgid);
 265        ixgbe_dcb_unpack_prio(dcb_config, DCB_TX_CONFIG, ptype);
 266        ixgbe_dcb_unpack_map(dcb_config, DCB_TX_CONFIG, prio_tc);
 267
 268        switch (hw->mac.type) {
 269        case ixgbe_mac_82598EB:
 270                return ixgbe_dcb_hw_config_82598(hw, pfc_en, refill, max,
 271                                                 bwgid, ptype);
 272        case ixgbe_mac_82599EB:
 273        case ixgbe_mac_X540:
 274        case ixgbe_mac_X550:
 275        case ixgbe_mac_X550EM_x:
 276        case ixgbe_mac_x550em_a:
 277                return ixgbe_dcb_hw_config_82599(hw, pfc_en, refill, max,
 278                                                 bwgid, ptype, prio_tc);
 279        default:
 280                break;
 281        }
 282        return 0;
 283}
 284
 285/* Helper routines to abstract HW specifics from DCB netlink ops */
 286s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc)
 287{
 288        switch (hw->mac.type) {
 289        case ixgbe_mac_82598EB:
 290                return ixgbe_dcb_config_pfc_82598(hw, pfc_en);
 291        case ixgbe_mac_82599EB:
 292        case ixgbe_mac_X540:
 293        case ixgbe_mac_X550:
 294        case ixgbe_mac_X550EM_x:
 295        case ixgbe_mac_x550em_a:
 296                return ixgbe_dcb_config_pfc_82599(hw, pfc_en, prio_tc);
 297        default:
 298                break;
 299        }
 300        return -EINVAL;
 301}
 302
 303s32 ixgbe_dcb_hw_ets(struct ixgbe_hw *hw, struct ieee_ets *ets, int max_frame)
 304{
 305        __u16 refill[IEEE_8021QAZ_MAX_TCS], max[IEEE_8021QAZ_MAX_TCS];
 306        __u8 prio_type[IEEE_8021QAZ_MAX_TCS];
 307        int i;
 308
 309        /* naively give each TC a bwg to map onto CEE hardware */
 310        __u8 bwg_id[IEEE_8021QAZ_MAX_TCS] = {0, 1, 2, 3, 4, 5, 6, 7};
 311
 312        /* Map TSA onto CEE prio type */
 313        for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
 314                switch (ets->tc_tsa[i]) {
 315                case IEEE_8021QAZ_TSA_STRICT:
 316                        prio_type[i] = 2;
 317                        break;
 318                case IEEE_8021QAZ_TSA_ETS:
 319                        prio_type[i] = 0;
 320                        break;
 321                default:
 322                        /* Hardware only supports priority strict or
 323                         * ETS transmission selection algorithms if
 324                         * we receive some other value from dcbnl
 325                         * throw an error
 326                         */
 327                        return -EINVAL;
 328                }
 329        }
 330
 331        ixgbe_ieee_credits(ets->tc_tx_bw, refill, max, max_frame);
 332        return ixgbe_dcb_hw_ets_config(hw, refill, max,
 333                                       bwg_id, prio_type, ets->prio_tc);
 334}
 335
 336s32 ixgbe_dcb_hw_ets_config(struct ixgbe_hw *hw,
 337                            u16 *refill, u16 *max, u8 *bwg_id,
 338                            u8 *prio_type, u8 *prio_tc)
 339{
 340        switch (hw->mac.type) {
 341        case ixgbe_mac_82598EB:
 342                ixgbe_dcb_config_rx_arbiter_82598(hw, refill, max,
 343                                                        prio_type);
 344                ixgbe_dcb_config_tx_desc_arbiter_82598(hw, refill, max,
 345                                                             bwg_id, prio_type);
 346                ixgbe_dcb_config_tx_data_arbiter_82598(hw, refill, max,
 347                                                             bwg_id, prio_type);
 348                break;
 349        case ixgbe_mac_82599EB:
 350        case ixgbe_mac_X540:
 351        case ixgbe_mac_X550:
 352        case ixgbe_mac_X550EM_x:
 353        case ixgbe_mac_x550em_a:
 354                ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max,
 355                                                  bwg_id, prio_type, prio_tc);
 356                ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max,
 357                                                       bwg_id, prio_type);
 358                ixgbe_dcb_config_tx_data_arbiter_82599(hw, refill, max, bwg_id,
 359                                                       prio_type, prio_tc);
 360                break;
 361        default:
 362                break;
 363        }
 364        return 0;
 365}
 366
 367static void ixgbe_dcb_read_rtrup2tc_82599(struct ixgbe_hw *hw, u8 *map)
 368{
 369        u32 reg, i;
 370
 371        reg = IXGBE_READ_REG(hw, IXGBE_RTRUP2TC);
 372        for (i = 0; i < MAX_USER_PRIORITY; i++)
 373                map[i] = IXGBE_RTRUP2TC_UP_MASK &
 374                        (reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT));
 375}
 376
 377void ixgbe_dcb_read_rtrup2tc(struct ixgbe_hw *hw, u8 *map)
 378{
 379        switch (hw->mac.type) {
 380        case ixgbe_mac_82599EB:
 381        case ixgbe_mac_X540:
 382        case ixgbe_mac_X550:
 383        case ixgbe_mac_X550EM_x:
 384        case ixgbe_mac_x550em_a:
 385                ixgbe_dcb_read_rtrup2tc_82599(hw, map);
 386                break;
 387        default:
 388                break;
 389        }
 390}
 391