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