aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ixgbe/ixgbe_dcb_nl.c
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2008-11-20 23:52:10 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-20 23:52:10 -0500
commit2f90b8657ec942d1880f720e0177ee71df7c8e3c (patch)
tree844114b22c548fedbab67e53b09b2efcf170563a /drivers/net/ixgbe/ixgbe_dcb_nl.c
parent9db66bdcc83749affe61c61eb8ff3cf08f42afec (diff)
ixgbe: this patch adds support for DCB to the kernel and ixgbe driver
This adds support for Data Center Bridging (DCB) features in the ixgbe driver and adds an rtnetlink interface for configuring DCB to the kernel. The DCB feature support included are Priority Grouping (PG) - which allows bandwidth guarantees to be allocated to groups to traffic based on the 802.1q priority, and Priority Based Flow Control (PFC) - which introduces a new MAC control PAUSE frame which works at granularity of the 802.1p priority instead of the link (IEEE 802.3x). Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_dcb_nl.c')
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_nl.c356
1 files changed, 356 insertions, 0 deletions
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c
new file mode 100644
index 000000000000..50bff2af6b04
--- /dev/null
+++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c
@@ -0,0 +1,356 @@
1/*******************************************************************************
2
3 Intel 10 Gigabit PCI Express Linux driver
4 Copyright(c) 1999 - 2008 Intel Corporation.
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms and conditions of the GNU General Public License,
8 version 2, as published by the Free Software Foundation.
9
10 This program is distributed in the hope it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 more details.
14
15 You should have received a copy of the GNU General Public License along with
16 this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18
19 The full GNU General Public License is included in this distribution in
20 the file called "COPYING".
21
22 Contact Information:
23 Linux NICS <linux.nics@intel.com>
24 e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
25 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
26
27*******************************************************************************/
28
29#include "ixgbe.h"
30#include <linux/dcbnl.h>
31
32/* Callbacks for DCB netlink in the kernel */
33#define BIT_DCB_MODE 0x01
34#define BIT_PFC 0x02
35#define BIT_PG_RX 0x04
36#define BIT_PG_TX 0x08
37
38int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg,
39 struct ixgbe_dcb_config *dst_dcb_cfg, int tc_max)
40{
41 struct tc_configuration *src_tc_cfg = NULL;
42 struct tc_configuration *dst_tc_cfg = NULL;
43 int i;
44
45 if (!src_dcb_cfg || !dst_dcb_cfg)
46 return -EINVAL;
47
48 for (i = DCB_PG_ATTR_TC_0; i < tc_max + DCB_PG_ATTR_TC_0; i++) {
49 src_tc_cfg = &src_dcb_cfg->tc_config[i - DCB_PG_ATTR_TC_0];
50 dst_tc_cfg = &dst_dcb_cfg->tc_config[i - DCB_PG_ATTR_TC_0];
51
52 dst_tc_cfg->path[DCB_TX_CONFIG].prio_type =
53 src_tc_cfg->path[DCB_TX_CONFIG].prio_type;
54
55 dst_tc_cfg->path[DCB_TX_CONFIG].bwg_id =
56 src_tc_cfg->path[DCB_TX_CONFIG].bwg_id;
57
58 dst_tc_cfg->path[DCB_TX_CONFIG].bwg_percent =
59 src_tc_cfg->path[DCB_TX_CONFIG].bwg_percent;
60
61 dst_tc_cfg->path[DCB_TX_CONFIG].up_to_tc_bitmap =
62 src_tc_cfg->path[DCB_TX_CONFIG].up_to_tc_bitmap;
63
64 dst_tc_cfg->path[DCB_RX_CONFIG].prio_type =
65 src_tc_cfg->path[DCB_RX_CONFIG].prio_type;
66
67 dst_tc_cfg->path[DCB_RX_CONFIG].bwg_id =
68 src_tc_cfg->path[DCB_RX_CONFIG].bwg_id;
69
70 dst_tc_cfg->path[DCB_RX_CONFIG].bwg_percent =
71 src_tc_cfg->path[DCB_RX_CONFIG].bwg_percent;
72
73 dst_tc_cfg->path[DCB_RX_CONFIG].up_to_tc_bitmap =
74 src_tc_cfg->path[DCB_RX_CONFIG].up_to_tc_bitmap;
75 }
76
77 for (i = DCB_PG_ATTR_BW_ID_0; i < DCB_PG_ATTR_BW_ID_MAX; i++) {
78 dst_dcb_cfg->bw_percentage[DCB_TX_CONFIG]
79 [i-DCB_PG_ATTR_BW_ID_0] = src_dcb_cfg->bw_percentage
80 [DCB_TX_CONFIG][i-DCB_PG_ATTR_BW_ID_0];
81 dst_dcb_cfg->bw_percentage[DCB_RX_CONFIG]
82 [i-DCB_PG_ATTR_BW_ID_0] = src_dcb_cfg->bw_percentage
83 [DCB_RX_CONFIG][i-DCB_PG_ATTR_BW_ID_0];
84 }
85
86 for (i = DCB_PFC_UP_ATTR_0; i < DCB_PFC_UP_ATTR_MAX; i++) {
87 dst_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc =
88 src_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc;
89 }
90
91 return 0;
92}
93
94static u8 ixgbe_dcbnl_get_state(struct net_device *netdev)
95{
96 struct ixgbe_adapter *adapter = netdev_priv(netdev);
97
98 DPRINTK(DRV, INFO, "Get DCB Admin Mode.\n");
99
100 return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED);
101}
102
103static u16 ixgbe_dcb_select_queue(struct net_device *dev, struct sk_buff *skb)
104{
105 /* All traffic should default to class 0 */
106 return 0;
107}
108
109static void ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
110{
111 struct ixgbe_adapter *adapter = netdev_priv(netdev);
112
113 DPRINTK(DRV, INFO, "Set DCB Admin Mode.\n");
114
115 if (state > 0) {
116 /* Turn on DCB */
117 if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
118 return;
119 } else {
120 if (netif_running(netdev))
121 netdev->stop(netdev);
122 ixgbe_reset_interrupt_capability(adapter);
123 ixgbe_napi_del_all(adapter);
124 kfree(adapter->tx_ring);
125 kfree(adapter->rx_ring);
126 adapter->tx_ring = NULL;
127 adapter->rx_ring = NULL;
128 netdev->select_queue = &ixgbe_dcb_select_queue;
129
130 adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
131 adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
132 ixgbe_init_interrupt_scheme(adapter);
133 ixgbe_napi_add_all(adapter);
134 if (netif_running(netdev))
135 netdev->open(netdev);
136 }
137 } else {
138 /* Turn off DCB */
139 if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
140 if (netif_running(netdev))
141 netdev->stop(netdev);
142 ixgbe_reset_interrupt_capability(adapter);
143 ixgbe_napi_del_all(adapter);
144 kfree(adapter->tx_ring);
145 kfree(adapter->rx_ring);
146 adapter->tx_ring = NULL;
147 adapter->rx_ring = NULL;
148 netdev->select_queue = NULL;
149
150 adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
151 adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
152 ixgbe_init_interrupt_scheme(adapter);
153 ixgbe_napi_add_all(adapter);
154 if (netif_running(netdev))
155 netdev->open(netdev);
156 } else {
157 return;
158 }
159 }
160}
161
162static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev,
163 u8 *perm_addr)
164{
165 struct ixgbe_adapter *adapter = netdev_priv(netdev);
166 int i;
167
168 for (i = 0; i < netdev->addr_len; i++)
169 perm_addr[i] = adapter->hw.mac.perm_addr[i];
170}
171
172static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,
173 u8 prio, u8 bwg_id, u8 bw_pct,
174 u8 up_map)
175{
176 struct ixgbe_adapter *adapter = netdev_priv(netdev);
177
178 if (prio != DCB_ATTR_VALUE_UNDEFINED)
179 adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type = prio;
180 if (bwg_id != DCB_ATTR_VALUE_UNDEFINED)
181 adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_id = bwg_id;
182 if (bw_pct != DCB_ATTR_VALUE_UNDEFINED)
183 adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent =
184 bw_pct;
185 if (up_map != DCB_ATTR_VALUE_UNDEFINED)
186 adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap =
187 up_map;
188
189 if ((adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type !=
190 adapter->dcb_cfg.tc_config[tc].path[0].prio_type) ||
191 (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_id !=
192 adapter->dcb_cfg.tc_config[tc].path[0].bwg_id) ||
193 (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent !=
194 adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent) ||
195 (adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap !=
196 adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap))
197 adapter->dcb_set_bitmap |= BIT_PG_TX;
198}
199
200static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
201 u8 bw_pct)
202{
203 struct ixgbe_adapter *adapter = netdev_priv(netdev);
204
205 adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct;
206
207 if (adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] !=
208 adapter->dcb_cfg.bw_percentage[0][bwg_id])
209 adapter->dcb_set_bitmap |= BIT_PG_RX;
210}
211
212static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc,
213 u8 prio, u8 bwg_id, u8 bw_pct,
214 u8 up_map)
215{
216 struct ixgbe_adapter *adapter = netdev_priv(netdev);
217
218 if (prio != DCB_ATTR_VALUE_UNDEFINED)
219 adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type = prio;
220 if (bwg_id != DCB_ATTR_VALUE_UNDEFINED)
221 adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_id = bwg_id;
222 if (bw_pct != DCB_ATTR_VALUE_UNDEFINED)
223 adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent =
224 bw_pct;
225 if (up_map != DCB_ATTR_VALUE_UNDEFINED)
226 adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap =
227 up_map;
228
229 if ((adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type !=
230 adapter->dcb_cfg.tc_config[tc].path[1].prio_type) ||
231 (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_id !=
232 adapter->dcb_cfg.tc_config[tc].path[1].bwg_id) ||
233 (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent !=
234 adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent) ||
235 (adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap !=
236 adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap))
237 adapter->dcb_set_bitmap |= BIT_PG_RX;
238}
239
240static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
241 u8 bw_pct)
242{
243 struct ixgbe_adapter *adapter = netdev_priv(netdev);
244
245 adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct;
246
247 if (adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] !=
248 adapter->dcb_cfg.bw_percentage[1][bwg_id])
249 adapter->dcb_set_bitmap |= BIT_PG_RX;
250}
251
252static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc,
253 u8 *prio, u8 *bwg_id, u8 *bw_pct,
254 u8 *up_map)
255{
256 struct ixgbe_adapter *adapter = netdev_priv(netdev);
257
258 *prio = adapter->dcb_cfg.tc_config[tc].path[0].prio_type;
259 *bwg_id = adapter->dcb_cfg.tc_config[tc].path[0].bwg_id;
260 *bw_pct = adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent;
261 *up_map = adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap;
262}
263
264static void ixgbe_dcbnl_get_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
265 u8 *bw_pct)
266{
267 struct ixgbe_adapter *adapter = netdev_priv(netdev);
268
269 *bw_pct = adapter->dcb_cfg.bw_percentage[0][bwg_id];
270}
271
272static void ixgbe_dcbnl_get_pg_tc_cfg_rx(struct net_device *netdev, int tc,
273 u8 *prio, u8 *bwg_id, u8 *bw_pct,
274 u8 *up_map)
275{
276 struct ixgbe_adapter *adapter = netdev_priv(netdev);
277
278 *prio = adapter->dcb_cfg.tc_config[tc].path[1].prio_type;
279 *bwg_id = adapter->dcb_cfg.tc_config[tc].path[1].bwg_id;
280 *bw_pct = adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent;
281 *up_map = adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap;
282}
283
284static void ixgbe_dcbnl_get_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
285 u8 *bw_pct)
286{
287 struct ixgbe_adapter *adapter = netdev_priv(netdev);
288
289 *bw_pct = adapter->dcb_cfg.bw_percentage[1][bwg_id];
290}
291
292static void ixgbe_dcbnl_set_pfc_cfg(struct net_device *netdev, int priority,
293 u8 setting)
294{
295 struct ixgbe_adapter *adapter = netdev_priv(netdev);
296
297 adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc = setting;
298 if (adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc !=
299 adapter->dcb_cfg.tc_config[priority].dcb_pfc)
300 adapter->dcb_set_bitmap |= BIT_PFC;
301}
302
303static void ixgbe_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority,
304 u8 *setting)
305{
306 struct ixgbe_adapter *adapter = netdev_priv(netdev);
307
308 *setting = adapter->dcb_cfg.tc_config[priority].dcb_pfc;
309}
310
311static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
312{
313 struct ixgbe_adapter *adapter = netdev_priv(netdev);
314 int ret;
315
316 if (!adapter->dcb_set_bitmap)
317 return 1;
318
319 while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
320 msleep(1);
321
322 if (netif_running(netdev))
323 ixgbe_down(adapter);
324
325 ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
326 adapter->ring_feature[RING_F_DCB].indices);
327 if (ret) {
328 clear_bit(__IXGBE_RESETTING, &adapter->state);
329 return ret;
330 }
331
332 if (netif_running(netdev))
333 ixgbe_up(adapter);
334
335 adapter->dcb_set_bitmap = 0x00;
336 clear_bit(__IXGBE_RESETTING, &adapter->state);
337 return ret;
338}
339
340struct dcbnl_rtnl_ops dcbnl_ops = {
341 .getstate = ixgbe_dcbnl_get_state,
342 .setstate = ixgbe_dcbnl_set_state,
343 .getpermhwaddr = ixgbe_dcbnl_get_perm_hw_addr,
344 .setpgtccfgtx = ixgbe_dcbnl_set_pg_tc_cfg_tx,
345 .setpgbwgcfgtx = ixgbe_dcbnl_set_pg_bwg_cfg_tx,
346 .setpgtccfgrx = ixgbe_dcbnl_set_pg_tc_cfg_rx,
347 .setpgbwgcfgrx = ixgbe_dcbnl_set_pg_bwg_cfg_rx,
348 .getpgtccfgtx = ixgbe_dcbnl_get_pg_tc_cfg_tx,
349 .getpgbwgcfgtx = ixgbe_dcbnl_get_pg_bwg_cfg_tx,
350 .getpgtccfgrx = ixgbe_dcbnl_get_pg_tc_cfg_rx,
351 .getpgbwgcfgrx = ixgbe_dcbnl_get_pg_bwg_cfg_rx,
352 .setpfccfg = ixgbe_dcbnl_set_pfc_cfg,
353 .getpfccfg = ixgbe_dcbnl_get_pfc_cfg,
354 .setall = ixgbe_dcbnl_set_all
355};
356