xref: /linux/drivers/net/ethernet/netronome/nfp/nic/dcb.c (revision b8fa3e3833c14151a47ebebbc5427dcfe94bb407)
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	1
18 #define NFP_DCB_TRUST_DSCP	2
19 #define NFP_DCB_TRUST_INVALID	0xff
20 
21 #define NFP_DCB_TSA_VENDOR	1
22 #define NFP_DCB_TSA_STRICT	2
23 #define NFP_DCB_TSA_ETS		3
24 
25 #define NFP_DCB_GBL_ENABLE	BIT(0)
26 #define NFP_DCB_QOS_ENABLE	BIT(1)
27 #define NFP_DCB_DISABLE		0
28 #define NFP_DCB_ALL_QOS_ENABLE	(NFP_DCB_GBL_ENABLE | NFP_DCB_QOS_ENABLE)
29 
30 #define NFP_DCB_UPDATE_MSK_SZ	4
31 #define NFP_DCB_TC_RATE_MAX	0xffff
32 
33 #define NFP_DCB_DATA_OFF_DSCP2IDX	0
34 #define NFP_DCB_DATA_OFF_PCP2IDX	64
35 #define NFP_DCB_DATA_OFF_TSA		80
36 #define NFP_DCB_DATA_OFF_IDX_BW_PCT	88
37 #define NFP_DCB_DATA_OFF_RATE		96
38 #define NFP_DCB_DATA_OFF_CAP		112
39 #define NFP_DCB_DATA_OFF_ENABLE		116
40 #define NFP_DCB_DATA_OFF_TRUST		120
41 
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 
50 static 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 
57 static 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 
69 static 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 
86 static 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 
116 static 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 
148 static 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 
175 static 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 
193 static 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 
209 static 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 
235 static 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 
251 static 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 
263 static 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 
313 static 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 
327 static 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 
362 static 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 
399 static 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 
430 static 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 
477 static 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 
513 static 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 
523 int 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 
564 void 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