]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.drivers/open-fcoe-dcb-support
Fix oinkmaster patch.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.drivers / open-fcoe-dcb-support
CommitLineData
2cb7cef9
BS
1From: Hannes Reinecke <hare@suse.de>
2Date: Wed, 17 Sep 2008 16:49:40 +0200
3Subject: FCoE: Add DCB support
4References: FATE#303913
5
6Signed-off-by: Hannes Reinecke <hare@suse.de>
7---
8 drivers/net/ixgbe/Makefile | 3
9 drivers/net/ixgbe/ixgbe.h | 26
10 drivers/net/ixgbe/ixgbe_dcb.c | 332 ++++++++++
11 drivers/net/ixgbe/ixgbe_dcb.h | 189 ++++++
12 drivers/net/ixgbe/ixgbe_dcb_82598.c | 398 +++++++++++++
13 drivers/net/ixgbe/ixgbe_dcb_82598.h | 98 +++
14 drivers/net/ixgbe/ixgbe_dcb_nl.c | 611 ++++++++++++++++++++
15 drivers/net/ixgbe/ixgbe_ethtool.c | 37 +
16 drivers/net/ixgbe/ixgbe_main.c | 192 +++++-
17 include/linux/dcbnl.h | 324 ++++++++++
18 include/linux/netdevice.h | 8
19 include/linux/rtnetlink.h | 5
20 include/net/dcbnl.h | 40 +
21 net/Kconfig | 1
22 net/Makefile | 3
23 net/dcb/Kconfig | 12
24 net/dcb/Makefile | 1
25 net/dcb/dcbnl.c | 1091 ++++++++++++++++++++++++++++++++++++
26 18 files changed, 3349 insertions(+), 22 deletions(-)
27 create mode 100644 drivers/net/ixgbe/ixgbe_dcb.c
28 create mode 100644 drivers/net/ixgbe/ixgbe_dcb.h
29 create mode 100644 drivers/net/ixgbe/ixgbe_dcb_82598.c
30 create mode 100644 drivers/net/ixgbe/ixgbe_dcb_82598.h
31 create mode 100644 drivers/net/ixgbe/ixgbe_dcb_nl.c
32 create mode 100644 include/linux/dcbnl.h
33 create mode 100644 include/net/dcbnl.h
34 create mode 100644 net/dcb/Kconfig
35 create mode 100644 net/dcb/Makefile
36 create mode 100644 net/dcb/dcbnl.c
37
38--- /dev/null
39+++ b/drivers/net/ixgbe/ixgbe_dcb_82598.c
40@@ -0,0 +1,398 @@
41+/*******************************************************************************
42+
43+ Intel 10 Gigabit PCI Express Linux driver
44+ Copyright(c) 1999 - 2007 Intel Corporation.
45+
46+ This program is free software; you can redistribute it and/or modify it
47+ under the terms and conditions of the GNU General Public License,
48+ version 2, as published by the Free Software Foundation.
49+
50+ This program is distributed in the hope it will be useful, but WITHOUT
51+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
52+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
53+ more details.
54+
55+ You should have received a copy of the GNU General Public License along with
56+ this program; if not, write to the Free Software Foundation, Inc.,
57+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
58+
59+ The full GNU General Public License is included in this distribution in
60+ the file called "COPYING".
61+
62+ Contact Information:
63+ Linux NICS <linux.nics@intel.com>
64+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
65+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
66+
67+*******************************************************************************/
68+
69+#include "ixgbe.h"
70+#include "ixgbe_type.h"
71+#include "ixgbe_dcb.h"
72+#include "ixgbe_dcb_82598.h"
73+
74+/**
75+ * ixgbe_dcb_get_tc_stats_82598 - Return status data for each traffic class
76+ * @hw: pointer to hardware structure
77+ * @stats: pointer to statistics structure
78+ * @tc_count: Number of elements in bwg_array.
79+ *
80+ * This function returns the status data for each of the Traffic Classes in use.
81+ */
82+s32 ixgbe_dcb_get_tc_stats_82598(struct ixgbe_hw *hw,
83+ struct ixgbe_hw_stats *stats,
84+ u8 tc_count)
85+{
86+ int tc;
87+
88+ if (tc_count > MAX_TRAFFIC_CLASS)
89+ return DCB_ERR_PARAM;
90+
91+ /* Statistics pertaining to each traffic class */
92+ for (tc = 0; tc < tc_count; tc++) {
93+ /* Transmitted Packets */
94+ stats->qptc[tc] += IXGBE_READ_REG(hw, IXGBE_QPTC(tc));
95+ /* Transmitted Bytes */
96+ stats->qbtc[tc] += IXGBE_READ_REG(hw, IXGBE_QBTC(tc));
97+ /* Received Packets */
98+ stats->qprc[tc] += IXGBE_READ_REG(hw, IXGBE_QPRC(tc));
99+ /* Received Bytes */
100+ stats->qbrc[tc] += IXGBE_READ_REG(hw, IXGBE_QBRC(tc));
101+ }
102+
103+ return 0;
104+}
105+
106+/**
107+ * ixgbe_dcb_get_pfc_stats_82598 - Returns CBFC status data
108+ * @hw: pointer to hardware structure
109+ * @stats: pointer to statistics structure
110+ * @tc_count: Number of elements in bwg_array.
111+ *
112+ * This function returns the CBFC status data for each of the Traffic Classes.
113+ */
114+s32 ixgbe_dcb_get_pfc_stats_82598(struct ixgbe_hw *hw,
115+ struct ixgbe_hw_stats *stats,
116+ u8 tc_count)
117+{
118+ int tc;
119+
120+ if (tc_count > MAX_TRAFFIC_CLASS)
121+ return DCB_ERR_PARAM;
122+
123+ for (tc = 0; tc < tc_count; tc++) {
124+ /* Priority XOFF Transmitted */
125+ stats->pxofftxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(tc));
126+ /* Priority XOFF Received */
127+ stats->pxoffrxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(tc));
128+ }
129+
130+ return 0;
131+}
132+
133+/**
134+ * ixgbe_dcb_config_packet_buffers_82598 - Configure packet buffers
135+ * @hw: pointer to hardware structure
136+ * @dcb_config: pointer to ixgbe_dcb_config structure
137+ *
138+ * Configure packet buffers for DCB mode.
139+ */
140+s32 ixgbe_dcb_config_packet_buffers_82598(struct ixgbe_hw *hw,
141+ struct ixgbe_dcb_config *dcb_config)
142+{
143+ s32 ret_val = 0;
144+ u32 value = IXGBE_RXPBSIZE_64KB;
145+ u8 i = 0;
146+
147+ /* Setup Rx packet buffer sizes */
148+ switch (dcb_config->rx_pba_cfg) {
149+ case pba_80_48:
150+ /* Setup the first four at 80KB */
151+ value = IXGBE_RXPBSIZE_80KB;
152+ for (; i < 4; i++)
153+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), value);
154+ /* Setup the last four at 48KB...don't re-init i */
155+ value = IXGBE_RXPBSIZE_48KB;
156+ /* Fall Through */
157+ case pba_equal:
158+ default:
159+ for (; i < IXGBE_MAX_PACKET_BUFFERS; i++)
160+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), value);
161+
162+ /* Setup Tx packet buffer sizes */
163+ for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) {
164+ IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i),
165+ IXGBE_TXPBSIZE_40KB);
166+ }
167+ break;
168+ }
169+
170+ return ret_val;
171+}
172+
173+/**
174+ * ixgbe_dcb_config_rx_arbiter_82598 - Config Rx data arbiter
175+ * @hw: pointer to hardware structure
176+ * @dcb_config: pointer to ixgbe_dcb_config structure
177+ *
178+ * Configure Rx Data Arbiter and credits for each traffic class.
179+ */
180+s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw,
181+ struct ixgbe_dcb_config *dcb_config)
182+{
183+ struct tc_bw_alloc *p;
184+ u32 reg = 0;
185+ u32 credit_refill = 0;
186+ u32 credit_max = 0;
187+ u8 i = 0;
188+
189+ reg = IXGBE_READ_REG(hw, IXGBE_RUPPBMR) | IXGBE_RUPPBMR_MQA;
190+ IXGBE_WRITE_REG(hw, IXGBE_RUPPBMR, reg);
191+
192+ reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
193+ /* Enable Arbiter */
194+ reg &= ~IXGBE_RMCS_ARBDIS;
195+ /* Enable Receive Recycle within the BWG */
196+ reg |= IXGBE_RMCS_RRM;
197+ /* Enable Deficit Fixed Priority arbitration*/
198+ reg |= IXGBE_RMCS_DFP;
199+
200+ IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg);
201+
202+ /* Configure traffic class credits and priority */
203+ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
204+ p = &dcb_config->tc_config[i].path[DCB_RX_CONFIG];
205+ credit_refill = p->data_credits_refill;
206+ credit_max = p->data_credits_max;
207+
208+ reg = credit_refill | (credit_max << IXGBE_RT2CR_MCL_SHIFT);
209+
210+ if (p->prio_type == prio_link)
211+ reg |= IXGBE_RT2CR_LSP;
212+
213+ IXGBE_WRITE_REG(hw, IXGBE_RT2CR(i), reg);
214+ }
215+
216+ reg = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
217+ reg |= IXGBE_RDRXCTL_RDMTS_1_2;
218+ reg |= IXGBE_RDRXCTL_MPBEN;
219+ reg |= IXGBE_RDRXCTL_MCEN;
220+ IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, reg);
221+
222+ reg = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
223+ /* Make sure there is enough descriptors before arbitration */
224+ reg &= ~IXGBE_RXCTRL_DMBYPS;
225+ IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg);
226+
227+ return 0;
228+}
229+
230+/**
231+ * ixgbe_dcb_config_tx_desc_arbiter_82598 - Config Tx Desc. arbiter
232+ * @hw: pointer to hardware structure
233+ * @dcb_config: pointer to ixgbe_dcb_config structure
234+ *
235+ * Configure Tx Descriptor Arbiter and credits for each traffic class.
236+ */
237+s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw,
238+ struct ixgbe_dcb_config *dcb_config)
239+{
240+ struct tc_bw_alloc *p;
241+ u32 reg, max_credits;
242+ u8 i;
243+
244+ reg = IXGBE_READ_REG(hw, IXGBE_DPMCS);
245+
246+ /* Enable arbiter */
247+ reg &= ~IXGBE_DPMCS_ARBDIS;
248+ if (!(dcb_config->round_robin_enable)) {
249+ /* Enable DFP and Recycle mode */
250+ reg |= (IXGBE_DPMCS_TDPAC | IXGBE_DPMCS_TRM);
251+ }
252+ reg |= IXGBE_DPMCS_TSOEF;
253+ /* Configure Max TSO packet size 34KB including payload and headers */
254+ reg |= (0x4 << IXGBE_DPMCS_MTSOS_SHIFT);
255+
256+ IXGBE_WRITE_REG(hw, IXGBE_DPMCS, reg);
257+
258+ /* Configure traffic class credits and priority */
259+ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
260+ p = &dcb_config->tc_config[i].path[DCB_TX_CONFIG];
261+ max_credits = dcb_config->tc_config[i].desc_credits_max;
262+ reg = max_credits << IXGBE_TDTQ2TCCR_MCL_SHIFT;
263+ reg |= p->data_credits_refill;
264+ reg |= (u32)(p->bwg_id) << IXGBE_TDTQ2TCCR_BWG_SHIFT;
265+
266+ if (p->prio_type == prio_group)
267+ reg |= IXGBE_TDTQ2TCCR_GSP;
268+
269+ if (p->prio_type == prio_link)
270+ reg |= IXGBE_TDTQ2TCCR_LSP;
271+
272+ IXGBE_WRITE_REG(hw, IXGBE_TDTQ2TCCR(i), reg);
273+ }
274+
275+ return 0;
276+}
277+
278+/**
279+ * ixgbe_dcb_config_tx_data_arbiter_82598 - Config Tx data arbiter
280+ * @hw: pointer to hardware structure
281+ * @dcb_config: pointer to ixgbe_dcb_config structure
282+ *
283+ * Configure Tx Data Arbiter and credits for each traffic class.
284+ */
285+s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
286+ struct ixgbe_dcb_config *dcb_config)
287+{
288+ struct tc_bw_alloc *p;
289+ u32 reg;
290+ u8 i;
291+
292+ reg = IXGBE_READ_REG(hw, IXGBE_PDPMCS);
293+ /* Enable Data Plane Arbiter */
294+ reg &= ~IXGBE_PDPMCS_ARBDIS;
295+ /* Enable DFP and Transmit Recycle Mode */
296+ reg |= (IXGBE_PDPMCS_TPPAC | IXGBE_PDPMCS_TRM);
297+
298+ IXGBE_WRITE_REG(hw, IXGBE_PDPMCS, reg);
299+
300+ /* Configure traffic class credits and priority */
301+ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
302+ p = &dcb_config->tc_config[i].path[DCB_TX_CONFIG];
303+ reg = p->data_credits_refill;
304+ reg |= (u32)(p->data_credits_max) << IXGBE_TDPT2TCCR_MCL_SHIFT;
305+ reg |= (u32)(p->bwg_id) << IXGBE_TDPT2TCCR_BWG_SHIFT;
306+
307+ if (p->prio_type == prio_group)
308+ reg |= IXGBE_TDPT2TCCR_GSP;
309+
310+ if (p->prio_type == prio_link)
311+ reg |= IXGBE_TDPT2TCCR_LSP;
312+
313+ IXGBE_WRITE_REG(hw, IXGBE_TDPT2TCCR(i), reg);
314+ }
315+
316+ /* Enable Tx packet buffer division */
317+ reg = IXGBE_READ_REG(hw, IXGBE_DTXCTL);
318+ reg |= IXGBE_DTXCTL_ENDBUBD;
319+ IXGBE_WRITE_REG(hw, IXGBE_DTXCTL, reg);
320+
321+ return 0;
322+}
323+
324+/**
325+ * ixgbe_dcb_config_pfc_82598 - Config priority flow control
326+ * @hw: pointer to hardware structure
327+ * @dcb_config: pointer to ixgbe_dcb_config structure
328+ *
329+ * Configure Priority Flow Control for each traffic class.
330+ */
331+s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw,
332+ struct ixgbe_dcb_config *dcb_config)
333+{
334+ u32 reg, rx_pba_size;
335+ u8 i;
336+
337+ /* Enable Transmit Priority Flow Control */
338+ reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
339+ reg &= ~IXGBE_RMCS_TFCE_802_3X;
340+ /* correct the reporting of our flow control status */
341+ hw->fc.type = ixgbe_fc_none;
342+ reg |= IXGBE_RMCS_TFCE_PRIORITY;
343+ IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg);
344+
345+ /* Enable Receive Priority Flow Control */
346+ reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
347+ reg &= ~IXGBE_FCTRL_RFCE;
348+ reg |= IXGBE_FCTRL_RPFCE;
349+ IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg);
350+
351+ /*
352+ * Configure flow control thresholds and enable priority flow control
353+ * for each traffic class.
354+ */
355+ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
356+ if (dcb_config->rx_pba_cfg == pba_equal) {
357+ rx_pba_size = IXGBE_RXPBSIZE_64KB;
358+ } else {
359+ rx_pba_size = (i < 4) ? IXGBE_RXPBSIZE_80KB
360+ : IXGBE_RXPBSIZE_48KB;
361+ }
362+
363+ reg = ((rx_pba_size >> 5) & 0xFFF0);
364+ if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx ||
365+ dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full)
366+ reg |= IXGBE_FCRTL_XONE;
367+
368+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), reg);
369+
370+ reg = ((rx_pba_size >> 2) & 0xFFF0);
371+ if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx ||
372+ dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full)
373+ reg |= IXGBE_FCRTH_FCEN;
374+
375+ IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), reg);
376+ }
377+
378+ /* Configure pause time */
379+ for (i = 0; i < (MAX_TRAFFIC_CLASS >> 1); i++)
380+ IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), 0x68006800);
381+
382+ /* Configure flow control refresh threshold value */
383+ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, 0x3400);
384+
385+ return 0;
386+}
387+
388+/**
389+ * ixgbe_dcb_config_tc_stats_82598 - Configure traffic class statistics
390+ * @hw: pointer to hardware structure
391+ *
392+ * Configure queue statistics registers, all queues belonging to same traffic
393+ * class uses a single set of queue statistics counters.
394+ */
395+s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw)
396+{
397+ u32 reg = 0;
398+ u8 i = 0;
399+ u8 j = 0;
400+
401+ /* Receive Queues stats setting - 8 queues per statistics reg */
402+ for (i = 0, j = 0; i < 15 && j < 8; i = i + 2, j++) {
403+ reg = IXGBE_READ_REG(hw, IXGBE_RQSMR(i));
404+ reg |= ((0x1010101) * j);
405+ IXGBE_WRITE_REG(hw, IXGBE_RQSMR(i), reg);
406+ reg = IXGBE_READ_REG(hw, IXGBE_RQSMR(i + 1));
407+ reg |= ((0x1010101) * j);
408+ IXGBE_WRITE_REG(hw, IXGBE_RQSMR(i + 1), reg);
409+ }
410+ /* Transmit Queues stats setting - 4 queues per statistics reg */
411+ for (i = 0; i < 8; i++) {
412+ reg = IXGBE_READ_REG(hw, IXGBE_TQSMR(i));
413+ reg |= ((0x1010101) * i);
414+ IXGBE_WRITE_REG(hw, IXGBE_TQSMR(i), reg);
415+ }
416+
417+ return 0;
418+}
419+
420+/**
421+ * ixgbe_dcb_hw_config_82598 - Config and enable DCB
422+ * @hw: pointer to hardware structure
423+ * @dcb_config: pointer to ixgbe_dcb_config structure
424+ *
425+ * Configure dcb settings and enable dcb mode.
426+ */
427+s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw,
428+ struct ixgbe_dcb_config *dcb_config)
429+{
430+ ixgbe_dcb_config_packet_buffers_82598(hw, dcb_config);
431+ ixgbe_dcb_config_rx_arbiter_82598(hw, dcb_config);
432+ ixgbe_dcb_config_tx_desc_arbiter_82598(hw, dcb_config);
433+ ixgbe_dcb_config_tx_data_arbiter_82598(hw, dcb_config);
434+ ixgbe_dcb_config_pfc_82598(hw, dcb_config);
435+ ixgbe_dcb_config_tc_stats_82598(hw);
436+
437+ return 0;
438+}
439--- /dev/null
440+++ b/drivers/net/ixgbe/ixgbe_dcb_82598.h
441@@ -0,0 +1,98 @@
442+/*******************************************************************************
443+
444+ Intel 10 Gigabit PCI Express Linux driver
445+ Copyright(c) 1999 - 2007 Intel Corporation.
446+
447+ This program is free software; you can redistribute it and/or modify it
448+ under the terms and conditions of the GNU General Public License,
449+ version 2, as published by the Free Software Foundation.
450+
451+ This program is distributed in the hope it will be useful, but WITHOUT
452+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
453+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
454+ more details.
455+
456+ You should have received a copy of the GNU General Public License along with
457+ this program; if not, write to the Free Software Foundation, Inc.,
458+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
459+
460+ The full GNU General Public License is included in this distribution in
461+ the file called "COPYING".
462+
463+ Contact Information:
464+ Linux NICS <linux.nics@intel.com>
465+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
466+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
467+
468+*******************************************************************************/
469+
470+#ifndef _DCB_82598_CONFIG_H_
471+#define _DCB_82598_CONFIG_H_
472+
473+/* DCB register definitions */
474+
475+#define IXGBE_DPMCS_MTSOS_SHIFT 16
476+#define IXGBE_DPMCS_TDPAC 0x00000001 /* 0 Round Robin, 1 DFP - Deficit Fixed Priority */
477+#define IXGBE_DPMCS_TRM 0x00000010 /* Transmit Recycle Mode */
478+#define IXGBE_DPMCS_ARBDIS 0x00000040 /* DCB arbiter disable */
479+#define IXGBE_DPMCS_TSOEF 0x00080000 /* TSO Expand Factor: 0=x4, 1=x2 */
480+
481+#define IXGBE_RUPPBMR_MQA 0x80000000 /* Enable UP to queue mapping */
482+
483+#define IXGBE_RT2CR_MCL_SHIFT 12 /* Offset to Max Credit Limit setting */
484+#define IXGBE_RT2CR_LSP 0x80000000 /* LSP enable bit */
485+
486+#define IXGBE_RDRXCTL_MPBEN 0x00000010 /* DMA config for multiple packet buffers enable */
487+#define IXGBE_RDRXCTL_MCEN 0x00000040 /* DMA config for multiple cores (RSS) enable */
488+
489+#define IXGBE_TDTQ2TCCR_MCL_SHIFT 12
490+#define IXGBE_TDTQ2TCCR_BWG_SHIFT 9
491+#define IXGBE_TDTQ2TCCR_GSP 0x40000000
492+#define IXGBE_TDTQ2TCCR_LSP 0x80000000
493+
494+#define IXGBE_TDPT2TCCR_MCL_SHIFT 12
495+#define IXGBE_TDPT2TCCR_BWG_SHIFT 9
496+#define IXGBE_TDPT2TCCR_GSP 0x40000000
497+#define IXGBE_TDPT2TCCR_LSP 0x80000000
498+
499+#define IXGBE_PDPMCS_TPPAC 0x00000020 /* 0 Round Robin, 1 for DFP - Deficit Fixed Priority */
500+#define IXGBE_PDPMCS_ARBDIS 0x00000040 /* Arbiter disable */
501+#define IXGBE_PDPMCS_TRM 0x00000100 /* Transmit Recycle Mode enable */
502+
503+#define IXGBE_DTXCTL_ENDBUBD 0x00000004 /* Enable DBU buffer division */
504+
505+#define IXGBE_TXPBSIZE_40KB 0x0000A000 /* 40KB Packet Buffer */
506+#define IXGBE_RXPBSIZE_48KB 0x0000C000 /* 48KB Packet Buffer */
507+#define IXGBE_RXPBSIZE_64KB 0x00010000 /* 64KB Packet Buffer */
508+#define IXGBE_RXPBSIZE_80KB 0x00014000 /* 80KB Packet Buffer */
509+
510+#define IXGBE_RDRXCTL_RDMTS_1_2 0x00000000
511+
512+/* DCB hardware-specific driver APIs */
513+
514+/* DCB PFC functions */
515+s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw,
516+ struct ixgbe_dcb_config *dcb_config);
517+s32 ixgbe_dcb_get_pfc_stats_82598(struct ixgbe_hw *hw,
518+ struct ixgbe_hw_stats *stats,
519+ u8 tc_count);
520+
521+/* DCB traffic class stats */
522+s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw);
523+s32 ixgbe_dcb_get_tc_stats_82598(struct ixgbe_hw *hw,
524+ struct ixgbe_hw_stats *stats,
525+ u8 tc_count);
526+
527+/* DCB config arbiters */
528+s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw,
529+ struct ixgbe_dcb_config *dcb_config);
530+s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
531+ struct ixgbe_dcb_config *dcb_config);
532+s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw,
533+ struct ixgbe_dcb_config *dcb_config);
534+
535+/* DCB hw initialization */
536+s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw,
537+ struct ixgbe_dcb_config *config);
538+
539+#endif /* _DCB_82598_CONFIG_H */
540--- /dev/null
541+++ b/drivers/net/ixgbe/ixgbe_dcb.c
542@@ -0,0 +1,332 @@
543+/*******************************************************************************
544+
545+ Intel 10 Gigabit PCI Express Linux driver
546+ Copyright(c) 1999 - 2007 Intel Corporation.
547+
548+ This program is free software; you can redistribute it and/or modify it
549+ under the terms and conditions of the GNU General Public License,
550+ version 2, as published by the Free Software Foundation.
551+
552+ This program is distributed in the hope it will be useful, but WITHOUT
553+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
554+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
555+ more details.
556+
557+ You should have received a copy of the GNU General Public License along with
558+ this program; if not, write to the Free Software Foundation, Inc.,
559+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
560+
561+ The full GNU General Public License is included in this distribution in
562+ the file called "COPYING".
563+
564+ Contact Information:
565+ Linux NICS <linux.nics@intel.com>
566+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
567+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
568+
569+*******************************************************************************/
570+
571+
572+#include "ixgbe.h"
573+#include "ixgbe_type.h"
574+#include "ixgbe_dcb.h"
575+#include "ixgbe_dcb_82598.h"
576+
577+/**
578+ * ixgbe_dcb_config - Struct containing DCB settings.
579+ * @dcb_config: Pointer to DCB config structure
580+ *
581+ * This function checks DCB rules for DCB settings.
582+ * The following rules are checked:
583+ * 1. The sum of bandwidth percentages of all Bandwidth Groups must total 100%.
584+ * 2. The sum of bandwidth percentages of all Traffic Classes within a Bandwidth
585+ * Group must total 100.
586+ * 3. A Traffic Class should not be set to both Link Strict Priority
587+ * and Group Strict Priority.
588+ * 4. Link strict Bandwidth Groups can only have link strict traffic classes
589+ * with zero bandwidth.
590+ */
591+s32 ixgbe_dcb_check_config(struct ixgbe_dcb_config *dcb_config)
592+{
593+ struct tc_bw_alloc *p;
594+ s32 ret_val = 0;
595+ u8 i, j, bw = 0, bw_id;
596+ u8 bw_sum[2][MAX_BW_GROUP];
597+ bool link_strict[2][MAX_BW_GROUP];
598+
599+ memset(bw_sum, 0, sizeof(bw_sum));
600+ memset(link_strict, 0, sizeof(link_strict));
601+
602+ /* First Tx, then Rx */
603+ for (i = 0; i < 2; i++) {
604+ /* Check each traffic class for rule violation */
605+ for (j = 0; j < MAX_TRAFFIC_CLASS; j++) {
606+ p = &dcb_config->tc_config[j].path[i];
607+
608+ bw = p->bwg_percent;
609+ bw_id = p->bwg_id;
610+
611+ if (bw_id >= MAX_BW_GROUP) {
612+ ret_val = DCB_ERR_CONFIG;
613+ goto err_config;
614+ }
615+ if (p->prio_type == prio_link) {
616+ link_strict[i][bw_id] = true;
617+ /* Link strict should have zero bandwidth */
618+ if (bw) {
619+ ret_val = DCB_ERR_LS_BW_NONZERO;
620+ goto err_config;
621+ }
622+ } else if (!bw) {
623+ /*
624+ * Traffic classes without link strict
625+ * should have non-zero bandwidth.
626+ */
627+ ret_val = DCB_ERR_TC_BW_ZERO;
628+ goto err_config;
629+ }
630+ bw_sum[i][bw_id] += bw;
631+ }
632+
633+ bw = 0;
634+
635+ /* Check each bandwidth group for rule violation */
636+ for (j = 0; j < MAX_BW_GROUP; j++) {
637+ bw += dcb_config->bw_percentage[i][j];
638+ /*
639+ * Sum of bandwidth percentages of all traffic classes
640+ * within a Bandwidth Group must total 100 except for
641+ * link strict group (zero bandwidth).
642+ */
643+ if (link_strict[i][j]) {
644+ if (bw_sum[i][j]) {
645+ /*
646+ * Link strict group should have zero
647+ * bandwidth.
648+ */
649+ ret_val = DCB_ERR_LS_BWG_NONZERO;
650+ goto err_config;
651+ }
652+ } else if (bw_sum[i][j] != BW_PERCENT &&
653+ bw_sum[i][j] != 0) {
654+ ret_val = DCB_ERR_TC_BW;
655+ goto err_config;
656+ }
657+ }
658+
659+ if (bw != BW_PERCENT) {
660+ ret_val = DCB_ERR_BW_GROUP;
661+ goto err_config;
662+ }
663+ }
664+
665+err_config:
666+ return ret_val;
667+}
668+
669+/**
670+ * ixgbe_dcb_calculate_tc_credits - Calculates traffic class credits
671+ * @ixgbe_dcb_config: Struct containing DCB settings.
672+ * @direction: Configuring either Tx or Rx.
673+ *
674+ * This function calculates the credits allocated to each traffic class.
675+ * It should be called only after the rules are checked by
676+ * ixgbe_dcb_check_config().
677+ */
678+s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *dcb_config,
679+ u8 direction)
680+{
681+ struct tc_bw_alloc *p;
682+ s32 ret_val = 0;
683+ /* Initialization values default for Tx settings */
684+ u32 credit_refill = 0;
685+ u32 credit_max = 0;
686+ u16 link_percentage = 0;
687+ u8 bw_percent = 0;
688+ u8 i;
689+
690+ if (dcb_config == NULL) {
691+ ret_val = DCB_ERR_CONFIG;
692+ goto out;
693+ }
694+
695+ /* Find out the link percentage for each TC first */
696+ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
697+ p = &dcb_config->tc_config[i].path[direction];
698+ bw_percent = dcb_config->bw_percentage[direction][p->bwg_id];
699+
700+ link_percentage = p->bwg_percent;
701+ /* Must be careful of integer division for very small nums */
702+ link_percentage = (link_percentage * bw_percent) / 100;
703+ if (p->bwg_percent > 0 && link_percentage == 0)
704+ link_percentage = 1;
705+
706+ /* Save link_percentage for reference */
707+ p->link_percent = (u8)link_percentage;
708+
709+ /* Calculate credit refill and save it */
710+ credit_refill = link_percentage * MINIMUM_CREDIT_REFILL;
711+ p->data_credits_refill = (u16)credit_refill;
712+
713+ /* Calculate maximum credit for the TC */
714+ credit_max = (link_percentage * MAX_CREDIT) / 100;
715+
716+ /*
717+ * Adjustment based on rule checking, if the percentage
718+ * of a TC is too small, the maximum credit may not be
719+ * enough to send out a jumbo frame in data plane arbitration.
720+ */
721+ if (credit_max && (credit_max < MINIMUM_CREDIT_FOR_JUMBO))
722+ credit_max = MINIMUM_CREDIT_FOR_JUMBO;
723+
724+ if (direction == DCB_TX_CONFIG) {
725+ /*
726+ * Adjustment based on rule checking, if the
727+ * percentage of a TC is too small, the maximum
728+ * credit may not be enough to send out a TSO
729+ * packet in descriptor plane arbitration.
730+ */
731+ if (credit_max &&
732+ (credit_max < MINIMUM_CREDIT_FOR_TSO))
733+ credit_max = MINIMUM_CREDIT_FOR_TSO;
734+
735+ dcb_config->tc_config[i].desc_credits_max =
736+ (u16)credit_max;
737+ }
738+
739+ p->data_credits_max = (u16)credit_max;
740+ }
741+
742+out:
743+ return ret_val;
744+}
745+
746+/**
747+ * ixgbe_dcb_get_tc_stats - Returns status of each traffic class
748+ * @hw: pointer to hardware structure
749+ * @stats: pointer to statistics structure
750+ * @tc_count: Number of elements in bwg_array.
751+ *
752+ * This function returns the status data for each of the Traffic Classes in use.
753+ */
754+s32 ixgbe_dcb_get_tc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats,
755+ u8 tc_count)
756+{
757+ s32 ret = 0;
758+ if (hw->mac.type == ixgbe_mac_82598EB)
759+ ret = ixgbe_dcb_get_tc_stats_82598(hw, stats, tc_count);
760+ return ret;
761+}
762+
763+/**
764+ * ixgbe_dcb_get_pfc_stats - Returns CBFC status of each traffic class
765+ * hw - pointer to hardware structure
766+ * stats - pointer to statistics structure
767+ * tc_count - Number of elements in bwg_array.
768+ *
769+ * This function returns the CBFC status data for each of the Traffic Classes.
770+ */
771+s32 ixgbe_dcb_get_pfc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats,
772+ u8 tc_count)
773+{
774+ s32 ret = 0;
775+ if (hw->mac.type == ixgbe_mac_82598EB)
776+ ret = ixgbe_dcb_get_pfc_stats_82598(hw, stats, tc_count);
777+ return ret;
778+}
779+
780+/**
781+ * ixgbe_dcb_config_rx_arbiter - Config Rx arbiter
782+ * @hw: pointer to hardware structure
783+ * @dcb_config: pointer to ixgbe_dcb_config structure
784+ *
785+ * Configure Rx Data Arbiter and credits for each traffic class.
786+ */
787+s32 ixgbe_dcb_config_rx_arbiter(struct ixgbe_hw *hw,
788+ struct ixgbe_dcb_config *dcb_config)
789+{
790+ s32 ret = 0;
791+ if (hw->mac.type == ixgbe_mac_82598EB)
792+ ret = ixgbe_dcb_config_rx_arbiter_82598(hw, dcb_config);
793+ return ret;
794+}
795+
796+/**
797+ * ixgbe_dcb_config_tx_desc_arbiter - Config Tx Desc arbiter
798+ * @hw: pointer to hardware structure
799+ * @dcb_config: pointer to ixgbe_dcb_config structure
800+ *
801+ * Configure Tx Descriptor Arbiter and credits for each traffic class.
802+ */
803+s32 ixgbe_dcb_config_tx_desc_arbiter(struct ixgbe_hw *hw,
804+ struct ixgbe_dcb_config *dcb_config)
805+{
806+ s32 ret = 0;
807+ if (hw->mac.type == ixgbe_mac_82598EB)
808+ ret = ixgbe_dcb_config_tx_desc_arbiter_82598(hw, dcb_config);
809+ return ret;
810+}
811+
812+/**
813+ * ixgbe_dcb_config_tx_data_arbiter - Config Tx data arbiter
814+ * @hw: pointer to hardware structure
815+ * @dcb_config: pointer to ixgbe_dcb_config structure
816+ *
817+ * Configure Tx Data Arbiter and credits for each traffic class.
818+ */
819+s32 ixgbe_dcb_config_tx_data_arbiter(struct ixgbe_hw *hw,
820+ struct ixgbe_dcb_config *dcb_config)
821+{
822+ s32 ret = 0;
823+ if (hw->mac.type == ixgbe_mac_82598EB)
824+ ret = ixgbe_dcb_config_tx_data_arbiter_82598(hw, dcb_config);
825+ return ret;
826+}
827+
828+/**
829+ * ixgbe_dcb_config_pfc - Config priority flow control
830+ * @hw: pointer to hardware structure
831+ * @dcb_config: pointer to ixgbe_dcb_config structure
832+ *
833+ * Configure Priority Flow Control for each traffic class.
834+ */
835+s32 ixgbe_dcb_config_pfc(struct ixgbe_hw *hw,
836+ struct ixgbe_dcb_config *dcb_config)
837+{
838+ s32 ret = 0;
839+ if (hw->mac.type == ixgbe_mac_82598EB)
840+ ret = ixgbe_dcb_config_pfc_82598(hw, dcb_config);
841+ return ret;
842+}
843+
844+/**
845+ * ixgbe_dcb_config_tc_stats - Config traffic class statistics
846+ * @hw: pointer to hardware structure
847+ *
848+ * Configure queue statistics registers, all queues belonging to same traffic
849+ * class uses a single set of queue statistics counters.
850+ */
851+s32 ixgbe_dcb_config_tc_stats(struct ixgbe_hw *hw)
852+{
853+ s32 ret = 0;
854+ if (hw->mac.type == ixgbe_mac_82598EB)
855+ ret = ixgbe_dcb_config_tc_stats_82598(hw);
856+ return ret;
857+}
858+
859+/**
860+ * ixgbe_dcb_hw_config - Config and enable DCB
861+ * @hw: pointer to hardware structure
862+ * @dcb_config: pointer to ixgbe_dcb_config structure
863+ *
864+ * Configure dcb settings and enable dcb mode.
865+ */
866+s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw,
867+ struct ixgbe_dcb_config *dcb_config)
868+{
869+ s32 ret = 0;
870+ if (hw->mac.type == ixgbe_mac_82598EB)
871+ ret = ixgbe_dcb_hw_config_82598(hw, dcb_config);
872+ return ret;
873+}
874+
875--- /dev/null
876+++ b/drivers/net/ixgbe/ixgbe_dcb.h
877@@ -0,0 +1,189 @@
878+/*******************************************************************************
879+
880+ Intel 10 Gigabit PCI Express Linux driver
881+ Copyright(c) 1999 - 2007 Intel Corporation.
882+
883+ This program is free software; you can redistribute it and/or modify it
884+ under the terms and conditions of the GNU General Public License,
885+ version 2, as published by the Free Software Foundation.
886+
887+ This program is distributed in the hope it will be useful, but WITHOUT
888+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
889+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
890+ more details.
891+
892+ You should have received a copy of the GNU General Public License along with
893+ this program; if not, write to the Free Software Foundation, Inc.,
894+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
895+
896+ The full GNU General Public License is included in this distribution in
897+ the file called "COPYING".
898+
899+ Contact Information:
900+ Linux NICS <linux.nics@intel.com>
901+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
902+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
903+
904+*******************************************************************************/
905+
906+#ifndef _DCB_CONFIG_H_
907+#define _DCB_CONFIG_H_
908+
909+#include "ixgbe_type.h"
910+
911+/* DCB data structures */
912+
913+#define IXGBE_MAX_PACKET_BUFFERS 8
914+#define MAX_USER_PRIORITY 8
915+#define MAX_TRAFFIC_CLASS 8
916+#define MAX_BW_GROUP 8
917+#define BW_PERCENT 100
918+
919+#define DCB_TX_CONFIG 0
920+#define DCB_RX_CONFIG 1
921+
922+/* DCB error Codes */
923+#define DCB_SUCCESS 0
924+#define DCB_ERR_CONFIG -1
925+#define DCB_ERR_PARAM -2
926+
927+/* Transmit and receive Errors */
928+/* Error in bandwidth group allocation */
929+#define DCB_ERR_BW_GROUP -3
930+/* Error in traffic class bandwidth allocation */
931+#define DCB_ERR_TC_BW -4
932+/* Traffic class has both link strict and group strict enabled */
933+#define DCB_ERR_LS_GS -5
934+/* Link strict traffic class has non zero bandwidth */
935+#define DCB_ERR_LS_BW_NONZERO -6
936+/* Link strict bandwidth group has non zero bandwidth */
937+#define DCB_ERR_LS_BWG_NONZERO -7
938+/* Traffic class has zero bandwidth */
939+#define DCB_ERR_TC_BW_ZERO -8
940+
941+#define DCB_NOT_IMPLEMENTED 0x7FFFFFFF
942+
943+struct dcb_pfc_tc_debug {
944+ u8 tc;
945+ u8 pause_status;
946+ u64 pause_quanta;
947+};
948+
949+enum strict_prio_type {
950+ prio_none = 0,
951+ prio_group,
952+ prio_link
953+};
954+
955+/* Traffic class bandwidth allocation per direction */
956+struct tc_bw_alloc {
957+ u8 bwg_id; /* Bandwidth Group (BWG) ID */
958+ u8 bwg_percent; /* % of BWG's bandwidth */
959+ u8 link_percent; /* % of link bandwidth */
960+ u8 up_to_tc_bitmap; /* User Priority to Traffic Class mapping */
961+ u16 data_credits_refill; /* Credit refill amount in 64B granularity */
962+ u16 data_credits_max; /* Max credits for a configured packet buffer
963+ * in 64B granularity.*/
964+ enum strict_prio_type prio_type; /* Link or Group Strict Priority */
965+};
966+
967+enum dcb_pfc_type {
968+ pfc_disabled = 0,
969+ pfc_enabled_full,
970+ pfc_enabled_tx,
971+ pfc_enabled_rx
972+};
973+
974+/* Traffic class configuration */
975+struct tc_configuration {
976+ struct tc_bw_alloc path[2]; /* One each for Tx/Rx */
977+ enum dcb_pfc_type dcb_pfc; /* Class based flow control setting */
978+
979+ u16 desc_credits_max; /* For Tx Descriptor arbitration */
980+ u8 tc; /* Traffic class (TC) */
981+};
982+
983+enum dcb_rx_pba_cfg {
984+ pba_equal, /* PBA[0-7] each use 64KB FIFO */
985+ pba_80_48 /* PBA[0-3] each use 80KB, PBA[4-7] each use 48KB */
986+};
987+
988+/*
989+ * This structure contains many values encoded as fixed-point
990+ * numbers, meaning that some of bits are dedicated to the
991+ * magnitude and others to the fraction part. In the comments
992+ * this is shown as f=n, where n is the number of fraction bits.
993+ * These fraction bits are always the low-order bits. The size
994+ * of the magnitude is not specified.
995+ */
996+struct bcn_config {
997+ u32 rp_admin_mode[MAX_TRAFFIC_CLASS]; /* BCN enabled, per TC */
998+ u32 bcna_option[2]; /* BCNA Port + MAC Addr */
999+ u32 rp_w; /* Derivative Weight, f=3 */
1000+ u32 rp_gi; /* Increase Gain, f=12 */
1001+ u32 rp_gd; /* Decrease Gain, f=12 */
1002+ u32 rp_ru; /* Rate Unit */
1003+ u32 rp_alpha; /* Max Decrease Factor, f=12 */
1004+ u32 rp_beta; /* Max Increase Factor, f=12 */
1005+ u32 rp_ri; /* Initial Rate */
1006+ u32 rp_td; /* Drift Interval Timer */
1007+ u32 rp_rd; /* Drift Increase */
1008+ u32 rp_tmax; /* Severe Congestion Backoff Timer Range */
1009+ u32 rp_rmin; /* Severe Congestion Restart Rate */
1010+ u32 rp_wrtt; /* RTT Moving Average Weight */
1011+};
1012+
1013+struct ixgbe_dcb_config {
1014+ struct bcn_config bcn;
1015+
1016+ struct tc_configuration tc_config[MAX_TRAFFIC_CLASS];
1017+ u8 bw_percentage[2][MAX_BW_GROUP]; /* One each for Tx/Rx */
1018+
1019+ bool round_robin_enable;
1020+
1021+ enum dcb_rx_pba_cfg rx_pba_cfg;
1022+
1023+ u32 dcb_cfg_version; /* Not used...OS-specific? */
1024+ u32 link_speed; /* For bandwidth allocation validation purpose */
1025+};
1026+
1027+/* DCB driver APIs */
1028+
1029+/* DCB rule checking function.*/
1030+s32 ixgbe_dcb_check_config(struct ixgbe_dcb_config *config);
1031+
1032+/* DCB credits calculation */
1033+s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *config,
1034+ u8 direction);
1035+
1036+/* DCB PFC functions */
1037+s32 ixgbe_dcb_config_pfc(struct ixgbe_hw *hw,
1038+ struct ixgbe_dcb_config *dcb_config);
1039+s32 ixgbe_dcb_get_pfc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats,
1040+ u8 tc_count);
1041+
1042+/* DCB traffic class stats */
1043+s32 ixgbe_dcb_config_tc_stats(struct ixgbe_hw *);
1044+s32 ixgbe_dcb_get_tc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats,
1045+ u8 tc_count);
1046+
1047+/* DCB config arbiters */
1048+s32 ixgbe_dcb_config_tx_desc_arbiter(struct ixgbe_hw *hw,
1049+ struct ixgbe_dcb_config *dcb_config);
1050+s32 ixgbe_dcb_config_tx_data_arbiter(struct ixgbe_hw *hw,
1051+ struct ixgbe_dcb_config *dcb_config);
1052+s32 ixgbe_dcb_config_rx_arbiter(struct ixgbe_hw *hw,
1053+ struct ixgbe_dcb_config *dcb_config);
1054+
1055+/* DCB hw initialization */
1056+s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw, struct ixgbe_dcb_config *config);
1057+
1058+/* DCB definitions for credit calculation */
1059+#define MAX_CREDIT_REFILL 511 /* 0x1FF * 64B = 32704B */
1060+#define MINIMUM_CREDIT_REFILL 5 /* 5*64B = 320B */
1061+#define MINIMUM_CREDIT_FOR_JUMBO 145 /* 145= UpperBound((9*1024+54)/64B) for 9KB jumbo frame */
1062+#define DCB_MAX_TSO_SIZE (32*1024) /* MAX TSO packet size supported in DCB mode */
1063+#define MINIMUM_CREDIT_FOR_TSO (DCB_MAX_TSO_SIZE/64 + 1) /* 513 for 32KB TSO packet */
1064+#define MAX_CREDIT 4095 /* Maximum credit supported: 256KB * 1204 / 64B */
1065+
1066+#endif /* _DCB_CONFIG_H */
1067--- /dev/null
1068+++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c
1069@@ -0,0 +1,611 @@
1070+/*******************************************************************************
1071+
1072+ Intel 10 Gigabit PCI Express Linux driver
1073+ Copyright(c) 1999 - 2008 Intel Corporation.
1074+
1075+ This program is free software; you can redistribute it and/or modify it
1076+ under the terms and conditions of the GNU General Public License,
1077+ version 2, as published by the Free Software Foundation.
1078+
1079+ This program is distributed in the hope it will be useful, but WITHOUT
1080+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1081+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
1082+ more details.
1083+
1084+ You should have received a copy of the GNU General Public License along with
1085+ this program; if not, write to the Free Software Foundation, Inc.,
1086+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
1087+
1088+ The full GNU General Public License is included in this distribution in
1089+ the file called "COPYING".
1090+
1091+ Contact Information:
1092+ Linux NICS <linux.nics@intel.com>
1093+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
1094+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
1095+
1096+*******************************************************************************/
1097+
1098+#include "ixgbe.h"
1099+#include <linux/dcbnl.h>
1100+
1101+/* Callbacks for DCB netlink in the kernel */
1102+#define BIT_DCB_MODE 0x01
1103+#define BIT_PFC 0x02
1104+#define BIT_PG_RX 0x04
1105+#define BIT_PG_TX 0x08
1106+#define BIT_BCN 0x10
1107+
1108+int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg,
1109+ struct ixgbe_dcb_config *dst_dcb_cfg, int tc_max)
1110+{
1111+ struct tc_configuration *src_tc_cfg = NULL;
1112+ struct tc_configuration *dst_tc_cfg = NULL;
1113+ int i;
1114+
1115+ if (!src_dcb_cfg || !dst_dcb_cfg)
1116+ return -EINVAL;
1117+
1118+ for (i = DCB_PG_ATTR_TC_0; i < tc_max + DCB_PG_ATTR_TC_0; i++) {
1119+ src_tc_cfg = &src_dcb_cfg->tc_config[i - DCB_PG_ATTR_TC_0];
1120+ dst_tc_cfg = &dst_dcb_cfg->tc_config[i - DCB_PG_ATTR_TC_0];
1121+
1122+ dst_tc_cfg->path[DCB_TX_CONFIG].prio_type =
1123+ src_tc_cfg->path[DCB_TX_CONFIG].prio_type;
1124+
1125+ dst_tc_cfg->path[DCB_TX_CONFIG].bwg_id =
1126+ src_tc_cfg->path[DCB_TX_CONFIG].bwg_id;
1127+
1128+ dst_tc_cfg->path[DCB_TX_CONFIG].bwg_percent =
1129+ src_tc_cfg->path[DCB_TX_CONFIG].bwg_percent;
1130+
1131+ dst_tc_cfg->path[DCB_TX_CONFIG].up_to_tc_bitmap =
1132+ src_tc_cfg->path[DCB_TX_CONFIG].up_to_tc_bitmap;
1133+
1134+ dst_tc_cfg->path[DCB_RX_CONFIG].prio_type =
1135+ src_tc_cfg->path[DCB_RX_CONFIG].prio_type;
1136+
1137+ dst_tc_cfg->path[DCB_RX_CONFIG].bwg_id =
1138+ src_tc_cfg->path[DCB_RX_CONFIG].bwg_id;
1139+
1140+ dst_tc_cfg->path[DCB_RX_CONFIG].bwg_percent =
1141+ src_tc_cfg->path[DCB_RX_CONFIG].bwg_percent;
1142+
1143+ dst_tc_cfg->path[DCB_RX_CONFIG].up_to_tc_bitmap =
1144+ src_tc_cfg->path[DCB_RX_CONFIG].up_to_tc_bitmap;
1145+ }
1146+
1147+ for (i = DCB_PG_ATTR_BW_ID_0; i < DCB_PG_ATTR_BW_ID_MAX; i++) {
1148+ dst_dcb_cfg->bw_percentage[DCB_TX_CONFIG]
1149+ [i-DCB_PG_ATTR_BW_ID_0] = src_dcb_cfg->bw_percentage
1150+ [DCB_TX_CONFIG][i-DCB_PG_ATTR_BW_ID_0];
1151+ dst_dcb_cfg->bw_percentage[DCB_RX_CONFIG]
1152+ [i-DCB_PG_ATTR_BW_ID_0] = src_dcb_cfg->bw_percentage
1153+ [DCB_RX_CONFIG][i-DCB_PG_ATTR_BW_ID_0];
1154+ }
1155+
1156+ for (i = DCB_PFC_UP_ATTR_0; i < DCB_PFC_UP_ATTR_MAX; i++) {
1157+ dst_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc =
1158+ src_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc;
1159+ }
1160+
1161+ for (i = DCB_BCN_ATTR_RP_0; i < DCB_BCN_ATTR_RP_ALL; i++) {
1162+ dst_dcb_cfg->bcn.rp_admin_mode[i - DCB_BCN_ATTR_RP_0] =
1163+ src_dcb_cfg->bcn.rp_admin_mode[i - DCB_BCN_ATTR_RP_0];
1164+ }
1165+ dst_dcb_cfg->bcn.rp_alpha = src_dcb_cfg->bcn.rp_alpha;
1166+ dst_dcb_cfg->bcn.rp_beta = src_dcb_cfg->bcn.rp_beta;
1167+ dst_dcb_cfg->bcn.rp_gd = src_dcb_cfg->bcn.rp_gd;
1168+ dst_dcb_cfg->bcn.rp_gi = src_dcb_cfg->bcn.rp_gi;
1169+ dst_dcb_cfg->bcn.rp_tmax = src_dcb_cfg->bcn.rp_tmax;
1170+ dst_dcb_cfg->bcn.rp_td = src_dcb_cfg->bcn.rp_td;
1171+ dst_dcb_cfg->bcn.rp_rmin = src_dcb_cfg->bcn.rp_rmin;
1172+ dst_dcb_cfg->bcn.rp_w = src_dcb_cfg->bcn.rp_w;
1173+ dst_dcb_cfg->bcn.rp_rd = src_dcb_cfg->bcn.rp_rd;
1174+ dst_dcb_cfg->bcn.rp_ru = src_dcb_cfg->bcn.rp_ru;
1175+ dst_dcb_cfg->bcn.rp_wrtt = src_dcb_cfg->bcn.rp_wrtt;
1176+ dst_dcb_cfg->bcn.rp_ri = src_dcb_cfg->bcn.rp_ri;
1177+
1178+ return 0;
1179+}
1180+
1181+static u8 ixgbe_dcbnl_get_state(struct net_device *netdev)
1182+{
1183+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1184+
1185+ DPRINTK(DRV, INFO, "Get DCB Admin Mode.\n");
1186+
1187+ return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED);
1188+}
1189+
1190+static u16 ixgbe_dcb_select_queue(struct net_device *dev, struct sk_buff *skb)
1191+{
1192+ /* All traffic should default to class 0 */
1193+ return 0;
1194+}
1195+
1196+static void ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
1197+{
1198+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1199+
1200+ DPRINTK(DRV, INFO, "Set DCB Admin Mode.\n");
1201+
1202+ if (state > 0) {
1203+ /* Turn on DCB */
1204+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
1205+ return;
1206+ } else {
1207+ if (netdev->flags & IFF_UP)
1208+ netdev->stop(netdev);
1209+ ixgbe_reset_interrupt_capability(adapter);
1210+ ixgbe_napi_del_all(adapter);
1211+ kfree(adapter->tx_ring);
1212+ kfree(adapter->rx_ring);
1213+ adapter->tx_ring = NULL;
1214+ adapter->rx_ring = NULL;
1215+ netdev->select_queue = &ixgbe_dcb_select_queue;
1216+
1217+ adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
1218+ adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
1219+ ixgbe_init_interrupt_scheme(adapter);
1220+ ixgbe_napi_add_all(adapter);
1221+ if (netdev->flags & IFF_UP)
1222+ netdev->open(netdev);
1223+ }
1224+ } else {
1225+ /* Turn off DCB */
1226+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
1227+ if (netdev->flags & IFF_UP)
1228+ netdev->stop(netdev);
1229+ ixgbe_reset_interrupt_capability(adapter);
1230+ ixgbe_napi_del_all(adapter);
1231+ kfree(adapter->tx_ring);
1232+ kfree(adapter->rx_ring);
1233+ adapter->tx_ring = NULL;
1234+ adapter->rx_ring = NULL;
1235+ netdev->select_queue = NULL;
1236+
1237+ adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
1238+ adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
1239+ ixgbe_init_interrupt_scheme(adapter);
1240+ ixgbe_napi_add_all(adapter);
1241+ if (netdev->flags & IFF_UP)
1242+ netdev->open(netdev);
1243+ } else {
1244+ return;
1245+ }
1246+ }
1247+}
1248+
1249+static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev,
1250+ u8 *perm_addr)
1251+{
1252+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1253+ int i;
1254+
1255+ for (i = 0; i < netdev->addr_len; i++)
1256+ perm_addr[i] = adapter->hw.mac.perm_addr[i];
1257+}
1258+
1259+static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,
1260+ u8 prio, u8 bwg_id, u8 bw_pct,
1261+ u8 up_map)
1262+{
1263+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1264+
1265+ if (prio != DCB_ATTR_VALUE_UNDEFINED)
1266+ adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type = prio;
1267+ if (bwg_id != DCB_ATTR_VALUE_UNDEFINED)
1268+ adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_id = bwg_id;
1269+ if (bw_pct != DCB_ATTR_VALUE_UNDEFINED)
1270+ adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent =
1271+ bw_pct;
1272+ if (up_map != DCB_ATTR_VALUE_UNDEFINED)
1273+ adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap =
1274+ up_map;
1275+
1276+ if ((adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type !=
1277+ adapter->dcb_cfg.tc_config[tc].path[0].prio_type) ||
1278+ (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_id !=
1279+ adapter->dcb_cfg.tc_config[tc].path[0].bwg_id) ||
1280+ (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent !=
1281+ adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent) ||
1282+ (adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap !=
1283+ adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap))
1284+ adapter->dcb_set_bitmap |= BIT_PG_TX;
1285+}
1286+
1287+static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
1288+ u8 bw_pct)
1289+{
1290+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1291+
1292+ adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct;
1293+
1294+ if (adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] !=
1295+ adapter->dcb_cfg.bw_percentage[0][bwg_id])
1296+ adapter->dcb_set_bitmap |= BIT_PG_RX;
1297+}
1298+
1299+static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc,
1300+ u8 prio, u8 bwg_id, u8 bw_pct,
1301+ u8 up_map)
1302+{
1303+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1304+
1305+ if (prio != DCB_ATTR_VALUE_UNDEFINED)
1306+ adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type = prio;
1307+ if (bwg_id != DCB_ATTR_VALUE_UNDEFINED)
1308+ adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_id = bwg_id;
1309+ if (bw_pct != DCB_ATTR_VALUE_UNDEFINED)
1310+ adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent =
1311+ bw_pct;
1312+ if (up_map != DCB_ATTR_VALUE_UNDEFINED)
1313+ adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap =
1314+ up_map;
1315+
1316+ if ((adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type !=
1317+ adapter->dcb_cfg.tc_config[tc].path[1].prio_type) ||
1318+ (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_id !=
1319+ adapter->dcb_cfg.tc_config[tc].path[1].bwg_id) ||
1320+ (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent !=
1321+ adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent) ||
1322+ (adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap !=
1323+ adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap))
1324+ adapter->dcb_set_bitmap |= BIT_PG_RX;
1325+}
1326+
1327+static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
1328+ u8 bw_pct)
1329+{
1330+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1331+
1332+ adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct;
1333+
1334+ if (adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] !=
1335+ adapter->dcb_cfg.bw_percentage[1][bwg_id])
1336+ adapter->dcb_set_bitmap |= BIT_PG_RX;
1337+}
1338+
1339+static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc,
1340+ u8 *prio, u8 *bwg_id, u8 *bw_pct,
1341+ u8 *up_map)
1342+{
1343+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1344+
1345+ *prio = adapter->dcb_cfg.tc_config[tc].path[0].prio_type;
1346+ *bwg_id = adapter->dcb_cfg.tc_config[tc].path[0].bwg_id;
1347+ *bw_pct = adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent;
1348+ *up_map = adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap;
1349+}
1350+
1351+static void ixgbe_dcbnl_get_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
1352+ u8 *bw_pct)
1353+{
1354+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1355+
1356+ *bw_pct = adapter->dcb_cfg.bw_percentage[0][bwg_id];
1357+}
1358+
1359+static void ixgbe_dcbnl_get_pg_tc_cfg_rx(struct net_device *netdev, int tc,
1360+ u8 *prio, u8 *bwg_id, u8 *bw_pct,
1361+ u8 *up_map)
1362+{
1363+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1364+
1365+ *prio = adapter->dcb_cfg.tc_config[tc].path[1].prio_type;
1366+ *bwg_id = adapter->dcb_cfg.tc_config[tc].path[1].bwg_id;
1367+ *bw_pct = adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent;
1368+ *up_map = adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap;
1369+}
1370+
1371+static void ixgbe_dcbnl_get_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
1372+ u8 *bw_pct)
1373+{
1374+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1375+
1376+ *bw_pct = adapter->dcb_cfg.bw_percentage[1][bwg_id];
1377+}
1378+
1379+static void ixgbe_dcbnl_set_pfc_cfg(struct net_device *netdev, int priority,
1380+ u8 setting)
1381+{
1382+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1383+
1384+ adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc = setting;
1385+ if (adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc !=
1386+ adapter->dcb_cfg.tc_config[priority].dcb_pfc)
1387+ adapter->dcb_set_bitmap |= BIT_PFC;
1388+}
1389+
1390+static void ixgbe_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority,
1391+ u8 *setting)
1392+{
1393+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1394+
1395+ *setting = adapter->dcb_cfg.tc_config[priority].dcb_pfc;
1396+}
1397+
1398+static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
1399+{
1400+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1401+ int ret;
1402+
1403+ adapter->dcb_set_bitmap &= ~BIT_BCN; /* no set for BCN */
1404+ if (!adapter->dcb_set_bitmap)
1405+ return 1;
1406+
1407+ while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
1408+ msleep(1);
1409+
1410+ ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
1411+ adapter->ring_feature[RING_F_DCB].indices);
1412+ if (ret) {
1413+ clear_bit(__IXGBE_RESETTING, &adapter->state);
1414+ return ret;
1415+ }
1416+
1417+ ixgbe_down(adapter);
1418+ ixgbe_up(adapter);
1419+ adapter->dcb_set_bitmap = 0x00;
1420+ clear_bit(__IXGBE_RESETTING, &adapter->state);
1421+ return ret;
1422+}
1423+
1424+static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap)
1425+{
1426+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1427+ u8 rval = 0;
1428+
1429+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
1430+ switch (capid) {
1431+ case DCB_CAP_ATTR_PG:
1432+ *cap = true;
1433+ break;
1434+ case DCB_CAP_ATTR_PFC:
1435+ *cap = true;
1436+ break;
1437+ case DCB_CAP_ATTR_UP2TC:
1438+ *cap = false;
1439+ break;
1440+ case DCB_CAP_ATTR_PG_TCS:
1441+ *cap = 0x80;
1442+ break;
1443+ case DCB_CAP_ATTR_PFC_TCS:
1444+ *cap = 0x80;
1445+ break;
1446+ case DCB_CAP_ATTR_GSP:
1447+ *cap = true;
1448+ break;
1449+ case DCB_CAP_ATTR_BCN:
1450+ *cap = false;
1451+ break;
1452+ default:
1453+ rval = -EINVAL;
1454+ break;
1455+ }
1456+ } else {
1457+ rval = -EINVAL;
1458+ }
1459+
1460+ return rval;
1461+}
1462+
1463+static u8 ixgbe_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num)
1464+{
1465+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1466+ u8 rval = 0;
1467+
1468+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
1469+ switch (tcid) {
1470+ case DCB_NUMTCS_ATTR_PG:
1471+ *num = MAX_TRAFFIC_CLASS;
1472+ break;
1473+ case DCB_NUMTCS_ATTR_PFC:
1474+ *num = MAX_TRAFFIC_CLASS;
1475+ break;
1476+ default:
1477+ rval = -EINVAL;
1478+ break;
1479+ }
1480+ } else {
1481+ rval = -EINVAL;
1482+ }
1483+
1484+ return rval;
1485+}
1486+
1487+static u8 ixgbe_dcbnl_setnumtcs(struct net_device *netdev, int tcid, u8 num)
1488+{
1489+ return -EINVAL;
1490+}
1491+
1492+static u8 ixgbe_dcbnl_getpfcstate(struct net_device *netdev)
1493+{
1494+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1495+
1496+ return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED);
1497+}
1498+
1499+static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
1500+{
1501+ return;
1502+}
1503+
1504+static void ixgbe_dcbnl_getbcnrp(struct net_device *netdev, int priority,
1505+ u8 *setting)
1506+{
1507+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1508+
1509+ *setting = adapter->dcb_cfg.bcn.rp_admin_mode[priority];
1510+}
1511+
1512+
1513+static void ixgbe_dcbnl_getbcncfg(struct net_device *netdev, int enum_index,
1514+ u32 *setting)
1515+{
1516+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1517+
1518+ switch (enum_index) {
1519+ case DCB_BCN_ATTR_ALPHA:
1520+ *setting = adapter->dcb_cfg.bcn.rp_alpha;
1521+ break;
1522+ case DCB_BCN_ATTR_BETA:
1523+ *setting = adapter->dcb_cfg.bcn.rp_beta;
1524+ break;
1525+ case DCB_BCN_ATTR_GD:
1526+ *setting = adapter->dcb_cfg.bcn.rp_gd;
1527+ break;
1528+ case DCB_BCN_ATTR_GI:
1529+ *setting = adapter->dcb_cfg.bcn.rp_gi;
1530+ break;
1531+ case DCB_BCN_ATTR_TMAX:
1532+ *setting = adapter->dcb_cfg.bcn.rp_tmax;
1533+ break;
1534+ case DCB_BCN_ATTR_TD:
1535+ *setting = adapter->dcb_cfg.bcn.rp_td;
1536+ break;
1537+ case DCB_BCN_ATTR_RMIN:
1538+ *setting = adapter->dcb_cfg.bcn.rp_rmin;
1539+ break;
1540+ case DCB_BCN_ATTR_W:
1541+ *setting = adapter->dcb_cfg.bcn.rp_w;
1542+ break;
1543+ case DCB_BCN_ATTR_RD:
1544+ *setting = adapter->dcb_cfg.bcn.rp_rd;
1545+ break;
1546+ case DCB_BCN_ATTR_RU:
1547+ *setting = adapter->dcb_cfg.bcn.rp_ru;
1548+ break;
1549+ case DCB_BCN_ATTR_WRTT:
1550+ *setting = adapter->dcb_cfg.bcn.rp_wrtt;
1551+ break;
1552+ case DCB_BCN_ATTR_RI:
1553+ *setting = adapter->dcb_cfg.bcn.rp_ri;
1554+ break;
1555+ default:
1556+ *setting = -1;
1557+ }
1558+}
1559+
1560+static void ixgbe_dcbnl_setbcnrp(struct net_device *netdev, int priority,
1561+ u8 setting)
1562+{
1563+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1564+
1565+ adapter->temp_dcb_cfg.bcn.rp_admin_mode[priority] = setting;
1566+
1567+ if (adapter->temp_dcb_cfg.bcn.rp_admin_mode[priority] !=
1568+ adapter->dcb_cfg.bcn.rp_admin_mode[priority])
1569+ adapter->dcb_set_bitmap |= BIT_BCN;
1570+}
1571+
1572+static void ixgbe_dcbnl_setbcncfg(struct net_device *netdev, int enum_index,
1573+ u32 setting)
1574+{
1575+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
1576+
1577+ switch (enum_index) {
1578+ case DCB_BCN_ATTR_ALPHA:
1579+ adapter->temp_dcb_cfg.bcn.rp_alpha = setting;
1580+ if (adapter->temp_dcb_cfg.bcn.rp_alpha !=
1581+ adapter->dcb_cfg.bcn.rp_alpha)
1582+ adapter->dcb_set_bitmap |= BIT_BCN;
1583+ break;
1584+ case DCB_BCN_ATTR_BETA:
1585+ adapter->temp_dcb_cfg.bcn.rp_beta = setting;
1586+ if (adapter->temp_dcb_cfg.bcn.rp_beta !=
1587+ adapter->dcb_cfg.bcn.rp_beta)
1588+ adapter->dcb_set_bitmap |= BIT_BCN;
1589+ break;
1590+ case DCB_BCN_ATTR_GD:
1591+ adapter->temp_dcb_cfg.bcn.rp_gd = setting;
1592+ if (adapter->temp_dcb_cfg.bcn.rp_gd !=
1593+ adapter->dcb_cfg.bcn.rp_gd)
1594+ adapter->dcb_set_bitmap |= BIT_BCN;
1595+ break;
1596+ case DCB_BCN_ATTR_GI:
1597+ adapter->temp_dcb_cfg.bcn.rp_gi = setting;
1598+ if (adapter->temp_dcb_cfg.bcn.rp_gi !=
1599+ adapter->dcb_cfg.bcn.rp_gi)
1600+ adapter->dcb_set_bitmap |= BIT_BCN;
1601+ break;
1602+ case DCB_BCN_ATTR_TMAX:
1603+ adapter->temp_dcb_cfg.bcn.rp_tmax = setting;
1604+ if (adapter->temp_dcb_cfg.bcn.rp_tmax !=
1605+ adapter->dcb_cfg.bcn.rp_tmax)
1606+ adapter->dcb_set_bitmap |= BIT_BCN;
1607+ break;
1608+ case DCB_BCN_ATTR_TD:
1609+ adapter->temp_dcb_cfg.bcn.rp_td = setting;
1610+ if (adapter->temp_dcb_cfg.bcn.rp_td !=
1611+ adapter->dcb_cfg.bcn.rp_td)
1612+ adapter->dcb_set_bitmap |= BIT_BCN;
1613+ break;
1614+ case DCB_BCN_ATTR_RMIN:
1615+ adapter->temp_dcb_cfg.bcn.rp_rmin = setting;
1616+ if (adapter->temp_dcb_cfg.bcn.rp_rmin !=
1617+ adapter->dcb_cfg.bcn.rp_rmin)
1618+ adapter->dcb_set_bitmap |= BIT_BCN;
1619+ break;
1620+ case DCB_BCN_ATTR_W:
1621+ adapter->temp_dcb_cfg.bcn.rp_w = setting;
1622+ if (adapter->temp_dcb_cfg.bcn.rp_w !=
1623+ adapter->dcb_cfg.bcn.rp_w)
1624+ adapter->dcb_set_bitmap |= BIT_BCN;
1625+ break;
1626+ case DCB_BCN_ATTR_RD:
1627+ adapter->temp_dcb_cfg.bcn.rp_rd = setting;
1628+ if (adapter->temp_dcb_cfg.bcn.rp_rd !=
1629+ adapter->dcb_cfg.bcn.rp_rd)
1630+ adapter->dcb_set_bitmap |= BIT_BCN;
1631+ break;
1632+ case DCB_BCN_ATTR_RU:
1633+ adapter->temp_dcb_cfg.bcn.rp_ru = setting;
1634+ if (adapter->temp_dcb_cfg.bcn.rp_ru !=
1635+ adapter->dcb_cfg.bcn.rp_ru)
1636+ adapter->dcb_set_bitmap |= BIT_BCN;
1637+ break;
1638+ case DCB_BCN_ATTR_WRTT:
1639+ adapter->temp_dcb_cfg.bcn.rp_wrtt = setting;
1640+ if (adapter->temp_dcb_cfg.bcn.rp_wrtt !=
1641+ adapter->dcb_cfg.bcn.rp_wrtt)
1642+ adapter->dcb_set_bitmap |= BIT_BCN;
1643+ break;
1644+ case DCB_BCN_ATTR_RI:
1645+ adapter->temp_dcb_cfg.bcn.rp_ri = setting;
1646+ if (adapter->temp_dcb_cfg.bcn.rp_ri !=
1647+ adapter->dcb_cfg.bcn.rp_ri)
1648+ adapter->dcb_set_bitmap |= BIT_BCN;
1649+ break;
1650+ default:
1651+ break;
1652+ }
1653+}
1654+
1655+struct dcbnl_rtnl_ops dcbnl_ops = {
1656+ .getstate = ixgbe_dcbnl_get_state,
1657+ .setstate = ixgbe_dcbnl_set_state,
1658+ .getpermhwaddr = ixgbe_dcbnl_get_perm_hw_addr,
1659+ .setpgtccfgtx = ixgbe_dcbnl_set_pg_tc_cfg_tx,
1660+ .setpgbwgcfgtx = ixgbe_dcbnl_set_pg_bwg_cfg_tx,
1661+ .setpgtccfgrx = ixgbe_dcbnl_set_pg_tc_cfg_rx,
1662+ .setpgbwgcfgrx = ixgbe_dcbnl_set_pg_bwg_cfg_rx,
1663+ .getpgtccfgtx = ixgbe_dcbnl_get_pg_tc_cfg_tx,
1664+ .getpgbwgcfgtx = ixgbe_dcbnl_get_pg_bwg_cfg_tx,
1665+ .getpgtccfgrx = ixgbe_dcbnl_get_pg_tc_cfg_rx,
1666+ .getpgbwgcfgrx = ixgbe_dcbnl_get_pg_bwg_cfg_rx,
1667+ .setpfccfg = ixgbe_dcbnl_set_pfc_cfg,
1668+ .getpfccfg = ixgbe_dcbnl_get_pfc_cfg,
1669+ .setall = ixgbe_dcbnl_set_all,
1670+ .getcap = ixgbe_dcbnl_getcap,
1671+ .getnumtcs = ixgbe_dcbnl_getnumtcs,
1672+ .setnumtcs = ixgbe_dcbnl_setnumtcs,
1673+ .getpfcstate = ixgbe_dcbnl_getpfcstate,
1674+ .setpfcstate = ixgbe_dcbnl_setpfcstate,
1675+ .getbcncfg = ixgbe_dcbnl_getbcncfg,
1676+ .getbcnrp = ixgbe_dcbnl_getbcnrp,
1677+ .setbcncfg = ixgbe_dcbnl_setbcncfg,
1678+ .setbcnrp = ixgbe_dcbnl_setbcnrp
1679+};
1680+
1681--- a/drivers/net/ixgbe/ixgbe_ethtool.c
1682+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
1683@@ -99,9 +99,18 @@ static struct ixgbe_stats ixgbe_gstrings
1684 ((((struct ixgbe_adapter *)netdev->priv)->num_tx_queues + \
1685 ((struct ixgbe_adapter *)netdev->priv)->num_rx_queues) * \
1686 (sizeof(struct ixgbe_queue_stats) / sizeof(u64)))
1687-#define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + IXGBE_QUEUE_STATS_LEN)
1688 #define IXGBE_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbe_gstrings_stats)
1689-#define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + IXGBE_QUEUE_STATS_LEN)
1690+#define IXGBE_PB_STATS_LEN ( \
1691+ (((struct ixgbe_adapter *)netdev->priv)->flags & \
1692+ IXGBE_FLAG_DCB_ENABLED) ? \
1693+ (sizeof(((struct ixgbe_adapter *)0)->stats.pxonrxc) + \
1694+ sizeof(((struct ixgbe_adapter *)0)->stats.pxontxc) + \
1695+ sizeof(((struct ixgbe_adapter *)0)->stats.pxoffrxc) + \
1696+ sizeof(((struct ixgbe_adapter *)0)->stats.pxofftxc)) \
1697+ / sizeof(u64) : 0)
1698+#define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + \
1699+ IXGBE_PB_STATS_LEN + \
1700+ IXGBE_QUEUE_STATS_LEN)
1701
1702 static int ixgbe_get_settings(struct net_device *netdev,
1703 struct ethtool_cmd *ecmd)
1704@@ -809,6 +818,16 @@ static void ixgbe_get_ethtool_stats(stru
1705 data[i + k] = queue_stat[k];
1706 i += k;
1707 }
1708+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
1709+ for (j = 0; j < MAX_TX_PACKET_BUFFERS; j++) {
1710+ data[i++] = adapter->stats.pxontxc[j];
1711+ data[i++] = adapter->stats.pxofftxc[j];
1712+ }
1713+ for (j = 0; j < MAX_RX_PACKET_BUFFERS; j++) {
1714+ data[i++] = adapter->stats.pxonrxc[j];
1715+ data[i++] = adapter->stats.pxoffrxc[j];
1716+ }
1717+ }
1718 }
1719
1720 static void ixgbe_get_strings(struct net_device *netdev, u32 stringset,
1721@@ -837,6 +856,20 @@ static void ixgbe_get_strings(struct net
1722 sprintf(p, "rx_queue_%u_bytes", i);
1723 p += ETH_GSTRING_LEN;
1724 }
1725+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
1726+ for (i = 0; i < MAX_TX_PACKET_BUFFERS; i++) {
1727+ sprintf(p, "tx_pb_%u_pxon", i);
1728+ p += ETH_GSTRING_LEN;
1729+ sprintf(p, "tx_pb_%u_pxoff", i);
1730+ p += ETH_GSTRING_LEN;
1731+ }
1732+ for (i = 0; i < MAX_RX_PACKET_BUFFERS; i++) {
1733+ sprintf(p, "rx_pb_%u_pxon", i);
1734+ p += ETH_GSTRING_LEN;
1735+ sprintf(p, "rx_pb_%u_pxoff", i);
1736+ p += ETH_GSTRING_LEN;
1737+ }
1738+ }
1739 /* BUG_ON(p - data != IXGBE_STATS_LEN * ETH_GSTRING_LEN); */
1740 break;
1741 }
1742--- a/drivers/net/ixgbe/ixgbe.h
1743+++ b/drivers/net/ixgbe/ixgbe.h
1744@@ -40,6 +40,7 @@
1745
1746 #include "ixgbe_type.h"
1747 #include "ixgbe_common.h"
1748+#include "ixgbe_dcb.h"
1749
1750 #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
1751 #include <linux/dca.h>
1752@@ -89,6 +90,7 @@
1753 #define IXGBE_TX_FLAGS_TSO (u32)(1 << 2)
1754 #define IXGBE_TX_FLAGS_IPV4 (u32)(1 << 3)
1755 #define IXGBE_TX_FLAGS_VLAN_MASK 0xffff0000
1756+#define IXGBE_TX_FLAGS_VLAN_PRIO_MASK 0x0000e000
1757 #define IXGBE_TX_FLAGS_VLAN_SHIFT 16
1758
1759 /* wrapper around a pointer to a socket buffer,
1760@@ -136,7 +138,7 @@ struct ixgbe_ring {
1761
1762 u16 reg_idx; /* holds the special value that gets the hardware register
1763 * offset associated with this ring, which is different
1764- * for DCE and RSS modes */
1765+ * for DCB and RSS modes */
1766
1767 #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
1768 /* cpu for tx queue */
1769@@ -156,8 +158,10 @@ struct ixgbe_ring {
1770 u16 rx_buf_len;
1771 };
1772
1773+#define RING_F_DCB 0
1774 #define RING_F_VMDQ 1
1775 #define RING_F_RSS 2
1776+#define IXGBE_MAX_DCB_INDICES 8
1777 #define IXGBE_MAX_RSS_INDICES 16
1778 #define IXGBE_MAX_VMDQ_INDICES 16
1779 struct ixgbe_ring_feature {
1780@@ -168,6 +172,10 @@ struct ixgbe_ring_feature {
1781 #define MAX_RX_QUEUES 64
1782 #define MAX_TX_QUEUES 32
1783
1784+#define MAX_RX_PACKET_BUFFERS ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) \
1785+ ? 8 : 1)
1786+#define MAX_TX_PACKET_BUFFERS MAX_RX_PACKET_BUFFERS
1787+
1788 /* MAX_MSIX_Q_VECTORS of these are allocated,
1789 * but we only use one per queue-specific vector.
1790 */
1791@@ -219,6 +227,9 @@ struct ixgbe_adapter {
1792 struct work_struct reset_task;
1793 struct ixgbe_q_vector q_vector[MAX_MSIX_Q_VECTORS];
1794 char name[MAX_MSIX_COUNT][IFNAMSIZ + 5];
1795+ struct ixgbe_dcb_config dcb_cfg;
1796+ struct ixgbe_dcb_config temp_dcb_cfg;
1797+ u8 dcb_set_bitmap;
1798
1799 /* Interrupt Throttle Rate */
1800 u32 itr_setting;
1801@@ -273,6 +284,7 @@ struct ixgbe_adapter {
1802 #define IXGBE_FLAG_VMDQ_ENABLED (u32)(1 << 19)
1803 #define IXGBE_FLAG_NEED_LINK_UPDATE (u32)(1 << 22)
1804 #define IXGBE_FLAG_IN_WATCHDOG_TASK (u32)(1 << 23)
1805+#define IXGBE_FLAG_DCB_ENABLED (u32)(1 << 24)
1806
1807 /* default to trying for four seconds */
1808 #define IXGBE_TRY_LINK_TIMEOUT (4 * HZ)
1809@@ -318,6 +330,13 @@ enum ixgbe_boards {
1810 };
1811
1812 extern struct ixgbe_info ixgbe_82598_info;
1813+#ifdef CONFIG_DCBNL
1814+extern struct dcbnl_rtnl_ops dcbnl_ops;
1815+extern int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg,
1816+ struct ixgbe_dcb_config *dst_dcb_cfg, int tc_max);
1817+#endif
1818+
1819+
1820
1821 extern char ixgbe_driver_name[];
1822 extern const char ixgbe_driver_version[];
1823@@ -332,5 +351,8 @@ extern int ixgbe_setup_tx_resources(stru
1824 extern void ixgbe_free_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
1825 extern void ixgbe_free_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
1826 extern void ixgbe_update_stats(struct ixgbe_adapter *adapter);
1827-
1828+extern void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter);
1829+extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter);
1830+void ixgbe_napi_add_all(struct ixgbe_adapter *adapter);
1831+void ixgbe_napi_del_all(struct ixgbe_adapter *adapter);
1832 #endif /* _IXGBE_H_ */
1833--- a/drivers/net/ixgbe/ixgbe_main.c
1834+++ b/drivers/net/ixgbe/ixgbe_main.c
1835@@ -403,7 +403,7 @@ static void ixgbe_receive_skb(struct ixg
1836 #ifdef CONFIG_IXGBE_LRO
1837 if (adapter->netdev->features & NETIF_F_LRO &&
1838 skb->ip_summed == CHECKSUM_UNNECESSARY) {
1839- if (adapter->vlgrp && is_vlan)
1840+ if (adapter->vlgrp && is_vlan && (tag != 0))
1841 lro_vlan_hwaccel_receive_skb(&ring->lro_mgr, skb,
1842 adapter->vlgrp, tag,
1843 rx_desc);
1844@@ -413,12 +413,12 @@ static void ixgbe_receive_skb(struct ixg
1845 } else {
1846 #endif
1847 if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
1848- if (adapter->vlgrp && is_vlan)
1849+ if (adapter->vlgrp && is_vlan && (tag != 0))
1850 vlan_hwaccel_receive_skb(skb, adapter->vlgrp, tag);
1851 else
1852 netif_receive_skb(skb);
1853 } else {
1854- if (adapter->vlgrp && is_vlan)
1855+ if (adapter->vlgrp && is_vlan && (tag != 0))
1856 vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
1857 else
1858 netif_rx(skb);
1859@@ -1656,10 +1656,12 @@ static void ixgbe_configure_rx(struct ix
1860 * effects of setting this bit are only that SRRCTL must be
1861 * fully programmed [0..15]
1862 */
1863- rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
1864- rdrxctl |= IXGBE_RDRXCTL_MVMEN;
1865- IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
1866-
1867+ if (adapter->flags &
1868+ (IXGBE_FLAG_RSS_ENABLED | IXGBE_FLAG_VMDQ_ENABLED)) {
1869+ rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
1870+ rdrxctl |= IXGBE_RDRXCTL_MVMEN;
1871+ IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
1872+ }
1873
1874 if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
1875 /* Fill out redirection table */
1876@@ -1718,6 +1720,16 @@ static void ixgbe_vlan_rx_register(struc
1877 ixgbe_irq_disable(adapter);
1878 adapter->vlgrp = grp;
1879
1880+ /*
1881+ * For a DCB driver, always enable VLAN tag stripping so we can
1882+ * still receive traffic from a DCB-enabled host even if we're
1883+ * not in DCB mode.
1884+ */
1885+ ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_VLNCTRL);
1886+ ctrl |= IXGBE_VLNCTRL_VME;
1887+ ctrl &= ~IXGBE_VLNCTRL_CFIEN;
1888+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl);
1889+
1890 if (grp) {
1891 /* enable VLAN tag insert/strip */
1892 ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_VLNCTRL);
1893@@ -1882,6 +1894,42 @@ static void ixgbe_napi_disable_all(struc
1894 }
1895 }
1896
1897+/*
1898+ * ixgbe_configure_dcb - Configure DCB hardware
1899+ * @adapter: ixgbe adapter struct
1900+ *
1901+ * This is called by the driver on open to configure the DCB hardware.
1902+ * This is also called by the gennetlink interface when reconfiguring
1903+ * the DCB state.
1904+ */
1905+static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
1906+{
1907+ struct ixgbe_hw *hw = &adapter->hw;
1908+ u32 txdctl, vlnctrl;
1909+ int i, j;
1910+
1911+ ixgbe_dcb_check_config(&adapter->dcb_cfg);
1912+ ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_TX_CONFIG);
1913+ ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_RX_CONFIG);
1914+
1915+ /* reconfigure the hardware */
1916+ ixgbe_dcb_hw_config(&adapter->hw, &adapter->dcb_cfg);
1917+
1918+ for (i = 0; i < adapter->num_tx_queues; i++) {
1919+ j = adapter->tx_ring[i].reg_idx;
1920+ txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
1921+ /* PThresh workaround for Tx hang with DFP enabled. */
1922+ txdctl |= 32;
1923+ IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
1924+ }
1925+ /* Enable VLAN tag insert/strip */
1926+ vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
1927+ vlnctrl |= IXGBE_VLNCTRL_VME | IXGBE_VLNCTRL_VFE;
1928+ vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
1929+ IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
1930+ hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true);
1931+}
1932+
1933 static void ixgbe_configure(struct ixgbe_adapter *adapter)
1934 {
1935 struct net_device *netdev = adapter->netdev;
1936@@ -1890,6 +1938,12 @@ static void ixgbe_configure(struct ixgbe
1937 ixgbe_set_rx_mode(netdev);
1938
1939 ixgbe_restore_vlan(adapter);
1940+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
1941+ netif_set_gso_max_size(netdev, 32768);
1942+ ixgbe_configure_dcb(adapter);
1943+ } else {
1944+ netif_set_gso_max_size(netdev, 65536);
1945+ }
1946
1947 ixgbe_configure_tx(adapter);
1948 ixgbe_configure_rx(adapter);
1949@@ -2236,6 +2290,11 @@ static void ixgbe_reset_task(struct work
1950 struct ixgbe_adapter *adapter;
1951 adapter = container_of(work, struct ixgbe_adapter, reset_task);
1952
1953+ /* If we're already down or resetting, just bail */
1954+ if (test_bit(__IXGBE_DOWN, &adapter->state) ||
1955+ test_bit(__IXGBE_RESETTING, &adapter->state))
1956+ return;
1957+
1958 adapter->tx_timeout_count++;
1959
1960 ixgbe_reinit_locked(adapter);
1961@@ -2245,15 +2304,31 @@ static void ixgbe_set_num_queues(struct
1962 {
1963 int nrq = 1, ntq = 1;
1964 int feature_mask = 0, rss_i, rss_m;
1965+ int dcb_i, dcb_m;
1966
1967 /* Number of supported queues */
1968 switch (adapter->hw.mac.type) {
1969 case ixgbe_mac_82598EB:
1970+ dcb_i = adapter->ring_feature[RING_F_DCB].indices;
1971+ dcb_m = 0;
1972 rss_i = adapter->ring_feature[RING_F_RSS].indices;
1973 rss_m = 0;
1974 feature_mask |= IXGBE_FLAG_RSS_ENABLED;
1975+ feature_mask |= IXGBE_FLAG_DCB_ENABLED;
1976
1977 switch (adapter->flags & feature_mask) {
1978+ case (IXGBE_FLAG_RSS_ENABLED | IXGBE_FLAG_DCB_ENABLED):
1979+ dcb_m = 0x7 << 3;
1980+ rss_i = min(8, rss_i);
1981+ rss_m = 0x7;
1982+ nrq = dcb_i * rss_i;
1983+ ntq = min(MAX_TX_QUEUES, dcb_i * rss_i);
1984+ break;
1985+ case (IXGBE_FLAG_DCB_ENABLED):
1986+ dcb_m = 0x7 << 3;
1987+ nrq = dcb_i;
1988+ ntq = dcb_i;
1989+ break;
1990 case (IXGBE_FLAG_RSS_ENABLED):
1991 rss_m = 0xF;
1992 nrq = rss_i;
1993@@ -2261,6 +2336,8 @@ static void ixgbe_set_num_queues(struct
1994 break;
1995 case 0:
1996 default:
1997+ dcb_i = 0;
1998+ dcb_m = 0;
1999 rss_i = 0;
2000 rss_m = 0;
2001 nrq = 1;
2002@@ -2268,6 +2345,12 @@ static void ixgbe_set_num_queues(struct
2003 break;
2004 }
2005
2006+ /* Sanity check, we should never have zero queues */
2007+ nrq = (nrq ?:1);
2008+ ntq = (ntq ?:1);
2009+
2010+ adapter->ring_feature[RING_F_DCB].indices = dcb_i;
2011+ adapter->ring_feature[RING_F_DCB].mask = dcb_m;
2012 adapter->ring_feature[RING_F_RSS].indices = rss_i;
2013 adapter->ring_feature[RING_F_RSS].mask = rss_m;
2014 break;
2015@@ -2319,6 +2402,7 @@ static void ixgbe_acquire_msix_vectors(s
2016 adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
2017 kfree(adapter->msix_entries);
2018 adapter->msix_entries = NULL;
2019+ adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
2020 adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
2021 ixgbe_set_num_queues(adapter);
2022 } else {
2023@@ -2338,15 +2422,42 @@ static void __devinit ixgbe_cache_ring_r
2024 {
2025 int feature_mask = 0, rss_i;
2026 int i, txr_idx, rxr_idx;
2027+ int dcb_i;
2028
2029 /* Number of supported queues */
2030 switch (adapter->hw.mac.type) {
2031 case ixgbe_mac_82598EB:
2032+ dcb_i = adapter->ring_feature[RING_F_DCB].indices;
2033 rss_i = adapter->ring_feature[RING_F_RSS].indices;
2034 txr_idx = 0;
2035 rxr_idx = 0;
2036+ feature_mask |= IXGBE_FLAG_DCB_ENABLED;
2037 feature_mask |= IXGBE_FLAG_RSS_ENABLED;
2038 switch (adapter->flags & feature_mask) {
2039+ case (IXGBE_FLAG_RSS_ENABLED | IXGBE_FLAG_DCB_ENABLED):
2040+ for (i = 0; i < dcb_i; i++) {
2041+ int j;
2042+ /* Rx first */
2043+ for (j = 0; j < adapter->num_rx_queues; j++) {
2044+ adapter->rx_ring[rxr_idx].reg_idx =
2045+ i << 3 | j;
2046+ rxr_idx++;
2047+ }
2048+ /* Tx now */
2049+ for (j = 0; j < adapter->num_tx_queues; j++) {
2050+ adapter->tx_ring[txr_idx].reg_idx =
2051+ i << 2 | (j >> 1);
2052+ if (j & 1)
2053+ txr_idx++;
2054+ }
2055+ }
2056+ case (IXGBE_FLAG_DCB_ENABLED):
2057+ /* the number of queues is assumed to be symmetric */
2058+ for (i = 0; i < dcb_i; i++) {
2059+ adapter->rx_ring[i].reg_idx = i << 3;
2060+ adapter->tx_ring[i].reg_idx = i << 2;
2061+ }
2062+ break;
2063 case (IXGBE_FLAG_RSS_ENABLED):
2064 for (i = 0; i < adapter->num_rx_queues; i++)
2065 adapter->rx_ring[i].reg_idx = i;
2066@@ -2371,7 +2482,7 @@ static void __devinit ixgbe_cache_ring_r
2067 * number of queues at compile-time. The polling_netdev array is
2068 * intended for Multiqueue, but should work fine with a single queue.
2069 **/
2070-static int __devinit ixgbe_alloc_queues(struct ixgbe_adapter *adapter)
2071+static int ixgbe_alloc_queues(struct ixgbe_adapter *adapter)
2072 {
2073 int i;
2074
2075@@ -2412,8 +2523,7 @@ err_tx_ring_allocation:
2076 * Attempt to configure the interrupts using the best available
2077 * capabilities of the hardware and the kernel.
2078 **/
2079-static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter
2080- *adapter)
2081+static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter)
2082 {
2083 int err = 0;
2084 int vector, v_budget;
2085@@ -2441,6 +2551,7 @@ static int __devinit ixgbe_set_interrupt
2086 adapter->msix_entries = kcalloc(v_budget,
2087 sizeof(struct msix_entry), GFP_KERNEL);
2088 if (!adapter->msix_entries) {
2089+ adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
2090 adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
2091 ixgbe_set_num_queues(adapter);
2092 kfree(adapter->tx_ring);
2093@@ -2481,7 +2592,7 @@ out:
2094 return err;
2095 }
2096
2097-static void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter)
2098+void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter)
2099 {
2100 if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
2101 adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
2102@@ -2505,7 +2616,7 @@ static void ixgbe_reset_interrupt_capabi
2103 * - Hardware queue count (num_*_queues)
2104 * - defined by miscellaneous hardware support/features (RSS, etc.)
2105 **/
2106-static int __devinit ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
2107+int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
2108 {
2109 int err;
2110
2111@@ -2553,6 +2664,8 @@ static int __devinit ixgbe_sw_init(struc
2112 struct ixgbe_hw *hw = &adapter->hw;
2113 struct pci_dev *pdev = adapter->pdev;
2114 unsigned int rss;
2115+ int j;
2116+ struct tc_configuration *tc;
2117
2118 /* PCI config space info */
2119
2120@@ -2566,6 +2679,26 @@ static int __devinit ixgbe_sw_init(struc
2121 rss = min(IXGBE_MAX_RSS_INDICES, (int)num_online_cpus());
2122 adapter->ring_feature[RING_F_RSS].indices = rss;
2123 adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
2124+ adapter->ring_feature[RING_F_DCB].indices = IXGBE_MAX_DCB_INDICES;
2125+
2126+ /* Configure DCB traffic classes */
2127+ for (j = 0; j < MAX_TRAFFIC_CLASS; j++) {
2128+ tc = &adapter->dcb_cfg.tc_config[j];
2129+ tc->path[DCB_TX_CONFIG].bwg_id = 0;
2130+ tc->path[DCB_TX_CONFIG].bwg_percent = 12 + (j & 1);
2131+ tc->path[DCB_RX_CONFIG].bwg_id = 0;
2132+ tc->path[DCB_RX_CONFIG].bwg_percent = 12 + (j & 1);
2133+ tc->dcb_pfc = pfc_disabled;
2134+ }
2135+ adapter->dcb_cfg.bw_percentage[DCB_TX_CONFIG][0] = 100;
2136+ adapter->dcb_cfg.bw_percentage[DCB_RX_CONFIG][0] = 100;
2137+ adapter->dcb_cfg.rx_pba_cfg = pba_equal;
2138+ adapter->dcb_cfg.round_robin_enable = false;
2139+ adapter->dcb_set_bitmap = 0x00;
2140+#ifdef CONFIG_DCBNL
2141+ ixgbe_copy_dcb_cfg(&adapter->dcb_cfg, &adapter->temp_dcb_cfg,
2142+ adapter->ring_feature[RING_F_DCB].indices);
2143+#endif
2144
2145 /* default flow control settings */
2146 hw->fc.original_type = ixgbe_fc_none;
2147@@ -2945,7 +3078,7 @@ static int ixgbe_close(struct net_device
2148 * @adapter: private struct
2149 * helper function to napi_add each possible q_vector->napi
2150 */
2151-static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter)
2152+void ixgbe_napi_add_all(struct ixgbe_adapter *adapter)
2153 {
2154 int q_idx, q_vectors;
2155 int (*poll)(struct napi_struct *, int);
2156@@ -2966,7 +3099,7 @@ static void ixgbe_napi_add_all(struct ix
2157 }
2158 }
2159
2160-static void ixgbe_napi_del_all(struct ixgbe_adapter *adapter)
2161+void ixgbe_napi_del_all(struct ixgbe_adapter *adapter)
2162 {
2163 int q_idx;
2164 int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
2165@@ -3087,6 +3220,18 @@ void ixgbe_update_stats(struct ixgbe_ada
2166 adapter->stats.mpc[i] += mpc;
2167 total_mpc += adapter->stats.mpc[i];
2168 adapter->stats.rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i));
2169+ adapter->stats.qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
2170+ adapter->stats.qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC(i));
2171+ adapter->stats.qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
2172+ adapter->stats.qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC(i));
2173+ adapter->stats.pxonrxc[i] += IXGBE_READ_REG(hw,
2174+ IXGBE_PXONRXC(i));
2175+ adapter->stats.pxontxc[i] += IXGBE_READ_REG(hw,
2176+ IXGBE_PXONTXC(i));
2177+ adapter->stats.pxoffrxc[i] += IXGBE_READ_REG(hw,
2178+ IXGBE_PXOFFRXC(i));
2179+ adapter->stats.pxofftxc[i] += IXGBE_READ_REG(hw,
2180+ IXGBE_PXOFFTXC(i));
2181 }
2182 adapter->stats.gprc += IXGBE_READ_REG(hw, IXGBE_GPRC);
2183 /* work around hardware counting issue */
2184@@ -3584,6 +3729,14 @@ static int ixgbe_xmit_frame(struct sk_bu
2185
2186 if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
2187 tx_flags |= vlan_tx_tag_get(skb);
2188+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
2189+ tx_flags &= ~IXGBE_TX_FLAGS_VLAN_PRIO_MASK;
2190+ tx_flags |= (skb->queue_mapping << 13);
2191+ }
2192+ tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
2193+ tx_flags |= IXGBE_TX_FLAGS_VLAN;
2194+ } else if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
2195+ tx_flags |= (skb->queue_mapping << 13);
2196 tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
2197 tx_flags |= IXGBE_TX_FLAGS_VLAN;
2198 }
2199@@ -3852,6 +4005,13 @@ static int __devinit ixgbe_probe(struct
2200 netdev->vlan_features |= NETIF_F_IP_CSUM;
2201 netdev->vlan_features |= NETIF_F_SG;
2202
2203+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
2204+ adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
2205+
2206+#ifdef CONFIG_DCBNL
2207+ netdev->dcbnl_ops = &dcbnl_ops;
2208+#endif
2209+
2210 if (pci_using_dac)
2211 netdev->features |= NETIF_F_HIGHDMA;
2212
2213@@ -4108,7 +4268,6 @@ static struct pci_driver ixgbe_driver =
2214 **/
2215 static int __init ixgbe_init_module(void)
2216 {
2217- int ret;
2218 printk(KERN_INFO "%s: %s - version %s\n", ixgbe_driver_name,
2219 ixgbe_driver_string, ixgbe_driver_version);
2220
2221@@ -4118,8 +4277,7 @@ static int __init ixgbe_init_module(void
2222 dca_register_notify(&dca_notifier);
2223
2224 #endif
2225- ret = pci_register_driver(&ixgbe_driver);
2226- return ret;
2227+ return pci_register_driver(&ixgbe_driver);
2228 }
2229
2230 module_init(ixgbe_init_module);
2231--- a/drivers/net/ixgbe/Makefile
2232+++ b/drivers/net/ixgbe/Makefile
2233@@ -33,4 +33,5 @@
2234 obj-$(CONFIG_IXGBE) += ixgbe.o
2235
2236 ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \
2237- ixgbe_82598.o ixgbe_phy.o
2238+ ixgbe_82598.o ixgbe_phy.o ixgbe_dcb.o ixgbe_dcb_82598.o \
2239+ ixgbe_dcb_nl.o
2240--- /dev/null
2241+++ b/include/linux/dcbnl.h
2242@@ -0,0 +1,324 @@
2243+#ifndef __LINUX_DCBNL_H__
2244+#define __LINUX_DCBNL_H__
2245+/*
2246+ * Data Center Bridging (DCB) netlink header
2247+ *
2248+ * Copyright 2008, Lucy Liu <lucy.liu@intel.com>
2249+ */
2250+
2251+#define DCB_PROTO_VERSION 1
2252+
2253+struct dcbmsg {
2254+ unsigned char dcb_family;
2255+ __u8 cmd;
2256+ __u16 dcb_pad;
2257+};
2258+
2259+/**
2260+ * enum dcbnl_commands - supported DCB commands
2261+ *
2262+ * @DCB_CMD_UNDEFINED: unspecified command to catch errors
2263+ * @DCB_CMD_GSTATE: request the state of DCB in the device
2264+ * @DCB_CMD_SSTATE: set the state of DCB in the device
2265+ * @DCB_CMD_PGTX_GCFG: request the priority group configuration for Tx
2266+ * @DCB_CMD_PGTX_SCFG: set the priority group configuration for Tx
2267+ * @DCB_CMD_PGRX_GCFG: request the priority group configuration for Rx
2268+ * @DCB_CMD_PGRX_SCFG: set the priority group configuration for Rx
2269+ * @DCB_CMD_PFC_GCFG: request the priority flow control configuration
2270+ * @DCB_CMD_PFC_SCFG: set the priority flow control configuration
2271+ * @DCB_CMD_SET_ALL: apply all changes to the underlying device
2272+ * @DCB_CMD_GPERM_HWADDR: get the permanent MAC address of the underlying
2273+ * device. Only useful when using bonding.
2274+ * @DCB_CMD_GCAP: request the DCB capabilities of the device
2275+ * @DCB_CMD_GNUMTCS: get the number of traffic classes currently supported
2276+ * @DCB_CMD_SNUMTCS: set the number of traffic classes
2277+ * @DCB_CMD_GBCN: set backward congestion notification configuration
2278+ * @DCB_CMD_SBCN: get backward congestion notification configration.
2279+ */
2280+enum dcbnl_commands {
2281+ DCB_CMD_UNDEFINED,
2282+
2283+ DCB_CMD_GSTATE,
2284+ DCB_CMD_SSTATE,
2285+
2286+ DCB_CMD_PGTX_GCFG,
2287+ DCB_CMD_PGTX_SCFG,
2288+ DCB_CMD_PGRX_GCFG,
2289+ DCB_CMD_PGRX_SCFG,
2290+
2291+ DCB_CMD_PFC_GCFG,
2292+ DCB_CMD_PFC_SCFG,
2293+
2294+ DCB_CMD_SET_ALL,
2295+
2296+ DCB_CMD_GPERM_HWADDR,
2297+
2298+ DCB_CMD_GCAP,
2299+
2300+ DCB_CMD_GNUMTCS,
2301+ DCB_CMD_SNUMTCS,
2302+
2303+ DCB_CMD_PFC_GSTATE,
2304+ DCB_CMD_PFC_SSTATE,
2305+
2306+ DCB_CMD_BCN_GCFG,
2307+ DCB_CMD_BCN_SCFG,
2308+
2309+ __DCB_CMD_ENUM_MAX,
2310+ DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1,
2311+};
2312+
2313+/**
2314+ * enum dcbnl_attrs - DCB top-level netlink attributes
2315+ *
2316+ * @DCB_ATTR_UNDEFINED: unspecified attribute to catch errors
2317+ * @DCB_ATTR_IFNAME: interface name of the underlying device (NLA_STRING)
2318+ * @DCB_ATTR_STATE: enable state of DCB in the device (NLA_U8)
2319+ * @DCB_ATTR_PFC_STATE: enable state of PFC in the device (NLA_U8)
2320+ * @DCB_ATTR_PFC_CFG: priority flow control configuration (NLA_NESTED)
2321+ * @DCB_ATTR_NUM_TC: number of traffic classes supported in the device (NLA_U8)
2322+ * @DCB_ATTR_PG_CFG: priority group configuration (NLA_NESTED)
2323+ * @DCB_ATTR_SET_ALL: bool to commit changes to hardware or not (NLA_U8)
2324+ * @DCB_ATTR_PERM_HWADDR: MAC address of the physical device (NLA_NESTED)
2325+ * @DCB_ATTR_CAP: DCB capabilities of the device (NLA_NESTED)
2326+ * @DCB_ATTR_NUMTCS: number of traffic classes supported (NLA_NESTED)
2327+ * @DCB_ATTR_BCN: backward congestion notification configuration (NLA_NESTED)
2328+ */
2329+enum dcbnl_attrs {
2330+ DCB_ATTR_UNDEFINED,
2331+
2332+ DCB_ATTR_IFNAME,
2333+ DCB_ATTR_STATE,
2334+ DCB_ATTR_PFC_STATE,
2335+ DCB_ATTR_PFC_CFG,
2336+ DCB_ATTR_NUM_TC,
2337+ DCB_ATTR_PG_CFG,
2338+ DCB_ATTR_SET_ALL,
2339+ DCB_ATTR_PERM_HWADDR,
2340+ DCB_ATTR_CAP,
2341+ DCB_ATTR_NUMTCS,
2342+ DCB_ATTR_BCN,
2343+
2344+ __DCB_ATTR_ENUM_MAX,
2345+ DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1,
2346+};
2347+
2348+/**
2349+ * enum dcbnl_pfc_attrs - DCB Priority Flow Control user priority nested attrs
2350+ *
2351+ * @DCB_PFC_UP_ATTR_UNDEFINED: unspecified attribute to catch errors
2352+ * @DCB_PFC_UP_ATTR_0: Priority Flow Control value for User Priority 0 (NLA_U8)
2353+ * @DCB_PFC_UP_ATTR_1: Priority Flow Control value for User Priority 1 (NLA_U8)
2354+ * @DCB_PFC_UP_ATTR_2: Priority Flow Control value for User Priority 2 (NLA_U8)
2355+ * @DCB_PFC_UP_ATTR_3: Priority Flow Control value for User Priority 3 (NLA_U8)
2356+ * @DCB_PFC_UP_ATTR_4: Priority Flow Control value for User Priority 4 (NLA_U8)
2357+ * @DCB_PFC_UP_ATTR_5: Priority Flow Control value for User Priority 5 (NLA_U8)
2358+ * @DCB_PFC_UP_ATTR_6: Priority Flow Control value for User Priority 6 (NLA_U8)
2359+ * @DCB_PFC_UP_ATTR_7: Priority Flow Control value for User Priority 7 (NLA_U8)
2360+ * @DCB_PFC_UP_ATTR_MAX: highest attribute number currently defined
2361+ * @DCB_PFC_UP_ATTR_ALL: apply to all priority flow control attrs (NLA_FLAG)
2362+ *
2363+ */
2364+enum dcbnl_pfc_up_attrs {
2365+ DCB_PFC_UP_ATTR_UNDEFINED,
2366+
2367+ DCB_PFC_UP_ATTR_0,
2368+ DCB_PFC_UP_ATTR_1,
2369+ DCB_PFC_UP_ATTR_2,
2370+ DCB_PFC_UP_ATTR_3,
2371+ DCB_PFC_UP_ATTR_4,
2372+ DCB_PFC_UP_ATTR_5,
2373+ DCB_PFC_UP_ATTR_6,
2374+ DCB_PFC_UP_ATTR_7,
2375+ DCB_PFC_UP_ATTR_ALL,
2376+
2377+ __DCB_PFC_UP_ATTR_ENUM_MAX,
2378+ DCB_PFC_UP_ATTR_MAX = __DCB_PFC_UP_ATTR_ENUM_MAX - 1,
2379+};
2380+
2381+/**
2382+ * enum dcbnl_pg_attrs - DCB Priority Group attributes
2383+ *
2384+ * @DCB_PG_ATTR_UNDEFINED: unspecified attribute to catch errors
2385+ * @DCB_PG_ATTR_TC_0: Priority Group Traffic Class 0 configuration (NLA_NESTED)
2386+ * @DCB_PG_ATTR_TC_1: Priority Group Traffic Class 1 configuration (NLA_NESTED)
2387+ * @DCB_PG_ATTR_TC_2: Priority Group Traffic Class 2 configuration (NLA_NESTED)
2388+ * @DCB_PG_ATTR_TC_3: Priority Group Traffic Class 3 configuration (NLA_NESTED)
2389+ * @DCB_PG_ATTR_TC_4: Priority Group Traffic Class 4 configuration (NLA_NESTED)
2390+ * @DCB_PG_ATTR_TC_5: Priority Group Traffic Class 5 configuration (NLA_NESTED)
2391+ * @DCB_PG_ATTR_TC_6: Priority Group Traffic Class 6 configuration (NLA_NESTED)
2392+ * @DCB_PG_ATTR_TC_7: Priority Group Traffic Class 7 configuration (NLA_NESTED)
2393+ * @DCB_PG_ATTR_TC_MAX: highest attribute number currently defined
2394+ * @DCB_PG_ATTR_TC_ALL: apply to all traffic classes (NLA_NESTED)
2395+ * @DCB_PG_ATTR_BW_ID_0: Percent of link bandwidth for Priority Group 0 (NLA_U8)
2396+ * @DCB_PG_ATTR_BW_ID_1: Percent of link bandwidth for Priority Group 1 (NLA_U8)
2397+ * @DCB_PG_ATTR_BW_ID_2: Percent of link bandwidth for Priority Group 2 (NLA_U8)
2398+ * @DCB_PG_ATTR_BW_ID_3: Percent of link bandwidth for Priority Group 3 (NLA_U8)
2399+ * @DCB_PG_ATTR_BW_ID_4: Percent of link bandwidth for Priority Group 4 (NLA_U8)
2400+ * @DCB_PG_ATTR_BW_ID_5: Percent of link bandwidth for Priority Group 5 (NLA_U8)
2401+ * @DCB_PG_ATTR_BW_ID_6: Percent of link bandwidth for Priority Group 6 (NLA_U8)
2402+ * @DCB_PG_ATTR_BW_ID_7: Percent of link bandwidth for Priority Group 7 (NLA_U8)
2403+ * @DCB_PG_ATTR_BW_ID_MAX: highest attribute number currently defined
2404+ * @DCB_PG_ATTR_BW_ID_ALL: apply to all priority groups (NLA_FLAG)
2405+ *
2406+ */
2407+enum dcbnl_pg_attrs {
2408+ DCB_PG_ATTR_UNDEFINED,
2409+
2410+ DCB_PG_ATTR_TC_0,
2411+ DCB_PG_ATTR_TC_1,
2412+ DCB_PG_ATTR_TC_2,
2413+ DCB_PG_ATTR_TC_3,
2414+ DCB_PG_ATTR_TC_4,
2415+ DCB_PG_ATTR_TC_5,
2416+ DCB_PG_ATTR_TC_6,
2417+ DCB_PG_ATTR_TC_7,
2418+ DCB_PG_ATTR_TC_MAX,
2419+ DCB_PG_ATTR_TC_ALL,
2420+
2421+ DCB_PG_ATTR_BW_ID_0,
2422+ DCB_PG_ATTR_BW_ID_1,
2423+ DCB_PG_ATTR_BW_ID_2,
2424+ DCB_PG_ATTR_BW_ID_3,
2425+ DCB_PG_ATTR_BW_ID_4,
2426+ DCB_PG_ATTR_BW_ID_5,
2427+ DCB_PG_ATTR_BW_ID_6,
2428+ DCB_PG_ATTR_BW_ID_7,
2429+ DCB_PG_ATTR_BW_ID_MAX,
2430+ DCB_PG_ATTR_BW_ID_ALL,
2431+
2432+ __DCB_PG_ATTR_ENUM_MAX,
2433+ DCB_PG_ATTR_MAX = __DCB_PG_ATTR_ENUM_MAX - 1,
2434+};
2435+
2436+/**
2437+ * enum dcbnl_tc_attrs - DCB Traffic Class attributes
2438+ *
2439+ * @DCB_TC_ATTR_PARAM_UNDEFINED: unspecified attribute to catch errors
2440+ * @DCB_TC_ATTR_PARAM_PGID: (NLA_U8) Priority group the traffic class belongs to
2441+ * Valid values are: 0-7
2442+ * @DCB_TC_ATTR_PARAM_UP_MAPPING: (NLA_U8) Traffic class to user priority map
2443+ * Some devices may not support changing the
2444+ * user priority map of a TC.
2445+ * @DCB_TC_ATTR_PARAM_STRICT_PRIO: (NLA_U8) Strict priority setting
2446+ * 0 - none
2447+ * 1 - group strict
2448+ * 2 - link strict
2449+ * @DCB_TC_ATTR_PARAM_BW_PCT: optional - (NLA_U8) If supported by the device and
2450+ * not configured to use link strict priority,
2451+ * this is the percentage of bandwidth of the
2452+ * priority group this traffic class belongs to
2453+ * @DCB_TC_ATTR_PARAM_ALL: (NLA_FLAG) all traffic class parameters
2454+ *
2455+ */
2456+enum dcbnl_tc_attrs {
2457+ DCB_TC_ATTR_PARAM_UNDEFINED,
2458+
2459+ DCB_TC_ATTR_PARAM_PGID,
2460+ DCB_TC_ATTR_PARAM_UP_MAPPING,
2461+ DCB_TC_ATTR_PARAM_STRICT_PRIO,
2462+ DCB_TC_ATTR_PARAM_BW_PCT,
2463+ DCB_TC_ATTR_PARAM_ALL,
2464+
2465+ __DCB_TC_ATTR_PARAM_ENUM_MAX,
2466+ DCB_TC_ATTR_PARAM_MAX = __DCB_TC_ATTR_PARAM_ENUM_MAX - 1,
2467+};
2468+
2469+/**
2470+ * enum dcbnl_cap_attrs - DCB Capability attributes
2471+ *
2472+ * @DCB_CAP_ATTR_UNDEFINED: unspecified attribute to catch errors
2473+ * @DCB_CAP_ATTR_ALL: (NLA_FLAG) all capability parameters
2474+ * @DCB_CAP_ATTR_PG: (NLA_U8) device supports Priority Groups
2475+ * @DCB_CAP_ATTR_PFC: (NLA_U8) device supports Priority Flow Control
2476+ * @DCB_CAP_ATTR_UP2TC: (NLA_U8) device supports user priority to
2477+ * traffic class mapping
2478+ * @DCB_CAP_ATTR_PG_TCS: (NLA_U8) bitmap where each bit represents a
2479+ * number of traffic classes the device
2480+ * can be configured to use for Priority Groups
2481+ * @DCB_CAP_ATTR_PFC_TCS: (NLA_U8) bitmap where each bit represents a
2482+ * number of traffic classes the device can be
2483+ * configured to use for Priority Flow Control
2484+ * @DCB_CAP_ATTR_GSP: (NLA_U8) device supports group strict priority
2485+ * @DCB_CAP_ATTR_BCN: (NLA_U8) device supports Backwards Congestion
2486+ * Notification
2487+ */
2488+enum dcbnl_cap_attrs {
2489+ DCB_CAP_ATTR_UNDEFINED,
2490+ DCB_CAP_ATTR_ALL,
2491+ DCB_CAP_ATTR_PG,
2492+ DCB_CAP_ATTR_PFC,
2493+ DCB_CAP_ATTR_UP2TC,
2494+ DCB_CAP_ATTR_PG_TCS,
2495+ DCB_CAP_ATTR_PFC_TCS,
2496+ DCB_CAP_ATTR_GSP,
2497+ DCB_CAP_ATTR_BCN,
2498+
2499+ __DCB_CAP_ATTR_ENUM_MAX,
2500+ DCB_CAP_ATTR_MAX = __DCB_CAP_ATTR_ENUM_MAX - 1,
2501+};
2502+
2503+/**
2504+ * enum dcbnl_numtcs_attrs - number of traffic classes
2505+ *
2506+ * @DCB_NUMTCS_ATTR_UNDEFINED: unspecified attribute to catch errors
2507+ * @DCB_NUMTCS_ATTR_ALL: (NLA_FLAG) all traffic class attributes
2508+ * @DCB_NUMTCS_ATTR_PG: (NLA_U8) number of traffic classes used for
2509+ * priority groups
2510+ * @DCB_NUMTCS_ATTR_PFC: (NLA_U8) number of traffic classes which can
2511+ * support priority flow control
2512+ */
2513+enum dcbnl_numtcs_attrs {
2514+ DCB_NUMTCS_ATTR_UNDEFINED,
2515+ DCB_NUMTCS_ATTR_ALL,
2516+ DCB_NUMTCS_ATTR_PG,
2517+ DCB_NUMTCS_ATTR_PFC,
2518+
2519+ __DCB_NUMTCS_ATTR_ENUM_MAX,
2520+ DCB_NUMTCS_ATTR_MAX = __DCB_NUMTCS_ATTR_ENUM_MAX - 1,
2521+};
2522+
2523+enum dcbnl_bcn_attrs{
2524+ DCB_BCN_ATTR_UNDEFINED = 0,
2525+
2526+ DCB_BCN_ATTR_RP_0,
2527+ DCB_BCN_ATTR_RP_1,
2528+ DCB_BCN_ATTR_RP_2,
2529+ DCB_BCN_ATTR_RP_3,
2530+ DCB_BCN_ATTR_RP_4,
2531+ DCB_BCN_ATTR_RP_5,
2532+ DCB_BCN_ATTR_RP_6,
2533+ DCB_BCN_ATTR_RP_7,
2534+ DCB_BCN_ATTR_RP_ALL,
2535+
2536+ DCB_BCN_ATTR_ALPHA,
2537+ DCB_BCN_ATTR_BETA,
2538+ DCB_BCN_ATTR_GD,
2539+ DCB_BCN_ATTR_GI,
2540+ DCB_BCN_ATTR_TMAX,
2541+ DCB_BCN_ATTR_TD,
2542+ DCB_BCN_ATTR_RMIN,
2543+ DCB_BCN_ATTR_W,
2544+ DCB_BCN_ATTR_RD,
2545+ DCB_BCN_ATTR_RU,
2546+ DCB_BCN_ATTR_WRTT,
2547+ DCB_BCN_ATTR_RI,
2548+ DCB_BCN_ATTR_C,
2549+ DCB_BCN_ATTR_ALL,
2550+
2551+ __DCB_BCN_ATTR_ENUM_MAX,
2552+ DCB_BCN_ATTR_MAX = __DCB_BCN_ATTR_ENUM_MAX - 1,
2553+};
2554+
2555+/**
2556+ * enum dcb_general_attr_values - general DCB attribute values
2557+ *
2558+ * @DCB_ATTR_UNDEFINED: value used to indicate an attribute is not supported
2559+ *
2560+ */
2561+enum dcb_general_attr_values {
2562+ DCB_ATTR_VALUE_UNDEFINED = 0xff
2563+};
2564+
2565+
2566+#endif /* __LINUX_DCBNL_H__ */
2567--- a/include/linux/netdevice.h
2568+++ b/include/linux/netdevice.h
2569@@ -42,6 +42,9 @@
2570 #include <linux/workqueue.h>
2571
2572 #include <net/net_namespace.h>
2573+#ifdef CONFIG_DCBNL
2574+#include <net/dcbnl.h>
2575+#endif
2576
2577 struct vlan_group;
2578 struct ethtool_ops;
2579@@ -749,6 +752,11 @@ struct net_device
2580 /* for setting kernel sock attribute on TCP connection setup */
2581 #define GSO_MAX_SIZE 65536
2582 unsigned int gso_max_size;
2583+
2584+#ifdef CONFIG_DCBNL
2585+ /* Data Center Bridging netlink ops */
2586+ struct dcbnl_rtnl_ops *dcbnl_ops;
2587+#endif
2588 };
2589 #define to_net_dev(d) container_of(d, struct net_device, dev)
2590
2591--- a/include/linux/rtnetlink.h
2592+++ b/include/linux/rtnetlink.h
2593@@ -107,6 +107,11 @@ enum {
2594 RTM_GETADDRLABEL,
2595 #define RTM_GETADDRLABEL RTM_GETADDRLABEL
2596
2597+ RTM_GETDCB = 78,
2598+#define RTM_GETDCB RTM_GETDCB
2599+ RTM_SETDCB,
2600+#define RTM_SETDCB RTM_SETDCB
2601+
2602 __RTM_MAX,
2603 #define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
2604 };
2605--- /dev/null
2606+++ b/include/net/dcbnl.h
2607@@ -0,0 +1,40 @@
2608+#ifndef __NET_DCBNL_H__
2609+#define __NET_DCBNL_H__
2610+/*
2611+ * Data Center Bridging (DCB) netlink operations
2612+ *
2613+ * Copyright 2008, Lucy Liu <lucy.liu@intel.com>
2614+ */
2615+
2616+
2617+/*
2618+ * Ops struct for the netlink callbacks. Used by DCB-enabled drivers through
2619+ * the netdevice struct.
2620+ */
2621+struct dcbnl_rtnl_ops {
2622+ u8 (*getstate)(struct net_device *);
2623+ void (*setstate)(struct net_device *, u8);
2624+ void (*getpermhwaddr)(struct net_device *, u8 *);
2625+ void (*setpgtccfgtx)(struct net_device *, int, u8, u8, u8, u8);
2626+ void (*setpgbwgcfgtx)(struct net_device *, int, u8);
2627+ void (*setpgtccfgrx)(struct net_device *, int, u8, u8, u8, u8);
2628+ void (*setpgbwgcfgrx)(struct net_device *, int, u8);
2629+ void (*getpgtccfgtx)(struct net_device *, int, u8 *, u8 *, u8 *, u8 *);
2630+ void (*getpgbwgcfgtx)(struct net_device *, int, u8 *);
2631+ void (*getpgtccfgrx)(struct net_device *, int, u8 *, u8 *, u8 *, u8 *);
2632+ void (*getpgbwgcfgrx)(struct net_device *, int, u8 *);
2633+ void (*setpfccfg)(struct net_device *, int, u8);
2634+ void (*getpfccfg)(struct net_device *, int, u8 *);
2635+ u8 (*setall)(struct net_device *);
2636+ u8 (*getcap)(struct net_device *, int, u8 *);
2637+ u8 (*getnumtcs)(struct net_device *, int, u8 *);
2638+ u8 (*setnumtcs)(struct net_device *, int, u8);
2639+ u8 (*getpfcstate)(struct net_device *);
2640+ void (*setpfcstate)(struct net_device *, u8);
2641+ void (*getbcncfg)(struct net_device *, int, u32 *);
2642+ void (*setbcncfg)(struct net_device *, int, u32);
2643+ void (*getbcnrp)(struct net_device *, int, u8 *);
2644+ void (*setbcnrp)(struct net_device *, int, u8);
2645+};
2646+
2647+#endif /* __NET_DCBNL_H__ */
2648--- /dev/null
2649+++ b/net/dcb/dcbnl.c
2650@@ -0,0 +1,1091 @@
2651+/*
2652+ * This is the Data Center Bridging configuration interface.
2653+ *
2654+ * Copyright 2008, Lucy Liu <lucy.liu@intel.com>
2655+ *
2656+ */
2657+
2658+#include <linux/netdevice.h>
2659+#include <linux/netlink.h>
2660+#include <net/netlink.h>
2661+#include <net/rtnetlink.h>
2662+#include <linux/dcbnl.h>
2663+#include <linux/rtnetlink.h>
2664+#include <net/sock.h>
2665+
2666+MODULE_AUTHOR("Lucy Liu, <lucy.liu@intel.com>");
2667+MODULE_DESCRIPTION("Data Center Bridging generic netlink interface");
2668+MODULE_LICENSE("GPL");
2669+
2670+/**************** DCB attribute policies *************************************/
2671+
2672+/* DCB netlink attributes policy */
2673+static struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = {
2674+ [DCB_ATTR_IFNAME] = {.type = NLA_NUL_STRING, .len = IFNAMSIZ - 1},
2675+ [DCB_ATTR_STATE] = {.type = NLA_U8},
2676+ [DCB_ATTR_PFC_CFG] = {.type = NLA_NESTED},
2677+ [DCB_ATTR_PG_CFG] = {.type = NLA_NESTED},
2678+ [DCB_ATTR_SET_ALL] = {.type = NLA_U8},
2679+ [DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG},
2680+ [DCB_ATTR_CAP] = {.type = NLA_NESTED},
2681+ [DCB_ATTR_PFC_STATE] = {.type = NLA_U8},
2682+ [DCB_ATTR_BCN] = {.type = NLA_NESTED},
2683+};
2684+
2685+/* DCB priority flow control to User Priority nested attributes */
2686+static struct nla_policy dcbnl_pfc_up_nest[DCB_PFC_UP_ATTR_MAX + 1] = {
2687+ [DCB_PFC_UP_ATTR_0] = {.type = NLA_U8},
2688+ [DCB_PFC_UP_ATTR_1] = {.type = NLA_U8},
2689+ [DCB_PFC_UP_ATTR_2] = {.type = NLA_U8},
2690+ [DCB_PFC_UP_ATTR_3] = {.type = NLA_U8},
2691+ [DCB_PFC_UP_ATTR_4] = {.type = NLA_U8},
2692+ [DCB_PFC_UP_ATTR_5] = {.type = NLA_U8},
2693+ [DCB_PFC_UP_ATTR_6] = {.type = NLA_U8},
2694+ [DCB_PFC_UP_ATTR_7] = {.type = NLA_U8},
2695+ [DCB_PFC_UP_ATTR_ALL] = {.type = NLA_FLAG},
2696+};
2697+
2698+/* DCB priority grouping nested attributes */
2699+static struct nla_policy dcbnl_pg_nest[DCB_PG_ATTR_MAX + 1] = {
2700+ [DCB_PG_ATTR_TC_0] = {.type = NLA_NESTED},
2701+ [DCB_PG_ATTR_TC_1] = {.type = NLA_NESTED},
2702+ [DCB_PG_ATTR_TC_2] = {.type = NLA_NESTED},
2703+ [DCB_PG_ATTR_TC_3] = {.type = NLA_NESTED},
2704+ [DCB_PG_ATTR_TC_4] = {.type = NLA_NESTED},
2705+ [DCB_PG_ATTR_TC_5] = {.type = NLA_NESTED},
2706+ [DCB_PG_ATTR_TC_6] = {.type = NLA_NESTED},
2707+ [DCB_PG_ATTR_TC_7] = {.type = NLA_NESTED},
2708+ [DCB_PG_ATTR_TC_ALL] = {.type = NLA_NESTED},
2709+ [DCB_PG_ATTR_BW_ID_0] = {.type = NLA_U8},
2710+ [DCB_PG_ATTR_BW_ID_1] = {.type = NLA_U8},
2711+ [DCB_PG_ATTR_BW_ID_2] = {.type = NLA_U8},
2712+ [DCB_PG_ATTR_BW_ID_3] = {.type = NLA_U8},
2713+ [DCB_PG_ATTR_BW_ID_4] = {.type = NLA_U8},
2714+ [DCB_PG_ATTR_BW_ID_5] = {.type = NLA_U8},
2715+ [DCB_PG_ATTR_BW_ID_6] = {.type = NLA_U8},
2716+ [DCB_PG_ATTR_BW_ID_7] = {.type = NLA_U8},
2717+ [DCB_PG_ATTR_BW_ID_ALL] = {.type = NLA_FLAG},
2718+};
2719+
2720+/* DCB traffic class nested attributes. */
2721+static struct nla_policy dcbnl_tc_param_nest[DCB_TC_ATTR_PARAM_MAX + 1] = {
2722+ [DCB_TC_ATTR_PARAM_PGID] = {.type = NLA_U8},
2723+ [DCB_TC_ATTR_PARAM_UP_MAPPING] = {.type = NLA_U8},
2724+ [DCB_TC_ATTR_PARAM_STRICT_PRIO] = {.type = NLA_U8},
2725+ [DCB_TC_ATTR_PARAM_BW_PCT] = {.type = NLA_U8},
2726+ [DCB_TC_ATTR_PARAM_ALL] = {.type = NLA_FLAG},
2727+};
2728+
2729+/* DCB capabilities nested attributes. */
2730+static struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = {
2731+ [DCB_CAP_ATTR_ALL] = {.type = NLA_FLAG},
2732+ [DCB_CAP_ATTR_PG] = {.type = NLA_U8},
2733+ [DCB_CAP_ATTR_PFC] = {.type = NLA_U8},
2734+ [DCB_CAP_ATTR_UP2TC] = {.type = NLA_U8},
2735+ [DCB_CAP_ATTR_PG_TCS] = {.type = NLA_U8},
2736+ [DCB_CAP_ATTR_PFC_TCS] = {.type = NLA_U8},
2737+ [DCB_CAP_ATTR_GSP] = {.type = NLA_U8},
2738+ [DCB_CAP_ATTR_BCN] = {.type = NLA_U8},
2739+};
2740+
2741+/* DCB capabilities nested attributes. */
2742+static struct nla_policy dcbnl_numtcs_nest[DCB_NUMTCS_ATTR_MAX + 1] = {
2743+ [DCB_NUMTCS_ATTR_ALL] = {.type = NLA_FLAG},
2744+ [DCB_NUMTCS_ATTR_PG] = {.type = NLA_U8},
2745+ [DCB_NUMTCS_ATTR_PFC] = {.type = NLA_U8},
2746+};
2747+
2748+/* DCB BCN nested attributes. */
2749+static struct nla_policy dcbnl_bcn_nest[DCB_BCN_ATTR_MAX + 1] = {
2750+ [DCB_BCN_ATTR_RP_0] = {.type = NLA_U8},
2751+ [DCB_BCN_ATTR_RP_1] = {.type = NLA_U8},
2752+ [DCB_BCN_ATTR_RP_2] = {.type = NLA_U8},
2753+ [DCB_BCN_ATTR_RP_3] = {.type = NLA_U8},
2754+ [DCB_BCN_ATTR_RP_4] = {.type = NLA_U8},
2755+ [DCB_BCN_ATTR_RP_5] = {.type = NLA_U8},
2756+ [DCB_BCN_ATTR_RP_6] = {.type = NLA_U8},
2757+ [DCB_BCN_ATTR_RP_7] = {.type = NLA_U8},
2758+ [DCB_BCN_ATTR_RP_ALL] = {.type = NLA_FLAG},
2759+ [DCB_BCN_ATTR_ALPHA] = {.type = NLA_U32},
2760+ [DCB_BCN_ATTR_BETA] = {.type = NLA_U32},
2761+ [DCB_BCN_ATTR_GD] = {.type = NLA_U32},
2762+ [DCB_BCN_ATTR_GI] = {.type = NLA_U32},
2763+ [DCB_BCN_ATTR_TMAX] = {.type = NLA_U32},
2764+ [DCB_BCN_ATTR_TD] = {.type = NLA_U32},
2765+ [DCB_BCN_ATTR_RMIN] = {.type = NLA_U32},
2766+ [DCB_BCN_ATTR_W] = {.type = NLA_U32},
2767+ [DCB_BCN_ATTR_RD] = {.type = NLA_U32},
2768+ [DCB_BCN_ATTR_RU] = {.type = NLA_U32},
2769+ [DCB_BCN_ATTR_WRTT] = {.type = NLA_U32},
2770+ [DCB_BCN_ATTR_RI] = {.type = NLA_U32},
2771+ [DCB_BCN_ATTR_C] = {.type = NLA_U32},
2772+ [DCB_BCN_ATTR_ALL] = {.type = NLA_FLAG},
2773+};
2774+
2775+/* standard netlink reply call */
2776+static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid,
2777+ u32 seq, u16 flags)
2778+{
2779+ struct sk_buff *dcbnl_skb;
2780+ struct dcbmsg *dcb;
2781+ struct nlmsghdr *nlh;
2782+ int ret = -EINVAL;
2783+
2784+ dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2785+ if (!dcbnl_skb)
2786+ return ret;
2787+
2788+ nlh = NLMSG_NEW(dcbnl_skb, pid, seq, event, sizeof(*dcb), flags);
2789+
2790+ dcb = NLMSG_DATA(nlh);
2791+ dcb->dcb_family = AF_UNSPEC;
2792+ dcb->cmd = cmd;
2793+ dcb->dcb_pad = 0;
2794+
2795+ ret = nla_put_u8(dcbnl_skb, attr, value);
2796+ if (ret)
2797+ goto err;
2798+
2799+ /* end the message, assign the nlmsg_len. */
2800+ nlmsg_end(dcbnl_skb, nlh);
2801+ ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
2802+ if (ret)
2803+ goto err;
2804+
2805+ return 0;
2806+nlmsg_failure:
2807+err:
2808+ kfree(dcbnl_skb);
2809+ return ret;
2810+}
2811+
2812+static int dcbnl_getstate(struct net_device *netdev, struct nlattr **tb,
2813+ u32 pid, u32 seq, u16 flags)
2814+{
2815+ int ret = -EINVAL;
2816+
2817+ /* if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->getstate) */
2818+ if (!netdev->dcbnl_ops->getstate)
2819+ return ret;
2820+
2821+ ret = dcbnl_reply(netdev->dcbnl_ops->getstate(netdev), RTM_GETDCB,
2822+ DCB_CMD_GSTATE, DCB_ATTR_STATE, pid, seq, flags);
2823+
2824+ return ret;
2825+}
2826+
2827+static int dcbnl_getpfccfg(struct net_device *netdev, struct nlattr **tb,
2828+ u32 pid, u32 seq, u16 flags)
2829+{
2830+ struct sk_buff *dcbnl_skb;
2831+ struct nlmsghdr *nlh;
2832+ struct dcbmsg *dcb;
2833+ struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1], *nest;
2834+ u8 value;
2835+ int ret = -EINVAL;
2836+ int i;
2837+ int getall = 0;
2838+
2839+ if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->getpfccfg)
2840+ return ret;
2841+
2842+ ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
2843+ tb[DCB_ATTR_PFC_CFG],
2844+ dcbnl_pfc_up_nest);
2845+ if (ret)
2846+ goto err_out;
2847+
2848+ dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2849+ if (!dcbnl_skb)
2850+ goto err_out;
2851+
2852+ nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
2853+
2854+ dcb = NLMSG_DATA(nlh);
2855+ dcb->dcb_family = AF_UNSPEC;
2856+ dcb->cmd = DCB_CMD_PFC_GCFG;
2857+
2858+ nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PFC_CFG);
2859+ if (!nest)
2860+ goto err;
2861+
2862+ if (data[DCB_PFC_UP_ATTR_ALL])
2863+ getall = 1;
2864+
2865+ for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
2866+ if (!getall && !data[i])
2867+ continue;
2868+
2869+ netdev->dcbnl_ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0,
2870+ &value);
2871+ ret = nla_put_u8(dcbnl_skb, i, value);
2872+
2873+ if (ret) {
2874+ nla_nest_cancel(dcbnl_skb, nest);
2875+ goto err;
2876+ }
2877+ }
2878+ nla_nest_end(dcbnl_skb, nest);
2879+
2880+ nlmsg_end(dcbnl_skb, nlh);
2881+
2882+ ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
2883+ if (ret)
2884+ goto err;
2885+
2886+ return 0;
2887+nlmsg_failure:
2888+err:
2889+ kfree(dcbnl_skb);
2890+err_out:
2891+ return -EINVAL;
2892+}
2893+
2894+static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlattr **tb,
2895+ u32 pid, u32 seq, u16 flags)
2896+{
2897+ struct sk_buff *dcbnl_skb;
2898+ struct nlmsghdr *nlh;
2899+ struct dcbmsg *dcb;
2900+ u8 perm_addr[MAX_ADDR_LEN];
2901+ int ret = -EINVAL;
2902+
2903+ if (!netdev->dcbnl_ops->getpermhwaddr)
2904+ return ret;
2905+
2906+ dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2907+ if (!dcbnl_skb)
2908+ goto err_out;
2909+
2910+ nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
2911+
2912+ dcb = NLMSG_DATA(nlh);
2913+ dcb->dcb_family = AF_UNSPEC;
2914+ dcb->cmd = DCB_CMD_GPERM_HWADDR;
2915+
2916+ netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr);
2917+
2918+ ret = nla_put(dcbnl_skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr),
2919+ perm_addr);
2920+
2921+ nlmsg_end(dcbnl_skb, nlh);
2922+
2923+ ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
2924+ if (ret)
2925+ goto err;
2926+
2927+ return 0;
2928+
2929+nlmsg_failure:
2930+err:
2931+ kfree(dcbnl_skb);
2932+err_out:
2933+ return -EINVAL;
2934+}
2935+
2936+static int dcbnl_getcap(struct net_device *netdev, struct nlattr **tb,
2937+ u32 pid, u32 seq, u16 flags)
2938+{
2939+ struct sk_buff *dcbnl_skb;
2940+ struct nlmsghdr *nlh;
2941+ struct dcbmsg *dcb;
2942+ struct nlattr *data[DCB_CAP_ATTR_MAX + 1], *nest;
2943+ u8 value;
2944+ int ret = -EINVAL;
2945+ int i;
2946+ int getall = 0;
2947+
2948+ if (!tb[DCB_ATTR_CAP] || !netdev->dcbnl_ops->getcap)
2949+ return ret;
2950+
2951+ ret = nla_parse_nested(data, DCB_CAP_ATTR_MAX, tb[DCB_ATTR_CAP],
2952+ dcbnl_cap_nest);
2953+ if (ret)
2954+ goto err_out;
2955+
2956+ dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2957+ if (!dcbnl_skb)
2958+ goto err_out;
2959+
2960+ nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
2961+
2962+ dcb = NLMSG_DATA(nlh);
2963+ dcb->dcb_family = AF_UNSPEC;
2964+ dcb->cmd = DCB_CMD_GCAP;
2965+
2966+ nest = nla_nest_start(dcbnl_skb, DCB_ATTR_CAP);
2967+ if (!nest)
2968+ goto err;
2969+
2970+ if (data[DCB_CAP_ATTR_ALL])
2971+ getall = 1;
2972+
2973+ for (i = DCB_CAP_ATTR_ALL+1; i <= DCB_CAP_ATTR_MAX; i++) {
2974+ if (!getall && !data[i])
2975+ continue;
2976+
2977+ if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) {
2978+ ret = nla_put_u8(dcbnl_skb, i, value);
2979+
2980+ if (ret) {
2981+ nla_nest_cancel(dcbnl_skb, nest);
2982+ goto err;
2983+ }
2984+ }
2985+ }
2986+ nla_nest_end(dcbnl_skb, nest);
2987+
2988+ nlmsg_end(dcbnl_skb, nlh);
2989+
2990+ ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
2991+ if (ret)
2992+ goto err;
2993+
2994+ return 0;
2995+nlmsg_failure:
2996+err:
2997+ kfree(dcbnl_skb);
2998+err_out:
2999+ return -EINVAL;
3000+}
3001+
3002+static int dcbnl_getnumtcs(struct net_device *netdev, struct nlattr **tb,
3003+ u32 pid, u32 seq, u16 flags)
3004+{
3005+ struct sk_buff *dcbnl_skb;
3006+ struct nlmsghdr *nlh;
3007+ struct dcbmsg *dcb;
3008+ struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1], *nest;
3009+ u8 value;
3010+ int ret = -EINVAL;
3011+ int i;
3012+ int getall = 0;
3013+
3014+ if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->getnumtcs)
3015+ return ret;
3016+
3017+ ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
3018+ dcbnl_numtcs_nest);
3019+ if (ret) {
3020+ ret = -EINVAL;
3021+ goto err_out;
3022+ }
3023+
3024+ dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3025+ if (!dcbnl_skb) {
3026+ ret = -EINVAL;
3027+ goto err_out;
3028+ }
3029+
3030+ nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
3031+
3032+ dcb = NLMSG_DATA(nlh);
3033+ dcb->dcb_family = AF_UNSPEC;
3034+ dcb->cmd = DCB_CMD_GNUMTCS;
3035+
3036+ nest = nla_nest_start(dcbnl_skb, DCB_ATTR_NUMTCS);
3037+ if (!nest) {
3038+ ret = -EINVAL;
3039+ goto err;
3040+ }
3041+
3042+ if (data[DCB_NUMTCS_ATTR_ALL])
3043+ getall = 1;
3044+
3045+ for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
3046+ if (!getall && !data[i])
3047+ continue;
3048+
3049+ ret = netdev->dcbnl_ops->getnumtcs(netdev, i, &value);
3050+ if (!ret) {
3051+ ret = nla_put_u8(dcbnl_skb, i, value);
3052+
3053+ if (ret) {
3054+ nla_nest_cancel(dcbnl_skb, nest);
3055+ ret = -EINVAL;
3056+ goto err;
3057+ }
3058+ } else {
3059+ goto err;
3060+ }
3061+ }
3062+ nla_nest_end(dcbnl_skb, nest);
3063+
3064+ nlmsg_end(dcbnl_skb, nlh);
3065+
3066+ ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
3067+ if (ret) {
3068+ ret = -EINVAL;
3069+ goto err;
3070+ }
3071+
3072+ return 0;
3073+nlmsg_failure:
3074+err:
3075+ kfree(dcbnl_skb);
3076+err_out:
3077+ return ret;
3078+}
3079+
3080+static int dcbnl_setnumtcs(struct net_device *netdev, struct nlattr **tb,
3081+ u32 pid, u32 seq, u16 flags)
3082+{
3083+ struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1];
3084+ int ret = -EINVAL;
3085+ u8 value;
3086+ u8 status;
3087+ int i;
3088+
3089+ if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->setstate)
3090+ return ret;
3091+
3092+ ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS],
3093+ dcbnl_numtcs_nest);
3094+
3095+ if (ret) {
3096+ ret = -EINVAL;
3097+ goto err;
3098+ }
3099+
3100+ for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) {
3101+ if (data[i] == NULL)
3102+ continue;
3103+
3104+ value = nla_get_u8(data[i]);
3105+
3106+ ret = netdev->dcbnl_ops->setnumtcs(netdev, i, value);
3107+
3108+ if (ret)
3109+ goto err;
3110+ }
3111+
3112+ value = nla_get_u8(tb[DCB_ATTR_STATE]);
3113+
3114+ status = netdev->dcbnl_ops->setnumtcs(netdev, i, value);
3115+
3116+ ret = dcbnl_reply(!!status, RTM_SETDCB, DCB_CMD_SNUMTCS,
3117+ DCB_ATTR_NUMTCS, pid, seq, flags);
3118+
3119+err:
3120+ return ret;
3121+}
3122+
3123+static int dcbnl_getpfcstate(struct net_device *netdev, struct nlattr **tb,
3124+ u32 pid, u32 seq, u16 flags)
3125+{
3126+ int ret = -EINVAL;
3127+
3128+ if (!netdev->dcbnl_ops->getpfcstate)
3129+ return ret;
3130+
3131+ ret = dcbnl_reply(netdev->dcbnl_ops->getpfcstate(netdev), RTM_GETDCB,
3132+ DCB_CMD_PFC_GSTATE, DCB_ATTR_PFC_STATE,
3133+ pid, seq, flags);
3134+
3135+ return ret;
3136+}
3137+
3138+static int dcbnl_setpfcstate(struct net_device *netdev, struct nlattr **tb,
3139+ u32 pid, u32 seq, u16 flags)
3140+{
3141+ int ret = -EINVAL;
3142+ u8 value;
3143+
3144+ if (!tb[DCB_ATTR_PFC_STATE] || !netdev->dcbnl_ops->setpfcstate)
3145+ return ret;
3146+
3147+ value = nla_get_u8(tb[DCB_ATTR_STATE]);
3148+
3149+ netdev->dcbnl_ops->setstate(netdev, value);
3150+
3151+ ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SSTATE, DCB_ATTR_PFC_STATE,
3152+ pid, seq, flags);
3153+
3154+ return ret;
3155+}
3156+
3157+static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb,
3158+ u32 pid, u32 seq, u16 flags, int dir)
3159+{
3160+ struct sk_buff *dcbnl_skb;
3161+ struct nlmsghdr *nlh;
3162+ struct dcbmsg *dcb;
3163+ struct nlattr *pg_nest, *param_nest, *data;
3164+ struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
3165+ struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
3166+ u8 prio, pgid, tc_pct, up_map;
3167+ int ret = -EINVAL;
3168+ int getall = 0;
3169+ int i;
3170+
3171+ if (!tb[DCB_ATTR_PG_CFG] ||
3172+ !netdev->dcbnl_ops->getpgtccfgtx ||
3173+ !netdev->dcbnl_ops->getpgtccfgrx ||
3174+ !netdev->dcbnl_ops->getpgbwgcfgtx ||
3175+ !netdev->dcbnl_ops->getpgbwgcfgrx)
3176+ return ret;
3177+
3178+ ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
3179+ tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
3180+
3181+ if (ret)
3182+ goto err_out;
3183+
3184+ dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3185+ if (!dcbnl_skb)
3186+ goto err_out;
3187+
3188+ nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
3189+
3190+ dcb = NLMSG_DATA(nlh);
3191+ dcb->dcb_family = AF_UNSPEC;
3192+ dcb->cmd = (dir) ? DCB_CMD_PGRX_GCFG : DCB_CMD_PGTX_GCFG;
3193+
3194+ pg_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PG_CFG);
3195+ if (!pg_nest)
3196+ goto err;
3197+
3198+ if (pg_tb[DCB_PG_ATTR_TC_ALL])
3199+ getall = 1;
3200+
3201+ for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
3202+ if (!getall && !pg_tb[i])
3203+ continue;
3204+
3205+ if (pg_tb[DCB_PG_ATTR_TC_ALL])
3206+ data = pg_tb[DCB_PG_ATTR_TC_ALL];
3207+ else
3208+ data = pg_tb[i];
3209+ ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX,
3210+ data, dcbnl_tc_param_nest);
3211+ if (ret)
3212+ goto err_pg;
3213+
3214+ param_nest = nla_nest_start(dcbnl_skb, i);
3215+ if (!param_nest)
3216+ goto err_pg;
3217+
3218+ pgid = DCB_ATTR_VALUE_UNDEFINED;
3219+ prio = DCB_ATTR_VALUE_UNDEFINED;
3220+ tc_pct = DCB_ATTR_VALUE_UNDEFINED;
3221+ up_map = DCB_ATTR_VALUE_UNDEFINED;
3222+
3223+ if (dir) {
3224+ /* Rx */
3225+ netdev->dcbnl_ops->getpgtccfgrx(netdev,
3226+ i - DCB_PG_ATTR_TC_0, &prio,
3227+ &pgid, &tc_pct, &up_map);
3228+ } else {
3229+ /* Tx */
3230+ netdev->dcbnl_ops->getpgtccfgtx(netdev,
3231+ i - DCB_PG_ATTR_TC_0, &prio,
3232+ &pgid, &tc_pct, &up_map);
3233+ }
3234+
3235+ if (param_tb[DCB_TC_ATTR_PARAM_PGID] ||
3236+ param_tb[DCB_TC_ATTR_PARAM_ALL]) {
3237+ ret = nla_put_u8(dcbnl_skb,
3238+ DCB_TC_ATTR_PARAM_PGID, pgid);
3239+ if (ret)
3240+ goto err_param;
3241+ }
3242+ if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING] ||
3243+ param_tb[DCB_TC_ATTR_PARAM_ALL]) {
3244+ ret = nla_put_u8(dcbnl_skb,
3245+ DCB_TC_ATTR_PARAM_UP_MAPPING, up_map);
3246+ if (ret)
3247+ goto err_param;
3248+ }
3249+ if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO] ||
3250+ param_tb[DCB_TC_ATTR_PARAM_ALL]) {
3251+ ret = nla_put_u8(dcbnl_skb,
3252+ DCB_TC_ATTR_PARAM_STRICT_PRIO, prio);
3253+ if (ret)
3254+ goto err_param;
3255+ }
3256+ if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT] ||
3257+ param_tb[DCB_TC_ATTR_PARAM_ALL]) {
3258+ ret = nla_put_u8(dcbnl_skb, DCB_TC_ATTR_PARAM_BW_PCT,
3259+ tc_pct);
3260+ if (ret)
3261+ goto err_param;
3262+ }
3263+ nla_nest_end(dcbnl_skb, param_nest);
3264+ }
3265+
3266+ if (pg_tb[DCB_PG_ATTR_BW_ID_ALL])
3267+ getall = 1;
3268+ else
3269+ getall = 0;
3270+
3271+ for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
3272+ if (!getall && !pg_tb[i])
3273+ continue;
3274+
3275+ tc_pct = DCB_ATTR_VALUE_UNDEFINED;
3276+
3277+ if (dir) {
3278+ /* Rx */
3279+ netdev->dcbnl_ops->getpgbwgcfgrx(netdev,
3280+ i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
3281+ } else {
3282+ /* Tx */
3283+ netdev->dcbnl_ops->getpgbwgcfgtx(netdev,
3284+ i - DCB_PG_ATTR_BW_ID_0, &tc_pct);
3285+ }
3286+ ret = nla_put_u8(dcbnl_skb, i, tc_pct);
3287+
3288+ if (ret)
3289+ goto err_pg;
3290+ }
3291+
3292+ nla_nest_end(dcbnl_skb, pg_nest);
3293+
3294+ nlmsg_end(dcbnl_skb, nlh);
3295+
3296+ ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
3297+ if (ret)
3298+ goto err;
3299+
3300+ return 0;
3301+
3302+err_param:
3303+ nla_nest_cancel(dcbnl_skb, param_nest);
3304+err_pg:
3305+ nla_nest_cancel(dcbnl_skb, pg_nest);
3306+nlmsg_failure:
3307+err:
3308+ kfree(dcbnl_skb);
3309+err_out:
3310+ ret = -EINVAL;
3311+ return ret;
3312+}
3313+
3314+static int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlattr **tb,
3315+ u32 pid, u32 seq, u16 flags)
3316+{
3317+ return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 0);
3318+}
3319+
3320+static int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlattr **tb,
3321+ u32 pid, u32 seq, u16 flags)
3322+{
3323+ return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 1);
3324+}
3325+
3326+static int dcbnl_setstate(struct net_device *netdev, struct nlattr **tb,
3327+ u32 pid, u32 seq, u16 flags)
3328+{
3329+ int ret = -EINVAL;
3330+ u8 value;
3331+
3332+ if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->setstate)
3333+ return ret;
3334+
3335+ value = nla_get_u8(tb[DCB_ATTR_STATE]);
3336+
3337+ netdev->dcbnl_ops->setstate(netdev, value);
3338+
3339+ ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_SSTATE, DCB_ATTR_STATE,
3340+ pid, seq, flags);
3341+
3342+ return ret;
3343+}
3344+
3345+static int dcbnl_setpfccfg(struct net_device *netdev, struct nlattr **tb,
3346+ u32 pid, u32 seq, u16 flags)
3347+{
3348+ struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1];
3349+ int i;
3350+ int ret = -EINVAL;
3351+ u8 value;
3352+
3353+ if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->setpfccfg)
3354+ return ret;
3355+
3356+ ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX,
3357+ tb[DCB_ATTR_PFC_CFG],
3358+ dcbnl_pfc_up_nest);
3359+ if (ret)
3360+ goto err;
3361+
3362+ for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
3363+ if (data[i] == NULL)
3364+ continue;
3365+ value = nla_get_u8(data[i]);
3366+ netdev->dcbnl_ops->setpfccfg(netdev,
3367+ data[i]->nla_type - DCB_PFC_UP_ATTR_0, value);
3368+ }
3369+
3370+ ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SCFG, DCB_ATTR_PFC_CFG,
3371+ pid, seq, flags);
3372+err:
3373+ return ret;
3374+}
3375+
3376+static int dcbnl_setall(struct net_device *netdev, struct nlattr **tb,
3377+ u32 pid, u32 seq, u16 flags)
3378+{
3379+ int ret = -EINVAL;
3380+
3381+ if (!tb[DCB_ATTR_SET_ALL] || !netdev->dcbnl_ops->setall)
3382+ return ret;
3383+
3384+ ret = dcbnl_reply(netdev->dcbnl_ops->setall(netdev), RTM_SETDCB,
3385+ DCB_CMD_SET_ALL, DCB_ATTR_SET_ALL, pid, seq, flags);
3386+
3387+ return ret;
3388+}
3389+
3390+static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlattr **tb,
3391+ u32 pid, u32 seq, u16 flags, int dir)
3392+{
3393+ struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1];
3394+ struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1];
3395+ int ret = -EINVAL;
3396+ int i;
3397+ u8 pgid;
3398+ u8 up_map;
3399+ u8 prio;
3400+ u8 tc_pct;
3401+
3402+ if (!tb[DCB_ATTR_PG_CFG] ||
3403+ !netdev->dcbnl_ops->setpgtccfgtx ||
3404+ !netdev->dcbnl_ops->setpgtccfgrx ||
3405+ !netdev->dcbnl_ops->setpgbwgcfgtx ||
3406+ !netdev->dcbnl_ops->setpgbwgcfgrx)
3407+ return ret;
3408+
3409+ ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX,
3410+ tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest);
3411+ if (ret)
3412+ goto err;
3413+
3414+ for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
3415+ if (!pg_tb[i])
3416+ continue;
3417+
3418+ ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX,
3419+ pg_tb[i], dcbnl_tc_param_nest);
3420+ if (ret)
3421+ goto err;
3422+
3423+ pgid = DCB_ATTR_VALUE_UNDEFINED;
3424+ prio = DCB_ATTR_VALUE_UNDEFINED;
3425+ tc_pct = DCB_ATTR_VALUE_UNDEFINED;
3426+ up_map = DCB_ATTR_VALUE_UNDEFINED;
3427+
3428+ if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO])
3429+ prio =
3430+ nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO]);
3431+
3432+ if (param_tb[DCB_TC_ATTR_PARAM_PGID])
3433+ pgid = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_PGID]);
3434+
3435+ if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT])
3436+ tc_pct = nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_BW_PCT]);
3437+
3438+ if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING])
3439+ up_map =
3440+ nla_get_u8(param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING]);
3441+
3442+ /* dir: Tx = 0, Rx = 1 */
3443+ if (dir) {
3444+ /* Rx */
3445+ netdev->dcbnl_ops->setpgtccfgrx(netdev,
3446+ i - DCB_PG_ATTR_TC_0,
3447+ prio, pgid, tc_pct, up_map);
3448+ } else {
3449+ /* Tx */
3450+ netdev->dcbnl_ops->setpgtccfgtx(netdev,
3451+ i - DCB_PG_ATTR_TC_0,
3452+ prio, pgid, tc_pct, up_map);
3453+ }
3454+ }
3455+
3456+ for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
3457+ if (!pg_tb[i])
3458+ continue;
3459+
3460+ tc_pct = nla_get_u8(pg_tb[i]);
3461+
3462+ /* dir: Tx = 0, Rx = 1 */
3463+ if (dir) {
3464+ /* Rx */
3465+ netdev->dcbnl_ops->setpgbwgcfgrx(netdev,
3466+ i - DCB_PG_ATTR_BW_ID_0, tc_pct);
3467+ } else {
3468+ /* Tx */
3469+ netdev->dcbnl_ops->setpgbwgcfgtx(netdev,
3470+ i - DCB_PG_ATTR_BW_ID_0, tc_pct);
3471+ }
3472+ }
3473+
3474+ ret = dcbnl_reply(0, RTM_SETDCB,
3475+ (dir ? DCB_CMD_PGRX_SCFG : DCB_CMD_PGTX_SCFG),
3476+ DCB_ATTR_PG_CFG, pid, seq, flags);
3477+
3478+err:
3479+ return ret;
3480+}
3481+
3482+static int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlattr **tb,
3483+ u32 pid, u32 seq, u16 flags)
3484+{
3485+ return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 0);
3486+}
3487+
3488+static int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlattr **tb,
3489+ u32 pid, u32 seq, u16 flags)
3490+{
3491+ return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 1);
3492+}
3493+
3494+static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlattr **tb,
3495+ u32 pid, u32 seq, u16 flags)
3496+{
3497+ struct sk_buff *dcbnl_skb;
3498+ struct nlmsghdr *nlh;
3499+ struct dcbmsg *dcb;
3500+ struct nlattr *bcn_nest;
3501+ struct nlattr *bcn_tb[DCB_BCN_ATTR_MAX + 1];
3502+ u8 value_byte;
3503+ u32 value_integer;
3504+ int ret = -EINVAL;
3505+ bool getall = false;
3506+ int i;
3507+
3508+ if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->getbcnrp ||
3509+ !netdev->dcbnl_ops->getbcncfg)
3510+ return ret;
3511+
3512+ ret = nla_parse_nested(bcn_tb, DCB_BCN_ATTR_MAX,
3513+ tb[DCB_ATTR_BCN], dcbnl_bcn_nest);
3514+
3515+ if (ret)
3516+ goto err_out;
3517+
3518+ dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3519+ if (!dcbnl_skb)
3520+ goto err_out;
3521+
3522+ nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
3523+
3524+ dcb = NLMSG_DATA(nlh);
3525+ dcb->dcb_family = AF_UNSPEC;
3526+ dcb->cmd = DCB_CMD_BCN_GCFG;
3527+
3528+ bcn_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_BCN);
3529+ if (!bcn_nest)
3530+ goto err;
3531+
3532+ if (bcn_tb[DCB_BCN_ATTR_ALL])
3533+ getall = true;
3534+
3535+ for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
3536+ if (!getall && !bcn_tb[i])
3537+ continue;
3538+
3539+ netdev->dcbnl_ops->getbcnrp(netdev, i - DCB_BCN_ATTR_RP_0,
3540+ &value_byte);
3541+ ret = nla_put_u8(dcbnl_skb, i, value_byte);
3542+ if (ret)
3543+ goto err_bcn;
3544+ }
3545+
3546+ for (i = DCB_BCN_ATTR_ALPHA; i <= DCB_BCN_ATTR_RI; i++) {
3547+ if (!getall && !bcn_tb[i])
3548+ continue;
3549+
3550+ netdev->dcbnl_ops->getbcncfg(netdev, i,
3551+ &value_integer);
3552+ ret = nla_put_u32(dcbnl_skb, i, value_integer);
3553+ if (ret)
3554+ goto err_bcn;
3555+ }
3556+
3557+ nla_nest_end(dcbnl_skb, bcn_nest);
3558+
3559+ nlmsg_end(dcbnl_skb, nlh);
3560+
3561+ ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
3562+ if (ret)
3563+ goto err;
3564+
3565+ return 0;
3566+
3567+err_bcn:
3568+ nla_nest_cancel(dcbnl_skb, bcn_nest);
3569+nlmsg_failure:
3570+err:
3571+ kfree(dcbnl_skb);
3572+err_out:
3573+ ret = -EINVAL;
3574+ return ret;
3575+}
3576+
3577+static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlattr **tb,
3578+ u32 pid, u32 seq, u16 flags)
3579+{
3580+ struct nlattr *data[DCB_BCN_ATTR_MAX + 1];
3581+ int i;
3582+ int ret = -EINVAL;
3583+ u8 value_byte;
3584+ u32 value_int;
3585+
3586+ if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->setbcncfg
3587+ || !netdev->dcbnl_ops->setbcnrp)
3588+ return ret;
3589+
3590+ ret = nla_parse_nested(data, DCB_BCN_ATTR_MAX,
3591+ tb[DCB_ATTR_BCN],
3592+ dcbnl_pfc_up_nest);
3593+ if (ret)
3594+ goto err;
3595+
3596+ for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) {
3597+ if (data[i] == NULL)
3598+ continue;
3599+ value_byte = nla_get_u8(data[i]);
3600+ netdev->dcbnl_ops->setbcnrp(netdev,
3601+ data[i]->nla_type - DCB_BCN_ATTR_RP_0, value_byte);
3602+ }
3603+
3604+ for (i = DCB_BCN_ATTR_ALPHA; i <= DCB_BCN_ATTR_RI; i++) {
3605+ if (data[i] == NULL)
3606+ continue;
3607+ value_int = nla_get_u32(data[i]);
3608+ netdev->dcbnl_ops->setbcncfg(netdev,
3609+ i, value_int);
3610+ }
3611+
3612+ ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_BCN_SCFG, DCB_ATTR_BCN,
3613+ pid, seq, flags);
3614+err:
3615+ return ret;
3616+}
3617+
3618+static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
3619+{
3620+ struct net *net = sock_net(skb->sk);
3621+ struct net_device *netdev;
3622+ struct dcbmsg *dcb = (struct dcbmsg *)NLMSG_DATA(nlh);
3623+ struct nlattr *tb[DCB_ATTR_MAX + 1];
3624+ u32 pid = skb ? NETLINK_CB(skb).pid : 0;
3625+ int ret = -EINVAL;
3626+
3627+ if (net != &init_net)
3628+ return -EINVAL;
3629+
3630+ ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX,
3631+ dcbnl_rtnl_policy);
3632+ if (ret < 0)
3633+ return ret;
3634+
3635+ if (!tb[DCB_ATTR_IFNAME])
3636+ return -EINVAL;
3637+
3638+ netdev = dev_get_by_name(&init_net, nla_data(tb[DCB_ATTR_IFNAME]));
3639+ if (!netdev)
3640+ return -EINVAL;
3641+
3642+ if (!netdev->dcbnl_ops)
3643+ goto errout;
3644+
3645+ switch (dcb->cmd) {
3646+ case DCB_CMD_GSTATE:
3647+ ret = dcbnl_getstate(netdev, tb, pid, nlh->nlmsg_seq,
3648+ nlh->nlmsg_flags);
3649+ goto out;
3650+ case DCB_CMD_PFC_GCFG:
3651+ ret = dcbnl_getpfccfg(netdev, tb, pid, nlh->nlmsg_seq,
3652+ nlh->nlmsg_flags);
3653+ goto out;
3654+ case DCB_CMD_GPERM_HWADDR:
3655+ ret = dcbnl_getperm_hwaddr(netdev, tb, pid, nlh->nlmsg_seq,
3656+ nlh->nlmsg_flags);
3657+ goto out;
3658+ case DCB_CMD_PGTX_GCFG:
3659+ ret = dcbnl_pgtx_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
3660+ nlh->nlmsg_flags);
3661+ goto out;
3662+ case DCB_CMD_PGRX_GCFG:
3663+ ret = dcbnl_pgrx_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
3664+ nlh->nlmsg_flags);
3665+ goto out;
3666+ case DCB_CMD_BCN_GCFG:
3667+ ret = dcbnl_bcn_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
3668+ nlh->nlmsg_flags);
3669+ goto out;
3670+ case DCB_CMD_SSTATE:
3671+ ret = dcbnl_setstate(netdev, tb, pid, nlh->nlmsg_seq,
3672+ nlh->nlmsg_flags);
3673+ goto out;
3674+ case DCB_CMD_PFC_SCFG:
3675+ ret = dcbnl_setpfccfg(netdev, tb, pid, nlh->nlmsg_seq,
3676+ nlh->nlmsg_flags);
3677+ goto out;
3678+
3679+ case DCB_CMD_SET_ALL:
3680+ ret = dcbnl_setall(netdev, tb, pid, nlh->nlmsg_seq,
3681+ nlh->nlmsg_flags);
3682+ goto out;
3683+ case DCB_CMD_PGTX_SCFG:
3684+ ret = dcbnl_pgtx_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
3685+ nlh->nlmsg_flags);
3686+ goto out;
3687+ case DCB_CMD_PGRX_SCFG:
3688+ ret = dcbnl_pgrx_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
3689+ nlh->nlmsg_flags);
3690+ goto out;
3691+ case DCB_CMD_GCAP:
3692+ ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq,
3693+ nlh->nlmsg_flags);
3694+ goto out;
3695+ case DCB_CMD_GNUMTCS:
3696+ ret = dcbnl_getnumtcs(netdev, tb, pid, nlh->nlmsg_seq,
3697+ nlh->nlmsg_flags);
3698+ goto out;
3699+ case DCB_CMD_SNUMTCS:
3700+ ret = dcbnl_setnumtcs(netdev, tb, pid, nlh->nlmsg_seq,
3701+ nlh->nlmsg_flags);
3702+ goto out;
3703+ case DCB_CMD_PFC_GSTATE:
3704+ ret = dcbnl_getpfcstate(netdev, tb, pid, nlh->nlmsg_seq,
3705+ nlh->nlmsg_flags);
3706+ goto out;
3707+ case DCB_CMD_PFC_SSTATE:
3708+ ret = dcbnl_setpfcstate(netdev, tb, pid, nlh->nlmsg_seq,
3709+ nlh->nlmsg_flags);
3710+ goto out;
3711+ case DCB_CMD_BCN_SCFG:
3712+ ret = dcbnl_bcn_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
3713+ nlh->nlmsg_flags);
3714+ goto out;
3715+ default:
3716+ goto errout;
3717+ }
3718+errout:
3719+ ret = -EINVAL;
3720+out:
3721+ dev_put(netdev);
3722+ return ret;
3723+}
3724+
3725+static int __init dcbnl_init(void)
3726+{
3727+ rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL);
3728+ rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL);
3729+
3730+ return 0;
3731+}
3732+module_init(dcbnl_init);
3733+
3734+static void __exit dcbnl_exit(void)
3735+{
3736+ rtnl_unregister(PF_UNSPEC, RTM_GETDCB);
3737+ rtnl_unregister(PF_UNSPEC, RTM_SETDCB);
3738+}
3739+module_exit(dcbnl_exit);
3740+
3741+
3742--- /dev/null
3743+++ b/net/dcb/Kconfig
3744@@ -0,0 +1,12 @@
3745+config DCB
3746+ tristate "Data Center Bridging support"
3747+
3748+config DCBNL
3749+ bool "Data Center Bridging netlink interface support"
3750+ depends on DCB
3751+ default n
3752+ ---help---
3753+ This option turns on the netlink interface
3754+ (dcbnl) for Data Center Bridging capable devices.
3755+
3756+ If unsure, say N.
3757--- /dev/null
3758+++ b/net/dcb/Makefile
3759@@ -0,0 +1 @@
3760+obj-$(CONFIG_DCB) += dcbnl.o
3761--- a/net/Kconfig
3762+++ b/net/Kconfig
3763@@ -190,6 +190,7 @@ source "net/lapb/Kconfig"
3764 source "net/econet/Kconfig"
3765 source "net/wanrouter/Kconfig"
3766 source "net/sched/Kconfig"
3767+source "net/dcb/Kconfig"
3768
3769 menu "Network testing"
3770
3771--- a/net/Makefile
3772+++ b/net/Makefile
3773@@ -55,6 +55,9 @@ obj-$(CONFIG_NETLABEL) += netlabel/
3774 obj-$(CONFIG_IUCV) += iucv/
3775 obj-$(CONFIG_RFKILL) += rfkill/
3776 obj-$(CONFIG_NET_9P) += 9p/
3777+ifeq ($(CONFIG_DCBNL),y)
3778+obj-$(CONFIG_DCB) += dcb/
3779+endif
3780
3781 ifeq ($(CONFIG_NET),y)
3782 obj-$(CONFIG_SYSCTL) += sysctl_net.o