1316485Sdavidcs/* 2316485Sdavidcs * Copyright (c) 2017-2018 Cavium, Inc. 3316485Sdavidcs * All rights reserved. 4316485Sdavidcs * 5316485Sdavidcs * Redistribution and use in source and binary forms, with or without 6316485Sdavidcs * modification, are permitted provided that the following conditions 7316485Sdavidcs * are met: 8316485Sdavidcs * 9316485Sdavidcs * 1. Redistributions of source code must retain the above copyright 10316485Sdavidcs * notice, this list of conditions and the following disclaimer. 11316485Sdavidcs * 2. Redistributions in binary form must reproduce the above copyright 12316485Sdavidcs * notice, this list of conditions and the following disclaimer in the 13316485Sdavidcs * documentation and/or other materials provided with the distribution. 14316485Sdavidcs * 15316485Sdavidcs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16316485Sdavidcs * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17316485Sdavidcs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18316485Sdavidcs * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19316485Sdavidcs * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20316485Sdavidcs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21316485Sdavidcs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22316485Sdavidcs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23316485Sdavidcs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24316485Sdavidcs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25316485Sdavidcs * POSSIBILITY OF SUCH DAMAGE. 26316485Sdavidcs */ 27316485Sdavidcs 28316485Sdavidcs/* 29316485Sdavidcs * File : ecore_dcbx.c 30316485Sdavidcs */ 31316485Sdavidcs#include <sys/cdefs.h> 32316485Sdavidcs__FBSDID("$FreeBSD: stable/10/sys/dev/qlnx/qlnxe/ecore_dcbx.c 337519 2018-08-09 01:39:47Z davidcs $"); 33316485Sdavidcs 34316485Sdavidcs#include "bcm_osal.h" 35316485Sdavidcs#include "ecore.h" 36316485Sdavidcs#include "ecore_sp_commands.h" 37316485Sdavidcs#include "ecore_dcbx.h" 38316485Sdavidcs#include "ecore_cxt.h" 39316485Sdavidcs#include "ecore_gtt_reg_addr.h" 40316485Sdavidcs#include "ecore_iro.h" 41316485Sdavidcs#ifdef CONFIG_ECORE_ROCE 42337519Sdavidcs#include "ecore_rdma.h" 43316485Sdavidcs#endif 44316485Sdavidcs#include "ecore_iov_api.h" 45316485Sdavidcs 46316485Sdavidcs#define ECORE_DCBX_MAX_MIB_READ_TRY (100) 47316485Sdavidcs#define ECORE_ETH_TYPE_DEFAULT (0) 48316485Sdavidcs#define ECORE_ETH_TYPE_ROCE (0x8915) 49316485Sdavidcs#define ECORE_UDP_PORT_TYPE_ROCE_V2 (0x12B7) 50316485Sdavidcs#define ECORE_ETH_TYPE_FCOE (0x8906) 51316485Sdavidcs#define ECORE_TCP_PORT_ISCSI (0xCBC) 52316485Sdavidcs 53316485Sdavidcs#define ECORE_DCBX_INVALID_PRIORITY 0xFF 54316485Sdavidcs 55316485Sdavidcs/* Get Traffic Class from priority traffic class table, 4 bits represent 56316485Sdavidcs * the traffic class corresponding to the priority. 57316485Sdavidcs */ 58316485Sdavidcs#define ECORE_DCBX_PRIO2TC(prio_tc_tbl, prio) \ 59316485Sdavidcs ((u32)(prio_tc_tbl >> ((7 - prio) * 4)) & 0x7) 60316485Sdavidcs 61316485Sdavidcsstatic bool ecore_dcbx_app_ethtype(u32 app_info_bitmap) 62316485Sdavidcs{ 63320162Sdavidcs return !!(GET_MFW_FIELD(app_info_bitmap, DCBX_APP_SF) == 64316485Sdavidcs DCBX_APP_SF_ETHTYPE); 65316485Sdavidcs} 66316485Sdavidcs 67316485Sdavidcsstatic bool ecore_dcbx_ieee_app_ethtype(u32 app_info_bitmap) 68316485Sdavidcs{ 69320162Sdavidcs u8 mfw_val = GET_MFW_FIELD(app_info_bitmap, DCBX_APP_SF_IEEE); 70316485Sdavidcs 71316485Sdavidcs /* Old MFW */ 72316485Sdavidcs if (mfw_val == DCBX_APP_SF_IEEE_RESERVED) 73316485Sdavidcs return ecore_dcbx_app_ethtype(app_info_bitmap); 74316485Sdavidcs 75316485Sdavidcs return !!(mfw_val == DCBX_APP_SF_IEEE_ETHTYPE); 76316485Sdavidcs} 77316485Sdavidcs 78316485Sdavidcsstatic bool ecore_dcbx_app_port(u32 app_info_bitmap) 79316485Sdavidcs{ 80320162Sdavidcs return !!(GET_MFW_FIELD(app_info_bitmap, DCBX_APP_SF) == 81316485Sdavidcs DCBX_APP_SF_PORT); 82316485Sdavidcs} 83316485Sdavidcs 84316485Sdavidcsstatic bool ecore_dcbx_ieee_app_port(u32 app_info_bitmap, u8 type) 85316485Sdavidcs{ 86320162Sdavidcs u8 mfw_val = GET_MFW_FIELD(app_info_bitmap, DCBX_APP_SF_IEEE); 87316485Sdavidcs 88316485Sdavidcs /* Old MFW */ 89316485Sdavidcs if (mfw_val == DCBX_APP_SF_IEEE_RESERVED) 90316485Sdavidcs return ecore_dcbx_app_port(app_info_bitmap); 91316485Sdavidcs 92316485Sdavidcs return !!(mfw_val == type || mfw_val == DCBX_APP_SF_IEEE_TCP_UDP_PORT); 93316485Sdavidcs} 94316485Sdavidcs 95316485Sdavidcsstatic bool ecore_dcbx_default_tlv(u32 app_info_bitmap, u16 proto_id, bool ieee) 96316485Sdavidcs{ 97316485Sdavidcs bool ethtype; 98316485Sdavidcs 99316485Sdavidcs if (ieee) 100316485Sdavidcs ethtype = ecore_dcbx_ieee_app_ethtype(app_info_bitmap); 101316485Sdavidcs else 102316485Sdavidcs ethtype = ecore_dcbx_app_ethtype(app_info_bitmap); 103316485Sdavidcs 104316485Sdavidcs return !!(ethtype && (proto_id == ECORE_ETH_TYPE_DEFAULT)); 105316485Sdavidcs} 106316485Sdavidcs 107316485Sdavidcsstatic bool ecore_dcbx_iscsi_tlv(u32 app_info_bitmap, u16 proto_id, bool ieee) 108316485Sdavidcs{ 109316485Sdavidcs bool port; 110316485Sdavidcs 111316485Sdavidcs if (ieee) 112316485Sdavidcs port = ecore_dcbx_ieee_app_port(app_info_bitmap, 113316485Sdavidcs DCBX_APP_SF_IEEE_TCP_PORT); 114316485Sdavidcs else 115316485Sdavidcs port = ecore_dcbx_app_port(app_info_bitmap); 116316485Sdavidcs 117316485Sdavidcs return !!(port && (proto_id == ECORE_TCP_PORT_ISCSI)); 118316485Sdavidcs} 119316485Sdavidcs 120316485Sdavidcsstatic bool ecore_dcbx_fcoe_tlv(u32 app_info_bitmap, u16 proto_id, bool ieee) 121316485Sdavidcs{ 122316485Sdavidcs bool ethtype; 123316485Sdavidcs 124316485Sdavidcs if (ieee) 125316485Sdavidcs ethtype = ecore_dcbx_ieee_app_ethtype(app_info_bitmap); 126316485Sdavidcs else 127316485Sdavidcs ethtype = ecore_dcbx_app_ethtype(app_info_bitmap); 128316485Sdavidcs 129316485Sdavidcs return !!(ethtype && (proto_id == ECORE_ETH_TYPE_FCOE)); 130316485Sdavidcs} 131316485Sdavidcs 132316485Sdavidcsstatic bool ecore_dcbx_roce_tlv(u32 app_info_bitmap, u16 proto_id, bool ieee) 133316485Sdavidcs{ 134316485Sdavidcs bool ethtype; 135316485Sdavidcs 136316485Sdavidcs if (ieee) 137316485Sdavidcs ethtype = ecore_dcbx_ieee_app_ethtype(app_info_bitmap); 138316485Sdavidcs else 139316485Sdavidcs ethtype = ecore_dcbx_app_ethtype(app_info_bitmap); 140316485Sdavidcs 141316485Sdavidcs return !!(ethtype && (proto_id == ECORE_ETH_TYPE_ROCE)); 142316485Sdavidcs} 143316485Sdavidcs 144316485Sdavidcsstatic bool ecore_dcbx_roce_v2_tlv(u32 app_info_bitmap, u16 proto_id, bool ieee) 145316485Sdavidcs{ 146316485Sdavidcs bool port; 147316485Sdavidcs 148316485Sdavidcs if (ieee) 149316485Sdavidcs port = ecore_dcbx_ieee_app_port(app_info_bitmap, 150316485Sdavidcs DCBX_APP_SF_IEEE_UDP_PORT); 151316485Sdavidcs else 152316485Sdavidcs port = ecore_dcbx_app_port(app_info_bitmap); 153316485Sdavidcs 154316485Sdavidcs return !!(port && (proto_id == ECORE_UDP_PORT_TYPE_ROCE_V2)); 155316485Sdavidcs} 156316485Sdavidcs 157316485Sdavidcsstatic bool ecore_dcbx_iwarp_tlv(struct ecore_hwfn *p_hwfn, u32 app_info_bitmap, 158316485Sdavidcs u16 proto_id, bool ieee) 159316485Sdavidcs{ 160316485Sdavidcs bool port; 161316485Sdavidcs 162316485Sdavidcs if (!p_hwfn->p_dcbx_info->iwarp_port) 163316485Sdavidcs return false; 164316485Sdavidcs 165316485Sdavidcs if (ieee) 166316485Sdavidcs port = ecore_dcbx_ieee_app_port(app_info_bitmap, 167316485Sdavidcs DCBX_APP_SF_IEEE_TCP_PORT); 168316485Sdavidcs else 169316485Sdavidcs port = ecore_dcbx_app_port(app_info_bitmap); 170316485Sdavidcs 171316485Sdavidcs return !!(port && (proto_id == p_hwfn->p_dcbx_info->iwarp_port)); 172316485Sdavidcs} 173316485Sdavidcs 174316485Sdavidcsstatic void 175316485Sdavidcsecore_dcbx_dp_protocol(struct ecore_hwfn *p_hwfn, 176316485Sdavidcs struct ecore_dcbx_results *p_data) 177316485Sdavidcs{ 178316485Sdavidcs enum dcbx_protocol_type id; 179316485Sdavidcs int i; 180316485Sdavidcs 181316485Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "DCBX negotiated: %d\n", 182316485Sdavidcs p_data->dcbx_enabled); 183316485Sdavidcs 184316485Sdavidcs for (i = 0; i < OSAL_ARRAY_SIZE(ecore_dcbx_app_update); i++) { 185316485Sdavidcs id = ecore_dcbx_app_update[i].id; 186316485Sdavidcs 187316485Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, 188316485Sdavidcs "%s info: update %d, enable %d, prio %d, tc %d, num_active_tc %d dscp_enable = %d dscp_val = %d\n", 189316485Sdavidcs ecore_dcbx_app_update[i].name, p_data->arr[id].update, 190316485Sdavidcs p_data->arr[id].enable, p_data->arr[id].priority, 191316485Sdavidcs p_data->arr[id].tc, p_hwfn->hw_info.num_active_tc, 192316485Sdavidcs p_data->arr[id].dscp_enable, 193316485Sdavidcs p_data->arr[id].dscp_val); 194316485Sdavidcs } 195316485Sdavidcs} 196316485Sdavidcs 197337519Sdavidcsu8 ecore_dcbx_get_dscp_value(struct ecore_hwfn *p_hwfn, u8 pri) 198337519Sdavidcs{ 199337519Sdavidcs struct ecore_dcbx_dscp_params *dscp = &p_hwfn->p_dcbx_info->get.dscp; 200337519Sdavidcs u8 i; 201337519Sdavidcs 202337519Sdavidcs if (!dscp->enabled) 203337519Sdavidcs return ECORE_DCBX_DSCP_DISABLED; 204337519Sdavidcs 205337519Sdavidcs for (i = 0; i < ECORE_DCBX_DSCP_SIZE; i++) 206337519Sdavidcs if (pri == dscp->dscp_pri_map[i]) 207337519Sdavidcs return i; 208337519Sdavidcs 209337519Sdavidcs return ECORE_DCBX_DSCP_DISABLED; 210337519Sdavidcs} 211337519Sdavidcs 212316485Sdavidcsstatic void 213316485Sdavidcsecore_dcbx_set_params(struct ecore_dcbx_results *p_data, 214337519Sdavidcs struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 215316485Sdavidcs bool enable, u8 prio, u8 tc, 216316485Sdavidcs enum dcbx_protocol_type type, 217316485Sdavidcs enum ecore_pci_personality personality) 218316485Sdavidcs{ 219316485Sdavidcs /* PF update ramrod data */ 220316485Sdavidcs p_data->arr[type].enable = enable; 221316485Sdavidcs p_data->arr[type].priority = prio; 222316485Sdavidcs p_data->arr[type].tc = tc; 223337519Sdavidcs p_data->arr[type].dscp_val = ecore_dcbx_get_dscp_value(p_hwfn, prio); 224337519Sdavidcs if (p_data->arr[type].dscp_val == ECORE_DCBX_DSCP_DISABLED) { 225337519Sdavidcs p_data->arr[type].dscp_enable = false; 226337519Sdavidcs p_data->arr[type].dscp_val = 0; 227337519Sdavidcs } else 228337519Sdavidcs p_data->arr[type].dscp_enable = enable; 229316485Sdavidcs 230337519Sdavidcs p_data->arr[type].update = UPDATE_DCB_DSCP; 231316485Sdavidcs 232337519Sdavidcs /* Do not add valn tag 0 when DCB is enabled and port is in UFP mode */ 233337519Sdavidcs if (OSAL_TEST_BIT(ECORE_MF_UFP_SPECIFIC, &p_hwfn->p_dev->mf_bits)) 234337519Sdavidcs p_data->arr[type].dont_add_vlan0 = true; 235316485Sdavidcs 236316485Sdavidcs /* QM reconf data */ 237316485Sdavidcs if (p_hwfn->hw_info.personality == personality) 238316485Sdavidcs p_hwfn->hw_info.offload_tc = tc; 239337519Sdavidcs 240337519Sdavidcs /* Configure dcbx vlan priority in doorbell block for roce EDPM */ 241337519Sdavidcs if (OSAL_TEST_BIT(ECORE_MF_UFP_SPECIFIC, &p_hwfn->p_dev->mf_bits) && 242337519Sdavidcs (type == DCBX_PROTOCOL_ROCE)) { 243337519Sdavidcs ecore_wr(p_hwfn, p_ptt, DORQ_REG_TAG1_OVRD_MODE, 1); 244337519Sdavidcs ecore_wr(p_hwfn, p_ptt, DORQ_REG_PF_PCP_BB_K2, prio << 1); 245337519Sdavidcs } 246316485Sdavidcs} 247316485Sdavidcs 248316485Sdavidcs/* Update app protocol data and hw_info fields with the TLV info */ 249316485Sdavidcsstatic void 250316485Sdavidcsecore_dcbx_update_app_info(struct ecore_dcbx_results *p_data, 251337519Sdavidcs struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 252316485Sdavidcs bool enable, u8 prio, u8 tc, 253316485Sdavidcs enum dcbx_protocol_type type) 254316485Sdavidcs{ 255316485Sdavidcs enum ecore_pci_personality personality; 256316485Sdavidcs enum dcbx_protocol_type id; 257316485Sdavidcs int i; 258316485Sdavidcs 259316485Sdavidcs for (i = 0; i < OSAL_ARRAY_SIZE(ecore_dcbx_app_update); i++) { 260316485Sdavidcs id = ecore_dcbx_app_update[i].id; 261316485Sdavidcs 262316485Sdavidcs if (type != id) 263316485Sdavidcs continue; 264316485Sdavidcs 265316485Sdavidcs personality = ecore_dcbx_app_update[i].personality; 266316485Sdavidcs 267337519Sdavidcs ecore_dcbx_set_params(p_data, p_hwfn, p_ptt, enable, 268316485Sdavidcs prio, tc, type, personality); 269316485Sdavidcs } 270316485Sdavidcs} 271316485Sdavidcs 272316485Sdavidcsstatic enum _ecore_status_t 273316485Sdavidcsecore_dcbx_get_app_priority(u8 pri_bitmap, u8 *priority) 274316485Sdavidcs{ 275316485Sdavidcs u32 pri_mask, pri = ECORE_MAX_PFC_PRIORITIES; 276316485Sdavidcs u32 index = ECORE_MAX_PFC_PRIORITIES - 1; 277316485Sdavidcs enum _ecore_status_t rc = ECORE_SUCCESS; 278316485Sdavidcs 279316485Sdavidcs /* Bitmap 1 corresponds to priority 0, return priority 0 */ 280316485Sdavidcs if (pri_bitmap == 1) { 281316485Sdavidcs *priority = 0; 282316485Sdavidcs return rc; 283316485Sdavidcs } 284316485Sdavidcs 285316485Sdavidcs /* Choose the highest priority */ 286316485Sdavidcs while ((ECORE_MAX_PFC_PRIORITIES == pri) && index) { 287316485Sdavidcs pri_mask = 1 << index; 288316485Sdavidcs if (pri_bitmap & pri_mask) 289316485Sdavidcs pri = index; 290316485Sdavidcs index--; 291316485Sdavidcs } 292316485Sdavidcs 293316485Sdavidcs if (pri < ECORE_MAX_PFC_PRIORITIES) 294316485Sdavidcs *priority = (u8)pri; 295316485Sdavidcs else 296316485Sdavidcs rc = ECORE_INVAL; 297316485Sdavidcs 298316485Sdavidcs return rc; 299316485Sdavidcs} 300316485Sdavidcs 301316485Sdavidcsstatic bool 302316485Sdavidcsecore_dcbx_get_app_protocol_type(struct ecore_hwfn *p_hwfn, 303316485Sdavidcs u32 app_prio_bitmap, u16 id, 304316485Sdavidcs enum dcbx_protocol_type *type, bool ieee) 305316485Sdavidcs{ 306316485Sdavidcs if (ecore_dcbx_fcoe_tlv(app_prio_bitmap, id, ieee)) { 307316485Sdavidcs *type = DCBX_PROTOCOL_FCOE; 308316485Sdavidcs } else if (ecore_dcbx_roce_tlv(app_prio_bitmap, id, ieee)) { 309316485Sdavidcs *type = DCBX_PROTOCOL_ROCE; 310316485Sdavidcs } else if (ecore_dcbx_iscsi_tlv(app_prio_bitmap, id, ieee)) { 311316485Sdavidcs *type = DCBX_PROTOCOL_ISCSI; 312316485Sdavidcs } else if (ecore_dcbx_default_tlv(app_prio_bitmap, id, ieee)) { 313316485Sdavidcs *type = DCBX_PROTOCOL_ETH; 314316485Sdavidcs } else if (ecore_dcbx_roce_v2_tlv(app_prio_bitmap, id, ieee)) { 315316485Sdavidcs *type = DCBX_PROTOCOL_ROCE_V2; 316316485Sdavidcs } else if (ecore_dcbx_iwarp_tlv(p_hwfn, app_prio_bitmap, id, ieee)) { 317316485Sdavidcs *type = DCBX_PROTOCOL_IWARP; 318316485Sdavidcs } else { 319316485Sdavidcs *type = DCBX_MAX_PROTOCOL_TYPE; 320337519Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, 321337519Sdavidcs "No action required, App TLV entry = 0x%x\n", 322337519Sdavidcs app_prio_bitmap); 323316485Sdavidcs return false; 324316485Sdavidcs } 325316485Sdavidcs 326316485Sdavidcs return true; 327316485Sdavidcs} 328316485Sdavidcs 329337519Sdavidcs/* Parse app TLV's to update TC information in hw_info structure for 330316485Sdavidcs * reconfiguring QM. Get protocol specific data for PF update ramrod command. 331316485Sdavidcs */ 332316485Sdavidcsstatic enum _ecore_status_t 333337519Sdavidcsecore_dcbx_process_tlv(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 334316485Sdavidcs struct ecore_dcbx_results *p_data, 335316485Sdavidcs struct dcbx_app_priority_entry *p_tbl, u32 pri_tc_tbl, 336316485Sdavidcs int count, u8 dcbx_version) 337316485Sdavidcs{ 338316485Sdavidcs enum dcbx_protocol_type type; 339337519Sdavidcs bool enable, ieee, eth_tlv; 340316485Sdavidcs u8 tc, priority_map; 341316485Sdavidcs u16 protocol_id; 342316485Sdavidcs u8 priority; 343316485Sdavidcs enum _ecore_status_t rc = ECORE_SUCCESS; 344316485Sdavidcs int i; 345316485Sdavidcs 346316485Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, 347316485Sdavidcs "Num APP entries = %d pri_tc_tbl = 0x%x dcbx_version = %u\n", 348316485Sdavidcs count, pri_tc_tbl, dcbx_version); 349316485Sdavidcs 350316485Sdavidcs ieee = (dcbx_version == DCBX_CONFIG_VERSION_IEEE); 351337519Sdavidcs eth_tlv = false; 352316485Sdavidcs /* Parse APP TLV */ 353316485Sdavidcs for (i = 0; i < count; i++) { 354320162Sdavidcs protocol_id = GET_MFW_FIELD(p_tbl[i].entry, 355320162Sdavidcs DCBX_APP_PROTOCOL_ID); 356320162Sdavidcs priority_map = GET_MFW_FIELD(p_tbl[i].entry, DCBX_APP_PRI_MAP); 357316485Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "Id = 0x%x pri_map = %u\n", 358316485Sdavidcs protocol_id, priority_map); 359316485Sdavidcs rc = ecore_dcbx_get_app_priority(priority_map, &priority); 360316485Sdavidcs if (rc == ECORE_INVAL) { 361316485Sdavidcs DP_ERR(p_hwfn, "Invalid priority\n"); 362316485Sdavidcs return ECORE_INVAL; 363316485Sdavidcs } 364316485Sdavidcs 365316485Sdavidcs tc = ECORE_DCBX_PRIO2TC(pri_tc_tbl, priority); 366316485Sdavidcs if (ecore_dcbx_get_app_protocol_type(p_hwfn, p_tbl[i].entry, 367316485Sdavidcs protocol_id, &type, 368316485Sdavidcs ieee)) { 369316485Sdavidcs /* ETH always have the enable bit reset, as it gets 370316485Sdavidcs * vlan information per packet. For other protocols, 371316485Sdavidcs * should be set according to the dcbx_enabled 372316485Sdavidcs * indication, but we only got here if there was an 373316485Sdavidcs * app tlv for the protocol, so dcbx must be enabled. 374316485Sdavidcs */ 375337519Sdavidcs if (type == DCBX_PROTOCOL_ETH) { 376337519Sdavidcs enable = false; 377337519Sdavidcs eth_tlv = true; 378337519Sdavidcs } else 379337519Sdavidcs enable = true; 380316485Sdavidcs 381337519Sdavidcs ecore_dcbx_update_app_info(p_data, p_hwfn, p_ptt, 382337519Sdavidcs enable, priority, tc, type); 383316485Sdavidcs } 384316485Sdavidcs } 385316485Sdavidcs 386337519Sdavidcs /* If Eth TLV is not detected, use UFP TC as default TC */ 387337519Sdavidcs if (OSAL_TEST_BIT(ECORE_MF_UFP_SPECIFIC, 388337519Sdavidcs &p_hwfn->p_dev->mf_bits) && !eth_tlv) 389337519Sdavidcs p_data->arr[DCBX_PROTOCOL_ETH].tc = p_hwfn->ufp_info.tc; 390337519Sdavidcs 391316485Sdavidcs /* Update ramrod protocol data and hw_info fields 392316485Sdavidcs * with default info when corresponding APP TLV's are not detected. 393316485Sdavidcs * The enabled field has a different logic for ethernet as only for 394316485Sdavidcs * ethernet dcb should disabled by default, as the information arrives 395316485Sdavidcs * from the OS (unless an explicit app tlv was present). 396316485Sdavidcs */ 397316485Sdavidcs tc = p_data->arr[DCBX_PROTOCOL_ETH].tc; 398316485Sdavidcs priority = p_data->arr[DCBX_PROTOCOL_ETH].priority; 399316485Sdavidcs for (type = 0; type < DCBX_MAX_PROTOCOL_TYPE; type++) { 400316485Sdavidcs if (p_data->arr[type].update) 401316485Sdavidcs continue; 402316485Sdavidcs 403337519Sdavidcs /* if no app tlv was present, don't override in FW */ 404337519Sdavidcs ecore_dcbx_update_app_info(p_data, p_hwfn, p_ptt, false, 405316485Sdavidcs priority, tc, type); 406316485Sdavidcs } 407316485Sdavidcs 408316485Sdavidcs return ECORE_SUCCESS; 409316485Sdavidcs} 410316485Sdavidcs 411316485Sdavidcs/* Parse app TLV's to update TC information in hw_info structure for 412316485Sdavidcs * reconfiguring QM. Get protocol specific data for PF update ramrod command. 413316485Sdavidcs */ 414316485Sdavidcsstatic enum _ecore_status_t 415337519Sdavidcsecore_dcbx_process_mib_info(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt) 416316485Sdavidcs{ 417316485Sdavidcs struct dcbx_app_priority_feature *p_app; 418320162Sdavidcs struct dcbx_app_priority_entry *p_tbl; 419316485Sdavidcs struct ecore_dcbx_results data = { 0 }; 420316485Sdavidcs struct dcbx_ets_feature *p_ets; 421316485Sdavidcs struct ecore_hw_info *p_info; 422316485Sdavidcs u32 pri_tc_tbl, flags; 423316485Sdavidcs u8 dcbx_version; 424316485Sdavidcs int num_entries; 425320162Sdavidcs enum _ecore_status_t rc = ECORE_SUCCESS; 426316485Sdavidcs 427316485Sdavidcs flags = p_hwfn->p_dcbx_info->operational.flags; 428320162Sdavidcs dcbx_version = GET_MFW_FIELD(flags, DCBX_CONFIG_VERSION); 429316485Sdavidcs 430316485Sdavidcs p_app = &p_hwfn->p_dcbx_info->operational.features.app; 431316485Sdavidcs p_tbl = p_app->app_pri_tbl; 432316485Sdavidcs 433316485Sdavidcs p_ets = &p_hwfn->p_dcbx_info->operational.features.ets; 434316485Sdavidcs pri_tc_tbl = p_ets->pri_tc_tbl[0]; 435316485Sdavidcs 436316485Sdavidcs p_info = &p_hwfn->hw_info; 437320162Sdavidcs num_entries = GET_MFW_FIELD(p_app->flags, DCBX_APP_NUM_ENTRIES); 438316485Sdavidcs 439337519Sdavidcs rc = ecore_dcbx_process_tlv(p_hwfn, p_ptt, &data, p_tbl, pri_tc_tbl, 440316485Sdavidcs num_entries, dcbx_version); 441316485Sdavidcs if (rc != ECORE_SUCCESS) 442316485Sdavidcs return rc; 443316485Sdavidcs 444320162Sdavidcs p_info->num_active_tc = GET_MFW_FIELD(p_ets->flags, DCBX_ETS_MAX_TCS); 445320162Sdavidcs p_hwfn->qm_info.ooo_tc = GET_MFW_FIELD(p_ets->flags, DCBX_OOO_TC); 446316485Sdavidcs data.pf_id = p_hwfn->rel_pf_id; 447316485Sdavidcs data.dcbx_enabled = !!dcbx_version; 448316485Sdavidcs 449316485Sdavidcs ecore_dcbx_dp_protocol(p_hwfn, &data); 450316485Sdavidcs 451316485Sdavidcs OSAL_MEMCPY(&p_hwfn->p_dcbx_info->results, &data, 452316485Sdavidcs sizeof(struct ecore_dcbx_results)); 453316485Sdavidcs 454316485Sdavidcs return ECORE_SUCCESS; 455316485Sdavidcs} 456316485Sdavidcs 457316485Sdavidcsstatic enum _ecore_status_t 458316485Sdavidcsecore_dcbx_copy_mib(struct ecore_hwfn *p_hwfn, 459316485Sdavidcs struct ecore_ptt *p_ptt, 460316485Sdavidcs struct ecore_dcbx_mib_meta_data *p_data, 461316485Sdavidcs enum ecore_mib_read_type type) 462316485Sdavidcs{ 463316485Sdavidcs u32 prefix_seq_num, suffix_seq_num; 464316485Sdavidcs int read_count = 0; 465320162Sdavidcs enum _ecore_status_t rc = ECORE_SUCCESS; 466316485Sdavidcs 467316485Sdavidcs /* The data is considered to be valid only if both sequence numbers are 468316485Sdavidcs * the same. 469316485Sdavidcs */ 470316485Sdavidcs do { 471316485Sdavidcs if (type == ECORE_DCBX_REMOTE_LLDP_MIB) { 472316485Sdavidcs ecore_memcpy_from(p_hwfn, p_ptt, p_data->lldp_remote, 473316485Sdavidcs p_data->addr, p_data->size); 474316485Sdavidcs prefix_seq_num = p_data->lldp_remote->prefix_seq_num; 475316485Sdavidcs suffix_seq_num = p_data->lldp_remote->suffix_seq_num; 476337519Sdavidcs } else if (type == ECORE_DCBX_LLDP_TLVS) { 477337519Sdavidcs ecore_memcpy_from(p_hwfn, p_ptt, p_data->lldp_tlvs, 478337519Sdavidcs p_data->addr, p_data->size); 479337519Sdavidcs prefix_seq_num = p_data->lldp_tlvs->prefix_seq_num; 480337519Sdavidcs suffix_seq_num = p_data->lldp_tlvs->suffix_seq_num; 481337519Sdavidcs 482316485Sdavidcs } else { 483316485Sdavidcs ecore_memcpy_from(p_hwfn, p_ptt, p_data->mib, 484316485Sdavidcs p_data->addr, p_data->size); 485316485Sdavidcs prefix_seq_num = p_data->mib->prefix_seq_num; 486316485Sdavidcs suffix_seq_num = p_data->mib->suffix_seq_num; 487316485Sdavidcs } 488316485Sdavidcs read_count++; 489316485Sdavidcs 490316485Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, 491316485Sdavidcs "mib type = %d, try count = %d prefix seq num = %d suffix seq num = %d\n", 492316485Sdavidcs type, read_count, prefix_seq_num, suffix_seq_num); 493316485Sdavidcs } while ((prefix_seq_num != suffix_seq_num) && 494316485Sdavidcs (read_count < ECORE_DCBX_MAX_MIB_READ_TRY)); 495316485Sdavidcs 496316485Sdavidcs if (read_count >= ECORE_DCBX_MAX_MIB_READ_TRY) { 497316485Sdavidcs DP_ERR(p_hwfn, 498316485Sdavidcs "MIB read err, mib type = %d, try count = %d prefix seq num = %d suffix seq num = %d\n", 499316485Sdavidcs type, read_count, prefix_seq_num, suffix_seq_num); 500316485Sdavidcs rc = ECORE_IO; 501316485Sdavidcs } 502316485Sdavidcs 503316485Sdavidcs return rc; 504316485Sdavidcs} 505316485Sdavidcs 506316485Sdavidcsstatic void 507316485Sdavidcsecore_dcbx_get_priority_info(struct ecore_hwfn *p_hwfn, 508316485Sdavidcs struct ecore_dcbx_app_prio *p_prio, 509316485Sdavidcs struct ecore_dcbx_results *p_results) 510316485Sdavidcs{ 511316485Sdavidcs u8 val; 512316485Sdavidcs 513316485Sdavidcs p_prio->roce = ECORE_DCBX_INVALID_PRIORITY; 514316485Sdavidcs p_prio->roce_v2 = ECORE_DCBX_INVALID_PRIORITY; 515316485Sdavidcs p_prio->iscsi = ECORE_DCBX_INVALID_PRIORITY; 516316485Sdavidcs p_prio->fcoe = ECORE_DCBX_INVALID_PRIORITY; 517316485Sdavidcs 518316485Sdavidcs if (p_results->arr[DCBX_PROTOCOL_ROCE].update && 519316485Sdavidcs p_results->arr[DCBX_PROTOCOL_ROCE].enable) 520316485Sdavidcs p_prio->roce = p_results->arr[DCBX_PROTOCOL_ROCE].priority; 521316485Sdavidcs 522316485Sdavidcs if (p_results->arr[DCBX_PROTOCOL_ROCE_V2].update && 523316485Sdavidcs p_results->arr[DCBX_PROTOCOL_ROCE_V2].enable) { 524316485Sdavidcs val = p_results->arr[DCBX_PROTOCOL_ROCE_V2].priority; 525316485Sdavidcs p_prio->roce_v2 = val; 526316485Sdavidcs } 527316485Sdavidcs 528316485Sdavidcs if (p_results->arr[DCBX_PROTOCOL_ISCSI].update && 529316485Sdavidcs p_results->arr[DCBX_PROTOCOL_ISCSI].enable) 530316485Sdavidcs p_prio->iscsi = p_results->arr[DCBX_PROTOCOL_ISCSI].priority; 531316485Sdavidcs 532316485Sdavidcs if (p_results->arr[DCBX_PROTOCOL_FCOE].update && 533316485Sdavidcs p_results->arr[DCBX_PROTOCOL_FCOE].enable) 534316485Sdavidcs p_prio->fcoe = p_results->arr[DCBX_PROTOCOL_FCOE].priority; 535316485Sdavidcs 536316485Sdavidcs if (p_results->arr[DCBX_PROTOCOL_ETH].update && 537316485Sdavidcs p_results->arr[DCBX_PROTOCOL_ETH].enable) 538316485Sdavidcs p_prio->eth = p_results->arr[DCBX_PROTOCOL_ETH].priority; 539316485Sdavidcs 540316485Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, 541316485Sdavidcs "Priorities: iscsi %d, roce %d, roce v2 %d, fcoe %d, eth %d\n", 542316485Sdavidcs p_prio->iscsi, p_prio->roce, p_prio->roce_v2, p_prio->fcoe, 543316485Sdavidcs p_prio->eth); 544316485Sdavidcs} 545316485Sdavidcs 546316485Sdavidcsstatic void 547316485Sdavidcsecore_dcbx_get_app_data(struct ecore_hwfn *p_hwfn, 548316485Sdavidcs struct dcbx_app_priority_feature *p_app, 549316485Sdavidcs struct dcbx_app_priority_entry *p_tbl, 550316485Sdavidcs struct ecore_dcbx_params *p_params, bool ieee) 551316485Sdavidcs{ 552316485Sdavidcs struct ecore_app_entry *entry; 553316485Sdavidcs u8 pri_map; 554316485Sdavidcs int i; 555316485Sdavidcs 556320162Sdavidcs p_params->app_willing = GET_MFW_FIELD(p_app->flags, DCBX_APP_WILLING); 557320162Sdavidcs p_params->app_valid = GET_MFW_FIELD(p_app->flags, DCBX_APP_ENABLED); 558320162Sdavidcs p_params->app_error = GET_MFW_FIELD(p_app->flags, DCBX_APP_ERROR); 559320162Sdavidcs p_params->num_app_entries = GET_MFW_FIELD(p_app->flags, 560320162Sdavidcs DCBX_APP_NUM_ENTRIES); 561337519Sdavidcs for (i = 0; i < p_params->num_app_entries; i++) { 562316485Sdavidcs entry = &p_params->app_entry[i]; 563316485Sdavidcs if (ieee) { 564316485Sdavidcs u8 sf_ieee; 565316485Sdavidcs u32 val; 566316485Sdavidcs 567320162Sdavidcs sf_ieee = GET_MFW_FIELD(p_tbl[i].entry, 568320162Sdavidcs DCBX_APP_SF_IEEE); 569316485Sdavidcs switch (sf_ieee) { 570316485Sdavidcs case DCBX_APP_SF_IEEE_RESERVED: 571316485Sdavidcs /* Old MFW */ 572320162Sdavidcs val = GET_MFW_FIELD(p_tbl[i].entry, 573320162Sdavidcs DCBX_APP_SF); 574316485Sdavidcs entry->sf_ieee = val ? 575316485Sdavidcs ECORE_DCBX_SF_IEEE_TCP_UDP_PORT : 576316485Sdavidcs ECORE_DCBX_SF_IEEE_ETHTYPE; 577316485Sdavidcs break; 578316485Sdavidcs case DCBX_APP_SF_IEEE_ETHTYPE: 579316485Sdavidcs entry->sf_ieee = ECORE_DCBX_SF_IEEE_ETHTYPE; 580316485Sdavidcs break; 581316485Sdavidcs case DCBX_APP_SF_IEEE_TCP_PORT: 582316485Sdavidcs entry->sf_ieee = ECORE_DCBX_SF_IEEE_TCP_PORT; 583316485Sdavidcs break; 584316485Sdavidcs case DCBX_APP_SF_IEEE_UDP_PORT: 585316485Sdavidcs entry->sf_ieee = ECORE_DCBX_SF_IEEE_UDP_PORT; 586316485Sdavidcs break; 587316485Sdavidcs case DCBX_APP_SF_IEEE_TCP_UDP_PORT: 588316485Sdavidcs entry->sf_ieee = ECORE_DCBX_SF_IEEE_TCP_UDP_PORT; 589316485Sdavidcs break; 590316485Sdavidcs } 591316485Sdavidcs } else { 592320162Sdavidcs entry->ethtype = !(GET_MFW_FIELD(p_tbl[i].entry, 593320162Sdavidcs DCBX_APP_SF)); 594316485Sdavidcs } 595316485Sdavidcs 596320162Sdavidcs pri_map = GET_MFW_FIELD(p_tbl[i].entry, DCBX_APP_PRI_MAP); 597316485Sdavidcs ecore_dcbx_get_app_priority(pri_map, &entry->prio); 598320162Sdavidcs entry->proto_id = GET_MFW_FIELD(p_tbl[i].entry, 599320162Sdavidcs DCBX_APP_PROTOCOL_ID); 600316485Sdavidcs ecore_dcbx_get_app_protocol_type(p_hwfn, p_tbl[i].entry, 601316485Sdavidcs entry->proto_id, 602316485Sdavidcs &entry->proto_type, ieee); 603316485Sdavidcs } 604316485Sdavidcs 605316485Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, 606316485Sdavidcs "APP params: willing %d, valid %d error = %d\n", 607316485Sdavidcs p_params->app_willing, p_params->app_valid, 608316485Sdavidcs p_params->app_error); 609316485Sdavidcs} 610316485Sdavidcs 611316485Sdavidcsstatic void 612316485Sdavidcsecore_dcbx_get_pfc_data(struct ecore_hwfn *p_hwfn, 613316485Sdavidcs u32 pfc, struct ecore_dcbx_params *p_params) 614316485Sdavidcs{ 615316485Sdavidcs u8 pfc_map; 616316485Sdavidcs 617320162Sdavidcs p_params->pfc.willing = GET_MFW_FIELD(pfc, DCBX_PFC_WILLING); 618320162Sdavidcs p_params->pfc.max_tc = GET_MFW_FIELD(pfc, DCBX_PFC_CAPS); 619320162Sdavidcs p_params->pfc.enabled = GET_MFW_FIELD(pfc, DCBX_PFC_ENABLED); 620320162Sdavidcs pfc_map = GET_MFW_FIELD(pfc, DCBX_PFC_PRI_EN_BITMAP); 621316485Sdavidcs p_params->pfc.prio[0] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_0); 622316485Sdavidcs p_params->pfc.prio[1] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_1); 623316485Sdavidcs p_params->pfc.prio[2] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_2); 624316485Sdavidcs p_params->pfc.prio[3] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_3); 625316485Sdavidcs p_params->pfc.prio[4] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_4); 626316485Sdavidcs p_params->pfc.prio[5] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_5); 627316485Sdavidcs p_params->pfc.prio[6] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_6); 628316485Sdavidcs p_params->pfc.prio[7] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_7); 629316485Sdavidcs 630316485Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, 631316485Sdavidcs "PFC params: willing %d, pfc_bitmap %u max_tc = %u enabled = %d\n", 632316485Sdavidcs p_params->pfc.willing, pfc_map, p_params->pfc.max_tc, 633316485Sdavidcs p_params->pfc.enabled); 634316485Sdavidcs} 635316485Sdavidcs 636316485Sdavidcsstatic void 637316485Sdavidcsecore_dcbx_get_ets_data(struct ecore_hwfn *p_hwfn, 638316485Sdavidcs struct dcbx_ets_feature *p_ets, 639316485Sdavidcs struct ecore_dcbx_params *p_params) 640316485Sdavidcs{ 641316485Sdavidcs u32 bw_map[2], tsa_map[2], pri_map; 642316485Sdavidcs int i; 643316485Sdavidcs 644320162Sdavidcs p_params->ets_willing = GET_MFW_FIELD(p_ets->flags, DCBX_ETS_WILLING); 645320162Sdavidcs p_params->ets_enabled = GET_MFW_FIELD(p_ets->flags, DCBX_ETS_ENABLED); 646320162Sdavidcs p_params->ets_cbs = GET_MFW_FIELD(p_ets->flags, DCBX_ETS_CBS); 647320162Sdavidcs p_params->max_ets_tc = GET_MFW_FIELD(p_ets->flags, DCBX_ETS_MAX_TCS); 648316485Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, 649316485Sdavidcs "ETS params: willing %d, enabled = %d ets_cbs %d pri_tc_tbl_0 %x max_ets_tc %d\n", 650316485Sdavidcs p_params->ets_willing, p_params->ets_enabled, 651316485Sdavidcs p_params->ets_cbs, p_ets->pri_tc_tbl[0], 652316485Sdavidcs p_params->max_ets_tc); 653316485Sdavidcs if (p_params->ets_enabled && !p_params->max_ets_tc) 654316485Sdavidcs { 655316485Sdavidcs p_params->max_ets_tc = ECORE_MAX_PFC_PRIORITIES; 656316485Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, 657316485Sdavidcs "ETS params: max_ets_tc is forced to %d\n", 658316485Sdavidcs p_params->max_ets_tc); 659316485Sdavidcs } 660316485Sdavidcs /* 8 bit tsa and bw data corresponding to each of the 8 TC's are 661316485Sdavidcs * encoded in a type u32 array of size 2. 662316485Sdavidcs */ 663316485Sdavidcs bw_map[0] = OSAL_BE32_TO_CPU(p_ets->tc_bw_tbl[0]); 664316485Sdavidcs bw_map[1] = OSAL_BE32_TO_CPU(p_ets->tc_bw_tbl[1]); 665316485Sdavidcs tsa_map[0] = OSAL_BE32_TO_CPU(p_ets->tc_tsa_tbl[0]); 666316485Sdavidcs tsa_map[1] = OSAL_BE32_TO_CPU(p_ets->tc_tsa_tbl[1]); 667316485Sdavidcs pri_map = p_ets->pri_tc_tbl[0]; 668316485Sdavidcs for (i = 0; i < ECORE_MAX_PFC_PRIORITIES; i++) { 669316485Sdavidcs p_params->ets_tc_bw_tbl[i] = ((u8 *)bw_map)[i]; 670316485Sdavidcs p_params->ets_tc_tsa_tbl[i] = ((u8 *)tsa_map)[i]; 671316485Sdavidcs p_params->ets_pri_tc_tbl[i] = ECORE_DCBX_PRIO2TC(pri_map, i); 672316485Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, 673316485Sdavidcs "elem %d bw_tbl %x tsa_tbl %x\n", 674316485Sdavidcs i, p_params->ets_tc_bw_tbl[i], 675316485Sdavidcs p_params->ets_tc_tsa_tbl[i]); 676316485Sdavidcs } 677316485Sdavidcs} 678316485Sdavidcs 679316485Sdavidcsstatic void 680316485Sdavidcsecore_dcbx_get_common_params(struct ecore_hwfn *p_hwfn, 681316485Sdavidcs struct dcbx_app_priority_feature *p_app, 682316485Sdavidcs struct dcbx_app_priority_entry *p_tbl, 683316485Sdavidcs struct dcbx_ets_feature *p_ets, 684316485Sdavidcs u32 pfc, struct ecore_dcbx_params *p_params, 685316485Sdavidcs bool ieee) 686316485Sdavidcs{ 687316485Sdavidcs ecore_dcbx_get_app_data(p_hwfn, p_app, p_tbl, p_params, ieee); 688316485Sdavidcs ecore_dcbx_get_ets_data(p_hwfn, p_ets, p_params); 689316485Sdavidcs ecore_dcbx_get_pfc_data(p_hwfn, pfc, p_params); 690316485Sdavidcs} 691316485Sdavidcs 692316485Sdavidcsstatic void 693316485Sdavidcsecore_dcbx_get_local_params(struct ecore_hwfn *p_hwfn, 694316485Sdavidcs struct ecore_dcbx_get *params) 695316485Sdavidcs{ 696316485Sdavidcs struct dcbx_features *p_feat; 697316485Sdavidcs 698316485Sdavidcs p_feat = &p_hwfn->p_dcbx_info->local_admin.features; 699316485Sdavidcs ecore_dcbx_get_common_params(p_hwfn, &p_feat->app, 700316485Sdavidcs p_feat->app.app_pri_tbl, &p_feat->ets, 701316485Sdavidcs p_feat->pfc, ¶ms->local.params, false); 702316485Sdavidcs params->local.valid = true; 703316485Sdavidcs} 704316485Sdavidcs 705316485Sdavidcsstatic void 706316485Sdavidcsecore_dcbx_get_remote_params(struct ecore_hwfn *p_hwfn, 707316485Sdavidcs struct ecore_dcbx_get *params) 708316485Sdavidcs{ 709316485Sdavidcs struct dcbx_features *p_feat; 710316485Sdavidcs 711316485Sdavidcs p_feat = &p_hwfn->p_dcbx_info->remote.features; 712316485Sdavidcs ecore_dcbx_get_common_params(p_hwfn, &p_feat->app, 713316485Sdavidcs p_feat->app.app_pri_tbl, &p_feat->ets, 714316485Sdavidcs p_feat->pfc, ¶ms->remote.params, 715316485Sdavidcs false); 716316485Sdavidcs params->remote.valid = true; 717316485Sdavidcs} 718316485Sdavidcs 719337519Sdavidcsstatic void ecore_dcbx_get_dscp_params(struct ecore_hwfn *p_hwfn, 720337519Sdavidcs struct ecore_dcbx_get *params) 721337519Sdavidcs{ 722337519Sdavidcs struct ecore_dcbx_dscp_params *p_dscp; 723337519Sdavidcs struct dcb_dscp_map *p_dscp_map; 724337519Sdavidcs int i, j, entry; 725337519Sdavidcs u32 pri_map; 726337519Sdavidcs 727337519Sdavidcs p_dscp = ¶ms->dscp; 728337519Sdavidcs p_dscp_map = &p_hwfn->p_dcbx_info->dscp_map; 729337519Sdavidcs p_dscp->enabled = GET_MFW_FIELD(p_dscp_map->flags, DCB_DSCP_ENABLE); 730337519Sdavidcs 731337519Sdavidcs /* MFW encodes 64 dscp entries into 8 element array of u32 entries, 732337519Sdavidcs * where each entry holds the 4bit priority map for 8 dscp entries. 733337519Sdavidcs */ 734337519Sdavidcs for (i = 0, entry = 0; i < ECORE_DCBX_DSCP_SIZE / 8; i++) { 735337519Sdavidcs pri_map = p_dscp_map->dscp_pri_map[i]; 736337519Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "elem %d pri_map 0x%x\n", 737337519Sdavidcs entry, pri_map); 738337519Sdavidcs for (j = 0; j < ECORE_DCBX_DSCP_SIZE / 8; j++, entry++) 739337519Sdavidcs p_dscp->dscp_pri_map[entry] = (u32)(pri_map >> 740337519Sdavidcs (j * 4)) & 0xf; 741337519Sdavidcs } 742337519Sdavidcs} 743337519Sdavidcs 744337519Sdavidcsstatic void 745316485Sdavidcsecore_dcbx_get_operational_params(struct ecore_hwfn *p_hwfn, 746316485Sdavidcs struct ecore_dcbx_get *params) 747316485Sdavidcs{ 748316485Sdavidcs struct ecore_dcbx_operational_params *p_operational; 749316485Sdavidcs struct ecore_dcbx_results *p_results; 750316485Sdavidcs struct dcbx_features *p_feat; 751316485Sdavidcs bool enabled, err; 752316485Sdavidcs u32 flags; 753316485Sdavidcs bool val; 754316485Sdavidcs 755316485Sdavidcs flags = p_hwfn->p_dcbx_info->operational.flags; 756316485Sdavidcs 757316485Sdavidcs /* If DCBx version is non zero, then negotiation 758316485Sdavidcs * was successfuly performed 759316485Sdavidcs */ 760316485Sdavidcs p_operational = ¶ms->operational; 761320162Sdavidcs enabled = !!(GET_MFW_FIELD(flags, DCBX_CONFIG_VERSION) != 762316485Sdavidcs DCBX_CONFIG_VERSION_DISABLED); 763316485Sdavidcs if (!enabled) { 764316485Sdavidcs p_operational->enabled = enabled; 765316485Sdavidcs p_operational->valid = false; 766316485Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "Dcbx is disabled\n"); 767337519Sdavidcs return; 768316485Sdavidcs } 769316485Sdavidcs 770316485Sdavidcs p_feat = &p_hwfn->p_dcbx_info->operational.features; 771316485Sdavidcs p_results = &p_hwfn->p_dcbx_info->results; 772316485Sdavidcs 773320162Sdavidcs val = !!(GET_MFW_FIELD(flags, DCBX_CONFIG_VERSION) == 774316485Sdavidcs DCBX_CONFIG_VERSION_IEEE); 775316485Sdavidcs p_operational->ieee = val; 776316485Sdavidcs 777320162Sdavidcs val = !!(GET_MFW_FIELD(flags, DCBX_CONFIG_VERSION) == 778316485Sdavidcs DCBX_CONFIG_VERSION_CEE); 779316485Sdavidcs p_operational->cee = val; 780316485Sdavidcs 781320162Sdavidcs val = !!(GET_MFW_FIELD(flags, DCBX_CONFIG_VERSION) == 782316485Sdavidcs DCBX_CONFIG_VERSION_STATIC); 783316485Sdavidcs p_operational->local = val; 784316485Sdavidcs 785316485Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, 786316485Sdavidcs "Version support: ieee %d, cee %d, static %d\n", 787316485Sdavidcs p_operational->ieee, p_operational->cee, 788316485Sdavidcs p_operational->local); 789316485Sdavidcs 790316485Sdavidcs ecore_dcbx_get_common_params(p_hwfn, &p_feat->app, 791316485Sdavidcs p_feat->app.app_pri_tbl, &p_feat->ets, 792316485Sdavidcs p_feat->pfc, ¶ms->operational.params, 793316485Sdavidcs p_operational->ieee); 794316485Sdavidcs ecore_dcbx_get_priority_info(p_hwfn, &p_operational->app_prio, 795316485Sdavidcs p_results); 796320162Sdavidcs err = GET_MFW_FIELD(p_feat->app.flags, DCBX_APP_ERROR); 797316485Sdavidcs p_operational->err = err; 798316485Sdavidcs p_operational->enabled = enabled; 799316485Sdavidcs p_operational->valid = true; 800316485Sdavidcs} 801316485Sdavidcs 802320162Sdavidcsstatic void ecore_dcbx_get_local_lldp_params(struct ecore_hwfn *p_hwfn, 803320162Sdavidcs struct ecore_dcbx_get *params) 804316485Sdavidcs{ 805316485Sdavidcs struct lldp_config_params_s *p_local; 806316485Sdavidcs 807316485Sdavidcs p_local = &p_hwfn->p_dcbx_info->lldp_local[LLDP_NEAREST_BRIDGE]; 808316485Sdavidcs 809316485Sdavidcs OSAL_MEMCPY(params->lldp_local.local_chassis_id, 810316485Sdavidcs p_local->local_chassis_id, 811337519Sdavidcs sizeof(params->lldp_local.local_chassis_id)); 812316485Sdavidcs OSAL_MEMCPY(params->lldp_local.local_port_id, p_local->local_port_id, 813337519Sdavidcs sizeof(params->lldp_local.local_port_id)); 814316485Sdavidcs} 815316485Sdavidcs 816320162Sdavidcsstatic void ecore_dcbx_get_remote_lldp_params(struct ecore_hwfn *p_hwfn, 817320162Sdavidcs struct ecore_dcbx_get *params) 818316485Sdavidcs{ 819316485Sdavidcs struct lldp_status_params_s *p_remote; 820316485Sdavidcs 821316485Sdavidcs p_remote = &p_hwfn->p_dcbx_info->lldp_remote[LLDP_NEAREST_BRIDGE]; 822316485Sdavidcs 823316485Sdavidcs OSAL_MEMCPY(params->lldp_remote.peer_chassis_id, 824316485Sdavidcs p_remote->peer_chassis_id, 825337519Sdavidcs sizeof(params->lldp_remote.peer_chassis_id)); 826316485Sdavidcs OSAL_MEMCPY(params->lldp_remote.peer_port_id, p_remote->peer_port_id, 827337519Sdavidcs sizeof(params->lldp_remote.peer_port_id)); 828316485Sdavidcs} 829316485Sdavidcs 830316485Sdavidcsstatic enum _ecore_status_t 831320162Sdavidcsecore_dcbx_get_params(struct ecore_hwfn *p_hwfn, 832316485Sdavidcs struct ecore_dcbx_get *p_params, 833316485Sdavidcs enum ecore_mib_read_type type) 834316485Sdavidcs{ 835316485Sdavidcs switch (type) { 836316485Sdavidcs case ECORE_DCBX_REMOTE_MIB: 837320162Sdavidcs ecore_dcbx_get_remote_params(p_hwfn, p_params); 838316485Sdavidcs break; 839316485Sdavidcs case ECORE_DCBX_LOCAL_MIB: 840320162Sdavidcs ecore_dcbx_get_local_params(p_hwfn, p_params); 841316485Sdavidcs break; 842316485Sdavidcs case ECORE_DCBX_OPERATIONAL_MIB: 843320162Sdavidcs ecore_dcbx_get_operational_params(p_hwfn, p_params); 844316485Sdavidcs break; 845316485Sdavidcs case ECORE_DCBX_REMOTE_LLDP_MIB: 846320162Sdavidcs ecore_dcbx_get_remote_lldp_params(p_hwfn, p_params); 847316485Sdavidcs break; 848316485Sdavidcs case ECORE_DCBX_LOCAL_LLDP_MIB: 849320162Sdavidcs ecore_dcbx_get_local_lldp_params(p_hwfn, p_params); 850316485Sdavidcs break; 851316485Sdavidcs default: 852316485Sdavidcs DP_ERR(p_hwfn, "MIB read err, unknown mib type %d\n", type); 853316485Sdavidcs return ECORE_INVAL; 854316485Sdavidcs } 855316485Sdavidcs 856320162Sdavidcs return ECORE_SUCCESS; 857316485Sdavidcs} 858316485Sdavidcs 859316485Sdavidcsstatic enum _ecore_status_t 860316485Sdavidcsecore_dcbx_read_local_lldp_mib(struct ecore_hwfn *p_hwfn, 861316485Sdavidcs struct ecore_ptt *p_ptt) 862316485Sdavidcs{ 863316485Sdavidcs struct ecore_dcbx_mib_meta_data data; 864316485Sdavidcs enum _ecore_status_t rc = ECORE_SUCCESS; 865316485Sdavidcs 866316485Sdavidcs OSAL_MEM_ZERO(&data, sizeof(data)); 867316485Sdavidcs data.addr = p_hwfn->mcp_info->port_addr + offsetof(struct public_port, 868316485Sdavidcs lldp_config_params); 869316485Sdavidcs data.lldp_local = p_hwfn->p_dcbx_info->lldp_local; 870316485Sdavidcs data.size = sizeof(struct lldp_config_params_s); 871316485Sdavidcs ecore_memcpy_from(p_hwfn, p_ptt, data.lldp_local, data.addr, data.size); 872316485Sdavidcs 873316485Sdavidcs return rc; 874316485Sdavidcs} 875316485Sdavidcs 876316485Sdavidcsstatic enum _ecore_status_t 877316485Sdavidcsecore_dcbx_read_remote_lldp_mib(struct ecore_hwfn *p_hwfn, 878316485Sdavidcs struct ecore_ptt *p_ptt, 879316485Sdavidcs enum ecore_mib_read_type type) 880316485Sdavidcs{ 881316485Sdavidcs struct ecore_dcbx_mib_meta_data data; 882316485Sdavidcs enum _ecore_status_t rc = ECORE_SUCCESS; 883316485Sdavidcs 884316485Sdavidcs OSAL_MEM_ZERO(&data, sizeof(data)); 885316485Sdavidcs data.addr = p_hwfn->mcp_info->port_addr + offsetof(struct public_port, 886316485Sdavidcs lldp_status_params); 887316485Sdavidcs data.lldp_remote = p_hwfn->p_dcbx_info->lldp_remote; 888316485Sdavidcs data.size = sizeof(struct lldp_status_params_s); 889316485Sdavidcs rc = ecore_dcbx_copy_mib(p_hwfn, p_ptt, &data, type); 890316485Sdavidcs 891316485Sdavidcs return rc; 892316485Sdavidcs} 893316485Sdavidcs 894316485Sdavidcsstatic enum _ecore_status_t 895316485Sdavidcsecore_dcbx_read_operational_mib(struct ecore_hwfn *p_hwfn, 896316485Sdavidcs struct ecore_ptt *p_ptt, 897316485Sdavidcs enum ecore_mib_read_type type) 898316485Sdavidcs{ 899316485Sdavidcs struct ecore_dcbx_mib_meta_data data; 900316485Sdavidcs enum _ecore_status_t rc = ECORE_SUCCESS; 901316485Sdavidcs 902316485Sdavidcs OSAL_MEM_ZERO(&data, sizeof(data)); 903316485Sdavidcs data.addr = p_hwfn->mcp_info->port_addr + 904316485Sdavidcs offsetof(struct public_port, operational_dcbx_mib); 905316485Sdavidcs data.mib = &p_hwfn->p_dcbx_info->operational; 906316485Sdavidcs data.size = sizeof(struct dcbx_mib); 907316485Sdavidcs rc = ecore_dcbx_copy_mib(p_hwfn, p_ptt, &data, type); 908316485Sdavidcs 909316485Sdavidcs return rc; 910316485Sdavidcs} 911316485Sdavidcs 912316485Sdavidcsstatic enum _ecore_status_t 913316485Sdavidcsecore_dcbx_read_remote_mib(struct ecore_hwfn *p_hwfn, 914316485Sdavidcs struct ecore_ptt *p_ptt, 915316485Sdavidcs enum ecore_mib_read_type type) 916316485Sdavidcs{ 917316485Sdavidcs struct ecore_dcbx_mib_meta_data data; 918316485Sdavidcs enum _ecore_status_t rc = ECORE_SUCCESS; 919316485Sdavidcs 920316485Sdavidcs OSAL_MEM_ZERO(&data, sizeof(data)); 921316485Sdavidcs data.addr = p_hwfn->mcp_info->port_addr + 922316485Sdavidcs offsetof(struct public_port, remote_dcbx_mib); 923316485Sdavidcs data.mib = &p_hwfn->p_dcbx_info->remote; 924316485Sdavidcs data.size = sizeof(struct dcbx_mib); 925316485Sdavidcs rc = ecore_dcbx_copy_mib(p_hwfn, p_ptt, &data, type); 926316485Sdavidcs 927316485Sdavidcs return rc; 928316485Sdavidcs} 929316485Sdavidcs 930316485Sdavidcsstatic enum _ecore_status_t 931316485Sdavidcsecore_dcbx_read_local_mib(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt) 932316485Sdavidcs{ 933316485Sdavidcs struct ecore_dcbx_mib_meta_data data; 934316485Sdavidcs enum _ecore_status_t rc = ECORE_SUCCESS; 935316485Sdavidcs 936316485Sdavidcs OSAL_MEM_ZERO(&data, sizeof(data)); 937316485Sdavidcs data.addr = p_hwfn->mcp_info->port_addr + 938316485Sdavidcs offsetof(struct public_port, local_admin_dcbx_mib); 939316485Sdavidcs data.local_admin = &p_hwfn->p_dcbx_info->local_admin; 940316485Sdavidcs data.size = sizeof(struct dcbx_local_params); 941316485Sdavidcs ecore_memcpy_from(p_hwfn, p_ptt, data.local_admin, 942316485Sdavidcs data.addr, data.size); 943316485Sdavidcs 944316485Sdavidcs return rc; 945316485Sdavidcs} 946316485Sdavidcs 947316485Sdavidcsstatic void 948316485Sdavidcsecore_dcbx_read_dscp_mib(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt) 949316485Sdavidcs{ 950316485Sdavidcs struct ecore_dcbx_mib_meta_data data; 951316485Sdavidcs 952316485Sdavidcs data.addr = p_hwfn->mcp_info->port_addr + 953316485Sdavidcs offsetof(struct public_port, dcb_dscp_map); 954316485Sdavidcs data.dscp_map = &p_hwfn->p_dcbx_info->dscp_map; 955316485Sdavidcs data.size = sizeof(struct dcb_dscp_map); 956316485Sdavidcs ecore_memcpy_from(p_hwfn, p_ptt, data.dscp_map, data.addr, data.size); 957316485Sdavidcs} 958316485Sdavidcs 959316485Sdavidcsstatic enum _ecore_status_t ecore_dcbx_read_mib(struct ecore_hwfn *p_hwfn, 960316485Sdavidcs struct ecore_ptt *p_ptt, 961316485Sdavidcs enum ecore_mib_read_type type) 962316485Sdavidcs{ 963316485Sdavidcs enum _ecore_status_t rc = ECORE_INVAL; 964316485Sdavidcs 965316485Sdavidcs switch (type) { 966316485Sdavidcs case ECORE_DCBX_OPERATIONAL_MIB: 967316485Sdavidcs ecore_dcbx_read_dscp_mib(p_hwfn, p_ptt); 968316485Sdavidcs rc = ecore_dcbx_read_operational_mib(p_hwfn, p_ptt, type); 969316485Sdavidcs break; 970316485Sdavidcs case ECORE_DCBX_REMOTE_MIB: 971316485Sdavidcs rc = ecore_dcbx_read_remote_mib(p_hwfn, p_ptt, type); 972316485Sdavidcs break; 973316485Sdavidcs case ECORE_DCBX_LOCAL_MIB: 974316485Sdavidcs rc = ecore_dcbx_read_local_mib(p_hwfn, p_ptt); 975316485Sdavidcs break; 976316485Sdavidcs case ECORE_DCBX_REMOTE_LLDP_MIB: 977316485Sdavidcs rc = ecore_dcbx_read_remote_lldp_mib(p_hwfn, p_ptt, type); 978316485Sdavidcs break; 979316485Sdavidcs case ECORE_DCBX_LOCAL_LLDP_MIB: 980316485Sdavidcs rc = ecore_dcbx_read_local_lldp_mib(p_hwfn, p_ptt); 981316485Sdavidcs break; 982316485Sdavidcs default: 983316485Sdavidcs DP_ERR(p_hwfn, "MIB read err, unknown mib type %d\n", type); 984316485Sdavidcs } 985316485Sdavidcs 986316485Sdavidcs return rc; 987316485Sdavidcs} 988316485Sdavidcs 989316485Sdavidcs/* 990316485Sdavidcs * Read updated MIB. 991316485Sdavidcs * Reconfigure QM and invoke PF update ramrod command if operational MIB 992316485Sdavidcs * change is detected. 993316485Sdavidcs */ 994316485Sdavidcsenum _ecore_status_t 995316485Sdavidcsecore_dcbx_mib_update_event(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 996316485Sdavidcs enum ecore_mib_read_type type) 997316485Sdavidcs{ 998316485Sdavidcs enum _ecore_status_t rc = ECORE_SUCCESS; 999316485Sdavidcs 1000316485Sdavidcs rc = ecore_dcbx_read_mib(p_hwfn, p_ptt, type); 1001316485Sdavidcs if (rc) 1002316485Sdavidcs return rc; 1003316485Sdavidcs 1004316485Sdavidcs if (type == ECORE_DCBX_OPERATIONAL_MIB) { 1005320162Sdavidcs ecore_dcbx_get_dscp_params(p_hwfn, &p_hwfn->p_dcbx_info->get); 1006316485Sdavidcs 1007337519Sdavidcs rc = ecore_dcbx_process_mib_info(p_hwfn, p_ptt); 1008316485Sdavidcs if (!rc) { 1009316485Sdavidcs /* reconfigure tcs of QM queues according 1010316485Sdavidcs * to negotiation results 1011316485Sdavidcs */ 1012316485Sdavidcs ecore_qm_reconf(p_hwfn, p_ptt); 1013316485Sdavidcs 1014316485Sdavidcs /* update storm FW with negotiation results */ 1015320162Sdavidcs ecore_sp_pf_update_dcbx(p_hwfn); 1016316485Sdavidcs 1017316485Sdavidcs#ifdef CONFIG_ECORE_ROCE 1018316485Sdavidcs /* for roce PFs, we may want to enable/disable DPM 1019316485Sdavidcs * when DCBx change occurs 1020316485Sdavidcs */ 1021316485Sdavidcs if (ECORE_IS_ROCE_PERSONALITY(p_hwfn)) 1022316485Sdavidcs ecore_roce_dpm_dcbx(p_hwfn, p_ptt); 1023316485Sdavidcs#endif 1024316485Sdavidcs } 1025316485Sdavidcs } 1026316485Sdavidcs 1027320162Sdavidcs ecore_dcbx_get_params(p_hwfn, &p_hwfn->p_dcbx_info->get, type); 1028316485Sdavidcs 1029316485Sdavidcs if (type == ECORE_DCBX_OPERATIONAL_MIB) { 1030316485Sdavidcs struct ecore_dcbx_results *p_data; 1031316485Sdavidcs u16 val; 1032316485Sdavidcs 1033337519Sdavidcs /* Update the DSCP to TC mapping enable bit if required */ 1034316485Sdavidcs if (p_hwfn->p_dcbx_info->dscp_nig_update) { 1035337519Sdavidcs u8 val = !!p_hwfn->p_dcbx_info->get.dscp.enabled; 1036337519Sdavidcs u32 addr = NIG_REG_DSCP_TO_TC_MAP_ENABLE; 1037337519Sdavidcs 1038337519Sdavidcs rc = ecore_all_ppfids_wr(p_hwfn, p_ptt, addr, val); 1039337519Sdavidcs if (rc != ECORE_SUCCESS) { 1040337519Sdavidcs DP_NOTICE(p_hwfn, false, 1041337519Sdavidcs "Failed to update the DSCP to TC mapping enable bit\n"); 1042337519Sdavidcs return rc; 1043337519Sdavidcs } 1044337519Sdavidcs 1045316485Sdavidcs p_hwfn->p_dcbx_info->dscp_nig_update = false; 1046316485Sdavidcs } 1047316485Sdavidcs 1048316485Sdavidcs /* Configure in NIG which protocols support EDPM and should 1049316485Sdavidcs * honor PFC. 1050316485Sdavidcs */ 1051316485Sdavidcs p_data = &p_hwfn->p_dcbx_info->results; 1052316485Sdavidcs val = (0x1 << p_data->arr[DCBX_PROTOCOL_ROCE].tc) | 1053316485Sdavidcs (0x1 << p_data->arr[DCBX_PROTOCOL_ROCE_V2].tc); 1054316485Sdavidcs val <<= NIG_REG_TX_EDPM_CTRL_TX_EDPM_TC_EN_SHIFT; 1055316485Sdavidcs val |= NIG_REG_TX_EDPM_CTRL_TX_EDPM_EN; 1056316485Sdavidcs ecore_wr(p_hwfn, p_ptt, NIG_REG_TX_EDPM_CTRL, val); 1057316485Sdavidcs } 1058316485Sdavidcs 1059316485Sdavidcs OSAL_DCBX_AEN(p_hwfn, type); 1060316485Sdavidcs 1061316485Sdavidcs return rc; 1062316485Sdavidcs} 1063316485Sdavidcs 1064316485Sdavidcsenum _ecore_status_t ecore_dcbx_info_alloc(struct ecore_hwfn *p_hwfn) 1065316485Sdavidcs{ 1066337519Sdavidcs#ifndef __EXTRACT__LINUX__ 1067316485Sdavidcs OSAL_BUILD_BUG_ON(ECORE_LLDP_CHASSIS_ID_STAT_LEN != 1068316485Sdavidcs LLDP_CHASSIS_ID_STAT_LEN); 1069316485Sdavidcs OSAL_BUILD_BUG_ON(ECORE_LLDP_PORT_ID_STAT_LEN != 1070316485Sdavidcs LLDP_PORT_ID_STAT_LEN); 1071316485Sdavidcs OSAL_BUILD_BUG_ON(ECORE_DCBX_MAX_APP_PROTOCOL != 1072316485Sdavidcs DCBX_MAX_APP_PROTOCOL); 1073337519Sdavidcs#endif 1074316485Sdavidcs 1075316485Sdavidcs p_hwfn->p_dcbx_info = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL, 1076316485Sdavidcs sizeof(*p_hwfn->p_dcbx_info)); 1077316485Sdavidcs if (!p_hwfn->p_dcbx_info) { 1078337519Sdavidcs DP_NOTICE(p_hwfn, false, 1079316485Sdavidcs "Failed to allocate `struct ecore_dcbx_info'"); 1080316485Sdavidcs return ECORE_NOMEM; 1081316485Sdavidcs } 1082316485Sdavidcs 1083316485Sdavidcs p_hwfn->p_dcbx_info->iwarp_port = 1084316485Sdavidcs p_hwfn->pf_params.rdma_pf_params.iwarp_port; 1085316485Sdavidcs 1086316485Sdavidcs return ECORE_SUCCESS; 1087316485Sdavidcs} 1088316485Sdavidcs 1089316485Sdavidcsvoid ecore_dcbx_info_free(struct ecore_hwfn *p_hwfn) 1090316485Sdavidcs{ 1091316485Sdavidcs OSAL_FREE(p_hwfn->p_dev, p_hwfn->p_dcbx_info); 1092316485Sdavidcs p_hwfn->p_dcbx_info = OSAL_NULL; 1093316485Sdavidcs} 1094316485Sdavidcs 1095316485Sdavidcsstatic void ecore_dcbx_update_protocol_data(struct protocol_dcb_data *p_data, 1096316485Sdavidcs struct ecore_dcbx_results *p_src, 1097316485Sdavidcs enum dcbx_protocol_type type) 1098316485Sdavidcs{ 1099316485Sdavidcs p_data->dcb_enable_flag = p_src->arr[type].enable; 1100316485Sdavidcs p_data->dcb_priority = p_src->arr[type].priority; 1101316485Sdavidcs p_data->dcb_tc = p_src->arr[type].tc; 1102316485Sdavidcs p_data->dscp_enable_flag = p_src->arr[type].dscp_enable; 1103316485Sdavidcs p_data->dscp_val = p_src->arr[type].dscp_val; 1104337519Sdavidcs p_data->dcb_dont_add_vlan0 = p_src->arr[type].dont_add_vlan0; 1105316485Sdavidcs} 1106316485Sdavidcs 1107316485Sdavidcs/* Set pf update ramrod command params */ 1108316485Sdavidcsvoid ecore_dcbx_set_pf_update_params(struct ecore_dcbx_results *p_src, 1109316485Sdavidcs struct pf_update_ramrod_data *p_dest) 1110316485Sdavidcs{ 1111316485Sdavidcs struct protocol_dcb_data *p_dcb_data; 1112316485Sdavidcs u8 update_flag; 1113316485Sdavidcs 1114316485Sdavidcs update_flag = p_src->arr[DCBX_PROTOCOL_FCOE].update; 1115316485Sdavidcs p_dest->update_fcoe_dcb_data_mode = update_flag; 1116316485Sdavidcs 1117316485Sdavidcs update_flag = p_src->arr[DCBX_PROTOCOL_ROCE].update; 1118316485Sdavidcs p_dest->update_roce_dcb_data_mode = update_flag; 1119316485Sdavidcs 1120316485Sdavidcs update_flag = p_src->arr[DCBX_PROTOCOL_ROCE_V2].update; 1121316485Sdavidcs p_dest->update_rroce_dcb_data_mode = update_flag; 1122316485Sdavidcs 1123316485Sdavidcs update_flag = p_src->arr[DCBX_PROTOCOL_ISCSI].update; 1124316485Sdavidcs p_dest->update_iscsi_dcb_data_mode = update_flag; 1125316485Sdavidcs update_flag = p_src->arr[DCBX_PROTOCOL_ETH].update; 1126316485Sdavidcs p_dest->update_eth_dcb_data_mode = update_flag; 1127316485Sdavidcs update_flag = p_src->arr[DCBX_PROTOCOL_IWARP].update; 1128316485Sdavidcs p_dest->update_iwarp_dcb_data_mode = update_flag; 1129316485Sdavidcs 1130316485Sdavidcs p_dcb_data = &p_dest->fcoe_dcb_data; 1131316485Sdavidcs ecore_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_FCOE); 1132316485Sdavidcs p_dcb_data = &p_dest->roce_dcb_data; 1133316485Sdavidcs ecore_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_ROCE); 1134316485Sdavidcs p_dcb_data = &p_dest->rroce_dcb_data; 1135316485Sdavidcs ecore_dcbx_update_protocol_data(p_dcb_data, p_src, 1136316485Sdavidcs DCBX_PROTOCOL_ROCE_V2); 1137316485Sdavidcs p_dcb_data = &p_dest->iscsi_dcb_data; 1138316485Sdavidcs ecore_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_ISCSI); 1139316485Sdavidcs p_dcb_data = &p_dest->eth_dcb_data; 1140316485Sdavidcs ecore_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_ETH); 1141316485Sdavidcs p_dcb_data = &p_dest->iwarp_dcb_data; 1142316485Sdavidcs ecore_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_IWARP); 1143316485Sdavidcs} 1144316485Sdavidcs 1145316485Sdavidcsenum _ecore_status_t ecore_dcbx_query_params(struct ecore_hwfn *p_hwfn, 1146316485Sdavidcs struct ecore_dcbx_get *p_get, 1147316485Sdavidcs enum ecore_mib_read_type type) 1148316485Sdavidcs{ 1149316485Sdavidcs struct ecore_ptt *p_ptt; 1150316485Sdavidcs enum _ecore_status_t rc; 1151316485Sdavidcs 1152316485Sdavidcs if (IS_VF(p_hwfn->p_dev)) 1153316485Sdavidcs return ECORE_INVAL; 1154316485Sdavidcs 1155316485Sdavidcs p_ptt = ecore_ptt_acquire(p_hwfn); 1156337519Sdavidcs if (!p_ptt) 1157337519Sdavidcs return ECORE_TIMEOUT; 1158316485Sdavidcs 1159316485Sdavidcs rc = ecore_dcbx_read_mib(p_hwfn, p_ptt, type); 1160316485Sdavidcs if (rc != ECORE_SUCCESS) 1161316485Sdavidcs goto out; 1162316485Sdavidcs 1163337519Sdavidcs ecore_dcbx_get_dscp_params(p_hwfn, p_get); 1164337519Sdavidcs 1165320162Sdavidcs rc = ecore_dcbx_get_params(p_hwfn, p_get, type); 1166316485Sdavidcs 1167316485Sdavidcsout: 1168316485Sdavidcs ecore_ptt_release(p_hwfn, p_ptt); 1169316485Sdavidcs return rc; 1170316485Sdavidcs} 1171316485Sdavidcs 1172316485Sdavidcsstatic void 1173316485Sdavidcsecore_dcbx_set_pfc_data(struct ecore_hwfn *p_hwfn, 1174316485Sdavidcs u32 *pfc, struct ecore_dcbx_params *p_params) 1175316485Sdavidcs{ 1176316485Sdavidcs u8 pfc_map = 0; 1177316485Sdavidcs int i; 1178316485Sdavidcs 1179316485Sdavidcs *pfc &= ~DCBX_PFC_ERROR_MASK; 1180316485Sdavidcs 1181316485Sdavidcs if (p_params->pfc.willing) 1182316485Sdavidcs *pfc |= DCBX_PFC_WILLING_MASK; 1183316485Sdavidcs else 1184316485Sdavidcs *pfc &= ~DCBX_PFC_WILLING_MASK; 1185316485Sdavidcs 1186316485Sdavidcs if (p_params->pfc.enabled) 1187316485Sdavidcs *pfc |= DCBX_PFC_ENABLED_MASK; 1188316485Sdavidcs else 1189316485Sdavidcs *pfc &= ~DCBX_PFC_ENABLED_MASK; 1190316485Sdavidcs 1191316485Sdavidcs *pfc &= ~DCBX_PFC_CAPS_MASK; 1192320162Sdavidcs *pfc |= (u32)p_params->pfc.max_tc << DCBX_PFC_CAPS_OFFSET; 1193316485Sdavidcs 1194316485Sdavidcs for (i = 0; i < ECORE_MAX_PFC_PRIORITIES; i++) 1195316485Sdavidcs if (p_params->pfc.prio[i]) 1196316485Sdavidcs pfc_map |= (1 << i); 1197316485Sdavidcs *pfc &= ~DCBX_PFC_PRI_EN_BITMAP_MASK; 1198320162Sdavidcs *pfc |= (pfc_map << DCBX_PFC_PRI_EN_BITMAP_OFFSET); 1199316485Sdavidcs 1200316485Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "pfc = 0x%x\n", *pfc); 1201316485Sdavidcs} 1202316485Sdavidcs 1203316485Sdavidcsstatic void 1204316485Sdavidcsecore_dcbx_set_ets_data(struct ecore_hwfn *p_hwfn, 1205316485Sdavidcs struct dcbx_ets_feature *p_ets, 1206316485Sdavidcs struct ecore_dcbx_params *p_params) 1207316485Sdavidcs{ 1208316485Sdavidcs u8 *bw_map, *tsa_map; 1209316485Sdavidcs u32 val; 1210316485Sdavidcs int i; 1211316485Sdavidcs 1212316485Sdavidcs if (p_params->ets_willing) 1213316485Sdavidcs p_ets->flags |= DCBX_ETS_WILLING_MASK; 1214316485Sdavidcs else 1215316485Sdavidcs p_ets->flags &= ~DCBX_ETS_WILLING_MASK; 1216316485Sdavidcs 1217316485Sdavidcs if (p_params->ets_cbs) 1218316485Sdavidcs p_ets->flags |= DCBX_ETS_CBS_MASK; 1219316485Sdavidcs else 1220316485Sdavidcs p_ets->flags &= ~DCBX_ETS_CBS_MASK; 1221316485Sdavidcs 1222316485Sdavidcs if (p_params->ets_enabled) 1223316485Sdavidcs p_ets->flags |= DCBX_ETS_ENABLED_MASK; 1224316485Sdavidcs else 1225316485Sdavidcs p_ets->flags &= ~DCBX_ETS_ENABLED_MASK; 1226316485Sdavidcs 1227316485Sdavidcs p_ets->flags &= ~DCBX_ETS_MAX_TCS_MASK; 1228320162Sdavidcs p_ets->flags |= (u32)p_params->max_ets_tc << DCBX_ETS_MAX_TCS_OFFSET; 1229316485Sdavidcs 1230316485Sdavidcs bw_map = (u8 *)&p_ets->tc_bw_tbl[0]; 1231316485Sdavidcs tsa_map = (u8 *)&p_ets->tc_tsa_tbl[0]; 1232316485Sdavidcs p_ets->pri_tc_tbl[0] = 0; 1233316485Sdavidcs for (i = 0; i < ECORE_MAX_PFC_PRIORITIES; i++) { 1234316485Sdavidcs bw_map[i] = p_params->ets_tc_bw_tbl[i]; 1235316485Sdavidcs tsa_map[i] = p_params->ets_tc_tsa_tbl[i]; 1236316485Sdavidcs /* Copy the priority value to the corresponding 4 bits in the 1237316485Sdavidcs * traffic class table. 1238316485Sdavidcs */ 1239316485Sdavidcs val = (((u32)p_params->ets_pri_tc_tbl[i]) << ((7 - i) * 4)); 1240316485Sdavidcs p_ets->pri_tc_tbl[0] |= val; 1241316485Sdavidcs } 1242316485Sdavidcs for (i = 0; i < 2; i++) { 1243316485Sdavidcs p_ets->tc_bw_tbl[i] = OSAL_CPU_TO_BE32(p_ets->tc_bw_tbl[i]); 1244316485Sdavidcs p_ets->tc_tsa_tbl[i] = OSAL_CPU_TO_BE32(p_ets->tc_tsa_tbl[i]); 1245316485Sdavidcs } 1246316485Sdavidcs 1247316485Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, 1248316485Sdavidcs "flags = 0x%x pri_tc = 0x%x tc_bwl[] = {0x%x, 0x%x} tc_tsa = {0x%x, 0x%x}\n", 1249316485Sdavidcs p_ets->flags, p_ets->pri_tc_tbl[0], p_ets->tc_bw_tbl[0], 1250316485Sdavidcs p_ets->tc_bw_tbl[1], p_ets->tc_tsa_tbl[0], 1251316485Sdavidcs p_ets->tc_tsa_tbl[1]); 1252316485Sdavidcs} 1253316485Sdavidcs 1254316485Sdavidcsstatic void 1255316485Sdavidcsecore_dcbx_set_app_data(struct ecore_hwfn *p_hwfn, 1256316485Sdavidcs struct dcbx_app_priority_feature *p_app, 1257316485Sdavidcs struct ecore_dcbx_params *p_params, bool ieee) 1258316485Sdavidcs{ 1259316485Sdavidcs u32 *entry; 1260316485Sdavidcs int i; 1261316485Sdavidcs 1262316485Sdavidcs if (p_params->app_willing) 1263316485Sdavidcs p_app->flags |= DCBX_APP_WILLING_MASK; 1264316485Sdavidcs else 1265316485Sdavidcs p_app->flags &= ~DCBX_APP_WILLING_MASK; 1266316485Sdavidcs 1267316485Sdavidcs if (p_params->app_valid) 1268316485Sdavidcs p_app->flags |= DCBX_APP_ENABLED_MASK; 1269316485Sdavidcs else 1270316485Sdavidcs p_app->flags &= ~DCBX_APP_ENABLED_MASK; 1271316485Sdavidcs 1272316485Sdavidcs p_app->flags &= ~DCBX_APP_NUM_ENTRIES_MASK; 1273316485Sdavidcs p_app->flags |= (u32)p_params->num_app_entries << 1274320162Sdavidcs DCBX_APP_NUM_ENTRIES_OFFSET; 1275316485Sdavidcs 1276337519Sdavidcs for (i = 0; i < p_params->num_app_entries; i++) { 1277316485Sdavidcs entry = &p_app->app_pri_tbl[i].entry; 1278316485Sdavidcs *entry = 0; 1279316485Sdavidcs if (ieee) { 1280316485Sdavidcs *entry &= ~(DCBX_APP_SF_IEEE_MASK | DCBX_APP_SF_MASK); 1281316485Sdavidcs switch (p_params->app_entry[i].sf_ieee) { 1282316485Sdavidcs case ECORE_DCBX_SF_IEEE_ETHTYPE: 1283316485Sdavidcs *entry |= ((u32)DCBX_APP_SF_IEEE_ETHTYPE << 1284320162Sdavidcs DCBX_APP_SF_IEEE_OFFSET); 1285316485Sdavidcs *entry |= ((u32)DCBX_APP_SF_ETHTYPE << 1286320162Sdavidcs DCBX_APP_SF_OFFSET); 1287316485Sdavidcs break; 1288316485Sdavidcs case ECORE_DCBX_SF_IEEE_TCP_PORT: 1289316485Sdavidcs *entry |= ((u32)DCBX_APP_SF_IEEE_TCP_PORT << 1290320162Sdavidcs DCBX_APP_SF_IEEE_OFFSET); 1291316485Sdavidcs *entry |= ((u32)DCBX_APP_SF_PORT << 1292320162Sdavidcs DCBX_APP_SF_OFFSET); 1293316485Sdavidcs break; 1294316485Sdavidcs case ECORE_DCBX_SF_IEEE_UDP_PORT: 1295316485Sdavidcs *entry |= ((u32)DCBX_APP_SF_IEEE_UDP_PORT << 1296320162Sdavidcs DCBX_APP_SF_IEEE_OFFSET); 1297316485Sdavidcs *entry |= ((u32)DCBX_APP_SF_PORT << 1298320162Sdavidcs DCBX_APP_SF_OFFSET); 1299316485Sdavidcs break; 1300316485Sdavidcs case ECORE_DCBX_SF_IEEE_TCP_UDP_PORT: 1301316485Sdavidcs *entry |= (u32)DCBX_APP_SF_IEEE_TCP_UDP_PORT << 1302320162Sdavidcs DCBX_APP_SF_IEEE_OFFSET; 1303316485Sdavidcs *entry |= ((u32)DCBX_APP_SF_PORT << 1304320162Sdavidcs DCBX_APP_SF_OFFSET); 1305316485Sdavidcs break; 1306316485Sdavidcs } 1307316485Sdavidcs } else { 1308316485Sdavidcs *entry &= ~DCBX_APP_SF_MASK; 1309316485Sdavidcs if (p_params->app_entry[i].ethtype) 1310316485Sdavidcs *entry |= ((u32)DCBX_APP_SF_ETHTYPE << 1311320162Sdavidcs DCBX_APP_SF_OFFSET); 1312316485Sdavidcs else 1313316485Sdavidcs *entry |= ((u32)DCBX_APP_SF_PORT << 1314320162Sdavidcs DCBX_APP_SF_OFFSET); 1315316485Sdavidcs } 1316316485Sdavidcs *entry &= ~DCBX_APP_PROTOCOL_ID_MASK; 1317316485Sdavidcs *entry |= ((u32)p_params->app_entry[i].proto_id << 1318320162Sdavidcs DCBX_APP_PROTOCOL_ID_OFFSET); 1319316485Sdavidcs *entry &= ~DCBX_APP_PRI_MAP_MASK; 1320337519Sdavidcs *entry |= ((u32)(1 << p_params->app_entry[i].prio) << 1321320162Sdavidcs DCBX_APP_PRI_MAP_OFFSET); 1322316485Sdavidcs } 1323316485Sdavidcs 1324316485Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "flags = 0x%x\n", p_app->flags); 1325316485Sdavidcs} 1326316485Sdavidcs 1327337519Sdavidcsstatic void 1328316485Sdavidcsecore_dcbx_set_local_params(struct ecore_hwfn *p_hwfn, 1329316485Sdavidcs struct dcbx_local_params *local_admin, 1330316485Sdavidcs struct ecore_dcbx_set *params) 1331316485Sdavidcs{ 1332316485Sdavidcs bool ieee = false; 1333316485Sdavidcs 1334316485Sdavidcs local_admin->flags = 0; 1335316485Sdavidcs OSAL_MEMCPY(&local_admin->features, 1336316485Sdavidcs &p_hwfn->p_dcbx_info->operational.features, 1337316485Sdavidcs sizeof(local_admin->features)); 1338316485Sdavidcs 1339316485Sdavidcs if (params->enabled) { 1340316485Sdavidcs local_admin->config = params->ver_num; 1341316485Sdavidcs ieee = !!(params->ver_num & DCBX_CONFIG_VERSION_IEEE); 1342316485Sdavidcs } else 1343316485Sdavidcs local_admin->config = DCBX_CONFIG_VERSION_DISABLED; 1344316485Sdavidcs 1345337519Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "Dcbx version = %d\n", 1346337519Sdavidcs local_admin->config); 1347337519Sdavidcs 1348316485Sdavidcs if (params->override_flags & ECORE_DCBX_OVERRIDE_PFC_CFG) 1349316485Sdavidcs ecore_dcbx_set_pfc_data(p_hwfn, &local_admin->features.pfc, 1350316485Sdavidcs ¶ms->config.params); 1351316485Sdavidcs 1352316485Sdavidcs if (params->override_flags & ECORE_DCBX_OVERRIDE_ETS_CFG) 1353316485Sdavidcs ecore_dcbx_set_ets_data(p_hwfn, &local_admin->features.ets, 1354316485Sdavidcs ¶ms->config.params); 1355316485Sdavidcs 1356316485Sdavidcs if (params->override_flags & ECORE_DCBX_OVERRIDE_APP_CFG) 1357316485Sdavidcs ecore_dcbx_set_app_data(p_hwfn, &local_admin->features.app, 1358316485Sdavidcs ¶ms->config.params, ieee); 1359316485Sdavidcs} 1360316485Sdavidcs 1361316485Sdavidcsstatic enum _ecore_status_t 1362316485Sdavidcsecore_dcbx_set_dscp_params(struct ecore_hwfn *p_hwfn, 1363316485Sdavidcs struct dcb_dscp_map *p_dscp_map, 1364316485Sdavidcs struct ecore_dcbx_set *p_params) 1365316485Sdavidcs{ 1366316485Sdavidcs int entry, i, j; 1367316485Sdavidcs u32 val; 1368316485Sdavidcs 1369316485Sdavidcs OSAL_MEMCPY(p_dscp_map, &p_hwfn->p_dcbx_info->dscp_map, 1370316485Sdavidcs sizeof(*p_dscp_map)); 1371316485Sdavidcs 1372316485Sdavidcs p_dscp_map->flags &= ~DCB_DSCP_ENABLE_MASK; 1373316485Sdavidcs if (p_params->dscp.enabled) 1374316485Sdavidcs p_dscp_map->flags |= DCB_DSCP_ENABLE_MASK; 1375316485Sdavidcs 1376316485Sdavidcs for (i = 0, entry = 0; i < 8; i++) { 1377316485Sdavidcs val = 0; 1378316485Sdavidcs for (j = 0; j < 8; j++, entry++) 1379316485Sdavidcs val |= (((u32)p_params->dscp.dscp_pri_map[entry]) << 1380316485Sdavidcs (j * 4)); 1381316485Sdavidcs 1382337519Sdavidcs p_dscp_map->dscp_pri_map[i] = val; 1383316485Sdavidcs } 1384316485Sdavidcs 1385316485Sdavidcs p_hwfn->p_dcbx_info->dscp_nig_update = true; 1386316485Sdavidcs 1387316485Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "flags = 0x%x\n", p_dscp_map->flags); 1388337519Sdavidcs DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, 1389337519Sdavidcs "pri_map[] = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", 1390337519Sdavidcs p_dscp_map->dscp_pri_map[0], p_dscp_map->dscp_pri_map[1], 1391337519Sdavidcs p_dscp_map->dscp_pri_map[2], p_dscp_map->dscp_pri_map[3], 1392337519Sdavidcs p_dscp_map->dscp_pri_map[4], p_dscp_map->dscp_pri_map[5], 1393337519Sdavidcs p_dscp_map->dscp_pri_map[6], p_dscp_map->dscp_pri_map[7]); 1394316485Sdavidcs 1395316485Sdavidcs return ECORE_SUCCESS; 1396316485Sdavidcs} 1397316485Sdavidcs 1398316485Sdavidcsenum _ecore_status_t ecore_dcbx_config_params(struct ecore_hwfn *p_hwfn, 1399316485Sdavidcs struct ecore_ptt *p_ptt, 1400316485Sdavidcs struct ecore_dcbx_set *params, 1401316485Sdavidcs bool hw_commit) 1402316485Sdavidcs{ 1403316485Sdavidcs struct dcbx_local_params local_admin; 1404316485Sdavidcs struct ecore_dcbx_mib_meta_data data; 1405316485Sdavidcs struct dcb_dscp_map dscp_map; 1406316485Sdavidcs u32 resp = 0, param = 0; 1407316485Sdavidcs enum _ecore_status_t rc = ECORE_SUCCESS; 1408316485Sdavidcs 1409337519Sdavidcs OSAL_MEMCPY(&p_hwfn->p_dcbx_info->set, params, 1410337519Sdavidcs sizeof(p_hwfn->p_dcbx_info->set)); 1411337519Sdavidcs if (!hw_commit) 1412316485Sdavidcs return ECORE_SUCCESS; 1413316485Sdavidcs 1414316485Sdavidcs OSAL_MEMSET(&local_admin, 0, sizeof(local_admin)); 1415316485Sdavidcs ecore_dcbx_set_local_params(p_hwfn, &local_admin, params); 1416316485Sdavidcs 1417316485Sdavidcs data.addr = p_hwfn->mcp_info->port_addr + 1418316485Sdavidcs offsetof(struct public_port, local_admin_dcbx_mib); 1419316485Sdavidcs data.local_admin = &local_admin; 1420316485Sdavidcs data.size = sizeof(struct dcbx_local_params); 1421316485Sdavidcs ecore_memcpy_to(p_hwfn, p_ptt, data.addr, data.local_admin, data.size); 1422316485Sdavidcs 1423316485Sdavidcs if (params->override_flags & ECORE_DCBX_OVERRIDE_DSCP_CFG) { 1424316485Sdavidcs OSAL_MEMSET(&dscp_map, 0, sizeof(dscp_map)); 1425316485Sdavidcs ecore_dcbx_set_dscp_params(p_hwfn, &dscp_map, params); 1426316485Sdavidcs 1427316485Sdavidcs data.addr = p_hwfn->mcp_info->port_addr + 1428316485Sdavidcs offsetof(struct public_port, dcb_dscp_map); 1429316485Sdavidcs data.dscp_map = &dscp_map; 1430316485Sdavidcs data.size = sizeof(struct dcb_dscp_map); 1431316485Sdavidcs ecore_memcpy_to(p_hwfn, p_ptt, data.addr, data.dscp_map, 1432316485Sdavidcs data.size); 1433316485Sdavidcs } 1434316485Sdavidcs 1435316485Sdavidcs rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_SET_DCBX, 1436320162Sdavidcs 1 << DRV_MB_PARAM_LLDP_SEND_OFFSET, &resp, ¶m); 1437320162Sdavidcs if (rc != ECORE_SUCCESS) 1438316485Sdavidcs DP_NOTICE(p_hwfn, false, 1439316485Sdavidcs "Failed to send DCBX update request\n"); 1440316485Sdavidcs 1441316485Sdavidcs return rc; 1442316485Sdavidcs} 1443316485Sdavidcs 1444316485Sdavidcsenum _ecore_status_t ecore_dcbx_get_config_params(struct ecore_hwfn *p_hwfn, 1445316485Sdavidcs struct ecore_dcbx_set *params) 1446316485Sdavidcs{ 1447316485Sdavidcs struct ecore_dcbx_get *dcbx_info; 1448337519Sdavidcs enum _ecore_status_t rc; 1449316485Sdavidcs 1450316485Sdavidcs if (p_hwfn->p_dcbx_info->set.config.valid) { 1451316485Sdavidcs OSAL_MEMCPY(params, &p_hwfn->p_dcbx_info->set, 1452316485Sdavidcs sizeof(struct ecore_dcbx_set)); 1453316485Sdavidcs return ECORE_SUCCESS; 1454316485Sdavidcs } 1455316485Sdavidcs 1456316485Sdavidcs dcbx_info = OSAL_ALLOC(p_hwfn->p_dev, GFP_KERNEL, 1457316485Sdavidcs sizeof(*dcbx_info)); 1458337519Sdavidcs if (!dcbx_info) 1459316485Sdavidcs return ECORE_NOMEM; 1460316485Sdavidcs 1461316485Sdavidcs OSAL_MEMSET(dcbx_info, 0, sizeof(*dcbx_info)); 1462316485Sdavidcs rc = ecore_dcbx_query_params(p_hwfn, dcbx_info, 1463316485Sdavidcs ECORE_DCBX_OPERATIONAL_MIB); 1464316485Sdavidcs if (rc) { 1465316485Sdavidcs OSAL_FREE(p_hwfn->p_dev, dcbx_info); 1466316485Sdavidcs return rc; 1467316485Sdavidcs } 1468316485Sdavidcs p_hwfn->p_dcbx_info->set.override_flags = 0; 1469316485Sdavidcs 1470316485Sdavidcs p_hwfn->p_dcbx_info->set.ver_num = DCBX_CONFIG_VERSION_DISABLED; 1471316485Sdavidcs if (dcbx_info->operational.cee) 1472316485Sdavidcs p_hwfn->p_dcbx_info->set.ver_num |= DCBX_CONFIG_VERSION_CEE; 1473316485Sdavidcs if (dcbx_info->operational.ieee) 1474316485Sdavidcs p_hwfn->p_dcbx_info->set.ver_num |= DCBX_CONFIG_VERSION_IEEE; 1475316485Sdavidcs if (dcbx_info->operational.local) 1476316485Sdavidcs p_hwfn->p_dcbx_info->set.ver_num |= DCBX_CONFIG_VERSION_STATIC; 1477316485Sdavidcs 1478316485Sdavidcs p_hwfn->p_dcbx_info->set.enabled = dcbx_info->operational.enabled; 1479337519Sdavidcs OSAL_MEMCPY(&p_hwfn->p_dcbx_info->set.dscp, 1480337519Sdavidcs &p_hwfn->p_dcbx_info->get.dscp, 1481337519Sdavidcs sizeof(struct ecore_dcbx_dscp_params)); 1482316485Sdavidcs OSAL_MEMCPY(&p_hwfn->p_dcbx_info->set.config.params, 1483316485Sdavidcs &dcbx_info->operational.params, 1484337519Sdavidcs sizeof(p_hwfn->p_dcbx_info->set.config.params)); 1485316485Sdavidcs p_hwfn->p_dcbx_info->set.config.valid = true; 1486316485Sdavidcs 1487316485Sdavidcs OSAL_MEMCPY(params, &p_hwfn->p_dcbx_info->set, 1488316485Sdavidcs sizeof(struct ecore_dcbx_set)); 1489316485Sdavidcs 1490316485Sdavidcs OSAL_FREE(p_hwfn->p_dev, dcbx_info); 1491316485Sdavidcs 1492316485Sdavidcs return ECORE_SUCCESS; 1493316485Sdavidcs} 1494337519Sdavidcs 1495337519Sdavidcsenum _ecore_status_t ecore_lldp_register_tlv(struct ecore_hwfn *p_hwfn, 1496337519Sdavidcs struct ecore_ptt *p_ptt, 1497337519Sdavidcs enum ecore_lldp_agent agent, 1498337519Sdavidcs u8 tlv_type) 1499337519Sdavidcs{ 1500337519Sdavidcs u32 mb_param = 0, mcp_resp = 0, mcp_param = 0, val = 0; 1501337519Sdavidcs enum _ecore_status_t rc = ECORE_SUCCESS; 1502337519Sdavidcs 1503337519Sdavidcs switch (agent) { 1504337519Sdavidcs case ECORE_LLDP_NEAREST_BRIDGE: 1505337519Sdavidcs val = LLDP_NEAREST_BRIDGE; 1506337519Sdavidcs break; 1507337519Sdavidcs case ECORE_LLDP_NEAREST_NON_TPMR_BRIDGE: 1508337519Sdavidcs val = LLDP_NEAREST_NON_TPMR_BRIDGE; 1509337519Sdavidcs break; 1510337519Sdavidcs case ECORE_LLDP_NEAREST_CUSTOMER_BRIDGE: 1511337519Sdavidcs val = LLDP_NEAREST_CUSTOMER_BRIDGE; 1512337519Sdavidcs break; 1513337519Sdavidcs default: 1514337519Sdavidcs DP_ERR(p_hwfn, "Invalid agent type %d\n", agent); 1515337519Sdavidcs return ECORE_INVAL; 1516337519Sdavidcs } 1517337519Sdavidcs 1518337519Sdavidcs SET_MFW_FIELD(mb_param, DRV_MB_PARAM_LLDP_AGENT, val); 1519337519Sdavidcs SET_MFW_FIELD(mb_param, DRV_MB_PARAM_LLDP_TLV_RX_TYPE, tlv_type); 1520337519Sdavidcs 1521337519Sdavidcs rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_REGISTER_LLDP_TLVS_RX, 1522337519Sdavidcs mb_param, &mcp_resp, &mcp_param); 1523337519Sdavidcs if (rc != ECORE_SUCCESS) 1524337519Sdavidcs DP_NOTICE(p_hwfn, false, "Failed to register TLV\n"); 1525337519Sdavidcs 1526337519Sdavidcs return rc; 1527337519Sdavidcs} 1528337519Sdavidcs 1529337519Sdavidcsenum _ecore_status_t 1530337519Sdavidcsecore_lldp_mib_update_event(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt) 1531337519Sdavidcs{ 1532337519Sdavidcs struct ecore_dcbx_mib_meta_data data; 1533337519Sdavidcs enum _ecore_status_t rc = ECORE_SUCCESS; 1534337519Sdavidcs struct lldp_received_tlvs_s tlvs; 1535337519Sdavidcs int i; 1536337519Sdavidcs 1537337519Sdavidcs for (i = 0; i < LLDP_MAX_LLDP_AGENTS; i++) { 1538337519Sdavidcs OSAL_MEM_ZERO(&data, sizeof(data)); 1539337519Sdavidcs data.addr = p_hwfn->mcp_info->port_addr + 1540337519Sdavidcs offsetof(struct public_port, lldp_received_tlvs[i]); 1541337519Sdavidcs data.lldp_tlvs = &tlvs; 1542337519Sdavidcs data.size = sizeof(tlvs); 1543337519Sdavidcs rc = ecore_dcbx_copy_mib(p_hwfn, p_ptt, &data, 1544337519Sdavidcs ECORE_DCBX_LLDP_TLVS); 1545337519Sdavidcs if (rc != ECORE_SUCCESS) { 1546337519Sdavidcs DP_NOTICE(p_hwfn, false, "Failed to read lldp TLVs\n"); 1547337519Sdavidcs return rc; 1548337519Sdavidcs } 1549337519Sdavidcs 1550337519Sdavidcs if (!tlvs.length) 1551337519Sdavidcs continue; 1552337519Sdavidcs 1553337519Sdavidcs for (i = 0; i < MAX_TLV_BUFFER; i++) 1554337519Sdavidcs tlvs.tlvs_buffer[i] = 1555337519Sdavidcs OSAL_CPU_TO_BE32(tlvs.tlvs_buffer[i]); 1556337519Sdavidcs 1557337519Sdavidcs OSAL_LLDP_RX_TLVS(p_hwfn, tlvs.tlvs_buffer, tlvs.length); 1558337519Sdavidcs } 1559337519Sdavidcs 1560337519Sdavidcs return rc; 1561337519Sdavidcs} 1562337519Sdavidcs 1563337519Sdavidcsenum _ecore_status_t 1564337519Sdavidcsecore_lldp_get_params(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 1565337519Sdavidcs struct ecore_lldp_config_params *p_params) 1566337519Sdavidcs{ 1567337519Sdavidcs struct lldp_config_params_s lldp_params; 1568337519Sdavidcs u32 addr, val; 1569337519Sdavidcs int i; 1570337519Sdavidcs 1571337519Sdavidcs switch (p_params->agent) { 1572337519Sdavidcs case ECORE_LLDP_NEAREST_BRIDGE: 1573337519Sdavidcs val = LLDP_NEAREST_BRIDGE; 1574337519Sdavidcs break; 1575337519Sdavidcs case ECORE_LLDP_NEAREST_NON_TPMR_BRIDGE: 1576337519Sdavidcs val = LLDP_NEAREST_NON_TPMR_BRIDGE; 1577337519Sdavidcs break; 1578337519Sdavidcs case ECORE_LLDP_NEAREST_CUSTOMER_BRIDGE: 1579337519Sdavidcs val = LLDP_NEAREST_CUSTOMER_BRIDGE; 1580337519Sdavidcs break; 1581337519Sdavidcs default: 1582337519Sdavidcs DP_ERR(p_hwfn, "Invalid agent type %d\n", p_params->agent); 1583337519Sdavidcs return ECORE_INVAL; 1584337519Sdavidcs } 1585337519Sdavidcs 1586337519Sdavidcs addr = p_hwfn->mcp_info->port_addr + 1587337519Sdavidcs offsetof(struct public_port, lldp_config_params[val]); 1588337519Sdavidcs 1589337519Sdavidcs ecore_memcpy_from(p_hwfn, p_ptt, &lldp_params, addr, 1590337519Sdavidcs sizeof(lldp_params)); 1591337519Sdavidcs 1592337519Sdavidcs p_params->tx_interval = GET_MFW_FIELD(lldp_params.config, 1593337519Sdavidcs LLDP_CONFIG_TX_INTERVAL); 1594337519Sdavidcs p_params->tx_hold = GET_MFW_FIELD(lldp_params.config, LLDP_CONFIG_HOLD); 1595337519Sdavidcs p_params->tx_credit = GET_MFW_FIELD(lldp_params.config, 1596337519Sdavidcs LLDP_CONFIG_MAX_CREDIT); 1597337519Sdavidcs p_params->rx_enable = GET_MFW_FIELD(lldp_params.config, 1598337519Sdavidcs LLDP_CONFIG_ENABLE_RX); 1599337519Sdavidcs p_params->tx_enable = GET_MFW_FIELD(lldp_params.config, 1600337519Sdavidcs LLDP_CONFIG_ENABLE_TX); 1601337519Sdavidcs 1602337519Sdavidcs OSAL_MEMCPY(p_params->chassis_id_tlv, lldp_params.local_chassis_id, 1603337519Sdavidcs sizeof(p_params->chassis_id_tlv)); 1604337519Sdavidcs for (i = 0; i < ECORE_LLDP_CHASSIS_ID_STAT_LEN; i++) 1605337519Sdavidcs p_params->chassis_id_tlv[i] = 1606337519Sdavidcs OSAL_BE32_TO_CPU(p_params->chassis_id_tlv[i]); 1607337519Sdavidcs 1608337519Sdavidcs OSAL_MEMCPY(p_params->port_id_tlv, lldp_params.local_port_id, 1609337519Sdavidcs sizeof(p_params->port_id_tlv)); 1610337519Sdavidcs for (i = 0; i < ECORE_LLDP_PORT_ID_STAT_LEN; i++) 1611337519Sdavidcs p_params->port_id_tlv[i] = 1612337519Sdavidcs OSAL_BE32_TO_CPU(p_params->port_id_tlv[i]); 1613337519Sdavidcs 1614337519Sdavidcs return ECORE_SUCCESS; 1615337519Sdavidcs} 1616337519Sdavidcs 1617337519Sdavidcsenum _ecore_status_t 1618337519Sdavidcsecore_lldp_set_params(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 1619337519Sdavidcs struct ecore_lldp_config_params *p_params) 1620337519Sdavidcs{ 1621337519Sdavidcs u32 mb_param = 0, mcp_resp = 0, mcp_param = 0; 1622337519Sdavidcs struct lldp_config_params_s lldp_params; 1623337519Sdavidcs enum _ecore_status_t rc = ECORE_SUCCESS; 1624337519Sdavidcs u32 addr, val; 1625337519Sdavidcs int i; 1626337519Sdavidcs 1627337519Sdavidcs switch (p_params->agent) { 1628337519Sdavidcs case ECORE_LLDP_NEAREST_BRIDGE: 1629337519Sdavidcs val = LLDP_NEAREST_BRIDGE; 1630337519Sdavidcs break; 1631337519Sdavidcs case ECORE_LLDP_NEAREST_NON_TPMR_BRIDGE: 1632337519Sdavidcs val = LLDP_NEAREST_NON_TPMR_BRIDGE; 1633337519Sdavidcs break; 1634337519Sdavidcs case ECORE_LLDP_NEAREST_CUSTOMER_BRIDGE: 1635337519Sdavidcs val = LLDP_NEAREST_CUSTOMER_BRIDGE; 1636337519Sdavidcs break; 1637337519Sdavidcs default: 1638337519Sdavidcs DP_ERR(p_hwfn, "Invalid agent type %d\n", p_params->agent); 1639337519Sdavidcs return ECORE_INVAL; 1640337519Sdavidcs } 1641337519Sdavidcs 1642337519Sdavidcs SET_MFW_FIELD(mb_param, DRV_MB_PARAM_LLDP_AGENT, val); 1643337519Sdavidcs addr = p_hwfn->mcp_info->port_addr + 1644337519Sdavidcs offsetof(struct public_port, lldp_config_params[val]); 1645337519Sdavidcs 1646337519Sdavidcs OSAL_MEMSET(&lldp_params, 0, sizeof(lldp_params)); 1647337519Sdavidcs SET_MFW_FIELD(lldp_params.config, LLDP_CONFIG_TX_INTERVAL, 1648337519Sdavidcs p_params->tx_interval); 1649337519Sdavidcs SET_MFW_FIELD(lldp_params.config, LLDP_CONFIG_HOLD, p_params->tx_hold); 1650337519Sdavidcs SET_MFW_FIELD(lldp_params.config, LLDP_CONFIG_MAX_CREDIT, 1651337519Sdavidcs p_params->tx_credit); 1652337519Sdavidcs SET_MFW_FIELD(lldp_params.config, LLDP_CONFIG_ENABLE_RX, 1653337519Sdavidcs !!p_params->rx_enable); 1654337519Sdavidcs SET_MFW_FIELD(lldp_params.config, LLDP_CONFIG_ENABLE_TX, 1655337519Sdavidcs !!p_params->tx_enable); 1656337519Sdavidcs 1657337519Sdavidcs for (i = 0; i < ECORE_LLDP_CHASSIS_ID_STAT_LEN; i++) 1658337519Sdavidcs p_params->chassis_id_tlv[i] = 1659337519Sdavidcs OSAL_CPU_TO_BE32(p_params->chassis_id_tlv[i]); 1660337519Sdavidcs OSAL_MEMCPY(lldp_params.local_chassis_id, p_params->chassis_id_tlv, 1661337519Sdavidcs sizeof(lldp_params.local_chassis_id)); 1662337519Sdavidcs 1663337519Sdavidcs for (i = 0; i < ECORE_LLDP_PORT_ID_STAT_LEN; i++) 1664337519Sdavidcs p_params->port_id_tlv[i] = 1665337519Sdavidcs OSAL_CPU_TO_BE32(p_params->port_id_tlv[i]); 1666337519Sdavidcs OSAL_MEMCPY(lldp_params.local_port_id, p_params->port_id_tlv, 1667337519Sdavidcs sizeof(lldp_params.local_port_id)); 1668337519Sdavidcs 1669337519Sdavidcs ecore_memcpy_to(p_hwfn, p_ptt, addr, &lldp_params, sizeof(lldp_params)); 1670337519Sdavidcs 1671337519Sdavidcs rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_SET_LLDP, 1672337519Sdavidcs mb_param, &mcp_resp, &mcp_param); 1673337519Sdavidcs if (rc != ECORE_SUCCESS) 1674337519Sdavidcs DP_NOTICE(p_hwfn, false, "SET_LLDP failed, error = %d\n", rc); 1675337519Sdavidcs 1676337519Sdavidcs return rc; 1677337519Sdavidcs} 1678337519Sdavidcs 1679337519Sdavidcsenum _ecore_status_t 1680337519Sdavidcsecore_lldp_set_system_tlvs(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 1681337519Sdavidcs struct ecore_lldp_sys_tlvs *p_params) 1682337519Sdavidcs{ 1683337519Sdavidcs u32 mb_param = 0, mcp_resp = 0, mcp_param = 0; 1684337519Sdavidcs enum _ecore_status_t rc = ECORE_SUCCESS; 1685337519Sdavidcs struct lldp_system_tlvs_buffer_s lld_tlv_buf; 1686337519Sdavidcs u32 addr, *p_val; 1687337519Sdavidcs u8 len; 1688337519Sdavidcs int i; 1689337519Sdavidcs 1690337519Sdavidcs p_val = (u32 *)p_params->buf; 1691337519Sdavidcs for (i = 0; i < ECORE_LLDP_SYS_TLV_SIZE / 4; i++) 1692337519Sdavidcs p_val[i] = OSAL_CPU_TO_BE32(p_val[i]); 1693337519Sdavidcs 1694337519Sdavidcs OSAL_MEMSET(&lld_tlv_buf, 0, sizeof(lld_tlv_buf)); 1695337519Sdavidcs SET_MFW_FIELD(lld_tlv_buf.flags, LLDP_SYSTEM_TLV_VALID, 1); 1696337519Sdavidcs SET_MFW_FIELD(lld_tlv_buf.flags, LLDP_SYSTEM_TLV_MANDATORY, 1697337519Sdavidcs !!p_params->discard_mandatory_tlv); 1698337519Sdavidcs SET_MFW_FIELD(lld_tlv_buf.flags, LLDP_SYSTEM_TLV_LENGTH, 1699337519Sdavidcs p_params->buf_size); 1700337519Sdavidcs len = ECORE_LLDP_SYS_TLV_SIZE / 2; 1701337519Sdavidcs OSAL_MEMCPY(lld_tlv_buf.data, p_params->buf, len); 1702337519Sdavidcs 1703337519Sdavidcs addr = p_hwfn->mcp_info->port_addr + 1704337519Sdavidcs offsetof(struct public_port, system_lldp_tlvs_buf); 1705337519Sdavidcs ecore_memcpy_to(p_hwfn, p_ptt, addr, &lld_tlv_buf, sizeof(lld_tlv_buf)); 1706337519Sdavidcs 1707337519Sdavidcs if (p_params->buf_size > len) { 1708337519Sdavidcs addr = p_hwfn->mcp_info->port_addr + 1709337519Sdavidcs offsetof(struct public_port, system_lldp_tlvs_buf2); 1710337519Sdavidcs ecore_memcpy_to(p_hwfn, p_ptt, addr, &p_params->buf[len], 1711337519Sdavidcs ECORE_LLDP_SYS_TLV_SIZE / 2); 1712337519Sdavidcs } 1713337519Sdavidcs 1714337519Sdavidcs rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_SET_LLDP, 1715337519Sdavidcs mb_param, &mcp_resp, &mcp_param); 1716337519Sdavidcs if (rc != ECORE_SUCCESS) 1717337519Sdavidcs DP_NOTICE(p_hwfn, false, "SET_LLDP failed, error = %d\n", rc); 1718337519Sdavidcs 1719337519Sdavidcs return rc; 1720337519Sdavidcs} 1721337519Sdavidcs 1722337519Sdavidcsenum _ecore_status_t 1723337519Sdavidcsecore_dcbx_get_dscp_priority(struct ecore_hwfn *p_hwfn, 1724337519Sdavidcs u8 dscp_index, u8 *p_dscp_pri) 1725337519Sdavidcs{ 1726337519Sdavidcs struct ecore_dcbx_get *p_dcbx_info; 1727337519Sdavidcs enum _ecore_status_t rc; 1728337519Sdavidcs 1729337519Sdavidcs if (dscp_index >= ECORE_DCBX_DSCP_SIZE) { 1730337519Sdavidcs DP_ERR(p_hwfn, "Invalid dscp index %d\n", dscp_index); 1731337519Sdavidcs return ECORE_INVAL; 1732337519Sdavidcs } 1733337519Sdavidcs 1734337519Sdavidcs p_dcbx_info = OSAL_ALLOC(p_hwfn->p_dev, GFP_KERNEL, 1735337519Sdavidcs sizeof(*p_dcbx_info)); 1736337519Sdavidcs if (!p_dcbx_info) 1737337519Sdavidcs return ECORE_NOMEM; 1738337519Sdavidcs 1739337519Sdavidcs OSAL_MEMSET(p_dcbx_info, 0, sizeof(*p_dcbx_info)); 1740337519Sdavidcs rc = ecore_dcbx_query_params(p_hwfn, p_dcbx_info, 1741337519Sdavidcs ECORE_DCBX_OPERATIONAL_MIB); 1742337519Sdavidcs if (rc) { 1743337519Sdavidcs OSAL_FREE(p_hwfn->p_dev, p_dcbx_info); 1744337519Sdavidcs return rc; 1745337519Sdavidcs } 1746337519Sdavidcs 1747337519Sdavidcs *p_dscp_pri = p_dcbx_info->dscp.dscp_pri_map[dscp_index]; 1748337519Sdavidcs OSAL_FREE(p_hwfn->p_dev, p_dcbx_info); 1749337519Sdavidcs 1750337519Sdavidcs return ECORE_SUCCESS; 1751337519Sdavidcs} 1752337519Sdavidcs 1753337519Sdavidcsenum _ecore_status_t 1754337519Sdavidcsecore_dcbx_set_dscp_priority(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 1755337519Sdavidcs u8 dscp_index, u8 pri_val) 1756337519Sdavidcs{ 1757337519Sdavidcs struct ecore_dcbx_set dcbx_set; 1758337519Sdavidcs enum _ecore_status_t rc; 1759337519Sdavidcs 1760337519Sdavidcs if (dscp_index >= ECORE_DCBX_DSCP_SIZE || 1761337519Sdavidcs pri_val >= ECORE_MAX_PFC_PRIORITIES) { 1762337519Sdavidcs DP_ERR(p_hwfn, "Invalid dscp params: index = %d pri = %d\n", 1763337519Sdavidcs dscp_index, pri_val); 1764337519Sdavidcs return ECORE_INVAL; 1765337519Sdavidcs } 1766337519Sdavidcs 1767337519Sdavidcs OSAL_MEMSET(&dcbx_set, 0, sizeof(dcbx_set)); 1768337519Sdavidcs rc = ecore_dcbx_get_config_params(p_hwfn, &dcbx_set); 1769337519Sdavidcs if (rc) 1770337519Sdavidcs return rc; 1771337519Sdavidcs 1772337519Sdavidcs dcbx_set.override_flags = ECORE_DCBX_OVERRIDE_DSCP_CFG; 1773337519Sdavidcs dcbx_set.dscp.dscp_pri_map[dscp_index] = pri_val; 1774337519Sdavidcs 1775337519Sdavidcs return ecore_dcbx_config_params(p_hwfn, p_ptt, &dcbx_set, 1); 1776337519Sdavidcs} 1777337519Sdavidcs 1778337519Sdavidcsenum _ecore_status_t 1779337519Sdavidcsecore_lldp_get_stats(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 1780337519Sdavidcs struct ecore_lldp_stats *p_params) 1781337519Sdavidcs{ 1782337519Sdavidcs u32 mcp_resp = 0, mcp_param = 0, addr, val; 1783337519Sdavidcs struct lldp_stats_stc lldp_stats; 1784337519Sdavidcs enum _ecore_status_t rc; 1785337519Sdavidcs 1786337519Sdavidcs switch (p_params->agent) { 1787337519Sdavidcs case ECORE_LLDP_NEAREST_BRIDGE: 1788337519Sdavidcs val = LLDP_NEAREST_BRIDGE; 1789337519Sdavidcs break; 1790337519Sdavidcs case ECORE_LLDP_NEAREST_NON_TPMR_BRIDGE: 1791337519Sdavidcs val = LLDP_NEAREST_NON_TPMR_BRIDGE; 1792337519Sdavidcs break; 1793337519Sdavidcs case ECORE_LLDP_NEAREST_CUSTOMER_BRIDGE: 1794337519Sdavidcs val = LLDP_NEAREST_CUSTOMER_BRIDGE; 1795337519Sdavidcs break; 1796337519Sdavidcs default: 1797337519Sdavidcs DP_ERR(p_hwfn, "Invalid agent type %d\n", p_params->agent); 1798337519Sdavidcs return ECORE_INVAL; 1799337519Sdavidcs } 1800337519Sdavidcs 1801337519Sdavidcs rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_GET_LLDP_STATS, 1802337519Sdavidcs val << DRV_MB_PARAM_LLDP_STATS_AGENT_OFFSET, 1803337519Sdavidcs &mcp_resp, &mcp_param); 1804337519Sdavidcs if (rc != ECORE_SUCCESS) { 1805337519Sdavidcs DP_ERR(p_hwfn, "GET_LLDP_STATS failed, error = %d\n", rc); 1806337519Sdavidcs return rc; 1807337519Sdavidcs } 1808337519Sdavidcs 1809337519Sdavidcs addr = p_hwfn->mcp_info->drv_mb_addr + 1810337519Sdavidcs OFFSETOF(struct public_drv_mb, union_data); 1811337519Sdavidcs 1812337519Sdavidcs ecore_memcpy_from(p_hwfn, p_ptt, &lldp_stats, addr, sizeof(lldp_stats)); 1813337519Sdavidcs 1814337519Sdavidcs p_params->tx_frames = lldp_stats.tx_frames_total; 1815337519Sdavidcs p_params->rx_frames = lldp_stats.rx_frames_total; 1816337519Sdavidcs p_params->rx_discards = lldp_stats.rx_frames_discarded; 1817337519Sdavidcs p_params->rx_age_outs = lldp_stats.rx_age_outs; 1818337519Sdavidcs 1819337519Sdavidcs return ECORE_SUCCESS; 1820337519Sdavidcs} 1821