cxgb4 : Add DCBx support codebase and dcbnl_ops
[pandora-kernel.git] / drivers / net / ethernet / chelsio / cxgb4 / cxgb4_dcb.c
1 /*
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
23 /* Initialize a port's Data Center Bridging state.  Typically used after a
24  * Link Down event.
25  */
26 void cxgb4_dcb_state_init(struct net_device *dev)
27 {
28         struct port_info *pi = netdev2pinfo(dev);
29         struct port_dcb_info *dcb = &pi->dcb;
30
31         memset(dcb, 0, sizeof(struct port_dcb_info));
32         dcb->state = CXGB4_DCB_STATE_START;
33 }
34
35 /* Finite State machine for Data Center Bridging.
36  */
37 void cxgb4_dcb_state_fsm(struct net_device *dev,
38                          enum cxgb4_dcb_state_input input)
39 {
40         struct port_info *pi = netdev2pinfo(dev);
41         struct port_dcb_info *dcb = &pi->dcb;
42         struct adapter *adap = pi->adapter;
43
44         switch (input) {
45         case CXGB4_DCB_INPUT_FW_DISABLED: {
46                 /* Firmware tells us it's not doing DCB */
47                 switch (dcb->state) {
48                 case CXGB4_DCB_STATE_START: {
49                         /* we're going to use Host DCB */
50                         dcb->state = CXGB4_DCB_STATE_HOST;
51                         dcb->supported = CXGB4_DCBX_HOST_SUPPORT;
52                         dcb->enabled = 1;
53                         break;
54                 }
55
56                 case CXGB4_DCB_STATE_HOST: {
57                         /* we're alreaady in Host DCB mode */
58                         break;
59                 }
60
61                 default:
62                         goto bad_state_transition;
63                 }
64                 break;
65         }
66
67         case CXGB4_DCB_INPUT_FW_ENABLED: {
68                 /* Firmware tells us that it is doing DCB */
69                 switch (dcb->state) {
70                 case CXGB4_DCB_STATE_START: {
71                         /* we're going to use Firmware DCB */
72                         dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
73                         dcb->supported = CXGB4_DCBX_FW_SUPPORT;
74                         break;
75                 }
76
77                 case CXGB4_DCB_STATE_FW_INCOMPLETE:
78                 case CXGB4_DCB_STATE_FW_ALLSYNCED: {
79                         /* we're alreaady in firmware DCB mode */
80                         break;
81                 }
82
83                 default:
84                         goto bad_state_transition;
85                 }
86                 break;
87         }
88
89         case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
90                 /* Firmware tells us that its DCB state is incomplete */
91                 switch (dcb->state) {
92                 case CXGB4_DCB_STATE_FW_INCOMPLETE: {
93                         /* we're already incomplete */
94                         break;
95                 }
96
97                 case CXGB4_DCB_STATE_FW_ALLSYNCED: {
98                         /* We were successfully running with firmware DCB but
99                          * now it's telling us that it's in an "incomplete
100                          * state.  We need to reset back to a ground state
101                          * of incomplete.
102                          */
103                         cxgb4_dcb_state_init(dev);
104                         dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
105                         dcb->supported = CXGB4_DCBX_FW_SUPPORT;
106                         linkwatch_fire_event(dev);
107                         break;
108                 }
109
110                 default:
111                         goto bad_state_transition;
112                 }
113                 break;
114         }
115
116         case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
117                 /* Firmware tells us that its DCB state is complete */
118                 switch (dcb->state) {
119                 case CXGB4_DCB_STATE_FW_INCOMPLETE: {
120                         dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED;
121                         dcb->enabled = 1;
122                         linkwatch_fire_event(dev);
123                         break;
124                 }
125
126                 case CXGB4_DCB_STATE_FW_ALLSYNCED: {
127                         /* we're already all sync'ed */
128                         break;
129                 }
130
131                 default:
132                         goto bad_state_transition;
133                 }
134                 break;
135         }
136
137         default:
138                 goto  bad_state_input;
139         }
140         return;
141
142 bad_state_input:
143         dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: illegal input symbol %d\n",
144                 input);
145         return;
146
147 bad_state_transition:
148         dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: bad state transition, state = %d, input = %d\n",
149                 dcb->state, input);
150 }
151
152 /* Handle a DCB/DCBX update message from the firmware.
153  */
154 void cxgb4_dcb_handle_fw_update(struct adapter *adap,
155                                 const struct fw_port_cmd *pcmd)
156 {
157         const union fw_port_dcb *fwdcb = &pcmd->u.dcb;
158         int port = FW_PORT_CMD_PORTID_GET(be32_to_cpu(pcmd->op_to_portid));
159         struct net_device *dev = adap->port[port];
160         struct port_info *pi = netdev_priv(dev);
161         struct port_dcb_info *dcb = &pi->dcb;
162         int dcb_type = pcmd->u.dcb.pgid.type;
163
164         /* Handle Firmware DCB Control messages separately since they drive
165          * our state machine.
166          */
167         if (dcb_type == FW_PORT_DCB_TYPE_CONTROL) {
168                 enum cxgb4_dcb_state_input input =
169                         ((pcmd->u.dcb.control.all_syncd_pkd &
170                           FW_PORT_CMD_ALL_SYNCD)
171                          ? CXGB4_DCB_STATE_FW_ALLSYNCED
172                          : CXGB4_DCB_STATE_FW_INCOMPLETE);
173
174                 cxgb4_dcb_state_fsm(dev, input);
175                 return;
176         }
177
178         /* It's weird, and almost certainly an error, to get Firmware DCB
179          * messages when we either haven't been told whether we're going to be
180          * doing Host or Firmware DCB; and even worse when we've been told
181          * that we're doing Host DCB!
182          */
183         if (dcb->state == CXGB4_DCB_STATE_START ||
184             dcb->state == CXGB4_DCB_STATE_HOST) {
185                 dev_err(adap->pdev_dev, "Receiving Firmware DCB messages in State %d\n",
186                         dcb->state);
187                 return;
188         }
189
190         /* Now handle the general Firmware DCB update messages ...
191          */
192         switch (dcb_type) {
193         case FW_PORT_DCB_TYPE_PGID:
194                 dcb->pgid = be32_to_cpu(fwdcb->pgid.pgid);
195                 dcb->msgs |= CXGB4_DCB_FW_PGID;
196                 break;
197
198         case FW_PORT_DCB_TYPE_PGRATE:
199                 dcb->pg_num_tcs_supported = fwdcb->pgrate.num_tcs_supported;
200                 memcpy(dcb->pgrate, &fwdcb->pgrate.pgrate,
201                        sizeof(dcb->pgrate));
202                 dcb->msgs |= CXGB4_DCB_FW_PGRATE;
203                 break;
204
205         case FW_PORT_DCB_TYPE_PRIORATE:
206                 memcpy(dcb->priorate, &fwdcb->priorate.strict_priorate,
207                        sizeof(dcb->priorate));
208                 dcb->msgs |= CXGB4_DCB_FW_PRIORATE;
209                 break;
210
211         case FW_PORT_DCB_TYPE_PFC:
212                 dcb->pfcen = fwdcb->pfc.pfcen;
213                 dcb->pfc_num_tcs_supported = fwdcb->pfc.max_pfc_tcs;
214                 dcb->msgs |= CXGB4_DCB_FW_PFC;
215                 break;
216
217         case FW_PORT_DCB_TYPE_APP_ID: {
218                 const struct fw_port_app_priority *fwap = &fwdcb->app_priority;
219                 int idx = fwap->idx;
220                 struct app_priority *ap = &dcb->app_priority[idx];
221
222                 struct dcb_app app = {
223                         .selector = fwap->sel_field,
224                         .protocol = be16_to_cpu(fwap->protocolid),
225                         .priority = fwap->user_prio_map,
226                 };
227                 int err;
228
229                 err = dcb_setapp(dev, &app);
230                 if (err)
231                         dev_err(adap->pdev_dev,
232                                 "Failed DCB Set Application Priority: sel=%d, prot=%d, prio=%d, err=%d\n",
233                                 app.selector, app.protocol, app.priority, -err);
234
235                 ap->user_prio_map = fwap->user_prio_map;
236                 ap->sel_field = fwap->sel_field;
237                 ap->protocolid = be16_to_cpu(fwap->protocolid);
238                 dcb->msgs |= CXGB4_DCB_FW_APP_ID;
239                 break;
240         }
241
242         default:
243                 dev_err(adap->pdev_dev, "Unknown DCB update type received %x\n",
244                         dcb_type);
245                 break;
246         }
247 }
248
249 /* Data Center Bridging netlink operations.
250  */
251
252
253 /* Get current DCB enabled/disabled state.
254  */
255 static u8 cxgb4_getstate(struct net_device *dev)
256 {
257         struct port_info *pi = netdev2pinfo(dev);
258
259         return pi->dcb.enabled;
260 }
261
262 /* Set DCB enabled/disabled.
263  */
264 static u8 cxgb4_setstate(struct net_device *dev, u8 enabled)
265 {
266         struct port_info *pi = netdev2pinfo(dev);
267
268         /* Firmware doesn't provide any mechanism to control the DCB state.
269          */
270         if (enabled != (pi->dcb.state == CXGB4_DCB_STATE_FW_ALLSYNCED))
271                 return 1;
272
273         return 0;
274 }
275
276 static void cxgb4_getpgtccfg(struct net_device *dev, int tc,
277                              u8 *prio_type, u8 *pgid, u8 *bw_per,
278                              u8 *up_tc_map, int local)
279 {
280         struct fw_port_cmd pcmd;
281         struct port_info *pi = netdev2pinfo(dev);
282         struct adapter *adap = pi->adapter;
283         int err;
284
285         *prio_type = *pgid = *bw_per = *up_tc_map = 0;
286
287         if (local)
288                 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
289         else
290                 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
291
292         pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
293         err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
294         if (err != FW_PORT_DCB_CFG_SUCCESS) {
295                 dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
296                 return;
297         }
298         *pgid = (be32_to_cpu(pcmd.u.dcb.pgid.pgid) >> (tc * 4)) & 0xf;
299
300         INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
301         pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
302         err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
303         if (err != FW_PORT_DCB_CFG_SUCCESS) {
304                 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
305                         -err);
306                 return;
307         }
308
309         *bw_per = pcmd.u.dcb.pgrate.pgrate[*pgid];
310         *up_tc_map = (1 << tc);
311
312         /* prio_type is link strict */
313         *prio_type = 0x2;
314 }
315
316 static void cxgb4_getpgtccfg_tx(struct net_device *dev, int tc,
317                                 u8 *prio_type, u8 *pgid, u8 *bw_per,
318                                 u8 *up_tc_map)
319 {
320         return cxgb4_getpgtccfg(dev, tc, prio_type, pgid, bw_per, up_tc_map, 1);
321 }
322
323
324 static void cxgb4_getpgtccfg_rx(struct net_device *dev, int tc,
325                                 u8 *prio_type, u8 *pgid, u8 *bw_per,
326                                 u8 *up_tc_map)
327 {
328         return cxgb4_getpgtccfg(dev, tc, prio_type, pgid, bw_per, up_tc_map, 0);
329 }
330
331 static void cxgb4_setpgtccfg_tx(struct net_device *dev, int tc,
332                                 u8 prio_type, u8 pgid, u8 bw_per,
333                                 u8 up_tc_map)
334 {
335         struct fw_port_cmd pcmd;
336         struct port_info *pi = netdev2pinfo(dev);
337         struct adapter *adap = pi->adapter;
338         u32 _pgid;
339         int err;
340
341         if (pgid == DCB_ATTR_VALUE_UNDEFINED)
342                 return;
343         if (bw_per == DCB_ATTR_VALUE_UNDEFINED)
344                 return;
345
346         INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
347         pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
348
349         err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
350         if (err != FW_PORT_DCB_CFG_SUCCESS) {
351                 dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
352                 return;
353         }
354
355         _pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
356         _pgid &= ~(0xF << (tc * 4));
357         _pgid |= pgid << (tc * 4);
358         pcmd.u.dcb.pgid.pgid = cpu_to_be32(_pgid);
359
360         INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
361
362         err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
363         if (err != FW_PORT_DCB_CFG_SUCCESS) {
364                 dev_err(adap->pdev_dev, "DCB write PGID failed with %d\n",
365                         -err);
366                 return;
367         }
368
369         memset(&pcmd, 0, sizeof(struct fw_port_cmd));
370
371         INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
372         pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
373
374         err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
375         if (err != FW_PORT_DCB_CFG_SUCCESS) {
376                 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
377                         -err);
378                 return;
379         }
380
381         pcmd.u.dcb.pgrate.pgrate[pgid] = bw_per;
382
383         INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
384         if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
385                 pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY);
386
387         err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
388         if (err != FW_PORT_DCB_CFG_SUCCESS)
389                 dev_err(adap->pdev_dev, "DCB write PGRATE failed with %d\n",
390                         -err);
391 }
392
393 static void cxgb4_getpgbwgcfg(struct net_device *dev, int pgid, u8 *bw_per,
394                               int local)
395 {
396         struct fw_port_cmd pcmd;
397         struct port_info *pi = netdev2pinfo(dev);
398         struct adapter *adap = pi->adapter;
399         int err;
400
401         if (local)
402                 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
403         else
404                 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
405
406         pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
407         err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
408         if (err != FW_PORT_DCB_CFG_SUCCESS) {
409                 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
410                         -err);
411         } else {
412                 *bw_per = pcmd.u.dcb.pgrate.pgrate[pgid];
413         }
414 }
415
416 static void cxgb4_getpgbwgcfg_tx(struct net_device *dev, int pgid, u8 *bw_per)
417 {
418         return cxgb4_getpgbwgcfg(dev, pgid, bw_per, 1);
419 }
420
421 static void cxgb4_getpgbwgcfg_rx(struct net_device *dev, int pgid, u8 *bw_per)
422 {
423         return cxgb4_getpgbwgcfg(dev, pgid, bw_per, 0);
424 }
425
426 static void cxgb4_setpgbwgcfg_tx(struct net_device *dev, int pgid,
427                                  u8 bw_per)
428 {
429         struct fw_port_cmd pcmd;
430         struct port_info *pi = netdev2pinfo(dev);
431         struct adapter *adap = pi->adapter;
432         int err;
433
434         INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
435         pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
436
437         err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
438         if (err != FW_PORT_DCB_CFG_SUCCESS) {
439                 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
440                         -err);
441                 return;
442         }
443
444         pcmd.u.dcb.pgrate.pgrate[pgid] = bw_per;
445
446         INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
447         if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
448                 pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY);
449
450         err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
451
452         if (err != FW_PORT_DCB_CFG_SUCCESS)
453                 dev_err(adap->pdev_dev, "DCB write PGRATE failed with %d\n",
454                         -err);
455 }
456
457 /* Return whether the specified Traffic Class Priority has Priority Pause
458  * Frames enabled.
459  */
460 static void cxgb4_getpfccfg(struct net_device *dev, int priority, u8 *pfccfg)
461 {
462         struct port_info *pi = netdev2pinfo(dev);
463         struct port_dcb_info *dcb = &pi->dcb;
464
465         if (dcb->state != CXGB4_DCB_STATE_FW_ALLSYNCED ||
466             priority >= CXGB4_MAX_PRIORITY)
467                 *pfccfg = 0;
468         else
469                 *pfccfg = (pi->dcb.pfcen >> priority) & 1;
470 }
471
472 /* Enable/disable Priority Pause Frames for the specified Traffic Class
473  * Priority.
474  */
475 static void cxgb4_setpfccfg(struct net_device *dev, int priority, u8 pfccfg)
476 {
477         struct fw_port_cmd pcmd;
478         struct port_info *pi = netdev2pinfo(dev);
479         struct adapter *adap = pi->adapter;
480         int err;
481
482         if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED ||
483             priority >= CXGB4_MAX_PRIORITY)
484                 return;
485
486         INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
487         if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
488                 pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY);
489
490         pcmd.u.dcb.pfc.type = FW_PORT_DCB_TYPE_PFC;
491         pcmd.u.dcb.pfc.pfcen = cpu_to_be16(pi->dcb.pfcen);
492
493         if (pfccfg)
494                 pcmd.u.dcb.pfc.pfcen |= cpu_to_be16(1 << priority);
495         else
496                 pcmd.u.dcb.pfc.pfcen &= cpu_to_be16(~(1 << priority));
497
498         err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
499         if (err != FW_PORT_DCB_CFG_SUCCESS) {
500                 dev_err(adap->pdev_dev, "DCB PFC write failed with %d\n", -err);
501                 return;
502         }
503
504         pi->dcb.pfcen = be16_to_cpu(pcmd.u.dcb.pfc.pfcen);
505 }
506
507 static u8 cxgb4_setall(struct net_device *dev)
508 {
509         return 0;
510 }
511
512 /* Return DCB capabilities.
513  */
514 static u8 cxgb4_getcap(struct net_device *dev, int cap_id, u8 *caps)
515 {
516         struct port_info *pi = netdev2pinfo(dev);
517
518         switch (cap_id) {
519         case DCB_CAP_ATTR_PG:
520         case DCB_CAP_ATTR_PFC:
521                 *caps = true;
522                 break;
523
524         case DCB_CAP_ATTR_PG_TCS:
525                 /* 8 priorities for PG represented by bitmap */
526                 *caps = 0x80;
527                 break;
528
529         case DCB_CAP_ATTR_PFC_TCS:
530                 /* 8 priorities for PFC represented by bitmap */
531                 *caps = 0x80;
532                 break;
533
534         case DCB_CAP_ATTR_GSP:
535                 *caps = true;
536                 break;
537
538         case DCB_CAP_ATTR_UP2TC:
539         case DCB_CAP_ATTR_BCN:
540                 *caps = false;
541                 break;
542
543         case DCB_CAP_ATTR_DCBX:
544                 *caps = pi->dcb.supported;
545                 break;
546
547         default:
548                 *caps = false;
549         }
550
551         return 0;
552 }
553
554 /* Return the number of Traffic Classes for the indicated Traffic Class ID.
555  */
556 static int cxgb4_getnumtcs(struct net_device *dev, int tcs_id, u8 *num)
557 {
558         struct port_info *pi = netdev2pinfo(dev);
559
560         switch (tcs_id) {
561         case DCB_NUMTCS_ATTR_PG:
562                 if (pi->dcb.msgs & CXGB4_DCB_FW_PGRATE)
563                         *num = pi->dcb.pg_num_tcs_supported;
564                 else
565                         *num = 0x8;
566                 break;
567
568         case DCB_NUMTCS_ATTR_PFC:
569                 *num = 0x8;
570                 break;
571
572         default:
573                 return -EINVAL;
574         }
575
576         return 0;
577 }
578
579 /* Set the number of Traffic Classes supported for the indicated Traffic Class
580  * ID.
581  */
582 static int cxgb4_setnumtcs(struct net_device *dev, int tcs_id, u8 num)
583 {
584         /* Setting the number of Traffic Classes isn't supported.
585          */
586         return -ENOSYS;
587 }
588
589 /* Return whether Priority Flow Control is enabled.  */
590 static u8 cxgb4_getpfcstate(struct net_device *dev)
591 {
592         struct port_info *pi = netdev2pinfo(dev);
593
594         if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
595                 return false;
596
597         return pi->dcb.pfcen != 0;
598 }
599
600 /* Enable/disable Priority Flow Control. */
601 static void cxgb4_setpfcstate(struct net_device *dev, u8 state)
602 {
603         /* We can't enable/disable Priority Flow Control but we also can't
604          * return an error ...
605          */
606 }
607
608 /* Return the Application User Priority Map associated with the specified
609  * Application ID.
610  */
611 static int __cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id,
612                           int peer)
613 {
614         struct port_info *pi = netdev2pinfo(dev);
615         struct adapter *adap = pi->adapter;
616         int i;
617
618         if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
619                 return 0;
620
621         for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
622                 struct fw_port_cmd pcmd;
623                 int err;
624
625                 if (peer)
626                         INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
627                 else
628                         INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
629
630                 pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
631                 pcmd.u.dcb.app_priority.idx = i;
632
633                 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
634                 if (err != FW_PORT_DCB_CFG_SUCCESS) {
635                         dev_err(adap->pdev_dev, "DCB APP read failed with %d\n",
636                                 -err);
637                         return err;
638                 }
639                 if (be16_to_cpu(pcmd.u.dcb.app_priority.protocolid) == app_id)
640                         return pcmd.u.dcb.app_priority.user_prio_map;
641
642                 /* exhausted app list */
643                 if (!pcmd.u.dcb.app_priority.protocolid)
644                         break;
645         }
646
647         return -EEXIST;
648 }
649
650 /* Return the Application User Priority Map associated with the specified
651  * Application ID.  Since this routine is prototyped to return "u8" we can't
652  * return errors ...
653  */
654 static u8 cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id)
655 {
656         int result = __cxgb4_getapp(dev, app_idtype, app_id, 0);
657
658         if (result < 0)
659                 result = 0;
660
661         return result;
662 }
663
664 /* Write a new Application User Priority Map for the specified Application ID.
665  * This routine is prototyped to return "u8" but other instantiations of the
666  * DCB NetLink Operations "setapp" routines return negative errnos for errors.
667  * We follow their lead.
668  */
669 static u8 cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
670                        u8 app_prio)
671 {
672         struct fw_port_cmd pcmd;
673         struct port_info *pi = netdev2pinfo(dev);
674         struct adapter *adap = pi->adapter;
675         int i, err;
676
677
678         if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
679                 return -EINVAL;
680
681         /* DCB info gets thrown away on link up */
682         if (!netif_carrier_ok(dev))
683                 return -ENOLINK;
684
685         if (app_idtype != DCB_APP_IDTYPE_ETHTYPE &&
686             app_idtype != DCB_APP_IDTYPE_PORTNUM)
687                 return -EINVAL;
688
689         for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
690                 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
691                 pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
692                 pcmd.u.dcb.app_priority.idx = i;
693                 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
694
695                 if (err != FW_PORT_DCB_CFG_SUCCESS) {
696                         dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
697                                 -err);
698                         return err;
699                 }
700                 if (be16_to_cpu(pcmd.u.dcb.app_priority.protocolid) == app_id) {
701                         /* overwrite existing app table */
702                         pcmd.u.dcb.app_priority.protocolid = 0;
703                         break;
704                 }
705                 /* find first empty slot */
706                 if (!pcmd.u.dcb.app_priority.protocolid)
707                         break;
708         }
709
710         if (i == CXGB4_MAX_DCBX_APP_SUPPORTED) {
711                 /* no empty slots available */
712                 dev_err(adap->pdev_dev, "DCB app table full\n");
713                 return -EBUSY;
714         }
715
716         /* write out new app table entry */
717         INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
718         if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
719                 pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY);
720
721         pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
722         pcmd.u.dcb.app_priority.protocolid = cpu_to_be16(app_id);
723         pcmd.u.dcb.app_priority.sel_field = app_idtype;
724         pcmd.u.dcb.app_priority.user_prio_map = app_prio;
725         pcmd.u.dcb.app_priority.idx = i;
726
727         err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
728         if (err != FW_PORT_DCB_CFG_SUCCESS) {
729                 dev_err(adap->pdev_dev, "DCB app table write failed with %d\n",
730                         -err);
731                 return err;
732         }
733
734         return 0;
735 }
736
737 /* Return whether IEEE Data Center Bridging has been negotiated.
738  */
739 static inline int cxgb4_ieee_negotiation_complete(struct net_device *dev)
740 {
741         struct port_info *pi = netdev2pinfo(dev);
742         struct port_dcb_info *dcb = &pi->dcb;
743
744         return (dcb->state == CXGB4_DCB_STATE_FW_ALLSYNCED &&
745                 (dcb->supported & DCB_CAP_DCBX_VER_IEEE));
746 }
747
748 /* Fill in the Application User Priority Map associated with the
749  * specified Application.
750  */
751 static int cxgb4_ieee_getapp(struct net_device *dev, struct dcb_app *app)
752 {
753         int prio;
754
755         if (!cxgb4_ieee_negotiation_complete(dev))
756                 return -EINVAL;
757         if (!(app->selector && app->protocol))
758                 return -EINVAL;
759
760         prio = dcb_getapp(dev, app);
761         if (prio == 0) {
762                 /* If app doesn't exist in dcb_app table, try firmware
763                  * directly.
764                  */
765                 prio = __cxgb4_getapp(dev, app->selector, app->protocol, 0);
766         }
767
768         app->priority = prio;
769         return 0;
770 }
771
772 /* Write a new Application User Priority Map for the specified App id. */
773 static int cxgb4_ieee_setapp(struct net_device *dev, struct dcb_app *app)
774 {
775         if (!cxgb4_ieee_negotiation_complete(dev))
776                 return -EINVAL;
777         if (!(app->selector && app->protocol && app->priority))
778                 return -EINVAL;
779
780         cxgb4_setapp(dev, app->selector, app->protocol, app->priority);
781         return dcb_setapp(dev, app);
782 }
783
784 /* Return our DCBX parameters.
785  */
786 static u8 cxgb4_getdcbx(struct net_device *dev)
787 {
788         struct port_info *pi = netdev2pinfo(dev);
789
790         /* This is already set by cxgb4_set_dcb_caps, so just return it */
791         return pi->dcb.supported;
792 }
793
794 /* Set our DCBX parameters.
795  */
796 static u8 cxgb4_setdcbx(struct net_device *dev, u8 dcb_request)
797 {
798         struct port_info *pi = netdev2pinfo(dev);
799
800         /* Filter out requests which exceed our capabilities.
801          */
802         if ((dcb_request & (CXGB4_DCBX_FW_SUPPORT | CXGB4_DCBX_HOST_SUPPORT))
803             != dcb_request)
804                 return 1;
805
806         /* Can't set DCBX capabilities if DCBX isn't enabled. */
807         if (!pi->dcb.state)
808                 return 1;
809
810         /* There's currently no mechanism to allow for the firmware DCBX
811          * negotiation to be changed from the Host Driver.  If the caller
812          * requests exactly the same parameters that we already have then
813          * we'll allow them to be successfully "set" ...
814          */
815         if (dcb_request != pi->dcb.supported)
816                 return 1;
817
818         pi->dcb.supported = dcb_request;
819         return 0;
820 }
821
822 static int cxgb4_getpeer_app(struct net_device *dev,
823                              struct dcb_peer_app_info *info, u16 *app_count)
824 {
825         struct fw_port_cmd pcmd;
826         struct port_info *pi = netdev2pinfo(dev);
827         struct adapter *adap = pi->adapter;
828         int i, err = 0;
829
830         if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
831                 return 1;
832
833         info->willing = 0;
834         info->error = 0;
835
836         *app_count = 0;
837         for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
838                 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
839                 pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
840                 pcmd.u.dcb.app_priority.idx = *app_count;
841                 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
842
843                 if (err != FW_PORT_DCB_CFG_SUCCESS) {
844                         dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
845                                 -err);
846                         return err;
847                 }
848
849                 /* find first empty slot */
850                 if (!pcmd.u.dcb.app_priority.protocolid)
851                         break;
852         }
853         *app_count = i;
854         return err;
855 }
856
857 static int cxgb4_getpeerapp_tbl(struct net_device *dev, struct dcb_app *table)
858 {
859         struct fw_port_cmd pcmd;
860         struct port_info *pi = netdev2pinfo(dev);
861         struct adapter *adap = pi->adapter;
862         int i, err = 0;
863
864         if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
865                 return 1;
866
867         for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
868                 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
869                 pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
870                 pcmd.u.dcb.app_priority.idx = i;
871                 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
872
873                 if (err != FW_PORT_DCB_CFG_SUCCESS) {
874                         dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
875                                 -err);
876                         return err;
877                 }
878
879                 /* find first empty slot */
880                 if (!pcmd.u.dcb.app_priority.protocolid)
881                         break;
882
883                 table[i].selector = pcmd.u.dcb.app_priority.sel_field;
884                 table[i].protocol =
885                         be16_to_cpu(pcmd.u.dcb.app_priority.protocolid);
886                 table[i].priority = pcmd.u.dcb.app_priority.user_prio_map;
887         }
888         return err;
889 }
890
891 /* Return Priority Group information.
892  */
893 static int cxgb4_cee_peer_getpg(struct net_device *dev, struct cee_pg *pg)
894 {
895         struct fw_port_cmd pcmd;
896         struct port_info *pi = netdev2pinfo(dev);
897         struct adapter *adap = pi->adapter;
898         u32 pgid;
899         int i, err;
900
901         /* We're always "willing" -- the Switch Fabric always dictates the
902          * DCBX parameters to us.
903          */
904         pg->willing = true;
905
906         INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
907         pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
908         err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
909         if (err != FW_PORT_DCB_CFG_SUCCESS) {
910                 dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
911                 return err;
912         }
913         pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
914
915         for (i = 0; i < CXGB4_MAX_PRIORITY; i++)
916                 pg->prio_pg[i] = (pgid >> (i * 4)) & 0xF;
917
918         INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
919         pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
920         err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
921         if (err != FW_PORT_DCB_CFG_SUCCESS) {
922                 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
923                         -err);
924                 return err;
925         }
926
927         for (i = 0; i < CXGB4_MAX_PRIORITY; i++)
928                 pg->pg_bw[i] = pcmd.u.dcb.pgrate.pgrate[i];
929
930         return 0;
931 }
932
933 /* Return Priority Flow Control information.
934  */
935 static int cxgb4_cee_peer_getpfc(struct net_device *dev, struct cee_pfc *pfc)
936 {
937         struct port_info *pi = netdev2pinfo(dev);
938
939         cxgb4_getnumtcs(dev, DCB_NUMTCS_ATTR_PFC, &(pfc->tcs_supported));
940         pfc->pfc_en = pi->dcb.pfcen;
941
942         return 0;
943 }
944
945 const struct dcbnl_rtnl_ops cxgb4_dcb_ops = {
946         .ieee_getapp            = cxgb4_ieee_getapp,
947         .ieee_setapp            = cxgb4_ieee_setapp,
948
949         /* CEE std */
950         .getstate               = cxgb4_getstate,
951         .setstate               = cxgb4_setstate,
952         .getpgtccfgtx           = cxgb4_getpgtccfg_tx,
953         .getpgbwgcfgtx          = cxgb4_getpgbwgcfg_tx,
954         .getpgtccfgrx           = cxgb4_getpgtccfg_rx,
955         .getpgbwgcfgrx          = cxgb4_getpgbwgcfg_rx,
956         .setpgtccfgtx           = cxgb4_setpgtccfg_tx,
957         .setpgbwgcfgtx          = cxgb4_setpgbwgcfg_tx,
958         .setpfccfg              = cxgb4_setpfccfg,
959         .getpfccfg              = cxgb4_getpfccfg,
960         .setall                 = cxgb4_setall,
961         .getcap                 = cxgb4_getcap,
962         .getnumtcs              = cxgb4_getnumtcs,
963         .setnumtcs              = cxgb4_setnumtcs,
964         .getpfcstate            = cxgb4_getpfcstate,
965         .setpfcstate            = cxgb4_setpfcstate,
966         .getapp                 = cxgb4_getapp,
967         .setapp                 = cxgb4_setapp,
968
969         /* DCBX configuration */
970         .getdcbx                = cxgb4_getdcbx,
971         .setdcbx                = cxgb4_setdcbx,
972
973         /* peer apps */
974         .peer_getappinfo        = cxgb4_getpeer_app,
975         .peer_getapptable       = cxgb4_getpeerapp_tbl,
976
977         /* CEE peer */
978         .cee_peer_getpg         = cxgb4_cee_peer_getpg,
979         .cee_peer_getpfc        = cxgb4_cee_peer_getpfc,
980 };