diff options
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_dcb_nl.c')
-rw-r--r-- | drivers/net/ixgbe/ixgbe_dcb_nl.c | 356 |
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 | |||
38 | int 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 | |||
94 | static 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 | |||
103 | static 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 | |||
109 | static 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 | |||
162 | static 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 | |||
172 | static 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 | |||
200 | static 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 | |||
212 | static 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 | |||
240 | static 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 | |||
252 | static 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 | |||
264 | static 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 | |||
272 | static 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 | |||
284 | static 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 | |||
292 | static 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 | |||
303 | static 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 | |||
311 | static 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 | |||
340 | struct 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 | |||