aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-06-23 00:13:38 -0400
committerDavid S. Miller <davem@davemloft.net>2014-06-23 00:13:38 -0400
commit47cc3b4f0f5956055672ce89366ef17c03597087 (patch)
treecb59da2734549efe537fb579a6e287cf07b06714
parent9f8b93cb32e088d3377c86fabb666b884bac0f12 (diff)
parentce100b8b813da05338ec15e40c195ee597be9dc9 (diff)
Merge branch 'cxgb4-next'
Anish Bhatt says: ==================== cxgb4 : Add DCBx support to Chelsio cxgb4 driver This patchset adds support for DCBx via dcbnl_ops to the cxgb4 driver. This should enable cxgb4 to work with open-lldp and the like. The last patch only updates copyright year. v2 : move inclusion of struct port_dcb_info to the same patch as where it is defined. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/chelsio/Kconfig11
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/Makefile1
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h13
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c980
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h141
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c201
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/l2t.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/l2t.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sge.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.c78
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_msg.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_regs.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h97
15 files changed, 1492 insertions, 44 deletions
diff --git a/drivers/net/ethernet/chelsio/Kconfig b/drivers/net/ethernet/chelsio/Kconfig
index 570222c33410..c3ce9df0041a 100644
--- a/drivers/net/ethernet/chelsio/Kconfig
+++ b/drivers/net/ethernet/chelsio/Kconfig
@@ -86,6 +86,17 @@ config CHELSIO_T4
86 To compile this driver as a module choose M here; the module 86 To compile this driver as a module choose M here; the module
87 will be called cxgb4. 87 will be called cxgb4.
88 88
89config CHELSIO_T4_DCB
90 bool "Data Center Bridging (DCB) Support for Chelsio T4/T5 cards"
91 default n
92 depends on CHELSIO_T4 && DCB
93 ---help---
94 Enable DCB support through rtNetlink interface.
95 Say Y here if you want to enable Data Center Bridging (DCB) support
96 in the driver.
97
98 If unsure, say N.
99
89config CHELSIO_T4VF 100config CHELSIO_T4VF
90 tristate "Chelsio Communications T4/T5 Virtual Function Ethernet support" 101 tristate "Chelsio Communications T4/T5 Virtual Function Ethernet support"
91 depends on PCI 102 depends on PCI
diff --git a/drivers/net/ethernet/chelsio/cxgb4/Makefile b/drivers/net/ethernet/chelsio/cxgb4/Makefile
index 498667487f52..1df65c915b99 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/Makefile
+++ b/drivers/net/ethernet/chelsio/cxgb4/Makefile
@@ -5,3 +5,4 @@
5obj-$(CONFIG_CHELSIO_T4) += cxgb4.o 5obj-$(CONFIG_CHELSIO_T4) += cxgb4.o
6 6
7cxgb4-objs := cxgb4_main.o l2t.o t4_hw.o sge.o 7cxgb4-objs := cxgb4_main.o l2t.o t4_hw.o sge.o
8cxgb4-$(CONFIG_CHELSIO_T4_DCB) += cxgb4_dcb.o
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index f503dce4ab17..7b5425c9c0fb 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * This file is part of the Chelsio T4 Ethernet driver for Linux. 2 * This file is part of the Chelsio T4 Ethernet driver for Linux.
3 * 3 *
4 * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved. 4 * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
5 * 5 *
6 * This software is available to you under a choice of one of two 6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU 7 * licenses. You may choose to be licensed under the terms of the GNU
@@ -373,6 +373,8 @@ enum {
373struct adapter; 373struct adapter;
374struct sge_rspq; 374struct sge_rspq;
375 375
376#include "cxgb4_dcb.h"
377
376struct port_info { 378struct port_info {
377 struct adapter *adapter; 379 struct adapter *adapter;
378 u16 viid; 380 u16 viid;
@@ -389,6 +391,9 @@ struct port_info {
389 u8 rss_mode; 391 u8 rss_mode;
390 struct link_config link_cfg; 392 struct link_config link_cfg;
391 u16 *rss; 393 u16 *rss;
394#ifdef CONFIG_CHELSIO_T4_DCB
395 struct port_dcb_info dcb; /* Data Center Bridging support */
396#endif
392}; 397};
393 398
394struct dentry; 399struct dentry;
@@ -1007,6 +1012,10 @@ int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
1007int t4_set_params(struct adapter *adap, unsigned int mbox, unsigned int pf, 1012int t4_set_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
1008 unsigned int vf, unsigned int nparams, const u32 *params, 1013 unsigned int vf, unsigned int nparams, const u32 *params,
1009 const u32 *val); 1014 const u32 *val);
1015int t4_set_params_nosleep(struct adapter *adap, unsigned int mbox,
1016 unsigned int pf, unsigned int vf,
1017 unsigned int nparams, const u32 *params,
1018 const u32 *val);
1010int t4_cfg_pfvf(struct adapter *adap, unsigned int mbox, unsigned int pf, 1019int t4_cfg_pfvf(struct adapter *adap, unsigned int mbox, unsigned int pf,
1011 unsigned int vf, unsigned int txq, unsigned int txq_eth_ctrl, 1020 unsigned int vf, unsigned int txq, unsigned int txq_eth_ctrl,
1012 unsigned int rxqi, unsigned int rxq, unsigned int tc, 1021 unsigned int rxqi, unsigned int rxq, unsigned int tc,
@@ -1025,6 +1034,8 @@ int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid,
1025 int idx, const u8 *addr, bool persist, bool add_smt); 1034 int idx, const u8 *addr, bool persist, bool add_smt);
1026int t4_set_addr_hash(struct adapter *adap, unsigned int mbox, unsigned int viid, 1035int t4_set_addr_hash(struct adapter *adap, unsigned int mbox, unsigned int viid,
1027 bool ucast, u64 vec, bool sleep_ok); 1036 bool ucast, u64 vec, bool sleep_ok);
1037int t4_enable_vi_params(struct adapter *adap, unsigned int mbox,
1038 unsigned int viid, bool rx_en, bool tx_en, bool dcb_en);
1028int t4_enable_vi(struct adapter *adap, unsigned int mbox, unsigned int viid, 1039int t4_enable_vi(struct adapter *adap, unsigned int mbox, unsigned int viid,
1029 bool rx_en, bool tx_en); 1040 bool rx_en, bool tx_en);
1030int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid, 1041int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid,
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c
new file mode 100644
index 000000000000..39b4a85fceae
--- /dev/null
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c
@@ -0,0 +1,980 @@
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 */
26void 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 */
37void 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
142bad_state_input:
143 dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: illegal input symbol %d\n",
144 input);
145 return;
146
147bad_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 */
154void 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 */
255static 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 */
264static 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
276static 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
316static 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
324static 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
331static 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
393static 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
416static 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
421static 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
426static 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 */
460static 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 */
475static 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
507static u8 cxgb4_setall(struct net_device *dev)
508{
509 return 0;
510}
511
512/* Return DCB capabilities.
513 */
514static 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 */
556static 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 */
582static 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. */
590static 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. */
601static 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 */
611static 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 */
654static 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 */
669static 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 */
739static 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 */
751static 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. */
773static 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 */
786static 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 */
796static 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
822static 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
857static 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 */
893static 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 */
935static 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
945const 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};
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h
new file mode 100644
index 000000000000..1ec1d834e257
--- /dev/null
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h
@@ -0,0 +1,141 @@
1/*
2 * Copyright (C) 2013-2014 Chelsio Communications. All rights reserved.
3 *
4 * Written by Anish Bhatt (anish@chelsio.com)
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
17 *
18 */
19
20#ifndef __CXGB4_DCB_H
21#define __CXGB4_DCB_H
22
23#include <linux/netdevice.h>
24#include <linux/dcbnl.h>
25#include <net/dcbnl.h>
26
27#ifdef CONFIG_CHELSIO_T4_DCB
28
29#define CXGB4_DCBX_FW_SUPPORT \
30 (DCB_CAP_DCBX_VER_CEE | \
31 DCB_CAP_DCBX_VER_IEEE | \
32 DCB_CAP_DCBX_LLD_MANAGED)
33#define CXGB4_DCBX_HOST_SUPPORT \
34 (DCB_CAP_DCBX_VER_CEE | \
35 DCB_CAP_DCBX_VER_IEEE | \
36 DCB_CAP_DCBX_HOST)
37
38#define CXGB4_MAX_PRIORITY CXGB4_MAX_DCBX_APP_SUPPORTED
39#define CXGB4_MAX_TCS CXGB4_MAX_DCBX_APP_SUPPORTED
40
41#define INIT_PORT_DCB_CMD(__pcmd, __port, __op, __action) \
42 do { \
43 memset(&(__pcmd), 0, sizeof(__pcmd)); \
44 (__pcmd).op_to_portid = \
45 cpu_to_be32(FW_CMD_OP(FW_PORT_CMD) | \
46 FW_CMD_REQUEST | \
47 FW_CMD_##__op | \
48 FW_PORT_CMD_PORTID(__port)); \
49 (__pcmd).action_to_len16 = \
50 cpu_to_be32(FW_PORT_CMD_ACTION(__action) | \
51 FW_LEN16(pcmd)); \
52 } while (0)
53
54#define INIT_PORT_DCB_READ_PEER_CMD(__pcmd, __port) \
55 INIT_PORT_DCB_CMD(__pcmd, __port, READ, FW_PORT_ACTION_DCB_READ_RECV)
56
57#define INIT_PORT_DCB_READ_LOCAL_CMD(__pcmd, __port) \
58 INIT_PORT_DCB_CMD(__pcmd, __port, READ, FW_PORT_ACTION_DCB_READ_TRANS)
59
60#define INIT_PORT_DCB_READ_SYNC_CMD(__pcmd, __port) \
61 INIT_PORT_DCB_CMD(__pcmd, __port, READ, FW_PORT_ACTION_DCB_READ_DET)
62
63#define INIT_PORT_DCB_WRITE_CMD(__pcmd, __port) \
64 INIT_PORT_DCB_CMD(__pcmd, __port, EXEC, FW_PORT_ACTION_L2_DCB_CFG)
65
66/* States we can be in for a port's Data Center Bridging.
67 */
68enum cxgb4_dcb_state {
69 CXGB4_DCB_STATE_START, /* initial unknown state */
70 CXGB4_DCB_STATE_HOST, /* we're using Host DCB (if at all) */
71 CXGB4_DCB_STATE_FW_INCOMPLETE, /* using firmware DCB, incomplete */
72 CXGB4_DCB_STATE_FW_ALLSYNCED, /* using firmware DCB, all sync'ed */
73};
74
75/* Data Center Bridging state input for the Finite State Machine.
76 */
77enum cxgb4_dcb_state_input {
78 /* Input from the firmware.
79 */
80 CXGB4_DCB_INPUT_FW_DISABLED, /* firmware DCB disabled */
81 CXGB4_DCB_INPUT_FW_ENABLED, /* firmware DCB enabled */
82 CXGB4_DCB_INPUT_FW_INCOMPLETE, /* firmware reports incomplete DCB */
83 CXGB4_DCB_INPUT_FW_ALLSYNCED, /* firmware reports all sync'ed */
84
85};
86
87/* Firmware DCB messages that we've received so far ...
88 */
89enum cxgb4_dcb_fw_msgs {
90 CXGB4_DCB_FW_PGID = 0x01,
91 CXGB4_DCB_FW_PGRATE = 0x02,
92 CXGB4_DCB_FW_PRIORATE = 0x04,
93 CXGB4_DCB_FW_PFC = 0x08,
94 CXGB4_DCB_FW_APP_ID = 0x10,
95};
96
97#define CXGB4_MAX_DCBX_APP_SUPPORTED 8
98
99/* Data Center Bridging support;
100 */
101struct port_dcb_info {
102 enum cxgb4_dcb_state state; /* DCB State Machine */
103 enum cxgb4_dcb_fw_msgs msgs; /* DCB Firmware messages received */
104 unsigned int supported; /* OS DCB capabilities supported */
105 bool enabled; /* OS Enabled state */
106
107 /* Cached copies of DCB information sent by the firmware (in Host
108 * Native Endian format).
109 */
110 u32 pgid; /* Priority Group[0..7] */
111 u8 pfcen; /* Priority Flow Control[0..7] */
112 u8 pg_num_tcs_supported; /* max PG Traffic Classes */
113 u8 pfc_num_tcs_supported; /* max PFC Traffic Classes */
114 u8 pgrate[8]; /* Priority Group Rate[0..7] */
115 u8 priorate[8]; /* Priority Rate[0..7] */
116 struct app_priority { /* Application Information */
117 u8 user_prio_map; /* Priority Map bitfield */
118 u8 sel_field; /* Protocol ID interpretation */
119 u16 protocolid; /* Protocol ID */
120 } app_priority[CXGB4_MAX_DCBX_APP_SUPPORTED];
121};
122
123void cxgb4_dcb_state_init(struct net_device *);
124void cxgb4_dcb_state_fsm(struct net_device *, enum cxgb4_dcb_state_input);
125void cxgb4_dcb_handle_fw_update(struct adapter *, const struct fw_port_cmd *);
126void cxgb4_dcb_set_caps(struct adapter *, const struct fw_port_cmd *);
127extern const struct dcbnl_rtnl_ops cxgb4_dcb_ops;
128
129#define CXGB4_DCB_ENABLED true
130
131#else /* !CONFIG_CHELSIO_T4_DCB */
132
133static inline void cxgb4_dcb_state_init(struct net_device *dev)
134{
135}
136
137#define CXGB4_DCB_ENABLED false
138
139#endif /* !CONFIG_CHELSIO_T4_DCB */
140
141#endif /* __CXGB4_DCB_H */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 2f8d6b910383..02a0ebfa9c40 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * This file is part of the Chelsio T4 Ethernet driver for Linux. 2 * This file is part of the Chelsio T4 Ethernet driver for Linux.
3 * 3 *
4 * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved. 4 * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
5 * 5 *
6 * This software is available to you under a choice of one of two 6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU 7 * licenses. You may choose to be licensed under the terms of the GNU
@@ -67,6 +67,7 @@
67#include "t4_regs.h" 67#include "t4_regs.h"
68#include "t4_msg.h" 68#include "t4_msg.h"
69#include "t4fw_api.h" 69#include "t4fw_api.h"
70#include "cxgb4_dcb.h"
70#include "l2t.h" 71#include "l2t.h"
71 72
72#include <../drivers/net/bonding/bonding.h> 73#include <../drivers/net/bonding/bonding.h>
@@ -391,6 +392,17 @@ module_param_array(num_vf, uint, NULL, 0644);
391MODULE_PARM_DESC(num_vf, "number of VFs for each of PFs 0-3"); 392MODULE_PARM_DESC(num_vf, "number of VFs for each of PFs 0-3");
392#endif 393#endif
393 394
395/* TX Queue select used to determine what algorithm to use for selecting TX
396 * queue. Select between the kernel provided function (select_queue=0) or user
397 * cxgb_select_queue function (select_queue=1)
398 *
399 * Default: select_queue=0
400 */
401static int select_queue;
402module_param(select_queue, int, 0644);
403MODULE_PARM_DESC(select_queue,
404 "Select between kernel provided method of selecting or driver method of selecting TX queue. Default is kernel method.");
405
394/* 406/*
395 * The filter TCAM has a fixed portion and a variable portion. The fixed 407 * The filter TCAM has a fixed portion and a variable portion. The fixed
396 * portion can match on source/destination IP IPv4/IPv6 addresses and TCP/UDP 408 * portion can match on source/destination IP IPv4/IPv6 addresses and TCP/UDP
@@ -458,6 +470,42 @@ static void link_report(struct net_device *dev)
458 } 470 }
459} 471}
460 472
473#ifdef CONFIG_CHELSIO_T4_DCB
474/* Set up/tear down Data Center Bridging Priority mapping for a net device. */
475static void dcb_tx_queue_prio_enable(struct net_device *dev, int enable)
476{
477 struct port_info *pi = netdev_priv(dev);
478 struct adapter *adap = pi->adapter;
479 struct sge_eth_txq *txq = &adap->sge.ethtxq[pi->first_qset];
480 int i;
481
482 /* We use a simple mapping of Port TX Queue Index to DCB
483 * Priority when we're enabling DCB.
484 */
485 for (i = 0; i < pi->nqsets; i++, txq++) {
486 u32 name, value;
487 int err;
488
489 name = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) |
490 FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DMAQ_EQ_DCBPRIO_ETH) |
491 FW_PARAMS_PARAM_YZ(txq->q.cntxt_id));
492 value = enable ? i : 0xffffffff;
493
494 /* Since we can be called while atomic (from "interrupt
495 * level") we need to issue the Set Parameters Commannd
496 * without sleeping (timeout < 0).
497 */
498 err = t4_set_params_nosleep(adap, adap->mbox, adap->fn, 0, 1,
499 &name, &value);
500
501 if (err)
502 dev_err(adap->pdev_dev,
503 "Can't %s DCB Priority on port %d, TX Queue %d: err=%d\n",
504 enable ? "set" : "unset", pi->port_id, i, -err);
505 }
506}
507#endif /* CONFIG_CHELSIO_T4_DCB */
508
461void t4_os_link_changed(struct adapter *adapter, int port_id, int link_stat) 509void t4_os_link_changed(struct adapter *adapter, int port_id, int link_stat)
462{ 510{
463 struct net_device *dev = adapter->port[port_id]; 511 struct net_device *dev = adapter->port[port_id];
@@ -466,8 +514,13 @@ void t4_os_link_changed(struct adapter *adapter, int port_id, int link_stat)
466 if (netif_running(dev) && link_stat != netif_carrier_ok(dev)) { 514 if (netif_running(dev) && link_stat != netif_carrier_ok(dev)) {
467 if (link_stat) 515 if (link_stat)
468 netif_carrier_on(dev); 516 netif_carrier_on(dev);
469 else 517 else {
518#ifdef CONFIG_CHELSIO_T4_DCB
519 cxgb4_dcb_state_init(dev);
520 dcb_tx_queue_prio_enable(dev, false);
521#endif /* CONFIG_CHELSIO_T4_DCB */
470 netif_carrier_off(dev); 522 netif_carrier_off(dev);
523 }
471 524
472 link_report(dev); 525 link_report(dev);
473 } 526 }
@@ -601,10 +654,45 @@ static int link_start(struct net_device *dev)
601 ret = t4_link_start(pi->adapter, mb, pi->tx_chan, 654 ret = t4_link_start(pi->adapter, mb, pi->tx_chan,
602 &pi->link_cfg); 655 &pi->link_cfg);
603 if (ret == 0) 656 if (ret == 0)
604 ret = t4_enable_vi(pi->adapter, mb, pi->viid, true, true); 657 ret = t4_enable_vi_params(pi->adapter, mb, pi->viid, true,
658 true, CXGB4_DCB_ENABLED);
659
605 return ret; 660 return ret;
606} 661}
607 662
663int cxgb4_dcb_enabled(const struct net_device *dev)
664{
665#ifdef CONFIG_CHELSIO_T4_DCB
666 struct port_info *pi = netdev_priv(dev);
667
668 return pi->dcb.state == CXGB4_DCB_STATE_FW_ALLSYNCED;
669#else
670 return 0;
671#endif
672}
673EXPORT_SYMBOL(cxgb4_dcb_enabled);
674
675#ifdef CONFIG_CHELSIO_T4_DCB
676/* Handle a Data Center Bridging update message from the firmware. */
677static void dcb_rpl(struct adapter *adap, const struct fw_port_cmd *pcmd)
678{
679 int port = FW_PORT_CMD_PORTID_GET(ntohl(pcmd->op_to_portid));
680 struct net_device *dev = adap->port[port];
681 int old_dcb_enabled = cxgb4_dcb_enabled(dev);
682 int new_dcb_enabled;
683
684 cxgb4_dcb_handle_fw_update(adap, pcmd);
685 new_dcb_enabled = cxgb4_dcb_enabled(dev);
686
687 /* If the DCB has become enabled or disabled on the port then we're
688 * going to need to set up/tear down DCB Priority parameters for the
689 * TX Queues associated with the port.
690 */
691 if (new_dcb_enabled != old_dcb_enabled)
692 dcb_tx_queue_prio_enable(dev, new_dcb_enabled);
693}
694#endif /* CONFIG_CHELSIO_T4_DCB */
695
608/* Clear a filter and release any of its resources that we own. This also 696/* Clear a filter and release any of its resources that we own. This also
609 * clears the filter's "pending" status. 697 * clears the filter's "pending" status.
610 */ 698 */
@@ -709,8 +797,32 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp,
709 } else if (opcode == CPL_FW6_MSG || opcode == CPL_FW4_MSG) { 797 } else if (opcode == CPL_FW6_MSG || opcode == CPL_FW4_MSG) {
710 const struct cpl_fw6_msg *p = (void *)rsp; 798 const struct cpl_fw6_msg *p = (void *)rsp;
711 799
712 if (p->type == 0) 800#ifdef CONFIG_CHELSIO_T4_DCB
713 t4_handle_fw_rpl(q->adap, p->data); 801 const struct fw_port_cmd *pcmd = (const void *)p->data;
802 unsigned int cmd = FW_CMD_OP_GET(ntohl(pcmd->op_to_portid));
803 unsigned int action =
804 FW_PORT_CMD_ACTION_GET(ntohl(pcmd->action_to_len16));
805
806 if (cmd == FW_PORT_CMD &&
807 action == FW_PORT_ACTION_GET_PORT_INFO) {
808 int port = FW_PORT_CMD_PORTID_GET(
809 be32_to_cpu(pcmd->op_to_portid));
810 struct net_device *dev = q->adap->port[port];
811 int state_input = ((pcmd->u.info.dcbxdis_pkd &
812 FW_PORT_CMD_DCBXDIS)
813 ? CXGB4_DCB_INPUT_FW_DISABLED
814 : CXGB4_DCB_INPUT_FW_ENABLED);
815
816 cxgb4_dcb_state_fsm(dev, state_input);
817 }
818
819 if (cmd == FW_PORT_CMD &&
820 action == FW_PORT_ACTION_L2_DCB_CFG)
821 dcb_rpl(q->adap, pcmd);
822 else
823#endif
824 if (p->type == 0)
825 t4_handle_fw_rpl(q->adap, p->data);
714 } else if (opcode == CPL_L2T_WRITE_RPL) { 826 } else if (opcode == CPL_L2T_WRITE_RPL) {
715 const struct cpl_l2t_write_rpl *p = (void *)rsp; 827 const struct cpl_l2t_write_rpl *p = (void *)rsp;
716 828
@@ -1290,6 +1402,48 @@ static int del_filter_wr(struct adapter *adapter, int fidx)
1290 return 0; 1402 return 0;
1291} 1403}
1292 1404
1405static u16 cxgb_select_queue(struct net_device *dev, struct sk_buff *skb,
1406 void *accel_priv, select_queue_fallback_t fallback)
1407{
1408 int txq;
1409
1410#ifdef CONFIG_CHELSIO_T4_DCB
1411 /* If a Data Center Bridging has been successfully negotiated on this
1412 * link then we'll use the skb's priority to map it to a TX Queue.
1413 * The skb's priority is determined via the VLAN Tag Priority Code
1414 * Point field.
1415 */
1416 if (cxgb4_dcb_enabled(dev)) {
1417 u16 vlan_tci;
1418 int err;
1419
1420 err = vlan_get_tag(skb, &vlan_tci);
1421 if (unlikely(err)) {
1422 if (net_ratelimit())
1423 netdev_warn(dev,
1424 "TX Packet without VLAN Tag on DCB Link\n");
1425 txq = 0;
1426 } else {
1427 txq = (vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
1428 }
1429 return txq;
1430 }
1431#endif /* CONFIG_CHELSIO_T4_DCB */
1432
1433 if (select_queue) {
1434 txq = (skb_rx_queue_recorded(skb)
1435 ? skb_get_rx_queue(skb)
1436 : smp_processor_id());
1437
1438 while (unlikely(txq >= dev->real_num_tx_queues))
1439 txq -= dev->real_num_tx_queues;
1440
1441 return txq;
1442 }
1443
1444 return fallback(dev, skb) % dev->real_num_tx_queues;
1445}
1446
1293static inline int is_offload(const struct adapter *adap) 1447static inline int is_offload(const struct adapter *adap)
1294{ 1448{
1295 return adap->params.offload; 1449 return adap->params.offload;
@@ -4601,6 +4755,7 @@ static const struct net_device_ops cxgb4_netdev_ops = {
4601 .ndo_open = cxgb_open, 4755 .ndo_open = cxgb_open,
4602 .ndo_stop = cxgb_close, 4756 .ndo_stop = cxgb_close,
4603 .ndo_start_xmit = t4_eth_xmit, 4757 .ndo_start_xmit = t4_eth_xmit,
4758 .ndo_select_queue = cxgb_select_queue,
4604 .ndo_get_stats64 = cxgb_get_stats, 4759 .ndo_get_stats64 = cxgb_get_stats,
4605 .ndo_set_rx_mode = cxgb_set_rxmode, 4760 .ndo_set_rx_mode = cxgb_set_rxmode,
4606 .ndo_set_mac_address = cxgb_set_mac_addr, 4761 .ndo_set_mac_address = cxgb_set_mac_addr,
@@ -5841,12 +5996,33 @@ static inline void init_rspq(struct adapter *adap, struct sge_rspq *q,
5841static void cfg_queues(struct adapter *adap) 5996static void cfg_queues(struct adapter *adap)
5842{ 5997{
5843 struct sge *s = &adap->sge; 5998 struct sge *s = &adap->sge;
5844 int i, q10g = 0, n10g = 0, qidx = 0; 5999 int i, n10g = 0, qidx = 0;
6000#ifndef CONFIG_CHELSIO_T4_DCB
6001 int q10g = 0;
6002#endif
5845 int ciq_size; 6003 int ciq_size;
5846 6004
5847 for_each_port(adap, i) 6005 for_each_port(adap, i)
5848 n10g += is_x_10g_port(&adap2pinfo(adap, i)->link_cfg); 6006 n10g += is_x_10g_port(&adap2pinfo(adap, i)->link_cfg);
6007#ifdef CONFIG_CHELSIO_T4_DCB
6008 /* For Data Center Bridging support we need to be able to support up
6009 * to 8 Traffic Priorities; each of which will be assigned to its
6010 * own TX Queue in order to prevent Head-Of-Line Blocking.
6011 */
6012 if (adap->params.nports * 8 > MAX_ETH_QSETS) {
6013 dev_err(adap->pdev_dev, "MAX_ETH_QSETS=%d < %d!\n",
6014 MAX_ETH_QSETS, adap->params.nports * 8);
6015 BUG_ON(1);
6016 }
5849 6017
6018 for_each_port(adap, i) {
6019 struct port_info *pi = adap2pinfo(adap, i);
6020
6021 pi->first_qset = qidx;
6022 pi->nqsets = 8;
6023 qidx += pi->nqsets;
6024 }
6025#else /* !CONFIG_CHELSIO_T4_DCB */
5850 /* 6026 /*
5851 * We default to 1 queue per non-10G port and up to # of cores queues 6027 * We default to 1 queue per non-10G port and up to # of cores queues
5852 * per 10G port. 6028 * per 10G port.
@@ -5863,6 +6039,7 @@ static void cfg_queues(struct adapter *adap)
5863 pi->nqsets = is_x_10g_port(&pi->link_cfg) ? q10g : 1; 6039 pi->nqsets = is_x_10g_port(&pi->link_cfg) ? q10g : 1;
5864 qidx += pi->nqsets; 6040 qidx += pi->nqsets;
5865 } 6041 }
6042#endif /* !CONFIG_CHELSIO_T4_DCB */
5866 6043
5867 s->ethqsets = qidx; 6044 s->ethqsets = qidx;
5868 s->max_ethqsets = qidx; /* MSI-X may lower it later */ 6045 s->max_ethqsets = qidx; /* MSI-X may lower it later */
@@ -5981,8 +6158,14 @@ static int enable_msix(struct adapter *adap)
5981 /* need nchan for each possible ULD */ 6158 /* need nchan for each possible ULD */
5982 ofld_need = 3 * nchan; 6159 ofld_need = 3 * nchan;
5983 } 6160 }
6161#ifdef CONFIG_CHELSIO_T4_DCB
6162 /* For Data Center Bridging we need 8 Ethernet TX Priority Queues for
6163 * each port.
6164 */
6165 need = 8 * adap->params.nports + EXTRA_VECS + ofld_need;
6166#else
5984 need = adap->params.nports + EXTRA_VECS + ofld_need; 6167 need = adap->params.nports + EXTRA_VECS + ofld_need;
5985 6168#endif
5986 want = pci_enable_msix_range(adap->pdev, entries, need, want); 6169 want = pci_enable_msix_range(adap->pdev, entries, need, want);
5987 if (want < 0) 6170 if (want < 0)
5988 return want; 6171 return want;
@@ -6245,6 +6428,10 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
6245 netdev->priv_flags |= IFF_UNICAST_FLT; 6428 netdev->priv_flags |= IFF_UNICAST_FLT;
6246 6429
6247 netdev->netdev_ops = &cxgb4_netdev_ops; 6430 netdev->netdev_ops = &cxgb4_netdev_ops;
6431#ifdef CONFIG_CHELSIO_T4_DCB
6432 netdev->dcbnl_ops = &cxgb4_dcb_ops;
6433 cxgb4_dcb_state_init(netdev);
6434#endif
6248 netdev->ethtool_ops = &cxgb_ethtool_ops; 6435 netdev->ethtool_ops = &cxgb_ethtool_ops;
6249 } 6436 }
6250 6437
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index 55e9daf7f9d4..d719decbfb28 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * This file is part of the Chelsio T4 Ethernet driver for Linux. 2 * This file is part of the Chelsio T4 Ethernet driver for Linux.
3 * 3 *
4 * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved. 4 * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
5 * 5 *
6 * This software is available to you under a choice of one of two 6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU 7 * licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.c b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
index 8a96572fdde0..96041397ee15 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/l2t.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * This file is part of the Chelsio T4 Ethernet driver for Linux. 2 * This file is part of the Chelsio T4 Ethernet driver for Linux.
3 * 3 *
4 * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved. 4 * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
5 * 5 *
6 * This software is available to you under a choice of one of two 6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU 7 * licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.h b/drivers/net/ethernet/chelsio/cxgb4/l2t.h
index 85eb5c71358d..a30126ce90cb 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/l2t.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * This file is part of the Chelsio T4 Ethernet driver for Linux. 2 * This file is part of the Chelsio T4 Ethernet driver for Linux.
3 * 3 *
4 * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved. 4 * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
5 * 5 *
6 * This software is available to you under a choice of one of two 6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU 7 * licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index dd4355d248e4..8bae1aa744a7 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * This file is part of the Chelsio T4 Ethernet driver for Linux. 2 * This file is part of the Chelsio T4 Ethernet driver for Linux.
3 * 3 *
4 * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved. 4 * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
5 * 5 *
6 * This software is available to you under a choice of one of two 6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU 7 * licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index bba67681aeaa..6665cd410f2a 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * This file is part of the Chelsio T4 Ethernet driver for Linux. 2 * This file is part of the Chelsio T4 Ethernet driver for Linux.
3 * 3 *
4 * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved. 4 * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
5 * 5 *
6 * This software is available to you under a choice of one of two 6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU 7 * licenses. You may choose to be licensed under the terms of the GNU
@@ -3175,6 +3175,46 @@ int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
3175} 3175}
3176 3176
3177/** 3177/**
3178 * t4_set_params_nosleep - sets FW or device parameters
3179 * @adap: the adapter
3180 * @mbox: mailbox to use for the FW command
3181 * @pf: the PF
3182 * @vf: the VF
3183 * @nparams: the number of parameters
3184 * @params: the parameter names
3185 * @val: the parameter values
3186 *
3187 * Does not ever sleep
3188 * Sets the value of FW or device parameters. Up to 7 parameters can be
3189 * specified at once.
3190 */
3191int t4_set_params_nosleep(struct adapter *adap, unsigned int mbox,
3192 unsigned int pf, unsigned int vf,
3193 unsigned int nparams, const u32 *params,
3194 const u32 *val)
3195{
3196 struct fw_params_cmd c;
3197 __be32 *p = &c.param[0].mnem;
3198
3199 if (nparams > 7)
3200 return -EINVAL;
3201
3202 memset(&c, 0, sizeof(c));
3203 c.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_PARAMS_CMD) |
3204 FW_CMD_REQUEST | FW_CMD_WRITE |
3205 FW_PARAMS_CMD_PFN(pf) |
3206 FW_PARAMS_CMD_VFN(vf));
3207 c.retval_len16 = cpu_to_be32(FW_LEN16(c));
3208
3209 while (nparams--) {
3210 *p++ = cpu_to_be32(*params++);
3211 *p++ = cpu_to_be32(*val++);
3212 }
3213
3214 return t4_wr_mbox_ns(adap, mbox, &c, sizeof(c), NULL);
3215}
3216
3217/**
3178 * t4_set_params - sets FW or device parameters 3218 * t4_set_params - sets FW or device parameters
3179 * @adap: the adapter 3219 * @adap: the adapter
3180 * @mbox: mailbox to use for the FW command 3220 * @mbox: mailbox to use for the FW command
@@ -3499,6 +3539,33 @@ int t4_set_addr_hash(struct adapter *adap, unsigned int mbox, unsigned int viid,
3499} 3539}
3500 3540
3501/** 3541/**
3542 * t4_enable_vi_params - enable/disable a virtual interface
3543 * @adap: the adapter
3544 * @mbox: mailbox to use for the FW command
3545 * @viid: the VI id
3546 * @rx_en: 1=enable Rx, 0=disable Rx
3547 * @tx_en: 1=enable Tx, 0=disable Tx
3548 * @dcb_en: 1=enable delivery of Data Center Bridging messages.
3549 *
3550 * Enables/disables a virtual interface. Note that setting DCB Enable
3551 * only makes sense when enabling a Virtual Interface ...
3552 */
3553int t4_enable_vi_params(struct adapter *adap, unsigned int mbox,
3554 unsigned int viid, bool rx_en, bool tx_en, bool dcb_en)
3555{
3556 struct fw_vi_enable_cmd c;
3557
3558 memset(&c, 0, sizeof(c));
3559 c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST |
3560 FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid));
3561
3562 c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_IEN(rx_en) |
3563 FW_VI_ENABLE_CMD_EEN(tx_en) | FW_LEN16(c) |
3564 FW_VI_ENABLE_CMD_DCB_INFO(dcb_en));
3565 return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
3566}
3567
3568/**
3502 * t4_enable_vi - enable/disable a virtual interface 3569 * t4_enable_vi - enable/disable a virtual interface
3503 * @adap: the adapter 3570 * @adap: the adapter
3504 * @mbox: mailbox to use for the FW command 3571 * @mbox: mailbox to use for the FW command
@@ -3511,14 +3578,7 @@ int t4_set_addr_hash(struct adapter *adap, unsigned int mbox, unsigned int viid,
3511int t4_enable_vi(struct adapter *adap, unsigned int mbox, unsigned int viid, 3578int t4_enable_vi(struct adapter *adap, unsigned int mbox, unsigned int viid,
3512 bool rx_en, bool tx_en) 3579 bool rx_en, bool tx_en)
3513{ 3580{
3514 struct fw_vi_enable_cmd c; 3581 return t4_enable_vi_params(adap, mbox, viid, rx_en, tx_en, 0);
3515
3516 memset(&c, 0, sizeof(c));
3517 c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST |
3518 FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid));
3519 c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_IEN(rx_en) |
3520 FW_VI_ENABLE_CMD_EEN(tx_en) | FW_LEN16(c));
3521 return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
3522} 3582}
3523 3583
3524/** 3584/**
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
index 71b799b5b0f4..35e3d8e32881 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * This file is part of the Chelsio T4 Ethernet driver for Linux. 2 * This file is part of the Chelsio T4 Ethernet driver for Linux.
3 * 3 *
4 * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved. 4 * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
5 * 5 *
6 * This software is available to you under a choice of one of two 6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU 7 * licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
index 973eb11aa98a..abb45809c0c8 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * This file is part of the Chelsio T4 Ethernet driver for Linux. 2 * This file is part of the Chelsio T4 Ethernet driver for Linux.
3 * 3 *
4 * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved. 4 * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
5 * 5 *
6 * This software is available to you under a choice of one of two 6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU 7 * licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
index 225ad8a5722d..3360025ad922 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * This file is part of the Chelsio T4 Ethernet driver for Linux. 2 * This file is part of the Chelsio T4 Ethernet driver for Linux.
3 * 3 *
4 * Copyright (c) 2010 Chelsio Communications, Inc. All rights reserved. 4 * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
5 * 5 *
6 * This software is available to you under a choice of one of two 6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU 7 * licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
index 9cc973fbcf26..4a6ae4db7397 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * This file is part of the Chelsio T4 Ethernet driver for Linux. 2 * This file is part of the Chelsio T4 Ethernet driver for Linux.
3 * 3 *
4 * Copyright (c) 2009-2010 Chelsio Communications, Inc. All rights reserved. 4 * Copyright (c) 2009-2014 Chelsio Communications, Inc. All rights reserved.
5 * 5 *
6 * This software is available to you under a choice of one of two 6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU 7 * licenses. You may choose to be licensed under the terms of the GNU
@@ -46,9 +46,11 @@ enum fw_retval {
46 FW_EFAULT = 14, /* bad address; fw bad */ 46 FW_EFAULT = 14, /* bad address; fw bad */
47 FW_EBUSY = 16, /* resource busy */ 47 FW_EBUSY = 16, /* resource busy */
48 FW_EEXIST = 17, /* file exists */ 48 FW_EEXIST = 17, /* file exists */
49 FW_ENODEV = 19, /* no such device */
49 FW_EINVAL = 22, /* invalid argument */ 50 FW_EINVAL = 22, /* invalid argument */
50 FW_ENOSPC = 28, /* no space left on device */ 51 FW_ENOSPC = 28, /* no space left on device */
51 FW_ENOSYS = 38, /* functionality not implemented */ 52 FW_ENOSYS = 38, /* functionality not implemented */
53 FW_ENODATA = 61, /* no data available */
52 FW_EPROTO = 71, /* protocol error */ 54 FW_EPROTO = 71, /* protocol error */
53 FW_EADDRINUSE = 98, /* address already in use */ 55 FW_EADDRINUSE = 98, /* address already in use */
54 FW_EADDRNOTAVAIL = 99, /* cannot assigned requested address */ 56 FW_EADDRNOTAVAIL = 99, /* cannot assigned requested address */
@@ -989,6 +991,7 @@ enum fw_params_param_dmaq {
989 FW_PARAMS_PARAM_DMAQ_EQ_CMPLIQID_MNGT = 0x10, 991 FW_PARAMS_PARAM_DMAQ_EQ_CMPLIQID_MNGT = 0x10,
990 FW_PARAMS_PARAM_DMAQ_EQ_CMPLIQID_CTRL = 0x11, 992 FW_PARAMS_PARAM_DMAQ_EQ_CMPLIQID_CTRL = 0x11,
991 FW_PARAMS_PARAM_DMAQ_EQ_SCHEDCLASS_ETH = 0x12, 993 FW_PARAMS_PARAM_DMAQ_EQ_SCHEDCLASS_ETH = 0x12,
994 FW_PARAMS_PARAM_DMAQ_EQ_DCBPRIO_ETH = 0x13,
992}; 995};
993 996
994#define FW_PARAMS_MNEM(x) ((x) << 24) 997#define FW_PARAMS_MNEM(x) ((x) << 24)
@@ -1422,6 +1425,7 @@ struct fw_vi_enable_cmd {
1422#define FW_VI_ENABLE_CMD_VIID(x) ((x) << 0) 1425#define FW_VI_ENABLE_CMD_VIID(x) ((x) << 0)
1423#define FW_VI_ENABLE_CMD_IEN(x) ((x) << 31) 1426#define FW_VI_ENABLE_CMD_IEN(x) ((x) << 31)
1424#define FW_VI_ENABLE_CMD_EEN(x) ((x) << 30) 1427#define FW_VI_ENABLE_CMD_EEN(x) ((x) << 30)
1428#define FW_VI_ENABLE_CMD_DCB_INFO(x) ((x) << 28)
1425#define FW_VI_ENABLE_CMD_LED (1U << 29) 1429#define FW_VI_ENABLE_CMD_LED (1U << 29)
1426 1430
1427/* VI VF stats offset definitions */ 1431/* VI VF stats offset definitions */
@@ -1594,6 +1598,9 @@ enum fw_port_action {
1594 FW_PORT_ACTION_GET_PORT_INFO = 0x0003, 1598 FW_PORT_ACTION_GET_PORT_INFO = 0x0003,
1595 FW_PORT_ACTION_L2_PPP_CFG = 0x0004, 1599 FW_PORT_ACTION_L2_PPP_CFG = 0x0004,
1596 FW_PORT_ACTION_L2_DCB_CFG = 0x0005, 1600 FW_PORT_ACTION_L2_DCB_CFG = 0x0005,
1601 FW_PORT_ACTION_DCB_READ_TRANS = 0x0006,
1602 FW_PORT_ACTION_DCB_READ_RECV = 0x0007,
1603 FW_PORT_ACTION_DCB_READ_DET = 0x0008,
1597 FW_PORT_ACTION_LOW_PWR_TO_NORMAL = 0x0010, 1604 FW_PORT_ACTION_LOW_PWR_TO_NORMAL = 0x0010,
1598 FW_PORT_ACTION_L1_LOW_PWR_EN = 0x0011, 1605 FW_PORT_ACTION_L1_LOW_PWR_EN = 0x0011,
1599 FW_PORT_ACTION_L2_WOL_MODE_EN = 0x0012, 1606 FW_PORT_ACTION_L2_WOL_MODE_EN = 0x0012,
@@ -1637,6 +1644,14 @@ enum fw_port_dcb_type {
1637 FW_PORT_DCB_TYPE_PRIORATE = 0x02, 1644 FW_PORT_DCB_TYPE_PRIORATE = 0x02,
1638 FW_PORT_DCB_TYPE_PFC = 0x03, 1645 FW_PORT_DCB_TYPE_PFC = 0x03,
1639 FW_PORT_DCB_TYPE_APP_ID = 0x04, 1646 FW_PORT_DCB_TYPE_APP_ID = 0x04,
1647 FW_PORT_DCB_TYPE_CONTROL = 0x05,
1648};
1649
1650enum fw_port_dcb_feature_state {
1651 FW_PORT_DCB_FEATURE_STATE_PENDING = 0x0,
1652 FW_PORT_DCB_FEATURE_STATE_SUCCESS = 0x1,
1653 FW_PORT_DCB_FEATURE_STATE_ERROR = 0x2,
1654 FW_PORT_DCB_FEATURE_STATE_TIMEOUT = 0x3,
1640}; 1655};
1641 1656
1642struct fw_port_cmd { 1657struct fw_port_cmd {
@@ -1648,9 +1663,11 @@ struct fw_port_cmd {
1648 __be32 r; 1663 __be32 r;
1649 } l1cfg; 1664 } l1cfg;
1650 struct fw_port_l2cfg { 1665 struct fw_port_l2cfg {
1651 __be16 ctlbf_to_ivlan0; 1666 __u8 ctlbf;
1667 __u8 ovlan3_to_ivlan0;
1652 __be16 ivlantype; 1668 __be16 ivlantype;
1653 __be32 txipg_pkd; 1669 __be16 txipg_force_pinfo;
1670 __be16 mtu;
1654 __be16 ovlan0mask; 1671 __be16 ovlan0mask;
1655 __be16 ovlan0type; 1672 __be16 ovlan0type;
1656 __be16 ovlan1mask; 1673 __be16 ovlan1mask;
@@ -1666,24 +1683,60 @@ struct fw_port_cmd {
1666 __be16 acap; 1683 __be16 acap;
1667 __be16 mtu; 1684 __be16 mtu;
1668 __u8 cbllen; 1685 __u8 cbllen;
1669 __u8 r9; 1686 __u8 auxlinfo;
1670 __be32 r10; 1687 __u8 dcbxdis_pkd;
1671 __be64 r11; 1688 __u8 r8_lo[3];
1689 __be64 r9;
1672 } info; 1690 } info;
1673 struct fw_port_ppp { 1691 struct fw_port_diags {
1674 __be32 pppen_to_ncsich; 1692 __u8 diagop;
1675 __be32 r11; 1693 __u8 r[3];
1676 } ppp; 1694 __be32 diagval;
1677 struct fw_port_dcb { 1695 } diags;
1678 __be16 cfg; 1696 union fw_port_dcb {
1679 u8 up_map; 1697 struct fw_port_dcb_pgid {
1680 u8 sf_cfgrc; 1698 __u8 type;
1681 __be16 prot_ix; 1699 __u8 apply_pkd;
1682 u8 pe7_to_pe0; 1700 __u8 r10_lo[2];
1683 u8 numTCPFCs; 1701 __be32 pgid;
1684 __be32 pgid0_to_pgid7; 1702 __be64 r11;
1685 __be32 numTCs_oui; 1703 } pgid;
1686 u8 pgpc[8]; 1704 struct fw_port_dcb_pgrate {
1705 __u8 type;
1706 __u8 apply_pkd;
1707 __u8 r10_lo[5];
1708 __u8 num_tcs_supported;
1709 __u8 pgrate[8];
1710 } pgrate;
1711 struct fw_port_dcb_priorate {
1712 __u8 type;
1713 __u8 apply_pkd;
1714 __u8 r10_lo[6];
1715 __u8 strict_priorate[8];
1716 } priorate;
1717 struct fw_port_dcb_pfc {
1718 __u8 type;
1719 __u8 pfcen;
1720 __u8 r10[5];
1721 __u8 max_pfc_tcs;
1722 __be64 r11;
1723 } pfc;
1724 struct fw_port_app_priority {
1725 __u8 type;
1726 __u8 r10[2];
1727 __u8 idx;
1728 __u8 user_prio_map;
1729 __u8 sel_field;
1730 __be16 protocolid;
1731 __be64 r12;
1732 } app_priority;
1733 struct fw_port_dcb_control {
1734 __u8 type;
1735 __u8 all_syncd_pkd;
1736 __be16 pfc_state_to_app_state;
1737 __be32 r11;
1738 __be64 r12;
1739 } control;
1687 } dcb; 1740 } dcb;
1688 } u; 1741 } u;
1689}; 1742};
@@ -1720,6 +1773,10 @@ struct fw_port_cmd {
1720#define FW_PORT_CMD_MODTYPE_MASK 0x1f 1773#define FW_PORT_CMD_MODTYPE_MASK 0x1f
1721#define FW_PORT_CMD_MODTYPE_GET(x) (((x) >> 0) & FW_PORT_CMD_MODTYPE_MASK) 1774#define FW_PORT_CMD_MODTYPE_GET(x) (((x) >> 0) & FW_PORT_CMD_MODTYPE_MASK)
1722 1775
1776#define FW_PORT_CMD_DCBXDIS (1U << 7)
1777#define FW_PORT_CMD_APPLY (1U << 7)
1778#define FW_PORT_CMD_ALL_SYNCD (1U << 7)
1779
1723#define FW_PORT_CMD_PPPEN(x) ((x) << 31) 1780#define FW_PORT_CMD_PPPEN(x) ((x) << 31)
1724#define FW_PORT_CMD_TPSRC(x) ((x) << 28) 1781#define FW_PORT_CMD_TPSRC(x) ((x) << 28)
1725#define FW_PORT_CMD_NCSISRC(x) ((x) << 24) 1782#define FW_PORT_CMD_NCSISRC(x) ((x) << 24)