brintos

brintos / linux-shallow public Read only

0
0
Text · 13.3 KiB · bb498ac Raw
572 lines · c
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)2/* Copyright (C) 2023 Corigine, Inc. */3 4#include <linux/device.h>5#include <linux/netdevice.h>6#include <net/dcbnl.h>7 8#include "../nfp_app.h"9#include "../nfp_net.h"10#include "../nfp_main.h"11#include "../nfpcore/nfp_cpp.h"12#include "../nfpcore/nfp_nffw.h"13#include "../nfp_net_sriov.h"14 15#include "main.h"16 17#define NFP_DCB_TRUST_PCP	118#define NFP_DCB_TRUST_DSCP	219#define NFP_DCB_TRUST_INVALID	0xff20 21#define NFP_DCB_TSA_VENDOR	122#define NFP_DCB_TSA_STRICT	223#define NFP_DCB_TSA_ETS		324 25#define NFP_DCB_GBL_ENABLE	BIT(0)26#define NFP_DCB_QOS_ENABLE	BIT(1)27#define NFP_DCB_DISABLE		028#define NFP_DCB_ALL_QOS_ENABLE	(NFP_DCB_GBL_ENABLE | NFP_DCB_QOS_ENABLE)29 30#define NFP_DCB_UPDATE_MSK_SZ	431#define NFP_DCB_TC_RATE_MAX	0xffff32 33#define NFP_DCB_DATA_OFF_DSCP2IDX	034#define NFP_DCB_DATA_OFF_PCP2IDX	6435#define NFP_DCB_DATA_OFF_TSA		8036#define NFP_DCB_DATA_OFF_IDX_BW_PCT	8837#define NFP_DCB_DATA_OFF_RATE		9638#define NFP_DCB_DATA_OFF_CAP		11239#define NFP_DCB_DATA_OFF_ENABLE		11640#define NFP_DCB_DATA_OFF_TRUST		12041 42#define NFP_DCB_MSG_MSK_ENABLE	BIT(31)43#define NFP_DCB_MSG_MSK_TRUST	BIT(30)44#define NFP_DCB_MSG_MSK_TSA	BIT(29)45#define NFP_DCB_MSG_MSK_DSCP	BIT(28)46#define NFP_DCB_MSG_MSK_PCP	BIT(27)47#define NFP_DCB_MSG_MSK_RATE	BIT(26)48#define NFP_DCB_MSG_MSK_PCT	BIT(25)49 50static struct nfp_dcb *get_dcb_priv(struct nfp_net *nn)51{52	struct nfp_dcb *dcb = &((struct nfp_app_nic_private *)nn->app_priv)->dcb;53 54	return dcb;55}56 57static u8 nfp_tsa_ieee2nfp(u8 tsa)58{59	switch (tsa) {60	case IEEE_8021QAZ_TSA_STRICT:61		return NFP_DCB_TSA_STRICT;62	case IEEE_8021QAZ_TSA_ETS:63		return NFP_DCB_TSA_ETS;64	default:65		return NFP_DCB_TSA_VENDOR;66	}67}68 69static int nfp_nic_dcbnl_ieee_getets(struct net_device *dev,70				     struct ieee_ets *ets)71{72	struct nfp_net *nn = netdev_priv(dev);73	struct nfp_dcb *dcb;74 75	dcb = get_dcb_priv(nn);76 77	for (unsigned int i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {78		ets->prio_tc[i] = dcb->prio2tc[i];79		ets->tc_tx_bw[i] = dcb->tc_tx_pct[i];80		ets->tc_tsa[i] = dcb->tc_tsa[i];81	}82 83	return 0;84}85 86static bool nfp_refresh_tc2idx(struct nfp_net *nn)87{88	u8 tc2idx[IEEE_8021QAZ_MAX_TCS];89	bool change = false;90	struct nfp_dcb *dcb;91	int maxstrict = 0;92 93	dcb = get_dcb_priv(nn);94 95	for (unsigned int i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {96		tc2idx[i] = i;97		if (dcb->tc_tsa[i] == IEEE_8021QAZ_TSA_STRICT)98			maxstrict = i;99	}100 101	if (maxstrict > 0 && dcb->tc_tsa[0] != IEEE_8021QAZ_TSA_STRICT) {102		tc2idx[0] = maxstrict;103		tc2idx[maxstrict] = 0;104	}105 106	for (unsigned int j = 0; j < IEEE_8021QAZ_MAX_TCS; j++) {107		if (dcb->tc2idx[j] != tc2idx[j]) {108			change = true;109			dcb->tc2idx[j] = tc2idx[j];110		}111	}112 113	return change;114}115 116static int nfp_fill_maxrate(struct nfp_net *nn, u64 *max_rate_array)117{118	struct nfp_app *app  = nn->app;119	struct nfp_dcb *dcb;120	u32 ratembps;121 122	dcb = get_dcb_priv(nn);123 124	for (unsigned int i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {125		/* Convert bandwidth from kbps to mbps. */126		ratembps = max_rate_array[i] / 1024;127 128		/* Reject input values >= NFP_DCB_TC_RATE_MAX */129		if (ratembps >= NFP_DCB_TC_RATE_MAX) {130			nfp_warn(app->cpp, "ratembps(%d) must less than %d.",131				 ratembps, NFP_DCB_TC_RATE_MAX);132			return -EINVAL;133		}134		/* Input value 0 mapped to NFP_DCB_TC_RATE_MAX for firmware. */135		if (ratembps == 0)136			ratembps = NFP_DCB_TC_RATE_MAX;137 138		writew((u16)ratembps, dcb->dcbcfg_tbl +139		       dcb->cfg_offset + NFP_DCB_DATA_OFF_RATE + dcb->tc2idx[i] * 2);140		/* for rate value from user space, need to sync to dcb structure */141		if (dcb->tc_maxrate != max_rate_array)142			dcb->tc_maxrate[i] = max_rate_array[i];143	}144 145	return 0;146}147 148static int update_dscp_maxrate(struct net_device *dev, u32 *update)149{150	struct nfp_net *nn = netdev_priv(dev);151	struct nfp_dcb *dcb;152	int err;153 154	dcb = get_dcb_priv(nn);155 156	err = nfp_fill_maxrate(nn, dcb->tc_maxrate);157	if (err)158		return err;159 160	*update |= NFP_DCB_MSG_MSK_RATE;161 162	/* We only refresh dscp in dscp trust mode. */163	if (dcb->dscp_cnt > 0) {164		for (unsigned int i = 0; i < NFP_NET_MAX_DSCP; i++) {165			writeb(dcb->tc2idx[dcb->prio2tc[dcb->dscp2prio[i]]],166			       dcb->dcbcfg_tbl + dcb->cfg_offset +167			       NFP_DCB_DATA_OFF_DSCP2IDX + i);168		}169		*update |= NFP_DCB_MSG_MSK_DSCP;170	}171 172	return 0;173}174 175static void nfp_nic_set_trust(struct nfp_net *nn, u32 *update)176{177	struct nfp_dcb *dcb;178	u8 trust;179 180	dcb = get_dcb_priv(nn);181 182	if (dcb->trust_status != NFP_DCB_TRUST_INVALID)183		return;184 185	trust = dcb->dscp_cnt > 0 ? NFP_DCB_TRUST_DSCP : NFP_DCB_TRUST_PCP;186	writeb(trust, dcb->dcbcfg_tbl + dcb->cfg_offset +187	       NFP_DCB_DATA_OFF_TRUST);188 189	dcb->trust_status = trust;190	*update |= NFP_DCB_MSG_MSK_TRUST;191}192 193static void nfp_nic_set_enable(struct nfp_net *nn, u32 enable, u32 *update)194{195	struct nfp_dcb *dcb;196	u32 value = 0;197 198	dcb = get_dcb_priv(nn);199 200	value = readl(dcb->dcbcfg_tbl + dcb->cfg_offset +201		      NFP_DCB_DATA_OFF_ENABLE);202	if (value != enable) {203		writel(enable, dcb->dcbcfg_tbl + dcb->cfg_offset +204		       NFP_DCB_DATA_OFF_ENABLE);205		*update |= NFP_DCB_MSG_MSK_ENABLE;206	}207}208 209static int dcb_ets_check(struct net_device *dev, struct ieee_ets *ets)210{211	struct nfp_net *nn = netdev_priv(dev);212	struct nfp_app *app = nn->app;213	bool ets_exists = false;214	int sum = 0;215 216	for (unsigned int i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {217		/* For ets mode, check bw percentage sum. */218		if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) {219			ets_exists = true;220			sum += ets->tc_tx_bw[i];221		} else if (ets->tc_tx_bw[i]) {222			nfp_warn(app->cpp, "ETS BW for strict/vendor TC must be 0.");223			return -EINVAL;224		}225	}226 227	if (ets_exists && sum != 100) {228		nfp_warn(app->cpp, "Failed to validate ETS BW: sum must be 100.");229		return -EINVAL;230	}231 232	return 0;233}234 235static void nfp_nic_fill_ets(struct nfp_net *nn)236{237	struct nfp_dcb *dcb;238 239	dcb = get_dcb_priv(nn);240 241	for (unsigned int i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {242		writeb(dcb->tc2idx[dcb->prio2tc[i]],243		       dcb->dcbcfg_tbl + dcb->cfg_offset + NFP_DCB_DATA_OFF_PCP2IDX + i);244		writeb(dcb->tc_tx_pct[i], dcb->dcbcfg_tbl +245		       dcb->cfg_offset + NFP_DCB_DATA_OFF_IDX_BW_PCT + dcb->tc2idx[i]);246		writeb(nfp_tsa_ieee2nfp(dcb->tc_tsa[i]), dcb->dcbcfg_tbl +247		       dcb->cfg_offset + NFP_DCB_DATA_OFF_TSA + dcb->tc2idx[i]);248	}249}250 251static void nfp_nic_ets_init(struct nfp_net *nn, u32 *update)252{253	struct nfp_dcb *dcb = get_dcb_priv(nn);254 255	if (dcb->ets_init)256		return;257 258	nfp_nic_fill_ets(nn);259	dcb->ets_init = true;260	*update |= NFP_DCB_MSG_MSK_TSA | NFP_DCB_MSG_MSK_PCT | NFP_DCB_MSG_MSK_PCP;261}262 263static int nfp_nic_dcbnl_ieee_setets(struct net_device *dev,264				     struct ieee_ets *ets)265{266	const u32 cmd = NFP_NET_CFG_MBOX_CMD_DCB_UPDATE;267	struct nfp_net *nn = netdev_priv(dev);268	struct nfp_app *app = nn->app;269	struct nfp_dcb *dcb;270	u32 update = 0;271	bool change;272	int err;273 274	err = dcb_ets_check(dev, ets);275	if (err)276		return err;277 278	dcb = get_dcb_priv(nn);279 280	for (unsigned int i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {281		dcb->prio2tc[i] = ets->prio_tc[i];282		dcb->tc_tx_pct[i] = ets->tc_tx_bw[i];283		dcb->tc_tsa[i] = ets->tc_tsa[i];284	}285 286	change = nfp_refresh_tc2idx(nn);287	nfp_nic_fill_ets(nn);288	dcb->ets_init = true;289	if (change || !dcb->rate_init) {290		err = update_dscp_maxrate(dev, &update);291		if (err) {292			nfp_warn(app->cpp,293				 "nfp dcbnl ieee setets ERROR:%d.",294				 err);295			return err;296		}297 298		dcb->rate_init = true;299	}300	nfp_nic_set_enable(nn, NFP_DCB_ALL_QOS_ENABLE, &update);301	nfp_nic_set_trust(nn, &update);302	err = nfp_net_mbox_lock(nn, NFP_DCB_UPDATE_MSK_SZ);303	if (err)304		return err;305 306	nn_writel(nn, nn->tlv_caps.mbox_off + NFP_NET_CFG_MBOX_SIMPLE_VAL,307		  update | NFP_DCB_MSG_MSK_TSA | NFP_DCB_MSG_MSK_PCT |308		  NFP_DCB_MSG_MSK_PCP);309 310	return nfp_net_mbox_reconfig_and_unlock(nn, cmd);311}312 313static int nfp_nic_dcbnl_ieee_getmaxrate(struct net_device *dev,314					 struct ieee_maxrate *maxrate)315{316	struct nfp_net *nn = netdev_priv(dev);317	struct nfp_dcb *dcb;318 319	dcb = get_dcb_priv(nn);320 321	for (unsigned int i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)322		maxrate->tc_maxrate[i] = dcb->tc_maxrate[i];323 324	return 0;325}326 327static int nfp_nic_dcbnl_ieee_setmaxrate(struct net_device *dev,328					 struct ieee_maxrate *maxrate)329{330	const u32 cmd = NFP_NET_CFG_MBOX_CMD_DCB_UPDATE;331	struct nfp_net *nn = netdev_priv(dev);332	struct nfp_app *app = nn->app;333	struct nfp_dcb *dcb;334	u32 update = 0;335	int err;336 337	err = nfp_fill_maxrate(nn, maxrate->tc_maxrate);338	if (err) {339		nfp_warn(app->cpp,340			 "nfp dcbnl ieee setmaxrate ERROR:%d.",341			 err);342		return err;343	}344 345	dcb = get_dcb_priv(nn);346 347	dcb->rate_init = true;348	nfp_nic_set_enable(nn, NFP_DCB_ALL_QOS_ENABLE, &update);349	nfp_nic_set_trust(nn, &update);350	nfp_nic_ets_init(nn, &update);351 352	err = nfp_net_mbox_lock(nn, NFP_DCB_UPDATE_MSK_SZ);353	if (err)354		return err;355 356	nn_writel(nn, nn->tlv_caps.mbox_off + NFP_NET_CFG_MBOX_SIMPLE_VAL,357		  update | NFP_DCB_MSG_MSK_RATE);358 359	return nfp_net_mbox_reconfig_and_unlock(nn, cmd);360}361 362static int nfp_nic_set_trust_status(struct nfp_net *nn, u8 status)363{364	const u32 cmd = NFP_NET_CFG_MBOX_CMD_DCB_UPDATE;365	struct nfp_dcb *dcb;366	u32 update = 0;367	int err;368 369	dcb = get_dcb_priv(nn);370	if (!dcb->rate_init) {371		err = nfp_fill_maxrate(nn, dcb->tc_maxrate);372		if (err)373			return err;374 375		update |= NFP_DCB_MSG_MSK_RATE;376		dcb->rate_init = true;377	}378 379	err = nfp_net_mbox_lock(nn, NFP_DCB_UPDATE_MSK_SZ);380	if (err)381		return err;382 383	nfp_nic_ets_init(nn, &update);384	writeb(status, dcb->dcbcfg_tbl + dcb->cfg_offset +385	       NFP_DCB_DATA_OFF_TRUST);386	nfp_nic_set_enable(nn, NFP_DCB_ALL_QOS_ENABLE, &update);387	nn_writel(nn, nn->tlv_caps.mbox_off + NFP_NET_CFG_MBOX_SIMPLE_VAL,388		  update | NFP_DCB_MSG_MSK_TRUST);389 390	err = nfp_net_mbox_reconfig_and_unlock(nn, cmd);391	if (err)392		return err;393 394	dcb->trust_status = status;395 396	return 0;397}398 399static int nfp_nic_set_dscp2prio(struct nfp_net *nn, u8 dscp, u8 prio)400{401	const u32 cmd = NFP_NET_CFG_MBOX_CMD_DCB_UPDATE;402	struct nfp_dcb *dcb;403	u8 idx, tc;404	int err;405 406	err = nfp_net_mbox_lock(nn, NFP_DCB_UPDATE_MSK_SZ);407	if (err)408		return err;409 410	dcb = get_dcb_priv(nn);411 412	tc = dcb->prio2tc[prio];413	idx = dcb->tc2idx[tc];414 415	writeb(idx, dcb->dcbcfg_tbl + dcb->cfg_offset +416	       NFP_DCB_DATA_OFF_DSCP2IDX + dscp);417 418	nn_writel(nn, nn->tlv_caps.mbox_off +419		  NFP_NET_CFG_MBOX_SIMPLE_VAL, NFP_DCB_MSG_MSK_DSCP);420 421	err = nfp_net_mbox_reconfig_and_unlock(nn, cmd);422	if (err)423		return err;424 425	dcb->dscp2prio[dscp] = prio;426 427	return 0;428}429 430static int nfp_nic_dcbnl_ieee_setapp(struct net_device *dev,431				     struct dcb_app *app)432{433	struct nfp_net *nn = netdev_priv(dev);434	struct dcb_app old_app;435	struct nfp_dcb *dcb;436	bool is_new;437	int err;438 439	if (app->selector != IEEE_8021QAZ_APP_SEL_DSCP)440		return -EINVAL;441 442	dcb = get_dcb_priv(nn);443 444	/* Save the old entry info */445	old_app.selector = IEEE_8021QAZ_APP_SEL_DSCP;446	old_app.protocol = app->protocol;447	old_app.priority = dcb->dscp2prio[app->protocol];448 449	/* Check trust status */450	if (!dcb->dscp_cnt) {451		err = nfp_nic_set_trust_status(nn, NFP_DCB_TRUST_DSCP);452		if (err)453			return err;454	}455 456	/* Check if the new mapping is same as old or in init stage */457	if (app->priority != old_app.priority || app->priority == 0) {458		err = nfp_nic_set_dscp2prio(nn, app->protocol, app->priority);459		if (err)460			return err;461	}462 463	/* Delete the old entry if exists */464	is_new = !!dcb_ieee_delapp(dev, &old_app);465 466	/* Add new entry and update counter */467	err = dcb_ieee_setapp(dev, app);468	if (err)469		return err;470 471	if (is_new)472		dcb->dscp_cnt++;473 474	return 0;475}476 477static int nfp_nic_dcbnl_ieee_delapp(struct net_device *dev,478				     struct dcb_app *app)479{480	struct nfp_net *nn = netdev_priv(dev);481	struct nfp_dcb *dcb;482	int err;483 484	if (app->selector != IEEE_8021QAZ_APP_SEL_DSCP)485		return -EINVAL;486 487	dcb = get_dcb_priv(nn);488 489	/* Check if the dcb_app param match fw */490	if (app->priority != dcb->dscp2prio[app->protocol])491		return -ENOENT;492 493	/* Set fw dscp mapping to 0 */494	err = nfp_nic_set_dscp2prio(nn, app->protocol, 0);495	if (err)496		return err;497 498	/* Delete app from dcb list */499	err = dcb_ieee_delapp(dev, app);500	if (err)501		return err;502 503	/* Decrease dscp counter */504	dcb->dscp_cnt--;505 506	/* If no dscp mapping is configured, trust pcp */507	if (dcb->dscp_cnt == 0)508		return nfp_nic_set_trust_status(nn, NFP_DCB_TRUST_PCP);509 510	return 0;511}512 513static const struct dcbnl_rtnl_ops nfp_nic_dcbnl_ops = {514	/* ieee 802.1Qaz std */515	.ieee_getets	= nfp_nic_dcbnl_ieee_getets,516	.ieee_setets	= nfp_nic_dcbnl_ieee_setets,517	.ieee_getmaxrate = nfp_nic_dcbnl_ieee_getmaxrate,518	.ieee_setmaxrate = nfp_nic_dcbnl_ieee_setmaxrate,519	.ieee_setapp	= nfp_nic_dcbnl_ieee_setapp,520	.ieee_delapp	= nfp_nic_dcbnl_ieee_delapp,521};522 523int nfp_nic_dcb_init(struct nfp_net *nn)524{525	struct nfp_app *app = nn->app;526	struct nfp_dcb *dcb;527	int err;528 529	dcb = get_dcb_priv(nn);530	dcb->cfg_offset = NFP_DCB_CFG_STRIDE * nn->id;531	dcb->dcbcfg_tbl = nfp_pf_map_rtsym(app->pf, "net.dcbcfg_tbl",532					   "_abi_dcb_cfg",533					   dcb->cfg_offset, &dcb->dcbcfg_tbl_area);534	if (IS_ERR(dcb->dcbcfg_tbl)) {535		if (PTR_ERR(dcb->dcbcfg_tbl) != -ENOENT) {536			err = PTR_ERR(dcb->dcbcfg_tbl);537			dcb->dcbcfg_tbl = NULL;538			nfp_err(app->cpp,539				"Failed to map dcbcfg_tbl area, min_size %u.\n",540				dcb->cfg_offset);541			return err;542		}543		dcb->dcbcfg_tbl = NULL;544	}545 546	if (dcb->dcbcfg_tbl) {547		for (unsigned int i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {548			dcb->prio2tc[i] = i;549			dcb->tc2idx[i] = i;550			dcb->tc_tx_pct[i] = 0;551			dcb->tc_maxrate[i] = 0;552			dcb->tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR;553		}554		dcb->trust_status = NFP_DCB_TRUST_INVALID;555		dcb->rate_init = false;556		dcb->ets_init = false;557 558		nn->dp.netdev->dcbnl_ops = &nfp_nic_dcbnl_ops;559	}560 561	return 0;562}563 564void nfp_nic_dcb_clean(struct nfp_net *nn)565{566	struct nfp_dcb *dcb;567 568	dcb = get_dcb_priv(nn);569	if (dcb->dcbcfg_tbl_area)570		nfp_cpp_area_release_free(dcb->dcbcfg_tbl_area);571}572