xref: /openbmc/linux/drivers/net/ethernet/intel/fm10k/fm10k_dcbnl.c (revision 8be98d2f2a0a262f8bf8a0bc1fdf522b3c7aab17)
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