Back to home page

OSCL-LXR

 
 

    


0001 /* Broadcom NetXtreme-C/E network driver.
0002  *
0003  * Copyright (c) 2014-2016 Broadcom Corporation
0004  * Copyright (c) 2016-2017 Broadcom Limited
0005  *
0006  * This program is free software; you can redistribute it and/or modify
0007  * it under the terms of the GNU General Public License as published by
0008  * the Free Software Foundation.
0009  */
0010 
0011 #include <linux/netdevice.h>
0012 #include <linux/types.h>
0013 #include <linux/errno.h>
0014 #include <linux/rtnetlink.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/pci.h>
0017 #include <linux/etherdevice.h>
0018 #include <rdma/ib_verbs.h>
0019 #include "bnxt_hsi.h"
0020 #include "bnxt.h"
0021 #include "bnxt_hwrm.h"
0022 #include "bnxt_dcb.h"
0023 
0024 #ifdef CONFIG_BNXT_DCB
0025 static int bnxt_queue_to_tc(struct bnxt *bp, u8 queue_id)
0026 {
0027     int i, j;
0028 
0029     for (i = 0; i < bp->max_tc; i++) {
0030         if (bp->q_info[i].queue_id == queue_id) {
0031             for (j = 0; j < bp->max_tc; j++) {
0032                 if (bp->tc_to_qidx[j] == i)
0033                     return j;
0034             }
0035         }
0036     }
0037     return -EINVAL;
0038 }
0039 
0040 static int bnxt_hwrm_queue_pri2cos_cfg(struct bnxt *bp, struct ieee_ets *ets)
0041 {
0042     struct hwrm_queue_pri2cos_cfg_input *req;
0043     u8 *pri2cos;
0044     int rc, i;
0045 
0046     rc = hwrm_req_init(bp, req, HWRM_QUEUE_PRI2COS_CFG);
0047     if (rc)
0048         return rc;
0049 
0050     req->flags = cpu_to_le32(QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH_BIDIR |
0051                  QUEUE_PRI2COS_CFG_REQ_FLAGS_IVLAN);
0052 
0053     pri2cos = &req->pri0_cos_queue_id;
0054     for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
0055         u8 qidx;
0056 
0057         req->enables |= cpu_to_le32(
0058             QUEUE_PRI2COS_CFG_REQ_ENABLES_PRI0_COS_QUEUE_ID << i);
0059 
0060         qidx = bp->tc_to_qidx[ets->prio_tc[i]];
0061         pri2cos[i] = bp->q_info[qidx].queue_id;
0062     }
0063     return hwrm_req_send(bp, req);
0064 }
0065 
0066 static int bnxt_hwrm_queue_pri2cos_qcfg(struct bnxt *bp, struct ieee_ets *ets)
0067 {
0068     struct hwrm_queue_pri2cos_qcfg_output *resp;
0069     struct hwrm_queue_pri2cos_qcfg_input *req;
0070     int rc;
0071 
0072     rc = hwrm_req_init(bp, req, HWRM_QUEUE_PRI2COS_QCFG);
0073     if (rc)
0074         return rc;
0075 
0076     req->flags = cpu_to_le32(QUEUE_PRI2COS_QCFG_REQ_FLAGS_IVLAN);
0077     resp = hwrm_req_hold(bp, req);
0078     rc = hwrm_req_send(bp, req);
0079     if (!rc) {
0080         u8 *pri2cos = &resp->pri0_cos_queue_id;
0081         int i;
0082 
0083         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
0084             u8 queue_id = pri2cos[i];
0085             int tc;
0086 
0087             tc = bnxt_queue_to_tc(bp, queue_id);
0088             if (tc >= 0)
0089                 ets->prio_tc[i] = tc;
0090         }
0091     }
0092     hwrm_req_drop(bp, req);
0093     return rc;
0094 }
0095 
0096 static int bnxt_hwrm_queue_cos2bw_cfg(struct bnxt *bp, struct ieee_ets *ets,
0097                       u8 max_tc)
0098 {
0099     struct hwrm_queue_cos2bw_cfg_input *req;
0100     struct bnxt_cos2bw_cfg cos2bw;
0101     void *data;
0102     int rc, i;
0103 
0104     rc = hwrm_req_init(bp, req, HWRM_QUEUE_COS2BW_CFG);
0105     if (rc)
0106         return rc;
0107 
0108     for (i = 0; i < max_tc; i++) {
0109         u8 qidx = bp->tc_to_qidx[i];
0110 
0111         req->enables |= cpu_to_le32(
0112             QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID0_VALID <<
0113             qidx);
0114 
0115         memset(&cos2bw, 0, sizeof(cos2bw));
0116         cos2bw.queue_id = bp->q_info[qidx].queue_id;
0117         if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_STRICT) {
0118             cos2bw.tsa =
0119                 QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_SP;
0120             cos2bw.pri_lvl = i;
0121         } else {
0122             cos2bw.tsa =
0123                 QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_ETS;
0124             cos2bw.bw_weight = ets->tc_tx_bw[i];
0125             /* older firmware requires min_bw to be set to the
0126              * same weight value in percent.
0127              */
0128             cos2bw.min_bw =
0129                 cpu_to_le32((ets->tc_tx_bw[i] * 100) |
0130                         BW_VALUE_UNIT_PERCENT1_100);
0131         }
0132         data = &req->unused_0 + qidx * (sizeof(cos2bw) - 4);
0133         memcpy(data, &cos2bw.queue_id, sizeof(cos2bw) - 4);
0134         if (qidx == 0) {
0135             req->queue_id0 = cos2bw.queue_id;
0136             req->unused_0 = 0;
0137         }
0138     }
0139     return hwrm_req_send(bp, req);
0140 }
0141 
0142 static int bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt *bp, struct ieee_ets *ets)
0143 {
0144     struct hwrm_queue_cos2bw_qcfg_output *resp;
0145     struct hwrm_queue_cos2bw_qcfg_input *req;
0146     struct bnxt_cos2bw_cfg cos2bw;
0147     void *data;
0148     int rc, i;
0149 
0150     rc = hwrm_req_init(bp, req, HWRM_QUEUE_COS2BW_QCFG);
0151     if (rc)
0152         return rc;
0153 
0154     resp = hwrm_req_hold(bp, req);
0155     rc = hwrm_req_send(bp, req);
0156     if (rc) {
0157         hwrm_req_drop(bp, req);
0158         return rc;
0159     }
0160 
0161     data = &resp->queue_id0 + offsetof(struct bnxt_cos2bw_cfg, queue_id);
0162     for (i = 0; i < bp->max_tc; i++, data += sizeof(cos2bw.cfg)) {
0163         int tc;
0164 
0165         memcpy(&cos2bw.cfg, data, sizeof(cos2bw.cfg));
0166         if (i == 0)
0167             cos2bw.queue_id = resp->queue_id0;
0168 
0169         tc = bnxt_queue_to_tc(bp, cos2bw.queue_id);
0170         if (tc < 0)
0171             continue;
0172 
0173         if (cos2bw.tsa ==
0174             QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_SP) {
0175             ets->tc_tsa[tc] = IEEE_8021QAZ_TSA_STRICT;
0176         } else {
0177             ets->tc_tsa[tc] = IEEE_8021QAZ_TSA_ETS;
0178             ets->tc_tx_bw[tc] = cos2bw.bw_weight;
0179         }
0180     }
0181     hwrm_req_drop(bp, req);
0182     return 0;
0183 }
0184 
0185 static int bnxt_queue_remap(struct bnxt *bp, unsigned int lltc_mask)
0186 {
0187     unsigned long qmap = 0;
0188     int max = bp->max_tc;
0189     int i, j, rc;
0190 
0191     /* Assign lossless TCs first */
0192     for (i = 0, j = 0; i < max; ) {
0193         if (lltc_mask & (1 << i)) {
0194             if (BNXT_LLQ(bp->q_info[j].queue_profile)) {
0195                 bp->tc_to_qidx[i] = j;
0196                 __set_bit(j, &qmap);
0197                 i++;
0198             }
0199             j++;
0200             continue;
0201         }
0202         i++;
0203     }
0204 
0205     for (i = 0, j = 0; i < max; i++) {
0206         if (lltc_mask & (1 << i))
0207             continue;
0208         j = find_next_zero_bit(&qmap, max, j);
0209         bp->tc_to_qidx[i] = j;
0210         __set_bit(j, &qmap);
0211         j++;
0212     }
0213 
0214     if (netif_running(bp->dev)) {
0215         bnxt_close_nic(bp, false, false);
0216         rc = bnxt_open_nic(bp, false, false);
0217         if (rc) {
0218             netdev_warn(bp->dev, "failed to open NIC, rc = %d\n", rc);
0219             return rc;
0220         }
0221     }
0222     if (bp->ieee_ets) {
0223         int tc = netdev_get_num_tc(bp->dev);
0224 
0225         if (!tc)
0226             tc = 1;
0227         rc = bnxt_hwrm_queue_cos2bw_cfg(bp, bp->ieee_ets, tc);
0228         if (rc) {
0229             netdev_warn(bp->dev, "failed to config BW, rc = %d\n", rc);
0230             return rc;
0231         }
0232         rc = bnxt_hwrm_queue_pri2cos_cfg(bp, bp->ieee_ets);
0233         if (rc) {
0234             netdev_warn(bp->dev, "failed to config prio, rc = %d\n", rc);
0235             return rc;
0236         }
0237     }
0238     return 0;
0239 }
0240 
0241 static int bnxt_hwrm_queue_pfc_cfg(struct bnxt *bp, struct ieee_pfc *pfc)
0242 {
0243     struct hwrm_queue_pfcenable_cfg_input *req;
0244     struct ieee_ets *my_ets = bp->ieee_ets;
0245     unsigned int tc_mask = 0, pri_mask = 0;
0246     u8 i, pri, lltc_count = 0;
0247     bool need_q_remap = false;
0248     int rc;
0249 
0250     if (!my_ets)
0251         return -EINVAL;
0252 
0253     for (i = 0; i < bp->max_tc; i++) {
0254         for (pri = 0; pri < IEEE_8021QAZ_MAX_TCS; pri++) {
0255             if ((pfc->pfc_en & (1 << pri)) &&
0256                 (my_ets->prio_tc[pri] == i)) {
0257                 pri_mask |= 1 << pri;
0258                 tc_mask |= 1 << i;
0259             }
0260         }
0261         if (tc_mask & (1 << i))
0262             lltc_count++;
0263     }
0264     if (lltc_count > bp->max_lltc)
0265         return -EINVAL;
0266 
0267     for (i = 0; i < bp->max_tc; i++) {
0268         if (tc_mask & (1 << i)) {
0269             u8 qidx = bp->tc_to_qidx[i];
0270 
0271             if (!BNXT_LLQ(bp->q_info[qidx].queue_profile)) {
0272                 need_q_remap = true;
0273                 break;
0274             }
0275         }
0276     }
0277 
0278     if (need_q_remap)
0279         bnxt_queue_remap(bp, tc_mask);
0280 
0281     rc = hwrm_req_init(bp, req, HWRM_QUEUE_PFCENABLE_CFG);
0282     if (rc)
0283         return rc;
0284 
0285     req->flags = cpu_to_le32(pri_mask);
0286     return hwrm_req_send(bp, req);
0287 }
0288 
0289 static int bnxt_hwrm_queue_pfc_qcfg(struct bnxt *bp, struct ieee_pfc *pfc)
0290 {
0291     struct hwrm_queue_pfcenable_qcfg_output *resp;
0292     struct hwrm_queue_pfcenable_qcfg_input *req;
0293     u8 pri_mask;
0294     int rc;
0295 
0296     rc = hwrm_req_init(bp, req, HWRM_QUEUE_PFCENABLE_QCFG);
0297     if (rc)
0298         return rc;
0299 
0300     resp = hwrm_req_hold(bp, req);
0301     rc = hwrm_req_send(bp, req);
0302     if (rc) {
0303         hwrm_req_drop(bp, req);
0304         return rc;
0305     }
0306 
0307     pri_mask = le32_to_cpu(resp->flags);
0308     pfc->pfc_en = pri_mask;
0309     hwrm_req_drop(bp, req);
0310     return 0;
0311 }
0312 
0313 static int bnxt_hwrm_set_dcbx_app(struct bnxt *bp, struct dcb_app *app,
0314                   bool add)
0315 {
0316     struct hwrm_fw_set_structured_data_input *set;
0317     struct hwrm_fw_get_structured_data_input *get;
0318     struct hwrm_struct_data_dcbx_app *fw_app;
0319     struct hwrm_struct_hdr *data;
0320     dma_addr_t mapping;
0321     size_t data_len;
0322     int rc, n, i;
0323 
0324     if (bp->hwrm_spec_code < 0x10601)
0325         return 0;
0326 
0327     rc = hwrm_req_init(bp, get, HWRM_FW_GET_STRUCTURED_DATA);
0328     if (rc)
0329         return rc;
0330 
0331     hwrm_req_hold(bp, get);
0332     hwrm_req_alloc_flags(bp, get, GFP_KERNEL | __GFP_ZERO);
0333 
0334     n = IEEE_8021QAZ_MAX_TCS;
0335     data_len = sizeof(*data) + sizeof(*fw_app) * n;
0336     data = hwrm_req_dma_slice(bp, get, data_len, &mapping);
0337     if (!data) {
0338         rc = -ENOMEM;
0339         goto set_app_exit;
0340     }
0341 
0342     get->dest_data_addr = cpu_to_le64(mapping);
0343     get->structure_id = cpu_to_le16(STRUCT_HDR_STRUCT_ID_DCBX_APP);
0344     get->subtype = cpu_to_le16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL);
0345     get->count = 0;
0346     rc = hwrm_req_send(bp, get);
0347     if (rc)
0348         goto set_app_exit;
0349 
0350     fw_app = (struct hwrm_struct_data_dcbx_app *)(data + 1);
0351 
0352     if (data->struct_id != cpu_to_le16(STRUCT_HDR_STRUCT_ID_DCBX_APP)) {
0353         rc = -ENODEV;
0354         goto set_app_exit;
0355     }
0356 
0357     n = data->count;
0358     for (i = 0; i < n; i++, fw_app++) {
0359         if (fw_app->protocol_id == cpu_to_be16(app->protocol) &&
0360             fw_app->protocol_selector == app->selector &&
0361             fw_app->priority == app->priority) {
0362             if (add)
0363                 goto set_app_exit;
0364             else
0365                 break;
0366         }
0367     }
0368     if (add) {
0369         /* append */
0370         n++;
0371         fw_app->protocol_id = cpu_to_be16(app->protocol);
0372         fw_app->protocol_selector = app->selector;
0373         fw_app->priority = app->priority;
0374         fw_app->valid = 1;
0375     } else {
0376         size_t len = 0;
0377 
0378         /* not found, nothing to delete */
0379         if (n == i)
0380             goto set_app_exit;
0381 
0382         len = (n - 1 - i) * sizeof(*fw_app);
0383         if (len)
0384             memmove(fw_app, fw_app + 1, len);
0385         n--;
0386         memset(fw_app + n, 0, sizeof(*fw_app));
0387     }
0388     data->count = n;
0389     data->len = cpu_to_le16(sizeof(*fw_app) * n);
0390     data->subtype = cpu_to_le16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL);
0391 
0392     rc = hwrm_req_init(bp, set, HWRM_FW_SET_STRUCTURED_DATA);
0393     if (rc)
0394         goto set_app_exit;
0395 
0396     set->src_data_addr = cpu_to_le64(mapping);
0397     set->data_len = cpu_to_le16(sizeof(*data) + sizeof(*fw_app) * n);
0398     set->hdr_cnt = 1;
0399     rc = hwrm_req_send(bp, set);
0400 
0401 set_app_exit:
0402     hwrm_req_drop(bp, get); /* dropping get request and associated slice */
0403     return rc;
0404 }
0405 
0406 static int bnxt_hwrm_queue_dscp_qcaps(struct bnxt *bp)
0407 {
0408     struct hwrm_queue_dscp_qcaps_output *resp;
0409     struct hwrm_queue_dscp_qcaps_input *req;
0410     int rc;
0411 
0412     bp->max_dscp_value = 0;
0413     if (bp->hwrm_spec_code < 0x10800 || BNXT_VF(bp))
0414         return 0;
0415 
0416     rc = hwrm_req_init(bp, req, HWRM_QUEUE_DSCP_QCAPS);
0417     if (rc)
0418         return rc;
0419 
0420     resp = hwrm_req_hold(bp, req);
0421     rc = hwrm_req_send_silent(bp, req);
0422     if (!rc) {
0423         bp->max_dscp_value = (1 << resp->num_dscp_bits) - 1;
0424         if (bp->max_dscp_value < 0x3f)
0425             bp->max_dscp_value = 0;
0426     }
0427     hwrm_req_drop(bp, req);
0428     return rc;
0429 }
0430 
0431 static int bnxt_hwrm_queue_dscp2pri_cfg(struct bnxt *bp, struct dcb_app *app,
0432                     bool add)
0433 {
0434     struct hwrm_queue_dscp2pri_cfg_input *req;
0435     struct bnxt_dscp2pri_entry *dscp2pri;
0436     dma_addr_t mapping;
0437     int rc;
0438 
0439     if (bp->hwrm_spec_code < 0x10800)
0440         return 0;
0441 
0442     rc = hwrm_req_init(bp, req, HWRM_QUEUE_DSCP2PRI_CFG);
0443     if (rc)
0444         return rc;
0445 
0446     dscp2pri = hwrm_req_dma_slice(bp, req, sizeof(*dscp2pri), &mapping);
0447     if (!dscp2pri) {
0448         hwrm_req_drop(bp, req);
0449         return -ENOMEM;
0450     }
0451 
0452     req->src_data_addr = cpu_to_le64(mapping);
0453     dscp2pri->dscp = app->protocol;
0454     if (add)
0455         dscp2pri->mask = 0x3f;
0456     else
0457         dscp2pri->mask = 0;
0458     dscp2pri->pri = app->priority;
0459     req->entry_cnt = cpu_to_le16(1);
0460     rc = hwrm_req_send(bp, req);
0461     return rc;
0462 }
0463 
0464 static int bnxt_ets_validate(struct bnxt *bp, struct ieee_ets *ets, u8 *tc)
0465 {
0466     int total_ets_bw = 0;
0467     bool zero = false;
0468     u8 max_tc = 0;
0469     int i;
0470 
0471     for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
0472         if (ets->prio_tc[i] > bp->max_tc) {
0473             netdev_err(bp->dev, "priority to TC mapping exceeds TC count %d\n",
0474                    ets->prio_tc[i]);
0475             return -EINVAL;
0476         }
0477         if (ets->prio_tc[i] > max_tc)
0478             max_tc = ets->prio_tc[i];
0479 
0480         if ((ets->tc_tx_bw[i] || ets->tc_tsa[i]) && i > bp->max_tc)
0481             return -EINVAL;
0482 
0483         switch (ets->tc_tsa[i]) {
0484         case IEEE_8021QAZ_TSA_STRICT:
0485             break;
0486         case IEEE_8021QAZ_TSA_ETS:
0487             total_ets_bw += ets->tc_tx_bw[i];
0488             zero = zero || !ets->tc_tx_bw[i];
0489             break;
0490         default:
0491             return -ENOTSUPP;
0492         }
0493     }
0494     if (total_ets_bw > 100) {
0495         netdev_warn(bp->dev, "rejecting ETS config exceeding available bandwidth\n");
0496         return -EINVAL;
0497     }
0498     if (zero && total_ets_bw == 100) {
0499         netdev_warn(bp->dev, "rejecting ETS config starving a TC\n");
0500         return -EINVAL;
0501     }
0502 
0503     if (max_tc >= bp->max_tc)
0504         *tc = bp->max_tc;
0505     else
0506         *tc = max_tc + 1;
0507     return 0;
0508 }
0509 
0510 static int bnxt_dcbnl_ieee_getets(struct net_device *dev, struct ieee_ets *ets)
0511 {
0512     struct bnxt *bp = netdev_priv(dev);
0513     struct ieee_ets *my_ets = bp->ieee_ets;
0514     int rc;
0515 
0516     ets->ets_cap = bp->max_tc;
0517 
0518     if (!my_ets) {
0519         if (bp->dcbx_cap & DCB_CAP_DCBX_HOST)
0520             return 0;
0521 
0522         my_ets = kzalloc(sizeof(*my_ets), GFP_KERNEL);
0523         if (!my_ets)
0524             return -ENOMEM;
0525         rc = bnxt_hwrm_queue_cos2bw_qcfg(bp, my_ets);
0526         if (rc)
0527             goto error;
0528         rc = bnxt_hwrm_queue_pri2cos_qcfg(bp, my_ets);
0529         if (rc)
0530             goto error;
0531 
0532         /* cache result */
0533         bp->ieee_ets = my_ets;
0534     }
0535 
0536     ets->cbs = my_ets->cbs;
0537     memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw));
0538     memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw));
0539     memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa));
0540     memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc));
0541     return 0;
0542 error:
0543     kfree(my_ets);
0544     return rc;
0545 }
0546 
0547 static int bnxt_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets)
0548 {
0549     struct bnxt *bp = netdev_priv(dev);
0550     struct ieee_ets *my_ets = bp->ieee_ets;
0551     u8 max_tc = 0;
0552     int rc, i;
0553 
0554     if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
0555         !(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
0556         return -EINVAL;
0557 
0558     rc = bnxt_ets_validate(bp, ets, &max_tc);
0559     if (!rc) {
0560         if (!my_ets) {
0561             my_ets = kzalloc(sizeof(*my_ets), GFP_KERNEL);
0562             if (!my_ets)
0563                 return -ENOMEM;
0564             /* initialize PRI2TC mappings to invalid value */
0565             for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
0566                 my_ets->prio_tc[i] = IEEE_8021QAZ_MAX_TCS;
0567             bp->ieee_ets = my_ets;
0568         }
0569         rc = bnxt_setup_mq_tc(dev, max_tc);
0570         if (rc)
0571             return rc;
0572         rc = bnxt_hwrm_queue_cos2bw_cfg(bp, ets, max_tc);
0573         if (rc)
0574             return rc;
0575         rc = bnxt_hwrm_queue_pri2cos_cfg(bp, ets);
0576         if (rc)
0577             return rc;
0578         memcpy(my_ets, ets, sizeof(*my_ets));
0579     }
0580     return rc;
0581 }
0582 
0583 static int bnxt_dcbnl_ieee_getpfc(struct net_device *dev, struct ieee_pfc *pfc)
0584 {
0585     struct bnxt *bp = netdev_priv(dev);
0586     __le64 *stats = bp->port_stats.hw_stats;
0587     struct ieee_pfc *my_pfc = bp->ieee_pfc;
0588     long rx_off, tx_off;
0589     int i, rc;
0590 
0591     pfc->pfc_cap = bp->max_lltc;
0592 
0593     if (!my_pfc) {
0594         if (bp->dcbx_cap & DCB_CAP_DCBX_HOST)
0595             return 0;
0596 
0597         my_pfc = kzalloc(sizeof(*my_pfc), GFP_KERNEL);
0598         if (!my_pfc)
0599             return 0;
0600         bp->ieee_pfc = my_pfc;
0601         rc = bnxt_hwrm_queue_pfc_qcfg(bp, my_pfc);
0602         if (rc)
0603             return 0;
0604     }
0605 
0606     pfc->pfc_en = my_pfc->pfc_en;
0607     pfc->mbc = my_pfc->mbc;
0608     pfc->delay = my_pfc->delay;
0609 
0610     if (!stats)
0611         return 0;
0612 
0613     rx_off = BNXT_RX_STATS_OFFSET(rx_pfc_ena_frames_pri0);
0614     tx_off = BNXT_TX_STATS_OFFSET(tx_pfc_ena_frames_pri0);
0615     for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++, rx_off++, tx_off++) {
0616         pfc->requests[i] = le64_to_cpu(*(stats + tx_off));
0617         pfc->indications[i] = le64_to_cpu(*(stats + rx_off));
0618     }
0619 
0620     return 0;
0621 }
0622 
0623 static int bnxt_dcbnl_ieee_setpfc(struct net_device *dev, struct ieee_pfc *pfc)
0624 {
0625     struct bnxt *bp = netdev_priv(dev);
0626     struct ieee_pfc *my_pfc = bp->ieee_pfc;
0627     int rc;
0628 
0629     if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
0630         !(bp->dcbx_cap & DCB_CAP_DCBX_HOST) ||
0631         (bp->phy_flags & BNXT_PHY_FL_NO_PAUSE))
0632         return -EINVAL;
0633 
0634     if (!my_pfc) {
0635         my_pfc = kzalloc(sizeof(*my_pfc), GFP_KERNEL);
0636         if (!my_pfc)
0637             return -ENOMEM;
0638         bp->ieee_pfc = my_pfc;
0639     }
0640     rc = bnxt_hwrm_queue_pfc_cfg(bp, pfc);
0641     if (!rc)
0642         memcpy(my_pfc, pfc, sizeof(*my_pfc));
0643 
0644     return rc;
0645 }
0646 
0647 static int bnxt_dcbnl_ieee_dscp_app_prep(struct bnxt *bp, struct dcb_app *app)
0648 {
0649     if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) {
0650         if (!bp->max_dscp_value)
0651             return -ENOTSUPP;
0652         if (app->protocol > bp->max_dscp_value)
0653             return -EINVAL;
0654     }
0655     return 0;
0656 }
0657 
0658 static int bnxt_dcbnl_ieee_setapp(struct net_device *dev, struct dcb_app *app)
0659 {
0660     struct bnxt *bp = netdev_priv(dev);
0661     int rc;
0662 
0663     if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
0664         !(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
0665         return -EINVAL;
0666 
0667     rc = bnxt_dcbnl_ieee_dscp_app_prep(bp, app);
0668     if (rc)
0669         return rc;
0670 
0671     rc = dcb_ieee_setapp(dev, app);
0672     if (rc)
0673         return rc;
0674 
0675     if ((app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
0676          app->protocol == ETH_P_IBOE) ||
0677         (app->selector == IEEE_8021QAZ_APP_SEL_DGRAM &&
0678          app->protocol == ROCE_V2_UDP_DPORT))
0679         rc = bnxt_hwrm_set_dcbx_app(bp, app, true);
0680 
0681     if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
0682         rc = bnxt_hwrm_queue_dscp2pri_cfg(bp, app, true);
0683 
0684     return rc;
0685 }
0686 
0687 static int bnxt_dcbnl_ieee_delapp(struct net_device *dev, struct dcb_app *app)
0688 {
0689     struct bnxt *bp = netdev_priv(dev);
0690     int rc;
0691 
0692     if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
0693         !(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
0694         return -EINVAL;
0695 
0696     rc = bnxt_dcbnl_ieee_dscp_app_prep(bp, app);
0697     if (rc)
0698         return rc;
0699 
0700     rc = dcb_ieee_delapp(dev, app);
0701     if (rc)
0702         return rc;
0703     if ((app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
0704          app->protocol == ETH_P_IBOE) ||
0705         (app->selector == IEEE_8021QAZ_APP_SEL_DGRAM &&
0706          app->protocol == ROCE_V2_UDP_DPORT))
0707         rc = bnxt_hwrm_set_dcbx_app(bp, app, false);
0708 
0709     if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
0710         rc = bnxt_hwrm_queue_dscp2pri_cfg(bp, app, false);
0711 
0712     return rc;
0713 }
0714 
0715 static u8 bnxt_dcbnl_getdcbx(struct net_device *dev)
0716 {
0717     struct bnxt *bp = netdev_priv(dev);
0718 
0719     return bp->dcbx_cap;
0720 }
0721 
0722 static u8 bnxt_dcbnl_setdcbx(struct net_device *dev, u8 mode)
0723 {
0724     struct bnxt *bp = netdev_priv(dev);
0725 
0726     /* All firmware DCBX settings are set in NVRAM */
0727     if (bp->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)
0728         return 1;
0729 
0730     if (mode & DCB_CAP_DCBX_HOST) {
0731         if (BNXT_VF(bp) || (bp->fw_cap & BNXT_FW_CAP_LLDP_AGENT))
0732             return 1;
0733 
0734         /* only support IEEE */
0735         if ((mode & DCB_CAP_DCBX_VER_CEE) ||
0736             !(mode & DCB_CAP_DCBX_VER_IEEE))
0737             return 1;
0738     }
0739 
0740     if (mode == bp->dcbx_cap)
0741         return 0;
0742 
0743     bp->dcbx_cap = mode;
0744     return 0;
0745 }
0746 
0747 static const struct dcbnl_rtnl_ops dcbnl_ops = {
0748     .ieee_getets    = bnxt_dcbnl_ieee_getets,
0749     .ieee_setets    = bnxt_dcbnl_ieee_setets,
0750     .ieee_getpfc    = bnxt_dcbnl_ieee_getpfc,
0751     .ieee_setpfc    = bnxt_dcbnl_ieee_setpfc,
0752     .ieee_setapp    = bnxt_dcbnl_ieee_setapp,
0753     .ieee_delapp    = bnxt_dcbnl_ieee_delapp,
0754     .getdcbx    = bnxt_dcbnl_getdcbx,
0755     .setdcbx    = bnxt_dcbnl_setdcbx,
0756 };
0757 
0758 void bnxt_dcb_init(struct bnxt *bp)
0759 {
0760     bp->dcbx_cap = 0;
0761     if (bp->hwrm_spec_code < 0x10501)
0762         return;
0763 
0764     bnxt_hwrm_queue_dscp_qcaps(bp);
0765     bp->dcbx_cap = DCB_CAP_DCBX_VER_IEEE;
0766     if (BNXT_PF(bp) && !(bp->fw_cap & BNXT_FW_CAP_LLDP_AGENT))
0767         bp->dcbx_cap |= DCB_CAP_DCBX_HOST;
0768     else if (bp->fw_cap & BNXT_FW_CAP_DCBX_AGENT)
0769         bp->dcbx_cap |= DCB_CAP_DCBX_LLD_MANAGED;
0770     bp->dev->dcbnl_ops = &dcbnl_ops;
0771 }
0772 
0773 void bnxt_dcb_free(struct bnxt *bp)
0774 {
0775     kfree(bp->ieee_pfc);
0776     kfree(bp->ieee_ets);
0777     bp->ieee_pfc = NULL;
0778     bp->ieee_ets = NULL;
0779 }
0780 
0781 #else
0782 
0783 void bnxt_dcb_init(struct bnxt *bp)
0784 {
0785 }
0786 
0787 void bnxt_dcb_free(struct bnxt *bp)
0788 {
0789 }
0790 
0791 #endif