Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
0002 /* QLogic qed NIC Driver
0003  * Copyright (c) 2015-2017  QLogic Corporation
0004  * Copyright (c) 2019-2020 Marvell International Ltd.
0005  */
0006 
0007 #include <linux/types.h>
0008 #include <asm/byteorder.h>
0009 #include <linux/bitops.h>
0010 #include <linux/dcbnl.h>
0011 #include <linux/errno.h>
0012 #include <linux/kernel.h>
0013 #include <linux/slab.h>
0014 #include <linux/string.h>
0015 #include "qed.h"
0016 #include "qed_cxt.h"
0017 #include "qed_dcbx.h"
0018 #include "qed_hsi.h"
0019 #include "qed_sp.h"
0020 #include "qed_sriov.h"
0021 #include "qed_rdma.h"
0022 #ifdef CONFIG_DCB
0023 #include <linux/qed/qed_eth_if.h>
0024 #endif
0025 
0026 #define QED_DCBX_MAX_MIB_READ_TRY       (100)
0027 #define QED_ETH_TYPE_DEFAULT            (0)
0028 #define QED_ETH_TYPE_ROCE               (0x8915)
0029 #define QED_UDP_PORT_TYPE_ROCE_V2       (0x12B7)
0030 #define QED_ETH_TYPE_FCOE               (0x8906)
0031 #define QED_TCP_PORT_ISCSI              (0xCBC)
0032 
0033 #define QED_DCBX_INVALID_PRIORITY       0xFF
0034 
0035 /* Get Traffic Class from priority traffic class table, 4 bits represent
0036  * the traffic class corresponding to the priority.
0037  */
0038 #define QED_DCBX_PRIO2TC(prio_tc_tbl, prio) \
0039     ((u32)(prio_tc_tbl >> ((7 - prio) * 4)) & 0x7)
0040 
0041 static const struct qed_dcbx_app_metadata qed_dcbx_app_update[] = {
0042     {DCBX_PROTOCOL_ISCSI, "ISCSI", QED_PCI_ISCSI},
0043     {DCBX_PROTOCOL_FCOE, "FCOE", QED_PCI_FCOE},
0044     {DCBX_PROTOCOL_ROCE, "ROCE", QED_PCI_ETH_ROCE},
0045     {DCBX_PROTOCOL_ROCE_V2, "ROCE_V2", QED_PCI_ETH_ROCE},
0046     {DCBX_PROTOCOL_ETH, "ETH", QED_PCI_ETH},
0047 };
0048 
0049 static bool qed_dcbx_app_ethtype(u32 app_info_bitmap)
0050 {
0051     return !!(QED_MFW_GET_FIELD(app_info_bitmap, DCBX_APP_SF) ==
0052           DCBX_APP_SF_ETHTYPE);
0053 }
0054 
0055 static bool qed_dcbx_ieee_app_ethtype(u32 app_info_bitmap)
0056 {
0057     u8 mfw_val = QED_MFW_GET_FIELD(app_info_bitmap, DCBX_APP_SF_IEEE);
0058 
0059     /* Old MFW */
0060     if (mfw_val == DCBX_APP_SF_IEEE_RESERVED)
0061         return qed_dcbx_app_ethtype(app_info_bitmap);
0062 
0063     return !!(mfw_val == DCBX_APP_SF_IEEE_ETHTYPE);
0064 }
0065 
0066 static bool qed_dcbx_app_port(u32 app_info_bitmap)
0067 {
0068     return !!(QED_MFW_GET_FIELD(app_info_bitmap, DCBX_APP_SF) ==
0069           DCBX_APP_SF_PORT);
0070 }
0071 
0072 static bool qed_dcbx_ieee_app_port(u32 app_info_bitmap, u8 type)
0073 {
0074     u8 mfw_val = QED_MFW_GET_FIELD(app_info_bitmap, DCBX_APP_SF_IEEE);
0075 
0076     /* Old MFW */
0077     if (mfw_val == DCBX_APP_SF_IEEE_RESERVED)
0078         return qed_dcbx_app_port(app_info_bitmap);
0079 
0080     return !!(mfw_val == type || mfw_val == DCBX_APP_SF_IEEE_TCP_UDP_PORT);
0081 }
0082 
0083 static bool qed_dcbx_default_tlv(u32 app_info_bitmap, u16 proto_id, bool ieee)
0084 {
0085     bool ethtype;
0086 
0087     if (ieee)
0088         ethtype = qed_dcbx_ieee_app_ethtype(app_info_bitmap);
0089     else
0090         ethtype = qed_dcbx_app_ethtype(app_info_bitmap);
0091 
0092     return !!(ethtype && (proto_id == QED_ETH_TYPE_DEFAULT));
0093 }
0094 
0095 static bool qed_dcbx_iscsi_tlv(u32 app_info_bitmap, u16 proto_id, bool ieee)
0096 {
0097     bool port;
0098 
0099     if (ieee)
0100         port = qed_dcbx_ieee_app_port(app_info_bitmap,
0101                           DCBX_APP_SF_IEEE_TCP_PORT);
0102     else
0103         port = qed_dcbx_app_port(app_info_bitmap);
0104 
0105     return !!(port && (proto_id == QED_TCP_PORT_ISCSI));
0106 }
0107 
0108 static bool qed_dcbx_fcoe_tlv(u32 app_info_bitmap, u16 proto_id, bool ieee)
0109 {
0110     bool ethtype;
0111 
0112     if (ieee)
0113         ethtype = qed_dcbx_ieee_app_ethtype(app_info_bitmap);
0114     else
0115         ethtype = qed_dcbx_app_ethtype(app_info_bitmap);
0116 
0117     return !!(ethtype && (proto_id == QED_ETH_TYPE_FCOE));
0118 }
0119 
0120 static bool qed_dcbx_roce_tlv(u32 app_info_bitmap, u16 proto_id, bool ieee)
0121 {
0122     bool ethtype;
0123 
0124     if (ieee)
0125         ethtype = qed_dcbx_ieee_app_ethtype(app_info_bitmap);
0126     else
0127         ethtype = qed_dcbx_app_ethtype(app_info_bitmap);
0128 
0129     return !!(ethtype && (proto_id == QED_ETH_TYPE_ROCE));
0130 }
0131 
0132 static bool qed_dcbx_roce_v2_tlv(u32 app_info_bitmap, u16 proto_id, bool ieee)
0133 {
0134     bool port;
0135 
0136     if (ieee)
0137         port = qed_dcbx_ieee_app_port(app_info_bitmap,
0138                           DCBX_APP_SF_IEEE_UDP_PORT);
0139     else
0140         port = qed_dcbx_app_port(app_info_bitmap);
0141 
0142     return !!(port && (proto_id == QED_UDP_PORT_TYPE_ROCE_V2));
0143 }
0144 
0145 static void
0146 qed_dcbx_dp_protocol(struct qed_hwfn *p_hwfn, struct qed_dcbx_results *p_data)
0147 {
0148     enum dcbx_protocol_type id;
0149     int i;
0150 
0151     DP_VERBOSE(p_hwfn, QED_MSG_DCB, "DCBX negotiated: %d\n",
0152            p_data->dcbx_enabled);
0153 
0154     for (i = 0; i < ARRAY_SIZE(qed_dcbx_app_update); i++) {
0155         id = qed_dcbx_app_update[i].id;
0156 
0157         DP_VERBOSE(p_hwfn, QED_MSG_DCB,
0158                "%s info: update %d, enable %d, prio %d, tc %d, num_tc %d\n",
0159                qed_dcbx_app_update[i].name, p_data->arr[id].update,
0160                p_data->arr[id].enable, p_data->arr[id].priority,
0161                p_data->arr[id].tc, p_hwfn->hw_info.num_active_tc);
0162     }
0163 }
0164 
0165 static void
0166 qed_dcbx_set_params(struct qed_dcbx_results *p_data,
0167             struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
0168             bool app_tlv, bool enable, u8 prio, u8 tc,
0169             enum dcbx_protocol_type type,
0170             enum qed_pci_personality personality)
0171 {
0172     /* PF update ramrod data */
0173     p_data->arr[type].enable = enable;
0174     p_data->arr[type].priority = prio;
0175     p_data->arr[type].tc = tc;
0176     if (enable)
0177         p_data->arr[type].update = UPDATE_DCB;
0178     else
0179         p_data->arr[type].update = DONT_UPDATE_DCB_DSCP;
0180 
0181     if (test_bit(QED_MF_DONT_ADD_VLAN0_TAG, &p_hwfn->cdev->mf_bits))
0182         p_data->arr[type].dont_add_vlan0 = true;
0183 
0184     /* QM reconf data */
0185     if (app_tlv && p_hwfn->hw_info.personality == personality)
0186         qed_hw_info_set_offload_tc(&p_hwfn->hw_info, tc);
0187 
0188     /* Configure dcbx vlan priority in doorbell block for roce EDPM */
0189     if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits) &&
0190         type == DCBX_PROTOCOL_ROCE) {
0191         qed_wr(p_hwfn, p_ptt, DORQ_REG_TAG1_OVRD_MODE, 1);
0192         qed_wr(p_hwfn, p_ptt, DORQ_REG_PF_PCP_BB_K2, prio << 1);
0193     }
0194 }
0195 
0196 /* Update app protocol data and hw_info fields with the TLV info */
0197 static void
0198 qed_dcbx_update_app_info(struct qed_dcbx_results *p_data,
0199              struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
0200              bool app_tlv, bool enable, u8 prio, u8 tc,
0201              enum dcbx_protocol_type type)
0202 {
0203     enum qed_pci_personality personality;
0204     enum dcbx_protocol_type id;
0205     int i;
0206 
0207     for (i = 0; i < ARRAY_SIZE(qed_dcbx_app_update); i++) {
0208         id = qed_dcbx_app_update[i].id;
0209 
0210         if (type != id)
0211             continue;
0212 
0213         personality = qed_dcbx_app_update[i].personality;
0214 
0215         qed_dcbx_set_params(p_data, p_hwfn, p_ptt, app_tlv, enable,
0216                     prio, tc, type, personality);
0217     }
0218 }
0219 
0220 static bool
0221 qed_dcbx_get_app_protocol_type(struct qed_hwfn *p_hwfn,
0222                    u32 app_prio_bitmap,
0223                    u16 id, enum dcbx_protocol_type *type, bool ieee)
0224 {
0225     if (qed_dcbx_fcoe_tlv(app_prio_bitmap, id, ieee)) {
0226         *type = DCBX_PROTOCOL_FCOE;
0227     } else if (qed_dcbx_roce_tlv(app_prio_bitmap, id, ieee)) {
0228         *type = DCBX_PROTOCOL_ROCE;
0229     } else if (qed_dcbx_iscsi_tlv(app_prio_bitmap, id, ieee)) {
0230         *type = DCBX_PROTOCOL_ISCSI;
0231     } else if (qed_dcbx_default_tlv(app_prio_bitmap, id, ieee)) {
0232         *type = DCBX_PROTOCOL_ETH;
0233     } else if (qed_dcbx_roce_v2_tlv(app_prio_bitmap, id, ieee)) {
0234         *type = DCBX_PROTOCOL_ROCE_V2;
0235     } else {
0236         *type = DCBX_MAX_PROTOCOL_TYPE;
0237         DP_VERBOSE(p_hwfn, QED_MSG_DCB,
0238                "No action required, App TLV entry = 0x%x\n",
0239                app_prio_bitmap);
0240         return false;
0241     }
0242 
0243     return true;
0244 }
0245 
0246 /* Parse app TLV's to update TC information in hw_info structure for
0247  * reconfiguring QM. Get protocol specific data for PF update ramrod command.
0248  */
0249 static int
0250 qed_dcbx_process_tlv(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
0251              struct qed_dcbx_results *p_data,
0252              struct dcbx_app_priority_entry *p_tbl,
0253              u32 pri_tc_tbl, int count, u8 dcbx_version)
0254 {
0255     enum dcbx_protocol_type type;
0256     bool enable, ieee, eth_tlv;
0257     u8 tc, priority_map;
0258     u16 protocol_id;
0259     int priority;
0260     int i;
0261 
0262     DP_VERBOSE(p_hwfn, QED_MSG_DCB, "Num APP entries = %d\n", count);
0263 
0264     ieee = (dcbx_version == DCBX_CONFIG_VERSION_IEEE);
0265     eth_tlv = false;
0266     /* Parse APP TLV */
0267     for (i = 0; i < count; i++) {
0268         protocol_id = QED_MFW_GET_FIELD(p_tbl[i].entry,
0269                         DCBX_APP_PROTOCOL_ID);
0270         priority_map = QED_MFW_GET_FIELD(p_tbl[i].entry,
0271                          DCBX_APP_PRI_MAP);
0272         priority = ffs(priority_map) - 1;
0273         if (priority < 0) {
0274             DP_ERR(p_hwfn, "Invalid priority\n");
0275             return -EINVAL;
0276         }
0277 
0278         tc = QED_DCBX_PRIO2TC(pri_tc_tbl, priority);
0279         if (qed_dcbx_get_app_protocol_type(p_hwfn, p_tbl[i].entry,
0280                            protocol_id, &type, ieee)) {
0281             /* ETH always have the enable bit reset, as it gets
0282              * vlan information per packet. For other protocols,
0283              * should be set according to the dcbx_enabled
0284              * indication, but we only got here if there was an
0285              * app tlv for the protocol, so dcbx must be enabled.
0286              */
0287             if (type == DCBX_PROTOCOL_ETH) {
0288                 enable = false;
0289                 eth_tlv = true;
0290             } else {
0291                 enable = true;
0292             }
0293 
0294             qed_dcbx_update_app_info(p_data, p_hwfn, p_ptt, true,
0295                          enable, priority, tc, type);
0296         }
0297     }
0298 
0299     /* If Eth TLV is not detected, use UFP TC as default TC */
0300     if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits) && !eth_tlv)
0301         p_data->arr[DCBX_PROTOCOL_ETH].tc = p_hwfn->ufp_info.tc;
0302 
0303     /* Update ramrod protocol data and hw_info fields
0304      * with default info when corresponding APP TLV's are not detected.
0305      * The enabled field has a different logic for ethernet as only for
0306      * ethernet dcb should disabled by default, as the information arrives
0307      * from the OS (unless an explicit app tlv was present).
0308      */
0309     tc = p_data->arr[DCBX_PROTOCOL_ETH].tc;
0310     priority = p_data->arr[DCBX_PROTOCOL_ETH].priority;
0311     for (type = 0; type < DCBX_MAX_PROTOCOL_TYPE; type++) {
0312         if (p_data->arr[type].update)
0313             continue;
0314 
0315         enable = (type == DCBX_PROTOCOL_ETH) ? false : !!dcbx_version;
0316         qed_dcbx_update_app_info(p_data, p_hwfn, p_ptt, false, enable,
0317                      priority, tc, type);
0318     }
0319 
0320     return 0;
0321 }
0322 
0323 /* Parse app TLV's to update TC information in hw_info structure for
0324  * reconfiguring QM. Get protocol specific data for PF update ramrod command.
0325  */
0326 static int
0327 qed_dcbx_process_mib_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
0328 {
0329     struct dcbx_app_priority_feature *p_app;
0330     struct dcbx_app_priority_entry *p_tbl;
0331     struct qed_dcbx_results data = { 0 };
0332     struct dcbx_ets_feature *p_ets;
0333     struct qed_hw_info *p_info;
0334     u32 pri_tc_tbl, flags;
0335     u8 dcbx_version;
0336     int num_entries;
0337     int rc = 0;
0338 
0339     flags = p_hwfn->p_dcbx_info->operational.flags;
0340     dcbx_version = QED_MFW_GET_FIELD(flags, DCBX_CONFIG_VERSION);
0341 
0342     p_app = &p_hwfn->p_dcbx_info->operational.features.app;
0343     p_tbl = p_app->app_pri_tbl;
0344 
0345     p_ets = &p_hwfn->p_dcbx_info->operational.features.ets;
0346     pri_tc_tbl = p_ets->pri_tc_tbl[0];
0347 
0348     p_info = &p_hwfn->hw_info;
0349     num_entries = QED_MFW_GET_FIELD(p_app->flags, DCBX_APP_NUM_ENTRIES);
0350 
0351     rc = qed_dcbx_process_tlv(p_hwfn, p_ptt, &data, p_tbl, pri_tc_tbl,
0352                   num_entries, dcbx_version);
0353     if (rc)
0354         return rc;
0355 
0356     p_info->num_active_tc = QED_MFW_GET_FIELD(p_ets->flags,
0357                           DCBX_ETS_MAX_TCS);
0358     p_hwfn->qm_info.ooo_tc = QED_MFW_GET_FIELD(p_ets->flags, DCBX_OOO_TC);
0359     data.pf_id = p_hwfn->rel_pf_id;
0360     data.dcbx_enabled = !!dcbx_version;
0361 
0362     qed_dcbx_dp_protocol(p_hwfn, &data);
0363 
0364     memcpy(&p_hwfn->p_dcbx_info->results, &data,
0365            sizeof(struct qed_dcbx_results));
0366 
0367     return 0;
0368 }
0369 
0370 static int
0371 qed_dcbx_copy_mib(struct qed_hwfn *p_hwfn,
0372           struct qed_ptt *p_ptt,
0373           struct qed_dcbx_mib_meta_data *p_data,
0374           enum qed_mib_read_type type)
0375 {
0376     u32 prefix_seq_num, suffix_seq_num;
0377     int read_count = 0;
0378     int rc = 0;
0379 
0380     /* The data is considered to be valid only if both sequence numbers are
0381      * the same.
0382      */
0383     do {
0384         if (type == QED_DCBX_REMOTE_LLDP_MIB) {
0385             qed_memcpy_from(p_hwfn, p_ptt, p_data->lldp_remote,
0386                     p_data->addr, p_data->size);
0387             prefix_seq_num = p_data->lldp_remote->prefix_seq_num;
0388             suffix_seq_num = p_data->lldp_remote->suffix_seq_num;
0389         } else {
0390             qed_memcpy_from(p_hwfn, p_ptt, p_data->mib,
0391                     p_data->addr, p_data->size);
0392             prefix_seq_num = p_data->mib->prefix_seq_num;
0393             suffix_seq_num = p_data->mib->suffix_seq_num;
0394         }
0395         read_count++;
0396 
0397         DP_VERBOSE(p_hwfn,
0398                QED_MSG_DCB,
0399                "mib type = %d, try count = %d prefix seq num  = %d suffix seq num = %d\n",
0400                type, read_count, prefix_seq_num, suffix_seq_num);
0401     } while ((prefix_seq_num != suffix_seq_num) &&
0402          (read_count < QED_DCBX_MAX_MIB_READ_TRY));
0403 
0404     if (read_count >= QED_DCBX_MAX_MIB_READ_TRY) {
0405         DP_ERR(p_hwfn,
0406                "MIB read err, mib type = %d, try count = %d prefix seq num = %d suffix seq num = %d\n",
0407                type, read_count, prefix_seq_num, suffix_seq_num);
0408         rc = -EIO;
0409     }
0410 
0411     return rc;
0412 }
0413 
0414 static void
0415 qed_dcbx_get_priority_info(struct qed_hwfn *p_hwfn,
0416                struct qed_dcbx_app_prio *p_prio,
0417                struct qed_dcbx_results *p_results)
0418 {
0419     u8 val;
0420 
0421     p_prio->roce = QED_DCBX_INVALID_PRIORITY;
0422     p_prio->roce_v2 = QED_DCBX_INVALID_PRIORITY;
0423     p_prio->iscsi = QED_DCBX_INVALID_PRIORITY;
0424     p_prio->fcoe = QED_DCBX_INVALID_PRIORITY;
0425 
0426     if (p_results->arr[DCBX_PROTOCOL_ROCE].update &&
0427         p_results->arr[DCBX_PROTOCOL_ROCE].enable)
0428         p_prio->roce = p_results->arr[DCBX_PROTOCOL_ROCE].priority;
0429 
0430     if (p_results->arr[DCBX_PROTOCOL_ROCE_V2].update &&
0431         p_results->arr[DCBX_PROTOCOL_ROCE_V2].enable) {
0432         val = p_results->arr[DCBX_PROTOCOL_ROCE_V2].priority;
0433         p_prio->roce_v2 = val;
0434     }
0435 
0436     if (p_results->arr[DCBX_PROTOCOL_ISCSI].update &&
0437         p_results->arr[DCBX_PROTOCOL_ISCSI].enable)
0438         p_prio->iscsi = p_results->arr[DCBX_PROTOCOL_ISCSI].priority;
0439 
0440     if (p_results->arr[DCBX_PROTOCOL_FCOE].update &&
0441         p_results->arr[DCBX_PROTOCOL_FCOE].enable)
0442         p_prio->fcoe = p_results->arr[DCBX_PROTOCOL_FCOE].priority;
0443 
0444     if (p_results->arr[DCBX_PROTOCOL_ETH].update &&
0445         p_results->arr[DCBX_PROTOCOL_ETH].enable)
0446         p_prio->eth = p_results->arr[DCBX_PROTOCOL_ETH].priority;
0447 
0448     DP_VERBOSE(p_hwfn, QED_MSG_DCB,
0449            "Priorities: iscsi %d, roce %d, roce v2 %d, fcoe %d, eth %d\n",
0450            p_prio->iscsi, p_prio->roce, p_prio->roce_v2, p_prio->fcoe,
0451            p_prio->eth);
0452 }
0453 
0454 static void
0455 qed_dcbx_get_app_data(struct qed_hwfn *p_hwfn,
0456               struct dcbx_app_priority_feature *p_app,
0457               struct dcbx_app_priority_entry *p_tbl,
0458               struct qed_dcbx_params *p_params, bool ieee)
0459 {
0460     struct qed_app_entry *entry;
0461     u8 pri_map;
0462     int i;
0463 
0464     p_params->app_willing = QED_MFW_GET_FIELD(p_app->flags,
0465                           DCBX_APP_WILLING);
0466     p_params->app_valid = QED_MFW_GET_FIELD(p_app->flags, DCBX_APP_ENABLED);
0467     p_params->app_error = QED_MFW_GET_FIELD(p_app->flags, DCBX_APP_ERROR);
0468     p_params->num_app_entries = QED_MFW_GET_FIELD(p_app->flags,
0469                               DCBX_APP_NUM_ENTRIES);
0470     for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++) {
0471         entry = &p_params->app_entry[i];
0472         if (ieee) {
0473             u8 sf_ieee;
0474             u32 val;
0475 
0476             sf_ieee = QED_MFW_GET_FIELD(p_tbl[i].entry,
0477                             DCBX_APP_SF_IEEE);
0478             switch (sf_ieee) {
0479             case DCBX_APP_SF_IEEE_RESERVED:
0480                 /* Old MFW */
0481                 val = QED_MFW_GET_FIELD(p_tbl[i].entry,
0482                             DCBX_APP_SF);
0483                 entry->sf_ieee = val ?
0484                     QED_DCBX_SF_IEEE_TCP_UDP_PORT :
0485                     QED_DCBX_SF_IEEE_ETHTYPE;
0486                 break;
0487             case DCBX_APP_SF_IEEE_ETHTYPE:
0488                 entry->sf_ieee = QED_DCBX_SF_IEEE_ETHTYPE;
0489                 break;
0490             case DCBX_APP_SF_IEEE_TCP_PORT:
0491                 entry->sf_ieee = QED_DCBX_SF_IEEE_TCP_PORT;
0492                 break;
0493             case DCBX_APP_SF_IEEE_UDP_PORT:
0494                 entry->sf_ieee = QED_DCBX_SF_IEEE_UDP_PORT;
0495                 break;
0496             case DCBX_APP_SF_IEEE_TCP_UDP_PORT:
0497                 entry->sf_ieee = QED_DCBX_SF_IEEE_TCP_UDP_PORT;
0498                 break;
0499             }
0500         } else {
0501             entry->ethtype = !(QED_MFW_GET_FIELD(p_tbl[i].entry,
0502                                  DCBX_APP_SF));
0503         }
0504 
0505         pri_map = QED_MFW_GET_FIELD(p_tbl[i].entry, DCBX_APP_PRI_MAP);
0506         entry->prio = ffs(pri_map) - 1;
0507         entry->proto_id = QED_MFW_GET_FIELD(p_tbl[i].entry,
0508                             DCBX_APP_PROTOCOL_ID);
0509         qed_dcbx_get_app_protocol_type(p_hwfn, p_tbl[i].entry,
0510                            entry->proto_id,
0511                            &entry->proto_type, ieee);
0512     }
0513 
0514     DP_VERBOSE(p_hwfn, QED_MSG_DCB,
0515            "APP params: willing %d, valid %d error = %d\n",
0516            p_params->app_willing, p_params->app_valid,
0517            p_params->app_error);
0518 }
0519 
0520 static void
0521 qed_dcbx_get_pfc_data(struct qed_hwfn *p_hwfn,
0522               u32 pfc, struct qed_dcbx_params *p_params)
0523 {
0524     u8 pfc_map;
0525 
0526     p_params->pfc.willing = QED_MFW_GET_FIELD(pfc, DCBX_PFC_WILLING);
0527     p_params->pfc.max_tc = QED_MFW_GET_FIELD(pfc, DCBX_PFC_CAPS);
0528     p_params->pfc.enabled = QED_MFW_GET_FIELD(pfc, DCBX_PFC_ENABLED);
0529     pfc_map = QED_MFW_GET_FIELD(pfc, DCBX_PFC_PRI_EN_BITMAP);
0530     p_params->pfc.prio[0] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_0);
0531     p_params->pfc.prio[1] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_1);
0532     p_params->pfc.prio[2] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_2);
0533     p_params->pfc.prio[3] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_3);
0534     p_params->pfc.prio[4] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_4);
0535     p_params->pfc.prio[5] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_5);
0536     p_params->pfc.prio[6] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_6);
0537     p_params->pfc.prio[7] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_7);
0538 
0539     DP_VERBOSE(p_hwfn, QED_MSG_DCB,
0540            "PFC params: willing %d, pfc_bitmap %u max_tc = %u enabled = %d\n",
0541            p_params->pfc.willing, pfc_map, p_params->pfc.max_tc,
0542            p_params->pfc.enabled);
0543 }
0544 
0545 static void
0546 qed_dcbx_get_ets_data(struct qed_hwfn *p_hwfn,
0547               struct dcbx_ets_feature *p_ets,
0548               struct qed_dcbx_params *p_params)
0549 {
0550     __be32 bw_map[2], tsa_map[2];
0551     u32 pri_map;
0552     int i;
0553 
0554     p_params->ets_willing = QED_MFW_GET_FIELD(p_ets->flags,
0555                           DCBX_ETS_WILLING);
0556     p_params->ets_enabled = QED_MFW_GET_FIELD(p_ets->flags,
0557                           DCBX_ETS_ENABLED);
0558     p_params->ets_cbs = QED_MFW_GET_FIELD(p_ets->flags, DCBX_ETS_CBS);
0559     p_params->max_ets_tc = QED_MFW_GET_FIELD(p_ets->flags,
0560                          DCBX_ETS_MAX_TCS);
0561     DP_VERBOSE(p_hwfn, QED_MSG_DCB,
0562            "ETS params: willing %d, enabled = %d ets_cbs %d pri_tc_tbl_0 %x max_ets_tc %d\n",
0563            p_params->ets_willing, p_params->ets_enabled,
0564            p_params->ets_cbs, p_ets->pri_tc_tbl[0],
0565            p_params->max_ets_tc);
0566 
0567     if (p_params->ets_enabled && !p_params->max_ets_tc) {
0568         p_params->max_ets_tc = QED_MAX_PFC_PRIORITIES;
0569         DP_VERBOSE(p_hwfn, QED_MSG_DCB,
0570                "ETS params: max_ets_tc is forced to %d\n",
0571         p_params->max_ets_tc);
0572     }
0573 
0574     /* 8 bit tsa and bw data corresponding to each of the 8 TC's are
0575      * encoded in a type u32 array of size 2.
0576      */
0577     cpu_to_be32_array(bw_map, p_ets->tc_bw_tbl, 2);
0578     cpu_to_be32_array(tsa_map, p_ets->tc_tsa_tbl, 2);
0579     pri_map = p_ets->pri_tc_tbl[0];
0580 
0581     for (i = 0; i < QED_MAX_PFC_PRIORITIES; i++) {
0582         p_params->ets_tc_bw_tbl[i] = ((u8 *)bw_map)[i];
0583         p_params->ets_tc_tsa_tbl[i] = ((u8 *)tsa_map)[i];
0584         p_params->ets_pri_tc_tbl[i] = QED_DCBX_PRIO2TC(pri_map, i);
0585         DP_VERBOSE(p_hwfn, QED_MSG_DCB,
0586                "elem %d  bw_tbl %x tsa_tbl %x\n",
0587                i, p_params->ets_tc_bw_tbl[i],
0588                p_params->ets_tc_tsa_tbl[i]);
0589     }
0590 }
0591 
0592 static void
0593 qed_dcbx_get_common_params(struct qed_hwfn *p_hwfn,
0594                struct dcbx_app_priority_feature *p_app,
0595                struct dcbx_app_priority_entry *p_tbl,
0596                struct dcbx_ets_feature *p_ets,
0597                u32 pfc, struct qed_dcbx_params *p_params, bool ieee)
0598 {
0599     qed_dcbx_get_app_data(p_hwfn, p_app, p_tbl, p_params, ieee);
0600     qed_dcbx_get_ets_data(p_hwfn, p_ets, p_params);
0601     qed_dcbx_get_pfc_data(p_hwfn, pfc, p_params);
0602 }
0603 
0604 static void
0605 qed_dcbx_get_local_params(struct qed_hwfn *p_hwfn, struct qed_dcbx_get *params)
0606 {
0607     struct dcbx_features *p_feat;
0608 
0609     p_feat = &p_hwfn->p_dcbx_info->local_admin.features;
0610     qed_dcbx_get_common_params(p_hwfn, &p_feat->app,
0611                    p_feat->app.app_pri_tbl, &p_feat->ets,
0612                    p_feat->pfc, &params->local.params, false);
0613     params->local.valid = true;
0614 }
0615 
0616 static void
0617 qed_dcbx_get_remote_params(struct qed_hwfn *p_hwfn, struct qed_dcbx_get *params)
0618 {
0619     struct dcbx_features *p_feat;
0620 
0621     p_feat = &p_hwfn->p_dcbx_info->remote.features;
0622     qed_dcbx_get_common_params(p_hwfn, &p_feat->app,
0623                    p_feat->app.app_pri_tbl, &p_feat->ets,
0624                    p_feat->pfc, &params->remote.params, false);
0625     params->remote.valid = true;
0626 }
0627 
0628 static void
0629 qed_dcbx_get_operational_params(struct qed_hwfn *p_hwfn,
0630                 struct qed_dcbx_get *params)
0631 {
0632     struct qed_dcbx_operational_params *p_operational;
0633     struct qed_dcbx_results *p_results;
0634     struct dcbx_features *p_feat;
0635     bool enabled, err;
0636     u32 flags;
0637     bool val;
0638 
0639     flags = p_hwfn->p_dcbx_info->operational.flags;
0640 
0641     /* If DCBx version is non zero, then negotiation
0642      * was successfuly performed
0643      */
0644     p_operational = &params->operational;
0645     enabled = !!(QED_MFW_GET_FIELD(flags, DCBX_CONFIG_VERSION) !=
0646              DCBX_CONFIG_VERSION_DISABLED);
0647     if (!enabled) {
0648         p_operational->enabled = enabled;
0649         p_operational->valid = false;
0650         DP_VERBOSE(p_hwfn, QED_MSG_DCB, "Dcbx is disabled\n");
0651         return;
0652     }
0653 
0654     p_feat = &p_hwfn->p_dcbx_info->operational.features;
0655     p_results = &p_hwfn->p_dcbx_info->results;
0656 
0657     val = !!(QED_MFW_GET_FIELD(flags, DCBX_CONFIG_VERSION) ==
0658          DCBX_CONFIG_VERSION_IEEE);
0659     p_operational->ieee = val;
0660     val = !!(QED_MFW_GET_FIELD(flags, DCBX_CONFIG_VERSION) ==
0661          DCBX_CONFIG_VERSION_CEE);
0662     p_operational->cee = val;
0663 
0664     val = !!(QED_MFW_GET_FIELD(flags, DCBX_CONFIG_VERSION) ==
0665          DCBX_CONFIG_VERSION_STATIC);
0666     p_operational->local = val;
0667 
0668     DP_VERBOSE(p_hwfn, QED_MSG_DCB,
0669            "Version support: ieee %d, cee %d, static %d\n",
0670            p_operational->ieee, p_operational->cee,
0671            p_operational->local);
0672 
0673     qed_dcbx_get_common_params(p_hwfn, &p_feat->app,
0674                    p_feat->app.app_pri_tbl, &p_feat->ets,
0675                    p_feat->pfc, &params->operational.params,
0676                    p_operational->ieee);
0677     qed_dcbx_get_priority_info(p_hwfn, &p_operational->app_prio, p_results);
0678     err = QED_MFW_GET_FIELD(p_feat->app.flags, DCBX_APP_ERROR);
0679     p_operational->err = err;
0680     p_operational->enabled = enabled;
0681     p_operational->valid = true;
0682 }
0683 
0684 static void
0685 qed_dcbx_get_local_lldp_params(struct qed_hwfn *p_hwfn,
0686                    struct qed_dcbx_get *params)
0687 {
0688     struct lldp_config_params_s *p_local;
0689 
0690     p_local = &p_hwfn->p_dcbx_info->lldp_local[LLDP_NEAREST_BRIDGE];
0691 
0692     memcpy(params->lldp_local.local_chassis_id, p_local->local_chassis_id,
0693            sizeof(p_local->local_chassis_id));
0694     memcpy(params->lldp_local.local_port_id, p_local->local_port_id,
0695            sizeof(p_local->local_port_id));
0696 }
0697 
0698 static void
0699 qed_dcbx_get_remote_lldp_params(struct qed_hwfn *p_hwfn,
0700                 struct qed_dcbx_get *params)
0701 {
0702     struct lldp_status_params_s *p_remote;
0703 
0704     p_remote = &p_hwfn->p_dcbx_info->lldp_remote[LLDP_NEAREST_BRIDGE];
0705 
0706     memcpy(params->lldp_remote.peer_chassis_id, p_remote->peer_chassis_id,
0707            sizeof(p_remote->peer_chassis_id));
0708     memcpy(params->lldp_remote.peer_port_id, p_remote->peer_port_id,
0709            sizeof(p_remote->peer_port_id));
0710 }
0711 
0712 static int
0713 qed_dcbx_get_params(struct qed_hwfn *p_hwfn, struct qed_dcbx_get *p_params,
0714             enum qed_mib_read_type type)
0715 {
0716     switch (type) {
0717     case QED_DCBX_REMOTE_MIB:
0718         qed_dcbx_get_remote_params(p_hwfn, p_params);
0719         break;
0720     case QED_DCBX_LOCAL_MIB:
0721         qed_dcbx_get_local_params(p_hwfn, p_params);
0722         break;
0723     case QED_DCBX_OPERATIONAL_MIB:
0724         qed_dcbx_get_operational_params(p_hwfn, p_params);
0725         break;
0726     case QED_DCBX_REMOTE_LLDP_MIB:
0727         qed_dcbx_get_remote_lldp_params(p_hwfn, p_params);
0728         break;
0729     case QED_DCBX_LOCAL_LLDP_MIB:
0730         qed_dcbx_get_local_lldp_params(p_hwfn, p_params);
0731         break;
0732     default:
0733         DP_ERR(p_hwfn, "MIB read err, unknown mib type %d\n", type);
0734         return -EINVAL;
0735     }
0736 
0737     return 0;
0738 }
0739 
0740 static int
0741 qed_dcbx_read_local_lldp_mib(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
0742 {
0743     struct qed_dcbx_mib_meta_data data;
0744 
0745     memset(&data, 0, sizeof(data));
0746     data.addr = p_hwfn->mcp_info->port_addr + offsetof(struct public_port,
0747                                lldp_config_params);
0748     data.lldp_local = p_hwfn->p_dcbx_info->lldp_local;
0749     data.size = sizeof(struct lldp_config_params_s);
0750     qed_memcpy_from(p_hwfn, p_ptt, data.lldp_local, data.addr, data.size);
0751 
0752     return 0;
0753 }
0754 
0755 static int
0756 qed_dcbx_read_remote_lldp_mib(struct qed_hwfn *p_hwfn,
0757                   struct qed_ptt *p_ptt,
0758                   enum qed_mib_read_type type)
0759 {
0760     struct qed_dcbx_mib_meta_data data;
0761     int rc = 0;
0762 
0763     memset(&data, 0, sizeof(data));
0764     data.addr = p_hwfn->mcp_info->port_addr + offsetof(struct public_port,
0765                                lldp_status_params);
0766     data.lldp_remote = p_hwfn->p_dcbx_info->lldp_remote;
0767     data.size = sizeof(struct lldp_status_params_s);
0768     rc = qed_dcbx_copy_mib(p_hwfn, p_ptt, &data, type);
0769 
0770     return rc;
0771 }
0772 
0773 static int
0774 qed_dcbx_read_operational_mib(struct qed_hwfn *p_hwfn,
0775                   struct qed_ptt *p_ptt,
0776                   enum qed_mib_read_type type)
0777 {
0778     struct qed_dcbx_mib_meta_data data;
0779     int rc = 0;
0780 
0781     memset(&data, 0, sizeof(data));
0782     data.addr = p_hwfn->mcp_info->port_addr +
0783             offsetof(struct public_port, operational_dcbx_mib);
0784     data.mib = &p_hwfn->p_dcbx_info->operational;
0785     data.size = sizeof(struct dcbx_mib);
0786     rc = qed_dcbx_copy_mib(p_hwfn, p_ptt, &data, type);
0787 
0788     return rc;
0789 }
0790 
0791 static int
0792 qed_dcbx_read_remote_mib(struct qed_hwfn *p_hwfn,
0793              struct qed_ptt *p_ptt, enum qed_mib_read_type type)
0794 {
0795     struct qed_dcbx_mib_meta_data data;
0796     int rc = 0;
0797 
0798     memset(&data, 0, sizeof(data));
0799     data.addr = p_hwfn->mcp_info->port_addr +
0800             offsetof(struct public_port, remote_dcbx_mib);
0801     data.mib = &p_hwfn->p_dcbx_info->remote;
0802     data.size = sizeof(struct dcbx_mib);
0803     rc = qed_dcbx_copy_mib(p_hwfn, p_ptt, &data, type);
0804 
0805     return rc;
0806 }
0807 
0808 static int
0809 qed_dcbx_read_local_mib(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
0810 {
0811     struct qed_dcbx_mib_meta_data data;
0812 
0813     memset(&data, 0, sizeof(data));
0814     data.addr = p_hwfn->mcp_info->port_addr +
0815             offsetof(struct public_port, local_admin_dcbx_mib);
0816     data.local_admin = &p_hwfn->p_dcbx_info->local_admin;
0817     data.size = sizeof(struct dcbx_local_params);
0818     qed_memcpy_from(p_hwfn, p_ptt, data.local_admin, data.addr, data.size);
0819 
0820     return 0;
0821 }
0822 
0823 static int qed_dcbx_read_mib(struct qed_hwfn *p_hwfn,
0824                  struct qed_ptt *p_ptt, enum qed_mib_read_type type)
0825 {
0826     int rc = -EINVAL;
0827 
0828     switch (type) {
0829     case QED_DCBX_OPERATIONAL_MIB:
0830         rc = qed_dcbx_read_operational_mib(p_hwfn, p_ptt, type);
0831         break;
0832     case QED_DCBX_REMOTE_MIB:
0833         rc = qed_dcbx_read_remote_mib(p_hwfn, p_ptt, type);
0834         break;
0835     case QED_DCBX_LOCAL_MIB:
0836         rc = qed_dcbx_read_local_mib(p_hwfn, p_ptt);
0837         break;
0838     case QED_DCBX_REMOTE_LLDP_MIB:
0839         rc = qed_dcbx_read_remote_lldp_mib(p_hwfn, p_ptt, type);
0840         break;
0841     case QED_DCBX_LOCAL_LLDP_MIB:
0842         rc = qed_dcbx_read_local_lldp_mib(p_hwfn, p_ptt);
0843         break;
0844     default:
0845         DP_ERR(p_hwfn, "MIB read err, unknown mib type %d\n", type);
0846     }
0847 
0848     return rc;
0849 }
0850 
0851 static void qed_dcbx_aen(struct qed_hwfn *hwfn, u32 mib_type)
0852 {
0853     struct qed_common_cb_ops *op = hwfn->cdev->protocol_ops.common;
0854     void *cookie = hwfn->cdev->ops_cookie;
0855 
0856     if (cookie && op->dcbx_aen)
0857         op->dcbx_aen(cookie, &hwfn->p_dcbx_info->get, mib_type);
0858 }
0859 
0860 /* Read updated MIB.
0861  * Reconfigure QM and invoke PF update ramrod command if operational MIB
0862  * change is detected.
0863  */
0864 int
0865 qed_dcbx_mib_update_event(struct qed_hwfn *p_hwfn,
0866               struct qed_ptt *p_ptt, enum qed_mib_read_type type)
0867 {
0868     int rc = 0;
0869 
0870     rc = qed_dcbx_read_mib(p_hwfn, p_ptt, type);
0871     if (rc)
0872         return rc;
0873 
0874     if (type == QED_DCBX_OPERATIONAL_MIB) {
0875         rc = qed_dcbx_process_mib_info(p_hwfn, p_ptt);
0876         if (!rc) {
0877             /* reconfigure tcs of QM queues according
0878              * to negotiation results
0879              */
0880             qed_qm_reconf(p_hwfn, p_ptt);
0881 
0882             /* update storm FW with negotiation results */
0883             qed_sp_pf_update(p_hwfn);
0884 
0885             /* for roce PFs, we may want to enable/disable DPM
0886              * when DCBx change occurs
0887              */
0888             if (p_hwfn->hw_info.personality ==
0889                 QED_PCI_ETH_ROCE)
0890                 qed_roce_dpm_dcbx(p_hwfn, p_ptt);
0891         }
0892     }
0893 
0894     qed_dcbx_get_params(p_hwfn, &p_hwfn->p_dcbx_info->get, type);
0895 
0896     if (type == QED_DCBX_OPERATIONAL_MIB) {
0897         struct qed_dcbx_results *p_data;
0898         u16 val;
0899 
0900         /* Configure in NIG which protocols support EDPM and should
0901          * honor PFC.
0902          */
0903         p_data = &p_hwfn->p_dcbx_info->results;
0904         val = (0x1 << p_data->arr[DCBX_PROTOCOL_ROCE].tc) |
0905               (0x1 << p_data->arr[DCBX_PROTOCOL_ROCE_V2].tc);
0906         val <<= NIG_REG_TX_EDPM_CTRL_TX_EDPM_TC_EN_SHIFT;
0907         val |= NIG_REG_TX_EDPM_CTRL_TX_EDPM_EN;
0908         qed_wr(p_hwfn, p_ptt, NIG_REG_TX_EDPM_CTRL, val);
0909     }
0910 
0911     qed_dcbx_aen(p_hwfn, type);
0912 
0913     return rc;
0914 }
0915 
0916 int qed_dcbx_info_alloc(struct qed_hwfn *p_hwfn)
0917 {
0918     p_hwfn->p_dcbx_info = kzalloc(sizeof(*p_hwfn->p_dcbx_info), GFP_KERNEL);
0919     if (!p_hwfn->p_dcbx_info)
0920         return -ENOMEM;
0921 
0922     return 0;
0923 }
0924 
0925 void qed_dcbx_info_free(struct qed_hwfn *p_hwfn)
0926 {
0927     kfree(p_hwfn->p_dcbx_info);
0928     p_hwfn->p_dcbx_info = NULL;
0929 }
0930 
0931 static void qed_dcbx_update_protocol_data(struct protocol_dcb_data *p_data,
0932                       struct qed_dcbx_results *p_src,
0933                       enum dcbx_protocol_type type)
0934 {
0935     p_data->dcb_enable_flag = p_src->arr[type].enable;
0936     p_data->dcb_priority = p_src->arr[type].priority;
0937     p_data->dcb_tc = p_src->arr[type].tc;
0938     p_data->dcb_dont_add_vlan0 = p_src->arr[type].dont_add_vlan0;
0939 }
0940 
0941 /* Set pf update ramrod command params */
0942 void qed_dcbx_set_pf_update_params(struct qed_dcbx_results *p_src,
0943                    struct pf_update_ramrod_data *p_dest)
0944 {
0945     struct protocol_dcb_data *p_dcb_data;
0946     u8 update_flag;
0947 
0948     update_flag = p_src->arr[DCBX_PROTOCOL_FCOE].update;
0949     p_dest->update_fcoe_dcb_data_mode = update_flag;
0950 
0951     update_flag = p_src->arr[DCBX_PROTOCOL_ROCE].update;
0952     p_dest->update_roce_dcb_data_mode = update_flag;
0953 
0954     update_flag = p_src->arr[DCBX_PROTOCOL_ROCE_V2].update;
0955     p_dest->update_rroce_dcb_data_mode = update_flag;
0956 
0957     update_flag = p_src->arr[DCBX_PROTOCOL_ISCSI].update;
0958     p_dest->update_iscsi_dcb_data_mode = update_flag;
0959     update_flag = p_src->arr[DCBX_PROTOCOL_ETH].update;
0960     p_dest->update_eth_dcb_data_mode = update_flag;
0961 
0962     p_dcb_data = &p_dest->fcoe_dcb_data;
0963     qed_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_FCOE);
0964     p_dcb_data = &p_dest->roce_dcb_data;
0965     qed_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_ROCE);
0966     p_dcb_data = &p_dest->rroce_dcb_data;
0967     qed_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_ROCE_V2);
0968     p_dcb_data = &p_dest->iscsi_dcb_data;
0969     qed_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_ISCSI);
0970     p_dcb_data = &p_dest->eth_dcb_data;
0971     qed_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_ETH);
0972 }
0973 
0974 u8 qed_dcbx_get_priority_tc(struct qed_hwfn *p_hwfn, u8 pri)
0975 {
0976     struct qed_dcbx_get *dcbx_info = &p_hwfn->p_dcbx_info->get;
0977 
0978     if (pri >= QED_MAX_PFC_PRIORITIES) {
0979         DP_ERR(p_hwfn, "Invalid priority %d\n", pri);
0980         return QED_DCBX_DEFAULT_TC;
0981     }
0982 
0983     if (!dcbx_info->operational.valid) {
0984         DP_VERBOSE(p_hwfn, QED_MSG_DCB,
0985                "Dcbx parameters not available\n");
0986         return QED_DCBX_DEFAULT_TC;
0987     }
0988 
0989     return dcbx_info->operational.params.ets_pri_tc_tbl[pri];
0990 }
0991 
0992 #ifdef CONFIG_DCB
0993 static int qed_dcbx_query_params(struct qed_hwfn *p_hwfn,
0994                  struct qed_dcbx_get *p_get,
0995                  enum qed_mib_read_type type)
0996 {
0997     struct qed_ptt *p_ptt;
0998     int rc;
0999 
1000     if (IS_VF(p_hwfn->cdev))
1001         return -EINVAL;
1002 
1003     p_ptt = qed_ptt_acquire(p_hwfn);
1004     if (!p_ptt)
1005         return -EBUSY;
1006 
1007     rc = qed_dcbx_read_mib(p_hwfn, p_ptt, type);
1008     if (rc)
1009         goto out;
1010 
1011     rc = qed_dcbx_get_params(p_hwfn, p_get, type);
1012 
1013 out:
1014     qed_ptt_release(p_hwfn, p_ptt);
1015     return rc;
1016 }
1017 
1018 static void
1019 qed_dcbx_set_pfc_data(struct qed_hwfn *p_hwfn,
1020               u32 *pfc, struct qed_dcbx_params *p_params)
1021 {
1022     u8 pfc_map = 0;
1023     int i;
1024 
1025     *pfc &= ~DCBX_PFC_ERROR_MASK;
1026 
1027     if (p_params->pfc.willing)
1028         *pfc |= DCBX_PFC_WILLING_MASK;
1029     else
1030         *pfc &= ~DCBX_PFC_WILLING_MASK;
1031 
1032     if (p_params->pfc.enabled)
1033         *pfc |= DCBX_PFC_ENABLED_MASK;
1034     else
1035         *pfc &= ~DCBX_PFC_ENABLED_MASK;
1036 
1037     *pfc &= ~DCBX_PFC_CAPS_MASK;
1038     *pfc |= (u32)p_params->pfc.max_tc << DCBX_PFC_CAPS_SHIFT;
1039 
1040     for (i = 0; i < QED_MAX_PFC_PRIORITIES; i++)
1041         if (p_params->pfc.prio[i])
1042             pfc_map |= BIT(i);
1043 
1044     *pfc &= ~DCBX_PFC_PRI_EN_BITMAP_MASK;
1045     *pfc |= (pfc_map << DCBX_PFC_PRI_EN_BITMAP_SHIFT);
1046 
1047     DP_VERBOSE(p_hwfn, QED_MSG_DCB, "pfc = 0x%x\n", *pfc);
1048 }
1049 
1050 static void
1051 qed_dcbx_set_ets_data(struct qed_hwfn *p_hwfn,
1052               struct dcbx_ets_feature *p_ets,
1053               struct qed_dcbx_params *p_params)
1054 {
1055     __be32 bw_map[2], tsa_map[2];
1056     u32 val;
1057     int i;
1058 
1059     if (p_params->ets_willing)
1060         p_ets->flags |= DCBX_ETS_WILLING_MASK;
1061     else
1062         p_ets->flags &= ~DCBX_ETS_WILLING_MASK;
1063 
1064     if (p_params->ets_cbs)
1065         p_ets->flags |= DCBX_ETS_CBS_MASK;
1066     else
1067         p_ets->flags &= ~DCBX_ETS_CBS_MASK;
1068 
1069     if (p_params->ets_enabled)
1070         p_ets->flags |= DCBX_ETS_ENABLED_MASK;
1071     else
1072         p_ets->flags &= ~DCBX_ETS_ENABLED_MASK;
1073 
1074     p_ets->flags &= ~DCBX_ETS_MAX_TCS_MASK;
1075     p_ets->flags |= (u32)p_params->max_ets_tc << DCBX_ETS_MAX_TCS_SHIFT;
1076 
1077     p_ets->pri_tc_tbl[0] = 0;
1078 
1079     for (i = 0; i < QED_MAX_PFC_PRIORITIES; i++) {
1080         ((u8 *)bw_map)[i] = p_params->ets_tc_bw_tbl[i];
1081         ((u8 *)tsa_map)[i] = p_params->ets_tc_tsa_tbl[i];
1082 
1083         /* Copy the priority value to the corresponding 4 bits in the
1084          * traffic class table.
1085          */
1086         val = (((u32)p_params->ets_pri_tc_tbl[i]) << ((7 - i) * 4));
1087         p_ets->pri_tc_tbl[0] |= val;
1088     }
1089 
1090     be32_to_cpu_array(p_ets->tc_bw_tbl, bw_map, 2);
1091     be32_to_cpu_array(p_ets->tc_tsa_tbl, tsa_map, 2);
1092 }
1093 
1094 static void
1095 qed_dcbx_set_app_data(struct qed_hwfn *p_hwfn,
1096               struct dcbx_app_priority_feature *p_app,
1097               struct qed_dcbx_params *p_params, bool ieee)
1098 {
1099     u32 *entry;
1100     int i;
1101 
1102     if (p_params->app_willing)
1103         p_app->flags |= DCBX_APP_WILLING_MASK;
1104     else
1105         p_app->flags &= ~DCBX_APP_WILLING_MASK;
1106 
1107     if (p_params->app_valid)
1108         p_app->flags |= DCBX_APP_ENABLED_MASK;
1109     else
1110         p_app->flags &= ~DCBX_APP_ENABLED_MASK;
1111 
1112     p_app->flags &= ~DCBX_APP_NUM_ENTRIES_MASK;
1113     p_app->flags |= (u32)p_params->num_app_entries <<
1114         DCBX_APP_NUM_ENTRIES_SHIFT;
1115 
1116     for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++) {
1117         entry = &p_app->app_pri_tbl[i].entry;
1118         *entry = 0;
1119         if (ieee) {
1120             *entry &= ~(DCBX_APP_SF_IEEE_MASK | DCBX_APP_SF_MASK);
1121             switch (p_params->app_entry[i].sf_ieee) {
1122             case QED_DCBX_SF_IEEE_ETHTYPE:
1123                 *entry |= ((u32)DCBX_APP_SF_IEEE_ETHTYPE <<
1124                        DCBX_APP_SF_IEEE_SHIFT);
1125                 *entry |= ((u32)DCBX_APP_SF_ETHTYPE <<
1126                        DCBX_APP_SF_SHIFT);
1127                 break;
1128             case QED_DCBX_SF_IEEE_TCP_PORT:
1129                 *entry |= ((u32)DCBX_APP_SF_IEEE_TCP_PORT <<
1130                        DCBX_APP_SF_IEEE_SHIFT);
1131                 *entry |= ((u32)DCBX_APP_SF_PORT <<
1132                        DCBX_APP_SF_SHIFT);
1133                 break;
1134             case QED_DCBX_SF_IEEE_UDP_PORT:
1135                 *entry |= ((u32)DCBX_APP_SF_IEEE_UDP_PORT <<
1136                        DCBX_APP_SF_IEEE_SHIFT);
1137                 *entry |= ((u32)DCBX_APP_SF_PORT <<
1138                        DCBX_APP_SF_SHIFT);
1139                 break;
1140             case QED_DCBX_SF_IEEE_TCP_UDP_PORT:
1141                 *entry |= ((u32)DCBX_APP_SF_IEEE_TCP_UDP_PORT <<
1142                        DCBX_APP_SF_IEEE_SHIFT);
1143                 *entry |= ((u32)DCBX_APP_SF_PORT <<
1144                        DCBX_APP_SF_SHIFT);
1145                 break;
1146             }
1147         } else {
1148             *entry &= ~DCBX_APP_SF_MASK;
1149             if (p_params->app_entry[i].ethtype)
1150                 *entry |= ((u32)DCBX_APP_SF_ETHTYPE <<
1151                        DCBX_APP_SF_SHIFT);
1152             else
1153                 *entry |= ((u32)DCBX_APP_SF_PORT <<
1154                        DCBX_APP_SF_SHIFT);
1155         }
1156 
1157         *entry &= ~DCBX_APP_PROTOCOL_ID_MASK;
1158         *entry |= ((u32)p_params->app_entry[i].proto_id <<
1159                DCBX_APP_PROTOCOL_ID_SHIFT);
1160         *entry &= ~DCBX_APP_PRI_MAP_MASK;
1161         *entry |= ((u32)(p_params->app_entry[i].prio) <<
1162                DCBX_APP_PRI_MAP_SHIFT);
1163     }
1164 }
1165 
1166 static void
1167 qed_dcbx_set_local_params(struct qed_hwfn *p_hwfn,
1168               struct dcbx_local_params *local_admin,
1169               struct qed_dcbx_set *params)
1170 {
1171     bool ieee = false;
1172 
1173     local_admin->flags = 0;
1174     memcpy(&local_admin->features,
1175            &p_hwfn->p_dcbx_info->operational.features,
1176            sizeof(local_admin->features));
1177 
1178     if (params->enabled) {
1179         local_admin->config = params->ver_num;
1180         ieee = !!(params->ver_num & DCBX_CONFIG_VERSION_IEEE);
1181     } else {
1182         local_admin->config = DCBX_CONFIG_VERSION_DISABLED;
1183     }
1184 
1185     DP_VERBOSE(p_hwfn, QED_MSG_DCB, "Dcbx version = %d\n",
1186            local_admin->config);
1187 
1188     if (params->override_flags & QED_DCBX_OVERRIDE_PFC_CFG)
1189         qed_dcbx_set_pfc_data(p_hwfn, &local_admin->features.pfc,
1190                       &params->config.params);
1191 
1192     if (params->override_flags & QED_DCBX_OVERRIDE_ETS_CFG)
1193         qed_dcbx_set_ets_data(p_hwfn, &local_admin->features.ets,
1194                       &params->config.params);
1195 
1196     if (params->override_flags & QED_DCBX_OVERRIDE_APP_CFG)
1197         qed_dcbx_set_app_data(p_hwfn, &local_admin->features.app,
1198                       &params->config.params, ieee);
1199 }
1200 
1201 int qed_dcbx_config_params(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
1202                struct qed_dcbx_set *params, bool hw_commit)
1203 {
1204     struct dcbx_local_params local_admin;
1205     struct qed_dcbx_mib_meta_data data;
1206     u32 resp = 0, param = 0;
1207     int rc = 0;
1208 
1209     if (!hw_commit) {
1210         memcpy(&p_hwfn->p_dcbx_info->set, params,
1211                sizeof(struct qed_dcbx_set));
1212         return 0;
1213     }
1214 
1215     /* clear set-parmas cache */
1216     memset(&p_hwfn->p_dcbx_info->set, 0, sizeof(p_hwfn->p_dcbx_info->set));
1217 
1218     memset(&local_admin, 0, sizeof(local_admin));
1219     qed_dcbx_set_local_params(p_hwfn, &local_admin, params);
1220 
1221     data.addr = p_hwfn->mcp_info->port_addr +
1222         offsetof(struct public_port, local_admin_dcbx_mib);
1223     data.local_admin = &local_admin;
1224     data.size = sizeof(struct dcbx_local_params);
1225     qed_memcpy_to(p_hwfn, p_ptt, data.addr, data.local_admin, data.size);
1226 
1227     rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_SET_DCBX,
1228              1 << DRV_MB_PARAM_LLDP_SEND_SHIFT, &resp, &param);
1229     if (rc)
1230         DP_NOTICE(p_hwfn, "Failed to send DCBX update request\n");
1231 
1232     return rc;
1233 }
1234 
1235 int qed_dcbx_get_config_params(struct qed_hwfn *p_hwfn,
1236                    struct qed_dcbx_set *params)
1237 {
1238     struct qed_dcbx_get *dcbx_info;
1239     int rc;
1240 
1241     if (p_hwfn->p_dcbx_info->set.config.valid) {
1242         memcpy(params, &p_hwfn->p_dcbx_info->set,
1243                sizeof(struct qed_dcbx_set));
1244         return 0;
1245     }
1246 
1247     dcbx_info = kzalloc(sizeof(*dcbx_info), GFP_KERNEL);
1248     if (!dcbx_info)
1249         return -ENOMEM;
1250 
1251     rc = qed_dcbx_query_params(p_hwfn, dcbx_info, QED_DCBX_OPERATIONAL_MIB);
1252     if (rc) {
1253         kfree(dcbx_info);
1254         return rc;
1255     }
1256 
1257     p_hwfn->p_dcbx_info->set.override_flags = 0;
1258     p_hwfn->p_dcbx_info->set.ver_num = DCBX_CONFIG_VERSION_DISABLED;
1259     if (dcbx_info->operational.cee)
1260         p_hwfn->p_dcbx_info->set.ver_num |= DCBX_CONFIG_VERSION_CEE;
1261     if (dcbx_info->operational.ieee)
1262         p_hwfn->p_dcbx_info->set.ver_num |= DCBX_CONFIG_VERSION_IEEE;
1263     if (dcbx_info->operational.local)
1264         p_hwfn->p_dcbx_info->set.ver_num |= DCBX_CONFIG_VERSION_STATIC;
1265 
1266     p_hwfn->p_dcbx_info->set.enabled = dcbx_info->operational.enabled;
1267     BUILD_BUG_ON(sizeof(dcbx_info->operational.params) !=
1268              sizeof(p_hwfn->p_dcbx_info->set.config.params));
1269     memcpy(&p_hwfn->p_dcbx_info->set.config.params,
1270            &dcbx_info->operational.params,
1271            sizeof(p_hwfn->p_dcbx_info->set.config.params));
1272     p_hwfn->p_dcbx_info->set.config.valid = true;
1273 
1274     memcpy(params, &p_hwfn->p_dcbx_info->set, sizeof(struct qed_dcbx_set));
1275 
1276     kfree(dcbx_info);
1277 
1278     return 0;
1279 }
1280 
1281 static struct qed_dcbx_get *qed_dcbnl_get_dcbx(struct qed_hwfn *hwfn,
1282                            enum qed_mib_read_type type)
1283 {
1284     struct qed_dcbx_get *dcbx_info;
1285 
1286     dcbx_info = kzalloc(sizeof(*dcbx_info), GFP_ATOMIC);
1287     if (!dcbx_info)
1288         return NULL;
1289 
1290     if (qed_dcbx_query_params(hwfn, dcbx_info, type)) {
1291         kfree(dcbx_info);
1292         return NULL;
1293     }
1294 
1295     if ((type == QED_DCBX_OPERATIONAL_MIB) &&
1296         !dcbx_info->operational.enabled) {
1297         DP_INFO(hwfn, "DCBX is not enabled/operational\n");
1298         kfree(dcbx_info);
1299         return NULL;
1300     }
1301 
1302     return dcbx_info;
1303 }
1304 
1305 static u8 qed_dcbnl_getstate(struct qed_dev *cdev)
1306 {
1307     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1308     struct qed_dcbx_get *dcbx_info;
1309     bool enabled;
1310 
1311     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_OPERATIONAL_MIB);
1312     if (!dcbx_info)
1313         return 0;
1314 
1315     enabled = dcbx_info->operational.enabled;
1316     DP_VERBOSE(hwfn, QED_MSG_DCB, "DCB state = %d\n", enabled);
1317     kfree(dcbx_info);
1318 
1319     return enabled;
1320 }
1321 
1322 static u8 qed_dcbnl_setstate(struct qed_dev *cdev, u8 state)
1323 {
1324     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1325     struct qed_dcbx_set dcbx_set;
1326     struct qed_ptt *ptt;
1327     int rc;
1328 
1329     DP_VERBOSE(hwfn, QED_MSG_DCB, "DCB state = %d\n", state);
1330 
1331     memset(&dcbx_set, 0, sizeof(dcbx_set));
1332     rc = qed_dcbx_get_config_params(hwfn, &dcbx_set);
1333     if (rc)
1334         return 1;
1335 
1336     dcbx_set.enabled = !!state;
1337 
1338     ptt = qed_ptt_acquire(hwfn);
1339     if (!ptt)
1340         return 1;
1341 
1342     rc = qed_dcbx_config_params(hwfn, ptt, &dcbx_set, 0);
1343 
1344     qed_ptt_release(hwfn, ptt);
1345 
1346     return rc ? 1 : 0;
1347 }
1348 
1349 static void qed_dcbnl_getpgtccfgtx(struct qed_dev *cdev, int tc, u8 *prio_type,
1350                    u8 *pgid, u8 *bw_pct, u8 *up_map)
1351 {
1352     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1353     struct qed_dcbx_get *dcbx_info;
1354 
1355     DP_VERBOSE(hwfn, QED_MSG_DCB, "tc = %d\n", tc);
1356     *prio_type = *pgid = *bw_pct = *up_map = 0;
1357     if (tc < 0 || tc >= QED_MAX_PFC_PRIORITIES) {
1358         DP_INFO(hwfn, "Invalid tc %d\n", tc);
1359         return;
1360     }
1361 
1362     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_OPERATIONAL_MIB);
1363     if (!dcbx_info)
1364         return;
1365 
1366     *pgid = dcbx_info->operational.params.ets_pri_tc_tbl[tc];
1367     kfree(dcbx_info);
1368 }
1369 
1370 static void qed_dcbnl_getpgbwgcfgtx(struct qed_dev *cdev, int pgid, u8 *bw_pct)
1371 {
1372     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1373     struct qed_dcbx_get *dcbx_info;
1374 
1375     *bw_pct = 0;
1376     DP_VERBOSE(hwfn, QED_MSG_DCB, "pgid = %d\n", pgid);
1377     if (pgid < 0 || pgid >= QED_MAX_PFC_PRIORITIES) {
1378         DP_INFO(hwfn, "Invalid pgid %d\n", pgid);
1379         return;
1380     }
1381 
1382     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_OPERATIONAL_MIB);
1383     if (!dcbx_info)
1384         return;
1385 
1386     *bw_pct = dcbx_info->operational.params.ets_tc_bw_tbl[pgid];
1387     DP_VERBOSE(hwfn, QED_MSG_DCB, "bw_pct = %d\n", *bw_pct);
1388     kfree(dcbx_info);
1389 }
1390 
1391 static void qed_dcbnl_getpgtccfgrx(struct qed_dev *cdev, int tc, u8 *prio,
1392                    u8 *bwg_id, u8 *bw_pct, u8 *up_map)
1393 {
1394     DP_INFO(QED_LEADING_HWFN(cdev), "Rx ETS is not supported\n");
1395     *prio = *bwg_id = *bw_pct = *up_map = 0;
1396 }
1397 
1398 static void qed_dcbnl_getpgbwgcfgrx(struct qed_dev *cdev,
1399                     int bwg_id, u8 *bw_pct)
1400 {
1401     DP_INFO(QED_LEADING_HWFN(cdev), "Rx ETS is not supported\n");
1402     *bw_pct = 0;
1403 }
1404 
1405 static void qed_dcbnl_getpfccfg(struct qed_dev *cdev,
1406                 int priority, u8 *setting)
1407 {
1408     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1409     struct qed_dcbx_get *dcbx_info;
1410 
1411     DP_VERBOSE(hwfn, QED_MSG_DCB, "priority = %d\n", priority);
1412     if (priority < 0 || priority >= QED_MAX_PFC_PRIORITIES) {
1413         DP_INFO(hwfn, "Invalid priority %d\n", priority);
1414         return;
1415     }
1416 
1417     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_OPERATIONAL_MIB);
1418     if (!dcbx_info)
1419         return;
1420 
1421     *setting = dcbx_info->operational.params.pfc.prio[priority];
1422     DP_VERBOSE(hwfn, QED_MSG_DCB, "setting = %d\n", *setting);
1423     kfree(dcbx_info);
1424 }
1425 
1426 static void qed_dcbnl_setpfccfg(struct qed_dev *cdev, int priority, u8 setting)
1427 {
1428     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1429     struct qed_dcbx_set dcbx_set;
1430     struct qed_ptt *ptt;
1431     int rc;
1432 
1433     DP_VERBOSE(hwfn, QED_MSG_DCB, "priority = %d setting = %d\n",
1434            priority, setting);
1435     if (priority < 0 || priority >= QED_MAX_PFC_PRIORITIES) {
1436         DP_INFO(hwfn, "Invalid priority %d\n", priority);
1437         return;
1438     }
1439 
1440     memset(&dcbx_set, 0, sizeof(dcbx_set));
1441     rc = qed_dcbx_get_config_params(hwfn, &dcbx_set);
1442     if (rc)
1443         return;
1444 
1445     dcbx_set.override_flags |= QED_DCBX_OVERRIDE_PFC_CFG;
1446     dcbx_set.config.params.pfc.prio[priority] = !!setting;
1447 
1448     ptt = qed_ptt_acquire(hwfn);
1449     if (!ptt)
1450         return;
1451 
1452     rc = qed_dcbx_config_params(hwfn, ptt, &dcbx_set, 0);
1453 
1454     qed_ptt_release(hwfn, ptt);
1455 }
1456 
1457 static u8 qed_dcbnl_getcap(struct qed_dev *cdev, int capid, u8 *cap)
1458 {
1459     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1460     struct qed_dcbx_get *dcbx_info;
1461     int rc = 0;
1462 
1463     DP_VERBOSE(hwfn, QED_MSG_DCB, "capid = %d\n", capid);
1464     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_OPERATIONAL_MIB);
1465     if (!dcbx_info)
1466         return 1;
1467 
1468     switch (capid) {
1469     case DCB_CAP_ATTR_PG:
1470     case DCB_CAP_ATTR_PFC:
1471     case DCB_CAP_ATTR_UP2TC:
1472     case DCB_CAP_ATTR_GSP:
1473         *cap = true;
1474         break;
1475     case DCB_CAP_ATTR_PG_TCS:
1476     case DCB_CAP_ATTR_PFC_TCS:
1477         *cap = 0x80;
1478         break;
1479     case DCB_CAP_ATTR_DCBX:
1480         *cap = (DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_VER_IEEE |
1481             DCB_CAP_DCBX_STATIC);
1482         break;
1483     default:
1484         *cap = false;
1485         rc = 1;
1486     }
1487 
1488     DP_VERBOSE(hwfn, QED_MSG_DCB, "id = %d caps = %d\n", capid, *cap);
1489     kfree(dcbx_info);
1490 
1491     return rc;
1492 }
1493 
1494 static int qed_dcbnl_getnumtcs(struct qed_dev *cdev, int tcid, u8 *num)
1495 {
1496     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1497     struct qed_dcbx_get *dcbx_info;
1498     int rc = 0;
1499 
1500     DP_VERBOSE(hwfn, QED_MSG_DCB, "tcid = %d\n", tcid);
1501     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_OPERATIONAL_MIB);
1502     if (!dcbx_info)
1503         return -EINVAL;
1504 
1505     switch (tcid) {
1506     case DCB_NUMTCS_ATTR_PG:
1507         *num = dcbx_info->operational.params.max_ets_tc;
1508         break;
1509     case DCB_NUMTCS_ATTR_PFC:
1510         *num = dcbx_info->operational.params.pfc.max_tc;
1511         break;
1512     default:
1513         rc = -EINVAL;
1514     }
1515 
1516     kfree(dcbx_info);
1517     DP_VERBOSE(hwfn, QED_MSG_DCB, "numtcs = %d\n", *num);
1518 
1519     return rc;
1520 }
1521 
1522 static u8 qed_dcbnl_getpfcstate(struct qed_dev *cdev)
1523 {
1524     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1525     struct qed_dcbx_get *dcbx_info;
1526     bool enabled;
1527 
1528     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_OPERATIONAL_MIB);
1529     if (!dcbx_info)
1530         return 0;
1531 
1532     enabled = dcbx_info->operational.params.pfc.enabled;
1533     DP_VERBOSE(hwfn, QED_MSG_DCB, "pfc state = %d\n", enabled);
1534     kfree(dcbx_info);
1535 
1536     return enabled;
1537 }
1538 
1539 static u8 qed_dcbnl_getdcbx(struct qed_dev *cdev)
1540 {
1541     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1542     struct qed_dcbx_get *dcbx_info;
1543     u8 mode = 0;
1544 
1545     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_OPERATIONAL_MIB);
1546     if (!dcbx_info)
1547         return 0;
1548 
1549     if (dcbx_info->operational.ieee)
1550         mode |= DCB_CAP_DCBX_VER_IEEE;
1551     if (dcbx_info->operational.cee)
1552         mode |= DCB_CAP_DCBX_VER_CEE;
1553     if (dcbx_info->operational.local)
1554         mode |= DCB_CAP_DCBX_STATIC;
1555 
1556     DP_VERBOSE(hwfn, QED_MSG_DCB, "dcb mode = %d\n", mode);
1557     kfree(dcbx_info);
1558 
1559     return mode;
1560 }
1561 
1562 static void qed_dcbnl_setpgtccfgtx(struct qed_dev *cdev,
1563                    int tc,
1564                    u8 pri_type, u8 pgid, u8 bw_pct, u8 up_map)
1565 {
1566     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1567     struct qed_dcbx_set dcbx_set;
1568     struct qed_ptt *ptt;
1569     int rc;
1570 
1571     DP_VERBOSE(hwfn, QED_MSG_DCB,
1572            "tc = %d pri_type = %d pgid = %d bw_pct = %d up_map = %d\n",
1573            tc, pri_type, pgid, bw_pct, up_map);
1574 
1575     if (tc < 0 || tc >= QED_MAX_PFC_PRIORITIES) {
1576         DP_INFO(hwfn, "Invalid tc %d\n", tc);
1577         return;
1578     }
1579 
1580     memset(&dcbx_set, 0, sizeof(dcbx_set));
1581     rc = qed_dcbx_get_config_params(hwfn, &dcbx_set);
1582     if (rc)
1583         return;
1584 
1585     dcbx_set.override_flags |= QED_DCBX_OVERRIDE_ETS_CFG;
1586     dcbx_set.config.params.ets_pri_tc_tbl[tc] = pgid;
1587 
1588     ptt = qed_ptt_acquire(hwfn);
1589     if (!ptt)
1590         return;
1591 
1592     rc = qed_dcbx_config_params(hwfn, ptt, &dcbx_set, 0);
1593 
1594     qed_ptt_release(hwfn, ptt);
1595 }
1596 
1597 static void qed_dcbnl_setpgtccfgrx(struct qed_dev *cdev, int prio,
1598                    u8 pri_type, u8 pgid, u8 bw_pct, u8 up_map)
1599 {
1600     DP_INFO(QED_LEADING_HWFN(cdev), "Rx ETS is not supported\n");
1601 }
1602 
1603 static void qed_dcbnl_setpgbwgcfgtx(struct qed_dev *cdev, int pgid, u8 bw_pct)
1604 {
1605     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1606     struct qed_dcbx_set dcbx_set;
1607     struct qed_ptt *ptt;
1608     int rc;
1609 
1610     DP_VERBOSE(hwfn, QED_MSG_DCB, "pgid = %d bw_pct = %d\n", pgid, bw_pct);
1611     if (pgid < 0 || pgid >= QED_MAX_PFC_PRIORITIES) {
1612         DP_INFO(hwfn, "Invalid pgid %d\n", pgid);
1613         return;
1614     }
1615 
1616     memset(&dcbx_set, 0, sizeof(dcbx_set));
1617     rc = qed_dcbx_get_config_params(hwfn, &dcbx_set);
1618     if (rc)
1619         return;
1620 
1621     dcbx_set.override_flags |= QED_DCBX_OVERRIDE_ETS_CFG;
1622     dcbx_set.config.params.ets_tc_bw_tbl[pgid] = bw_pct;
1623 
1624     ptt = qed_ptt_acquire(hwfn);
1625     if (!ptt)
1626         return;
1627 
1628     rc = qed_dcbx_config_params(hwfn, ptt, &dcbx_set, 0);
1629 
1630     qed_ptt_release(hwfn, ptt);
1631 }
1632 
1633 static void qed_dcbnl_setpgbwgcfgrx(struct qed_dev *cdev, int pgid, u8 bw_pct)
1634 {
1635     DP_INFO(QED_LEADING_HWFN(cdev), "Rx ETS is not supported\n");
1636 }
1637 
1638 static u8 qed_dcbnl_setall(struct qed_dev *cdev)
1639 {
1640     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1641     struct qed_dcbx_set dcbx_set;
1642     struct qed_ptt *ptt;
1643     int rc;
1644 
1645     memset(&dcbx_set, 0, sizeof(dcbx_set));
1646     rc = qed_dcbx_get_config_params(hwfn, &dcbx_set);
1647     if (rc)
1648         return 1;
1649 
1650     ptt = qed_ptt_acquire(hwfn);
1651     if (!ptt)
1652         return 1;
1653 
1654     rc = qed_dcbx_config_params(hwfn, ptt, &dcbx_set, 1);
1655 
1656     qed_ptt_release(hwfn, ptt);
1657 
1658     return rc;
1659 }
1660 
1661 static int qed_dcbnl_setnumtcs(struct qed_dev *cdev, int tcid, u8 num)
1662 {
1663     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1664     struct qed_dcbx_set dcbx_set;
1665     struct qed_ptt *ptt;
1666     int rc;
1667 
1668     DP_VERBOSE(hwfn, QED_MSG_DCB, "tcid = %d num = %d\n", tcid, num);
1669     memset(&dcbx_set, 0, sizeof(dcbx_set));
1670     rc = qed_dcbx_get_config_params(hwfn, &dcbx_set);
1671     if (rc)
1672         return 1;
1673 
1674     switch (tcid) {
1675     case DCB_NUMTCS_ATTR_PG:
1676         dcbx_set.override_flags |= QED_DCBX_OVERRIDE_ETS_CFG;
1677         dcbx_set.config.params.max_ets_tc = num;
1678         break;
1679     case DCB_NUMTCS_ATTR_PFC:
1680         dcbx_set.override_flags |= QED_DCBX_OVERRIDE_PFC_CFG;
1681         dcbx_set.config.params.pfc.max_tc = num;
1682         break;
1683     default:
1684         DP_INFO(hwfn, "Invalid tcid %d\n", tcid);
1685         return -EINVAL;
1686     }
1687 
1688     ptt = qed_ptt_acquire(hwfn);
1689     if (!ptt)
1690         return -EINVAL;
1691 
1692     rc = qed_dcbx_config_params(hwfn, ptt, &dcbx_set, 0);
1693 
1694     qed_ptt_release(hwfn, ptt);
1695 
1696     return 0;
1697 }
1698 
1699 static void qed_dcbnl_setpfcstate(struct qed_dev *cdev, u8 state)
1700 {
1701     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1702     struct qed_dcbx_set dcbx_set;
1703     struct qed_ptt *ptt;
1704     int rc;
1705 
1706     DP_VERBOSE(hwfn, QED_MSG_DCB, "new state = %d\n", state);
1707 
1708     memset(&dcbx_set, 0, sizeof(dcbx_set));
1709     rc = qed_dcbx_get_config_params(hwfn, &dcbx_set);
1710     if (rc)
1711         return;
1712 
1713     dcbx_set.override_flags |= QED_DCBX_OVERRIDE_PFC_CFG;
1714     dcbx_set.config.params.pfc.enabled = !!state;
1715 
1716     ptt = qed_ptt_acquire(hwfn);
1717     if (!ptt)
1718         return;
1719 
1720     rc = qed_dcbx_config_params(hwfn, ptt, &dcbx_set, 0);
1721 
1722     qed_ptt_release(hwfn, ptt);
1723 }
1724 
1725 static int qed_dcbnl_getapp(struct qed_dev *cdev, u8 idtype, u16 idval)
1726 {
1727     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1728     struct qed_dcbx_get *dcbx_info;
1729     struct qed_app_entry *entry;
1730     bool ethtype;
1731     u8 prio = 0;
1732     int i;
1733 
1734     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_OPERATIONAL_MIB);
1735     if (!dcbx_info)
1736         return -EINVAL;
1737 
1738     ethtype = !!(idtype == DCB_APP_IDTYPE_ETHTYPE);
1739     for (i = 0; i < QED_DCBX_MAX_APP_PROTOCOL; i++) {
1740         entry = &dcbx_info->operational.params.app_entry[i];
1741         if ((entry->ethtype == ethtype) && (entry->proto_id == idval)) {
1742             prio = entry->prio;
1743             break;
1744         }
1745     }
1746 
1747     if (i == QED_DCBX_MAX_APP_PROTOCOL) {
1748         DP_ERR(cdev, "App entry (%d, %d) not found\n", idtype, idval);
1749         kfree(dcbx_info);
1750         return -EINVAL;
1751     }
1752 
1753     kfree(dcbx_info);
1754 
1755     return prio;
1756 }
1757 
1758 static int qed_dcbnl_setapp(struct qed_dev *cdev,
1759                 u8 idtype, u16 idval, u8 pri_map)
1760 {
1761     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1762     struct qed_dcbx_set dcbx_set;
1763     struct qed_app_entry *entry;
1764     struct qed_ptt *ptt;
1765     bool ethtype;
1766     int rc, i;
1767 
1768     memset(&dcbx_set, 0, sizeof(dcbx_set));
1769     rc = qed_dcbx_get_config_params(hwfn, &dcbx_set);
1770     if (rc)
1771         return -EINVAL;
1772 
1773     ethtype = !!(idtype == DCB_APP_IDTYPE_ETHTYPE);
1774     for (i = 0; i < QED_DCBX_MAX_APP_PROTOCOL; i++) {
1775         entry = &dcbx_set.config.params.app_entry[i];
1776         if ((entry->ethtype == ethtype) && (entry->proto_id == idval))
1777             break;
1778         /* First empty slot */
1779         if (!entry->proto_id) {
1780             dcbx_set.config.params.num_app_entries++;
1781             break;
1782         }
1783     }
1784 
1785     if (i == QED_DCBX_MAX_APP_PROTOCOL) {
1786         DP_ERR(cdev, "App table is full\n");
1787         return -EBUSY;
1788     }
1789 
1790     dcbx_set.override_flags |= QED_DCBX_OVERRIDE_APP_CFG;
1791     dcbx_set.config.params.app_entry[i].ethtype = ethtype;
1792     dcbx_set.config.params.app_entry[i].proto_id = idval;
1793     dcbx_set.config.params.app_entry[i].prio = pri_map;
1794 
1795     ptt = qed_ptt_acquire(hwfn);
1796     if (!ptt)
1797         return -EBUSY;
1798 
1799     rc = qed_dcbx_config_params(hwfn, ptt, &dcbx_set, 0);
1800 
1801     qed_ptt_release(hwfn, ptt);
1802 
1803     return rc;
1804 }
1805 
1806 static u8 qed_dcbnl_setdcbx(struct qed_dev *cdev, u8 mode)
1807 {
1808     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1809     struct qed_dcbx_set dcbx_set;
1810     struct qed_ptt *ptt;
1811     int rc;
1812 
1813     DP_VERBOSE(hwfn, QED_MSG_DCB, "new mode = %x\n", mode);
1814 
1815     if (!(mode & DCB_CAP_DCBX_VER_IEEE) &&
1816         !(mode & DCB_CAP_DCBX_VER_CEE) && !(mode & DCB_CAP_DCBX_STATIC)) {
1817         DP_INFO(hwfn, "Allowed modes are cee, ieee or static\n");
1818         return 1;
1819     }
1820 
1821     memset(&dcbx_set, 0, sizeof(dcbx_set));
1822     rc = qed_dcbx_get_config_params(hwfn, &dcbx_set);
1823     if (rc)
1824         return 1;
1825 
1826     dcbx_set.ver_num = 0;
1827     if (mode & DCB_CAP_DCBX_VER_CEE) {
1828         dcbx_set.ver_num |= DCBX_CONFIG_VERSION_CEE;
1829         dcbx_set.enabled = true;
1830     }
1831 
1832     if (mode & DCB_CAP_DCBX_VER_IEEE) {
1833         dcbx_set.ver_num |= DCBX_CONFIG_VERSION_IEEE;
1834         dcbx_set.enabled = true;
1835     }
1836 
1837     if (mode & DCB_CAP_DCBX_STATIC) {
1838         dcbx_set.ver_num |= DCBX_CONFIG_VERSION_STATIC;
1839         dcbx_set.enabled = true;
1840     }
1841 
1842     ptt = qed_ptt_acquire(hwfn);
1843     if (!ptt)
1844         return 1;
1845 
1846     rc = qed_dcbx_config_params(hwfn, ptt, &dcbx_set, 0);
1847 
1848     qed_ptt_release(hwfn, ptt);
1849 
1850     return rc;
1851 }
1852 
1853 static u8 qed_dcbnl_getfeatcfg(struct qed_dev *cdev, int featid, u8 *flags)
1854 {
1855     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1856     struct qed_dcbx_get *dcbx_info;
1857 
1858     DP_VERBOSE(hwfn, QED_MSG_DCB, "Feature id  = %d\n", featid);
1859     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_OPERATIONAL_MIB);
1860     if (!dcbx_info)
1861         return 1;
1862 
1863     *flags = 0;
1864     switch (featid) {
1865     case DCB_FEATCFG_ATTR_PG:
1866         if (dcbx_info->operational.params.ets_enabled)
1867             *flags = DCB_FEATCFG_ENABLE;
1868         else
1869             *flags = DCB_FEATCFG_ERROR;
1870         break;
1871     case DCB_FEATCFG_ATTR_PFC:
1872         if (dcbx_info->operational.params.pfc.enabled)
1873             *flags = DCB_FEATCFG_ENABLE;
1874         else
1875             *flags = DCB_FEATCFG_ERROR;
1876         break;
1877     case DCB_FEATCFG_ATTR_APP:
1878         if (dcbx_info->operational.params.app_valid)
1879             *flags = DCB_FEATCFG_ENABLE;
1880         else
1881             *flags = DCB_FEATCFG_ERROR;
1882         break;
1883     default:
1884         DP_INFO(hwfn, "Invalid feature-ID %d\n", featid);
1885         kfree(dcbx_info);
1886         return 1;
1887     }
1888 
1889     DP_VERBOSE(hwfn, QED_MSG_DCB, "flags = %d\n", *flags);
1890     kfree(dcbx_info);
1891 
1892     return 0;
1893 }
1894 
1895 static u8 qed_dcbnl_setfeatcfg(struct qed_dev *cdev, int featid, u8 flags)
1896 {
1897     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1898     struct qed_dcbx_set dcbx_set;
1899     bool enabled, willing;
1900     struct qed_ptt *ptt;
1901     int rc;
1902 
1903     DP_VERBOSE(hwfn, QED_MSG_DCB, "featid = %d flags = %d\n",
1904            featid, flags);
1905     memset(&dcbx_set, 0, sizeof(dcbx_set));
1906     rc = qed_dcbx_get_config_params(hwfn, &dcbx_set);
1907     if (rc)
1908         return 1;
1909 
1910     enabled = !!(flags & DCB_FEATCFG_ENABLE);
1911     willing = !!(flags & DCB_FEATCFG_WILLING);
1912     switch (featid) {
1913     case DCB_FEATCFG_ATTR_PG:
1914         dcbx_set.override_flags |= QED_DCBX_OVERRIDE_ETS_CFG;
1915         dcbx_set.config.params.ets_enabled = enabled;
1916         dcbx_set.config.params.ets_willing = willing;
1917         break;
1918     case DCB_FEATCFG_ATTR_PFC:
1919         dcbx_set.override_flags |= QED_DCBX_OVERRIDE_PFC_CFG;
1920         dcbx_set.config.params.pfc.enabled = enabled;
1921         dcbx_set.config.params.pfc.willing = willing;
1922         break;
1923     case DCB_FEATCFG_ATTR_APP:
1924         dcbx_set.override_flags |= QED_DCBX_OVERRIDE_APP_CFG;
1925         dcbx_set.config.params.app_willing = willing;
1926         break;
1927     default:
1928         DP_INFO(hwfn, "Invalid feature-ID %d\n", featid);
1929         return 1;
1930     }
1931 
1932     ptt = qed_ptt_acquire(hwfn);
1933     if (!ptt)
1934         return 1;
1935 
1936     rc = qed_dcbx_config_params(hwfn, ptt, &dcbx_set, 0);
1937 
1938     qed_ptt_release(hwfn, ptt);
1939 
1940     return 0;
1941 }
1942 
1943 static int qed_dcbnl_peer_getappinfo(struct qed_dev *cdev,
1944                      struct dcb_peer_app_info *info,
1945                      u16 *app_count)
1946 {
1947     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1948     struct qed_dcbx_get *dcbx_info;
1949 
1950     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_REMOTE_MIB);
1951     if (!dcbx_info)
1952         return -EINVAL;
1953 
1954     info->willing = dcbx_info->remote.params.app_willing;
1955     info->error = dcbx_info->remote.params.app_error;
1956     *app_count = dcbx_info->remote.params.num_app_entries;
1957     kfree(dcbx_info);
1958 
1959     return 0;
1960 }
1961 
1962 static int qed_dcbnl_peer_getapptable(struct qed_dev *cdev,
1963                       struct dcb_app *table)
1964 {
1965     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1966     struct qed_dcbx_get *dcbx_info;
1967     int i;
1968 
1969     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_REMOTE_MIB);
1970     if (!dcbx_info)
1971         return -EINVAL;
1972 
1973     for (i = 0; i < dcbx_info->remote.params.num_app_entries; i++) {
1974         if (dcbx_info->remote.params.app_entry[i].ethtype)
1975             table[i].selector = DCB_APP_IDTYPE_ETHTYPE;
1976         else
1977             table[i].selector = DCB_APP_IDTYPE_PORTNUM;
1978         table[i].priority = dcbx_info->remote.params.app_entry[i].prio;
1979         table[i].protocol =
1980             dcbx_info->remote.params.app_entry[i].proto_id;
1981     }
1982 
1983     kfree(dcbx_info);
1984 
1985     return 0;
1986 }
1987 
1988 static int qed_dcbnl_cee_peer_getpfc(struct qed_dev *cdev, struct cee_pfc *pfc)
1989 {
1990     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
1991     struct qed_dcbx_get *dcbx_info;
1992     int i;
1993 
1994     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_REMOTE_MIB);
1995     if (!dcbx_info)
1996         return -EINVAL;
1997 
1998     for (i = 0; i < QED_MAX_PFC_PRIORITIES; i++)
1999         if (dcbx_info->remote.params.pfc.prio[i])
2000             pfc->pfc_en |= BIT(i);
2001 
2002     pfc->tcs_supported = dcbx_info->remote.params.pfc.max_tc;
2003     DP_VERBOSE(hwfn, QED_MSG_DCB, "pfc state = %d tcs_supported = %d\n",
2004            pfc->pfc_en, pfc->tcs_supported);
2005     kfree(dcbx_info);
2006 
2007     return 0;
2008 }
2009 
2010 static int qed_dcbnl_cee_peer_getpg(struct qed_dev *cdev, struct cee_pg *pg)
2011 {
2012     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
2013     struct qed_dcbx_get *dcbx_info;
2014     int i;
2015 
2016     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_REMOTE_MIB);
2017     if (!dcbx_info)
2018         return -EINVAL;
2019 
2020     pg->willing = dcbx_info->remote.params.ets_willing;
2021     for (i = 0; i < QED_MAX_PFC_PRIORITIES; i++) {
2022         pg->pg_bw[i] = dcbx_info->remote.params.ets_tc_bw_tbl[i];
2023         pg->prio_pg[i] = dcbx_info->remote.params.ets_pri_tc_tbl[i];
2024     }
2025 
2026     DP_VERBOSE(hwfn, QED_MSG_DCB, "willing = %d", pg->willing);
2027     kfree(dcbx_info);
2028 
2029     return 0;
2030 }
2031 
2032 static int qed_dcbnl_get_ieee_pfc(struct qed_dev *cdev,
2033                   struct ieee_pfc *pfc, bool remote)
2034 {
2035     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
2036     struct qed_dcbx_params *params;
2037     struct qed_dcbx_get *dcbx_info;
2038     int rc, i;
2039 
2040     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_OPERATIONAL_MIB);
2041     if (!dcbx_info)
2042         return -EINVAL;
2043 
2044     if (!dcbx_info->operational.ieee) {
2045         DP_INFO(hwfn, "DCBX is not enabled/operational in IEEE mode\n");
2046         kfree(dcbx_info);
2047         return -EINVAL;
2048     }
2049 
2050     if (remote) {
2051         memset(dcbx_info, 0, sizeof(*dcbx_info));
2052         rc = qed_dcbx_query_params(hwfn, dcbx_info,
2053                        QED_DCBX_REMOTE_MIB);
2054         if (rc) {
2055             kfree(dcbx_info);
2056             return -EINVAL;
2057         }
2058 
2059         params = &dcbx_info->remote.params;
2060     } else {
2061         params = &dcbx_info->operational.params;
2062     }
2063 
2064     pfc->pfc_cap = params->pfc.max_tc;
2065     pfc->pfc_en = 0;
2066     for (i = 0; i < QED_MAX_PFC_PRIORITIES; i++)
2067         if (params->pfc.prio[i])
2068             pfc->pfc_en |= BIT(i);
2069 
2070     kfree(dcbx_info);
2071 
2072     return 0;
2073 }
2074 
2075 static int qed_dcbnl_ieee_getpfc(struct qed_dev *cdev, struct ieee_pfc *pfc)
2076 {
2077     return qed_dcbnl_get_ieee_pfc(cdev, pfc, false);
2078 }
2079 
2080 static int qed_dcbnl_ieee_setpfc(struct qed_dev *cdev, struct ieee_pfc *pfc)
2081 {
2082     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
2083     struct qed_dcbx_get *dcbx_info;
2084     struct qed_dcbx_set dcbx_set;
2085     struct qed_ptt *ptt;
2086     int rc, i;
2087 
2088     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_OPERATIONAL_MIB);
2089     if (!dcbx_info)
2090         return -EINVAL;
2091 
2092     if (!dcbx_info->operational.ieee) {
2093         DP_INFO(hwfn, "DCBX is not enabled/operational in IEEE mode\n");
2094         kfree(dcbx_info);
2095         return -EINVAL;
2096     }
2097 
2098     kfree(dcbx_info);
2099 
2100     memset(&dcbx_set, 0, sizeof(dcbx_set));
2101     rc = qed_dcbx_get_config_params(hwfn, &dcbx_set);
2102     if (rc)
2103         return -EINVAL;
2104 
2105     dcbx_set.override_flags |= QED_DCBX_OVERRIDE_PFC_CFG;
2106     for (i = 0; i < QED_MAX_PFC_PRIORITIES; i++)
2107         dcbx_set.config.params.pfc.prio[i] = !!(pfc->pfc_en & BIT(i));
2108 
2109     dcbx_set.config.params.pfc.max_tc = pfc->pfc_cap;
2110 
2111     ptt = qed_ptt_acquire(hwfn);
2112     if (!ptt)
2113         return -EINVAL;
2114 
2115     rc = qed_dcbx_config_params(hwfn, ptt, &dcbx_set, 0);
2116 
2117     qed_ptt_release(hwfn, ptt);
2118 
2119     return rc;
2120 }
2121 
2122 static int qed_dcbnl_get_ieee_ets(struct qed_dev *cdev,
2123                   struct ieee_ets *ets, bool remote)
2124 {
2125     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
2126     struct qed_dcbx_get *dcbx_info;
2127     struct qed_dcbx_params *params;
2128     int rc;
2129 
2130     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_OPERATIONAL_MIB);
2131     if (!dcbx_info)
2132         return -EINVAL;
2133 
2134     if (!dcbx_info->operational.ieee) {
2135         DP_INFO(hwfn, "DCBX is not enabled/operational in IEEE mode\n");
2136         kfree(dcbx_info);
2137         return -EINVAL;
2138     }
2139 
2140     if (remote) {
2141         memset(dcbx_info, 0, sizeof(*dcbx_info));
2142         rc = qed_dcbx_query_params(hwfn, dcbx_info,
2143                        QED_DCBX_REMOTE_MIB);
2144         if (rc) {
2145             kfree(dcbx_info);
2146             return -EINVAL;
2147         }
2148 
2149         params = &dcbx_info->remote.params;
2150     } else {
2151         params = &dcbx_info->operational.params;
2152     }
2153 
2154     ets->ets_cap = params->max_ets_tc;
2155     ets->willing = params->ets_willing;
2156     ets->cbs = params->ets_cbs;
2157     memcpy(ets->tc_tx_bw, params->ets_tc_bw_tbl, sizeof(ets->tc_tx_bw));
2158     memcpy(ets->tc_tsa, params->ets_tc_tsa_tbl, sizeof(ets->tc_tsa));
2159     memcpy(ets->prio_tc, params->ets_pri_tc_tbl, sizeof(ets->prio_tc));
2160     kfree(dcbx_info);
2161 
2162     return 0;
2163 }
2164 
2165 static int qed_dcbnl_ieee_getets(struct qed_dev *cdev, struct ieee_ets *ets)
2166 {
2167     return qed_dcbnl_get_ieee_ets(cdev, ets, false);
2168 }
2169 
2170 static int qed_dcbnl_ieee_setets(struct qed_dev *cdev, struct ieee_ets *ets)
2171 {
2172     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
2173     struct qed_dcbx_get *dcbx_info;
2174     struct qed_dcbx_set dcbx_set;
2175     struct qed_ptt *ptt;
2176     int rc;
2177 
2178     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_OPERATIONAL_MIB);
2179     if (!dcbx_info)
2180         return -EINVAL;
2181 
2182     if (!dcbx_info->operational.ieee) {
2183         DP_INFO(hwfn, "DCBX is not enabled/operational in IEEE mode\n");
2184         kfree(dcbx_info);
2185         return -EINVAL;
2186     }
2187 
2188     kfree(dcbx_info);
2189 
2190     memset(&dcbx_set, 0, sizeof(dcbx_set));
2191     rc = qed_dcbx_get_config_params(hwfn, &dcbx_set);
2192     if (rc)
2193         return -EINVAL;
2194 
2195     dcbx_set.override_flags |= QED_DCBX_OVERRIDE_ETS_CFG;
2196     dcbx_set.config.params.max_ets_tc = ets->ets_cap;
2197     dcbx_set.config.params.ets_willing = ets->willing;
2198     dcbx_set.config.params.ets_cbs = ets->cbs;
2199     memcpy(dcbx_set.config.params.ets_tc_bw_tbl, ets->tc_tx_bw,
2200            sizeof(ets->tc_tx_bw));
2201     memcpy(dcbx_set.config.params.ets_tc_tsa_tbl, ets->tc_tsa,
2202            sizeof(ets->tc_tsa));
2203     memcpy(dcbx_set.config.params.ets_pri_tc_tbl, ets->prio_tc,
2204            sizeof(ets->prio_tc));
2205 
2206     ptt = qed_ptt_acquire(hwfn);
2207     if (!ptt)
2208         return -EINVAL;
2209 
2210     rc = qed_dcbx_config_params(hwfn, ptt, &dcbx_set, 0);
2211 
2212     qed_ptt_release(hwfn, ptt);
2213 
2214     return rc;
2215 }
2216 
2217 static int
2218 qed_dcbnl_ieee_peer_getets(struct qed_dev *cdev, struct ieee_ets *ets)
2219 {
2220     return qed_dcbnl_get_ieee_ets(cdev, ets, true);
2221 }
2222 
2223 static int
2224 qed_dcbnl_ieee_peer_getpfc(struct qed_dev *cdev, struct ieee_pfc *pfc)
2225 {
2226     return qed_dcbnl_get_ieee_pfc(cdev, pfc, true);
2227 }
2228 
2229 static int qed_get_sf_ieee_value(u8 selector, u8 *sf_ieee)
2230 {
2231     switch (selector) {
2232     case IEEE_8021QAZ_APP_SEL_ETHERTYPE:
2233         *sf_ieee = QED_DCBX_SF_IEEE_ETHTYPE;
2234         break;
2235     case IEEE_8021QAZ_APP_SEL_STREAM:
2236         *sf_ieee = QED_DCBX_SF_IEEE_TCP_PORT;
2237         break;
2238     case IEEE_8021QAZ_APP_SEL_DGRAM:
2239         *sf_ieee = QED_DCBX_SF_IEEE_UDP_PORT;
2240         break;
2241     case IEEE_8021QAZ_APP_SEL_ANY:
2242         *sf_ieee = QED_DCBX_SF_IEEE_TCP_UDP_PORT;
2243         break;
2244     default:
2245         return -EINVAL;
2246     }
2247 
2248     return 0;
2249 }
2250 
2251 static int qed_dcbnl_ieee_getapp(struct qed_dev *cdev, struct dcb_app *app)
2252 {
2253     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
2254     struct qed_dcbx_get *dcbx_info;
2255     struct qed_app_entry *entry;
2256     u8 prio = 0;
2257     u8 sf_ieee;
2258     int i;
2259 
2260     DP_VERBOSE(hwfn, QED_MSG_DCB, "selector = %d protocol = %d\n",
2261            app->selector, app->protocol);
2262 
2263     if (qed_get_sf_ieee_value(app->selector, &sf_ieee)) {
2264         DP_INFO(cdev, "Invalid selector field value %d\n",
2265             app->selector);
2266         return -EINVAL;
2267     }
2268 
2269     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_OPERATIONAL_MIB);
2270     if (!dcbx_info)
2271         return -EINVAL;
2272 
2273     if (!dcbx_info->operational.ieee) {
2274         DP_INFO(hwfn, "DCBX is not enabled/operational in IEEE mode\n");
2275         kfree(dcbx_info);
2276         return -EINVAL;
2277     }
2278 
2279     for (i = 0; i < QED_DCBX_MAX_APP_PROTOCOL; i++) {
2280         entry = &dcbx_info->operational.params.app_entry[i];
2281         if ((entry->sf_ieee == sf_ieee) &&
2282             (entry->proto_id == app->protocol)) {
2283             prio = entry->prio;
2284             break;
2285         }
2286     }
2287 
2288     if (i == QED_DCBX_MAX_APP_PROTOCOL) {
2289         DP_ERR(cdev, "App entry (%d, %d) not found\n", app->selector,
2290                app->protocol);
2291         kfree(dcbx_info);
2292         return -EINVAL;
2293     }
2294 
2295     app->priority = ffs(prio) - 1;
2296 
2297     kfree(dcbx_info);
2298 
2299     return 0;
2300 }
2301 
2302 static int qed_dcbnl_ieee_setapp(struct qed_dev *cdev, struct dcb_app *app)
2303 {
2304     struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
2305     struct qed_dcbx_get *dcbx_info;
2306     struct qed_dcbx_set dcbx_set;
2307     struct qed_app_entry *entry;
2308     struct qed_ptt *ptt;
2309     u8 sf_ieee;
2310     int rc, i;
2311 
2312     DP_VERBOSE(hwfn, QED_MSG_DCB, "selector = %d protocol = %d pri = %d\n",
2313            app->selector, app->protocol, app->priority);
2314     if (app->priority >= QED_MAX_PFC_PRIORITIES) {
2315         DP_INFO(hwfn, "Invalid priority %d\n", app->priority);
2316         return -EINVAL;
2317     }
2318 
2319     if (qed_get_sf_ieee_value(app->selector, &sf_ieee)) {
2320         DP_INFO(cdev, "Invalid selector field value %d\n",
2321             app->selector);
2322         return -EINVAL;
2323     }
2324 
2325     dcbx_info = qed_dcbnl_get_dcbx(hwfn, QED_DCBX_OPERATIONAL_MIB);
2326     if (!dcbx_info)
2327         return -EINVAL;
2328 
2329     if (!dcbx_info->operational.ieee) {
2330         DP_INFO(hwfn, "DCBX is not enabled/operational in IEEE mode\n");
2331         kfree(dcbx_info);
2332         return -EINVAL;
2333     }
2334 
2335     kfree(dcbx_info);
2336 
2337     memset(&dcbx_set, 0, sizeof(dcbx_set));
2338     rc = qed_dcbx_get_config_params(hwfn, &dcbx_set);
2339     if (rc)
2340         return -EINVAL;
2341 
2342     for (i = 0; i < QED_DCBX_MAX_APP_PROTOCOL; i++) {
2343         entry = &dcbx_set.config.params.app_entry[i];
2344         if ((entry->sf_ieee == sf_ieee) &&
2345             (entry->proto_id == app->protocol))
2346             break;
2347         /* First empty slot */
2348         if (!entry->proto_id) {
2349             dcbx_set.config.params.num_app_entries++;
2350             break;
2351         }
2352     }
2353 
2354     if (i == QED_DCBX_MAX_APP_PROTOCOL) {
2355         DP_ERR(cdev, "App table is full\n");
2356         return -EBUSY;
2357     }
2358 
2359     dcbx_set.override_flags |= QED_DCBX_OVERRIDE_APP_CFG;
2360     dcbx_set.config.params.app_entry[i].sf_ieee = sf_ieee;
2361     dcbx_set.config.params.app_entry[i].proto_id = app->protocol;
2362     dcbx_set.config.params.app_entry[i].prio = BIT(app->priority);
2363 
2364     ptt = qed_ptt_acquire(hwfn);
2365     if (!ptt)
2366         return -EBUSY;
2367 
2368     rc = qed_dcbx_config_params(hwfn, ptt, &dcbx_set, 0);
2369 
2370     qed_ptt_release(hwfn, ptt);
2371 
2372     return rc;
2373 }
2374 
2375 const struct qed_eth_dcbnl_ops qed_dcbnl_ops_pass = {
2376     .getstate = qed_dcbnl_getstate,
2377     .setstate = qed_dcbnl_setstate,
2378     .getpgtccfgtx = qed_dcbnl_getpgtccfgtx,
2379     .getpgbwgcfgtx = qed_dcbnl_getpgbwgcfgtx,
2380     .getpgtccfgrx = qed_dcbnl_getpgtccfgrx,
2381     .getpgbwgcfgrx = qed_dcbnl_getpgbwgcfgrx,
2382     .getpfccfg = qed_dcbnl_getpfccfg,
2383     .setpfccfg = qed_dcbnl_setpfccfg,
2384     .getcap = qed_dcbnl_getcap,
2385     .getnumtcs = qed_dcbnl_getnumtcs,
2386     .getpfcstate = qed_dcbnl_getpfcstate,
2387     .getdcbx = qed_dcbnl_getdcbx,
2388     .setpgtccfgtx = qed_dcbnl_setpgtccfgtx,
2389     .setpgtccfgrx = qed_dcbnl_setpgtccfgrx,
2390     .setpgbwgcfgtx = qed_dcbnl_setpgbwgcfgtx,
2391     .setpgbwgcfgrx = qed_dcbnl_setpgbwgcfgrx,
2392     .setall = qed_dcbnl_setall,
2393     .setnumtcs = qed_dcbnl_setnumtcs,
2394     .setpfcstate = qed_dcbnl_setpfcstate,
2395     .setapp = qed_dcbnl_setapp,
2396     .setdcbx = qed_dcbnl_setdcbx,
2397     .setfeatcfg = qed_dcbnl_setfeatcfg,
2398     .getfeatcfg = qed_dcbnl_getfeatcfg,
2399     .getapp = qed_dcbnl_getapp,
2400     .peer_getappinfo = qed_dcbnl_peer_getappinfo,
2401     .peer_getapptable = qed_dcbnl_peer_getapptable,
2402     .cee_peer_getpfc = qed_dcbnl_cee_peer_getpfc,
2403     .cee_peer_getpg = qed_dcbnl_cee_peer_getpg,
2404     .ieee_getpfc = qed_dcbnl_ieee_getpfc,
2405     .ieee_setpfc = qed_dcbnl_ieee_setpfc,
2406     .ieee_getets = qed_dcbnl_ieee_getets,
2407     .ieee_setets = qed_dcbnl_ieee_setets,
2408     .ieee_peer_getpfc = qed_dcbnl_ieee_peer_getpfc,
2409     .ieee_peer_getets = qed_dcbnl_ieee_peer_getets,
2410     .ieee_getapp = qed_dcbnl_ieee_getapp,
2411     .ieee_setapp = qed_dcbnl_ieee_setapp,
2412 };
2413 
2414 #endif