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, &params->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, &params->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 = &params->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 = &params->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, &params->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					&params->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					&params->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					&params->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, &param);
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