linux/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 2013-2014 Chelsio Communications.  All rights reserved.
   3 *
   4 *  Written by Anish Bhatt (anish@chelsio.com)
   5 *             Casey Leedom (leedom@chelsio.com)
   6 *
   7 *  This program is free software; you can redistribute it and/or modify it
   8 *  under the terms and conditions of the GNU General Public License,
   9 *  version 2, as published by the Free Software Foundation.
  10 *
  11 *  This program is distributed in the hope it will be useful, but WITHOUT
  12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  14 *  more details.
  15 *
  16 *  The full GNU General Public License is included in this distribution in
  17 *  the file called "COPYING".
  18 *
  19 */
  20
  21#include "cxgb4.h"
  22
  23/* DCBx version control
  24 */
  25static const char * const dcb_ver_array[] = {
  26        "Unknown",
  27        "DCBx-CIN",
  28        "DCBx-CEE 1.01",
  29        "DCBx-IEEE",
  30        "", "", "",
  31        "Auto Negotiated"
  32};
  33
  34static inline bool cxgb4_dcb_state_synced(enum cxgb4_dcb_state state)
  35{
  36        if (state == CXGB4_DCB_STATE_FW_ALLSYNCED ||
  37            state == CXGB4_DCB_STATE_HOST)
  38                return true;
  39        else
  40                return false;
  41}
  42
  43/* Initialize a port's Data Center Bridging state.  Typically used after a
  44 * Link Down event.
  45 */
  46void cxgb4_dcb_state_init(struct net_device *dev)
  47{
  48        struct port_info *pi = netdev2pinfo(dev);
  49        struct port_dcb_info *dcb = &pi->dcb;
  50        int version_temp = dcb->dcb_version;
  51
  52        memset(dcb, 0, sizeof(struct port_dcb_info));
  53        dcb->state = CXGB4_DCB_STATE_START;
  54        if (version_temp)
  55                dcb->dcb_version = version_temp;
  56
  57        netdev_dbg(dev, "%s: Initializing DCB state for port[%d]\n",
  58                    __func__, pi->port_id);
  59}
  60
  61void cxgb4_dcb_version_init(struct net_device *dev)
  62{
  63        struct port_info *pi = netdev2pinfo(dev);
  64        struct port_dcb_info *dcb = &pi->dcb;
  65
  66        /* Any writes here are only done on kernels that exlicitly need
  67         * a specific version, say < 2.6.38 which only support CEE
  68         */
  69        dcb->dcb_version = FW_PORT_DCB_VER_AUTO;
  70}
  71
  72static void cxgb4_dcb_cleanup_apps(struct net_device *dev)
  73{
  74        struct port_info *pi = netdev2pinfo(dev);
  75        struct adapter *adap = pi->adapter;
  76        struct port_dcb_info *dcb = &pi->dcb;
  77        struct dcb_app app;
  78        int i, err;
  79
  80        /* zero priority implies remove */
  81        app.priority = 0;
  82
  83        for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
  84                /* Check if app list is exhausted */
  85                if (!dcb->app_priority[i].protocolid)
  86                        break;
  87
  88                app.protocol = dcb->app_priority[i].protocolid;
  89
  90                if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) {
  91                        app.priority = dcb->app_priority[i].user_prio_map;
  92                        app.selector = dcb->app_priority[i].sel_field + 1;
  93                        err = dcb_ieee_delapp(dev, &app);
  94                } else {
  95                        app.selector = !!(dcb->app_priority[i].sel_field);
  96                        err = dcb_setapp(dev, &app);
  97                }
  98
  99                if (err) {
 100                        dev_err(adap->pdev_dev,
 101                                "Failed DCB Clear %s Application Priority: sel=%d, prot=%d, , err=%d\n",
 102                                dcb_ver_array[dcb->dcb_version], app.selector,
 103                                app.protocol, -err);
 104                        break;
 105                }
 106        }
 107}
 108
 109/* Finite State machine for Data Center Bridging.
 110 */
 111void cxgb4_dcb_state_fsm(struct net_device *dev,
 112                         enum cxgb4_dcb_state_input transition_to)
 113{
 114        struct port_info *pi = netdev2pinfo(dev);
 115        struct port_dcb_info *dcb = &pi->dcb;
 116        struct adapter *adap = pi->adapter;
 117        enum cxgb4_dcb_state current_state = dcb->state;
 118
 119        netdev_dbg(dev, "%s: State change from %d to %d for %s\n",
 120                    __func__, dcb->state, transition_to, dev->name);
 121
 122        switch (current_state) {
 123        case CXGB4_DCB_STATE_START: {
 124                switch (transition_to) {
 125                case CXGB4_DCB_INPUT_FW_DISABLED: {
 126                        /* we're going to use Host DCB */
 127                        dcb->state = CXGB4_DCB_STATE_HOST;
 128                        dcb->supported = CXGB4_DCBX_HOST_SUPPORT;
 129                        break;
 130                }
 131
 132                case CXGB4_DCB_INPUT_FW_ENABLED: {
 133                        /* we're going to use Firmware DCB */
 134                        dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
 135                        dcb->supported = DCB_CAP_DCBX_LLD_MANAGED;
 136                        if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE)
 137                                dcb->supported |= DCB_CAP_DCBX_VER_IEEE;
 138                        else
 139                                dcb->supported |= DCB_CAP_DCBX_VER_CEE;
 140                        break;
 141                }
 142
 143                case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
 144                        /* expected transition */
 145                        break;
 146                }
 147
 148                case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
 149                        dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED;
 150                        break;
 151                }
 152
 153                default:
 154                        goto bad_state_input;
 155                }
 156                break;
 157        }
 158
 159        case CXGB4_DCB_STATE_FW_INCOMPLETE: {
 160                switch (transition_to) {
 161                case CXGB4_DCB_INPUT_FW_ENABLED: {
 162                        /* we're alreaady in firmware DCB mode */
 163                        break;
 164                }
 165
 166                case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
 167                        /* we're already incomplete */
 168                        break;
 169                }
 170
 171                case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
 172                        dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED;
 173                        dcb->enabled = 1;
 174                        linkwatch_fire_event(dev);
 175                        break;
 176                }
 177
 178                default:
 179                        goto bad_state_input;
 180                }
 181                break;
 182        }
 183
 184        case CXGB4_DCB_STATE_FW_ALLSYNCED: {
 185                switch (transition_to) {
 186                case CXGB4_DCB_INPUT_FW_ENABLED: {
 187                        /* we're alreaady in firmware DCB mode */
 188                        break;
 189                }
 190
 191                case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
 192                        /* We were successfully running with firmware DCB but
 193                         * now it's telling us that it's in an "incomplete
 194                         * state.  We need to reset back to a ground state
 195                         * of incomplete.
 196                         */
 197                        cxgb4_dcb_cleanup_apps(dev);
 198                        cxgb4_dcb_state_init(dev);
 199                        dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
 200                        dcb->supported = CXGB4_DCBX_FW_SUPPORT;
 201                        linkwatch_fire_event(dev);
 202                        break;
 203                }
 204
 205                case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
 206                        /* we're already all sync'ed
 207                         * this is only applicable for IEEE or
 208                         * when another VI already completed negotiaton
 209                         */
 210                        dcb->enabled = 1;
 211                        linkwatch_fire_event(dev);
 212                        break;
 213                }
 214
 215                default:
 216                        goto bad_state_input;
 217                }
 218                break;
 219        }
 220
 221        case CXGB4_DCB_STATE_HOST: {
 222                switch (transition_to) {
 223                case CXGB4_DCB_INPUT_FW_DISABLED: {
 224                        /* we're alreaady in Host DCB mode */
 225                        break;
 226                }
 227
 228                default:
 229                        goto bad_state_input;
 230                }
 231                break;
 232        }
 233
 234        default:
 235                goto bad_state_transition;
 236        }
 237        return;
 238
 239bad_state_input:
 240        dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: illegal input symbol %d\n",
 241                transition_to);
 242        return;
 243
 244bad_state_transition:
 245        dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: bad state transition, state = %d, input = %d\n",
 246                current_state, transition_to);
 247}
 248
 249/* Handle a DCB/DCBX update message from the firmware.
 250 */
 251void cxgb4_dcb_handle_fw_update(struct adapter *adap,
 252                                const struct fw_port_cmd *pcmd)
 253{
 254        const union fw_port_dcb *fwdcb = &pcmd->u.dcb;
 255        int port = FW_PORT_CMD_PORTID_G(be32_to_cpu(pcmd->op_to_portid));
 256        struct net_device *dev = adap->port[adap->chan_map[port]];
 257        struct port_info *pi = netdev_priv(dev);
 258        struct port_dcb_info *dcb = &pi->dcb;
 259        int dcb_type = pcmd->u.dcb.pgid.type;
 260        int dcb_running_version;
 261
 262        /* Handle Firmware DCB Control messages separately since they drive
 263         * our state machine.
 264         */
 265        if (dcb_type == FW_PORT_DCB_TYPE_CONTROL) {
 266                enum cxgb4_dcb_state_input input =
 267                        ((pcmd->u.dcb.control.all_syncd_pkd &
 268                          FW_PORT_CMD_ALL_SYNCD_F)
 269                         ? CXGB4_DCB_STATE_FW_ALLSYNCED
 270                         : CXGB4_DCB_STATE_FW_INCOMPLETE);
 271
 272                if (dcb->dcb_version != FW_PORT_DCB_VER_UNKNOWN) {
 273                        dcb_running_version = FW_PORT_CMD_DCB_VERSION_G(
 274                                be16_to_cpu(
 275                                pcmd->u.dcb.control.dcb_version_to_app_state));
 276                        if (dcb_running_version == FW_PORT_DCB_VER_CEE1D01 ||
 277                            dcb_running_version == FW_PORT_DCB_VER_IEEE) {
 278                                dcb->dcb_version = dcb_running_version;
 279                                dev_warn(adap->pdev_dev, "Interface %s is running %s\n",
 280                                         dev->name,
 281                                         dcb_ver_array[dcb->dcb_version]);
 282                        } else {
 283                                dev_warn(adap->pdev_dev,
 284                                         "Something screwed up, requested firmware for %s, but firmware returned %s instead\n",
 285                                         dcb_ver_array[dcb->dcb_version],
 286                                         dcb_ver_array[dcb_running_version]);
 287                                dcb->dcb_version = FW_PORT_DCB_VER_UNKNOWN;
 288                        }
 289                }
 290
 291                cxgb4_dcb_state_fsm(dev, input);
 292                return;
 293        }
 294
 295        /* It's weird, and almost certainly an error, to get Firmware DCB
 296         * messages when we either haven't been told whether we're going to be
 297         * doing Host or Firmware DCB; and even worse when we've been told
 298         * that we're doing Host DCB!
 299         */
 300        if (dcb->state == CXGB4_DCB_STATE_START ||
 301            dcb->state == CXGB4_DCB_STATE_HOST) {
 302                dev_err(adap->pdev_dev, "Receiving Firmware DCB messages in State %d\n",
 303                        dcb->state);
 304                return;
 305        }
 306
 307        /* Now handle the general Firmware DCB update messages ...
 308         */
 309        switch (dcb_type) {
 310        case FW_PORT_DCB_TYPE_PGID:
 311                dcb->pgid = be32_to_cpu(fwdcb->pgid.pgid);
 312                dcb->msgs |= CXGB4_DCB_FW_PGID;
 313                break;
 314
 315        case FW_PORT_DCB_TYPE_PGRATE:
 316                dcb->pg_num_tcs_supported = fwdcb->pgrate.num_tcs_supported;
 317                memcpy(dcb->pgrate, &fwdcb->pgrate.pgrate,
 318                       sizeof(dcb->pgrate));
 319                memcpy(dcb->tsa, &fwdcb->pgrate.tsa,
 320                       sizeof(dcb->tsa));
 321                dcb->msgs |= CXGB4_DCB_FW_PGRATE;
 322                if (dcb->msgs & CXGB4_DCB_FW_PGID)
 323                        IEEE_FAUX_SYNC(dev, dcb);
 324                break;
 325
 326        case FW_PORT_DCB_TYPE_PRIORATE:
 327                memcpy(dcb->priorate, &fwdcb->priorate.strict_priorate,
 328                       sizeof(dcb->priorate));
 329                dcb->msgs |= CXGB4_DCB_FW_PRIORATE;
 330                break;
 331
 332        case FW_PORT_DCB_TYPE_PFC:
 333                dcb->pfcen = fwdcb->pfc.pfcen;
 334                dcb->pfc_num_tcs_supported = fwdcb->pfc.max_pfc_tcs;
 335                dcb->msgs |= CXGB4_DCB_FW_PFC;
 336                IEEE_FAUX_SYNC(dev, dcb);
 337                break;
 338
 339        case FW_PORT_DCB_TYPE_APP_ID: {
 340                const struct fw_port_app_priority *fwap = &fwdcb->app_priority;
 341                int idx = fwap->idx;
 342                struct app_priority *ap = &dcb->app_priority[idx];
 343
 344                struct dcb_app app = {
 345                        .protocol = be16_to_cpu(fwap->protocolid),
 346                };
 347                int err;
 348
 349                /* Convert from firmware format to relevant format
 350                 * when using app selector
 351                 */
 352                if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) {
 353                        app.selector = (fwap->sel_field + 1);
 354                        app.priority = ffs(fwap->user_prio_map) - 1;
 355                        err = dcb_ieee_setapp(dev, &app);
 356                        IEEE_FAUX_SYNC(dev, dcb);
 357                } else {
 358                        /* Default is CEE */
 359                        app.selector = !!(fwap->sel_field);
 360                        app.priority = fwap->user_prio_map;
 361                        err = dcb_setapp(dev, &app);
 362                }
 363
 364                if (err)
 365                        dev_err(adap->pdev_dev,
 366                                "Failed DCB Set Application Priority: sel=%d, prot=%d, prio=%d, err=%d\n",
 367                                app.selector, app.protocol, app.priority, -err);
 368
 369                ap->user_prio_map = fwap->user_prio_map;
 370                ap->sel_field = fwap->sel_field;
 371                ap->protocolid = be16_to_cpu(fwap->protocolid);
 372                dcb->msgs |= CXGB4_DCB_FW_APP_ID;
 373                break;
 374        }
 375
 376        default:
 377                dev_err(adap->pdev_dev, "Unknown DCB update type received %x\n",
 378                        dcb_type);
 379                break;
 380        }
 381}
 382
 383/* Data Center Bridging netlink operations.
 384 */
 385
 386
 387/* Get current DCB enabled/disabled state.
 388 */
 389static u8 cxgb4_getstate(struct net_device *dev)
 390{
 391        struct port_info *pi = netdev2pinfo(dev);
 392
 393        return pi->dcb.enabled;
 394}
 395
 396/* Set DCB enabled/disabled.
 397 */
 398static u8 cxgb4_setstate(struct net_device *dev, u8 enabled)
 399{
 400        struct port_info *pi = netdev2pinfo(dev);
 401
 402        /* If DCBx is host-managed, dcb is enabled by outside lldp agents */
 403        if (pi->dcb.state == CXGB4_DCB_STATE_HOST) {
 404                pi->dcb.enabled = enabled;
 405                return 0;
 406        }
 407
 408        /* Firmware doesn't provide any mechanism to control the DCB state.
 409         */
 410        if (enabled != (pi->dcb.state == CXGB4_DCB_STATE_FW_ALLSYNCED))
 411                return 1;
 412
 413        return 0;
 414}
 415
 416static void cxgb4_getpgtccfg(struct net_device *dev, int tc,
 417                             u8 *prio_type, u8 *pgid, u8 *bw_per,
 418                             u8 *up_tc_map, int local)
 419{
 420        struct fw_port_cmd pcmd;
 421        struct port_info *pi = netdev2pinfo(dev);
 422        struct adapter *adap = pi->adapter;
 423        int err;
 424
 425        *prio_type = *pgid = *bw_per = *up_tc_map = 0;
 426
 427        if (local)
 428                INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
 429        else
 430                INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
 431
 432        pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
 433        err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
 434        if (err != FW_PORT_DCB_CFG_SUCCESS) {
 435                dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
 436                return;
 437        }
 438        *pgid = (be32_to_cpu(pcmd.u.dcb.pgid.pgid) >> (tc * 4)) & 0xf;
 439
 440        if (local)
 441                INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
 442        else
 443                INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
 444        pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
 445        err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
 446        if (err != FW_PORT_DCB_CFG_SUCCESS) {
 447                dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
 448                        -err);
 449                return;
 450        }
 451
 452        *bw_per = pcmd.u.dcb.pgrate.pgrate[*pgid];
 453        *up_tc_map = (1 << tc);
 454
 455        /* prio_type is link strict */
 456        if (*pgid != 0xF)
 457                *prio_type = 0x2;
 458}
 459
 460static void cxgb4_getpgtccfg_tx(struct net_device *dev, int tc,
 461                                u8 *prio_type, u8 *pgid, u8 *bw_per,
 462                                u8 *up_tc_map)
 463{
 464        /* tc 0 is written at MSB position */
 465        return cxgb4_getpgtccfg(dev, (7 - tc), prio_type, pgid, bw_per,
 466                                up_tc_map, 1);
 467}
 468
 469
 470static void cxgb4_getpgtccfg_rx(struct net_device *dev, int tc,
 471                                u8 *prio_type, u8 *pgid, u8 *bw_per,
 472                                u8 *up_tc_map)
 473{
 474        /* tc 0 is written at MSB position */
 475        return cxgb4_getpgtccfg(dev, (7 - tc), prio_type, pgid, bw_per,
 476                                up_tc_map, 0);
 477}
 478
 479static void cxgb4_setpgtccfg_tx(struct net_device *dev, int tc,
 480                                u8 prio_type, u8 pgid, u8 bw_per,
 481                                u8 up_tc_map)
 482{
 483        struct fw_port_cmd pcmd;
 484        struct port_info *pi = netdev2pinfo(dev);
 485        struct adapter *adap = pi->adapter;
 486        int fw_tc = 7 - tc;
 487        u32 _pgid;
 488        int err;
 489
 490        if (pgid == DCB_ATTR_VALUE_UNDEFINED)
 491                return;
 492        if (bw_per == DCB_ATTR_VALUE_UNDEFINED)
 493                return;
 494
 495        INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
 496        pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
 497
 498        err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
 499        if (err != FW_PORT_DCB_CFG_SUCCESS) {
 500                dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
 501                return;
 502        }
 503
 504        _pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
 505        _pgid &= ~(0xF << (fw_tc * 4));
 506        _pgid |= pgid << (fw_tc * 4);
 507        pcmd.u.dcb.pgid.pgid = cpu_to_be32(_pgid);
 508
 509        INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
 510
 511        err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
 512        if (err != FW_PORT_DCB_CFG_SUCCESS) {
 513                dev_err(adap->pdev_dev, "DCB write PGID failed with %d\n",
 514                        -err);
 515                return;
 516        }
 517
 518        memset(&pcmd, 0, sizeof(struct fw_port_cmd));
 519
 520        INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
 521        pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
 522
 523        err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
 524        if (err != FW_PORT_DCB_CFG_SUCCESS) {
 525                dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
 526                        -err);
 527                return;
 528        }
 529
 530        pcmd.u.dcb.pgrate.pgrate[pgid] = bw_per;
 531
 532        INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
 533        if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
 534                pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F);
 535
 536        err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
 537        if (err != FW_PORT_DCB_CFG_SUCCESS)
 538                dev_err(adap->pdev_dev, "DCB write PGRATE failed with %d\n",
 539                        -err);
 540}
 541
 542static void cxgb4_getpgbwgcfg(struct net_device *dev, int pgid, u8 *bw_per,
 543                              int local)
 544{
 545        struct fw_port_cmd pcmd;
 546        struct port_info *pi = netdev2pinfo(dev);
 547        struct adapter *adap = pi->adapter;
 548        int err;
 549
 550        if (local)
 551                INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
 552        else
 553                INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
 554
 555        pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
 556        err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
 557        if (err != FW_PORT_DCB_CFG_SUCCESS) {
 558                dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
 559                        -err);
 560                return;
 561        }
 562
 563        *bw_per = pcmd.u.dcb.pgrate.pgrate[pgid];
 564}
 565
 566static void cxgb4_getpgbwgcfg_tx(struct net_device *dev, int pgid, u8 *bw_per)
 567{
 568        return cxgb4_getpgbwgcfg(dev, pgid, bw_per, 1);
 569}
 570
 571static void cxgb4_getpgbwgcfg_rx(struct net_device *dev, int pgid, u8 *bw_per)
 572{
 573        return cxgb4_getpgbwgcfg(dev, pgid, bw_per, 0);
 574}
 575
 576static void cxgb4_setpgbwgcfg_tx(struct net_device *dev, int pgid,
 577                                 u8 bw_per)
 578{
 579        struct fw_port_cmd pcmd;
 580        struct port_info *pi = netdev2pinfo(dev);
 581        struct adapter *adap = pi->adapter;
 582        int err;
 583
 584        INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
 585        pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
 586
 587        err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
 588        if (err != FW_PORT_DCB_CFG_SUCCESS) {
 589                dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
 590                        -err);
 591                return;
 592        }
 593
 594        pcmd.u.dcb.pgrate.pgrate[pgid] = bw_per;
 595
 596        INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
 597        if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
 598                pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F);
 599
 600        err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
 601
 602        if (err != FW_PORT_DCB_CFG_SUCCESS)
 603                dev_err(adap->pdev_dev, "DCB write PGRATE failed with %d\n",
 604                        -err);
 605}
 606
 607/* Return whether the specified Traffic Class Priority has Priority Pause
 608 * Frames enabled.
 609 */
 610static void cxgb4_getpfccfg(struct net_device *dev, int priority, u8 *pfccfg)
 611{
 612        struct port_info *pi = netdev2pinfo(dev);
 613        struct port_dcb_info *dcb = &pi->dcb;
 614
 615        if (!cxgb4_dcb_state_synced(dcb->state) ||
 616            priority >= CXGB4_MAX_PRIORITY)
 617                *pfccfg = 0;
 618        else
 619                *pfccfg = (pi->dcb.pfcen >> (7 - priority)) & 1;
 620}
 621
 622/* Enable/disable Priority Pause Frames for the specified Traffic Class
 623 * Priority.
 624 */
 625static void cxgb4_setpfccfg(struct net_device *dev, int priority, u8 pfccfg)
 626{
 627        struct fw_port_cmd pcmd;
 628        struct port_info *pi = netdev2pinfo(dev);
 629        struct adapter *adap = pi->adapter;
 630        int err;
 631
 632        if (!cxgb4_dcb_state_synced(pi->dcb.state) ||
 633            priority >= CXGB4_MAX_PRIORITY)
 634                return;
 635
 636        INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
 637        if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
 638                pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F);
 639
 640        pcmd.u.dcb.pfc.type = FW_PORT_DCB_TYPE_PFC;
 641        pcmd.u.dcb.pfc.pfcen = pi->dcb.pfcen;
 642
 643        if (pfccfg)
 644                pcmd.u.dcb.pfc.pfcen |= (1 << (7 - priority));
 645        else
 646                pcmd.u.dcb.pfc.pfcen &= (~(1 << (7 - priority)));
 647
 648        err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
 649        if (err != FW_PORT_DCB_CFG_SUCCESS) {
 650                dev_err(adap->pdev_dev, "DCB PFC write failed with %d\n", -err);
 651                return;
 652        }
 653
 654        pi->dcb.pfcen = pcmd.u.dcb.pfc.pfcen;
 655}
 656
 657static u8 cxgb4_setall(struct net_device *dev)
 658{
 659        return 0;
 660}
 661
 662/* Return DCB capabilities.
 663 */
 664static u8 cxgb4_getcap(struct net_device *dev, int cap_id, u8 *caps)
 665{
 666        struct port_info *pi = netdev2pinfo(dev);
 667
 668        switch (cap_id) {
 669        case DCB_CAP_ATTR_PG:
 670        case DCB_CAP_ATTR_PFC:
 671                *caps = true;
 672                break;
 673
 674        case DCB_CAP_ATTR_PG_TCS:
 675                /* 8 priorities for PG represented by bitmap */
 676                *caps = 0x80;
 677                break;
 678
 679        case DCB_CAP_ATTR_PFC_TCS:
 680                /* 8 priorities for PFC represented by bitmap */
 681                *caps = 0x80;
 682                break;
 683
 684        case DCB_CAP_ATTR_GSP:
 685                *caps = true;
 686                break;
 687
 688        case DCB_CAP_ATTR_UP2TC:
 689        case DCB_CAP_ATTR_BCN:
 690                *caps = false;
 691                break;
 692
 693        case DCB_CAP_ATTR_DCBX:
 694                *caps = pi->dcb.supported;
 695                break;
 696
 697        default:
 698                *caps = false;
 699        }
 700
 701        return 0;
 702}
 703
 704/* Return the number of Traffic Classes for the indicated Traffic Class ID.
 705 */
 706static int cxgb4_getnumtcs(struct net_device *dev, int tcs_id, u8 *num)
 707{
 708        struct port_info *pi = netdev2pinfo(dev);
 709
 710        switch (tcs_id) {
 711        case DCB_NUMTCS_ATTR_PG:
 712                if (pi->dcb.msgs & CXGB4_DCB_FW_PGRATE)
 713                        *num = pi->dcb.pg_num_tcs_supported;
 714                else
 715                        *num = 0x8;
 716                break;
 717
 718        case DCB_NUMTCS_ATTR_PFC:
 719                *num = 0x8;
 720                break;
 721
 722        default:
 723                return -EINVAL;
 724        }
 725
 726        return 0;
 727}
 728
 729/* Set the number of Traffic Classes supported for the indicated Traffic Class
 730 * ID.
 731 */
 732static int cxgb4_setnumtcs(struct net_device *dev, int tcs_id, u8 num)
 733{
 734        /* Setting the number of Traffic Classes isn't supported.
 735         */
 736        return -ENOSYS;
 737}
 738
 739/* Return whether Priority Flow Control is enabled.  */
 740static u8 cxgb4_getpfcstate(struct net_device *dev)
 741{
 742        struct port_info *pi = netdev2pinfo(dev);
 743
 744        if (!cxgb4_dcb_state_synced(pi->dcb.state))
 745                return false;
 746
 747        return pi->dcb.pfcen != 0;
 748}
 749
 750/* Enable/disable Priority Flow Control. */
 751static void cxgb4_setpfcstate(struct net_device *dev, u8 state)
 752{
 753        /* We can't enable/disable Priority Flow Control but we also can't
 754         * return an error ...
 755         */
 756}
 757
 758/* Return the Application User Priority Map associated with the specified
 759 * Application ID.
 760 */
 761static int __cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id,
 762                          int peer)
 763{
 764        struct port_info *pi = netdev2pinfo(dev);
 765        struct adapter *adap = pi->adapter;
 766        int i;
 767
 768        if (!cxgb4_dcb_state_synced(pi->dcb.state))
 769                return 0;
 770
 771        for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
 772                struct fw_port_cmd pcmd;
 773                int err;
 774
 775                if (peer)
 776                        INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
 777                else
 778                        INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
 779
 780                pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
 781                pcmd.u.dcb.app_priority.idx = i;
 782
 783                err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
 784                if (err != FW_PORT_DCB_CFG_SUCCESS) {
 785                        dev_err(adap->pdev_dev, "DCB APP read failed with %d\n",
 786                                -err);
 787                        return err;
 788                }
 789                if (be16_to_cpu(pcmd.u.dcb.app_priority.protocolid) == app_id)
 790                        if (pcmd.u.dcb.app_priority.sel_field == app_idtype)
 791                                return pcmd.u.dcb.app_priority.user_prio_map;
 792
 793                /* exhausted app list */
 794                if (!pcmd.u.dcb.app_priority.protocolid)
 795                        break;
 796        }
 797
 798        return -EEXIST;
 799}
 800
 801/* Return the Application User Priority Map associated with the specified
 802 * Application ID.
 803 */
 804static int cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id)
 805{
 806        /* Convert app_idtype to firmware format before querying */
 807        return __cxgb4_getapp(dev, app_idtype == DCB_APP_IDTYPE_ETHTYPE ?
 808                              app_idtype : 3, app_id, 0);
 809}
 810
 811/* Write a new Application User Priority Map for the specified Application ID
 812 */
 813static int __cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
 814                          u8 app_prio)
 815{
 816        struct fw_port_cmd pcmd;
 817        struct port_info *pi = netdev2pinfo(dev);
 818        struct adapter *adap = pi->adapter;
 819        int i, err;
 820
 821
 822        if (!cxgb4_dcb_state_synced(pi->dcb.state))
 823                return -EINVAL;
 824
 825        /* DCB info gets thrown away on link up */
 826        if (!netif_carrier_ok(dev))
 827                return -ENOLINK;
 828
 829        for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
 830                INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
 831                pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
 832                pcmd.u.dcb.app_priority.idx = i;
 833                err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
 834
 835                if (err != FW_PORT_DCB_CFG_SUCCESS) {
 836                        dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
 837                                -err);
 838                        return err;
 839                }
 840                if (be16_to_cpu(pcmd.u.dcb.app_priority.protocolid) == app_id) {
 841                        /* overwrite existing app table */
 842                        pcmd.u.dcb.app_priority.protocolid = 0;
 843                        break;
 844                }
 845                /* find first empty slot */
 846                if (!pcmd.u.dcb.app_priority.protocolid)
 847                        break;
 848        }
 849
 850        if (i == CXGB4_MAX_DCBX_APP_SUPPORTED) {
 851                /* no empty slots available */
 852                dev_err(adap->pdev_dev, "DCB app table full\n");
 853                return -EBUSY;
 854        }
 855
 856        /* write out new app table entry */
 857        INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
 858        if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
 859                pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F);
 860
 861        pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
 862        pcmd.u.dcb.app_priority.protocolid = cpu_to_be16(app_id);
 863        pcmd.u.dcb.app_priority.sel_field = app_idtype;
 864        pcmd.u.dcb.app_priority.user_prio_map = app_prio;
 865        pcmd.u.dcb.app_priority.idx = i;
 866
 867        err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
 868        if (err != FW_PORT_DCB_CFG_SUCCESS) {
 869                dev_err(adap->pdev_dev, "DCB app table write failed with %d\n",
 870                        -err);
 871                return err;
 872        }
 873
 874        return 0;
 875}
 876
 877/* Priority for CEE inside dcb_app is bitmask, with 0 being an invalid value */
 878static int cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
 879                        u8 app_prio)
 880{
 881        int ret;
 882        struct dcb_app app = {
 883                .selector = app_idtype,
 884                .protocol = app_id,
 885                .priority = app_prio,
 886        };
 887
 888        if (app_idtype != DCB_APP_IDTYPE_ETHTYPE &&
 889            app_idtype != DCB_APP_IDTYPE_PORTNUM)
 890                return -EINVAL;
 891
 892        /* Convert app_idtype to a format that firmware understands */
 893        ret = __cxgb4_setapp(dev, app_idtype == DCB_APP_IDTYPE_ETHTYPE ?
 894                              app_idtype : 3, app_id, app_prio);
 895        if (ret)
 896                return ret;
 897
 898        return dcb_setapp(dev, &app);
 899}
 900
 901/* Return whether IEEE Data Center Bridging has been negotiated.
 902 */
 903static inline int
 904cxgb4_ieee_negotiation_complete(struct net_device *dev,
 905                                enum cxgb4_dcb_fw_msgs dcb_subtype)
 906{
 907        struct port_info *pi = netdev2pinfo(dev);
 908        struct port_dcb_info *dcb = &pi->dcb;
 909
 910        if (dcb->state == CXGB4_DCB_STATE_FW_ALLSYNCED)
 911                if (dcb_subtype && !(dcb->msgs & dcb_subtype))
 912                        return 0;
 913
 914        return (cxgb4_dcb_state_synced(dcb->state) &&
 915                (dcb->supported & DCB_CAP_DCBX_VER_IEEE));
 916}
 917
 918static int cxgb4_ieee_read_ets(struct net_device *dev, struct ieee_ets *ets,
 919                               int local)
 920{
 921        struct port_info *pi = netdev2pinfo(dev);
 922        struct port_dcb_info *dcb = &pi->dcb;
 923        struct adapter *adap = pi->adapter;
 924        uint32_t tc_info;
 925        struct fw_port_cmd pcmd;
 926        int i, bwg, err;
 927
 928        if (!(dcb->msgs & (CXGB4_DCB_FW_PGID | CXGB4_DCB_FW_PGRATE)))
 929                return 0;
 930
 931        ets->ets_cap =  dcb->pg_num_tcs_supported;
 932
 933        if (local) {
 934                ets->willing = 1;
 935                INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
 936        } else {
 937                INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
 938        }
 939
 940        pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
 941        err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
 942        if (err != FW_PORT_DCB_CFG_SUCCESS) {
 943                dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
 944                return err;
 945        }
 946
 947        tc_info = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
 948
 949        if (local)
 950                INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
 951        else
 952                INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
 953
 954        pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
 955        err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
 956        if (err != FW_PORT_DCB_CFG_SUCCESS) {
 957                dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
 958                        -err);
 959                return err;
 960        }
 961
 962        for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
 963                bwg = (tc_info >> ((7 - i) * 4)) & 0xF;
 964                ets->prio_tc[i] = bwg;
 965                ets->tc_tx_bw[i] = pcmd.u.dcb.pgrate.pgrate[i];
 966                ets->tc_rx_bw[i] = ets->tc_tx_bw[i];
 967                ets->tc_tsa[i] = pcmd.u.dcb.pgrate.tsa[i];
 968        }
 969
 970        return 0;
 971}
 972
 973static int cxgb4_ieee_get_ets(struct net_device *dev, struct ieee_ets *ets)
 974{
 975        return cxgb4_ieee_read_ets(dev, ets, 1);
 976}
 977
 978/* We reuse this for peer PFC as well, as we can't have it enabled one way */
 979static int cxgb4_ieee_get_pfc(struct net_device *dev, struct ieee_pfc *pfc)
 980{
 981        struct port_info *pi = netdev2pinfo(dev);
 982        struct port_dcb_info *dcb = &pi->dcb;
 983
 984        memset(pfc, 0, sizeof(struct ieee_pfc));
 985
 986        if (!(dcb->msgs & CXGB4_DCB_FW_PFC))
 987                return 0;
 988
 989        pfc->pfc_cap = dcb->pfc_num_tcs_supported;
 990        pfc->pfc_en = bitswap_1(dcb->pfcen);
 991
 992        return 0;
 993}
 994
 995static int cxgb4_ieee_peer_ets(struct net_device *dev, struct ieee_ets *ets)
 996{
 997        return cxgb4_ieee_read_ets(dev, ets, 0);
 998}
 999
1000/* Fill in the Application User Priority Map associated with the
1001 * specified Application.
1002 * Priority for IEEE dcb_app is an integer, with 0 being a valid value
1003 */
1004static int cxgb4_ieee_getapp(struct net_device *dev, struct dcb_app *app)
1005{
1006        int prio;
1007
1008        if (!cxgb4_ieee_negotiation_complete(dev, CXGB4_DCB_FW_APP_ID))
1009                return -EINVAL;
1010        if (!(app->selector && app->protocol))
1011                return -EINVAL;
1012
1013        /* Try querying firmware first, use firmware format */
1014        prio = __cxgb4_getapp(dev, app->selector - 1, app->protocol, 0);
1015
1016        if (prio < 0)
1017                prio = dcb_ieee_getapp_mask(dev, app);
1018
1019        app->priority = ffs(prio) - 1;
1020        return 0;
1021}
1022
1023/* Write a new Application User Priority Map for the specified Application ID.
1024 * Priority for IEEE dcb_app is an integer, with 0 being a valid value
1025 */
1026static int cxgb4_ieee_setapp(struct net_device *dev, struct dcb_app *app)
1027{
1028        int ret;
1029
1030        if (!cxgb4_ieee_negotiation_complete(dev, CXGB4_DCB_FW_APP_ID))
1031                return -EINVAL;
1032        if (!(app->selector && app->protocol))
1033                return -EINVAL;
1034
1035        if (!(app->selector > IEEE_8021QAZ_APP_SEL_ETHERTYPE  &&
1036              app->selector < IEEE_8021QAZ_APP_SEL_ANY))
1037                return -EINVAL;
1038
1039        /* change selector to a format that firmware understands */
1040        ret = __cxgb4_setapp(dev, app->selector - 1, app->protocol,
1041                             (1 << app->priority));
1042        if (ret)
1043                return ret;
1044
1045        return dcb_ieee_setapp(dev, app);
1046}
1047
1048/* Return our DCBX parameters.
1049 */
1050static u8 cxgb4_getdcbx(struct net_device *dev)
1051{
1052        struct port_info *pi = netdev2pinfo(dev);
1053
1054        /* This is already set by cxgb4_set_dcb_caps, so just return it */
1055        return pi->dcb.supported;
1056}
1057
1058/* Set our DCBX parameters.
1059 */
1060static u8 cxgb4_setdcbx(struct net_device *dev, u8 dcb_request)
1061{
1062        struct port_info *pi = netdev2pinfo(dev);
1063
1064        /* Filter out requests which exceed our capabilities.
1065         */
1066        if ((dcb_request & (CXGB4_DCBX_FW_SUPPORT | CXGB4_DCBX_HOST_SUPPORT))
1067            != dcb_request)
1068                return 1;
1069
1070        /* Can't enable DCB if we haven't successfully negotiated it.
1071         */
1072        if (!cxgb4_dcb_state_synced(pi->dcb.state))
1073                return 1;
1074
1075        /* There's currently no mechanism to allow for the firmware DCBX
1076         * negotiation to be changed from the Host Driver.  If the caller
1077         * requests exactly the same parameters that we already have then
1078         * we'll allow them to be successfully "set" ...
1079         */
1080        if (dcb_request != pi->dcb.supported)
1081                return 1;
1082
1083        pi->dcb.supported = dcb_request;
1084        return 0;
1085}
1086
1087static int cxgb4_getpeer_app(struct net_device *dev,
1088                             struct dcb_peer_app_info *info, u16 *app_count)
1089{
1090        struct fw_port_cmd pcmd;
1091        struct port_info *pi = netdev2pinfo(dev);
1092        struct adapter *adap = pi->adapter;
1093        int i, err = 0;
1094
1095        if (!cxgb4_dcb_state_synced(pi->dcb.state))
1096                return 1;
1097
1098        info->willing = 0;
1099        info->error = 0;
1100
1101        *app_count = 0;
1102        for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
1103                INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
1104                pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
1105                pcmd.u.dcb.app_priority.idx = *app_count;
1106                err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
1107
1108                if (err != FW_PORT_DCB_CFG_SUCCESS) {
1109                        dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
1110                                -err);
1111                        return err;
1112                }
1113
1114                /* find first empty slot */
1115                if (!pcmd.u.dcb.app_priority.protocolid)
1116                        break;
1117        }
1118        *app_count = i;
1119        return err;
1120}
1121
1122static int cxgb4_getpeerapp_tbl(struct net_device *dev, struct dcb_app *table)
1123{
1124        struct fw_port_cmd pcmd;
1125        struct port_info *pi = netdev2pinfo(dev);
1126        struct adapter *adap = pi->adapter;
1127        int i, err = 0;
1128
1129        if (!cxgb4_dcb_state_synced(pi->dcb.state))
1130                return 1;
1131
1132        for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
1133                INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
1134                pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
1135                pcmd.u.dcb.app_priority.idx = i;
1136                err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
1137
1138                if (err != FW_PORT_DCB_CFG_SUCCESS) {
1139                        dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
1140                                -err);
1141                        return err;
1142                }
1143
1144                /* find first empty slot */
1145                if (!pcmd.u.dcb.app_priority.protocolid)
1146                        break;
1147
1148                table[i].selector = (pcmd.u.dcb.app_priority.sel_field + 1);
1149                table[i].protocol =
1150                        be16_to_cpu(pcmd.u.dcb.app_priority.protocolid);
1151                table[i].priority =
1152                        ffs(pcmd.u.dcb.app_priority.user_prio_map) - 1;
1153        }
1154        return err;
1155}
1156
1157/* Return Priority Group information.
1158 */
1159static int cxgb4_cee_peer_getpg(struct net_device *dev, struct cee_pg *pg)
1160{
1161        struct fw_port_cmd pcmd;
1162        struct port_info *pi = netdev2pinfo(dev);
1163        struct adapter *adap = pi->adapter;
1164        u32 pgid;
1165        int i, err;
1166
1167        /* We're always "willing" -- the Switch Fabric always dictates the
1168         * DCBX parameters to us.
1169         */
1170        pg->willing = true;
1171
1172        INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
1173        pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
1174        err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
1175        if (err != FW_PORT_DCB_CFG_SUCCESS) {
1176                dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
1177                return err;
1178        }
1179        pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
1180
1181        for (i = 0; i < CXGB4_MAX_PRIORITY; i++)
1182                pg->prio_pg[7 - i] = (pgid >> (i * 4)) & 0xF;
1183
1184        INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
1185        pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
1186        err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
1187        if (err != FW_PORT_DCB_CFG_SUCCESS) {
1188                dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
1189                        -err);
1190                return err;
1191        }
1192
1193        for (i = 0; i < CXGB4_MAX_PRIORITY; i++)
1194                pg->pg_bw[i] = pcmd.u.dcb.pgrate.pgrate[i];
1195
1196        pg->tcs_supported = pcmd.u.dcb.pgrate.num_tcs_supported;
1197
1198        return 0;
1199}
1200
1201/* Return Priority Flow Control information.
1202 */
1203static int cxgb4_cee_peer_getpfc(struct net_device *dev, struct cee_pfc *pfc)
1204{
1205        struct port_info *pi = netdev2pinfo(dev);
1206
1207        cxgb4_getnumtcs(dev, DCB_NUMTCS_ATTR_PFC, &(pfc->tcs_supported));
1208
1209        /* Firmware sends this to us in a formwat that is a bit flipped version
1210         * of spec, correct it before we send it to host. This is taken care of
1211         * by bit shifting in other uses of pfcen
1212         */
1213        pfc->pfc_en = bitswap_1(pi->dcb.pfcen);
1214
1215        pfc->tcs_supported = pi->dcb.pfc_num_tcs_supported;
1216
1217        return 0;
1218}
1219
1220const struct dcbnl_rtnl_ops cxgb4_dcb_ops = {
1221        .ieee_getets            = cxgb4_ieee_get_ets,
1222        .ieee_getpfc            = cxgb4_ieee_get_pfc,
1223        .ieee_getapp            = cxgb4_ieee_getapp,
1224        .ieee_setapp            = cxgb4_ieee_setapp,
1225        .ieee_peer_getets       = cxgb4_ieee_peer_ets,
1226        .ieee_peer_getpfc       = cxgb4_ieee_get_pfc,
1227
1228        /* CEE std */
1229        .getstate               = cxgb4_getstate,
1230        .setstate               = cxgb4_setstate,
1231        .getpgtccfgtx           = cxgb4_getpgtccfg_tx,
1232        .getpgbwgcfgtx          = cxgb4_getpgbwgcfg_tx,
1233        .getpgtccfgrx           = cxgb4_getpgtccfg_rx,
1234        .getpgbwgcfgrx          = cxgb4_getpgbwgcfg_rx,
1235        .setpgtccfgtx           = cxgb4_setpgtccfg_tx,
1236        .setpgbwgcfgtx          = cxgb4_setpgbwgcfg_tx,
1237        .setpfccfg              = cxgb4_setpfccfg,
1238        .getpfccfg              = cxgb4_getpfccfg,
1239        .setall                 = cxgb4_setall,
1240        .getcap                 = cxgb4_getcap,
1241        .getnumtcs              = cxgb4_getnumtcs,
1242        .setnumtcs              = cxgb4_setnumtcs,
1243        .getpfcstate            = cxgb4_getpfcstate,
1244        .setpfcstate            = cxgb4_setpfcstate,
1245        .getapp                 = cxgb4_getapp,
1246        .setapp                 = cxgb4_setapp,
1247
1248        /* DCBX configuration */
1249        .getdcbx                = cxgb4_getdcbx,
1250        .setdcbx                = cxgb4_setdcbx,
1251
1252        /* peer apps */
1253        .peer_getappinfo        = cxgb4_getpeer_app,
1254        .peer_getapptable       = cxgb4_getpeerapp_tbl,
1255
1256        /* CEE peer */
1257        .cee_peer_getpg         = cxgb4_cee_peer_getpg,
1258        .cee_peer_getpfc        = cxgb4_cee_peer_getpfc,
1259};
1260