root/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. bnxt_queue_to_tc
  2. bnxt_hwrm_queue_pri2cos_cfg
  3. bnxt_hwrm_queue_pri2cos_qcfg
  4. bnxt_hwrm_queue_cos2bw_cfg
  5. bnxt_hwrm_queue_cos2bw_qcfg
  6. bnxt_queue_remap
  7. bnxt_hwrm_queue_pfc_cfg
  8. bnxt_hwrm_queue_pfc_qcfg
  9. bnxt_hwrm_set_dcbx_app
  10. bnxt_hwrm_queue_dscp_qcaps
  11. bnxt_hwrm_queue_dscp2pri_cfg
  12. bnxt_ets_validate
  13. bnxt_dcbnl_ieee_getets
  14. bnxt_dcbnl_ieee_setets
  15. bnxt_dcbnl_ieee_getpfc
  16. bnxt_dcbnl_ieee_setpfc
  17. bnxt_dcbnl_ieee_dscp_app_prep
  18. bnxt_dcbnl_ieee_setapp
  19. bnxt_dcbnl_ieee_delapp
  20. bnxt_dcbnl_getdcbx
  21. bnxt_dcbnl_setdcbx
  22. bnxt_dcb_init
  23. bnxt_dcb_free
  24. bnxt_dcb_init
  25. bnxt_dcb_free

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

/* [<][>][^][v][top][bottom][index][help] */