162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright(c) 2013 - 2019 Intel Corporation. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include "fm10k.h" 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci/** 762306a36Sopenharmony_ci * fm10k_dcbnl_ieee_getets - get the ETS configuration for the device 862306a36Sopenharmony_ci * @dev: netdev interface for the device 962306a36Sopenharmony_ci * @ets: ETS structure to push configuration to 1062306a36Sopenharmony_ci **/ 1162306a36Sopenharmony_cistatic int fm10k_dcbnl_ieee_getets(struct net_device *dev, struct ieee_ets *ets) 1262306a36Sopenharmony_ci{ 1362306a36Sopenharmony_ci int i; 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci /* we support 8 TCs in all modes */ 1662306a36Sopenharmony_ci ets->ets_cap = IEEE_8021QAZ_MAX_TCS; 1762306a36Sopenharmony_ci ets->cbs = 0; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci /* we only support strict priority and cannot do traffic shaping */ 2062306a36Sopenharmony_ci memset(ets->tc_tx_bw, 0, sizeof(ets->tc_tx_bw)); 2162306a36Sopenharmony_ci memset(ets->tc_rx_bw, 0, sizeof(ets->tc_rx_bw)); 2262306a36Sopenharmony_ci memset(ets->tc_tsa, IEEE_8021QAZ_TSA_STRICT, sizeof(ets->tc_tsa)); 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci /* populate the prio map based on the netdev */ 2562306a36Sopenharmony_ci for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) 2662306a36Sopenharmony_ci ets->prio_tc[i] = netdev_get_prio_tc_map(dev, i); 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci return 0; 2962306a36Sopenharmony_ci} 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci/** 3262306a36Sopenharmony_ci * fm10k_dcbnl_ieee_setets - set the ETS configuration for the device 3362306a36Sopenharmony_ci * @dev: netdev interface for the device 3462306a36Sopenharmony_ci * @ets: ETS structure to pull configuration from 3562306a36Sopenharmony_ci **/ 3662306a36Sopenharmony_cistatic int fm10k_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci u8 num_tc = 0; 3962306a36Sopenharmony_ci int i; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci /* verify type and determine num_tcs needed */ 4262306a36Sopenharmony_ci for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { 4362306a36Sopenharmony_ci if (ets->tc_tx_bw[i] || ets->tc_rx_bw[i]) 4462306a36Sopenharmony_ci return -EINVAL; 4562306a36Sopenharmony_ci if (ets->tc_tsa[i] != IEEE_8021QAZ_TSA_STRICT) 4662306a36Sopenharmony_ci return -EINVAL; 4762306a36Sopenharmony_ci if (ets->prio_tc[i] > num_tc) 4862306a36Sopenharmony_ci num_tc = ets->prio_tc[i]; 4962306a36Sopenharmony_ci } 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci /* if requested TC is greater than 0 then num_tcs is max + 1 */ 5262306a36Sopenharmony_ci if (num_tc) 5362306a36Sopenharmony_ci num_tc++; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci if (num_tc > IEEE_8021QAZ_MAX_TCS) 5662306a36Sopenharmony_ci return -EINVAL; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci /* update TC hardware mapping if necessary */ 5962306a36Sopenharmony_ci if (num_tc != netdev_get_num_tc(dev)) { 6062306a36Sopenharmony_ci int err = fm10k_setup_tc(dev, num_tc); 6162306a36Sopenharmony_ci if (err) 6262306a36Sopenharmony_ci return err; 6362306a36Sopenharmony_ci } 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci /* update priority mapping */ 6662306a36Sopenharmony_ci for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) 6762306a36Sopenharmony_ci netdev_set_prio_tc_map(dev, i, ets->prio_tc[i]); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci return 0; 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci/** 7362306a36Sopenharmony_ci * fm10k_dcbnl_ieee_getpfc - get the PFC configuration for the device 7462306a36Sopenharmony_ci * @dev: netdev interface for the device 7562306a36Sopenharmony_ci * @pfc: PFC structure to push configuration to 7662306a36Sopenharmony_ci **/ 7762306a36Sopenharmony_cistatic int fm10k_dcbnl_ieee_getpfc(struct net_device *dev, struct ieee_pfc *pfc) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci struct fm10k_intfc *interface = netdev_priv(dev); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci /* record flow control max count and state of TCs */ 8262306a36Sopenharmony_ci pfc->pfc_cap = IEEE_8021QAZ_MAX_TCS; 8362306a36Sopenharmony_ci pfc->pfc_en = interface->pfc_en; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci return 0; 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci/** 8962306a36Sopenharmony_ci * fm10k_dcbnl_ieee_setpfc - set the PFC configuration for the device 9062306a36Sopenharmony_ci * @dev: netdev interface for the device 9162306a36Sopenharmony_ci * @pfc: PFC structure to pull configuration from 9262306a36Sopenharmony_ci **/ 9362306a36Sopenharmony_cistatic int fm10k_dcbnl_ieee_setpfc(struct net_device *dev, struct ieee_pfc *pfc) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci struct fm10k_intfc *interface = netdev_priv(dev); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci /* record PFC configuration to interface */ 9862306a36Sopenharmony_ci interface->pfc_en = pfc->pfc_en; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci /* if we are running update the drop_en state for all queues */ 10162306a36Sopenharmony_ci if (netif_running(dev)) 10262306a36Sopenharmony_ci fm10k_update_rx_drop_en(interface); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci return 0; 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci/** 10862306a36Sopenharmony_ci * fm10k_dcbnl_getdcbx - get the DCBX configuration for the device 10962306a36Sopenharmony_ci * @dev: netdev interface for the device 11062306a36Sopenharmony_ci * 11162306a36Sopenharmony_ci * Returns that we support only IEEE DCB for this interface 11262306a36Sopenharmony_ci **/ 11362306a36Sopenharmony_cistatic u8 fm10k_dcbnl_getdcbx(struct net_device __always_unused *dev) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci return DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE; 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci/** 11962306a36Sopenharmony_ci * fm10k_dcbnl_setdcbx - get the DCBX configuration for the device 12062306a36Sopenharmony_ci * @dev: netdev interface for the device 12162306a36Sopenharmony_ci * @mode: new mode for this device 12262306a36Sopenharmony_ci * 12362306a36Sopenharmony_ci * Returns error on attempt to enable anything but IEEE DCB for this interface 12462306a36Sopenharmony_ci **/ 12562306a36Sopenharmony_cistatic u8 fm10k_dcbnl_setdcbx(struct net_device __always_unused *dev, u8 mode) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci return (mode != (DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE)) ? 1 : 0; 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistatic const struct dcbnl_rtnl_ops fm10k_dcbnl_ops = { 13162306a36Sopenharmony_ci .ieee_getets = fm10k_dcbnl_ieee_getets, 13262306a36Sopenharmony_ci .ieee_setets = fm10k_dcbnl_ieee_setets, 13362306a36Sopenharmony_ci .ieee_getpfc = fm10k_dcbnl_ieee_getpfc, 13462306a36Sopenharmony_ci .ieee_setpfc = fm10k_dcbnl_ieee_setpfc, 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci .getdcbx = fm10k_dcbnl_getdcbx, 13762306a36Sopenharmony_ci .setdcbx = fm10k_dcbnl_setdcbx, 13862306a36Sopenharmony_ci}; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci/** 14162306a36Sopenharmony_ci * fm10k_dcbnl_set_ops - Configures dcbnl ops pointer for netdev 14262306a36Sopenharmony_ci * @dev: netdev interface for the device 14362306a36Sopenharmony_ci * 14462306a36Sopenharmony_ci * Enables PF for DCB by assigning DCBNL ops pointer. 14562306a36Sopenharmony_ci **/ 14662306a36Sopenharmony_civoid fm10k_dcbnl_set_ops(struct net_device *dev) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci struct fm10k_intfc *interface = netdev_priv(dev); 14962306a36Sopenharmony_ci struct fm10k_hw *hw = &interface->hw; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci if (hw->mac.type == fm10k_mac_pf) 15262306a36Sopenharmony_ci dev->dcbnl_ops = &fm10k_dcbnl_ops; 15362306a36Sopenharmony_ci} 154