blob: ee819fd12bd2a59360a4b454325c50a6ad2c108e [file] [log] [blame]
Anish Bhatt76bcb312014-06-19 21:37:12 -07001/*
2 * Copyright (C) 2013-2014 Chelsio Communications. All rights reserved.
3 *
4 * Written by Anish Bhatt (anish@chelsio.com)
5 * Casey Leedom (leedom@chelsio.com)
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * The full GNU General Public License is included in this distribution in
17 * the file called "COPYING".
18 *
19 */
20
21#include "cxgb4.h"
22
Anish Bhatt10b00462014-08-07 16:14:03 -070023/* DCBx version control
24 */
25char *dcb_ver_array[] = {
26 "Unknown",
27 "DCBx-CIN",
28 "DCBx-CEE 1.01",
29 "DCBx-IEEE",
30 "", "", "",
31 "Auto Negotiated"
32};
33
Anish Bhatt76bcb312014-06-19 21:37:12 -070034/* Initialize a port's Data Center Bridging state. Typically used after a
35 * Link Down event.
36 */
37void cxgb4_dcb_state_init(struct net_device *dev)
38{
39 struct port_info *pi = netdev2pinfo(dev);
40 struct port_dcb_info *dcb = &pi->dcb;
Anish Bhatt10b00462014-08-07 16:14:03 -070041 int version_temp = dcb->dcb_version;
Anish Bhatt76bcb312014-06-19 21:37:12 -070042
43 memset(dcb, 0, sizeof(struct port_dcb_info));
44 dcb->state = CXGB4_DCB_STATE_START;
Anish Bhatt10b00462014-08-07 16:14:03 -070045 if (version_temp)
46 dcb->dcb_version = version_temp;
47
48 netdev_dbg(dev, "%s: Initializing DCB state for port[%d]\n",
49 __func__, pi->port_id);
50}
51
52void cxgb4_dcb_version_init(struct net_device *dev)
53{
54 struct port_info *pi = netdev2pinfo(dev);
55 struct port_dcb_info *dcb = &pi->dcb;
56
57 /* Any writes here are only done on kernels that exlicitly need
58 * a specific version, say < 2.6.38 which only support CEE
59 */
60 dcb->dcb_version = FW_PORT_DCB_VER_AUTO;
Anish Bhatt76bcb312014-06-19 21:37:12 -070061}
62
Anish Bhatt2376c872014-10-23 14:37:30 -070063static void cxgb4_dcb_cleanup_apps(struct net_device *dev)
64{
65 struct port_info *pi = netdev2pinfo(dev);
66 struct adapter *adap = pi->adapter;
67 struct port_dcb_info *dcb = &pi->dcb;
68 struct dcb_app app;
69 int i, err;
70
71 /* zero priority implies remove */
72 app.priority = 0;
73
74 for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
75 /* Check if app list is exhausted */
76 if (!dcb->app_priority[i].protocolid)
77 break;
78
79 app.protocol = dcb->app_priority[i].protocolid;
80
81 if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) {
82 app.selector = dcb->app_priority[i].sel_field + 1;
83 err = dcb_ieee_setapp(dev, &app);
84 } else {
85 app.selector = !!(dcb->app_priority[i].sel_field);
86 err = dcb_setapp(dev, &app);
87 }
88
89 if (err) {
90 dev_err(adap->pdev_dev,
91 "Failed DCB Clear %s Application Priority: sel=%d, prot=%d, , err=%d\n",
92 dcb_ver_array[dcb->dcb_version], app.selector,
93 app.protocol, -err);
94 break;
95 }
96 }
97}
98
Anish Bhatt76bcb312014-06-19 21:37:12 -070099/* Finite State machine for Data Center Bridging.
100 */
101void cxgb4_dcb_state_fsm(struct net_device *dev,
Anish Bhatt10b00462014-08-07 16:14:03 -0700102 enum cxgb4_dcb_state_input transition_to)
Anish Bhatt76bcb312014-06-19 21:37:12 -0700103{
104 struct port_info *pi = netdev2pinfo(dev);
105 struct port_dcb_info *dcb = &pi->dcb;
106 struct adapter *adap = pi->adapter;
Anish Bhatt10b00462014-08-07 16:14:03 -0700107 enum cxgb4_dcb_state current_state = dcb->state;
Anish Bhatt76bcb312014-06-19 21:37:12 -0700108
Anish Bhatt10b00462014-08-07 16:14:03 -0700109 netdev_dbg(dev, "%s: State change from %d to %d for %s\n",
110 __func__, dcb->state, transition_to, dev->name);
111
112 switch (current_state) {
113 case CXGB4_DCB_STATE_START: {
114 switch (transition_to) {
115 case CXGB4_DCB_INPUT_FW_DISABLED: {
Anish Bhatt76bcb312014-06-19 21:37:12 -0700116 /* we're going to use Host DCB */
117 dcb->state = CXGB4_DCB_STATE_HOST;
118 dcb->supported = CXGB4_DCBX_HOST_SUPPORT;
119 dcb->enabled = 1;
120 break;
121 }
122
Anish Bhatt10b00462014-08-07 16:14:03 -0700123 case CXGB4_DCB_INPUT_FW_ENABLED: {
Anish Bhatt76bcb312014-06-19 21:37:12 -0700124 /* we're going to use Firmware DCB */
125 dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
126 dcb->supported = CXGB4_DCBX_FW_SUPPORT;
127 break;
128 }
129
Anish Bhatt10b00462014-08-07 16:14:03 -0700130 case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
131 /* expected transition */
132 break;
133 }
134
135 case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
136 dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED;
Anish Bhatt76bcb312014-06-19 21:37:12 -0700137 break;
138 }
139
140 default:
Anish Bhatt10b00462014-08-07 16:14:03 -0700141 goto bad_state_input;
Anish Bhatt76bcb312014-06-19 21:37:12 -0700142 }
143 break;
144 }
145
Anish Bhatt10b00462014-08-07 16:14:03 -0700146 case CXGB4_DCB_STATE_FW_INCOMPLETE: {
147 switch (transition_to) {
148 case CXGB4_DCB_INPUT_FW_ENABLED: {
149 /* we're alreaady in firmware DCB mode */
150 break;
151 }
152
153 case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
Anish Bhatt76bcb312014-06-19 21:37:12 -0700154 /* we're already incomplete */
155 break;
156 }
157
Anish Bhatt10b00462014-08-07 16:14:03 -0700158 case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
159 dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED;
160 dcb->enabled = 1;
161 linkwatch_fire_event(dev);
162 break;
163 }
164
165 default:
166 goto bad_state_input;
167 }
168 break;
169 }
170
171 case CXGB4_DCB_STATE_FW_ALLSYNCED: {
172 switch (transition_to) {
173 case CXGB4_DCB_INPUT_FW_ENABLED: {
174 /* we're alreaady in firmware DCB mode */
175 break;
176 }
177
178 case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
Anish Bhatt76bcb312014-06-19 21:37:12 -0700179 /* We were successfully running with firmware DCB but
180 * now it's telling us that it's in an "incomplete
181 * state. We need to reset back to a ground state
182 * of incomplete.
183 */
Anish Bhatt2376c872014-10-23 14:37:30 -0700184 cxgb4_dcb_cleanup_apps(dev);
Anish Bhatt76bcb312014-06-19 21:37:12 -0700185 cxgb4_dcb_state_init(dev);
186 dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
187 dcb->supported = CXGB4_DCBX_FW_SUPPORT;
188 linkwatch_fire_event(dev);
189 break;
190 }
191
Anish Bhatt10b00462014-08-07 16:14:03 -0700192 case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
193 /* we're already all sync'ed
194 * this is only applicable for IEEE or
195 * when another VI already completed negotiaton
196 */
Anish Bhatt76bcb312014-06-19 21:37:12 -0700197 dcb->enabled = 1;
198 linkwatch_fire_event(dev);
199 break;
200 }
201
Anish Bhatt10b00462014-08-07 16:14:03 -0700202 default:
203 goto bad_state_input;
204 }
205 break;
206 }
207
208 case CXGB4_DCB_STATE_HOST: {
209 switch (transition_to) {
210 case CXGB4_DCB_INPUT_FW_DISABLED: {
211 /* we're alreaady in Host DCB mode */
Anish Bhatt76bcb312014-06-19 21:37:12 -0700212 break;
213 }
214
215 default:
Anish Bhatt10b00462014-08-07 16:14:03 -0700216 goto bad_state_input;
Anish Bhatt76bcb312014-06-19 21:37:12 -0700217 }
218 break;
219 }
220
221 default:
Anish Bhatt10b00462014-08-07 16:14:03 -0700222 goto bad_state_transition;
Anish Bhatt76bcb312014-06-19 21:37:12 -0700223 }
224 return;
225
226bad_state_input:
227 dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: illegal input symbol %d\n",
Anish Bhatt10b00462014-08-07 16:14:03 -0700228 transition_to);
Anish Bhatt76bcb312014-06-19 21:37:12 -0700229 return;
230
231bad_state_transition:
232 dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: bad state transition, state = %d, input = %d\n",
Anish Bhatt10b00462014-08-07 16:14:03 -0700233 current_state, transition_to);
Anish Bhatt76bcb312014-06-19 21:37:12 -0700234}
235
236/* Handle a DCB/DCBX update message from the firmware.
237 */
238void cxgb4_dcb_handle_fw_update(struct adapter *adap,
239 const struct fw_port_cmd *pcmd)
240{
241 const union fw_port_dcb *fwdcb = &pcmd->u.dcb;
242 int port = FW_PORT_CMD_PORTID_GET(be32_to_cpu(pcmd->op_to_portid));
243 struct net_device *dev = adap->port[port];
244 struct port_info *pi = netdev_priv(dev);
245 struct port_dcb_info *dcb = &pi->dcb;
246 int dcb_type = pcmd->u.dcb.pgid.type;
Anish Bhatt10b00462014-08-07 16:14:03 -0700247 int dcb_running_version;
Anish Bhatt76bcb312014-06-19 21:37:12 -0700248
249 /* Handle Firmware DCB Control messages separately since they drive
250 * our state machine.
251 */
252 if (dcb_type == FW_PORT_DCB_TYPE_CONTROL) {
253 enum cxgb4_dcb_state_input input =
254 ((pcmd->u.dcb.control.all_syncd_pkd &
255 FW_PORT_CMD_ALL_SYNCD)
256 ? CXGB4_DCB_STATE_FW_ALLSYNCED
257 : CXGB4_DCB_STATE_FW_INCOMPLETE);
258
Anish Bhatt10b00462014-08-07 16:14:03 -0700259 if (dcb->dcb_version != FW_PORT_DCB_VER_UNKNOWN) {
260 dcb_running_version = FW_PORT_CMD_DCB_VERSION_GET(
261 be16_to_cpu(
262 pcmd->u.dcb.control.dcb_version_to_app_state));
263 if (dcb_running_version == FW_PORT_DCB_VER_CEE1D01 ||
264 dcb_running_version == FW_PORT_DCB_VER_IEEE) {
265 dcb->dcb_version = dcb_running_version;
266 dev_warn(adap->pdev_dev, "Interface %s is running %s\n",
267 dev->name,
268 dcb_ver_array[dcb->dcb_version]);
269 } else {
270 dev_warn(adap->pdev_dev,
271 "Something screwed up, requested firmware for %s, but firmware returned %s instead\n",
272 dcb_ver_array[dcb->dcb_version],
273 dcb_ver_array[dcb_running_version]);
274 dcb->dcb_version = FW_PORT_DCB_VER_UNKNOWN;
275 }
276 }
277
Anish Bhatt76bcb312014-06-19 21:37:12 -0700278 cxgb4_dcb_state_fsm(dev, input);
279 return;
280 }
281
282 /* It's weird, and almost certainly an error, to get Firmware DCB
283 * messages when we either haven't been told whether we're going to be
284 * doing Host or Firmware DCB; and even worse when we've been told
285 * that we're doing Host DCB!
286 */
287 if (dcb->state == CXGB4_DCB_STATE_START ||
288 dcb->state == CXGB4_DCB_STATE_HOST) {
289 dev_err(adap->pdev_dev, "Receiving Firmware DCB messages in State %d\n",
290 dcb->state);
291 return;
292 }
293
294 /* Now handle the general Firmware DCB update messages ...
295 */
296 switch (dcb_type) {
297 case FW_PORT_DCB_TYPE_PGID:
298 dcb->pgid = be32_to_cpu(fwdcb->pgid.pgid);
299 dcb->msgs |= CXGB4_DCB_FW_PGID;
300 break;
301
302 case FW_PORT_DCB_TYPE_PGRATE:
303 dcb->pg_num_tcs_supported = fwdcb->pgrate.num_tcs_supported;
304 memcpy(dcb->pgrate, &fwdcb->pgrate.pgrate,
305 sizeof(dcb->pgrate));
Anish Bhatt10b00462014-08-07 16:14:03 -0700306 memcpy(dcb->tsa, &fwdcb->pgrate.tsa,
307 sizeof(dcb->tsa));
Anish Bhatt76bcb312014-06-19 21:37:12 -0700308 dcb->msgs |= CXGB4_DCB_FW_PGRATE;
Anish Bhatt10b00462014-08-07 16:14:03 -0700309 if (dcb->msgs & CXGB4_DCB_FW_PGID)
310 IEEE_FAUX_SYNC(dev, dcb);
Anish Bhatt76bcb312014-06-19 21:37:12 -0700311 break;
312
313 case FW_PORT_DCB_TYPE_PRIORATE:
314 memcpy(dcb->priorate, &fwdcb->priorate.strict_priorate,
315 sizeof(dcb->priorate));
316 dcb->msgs |= CXGB4_DCB_FW_PRIORATE;
317 break;
318
319 case FW_PORT_DCB_TYPE_PFC:
320 dcb->pfcen = fwdcb->pfc.pfcen;
321 dcb->pfc_num_tcs_supported = fwdcb->pfc.max_pfc_tcs;
322 dcb->msgs |= CXGB4_DCB_FW_PFC;
Anish Bhatt10b00462014-08-07 16:14:03 -0700323 IEEE_FAUX_SYNC(dev, dcb);
Anish Bhatt76bcb312014-06-19 21:37:12 -0700324 break;
325
326 case FW_PORT_DCB_TYPE_APP_ID: {
327 const struct fw_port_app_priority *fwap = &fwdcb->app_priority;
328 int idx = fwap->idx;
329 struct app_priority *ap = &dcb->app_priority[idx];
330
331 struct dcb_app app = {
Anish Bhatt76bcb312014-06-19 21:37:12 -0700332 .protocol = be16_to_cpu(fwap->protocolid),
Anish Bhatt76bcb312014-06-19 21:37:12 -0700333 };
334 int err;
335
Anish Bhatt10b00462014-08-07 16:14:03 -0700336 /* Convert from firmware format to relevant format
337 * when using app selector
338 */
339 if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) {
340 app.selector = (fwap->sel_field + 1);
341 app.priority = ffs(fwap->user_prio_map) - 1;
342 err = dcb_ieee_setapp(dev, &app);
343 IEEE_FAUX_SYNC(dev, dcb);
344 } else {
345 /* Default is CEE */
346 app.selector = !!(fwap->sel_field);
347 app.priority = fwap->user_prio_map;
348 err = dcb_setapp(dev, &app);
349 }
350
Anish Bhatt76bcb312014-06-19 21:37:12 -0700351 if (err)
352 dev_err(adap->pdev_dev,
353 "Failed DCB Set Application Priority: sel=%d, prot=%d, prio=%d, err=%d\n",
354 app.selector, app.protocol, app.priority, -err);
355
356 ap->user_prio_map = fwap->user_prio_map;
357 ap->sel_field = fwap->sel_field;
358 ap->protocolid = be16_to_cpu(fwap->protocolid);
359 dcb->msgs |= CXGB4_DCB_FW_APP_ID;
360 break;
361 }
362
363 default:
364 dev_err(adap->pdev_dev, "Unknown DCB update type received %x\n",
365 dcb_type);
366 break;
367 }
368}
369
370/* Data Center Bridging netlink operations.
371 */
372
373
374/* Get current DCB enabled/disabled state.
375 */
376static u8 cxgb4_getstate(struct net_device *dev)
377{
378 struct port_info *pi = netdev2pinfo(dev);
379
380 return pi->dcb.enabled;
381}
382
383/* Set DCB enabled/disabled.
384 */
385static u8 cxgb4_setstate(struct net_device *dev, u8 enabled)
386{
387 struct port_info *pi = netdev2pinfo(dev);
388
389 /* Firmware doesn't provide any mechanism to control the DCB state.
390 */
391 if (enabled != (pi->dcb.state == CXGB4_DCB_STATE_FW_ALLSYNCED))
392 return 1;
393
394 return 0;
395}
396
397static void cxgb4_getpgtccfg(struct net_device *dev, int tc,
398 u8 *prio_type, u8 *pgid, u8 *bw_per,
399 u8 *up_tc_map, int local)
400{
401 struct fw_port_cmd pcmd;
402 struct port_info *pi = netdev2pinfo(dev);
403 struct adapter *adap = pi->adapter;
404 int err;
405
406 *prio_type = *pgid = *bw_per = *up_tc_map = 0;
407
408 if (local)
409 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
410 else
411 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
412
413 pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
414 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
415 if (err != FW_PORT_DCB_CFG_SUCCESS) {
416 dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
417 return;
418 }
419 *pgid = (be32_to_cpu(pcmd.u.dcb.pgid.pgid) >> (tc * 4)) & 0xf;
420
421 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
422 pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
423 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
424 if (err != FW_PORT_DCB_CFG_SUCCESS) {
425 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
426 -err);
427 return;
428 }
429
430 *bw_per = pcmd.u.dcb.pgrate.pgrate[*pgid];
431 *up_tc_map = (1 << tc);
432
433 /* prio_type is link strict */
434 *prio_type = 0x2;
435}
436
437static void cxgb4_getpgtccfg_tx(struct net_device *dev, int tc,
438 u8 *prio_type, u8 *pgid, u8 *bw_per,
439 u8 *up_tc_map)
440{
441 return cxgb4_getpgtccfg(dev, tc, prio_type, pgid, bw_per, up_tc_map, 1);
442}
443
444
445static void cxgb4_getpgtccfg_rx(struct net_device *dev, int tc,
446 u8 *prio_type, u8 *pgid, u8 *bw_per,
447 u8 *up_tc_map)
448{
449 return cxgb4_getpgtccfg(dev, tc, prio_type, pgid, bw_per, up_tc_map, 0);
450}
451
452static void cxgb4_setpgtccfg_tx(struct net_device *dev, int tc,
453 u8 prio_type, u8 pgid, u8 bw_per,
454 u8 up_tc_map)
455{
456 struct fw_port_cmd pcmd;
457 struct port_info *pi = netdev2pinfo(dev);
458 struct adapter *adap = pi->adapter;
459 u32 _pgid;
460 int err;
461
462 if (pgid == DCB_ATTR_VALUE_UNDEFINED)
463 return;
464 if (bw_per == DCB_ATTR_VALUE_UNDEFINED)
465 return;
466
467 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
468 pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
469
470 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
471 if (err != FW_PORT_DCB_CFG_SUCCESS) {
472 dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
473 return;
474 }
475
476 _pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
477 _pgid &= ~(0xF << (tc * 4));
478 _pgid |= pgid << (tc * 4);
479 pcmd.u.dcb.pgid.pgid = cpu_to_be32(_pgid);
480
481 INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
482
483 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
484 if (err != FW_PORT_DCB_CFG_SUCCESS) {
485 dev_err(adap->pdev_dev, "DCB write PGID failed with %d\n",
486 -err);
487 return;
488 }
489
490 memset(&pcmd, 0, sizeof(struct fw_port_cmd));
491
492 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
493 pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
494
495 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
496 if (err != FW_PORT_DCB_CFG_SUCCESS) {
497 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
498 -err);
499 return;
500 }
501
502 pcmd.u.dcb.pgrate.pgrate[pgid] = bw_per;
503
504 INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
505 if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
506 pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY);
507
508 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
509 if (err != FW_PORT_DCB_CFG_SUCCESS)
510 dev_err(adap->pdev_dev, "DCB write PGRATE failed with %d\n",
511 -err);
512}
513
514static void cxgb4_getpgbwgcfg(struct net_device *dev, int pgid, u8 *bw_per,
515 int local)
516{
517 struct fw_port_cmd pcmd;
518 struct port_info *pi = netdev2pinfo(dev);
519 struct adapter *adap = pi->adapter;
520 int err;
521
522 if (local)
523 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
524 else
525 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
526
527 pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
528 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
529 if (err != FW_PORT_DCB_CFG_SUCCESS) {
530 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
531 -err);
Anish Bhatt10b00462014-08-07 16:14:03 -0700532 return;
Anish Bhatt76bcb312014-06-19 21:37:12 -0700533 }
Anish Bhatt10b00462014-08-07 16:14:03 -0700534
535 *bw_per = pcmd.u.dcb.pgrate.pgrate[pgid];
Anish Bhatt76bcb312014-06-19 21:37:12 -0700536}
537
538static void cxgb4_getpgbwgcfg_tx(struct net_device *dev, int pgid, u8 *bw_per)
539{
540 return cxgb4_getpgbwgcfg(dev, pgid, bw_per, 1);
541}
542
543static void cxgb4_getpgbwgcfg_rx(struct net_device *dev, int pgid, u8 *bw_per)
544{
545 return cxgb4_getpgbwgcfg(dev, pgid, bw_per, 0);
546}
547
548static void cxgb4_setpgbwgcfg_tx(struct net_device *dev, int pgid,
549 u8 bw_per)
550{
551 struct fw_port_cmd pcmd;
552 struct port_info *pi = netdev2pinfo(dev);
553 struct adapter *adap = pi->adapter;
554 int err;
555
556 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
557 pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
558
559 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
560 if (err != FW_PORT_DCB_CFG_SUCCESS) {
561 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
562 -err);
563 return;
564 }
565
566 pcmd.u.dcb.pgrate.pgrate[pgid] = bw_per;
567
568 INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
569 if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
570 pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY);
571
572 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
573
574 if (err != FW_PORT_DCB_CFG_SUCCESS)
575 dev_err(adap->pdev_dev, "DCB write PGRATE failed with %d\n",
576 -err);
577}
578
579/* Return whether the specified Traffic Class Priority has Priority Pause
580 * Frames enabled.
581 */
582static void cxgb4_getpfccfg(struct net_device *dev, int priority, u8 *pfccfg)
583{
584 struct port_info *pi = netdev2pinfo(dev);
585 struct port_dcb_info *dcb = &pi->dcb;
586
587 if (dcb->state != CXGB4_DCB_STATE_FW_ALLSYNCED ||
588 priority >= CXGB4_MAX_PRIORITY)
589 *pfccfg = 0;
590 else
591 *pfccfg = (pi->dcb.pfcen >> priority) & 1;
592}
593
594/* Enable/disable Priority Pause Frames for the specified Traffic Class
595 * Priority.
596 */
597static void cxgb4_setpfccfg(struct net_device *dev, int priority, u8 pfccfg)
598{
599 struct fw_port_cmd pcmd;
600 struct port_info *pi = netdev2pinfo(dev);
601 struct adapter *adap = pi->adapter;
602 int err;
603
604 if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED ||
605 priority >= CXGB4_MAX_PRIORITY)
606 return;
607
608 INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
609 if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
610 pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY);
611
612 pcmd.u.dcb.pfc.type = FW_PORT_DCB_TYPE_PFC;
Anish Bhatt5433ba32014-06-23 23:11:09 -0700613 pcmd.u.dcb.pfc.pfcen = pi->dcb.pfcen;
Anish Bhatt76bcb312014-06-19 21:37:12 -0700614
615 if (pfccfg)
Anish Bhatt5433ba32014-06-23 23:11:09 -0700616 pcmd.u.dcb.pfc.pfcen |= (1 << priority);
Anish Bhatt76bcb312014-06-19 21:37:12 -0700617 else
Anish Bhatt5433ba32014-06-23 23:11:09 -0700618 pcmd.u.dcb.pfc.pfcen &= (~(1 << priority));
Anish Bhatt76bcb312014-06-19 21:37:12 -0700619
620 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
621 if (err != FW_PORT_DCB_CFG_SUCCESS) {
622 dev_err(adap->pdev_dev, "DCB PFC write failed with %d\n", -err);
623 return;
624 }
625
Anish Bhatt5433ba32014-06-23 23:11:09 -0700626 pi->dcb.pfcen = pcmd.u.dcb.pfc.pfcen;
Anish Bhatt76bcb312014-06-19 21:37:12 -0700627}
628
629static u8 cxgb4_setall(struct net_device *dev)
630{
631 return 0;
632}
633
634/* Return DCB capabilities.
635 */
636static u8 cxgb4_getcap(struct net_device *dev, int cap_id, u8 *caps)
637{
638 struct port_info *pi = netdev2pinfo(dev);
639
640 switch (cap_id) {
641 case DCB_CAP_ATTR_PG:
642 case DCB_CAP_ATTR_PFC:
643 *caps = true;
644 break;
645
646 case DCB_CAP_ATTR_PG_TCS:
647 /* 8 priorities for PG represented by bitmap */
648 *caps = 0x80;
649 break;
650
651 case DCB_CAP_ATTR_PFC_TCS:
652 /* 8 priorities for PFC represented by bitmap */
653 *caps = 0x80;
654 break;
655
656 case DCB_CAP_ATTR_GSP:
657 *caps = true;
658 break;
659
660 case DCB_CAP_ATTR_UP2TC:
661 case DCB_CAP_ATTR_BCN:
662 *caps = false;
663 break;
664
665 case DCB_CAP_ATTR_DCBX:
666 *caps = pi->dcb.supported;
667 break;
668
669 default:
670 *caps = false;
671 }
672
673 return 0;
674}
675
676/* Return the number of Traffic Classes for the indicated Traffic Class ID.
677 */
678static int cxgb4_getnumtcs(struct net_device *dev, int tcs_id, u8 *num)
679{
680 struct port_info *pi = netdev2pinfo(dev);
681
682 switch (tcs_id) {
683 case DCB_NUMTCS_ATTR_PG:
684 if (pi->dcb.msgs & CXGB4_DCB_FW_PGRATE)
685 *num = pi->dcb.pg_num_tcs_supported;
686 else
687 *num = 0x8;
688 break;
689
690 case DCB_NUMTCS_ATTR_PFC:
691 *num = 0x8;
692 break;
693
694 default:
695 return -EINVAL;
696 }
697
698 return 0;
699}
700
701/* Set the number of Traffic Classes supported for the indicated Traffic Class
702 * ID.
703 */
704static int cxgb4_setnumtcs(struct net_device *dev, int tcs_id, u8 num)
705{
706 /* Setting the number of Traffic Classes isn't supported.
707 */
708 return -ENOSYS;
709}
710
711/* Return whether Priority Flow Control is enabled. */
712static u8 cxgb4_getpfcstate(struct net_device *dev)
713{
714 struct port_info *pi = netdev2pinfo(dev);
715
716 if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
717 return false;
718
719 return pi->dcb.pfcen != 0;
720}
721
722/* Enable/disable Priority Flow Control. */
723static void cxgb4_setpfcstate(struct net_device *dev, u8 state)
724{
725 /* We can't enable/disable Priority Flow Control but we also can't
726 * return an error ...
727 */
728}
729
730/* Return the Application User Priority Map associated with the specified
731 * Application ID.
732 */
733static int __cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id,
734 int peer)
735{
736 struct port_info *pi = netdev2pinfo(dev);
737 struct adapter *adap = pi->adapter;
738 int i;
739
740 if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
741 return 0;
742
743 for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
744 struct fw_port_cmd pcmd;
745 int err;
746
747 if (peer)
748 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
749 else
750 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
751
752 pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
753 pcmd.u.dcb.app_priority.idx = i;
754
755 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
756 if (err != FW_PORT_DCB_CFG_SUCCESS) {
757 dev_err(adap->pdev_dev, "DCB APP read failed with %d\n",
758 -err);
759 return err;
760 }
761 if (be16_to_cpu(pcmd.u.dcb.app_priority.protocolid) == app_id)
Anish Bhatt10b00462014-08-07 16:14:03 -0700762 if (pcmd.u.dcb.app_priority.sel_field == app_idtype)
763 return pcmd.u.dcb.app_priority.user_prio_map;
Anish Bhatt76bcb312014-06-19 21:37:12 -0700764
765 /* exhausted app list */
766 if (!pcmd.u.dcb.app_priority.protocolid)
767 break;
768 }
769
770 return -EEXIST;
771}
772
773/* Return the Application User Priority Map associated with the specified
Anish Bhattc2659472014-07-16 22:32:39 -0700774 * Application ID.
Anish Bhatt76bcb312014-06-19 21:37:12 -0700775 */
Anish Bhattc2659472014-07-16 22:32:39 -0700776static int cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id)
Anish Bhatt76bcb312014-06-19 21:37:12 -0700777{
Anish Bhattc2659472014-07-16 22:32:39 -0700778 return __cxgb4_getapp(dev, app_idtype, app_id, 0);
Anish Bhatt76bcb312014-06-19 21:37:12 -0700779}
780
Anish Bhattc2659472014-07-16 22:32:39 -0700781/* Write a new Application User Priority Map for the specified Application ID
Anish Bhatt76bcb312014-06-19 21:37:12 -0700782 */
Anish Bhatt10b00462014-08-07 16:14:03 -0700783static int __cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
784 u8 app_prio)
Anish Bhatt76bcb312014-06-19 21:37:12 -0700785{
786 struct fw_port_cmd pcmd;
787 struct port_info *pi = netdev2pinfo(dev);
788 struct adapter *adap = pi->adapter;
789 int i, err;
790
791
792 if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
793 return -EINVAL;
794
795 /* DCB info gets thrown away on link up */
796 if (!netif_carrier_ok(dev))
797 return -ENOLINK;
798
Anish Bhatt76bcb312014-06-19 21:37:12 -0700799 for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
800 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
801 pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
802 pcmd.u.dcb.app_priority.idx = i;
803 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
804
805 if (err != FW_PORT_DCB_CFG_SUCCESS) {
806 dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
807 -err);
808 return err;
809 }
810 if (be16_to_cpu(pcmd.u.dcb.app_priority.protocolid) == app_id) {
811 /* overwrite existing app table */
812 pcmd.u.dcb.app_priority.protocolid = 0;
813 break;
814 }
815 /* find first empty slot */
816 if (!pcmd.u.dcb.app_priority.protocolid)
817 break;
818 }
819
820 if (i == CXGB4_MAX_DCBX_APP_SUPPORTED) {
821 /* no empty slots available */
822 dev_err(adap->pdev_dev, "DCB app table full\n");
823 return -EBUSY;
824 }
825
826 /* write out new app table entry */
827 INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
828 if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
829 pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY);
830
831 pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
832 pcmd.u.dcb.app_priority.protocolid = cpu_to_be16(app_id);
833 pcmd.u.dcb.app_priority.sel_field = app_idtype;
834 pcmd.u.dcb.app_priority.user_prio_map = app_prio;
835 pcmd.u.dcb.app_priority.idx = i;
836
837 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
838 if (err != FW_PORT_DCB_CFG_SUCCESS) {
839 dev_err(adap->pdev_dev, "DCB app table write failed with %d\n",
840 -err);
841 return err;
842 }
843
844 return 0;
845}
846
Anish Bhatt10b00462014-08-07 16:14:03 -0700847/* Priority for CEE inside dcb_app is bitmask, with 0 being an invalid value */
848static int cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
849 u8 app_prio)
850{
851 int ret;
852 struct dcb_app app = {
853 .selector = app_idtype,
854 .protocol = app_id,
855 .priority = app_prio,
856 };
857
858 if (app_idtype != DCB_APP_IDTYPE_ETHTYPE &&
859 app_idtype != DCB_APP_IDTYPE_PORTNUM)
860 return -EINVAL;
861
862 /* Convert app_idtype to a format that firmware understands */
863 ret = __cxgb4_setapp(dev, app_idtype == DCB_APP_IDTYPE_ETHTYPE ?
864 app_idtype : 3, app_id, app_prio);
865 if (ret)
866 return ret;
867
868 return dcb_setapp(dev, &app);
869}
870
Anish Bhatt76bcb312014-06-19 21:37:12 -0700871/* Return whether IEEE Data Center Bridging has been negotiated.
872 */
Anish Bhatt2376c872014-10-23 14:37:30 -0700873static inline int
874cxgb4_ieee_negotiation_complete(struct net_device *dev,
875 enum cxgb4_dcb_fw_msgs dcb_subtype)
Anish Bhatt76bcb312014-06-19 21:37:12 -0700876{
877 struct port_info *pi = netdev2pinfo(dev);
878 struct port_dcb_info *dcb = &pi->dcb;
879
Anish Bhatt2376c872014-10-23 14:37:30 -0700880 if (dcb_subtype && !(dcb->msgs & dcb_subtype))
881 return 0;
882
Anish Bhatt76bcb312014-06-19 21:37:12 -0700883 return (dcb->state == CXGB4_DCB_STATE_FW_ALLSYNCED &&
884 (dcb->supported & DCB_CAP_DCBX_VER_IEEE));
885}
886
887/* Fill in the Application User Priority Map associated with the
888 * specified Application.
Anish Bhatt10b00462014-08-07 16:14:03 -0700889 * Priority for IEEE dcb_app is an integer, with 0 being a valid value
Anish Bhatt76bcb312014-06-19 21:37:12 -0700890 */
891static int cxgb4_ieee_getapp(struct net_device *dev, struct dcb_app *app)
892{
893 int prio;
894
Anish Bhatt2376c872014-10-23 14:37:30 -0700895 if (!cxgb4_ieee_negotiation_complete(dev, CXGB4_DCB_FW_APP_ID))
Anish Bhatt76bcb312014-06-19 21:37:12 -0700896 return -EINVAL;
897 if (!(app->selector && app->protocol))
898 return -EINVAL;
899
Anish Bhatt10b00462014-08-07 16:14:03 -0700900 /* Try querying firmware first, use firmware format */
901 prio = __cxgb4_getapp(dev, app->selector - 1, app->protocol, 0);
Anish Bhatt76bcb312014-06-19 21:37:12 -0700902
Anish Bhatt10b00462014-08-07 16:14:03 -0700903 if (prio < 0)
904 prio = dcb_ieee_getapp_mask(dev, app);
905
906 app->priority = ffs(prio) - 1;
Anish Bhatt76bcb312014-06-19 21:37:12 -0700907 return 0;
908}
909
Anish Bhatt10b00462014-08-07 16:14:03 -0700910/* Write a new Application User Priority Map for the specified Application ID.
911 * Priority for IEEE dcb_app is an integer, with 0 being a valid value
912 */
Anish Bhatt76bcb312014-06-19 21:37:12 -0700913static int cxgb4_ieee_setapp(struct net_device *dev, struct dcb_app *app)
914{
Anish Bhatt10b00462014-08-07 16:14:03 -0700915 int ret;
916
Anish Bhatt2376c872014-10-23 14:37:30 -0700917 if (!cxgb4_ieee_negotiation_complete(dev, CXGB4_DCB_FW_APP_ID))
Anish Bhatt76bcb312014-06-19 21:37:12 -0700918 return -EINVAL;
Anish Bhatt10b00462014-08-07 16:14:03 -0700919 if (!(app->selector && app->protocol))
Anish Bhatt76bcb312014-06-19 21:37:12 -0700920 return -EINVAL;
921
Anish Bhatt10b00462014-08-07 16:14:03 -0700922 if (!(app->selector > IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
923 app->selector < IEEE_8021QAZ_APP_SEL_ANY))
924 return -EINVAL;
925
926 /* change selector to a format that firmware understands */
927 ret = __cxgb4_setapp(dev, app->selector - 1, app->protocol,
928 (1 << app->priority));
929 if (ret)
930 return ret;
931
932 return dcb_ieee_setapp(dev, app);
Anish Bhatt76bcb312014-06-19 21:37:12 -0700933}
934
935/* Return our DCBX parameters.
936 */
937static u8 cxgb4_getdcbx(struct net_device *dev)
938{
939 struct port_info *pi = netdev2pinfo(dev);
940
941 /* This is already set by cxgb4_set_dcb_caps, so just return it */
942 return pi->dcb.supported;
943}
944
945/* Set our DCBX parameters.
946 */
947static u8 cxgb4_setdcbx(struct net_device *dev, u8 dcb_request)
948{
949 struct port_info *pi = netdev2pinfo(dev);
950
951 /* Filter out requests which exceed our capabilities.
952 */
953 if ((dcb_request & (CXGB4_DCBX_FW_SUPPORT | CXGB4_DCBX_HOST_SUPPORT))
954 != dcb_request)
955 return 1;
956
Anish Bhatt10b00462014-08-07 16:14:03 -0700957 /* Can't enable DCB if we haven't successfully negotiated it.
958 */
959 if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
Anish Bhatt76bcb312014-06-19 21:37:12 -0700960 return 1;
961
962 /* There's currently no mechanism to allow for the firmware DCBX
963 * negotiation to be changed from the Host Driver. If the caller
964 * requests exactly the same parameters that we already have then
965 * we'll allow them to be successfully "set" ...
966 */
967 if (dcb_request != pi->dcb.supported)
968 return 1;
969
970 pi->dcb.supported = dcb_request;
971 return 0;
972}
973
974static int cxgb4_getpeer_app(struct net_device *dev,
975 struct dcb_peer_app_info *info, u16 *app_count)
976{
977 struct fw_port_cmd pcmd;
978 struct port_info *pi = netdev2pinfo(dev);
979 struct adapter *adap = pi->adapter;
980 int i, err = 0;
981
982 if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
983 return 1;
984
985 info->willing = 0;
986 info->error = 0;
987
988 *app_count = 0;
989 for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
990 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
991 pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
992 pcmd.u.dcb.app_priority.idx = *app_count;
993 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
994
995 if (err != FW_PORT_DCB_CFG_SUCCESS) {
996 dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
997 -err);
998 return err;
999 }
1000
1001 /* find first empty slot */
1002 if (!pcmd.u.dcb.app_priority.protocolid)
1003 break;
1004 }
1005 *app_count = i;
1006 return err;
1007}
1008
1009static int cxgb4_getpeerapp_tbl(struct net_device *dev, struct dcb_app *table)
1010{
1011 struct fw_port_cmd pcmd;
1012 struct port_info *pi = netdev2pinfo(dev);
1013 struct adapter *adap = pi->adapter;
1014 int i, err = 0;
1015
1016 if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
1017 return 1;
1018
1019 for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
1020 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
1021 pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
1022 pcmd.u.dcb.app_priority.idx = i;
1023 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
1024
1025 if (err != FW_PORT_DCB_CFG_SUCCESS) {
1026 dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
1027 -err);
1028 return err;
1029 }
1030
1031 /* find first empty slot */
1032 if (!pcmd.u.dcb.app_priority.protocolid)
1033 break;
1034
1035 table[i].selector = pcmd.u.dcb.app_priority.sel_field;
1036 table[i].protocol =
1037 be16_to_cpu(pcmd.u.dcb.app_priority.protocolid);
Anish Bhatt10b00462014-08-07 16:14:03 -07001038 table[i].priority =
1039 ffs(pcmd.u.dcb.app_priority.user_prio_map) - 1;
Anish Bhatt76bcb312014-06-19 21:37:12 -07001040 }
1041 return err;
1042}
1043
1044/* Return Priority Group information.
1045 */
1046static int cxgb4_cee_peer_getpg(struct net_device *dev, struct cee_pg *pg)
1047{
1048 struct fw_port_cmd pcmd;
1049 struct port_info *pi = netdev2pinfo(dev);
1050 struct adapter *adap = pi->adapter;
1051 u32 pgid;
1052 int i, err;
1053
1054 /* We're always "willing" -- the Switch Fabric always dictates the
1055 * DCBX parameters to us.
1056 */
1057 pg->willing = true;
1058
1059 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
1060 pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
1061 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
1062 if (err != FW_PORT_DCB_CFG_SUCCESS) {
1063 dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
1064 return err;
1065 }
1066 pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
1067
1068 for (i = 0; i < CXGB4_MAX_PRIORITY; i++)
1069 pg->prio_pg[i] = (pgid >> (i * 4)) & 0xF;
1070
1071 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
1072 pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
1073 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
1074 if (err != FW_PORT_DCB_CFG_SUCCESS) {
1075 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
1076 -err);
1077 return err;
1078 }
1079
1080 for (i = 0; i < CXGB4_MAX_PRIORITY; i++)
1081 pg->pg_bw[i] = pcmd.u.dcb.pgrate.pgrate[i];
1082
1083 return 0;
1084}
1085
1086/* Return Priority Flow Control information.
1087 */
1088static int cxgb4_cee_peer_getpfc(struct net_device *dev, struct cee_pfc *pfc)
1089{
1090 struct port_info *pi = netdev2pinfo(dev);
1091
1092 cxgb4_getnumtcs(dev, DCB_NUMTCS_ATTR_PFC, &(pfc->tcs_supported));
1093 pfc->pfc_en = pi->dcb.pfcen;
1094
1095 return 0;
1096}
1097
1098const struct dcbnl_rtnl_ops cxgb4_dcb_ops = {
1099 .ieee_getapp = cxgb4_ieee_getapp,
1100 .ieee_setapp = cxgb4_ieee_setapp,
1101
1102 /* CEE std */
1103 .getstate = cxgb4_getstate,
1104 .setstate = cxgb4_setstate,
1105 .getpgtccfgtx = cxgb4_getpgtccfg_tx,
1106 .getpgbwgcfgtx = cxgb4_getpgbwgcfg_tx,
1107 .getpgtccfgrx = cxgb4_getpgtccfg_rx,
1108 .getpgbwgcfgrx = cxgb4_getpgbwgcfg_rx,
1109 .setpgtccfgtx = cxgb4_setpgtccfg_tx,
1110 .setpgbwgcfgtx = cxgb4_setpgbwgcfg_tx,
1111 .setpfccfg = cxgb4_setpfccfg,
1112 .getpfccfg = cxgb4_getpfccfg,
1113 .setall = cxgb4_setall,
1114 .getcap = cxgb4_getcap,
1115 .getnumtcs = cxgb4_getnumtcs,
1116 .setnumtcs = cxgb4_setnumtcs,
1117 .getpfcstate = cxgb4_getpfcstate,
1118 .setpfcstate = cxgb4_setpfcstate,
1119 .getapp = cxgb4_getapp,
1120 .setapp = cxgb4_setapp,
1121
1122 /* DCBX configuration */
1123 .getdcbx = cxgb4_getdcbx,
1124 .setdcbx = cxgb4_setdcbx,
1125
1126 /* peer apps */
1127 .peer_getappinfo = cxgb4_getpeer_app,
1128 .peer_getapptable = cxgb4_getpeerapp_tbl,
1129
1130 /* CEE peer */
1131 .cee_peer_getpg = cxgb4_cee_peer_getpg,
1132 .cee_peer_getpfc = cxgb4_cee_peer_getpfc,
1133};