xref: /linux/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c (revision 26fbb4c8c7c3ee9a4c3b4de555a8587b5a19154e)
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  */
13 const char * const dcb_ver_array[] = {
14 	"Unknown",
15 	"DCBx-CIN",
16 	"DCBx-CEE 1.01",
17 	"DCBx-IEEE",
18 	"", "", "",
19 	"Auto Negotiated"
20 };
21 
22 static 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  */
33 void 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 
48 void 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 
59 static 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  */
99 void 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  */
110 static 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  */
125 void 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 
261 bad_state_input:
262 	dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: illegal input symbol %d\n",
263 		transition_to);
264 	return;
265 
266 bad_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  */
273 void 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, 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  */
411 static 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  */
420 static 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 
438 static 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, adap->mbox, &pcmd, sizeof(pcmd), &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, adap->mbox, &pcmd, sizeof(pcmd), &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 
482 static 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, (7 - tc), prio_type, pgid, bw_per,
488 				up_tc_map, 1);
489 }
490 
491 
492 static 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, (7 - tc), prio_type, pgid, bw_per,
498 				up_tc_map, 0);
499 }
500 
501 static 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, adap->mbox, &pcmd, sizeof(pcmd), &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, adap->mbox, &pcmd, sizeof(pcmd), &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, adap->mbox, &pcmd, sizeof(pcmd), &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, adap->mbox, &pcmd, sizeof(pcmd), &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 
564 static 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, adap->mbox, &pcmd, sizeof(pcmd), &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 
588 static void cxgb4_getpgbwgcfg_tx(struct net_device *dev, int pgid, u8 *bw_per)
589 {
590 	return cxgb4_getpgbwgcfg(dev, pgid, bw_per, 1);
591 }
592 
593 static void cxgb4_getpgbwgcfg_rx(struct net_device *dev, int pgid, u8 *bw_per)
594 {
595 	return cxgb4_getpgbwgcfg(dev, pgid, bw_per, 0);
596 }
597 
598 static 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, adap->mbox, &pcmd, sizeof(pcmd), &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, adap->mbox, &pcmd, sizeof(pcmd), &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  */
632 static 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(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  */
647 static 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(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, adap->mbox, &pcmd, sizeof(pcmd), &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 
679 static u8 cxgb4_setall(struct net_device *dev)
680 {
681 	return 0;
682 }
683 
684 /* Return DCB capabilities.
685  */
686 static 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  */
728 static 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  */
754 static 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.  */
762 static u8 cxgb4_getpfcstate(struct net_device *dev)
763 {
764 	struct port_info *pi = netdev2pinfo(dev);
765 
766 	if (!cxgb4_dcb_state_synced(pi->dcb.state))
767 		return false;
768 
769 	return pi->dcb.pfcen != 0;
770 }
771 
772 /* Enable/disable Priority Flow Control. */
773 static 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  */
783 static 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(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, adap->mbox, &pcmd, sizeof(pcmd), &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  */
826 static 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 == DCB_APP_IDTYPE_ETHTYPE ?
830 			      app_idtype : 3, app_id, 0);
831 }
832 
833 /* Write a new Application User Priority Map for the specified Application ID
834  */
835 static 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(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, adap->mbox, &pcmd, sizeof(pcmd), &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, adap->mbox, &pcmd, sizeof(pcmd), &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 */
900 static 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 == 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  */
925 static inline int
926 cxgb4_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(dcb->state) &&
937 		(dcb->supported & DCB_CAP_DCBX_VER_IEEE));
938 }
939 
940 static 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, adap->mbox, &pcmd, sizeof(pcmd), &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, adap->mbox, &pcmd, sizeof(pcmd), &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 
995 static int cxgb4_ieee_get_ets(struct net_device *dev, struct ieee_ets *ets)
996 {
997 	return cxgb4_ieee_read_ets(dev, ets, 1);
998 }
999 
1000 /* We reuse this for peer PFC as well, as we can't have it enabled one way */
1001 static 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(dcb->pfcen);
1013 
1014 	return 0;
1015 }
1016 
1017 static int cxgb4_ieee_peer_ets(struct net_device *dev, struct ieee_ets *ets)
1018 {
1019 	return cxgb4_ieee_read_ets(dev, ets, 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  */
1026 static int cxgb4_ieee_getapp(struct net_device *dev, struct dcb_app *app)
1027 {
1028 	int prio;
1029 
1030 	if (!cxgb4_ieee_negotiation_complete(dev, 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->selector - 1, app->protocol, 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  */
1048 static int cxgb4_ieee_setapp(struct net_device *dev, struct dcb_app *app)
1049 {
1050 	int ret;
1051 
1052 	if (!cxgb4_ieee_negotiation_complete(dev, 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->selector - 1, app->protocol,
1063 			     (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  */
1072 static 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  */
1082 static 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(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 
1109 static 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(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, adap->mbox, &pcmd, sizeof(pcmd), &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 
1144 static 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(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, adap->mbox, &pcmd, sizeof(pcmd), &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  */
1181 static 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, adap->mbox, &pcmd, sizeof(pcmd), &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, adap->mbox, &pcmd, sizeof(pcmd), &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  */
1225 static 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, DCB_NUMTCS_ATTR_PFC, &(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(pi->dcb.pfcen);
1236 
1237 	pfc->tcs_supported = pi->dcb.pfc_num_tcs_supported;
1238 
1239 	return 0;
1240 }
1241 
1242 const 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