diff options
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_dcb_nl.c')
-rw-r--r-- | drivers/net/ixgbe/ixgbe_dcb_nl.c | 429 |
1 files changed, 328 insertions, 101 deletions
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index bf566e8a455..fec4c724c37 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,7 +129,6 @@ 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 | adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; | ||
134 | switch (adapter->hw.mac.type) { | 132 | switch (adapter->hw.mac.type) { |
135 | case ixgbe_mac_82598EB: | 133 | case ixgbe_mac_82598EB: |
136 | adapter->last_lfc_mode = adapter->hw.fc.current_mode; | 134 | adapter->last_lfc_mode = adapter->hw.fc.current_mode; |
@@ -146,6 +144,9 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) | |||
146 | } | 144 | } |
147 | 145 | ||
148 | 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 | |||
149 | ixgbe_init_interrupt_scheme(adapter); | 150 | ixgbe_init_interrupt_scheme(adapter); |
150 | if (netif_running(netdev)) | 151 | if (netif_running(netdev)) |
151 | netdev->netdev_ops->ndo_open(netdev); | 152 | netdev->netdev_ops->ndo_open(netdev); |
@@ -160,7 +161,6 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) | |||
160 | adapter->temp_dcb_cfg.pfc_mode_enable = false; | 161 | adapter->temp_dcb_cfg.pfc_mode_enable = false; |
161 | adapter->dcb_cfg.pfc_mode_enable = false; | 162 | adapter->dcb_cfg.pfc_mode_enable = false; |
162 | adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; | 163 | adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; |
163 | adapter->flags |= IXGBE_FLAG_RSS_ENABLED; | ||
164 | switch (adapter->hw.mac.type) { | 164 | switch (adapter->hw.mac.type) { |
165 | case ixgbe_mac_82599EB: | 165 | case ixgbe_mac_82599EB: |
166 | case ixgbe_mac_X540: | 166 | case ixgbe_mac_X540: |
@@ -170,6 +170,8 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) | |||
170 | break; | 170 | break; |
171 | } | 171 | } |
172 | 172 | ||
173 | ixgbe_setup_tc(netdev, 0); | ||
174 | |||
173 | ixgbe_init_interrupt_scheme(adapter); | 175 | ixgbe_init_interrupt_scheme(adapter); |
174 | if (netif_running(netdev)) | 176 | if (netif_running(netdev)) |
175 | netdev->netdev_ops->ndo_open(netdev); | 177 | netdev->netdev_ops->ndo_open(netdev); |
@@ -225,10 +227,8 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc, | |||
225 | (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent != | 227 | (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent != |
226 | adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent) || | 228 | adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent) || |
227 | (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 != |
228 | 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)) |
229 | adapter->dcb_set_bitmap |= BIT_PG_TX; | 231 | adapter->dcb_set_bitmap |= BIT_PG_TX; |
230 | adapter->dcb_set_bitmap |= BIT_RESETLINK; | ||
231 | } | ||
232 | } | 232 | } |
233 | 233 | ||
234 | 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, |
@@ -239,10 +239,8 @@ static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id, | |||
239 | adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct; | 239 | adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct; |
240 | 240 | ||
241 | if (adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] != | 241 | if (adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] != |
242 | adapter->dcb_cfg.bw_percentage[0][bwg_id]) { | 242 | adapter->dcb_cfg.bw_percentage[0][bwg_id]) |
243 | adapter->dcb_set_bitmap |= BIT_PG_TX; | 243 | adapter->dcb_set_bitmap |= BIT_PG_TX; |
244 | adapter->dcb_set_bitmap |= BIT_RESETLINK; | ||
245 | } | ||
246 | } | 244 | } |
247 | 245 | ||
248 | 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, |
@@ -269,10 +267,8 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc, | |||
269 | (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent != | 267 | (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent != |
270 | adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent) || | 268 | adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent) || |
271 | (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 != |
272 | 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)) |
273 | adapter->dcb_set_bitmap |= BIT_PG_RX; | 271 | adapter->dcb_set_bitmap |= BIT_PG_RX; |
274 | adapter->dcb_set_bitmap |= BIT_RESETLINK; | ||
275 | } | ||
276 | } | 272 | } |
277 | 273 | ||
278 | 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, |
@@ -283,10 +279,8 @@ static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id, | |||
283 | adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct; | 279 | adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct; |
284 | 280 | ||
285 | if (adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] != | 281 | if (adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] != |
286 | adapter->dcb_cfg.bw_percentage[1][bwg_id]) { | 282 | adapter->dcb_cfg.bw_percentage[1][bwg_id]) |
287 | adapter->dcb_set_bitmap |= BIT_PG_RX; | 283 | adapter->dcb_set_bitmap |= BIT_PG_RX; |
288 | adapter->dcb_set_bitmap |= BIT_RESETLINK; | ||
289 | } | ||
290 | } | 284 | } |
291 | 285 | ||
292 | 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, |
@@ -355,31 +349,28 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) | |||
355 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 349 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
356 | int ret; | 350 | int ret; |
357 | 351 | ||
358 | if (!adapter->dcb_set_bitmap) | 352 | if (!adapter->dcb_set_bitmap || |
353 | !(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) | ||
359 | return DCB_NO_HW_CHG; | 354 | return DCB_NO_HW_CHG; |
360 | 355 | ||
361 | ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg, | 356 | ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg, |
362 | adapter->ring_feature[RING_F_DCB].indices); | 357 | MAX_TRAFFIC_CLASS); |
363 | 358 | ||
364 | if (ret) | 359 | if (ret) |
365 | return DCB_NO_HW_CHG; | 360 | return DCB_NO_HW_CHG; |
366 | 361 | ||
367 | /* | 362 | /* |
368 | * Only take down the adapter if the configuration change | 363 | * Only take down the adapter if an app change occured. FCoE |
369 | * requires a reset. | 364 | * may shuffle tx rings in this case and this can not be done |
365 | * without a reset currently. | ||
370 | */ | 366 | */ |
371 | if (adapter->dcb_set_bitmap & BIT_RESETLINK) { | 367 | if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) { |
372 | while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) | 368 | while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) |
373 | msleep(1); | 369 | msleep(1); |
374 | 370 | ||
375 | if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) { | 371 | if (netif_running(netdev)) |
376 | if (netif_running(netdev)) | 372 | netdev->netdev_ops->ndo_stop(netdev); |
377 | netdev->netdev_ops->ndo_stop(netdev); | 373 | ixgbe_clear_interrupt_scheme(adapter); |
378 | ixgbe_clear_interrupt_scheme(adapter); | ||
379 | } else { | ||
380 | if (netif_running(netdev)) | ||
381 | ixgbe_down(adapter); | ||
382 | } | ||
383 | } | 374 | } |
384 | 375 | ||
385 | if (adapter->dcb_cfg.pfc_mode_enable) { | 376 | if (adapter->dcb_cfg.pfc_mode_enable) { |
@@ -408,29 +399,53 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) | |||
408 | } | 399 | } |
409 | } | 400 | } |
410 | 401 | ||
411 | if (adapter->dcb_set_bitmap & BIT_RESETLINK) { | 402 | if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) { |
412 | if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) { | 403 | ixgbe_init_interrupt_scheme(adapter); |
413 | ixgbe_init_interrupt_scheme(adapter); | 404 | if (netif_running(netdev)) |
414 | if (netif_running(netdev)) | 405 | netdev->netdev_ops->ndo_open(netdev); |
415 | netdev->netdev_ops->ndo_open(netdev); | ||
416 | } else { | ||
417 | if (netif_running(netdev)) | ||
418 | ixgbe_up(adapter); | ||
419 | } | ||
420 | ret = DCB_HW_CHG_RST; | 406 | ret = DCB_HW_CHG_RST; |
421 | } else if (adapter->dcb_set_bitmap & BIT_PFC) { | 407 | } |
422 | if (adapter->hw.mac.type == ixgbe_mac_82598EB) | 408 | |
423 | ixgbe_dcb_config_pfc_82598(&adapter->hw, | 409 | if (adapter->dcb_set_bitmap & BIT_PFC) { |
424 | &adapter->dcb_cfg); | 410 | u8 pfc_en; |
425 | else if (adapter->hw.mac.type == ixgbe_mac_82599EB) | 411 | ixgbe_dcb_unpack_pfc(&adapter->dcb_cfg, &pfc_en); |
426 | ixgbe_dcb_config_pfc_82599(&adapter->hw, | 412 | ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc_en); |
427 | &adapter->dcb_cfg); | ||
428 | ret = DCB_HW_CHG; | 413 | ret = DCB_HW_CHG; |
429 | } | 414 | } |
415 | |||
416 | if (adapter->dcb_set_bitmap & (BIT_PG_TX|BIT_PG_RX)) { | ||
417 | u16 refill[MAX_TRAFFIC_CLASS], max[MAX_TRAFFIC_CLASS]; | ||
418 | u8 bwg_id[MAX_TRAFFIC_CLASS], prio_type[MAX_TRAFFIC_CLASS]; | ||
419 | /* Priority to TC mapping in CEE case default to 1:1 */ | ||
420 | u8 prio_tc[MAX_TRAFFIC_CLASS] = {0, 1, 2, 3, 4, 5, 6, 7}; | ||
421 | int max_frame = adapter->netdev->mtu + ETH_HLEN + ETH_FCS_LEN; | ||
422 | |||
423 | #ifdef CONFIG_FCOE | ||
424 | if (adapter->netdev->features & NETIF_F_FCOE_MTU) | ||
425 | max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE); | ||
426 | #endif | ||
427 | |||
428 | ixgbe_dcb_calculate_tc_credits(&adapter->hw, &adapter->dcb_cfg, | ||
429 | max_frame, DCB_TX_CONFIG); | ||
430 | ixgbe_dcb_calculate_tc_credits(&adapter->hw, &adapter->dcb_cfg, | ||
431 | max_frame, DCB_RX_CONFIG); | ||
432 | |||
433 | ixgbe_dcb_unpack_refill(&adapter->dcb_cfg, | ||
434 | DCB_TX_CONFIG, refill); | ||
435 | ixgbe_dcb_unpack_max(&adapter->dcb_cfg, max); | ||
436 | ixgbe_dcb_unpack_bwgid(&adapter->dcb_cfg, | ||
437 | DCB_TX_CONFIG, bwg_id); | ||
438 | ixgbe_dcb_unpack_prio(&adapter->dcb_cfg, | ||
439 | DCB_TX_CONFIG, prio_type); | ||
440 | |||
441 | ixgbe_dcb_hw_ets_config(&adapter->hw, refill, max, | ||
442 | bwg_id, prio_type, prio_tc); | ||
443 | } | ||
444 | |||
430 | if (adapter->dcb_cfg.pfc_mode_enable) | 445 | if (adapter->dcb_cfg.pfc_mode_enable) |
431 | adapter->hw.fc.current_mode = ixgbe_fc_pfc; | 446 | adapter->hw.fc.current_mode = ixgbe_fc_pfc; |
432 | 447 | ||
433 | if (adapter->dcb_set_bitmap & BIT_RESETLINK) | 448 | if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) |
434 | clear_bit(__IXGBE_RESETTING, &adapter->state); | 449 | clear_bit(__IXGBE_RESETTING, &adapter->state); |
435 | adapter->dcb_set_bitmap = 0x00; | 450 | adapter->dcb_set_bitmap = 0x00; |
436 | return ret; | 451 | return ret; |
@@ -439,40 +454,38 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) | |||
439 | static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap) | 454 | static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap) |
440 | { | 455 | { |
441 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 456 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
442 | u8 rval = 0; | ||
443 | 457 | ||
444 | if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { | 458 | switch (capid) { |
445 | switch (capid) { | 459 | case DCB_CAP_ATTR_PG: |
446 | case DCB_CAP_ATTR_PG: | 460 | *cap = true; |
447 | *cap = true; | 461 | break; |
448 | break; | 462 | case DCB_CAP_ATTR_PFC: |
449 | case DCB_CAP_ATTR_PFC: | 463 | *cap = true; |
450 | *cap = true; | 464 | break; |
451 | break; | 465 | case DCB_CAP_ATTR_UP2TC: |
452 | case DCB_CAP_ATTR_UP2TC: | 466 | *cap = false; |
453 | *cap = false; | 467 | break; |
454 | break; | 468 | case DCB_CAP_ATTR_PG_TCS: |
455 | case DCB_CAP_ATTR_PG_TCS: | 469 | *cap = 0x80; |
456 | *cap = 0x80; | 470 | break; |
457 | break; | 471 | case DCB_CAP_ATTR_PFC_TCS: |
458 | case DCB_CAP_ATTR_PFC_TCS: | 472 | *cap = 0x80; |
459 | *cap = 0x80; | 473 | break; |
460 | break; | 474 | case DCB_CAP_ATTR_GSP: |
461 | case DCB_CAP_ATTR_GSP: | 475 | *cap = true; |
462 | *cap = true; | 476 | break; |
463 | break; | 477 | case DCB_CAP_ATTR_BCN: |
464 | case DCB_CAP_ATTR_BCN: | 478 | *cap = false; |
465 | *cap = false; | 479 | break; |
466 | break; | 480 | case DCB_CAP_ATTR_DCBX: |
467 | default: | 481 | *cap = adapter->dcbx_cap; |
468 | rval = -EINVAL; | 482 | break; |
469 | break; | 483 | default: |
470 | } | 484 | *cap = false; |
471 | } else { | 485 | break; |
472 | rval = -EINVAL; | ||
473 | } | 486 | } |
474 | 487 | ||
475 | return rval; | 488 | return 0; |
476 | } | 489 | } |
477 | 490 | ||
478 | static u8 ixgbe_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num) | 491 | static u8 ixgbe_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num) |
@@ -533,21 +546,16 @@ static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state) | |||
533 | */ | 546 | */ |
534 | static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id) | 547 | static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id) |
535 | { | 548 | { |
536 | u8 rval = 0; | 549 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
550 | struct dcb_app app = { | ||
551 | .selector = idtype, | ||
552 | .protocol = id, | ||
553 | }; | ||
537 | 554 | ||
538 | switch (idtype) { | 555 | if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) |
539 | case DCB_APP_IDTYPE_ETHTYPE: | 556 | return 0; |
540 | #ifdef IXGBE_FCOE | 557 | |
541 | if (id == ETH_P_FCOE) | 558 | return dcb_getapp(netdev, &app); |
542 | rval = ixgbe_fcoe_getapp(netdev_priv(netdev)); | ||
543 | #endif | ||
544 | break; | ||
545 | case DCB_APP_IDTYPE_PORTNUM: | ||
546 | break; | ||
547 | default: | ||
548 | break; | ||
549 | } | ||
550 | return rval; | ||
551 | } | 559 | } |
552 | 560 | ||
553 | /** | 561 | /** |
@@ -562,24 +570,45 @@ static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id) | |||
562 | static u8 ixgbe_dcbnl_setapp(struct net_device *netdev, | 570 | static u8 ixgbe_dcbnl_setapp(struct net_device *netdev, |
563 | u8 idtype, u16 id, u8 up) | 571 | u8 idtype, u16 id, u8 up) |
564 | { | 572 | { |
573 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
565 | u8 rval = 1; | 574 | u8 rval = 1; |
575 | struct dcb_app app = { | ||
576 | .selector = idtype, | ||
577 | .protocol = id, | ||
578 | .priority = up | ||
579 | }; | ||
580 | |||
581 | if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) | ||
582 | return rval; | ||
583 | |||
584 | rval = dcb_setapp(netdev, &app); | ||
566 | 585 | ||
567 | switch (idtype) { | 586 | switch (idtype) { |
568 | case DCB_APP_IDTYPE_ETHTYPE: | 587 | case DCB_APP_IDTYPE_ETHTYPE: |
569 | #ifdef IXGBE_FCOE | 588 | #ifdef IXGBE_FCOE |
570 | if (id == ETH_P_FCOE) { | 589 | if (id == ETH_P_FCOE) { |
571 | u8 tc; | 590 | u8 old_tc; |
572 | struct ixgbe_adapter *adapter; | ||
573 | 591 | ||
574 | adapter = netdev_priv(netdev); | 592 | /* Get current programmed tc */ |
575 | tc = adapter->fcoe.tc; | 593 | old_tc = adapter->fcoe.tc; |
576 | rval = ixgbe_fcoe_setapp(adapter, up); | 594 | rval = ixgbe_fcoe_setapp(adapter, up); |
577 | if ((!rval) && (tc != adapter->fcoe.tc) && | 595 | |
578 | (adapter->flags & IXGBE_FLAG_DCB_ENABLED) && | 596 | if (rval || |
579 | (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)) { | 597 | !(adapter->flags & IXGBE_FLAG_DCB_ENABLED) || |
598 | !(adapter->flags & IXGBE_FLAG_FCOE_ENABLED)) | ||
599 | break; | ||
600 | |||
601 | /* The FCoE application priority may be changed multiple | ||
602 | * times in quick sucession with switches that build up | ||
603 | * TLVs. To avoid creating uneeded device resets this | ||
604 | * checks the actual HW configuration and clears | ||
605 | * BIT_APP_UPCHG if a HW configuration change is not | ||
606 | * need | ||
607 | */ | ||
608 | if (old_tc == adapter->fcoe.tc) | ||
609 | adapter->dcb_set_bitmap &= ~BIT_APP_UPCHG; | ||
610 | else | ||
580 | adapter->dcb_set_bitmap |= BIT_APP_UPCHG; | 611 | adapter->dcb_set_bitmap |= BIT_APP_UPCHG; |
581 | adapter->dcb_set_bitmap |= BIT_RESETLINK; | ||
582 | } | ||
583 | } | 612 | } |
584 | #endif | 613 | #endif |
585 | break; | 614 | break; |
@@ -591,7 +620,204 @@ static u8 ixgbe_dcbnl_setapp(struct net_device *netdev, | |||
591 | return rval; | 620 | return rval; |
592 | } | 621 | } |
593 | 622 | ||
623 | static int ixgbe_dcbnl_ieee_getets(struct net_device *dev, | ||
624 | struct ieee_ets *ets) | ||
625 | { | ||
626 | struct ixgbe_adapter *adapter = netdev_priv(dev); | ||
627 | struct ieee_ets *my_ets = adapter->ixgbe_ieee_ets; | ||
628 | |||
629 | /* No IEEE PFC settings available */ | ||
630 | if (!my_ets) | ||
631 | return -EINVAL; | ||
632 | |||
633 | ets->ets_cap = MAX_TRAFFIC_CLASS; | ||
634 | ets->cbs = my_ets->cbs; | ||
635 | memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw)); | ||
636 | memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw)); | ||
637 | memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa)); | ||
638 | memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc)); | ||
639 | return 0; | ||
640 | } | ||
641 | |||
642 | static int ixgbe_dcbnl_ieee_setets(struct net_device *dev, | ||
643 | struct ieee_ets *ets) | ||
644 | { | ||
645 | struct ixgbe_adapter *adapter = netdev_priv(dev); | ||
646 | __u16 refill[IEEE_8021QAZ_MAX_TCS], max[IEEE_8021QAZ_MAX_TCS]; | ||
647 | __u8 prio_type[IEEE_8021QAZ_MAX_TCS]; | ||
648 | int max_frame = dev->mtu + ETH_HLEN + ETH_FCS_LEN; | ||
649 | int i, err; | ||
650 | __u64 *p = (__u64 *) ets->prio_tc; | ||
651 | /* naively give each TC a bwg to map onto CEE hardware */ | ||
652 | __u8 bwg_id[IEEE_8021QAZ_MAX_TCS] = {0, 1, 2, 3, 4, 5, 6, 7}; | ||
653 | |||
654 | if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) | ||
655 | return -EINVAL; | ||
656 | |||
657 | if (!adapter->ixgbe_ieee_ets) { | ||
658 | adapter->ixgbe_ieee_ets = kmalloc(sizeof(struct ieee_ets), | ||
659 | GFP_KERNEL); | ||
660 | if (!adapter->ixgbe_ieee_ets) | ||
661 | return -ENOMEM; | ||
662 | } | ||
663 | |||
664 | memcpy(adapter->ixgbe_ieee_ets, ets, sizeof(*adapter->ixgbe_ieee_ets)); | ||
665 | |||
666 | /* Map TSA onto CEE prio type */ | ||
667 | for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { | ||
668 | switch (ets->tc_tsa[i]) { | ||
669 | case IEEE_8021QAZ_TSA_STRICT: | ||
670 | prio_type[i] = 2; | ||
671 | break; | ||
672 | case IEEE_8021QAZ_TSA_ETS: | ||
673 | prio_type[i] = 0; | ||
674 | break; | ||
675 | default: | ||
676 | /* Hardware only supports priority strict or | ||
677 | * ETS transmission selection algorithms if | ||
678 | * we receive some other value from dcbnl | ||
679 | * throw an error | ||
680 | */ | ||
681 | return -EINVAL; | ||
682 | } | ||
683 | } | ||
684 | |||
685 | if (*p) | ||
686 | ixgbe_dcbnl_set_state(dev, 1); | ||
687 | else | ||
688 | ixgbe_dcbnl_set_state(dev, 0); | ||
689 | |||
690 | ixgbe_ieee_credits(ets->tc_tx_bw, refill, max, max_frame); | ||
691 | err = ixgbe_dcb_hw_ets_config(&adapter->hw, refill, max, | ||
692 | bwg_id, prio_type, ets->prio_tc); | ||
693 | return err; | ||
694 | } | ||
695 | |||
696 | static int ixgbe_dcbnl_ieee_getpfc(struct net_device *dev, | ||
697 | struct ieee_pfc *pfc) | ||
698 | { | ||
699 | struct ixgbe_adapter *adapter = netdev_priv(dev); | ||
700 | struct ieee_pfc *my_pfc = adapter->ixgbe_ieee_pfc; | ||
701 | int i; | ||
702 | |||
703 | /* No IEEE PFC settings available */ | ||
704 | if (!my_pfc) | ||
705 | return -EINVAL; | ||
706 | |||
707 | pfc->pfc_cap = MAX_TRAFFIC_CLASS; | ||
708 | pfc->pfc_en = my_pfc->pfc_en; | ||
709 | pfc->mbc = my_pfc->mbc; | ||
710 | pfc->delay = my_pfc->delay; | ||
711 | |||
712 | for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { | ||
713 | pfc->requests[i] = adapter->stats.pxoffrxc[i]; | ||
714 | pfc->indications[i] = adapter->stats.pxofftxc[i]; | ||
715 | } | ||
716 | |||
717 | return 0; | ||
718 | } | ||
719 | |||
720 | static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev, | ||
721 | struct ieee_pfc *pfc) | ||
722 | { | ||
723 | struct ixgbe_adapter *adapter = netdev_priv(dev); | ||
724 | int err; | ||
725 | |||
726 | if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) | ||
727 | return -EINVAL; | ||
728 | |||
729 | if (!adapter->ixgbe_ieee_pfc) { | ||
730 | adapter->ixgbe_ieee_pfc = kmalloc(sizeof(struct ieee_pfc), | ||
731 | GFP_KERNEL); | ||
732 | if (!adapter->ixgbe_ieee_pfc) | ||
733 | return -ENOMEM; | ||
734 | } | ||
735 | |||
736 | memcpy(adapter->ixgbe_ieee_pfc, pfc, sizeof(*adapter->ixgbe_ieee_pfc)); | ||
737 | err = ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc->pfc_en); | ||
738 | return err; | ||
739 | } | ||
740 | |||
741 | static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev, | ||
742 | struct dcb_app *app) | ||
743 | { | ||
744 | struct ixgbe_adapter *adapter = netdev_priv(dev); | ||
745 | |||
746 | if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) | ||
747 | return -EINVAL; | ||
748 | #ifdef IXGBE_FCOE | ||
749 | if (app->selector == 1 && app->protocol == ETH_P_FCOE) { | ||
750 | if (adapter->fcoe.tc == app->priority) | ||
751 | goto setapp; | ||
752 | |||
753 | /* In IEEE mode map up to tc 1:1 */ | ||
754 | adapter->fcoe.tc = app->priority; | ||
755 | adapter->fcoe.up = app->priority; | ||
756 | |||
757 | /* Force hardware reset required to push FCoE | ||
758 | * setup on {tx|rx}_rings | ||
759 | */ | ||
760 | adapter->dcb_set_bitmap |= BIT_APP_UPCHG; | ||
761 | ixgbe_dcbnl_set_all(dev); | ||
762 | } | ||
763 | |||
764 | setapp: | ||
765 | #endif | ||
766 | dcb_setapp(dev, app); | ||
767 | return 0; | ||
768 | } | ||
769 | |||
770 | static u8 ixgbe_dcbnl_getdcbx(struct net_device *dev) | ||
771 | { | ||
772 | struct ixgbe_adapter *adapter = netdev_priv(dev); | ||
773 | return adapter->dcbx_cap; | ||
774 | } | ||
775 | |||
776 | static u8 ixgbe_dcbnl_setdcbx(struct net_device *dev, u8 mode) | ||
777 | { | ||
778 | struct ixgbe_adapter *adapter = netdev_priv(dev); | ||
779 | struct ieee_ets ets = {0}; | ||
780 | struct ieee_pfc pfc = {0}; | ||
781 | |||
782 | /* no support for LLD_MANAGED modes or CEE+IEEE */ | ||
783 | if ((mode & DCB_CAP_DCBX_LLD_MANAGED) || | ||
784 | ((mode & DCB_CAP_DCBX_VER_IEEE) && (mode & DCB_CAP_DCBX_VER_CEE)) || | ||
785 | !(mode & DCB_CAP_DCBX_HOST)) | ||
786 | return 1; | ||
787 | |||
788 | if (mode == adapter->dcbx_cap) | ||
789 | return 0; | ||
790 | |||
791 | adapter->dcbx_cap = mode; | ||
792 | |||
793 | /* ETS and PFC defaults */ | ||
794 | ets.ets_cap = 8; | ||
795 | pfc.pfc_cap = 8; | ||
796 | |||
797 | if (mode & DCB_CAP_DCBX_VER_IEEE) { | ||
798 | ixgbe_dcbnl_ieee_setets(dev, &ets); | ||
799 | ixgbe_dcbnl_ieee_setpfc(dev, &pfc); | ||
800 | } else if (mode & DCB_CAP_DCBX_VER_CEE) { | ||
801 | adapter->dcb_set_bitmap |= (BIT_PFC & BIT_PG_TX & BIT_PG_RX); | ||
802 | ixgbe_dcbnl_set_all(dev); | ||
803 | } else { | ||
804 | /* Drop into single TC mode strict priority as this | ||
805 | * indicates CEE and IEEE versions are disabled | ||
806 | */ | ||
807 | ixgbe_dcbnl_ieee_setets(dev, &ets); | ||
808 | ixgbe_dcbnl_ieee_setpfc(dev, &pfc); | ||
809 | ixgbe_dcbnl_set_state(dev, 0); | ||
810 | } | ||
811 | |||
812 | return 0; | ||
813 | } | ||
814 | |||
594 | const struct dcbnl_rtnl_ops dcbnl_ops = { | 815 | const struct dcbnl_rtnl_ops dcbnl_ops = { |
816 | .ieee_getets = ixgbe_dcbnl_ieee_getets, | ||
817 | .ieee_setets = ixgbe_dcbnl_ieee_setets, | ||
818 | .ieee_getpfc = ixgbe_dcbnl_ieee_getpfc, | ||
819 | .ieee_setpfc = ixgbe_dcbnl_ieee_setpfc, | ||
820 | .ieee_setapp = ixgbe_dcbnl_ieee_setapp, | ||
595 | .getstate = ixgbe_dcbnl_get_state, | 821 | .getstate = ixgbe_dcbnl_get_state, |
596 | .setstate = ixgbe_dcbnl_set_state, | 822 | .setstate = ixgbe_dcbnl_set_state, |
597 | .getpermhwaddr = ixgbe_dcbnl_get_perm_hw_addr, | 823 | .getpermhwaddr = ixgbe_dcbnl_get_perm_hw_addr, |
@@ -613,5 +839,6 @@ const struct dcbnl_rtnl_ops dcbnl_ops = { | |||
613 | .setpfcstate = ixgbe_dcbnl_setpfcstate, | 839 | .setpfcstate = ixgbe_dcbnl_setpfcstate, |
614 | .getapp = ixgbe_dcbnl_getapp, | 840 | .getapp = ixgbe_dcbnl_getapp, |
615 | .setapp = ixgbe_dcbnl_setapp, | 841 | .setapp = ixgbe_dcbnl_setapp, |
842 | .getdcbx = ixgbe_dcbnl_getdcbx, | ||
843 | .setdcbx = ixgbe_dcbnl_setdcbx, | ||
616 | }; | 844 | }; |
617 | |||