1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2013-2014 Chelsio Communications. All rights reserved.
4 *
5 * Written by Anish Bhatt (anish@chelsio.com)
6 * Casey Leedom (leedom@chelsio.com)
7 */
8
9#include "cxgb4.h"
10
11/* DCBx version control
12 */
13const char * const dcb_ver_array[] = {
14 "Unknown",
15 "DCBx-CIN",
16 "DCBx-CEE 1.01",
17 "DCBx-IEEE",
18 "", "", "",
19 "Auto Negotiated"
20};
21
22static inline bool cxgb4_dcb_state_synced(enum cxgb4_dcb_state state)
23{
24 if (state == CXGB4_DCB_STATE_FW_ALLSYNCED ||
25 state == CXGB4_DCB_STATE_HOST)
26 return true;
27 else
28 return false;
29}
30
31/* Initialize a port's Data Center Bridging state.
32 */
33void cxgb4_dcb_state_init(struct net_device *dev)
34{
35 struct port_info *pi = netdev2pinfo(dev);
36 struct port_dcb_info *dcb = &pi->dcb;
37 int version_temp = dcb->dcb_version;
38
39 memset(dcb, 0, sizeof(struct port_dcb_info));
40 dcb->state = CXGB4_DCB_STATE_START;
41 if (version_temp)
42 dcb->dcb_version = version_temp;
43
44 netdev_dbg(dev, "%s: Initializing DCB state for port[%d]\n",
45 __func__, pi->port_id);
46}
47
48void cxgb4_dcb_version_init(struct net_device *dev)
49{
50 struct port_info *pi = netdev2pinfo(dev);
51 struct port_dcb_info *dcb = &pi->dcb;
52
53 /* Any writes here are only done on kernels that exlicitly need
54 * a specific version, say < 2.6.38 which only support CEE
55 */
56 dcb->dcb_version = FW_PORT_DCB_VER_AUTO;
57}
58
59static void cxgb4_dcb_cleanup_apps(struct net_device *dev)
60{
61 struct port_info *pi = netdev2pinfo(dev);
62 struct adapter *adap = pi->adapter;
63 struct port_dcb_info *dcb = &pi->dcb;
64 struct dcb_app app;
65 int i, err;
66
67 /* zero priority implies remove */
68 app.priority = 0;
69
70 for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
71 /* Check if app list is exhausted */
72 if (!dcb->app_priority[i].protocolid)
73 break;
74
75 app.protocol = dcb->app_priority[i].protocolid;
76
77 if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) {
78 app.priority = dcb->app_priority[i].user_prio_map;
79 app.selector = dcb->app_priority[i].sel_field + 1;
80 err = dcb_ieee_delapp(dev, &app);
81 } else {
82 app.selector = !!(dcb->app_priority[i].sel_field);
83 err = dcb_setapp(dev, &app);
84 }
85
86 if (err) {
87 dev_err(adap->pdev_dev,
88 "Failed DCB Clear %s Application Priority: sel=%d, prot=%d, err=%d\n",
89 dcb_ver_array[dcb->dcb_version], app.selector,
90 app.protocol, -err);
91 break;
92 }
93 }
94}
95
96/* Reset a port's Data Center Bridging state. Typically used after a
97 * Link Down event.
98 */
99void cxgb4_dcb_reset(struct net_device *dev)
100{
101 cxgb4_dcb_cleanup_apps(dev);
102 cxgb4_dcb_state_init(dev);
103}
104
105/* update the dcb port support, if version is IEEE then set it to
106 * FW_PORT_DCB_VER_IEEE and if DCB_CAP_DCBX_VER_CEE is already set then
107 * clear that. and if it is set to CEE then set dcb supported to
108 * DCB_CAP_DCBX_VER_CEE & if DCB_CAP_DCBX_VER_IEEE is set, clear it
109 */
110static inline void cxgb4_dcb_update_support(struct port_dcb_info *dcb)
111{
112 if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) {
113 if (dcb->supported & DCB_CAP_DCBX_VER_CEE)
114 dcb->supported &= ~DCB_CAP_DCBX_VER_CEE;
115 dcb->supported |= DCB_CAP_DCBX_VER_IEEE;
116 } else if (dcb->dcb_version == FW_PORT_DCB_VER_CEE1D01) {
117 if (dcb->supported & DCB_CAP_DCBX_VER_IEEE)
118 dcb->supported &= ~DCB_CAP_DCBX_VER_IEEE;
119 dcb->supported |= DCB_CAP_DCBX_VER_CEE;
120 }
121}
122
123/* Finite State machine for Data Center Bridging.
124 */
125void cxgb4_dcb_state_fsm(struct net_device *dev,
126 enum cxgb4_dcb_state_input transition_to)
127{
128 struct port_info *pi = netdev2pinfo(dev);
129 struct port_dcb_info *dcb = &pi->dcb;
130 struct adapter *adap = pi->adapter;
131 enum cxgb4_dcb_state current_state = dcb->state;
132
133 netdev_dbg(dev, "%s: State change from %d to %d for %s\n",
134 __func__, dcb->state, transition_to, dev->name);
135
136 switch (current_state) {
137 case CXGB4_DCB_STATE_START: {
138 switch (transition_to) {
139 case CXGB4_DCB_INPUT_FW_DISABLED: {
140 /* we're going to use Host DCB */
141 dcb->state = CXGB4_DCB_STATE_HOST;
142 dcb->supported = CXGB4_DCBX_HOST_SUPPORT;
143 break;
144 }
145
146 case CXGB4_DCB_INPUT_FW_ENABLED: {
147 /* we're going to use Firmware DCB */
148 dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
149 dcb->supported = DCB_CAP_DCBX_LLD_MANAGED;
150 if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE)
151 dcb->supported |= DCB_CAP_DCBX_VER_IEEE;
152 else
153 dcb->supported |= DCB_CAP_DCBX_VER_CEE;
154 break;
155 }
156
157 case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
158 /* expected transition */
159 break;
160 }
161
162 case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
163 dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED;
164 break;
165 }
166
167 default:
168 goto bad_state_input;
169 }
170 break;
171 }
172
173 case CXGB4_DCB_STATE_FW_INCOMPLETE: {
174 if (transition_to != CXGB4_DCB_INPUT_FW_DISABLED) {
175 /* during this CXGB4_DCB_STATE_FW_INCOMPLETE state,
176 * check if the dcb version is changed (there can be
177 * mismatch in default config & the negotiated switch
178 * configuration at FW, so update the dcb support
179 * accordingly.
180 */
181 cxgb4_dcb_update_support(dcb);
182 }
183 switch (transition_to) {
184 case CXGB4_DCB_INPUT_FW_ENABLED: {
185 /* we're alreaady in firmware DCB mode */
186 break;
187 }
188
189 case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
190 /* we're already incomplete */
191 break;
192 }
193
194 case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
195 dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED;
196 dcb->enabled = 1;
197 linkwatch_fire_event(dev);
198 break;
199 }
200
201 default:
202 goto bad_state_input;
203 }
204 break;
205 }
206
207 case CXGB4_DCB_STATE_FW_ALLSYNCED: {
208 switch (transition_to) {
209 case CXGB4_DCB_INPUT_FW_ENABLED: {
210 /* we're alreaady in firmware DCB mode */
211 break;
212 }
213
214 case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
215 /* We were successfully running with firmware DCB but
216 * now it's telling us that it's in an "incomplete
217 * state. We need to reset back to a ground state
218 * of incomplete.
219 */
220 cxgb4_dcb_reset(dev);
221 dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
222 dcb->supported = CXGB4_DCBX_FW_SUPPORT;
223 linkwatch_fire_event(dev);
224 break;
225 }
226
227 case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
228 /* we're already all sync'ed
229 * this is only applicable for IEEE or
230 * when another VI already completed negotiaton
231 */
232 dcb->enabled = 1;
233 linkwatch_fire_event(dev);
234 break;
235 }
236
237 default:
238 goto bad_state_input;
239 }
240 break;
241 }
242
243 case CXGB4_DCB_STATE_HOST: {
244 switch (transition_to) {
245 case CXGB4_DCB_INPUT_FW_DISABLED: {
246 /* we're alreaady in Host DCB mode */
247 break;
248 }
249
250 default:
251 goto bad_state_input;
252 }
253 break;
254 }
255
256 default:
257 goto bad_state_transition;
258 }
259 return;
260
261bad_state_input:
262 dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: illegal input symbol %d\n",
263 transition_to);
264 return;
265
266bad_state_transition:
267 dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: bad state transition, state = %d, input = %d\n",
268 current_state, transition_to);
269}
270
271/* Handle a DCB/DCBX update message from the firmware.
272 */
273void cxgb4_dcb_handle_fw_update(struct adapter *adap,
274 const struct fw_port_cmd *pcmd)
275{
276 const union fw_port_dcb *fwdcb = &pcmd->u.dcb;
277 int port = FW_PORT_CMD_PORTID_G(be32_to_cpu(pcmd->op_to_portid));
278 struct net_device *dev = adap->port[adap->chan_map[port]];
279 struct port_info *pi = netdev_priv(dev);
280 struct port_dcb_info *dcb = &pi->dcb;
281 int dcb_type = pcmd->u.dcb.pgid.type;
282 int dcb_running_version;
283
284 /* Handle Firmware DCB Control messages separately since they drive
285 * our state machine.
286 */
287 if (dcb_type == FW_PORT_DCB_TYPE_CONTROL) {
288 enum cxgb4_dcb_state_input input =
289 ((pcmd->u.dcb.control.all_syncd_pkd &
290 FW_PORT_CMD_ALL_SYNCD_F)
291 ? CXGB4_DCB_INPUT_FW_ALLSYNCED
292 : CXGB4_DCB_INPUT_FW_INCOMPLETE);
293
294 if (dcb->dcb_version != FW_PORT_DCB_VER_UNKNOWN) {
295 dcb_running_version = FW_PORT_CMD_DCB_VERSION_G(
296 be16_to_cpu(
297 pcmd->u.dcb.control.dcb_version_to_app_state));
298 if (dcb_running_version == FW_PORT_DCB_VER_CEE1D01 ||
299 dcb_running_version == FW_PORT_DCB_VER_IEEE) {
300 dcb->dcb_version = dcb_running_version;
301 dev_warn(adap->pdev_dev, "Interface %s is running %s\n",
302 dev->name,
303 dcb_ver_array[dcb->dcb_version]);
304 } else {
305 dev_warn(adap->pdev_dev,
306 "Something screwed up, requested firmware for %s, but firmware returned %s instead\n",
307 dcb_ver_array[dcb->dcb_version],
308 dcb_ver_array[dcb_running_version]);
309 dcb->dcb_version = FW_PORT_DCB_VER_UNKNOWN;
310 }
311 }
312
313 cxgb4_dcb_state_fsm(dev, transition_to: input);
314 return;
315 }
316
317 /* It's weird, and almost certainly an error, to get Firmware DCB
318 * messages when we either haven't been told whether we're going to be
319 * doing Host or Firmware DCB; and even worse when we've been told
320 * that we're doing Host DCB!
321 */
322 if (dcb->state == CXGB4_DCB_STATE_START ||
323 dcb->state == CXGB4_DCB_STATE_HOST) {
324 dev_err(adap->pdev_dev, "Receiving Firmware DCB messages in State %d\n",
325 dcb->state);
326 return;
327 }
328
329 /* Now handle the general Firmware DCB update messages ...
330 */
331 switch (dcb_type) {
332 case FW_PORT_DCB_TYPE_PGID:
333 dcb->pgid = be32_to_cpu(fwdcb->pgid.pgid);
334 dcb->msgs |= CXGB4_DCB_FW_PGID;
335 break;
336
337 case FW_PORT_DCB_TYPE_PGRATE:
338 dcb->pg_num_tcs_supported = fwdcb->pgrate.num_tcs_supported;
339 memcpy(dcb->pgrate, &fwdcb->pgrate.pgrate,
340 sizeof(dcb->pgrate));
341 memcpy(dcb->tsa, &fwdcb->pgrate.tsa,
342 sizeof(dcb->tsa));
343 dcb->msgs |= CXGB4_DCB_FW_PGRATE;
344 if (dcb->msgs & CXGB4_DCB_FW_PGID)
345 IEEE_FAUX_SYNC(dev, dcb);
346 break;
347
348 case FW_PORT_DCB_TYPE_PRIORATE:
349 memcpy(dcb->priorate, &fwdcb->priorate.strict_priorate,
350 sizeof(dcb->priorate));
351 dcb->msgs |= CXGB4_DCB_FW_PRIORATE;
352 break;
353
354 case FW_PORT_DCB_TYPE_PFC:
355 dcb->pfcen = fwdcb->pfc.pfcen;
356 dcb->pfc_num_tcs_supported = fwdcb->pfc.max_pfc_tcs;
357 dcb->msgs |= CXGB4_DCB_FW_PFC;
358 IEEE_FAUX_SYNC(dev, dcb);
359 break;
360
361 case FW_PORT_DCB_TYPE_APP_ID: {
362 const struct fw_port_app_priority *fwap = &fwdcb->app_priority;
363 int idx = fwap->idx;
364 struct app_priority *ap = &dcb->app_priority[idx];
365
366 struct dcb_app app = {
367 .protocol = be16_to_cpu(fwap->protocolid),
368 };
369 int err;
370
371 /* Convert from firmware format to relevant format
372 * when using app selector
373 */
374 if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) {
375 app.selector = (fwap->sel_field + 1);
376 app.priority = ffs(fwap->user_prio_map) - 1;
377 err = dcb_ieee_setapp(dev, &app);
378 IEEE_FAUX_SYNC(dev, dcb);
379 } else {
380 /* Default is CEE */
381 app.selector = !!(fwap->sel_field);
382 app.priority = fwap->user_prio_map;
383 err = dcb_setapp(dev, &app);
384 }
385
386 if (err)
387 dev_err(adap->pdev_dev,
388 "Failed DCB Set Application Priority: sel=%d, prot=%d, prio=%d, err=%d\n",
389 app.selector, app.protocol, app.priority, -err);
390
391 ap->user_prio_map = fwap->user_prio_map;
392 ap->sel_field = fwap->sel_field;
393 ap->protocolid = be16_to_cpu(fwap->protocolid);
394 dcb->msgs |= CXGB4_DCB_FW_APP_ID;
395 break;
396 }
397
398 default:
399 dev_err(adap->pdev_dev, "Unknown DCB update type received %x\n",
400 dcb_type);
401 break;
402 }
403}
404
405/* Data Center Bridging netlink operations.
406 */
407
408
409/* Get current DCB enabled/disabled state.
410 */
411static u8 cxgb4_getstate(struct net_device *dev)
412{
413 struct port_info *pi = netdev2pinfo(dev);
414
415 return pi->dcb.enabled;
416}
417
418/* Set DCB enabled/disabled.
419 */
420static u8 cxgb4_setstate(struct net_device *dev, u8 enabled)
421{
422 struct port_info *pi = netdev2pinfo(dev);
423
424 /* If DCBx is host-managed, dcb is enabled by outside lldp agents */
425 if (pi->dcb.state == CXGB4_DCB_STATE_HOST) {
426 pi->dcb.enabled = enabled;
427 return 0;
428 }
429
430 /* Firmware doesn't provide any mechanism to control the DCB state.
431 */
432 if (enabled != (pi->dcb.state == CXGB4_DCB_STATE_FW_ALLSYNCED))
433 return 1;
434
435 return 0;
436}
437
438static void cxgb4_getpgtccfg(struct net_device *dev, int tc,
439 u8 *prio_type, u8 *pgid, u8 *bw_per,
440 u8 *up_tc_map, int local)
441{
442 struct fw_port_cmd pcmd;
443 struct port_info *pi = netdev2pinfo(dev);
444 struct adapter *adap = pi->adapter;
445 int err;
446
447 *prio_type = *pgid = *bw_per = *up_tc_map = 0;
448
449 if (local)
450 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
451 else
452 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
453
454 pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
455 err = t4_wr_mbox(adap, mbox: adap->mbox, cmd: &pcmd, size: sizeof(pcmd), rpl: &pcmd);
456 if (err != FW_PORT_DCB_CFG_SUCCESS) {
457 dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
458 return;
459 }
460 *pgid = (be32_to_cpu(pcmd.u.dcb.pgid.pgid) >> (tc * 4)) & 0xf;
461
462 if (local)
463 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
464 else
465 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
466 pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
467 err = t4_wr_mbox(adap, mbox: adap->mbox, cmd: &pcmd, size: sizeof(pcmd), rpl: &pcmd);
468 if (err != FW_PORT_DCB_CFG_SUCCESS) {
469 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
470 -err);
471 return;
472 }
473
474 *bw_per = pcmd.u.dcb.pgrate.pgrate[*pgid];
475 *up_tc_map = (1 << tc);
476
477 /* prio_type is link strict */
478 if (*pgid != 0xF)
479 *prio_type = 0x2;
480}
481
482static void cxgb4_getpgtccfg_tx(struct net_device *dev, int tc,
483 u8 *prio_type, u8 *pgid, u8 *bw_per,
484 u8 *up_tc_map)
485{
486 /* tc 0 is written at MSB position */
487 return cxgb4_getpgtccfg(dev, tc: (7 - tc), prio_type, pgid, bw_per,
488 up_tc_map, local: 1);
489}
490
491
492static void cxgb4_getpgtccfg_rx(struct net_device *dev, int tc,
493 u8 *prio_type, u8 *pgid, u8 *bw_per,
494 u8 *up_tc_map)
495{
496 /* tc 0 is written at MSB position */
497 return cxgb4_getpgtccfg(dev, tc: (7 - tc), prio_type, pgid, bw_per,
498 up_tc_map, local: 0);
499}
500
501static void cxgb4_setpgtccfg_tx(struct net_device *dev, int tc,
502 u8 prio_type, u8 pgid, u8 bw_per,
503 u8 up_tc_map)
504{
505 struct fw_port_cmd pcmd;
506 struct port_info *pi = netdev2pinfo(dev);
507 struct adapter *adap = pi->adapter;
508 int fw_tc = 7 - tc;
509 u32 _pgid;
510 int err;
511
512 if (pgid == DCB_ATTR_VALUE_UNDEFINED)
513 return;
514 if (bw_per == DCB_ATTR_VALUE_UNDEFINED)
515 return;
516
517 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
518 pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
519
520 err = t4_wr_mbox(adap, mbox: adap->mbox, cmd: &pcmd, size: sizeof(pcmd), rpl: &pcmd);
521 if (err != FW_PORT_DCB_CFG_SUCCESS) {
522 dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
523 return;
524 }
525
526 _pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
527 _pgid &= ~(0xF << (fw_tc * 4));
528 _pgid |= pgid << (fw_tc * 4);
529 pcmd.u.dcb.pgid.pgid = cpu_to_be32(_pgid);
530
531 INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
532
533 err = t4_wr_mbox(adap, mbox: adap->mbox, cmd: &pcmd, size: sizeof(pcmd), rpl: &pcmd);
534 if (err != FW_PORT_DCB_CFG_SUCCESS) {
535 dev_err(adap->pdev_dev, "DCB write PGID failed with %d\n",
536 -err);
537 return;
538 }
539
540 memset(&pcmd, 0, sizeof(struct fw_port_cmd));
541
542 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
543 pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
544
545 err = t4_wr_mbox(adap, mbox: adap->mbox, cmd: &pcmd, size: sizeof(pcmd), rpl: &pcmd);
546 if (err != FW_PORT_DCB_CFG_SUCCESS) {
547 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
548 -err);
549 return;
550 }
551
552 pcmd.u.dcb.pgrate.pgrate[pgid] = bw_per;
553
554 INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
555 if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
556 pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F);
557
558 err = t4_wr_mbox(adap, mbox: adap->mbox, cmd: &pcmd, size: sizeof(pcmd), rpl: &pcmd);
559 if (err != FW_PORT_DCB_CFG_SUCCESS)
560 dev_err(adap->pdev_dev, "DCB write PGRATE failed with %d\n",
561 -err);
562}
563
564static void cxgb4_getpgbwgcfg(struct net_device *dev, int pgid, u8 *bw_per,
565 int local)
566{
567 struct fw_port_cmd pcmd;
568 struct port_info *pi = netdev2pinfo(dev);
569 struct adapter *adap = pi->adapter;
570 int err;
571
572 if (local)
573 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
574 else
575 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
576
577 pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
578 err = t4_wr_mbox(adap, mbox: adap->mbox, cmd: &pcmd, size: sizeof(pcmd), rpl: &pcmd);
579 if (err != FW_PORT_DCB_CFG_SUCCESS) {
580 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
581 -err);
582 return;
583 }
584
585 *bw_per = pcmd.u.dcb.pgrate.pgrate[pgid];
586}
587
588static void cxgb4_getpgbwgcfg_tx(struct net_device *dev, int pgid, u8 *bw_per)
589{
590 return cxgb4_getpgbwgcfg(dev, pgid, bw_per, local: 1);
591}
592
593static void cxgb4_getpgbwgcfg_rx(struct net_device *dev, int pgid, u8 *bw_per)
594{
595 return cxgb4_getpgbwgcfg(dev, pgid, bw_per, local: 0);
596}
597
598static void cxgb4_setpgbwgcfg_tx(struct net_device *dev, int pgid,
599 u8 bw_per)
600{
601 struct fw_port_cmd pcmd;
602 struct port_info *pi = netdev2pinfo(dev);
603 struct adapter *adap = pi->adapter;
604 int err;
605
606 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
607 pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
608
609 err = t4_wr_mbox(adap, mbox: adap->mbox, cmd: &pcmd, size: sizeof(pcmd), rpl: &pcmd);
610 if (err != FW_PORT_DCB_CFG_SUCCESS) {
611 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
612 -err);
613 return;
614 }
615
616 pcmd.u.dcb.pgrate.pgrate[pgid] = bw_per;
617
618 INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
619 if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
620 pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F);
621
622 err = t4_wr_mbox(adap, mbox: adap->mbox, cmd: &pcmd, size: sizeof(pcmd), rpl: &pcmd);
623
624 if (err != FW_PORT_DCB_CFG_SUCCESS)
625 dev_err(adap->pdev_dev, "DCB write PGRATE failed with %d\n",
626 -err);
627}
628
629/* Return whether the specified Traffic Class Priority has Priority Pause
630 * Frames enabled.
631 */
632static void cxgb4_getpfccfg(struct net_device *dev, int priority, u8 *pfccfg)
633{
634 struct port_info *pi = netdev2pinfo(dev);
635 struct port_dcb_info *dcb = &pi->dcb;
636
637 if (!cxgb4_dcb_state_synced(state: dcb->state) ||
638 priority >= CXGB4_MAX_PRIORITY)
639 *pfccfg = 0;
640 else
641 *pfccfg = (pi->dcb.pfcen >> (7 - priority)) & 1;
642}
643
644/* Enable/disable Priority Pause Frames for the specified Traffic Class
645 * Priority.
646 */
647static void cxgb4_setpfccfg(struct net_device *dev, int priority, u8 pfccfg)
648{
649 struct fw_port_cmd pcmd;
650 struct port_info *pi = netdev2pinfo(dev);
651 struct adapter *adap = pi->adapter;
652 int err;
653
654 if (!cxgb4_dcb_state_synced(state: pi->dcb.state) ||
655 priority >= CXGB4_MAX_PRIORITY)
656 return;
657
658 INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
659 if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
660 pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F);
661
662 pcmd.u.dcb.pfc.type = FW_PORT_DCB_TYPE_PFC;
663 pcmd.u.dcb.pfc.pfcen = pi->dcb.pfcen;
664
665 if (pfccfg)
666 pcmd.u.dcb.pfc.pfcen |= (1 << (7 - priority));
667 else
668 pcmd.u.dcb.pfc.pfcen &= (~(1 << (7 - priority)));
669
670 err = t4_wr_mbox(adap, mbox: adap->mbox, cmd: &pcmd, size: sizeof(pcmd), rpl: &pcmd);
671 if (err != FW_PORT_DCB_CFG_SUCCESS) {
672 dev_err(adap->pdev_dev, "DCB PFC write failed with %d\n", -err);
673 return;
674 }
675
676 pi->dcb.pfcen = pcmd.u.dcb.pfc.pfcen;
677}
678
679static u8 cxgb4_setall(struct net_device *dev)
680{
681 return 0;
682}
683
684/* Return DCB capabilities.
685 */
686static u8 cxgb4_getcap(struct net_device *dev, int cap_id, u8 *caps)
687{
688 struct port_info *pi = netdev2pinfo(dev);
689
690 switch (cap_id) {
691 case DCB_CAP_ATTR_PG:
692 case DCB_CAP_ATTR_PFC:
693 *caps = true;
694 break;
695
696 case DCB_CAP_ATTR_PG_TCS:
697 /* 8 priorities for PG represented by bitmap */
698 *caps = 0x80;
699 break;
700
701 case DCB_CAP_ATTR_PFC_TCS:
702 /* 8 priorities for PFC represented by bitmap */
703 *caps = 0x80;
704 break;
705
706 case DCB_CAP_ATTR_GSP:
707 *caps = true;
708 break;
709
710 case DCB_CAP_ATTR_UP2TC:
711 case DCB_CAP_ATTR_BCN:
712 *caps = false;
713 break;
714
715 case DCB_CAP_ATTR_DCBX:
716 *caps = pi->dcb.supported;
717 break;
718
719 default:
720 *caps = false;
721 }
722
723 return 0;
724}
725
726/* Return the number of Traffic Classes for the indicated Traffic Class ID.
727 */
728static int cxgb4_getnumtcs(struct net_device *dev, int tcs_id, u8 *num)
729{
730 struct port_info *pi = netdev2pinfo(dev);
731
732 switch (tcs_id) {
733 case DCB_NUMTCS_ATTR_PG:
734 if (pi->dcb.msgs & CXGB4_DCB_FW_PGRATE)
735 *num = pi->dcb.pg_num_tcs_supported;
736 else
737 *num = 0x8;
738 break;
739
740 case DCB_NUMTCS_ATTR_PFC:
741 *num = 0x8;
742 break;
743
744 default:
745 return -EINVAL;
746 }
747
748 return 0;
749}
750
751/* Set the number of Traffic Classes supported for the indicated Traffic Class
752 * ID.
753 */
754static int cxgb4_setnumtcs(struct net_device *dev, int tcs_id, u8 num)
755{
756 /* Setting the number of Traffic Classes isn't supported.
757 */
758 return -ENOSYS;
759}
760
761/* Return whether Priority Flow Control is enabled. */
762static u8 cxgb4_getpfcstate(struct net_device *dev)
763{
764 struct port_info *pi = netdev2pinfo(dev);
765
766 if (!cxgb4_dcb_state_synced(state: pi->dcb.state))
767 return false;
768
769 return pi->dcb.pfcen != 0;
770}
771
772/* Enable/disable Priority Flow Control. */
773static void cxgb4_setpfcstate(struct net_device *dev, u8 state)
774{
775 /* We can't enable/disable Priority Flow Control but we also can't
776 * return an error ...
777 */
778}
779
780/* Return the Application User Priority Map associated with the specified
781 * Application ID.
782 */
783static int __cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id,
784 int peer)
785{
786 struct port_info *pi = netdev2pinfo(dev);
787 struct adapter *adap = pi->adapter;
788 int i;
789
790 if (!cxgb4_dcb_state_synced(state: pi->dcb.state))
791 return 0;
792
793 for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
794 struct fw_port_cmd pcmd;
795 int err;
796
797 if (peer)
798 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
799 else
800 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
801
802 pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
803 pcmd.u.dcb.app_priority.idx = i;
804
805 err = t4_wr_mbox(adap, mbox: adap->mbox, cmd: &pcmd, size: sizeof(pcmd), rpl: &pcmd);
806 if (err != FW_PORT_DCB_CFG_SUCCESS) {
807 dev_err(adap->pdev_dev, "DCB APP read failed with %d\n",
808 -err);
809 return err;
810 }
811 if (be16_to_cpu(pcmd.u.dcb.app_priority.protocolid) == app_id)
812 if (pcmd.u.dcb.app_priority.sel_field == app_idtype)
813 return pcmd.u.dcb.app_priority.user_prio_map;
814
815 /* exhausted app list */
816 if (!pcmd.u.dcb.app_priority.protocolid)
817 break;
818 }
819
820 return -EEXIST;
821}
822
823/* Return the Application User Priority Map associated with the specified
824 * Application ID.
825 */
826static int cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id)
827{
828 /* Convert app_idtype to firmware format before querying */
829 return __cxgb4_getapp(dev, app_idtype: app_idtype == DCB_APP_IDTYPE_ETHTYPE ?
830 app_idtype : 3, app_id, peer: 0);
831}
832
833/* Write a new Application User Priority Map for the specified Application ID
834 */
835static int __cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
836 u8 app_prio)
837{
838 struct fw_port_cmd pcmd;
839 struct port_info *pi = netdev2pinfo(dev);
840 struct adapter *adap = pi->adapter;
841 int i, err;
842
843
844 if (!cxgb4_dcb_state_synced(state: pi->dcb.state))
845 return -EINVAL;
846
847 /* DCB info gets thrown away on link up */
848 if (!netif_carrier_ok(dev))
849 return -ENOLINK;
850
851 for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
852 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
853 pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
854 pcmd.u.dcb.app_priority.idx = i;
855 err = t4_wr_mbox(adap, mbox: adap->mbox, cmd: &pcmd, size: sizeof(pcmd), rpl: &pcmd);
856
857 if (err != FW_PORT_DCB_CFG_SUCCESS) {
858 dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
859 -err);
860 return err;
861 }
862 if (be16_to_cpu(pcmd.u.dcb.app_priority.protocolid) == app_id) {
863 /* overwrite existing app table */
864 pcmd.u.dcb.app_priority.protocolid = 0;
865 break;
866 }
867 /* find first empty slot */
868 if (!pcmd.u.dcb.app_priority.protocolid)
869 break;
870 }
871
872 if (i == CXGB4_MAX_DCBX_APP_SUPPORTED) {
873 /* no empty slots available */
874 dev_err(adap->pdev_dev, "DCB app table full\n");
875 return -EBUSY;
876 }
877
878 /* write out new app table entry */
879 INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
880 if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
881 pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F);
882
883 pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
884 pcmd.u.dcb.app_priority.protocolid = cpu_to_be16(app_id);
885 pcmd.u.dcb.app_priority.sel_field = app_idtype;
886 pcmd.u.dcb.app_priority.user_prio_map = app_prio;
887 pcmd.u.dcb.app_priority.idx = i;
888
889 err = t4_wr_mbox(adap, mbox: adap->mbox, cmd: &pcmd, size: sizeof(pcmd), rpl: &pcmd);
890 if (err != FW_PORT_DCB_CFG_SUCCESS) {
891 dev_err(adap->pdev_dev, "DCB app table write failed with %d\n",
892 -err);
893 return err;
894 }
895
896 return 0;
897}
898
899/* Priority for CEE inside dcb_app is bitmask, with 0 being an invalid value */
900static int cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
901 u8 app_prio)
902{
903 int ret;
904 struct dcb_app app = {
905 .selector = app_idtype,
906 .protocol = app_id,
907 .priority = app_prio,
908 };
909
910 if (app_idtype != DCB_APP_IDTYPE_ETHTYPE &&
911 app_idtype != DCB_APP_IDTYPE_PORTNUM)
912 return -EINVAL;
913
914 /* Convert app_idtype to a format that firmware understands */
915 ret = __cxgb4_setapp(dev, app_idtype: app_idtype == DCB_APP_IDTYPE_ETHTYPE ?
916 app_idtype : 3, app_id, app_prio);
917 if (ret)
918 return ret;
919
920 return dcb_setapp(dev, &app);
921}
922
923/* Return whether IEEE Data Center Bridging has been negotiated.
924 */
925static inline int
926cxgb4_ieee_negotiation_complete(struct net_device *dev,
927 enum cxgb4_dcb_fw_msgs dcb_subtype)
928{
929 struct port_info *pi = netdev2pinfo(dev);
930 struct port_dcb_info *dcb = &pi->dcb;
931
932 if (dcb->state == CXGB4_DCB_STATE_FW_ALLSYNCED)
933 if (dcb_subtype && !(dcb->msgs & dcb_subtype))
934 return 0;
935
936 return (cxgb4_dcb_state_synced(state: dcb->state) &&
937 (dcb->supported & DCB_CAP_DCBX_VER_IEEE));
938}
939
940static int cxgb4_ieee_read_ets(struct net_device *dev, struct ieee_ets *ets,
941 int local)
942{
943 struct port_info *pi = netdev2pinfo(dev);
944 struct port_dcb_info *dcb = &pi->dcb;
945 struct adapter *adap = pi->adapter;
946 uint32_t tc_info;
947 struct fw_port_cmd pcmd;
948 int i, bwg, err;
949
950 if (!(dcb->msgs & (CXGB4_DCB_FW_PGID | CXGB4_DCB_FW_PGRATE)))
951 return 0;
952
953 ets->ets_cap = dcb->pg_num_tcs_supported;
954
955 if (local) {
956 ets->willing = 1;
957 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
958 } else {
959 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
960 }
961
962 pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
963 err = t4_wr_mbox(adap, mbox: adap->mbox, cmd: &pcmd, size: sizeof(pcmd), rpl: &pcmd);
964 if (err != FW_PORT_DCB_CFG_SUCCESS) {
965 dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
966 return err;
967 }
968
969 tc_info = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
970
971 if (local)
972 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
973 else
974 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
975
976 pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
977 err = t4_wr_mbox(adap, mbox: adap->mbox, cmd: &pcmd, size: sizeof(pcmd), rpl: &pcmd);
978 if (err != FW_PORT_DCB_CFG_SUCCESS) {
979 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
980 -err);
981 return err;
982 }
983
984 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
985 bwg = (tc_info >> ((7 - i) * 4)) & 0xF;
986 ets->prio_tc[i] = bwg;
987 ets->tc_tx_bw[i] = pcmd.u.dcb.pgrate.pgrate[i];
988 ets->tc_rx_bw[i] = ets->tc_tx_bw[i];
989 ets->tc_tsa[i] = pcmd.u.dcb.pgrate.tsa[i];
990 }
991
992 return 0;
993}
994
995static int cxgb4_ieee_get_ets(struct net_device *dev, struct ieee_ets *ets)
996{
997 return cxgb4_ieee_read_ets(dev, ets, local: 1);
998}
999
1000/* We reuse this for peer PFC as well, as we can't have it enabled one way */
1001static int cxgb4_ieee_get_pfc(struct net_device *dev, struct ieee_pfc *pfc)
1002{
1003 struct port_info *pi = netdev2pinfo(dev);
1004 struct port_dcb_info *dcb = &pi->dcb;
1005
1006 memset(pfc, 0, sizeof(struct ieee_pfc));
1007
1008 if (!(dcb->msgs & CXGB4_DCB_FW_PFC))
1009 return 0;
1010
1011 pfc->pfc_cap = dcb->pfc_num_tcs_supported;
1012 pfc->pfc_en = bitswap_1(val: dcb->pfcen);
1013
1014 return 0;
1015}
1016
1017static int cxgb4_ieee_peer_ets(struct net_device *dev, struct ieee_ets *ets)
1018{
1019 return cxgb4_ieee_read_ets(dev, ets, local: 0);
1020}
1021
1022/* Fill in the Application User Priority Map associated with the
1023 * specified Application.
1024 * Priority for IEEE dcb_app is an integer, with 0 being a valid value
1025 */
1026static int cxgb4_ieee_getapp(struct net_device *dev, struct dcb_app *app)
1027{
1028 int prio;
1029
1030 if (!cxgb4_ieee_negotiation_complete(dev, dcb_subtype: CXGB4_DCB_FW_APP_ID))
1031 return -EINVAL;
1032 if (!(app->selector && app->protocol))
1033 return -EINVAL;
1034
1035 /* Try querying firmware first, use firmware format */
1036 prio = __cxgb4_getapp(dev, app_idtype: app->selector - 1, app_id: app->protocol, peer: 0);
1037
1038 if (prio < 0)
1039 prio = dcb_ieee_getapp_mask(dev, app);
1040
1041 app->priority = ffs(prio) - 1;
1042 return 0;
1043}
1044
1045/* Write a new Application User Priority Map for the specified Application ID.
1046 * Priority for IEEE dcb_app is an integer, with 0 being a valid value
1047 */
1048static int cxgb4_ieee_setapp(struct net_device *dev, struct dcb_app *app)
1049{
1050 int ret;
1051
1052 if (!cxgb4_ieee_negotiation_complete(dev, dcb_subtype: CXGB4_DCB_FW_APP_ID))
1053 return -EINVAL;
1054 if (!(app->selector && app->protocol))
1055 return -EINVAL;
1056
1057 if (!(app->selector > IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
1058 app->selector < IEEE_8021QAZ_APP_SEL_ANY))
1059 return -EINVAL;
1060
1061 /* change selector to a format that firmware understands */
1062 ret = __cxgb4_setapp(dev, app_idtype: app->selector - 1, app_id: app->protocol,
1063 app_prio: (1 << app->priority));
1064 if (ret)
1065 return ret;
1066
1067 return dcb_ieee_setapp(dev, app);
1068}
1069
1070/* Return our DCBX parameters.
1071 */
1072static u8 cxgb4_getdcbx(struct net_device *dev)
1073{
1074 struct port_info *pi = netdev2pinfo(dev);
1075
1076 /* This is already set by cxgb4_set_dcb_caps, so just return it */
1077 return pi->dcb.supported;
1078}
1079
1080/* Set our DCBX parameters.
1081 */
1082static u8 cxgb4_setdcbx(struct net_device *dev, u8 dcb_request)
1083{
1084 struct port_info *pi = netdev2pinfo(dev);
1085
1086 /* Filter out requests which exceed our capabilities.
1087 */
1088 if ((dcb_request & (CXGB4_DCBX_FW_SUPPORT | CXGB4_DCBX_HOST_SUPPORT))
1089 != dcb_request)
1090 return 1;
1091
1092 /* Can't enable DCB if we haven't successfully negotiated it.
1093 */
1094 if (!cxgb4_dcb_state_synced(state: pi->dcb.state))
1095 return 1;
1096
1097 /* There's currently no mechanism to allow for the firmware DCBX
1098 * negotiation to be changed from the Host Driver. If the caller
1099 * requests exactly the same parameters that we already have then
1100 * we'll allow them to be successfully "set" ...
1101 */
1102 if (dcb_request != pi->dcb.supported)
1103 return 1;
1104
1105 pi->dcb.supported = dcb_request;
1106 return 0;
1107}
1108
1109static int cxgb4_getpeer_app(struct net_device *dev,
1110 struct dcb_peer_app_info *info, u16 *app_count)
1111{
1112 struct fw_port_cmd pcmd;
1113 struct port_info *pi = netdev2pinfo(dev);
1114 struct adapter *adap = pi->adapter;
1115 int i, err = 0;
1116
1117 if (!cxgb4_dcb_state_synced(state: pi->dcb.state))
1118 return 1;
1119
1120 info->willing = 0;
1121 info->error = 0;
1122
1123 *app_count = 0;
1124 for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
1125 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
1126 pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
1127 pcmd.u.dcb.app_priority.idx = *app_count;
1128 err = t4_wr_mbox(adap, mbox: adap->mbox, cmd: &pcmd, size: sizeof(pcmd), rpl: &pcmd);
1129
1130 if (err != FW_PORT_DCB_CFG_SUCCESS) {
1131 dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
1132 -err);
1133 return err;
1134 }
1135
1136 /* find first empty slot */
1137 if (!pcmd.u.dcb.app_priority.protocolid)
1138 break;
1139 }
1140 *app_count = i;
1141 return err;
1142}
1143
1144static int cxgb4_getpeerapp_tbl(struct net_device *dev, struct dcb_app *table)
1145{
1146 struct fw_port_cmd pcmd;
1147 struct port_info *pi = netdev2pinfo(dev);
1148 struct adapter *adap = pi->adapter;
1149 int i, err = 0;
1150
1151 if (!cxgb4_dcb_state_synced(state: pi->dcb.state))
1152 return 1;
1153
1154 for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
1155 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
1156 pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
1157 pcmd.u.dcb.app_priority.idx = i;
1158 err = t4_wr_mbox(adap, mbox: adap->mbox, cmd: &pcmd, size: sizeof(pcmd), rpl: &pcmd);
1159
1160 if (err != FW_PORT_DCB_CFG_SUCCESS) {
1161 dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
1162 -err);
1163 return err;
1164 }
1165
1166 /* find first empty slot */
1167 if (!pcmd.u.dcb.app_priority.protocolid)
1168 break;
1169
1170 table[i].selector = (pcmd.u.dcb.app_priority.sel_field + 1);
1171 table[i].protocol =
1172 be16_to_cpu(pcmd.u.dcb.app_priority.protocolid);
1173 table[i].priority =
1174 ffs(pcmd.u.dcb.app_priority.user_prio_map) - 1;
1175 }
1176 return err;
1177}
1178
1179/* Return Priority Group information.
1180 */
1181static int cxgb4_cee_peer_getpg(struct net_device *dev, struct cee_pg *pg)
1182{
1183 struct fw_port_cmd pcmd;
1184 struct port_info *pi = netdev2pinfo(dev);
1185 struct adapter *adap = pi->adapter;
1186 u32 pgid;
1187 int i, err;
1188
1189 /* We're always "willing" -- the Switch Fabric always dictates the
1190 * DCBX parameters to us.
1191 */
1192 pg->willing = true;
1193
1194 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
1195 pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
1196 err = t4_wr_mbox(adap, mbox: adap->mbox, cmd: &pcmd, size: sizeof(pcmd), rpl: &pcmd);
1197 if (err != FW_PORT_DCB_CFG_SUCCESS) {
1198 dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
1199 return err;
1200 }
1201 pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
1202
1203 for (i = 0; i < CXGB4_MAX_PRIORITY; i++)
1204 pg->prio_pg[7 - i] = (pgid >> (i * 4)) & 0xF;
1205
1206 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
1207 pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
1208 err = t4_wr_mbox(adap, mbox: adap->mbox, cmd: &pcmd, size: sizeof(pcmd), rpl: &pcmd);
1209 if (err != FW_PORT_DCB_CFG_SUCCESS) {
1210 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
1211 -err);
1212 return err;
1213 }
1214
1215 for (i = 0; i < CXGB4_MAX_PRIORITY; i++)
1216 pg->pg_bw[i] = pcmd.u.dcb.pgrate.pgrate[i];
1217
1218 pg->tcs_supported = pcmd.u.dcb.pgrate.num_tcs_supported;
1219
1220 return 0;
1221}
1222
1223/* Return Priority Flow Control information.
1224 */
1225static int cxgb4_cee_peer_getpfc(struct net_device *dev, struct cee_pfc *pfc)
1226{
1227 struct port_info *pi = netdev2pinfo(dev);
1228
1229 cxgb4_getnumtcs(dev, tcs_id: DCB_NUMTCS_ATTR_PFC, num: &(pfc->tcs_supported));
1230
1231 /* Firmware sends this to us in a formwat that is a bit flipped version
1232 * of spec, correct it before we send it to host. This is taken care of
1233 * by bit shifting in other uses of pfcen
1234 */
1235 pfc->pfc_en = bitswap_1(val: pi->dcb.pfcen);
1236
1237 pfc->tcs_supported = pi->dcb.pfc_num_tcs_supported;
1238
1239 return 0;
1240}
1241
1242const struct dcbnl_rtnl_ops cxgb4_dcb_ops = {
1243 .ieee_getets = cxgb4_ieee_get_ets,
1244 .ieee_getpfc = cxgb4_ieee_get_pfc,
1245 .ieee_getapp = cxgb4_ieee_getapp,
1246 .ieee_setapp = cxgb4_ieee_setapp,
1247 .ieee_peer_getets = cxgb4_ieee_peer_ets,
1248 .ieee_peer_getpfc = cxgb4_ieee_get_pfc,
1249
1250 /* CEE std */
1251 .getstate = cxgb4_getstate,
1252 .setstate = cxgb4_setstate,
1253 .getpgtccfgtx = cxgb4_getpgtccfg_tx,
1254 .getpgbwgcfgtx = cxgb4_getpgbwgcfg_tx,
1255 .getpgtccfgrx = cxgb4_getpgtccfg_rx,
1256 .getpgbwgcfgrx = cxgb4_getpgbwgcfg_rx,
1257 .setpgtccfgtx = cxgb4_setpgtccfg_tx,
1258 .setpgbwgcfgtx = cxgb4_setpgbwgcfg_tx,
1259 .setpfccfg = cxgb4_setpfccfg,
1260 .getpfccfg = cxgb4_getpfccfg,
1261 .setall = cxgb4_setall,
1262 .getcap = cxgb4_getcap,
1263 .getnumtcs = cxgb4_getnumtcs,
1264 .setnumtcs = cxgb4_setnumtcs,
1265 .getpfcstate = cxgb4_getpfcstate,
1266 .setpfcstate = cxgb4_setpfcstate,
1267 .getapp = cxgb4_getapp,
1268 .setapp = cxgb4_setapp,
1269
1270 /* DCBX configuration */
1271 .getdcbx = cxgb4_getdcbx,
1272 .setdcbx = cxgb4_setdcbx,
1273
1274 /* peer apps */
1275 .peer_getappinfo = cxgb4_getpeer_app,
1276 .peer_getapptable = cxgb4_getpeerapp_tbl,
1277
1278 /* CEE peer */
1279 .cee_peer_getpg = cxgb4_cee_peer_getpg,
1280 .cee_peer_getpfc = cxgb4_cee_peer_getpfc,
1281};
1282

source code of linux/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c