Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.1-rc8 816 lines 24 kB view raw
1/******************************************************************************* 2 3 Intel 10 Gigabit PCI Express Linux driver 4 Copyright(c) 1999 - 2011 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#include "ixgbe_dcb_82598.h" 32#include "ixgbe_dcb_82599.h" 33 34/* Callbacks for DCB netlink in the kernel */ 35#define BIT_DCB_MODE 0x01 36#define BIT_PFC 0x02 37#define BIT_PG_RX 0x04 38#define BIT_PG_TX 0x08 39#define BIT_APP_UPCHG 0x10 40#define BIT_LINKSPEED 0x80 41 42/* Responses for the DCB_C_SET_ALL command */ 43#define DCB_HW_CHG_RST 0 /* DCB configuration changed with reset */ 44#define DCB_NO_HW_CHG 1 /* DCB configuration did not change */ 45#define DCB_HW_CHG 2 /* DCB configuration changed, no reset */ 46 47int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg, 48 struct ixgbe_dcb_config *dst_dcb_cfg, int tc_max) 49{ 50 struct tc_configuration *src_tc_cfg = NULL; 51 struct tc_configuration *dst_tc_cfg = NULL; 52 int i; 53 54 if (!src_dcb_cfg || !dst_dcb_cfg) 55 return -EINVAL; 56 57 for (i = DCB_PG_ATTR_TC_0; i < tc_max + DCB_PG_ATTR_TC_0; i++) { 58 src_tc_cfg = &src_dcb_cfg->tc_config[i - DCB_PG_ATTR_TC_0]; 59 dst_tc_cfg = &dst_dcb_cfg->tc_config[i - DCB_PG_ATTR_TC_0]; 60 61 dst_tc_cfg->path[DCB_TX_CONFIG].prio_type = 62 src_tc_cfg->path[DCB_TX_CONFIG].prio_type; 63 64 dst_tc_cfg->path[DCB_TX_CONFIG].bwg_id = 65 src_tc_cfg->path[DCB_TX_CONFIG].bwg_id; 66 67 dst_tc_cfg->path[DCB_TX_CONFIG].bwg_percent = 68 src_tc_cfg->path[DCB_TX_CONFIG].bwg_percent; 69 70 dst_tc_cfg->path[DCB_TX_CONFIG].up_to_tc_bitmap = 71 src_tc_cfg->path[DCB_TX_CONFIG].up_to_tc_bitmap; 72 73 dst_tc_cfg->path[DCB_RX_CONFIG].prio_type = 74 src_tc_cfg->path[DCB_RX_CONFIG].prio_type; 75 76 dst_tc_cfg->path[DCB_RX_CONFIG].bwg_id = 77 src_tc_cfg->path[DCB_RX_CONFIG].bwg_id; 78 79 dst_tc_cfg->path[DCB_RX_CONFIG].bwg_percent = 80 src_tc_cfg->path[DCB_RX_CONFIG].bwg_percent; 81 82 dst_tc_cfg->path[DCB_RX_CONFIG].up_to_tc_bitmap = 83 src_tc_cfg->path[DCB_RX_CONFIG].up_to_tc_bitmap; 84 } 85 86 for (i = DCB_PG_ATTR_BW_ID_0; i < DCB_PG_ATTR_BW_ID_MAX; i++) { 87 dst_dcb_cfg->bw_percentage[DCB_TX_CONFIG] 88 [i-DCB_PG_ATTR_BW_ID_0] = src_dcb_cfg->bw_percentage 89 [DCB_TX_CONFIG][i-DCB_PG_ATTR_BW_ID_0]; 90 dst_dcb_cfg->bw_percentage[DCB_RX_CONFIG] 91 [i-DCB_PG_ATTR_BW_ID_0] = src_dcb_cfg->bw_percentage 92 [DCB_RX_CONFIG][i-DCB_PG_ATTR_BW_ID_0]; 93 } 94 95 for (i = DCB_PFC_UP_ATTR_0; i < DCB_PFC_UP_ATTR_MAX; i++) { 96 dst_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc = 97 src_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc; 98 } 99 100 dst_dcb_cfg->pfc_mode_enable = src_dcb_cfg->pfc_mode_enable; 101 102 return 0; 103} 104 105static u8 ixgbe_dcbnl_get_state(struct net_device *netdev) 106{ 107 struct ixgbe_adapter *adapter = netdev_priv(netdev); 108 109 return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED); 110} 111 112static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) 113{ 114 u8 err = 0; 115 struct ixgbe_adapter *adapter = netdev_priv(netdev); 116 117 /* verify there is something to do, if not then exit */ 118 if (!!state != !(adapter->flags & IXGBE_FLAG_DCB_ENABLED)) 119 return err; 120 121 if (state > 0) { 122 /* Turn on DCB */ 123 if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) { 124 e_err(drv, "Enable failed, needs MSI-X\n"); 125 err = 1; 126 goto out; 127 } 128 129 adapter->flags |= IXGBE_FLAG_DCB_ENABLED; 130 131 switch (adapter->hw.mac.type) { 132 case ixgbe_mac_82598EB: 133 adapter->last_lfc_mode = adapter->hw.fc.current_mode; 134 adapter->hw.fc.requested_mode = ixgbe_fc_none; 135 break; 136 case ixgbe_mac_82599EB: 137 case ixgbe_mac_X540: 138 adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; 139 break; 140 default: 141 break; 142 } 143 144 ixgbe_setup_tc(netdev, MAX_TRAFFIC_CLASS); 145 } else { 146 /* Turn off DCB */ 147 adapter->hw.fc.requested_mode = adapter->last_lfc_mode; 148 adapter->temp_dcb_cfg.pfc_mode_enable = false; 149 adapter->dcb_cfg.pfc_mode_enable = false; 150 adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; 151 switch (adapter->hw.mac.type) { 152 case ixgbe_mac_82599EB: 153 case ixgbe_mac_X540: 154 if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) 155 adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; 156 break; 157 default: 158 break; 159 } 160 ixgbe_setup_tc(netdev, 0); 161 } 162 163out: 164 return err; 165} 166 167static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev, 168 u8 *perm_addr) 169{ 170 struct ixgbe_adapter *adapter = netdev_priv(netdev); 171 int i, j; 172 173 memset(perm_addr, 0xff, MAX_ADDR_LEN); 174 175 for (i = 0; i < netdev->addr_len; i++) 176 perm_addr[i] = adapter->hw.mac.perm_addr[i]; 177 178 switch (adapter->hw.mac.type) { 179 case ixgbe_mac_82599EB: 180 case ixgbe_mac_X540: 181 for (j = 0; j < netdev->addr_len; j++, i++) 182 perm_addr[i] = adapter->hw.mac.san_addr[j]; 183 break; 184 default: 185 break; 186 } 187} 188 189static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc, 190 u8 prio, u8 bwg_id, u8 bw_pct, 191 u8 up_map) 192{ 193 struct ixgbe_adapter *adapter = netdev_priv(netdev); 194 195 if (prio != DCB_ATTR_VALUE_UNDEFINED) 196 adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type = prio; 197 if (bwg_id != DCB_ATTR_VALUE_UNDEFINED) 198 adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_id = bwg_id; 199 if (bw_pct != DCB_ATTR_VALUE_UNDEFINED) 200 adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent = 201 bw_pct; 202 if (up_map != DCB_ATTR_VALUE_UNDEFINED) 203 adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap = 204 up_map; 205 206 if ((adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type != 207 adapter->dcb_cfg.tc_config[tc].path[0].prio_type) || 208 (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_id != 209 adapter->dcb_cfg.tc_config[tc].path[0].bwg_id) || 210 (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent != 211 adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent) || 212 (adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap != 213 adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap)) 214 adapter->dcb_set_bitmap |= BIT_PG_TX; 215} 216 217static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id, 218 u8 bw_pct) 219{ 220 struct ixgbe_adapter *adapter = netdev_priv(netdev); 221 222 adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct; 223 224 if (adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] != 225 adapter->dcb_cfg.bw_percentage[0][bwg_id]) 226 adapter->dcb_set_bitmap |= BIT_PG_TX; 227} 228 229static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc, 230 u8 prio, u8 bwg_id, u8 bw_pct, 231 u8 up_map) 232{ 233 struct ixgbe_adapter *adapter = netdev_priv(netdev); 234 235 if (prio != DCB_ATTR_VALUE_UNDEFINED) 236 adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type = prio; 237 if (bwg_id != DCB_ATTR_VALUE_UNDEFINED) 238 adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_id = bwg_id; 239 if (bw_pct != DCB_ATTR_VALUE_UNDEFINED) 240 adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent = 241 bw_pct; 242 if (up_map != DCB_ATTR_VALUE_UNDEFINED) 243 adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap = 244 up_map; 245 246 if ((adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type != 247 adapter->dcb_cfg.tc_config[tc].path[1].prio_type) || 248 (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_id != 249 adapter->dcb_cfg.tc_config[tc].path[1].bwg_id) || 250 (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent != 251 adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent) || 252 (adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap != 253 adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap)) 254 adapter->dcb_set_bitmap |= BIT_PG_RX; 255} 256 257static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id, 258 u8 bw_pct) 259{ 260 struct ixgbe_adapter *adapter = netdev_priv(netdev); 261 262 adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct; 263 264 if (adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] != 265 adapter->dcb_cfg.bw_percentage[1][bwg_id]) 266 adapter->dcb_set_bitmap |= BIT_PG_RX; 267} 268 269static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc, 270 u8 *prio, u8 *bwg_id, u8 *bw_pct, 271 u8 *up_map) 272{ 273 struct ixgbe_adapter *adapter = netdev_priv(netdev); 274 275 *prio = adapter->dcb_cfg.tc_config[tc].path[0].prio_type; 276 *bwg_id = adapter->dcb_cfg.tc_config[tc].path[0].bwg_id; 277 *bw_pct = adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent; 278 *up_map = adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap; 279} 280 281static void ixgbe_dcbnl_get_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id, 282 u8 *bw_pct) 283{ 284 struct ixgbe_adapter *adapter = netdev_priv(netdev); 285 286 *bw_pct = adapter->dcb_cfg.bw_percentage[0][bwg_id]; 287} 288 289static void ixgbe_dcbnl_get_pg_tc_cfg_rx(struct net_device *netdev, int tc, 290 u8 *prio, u8 *bwg_id, u8 *bw_pct, 291 u8 *up_map) 292{ 293 struct ixgbe_adapter *adapter = netdev_priv(netdev); 294 295 *prio = adapter->dcb_cfg.tc_config[tc].path[1].prio_type; 296 *bwg_id = adapter->dcb_cfg.tc_config[tc].path[1].bwg_id; 297 *bw_pct = adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent; 298 *up_map = adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap; 299} 300 301static void ixgbe_dcbnl_get_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id, 302 u8 *bw_pct) 303{ 304 struct ixgbe_adapter *adapter = netdev_priv(netdev); 305 306 *bw_pct = adapter->dcb_cfg.bw_percentage[1][bwg_id]; 307} 308 309static void ixgbe_dcbnl_set_pfc_cfg(struct net_device *netdev, int priority, 310 u8 setting) 311{ 312 struct ixgbe_adapter *adapter = netdev_priv(netdev); 313 314 adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc = setting; 315 if (adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc != 316 adapter->dcb_cfg.tc_config[priority].dcb_pfc) { 317 adapter->dcb_set_bitmap |= BIT_PFC; 318 adapter->temp_dcb_cfg.pfc_mode_enable = true; 319 } 320} 321 322static void ixgbe_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority, 323 u8 *setting) 324{ 325 struct ixgbe_adapter *adapter = netdev_priv(netdev); 326 327 *setting = adapter->dcb_cfg.tc_config[priority].dcb_pfc; 328} 329 330static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) 331{ 332 struct ixgbe_adapter *adapter = netdev_priv(netdev); 333 int ret; 334#ifdef IXGBE_FCOE 335 struct dcb_app app = { 336 .selector = DCB_APP_IDTYPE_ETHTYPE, 337 .protocol = ETH_P_FCOE, 338 }; 339 u8 up = dcb_getapp(netdev, &app); 340#endif 341 342 ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg, 343 MAX_TRAFFIC_CLASS); 344 if (ret) 345 return DCB_NO_HW_CHG; 346 347#ifdef IXGBE_FCOE 348 if (up && (up != (1 << adapter->fcoe.up))) 349 adapter->dcb_set_bitmap |= BIT_APP_UPCHG; 350 351 /* 352 * Only take down the adapter if an app change occurred. FCoE 353 * may shuffle tx rings in this case and this can not be done 354 * without a reset currently. 355 */ 356 if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) { 357 while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) 358 usleep_range(1000, 2000); 359 360 adapter->fcoe.up = ffs(up) - 1; 361 362 if (netif_running(netdev)) 363 netdev->netdev_ops->ndo_stop(netdev); 364 ixgbe_clear_interrupt_scheme(adapter); 365 } 366#endif 367 368 if (adapter->dcb_cfg.pfc_mode_enable) { 369 switch (adapter->hw.mac.type) { 370 case ixgbe_mac_82599EB: 371 case ixgbe_mac_X540: 372 if (adapter->hw.fc.current_mode != ixgbe_fc_pfc) 373 adapter->last_lfc_mode = 374 adapter->hw.fc.current_mode; 375 break; 376 default: 377 break; 378 } 379 adapter->hw.fc.requested_mode = ixgbe_fc_pfc; 380 } else { 381 switch (adapter->hw.mac.type) { 382 case ixgbe_mac_82598EB: 383 adapter->hw.fc.requested_mode = ixgbe_fc_none; 384 break; 385 case ixgbe_mac_82599EB: 386 case ixgbe_mac_X540: 387 adapter->hw.fc.requested_mode = adapter->last_lfc_mode; 388 break; 389 default: 390 break; 391 } 392 } 393 394#ifdef IXGBE_FCOE 395 if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) { 396 ixgbe_init_interrupt_scheme(adapter); 397 if (netif_running(netdev)) 398 netdev->netdev_ops->ndo_open(netdev); 399 ret = DCB_HW_CHG_RST; 400 } 401#endif 402 403 if (adapter->dcb_set_bitmap & BIT_PFC) { 404 u8 pfc_en; 405 ixgbe_dcb_unpack_pfc(&adapter->dcb_cfg, &pfc_en); 406 ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc_en); 407 ret = DCB_HW_CHG; 408 } 409 410 if (adapter->dcb_set_bitmap & (BIT_PG_TX|BIT_PG_RX)) { 411 u16 refill[MAX_TRAFFIC_CLASS], max[MAX_TRAFFIC_CLASS]; 412 u8 bwg_id[MAX_TRAFFIC_CLASS], prio_type[MAX_TRAFFIC_CLASS]; 413 /* Priority to TC mapping in CEE case default to 1:1 */ 414 u8 prio_tc[MAX_TRAFFIC_CLASS] = {0, 1, 2, 3, 4, 5, 6, 7}; 415 int max_frame = adapter->netdev->mtu + ETH_HLEN + ETH_FCS_LEN; 416 417#ifdef CONFIG_FCOE 418 if (adapter->netdev->features & NETIF_F_FCOE_MTU) 419 max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE); 420#endif 421 422 ixgbe_dcb_calculate_tc_credits(&adapter->hw, &adapter->dcb_cfg, 423 max_frame, DCB_TX_CONFIG); 424 ixgbe_dcb_calculate_tc_credits(&adapter->hw, &adapter->dcb_cfg, 425 max_frame, DCB_RX_CONFIG); 426 427 ixgbe_dcb_unpack_refill(&adapter->dcb_cfg, 428 DCB_TX_CONFIG, refill); 429 ixgbe_dcb_unpack_max(&adapter->dcb_cfg, max); 430 ixgbe_dcb_unpack_bwgid(&adapter->dcb_cfg, 431 DCB_TX_CONFIG, bwg_id); 432 ixgbe_dcb_unpack_prio(&adapter->dcb_cfg, 433 DCB_TX_CONFIG, prio_type); 434 435 ixgbe_dcb_hw_ets_config(&adapter->hw, refill, max, 436 bwg_id, prio_type, prio_tc); 437 } 438 439 if (adapter->dcb_cfg.pfc_mode_enable) 440 adapter->hw.fc.current_mode = ixgbe_fc_pfc; 441 442 if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) 443 clear_bit(__IXGBE_RESETTING, &adapter->state); 444 adapter->dcb_set_bitmap = 0x00; 445 return ret; 446} 447 448static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap) 449{ 450 struct ixgbe_adapter *adapter = netdev_priv(netdev); 451 452 switch (capid) { 453 case DCB_CAP_ATTR_PG: 454 *cap = true; 455 break; 456 case DCB_CAP_ATTR_PFC: 457 *cap = true; 458 break; 459 case DCB_CAP_ATTR_UP2TC: 460 *cap = false; 461 break; 462 case DCB_CAP_ATTR_PG_TCS: 463 *cap = 0x80; 464 break; 465 case DCB_CAP_ATTR_PFC_TCS: 466 *cap = 0x80; 467 break; 468 case DCB_CAP_ATTR_GSP: 469 *cap = true; 470 break; 471 case DCB_CAP_ATTR_BCN: 472 *cap = false; 473 break; 474 case DCB_CAP_ATTR_DCBX: 475 *cap = adapter->dcbx_cap; 476 break; 477 default: 478 *cap = false; 479 break; 480 } 481 482 return 0; 483} 484 485static u8 ixgbe_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num) 486{ 487 struct ixgbe_adapter *adapter = netdev_priv(netdev); 488 u8 rval = 0; 489 490 if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { 491 switch (tcid) { 492 case DCB_NUMTCS_ATTR_PG: 493 *num = MAX_TRAFFIC_CLASS; 494 break; 495 case DCB_NUMTCS_ATTR_PFC: 496 *num = MAX_TRAFFIC_CLASS; 497 break; 498 default: 499 rval = -EINVAL; 500 break; 501 } 502 } else { 503 rval = -EINVAL; 504 } 505 506 return rval; 507} 508 509static u8 ixgbe_dcbnl_setnumtcs(struct net_device *netdev, int tcid, u8 num) 510{ 511 return -EINVAL; 512} 513 514static u8 ixgbe_dcbnl_getpfcstate(struct net_device *netdev) 515{ 516 struct ixgbe_adapter *adapter = netdev_priv(netdev); 517 518 return adapter->dcb_cfg.pfc_mode_enable; 519} 520 521static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state) 522{ 523 struct ixgbe_adapter *adapter = netdev_priv(netdev); 524 525 adapter->temp_dcb_cfg.pfc_mode_enable = state; 526 if (adapter->temp_dcb_cfg.pfc_mode_enable != 527 adapter->dcb_cfg.pfc_mode_enable) 528 adapter->dcb_set_bitmap |= BIT_PFC; 529} 530 531/** 532 * ixgbe_dcbnl_getapp - retrieve the DCBX application user priority 533 * @netdev : the corresponding netdev 534 * @idtype : identifies the id as ether type or TCP/UDP port number 535 * @id: id is either ether type or TCP/UDP port number 536 * 537 * Returns : on success, returns a non-zero 802.1p user priority bitmap 538 * otherwise returns 0 as the invalid user priority bitmap to indicate an 539 * error. 540 */ 541static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id) 542{ 543 struct ixgbe_adapter *adapter = netdev_priv(netdev); 544 struct dcb_app app = { 545 .selector = idtype, 546 .protocol = id, 547 }; 548 549 if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) 550 return 0; 551 552 return dcb_getapp(netdev, &app); 553} 554 555static int ixgbe_dcbnl_ieee_getets(struct net_device *dev, 556 struct ieee_ets *ets) 557{ 558 struct ixgbe_adapter *adapter = netdev_priv(dev); 559 struct ieee_ets *my_ets = adapter->ixgbe_ieee_ets; 560 561 /* No IEEE PFC settings available */ 562 if (!my_ets) 563 return -EINVAL; 564 565 ets->ets_cap = MAX_TRAFFIC_CLASS; 566 ets->cbs = my_ets->cbs; 567 memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw)); 568 memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw)); 569 memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa)); 570 memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc)); 571 return 0; 572} 573 574static int ixgbe_dcbnl_ieee_setets(struct net_device *dev, 575 struct ieee_ets *ets) 576{ 577 struct ixgbe_adapter *adapter = netdev_priv(dev); 578 __u16 refill[IEEE_8021QAZ_MAX_TCS], max[IEEE_8021QAZ_MAX_TCS]; 579 __u8 prio_type[IEEE_8021QAZ_MAX_TCS]; 580 int max_frame = dev->mtu + ETH_HLEN + ETH_FCS_LEN; 581 int i, err; 582 __u64 *p = (__u64 *) ets->prio_tc; 583 /* naively give each TC a bwg to map onto CEE hardware */ 584 __u8 bwg_id[IEEE_8021QAZ_MAX_TCS] = {0, 1, 2, 3, 4, 5, 6, 7}; 585 586 if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) 587 return -EINVAL; 588 589 if (!adapter->ixgbe_ieee_ets) { 590 adapter->ixgbe_ieee_ets = kmalloc(sizeof(struct ieee_ets), 591 GFP_KERNEL); 592 if (!adapter->ixgbe_ieee_ets) 593 return -ENOMEM; 594 } 595 596 memcpy(adapter->ixgbe_ieee_ets, ets, sizeof(*adapter->ixgbe_ieee_ets)); 597 598 /* Map TSA onto CEE prio type */ 599 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { 600 switch (ets->tc_tsa[i]) { 601 case IEEE_8021QAZ_TSA_STRICT: 602 prio_type[i] = 2; 603 break; 604 case IEEE_8021QAZ_TSA_ETS: 605 prio_type[i] = 0; 606 break; 607 default: 608 /* Hardware only supports priority strict or 609 * ETS transmission selection algorithms if 610 * we receive some other value from dcbnl 611 * throw an error 612 */ 613 return -EINVAL; 614 } 615 } 616 617 if (*p) 618 ixgbe_dcbnl_set_state(dev, 1); 619 else 620 ixgbe_dcbnl_set_state(dev, 0); 621 622 ixgbe_ieee_credits(ets->tc_tx_bw, refill, max, max_frame); 623 err = ixgbe_dcb_hw_ets_config(&adapter->hw, refill, max, 624 bwg_id, prio_type, ets->prio_tc); 625 return err; 626} 627 628static int ixgbe_dcbnl_ieee_getpfc(struct net_device *dev, 629 struct ieee_pfc *pfc) 630{ 631 struct ixgbe_adapter *adapter = netdev_priv(dev); 632 struct ieee_pfc *my_pfc = adapter->ixgbe_ieee_pfc; 633 int i; 634 635 /* No IEEE PFC settings available */ 636 if (!my_pfc) 637 return -EINVAL; 638 639 pfc->pfc_cap = MAX_TRAFFIC_CLASS; 640 pfc->pfc_en = my_pfc->pfc_en; 641 pfc->mbc = my_pfc->mbc; 642 pfc->delay = my_pfc->delay; 643 644 for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { 645 pfc->requests[i] = adapter->stats.pxoffrxc[i]; 646 pfc->indications[i] = adapter->stats.pxofftxc[i]; 647 } 648 649 return 0; 650} 651 652static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev, 653 struct ieee_pfc *pfc) 654{ 655 struct ixgbe_adapter *adapter = netdev_priv(dev); 656 int err; 657 658 if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) 659 return -EINVAL; 660 661 if (!adapter->ixgbe_ieee_pfc) { 662 adapter->ixgbe_ieee_pfc = kmalloc(sizeof(struct ieee_pfc), 663 GFP_KERNEL); 664 if (!adapter->ixgbe_ieee_pfc) 665 return -ENOMEM; 666 } 667 668 memcpy(adapter->ixgbe_ieee_pfc, pfc, sizeof(*adapter->ixgbe_ieee_pfc)); 669 err = ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc->pfc_en); 670 return err; 671} 672 673#ifdef IXGBE_FCOE 674static void ixgbe_dcbnl_devreset(struct net_device *dev) 675{ 676 struct ixgbe_adapter *adapter = netdev_priv(dev); 677 678 if (netif_running(dev)) 679 dev->netdev_ops->ndo_stop(dev); 680 681 ixgbe_clear_interrupt_scheme(adapter); 682 ixgbe_init_interrupt_scheme(adapter); 683 684 if (netif_running(dev)) 685 dev->netdev_ops->ndo_open(dev); 686} 687#endif 688 689static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev, 690 struct dcb_app *app) 691{ 692 struct ixgbe_adapter *adapter = netdev_priv(dev); 693 int err = -EINVAL; 694 695 if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) 696 return err; 697 698 err = dcb_ieee_setapp(dev, app); 699 700#ifdef IXGBE_FCOE 701 if (!err && app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE && 702 app->protocol == ETH_P_FCOE) { 703 u8 app_mask = dcb_ieee_getapp_mask(dev, app); 704 705 if (app_mask & (1 << adapter->fcoe.up)) 706 return err; 707 708 adapter->fcoe.up = app->priority; 709 ixgbe_dcbnl_devreset(dev); 710 } 711#endif 712 return 0; 713} 714 715static int ixgbe_dcbnl_ieee_delapp(struct net_device *dev, 716 struct dcb_app *app) 717{ 718 struct ixgbe_adapter *adapter = netdev_priv(dev); 719 int err; 720 721 if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) 722 return -EINVAL; 723 724 err = dcb_ieee_delapp(dev, app); 725 726#ifdef IXGBE_FCOE 727 if (!err && app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE && 728 app->protocol == ETH_P_FCOE) { 729 u8 app_mask = dcb_ieee_getapp_mask(dev, app); 730 731 if (app_mask & (1 << adapter->fcoe.up)) 732 return err; 733 734 adapter->fcoe.up = app_mask ? 735 ffs(app_mask) - 1 : IXGBE_FCOE_DEFTC; 736 ixgbe_dcbnl_devreset(dev); 737 } 738#endif 739 return err; 740} 741 742static u8 ixgbe_dcbnl_getdcbx(struct net_device *dev) 743{ 744 struct ixgbe_adapter *adapter = netdev_priv(dev); 745 return adapter->dcbx_cap; 746} 747 748static u8 ixgbe_dcbnl_setdcbx(struct net_device *dev, u8 mode) 749{ 750 struct ixgbe_adapter *adapter = netdev_priv(dev); 751 struct ieee_ets ets = {0}; 752 struct ieee_pfc pfc = {0}; 753 754 /* no support for LLD_MANAGED modes or CEE+IEEE */ 755 if ((mode & DCB_CAP_DCBX_LLD_MANAGED) || 756 ((mode & DCB_CAP_DCBX_VER_IEEE) && (mode & DCB_CAP_DCBX_VER_CEE)) || 757 !(mode & DCB_CAP_DCBX_HOST)) 758 return 1; 759 760 if (mode == adapter->dcbx_cap) 761 return 0; 762 763 adapter->dcbx_cap = mode; 764 765 /* ETS and PFC defaults */ 766 ets.ets_cap = 8; 767 pfc.pfc_cap = 8; 768 769 if (mode & DCB_CAP_DCBX_VER_IEEE) { 770 ixgbe_dcbnl_ieee_setets(dev, &ets); 771 ixgbe_dcbnl_ieee_setpfc(dev, &pfc); 772 } else if (mode & DCB_CAP_DCBX_VER_CEE) { 773 adapter->dcb_set_bitmap |= (BIT_PFC & BIT_PG_TX & BIT_PG_RX); 774 ixgbe_dcbnl_set_all(dev); 775 } else { 776 /* Drop into single TC mode strict priority as this 777 * indicates CEE and IEEE versions are disabled 778 */ 779 ixgbe_dcbnl_ieee_setets(dev, &ets); 780 ixgbe_dcbnl_ieee_setpfc(dev, &pfc); 781 ixgbe_dcbnl_set_state(dev, 0); 782 } 783 784 return 0; 785} 786 787const struct dcbnl_rtnl_ops dcbnl_ops = { 788 .ieee_getets = ixgbe_dcbnl_ieee_getets, 789 .ieee_setets = ixgbe_dcbnl_ieee_setets, 790 .ieee_getpfc = ixgbe_dcbnl_ieee_getpfc, 791 .ieee_setpfc = ixgbe_dcbnl_ieee_setpfc, 792 .ieee_setapp = ixgbe_dcbnl_ieee_setapp, 793 .ieee_delapp = ixgbe_dcbnl_ieee_delapp, 794 .getstate = ixgbe_dcbnl_get_state, 795 .setstate = ixgbe_dcbnl_set_state, 796 .getpermhwaddr = ixgbe_dcbnl_get_perm_hw_addr, 797 .setpgtccfgtx = ixgbe_dcbnl_set_pg_tc_cfg_tx, 798 .setpgbwgcfgtx = ixgbe_dcbnl_set_pg_bwg_cfg_tx, 799 .setpgtccfgrx = ixgbe_dcbnl_set_pg_tc_cfg_rx, 800 .setpgbwgcfgrx = ixgbe_dcbnl_set_pg_bwg_cfg_rx, 801 .getpgtccfgtx = ixgbe_dcbnl_get_pg_tc_cfg_tx, 802 .getpgbwgcfgtx = ixgbe_dcbnl_get_pg_bwg_cfg_tx, 803 .getpgtccfgrx = ixgbe_dcbnl_get_pg_tc_cfg_rx, 804 .getpgbwgcfgrx = ixgbe_dcbnl_get_pg_bwg_cfg_rx, 805 .setpfccfg = ixgbe_dcbnl_set_pfc_cfg, 806 .getpfccfg = ixgbe_dcbnl_get_pfc_cfg, 807 .setall = ixgbe_dcbnl_set_all, 808 .getcap = ixgbe_dcbnl_getcap, 809 .getnumtcs = ixgbe_dcbnl_getnumtcs, 810 .setnumtcs = ixgbe_dcbnl_setnumtcs, 811 .getpfcstate = ixgbe_dcbnl_getpfcstate, 812 .setpfcstate = ixgbe_dcbnl_setpfcstate, 813 .getapp = ixgbe_dcbnl_getapp, 814 .getdcbx = ixgbe_dcbnl_getdcbx, 815 .setdcbx = ixgbe_dcbnl_setdcbx, 816};