2415 lines · c
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)2/* QLogic qed NIC Driver3 * Copyright (c) 2015-2017 QLogic Corporation4 * Copyright (c) 2019-2020 Marvell International Ltd.5 */6 7#include <linux/types.h>8#include <asm/byteorder.h>9#include <linux/bitops.h>10#include <linux/dcbnl.h>11#include <linux/errno.h>12#include <linux/kernel.h>13#include <linux/slab.h>14#include <linux/string.h>15#include "qed.h"16#include "qed_cxt.h"17#include "qed_dcbx.h"18#include "qed_hsi.h"19#include "qed_sp.h"20#include "qed_sriov.h"21#include "qed_rdma.h"22#ifdef CONFIG_DCB23#include <linux/qed/qed_eth_if.h>24#endif25 26#define QED_DCBX_MAX_MIB_READ_TRY (100)27#define QED_ETH_TYPE_DEFAULT (0)28#define QED_ETH_TYPE_ROCE (0x8915)29#define QED_UDP_PORT_TYPE_ROCE_V2 (0x12B7)30#define QED_ETH_TYPE_FCOE (0x8906)31#define QED_TCP_PORT_ISCSI (0xCBC)32 33#define QED_DCBX_INVALID_PRIORITY 0xFF34 35/* Get Traffic Class from priority traffic class table, 4 bits represent36 * the traffic class corresponding to the priority.37 */38#define QED_DCBX_PRIO2TC(prio_tc_tbl, prio) \39 ((u32)(prio_tc_tbl >> ((7 - prio) * 4)) & 0x7)40 41static const struct qed_dcbx_app_metadata qed_dcbx_app_update[] = {42 {DCBX_PROTOCOL_ISCSI, "ISCSI", QED_PCI_ISCSI},43 {DCBX_PROTOCOL_FCOE, "FCOE", QED_PCI_FCOE},44 {DCBX_PROTOCOL_ROCE, "ROCE", QED_PCI_ETH_ROCE},45 {DCBX_PROTOCOL_ROCE_V2, "ROCE_V2", QED_PCI_ETH_ROCE},46 {DCBX_PROTOCOL_ETH, "ETH", QED_PCI_ETH},47};48 49static bool qed_dcbx_app_ethtype(u32 app_info_bitmap)50{51 return !!(QED_MFW_GET_FIELD(app_info_bitmap, DCBX_APP_SF) ==52 DCBX_APP_SF_ETHTYPE);53}54 55static bool qed_dcbx_ieee_app_ethtype(u32 app_info_bitmap)56{57 u8 mfw_val = QED_MFW_GET_FIELD(app_info_bitmap, DCBX_APP_SF_IEEE);58 59 /* Old MFW */60 if (mfw_val == DCBX_APP_SF_IEEE_RESERVED)61 return qed_dcbx_app_ethtype(app_info_bitmap);62 63 return !!(mfw_val == DCBX_APP_SF_IEEE_ETHTYPE);64}65 66static bool qed_dcbx_app_port(u32 app_info_bitmap)67{68 return !!(QED_MFW_GET_FIELD(app_info_bitmap, DCBX_APP_SF) ==69 DCBX_APP_SF_PORT);70}71 72static bool qed_dcbx_ieee_app_port(u32 app_info_bitmap, u8 type)73{74 u8 mfw_val = QED_MFW_GET_FIELD(app_info_bitmap, DCBX_APP_SF_IEEE);75 76 /* Old MFW */77 if (mfw_val == DCBX_APP_SF_IEEE_RESERVED)78 return qed_dcbx_app_port(app_info_bitmap);79 80 return !!(mfw_val == type || mfw_val == DCBX_APP_SF_IEEE_TCP_UDP_PORT);81}82 83static bool qed_dcbx_default_tlv(u32 app_info_bitmap, u16 proto_id, bool ieee)84{85 bool ethtype;86 87 if (ieee)88 ethtype = qed_dcbx_ieee_app_ethtype(app_info_bitmap);89 else90 ethtype = qed_dcbx_app_ethtype(app_info_bitmap);91 92 return !!(ethtype && (proto_id == QED_ETH_TYPE_DEFAULT));93}94 95static bool qed_dcbx_iscsi_tlv(u32 app_info_bitmap, u16 proto_id, bool ieee)96{97 bool port;98 99 if (ieee)100 port = qed_dcbx_ieee_app_port(app_info_bitmap,101 DCBX_APP_SF_IEEE_TCP_PORT);102 else103 port = qed_dcbx_app_port(app_info_bitmap);104 105 return !!(port && (proto_id == QED_TCP_PORT_ISCSI));106}107 108static bool qed_dcbx_fcoe_tlv(u32 app_info_bitmap, u16 proto_id, bool ieee)109{110 bool ethtype;111 112 if (ieee)113 ethtype = qed_dcbx_ieee_app_ethtype(app_info_bitmap);114 else115 ethtype = qed_dcbx_app_ethtype(app_info_bitmap);116 117 return !!(ethtype && (proto_id == QED_ETH_TYPE_FCOE));118}119 120static bool qed_dcbx_roce_tlv(u32 app_info_bitmap, u16 proto_id, bool ieee)121{122 bool ethtype;123 124 if (ieee)125 ethtype = qed_dcbx_ieee_app_ethtype(app_info_bitmap);126 else127 ethtype = qed_dcbx_app_ethtype(app_info_bitmap);128 129 return !!(ethtype && (proto_id == QED_ETH_TYPE_ROCE));130}131 132static bool qed_dcbx_roce_v2_tlv(u32 app_info_bitmap, u16 proto_id, bool ieee)133{134 bool port;135 136 if (ieee)137 port = qed_dcbx_ieee_app_port(app_info_bitmap,138 DCBX_APP_SF_IEEE_UDP_PORT);139 else140 port = qed_dcbx_app_port(app_info_bitmap);141 142 return !!(port && (proto_id == QED_UDP_PORT_TYPE_ROCE_V2));143}144 145static void146qed_dcbx_dp_protocol(struct qed_hwfn *p_hwfn, struct qed_dcbx_results *p_data)147{148 enum dcbx_protocol_type id;149 int i;150 151 DP_VERBOSE(p_hwfn, QED_MSG_DCB, "DCBX negotiated: %d\n",152 p_data->dcbx_enabled);153 154 for (i = 0; i < ARRAY_SIZE(qed_dcbx_app_update); i++) {155 id = qed_dcbx_app_update[i].id;156 157 DP_VERBOSE(p_hwfn, QED_MSG_DCB,158 "%s info: update %d, enable %d, prio %d, tc %d, num_tc %d\n",159 qed_dcbx_app_update[i].name, p_data->arr[id].update,160 p_data->arr[id].enable, p_data->arr[id].priority,161 p_data->arr[id].tc, p_hwfn->hw_info.num_active_tc);162 }163}164 165static void166qed_dcbx_set_params(struct qed_dcbx_results *p_data,167 struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,168 bool app_tlv, bool enable, u8 prio, u8 tc,169 enum dcbx_protocol_type type,170 enum qed_pci_personality personality)171{172 /* PF update ramrod data */173 p_data->arr[type].enable = enable;174 p_data->arr[type].priority = prio;175 p_data->arr[type].tc = tc;176 if (enable)177 p_data->arr[type].update = UPDATE_DCB;178 else179 p_data->arr[type].update = DONT_UPDATE_DCB_DSCP;180 181 if (test_bit(QED_MF_DONT_ADD_VLAN0_TAG, &p_hwfn->cdev->mf_bits))182 p_data->arr[type].dont_add_vlan0 = true;183 184 /* QM reconf data */185 if (app_tlv && p_hwfn->hw_info.personality == personality)186 qed_hw_info_set_offload_tc(&p_hwfn->hw_info, tc);187 188 /* Configure dcbx vlan priority in doorbell block for roce EDPM */189 if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits) &&190 type == DCBX_PROTOCOL_ROCE) {191 qed_wr(p_hwfn, p_ptt, DORQ_REG_TAG1_OVRD_MODE, 1);192 qed_wr(p_hwfn, p_ptt, DORQ_REG_PF_PCP_BB_K2, prio << 1);193 }194}195 196/* Update app protocol data and hw_info fields with the TLV info */197static void198qed_dcbx_update_app_info(struct qed_dcbx_results *p_data,199 struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,200 bool app_tlv, bool enable, u8 prio, u8 tc,201 enum dcbx_protocol_type type)202{203 enum qed_pci_personality personality;204 enum dcbx_protocol_type id;205 int i;206 207 for (i = 0; i < ARRAY_SIZE(qed_dcbx_app_update); i++) {208 id = qed_dcbx_app_update[i].id;209 210 if (type != id)211 continue;212 213 personality = qed_dcbx_app_update[i].personality;214 215 qed_dcbx_set_params(p_data, p_hwfn, p_ptt, app_tlv, enable,216 prio, tc, type, personality);217 }218}219 220static bool221qed_dcbx_get_app_protocol_type(struct qed_hwfn *p_hwfn,222 u32 app_prio_bitmap,223 u16 id, enum dcbx_protocol_type *type, bool ieee)224{225 if (qed_dcbx_fcoe_tlv(app_prio_bitmap, id, ieee)) {226 *type = DCBX_PROTOCOL_FCOE;227 } else if (qed_dcbx_roce_tlv(app_prio_bitmap, id, ieee)) {228 *type = DCBX_PROTOCOL_ROCE;229 } else if (qed_dcbx_iscsi_tlv(app_prio_bitmap, id, ieee)) {230 *type = DCBX_PROTOCOL_ISCSI;231 } else if (qed_dcbx_default_tlv(app_prio_bitmap, id, ieee)) {232 *type = DCBX_PROTOCOL_ETH;233 } else if (qed_dcbx_roce_v2_tlv(app_prio_bitmap, id, ieee)) {234 *type = DCBX_PROTOCOL_ROCE_V2;235 } else {236 *type = DCBX_MAX_PROTOCOL_TYPE;237 DP_VERBOSE(p_hwfn, QED_MSG_DCB,238 "No action required, App TLV entry = 0x%x\n",239 app_prio_bitmap);240 return false;241 }242 243 return true;244}245 246/* Parse app TLV's to update TC information in hw_info structure for247 * reconfiguring QM. Get protocol specific data for PF update ramrod command.248 */249static int250qed_dcbx_process_tlv(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,251 struct qed_dcbx_results *p_data,252 struct dcbx_app_priority_entry *p_tbl,253 u32 pri_tc_tbl, int count, u8 dcbx_version)254{255 enum dcbx_protocol_type type;256 bool enable, ieee, eth_tlv;257 u8 tc, priority_map;258 u16 protocol_id;259 int priority;260 int i;261 262 DP_VERBOSE(p_hwfn, QED_MSG_DCB, "Num APP entries = %d\n", count);263 264 ieee = (dcbx_version == DCBX_CONFIG_VERSION_IEEE);265 eth_tlv = false;266 /* Parse APP TLV */267 for (i = 0; i < count; i++) {268 protocol_id = QED_MFW_GET_FIELD(p_tbl[i].entry,269 DCBX_APP_PROTOCOL_ID);270 priority_map = QED_MFW_GET_FIELD(p_tbl[i].entry,271 DCBX_APP_PRI_MAP);272 priority = ffs(priority_map) - 1;273 if (priority < 0) {274 DP_ERR(p_hwfn, "Invalid priority\n");275 return -EINVAL;276 }277 278 tc = QED_DCBX_PRIO2TC(pri_tc_tbl, priority);279 if (qed_dcbx_get_app_protocol_type(p_hwfn, p_tbl[i].entry,280 protocol_id, &type, ieee)) {281 /* ETH always have the enable bit reset, as it gets282 * vlan information per packet. For other protocols,283 * should be set according to the dcbx_enabled284 * indication, but we only got here if there was an285 * app tlv for the protocol, so dcbx must be enabled.286 */287 if (type == DCBX_PROTOCOL_ETH) {288 enable = false;289 eth_tlv = true;290 } else {291 enable = true;292 }293 294 qed_dcbx_update_app_info(p_data, p_hwfn, p_ptt, true,295 enable, priority, tc, type);296 }297 }298 299 /* If Eth TLV is not detected, use UFP TC as default TC */300 if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits) && !eth_tlv)301 p_data->arr[DCBX_PROTOCOL_ETH].tc = p_hwfn->ufp_info.tc;302 303 /* Update ramrod protocol data and hw_info fields304 * with default info when corresponding APP TLV's are not detected.305 * The enabled field has a different logic for ethernet as only for306 * ethernet dcb should disabled by default, as the information arrives307 * from the OS (unless an explicit app tlv was present).308 */309 tc = p_data->arr[DCBX_PROTOCOL_ETH].tc;310 priority = p_data->arr[DCBX_PROTOCOL_ETH].priority;311 for (type = 0; type < DCBX_MAX_PROTOCOL_TYPE; type++) {312 if (p_data->arr[type].update)313 continue;314 315 enable = (type == DCBX_PROTOCOL_ETH) ? false : !!dcbx_version;316 qed_dcbx_update_app_info(p_data, p_hwfn, p_ptt, false, enable,317 priority, tc, type);318 }319 320 return 0;321}322 323/* Parse app TLV's to update TC information in hw_info structure for324 * reconfiguring QM. Get protocol specific data for PF update ramrod command.325 */326static int327qed_dcbx_process_mib_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)328{329 struct dcbx_app_priority_feature *p_app;330 struct dcbx_app_priority_entry *p_tbl;331 struct qed_dcbx_results data = { 0 };332 struct dcbx_ets_feature *p_ets;333 struct qed_hw_info *p_info;334 u32 pri_tc_tbl, flags;335 u8 dcbx_version;336 int num_entries;337 int rc = 0;338 339 flags = p_hwfn->p_dcbx_info->operational.flags;340 dcbx_version = QED_MFW_GET_FIELD(flags, DCBX_CONFIG_VERSION);341 342 p_app = &p_hwfn->p_dcbx_info->operational.features.app;343 p_tbl = p_app->app_pri_tbl;344 345 p_ets = &p_hwfn->p_dcbx_info->operational.features.ets;346 pri_tc_tbl = p_ets->pri_tc_tbl[0];347 348 p_info = &p_hwfn->hw_info;349 num_entries = QED_MFW_GET_FIELD(p_app->flags, DCBX_APP_NUM_ENTRIES);350 351 rc = qed_dcbx_process_tlv(p_hwfn, p_ptt, &data, p_tbl, pri_tc_tbl,352 num_entries, dcbx_version);353 if (rc)354 return rc;355 356 p_info->num_active_tc = QED_MFW_GET_FIELD(p_ets->flags,357 DCBX_ETS_MAX_TCS);358 p_hwfn->qm_info.ooo_tc = QED_MFW_GET_FIELD(p_ets->flags, DCBX_OOO_TC);359 data.pf_id = p_hwfn->rel_pf_id;360 data.dcbx_enabled = !!dcbx_version;361 362 qed_dcbx_dp_protocol(p_hwfn, &data);363 364 memcpy(&p_hwfn->p_dcbx_info->results, &data,365 sizeof(struct qed_dcbx_results));366 367 return 0;368}369 370static int371qed_dcbx_copy_mib(struct qed_hwfn *p_hwfn,372 struct qed_ptt *p_ptt,373 struct qed_dcbx_mib_meta_data *p_data,374 enum qed_mib_read_type type)375{376 u32 prefix_seq_num, suffix_seq_num;377 int read_count = 0;378 int rc = 0;379 380 /* The data is considered to be valid only if both sequence numbers are381 * the same.382 */383 do {384 if (type == QED_DCBX_REMOTE_LLDP_MIB) {385 qed_memcpy_from(p_hwfn, p_ptt, p_data->lldp_remote,386 p_data->addr, p_data->size);387 prefix_seq_num = p_data->lldp_remote->prefix_seq_num;388 suffix_seq_num = p_data->lldp_remote->suffix_seq_num;389 } else {390 qed_memcpy_from(p_hwfn, p_ptt, p_data->mib,391 p_data->addr, p_data->size);392 prefix_seq_num = p_data->mib->prefix_seq_num;393 suffix_seq_num = p_data->mib->suffix_seq_num;394 }395 read_count++;396 397 DP_VERBOSE(p_hwfn,398 QED_MSG_DCB,399 "mib type = %d, try count = %d prefix seq num = %d suffix seq num = %d\n",400 type, read_count, prefix_seq_num, suffix_seq_num);401 } while ((prefix_seq_num != suffix_seq_num) &&402 (read_count < QED_DCBX_MAX_MIB_READ_TRY));403 404 if (read_count >= QED_DCBX_MAX_MIB_READ_TRY) {405 DP_ERR(p_hwfn,406 "MIB read err, mib type = %d, try count = %d prefix seq num = %d suffix seq num = %d\n",407 type, read_count, prefix_seq_num, suffix_seq_num);408 rc = -EIO;409 }410 411 return rc;412}413 414static void415qed_dcbx_get_priority_info(struct qed_hwfn *p_hwfn,416 struct qed_dcbx_app_prio *p_prio,417 struct qed_dcbx_results *p_results)418{419 u8 val;420 421 p_prio->roce = QED_DCBX_INVALID_PRIORITY;422 p_prio->roce_v2 = QED_DCBX_INVALID_PRIORITY;423 p_prio->iscsi = QED_DCBX_INVALID_PRIORITY;424 p_prio->fcoe = QED_DCBX_INVALID_PRIORITY;425 426 if (p_results->arr[DCBX_PROTOCOL_ROCE].update &&427 p_results->arr[DCBX_PROTOCOL_ROCE].enable)428 p_prio->roce = p_results->arr[DCBX_PROTOCOL_ROCE].priority;429 430 if (p_results->arr[DCBX_PROTOCOL_ROCE_V2].update &&431 p_results->arr[DCBX_PROTOCOL_ROCE_V2].enable) {432 val = p_results->arr[DCBX_PROTOCOL_ROCE_V2].priority;433 p_prio->roce_v2 = val;434 }435 436 if (p_results->arr[DCBX_PROTOCOL_ISCSI].update &&437 p_results->arr[DCBX_PROTOCOL_ISCSI].enable)438 p_prio->iscsi = p_results->arr[DCBX_PROTOCOL_ISCSI].priority;439 440 if (p_results->arr[DCBX_PROTOCOL_FCOE].update &&441 p_results->arr[DCBX_PROTOCOL_FCOE].enable)442 p_prio->fcoe = p_results->arr[DCBX_PROTOCOL_FCOE].priority;443 444 if (p_results->arr[DCBX_PROTOCOL_ETH].update &&445 p_results->arr[DCBX_PROTOCOL_ETH].enable)446 p_prio->eth = p_results->arr[DCBX_PROTOCOL_ETH].priority;447 448 DP_VERBOSE(p_hwfn, QED_MSG_DCB,449 "Priorities: iscsi %d, roce %d, roce v2 %d, fcoe %d, eth %d\n",450 p_prio->iscsi, p_prio->roce, p_prio->roce_v2, p_prio->fcoe,451 p_prio->eth);452}453 454static void455qed_dcbx_get_app_data(struct qed_hwfn *p_hwfn,456 struct dcbx_app_priority_feature *p_app,457 struct dcbx_app_priority_entry *p_tbl,458 struct qed_dcbx_params *p_params, bool ieee)459{460 struct qed_app_entry *entry;461 u8 pri_map;462 int i;463 464 p_params->app_willing = QED_MFW_GET_FIELD(p_app->flags,465 DCBX_APP_WILLING);466 p_params->app_valid = QED_MFW_GET_FIELD(p_app->flags, DCBX_APP_ENABLED);467 p_params->app_error = QED_MFW_GET_FIELD(p_app->flags, DCBX_APP_ERROR);468 p_params->num_app_entries = QED_MFW_GET_FIELD(p_app->flags,469 DCBX_APP_NUM_ENTRIES);470 for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++) {471 entry = &p_params->app_entry[i];472 if (ieee) {473 u8 sf_ieee;474 u32 val;475 476 sf_ieee = QED_MFW_GET_FIELD(p_tbl[i].entry,477 DCBX_APP_SF_IEEE);478 switch (sf_ieee) {479 case DCBX_APP_SF_IEEE_RESERVED:480 /* Old MFW */481 val = QED_MFW_GET_FIELD(p_tbl[i].entry,482 DCBX_APP_SF);483 entry->sf_ieee = val ?484 QED_DCBX_SF_IEEE_TCP_UDP_PORT :485 QED_DCBX_SF_IEEE_ETHTYPE;486 break;487 case DCBX_APP_SF_IEEE_ETHTYPE:488 entry->sf_ieee = QED_DCBX_SF_IEEE_ETHTYPE;489 break;490 case DCBX_APP_SF_IEEE_TCP_PORT:491 entry->sf_ieee = QED_DCBX_SF_IEEE_TCP_PORT;492 break;493 case DCBX_APP_SF_IEEE_UDP_PORT:494 entry->sf_ieee = QED_DCBX_SF_IEEE_UDP_PORT;495 break;496 case DCBX_APP_SF_IEEE_TCP_UDP_PORT:497 entry->sf_ieee = QED_DCBX_SF_IEEE_TCP_UDP_PORT;498 break;499 }500 } else {501 entry->ethtype = !(QED_MFW_GET_FIELD(p_tbl[i].entry,502 DCBX_APP_SF));503 }504 505 pri_map = QED_MFW_GET_FIELD(p_tbl[i].entry, DCBX_APP_PRI_MAP);506 entry->prio = ffs(pri_map) - 1;507 entry->proto_id = QED_MFW_GET_FIELD(p_tbl[i].entry,508 DCBX_APP_PROTOCOL_ID);509 qed_dcbx_get_app_protocol_type(p_hwfn, p_tbl[i].entry,510 entry->proto_id,511 &entry->proto_type, ieee);512 }513 514 DP_VERBOSE(p_hwfn, QED_MSG_DCB,515 "APP params: willing %d, valid %d error = %d\n",516 p_params->app_willing, p_params->app_valid,517 p_params->app_error);518}519 520static void521qed_dcbx_get_pfc_data(struct qed_hwfn *p_hwfn,522 u32 pfc, struct qed_dcbx_params *p_params)523{524 u8 pfc_map;525 526 p_params->pfc.willing = QED_MFW_GET_FIELD(pfc, DCBX_PFC_WILLING);527 p_params->pfc.max_tc = QED_MFW_GET_FIELD(pfc, DCBX_PFC_CAPS);528 p_params->pfc.enabled = QED_MFW_GET_FIELD(pfc, DCBX_PFC_ENABLED);529 pfc_map = QED_MFW_GET_FIELD(pfc, DCBX_PFC_PRI_EN_BITMAP);530 p_params->pfc.prio[0] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_0);531 p_params->pfc.prio[1] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_1);532 p_params->pfc.prio[2] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_2);533 p_params->pfc.prio[3] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_3);534 p_params->pfc.prio[4] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_4);535 p_params->pfc.prio[5] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_5);536 p_params->pfc.prio[6] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_6);537 p_params->pfc.prio[7] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_7);538 539 DP_VERBOSE(p_hwfn, QED_MSG_DCB,540 "PFC params: willing %d, pfc_bitmap %u max_tc = %u enabled = %d\n",541 p_params->pfc.willing, pfc_map, p_params->pfc.max_tc,542 p_params->pfc.enabled);543}544 545static void546qed_dcbx_get_ets_data(struct qed_hwfn *p_hwfn,547 struct dcbx_ets_feature *p_ets,548 struct qed_dcbx_params *p_params)549{550 __be32 bw_map[2], tsa_map[2];551 u32 pri_map;552 int i;553 554 p_params->ets_willing = QED_MFW_GET_FIELD(p_ets->flags,555 DCBX_ETS_WILLING);556 p_params->ets_enabled = QED_MFW_GET_FIELD(p_ets->flags,557 DCBX_ETS_ENABLED);558 p_params->ets_cbs = QED_MFW_GET_FIELD(p_ets->flags, DCBX_ETS_CBS);559 p_params->max_ets_tc = QED_MFW_GET_FIELD(p_ets->flags,560 DCBX_ETS_MAX_TCS);561 DP_VERBOSE(p_hwfn, QED_MSG_DCB,562 "ETS params: willing %d, enabled = %d ets_cbs %d pri_tc_tbl_0 %x max_ets_tc %d\n",563 p_params->ets_willing, p_params->ets_enabled,564 p_params->ets_cbs, p_ets->pri_tc_tbl[0],565 p_params->max_ets_tc);566 567 if (p_params->ets_enabled && !p_params->max_ets_tc) {568 p_params->max_ets_tc = QED_MAX_PFC_PRIORITIES;569 DP_VERBOSE(p_hwfn, QED_MSG_DCB,570 "ETS params: max_ets_tc is forced to %d\n",571 p_params->max_ets_tc);572 }573 574 /* 8 bit tsa and bw data corresponding to each of the 8 TC's are575 * encoded in a type u32 array of size 2.576 */577 cpu_to_be32_array(bw_map, p_ets->tc_bw_tbl, 2);578 cpu_to_be32_array(tsa_map, p_ets->tc_tsa_tbl, 2);579 pri_map = p_ets->pri_tc_tbl[0];580 581 for (i = 0; i < QED_MAX_PFC_PRIORITIES; i++) {582 p_params->ets_tc_bw_tbl[i] = ((u8 *)bw_map)[i];583 p_params->ets_tc_tsa_tbl[i] = ((u8 *)tsa_map)[i];584 p_params->ets_pri_tc_tbl[i] = QED_DCBX_PRIO2TC(pri_map, i);585 DP_VERBOSE(p_hwfn, QED_MSG_DCB,586 "elem %d bw_tbl %x tsa_tbl %x\n",587 i, p_params->ets_tc_bw_tbl[i],588 p_params->ets_tc_tsa_tbl[i]);589 }590}591 592static void593qed_dcbx_get_common_params(struct qed_hwfn *p_hwfn,594 struct dcbx_app_priority_feature *p_app,595 struct dcbx_app_priority_entry *p_tbl,596 struct dcbx_ets_feature *p_ets,597 u32 pfc, struct qed_dcbx_params *p_params, bool ieee)598{599 qed_dcbx_get_app_data(p_hwfn, p_app, p_tbl, p_params, ieee);600 qed_dcbx_get_ets_data(p_hwfn, p_ets, p_params);601 qed_dcbx_get_pfc_data(p_hwfn, pfc, p_params);602}603 604static void605qed_dcbx_get_local_params(struct qed_hwfn *p_hwfn, struct qed_dcbx_get *params)606{607 struct dcbx_features *p_feat;608 609 p_feat = &p_hwfn->p_dcbx_info->local_admin.features;610 qed_dcbx_get_common_params(p_hwfn, &p_feat->app,611 p_feat->app.app_pri_tbl, &p_feat->ets,612 p_feat->pfc, ¶ms->local.params, false);613 params->local.valid = true;614}615 616static void617qed_dcbx_get_remote_params(struct qed_hwfn *p_hwfn, struct qed_dcbx_get *params)618{619 struct dcbx_features *p_feat;620 621 p_feat = &p_hwfn->p_dcbx_info->remote.features;622 qed_dcbx_get_common_params(p_hwfn, &p_feat->app,623 p_feat->app.app_pri_tbl, &p_feat->ets,624 p_feat->pfc, ¶ms->remote.params, false);625 params->remote.valid = true;626}627 628static void629qed_dcbx_get_operational_params(struct qed_hwfn *p_hwfn,630 struct qed_dcbx_get *params)631{632 struct qed_dcbx_operational_params *p_operational;633 struct qed_dcbx_results *p_results;634 struct dcbx_features *p_feat;635 bool enabled, err;636 u32 flags;637 bool val;638 639 flags = p_hwfn->p_dcbx_info->operational.flags;640 641 /* If DCBx version is non zero, then negotiation642 * was successfuly performed643 */644 p_operational = ¶ms->operational;645 enabled = !!(QED_MFW_GET_FIELD(flags, DCBX_CONFIG_VERSION) !=646 DCBX_CONFIG_VERSION_DISABLED);647 if (!enabled) {648 p_operational->enabled = enabled;649 p_operational->valid = false;650 DP_VERBOSE(p_hwfn, QED_MSG_DCB, "Dcbx is disabled\n");651 return;652 }653 654 p_feat = &p_hwfn->p_dcbx_info->operational.features;655 p_results = &p_hwfn->p_dcbx_info->results;656 657 val = !!(QED_MFW_GET_FIELD(flags, DCBX_CONFIG_VERSION) ==658 DCBX_CONFIG_VERSION_IEEE);659 p_operational->ieee = val;660 val = !!(QED_MFW_GET_FIELD(flags, DCBX_CONFIG_VERSION) ==661 DCBX_CONFIG_VERSION_CEE);662 p_operational->cee = val;663 664 val = !!(QED_MFW_GET_FIELD(flags, DCBX_CONFIG_VERSION) ==665 DCBX_CONFIG_VERSION_STATIC);666 p_operational->local = val;667 668 DP_VERBOSE(p_hwfn, QED_MSG_DCB,669 "Version support: ieee %d, cee %d, static %d\n",670 p_operational->ieee, p_operational->cee,671 p_operational->local);672 673 qed_dcbx_get_common_params(p_hwfn, &p_feat->app,674 p_feat->app.app_pri_tbl, &p_feat->ets,675 p_feat->pfc, ¶ms->operational.params,676 p_operational->ieee);677 qed_dcbx_get_priority_info(p_hwfn, &p_operational->app_prio, p_results);678 err = QED_MFW_GET_FIELD(p_feat->app.flags, DCBX_APP_ERROR);679 p_operational->err = err;680 p_operational->enabled = enabled;681 p_operational->valid = true;682}683 684static void685qed_dcbx_get_local_lldp_params(struct qed_hwfn *p_hwfn,686 struct qed_dcbx_get *params)687{688 struct lldp_config_params_s *p_local;689 690 p_local = &p_hwfn->p_dcbx_info->lldp_local[LLDP_NEAREST_BRIDGE];691 692 memcpy(params->lldp_local.local_chassis_id, p_local->local_chassis_id,693 sizeof(p_local->local_chassis_id));694 memcpy(params->lldp_local.local_port_id, p_local->local_port_id,695 sizeof(p_local->local_port_id));696}697 698static void699qed_dcbx_get_remote_lldp_params(struct qed_hwfn *p_hwfn,700 struct qed_dcbx_get *params)701{702 struct lldp_status_params_s *p_remote;703 704 p_remote = &p_hwfn->p_dcbx_info->lldp_remote[LLDP_NEAREST_BRIDGE];705 706 memcpy(params->lldp_remote.peer_chassis_id, p_remote->peer_chassis_id,707 sizeof(p_remote->peer_chassis_id));708 memcpy(params->lldp_remote.peer_port_id, p_remote->peer_port_id,709 sizeof(p_remote->peer_port_id));710}711 712static int713qed_dcbx_get_params(struct qed_hwfn *p_hwfn, struct qed_dcbx_get *p_params,714 enum qed_mib_read_type type)715{716 switch (type) {717 case QED_DCBX_REMOTE_MIB:718 qed_dcbx_get_remote_params(p_hwfn, p_params);719 break;720 case QED_DCBX_LOCAL_MIB:721 qed_dcbx_get_local_params(p_hwfn, p_params);722 break;723 case QED_DCBX_OPERATIONAL_MIB:724 qed_dcbx_get_operational_params(p_hwfn, p_params);725 break;726 case QED_DCBX_REMOTE_LLDP_MIB:727 qed_dcbx_get_remote_lldp_params(p_hwfn, p_params);728 break;729 case QED_DCBX_LOCAL_LLDP_MIB:730 qed_dcbx_get_local_lldp_params(p_hwfn, p_params);731 break;732 default:733 DP_ERR(p_hwfn, "MIB read err, unknown mib type %d\n", type);734 return -EINVAL;735 }736 737 return 0;738}739 740static int741qed_dcbx_read_local_lldp_mib(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)742{743 struct qed_dcbx_mib_meta_data data;744 745 memset(&data, 0, sizeof(data));746 data.addr = p_hwfn->mcp_info->port_addr + offsetof(struct public_port,747 lldp_config_params);748 data.lldp_local = p_hwfn->p_dcbx_info->lldp_local;749 data.size = sizeof(struct lldp_config_params_s);750 qed_memcpy_from(p_hwfn, p_ptt, data.lldp_local, data.addr, data.size);751 752 return 0;753}754 755static int756qed_dcbx_read_remote_lldp_mib(struct qed_hwfn *p_hwfn,757 struct qed_ptt *p_ptt,758 enum qed_mib_read_type type)759{760 struct qed_dcbx_mib_meta_data data;761 int rc = 0;762 763 memset(&data, 0, sizeof(data));764 data.addr = p_hwfn->mcp_info->port_addr + offsetof(struct public_port,765 lldp_status_params);766 data.lldp_remote = p_hwfn->p_dcbx_info->lldp_remote;767 data.size = sizeof(struct lldp_status_params_s);768 rc = qed_dcbx_copy_mib(p_hwfn, p_ptt, &data, type);769 770 return rc;771}772 773static int774qed_dcbx_read_operational_mib(struct qed_hwfn *p_hwfn,775 struct qed_ptt *p_ptt,776 enum qed_mib_read_type type)777{778 struct qed_dcbx_mib_meta_data data;779 int rc = 0;780 781 memset(&data, 0, sizeof(data));782 data.addr = p_hwfn->mcp_info->port_addr +783 offsetof(struct public_port, operational_dcbx_mib);784 data.mib = &p_hwfn->p_dcbx_info->operational;785 data.size = sizeof(struct dcbx_mib);786 rc = qed_dcbx_copy_mib(p_hwfn, p_ptt, &data, type);787 788 return rc;789}790 791static int792qed_dcbx_read_remote_mib(struct qed_hwfn *p_hwfn,793 struct qed_ptt *p_ptt, enum qed_mib_read_type type)794{795 struct qed_dcbx_mib_meta_data data;796 int rc = 0;797 798 memset(&data, 0, sizeof(data));799 data.addr = p_hwfn->mcp_info->port_addr +800 offsetof(struct public_port, remote_dcbx_mib);801 data.mib = &p_hwfn->p_dcbx_info->remote;802 data.size = sizeof(struct dcbx_mib);803 rc = qed_dcbx_copy_mib(p_hwfn, p_ptt, &data, type);804 805 return rc;806}807 808static int809qed_dcbx_read_local_mib(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)810{811 struct qed_dcbx_mib_meta_data data;812 813 memset(&data, 0, sizeof(data));814 data.addr = p_hwfn->mcp_info->port_addr +815 offsetof(struct public_port, local_admin_dcbx_mib);816 data.local_admin = &p_hwfn->p_dcbx_info->local_admin;817 data.size = sizeof(struct dcbx_local_params);818 qed_memcpy_from(p_hwfn, p_ptt, data.local_admin, data.addr, data.size);819 820 return 0;821}822 823static int qed_dcbx_read_mib(struct qed_hwfn *p_hwfn,824 struct qed_ptt *p_ptt, enum qed_mib_read_type type)825{826 int rc = -EINVAL;827 828 switch (type) {829 case QED_DCBX_OPERATIONAL_MIB:830 rc = qed_dcbx_read_operational_mib(p_hwfn, p_ptt, type);831 break;832 case QED_DCBX_REMOTE_MIB:833 rc = qed_dcbx_read_remote_mib(p_hwfn, p_ptt, type);834 break;835 case QED_DCBX_LOCAL_MIB:836 rc = qed_dcbx_read_local_mib(p_hwfn, p_ptt);837 break;838 case QED_DCBX_REMOTE_LLDP_MIB:839 rc = qed_dcbx_read_remote_lldp_mib(p_hwfn, p_ptt, type);840 break;841 case QED_DCBX_LOCAL_LLDP_MIB:842 rc = qed_dcbx_read_local_lldp_mib(p_hwfn, p_ptt);843 break;844 default:845 DP_ERR(p_hwfn, "MIB read err, unknown mib type %d\n", type);846 }847 848 return rc;849}850 851static void qed_dcbx_aen(struct qed_hwfn *hwfn, u32 mib_type)852{853 struct qed_common_cb_ops *op = hwfn->cdev->protocol_ops.common;854 void *cookie = hwfn->cdev->ops_cookie;855 856 if (cookie && op->dcbx_aen)857 op->dcbx_aen(cookie, &hwfn->p_dcbx_info->get, mib_type);858}859 860/* Read updated MIB.861 * Reconfigure QM and invoke PF update ramrod command if operational MIB862 * change is detected.863 */864int865qed_dcbx_mib_update_event(struct qed_hwfn *p_hwfn,866 struct qed_ptt *p_ptt, enum qed_mib_read_type type)867{868 int rc = 0;869 870 rc = qed_dcbx_read_mib(p_hwfn, p_ptt, type);871 if (rc)872 return rc;873 874 if (type == QED_DCBX_OPERATIONAL_MIB) {875 rc = qed_dcbx_process_mib_info(p_hwfn, p_ptt);876 if (!rc) {877 /* reconfigure tcs of QM queues according878 * to negotiation results879 */880 qed_qm_reconf(p_hwfn, p_ptt);881 882 /* update storm FW with negotiation results */883 qed_sp_pf_update(p_hwfn);884 885 /* for roce PFs, we may want to enable/disable DPM886 * when DCBx change occurs887 */888 if (p_hwfn->hw_info.personality ==889 QED_PCI_ETH_ROCE)890 qed_roce_dpm_dcbx(p_hwfn, p_ptt);891 }892 }893 894 qed_dcbx_get_params(p_hwfn, &p_hwfn->p_dcbx_info->get, type);895 896 if (type == QED_DCBX_OPERATIONAL_MIB) {897 struct qed_dcbx_results *p_data;898 u16 val;899 900 /* Configure in NIG which protocols support EDPM and should901 * honor PFC.902 */903 p_data = &p_hwfn->p_dcbx_info->results;904 val = (0x1 << p_data->arr[DCBX_PROTOCOL_ROCE].tc) |905 (0x1 << p_data->arr[DCBX_PROTOCOL_ROCE_V2].tc);906 val <<= NIG_REG_TX_EDPM_CTRL_TX_EDPM_TC_EN_SHIFT;907 val |= NIG_REG_TX_EDPM_CTRL_TX_EDPM_EN;908 qed_wr(p_hwfn, p_ptt, NIG_REG_TX_EDPM_CTRL, val);909 }910 911 qed_dcbx_aen(p_hwfn, type);912 913 return rc;914}915 916int qed_dcbx_info_alloc(struct qed_hwfn *p_hwfn)917{918 p_hwfn->p_dcbx_info = kzalloc(sizeof(*p_hwfn->p_dcbx_info), GFP_KERNEL);919 if (!p_hwfn->p_dcbx_info)920 return -ENOMEM;921 922 return 0;923}924 925void qed_dcbx_info_free(struct qed_hwfn *p_hwfn)926{927 kfree(p_hwfn->p_dcbx_info);928 p_hwfn->p_dcbx_info = NULL;929}930 931static void qed_dcbx_update_protocol_data(struct protocol_dcb_data *p_data,932 struct qed_dcbx_results *p_src,933 enum dcbx_protocol_type type)934{935 p_data->dcb_enable_flag = p_src->arr[type].enable;936 p_data->dcb_priority = p_src->arr[type].priority;937 p_data->dcb_tc = p_src->arr[type].tc;938 p_data->dcb_dont_add_vlan0 = p_src->arr[type].dont_add_vlan0;939}940 941/* Set pf update ramrod command params */942void qed_dcbx_set_pf_update_params(struct qed_dcbx_results *p_src,943 struct pf_update_ramrod_data *p_dest)944{945 struct protocol_dcb_data *p_dcb_data;946 u8 update_flag;947 948 update_flag = p_src->arr[DCBX_PROTOCOL_FCOE].update;949 p_dest->update_fcoe_dcb_data_mode = update_flag;950 951 update_flag = p_src->arr[DCBX_PROTOCOL_ROCE].update;952 p_dest->update_roce_dcb_data_mode = update_flag;953 954 update_flag = p_src->arr[DCBX_PROTOCOL_ROCE_V2].update;955 p_dest->update_rroce_dcb_data_mode = update_flag;956 957 update_flag = p_src->arr[DCBX_PROTOCOL_ISCSI].update;958 p_dest->update_iscsi_dcb_data_mode = update_flag;959 update_flag = p_src->arr[DCBX_PROTOCOL_ETH].update;960 p_dest->update_eth_dcb_data_mode = update_flag;961 962 p_dcb_data = &p_dest->fcoe_dcb_data;963 qed_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_FCOE);964 p_dcb_data = &p_dest->roce_dcb_data;965 qed_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_ROCE);966 p_dcb_data = &p_dest->rroce_dcb_data;967 qed_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_ROCE_V2);968 p_dcb_data = &p_dest->iscsi_dcb_data;969 qed_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_ISCSI);970 p_dcb_data = &p_dest->eth_dcb_data;971 qed_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_ETH);972}973 974u8 qed_dcbx_get_priority_tc(struct qed_hwfn *p_hwfn, u8 pri)975{976 struct qed_dcbx_get *dcbx_info = &p_hwfn->p_dcbx_info->get;977 978 if (pri >= QED_MAX_PFC_PRIORITIES) {979 DP_ERR(p_hwfn, "Invalid priority %d\n", pri);980 return QED_DCBX_DEFAULT_TC;981 }982 983 if (!dcbx_info->operational.valid) {984 DP_VERBOSE(p_hwfn, QED_MSG_DCB,985 "Dcbx parameters not available\n");986 return QED_DCBX_DEFAULT_TC;987 }988 989 return dcbx_info->operational.params.ets_pri_tc_tbl[pri];990}991 992#ifdef CONFIG_DCB993static int qed_dcbx_query_params(struct qed_hwfn *p_hwfn,994 struct qed_dcbx_get *p_get,995 enum qed_mib_read_type type)996{997 struct qed_ptt *p_ptt;998 int rc;999 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 1013out:1014 qed_ptt_release(p_hwfn, p_ptt);1015 return rc;1016}1017 1018static void1019qed_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 else1030 *pfc &= ~DCBX_PFC_WILLING_MASK;1031 1032 if (p_params->pfc.enabled)1033 *pfc |= DCBX_PFC_ENABLED_MASK;1034 else1035 *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 1050static void1051qed_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 else1062 p_ets->flags &= ~DCBX_ETS_WILLING_MASK;1063 1064 if (p_params->ets_cbs)1065 p_ets->flags |= DCBX_ETS_CBS_MASK;1066 else1067 p_ets->flags &= ~DCBX_ETS_CBS_MASK;1068 1069 if (p_params->ets_enabled)1070 p_ets->flags |= DCBX_ETS_ENABLED_MASK;1071 else1072 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 the1084 * 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 1094static void1095qed_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 else1105 p_app->flags &= ~DCBX_APP_WILLING_MASK;1106 1107 if (p_params->app_valid)1108 p_app->flags |= DCBX_APP_ENABLED_MASK;1109 else1110 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 else1153 *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 1166static void1167qed_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 ¶ms->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 ¶ms->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 ¶ms->config.params, ieee);1199}1200 1201int 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, ¶m);1229 if (rc)1230 DP_NOTICE(p_hwfn, "Failed to send DCBX update request\n");1231 1232 return rc;1233}1234 1235int 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 1281static 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 1305static 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 1322static 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 1349static 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 1370static 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 1391static 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 1398static 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 1405static 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 1426static 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 1457static 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 1494static 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 1522static 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 1539static 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 1562static 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 1597static 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 1603static 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 1633static 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 1638static 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 1661static 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 1699static 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 1725static 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 1758static 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 1806static 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 1853static 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 else1869 *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 else1875 *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 else1881 *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 1895static 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 1943static 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 1962static 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 else1977 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 1988static 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 2010static 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 2032static 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 2075static 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 2080static 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 2122static 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 2165static 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 2170static 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 2217static int2218qed_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 2223static int2224qed_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 2229static 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 2251static 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 2302static 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 2375const 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#endif2415