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(val: (u16)ratembps, addr: 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, max_rate_array: 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(val: dcb->tc2idx[dcb->prio2tc[dcb->dscp2prio[i]]], |
166 | addr: 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(val: trust, addr: 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(addr: dcb->dcbcfg_tbl + dcb->cfg_offset + |
201 | NFP_DCB_DATA_OFF_ENABLE); |
202 | if (value != enable) { |
203 | writel(val: enable, addr: 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(val: dcb->tc2idx[dcb->prio2tc[i]], |
243 | addr: dcb->dcbcfg_tbl + dcb->cfg_offset + NFP_DCB_DATA_OFF_PCP2IDX + i); |
244 | writeb(val: dcb->tc_tx_pct[i], addr: dcb->dcbcfg_tbl + |
245 | dcb->cfg_offset + NFP_DCB_DATA_OFF_IDX_BW_PCT + dcb->tc2idx[i]); |
246 | writeb(val: nfp_tsa_ieee2nfp(tsa: dcb->tc_tsa[i]), addr: 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: &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: &update); |
301 | nfp_nic_set_trust(nn, update: &update); |
302 | err = nfp_net_mbox_lock(nn, NFP_DCB_UPDATE_MSK_SZ); |
303 | if (err) |
304 | return err; |
305 | |
306 | nn_writel(nn, off: nn->tlv_caps.mbox_off + NFP_NET_CFG_MBOX_SIMPLE_VAL, |
307 | val: 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, mbox_cmd: 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, max_rate_array: 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: &update); |
349 | nfp_nic_set_trust(nn, update: &update); |
350 | nfp_nic_ets_init(nn, update: &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, off: nn->tlv_caps.mbox_off + NFP_NET_CFG_MBOX_SIMPLE_VAL, |
357 | val: update | NFP_DCB_MSG_MSK_RATE); |
358 | |
359 | return nfp_net_mbox_reconfig_and_unlock(nn, mbox_cmd: 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, max_rate_array: 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: &update); |
384 | writeb(val: status, addr: dcb->dcbcfg_tbl + dcb->cfg_offset + |
385 | NFP_DCB_DATA_OFF_TRUST); |
386 | nfp_nic_set_enable(nn, NFP_DCB_ALL_QOS_ENABLE, update: &update); |
387 | nn_writel(nn, off: nn->tlv_caps.mbox_off + NFP_NET_CFG_MBOX_SIMPLE_VAL, |
388 | val: update | NFP_DCB_MSG_MSK_TRUST); |
389 | |
390 | err = nfp_net_mbox_reconfig_and_unlock(nn, mbox_cmd: 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(val: idx, addr: dcb->dcbcfg_tbl + dcb->cfg_offset + |
416 | NFP_DCB_DATA_OFF_DSCP2IDX + dscp); |
417 | |
418 | nn_writel(nn, off: 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, mbox_cmd: 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, dscp: app->protocol, prio: 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, dscp: app->protocol, prio: 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(pf: app->pf, name: "net.dcbcfg_tbl" , |
532 | sym_fmt: "_abi_dcb_cfg" , |
533 | min_size: dcb->cfg_offset, area: &dcb->dcbcfg_tbl_area); |
534 | if (IS_ERR(ptr: dcb->dcbcfg_tbl)) { |
535 | if (PTR_ERR(ptr: dcb->dcbcfg_tbl) != -ENOENT) { |
536 | err = PTR_ERR(ptr: 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(area: dcb->dcbcfg_tbl_area); |
571 | } |
572 | |