linux/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c
<<
>>
Prefs
   1/* Broadcom NetXtreme-C/E network driver.
   2 *
   3 * Copyright (c) 2014-2016 Broadcom Corporation
   4 * Copyright (c) 2016-2017 Broadcom Limited
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation.
   9 */
  10
  11#include <linux/netdevice.h>
  12#include <linux/types.h>
  13#include <linux/errno.h>
  14#include <linux/rtnetlink.h>
  15#include <linux/interrupt.h>
  16#include <linux/pci.h>
  17#include <linux/etherdevice.h>
  18#include <rdma/ib_verbs.h>
  19#include "bnxt_hsi.h"
  20#include "bnxt.h"
  21#include "bnxt_dcb.h"
  22
  23#ifdef CONFIG_BNXT_DCB
  24static int bnxt_queue_to_tc(struct bnxt *bp, u8 queue_id)
  25{
  26        int i, j;
  27
  28        for (i = 0; i < bp->max_tc; i++) {
  29                if (bp->q_info[i].queue_id == queue_id) {
  30                        for (j = 0; j < bp->max_tc; j++) {
  31                                if (bp->tc_to_qidx[j] == i)
  32                                        return j;
  33                        }
  34                }
  35        }
  36        return -EINVAL;
  37}
  38
  39static int bnxt_hwrm_queue_pri2cos_cfg(struct bnxt *bp, struct ieee_ets *ets)
  40{
  41        struct hwrm_queue_pri2cos_cfg_input req = {0};
  42        u8 *pri2cos;
  43        int i;
  44
  45        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PRI2COS_CFG, -1, -1);
  46        req.flags = cpu_to_le32(QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH_BIDIR |
  47                                QUEUE_PRI2COS_CFG_REQ_FLAGS_IVLAN);
  48
  49        pri2cos = &req.pri0_cos_queue_id;
  50        for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
  51                u8 qidx;
  52
  53                req.enables |= cpu_to_le32(
  54                        QUEUE_PRI2COS_CFG_REQ_ENABLES_PRI0_COS_QUEUE_ID << i);
  55
  56                qidx = bp->tc_to_qidx[ets->prio_tc[i]];
  57                pri2cos[i] = bp->q_info[qidx].queue_id;
  58        }
  59        return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
  60}
  61
  62static int bnxt_hwrm_queue_pri2cos_qcfg(struct bnxt *bp, struct ieee_ets *ets)
  63{
  64        struct hwrm_queue_pri2cos_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
  65        struct hwrm_queue_pri2cos_qcfg_input req = {0};
  66        int rc = 0;
  67
  68        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PRI2COS_QCFG, -1, -1);
  69        req.flags = cpu_to_le32(QUEUE_PRI2COS_QCFG_REQ_FLAGS_IVLAN);
  70
  71        mutex_lock(&bp->hwrm_cmd_lock);
  72        rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
  73        if (!rc) {
  74                u8 *pri2cos = &resp->pri0_cos_queue_id;
  75                int i;
  76
  77                for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
  78                        u8 queue_id = pri2cos[i];
  79                        int tc;
  80
  81                        tc = bnxt_queue_to_tc(bp, queue_id);
  82                        if (tc >= 0)
  83                                ets->prio_tc[i] = tc;
  84                }
  85        }
  86        mutex_unlock(&bp->hwrm_cmd_lock);
  87        return rc;
  88}
  89
  90static int bnxt_hwrm_queue_cos2bw_cfg(struct bnxt *bp, struct ieee_ets *ets,
  91                                      u8 max_tc)
  92{
  93        struct hwrm_queue_cos2bw_cfg_input req = {0};
  94        struct bnxt_cos2bw_cfg cos2bw;
  95        void *data;
  96        int i;
  97
  98        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_COS2BW_CFG, -1, -1);
  99        for (i = 0; i < max_tc; i++) {
 100                u8 qidx = bp->tc_to_qidx[i];
 101
 102                req.enables |= cpu_to_le32(
 103                        QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID0_VALID <<
 104                        qidx);
 105
 106                memset(&cos2bw, 0, sizeof(cos2bw));
 107                cos2bw.queue_id = bp->q_info[qidx].queue_id;
 108                if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_STRICT) {
 109                        cos2bw.tsa =
 110                                QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_SP;
 111                        cos2bw.pri_lvl = i;
 112                } else {
 113                        cos2bw.tsa =
 114                                QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_ETS;
 115                        cos2bw.bw_weight = ets->tc_tx_bw[i];
 116                        /* older firmware requires min_bw to be set to the
 117                         * same weight value in percent.
 118                         */
 119                        cos2bw.min_bw =
 120                                cpu_to_le32((ets->tc_tx_bw[i] * 100) |
 121                                            BW_VALUE_UNIT_PERCENT1_100);
 122                }
 123                data = &req.unused_0 + qidx * (sizeof(cos2bw) - 4);
 124                memcpy(data, &cos2bw.queue_id, sizeof(cos2bw) - 4);
 125                if (qidx == 0) {
 126                        req.queue_id0 = cos2bw.queue_id;
 127                        req.unused_0 = 0;
 128                }
 129        }
 130        return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
 131}
 132
 133static int bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt *bp, struct ieee_ets *ets)
 134{
 135        struct hwrm_queue_cos2bw_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
 136        struct hwrm_queue_cos2bw_qcfg_input req = {0};
 137        struct bnxt_cos2bw_cfg cos2bw;
 138        void *data;
 139        int rc, i;
 140
 141        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_COS2BW_QCFG, -1, -1);
 142
 143        mutex_lock(&bp->hwrm_cmd_lock);
 144        rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
 145        if (rc) {
 146                mutex_unlock(&bp->hwrm_cmd_lock);
 147                return rc;
 148        }
 149
 150        data = &resp->queue_id0 + offsetof(struct bnxt_cos2bw_cfg, queue_id);
 151        for (i = 0; i < bp->max_tc; i++, data += sizeof(cos2bw) - 4) {
 152                int tc;
 153
 154                memcpy(&cos2bw.queue_id, data, sizeof(cos2bw) - 4);
 155                if (i == 0)
 156                        cos2bw.queue_id = resp->queue_id0;
 157
 158                tc = bnxt_queue_to_tc(bp, cos2bw.queue_id);
 159                if (tc < 0)
 160                        continue;
 161
 162                if (cos2bw.tsa ==
 163                    QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_SP) {
 164                        ets->tc_tsa[tc] = IEEE_8021QAZ_TSA_STRICT;
 165                } else {
 166                        ets->tc_tsa[tc] = IEEE_8021QAZ_TSA_ETS;
 167                        ets->tc_tx_bw[tc] = cos2bw.bw_weight;
 168                }
 169        }
 170        mutex_unlock(&bp->hwrm_cmd_lock);
 171        return 0;
 172}
 173
 174static int bnxt_queue_remap(struct bnxt *bp, unsigned int lltc_mask)
 175{
 176        unsigned long qmap = 0;
 177        int max = bp->max_tc;
 178        int i, j, rc;
 179
 180        /* Assign lossless TCs first */
 181        for (i = 0, j = 0; i < max; ) {
 182                if (lltc_mask & (1 << i)) {
 183                        if (BNXT_LLQ(bp->q_info[j].queue_profile)) {
 184                                bp->tc_to_qidx[i] = j;
 185                                __set_bit(j, &qmap);
 186                                i++;
 187                        }
 188                        j++;
 189                        continue;
 190                }
 191                i++;
 192        }
 193
 194        for (i = 0, j = 0; i < max; i++) {
 195                if (lltc_mask & (1 << i))
 196                        continue;
 197                j = find_next_zero_bit(&qmap, max, j);
 198                bp->tc_to_qidx[i] = j;
 199                __set_bit(j, &qmap);
 200                j++;
 201        }
 202
 203        if (netif_running(bp->dev)) {
 204                bnxt_close_nic(bp, false, false);
 205                rc = bnxt_open_nic(bp, false, false);
 206                if (rc) {
 207                        netdev_warn(bp->dev, "failed to open NIC, rc = %d\n", rc);
 208                        return rc;
 209                }
 210        }
 211        if (bp->ieee_ets) {
 212                int tc = netdev_get_num_tc(bp->dev);
 213
 214                if (!tc)
 215                        tc = 1;
 216                rc = bnxt_hwrm_queue_cos2bw_cfg(bp, bp->ieee_ets, tc);
 217                if (rc) {
 218                        netdev_warn(bp->dev, "failed to config BW, rc = %d\n", rc);
 219                        return rc;
 220                }
 221                rc = bnxt_hwrm_queue_pri2cos_cfg(bp, bp->ieee_ets);
 222                if (rc) {
 223                        netdev_warn(bp->dev, "failed to config prio, rc = %d\n", rc);
 224                        return rc;
 225                }
 226        }
 227        return 0;
 228}
 229
 230static int bnxt_hwrm_queue_pfc_cfg(struct bnxt *bp, struct ieee_pfc *pfc)
 231{
 232        struct hwrm_queue_pfcenable_cfg_input req = {0};
 233        struct ieee_ets *my_ets = bp->ieee_ets;
 234        unsigned int tc_mask = 0, pri_mask = 0;
 235        u8 i, pri, lltc_count = 0;
 236        bool need_q_remap = false;
 237
 238        if (!my_ets)
 239                return -EINVAL;
 240
 241        for (i = 0; i < bp->max_tc; i++) {
 242                for (pri = 0; pri < IEEE_8021QAZ_MAX_TCS; pri++) {
 243                        if ((pfc->pfc_en & (1 << pri)) &&
 244                            (my_ets->prio_tc[pri] == i)) {
 245                                pri_mask |= 1 << pri;
 246                                tc_mask |= 1 << i;
 247                        }
 248                }
 249                if (tc_mask & (1 << i))
 250                        lltc_count++;
 251        }
 252        if (lltc_count > bp->max_lltc)
 253                return -EINVAL;
 254
 255        for (i = 0; i < bp->max_tc; i++) {
 256                if (tc_mask & (1 << i)) {
 257                        u8 qidx = bp->tc_to_qidx[i];
 258
 259                        if (!BNXT_LLQ(bp->q_info[qidx].queue_profile)) {
 260                                need_q_remap = true;
 261                                break;
 262                        }
 263                }
 264        }
 265
 266        if (need_q_remap)
 267                bnxt_queue_remap(bp, tc_mask);
 268
 269        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PFCENABLE_CFG, -1, -1);
 270        req.flags = cpu_to_le32(pri_mask);
 271        return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
 272}
 273
 274static int bnxt_hwrm_queue_pfc_qcfg(struct bnxt *bp, struct ieee_pfc *pfc)
 275{
 276        struct hwrm_queue_pfcenable_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
 277        struct hwrm_queue_pfcenable_qcfg_input req = {0};
 278        u8 pri_mask;
 279        int rc;
 280
 281        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PFCENABLE_QCFG, -1, -1);
 282
 283        mutex_lock(&bp->hwrm_cmd_lock);
 284        rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
 285        if (rc) {
 286                mutex_unlock(&bp->hwrm_cmd_lock);
 287                return rc;
 288        }
 289
 290        pri_mask = le32_to_cpu(resp->flags);
 291        pfc->pfc_en = pri_mask;
 292        mutex_unlock(&bp->hwrm_cmd_lock);
 293        return 0;
 294}
 295
 296static int bnxt_hwrm_set_dcbx_app(struct bnxt *bp, struct dcb_app *app,
 297                                  bool add)
 298{
 299        struct hwrm_fw_set_structured_data_input set = {0};
 300        struct hwrm_fw_get_structured_data_input get = {0};
 301        struct hwrm_struct_data_dcbx_app *fw_app;
 302        struct hwrm_struct_hdr *data;
 303        dma_addr_t mapping;
 304        size_t data_len;
 305        int rc, n, i;
 306
 307        if (bp->hwrm_spec_code < 0x10601)
 308                return 0;
 309
 310        n = IEEE_8021QAZ_MAX_TCS;
 311        data_len = sizeof(*data) + sizeof(*fw_app) * n;
 312        data = dma_alloc_coherent(&bp->pdev->dev, data_len, &mapping,
 313                                  GFP_KERNEL);
 314        if (!data)
 315                return -ENOMEM;
 316
 317        bnxt_hwrm_cmd_hdr_init(bp, &get, HWRM_FW_GET_STRUCTURED_DATA, -1, -1);
 318        get.dest_data_addr = cpu_to_le64(mapping);
 319        get.structure_id = cpu_to_le16(STRUCT_HDR_STRUCT_ID_DCBX_APP);
 320        get.subtype = cpu_to_le16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL);
 321        get.count = 0;
 322        rc = hwrm_send_message(bp, &get, sizeof(get), HWRM_CMD_TIMEOUT);
 323        if (rc)
 324                goto set_app_exit;
 325
 326        fw_app = (struct hwrm_struct_data_dcbx_app *)(data + 1);
 327
 328        if (data->struct_id != cpu_to_le16(STRUCT_HDR_STRUCT_ID_DCBX_APP)) {
 329                rc = -ENODEV;
 330                goto set_app_exit;
 331        }
 332
 333        n = data->count;
 334        for (i = 0; i < n; i++, fw_app++) {
 335                if (fw_app->protocol_id == cpu_to_be16(app->protocol) &&
 336                    fw_app->protocol_selector == app->selector &&
 337                    fw_app->priority == app->priority) {
 338                        if (add)
 339                                goto set_app_exit;
 340                        else
 341                                break;
 342                }
 343        }
 344        if (add) {
 345                /* append */
 346                n++;
 347                fw_app->protocol_id = cpu_to_be16(app->protocol);
 348                fw_app->protocol_selector = app->selector;
 349                fw_app->priority = app->priority;
 350                fw_app->valid = 1;
 351        } else {
 352                size_t len = 0;
 353
 354                /* not found, nothing to delete */
 355                if (n == i)
 356                        goto set_app_exit;
 357
 358                len = (n - 1 - i) * sizeof(*fw_app);
 359                if (len)
 360                        memmove(fw_app, fw_app + 1, len);
 361                n--;
 362                memset(fw_app + n, 0, sizeof(*fw_app));
 363        }
 364        data->count = n;
 365        data->len = cpu_to_le16(sizeof(*fw_app) * n);
 366        data->subtype = cpu_to_le16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL);
 367
 368        bnxt_hwrm_cmd_hdr_init(bp, &set, HWRM_FW_SET_STRUCTURED_DATA, -1, -1);
 369        set.src_data_addr = cpu_to_le64(mapping);
 370        set.data_len = cpu_to_le16(sizeof(*data) + sizeof(*fw_app) * n);
 371        set.hdr_cnt = 1;
 372        rc = hwrm_send_message(bp, &set, sizeof(set), HWRM_CMD_TIMEOUT);
 373
 374set_app_exit:
 375        dma_free_coherent(&bp->pdev->dev, data_len, data, mapping);
 376        return rc;
 377}
 378
 379static int bnxt_hwrm_queue_dscp_qcaps(struct bnxt *bp)
 380{
 381        struct hwrm_queue_dscp_qcaps_output *resp = bp->hwrm_cmd_resp_addr;
 382        struct hwrm_queue_dscp_qcaps_input req = {0};
 383        int rc;
 384
 385        bp->max_dscp_value = 0;
 386        if (bp->hwrm_spec_code < 0x10800 || BNXT_VF(bp))
 387                return 0;
 388
 389        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_DSCP_QCAPS, -1, -1);
 390        mutex_lock(&bp->hwrm_cmd_lock);
 391        rc = _hwrm_send_message_silent(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
 392        if (!rc) {
 393                bp->max_dscp_value = (1 << resp->num_dscp_bits) - 1;
 394                if (bp->max_dscp_value < 0x3f)
 395                        bp->max_dscp_value = 0;
 396        }
 397
 398        mutex_unlock(&bp->hwrm_cmd_lock);
 399        return rc;
 400}
 401
 402static int bnxt_hwrm_queue_dscp2pri_cfg(struct bnxt *bp, struct dcb_app *app,
 403                                        bool add)
 404{
 405        struct hwrm_queue_dscp2pri_cfg_input req = {0};
 406        struct bnxt_dscp2pri_entry *dscp2pri;
 407        dma_addr_t mapping;
 408        int rc;
 409
 410        if (bp->hwrm_spec_code < 0x10800)
 411                return 0;
 412
 413        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_DSCP2PRI_CFG, -1, -1);
 414        dscp2pri = dma_alloc_coherent(&bp->pdev->dev, sizeof(*dscp2pri),
 415                                      &mapping, GFP_KERNEL);
 416        if (!dscp2pri)
 417                return -ENOMEM;
 418
 419        req.src_data_addr = cpu_to_le64(mapping);
 420        dscp2pri->dscp = app->protocol;
 421        if (add)
 422                dscp2pri->mask = 0x3f;
 423        else
 424                dscp2pri->mask = 0;
 425        dscp2pri->pri = app->priority;
 426        req.entry_cnt = cpu_to_le16(1);
 427        rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
 428        dma_free_coherent(&bp->pdev->dev, sizeof(*dscp2pri), dscp2pri,
 429                          mapping);
 430        return rc;
 431}
 432
 433static int bnxt_ets_validate(struct bnxt *bp, struct ieee_ets *ets, u8 *tc)
 434{
 435        int total_ets_bw = 0;
 436        u8 max_tc = 0;
 437        int i;
 438
 439        for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
 440                if (ets->prio_tc[i] > bp->max_tc) {
 441                        netdev_err(bp->dev, "priority to TC mapping exceeds TC count %d\n",
 442                                   ets->prio_tc[i]);
 443                        return -EINVAL;
 444                }
 445                if (ets->prio_tc[i] > max_tc)
 446                        max_tc = ets->prio_tc[i];
 447
 448                if ((ets->tc_tx_bw[i] || ets->tc_tsa[i]) && i > bp->max_tc)
 449                        return -EINVAL;
 450
 451                switch (ets->tc_tsa[i]) {
 452                case IEEE_8021QAZ_TSA_STRICT:
 453                        break;
 454                case IEEE_8021QAZ_TSA_ETS:
 455                        total_ets_bw += ets->tc_tx_bw[i];
 456                        break;
 457                default:
 458                        return -ENOTSUPP;
 459                }
 460        }
 461        if (total_ets_bw > 100)
 462                return -EINVAL;
 463
 464        if (max_tc >= bp->max_tc)
 465                *tc = bp->max_tc;
 466        else
 467                *tc = max_tc + 1;
 468        return 0;
 469}
 470
 471static int bnxt_dcbnl_ieee_getets(struct net_device *dev, struct ieee_ets *ets)
 472{
 473        struct bnxt *bp = netdev_priv(dev);
 474        struct ieee_ets *my_ets = bp->ieee_ets;
 475        int rc;
 476
 477        ets->ets_cap = bp->max_tc;
 478
 479        if (!my_ets) {
 480                if (bp->dcbx_cap & DCB_CAP_DCBX_HOST)
 481                        return 0;
 482
 483                my_ets = kzalloc(sizeof(*my_ets), GFP_KERNEL);
 484                if (!my_ets)
 485                        return -ENOMEM;
 486                rc = bnxt_hwrm_queue_cos2bw_qcfg(bp, my_ets);
 487                if (rc)
 488                        goto error;
 489                rc = bnxt_hwrm_queue_pri2cos_qcfg(bp, my_ets);
 490                if (rc)
 491                        goto error;
 492
 493                /* cache result */
 494                bp->ieee_ets = my_ets;
 495        }
 496
 497        ets->cbs = my_ets->cbs;
 498        memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw));
 499        memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw));
 500        memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa));
 501        memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc));
 502        return 0;
 503error:
 504        kfree(my_ets);
 505        return rc;
 506}
 507
 508static int bnxt_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets)
 509{
 510        struct bnxt *bp = netdev_priv(dev);
 511        struct ieee_ets *my_ets = bp->ieee_ets;
 512        u8 max_tc = 0;
 513        int rc, i;
 514
 515        if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
 516            !(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
 517                return -EINVAL;
 518
 519        rc = bnxt_ets_validate(bp, ets, &max_tc);
 520        if (!rc) {
 521                if (!my_ets) {
 522                        my_ets = kzalloc(sizeof(*my_ets), GFP_KERNEL);
 523                        if (!my_ets)
 524                                return -ENOMEM;
 525                        /* initialize PRI2TC mappings to invalid value */
 526                        for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
 527                                my_ets->prio_tc[i] = IEEE_8021QAZ_MAX_TCS;
 528                        bp->ieee_ets = my_ets;
 529                }
 530                rc = bnxt_setup_mq_tc(dev, max_tc);
 531                if (rc)
 532                        return rc;
 533                rc = bnxt_hwrm_queue_cos2bw_cfg(bp, ets, max_tc);
 534                if (rc)
 535                        return rc;
 536                rc = bnxt_hwrm_queue_pri2cos_cfg(bp, ets);
 537                if (rc)
 538                        return rc;
 539                memcpy(my_ets, ets, sizeof(*my_ets));
 540        }
 541        return rc;
 542}
 543
 544static int bnxt_dcbnl_ieee_getpfc(struct net_device *dev, struct ieee_pfc *pfc)
 545{
 546        struct bnxt *bp = netdev_priv(dev);
 547        __le64 *stats = bp->port_stats.hw_stats;
 548        struct ieee_pfc *my_pfc = bp->ieee_pfc;
 549        long rx_off, tx_off;
 550        int i, rc;
 551
 552        pfc->pfc_cap = bp->max_lltc;
 553
 554        if (!my_pfc) {
 555                if (bp->dcbx_cap & DCB_CAP_DCBX_HOST)
 556                        return 0;
 557
 558                my_pfc = kzalloc(sizeof(*my_pfc), GFP_KERNEL);
 559                if (!my_pfc)
 560                        return 0;
 561                bp->ieee_pfc = my_pfc;
 562                rc = bnxt_hwrm_queue_pfc_qcfg(bp, my_pfc);
 563                if (rc)
 564                        return 0;
 565        }
 566
 567        pfc->pfc_en = my_pfc->pfc_en;
 568        pfc->mbc = my_pfc->mbc;
 569        pfc->delay = my_pfc->delay;
 570
 571        if (!stats)
 572                return 0;
 573
 574        rx_off = BNXT_RX_STATS_OFFSET(rx_pfc_ena_frames_pri0);
 575        tx_off = BNXT_TX_STATS_OFFSET(tx_pfc_ena_frames_pri0);
 576        for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++, rx_off++, tx_off++) {
 577                pfc->requests[i] = le64_to_cpu(*(stats + tx_off));
 578                pfc->indications[i] = le64_to_cpu(*(stats + rx_off));
 579        }
 580
 581        return 0;
 582}
 583
 584static int bnxt_dcbnl_ieee_setpfc(struct net_device *dev, struct ieee_pfc *pfc)
 585{
 586        struct bnxt *bp = netdev_priv(dev);
 587        struct ieee_pfc *my_pfc = bp->ieee_pfc;
 588        int rc;
 589
 590        if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
 591            !(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
 592                return -EINVAL;
 593
 594        if (!my_pfc) {
 595                my_pfc = kzalloc(sizeof(*my_pfc), GFP_KERNEL);
 596                if (!my_pfc)
 597                        return -ENOMEM;
 598                bp->ieee_pfc = my_pfc;
 599        }
 600        rc = bnxt_hwrm_queue_pfc_cfg(bp, pfc);
 601        if (!rc)
 602                memcpy(my_pfc, pfc, sizeof(*my_pfc));
 603
 604        return rc;
 605}
 606
 607static int bnxt_dcbnl_ieee_dscp_app_prep(struct bnxt *bp, struct dcb_app *app)
 608{
 609        if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) {
 610                if (!bp->max_dscp_value)
 611                        return -ENOTSUPP;
 612                if (app->protocol > bp->max_dscp_value)
 613                        return -EINVAL;
 614        }
 615        return 0;
 616}
 617
 618static int bnxt_dcbnl_ieee_setapp(struct net_device *dev, struct dcb_app *app)
 619{
 620        struct bnxt *bp = netdev_priv(dev);
 621        int rc;
 622
 623        if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
 624            !(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
 625                return -EINVAL;
 626
 627        rc = bnxt_dcbnl_ieee_dscp_app_prep(bp, app);
 628        if (rc)
 629                return rc;
 630
 631        rc = dcb_ieee_setapp(dev, app);
 632        if (rc)
 633                return rc;
 634
 635        if ((app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
 636             app->protocol == ETH_P_IBOE) ||
 637            (app->selector == IEEE_8021QAZ_APP_SEL_DGRAM &&
 638             app->protocol == ROCE_V2_UDP_DPORT))
 639                rc = bnxt_hwrm_set_dcbx_app(bp, app, true);
 640
 641        if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
 642                rc = bnxt_hwrm_queue_dscp2pri_cfg(bp, app, true);
 643
 644        return rc;
 645}
 646
 647static int bnxt_dcbnl_ieee_delapp(struct net_device *dev, struct dcb_app *app)
 648{
 649        struct bnxt *bp = netdev_priv(dev);
 650        int rc;
 651
 652        if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
 653            !(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
 654                return -EINVAL;
 655
 656        rc = bnxt_dcbnl_ieee_dscp_app_prep(bp, app);
 657        if (rc)
 658                return rc;
 659
 660        rc = dcb_ieee_delapp(dev, app);
 661        if (rc)
 662                return rc;
 663        if ((app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
 664             app->protocol == ETH_P_IBOE) ||
 665            (app->selector == IEEE_8021QAZ_APP_SEL_DGRAM &&
 666             app->protocol == ROCE_V2_UDP_DPORT))
 667                rc = bnxt_hwrm_set_dcbx_app(bp, app, false);
 668
 669        if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
 670                rc = bnxt_hwrm_queue_dscp2pri_cfg(bp, app, false);
 671
 672        return rc;
 673}
 674
 675static u8 bnxt_dcbnl_getdcbx(struct net_device *dev)
 676{
 677        struct bnxt *bp = netdev_priv(dev);
 678
 679        return bp->dcbx_cap;
 680}
 681
 682static u8 bnxt_dcbnl_setdcbx(struct net_device *dev, u8 mode)
 683{
 684        struct bnxt *bp = netdev_priv(dev);
 685
 686        /* All firmware DCBX settings are set in NVRAM */
 687        if (bp->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)
 688                return 1;
 689
 690        if (mode & DCB_CAP_DCBX_HOST) {
 691                if (BNXT_VF(bp) || (bp->fw_cap & BNXT_FW_CAP_LLDP_AGENT))
 692                        return 1;
 693
 694                /* only support IEEE */
 695                if ((mode & DCB_CAP_DCBX_VER_CEE) ||
 696                    !(mode & DCB_CAP_DCBX_VER_IEEE))
 697                        return 1;
 698        }
 699
 700        if (mode == bp->dcbx_cap)
 701                return 0;
 702
 703        bp->dcbx_cap = mode;
 704        return 0;
 705}
 706
 707static const struct dcbnl_rtnl_ops dcbnl_ops = {
 708        .ieee_getets    = bnxt_dcbnl_ieee_getets,
 709        .ieee_setets    = bnxt_dcbnl_ieee_setets,
 710        .ieee_getpfc    = bnxt_dcbnl_ieee_getpfc,
 711        .ieee_setpfc    = bnxt_dcbnl_ieee_setpfc,
 712        .ieee_setapp    = bnxt_dcbnl_ieee_setapp,
 713        .ieee_delapp    = bnxt_dcbnl_ieee_delapp,
 714        .getdcbx        = bnxt_dcbnl_getdcbx,
 715        .setdcbx        = bnxt_dcbnl_setdcbx,
 716};
 717
 718void bnxt_dcb_init(struct bnxt *bp)
 719{
 720        bp->dcbx_cap = 0;
 721        if (bp->hwrm_spec_code < 0x10501)
 722                return;
 723
 724        bnxt_hwrm_queue_dscp_qcaps(bp);
 725        bp->dcbx_cap = DCB_CAP_DCBX_VER_IEEE;
 726        if (BNXT_PF(bp) && !(bp->fw_cap & BNXT_FW_CAP_LLDP_AGENT))
 727                bp->dcbx_cap |= DCB_CAP_DCBX_HOST;
 728        else if (bp->fw_cap & BNXT_FW_CAP_DCBX_AGENT)
 729                bp->dcbx_cap |= DCB_CAP_DCBX_LLD_MANAGED;
 730        bp->dev->dcbnl_ops = &dcbnl_ops;
 731}
 732
 733void bnxt_dcb_free(struct bnxt *bp)
 734{
 735        kfree(bp->ieee_pfc);
 736        kfree(bp->ieee_ets);
 737        bp->ieee_pfc = NULL;
 738        bp->ieee_ets = NULL;
 739}
 740
 741#else
 742
 743void bnxt_dcb_init(struct bnxt *bp)
 744{
 745}
 746
 747void bnxt_dcb_free(struct bnxt *bp)
 748{
 749}
 750
 751#endif
 752