linux/drivers/net/ixgbe/ixgbe_dcb_nl.c
<<
>>
Prefs
   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        if (state > 0) {
 118                /* Turn on DCB */
 119                if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
 120                        goto out;
 121
 122                if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
 123                        e_err(drv, "Enable failed, needs MSI-X\n");
 124                        err = 1;
 125                        goto out;
 126                }
 127
 128                if (netif_running(netdev))
 129                        netdev->netdev_ops->ndo_stop(netdev);
 130                ixgbe_clear_interrupt_scheme(adapter);
 131
 132                switch (adapter->hw.mac.type) {
 133                case ixgbe_mac_82598EB:
 134                        adapter->last_lfc_mode = adapter->hw.fc.current_mode;
 135                        adapter->hw.fc.requested_mode = ixgbe_fc_none;
 136                        break;
 137                case ixgbe_mac_82599EB:
 138                case ixgbe_mac_X540:
 139                        adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
 140                        adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
 141                        break;
 142                default:
 143                        break;
 144                }
 145
 146                adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
 147                if (!netdev_get_num_tc(netdev))
 148                        ixgbe_setup_tc(netdev, MAX_TRAFFIC_CLASS);
 149
 150                ixgbe_init_interrupt_scheme(adapter);
 151                if (netif_running(netdev))
 152                        netdev->netdev_ops->ndo_open(netdev);
 153        } else {
 154                /* Turn off DCB */
 155                if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
 156                        if (netif_running(netdev))
 157                                netdev->netdev_ops->ndo_stop(netdev);
 158                        ixgbe_clear_interrupt_scheme(adapter);
 159
 160                        adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
 161                        adapter->temp_dcb_cfg.pfc_mode_enable = false;
 162                        adapter->dcb_cfg.pfc_mode_enable = false;
 163                        adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
 164                        switch (adapter->hw.mac.type) {
 165                        case ixgbe_mac_82599EB:
 166                        case ixgbe_mac_X540:
 167                                adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
 168                                break;
 169                        default:
 170                                break;
 171                        }
 172
 173                        ixgbe_setup_tc(netdev, 0);
 174
 175                        ixgbe_init_interrupt_scheme(adapter);
 176                        if (netif_running(netdev))
 177                                netdev->netdev_ops->ndo_open(netdev);
 178                }
 179        }
 180out:
 181        return err;
 182}
 183
 184static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev,
 185                                         u8 *perm_addr)
 186{
 187        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 188        int i, j;
 189
 190        memset(perm_addr, 0xff, MAX_ADDR_LEN);
 191
 192        for (i = 0; i < netdev->addr_len; i++)
 193                perm_addr[i] = adapter->hw.mac.perm_addr[i];
 194
 195        switch (adapter->hw.mac.type) {
 196        case ixgbe_mac_82599EB:
 197        case ixgbe_mac_X540:
 198                for (j = 0; j < netdev->addr_len; j++, i++)
 199                        perm_addr[i] = adapter->hw.mac.san_addr[j];
 200                break;
 201        default:
 202                break;
 203        }
 204}
 205
 206static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,
 207                                         u8 prio, u8 bwg_id, u8 bw_pct,
 208                                         u8 up_map)
 209{
 210        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 211
 212        if (prio != DCB_ATTR_VALUE_UNDEFINED)
 213                adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type = prio;
 214        if (bwg_id != DCB_ATTR_VALUE_UNDEFINED)
 215                adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_id = bwg_id;
 216        if (bw_pct != DCB_ATTR_VALUE_UNDEFINED)
 217                adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent =
 218                        bw_pct;
 219        if (up_map != DCB_ATTR_VALUE_UNDEFINED)
 220                adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap =
 221                        up_map;
 222
 223        if ((adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type !=
 224             adapter->dcb_cfg.tc_config[tc].path[0].prio_type) ||
 225            (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_id !=
 226             adapter->dcb_cfg.tc_config[tc].path[0].bwg_id) ||
 227            (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent !=
 228             adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent) ||
 229            (adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap !=
 230             adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap))
 231                adapter->dcb_set_bitmap |= BIT_PG_TX;
 232}
 233
 234static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
 235                                          u8 bw_pct)
 236{
 237        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 238
 239        adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct;
 240
 241        if (adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] !=
 242            adapter->dcb_cfg.bw_percentage[0][bwg_id])
 243                adapter->dcb_set_bitmap |= BIT_PG_TX;
 244}
 245
 246static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc,
 247                                         u8 prio, u8 bwg_id, u8 bw_pct,
 248                                         u8 up_map)
 249{
 250        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 251
 252        if (prio != DCB_ATTR_VALUE_UNDEFINED)
 253                adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type = prio;
 254        if (bwg_id != DCB_ATTR_VALUE_UNDEFINED)
 255                adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_id = bwg_id;
 256        if (bw_pct != DCB_ATTR_VALUE_UNDEFINED)
 257                adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent =
 258                        bw_pct;
 259        if (up_map != DCB_ATTR_VALUE_UNDEFINED)
 260                adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap =
 261                        up_map;
 262
 263        if ((adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type !=
 264             adapter->dcb_cfg.tc_config[tc].path[1].prio_type) ||
 265            (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_id !=
 266             adapter->dcb_cfg.tc_config[tc].path[1].bwg_id) ||
 267            (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent !=
 268             adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent) ||
 269            (adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap !=
 270             adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap))
 271                adapter->dcb_set_bitmap |= BIT_PG_RX;
 272}
 273
 274static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
 275                                          u8 bw_pct)
 276{
 277        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 278
 279        adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct;
 280
 281        if (adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] !=
 282            adapter->dcb_cfg.bw_percentage[1][bwg_id])
 283                adapter->dcb_set_bitmap |= BIT_PG_RX;
 284}
 285
 286static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc,
 287                                         u8 *prio, u8 *bwg_id, u8 *bw_pct,
 288                                         u8 *up_map)
 289{
 290        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 291
 292        *prio = adapter->dcb_cfg.tc_config[tc].path[0].prio_type;
 293        *bwg_id = adapter->dcb_cfg.tc_config[tc].path[0].bwg_id;
 294        *bw_pct = adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent;
 295        *up_map = adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap;
 296}
 297
 298static void ixgbe_dcbnl_get_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
 299                                          u8 *bw_pct)
 300{
 301        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 302
 303        *bw_pct = adapter->dcb_cfg.bw_percentage[0][bwg_id];
 304}
 305
 306static void ixgbe_dcbnl_get_pg_tc_cfg_rx(struct net_device *netdev, int tc,
 307                                         u8 *prio, u8 *bwg_id, u8 *bw_pct,
 308                                         u8 *up_map)
 309{
 310        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 311
 312        *prio = adapter->dcb_cfg.tc_config[tc].path[1].prio_type;
 313        *bwg_id = adapter->dcb_cfg.tc_config[tc].path[1].bwg_id;
 314        *bw_pct = adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent;
 315        *up_map = adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap;
 316}
 317
 318static void ixgbe_dcbnl_get_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
 319                                          u8 *bw_pct)
 320{
 321        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 322
 323        *bw_pct = adapter->dcb_cfg.bw_percentage[1][bwg_id];
 324}
 325
 326static void ixgbe_dcbnl_set_pfc_cfg(struct net_device *netdev, int priority,
 327                                    u8 setting)
 328{
 329        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 330
 331        adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc = setting;
 332        if (adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc !=
 333            adapter->dcb_cfg.tc_config[priority].dcb_pfc) {
 334                adapter->dcb_set_bitmap |= BIT_PFC;
 335                adapter->temp_dcb_cfg.pfc_mode_enable = true;
 336        }
 337}
 338
 339static void ixgbe_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority,
 340                                    u8 *setting)
 341{
 342        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 343
 344        *setting = adapter->dcb_cfg.tc_config[priority].dcb_pfc;
 345}
 346
 347static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
 348{
 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);
 355        int ret;
 356
 357        ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
 358                                 MAX_TRAFFIC_CLASS);
 359        if (ret)
 360                return DCB_NO_HW_CHG;
 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
 372        /*
 373         * Only take down the adapter if an app change occurred. FCoE
 374         * may shuffle tx rings in this case and this can not be done
 375         * without a reset currently.
 376         */
 377        if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) {
 378                while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
 379                        usleep_range(1000, 2000);
 380
 381                ixgbe_fcoe_setapp(adapter, up);
 382
 383                if (netif_running(netdev))
 384                        netdev->netdev_ops->ndo_stop(netdev);
 385                ixgbe_clear_interrupt_scheme(adapter);
 386        }
 387#endif
 388
 389        if (adapter->dcb_cfg.pfc_mode_enable) {
 390                switch (adapter->hw.mac.type) {
 391                case ixgbe_mac_82599EB:
 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                }
 400                adapter->hw.fc.requested_mode = ixgbe_fc_pfc;
 401        } else {
 402                switch (adapter->hw.mac.type) {
 403                case ixgbe_mac_82598EB:
 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                }
 413        }
 414
 415#ifdef IXGBE_FCOE
 416        if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) {
 417                ixgbe_init_interrupt_scheme(adapter);
 418                if (netif_running(netdev))
 419                        netdev->netdev_ops->ndo_open(netdev);
 420                ret = DCB_HW_CHG_RST;
 421        }
 422#endif
 423
 424        if (adapter->dcb_set_bitmap & BIT_PFC) {
 425                u8 pfc_en;
 426                ixgbe_dcb_unpack_pfc(&adapter->dcb_cfg, &pfc_en);
 427                ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc_en);
 428                ret = DCB_HW_CHG;
 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
 460        if (adapter->dcb_cfg.pfc_mode_enable)
 461                adapter->hw.fc.current_mode = ixgbe_fc_pfc;
 462
 463        if (adapter->dcb_set_bitmap & BIT_APP_UPCHG)
 464                clear_bit(__IXGBE_RESETTING, &adapter->state);
 465        adapter->dcb_set_bitmap = 0x00;
 466        return ret;
 467}
 468
 469static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap)
 470{
 471        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 472
 473        switch (capid) {
 474        case DCB_CAP_ATTR_PG:
 475                *cap = true;
 476                break;
 477        case DCB_CAP_ATTR_PFC:
 478                *cap = true;
 479                break;
 480        case DCB_CAP_ATTR_UP2TC:
 481                *cap = false;
 482                break;
 483        case DCB_CAP_ATTR_PG_TCS:
 484                *cap = 0x80;
 485                break;
 486        case DCB_CAP_ATTR_PFC_TCS:
 487                *cap = 0x80;
 488                break;
 489        case DCB_CAP_ATTR_GSP:
 490                *cap = true;
 491                break;
 492        case DCB_CAP_ATTR_BCN:
 493                *cap = false;
 494                break;
 495        case DCB_CAP_ATTR_DCBX:
 496                *cap = adapter->dcbx_cap;
 497                break;
 498        default:
 499                *cap = false;
 500                break;
 501        }
 502
 503        return 0;
 504}
 505
 506static u8 ixgbe_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num)
 507{
 508        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 509        u8 rval = 0;
 510
 511        if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
 512                switch (tcid) {
 513                case DCB_NUMTCS_ATTR_PG:
 514                        *num = MAX_TRAFFIC_CLASS;
 515                        break;
 516                case DCB_NUMTCS_ATTR_PFC:
 517                        *num = MAX_TRAFFIC_CLASS;
 518                        break;
 519                default:
 520                        rval = -EINVAL;
 521                        break;
 522                }
 523        } else {
 524                rval = -EINVAL;
 525        }
 526
 527        return rval;
 528}
 529
 530static u8 ixgbe_dcbnl_setnumtcs(struct net_device *netdev, int tcid, u8 num)
 531{
 532        return -EINVAL;
 533}
 534
 535static u8 ixgbe_dcbnl_getpfcstate(struct net_device *netdev)
 536{
 537        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 538
 539        return adapter->dcb_cfg.pfc_mode_enable;
 540}
 541
 542static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
 543{
 544        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 545
 546        adapter->temp_dcb_cfg.pfc_mode_enable = state;
 547        if (adapter->temp_dcb_cfg.pfc_mode_enable !=
 548                adapter->dcb_cfg.pfc_mode_enable)
 549                adapter->dcb_set_bitmap |= BIT_PFC;
 550}
 551
 552/**
 553 * ixgbe_dcbnl_getapp - retrieve the DCBX application user priority
 554 * @netdev : the corresponding netdev
 555 * @idtype : identifies the id as ether type or TCP/UDP port number
 556 * @id: id is either ether type or TCP/UDP port number
 557 *
 558 * Returns : on success, returns a non-zero 802.1p user priority bitmap
 559 * otherwise returns 0 as the invalid user priority bitmap to indicate an
 560 * error.
 561 */
 562static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)
 563{
 564        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 565        struct dcb_app app = {
 566                                .selector = idtype,
 567                                .protocol = id,
 568                             };
 569
 570        if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
 571                return 0;
 572
 573        return dcb_getapp(netdev, &app);
 574}
 575
 576static int ixgbe_dcbnl_ieee_getets(struct net_device *dev,
 577                                   struct ieee_ets *ets)
 578{
 579        struct ixgbe_adapter *adapter = netdev_priv(dev);
 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
 595static 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;
 615        }
 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;
 647}
 648
 649static int ixgbe_dcbnl_ieee_getpfc(struct net_device *dev,
 650                                   struct ieee_pfc *pfc)
 651{
 652        struct ixgbe_adapter *adapter = netdev_priv(dev);
 653        struct ieee_pfc *my_pfc = adapter->ixgbe_ieee_pfc;
 654        int i;
 655
 656        /* No IEEE PFC settings available */
 657        if (!my_pfc)
 658                return -EINVAL;
 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
 673static 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
 694static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev,
 695                                   struct dcb_app *app)
 696{
 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);
 703
 704#ifdef IXGBE_FCOE
 705        if (app->selector == 1 && app->protocol == ETH_P_FCOE &&
 706            adapter->fcoe.tc == app->priority)
 707                ixgbe_dcbnl_set_all(dev);
 708#endif
 709        return 0;
 710}
 711
 712static u8 ixgbe_dcbnl_getdcbx(struct net_device *dev)
 713{
 714        struct ixgbe_adapter *adapter = netdev_priv(dev);
 715        return adapter->dcbx_cap;
 716}
 717
 718static 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);
 752        }
 753
 754        return 0;
 755}
 756
 757const 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,
 763        .getstate       = ixgbe_dcbnl_get_state,
 764        .setstate       = ixgbe_dcbnl_set_state,
 765        .getpermhwaddr  = ixgbe_dcbnl_get_perm_hw_addr,
 766        .setpgtccfgtx   = ixgbe_dcbnl_set_pg_tc_cfg_tx,
 767        .setpgbwgcfgtx  = ixgbe_dcbnl_set_pg_bwg_cfg_tx,
 768        .setpgtccfgrx   = ixgbe_dcbnl_set_pg_tc_cfg_rx,
 769        .setpgbwgcfgrx  = ixgbe_dcbnl_set_pg_bwg_cfg_rx,
 770        .getpgtccfgtx   = ixgbe_dcbnl_get_pg_tc_cfg_tx,
 771        .getpgbwgcfgtx  = ixgbe_dcbnl_get_pg_bwg_cfg_tx,
 772        .getpgtccfgrx   = ixgbe_dcbnl_get_pg_tc_cfg_rx,
 773        .getpgbwgcfgrx  = ixgbe_dcbnl_get_pg_bwg_cfg_rx,
 774        .setpfccfg      = ixgbe_dcbnl_set_pfc_cfg,
 775        .getpfccfg      = ixgbe_dcbnl_get_pfc_cfg,
 776        .setall         = ixgbe_dcbnl_set_all,
 777        .getcap         = ixgbe_dcbnl_getcap,
 778        .getnumtcs      = ixgbe_dcbnl_getnumtcs,
 779        .setnumtcs      = ixgbe_dcbnl_setnumtcs,
 780        .getpfcstate    = ixgbe_dcbnl_getpfcstate,
 781        .setpfcstate    = ixgbe_dcbnl_setpfcstate,
 782        .getapp         = ixgbe_dcbnl_getapp,
 783        .getdcbx        = ixgbe_dcbnl_getdcbx,
 784        .setdcbx        = ixgbe_dcbnl_setdcbx,
 785};
 786