qed_dcbx.c (65475B)
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2/* QLogic qed NIC Driver 3 * Copyright (c) 2015-2017 QLogic Corporation 4 * 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_DCB 23#include <linux/qed/qed_eth_if.h> 24#endif 25 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 0xFF 34 35/* Get Traffic Class from priority traffic class table, 4 bits represent 36 * 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 else 90 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 else 103 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 else 115 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 else 127 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 else 140 port = qed_dcbx_app_port(app_info_bitmap); 141 142 return !!(port && (proto_id == QED_UDP_PORT_TYPE_ROCE_V2)); 143} 144 145static void 146qed_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 void 166qed_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 else 179 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 void 198qed_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 bool 221qed_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 for 247 * reconfiguring QM. Get protocol specific data for PF update ramrod command. 248 */ 249static int 250qed_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 gets 282 * vlan information per packet. For other protocols, 283 * should be set according to the dcbx_enabled 284 * indication, but we only got here if there was an 285 * 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 fields 304 * with default info when corresponding APP TLV's are not detected. 305 * The enabled field has a different logic for ethernet as only for 306 * ethernet dcb should disabled by default, as the information arrives 307 * 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 for 324 * reconfiguring QM. Get protocol specific data for PF update ramrod command. 325 */ 326static int 327qed_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 int 371qed_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 are 381 * 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 void 415qed_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 void 455qed_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 void 521qed_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 void 546qed_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 are 575 * 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 void 593qed_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 void 605qed_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 void 617qed_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 void 629qed_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 negotiation 642 * was successfuly performed 643 */ 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 void 685qed_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 void 699qed_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 int 713qed_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 int 741qed_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 int 756qed_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 int 774qed_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 int 792qed_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 int 809qed_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 MIB 862 * change is detected. 863 */ 864int 865qed_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 according 878 * to negotiation results 879 */ 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 DPM 886 * when DCBx change occurs 887 */ 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 should 901 * 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_DCB 993static 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 void 1019qed_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 1050static void 1051qed_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 1094static void 1095qed_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 1166static void 1167qed_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 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 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 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 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 int 2218qed_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 int 2224qed_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#endif