diff options
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_dcb_nl.c')
-rw-r--r-- | drivers/net/ixgbe/ixgbe_dcb_nl.c | 481 |
1 files changed, 340 insertions, 141 deletions
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index b53b465e24af..5e7ed225851a 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************************* | 1 | /******************************************************************************* |
2 | 2 | ||
3 | Intel 10 Gigabit PCI Express Linux driver | 3 | Intel 10 Gigabit PCI Express Linux driver |
4 | Copyright(c) 1999 - 2010 Intel Corporation. | 4 | Copyright(c) 1999 - 2011 Intel Corporation. |
5 | 5 | ||
6 | This program is free software; you can redistribute it and/or modify it | 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, | 7 | under the terms and conditions of the GNU General Public License, |
@@ -37,7 +37,6 @@ | |||
37 | #define BIT_PG_RX 0x04 | 37 | #define BIT_PG_RX 0x04 |
38 | #define BIT_PG_TX 0x08 | 38 | #define BIT_PG_TX 0x08 |
39 | #define BIT_APP_UPCHG 0x10 | 39 | #define BIT_APP_UPCHG 0x10 |
40 | #define BIT_RESETLINK 0x40 | ||
41 | #define BIT_LINKSPEED 0x80 | 40 | #define BIT_LINKSPEED 0x80 |
42 | 41 | ||
43 | /* Responses for the DCB_C_SET_ALL command */ | 42 | /* Responses for the DCB_C_SET_ALL command */ |
@@ -130,16 +129,24 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) | |||
130 | netdev->netdev_ops->ndo_stop(netdev); | 129 | netdev->netdev_ops->ndo_stop(netdev); |
131 | ixgbe_clear_interrupt_scheme(adapter); | 130 | ixgbe_clear_interrupt_scheme(adapter); |
132 | 131 | ||
133 | if (adapter->hw.mac.type == ixgbe_mac_82598EB) { | 132 | switch (adapter->hw.mac.type) { |
133 | case ixgbe_mac_82598EB: | ||
134 | adapter->last_lfc_mode = adapter->hw.fc.current_mode; | 134 | adapter->last_lfc_mode = adapter->hw.fc.current_mode; |
135 | adapter->hw.fc.requested_mode = ixgbe_fc_none; | 135 | adapter->hw.fc.requested_mode = ixgbe_fc_none; |
136 | } | 136 | break; |
137 | adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; | 137 | case ixgbe_mac_82599EB: |
138 | if (adapter->hw.mac.type == ixgbe_mac_82599EB) { | 138 | case ixgbe_mac_X540: |
139 | adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; | 139 | adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; |
140 | adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE; | 140 | adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE; |
141 | break; | ||
142 | default: | ||
143 | break; | ||
141 | } | 144 | } |
145 | |||
142 | adapter->flags |= IXGBE_FLAG_DCB_ENABLED; | 146 | adapter->flags |= IXGBE_FLAG_DCB_ENABLED; |
147 | if (!netdev_get_num_tc(netdev)) | ||
148 | ixgbe_setup_tc(netdev, MAX_TRAFFIC_CLASS); | ||
149 | |||
143 | ixgbe_init_interrupt_scheme(adapter); | 150 | ixgbe_init_interrupt_scheme(adapter); |
144 | if (netif_running(netdev)) | 151 | if (netif_running(netdev)) |
145 | netdev->netdev_ops->ndo_open(netdev); | 152 | netdev->netdev_ops->ndo_open(netdev); |
@@ -154,9 +161,16 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) | |||
154 | adapter->temp_dcb_cfg.pfc_mode_enable = false; | 161 | adapter->temp_dcb_cfg.pfc_mode_enable = false; |
155 | adapter->dcb_cfg.pfc_mode_enable = false; | 162 | adapter->dcb_cfg.pfc_mode_enable = false; |
156 | adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; | 163 | adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; |
157 | adapter->flags |= IXGBE_FLAG_RSS_ENABLED; | 164 | switch (adapter->hw.mac.type) { |
158 | if (adapter->hw.mac.type == ixgbe_mac_82599EB) | 165 | case ixgbe_mac_82599EB: |
166 | case ixgbe_mac_X540: | ||
159 | adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; | 167 | adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; |
168 | break; | ||
169 | default: | ||
170 | break; | ||
171 | } | ||
172 | |||
173 | ixgbe_setup_tc(netdev, 0); | ||
160 | 174 | ||
161 | ixgbe_init_interrupt_scheme(adapter); | 175 | ixgbe_init_interrupt_scheme(adapter); |
162 | if (netif_running(netdev)) | 176 | if (netif_running(netdev)) |
@@ -178,9 +192,14 @@ static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev, | |||
178 | for (i = 0; i < netdev->addr_len; i++) | 192 | for (i = 0; i < netdev->addr_len; i++) |
179 | perm_addr[i] = adapter->hw.mac.perm_addr[i]; | 193 | perm_addr[i] = adapter->hw.mac.perm_addr[i]; |
180 | 194 | ||
181 | if (adapter->hw.mac.type == ixgbe_mac_82599EB) { | 195 | switch (adapter->hw.mac.type) { |
196 | case ixgbe_mac_82599EB: | ||
197 | case ixgbe_mac_X540: | ||
182 | for (j = 0; j < netdev->addr_len; j++, i++) | 198 | for (j = 0; j < netdev->addr_len; j++, i++) |
183 | perm_addr[i] = adapter->hw.mac.san_addr[j]; | 199 | perm_addr[i] = adapter->hw.mac.san_addr[j]; |
200 | break; | ||
201 | default: | ||
202 | break; | ||
184 | } | 203 | } |
185 | } | 204 | } |
186 | 205 | ||
@@ -208,10 +227,8 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc, | |||
208 | (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent != | 227 | (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent != |
209 | adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent) || | 228 | adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent) || |
210 | (adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap != | 229 | (adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap != |
211 | adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap)) { | 230 | adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap)) |
212 | adapter->dcb_set_bitmap |= BIT_PG_TX; | 231 | adapter->dcb_set_bitmap |= BIT_PG_TX; |
213 | adapter->dcb_set_bitmap |= BIT_RESETLINK; | ||
214 | } | ||
215 | } | 232 | } |
216 | 233 | ||
217 | static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id, | 234 | static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id, |
@@ -222,10 +239,8 @@ static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id, | |||
222 | adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct; | 239 | adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct; |
223 | 240 | ||
224 | if (adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] != | 241 | if (adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] != |
225 | adapter->dcb_cfg.bw_percentage[0][bwg_id]) { | 242 | adapter->dcb_cfg.bw_percentage[0][bwg_id]) |
226 | adapter->dcb_set_bitmap |= BIT_PG_TX; | 243 | adapter->dcb_set_bitmap |= BIT_PG_TX; |
227 | adapter->dcb_set_bitmap |= BIT_RESETLINK; | ||
228 | } | ||
229 | } | 244 | } |
230 | 245 | ||
231 | static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc, | 246 | static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc, |
@@ -252,10 +267,8 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc, | |||
252 | (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent != | 267 | (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent != |
253 | adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent) || | 268 | adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent) || |
254 | (adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap != | 269 | (adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap != |
255 | adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap)) { | 270 | adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap)) |
256 | adapter->dcb_set_bitmap |= BIT_PG_RX; | 271 | adapter->dcb_set_bitmap |= BIT_PG_RX; |
257 | adapter->dcb_set_bitmap |= BIT_RESETLINK; | ||
258 | } | ||
259 | } | 272 | } |
260 | 273 | ||
261 | static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id, | 274 | static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id, |
@@ -266,10 +279,8 @@ static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id, | |||
266 | adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct; | 279 | adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct; |
267 | 280 | ||
268 | if (adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] != | 281 | if (adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] != |
269 | adapter->dcb_cfg.bw_percentage[1][bwg_id]) { | 282 | adapter->dcb_cfg.bw_percentage[1][bwg_id]) |
270 | adapter->dcb_set_bitmap |= BIT_PG_RX; | 283 | adapter->dcb_set_bitmap |= BIT_PG_RX; |
271 | adapter->dcb_set_bitmap |= BIT_RESETLINK; | ||
272 | } | ||
273 | } | 284 | } |
274 | 285 | ||
275 | static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc, | 286 | static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc, |
@@ -336,70 +347,120 @@ static void ixgbe_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority, | |||
336 | static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) | 347 | static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) |
337 | { | 348 | { |
338 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 349 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
350 | struct dcb_app app = { | ||
351 | .selector = DCB_APP_IDTYPE_ETHTYPE, | ||
352 | .protocol = ETH_P_FCOE, | ||
353 | }; | ||
354 | u8 up = dcb_getapp(netdev, &app); | ||
339 | int ret; | 355 | int ret; |
340 | 356 | ||
341 | if (!adapter->dcb_set_bitmap) | ||
342 | return DCB_NO_HW_CHG; | ||
343 | |||
344 | ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg, | 357 | ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg, |
345 | adapter->ring_feature[RING_F_DCB].indices); | 358 | MAX_TRAFFIC_CLASS); |
346 | |||
347 | if (ret) | 359 | if (ret) |
348 | return DCB_NO_HW_CHG; | 360 | return DCB_NO_HW_CHG; |
349 | 361 | ||
362 | /* In IEEE mode app data must be parsed into DCBX format for | ||
363 | * hardware routines. | ||
364 | */ | ||
365 | if (adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) | ||
366 | up = (1 << up); | ||
367 | |||
368 | #ifdef IXGBE_FCOE | ||
369 | if (up && (up != (1 << adapter->fcoe.up))) | ||
370 | adapter->dcb_set_bitmap |= BIT_APP_UPCHG; | ||
371 | |||
350 | /* | 372 | /* |
351 | * Only take down the adapter if the configuration change | 373 | * Only take down the adapter if an app change occurred. FCoE |
352 | * requires a reset. | 374 | * may shuffle tx rings in this case and this can not be done |
375 | * without a reset currently. | ||
353 | */ | 376 | */ |
354 | if (adapter->dcb_set_bitmap & BIT_RESETLINK) { | 377 | if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) { |
355 | while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) | 378 | while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) |
356 | msleep(1); | 379 | usleep_range(1000, 2000); |
357 | 380 | ||
358 | if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) { | 381 | ixgbe_fcoe_setapp(adapter, up); |
359 | if (netif_running(netdev)) | 382 | |
360 | netdev->netdev_ops->ndo_stop(netdev); | 383 | if (netif_running(netdev)) |
361 | ixgbe_clear_interrupt_scheme(adapter); | 384 | netdev->netdev_ops->ndo_stop(netdev); |
362 | } else { | 385 | ixgbe_clear_interrupt_scheme(adapter); |
363 | if (netif_running(netdev)) | ||
364 | ixgbe_down(adapter); | ||
365 | } | ||
366 | } | 386 | } |
387 | #endif | ||
367 | 388 | ||
368 | if (adapter->dcb_cfg.pfc_mode_enable) { | 389 | if (adapter->dcb_cfg.pfc_mode_enable) { |
369 | if ((adapter->hw.mac.type != ixgbe_mac_82598EB) && | 390 | switch (adapter->hw.mac.type) { |
370 | (adapter->hw.fc.current_mode != ixgbe_fc_pfc)) | 391 | case ixgbe_mac_82599EB: |
371 | adapter->last_lfc_mode = adapter->hw.fc.current_mode; | 392 | case ixgbe_mac_X540: |
393 | if (adapter->hw.fc.current_mode != ixgbe_fc_pfc) | ||
394 | adapter->last_lfc_mode = | ||
395 | adapter->hw.fc.current_mode; | ||
396 | break; | ||
397 | default: | ||
398 | break; | ||
399 | } | ||
372 | adapter->hw.fc.requested_mode = ixgbe_fc_pfc; | 400 | adapter->hw.fc.requested_mode = ixgbe_fc_pfc; |
373 | } else { | 401 | } else { |
374 | if (adapter->hw.mac.type != ixgbe_mac_82598EB) | 402 | switch (adapter->hw.mac.type) { |
375 | adapter->hw.fc.requested_mode = adapter->last_lfc_mode; | 403 | case ixgbe_mac_82598EB: |
376 | else | ||
377 | adapter->hw.fc.requested_mode = ixgbe_fc_none; | 404 | adapter->hw.fc.requested_mode = ixgbe_fc_none; |
405 | break; | ||
406 | case ixgbe_mac_82599EB: | ||
407 | case ixgbe_mac_X540: | ||
408 | adapter->hw.fc.requested_mode = adapter->last_lfc_mode; | ||
409 | break; | ||
410 | default: | ||
411 | break; | ||
412 | } | ||
378 | } | 413 | } |
379 | 414 | ||
380 | if (adapter->dcb_set_bitmap & BIT_RESETLINK) { | 415 | #ifdef IXGBE_FCOE |
381 | if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) { | 416 | if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) { |
382 | ixgbe_init_interrupt_scheme(adapter); | 417 | ixgbe_init_interrupt_scheme(adapter); |
383 | if (netif_running(netdev)) | 418 | if (netif_running(netdev)) |
384 | netdev->netdev_ops->ndo_open(netdev); | 419 | netdev->netdev_ops->ndo_open(netdev); |
385 | } else { | ||
386 | if (netif_running(netdev)) | ||
387 | ixgbe_up(adapter); | ||
388 | } | ||
389 | ret = DCB_HW_CHG_RST; | 420 | ret = DCB_HW_CHG_RST; |
390 | } else if (adapter->dcb_set_bitmap & BIT_PFC) { | 421 | } |
391 | if (adapter->hw.mac.type == ixgbe_mac_82598EB) | 422 | #endif |
392 | ixgbe_dcb_config_pfc_82598(&adapter->hw, | 423 | |
393 | &adapter->dcb_cfg); | 424 | if (adapter->dcb_set_bitmap & BIT_PFC) { |
394 | else if (adapter->hw.mac.type == ixgbe_mac_82599EB) | 425 | u8 pfc_en; |
395 | ixgbe_dcb_config_pfc_82599(&adapter->hw, | 426 | ixgbe_dcb_unpack_pfc(&adapter->dcb_cfg, &pfc_en); |
396 | &adapter->dcb_cfg); | 427 | ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc_en); |
397 | ret = DCB_HW_CHG; | 428 | ret = DCB_HW_CHG; |
398 | } | 429 | } |
430 | |||
431 | if (adapter->dcb_set_bitmap & (BIT_PG_TX|BIT_PG_RX)) { | ||
432 | u16 refill[MAX_TRAFFIC_CLASS], max[MAX_TRAFFIC_CLASS]; | ||
433 | u8 bwg_id[MAX_TRAFFIC_CLASS], prio_type[MAX_TRAFFIC_CLASS]; | ||
434 | /* Priority to TC mapping in CEE case default to 1:1 */ | ||
435 | u8 prio_tc[MAX_TRAFFIC_CLASS] = {0, 1, 2, 3, 4, 5, 6, 7}; | ||
436 | int max_frame = adapter->netdev->mtu + ETH_HLEN + ETH_FCS_LEN; | ||
437 | |||
438 | #ifdef CONFIG_FCOE | ||
439 | if (adapter->netdev->features & NETIF_F_FCOE_MTU) | ||
440 | max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE); | ||
441 | #endif | ||
442 | |||
443 | ixgbe_dcb_calculate_tc_credits(&adapter->hw, &adapter->dcb_cfg, | ||
444 | max_frame, DCB_TX_CONFIG); | ||
445 | ixgbe_dcb_calculate_tc_credits(&adapter->hw, &adapter->dcb_cfg, | ||
446 | max_frame, DCB_RX_CONFIG); | ||
447 | |||
448 | ixgbe_dcb_unpack_refill(&adapter->dcb_cfg, | ||
449 | DCB_TX_CONFIG, refill); | ||
450 | ixgbe_dcb_unpack_max(&adapter->dcb_cfg, max); | ||
451 | ixgbe_dcb_unpack_bwgid(&adapter->dcb_cfg, | ||
452 | DCB_TX_CONFIG, bwg_id); | ||
453 | ixgbe_dcb_unpack_prio(&adapter->dcb_cfg, | ||
454 | DCB_TX_CONFIG, prio_type); | ||
455 | |||
456 | ixgbe_dcb_hw_ets_config(&adapter->hw, refill, max, | ||
457 | bwg_id, prio_type, prio_tc); | ||
458 | } | ||
459 | |||
399 | if (adapter->dcb_cfg.pfc_mode_enable) | 460 | if (adapter->dcb_cfg.pfc_mode_enable) |
400 | adapter->hw.fc.current_mode = ixgbe_fc_pfc; | 461 | adapter->hw.fc.current_mode = ixgbe_fc_pfc; |
401 | 462 | ||
402 | if (adapter->dcb_set_bitmap & BIT_RESETLINK) | 463 | if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) |
403 | clear_bit(__IXGBE_RESETTING, &adapter->state); | 464 | clear_bit(__IXGBE_RESETTING, &adapter->state); |
404 | adapter->dcb_set_bitmap = 0x00; | 465 | adapter->dcb_set_bitmap = 0x00; |
405 | return ret; | 466 | return ret; |
@@ -408,40 +469,38 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) | |||
408 | static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap) | 469 | static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap) |
409 | { | 470 | { |
410 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 471 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
411 | u8 rval = 0; | ||
412 | 472 | ||
413 | if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { | 473 | switch (capid) { |
414 | switch (capid) { | 474 | case DCB_CAP_ATTR_PG: |
415 | case DCB_CAP_ATTR_PG: | 475 | *cap = true; |
416 | *cap = true; | 476 | break; |
417 | break; | 477 | case DCB_CAP_ATTR_PFC: |
418 | case DCB_CAP_ATTR_PFC: | 478 | *cap = true; |
419 | *cap = true; | 479 | break; |
420 | break; | 480 | case DCB_CAP_ATTR_UP2TC: |
421 | case DCB_CAP_ATTR_UP2TC: | 481 | *cap = false; |
422 | *cap = false; | 482 | break; |
423 | break; | 483 | case DCB_CAP_ATTR_PG_TCS: |
424 | case DCB_CAP_ATTR_PG_TCS: | 484 | *cap = 0x80; |
425 | *cap = 0x80; | 485 | break; |
426 | break; | 486 | case DCB_CAP_ATTR_PFC_TCS: |
427 | case DCB_CAP_ATTR_PFC_TCS: | 487 | *cap = 0x80; |
428 | *cap = 0x80; | 488 | break; |
429 | break; | 489 | case DCB_CAP_ATTR_GSP: |
430 | case DCB_CAP_ATTR_GSP: | 490 | *cap = true; |
431 | *cap = true; | 491 | break; |
432 | break; | 492 | case DCB_CAP_ATTR_BCN: |
433 | case DCB_CAP_ATTR_BCN: | 493 | *cap = false; |
434 | *cap = false; | 494 | break; |
435 | break; | 495 | case DCB_CAP_ATTR_DCBX: |
436 | default: | 496 | *cap = adapter->dcbx_cap; |
437 | rval = -EINVAL; | 497 | break; |
438 | break; | 498 | default: |
439 | } | 499 | *cap = false; |
440 | } else { | 500 | break; |
441 | rval = -EINVAL; | ||
442 | } | 501 | } |
443 | 502 | ||
444 | return rval; | 503 | return 0; |
445 | } | 504 | } |
446 | 505 | ||
447 | static u8 ixgbe_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num) | 506 | static u8 ixgbe_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num) |
@@ -502,65 +561,205 @@ static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state) | |||
502 | */ | 561 | */ |
503 | static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id) | 562 | static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id) |
504 | { | 563 | { |
505 | u8 rval = 0; | 564 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
565 | struct dcb_app app = { | ||
566 | .selector = idtype, | ||
567 | .protocol = id, | ||
568 | }; | ||
506 | 569 | ||
507 | switch (idtype) { | 570 | if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) |
508 | case DCB_APP_IDTYPE_ETHTYPE: | 571 | return 0; |
509 | #ifdef IXGBE_FCOE | 572 | |
510 | if (id == ETH_P_FCOE) | 573 | return dcb_getapp(netdev, &app); |
511 | rval = ixgbe_fcoe_getapp(netdev_priv(netdev)); | 574 | } |
512 | #endif | 575 | |
513 | break; | 576 | static int ixgbe_dcbnl_ieee_getets(struct net_device *dev, |
514 | case DCB_APP_IDTYPE_PORTNUM: | 577 | struct ieee_ets *ets) |
515 | break; | 578 | { |
516 | default: | 579 | struct ixgbe_adapter *adapter = netdev_priv(dev); |
517 | break; | 580 | struct ieee_ets *my_ets = adapter->ixgbe_ieee_ets; |
581 | |||
582 | /* No IEEE PFC settings available */ | ||
583 | if (!my_ets) | ||
584 | return -EINVAL; | ||
585 | |||
586 | ets->ets_cap = MAX_TRAFFIC_CLASS; | ||
587 | ets->cbs = my_ets->cbs; | ||
588 | memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw)); | ||
589 | memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw)); | ||
590 | memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa)); | ||
591 | memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc)); | ||
592 | return 0; | ||
593 | } | ||
594 | |||
595 | static int ixgbe_dcbnl_ieee_setets(struct net_device *dev, | ||
596 | struct ieee_ets *ets) | ||
597 | { | ||
598 | struct ixgbe_adapter *adapter = netdev_priv(dev); | ||
599 | __u16 refill[IEEE_8021QAZ_MAX_TCS], max[IEEE_8021QAZ_MAX_TCS]; | ||
600 | __u8 prio_type[IEEE_8021QAZ_MAX_TCS]; | ||
601 | int max_frame = dev->mtu + ETH_HLEN + ETH_FCS_LEN; | ||
602 | int i, err; | ||
603 | __u64 *p = (__u64 *) ets->prio_tc; | ||
604 | /* naively give each TC a bwg to map onto CEE hardware */ | ||
605 | __u8 bwg_id[IEEE_8021QAZ_MAX_TCS] = {0, 1, 2, 3, 4, 5, 6, 7}; | ||
606 | |||
607 | if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) | ||
608 | return -EINVAL; | ||
609 | |||
610 | if (!adapter->ixgbe_ieee_ets) { | ||
611 | adapter->ixgbe_ieee_ets = kmalloc(sizeof(struct ieee_ets), | ||
612 | GFP_KERNEL); | ||
613 | if (!adapter->ixgbe_ieee_ets) | ||
614 | return -ENOMEM; | ||
518 | } | 615 | } |
519 | return rval; | 616 | |
617 | memcpy(adapter->ixgbe_ieee_ets, ets, sizeof(*adapter->ixgbe_ieee_ets)); | ||
618 | |||
619 | /* Map TSA onto CEE prio type */ | ||
620 | for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { | ||
621 | switch (ets->tc_tsa[i]) { | ||
622 | case IEEE_8021QAZ_TSA_STRICT: | ||
623 | prio_type[i] = 2; | ||
624 | break; | ||
625 | case IEEE_8021QAZ_TSA_ETS: | ||
626 | prio_type[i] = 0; | ||
627 | break; | ||
628 | default: | ||
629 | /* Hardware only supports priority strict or | ||
630 | * ETS transmission selection algorithms if | ||
631 | * we receive some other value from dcbnl | ||
632 | * throw an error | ||
633 | */ | ||
634 | return -EINVAL; | ||
635 | } | ||
636 | } | ||
637 | |||
638 | if (*p) | ||
639 | ixgbe_dcbnl_set_state(dev, 1); | ||
640 | else | ||
641 | ixgbe_dcbnl_set_state(dev, 0); | ||
642 | |||
643 | ixgbe_ieee_credits(ets->tc_tx_bw, refill, max, max_frame); | ||
644 | err = ixgbe_dcb_hw_ets_config(&adapter->hw, refill, max, | ||
645 | bwg_id, prio_type, ets->prio_tc); | ||
646 | return err; | ||
520 | } | 647 | } |
521 | 648 | ||
522 | /** | 649 | static int ixgbe_dcbnl_ieee_getpfc(struct net_device *dev, |
523 | * ixgbe_dcbnl_setapp - set the DCBX application user priority | 650 | struct ieee_pfc *pfc) |
524 | * @netdev : the corresponding netdev | 651 | { |
525 | * @idtype : identifies the id as ether type or TCP/UDP port number | 652 | struct ixgbe_adapter *adapter = netdev_priv(dev); |
526 | * @id: id is either ether type or TCP/UDP port number | 653 | struct ieee_pfc *my_pfc = adapter->ixgbe_ieee_pfc; |
527 | * @up: the 802.1p user priority bitmap | 654 | int i; |
528 | * | 655 | |
529 | * Returns : 0 on success or 1 on error | 656 | /* No IEEE PFC settings available */ |
530 | */ | 657 | if (!my_pfc) |
531 | static u8 ixgbe_dcbnl_setapp(struct net_device *netdev, | 658 | return -EINVAL; |
532 | u8 idtype, u16 id, u8 up) | 659 | |
660 | pfc->pfc_cap = MAX_TRAFFIC_CLASS; | ||
661 | pfc->pfc_en = my_pfc->pfc_en; | ||
662 | pfc->mbc = my_pfc->mbc; | ||
663 | pfc->delay = my_pfc->delay; | ||
664 | |||
665 | for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { | ||
666 | pfc->requests[i] = adapter->stats.pxoffrxc[i]; | ||
667 | pfc->indications[i] = adapter->stats.pxofftxc[i]; | ||
668 | } | ||
669 | |||
670 | return 0; | ||
671 | } | ||
672 | |||
673 | static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev, | ||
674 | struct ieee_pfc *pfc) | ||
675 | { | ||
676 | struct ixgbe_adapter *adapter = netdev_priv(dev); | ||
677 | int err; | ||
678 | |||
679 | if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) | ||
680 | return -EINVAL; | ||
681 | |||
682 | if (!adapter->ixgbe_ieee_pfc) { | ||
683 | adapter->ixgbe_ieee_pfc = kmalloc(sizeof(struct ieee_pfc), | ||
684 | GFP_KERNEL); | ||
685 | if (!adapter->ixgbe_ieee_pfc) | ||
686 | return -ENOMEM; | ||
687 | } | ||
688 | |||
689 | memcpy(adapter->ixgbe_ieee_pfc, pfc, sizeof(*adapter->ixgbe_ieee_pfc)); | ||
690 | err = ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc->pfc_en); | ||
691 | return err; | ||
692 | } | ||
693 | |||
694 | static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev, | ||
695 | struct dcb_app *app) | ||
533 | { | 696 | { |
534 | u8 rval = 1; | 697 | struct ixgbe_adapter *adapter = netdev_priv(dev); |
698 | |||
699 | if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) | ||
700 | return -EINVAL; | ||
701 | |||
702 | dcb_setapp(dev, app); | ||
535 | 703 | ||
536 | switch (idtype) { | ||
537 | case DCB_APP_IDTYPE_ETHTYPE: | ||
538 | #ifdef IXGBE_FCOE | 704 | #ifdef IXGBE_FCOE |
539 | if (id == ETH_P_FCOE) { | 705 | if (app->selector == 1 && app->protocol == ETH_P_FCOE && |
540 | u8 tc; | 706 | adapter->fcoe.tc == app->priority) |
541 | struct ixgbe_adapter *adapter; | 707 | ixgbe_dcbnl_set_all(dev); |
542 | |||
543 | adapter = netdev_priv(netdev); | ||
544 | tc = adapter->fcoe.tc; | ||
545 | rval = ixgbe_fcoe_setapp(adapter, up); | ||
546 | if ((!rval) && (tc != adapter->fcoe.tc) && | ||
547 | (adapter->flags & IXGBE_FLAG_DCB_ENABLED) && | ||
548 | (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)) { | ||
549 | adapter->dcb_set_bitmap |= BIT_APP_UPCHG; | ||
550 | adapter->dcb_set_bitmap |= BIT_RESETLINK; | ||
551 | } | ||
552 | } | ||
553 | #endif | 708 | #endif |
554 | break; | 709 | return 0; |
555 | case DCB_APP_IDTYPE_PORTNUM: | 710 | } |
556 | break; | 711 | |
557 | default: | 712 | static u8 ixgbe_dcbnl_getdcbx(struct net_device *dev) |
558 | break; | 713 | { |
714 | struct ixgbe_adapter *adapter = netdev_priv(dev); | ||
715 | return adapter->dcbx_cap; | ||
716 | } | ||
717 | |||
718 | static u8 ixgbe_dcbnl_setdcbx(struct net_device *dev, u8 mode) | ||
719 | { | ||
720 | struct ixgbe_adapter *adapter = netdev_priv(dev); | ||
721 | struct ieee_ets ets = {0}; | ||
722 | struct ieee_pfc pfc = {0}; | ||
723 | |||
724 | /* no support for LLD_MANAGED modes or CEE+IEEE */ | ||
725 | if ((mode & DCB_CAP_DCBX_LLD_MANAGED) || | ||
726 | ((mode & DCB_CAP_DCBX_VER_IEEE) && (mode & DCB_CAP_DCBX_VER_CEE)) || | ||
727 | !(mode & DCB_CAP_DCBX_HOST)) | ||
728 | return 1; | ||
729 | |||
730 | if (mode == adapter->dcbx_cap) | ||
731 | return 0; | ||
732 | |||
733 | adapter->dcbx_cap = mode; | ||
734 | |||
735 | /* ETS and PFC defaults */ | ||
736 | ets.ets_cap = 8; | ||
737 | pfc.pfc_cap = 8; | ||
738 | |||
739 | if (mode & DCB_CAP_DCBX_VER_IEEE) { | ||
740 | ixgbe_dcbnl_ieee_setets(dev, &ets); | ||
741 | ixgbe_dcbnl_ieee_setpfc(dev, &pfc); | ||
742 | } else if (mode & DCB_CAP_DCBX_VER_CEE) { | ||
743 | adapter->dcb_set_bitmap |= (BIT_PFC & BIT_PG_TX & BIT_PG_RX); | ||
744 | ixgbe_dcbnl_set_all(dev); | ||
745 | } else { | ||
746 | /* Drop into single TC mode strict priority as this | ||
747 | * indicates CEE and IEEE versions are disabled | ||
748 | */ | ||
749 | ixgbe_dcbnl_ieee_setets(dev, &ets); | ||
750 | ixgbe_dcbnl_ieee_setpfc(dev, &pfc); | ||
751 | ixgbe_dcbnl_set_state(dev, 0); | ||
559 | } | 752 | } |
560 | return rval; | 753 | |
754 | return 0; | ||
561 | } | 755 | } |
562 | 756 | ||
563 | const struct dcbnl_rtnl_ops dcbnl_ops = { | 757 | const struct dcbnl_rtnl_ops dcbnl_ops = { |
758 | .ieee_getets = ixgbe_dcbnl_ieee_getets, | ||
759 | .ieee_setets = ixgbe_dcbnl_ieee_setets, | ||
760 | .ieee_getpfc = ixgbe_dcbnl_ieee_getpfc, | ||
761 | .ieee_setpfc = ixgbe_dcbnl_ieee_setpfc, | ||
762 | .ieee_setapp = ixgbe_dcbnl_ieee_setapp, | ||
564 | .getstate = ixgbe_dcbnl_get_state, | 763 | .getstate = ixgbe_dcbnl_get_state, |
565 | .setstate = ixgbe_dcbnl_set_state, | 764 | .setstate = ixgbe_dcbnl_set_state, |
566 | .getpermhwaddr = ixgbe_dcbnl_get_perm_hw_addr, | 765 | .getpermhwaddr = ixgbe_dcbnl_get_perm_hw_addr, |
@@ -581,6 +780,6 @@ const struct dcbnl_rtnl_ops dcbnl_ops = { | |||
581 | .getpfcstate = ixgbe_dcbnl_getpfcstate, | 780 | .getpfcstate = ixgbe_dcbnl_getpfcstate, |
582 | .setpfcstate = ixgbe_dcbnl_setpfcstate, | 781 | .setpfcstate = ixgbe_dcbnl_setpfcstate, |
583 | .getapp = ixgbe_dcbnl_getapp, | 782 | .getapp = ixgbe_dcbnl_getapp, |
584 | .setapp = ixgbe_dcbnl_setapp, | 783 | .getdcbx = ixgbe_dcbnl_getdcbx, |
784 | .setdcbx = ixgbe_dcbnl_setdcbx, | ||
585 | }; | 785 | }; |
586 | |||