cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ice_dcb_nl.c (28964B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright (c) 2019, Intel Corporation. */
      3
      4#include "ice.h"
      5#include "ice_dcb.h"
      6#include "ice_dcb_lib.h"
      7#include "ice_dcb_nl.h"
      8#include <net/dcbnl.h>
      9
     10/**
     11 * ice_dcbnl_devreset - perform enough of a ifdown/ifup to sync DCBNL info
     12 * @netdev: device associated with interface that needs reset
     13 */
     14static void ice_dcbnl_devreset(struct net_device *netdev)
     15{
     16	struct ice_pf *pf = ice_netdev_to_pf(netdev);
     17
     18	while (ice_is_reset_in_progress(pf->state))
     19		usleep_range(1000, 2000);
     20
     21	dev_close(netdev);
     22	netdev_state_change(netdev);
     23	dev_open(netdev, NULL);
     24	netdev_state_change(netdev);
     25}
     26
     27/**
     28 * ice_dcbnl_getets - retrieve local ETS configuration
     29 * @netdev: the relevant netdev
     30 * @ets: struct to hold ETS configuration
     31 */
     32static int ice_dcbnl_getets(struct net_device *netdev, struct ieee_ets *ets)
     33{
     34	struct ice_dcbx_cfg *dcbxcfg;
     35	struct ice_pf *pf;
     36
     37	pf = ice_netdev_to_pf(netdev);
     38	dcbxcfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg;
     39
     40	ets->willing = dcbxcfg->etscfg.willing;
     41	ets->ets_cap = dcbxcfg->etscfg.maxtcs;
     42	ets->cbs = dcbxcfg->etscfg.cbs;
     43	memcpy(ets->tc_tx_bw, dcbxcfg->etscfg.tcbwtable, sizeof(ets->tc_tx_bw));
     44	memcpy(ets->tc_rx_bw, dcbxcfg->etscfg.tcbwtable, sizeof(ets->tc_rx_bw));
     45	memcpy(ets->tc_tsa, dcbxcfg->etscfg.tsatable, sizeof(ets->tc_tsa));
     46	memcpy(ets->prio_tc, dcbxcfg->etscfg.prio_table, sizeof(ets->prio_tc));
     47	memcpy(ets->tc_reco_bw, dcbxcfg->etsrec.tcbwtable,
     48	       sizeof(ets->tc_reco_bw));
     49	memcpy(ets->tc_reco_tsa, dcbxcfg->etsrec.tsatable,
     50	       sizeof(ets->tc_reco_tsa));
     51	memcpy(ets->reco_prio_tc, dcbxcfg->etscfg.prio_table,
     52	       sizeof(ets->reco_prio_tc));
     53
     54	return 0;
     55}
     56
     57/**
     58 * ice_dcbnl_setets - set IEEE ETS configuration
     59 * @netdev: pointer to relevant netdev
     60 * @ets: struct to hold ETS configuration
     61 */
     62static int ice_dcbnl_setets(struct net_device *netdev, struct ieee_ets *ets)
     63{
     64	struct ice_pf *pf = ice_netdev_to_pf(netdev);
     65	struct ice_dcbx_cfg *new_cfg;
     66	int bwcfg = 0, bwrec = 0;
     67	int err, i;
     68
     69	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
     70	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
     71		return -EINVAL;
     72
     73	new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg;
     74
     75	mutex_lock(&pf->tc_mutex);
     76
     77	new_cfg->etscfg.willing = ets->willing;
     78	new_cfg->etscfg.cbs = ets->cbs;
     79	ice_for_each_traffic_class(i) {
     80		new_cfg->etscfg.tcbwtable[i] = ets->tc_tx_bw[i];
     81		bwcfg += ets->tc_tx_bw[i];
     82		new_cfg->etscfg.tsatable[i] = ets->tc_tsa[i];
     83		if (new_cfg->pfc_mode == ICE_QOS_MODE_VLAN) {
     84			/* in DSCP mode up->tc mapping cannot change */
     85			new_cfg->etscfg.prio_table[i] = ets->prio_tc[i];
     86			new_cfg->etsrec.prio_table[i] = ets->reco_prio_tc[i];
     87		}
     88		new_cfg->etsrec.tcbwtable[i] = ets->tc_reco_bw[i];
     89		bwrec += ets->tc_reco_bw[i];
     90		new_cfg->etsrec.tsatable[i] = ets->tc_reco_tsa[i];
     91	}
     92
     93	if (ice_dcb_bwchk(pf, new_cfg)) {
     94		err = -EINVAL;
     95		goto ets_out;
     96	}
     97
     98	new_cfg->etscfg.maxtcs = pf->hw.func_caps.common_cap.maxtc;
     99
    100	if (!bwcfg)
    101		new_cfg->etscfg.tcbwtable[0] = 100;
    102
    103	if (!bwrec)
    104		new_cfg->etsrec.tcbwtable[0] = 100;
    105
    106	err = ice_pf_dcb_cfg(pf, new_cfg, true);
    107	/* return of zero indicates new cfg applied */
    108	if (err == ICE_DCB_HW_CHG_RST)
    109		ice_dcbnl_devreset(netdev);
    110	if (err == ICE_DCB_NO_HW_CHG)
    111		err = ICE_DCB_HW_CHG_RST;
    112
    113ets_out:
    114	mutex_unlock(&pf->tc_mutex);
    115	return err;
    116}
    117
    118/**
    119 * ice_dcbnl_getnumtcs - Get max number of traffic classes supported
    120 * @dev: pointer to netdev struct
    121 * @tcid: TC ID
    122 * @num: total number of TCs supported by the adapter
    123 *
    124 * Return the total number of TCs supported
    125 */
    126static int
    127ice_dcbnl_getnumtcs(struct net_device *dev, int __always_unused tcid, u8 *num)
    128{
    129	struct ice_pf *pf = ice_netdev_to_pf(dev);
    130
    131	if (!test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags))
    132		return -EINVAL;
    133
    134	*num = pf->hw.func_caps.common_cap.maxtc;
    135	return 0;
    136}
    137
    138/**
    139 * ice_dcbnl_getdcbx - retrieve current DCBX capability
    140 * @netdev: pointer to the netdev struct
    141 */
    142static u8 ice_dcbnl_getdcbx(struct net_device *netdev)
    143{
    144	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    145
    146	return pf->dcbx_cap;
    147}
    148
    149/**
    150 * ice_dcbnl_setdcbx - set required DCBX capability
    151 * @netdev: the corresponding netdev
    152 * @mode: required mode
    153 */
    154static u8 ice_dcbnl_setdcbx(struct net_device *netdev, u8 mode)
    155{
    156	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    157	struct ice_qos_cfg *qos_cfg;
    158
    159	/* if FW LLDP agent is running, DCBNL not allowed to change mode */
    160	if (test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags))
    161		return ICE_DCB_NO_HW_CHG;
    162
    163	/* No support for LLD_MANAGED modes or CEE+IEEE */
    164	if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
    165	    ((mode & DCB_CAP_DCBX_VER_IEEE) && (mode & DCB_CAP_DCBX_VER_CEE)) ||
    166	    !(mode & DCB_CAP_DCBX_HOST))
    167		return ICE_DCB_NO_HW_CHG;
    168
    169	/* Already set to the given mode no change */
    170	if (mode == pf->dcbx_cap)
    171		return ICE_DCB_NO_HW_CHG;
    172
    173	qos_cfg = &pf->hw.port_info->qos_cfg;
    174
    175	/* DSCP configuration is not DCBx negotiated */
    176	if (qos_cfg->local_dcbx_cfg.pfc_mode == ICE_QOS_MODE_DSCP)
    177		return ICE_DCB_NO_HW_CHG;
    178
    179	pf->dcbx_cap = mode;
    180
    181	if (mode & DCB_CAP_DCBX_VER_CEE)
    182		qos_cfg->local_dcbx_cfg.dcbx_mode = ICE_DCBX_MODE_CEE;
    183	else
    184		qos_cfg->local_dcbx_cfg.dcbx_mode = ICE_DCBX_MODE_IEEE;
    185
    186	dev_info(ice_pf_to_dev(pf), "DCBx mode = 0x%x\n", mode);
    187	return ICE_DCB_HW_CHG_RST;
    188}
    189
    190/**
    191 * ice_dcbnl_get_perm_hw_addr - MAC address used by DCBX
    192 * @netdev: pointer to netdev struct
    193 * @perm_addr: buffer to return permanent MAC address
    194 */
    195static void ice_dcbnl_get_perm_hw_addr(struct net_device *netdev, u8 *perm_addr)
    196{
    197	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    198	struct ice_port_info *pi = pf->hw.port_info;
    199	int i, j;
    200
    201	memset(perm_addr, 0xff, MAX_ADDR_LEN);
    202
    203	for (i = 0; i < netdev->addr_len; i++)
    204		perm_addr[i] = pi->mac.perm_addr[i];
    205
    206	for (j = 0; j < netdev->addr_len; j++, i++)
    207		perm_addr[i] = pi->mac.perm_addr[j];
    208}
    209
    210/**
    211 * ice_get_pfc_delay - Retrieve PFC Link Delay
    212 * @hw: pointer to HW struct
    213 * @delay: holds the PFC Link Delay value
    214 */
    215static void ice_get_pfc_delay(struct ice_hw *hw, u16 *delay)
    216{
    217	u32 val;
    218
    219	val = rd32(hw, PRTDCB_GENC);
    220	*delay = (u16)((val & PRTDCB_GENC_PFCLDA_M) >> PRTDCB_GENC_PFCLDA_S);
    221}
    222
    223/**
    224 * ice_dcbnl_getpfc - retrieve local IEEE PFC config
    225 * @netdev: pointer to netdev struct
    226 * @pfc: struct to hold PFC info
    227 */
    228static int ice_dcbnl_getpfc(struct net_device *netdev, struct ieee_pfc *pfc)
    229{
    230	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    231	struct ice_port_info *pi = pf->hw.port_info;
    232	struct ice_dcbx_cfg *dcbxcfg;
    233	int i;
    234
    235	dcbxcfg = &pi->qos_cfg.local_dcbx_cfg;
    236	pfc->pfc_cap = dcbxcfg->pfc.pfccap;
    237	pfc->pfc_en = dcbxcfg->pfc.pfcena;
    238	pfc->mbc = dcbxcfg->pfc.mbc;
    239	ice_get_pfc_delay(&pf->hw, &pfc->delay);
    240
    241	ice_for_each_traffic_class(i) {
    242		pfc->requests[i] = pf->stats.priority_xoff_tx[i];
    243		pfc->indications[i] = pf->stats.priority_xoff_rx[i];
    244	}
    245
    246	return 0;
    247}
    248
    249/**
    250 * ice_dcbnl_setpfc - set local IEEE PFC config
    251 * @netdev: pointer to relevant netdev
    252 * @pfc: pointer to struct holding PFC config
    253 */
    254static int ice_dcbnl_setpfc(struct net_device *netdev, struct ieee_pfc *pfc)
    255{
    256	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    257	struct ice_dcbx_cfg *new_cfg;
    258	int err;
    259
    260	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
    261	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
    262		return -EINVAL;
    263
    264	mutex_lock(&pf->tc_mutex);
    265
    266	new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg;
    267
    268	if (pfc->pfc_cap)
    269		new_cfg->pfc.pfccap = pfc->pfc_cap;
    270	else
    271		new_cfg->pfc.pfccap = pf->hw.func_caps.common_cap.maxtc;
    272
    273	new_cfg->pfc.pfcena = pfc->pfc_en;
    274
    275	err = ice_pf_dcb_cfg(pf, new_cfg, true);
    276	if (err == ICE_DCB_HW_CHG_RST)
    277		ice_dcbnl_devreset(netdev);
    278	if (err == ICE_DCB_NO_HW_CHG)
    279		err = ICE_DCB_HW_CHG_RST;
    280	mutex_unlock(&pf->tc_mutex);
    281	return err;
    282}
    283
    284/**
    285 * ice_dcbnl_get_pfc_cfg - Get CEE PFC config
    286 * @netdev: pointer to netdev struct
    287 * @prio: corresponding user priority
    288 * @setting: the PFC setting for given priority
    289 */
    290static void
    291ice_dcbnl_get_pfc_cfg(struct net_device *netdev, int prio, u8 *setting)
    292{
    293	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    294	struct ice_port_info *pi = pf->hw.port_info;
    295
    296	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
    297	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
    298		return;
    299
    300	if (prio >= ICE_MAX_USER_PRIORITY)
    301		return;
    302
    303	*setting = (pi->qos_cfg.local_dcbx_cfg.pfc.pfcena >> prio) & 0x1;
    304	dev_dbg(ice_pf_to_dev(pf), "Get PFC Config up=%d, setting=%d, pfcenable=0x%x\n",
    305		prio, *setting, pi->qos_cfg.local_dcbx_cfg.pfc.pfcena);
    306}
    307
    308/**
    309 * ice_dcbnl_set_pfc_cfg - Set CEE PFC config
    310 * @netdev: the corresponding netdev
    311 * @prio: User Priority
    312 * @set: PFC setting to apply
    313 */
    314static void ice_dcbnl_set_pfc_cfg(struct net_device *netdev, int prio, u8 set)
    315{
    316	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    317	struct ice_dcbx_cfg *new_cfg;
    318
    319	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
    320	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
    321		return;
    322
    323	if (prio >= ICE_MAX_USER_PRIORITY)
    324		return;
    325
    326	new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg;
    327
    328	new_cfg->pfc.pfccap = pf->hw.func_caps.common_cap.maxtc;
    329	if (set)
    330		new_cfg->pfc.pfcena |= BIT(prio);
    331	else
    332		new_cfg->pfc.pfcena &= ~BIT(prio);
    333
    334	dev_dbg(ice_pf_to_dev(pf), "Set PFC config UP:%d set:%d pfcena:0x%x\n",
    335		prio, set, new_cfg->pfc.pfcena);
    336}
    337
    338/**
    339 * ice_dcbnl_getpfcstate - get CEE PFC mode
    340 * @netdev: pointer to netdev struct
    341 */
    342static u8 ice_dcbnl_getpfcstate(struct net_device *netdev)
    343{
    344	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    345	struct ice_port_info *pi = pf->hw.port_info;
    346
    347	/* Return enabled if any UP enabled for PFC */
    348	if (pi->qos_cfg.local_dcbx_cfg.pfc.pfcena)
    349		return 1;
    350
    351	return 0;
    352}
    353
    354/**
    355 * ice_dcbnl_getstate - get DCB enabled state
    356 * @netdev: pointer to netdev struct
    357 */
    358static u8 ice_dcbnl_getstate(struct net_device *netdev)
    359{
    360	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    361	u8 state = 0;
    362
    363	state = test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags);
    364
    365	dev_dbg(ice_pf_to_dev(pf), "DCB enabled state = %d\n", state);
    366	return state;
    367}
    368
    369/**
    370 * ice_dcbnl_setstate - Set CEE DCB state
    371 * @netdev: pointer to relevant netdev
    372 * @state: state value to set
    373 */
    374static u8 ice_dcbnl_setstate(struct net_device *netdev, u8 state)
    375{
    376	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    377
    378	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
    379	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
    380		return ICE_DCB_NO_HW_CHG;
    381
    382	/* Nothing to do */
    383	if (!!state == test_bit(ICE_FLAG_DCB_ENA, pf->flags))
    384		return ICE_DCB_NO_HW_CHG;
    385
    386	if (state) {
    387		set_bit(ICE_FLAG_DCB_ENA, pf->flags);
    388		memcpy(&pf->hw.port_info->qos_cfg.desired_dcbx_cfg,
    389		       &pf->hw.port_info->qos_cfg.local_dcbx_cfg,
    390		       sizeof(struct ice_dcbx_cfg));
    391	} else {
    392		clear_bit(ICE_FLAG_DCB_ENA, pf->flags);
    393	}
    394
    395	return ICE_DCB_HW_CHG;
    396}
    397
    398/**
    399 * ice_dcbnl_get_pg_tc_cfg_tx - get CEE PG Tx config
    400 * @netdev: pointer to netdev struct
    401 * @prio: the corresponding user priority
    402 * @prio_type: traffic priority type
    403 * @pgid: the BW group ID the traffic class belongs to
    404 * @bw_pct: BW percentage for the corresponding BWG
    405 * @up_map: prio mapped to corresponding TC
    406 */
    407static void
    408ice_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int prio,
    409			   u8 __always_unused *prio_type, u8 *pgid,
    410			   u8 __always_unused *bw_pct,
    411			   u8 __always_unused *up_map)
    412{
    413	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    414	struct ice_port_info *pi = pf->hw.port_info;
    415
    416	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
    417	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
    418		return;
    419
    420	if (prio >= ICE_MAX_USER_PRIORITY)
    421		return;
    422
    423	*pgid = pi->qos_cfg.local_dcbx_cfg.etscfg.prio_table[prio];
    424	dev_dbg(ice_pf_to_dev(pf), "Get PG config prio=%d tc=%d\n", prio,
    425		*pgid);
    426}
    427
    428/**
    429 * ice_dcbnl_set_pg_tc_cfg_tx - set CEE PG Tx config
    430 * @netdev: pointer to relevant netdev
    431 * @tc: the corresponding traffic class
    432 * @prio_type: the traffic priority type
    433 * @bwg_id: the BW group ID the TC belongs to
    434 * @bw_pct: the BW perventage for the BWG
    435 * @up_map: prio mapped to corresponding TC
    436 */
    437static void
    438ice_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,
    439			   u8 __always_unused prio_type,
    440			   u8 __always_unused bwg_id,
    441			   u8 __always_unused bw_pct, u8 up_map)
    442{
    443	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    444	struct ice_dcbx_cfg *new_cfg;
    445	int i;
    446
    447	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
    448	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
    449		return;
    450
    451	if (tc >= ICE_MAX_TRAFFIC_CLASS)
    452		return;
    453
    454	new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg;
    455
    456	/* prio_type, bwg_id and bw_pct per UP are not supported */
    457
    458	ice_for_each_traffic_class(i) {
    459		if (up_map & BIT(i))
    460			new_cfg->etscfg.prio_table[i] = tc;
    461	}
    462	new_cfg->etscfg.tsatable[tc] = ICE_IEEE_TSA_ETS;
    463}
    464
    465/**
    466 * ice_dcbnl_get_pg_bwg_cfg_tx - Get CEE PGBW config
    467 * @netdev: pointer to the netdev struct
    468 * @pgid: corresponding traffic class
    469 * @bw_pct: the BW percentage for the corresponding TC
    470 */
    471static void
    472ice_dcbnl_get_pg_bwg_cfg_tx(struct net_device *netdev, int pgid, u8 *bw_pct)
    473{
    474	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    475	struct ice_port_info *pi = pf->hw.port_info;
    476
    477	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
    478	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
    479		return;
    480
    481	if (pgid >= ICE_MAX_TRAFFIC_CLASS)
    482		return;
    483
    484	*bw_pct = pi->qos_cfg.local_dcbx_cfg.etscfg.tcbwtable[pgid];
    485	dev_dbg(ice_pf_to_dev(pf), "Get PG BW config tc=%d bw_pct=%d\n",
    486		pgid, *bw_pct);
    487}
    488
    489/**
    490 * ice_dcbnl_set_pg_bwg_cfg_tx - set CEE PG Tx BW config
    491 * @netdev: the corresponding netdev
    492 * @pgid: Correspongind traffic class
    493 * @bw_pct: the BW percentage for the specified TC
    494 */
    495static void
    496ice_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int pgid, u8 bw_pct)
    497{
    498	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    499	struct ice_dcbx_cfg *new_cfg;
    500
    501	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
    502	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
    503		return;
    504
    505	if (pgid >= ICE_MAX_TRAFFIC_CLASS)
    506		return;
    507
    508	new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg;
    509
    510	new_cfg->etscfg.tcbwtable[pgid] = bw_pct;
    511}
    512
    513/**
    514 * ice_dcbnl_get_pg_tc_cfg_rx - Get CEE PG Rx config
    515 * @netdev: pointer to netdev struct
    516 * @prio: the corresponding user priority
    517 * @prio_type: the traffic priority type
    518 * @pgid: the PG ID
    519 * @bw_pct: the BW percentage for the corresponding BWG
    520 * @up_map: prio mapped to corresponding TC
    521 */
    522static void
    523ice_dcbnl_get_pg_tc_cfg_rx(struct net_device *netdev, int prio,
    524			   u8 __always_unused *prio_type, u8 *pgid,
    525			   u8 __always_unused *bw_pct,
    526			   u8 __always_unused *up_map)
    527{
    528	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    529	struct ice_port_info *pi = pf->hw.port_info;
    530
    531	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
    532	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
    533		return;
    534
    535	if (prio >= ICE_MAX_USER_PRIORITY)
    536		return;
    537
    538	*pgid = pi->qos_cfg.local_dcbx_cfg.etscfg.prio_table[prio];
    539}
    540
    541/**
    542 * ice_dcbnl_set_pg_tc_cfg_rx
    543 * @netdev: relevant netdev struct
    544 * @prio: corresponding user priority
    545 * @prio_type: the traffic priority type
    546 * @pgid: the PG ID
    547 * @bw_pct: BW percentage for corresponding BWG
    548 * @up_map: prio mapped to corresponding TC
    549 *
    550 * lldpad requires this function pointer to be non-NULL to complete CEE config.
    551 */
    552static void
    553ice_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev,
    554			   int __always_unused prio,
    555			   u8 __always_unused prio_type,
    556			   u8 __always_unused pgid,
    557			   u8 __always_unused bw_pct,
    558			   u8 __always_unused up_map)
    559{
    560	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    561
    562	dev_dbg(ice_pf_to_dev(pf), "Rx TC PG Config Not Supported.\n");
    563}
    564
    565/**
    566 * ice_dcbnl_get_pg_bwg_cfg_rx - Get CEE PG BW Rx config
    567 * @netdev: pointer to netdev struct
    568 * @pgid: the corresponding traffic class
    569 * @bw_pct: the BW percentage for the corresponding TC
    570 */
    571static void
    572ice_dcbnl_get_pg_bwg_cfg_rx(struct net_device *netdev, int __always_unused pgid,
    573			    u8 *bw_pct)
    574{
    575	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    576
    577	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
    578	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
    579		return;
    580
    581	*bw_pct = 0;
    582}
    583
    584/**
    585 * ice_dcbnl_set_pg_bwg_cfg_rx
    586 * @netdev: the corresponding netdev
    587 * @pgid: corresponding TC
    588 * @bw_pct: BW percentage for given TC
    589 *
    590 * lldpad requires this function pointer to be non-NULL to complete CEE config.
    591 */
    592static void
    593ice_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int __always_unused pgid,
    594			    u8 __always_unused bw_pct)
    595{
    596	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    597
    598	dev_dbg(ice_pf_to_dev(pf), "Rx BWG PG Config Not Supported.\n");
    599}
    600
    601/**
    602 * ice_dcbnl_get_cap - Get DCBX capabilities of adapter
    603 * @netdev: pointer to netdev struct
    604 * @capid: the capability type
    605 * @cap: the capability value
    606 */
    607static u8 ice_dcbnl_get_cap(struct net_device *netdev, int capid, u8 *cap)
    608{
    609	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    610
    611	if (!(test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags)))
    612		return ICE_DCB_NO_HW_CHG;
    613
    614	switch (capid) {
    615	case DCB_CAP_ATTR_PG:
    616		*cap = true;
    617		break;
    618	case DCB_CAP_ATTR_PFC:
    619		*cap = true;
    620		break;
    621	case DCB_CAP_ATTR_UP2TC:
    622		*cap = false;
    623		break;
    624	case DCB_CAP_ATTR_PG_TCS:
    625		*cap = 0x80;
    626		break;
    627	case DCB_CAP_ATTR_PFC_TCS:
    628		*cap = 0x80;
    629		break;
    630	case DCB_CAP_ATTR_GSP:
    631		*cap = false;
    632		break;
    633	case DCB_CAP_ATTR_BCN:
    634		*cap = false;
    635		break;
    636	case DCB_CAP_ATTR_DCBX:
    637		*cap = pf->dcbx_cap;
    638		break;
    639	default:
    640		*cap = false;
    641		break;
    642	}
    643
    644	dev_dbg(ice_pf_to_dev(pf), "DCBX Get Capability cap=%d capval=0x%x\n",
    645		capid, *cap);
    646	return 0;
    647}
    648
    649/**
    650 * ice_dcbnl_getapp - get CEE APP
    651 * @netdev: pointer to netdev struct
    652 * @idtype: the App selector
    653 * @id: the App ethtype or port number
    654 */
    655static int ice_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)
    656{
    657	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    658	struct dcb_app app = {
    659				.selector = idtype,
    660				.protocol = id,
    661			     };
    662
    663	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
    664	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
    665		return -EINVAL;
    666
    667	return dcb_getapp(netdev, &app);
    668}
    669
    670/**
    671 * ice_dcbnl_find_app - Search for APP in given DCB config
    672 * @cfg: struct to hold DCBX config
    673 * @app: struct to hold app data to look for
    674 */
    675static bool
    676ice_dcbnl_find_app(struct ice_dcbx_cfg *cfg,
    677		   struct ice_dcb_app_priority_table *app)
    678{
    679	unsigned int i;
    680
    681	for (i = 0; i < cfg->numapps; i++) {
    682		if (app->selector == cfg->app[i].selector &&
    683		    app->prot_id == cfg->app[i].prot_id &&
    684		    app->priority == cfg->app[i].priority)
    685			return true;
    686	}
    687
    688	return false;
    689}
    690
    691#define ICE_BYTES_PER_DSCP_VAL		8
    692
    693/**
    694 * ice_dcbnl_setapp - set local IEEE App config
    695 * @netdev: relevant netdev struct
    696 * @app: struct to hold app config info
    697 */
    698static int ice_dcbnl_setapp(struct net_device *netdev, struct dcb_app *app)
    699{
    700	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    701	struct ice_dcb_app_priority_table new_app;
    702	struct ice_dcbx_cfg *old_cfg, *new_cfg;
    703	u8 max_tc;
    704	int ret;
    705
    706	/* ONLY DSCP APP TLVs have operational significance */
    707	if (app->selector != IEEE_8021QAZ_APP_SEL_DSCP)
    708		return -EINVAL;
    709
    710	/* only allow APP TLVs in SW Mode */
    711	if (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) {
    712		netdev_err(netdev, "can't do DSCP QoS when FW DCB agent active\n");
    713		return -EINVAL;
    714	}
    715
    716	if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
    717		return -EINVAL;
    718
    719	if (!ice_is_feature_supported(pf, ICE_F_DSCP))
    720		return -EOPNOTSUPP;
    721
    722	if (app->protocol >= ICE_DSCP_NUM_VAL) {
    723		netdev_err(netdev, "DSCP value 0x%04X out of range\n",
    724			   app->protocol);
    725		return -EINVAL;
    726	}
    727
    728	max_tc = pf->hw.func_caps.common_cap.maxtc;
    729	if (app->priority >= max_tc) {
    730		netdev_err(netdev, "TC %d out of range, max TC %d\n",
    731			   app->priority, max_tc);
    732		return -EINVAL;
    733	}
    734
    735	/* grab TC mutex */
    736	mutex_lock(&pf->tc_mutex);
    737
    738	new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg;
    739	old_cfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg;
    740
    741	ret = dcb_ieee_setapp(netdev, app);
    742	if (ret)
    743		goto setapp_out;
    744
    745	if (test_and_set_bit(app->protocol, new_cfg->dscp_mapped)) {
    746		netdev_err(netdev, "DSCP value 0x%04X already user mapped\n",
    747			   app->protocol);
    748		ret = dcb_ieee_delapp(netdev, app);
    749		if (ret)
    750			netdev_err(netdev, "Failed to delete re-mapping TLV\n");
    751		ret = -EINVAL;
    752		goto setapp_out;
    753	}
    754
    755	new_app.selector = app->selector;
    756	new_app.prot_id = app->protocol;
    757	new_app.priority = app->priority;
    758
    759	/* If port is not in DSCP mode, need to set */
    760	if (old_cfg->pfc_mode == ICE_QOS_MODE_VLAN) {
    761		int i, j;
    762
    763		/* set DSCP mode */
    764		ret = ice_aq_set_pfc_mode(&pf->hw, ICE_AQC_PFC_DSCP_BASED_PFC,
    765					  NULL);
    766		if (ret) {
    767			netdev_err(netdev, "Failed to set DSCP PFC mode %d\n",
    768				   ret);
    769			goto setapp_out;
    770		}
    771		netdev_info(netdev, "Switched QoS to L3 DSCP mode\n");
    772
    773		new_cfg->pfc_mode = ICE_QOS_MODE_DSCP;
    774
    775		/* set default DSCP QoS values */
    776		new_cfg->etscfg.willing = 0;
    777		new_cfg->pfc.pfccap = max_tc;
    778		new_cfg->pfc.willing = 0;
    779
    780		for (i = 0; i < max_tc; i++)
    781			for (j = 0; j < ICE_BYTES_PER_DSCP_VAL; j++) {
    782				int dscp, offset;
    783
    784				dscp = (i * max_tc) + j;
    785				offset = max_tc * ICE_BYTES_PER_DSCP_VAL;
    786
    787				new_cfg->dscp_map[dscp] = i;
    788				/* if less that 8 TCs supported */
    789				if (max_tc < ICE_MAX_TRAFFIC_CLASS)
    790					new_cfg->dscp_map[dscp + offset] = i;
    791			}
    792
    793		new_cfg->etscfg.tcbwtable[0] = 100;
    794		new_cfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS;
    795		new_cfg->etscfg.prio_table[0] = 0;
    796
    797		for (i = 1; i < max_tc; i++) {
    798			new_cfg->etscfg.tcbwtable[i] = 0;
    799			new_cfg->etscfg.tsatable[i] = ICE_IEEE_TSA_ETS;
    800			new_cfg->etscfg.prio_table[i] = i;
    801		}
    802	} /* end of switching to DSCP mode */
    803
    804	/* apply new mapping for this DSCP value */
    805	new_cfg->dscp_map[app->protocol] = app->priority;
    806	new_cfg->app[new_cfg->numapps++] = new_app;
    807
    808	ret = ice_pf_dcb_cfg(pf, new_cfg, true);
    809	/* return of zero indicates new cfg applied */
    810	if (ret == ICE_DCB_HW_CHG_RST)
    811		ice_dcbnl_devreset(netdev);
    812	else
    813		ret = ICE_DCB_NO_HW_CHG;
    814
    815setapp_out:
    816	mutex_unlock(&pf->tc_mutex);
    817	return ret;
    818}
    819
    820/**
    821 * ice_dcbnl_delapp - Delete local IEEE App config
    822 * @netdev: relevant netdev
    823 * @app: struct to hold app too delete
    824 *
    825 * Will not delete first application required by the FW
    826 */
    827static int ice_dcbnl_delapp(struct net_device *netdev, struct dcb_app *app)
    828{
    829	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    830	struct ice_dcbx_cfg *old_cfg, *new_cfg;
    831	unsigned int i, j;
    832	int ret = 0;
    833
    834	if (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) {
    835		netdev_err(netdev, "can't delete DSCP netlink app when FW DCB agent is active\n");
    836		return -EINVAL;
    837	}
    838
    839	mutex_lock(&pf->tc_mutex);
    840	old_cfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg;
    841
    842	ret = dcb_ieee_delapp(netdev, app);
    843	if (ret)
    844		goto delapp_out;
    845
    846	new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg;
    847
    848	for (i = 0; i < new_cfg->numapps; i++) {
    849		if (app->selector == new_cfg->app[i].selector &&
    850		    app->protocol == new_cfg->app[i].prot_id &&
    851		    app->priority == new_cfg->app[i].priority) {
    852			new_cfg->app[i].selector = 0;
    853			new_cfg->app[i].prot_id = 0;
    854			new_cfg->app[i].priority = 0;
    855			break;
    856		}
    857	}
    858
    859	/* Did not find DCB App */
    860	if (i == new_cfg->numapps) {
    861		ret = -EINVAL;
    862		goto delapp_out;
    863	}
    864
    865	new_cfg->numapps--;
    866
    867	for (j = i; j < new_cfg->numapps; j++) {
    868		new_cfg->app[j].selector = old_cfg->app[j + 1].selector;
    869		new_cfg->app[j].prot_id = old_cfg->app[j + 1].prot_id;
    870		new_cfg->app[j].priority = old_cfg->app[j + 1].priority;
    871	}
    872
    873	/* if not a DSCP APP TLV or DSCP is not supported, we are done */
    874	if (app->selector != IEEE_8021QAZ_APP_SEL_DSCP ||
    875	    !ice_is_feature_supported(pf, ICE_F_DSCP)) {
    876		ret = ICE_DCB_HW_CHG;
    877		goto delapp_out;
    878	}
    879
    880	/* if DSCP TLV, then need to address change in mapping */
    881	clear_bit(app->protocol, new_cfg->dscp_mapped);
    882	/* remap this DSCP value to default value */
    883	new_cfg->dscp_map[app->protocol] = app->protocol %
    884					   ICE_BYTES_PER_DSCP_VAL;
    885
    886	/* if the last DSCP mapping just got deleted, need to switch
    887	 * to L2 VLAN QoS mode
    888	 */
    889	if (bitmap_empty(new_cfg->dscp_mapped, ICE_DSCP_NUM_VAL) &&
    890	    new_cfg->pfc_mode == ICE_QOS_MODE_DSCP) {
    891		ret = ice_aq_set_pfc_mode(&pf->hw,
    892					  ICE_AQC_PFC_VLAN_BASED_PFC,
    893					  NULL);
    894		if (ret) {
    895			netdev_info(netdev, "Failed to set VLAN PFC mode %d\n",
    896				    ret);
    897			goto delapp_out;
    898		}
    899		netdev_info(netdev, "Switched QoS to L2 VLAN mode\n");
    900
    901		new_cfg->pfc_mode = ICE_QOS_MODE_VLAN;
    902
    903		ret = ice_dcb_sw_dflt_cfg(pf, true, true);
    904	} else {
    905		ret = ice_pf_dcb_cfg(pf, new_cfg, true);
    906	}
    907
    908	/* return of ICE_DCB_HW_CHG_RST indicates new cfg applied
    909	 * and reset needs to be performed
    910	 */
    911	if (ret == ICE_DCB_HW_CHG_RST)
    912		ice_dcbnl_devreset(netdev);
    913
    914	/* if the change was not siginificant enough to actually call
    915	 * the reconfiguration flow, we still need to tell caller that
    916	 * their request was successfully handled
    917	 */
    918	if (ret == ICE_DCB_NO_HW_CHG)
    919		ret = ICE_DCB_HW_CHG;
    920
    921delapp_out:
    922	mutex_unlock(&pf->tc_mutex);
    923	return ret;
    924}
    925
    926/**
    927 * ice_dcbnl_cee_set_all - Commit CEE DCB settings to HW
    928 * @netdev: the corresponding netdev
    929 */
    930static u8 ice_dcbnl_cee_set_all(struct net_device *netdev)
    931{
    932	struct ice_pf *pf = ice_netdev_to_pf(netdev);
    933	struct ice_dcbx_cfg *new_cfg;
    934	int err;
    935
    936	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
    937	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
    938		return ICE_DCB_NO_HW_CHG;
    939
    940	new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg;
    941
    942	mutex_lock(&pf->tc_mutex);
    943
    944	err = ice_pf_dcb_cfg(pf, new_cfg, true);
    945
    946	mutex_unlock(&pf->tc_mutex);
    947	return (err != ICE_DCB_HW_CHG_RST) ? ICE_DCB_NO_HW_CHG : err;
    948}
    949
    950static const struct dcbnl_rtnl_ops dcbnl_ops = {
    951	/* IEEE 802.1Qaz std */
    952	.ieee_getets = ice_dcbnl_getets,
    953	.ieee_setets = ice_dcbnl_setets,
    954	.ieee_getpfc = ice_dcbnl_getpfc,
    955	.ieee_setpfc = ice_dcbnl_setpfc,
    956	.ieee_setapp = ice_dcbnl_setapp,
    957	.ieee_delapp = ice_dcbnl_delapp,
    958
    959	/* CEE std */
    960	.getstate = ice_dcbnl_getstate,
    961	.setstate = ice_dcbnl_setstate,
    962	.getpermhwaddr = ice_dcbnl_get_perm_hw_addr,
    963	.setpgtccfgtx = ice_dcbnl_set_pg_tc_cfg_tx,
    964	.setpgbwgcfgtx = ice_dcbnl_set_pg_bwg_cfg_tx,
    965	.setpgtccfgrx = ice_dcbnl_set_pg_tc_cfg_rx,
    966	.setpgbwgcfgrx = ice_dcbnl_set_pg_bwg_cfg_rx,
    967	.getpgtccfgtx = ice_dcbnl_get_pg_tc_cfg_tx,
    968	.getpgbwgcfgtx = ice_dcbnl_get_pg_bwg_cfg_tx,
    969	.getpgtccfgrx = ice_dcbnl_get_pg_tc_cfg_rx,
    970	.getpgbwgcfgrx = ice_dcbnl_get_pg_bwg_cfg_rx,
    971	.setpfccfg = ice_dcbnl_set_pfc_cfg,
    972	.getpfccfg = ice_dcbnl_get_pfc_cfg,
    973	.setall = ice_dcbnl_cee_set_all,
    974	.getcap = ice_dcbnl_get_cap,
    975	.getnumtcs = ice_dcbnl_getnumtcs,
    976	.getpfcstate = ice_dcbnl_getpfcstate,
    977	.getapp = ice_dcbnl_getapp,
    978
    979	/* DCBX configuration */
    980	.getdcbx = ice_dcbnl_getdcbx,
    981	.setdcbx = ice_dcbnl_setdcbx,
    982};
    983
    984/**
    985 * ice_dcbnl_set_all - set all the apps and ieee data from DCBX config
    986 * @vsi: pointer to VSI struct
    987 */
    988void ice_dcbnl_set_all(struct ice_vsi *vsi)
    989{
    990	struct net_device *netdev = vsi->netdev;
    991	struct ice_dcbx_cfg *dcbxcfg;
    992	struct ice_port_info *pi;
    993	struct dcb_app sapp;
    994	struct ice_pf *pf;
    995	unsigned int i;
    996
    997	if (!netdev)
    998		return;
    999
   1000	pf = ice_netdev_to_pf(netdev);
   1001	pi = pf->hw.port_info;
   1002
   1003	/* SW DCB taken care of by SW Default Config */
   1004	if (pf->dcbx_cap & DCB_CAP_DCBX_HOST)
   1005		return;
   1006
   1007	/* DCB not enabled */
   1008	if (!test_bit(ICE_FLAG_DCB_ENA, pf->flags))
   1009		return;
   1010
   1011	dcbxcfg = &pi->qos_cfg.local_dcbx_cfg;
   1012
   1013	for (i = 0; i < dcbxcfg->numapps; i++) {
   1014		u8 prio, tc_map;
   1015
   1016		prio = dcbxcfg->app[i].priority;
   1017		tc_map = BIT(dcbxcfg->etscfg.prio_table[prio]);
   1018
   1019		/* Add APP only if the TC is enabled for this VSI */
   1020		if (tc_map & vsi->tc_cfg.ena_tc) {
   1021			sapp.selector = dcbxcfg->app[i].selector;
   1022			sapp.protocol = dcbxcfg->app[i].prot_id;
   1023			sapp.priority = prio;
   1024			dcb_ieee_setapp(netdev, &sapp);
   1025		}
   1026	}
   1027	/* Notify user-space of the changes */
   1028	dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, 0, 0);
   1029}
   1030
   1031/**
   1032 * ice_dcbnl_vsi_del_app - Delete APP on all VSIs
   1033 * @vsi: pointer to the main VSI
   1034 * @app: APP to delete
   1035 *
   1036 * Delete given APP from all the VSIs for given PF
   1037 */
   1038static void
   1039ice_dcbnl_vsi_del_app(struct ice_vsi *vsi,
   1040		      struct ice_dcb_app_priority_table *app)
   1041{
   1042	struct dcb_app sapp;
   1043	int err;
   1044
   1045	sapp.selector = app->selector;
   1046	sapp.protocol = app->prot_id;
   1047	sapp.priority = app->priority;
   1048	err = ice_dcbnl_delapp(vsi->netdev, &sapp);
   1049	dev_dbg(ice_pf_to_dev(vsi->back), "Deleting app for VSI idx=%d err=%d sel=%d proto=0x%x, prio=%d\n",
   1050		vsi->idx, err, app->selector, app->prot_id, app->priority);
   1051}
   1052
   1053/**
   1054 * ice_dcbnl_flush_apps - Delete all removed APPs
   1055 * @pf: the corresponding PF
   1056 * @old_cfg: old DCBX configuration data
   1057 * @new_cfg: new DCBX configuration data
   1058 *
   1059 * Find and delete all APPS that are not present in the passed
   1060 * DCB configuration
   1061 */
   1062void
   1063ice_dcbnl_flush_apps(struct ice_pf *pf, struct ice_dcbx_cfg *old_cfg,
   1064		     struct ice_dcbx_cfg *new_cfg)
   1065{
   1066	struct ice_vsi *main_vsi = ice_get_main_vsi(pf);
   1067	unsigned int i;
   1068
   1069	if (!main_vsi)
   1070		return;
   1071
   1072	for (i = 0; i < old_cfg->numapps; i++) {
   1073		struct ice_dcb_app_priority_table app = old_cfg->app[i];
   1074
   1075		/* The APP is not available anymore delete it */
   1076		if (!ice_dcbnl_find_app(new_cfg, &app))
   1077			ice_dcbnl_vsi_del_app(main_vsi, &app);
   1078	}
   1079}
   1080
   1081/**
   1082 * ice_dcbnl_setup - setup DCBNL
   1083 * @vsi: VSI to get associated netdev from
   1084 */
   1085void ice_dcbnl_setup(struct ice_vsi *vsi)
   1086{
   1087	struct net_device *netdev = vsi->netdev;
   1088	struct ice_pf *pf;
   1089
   1090	pf = ice_netdev_to_pf(netdev);
   1091	if (!test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags))
   1092		return;
   1093
   1094	netdev->dcbnl_ops = &dcbnl_ops;
   1095	ice_dcbnl_set_all(vsi);
   1096}