1ae06c70bSJeff Kirsher // SPDX-License-Identifier: GPL-2.0
230b1b498SJacob Keller /* Copyright(c) 2013 - 2019 Intel Corporation. */
39f801abcSAlexander Duyck
49f801abcSAlexander Duyck #include "fm10k.h"
59f801abcSAlexander Duyck
69f801abcSAlexander Duyck /**
79f801abcSAlexander Duyck * fm10k_dcbnl_ieee_getets - get the ETS configuration for the device
89f801abcSAlexander Duyck * @dev: netdev interface for the device
99f801abcSAlexander Duyck * @ets: ETS structure to push configuration to
109f801abcSAlexander Duyck **/
fm10k_dcbnl_ieee_getets(struct net_device * dev,struct ieee_ets * ets)119f801abcSAlexander Duyck static int fm10k_dcbnl_ieee_getets(struct net_device *dev, struct ieee_ets *ets)
129f801abcSAlexander Duyck {
139f801abcSAlexander Duyck int i;
149f801abcSAlexander Duyck
159f801abcSAlexander Duyck /* we support 8 TCs in all modes */
169f801abcSAlexander Duyck ets->ets_cap = IEEE_8021QAZ_MAX_TCS;
179f801abcSAlexander Duyck ets->cbs = 0;
189f801abcSAlexander Duyck
199f801abcSAlexander Duyck /* we only support strict priority and cannot do traffic shaping */
209f801abcSAlexander Duyck memset(ets->tc_tx_bw, 0, sizeof(ets->tc_tx_bw));
219f801abcSAlexander Duyck memset(ets->tc_rx_bw, 0, sizeof(ets->tc_rx_bw));
229f801abcSAlexander Duyck memset(ets->tc_tsa, IEEE_8021QAZ_TSA_STRICT, sizeof(ets->tc_tsa));
239f801abcSAlexander Duyck
249f801abcSAlexander Duyck /* populate the prio map based on the netdev */
259f801abcSAlexander Duyck for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
269f801abcSAlexander Duyck ets->prio_tc[i] = netdev_get_prio_tc_map(dev, i);
279f801abcSAlexander Duyck
289f801abcSAlexander Duyck return 0;
299f801abcSAlexander Duyck }
309f801abcSAlexander Duyck
319f801abcSAlexander Duyck /**
329f801abcSAlexander Duyck * fm10k_dcbnl_ieee_setets - set the ETS configuration for the device
339f801abcSAlexander Duyck * @dev: netdev interface for the device
349f801abcSAlexander Duyck * @ets: ETS structure to pull configuration from
359f801abcSAlexander Duyck **/
fm10k_dcbnl_ieee_setets(struct net_device * dev,struct ieee_ets * ets)369f801abcSAlexander Duyck static int fm10k_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets)
379f801abcSAlexander Duyck {
389f801abcSAlexander Duyck u8 num_tc = 0;
3930b1b498SJacob Keller int i;
409f801abcSAlexander Duyck
419f801abcSAlexander Duyck /* verify type and determine num_tcs needed */
429f801abcSAlexander Duyck for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
439f801abcSAlexander Duyck if (ets->tc_tx_bw[i] || ets->tc_rx_bw[i])
449f801abcSAlexander Duyck return -EINVAL;
459f801abcSAlexander Duyck if (ets->tc_tsa[i] != IEEE_8021QAZ_TSA_STRICT)
469f801abcSAlexander Duyck return -EINVAL;
479f801abcSAlexander Duyck if (ets->prio_tc[i] > num_tc)
489f801abcSAlexander Duyck num_tc = ets->prio_tc[i];
499f801abcSAlexander Duyck }
509f801abcSAlexander Duyck
519f801abcSAlexander Duyck /* if requested TC is greater than 0 then num_tcs is max + 1 */
529f801abcSAlexander Duyck if (num_tc)
539f801abcSAlexander Duyck num_tc++;
549f801abcSAlexander Duyck
559f801abcSAlexander Duyck if (num_tc > IEEE_8021QAZ_MAX_TCS)
569f801abcSAlexander Duyck return -EINVAL;
579f801abcSAlexander Duyck
589f801abcSAlexander Duyck /* update TC hardware mapping if necessary */
599f801abcSAlexander Duyck if (num_tc != netdev_get_num_tc(dev)) {
6030b1b498SJacob Keller int err = fm10k_setup_tc(dev, num_tc);
619f801abcSAlexander Duyck if (err)
629f801abcSAlexander Duyck return err;
639f801abcSAlexander Duyck }
649f801abcSAlexander Duyck
659f801abcSAlexander Duyck /* update priority mapping */
669f801abcSAlexander Duyck for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
679f801abcSAlexander Duyck netdev_set_prio_tc_map(dev, i, ets->prio_tc[i]);
689f801abcSAlexander Duyck
699f801abcSAlexander Duyck return 0;
709f801abcSAlexander Duyck }
719f801abcSAlexander Duyck
729f801abcSAlexander Duyck /**
739f801abcSAlexander Duyck * fm10k_dcbnl_ieee_getpfc - get the PFC configuration for the device
749f801abcSAlexander Duyck * @dev: netdev interface for the device
759f801abcSAlexander Duyck * @pfc: PFC structure to push configuration to
769f801abcSAlexander Duyck **/
fm10k_dcbnl_ieee_getpfc(struct net_device * dev,struct ieee_pfc * pfc)779f801abcSAlexander Duyck static int fm10k_dcbnl_ieee_getpfc(struct net_device *dev, struct ieee_pfc *pfc)
789f801abcSAlexander Duyck {
799f801abcSAlexander Duyck struct fm10k_intfc *interface = netdev_priv(dev);
809f801abcSAlexander Duyck
819f801abcSAlexander Duyck /* record flow control max count and state of TCs */
829f801abcSAlexander Duyck pfc->pfc_cap = IEEE_8021QAZ_MAX_TCS;
839f801abcSAlexander Duyck pfc->pfc_en = interface->pfc_en;
849f801abcSAlexander Duyck
859f801abcSAlexander Duyck return 0;
869f801abcSAlexander Duyck }
879f801abcSAlexander Duyck
889f801abcSAlexander Duyck /**
899f801abcSAlexander Duyck * fm10k_dcbnl_ieee_setpfc - set the PFC configuration for the device
909f801abcSAlexander Duyck * @dev: netdev interface for the device
919f801abcSAlexander Duyck * @pfc: PFC structure to pull configuration from
929f801abcSAlexander Duyck **/
fm10k_dcbnl_ieee_setpfc(struct net_device * dev,struct ieee_pfc * pfc)939f801abcSAlexander Duyck static int fm10k_dcbnl_ieee_setpfc(struct net_device *dev, struct ieee_pfc *pfc)
949f801abcSAlexander Duyck {
959f801abcSAlexander Duyck struct fm10k_intfc *interface = netdev_priv(dev);
969f801abcSAlexander Duyck
979f801abcSAlexander Duyck /* record PFC configuration to interface */
989f801abcSAlexander Duyck interface->pfc_en = pfc->pfc_en;
999f801abcSAlexander Duyck
1009f801abcSAlexander Duyck /* if we are running update the drop_en state for all queues */
1019f801abcSAlexander Duyck if (netif_running(dev))
1029f801abcSAlexander Duyck fm10k_update_rx_drop_en(interface);
1039f801abcSAlexander Duyck
1049f801abcSAlexander Duyck return 0;
1059f801abcSAlexander Duyck }
1069f801abcSAlexander Duyck
1079f801abcSAlexander Duyck /**
108*262de08fSJesse Brandeburg * fm10k_dcbnl_getdcbx - get the DCBX configuration for the device
1099f801abcSAlexander Duyck * @dev: netdev interface for the device
1109f801abcSAlexander Duyck *
1119f801abcSAlexander Duyck * Returns that we support only IEEE DCB for this interface
1129f801abcSAlexander Duyck **/
fm10k_dcbnl_getdcbx(struct net_device __always_unused * dev)113de445199SJeff Kirsher static u8 fm10k_dcbnl_getdcbx(struct net_device __always_unused *dev)
1149f801abcSAlexander Duyck {
1159f801abcSAlexander Duyck return DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE;
1169f801abcSAlexander Duyck }
1179f801abcSAlexander Duyck
1189f801abcSAlexander Duyck /**
119*262de08fSJesse Brandeburg * fm10k_dcbnl_setdcbx - get the DCBX configuration for the device
1209f801abcSAlexander Duyck * @dev: netdev interface for the device
1219f801abcSAlexander Duyck * @mode: new mode for this device
1229f801abcSAlexander Duyck *
1239f801abcSAlexander Duyck * Returns error on attempt to enable anything but IEEE DCB for this interface
1249f801abcSAlexander Duyck **/
fm10k_dcbnl_setdcbx(struct net_device __always_unused * dev,u8 mode)125de445199SJeff Kirsher static u8 fm10k_dcbnl_setdcbx(struct net_device __always_unused *dev, u8 mode)
1269f801abcSAlexander Duyck {
1279f801abcSAlexander Duyck return (mode != (DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE)) ? 1 : 0;
1289f801abcSAlexander Duyck }
1299f801abcSAlexander Duyck
1309f801abcSAlexander Duyck static const struct dcbnl_rtnl_ops fm10k_dcbnl_ops = {
1319f801abcSAlexander Duyck .ieee_getets = fm10k_dcbnl_ieee_getets,
1329f801abcSAlexander Duyck .ieee_setets = fm10k_dcbnl_ieee_setets,
1339f801abcSAlexander Duyck .ieee_getpfc = fm10k_dcbnl_ieee_getpfc,
1349f801abcSAlexander Duyck .ieee_setpfc = fm10k_dcbnl_ieee_setpfc,
1359f801abcSAlexander Duyck
1369f801abcSAlexander Duyck .getdcbx = fm10k_dcbnl_getdcbx,
1379f801abcSAlexander Duyck .setdcbx = fm10k_dcbnl_setdcbx,
1389f801abcSAlexander Duyck };
1399f801abcSAlexander Duyck
1409f801abcSAlexander Duyck /**
1419f801abcSAlexander Duyck * fm10k_dcbnl_set_ops - Configures dcbnl ops pointer for netdev
1429f801abcSAlexander Duyck * @dev: netdev interface for the device
1439f801abcSAlexander Duyck *
1449f801abcSAlexander Duyck * Enables PF for DCB by assigning DCBNL ops pointer.
1459f801abcSAlexander Duyck **/
fm10k_dcbnl_set_ops(struct net_device * dev)1469f801abcSAlexander Duyck void fm10k_dcbnl_set_ops(struct net_device *dev)
1479f801abcSAlexander Duyck {
1489f801abcSAlexander Duyck struct fm10k_intfc *interface = netdev_priv(dev);
1499f801abcSAlexander Duyck struct fm10k_hw *hw = &interface->hw;
1509f801abcSAlexander Duyck
1519f801abcSAlexander Duyck if (hw->mac.type == fm10k_mac_pf)
1529f801abcSAlexander Duyck dev->dcbnl_ops = &fm10k_dcbnl_ops;
1539f801abcSAlexander Duyck }
154