brintos

brintos / linux-shallow public Read only

0
0
Text · 27.6 KiB · 8aa43ae Raw
1033 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright(c) 2013 - 2021 Intel Corporation. */3 4#ifdef CONFIG_I40E_DCB5#include <net/dcbnl.h>6#include "i40e.h"7 8#define I40E_DCBNL_STATUS_SUCCESS	09#define I40E_DCBNL_STATUS_ERROR		110static bool i40e_dcbnl_find_app(struct i40e_dcbx_config *cfg,11				struct i40e_dcb_app_priority_table *app);12/**13 * i40e_get_pfc_delay - retrieve PFC Link Delay14 * @hw: pointer to hardware struct15 * @delay: holds the PFC Link delay value16 *17 * Returns PFC Link Delay from the PRTDCB_GENC.PFCLDA18 **/19static void i40e_get_pfc_delay(struct i40e_hw *hw, u16 *delay)20{21	u32 val;22 23	val = rd32(hw, I40E_PRTDCB_GENC);24	*delay = FIELD_GET(I40E_PRTDCB_GENC_PFCLDA_MASK, val);25}26 27/**28 * i40e_dcbnl_ieee_getets - retrieve local IEEE ETS configuration29 * @dev: the corresponding netdev30 * @ets: structure to hold the ETS information31 *32 * Returns local IEEE ETS configuration33 **/34static int i40e_dcbnl_ieee_getets(struct net_device *dev,35				  struct ieee_ets *ets)36{37	struct i40e_pf *pf = i40e_netdev_to_pf(dev);38	struct i40e_dcbx_config *dcbxcfg;39 40	if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))41		return -EINVAL;42 43	dcbxcfg = &pf->hw.local_dcbx_config;44	ets->willing = dcbxcfg->etscfg.willing;45	ets->ets_cap = I40E_MAX_TRAFFIC_CLASS;46	ets->cbs = dcbxcfg->etscfg.cbs;47	memcpy(ets->tc_tx_bw, dcbxcfg->etscfg.tcbwtable,48		sizeof(ets->tc_tx_bw));49	memcpy(ets->tc_rx_bw, dcbxcfg->etscfg.tcbwtable,50		sizeof(ets->tc_rx_bw));51	memcpy(ets->tc_tsa, dcbxcfg->etscfg.tsatable,52		sizeof(ets->tc_tsa));53	memcpy(ets->prio_tc, dcbxcfg->etscfg.prioritytable,54		sizeof(ets->prio_tc));55	memcpy(ets->tc_reco_bw, dcbxcfg->etsrec.tcbwtable,56		sizeof(ets->tc_reco_bw));57	memcpy(ets->tc_reco_tsa, dcbxcfg->etsrec.tsatable,58		sizeof(ets->tc_reco_tsa));59	memcpy(ets->reco_prio_tc, dcbxcfg->etscfg.prioritytable,60		sizeof(ets->reco_prio_tc));61 62	return 0;63}64 65/**66 * i40e_dcbnl_ieee_getpfc - retrieve local IEEE PFC configuration67 * @dev: the corresponding netdev68 * @pfc: structure to hold the PFC information69 *70 * Returns local IEEE PFC configuration71 **/72static int i40e_dcbnl_ieee_getpfc(struct net_device *dev,73				  struct ieee_pfc *pfc)74{75	struct i40e_pf *pf = i40e_netdev_to_pf(dev);76	struct i40e_dcbx_config *dcbxcfg;77	struct i40e_hw *hw = &pf->hw;78	int i;79 80	if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))81		return -EINVAL;82 83	dcbxcfg = &hw->local_dcbx_config;84	pfc->pfc_cap = dcbxcfg->pfc.pfccap;85	pfc->pfc_en = dcbxcfg->pfc.pfcenable;86	pfc->mbc = dcbxcfg->pfc.mbc;87	i40e_get_pfc_delay(hw, &pfc->delay);88 89	/* Get Requests/Indications */90	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {91		pfc->requests[i] = pf->stats.priority_xoff_tx[i];92		pfc->indications[i] = pf->stats.priority_xoff_rx[i];93	}94 95	return 0;96}97 98/**99 * i40e_dcbnl_ieee_setets - set IEEE ETS configuration100 * @netdev: the corresponding netdev101 * @ets: structure to hold the ETS information102 *103 * Set IEEE ETS configuration104 **/105static int i40e_dcbnl_ieee_setets(struct net_device *netdev,106				  struct ieee_ets *ets)107{108	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);109	struct i40e_dcbx_config *old_cfg;110	int i, ret;111 112	if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||113	    (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED))114		return -EINVAL;115 116	old_cfg = &pf->hw.local_dcbx_config;117	/* Copy current config into temp */118	pf->tmp_cfg = *old_cfg;119 120	/* Update the ETS configuration for temp */121	pf->tmp_cfg.etscfg.willing = ets->willing;122	pf->tmp_cfg.etscfg.maxtcs = I40E_MAX_TRAFFIC_CLASS;123	pf->tmp_cfg.etscfg.cbs = ets->cbs;124	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {125		pf->tmp_cfg.etscfg.tcbwtable[i] = ets->tc_tx_bw[i];126		pf->tmp_cfg.etscfg.tsatable[i] = ets->tc_tsa[i];127		pf->tmp_cfg.etscfg.prioritytable[i] = ets->prio_tc[i];128		pf->tmp_cfg.etsrec.tcbwtable[i] = ets->tc_reco_bw[i];129		pf->tmp_cfg.etsrec.tsatable[i] = ets->tc_reco_tsa[i];130		pf->tmp_cfg.etsrec.prioritytable[i] = ets->reco_prio_tc[i];131	}132 133	/* Commit changes to HW */134	ret = i40e_hw_dcb_config(pf, &pf->tmp_cfg);135	if (ret) {136		dev_info(&pf->pdev->dev,137			 "Failed setting DCB ETS configuration err %pe aq_err %s\n",138			 ERR_PTR(ret),139			 i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));140		return -EINVAL;141	}142 143	return 0;144}145 146/**147 * i40e_dcbnl_ieee_setpfc - set local IEEE PFC configuration148 * @netdev: the corresponding netdev149 * @pfc: structure to hold the PFC information150 *151 * Sets local IEEE PFC configuration152 **/153static int i40e_dcbnl_ieee_setpfc(struct net_device *netdev,154				  struct ieee_pfc *pfc)155{156	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);157	struct i40e_dcbx_config *old_cfg;158	int ret;159 160	if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||161	    (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED))162		return -EINVAL;163 164	old_cfg = &pf->hw.local_dcbx_config;165	/* Copy current config into temp */166	pf->tmp_cfg = *old_cfg;167	if (pfc->pfc_cap)168		pf->tmp_cfg.pfc.pfccap = pfc->pfc_cap;169	else170		pf->tmp_cfg.pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;171	pf->tmp_cfg.pfc.pfcenable = pfc->pfc_en;172 173	ret = i40e_hw_dcb_config(pf, &pf->tmp_cfg);174	if (ret) {175		dev_info(&pf->pdev->dev,176			 "Failed setting DCB PFC configuration err %pe aq_err %s\n",177			 ERR_PTR(ret),178			 i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));179		return -EINVAL;180	}181 182	return 0;183}184 185/**186 * i40e_dcbnl_ieee_setapp - set local IEEE App configuration187 * @netdev: the corresponding netdev188 * @app: structure to hold the Application information189 *190 * Sets local IEEE App configuration191 **/192static int i40e_dcbnl_ieee_setapp(struct net_device *netdev,193				  struct dcb_app *app)194{195	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);196	struct i40e_dcb_app_priority_table new_app;197	struct i40e_dcbx_config *old_cfg;198	int ret;199 200	if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||201	    (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED))202		return -EINVAL;203 204	old_cfg = &pf->hw.local_dcbx_config;205	if (old_cfg->numapps == I40E_DCBX_MAX_APPS)206		return -EINVAL;207 208	ret = dcb_ieee_setapp(netdev, app);209	if (ret)210		return ret;211 212	new_app.selector = app->selector;213	new_app.protocolid = app->protocol;214	new_app.priority = app->priority;215	/* Already internally available */216	if (i40e_dcbnl_find_app(old_cfg, &new_app))217		return 0;218 219	/* Copy current config into temp */220	pf->tmp_cfg = *old_cfg;221	/* Add the app */222	pf->tmp_cfg.app[pf->tmp_cfg.numapps++] = new_app;223 224	ret = i40e_hw_dcb_config(pf, &pf->tmp_cfg);225	if (ret) {226		dev_info(&pf->pdev->dev,227			 "Failed setting DCB configuration err %pe aq_err %s\n",228			 ERR_PTR(ret),229			 i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));230		return -EINVAL;231	}232 233	return 0;234}235 236/**237 * i40e_dcbnl_ieee_delapp - delete local IEEE App configuration238 * @netdev: the corresponding netdev239 * @app: structure to hold the Application information240 *241 * Deletes local IEEE App configuration other than the first application242 * required by firmware243 **/244static int i40e_dcbnl_ieee_delapp(struct net_device *netdev,245				  struct dcb_app *app)246{247	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);248	struct i40e_dcbx_config *old_cfg;249	int i, j, ret;250 251	if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||252	    (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED))253		return -EINVAL;254 255	ret = dcb_ieee_delapp(netdev, app);256	if (ret)257		return ret;258 259	old_cfg = &pf->hw.local_dcbx_config;260	/* Need one app for FW so keep it */261	if (old_cfg->numapps == 1)262		return 0;263 264	/* Copy current config into temp */265	pf->tmp_cfg = *old_cfg;266 267	/* Find and reset the app */268	for (i = 1; i < pf->tmp_cfg.numapps; i++) {269		if (app->selector == pf->tmp_cfg.app[i].selector &&270		    app->protocol == pf->tmp_cfg.app[i].protocolid &&271		    app->priority == pf->tmp_cfg.app[i].priority) {272			/* Reset the app data */273			pf->tmp_cfg.app[i].selector = 0;274			pf->tmp_cfg.app[i].protocolid = 0;275			pf->tmp_cfg.app[i].priority = 0;276			break;277		}278	}279 280	/* If the specific DCB app not found */281	if (i == pf->tmp_cfg.numapps)282		return -EINVAL;283 284	pf->tmp_cfg.numapps--;285	/* Overwrite the tmp_cfg app */286	for (j = i; j < pf->tmp_cfg.numapps; j++)287		pf->tmp_cfg.app[j] = old_cfg->app[j + 1];288 289	ret = i40e_hw_dcb_config(pf, &pf->tmp_cfg);290	if (ret) {291		dev_info(&pf->pdev->dev,292			 "Failed setting DCB configuration err %pe aq_err %s\n",293			 ERR_PTR(ret),294			 i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));295		return -EINVAL;296	}297 298	return 0;299}300 301/**302 * i40e_dcbnl_getstate - Get DCB enabled state303 * @netdev: the corresponding netdev304 *305 * Get the current DCB enabled state306 **/307static u8 i40e_dcbnl_getstate(struct net_device *netdev)308{309	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);310 311	dev_dbg(&pf->pdev->dev, "DCB state=%d\n",312		test_bit(I40E_FLAG_DCB_ENA, pf->flags) ? 1 : 0);313	return test_bit(I40E_FLAG_DCB_ENA, pf->flags) ? 1 : 0;314}315 316/**317 * i40e_dcbnl_setstate - Set DCB state318 * @netdev: the corresponding netdev319 * @state: enable or disable320 *321 * Set the DCB state322 **/323static u8 i40e_dcbnl_setstate(struct net_device *netdev, u8 state)324{325	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);326	int ret = I40E_DCBNL_STATUS_SUCCESS;327 328	if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) ||329	    (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED))330		return ret;331 332	dev_dbg(&pf->pdev->dev, "new state=%d current state=%d\n",333		state, test_bit(I40E_FLAG_DCB_ENA, pf->flags) ? 1 : 0);334	/* Nothing to do */335	if (!state == !test_bit(I40E_FLAG_DCB_ENA, pf->flags))336		return ret;337 338	if (i40e_is_sw_dcb(pf)) {339		if (state) {340			set_bit(I40E_FLAG_DCB_ENA, pf->flags);341			memcpy(&pf->hw.desired_dcbx_config,342			       &pf->hw.local_dcbx_config,343			       sizeof(struct i40e_dcbx_config));344		} else {345			clear_bit(I40E_FLAG_DCB_ENA, pf->flags);346		}347	} else {348		/* Cannot directly manipulate FW LLDP Agent */349		ret = I40E_DCBNL_STATUS_ERROR;350	}351	return ret;352}353 354/**355 * i40e_dcbnl_set_pg_tc_cfg_tx - Set CEE PG Tx config356 * @netdev: the corresponding netdev357 * @tc: the corresponding traffic class358 * @prio_type: the traffic priority type359 * @bwg_id: the BW group id the traffic class belongs to360 * @bw_pct: the BW percentage for the corresponding BWG361 * @up_map: prio mapped to corresponding tc362 *363 * Set Tx PG settings for CEE mode364 **/365static void i40e_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,366					u8 prio_type, u8 bwg_id, u8 bw_pct,367					u8 up_map)368{369	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);370	int i;371 372	if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) ||373	    (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED))374		return;375 376	/* LLTC not supported yet */377	if (tc >= I40E_MAX_TRAFFIC_CLASS)378		return;379 380	/* prio_type, bwg_id and bw_pct per UP are not supported */381 382	/* Use only up_map to map tc */383	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {384		if (up_map & BIT(i))385			pf->tmp_cfg.etscfg.prioritytable[i] = tc;386	}387	pf->tmp_cfg.etscfg.tsatable[tc] = I40E_IEEE_TSA_ETS;388	dev_dbg(&pf->pdev->dev,389		"Set PG config tc=%d bwg_id=%d prio_type=%d bw_pct=%d up_map=%d\n",390		tc, bwg_id, prio_type, bw_pct, up_map);391}392 393/**394 * i40e_dcbnl_set_pg_bwg_cfg_tx - Set CEE PG Tx BW config395 * @netdev: the corresponding netdev396 * @pgid: the corresponding traffic class397 * @bw_pct: the BW percentage for the specified traffic class398 *399 * Set Tx BW settings for CEE mode400 **/401static void i40e_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int pgid,402					 u8 bw_pct)403{404	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);405 406	if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) ||407	    (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED))408		return;409 410	/* LLTC not supported yet */411	if (pgid >= I40E_MAX_TRAFFIC_CLASS)412		return;413 414	pf->tmp_cfg.etscfg.tcbwtable[pgid] = bw_pct;415	dev_dbg(&pf->pdev->dev, "Set PG BW config tc=%d bw_pct=%d\n",416		pgid, bw_pct);417}418 419/**420 * i40e_dcbnl_set_pg_tc_cfg_rx - Set CEE PG Rx config421 * @netdev: the corresponding netdev422 * @prio: the corresponding traffic class423 * @prio_type: the traffic priority type424 * @pgid: the BW group id the traffic class belongs to425 * @bw_pct: the BW percentage for the corresponding BWG426 * @up_map: prio mapped to corresponding tc427 *428 * Set Rx BW settings for CEE mode. The hardware does not support this429 * so we won't allow setting of this parameter.430 **/431static void i40e_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev,432					int __always_unused prio,433					u8 __always_unused prio_type,434					u8 __always_unused pgid,435					u8 __always_unused bw_pct,436					u8 __always_unused up_map)437{438	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);439 440	dev_dbg(&pf->pdev->dev, "Rx TC PG Config Not Supported.\n");441}442 443/**444 * i40e_dcbnl_set_pg_bwg_cfg_rx - Set CEE PG Rx config445 * @netdev: the corresponding netdev446 * @pgid: the corresponding traffic class447 * @bw_pct: the BW percentage for the specified traffic class448 *449 * Set Rx BW settings for CEE mode. The hardware does not support this450 * so we won't allow setting of this parameter.451 **/452static void i40e_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int pgid,453					 u8 bw_pct)454{455	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);456 457	dev_dbg(&pf->pdev->dev, "Rx BWG PG Config Not Supported.\n");458}459 460/**461 * i40e_dcbnl_get_pg_tc_cfg_tx - Get CEE PG Tx config462 * @netdev: the corresponding netdev463 * @prio: the corresponding user priority464 * @prio_type: traffic priority type465 * @pgid: the BW group ID the traffic class belongs to466 * @bw_pct: BW percentage for the corresponding BWG467 * @up_map: prio mapped to corresponding TC468 *469 * Get Tx PG settings for CEE mode470 **/471static void i40e_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int prio,472					u8 __always_unused *prio_type,473					u8 *pgid,474					u8 __always_unused *bw_pct,475					u8 __always_unused *up_map)476{477	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);478 479	if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) ||480	    (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED))481		return;482 483	if (prio >= I40E_MAX_USER_PRIORITY)484		return;485 486	*pgid = pf->hw.local_dcbx_config.etscfg.prioritytable[prio];487	dev_dbg(&pf->pdev->dev, "Get PG config prio=%d tc=%d\n",488		prio, *pgid);489}490 491/**492 * i40e_dcbnl_get_pg_bwg_cfg_tx - Get CEE PG BW config493 * @netdev: the corresponding netdev494 * @pgid: the corresponding traffic class495 * @bw_pct: the BW percentage for the corresponding TC496 *497 * Get Tx BW settings for given TC in CEE mode498 **/499static void i40e_dcbnl_get_pg_bwg_cfg_tx(struct net_device *netdev, int pgid,500					 u8 *bw_pct)501{502	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);503 504	if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) ||505	    (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED))506		return;507 508	if (pgid >= I40E_MAX_TRAFFIC_CLASS)509		return;510 511	*bw_pct = pf->hw.local_dcbx_config.etscfg.tcbwtable[pgid];512	dev_dbg(&pf->pdev->dev, "Get PG BW config tc=%d bw_pct=%d\n",513		pgid, *bw_pct);514}515 516/**517 * i40e_dcbnl_get_pg_tc_cfg_rx - Get CEE PG Rx config518 * @netdev: the corresponding netdev519 * @prio: the corresponding user priority520 * @prio_type: the traffic priority type521 * @pgid: the PG ID522 * @bw_pct: the BW percentage for the corresponding BWG523 * @up_map: prio mapped to corresponding TC524 *525 * Get Rx PG settings for CEE mode. The UP2TC map is applied in same526 * manner for Tx and Rx (symmetrical) so return the TC information for527 * given priority accordingly.528 **/529static void i40e_dcbnl_get_pg_tc_cfg_rx(struct net_device *netdev, int prio,530					u8 *prio_type, u8 *pgid, u8 *bw_pct,531					u8 *up_map)532{533	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);534 535	if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) ||536	    (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED))537		return;538 539	if (prio >= I40E_MAX_USER_PRIORITY)540		return;541 542	*pgid = pf->hw.local_dcbx_config.etscfg.prioritytable[prio];543}544 545/**546 * i40e_dcbnl_get_pg_bwg_cfg_rx - Get CEE PG BW Rx config547 * @netdev: the corresponding netdev548 * @pgid: the corresponding traffic class549 * @bw_pct: the BW percentage for the corresponding TC550 *551 * Get Rx BW settings for given TC in CEE mode552 * The adapter doesn't support Rx ETS and runs in strict priority553 * mode in Rx path and hence just return 0.554 **/555static void i40e_dcbnl_get_pg_bwg_cfg_rx(struct net_device *netdev, int pgid,556					 u8 *bw_pct)557{558	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);559 560	if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) ||561	    (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED))562		return;563	*bw_pct = 0;564}565 566/**567 * i40e_dcbnl_set_pfc_cfg - Set CEE PFC configuration568 * @netdev: the corresponding netdev569 * @prio: the corresponding user priority570 * @setting: the PFC setting for given priority571 *572 * Set the PFC enabled/disabled setting for given user priority573 **/574static void i40e_dcbnl_set_pfc_cfg(struct net_device *netdev, int prio,575				   u8 setting)576{577	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);578 579	if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) ||580	    (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED))581		return;582 583	if (prio >= I40E_MAX_USER_PRIORITY)584		return;585 586	pf->tmp_cfg.pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;587	if (setting)588		pf->tmp_cfg.pfc.pfcenable |= BIT(prio);589	else590		pf->tmp_cfg.pfc.pfcenable &= ~BIT(prio);591	dev_dbg(&pf->pdev->dev,592		"Set PFC Config up=%d setting=%d pfcenable=0x%x\n",593		prio, setting, pf->tmp_cfg.pfc.pfcenable);594}595 596/**597 * i40e_dcbnl_get_pfc_cfg - Get CEE PFC configuration598 * @netdev: the corresponding netdev599 * @prio: the corresponding user priority600 * @setting: the PFC setting for given priority601 *602 * Get the PFC enabled/disabled setting for given user priority603 **/604static void i40e_dcbnl_get_pfc_cfg(struct net_device *netdev, int prio,605				   u8 *setting)606{607	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);608 609	if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) ||610	    (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED))611		return;612 613	if (prio >= I40E_MAX_USER_PRIORITY)614		return;615 616	*setting = (pf->hw.local_dcbx_config.pfc.pfcenable >> prio) & 0x1;617	dev_dbg(&pf->pdev->dev,618		"Get PFC Config up=%d setting=%d pfcenable=0x%x\n",619		prio, *setting, pf->hw.local_dcbx_config.pfc.pfcenable);620}621 622/**623 * i40e_dcbnl_cee_set_all - Commit CEE DCB settings to hardware624 * @netdev: the corresponding netdev625 *626 * Commit the current DCB configuration to hardware627 **/628static u8 i40e_dcbnl_cee_set_all(struct net_device *netdev)629{630	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);631	int err;632 633	if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) ||634	    (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED))635		return I40E_DCBNL_STATUS_ERROR;636 637	dev_dbg(&pf->pdev->dev, "Commit DCB Configuration to the hardware\n");638	err = i40e_hw_dcb_config(pf, &pf->tmp_cfg);639 640	return err ? I40E_DCBNL_STATUS_ERROR : I40E_DCBNL_STATUS_SUCCESS;641}642 643/**644 * i40e_dcbnl_get_cap - Get DCBX capabilities of adapter645 * @netdev: the corresponding netdev646 * @capid: the capability type647 * @cap: the capability value648 *649 * Return the capability value for a given capability type650 **/651static u8 i40e_dcbnl_get_cap(struct net_device *netdev, int capid, u8 *cap)652{653	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);654 655	if (!test_bit(I40E_FLAG_DCB_CAPABLE, pf->flags))656		return I40E_DCBNL_STATUS_ERROR;657 658	switch (capid) {659	case DCB_CAP_ATTR_PG:660	case DCB_CAP_ATTR_PFC:661		*cap = true;662		break;663	case DCB_CAP_ATTR_PG_TCS:664	case DCB_CAP_ATTR_PFC_TCS:665		*cap = 0x80;666		break;667	case DCB_CAP_ATTR_DCBX:668		*cap = pf->dcbx_cap;669		break;670	case DCB_CAP_ATTR_UP2TC:671	case DCB_CAP_ATTR_GSP:672	case DCB_CAP_ATTR_BCN:673	default:674		*cap = false;675		break;676	}677 678	dev_dbg(&pf->pdev->dev, "Get Capability cap=%d capval=0x%x\n",679		capid, *cap);680	return I40E_DCBNL_STATUS_SUCCESS;681}682 683/**684 * i40e_dcbnl_getnumtcs - Get max number of traffic classes supported685 * @netdev: the corresponding netdev686 * @tcid: the TC id687 * @num: total number of TCs supported by the device688 *689 * Return the total number of TCs supported by the adapter690 **/691static int i40e_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num)692{693	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);694 695	if (!test_bit(I40E_FLAG_DCB_CAPABLE, pf->flags))696		return -EINVAL;697 698	*num = I40E_MAX_TRAFFIC_CLASS;699	return 0;700}701 702/**703 * i40e_dcbnl_setnumtcs - Set CEE number of traffic classes704 * @netdev: the corresponding netdev705 * @tcid: the TC id706 * @num: total number of TCs707 *708 * Set the total number of TCs (Unsupported)709 **/710static int i40e_dcbnl_setnumtcs(struct net_device *netdev, int tcid, u8 num)711{712	return -EINVAL;713}714 715/**716 * i40e_dcbnl_getpfcstate - Get CEE PFC mode717 * @netdev: the corresponding netdev718 *719 * Get the current PFC enabled state720 **/721static u8 i40e_dcbnl_getpfcstate(struct net_device *netdev)722{723	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);724 725	/* Return enabled if any PFC enabled UP */726	if (pf->hw.local_dcbx_config.pfc.pfcenable)727		return 1;728	else729		return 0;730}731 732/**733 * i40e_dcbnl_setpfcstate - Set CEE PFC mode734 * @netdev: the corresponding netdev735 * @state: required state736 *737 * The PFC state to be set; this is enabled/disabled based on the PFC738 * priority settings and not via this call for i40e driver739 **/740static void i40e_dcbnl_setpfcstate(struct net_device *netdev, u8 state)741{742	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);743 744	dev_dbg(&pf->pdev->dev, "PFC State is modified via PFC config.\n");745}746 747/**748 * i40e_dcbnl_getapp - Get CEE APP749 * @netdev: the corresponding netdev750 * @idtype: the App selector751 * @id: the App ethtype or port number752 *753 * Return the CEE mode app for the given idtype and id754 **/755static int i40e_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)756{757	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);758	struct dcb_app app = {759				.selector = idtype,760				.protocol = id,761			     };762 763	if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) ||764	    (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED))765		return -EINVAL;766 767	return dcb_getapp(netdev, &app);768}769 770/**771 * i40e_dcbnl_setdcbx - set required DCBx capability772 * @netdev: the corresponding netdev773 * @mode: new DCB mode managed or CEE+IEEE774 *775 * Set DCBx capability features776 **/777static u8 i40e_dcbnl_setdcbx(struct net_device *netdev, u8 mode)778{779	struct i40e_pf *pf = i40e_netdev_to_pf(netdev);780 781	/* Do not allow to set mode if managed by Firmware */782	if (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)783		return I40E_DCBNL_STATUS_ERROR;784 785	/* No support for LLD_MANAGED modes or CEE+IEEE */786	if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||787	    ((mode & DCB_CAP_DCBX_VER_IEEE) && (mode & DCB_CAP_DCBX_VER_CEE)) ||788	    !(mode & DCB_CAP_DCBX_HOST))789		return I40E_DCBNL_STATUS_ERROR;790 791	/* Already set to the given mode no change */792	if (mode == pf->dcbx_cap)793		return I40E_DCBNL_STATUS_SUCCESS;794 795	pf->dcbx_cap = mode;796	if (mode & DCB_CAP_DCBX_VER_CEE)797		pf->hw.local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE;798	else799		pf->hw.local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE;800 801	dev_dbg(&pf->pdev->dev, "mode=%d\n", mode);802	return I40E_DCBNL_STATUS_SUCCESS;803}804 805/**806 * i40e_dcbnl_getdcbx - retrieve current DCBx capability807 * @dev: the corresponding netdev808 *809 * Returns DCBx capability features810 **/811static u8 i40e_dcbnl_getdcbx(struct net_device *dev)812{813	struct i40e_pf *pf = i40e_netdev_to_pf(dev);814 815	return pf->dcbx_cap;816}817 818/**819 * i40e_dcbnl_get_perm_hw_addr - MAC address used by DCBx820 * @dev: the corresponding netdev821 * @perm_addr: buffer to store the MAC address822 *823 * Returns the SAN MAC address used for LLDP exchange824 **/825static void i40e_dcbnl_get_perm_hw_addr(struct net_device *dev,826					u8 *perm_addr)827{828	struct i40e_pf *pf = i40e_netdev_to_pf(dev);829	int i;830 831	memset(perm_addr, 0xff, MAX_ADDR_LEN);832 833	for (i = 0; i < dev->addr_len; i++)834		perm_addr[i] = pf->hw.mac.perm_addr[i];835}836 837static const struct dcbnl_rtnl_ops dcbnl_ops = {838	.ieee_getets	= i40e_dcbnl_ieee_getets,839	.ieee_getpfc	= i40e_dcbnl_ieee_getpfc,840	.getdcbx	= i40e_dcbnl_getdcbx,841	.getpermhwaddr	= i40e_dcbnl_get_perm_hw_addr,842	.ieee_setets	= i40e_dcbnl_ieee_setets,843	.ieee_setpfc	= i40e_dcbnl_ieee_setpfc,844	.ieee_setapp	= i40e_dcbnl_ieee_setapp,845	.ieee_delapp	= i40e_dcbnl_ieee_delapp,846	.getstate	= i40e_dcbnl_getstate,847	.setstate	= i40e_dcbnl_setstate,848	.setpgtccfgtx	= i40e_dcbnl_set_pg_tc_cfg_tx,849	.setpgbwgcfgtx	= i40e_dcbnl_set_pg_bwg_cfg_tx,850	.setpgtccfgrx	= i40e_dcbnl_set_pg_tc_cfg_rx,851	.setpgbwgcfgrx	= i40e_dcbnl_set_pg_bwg_cfg_rx,852	.getpgtccfgtx	= i40e_dcbnl_get_pg_tc_cfg_tx,853	.getpgbwgcfgtx	= i40e_dcbnl_get_pg_bwg_cfg_tx,854	.getpgtccfgrx	= i40e_dcbnl_get_pg_tc_cfg_rx,855	.getpgbwgcfgrx	= i40e_dcbnl_get_pg_bwg_cfg_rx,856	.setpfccfg	= i40e_dcbnl_set_pfc_cfg,857	.getpfccfg	= i40e_dcbnl_get_pfc_cfg,858	.setall		= i40e_dcbnl_cee_set_all,859	.getcap		= i40e_dcbnl_get_cap,860	.getnumtcs	= i40e_dcbnl_getnumtcs,861	.setnumtcs	= i40e_dcbnl_setnumtcs,862	.getpfcstate	= i40e_dcbnl_getpfcstate,863	.setpfcstate	= i40e_dcbnl_setpfcstate,864	.getapp		= i40e_dcbnl_getapp,865	.setdcbx	= i40e_dcbnl_setdcbx,866};867 868/**869 * i40e_dcbnl_set_all - set all the apps and ieee data from DCBx config870 * @vsi: the corresponding vsi871 *872 * Set up all the IEEE APPs in the DCBNL App Table and generate event for873 * other settings874 **/875void i40e_dcbnl_set_all(struct i40e_vsi *vsi)876{877	struct net_device *dev = vsi->netdev;878	struct i40e_pf *pf = i40e_netdev_to_pf(dev);879	struct i40e_dcbx_config *dcbxcfg;880	struct i40e_hw *hw = &pf->hw;881	struct dcb_app sapp;882	u8 prio, tc_map;883	int i;884 885	/* SW DCB taken care by DCBNL set calls */886	if (pf->dcbx_cap & DCB_CAP_DCBX_HOST)887		return;888 889	/* DCB not enabled */890	if (!test_bit(I40E_FLAG_DCB_ENA, pf->flags))891		return;892 893	/* MFP mode but not an iSCSI PF so return */894	if (test_bit(I40E_FLAG_MFP_ENA, pf->flags) && !(hw->func_caps.iscsi))895		return;896 897	dcbxcfg = &hw->local_dcbx_config;898 899	/* Set up all the App TLVs if DCBx is negotiated */900	for (i = 0; i < dcbxcfg->numapps; i++) {901		prio = dcbxcfg->app[i].priority;902		tc_map = BIT(dcbxcfg->etscfg.prioritytable[prio]);903 904		/* Add APP only if the TC is enabled for this VSI */905		if (tc_map & vsi->tc_config.enabled_tc) {906			sapp.selector = dcbxcfg->app[i].selector;907			sapp.protocol = dcbxcfg->app[i].protocolid;908			sapp.priority = prio;909			dcb_ieee_setapp(dev, &sapp);910		}911	}912 913	/* Notify user-space of the changes */914	dcbnl_ieee_notify(dev, RTM_SETDCB, DCB_CMD_IEEE_SET, 0, 0);915}916 917/**918 * i40e_dcbnl_vsi_del_app - Delete APP for given VSI919 * @vsi: the corresponding vsi920 * @app: APP to delete921 *922 * Delete given APP from the DCBNL APP table for given923 * VSI924 **/925static int i40e_dcbnl_vsi_del_app(struct i40e_vsi *vsi,926				  struct i40e_dcb_app_priority_table *app)927{928	struct net_device *dev = vsi->netdev;929	struct dcb_app sapp;930 931	if (!dev)932		return -EINVAL;933 934	sapp.selector = app->selector;935	sapp.protocol = app->protocolid;936	sapp.priority = app->priority;937	return dcb_ieee_delapp(dev, &sapp);938}939 940/**941 * i40e_dcbnl_del_app - Delete APP on all VSIs942 * @pf: the corresponding PF943 * @app: APP to delete944 *945 * Delete given APP from all the VSIs for given PF946 **/947static void i40e_dcbnl_del_app(struct i40e_pf *pf,948			       struct i40e_dcb_app_priority_table *app)949{950	struct i40e_vsi *vsi;951	int v, err;952 953	i40e_pf_for_each_vsi(pf, v, vsi)954		if (vsi->netdev) {955			err = i40e_dcbnl_vsi_del_app(vsi, app);956			dev_dbg(&pf->pdev->dev, "Deleting app for VSI seid=%d err=%d sel=%d proto=0x%x prio=%d\n",957				vsi->seid, err, app->selector,958				app->protocolid, app->priority);959		}960}961 962/**963 * i40e_dcbnl_find_app - Search APP in given DCB config964 * @cfg: DCBX configuration data965 * @app: APP to search for966 *967 * Find given APP in the DCB configuration968 **/969static bool i40e_dcbnl_find_app(struct i40e_dcbx_config *cfg,970				struct i40e_dcb_app_priority_table *app)971{972	int i;973 974	for (i = 0; i < cfg->numapps; i++) {975		if (app->selector == cfg->app[i].selector &&976		    app->protocolid == cfg->app[i].protocolid &&977		    app->priority == cfg->app[i].priority)978			return true;979	}980 981	return false;982}983 984/**985 * i40e_dcbnl_flush_apps - Delete all removed APPs986 * @pf: the corresponding PF987 * @old_cfg: old DCBX configuration data988 * @new_cfg: new DCBX configuration data989 *990 * Find and delete all APPs that are not present in the passed991 * DCB configuration992 **/993void i40e_dcbnl_flush_apps(struct i40e_pf *pf,994			   struct i40e_dcbx_config *old_cfg,995			   struct i40e_dcbx_config *new_cfg)996{997	struct i40e_dcb_app_priority_table app;998	int i;999 1000	/* MFP mode but not an iSCSI PF so return */1001	if (test_bit(I40E_FLAG_MFP_ENA, pf->flags) && !(pf->hw.func_caps.iscsi))1002		return;1003 1004	for (i = 0; i < old_cfg->numapps; i++) {1005		app = old_cfg->app[i];1006		/* The APP is not available anymore delete it */1007		if (!i40e_dcbnl_find_app(new_cfg, &app))1008			i40e_dcbnl_del_app(pf, &app);1009	}1010}1011 1012/**1013 * i40e_dcbnl_setup - DCBNL setup1014 * @vsi: the corresponding vsi1015 *1016 * Set up DCBNL ops and initial APP TLVs1017 **/1018void i40e_dcbnl_setup(struct i40e_vsi *vsi)1019{1020	struct net_device *dev = vsi->netdev;1021	struct i40e_pf *pf = i40e_netdev_to_pf(dev);1022 1023	/* Not DCB capable */1024	if (!test_bit(I40E_FLAG_DCB_CAPABLE, pf->flags))1025		return;1026 1027	dev->dcbnl_ops = &dcbnl_ops;1028 1029	/* Set initial IEEE DCB settings */1030	i40e_dcbnl_set_all(vsi);1031}1032#endif /* CONFIG_I40E_DCB */1033