linux/drivers/net/ethernet/intel/fm10k/fm10k_dcbnl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Intel(R) Ethernet Switch Host Interface Driver
   3 * Copyright(c) 2013 - 2016 Intel Corporation.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms and conditions of the GNU General Public License,
   7 * version 2, as published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  12 * more details.
  13 *
  14 * The full GNU General Public License is included in this distribution in
  15 * the file called "COPYING".
  16 *
  17 * Contact Information:
  18 * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
  19 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  20 */
  21
  22#include "fm10k.h"
  23
  24/**
  25 * fm10k_dcbnl_ieee_getets - get the ETS configuration for the device
  26 * @dev: netdev interface for the device
  27 * @ets: ETS structure to push configuration to
  28 **/
  29static int fm10k_dcbnl_ieee_getets(struct net_device *dev, struct ieee_ets *ets)
  30{
  31        int i;
  32
  33        /* we support 8 TCs in all modes */
  34        ets->ets_cap = IEEE_8021QAZ_MAX_TCS;
  35        ets->cbs = 0;
  36
  37        /* we only support strict priority and cannot do traffic shaping */
  38        memset(ets->tc_tx_bw, 0, sizeof(ets->tc_tx_bw));
  39        memset(ets->tc_rx_bw, 0, sizeof(ets->tc_rx_bw));
  40        memset(ets->tc_tsa, IEEE_8021QAZ_TSA_STRICT, sizeof(ets->tc_tsa));
  41
  42        /* populate the prio map based on the netdev */
  43        for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
  44                ets->prio_tc[i] = netdev_get_prio_tc_map(dev, i);
  45
  46        return 0;
  47}
  48
  49/**
  50 * fm10k_dcbnl_ieee_setets - set the ETS configuration for the device
  51 * @dev: netdev interface for the device
  52 * @ets: ETS structure to pull configuration from
  53 **/
  54static int fm10k_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets)
  55{
  56        u8 num_tc = 0;
  57        int i, err;
  58
  59        /* verify type and determine num_tcs needed */
  60        for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
  61                if (ets->tc_tx_bw[i] || ets->tc_rx_bw[i])
  62                        return -EINVAL;
  63                if (ets->tc_tsa[i] != IEEE_8021QAZ_TSA_STRICT)
  64                        return -EINVAL;
  65                if (ets->prio_tc[i] > num_tc)
  66                        num_tc = ets->prio_tc[i];
  67        }
  68
  69        /* if requested TC is greater than 0 then num_tcs is max + 1 */
  70        if (num_tc)
  71                num_tc++;
  72
  73        if (num_tc > IEEE_8021QAZ_MAX_TCS)
  74                return -EINVAL;
  75
  76        /* update TC hardware mapping if necessary */
  77        if (num_tc != netdev_get_num_tc(dev)) {
  78                err = fm10k_setup_tc(dev, num_tc);
  79                if (err)
  80                        return err;
  81        }
  82
  83        /* update priority mapping */
  84        for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
  85                netdev_set_prio_tc_map(dev, i, ets->prio_tc[i]);
  86
  87        return 0;
  88}
  89
  90/**
  91 * fm10k_dcbnl_ieee_getpfc - get the PFC configuration for the device
  92 * @dev: netdev interface for the device
  93 * @pfc: PFC structure to push configuration to
  94 **/
  95static int fm10k_dcbnl_ieee_getpfc(struct net_device *dev, struct ieee_pfc *pfc)
  96{
  97        struct fm10k_intfc *interface = netdev_priv(dev);
  98
  99        /* record flow control max count and state of TCs */
 100        pfc->pfc_cap = IEEE_8021QAZ_MAX_TCS;
 101        pfc->pfc_en = interface->pfc_en;
 102
 103        return 0;
 104}
 105
 106/**
 107 * fm10k_dcbnl_ieee_setpfc - set the PFC configuration for the device
 108 * @dev: netdev interface for the device
 109 * @pfc: PFC structure to pull configuration from
 110 **/
 111static int fm10k_dcbnl_ieee_setpfc(struct net_device *dev, struct ieee_pfc *pfc)
 112{
 113        struct fm10k_intfc *interface = netdev_priv(dev);
 114
 115        /* record PFC configuration to interface */
 116        interface->pfc_en = pfc->pfc_en;
 117
 118        /* if we are running update the drop_en state for all queues */
 119        if (netif_running(dev))
 120                fm10k_update_rx_drop_en(interface);
 121
 122        return 0;
 123}
 124
 125/**
 126 * fm10k_dcbnl_ieee_getdcbx - get the DCBX configuration for the device
 127 * @dev: netdev interface for the device
 128 *
 129 * Returns that we support only IEEE DCB for this interface
 130 **/
 131static u8 fm10k_dcbnl_getdcbx(struct net_device __always_unused *dev)
 132{
 133        return DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE;
 134}
 135
 136/**
 137 * fm10k_dcbnl_ieee_setdcbx - get the DCBX configuration for the device
 138 * @dev: netdev interface for the device
 139 * @mode: new mode for this device
 140 *
 141 * Returns error on attempt to enable anything but IEEE DCB for this interface
 142 **/
 143static u8 fm10k_dcbnl_setdcbx(struct net_device __always_unused *dev, u8 mode)
 144{
 145        return (mode != (DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE)) ? 1 : 0;
 146}
 147
 148static const struct dcbnl_rtnl_ops fm10k_dcbnl_ops = {
 149        .ieee_getets    = fm10k_dcbnl_ieee_getets,
 150        .ieee_setets    = fm10k_dcbnl_ieee_setets,
 151        .ieee_getpfc    = fm10k_dcbnl_ieee_getpfc,
 152        .ieee_setpfc    = fm10k_dcbnl_ieee_setpfc,
 153
 154        .getdcbx        = fm10k_dcbnl_getdcbx,
 155        .setdcbx        = fm10k_dcbnl_setdcbx,
 156};
 157
 158/**
 159 * fm10k_dcbnl_set_ops - Configures dcbnl ops pointer for netdev
 160 * @dev: netdev interface for the device
 161 *
 162 * Enables PF for DCB by assigning DCBNL ops pointer.
 163 **/
 164void fm10k_dcbnl_set_ops(struct net_device *dev)
 165{
 166        struct fm10k_intfc *interface = netdev_priv(dev);
 167        struct fm10k_hw *hw = &interface->hw;
 168
 169        if (hw->mac.type == fm10k_mac_pf)
 170                dev->dcbnl_ops = &fm10k_dcbnl_ops;
 171}
 172