xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * QLogic qlcnic NIC Driver
4*4882a593Smuzhiyun  * Copyright (c)  2009-2013 QLogic Corporation
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <linux/types.h>
8*4882a593Smuzhiyun #include "qlcnic.h"
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #define QLC_DCB_NUM_PARAM		3
11*4882a593Smuzhiyun #define QLC_DCB_LOCAL_IDX		0
12*4882a593Smuzhiyun #define QLC_DCB_OPER_IDX		1
13*4882a593Smuzhiyun #define QLC_DCB_PEER_IDX		2
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #define QLC_DCB_GET_MAP(V)		(1 << V)
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #define QLC_DCB_FW_VER			0x2
18*4882a593Smuzhiyun #define QLC_DCB_MAX_TC			0x8
19*4882a593Smuzhiyun #define QLC_DCB_MAX_APP			0x8
20*4882a593Smuzhiyun #define QLC_DCB_MAX_PRIO		QLC_DCB_MAX_TC
21*4882a593Smuzhiyun #define QLC_DCB_MAX_PG			QLC_DCB_MAX_TC
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #define QLC_DCB_TSA_SUPPORT(V)		(V & 0x1)
24*4882a593Smuzhiyun #define QLC_DCB_ETS_SUPPORT(V)		((V >> 1) & 0x1)
25*4882a593Smuzhiyun #define QLC_DCB_VERSION_SUPPORT(V)	((V >> 2) & 0xf)
26*4882a593Smuzhiyun #define QLC_DCB_MAX_NUM_TC(V)		((V >> 20) & 0xf)
27*4882a593Smuzhiyun #define QLC_DCB_MAX_NUM_ETS_TC(V)	((V >> 24) & 0xf)
28*4882a593Smuzhiyun #define QLC_DCB_MAX_NUM_PFC_TC(V)	((V >> 28) & 0xf)
29*4882a593Smuzhiyun #define QLC_DCB_GET_TC_PRIO(X, P)	((X >> (P * 3)) & 0x7)
30*4882a593Smuzhiyun #define QLC_DCB_GET_PGID_PRIO(X, P)	((X >> (P * 8)) & 0xff)
31*4882a593Smuzhiyun #define QLC_DCB_GET_BWPER_PG(X, P)	((X >> (P * 8)) & 0xff)
32*4882a593Smuzhiyun #define QLC_DCB_GET_TSA_PG(X, P)	((X >> (P * 8)) & 0xff)
33*4882a593Smuzhiyun #define QLC_DCB_GET_PFC_PRIO(X, P)	(((X >> 24) >> P) & 0x1)
34*4882a593Smuzhiyun #define QLC_DCB_GET_PROTO_ID_APP(X)	((X >> 8) & 0xffff)
35*4882a593Smuzhiyun #define QLC_DCB_GET_SELECTOR_APP(X)	(X & 0xff)
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #define QLC_DCB_LOCAL_PARAM_FWID	0x3
38*4882a593Smuzhiyun #define QLC_DCB_OPER_PARAM_FWID		0x1
39*4882a593Smuzhiyun #define QLC_DCB_PEER_PARAM_FWID		0x2
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #define QLC_83XX_DCB_GET_NUMAPP(X)	((X >> 2) & 0xf)
42*4882a593Smuzhiyun #define QLC_83XX_DCB_TSA_VALID(X)	(X & 0x1)
43*4882a593Smuzhiyun #define QLC_83XX_DCB_PFC_VALID(X)	((X >> 1) & 0x1)
44*4882a593Smuzhiyun #define QLC_83XX_DCB_GET_PRIOMAP_APP(X)	(X >> 24)
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun #define QLC_82XX_DCB_GET_NUMAPP(X)	((X >> 12) & 0xf)
47*4882a593Smuzhiyun #define QLC_82XX_DCB_TSA_VALID(X)	((X >> 4) & 0x1)
48*4882a593Smuzhiyun #define QLC_82XX_DCB_PFC_VALID(X)	((X >> 5) & 0x1)
49*4882a593Smuzhiyun #define QLC_82XX_DCB_GET_PRIOVAL_APP(X)	((X >> 24) & 0x7)
50*4882a593Smuzhiyun #define QLC_82XX_DCB_GET_PRIOMAP_APP(X)	(1 << X)
51*4882a593Smuzhiyun #define QLC_82XX_DCB_PRIO_TC_MAP	(0x76543210)
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun static const struct dcbnl_rtnl_ops qlcnic_dcbnl_ops;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun static void qlcnic_dcb_aen_work(struct work_struct *);
56*4882a593Smuzhiyun static void qlcnic_dcb_data_cee_param_map(struct qlcnic_adapter *);
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun static inline void __qlcnic_init_dcbnl_ops(struct qlcnic_dcb *);
59*4882a593Smuzhiyun static void __qlcnic_dcb_free(struct qlcnic_dcb *);
60*4882a593Smuzhiyun static int __qlcnic_dcb_attach(struct qlcnic_dcb *);
61*4882a593Smuzhiyun static int __qlcnic_dcb_query_hw_capability(struct qlcnic_dcb *, char *);
62*4882a593Smuzhiyun static void __qlcnic_dcb_get_info(struct qlcnic_dcb *);
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_dcb *);
65*4882a593Smuzhiyun static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_dcb *, char *, u8);
66*4882a593Smuzhiyun static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_dcb *);
67*4882a593Smuzhiyun static void qlcnic_82xx_dcb_aen_handler(struct qlcnic_dcb *, void *);
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_dcb *);
70*4882a593Smuzhiyun static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_dcb *, char *, u8);
71*4882a593Smuzhiyun static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_dcb *);
72*4882a593Smuzhiyun static void qlcnic_83xx_dcb_aen_handler(struct qlcnic_dcb *, void *);
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun struct qlcnic_dcb_capability {
75*4882a593Smuzhiyun 	bool	tsa_capability;
76*4882a593Smuzhiyun 	bool	ets_capability;
77*4882a593Smuzhiyun 	u8	max_num_tc;
78*4882a593Smuzhiyun 	u8	max_ets_tc;
79*4882a593Smuzhiyun 	u8	max_pfc_tc;
80*4882a593Smuzhiyun 	u8	dcb_capability;
81*4882a593Smuzhiyun };
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun struct qlcnic_dcb_param {
84*4882a593Smuzhiyun 	u32 hdr_prio_pfc_map[2];
85*4882a593Smuzhiyun 	u32 prio_pg_map[2];
86*4882a593Smuzhiyun 	u32 pg_bw_map[2];
87*4882a593Smuzhiyun 	u32 pg_tsa_map[2];
88*4882a593Smuzhiyun 	u32 app[QLC_DCB_MAX_APP];
89*4882a593Smuzhiyun };
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun struct qlcnic_dcb_mbx_params {
92*4882a593Smuzhiyun 	/* 1st local, 2nd operational 3rd remote */
93*4882a593Smuzhiyun 	struct qlcnic_dcb_param type[3];
94*4882a593Smuzhiyun 	u32 prio_tc_map;
95*4882a593Smuzhiyun };
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun struct qlcnic_82xx_dcb_param_mbx_le {
98*4882a593Smuzhiyun 	__le32 hdr_prio_pfc_map[2];
99*4882a593Smuzhiyun 	__le32 prio_pg_map[2];
100*4882a593Smuzhiyun 	__le32 pg_bw_map[2];
101*4882a593Smuzhiyun 	__le32 pg_tsa_map[2];
102*4882a593Smuzhiyun 	__le32 app[QLC_DCB_MAX_APP];
103*4882a593Smuzhiyun };
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun enum qlcnic_dcb_selector {
106*4882a593Smuzhiyun 	QLC_SELECTOR_DEF = 0x0,
107*4882a593Smuzhiyun 	QLC_SELECTOR_ETHER,
108*4882a593Smuzhiyun 	QLC_SELECTOR_TCP,
109*4882a593Smuzhiyun 	QLC_SELECTOR_UDP,
110*4882a593Smuzhiyun };
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun enum qlcnic_dcb_prio_type {
113*4882a593Smuzhiyun 	QLC_PRIO_NONE = 0,
114*4882a593Smuzhiyun 	QLC_PRIO_GROUP,
115*4882a593Smuzhiyun 	QLC_PRIO_LINK,
116*4882a593Smuzhiyun };
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun enum qlcnic_dcb_pfc_type {
119*4882a593Smuzhiyun 	QLC_PFC_DISABLED = 0,
120*4882a593Smuzhiyun 	QLC_PFC_FULL,
121*4882a593Smuzhiyun 	QLC_PFC_TX,
122*4882a593Smuzhiyun 	QLC_PFC_RX
123*4882a593Smuzhiyun };
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun struct qlcnic_dcb_prio_cfg {
126*4882a593Smuzhiyun 	bool valid;
127*4882a593Smuzhiyun 	enum qlcnic_dcb_pfc_type pfc_type;
128*4882a593Smuzhiyun };
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun struct qlcnic_dcb_pg_cfg {
131*4882a593Smuzhiyun 	bool valid;
132*4882a593Smuzhiyun 	u8 total_bw_percent;		/* of Link/ port BW */
133*4882a593Smuzhiyun 	u8 prio_count;
134*4882a593Smuzhiyun 	u8 tsa_type;
135*4882a593Smuzhiyun };
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun struct qlcnic_dcb_tc_cfg {
138*4882a593Smuzhiyun 	bool valid;
139*4882a593Smuzhiyun 	struct qlcnic_dcb_prio_cfg prio_cfg[QLC_DCB_MAX_PRIO];
140*4882a593Smuzhiyun 	enum qlcnic_dcb_prio_type prio_type;	/* always prio_link */
141*4882a593Smuzhiyun 	u8 link_percent;			/* % of link bandwidth */
142*4882a593Smuzhiyun 	u8 bwg_percent;				/* % of BWG's bandwidth */
143*4882a593Smuzhiyun 	u8 up_tc_map;
144*4882a593Smuzhiyun 	u8 pgid;
145*4882a593Smuzhiyun };
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun struct qlcnic_dcb_app {
148*4882a593Smuzhiyun 	bool valid;
149*4882a593Smuzhiyun 	enum qlcnic_dcb_selector selector;
150*4882a593Smuzhiyun 	u16 protocol;
151*4882a593Smuzhiyun 	u8 priority;
152*4882a593Smuzhiyun };
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun struct qlcnic_dcb_cee {
155*4882a593Smuzhiyun 	struct qlcnic_dcb_tc_cfg tc_cfg[QLC_DCB_MAX_TC];
156*4882a593Smuzhiyun 	struct qlcnic_dcb_pg_cfg pg_cfg[QLC_DCB_MAX_PG];
157*4882a593Smuzhiyun 	struct qlcnic_dcb_app app[QLC_DCB_MAX_APP];
158*4882a593Smuzhiyun 	bool tc_param_valid;
159*4882a593Smuzhiyun 	bool pfc_mode_enable;
160*4882a593Smuzhiyun };
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun struct qlcnic_dcb_cfg {
163*4882a593Smuzhiyun 	/* 0 - local, 1 - operational, 2 - remote */
164*4882a593Smuzhiyun 	struct qlcnic_dcb_cee type[QLC_DCB_NUM_PARAM];
165*4882a593Smuzhiyun 	struct qlcnic_dcb_capability capability;
166*4882a593Smuzhiyun 	u32 version;
167*4882a593Smuzhiyun };
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun static const struct qlcnic_dcb_ops qlcnic_83xx_dcb_ops = {
170*4882a593Smuzhiyun 	.init_dcbnl_ops		= __qlcnic_init_dcbnl_ops,
171*4882a593Smuzhiyun 	.free			= __qlcnic_dcb_free,
172*4882a593Smuzhiyun 	.attach			= __qlcnic_dcb_attach,
173*4882a593Smuzhiyun 	.query_hw_capability	= __qlcnic_dcb_query_hw_capability,
174*4882a593Smuzhiyun 	.get_info		= __qlcnic_dcb_get_info,
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	.get_hw_capability	= qlcnic_83xx_dcb_get_hw_capability,
177*4882a593Smuzhiyun 	.query_cee_param	= qlcnic_83xx_dcb_query_cee_param,
178*4882a593Smuzhiyun 	.get_cee_cfg		= qlcnic_83xx_dcb_get_cee_cfg,
179*4882a593Smuzhiyun 	.aen_handler		= qlcnic_83xx_dcb_aen_handler,
180*4882a593Smuzhiyun };
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun static const struct qlcnic_dcb_ops qlcnic_82xx_dcb_ops = {
183*4882a593Smuzhiyun 	.init_dcbnl_ops		= __qlcnic_init_dcbnl_ops,
184*4882a593Smuzhiyun 	.free			= __qlcnic_dcb_free,
185*4882a593Smuzhiyun 	.attach			= __qlcnic_dcb_attach,
186*4882a593Smuzhiyun 	.query_hw_capability	= __qlcnic_dcb_query_hw_capability,
187*4882a593Smuzhiyun 	.get_info		= __qlcnic_dcb_get_info,
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	.get_hw_capability	= qlcnic_82xx_dcb_get_hw_capability,
190*4882a593Smuzhiyun 	.query_cee_param	= qlcnic_82xx_dcb_query_cee_param,
191*4882a593Smuzhiyun 	.get_cee_cfg		= qlcnic_82xx_dcb_get_cee_cfg,
192*4882a593Smuzhiyun 	.aen_handler		= qlcnic_82xx_dcb_aen_handler,
193*4882a593Smuzhiyun };
194*4882a593Smuzhiyun 
qlcnic_dcb_get_num_app(struct qlcnic_adapter * adapter,u32 val)195*4882a593Smuzhiyun static u8 qlcnic_dcb_get_num_app(struct qlcnic_adapter *adapter, u32 val)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun 	if (qlcnic_82xx_check(adapter))
198*4882a593Smuzhiyun 		return QLC_82XX_DCB_GET_NUMAPP(val);
199*4882a593Smuzhiyun 	else
200*4882a593Smuzhiyun 		return QLC_83XX_DCB_GET_NUMAPP(val);
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun 
qlcnic_dcb_pfc_hdr_valid(struct qlcnic_adapter * adapter,u32 val)203*4882a593Smuzhiyun static inline u8 qlcnic_dcb_pfc_hdr_valid(struct qlcnic_adapter *adapter,
204*4882a593Smuzhiyun 					  u32 val)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun 	if (qlcnic_82xx_check(adapter))
207*4882a593Smuzhiyun 		return QLC_82XX_DCB_PFC_VALID(val);
208*4882a593Smuzhiyun 	else
209*4882a593Smuzhiyun 		return QLC_83XX_DCB_PFC_VALID(val);
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
qlcnic_dcb_tsa_hdr_valid(struct qlcnic_adapter * adapter,u32 val)212*4882a593Smuzhiyun static inline u8 qlcnic_dcb_tsa_hdr_valid(struct qlcnic_adapter *adapter,
213*4882a593Smuzhiyun 					  u32 val)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun 	if (qlcnic_82xx_check(adapter))
216*4882a593Smuzhiyun 		return QLC_82XX_DCB_TSA_VALID(val);
217*4882a593Smuzhiyun 	else
218*4882a593Smuzhiyun 		return QLC_83XX_DCB_TSA_VALID(val);
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun 
qlcnic_dcb_get_prio_map_app(struct qlcnic_adapter * adapter,u32 val)221*4882a593Smuzhiyun static inline u8 qlcnic_dcb_get_prio_map_app(struct qlcnic_adapter *adapter,
222*4882a593Smuzhiyun 					     u32 val)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun 	if (qlcnic_82xx_check(adapter))
225*4882a593Smuzhiyun 		return QLC_82XX_DCB_GET_PRIOMAP_APP(val);
226*4882a593Smuzhiyun 	else
227*4882a593Smuzhiyun 		return QLC_83XX_DCB_GET_PRIOMAP_APP(val);
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun 
qlcnic_dcb_prio_count(u8 up_tc_map)230*4882a593Smuzhiyun static int qlcnic_dcb_prio_count(u8 up_tc_map)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun 	int j;
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	for (j = 0; j < QLC_DCB_MAX_TC; j++)
235*4882a593Smuzhiyun 		if (up_tc_map & QLC_DCB_GET_MAP(j))
236*4882a593Smuzhiyun 			break;
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	return j;
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun 
__qlcnic_init_dcbnl_ops(struct qlcnic_dcb * dcb)241*4882a593Smuzhiyun static inline void __qlcnic_init_dcbnl_ops(struct qlcnic_dcb *dcb)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun 	if (test_bit(QLCNIC_DCB_STATE, &dcb->state))
244*4882a593Smuzhiyun 		dcb->adapter->netdev->dcbnl_ops = &qlcnic_dcbnl_ops;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun 
qlcnic_set_dcb_ops(struct qlcnic_adapter * adapter)247*4882a593Smuzhiyun static void qlcnic_set_dcb_ops(struct qlcnic_adapter *adapter)
248*4882a593Smuzhiyun {
249*4882a593Smuzhiyun 	if (qlcnic_82xx_check(adapter))
250*4882a593Smuzhiyun 		adapter->dcb->ops = &qlcnic_82xx_dcb_ops;
251*4882a593Smuzhiyun 	else if (qlcnic_83xx_check(adapter))
252*4882a593Smuzhiyun 		adapter->dcb->ops = &qlcnic_83xx_dcb_ops;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun 
qlcnic_register_dcb(struct qlcnic_adapter * adapter)255*4882a593Smuzhiyun int qlcnic_register_dcb(struct qlcnic_adapter *adapter)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun 	struct qlcnic_dcb *dcb;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	if (qlcnic_sriov_vf_check(adapter))
260*4882a593Smuzhiyun 		return 0;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	dcb = kzalloc(sizeof(struct qlcnic_dcb), GFP_ATOMIC);
263*4882a593Smuzhiyun 	if (!dcb)
264*4882a593Smuzhiyun 		return -ENOMEM;
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	adapter->dcb = dcb;
267*4882a593Smuzhiyun 	dcb->adapter = adapter;
268*4882a593Smuzhiyun 	qlcnic_set_dcb_ops(adapter);
269*4882a593Smuzhiyun 	dcb->state = 0;
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	return 0;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun 
__qlcnic_dcb_free(struct qlcnic_dcb * dcb)274*4882a593Smuzhiyun static void __qlcnic_dcb_free(struct qlcnic_dcb *dcb)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun 	struct qlcnic_adapter *adapter;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	if (!dcb)
279*4882a593Smuzhiyun 		return;
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	adapter = dcb->adapter;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	while (test_bit(QLCNIC_DCB_AEN_MODE, &dcb->state))
284*4882a593Smuzhiyun 		usleep_range(10000, 11000);
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	cancel_delayed_work_sync(&dcb->aen_work);
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	if (dcb->wq) {
289*4882a593Smuzhiyun 		destroy_workqueue(dcb->wq);
290*4882a593Smuzhiyun 		dcb->wq = NULL;
291*4882a593Smuzhiyun 	}
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	kfree(dcb->cfg);
294*4882a593Smuzhiyun 	dcb->cfg = NULL;
295*4882a593Smuzhiyun 	kfree(dcb->param);
296*4882a593Smuzhiyun 	dcb->param = NULL;
297*4882a593Smuzhiyun 	kfree(dcb);
298*4882a593Smuzhiyun 	adapter->dcb = NULL;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun 
__qlcnic_dcb_get_info(struct qlcnic_dcb * dcb)301*4882a593Smuzhiyun static void __qlcnic_dcb_get_info(struct qlcnic_dcb *dcb)
302*4882a593Smuzhiyun {
303*4882a593Smuzhiyun 	qlcnic_dcb_get_hw_capability(dcb);
304*4882a593Smuzhiyun 	qlcnic_dcb_get_cee_cfg(dcb);
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun 
__qlcnic_dcb_attach(struct qlcnic_dcb * dcb)307*4882a593Smuzhiyun static int __qlcnic_dcb_attach(struct qlcnic_dcb *dcb)
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun 	int err = 0;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	INIT_DELAYED_WORK(&dcb->aen_work, qlcnic_dcb_aen_work);
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	dcb->wq = create_singlethread_workqueue("qlcnic-dcb");
314*4882a593Smuzhiyun 	if (!dcb->wq) {
315*4882a593Smuzhiyun 		dev_err(&dcb->adapter->pdev->dev,
316*4882a593Smuzhiyun 			"DCB workqueue allocation failed. DCB will be disabled\n");
317*4882a593Smuzhiyun 		return -1;
318*4882a593Smuzhiyun 	}
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	dcb->cfg = kzalloc(sizeof(struct qlcnic_dcb_cfg), GFP_ATOMIC);
321*4882a593Smuzhiyun 	if (!dcb->cfg) {
322*4882a593Smuzhiyun 		err = -ENOMEM;
323*4882a593Smuzhiyun 		goto out_free_wq;
324*4882a593Smuzhiyun 	}
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	dcb->param = kzalloc(sizeof(struct qlcnic_dcb_mbx_params), GFP_ATOMIC);
327*4882a593Smuzhiyun 	if (!dcb->param) {
328*4882a593Smuzhiyun 		err = -ENOMEM;
329*4882a593Smuzhiyun 		goto out_free_cfg;
330*4882a593Smuzhiyun 	}
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	return 0;
333*4882a593Smuzhiyun out_free_cfg:
334*4882a593Smuzhiyun 	kfree(dcb->cfg);
335*4882a593Smuzhiyun 	dcb->cfg = NULL;
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun out_free_wq:
338*4882a593Smuzhiyun 	destroy_workqueue(dcb->wq);
339*4882a593Smuzhiyun 	dcb->wq = NULL;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	return err;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun 
__qlcnic_dcb_query_hw_capability(struct qlcnic_dcb * dcb,char * buf)344*4882a593Smuzhiyun static int __qlcnic_dcb_query_hw_capability(struct qlcnic_dcb *dcb, char *buf)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun 	struct qlcnic_adapter *adapter = dcb->adapter;
347*4882a593Smuzhiyun 	struct qlcnic_cmd_args cmd;
348*4882a593Smuzhiyun 	u32 mbx_out;
349*4882a593Smuzhiyun 	int err;
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_CAP);
352*4882a593Smuzhiyun 	if (err)
353*4882a593Smuzhiyun 		return err;
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	err = qlcnic_issue_cmd(adapter, &cmd);
356*4882a593Smuzhiyun 	if (err) {
357*4882a593Smuzhiyun 		dev_err(&adapter->pdev->dev,
358*4882a593Smuzhiyun 			"Failed to query DCBX capability, err %d\n", err);
359*4882a593Smuzhiyun 	} else {
360*4882a593Smuzhiyun 		mbx_out = cmd.rsp.arg[1];
361*4882a593Smuzhiyun 		if (buf)
362*4882a593Smuzhiyun 			memcpy(buf, &mbx_out, sizeof(u32));
363*4882a593Smuzhiyun 	}
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	qlcnic_free_mbx_args(&cmd);
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	return err;
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun 
__qlcnic_dcb_get_capability(struct qlcnic_dcb * dcb,u32 * val)370*4882a593Smuzhiyun static int __qlcnic_dcb_get_capability(struct qlcnic_dcb *dcb, u32 *val)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun 	struct qlcnic_dcb_capability *cap = &dcb->cfg->capability;
373*4882a593Smuzhiyun 	u32 mbx_out;
374*4882a593Smuzhiyun 	int err;
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 	memset(cap, 0, sizeof(struct qlcnic_dcb_capability));
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	err = qlcnic_dcb_query_hw_capability(dcb, (char *)val);
379*4882a593Smuzhiyun 	if (err)
380*4882a593Smuzhiyun 		return err;
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	mbx_out = *val;
383*4882a593Smuzhiyun 	if (QLC_DCB_TSA_SUPPORT(mbx_out))
384*4882a593Smuzhiyun 		cap->tsa_capability = true;
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 	if (QLC_DCB_ETS_SUPPORT(mbx_out))
387*4882a593Smuzhiyun 		cap->ets_capability = true;
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	cap->max_num_tc = QLC_DCB_MAX_NUM_TC(mbx_out);
390*4882a593Smuzhiyun 	cap->max_ets_tc = QLC_DCB_MAX_NUM_ETS_TC(mbx_out);
391*4882a593Smuzhiyun 	cap->max_pfc_tc = QLC_DCB_MAX_NUM_PFC_TC(mbx_out);
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun 	if (cap->max_num_tc > QLC_DCB_MAX_TC ||
394*4882a593Smuzhiyun 	    cap->max_ets_tc > cap->max_num_tc ||
395*4882a593Smuzhiyun 	    cap->max_pfc_tc > cap->max_num_tc) {
396*4882a593Smuzhiyun 		dev_err(&dcb->adapter->pdev->dev, "Invalid DCB configuration\n");
397*4882a593Smuzhiyun 		return -EINVAL;
398*4882a593Smuzhiyun 	}
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	return err;
401*4882a593Smuzhiyun }
402*4882a593Smuzhiyun 
qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_dcb * dcb)403*4882a593Smuzhiyun static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_dcb *dcb)
404*4882a593Smuzhiyun {
405*4882a593Smuzhiyun 	struct qlcnic_dcb_cfg *cfg = dcb->cfg;
406*4882a593Smuzhiyun 	struct qlcnic_dcb_capability *cap;
407*4882a593Smuzhiyun 	u32 mbx_out;
408*4882a593Smuzhiyun 	int err;
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	err = __qlcnic_dcb_get_capability(dcb, &mbx_out);
411*4882a593Smuzhiyun 	if (err)
412*4882a593Smuzhiyun 		return err;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	cap = &cfg->capability;
415*4882a593Smuzhiyun 	cap->dcb_capability = DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_LLD_MANAGED;
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	if (cap->dcb_capability && cap->tsa_capability && cap->ets_capability)
418*4882a593Smuzhiyun 		set_bit(QLCNIC_DCB_STATE, &dcb->state);
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 	return err;
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun 
qlcnic_82xx_dcb_query_cee_param(struct qlcnic_dcb * dcb,char * buf,u8 type)423*4882a593Smuzhiyun static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_dcb *dcb,
424*4882a593Smuzhiyun 					   char *buf, u8 type)
425*4882a593Smuzhiyun {
426*4882a593Smuzhiyun 	u16 size = sizeof(struct qlcnic_82xx_dcb_param_mbx_le);
427*4882a593Smuzhiyun 	struct qlcnic_adapter *adapter = dcb->adapter;
428*4882a593Smuzhiyun 	struct qlcnic_82xx_dcb_param_mbx_le *prsp_le;
429*4882a593Smuzhiyun 	struct device *dev = &adapter->pdev->dev;
430*4882a593Smuzhiyun 	dma_addr_t cardrsp_phys_addr;
431*4882a593Smuzhiyun 	struct qlcnic_dcb_param rsp;
432*4882a593Smuzhiyun 	struct qlcnic_cmd_args cmd;
433*4882a593Smuzhiyun 	u64 phys_addr;
434*4882a593Smuzhiyun 	void *addr;
435*4882a593Smuzhiyun 	int err, i;
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	switch (type) {
438*4882a593Smuzhiyun 	case QLC_DCB_LOCAL_PARAM_FWID:
439*4882a593Smuzhiyun 	case QLC_DCB_OPER_PARAM_FWID:
440*4882a593Smuzhiyun 	case QLC_DCB_PEER_PARAM_FWID:
441*4882a593Smuzhiyun 		break;
442*4882a593Smuzhiyun 	default:
443*4882a593Smuzhiyun 		dev_err(dev, "Invalid parameter type %d\n", type);
444*4882a593Smuzhiyun 		return -EINVAL;
445*4882a593Smuzhiyun 	}
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	addr = dma_alloc_coherent(dev, size, &cardrsp_phys_addr, GFP_KERNEL);
448*4882a593Smuzhiyun 	if (addr == NULL)
449*4882a593Smuzhiyun 		return -ENOMEM;
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 	prsp_le = addr;
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_PARAM);
454*4882a593Smuzhiyun 	if (err)
455*4882a593Smuzhiyun 		goto out_free_rsp;
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 	phys_addr = cardrsp_phys_addr;
458*4882a593Smuzhiyun 	cmd.req.arg[1] = size | (type << 16);
459*4882a593Smuzhiyun 	cmd.req.arg[2] = MSD(phys_addr);
460*4882a593Smuzhiyun 	cmd.req.arg[3] = LSD(phys_addr);
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	err = qlcnic_issue_cmd(adapter, &cmd);
463*4882a593Smuzhiyun 	if (err) {
464*4882a593Smuzhiyun 		dev_err(dev, "Failed to query DCBX parameter, err %d\n", err);
465*4882a593Smuzhiyun 		goto out;
466*4882a593Smuzhiyun 	}
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 	memset(&rsp, 0, sizeof(struct qlcnic_dcb_param));
469*4882a593Smuzhiyun 	rsp.hdr_prio_pfc_map[0] = le32_to_cpu(prsp_le->hdr_prio_pfc_map[0]);
470*4882a593Smuzhiyun 	rsp.hdr_prio_pfc_map[1] = le32_to_cpu(prsp_le->hdr_prio_pfc_map[1]);
471*4882a593Smuzhiyun 	rsp.prio_pg_map[0] = le32_to_cpu(prsp_le->prio_pg_map[0]);
472*4882a593Smuzhiyun 	rsp.prio_pg_map[1] = le32_to_cpu(prsp_le->prio_pg_map[1]);
473*4882a593Smuzhiyun 	rsp.pg_bw_map[0] = le32_to_cpu(prsp_le->pg_bw_map[0]);
474*4882a593Smuzhiyun 	rsp.pg_bw_map[1] = le32_to_cpu(prsp_le->pg_bw_map[1]);
475*4882a593Smuzhiyun 	rsp.pg_tsa_map[0] = le32_to_cpu(prsp_le->pg_tsa_map[0]);
476*4882a593Smuzhiyun 	rsp.pg_tsa_map[1] = le32_to_cpu(prsp_le->pg_tsa_map[1]);
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 	for (i = 0; i < QLC_DCB_MAX_APP; i++)
479*4882a593Smuzhiyun 		rsp.app[i] = le32_to_cpu(prsp_le->app[i]);
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	if (buf)
482*4882a593Smuzhiyun 		memcpy(buf, &rsp, size);
483*4882a593Smuzhiyun out:
484*4882a593Smuzhiyun 	qlcnic_free_mbx_args(&cmd);
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun out_free_rsp:
487*4882a593Smuzhiyun 	dma_free_coherent(dev, size, addr, cardrsp_phys_addr);
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun 	return err;
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun 
qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_dcb * dcb)492*4882a593Smuzhiyun static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_dcb *dcb)
493*4882a593Smuzhiyun {
494*4882a593Smuzhiyun 	struct qlcnic_dcb_mbx_params *mbx;
495*4882a593Smuzhiyun 	int err;
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	mbx = dcb->param;
498*4882a593Smuzhiyun 	if (!mbx)
499*4882a593Smuzhiyun 		return 0;
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 	err = qlcnic_dcb_query_cee_param(dcb, (char *)&mbx->type[0],
502*4882a593Smuzhiyun 					 QLC_DCB_LOCAL_PARAM_FWID);
503*4882a593Smuzhiyun 	if (err)
504*4882a593Smuzhiyun 		return err;
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	err = qlcnic_dcb_query_cee_param(dcb, (char *)&mbx->type[1],
507*4882a593Smuzhiyun 					 QLC_DCB_OPER_PARAM_FWID);
508*4882a593Smuzhiyun 	if (err)
509*4882a593Smuzhiyun 		return err;
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun 	err = qlcnic_dcb_query_cee_param(dcb, (char *)&mbx->type[2],
512*4882a593Smuzhiyun 					 QLC_DCB_PEER_PARAM_FWID);
513*4882a593Smuzhiyun 	if (err)
514*4882a593Smuzhiyun 		return err;
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	mbx->prio_tc_map = QLC_82XX_DCB_PRIO_TC_MAP;
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun 	qlcnic_dcb_data_cee_param_map(dcb->adapter);
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun 	return err;
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun 
qlcnic_dcb_aen_work(struct work_struct * work)523*4882a593Smuzhiyun static void qlcnic_dcb_aen_work(struct work_struct *work)
524*4882a593Smuzhiyun {
525*4882a593Smuzhiyun 	struct qlcnic_dcb *dcb;
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun 	dcb = container_of(work, struct qlcnic_dcb, aen_work.work);
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 	qlcnic_dcb_get_cee_cfg(dcb);
530*4882a593Smuzhiyun 	clear_bit(QLCNIC_DCB_AEN_MODE, &dcb->state);
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun 
qlcnic_82xx_dcb_aen_handler(struct qlcnic_dcb * dcb,void * data)533*4882a593Smuzhiyun static void qlcnic_82xx_dcb_aen_handler(struct qlcnic_dcb *dcb, void *data)
534*4882a593Smuzhiyun {
535*4882a593Smuzhiyun 	if (test_and_set_bit(QLCNIC_DCB_AEN_MODE, &dcb->state))
536*4882a593Smuzhiyun 		return;
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 	queue_delayed_work(dcb->wq, &dcb->aen_work, 0);
539*4882a593Smuzhiyun }
540*4882a593Smuzhiyun 
qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_dcb * dcb)541*4882a593Smuzhiyun static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_dcb *dcb)
542*4882a593Smuzhiyun {
543*4882a593Smuzhiyun 	struct qlcnic_dcb_capability *cap = &dcb->cfg->capability;
544*4882a593Smuzhiyun 	u32 mbx_out;
545*4882a593Smuzhiyun 	int err;
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun 	err = __qlcnic_dcb_get_capability(dcb, &mbx_out);
548*4882a593Smuzhiyun 	if (err)
549*4882a593Smuzhiyun 		return err;
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 	if (mbx_out & BIT_2)
552*4882a593Smuzhiyun 		cap->dcb_capability = DCB_CAP_DCBX_VER_CEE;
553*4882a593Smuzhiyun 	if (mbx_out & BIT_3)
554*4882a593Smuzhiyun 		cap->dcb_capability |= DCB_CAP_DCBX_VER_IEEE;
555*4882a593Smuzhiyun 	if (cap->dcb_capability)
556*4882a593Smuzhiyun 		cap->dcb_capability |= DCB_CAP_DCBX_LLD_MANAGED;
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 	if (cap->dcb_capability && cap->tsa_capability && cap->ets_capability)
559*4882a593Smuzhiyun 		set_bit(QLCNIC_DCB_STATE, &dcb->state);
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun 	return err;
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun 
qlcnic_83xx_dcb_query_cee_param(struct qlcnic_dcb * dcb,char * buf,u8 idx)564*4882a593Smuzhiyun static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_dcb *dcb,
565*4882a593Smuzhiyun 					   char *buf, u8 idx)
566*4882a593Smuzhiyun {
567*4882a593Smuzhiyun 	struct qlcnic_adapter *adapter = dcb->adapter;
568*4882a593Smuzhiyun 	struct qlcnic_dcb_mbx_params mbx_out;
569*4882a593Smuzhiyun 	int err, i, j, k, max_app, size;
570*4882a593Smuzhiyun 	struct qlcnic_dcb_param *each;
571*4882a593Smuzhiyun 	struct qlcnic_cmd_args cmd;
572*4882a593Smuzhiyun 	u32 val;
573*4882a593Smuzhiyun 	char *p;
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun 	size = 0;
576*4882a593Smuzhiyun 	memset(&mbx_out, 0, sizeof(struct qlcnic_dcb_mbx_params));
577*4882a593Smuzhiyun 	memset(buf, 0, sizeof(struct qlcnic_dcb_mbx_params));
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun 	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_PARAM);
580*4882a593Smuzhiyun 	if (err)
581*4882a593Smuzhiyun 		return err;
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 	cmd.req.arg[0] |= QLC_DCB_FW_VER << 29;
584*4882a593Smuzhiyun 	err = qlcnic_issue_cmd(adapter, &cmd);
585*4882a593Smuzhiyun 	if (err) {
586*4882a593Smuzhiyun 		dev_err(&adapter->pdev->dev,
587*4882a593Smuzhiyun 			"Failed to query DCBX param, err %d\n", err);
588*4882a593Smuzhiyun 		goto out;
589*4882a593Smuzhiyun 	}
590*4882a593Smuzhiyun 
591*4882a593Smuzhiyun 	mbx_out.prio_tc_map = cmd.rsp.arg[1];
592*4882a593Smuzhiyun 	p = memcpy(buf, &mbx_out, sizeof(u32));
593*4882a593Smuzhiyun 	k = 2;
594*4882a593Smuzhiyun 	p += sizeof(u32);
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun 	for (j = 0; j < QLC_DCB_NUM_PARAM; j++) {
597*4882a593Smuzhiyun 		each = &mbx_out.type[j];
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun 		each->hdr_prio_pfc_map[0] = cmd.rsp.arg[k++];
600*4882a593Smuzhiyun 		each->hdr_prio_pfc_map[1] = cmd.rsp.arg[k++];
601*4882a593Smuzhiyun 		each->prio_pg_map[0] = cmd.rsp.arg[k++];
602*4882a593Smuzhiyun 		each->prio_pg_map[1] = cmd.rsp.arg[k++];
603*4882a593Smuzhiyun 		each->pg_bw_map[0] = cmd.rsp.arg[k++];
604*4882a593Smuzhiyun 		each->pg_bw_map[1] = cmd.rsp.arg[k++];
605*4882a593Smuzhiyun 		each->pg_tsa_map[0] = cmd.rsp.arg[k++];
606*4882a593Smuzhiyun 		each->pg_tsa_map[1] = cmd.rsp.arg[k++];
607*4882a593Smuzhiyun 		val = each->hdr_prio_pfc_map[0];
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 		max_app = qlcnic_dcb_get_num_app(adapter, val);
610*4882a593Smuzhiyun 		for (i = 0; i < max_app; i++)
611*4882a593Smuzhiyun 			each->app[i] = cmd.rsp.arg[i + k];
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 		size = 16 * sizeof(u32);
614*4882a593Smuzhiyun 		memcpy(p, &each->hdr_prio_pfc_map[0], size);
615*4882a593Smuzhiyun 		p += size;
616*4882a593Smuzhiyun 		if (j == 0)
617*4882a593Smuzhiyun 			k = 18;
618*4882a593Smuzhiyun 		else
619*4882a593Smuzhiyun 			k = 34;
620*4882a593Smuzhiyun 	}
621*4882a593Smuzhiyun out:
622*4882a593Smuzhiyun 	qlcnic_free_mbx_args(&cmd);
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun 	return err;
625*4882a593Smuzhiyun }
626*4882a593Smuzhiyun 
qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_dcb * dcb)627*4882a593Smuzhiyun static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_dcb *dcb)
628*4882a593Smuzhiyun {
629*4882a593Smuzhiyun 	int err;
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun 	err = qlcnic_dcb_query_cee_param(dcb, (char *)dcb->param, 0);
632*4882a593Smuzhiyun 	if (err)
633*4882a593Smuzhiyun 		return err;
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun 	qlcnic_dcb_data_cee_param_map(dcb->adapter);
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun 	return err;
638*4882a593Smuzhiyun }
639*4882a593Smuzhiyun 
qlcnic_83xx_dcb_aen_handler(struct qlcnic_dcb * dcb,void * data)640*4882a593Smuzhiyun static void qlcnic_83xx_dcb_aen_handler(struct qlcnic_dcb *dcb, void *data)
641*4882a593Smuzhiyun {
642*4882a593Smuzhiyun 	u32 *val = data;
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun 	if (test_and_set_bit(QLCNIC_DCB_AEN_MODE, &dcb->state))
645*4882a593Smuzhiyun 		return;
646*4882a593Smuzhiyun 
647*4882a593Smuzhiyun 	if (*val & BIT_8)
648*4882a593Smuzhiyun 		set_bit(QLCNIC_DCB_STATE, &dcb->state);
649*4882a593Smuzhiyun 	else
650*4882a593Smuzhiyun 		clear_bit(QLCNIC_DCB_STATE, &dcb->state);
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun 	queue_delayed_work(dcb->wq, &dcb->aen_work, 0);
653*4882a593Smuzhiyun }
654*4882a593Smuzhiyun 
qlcnic_dcb_fill_cee_tc_params(struct qlcnic_dcb_mbx_params * mbx,struct qlcnic_dcb_param * each,struct qlcnic_dcb_cee * type)655*4882a593Smuzhiyun static void qlcnic_dcb_fill_cee_tc_params(struct qlcnic_dcb_mbx_params *mbx,
656*4882a593Smuzhiyun 					  struct qlcnic_dcb_param *each,
657*4882a593Smuzhiyun 					  struct qlcnic_dcb_cee *type)
658*4882a593Smuzhiyun {
659*4882a593Smuzhiyun 	struct qlcnic_dcb_tc_cfg *tc_cfg;
660*4882a593Smuzhiyun 	u8 i, tc, pgid;
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun 	for (i = 0; i < QLC_DCB_MAX_PRIO; i++) {
663*4882a593Smuzhiyun 		tc = QLC_DCB_GET_TC_PRIO(mbx->prio_tc_map, i);
664*4882a593Smuzhiyun 		tc_cfg = &type->tc_cfg[tc];
665*4882a593Smuzhiyun 		tc_cfg->valid = true;
666*4882a593Smuzhiyun 		tc_cfg->up_tc_map |= QLC_DCB_GET_MAP(i);
667*4882a593Smuzhiyun 
668*4882a593Smuzhiyun 		if (QLC_DCB_GET_PFC_PRIO(each->hdr_prio_pfc_map[1], i) &&
669*4882a593Smuzhiyun 		    type->pfc_mode_enable) {
670*4882a593Smuzhiyun 			tc_cfg->prio_cfg[i].valid = true;
671*4882a593Smuzhiyun 			tc_cfg->prio_cfg[i].pfc_type = QLC_PFC_FULL;
672*4882a593Smuzhiyun 		}
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun 		if (i < 4)
675*4882a593Smuzhiyun 			pgid = QLC_DCB_GET_PGID_PRIO(each->prio_pg_map[0], i);
676*4882a593Smuzhiyun 		else
677*4882a593Smuzhiyun 			pgid = QLC_DCB_GET_PGID_PRIO(each->prio_pg_map[1], i);
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun 		tc_cfg->pgid = pgid;
680*4882a593Smuzhiyun 
681*4882a593Smuzhiyun 		tc_cfg->prio_type = QLC_PRIO_LINK;
682*4882a593Smuzhiyun 		type->pg_cfg[tc_cfg->pgid].prio_count++;
683*4882a593Smuzhiyun 	}
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun 
qlcnic_dcb_fill_cee_pg_params(struct qlcnic_dcb_param * each,struct qlcnic_dcb_cee * type)686*4882a593Smuzhiyun static void qlcnic_dcb_fill_cee_pg_params(struct qlcnic_dcb_param *each,
687*4882a593Smuzhiyun 					  struct qlcnic_dcb_cee *type)
688*4882a593Smuzhiyun {
689*4882a593Smuzhiyun 	struct qlcnic_dcb_pg_cfg *pg_cfg;
690*4882a593Smuzhiyun 	u8 i, tsa, bw_per;
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 	for (i = 0; i < QLC_DCB_MAX_PG; i++) {
693*4882a593Smuzhiyun 		pg_cfg = &type->pg_cfg[i];
694*4882a593Smuzhiyun 		pg_cfg->valid = true;
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun 		if (i < 4) {
697*4882a593Smuzhiyun 			bw_per = QLC_DCB_GET_BWPER_PG(each->pg_bw_map[0], i);
698*4882a593Smuzhiyun 			tsa = QLC_DCB_GET_TSA_PG(each->pg_tsa_map[0], i);
699*4882a593Smuzhiyun 		} else {
700*4882a593Smuzhiyun 			bw_per = QLC_DCB_GET_BWPER_PG(each->pg_bw_map[1], i);
701*4882a593Smuzhiyun 			tsa = QLC_DCB_GET_TSA_PG(each->pg_tsa_map[1], i);
702*4882a593Smuzhiyun 		}
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun 		pg_cfg->total_bw_percent = bw_per;
705*4882a593Smuzhiyun 		pg_cfg->tsa_type = tsa;
706*4882a593Smuzhiyun 	}
707*4882a593Smuzhiyun }
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun static void
qlcnic_dcb_fill_cee_app_params(struct qlcnic_adapter * adapter,u8 idx,struct qlcnic_dcb_param * each,struct qlcnic_dcb_cee * type)710*4882a593Smuzhiyun qlcnic_dcb_fill_cee_app_params(struct qlcnic_adapter *adapter, u8 idx,
711*4882a593Smuzhiyun 			       struct qlcnic_dcb_param *each,
712*4882a593Smuzhiyun 			       struct qlcnic_dcb_cee *type)
713*4882a593Smuzhiyun {
714*4882a593Smuzhiyun 	struct qlcnic_dcb_app *app;
715*4882a593Smuzhiyun 	u8 i, num_app, map, cnt;
716*4882a593Smuzhiyun 	struct dcb_app new_app;
717*4882a593Smuzhiyun 
718*4882a593Smuzhiyun 	num_app = qlcnic_dcb_get_num_app(adapter, each->hdr_prio_pfc_map[0]);
719*4882a593Smuzhiyun 	for (i = 0; i < num_app; i++) {
720*4882a593Smuzhiyun 		app = &type->app[i];
721*4882a593Smuzhiyun 		app->valid = true;
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun 		/* Only for CEE (-1) */
724*4882a593Smuzhiyun 		app->selector = QLC_DCB_GET_SELECTOR_APP(each->app[i]) - 1;
725*4882a593Smuzhiyun 		new_app.selector = app->selector;
726*4882a593Smuzhiyun 		app->protocol = QLC_DCB_GET_PROTO_ID_APP(each->app[i]);
727*4882a593Smuzhiyun 		new_app.protocol = app->protocol;
728*4882a593Smuzhiyun 		map = qlcnic_dcb_get_prio_map_app(adapter, each->app[i]);
729*4882a593Smuzhiyun 		cnt = qlcnic_dcb_prio_count(map);
730*4882a593Smuzhiyun 
731*4882a593Smuzhiyun 		if (cnt >= QLC_DCB_MAX_TC)
732*4882a593Smuzhiyun 			cnt = 0;
733*4882a593Smuzhiyun 
734*4882a593Smuzhiyun 		app->priority = cnt;
735*4882a593Smuzhiyun 		new_app.priority = cnt;
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun 		if (idx == QLC_DCB_OPER_IDX && adapter->netdev->dcbnl_ops)
738*4882a593Smuzhiyun 			dcb_setapp(adapter->netdev, &new_app);
739*4882a593Smuzhiyun 	}
740*4882a593Smuzhiyun }
741*4882a593Smuzhiyun 
qlcnic_dcb_map_cee_params(struct qlcnic_adapter * adapter,u8 idx)742*4882a593Smuzhiyun static void qlcnic_dcb_map_cee_params(struct qlcnic_adapter *adapter, u8 idx)
743*4882a593Smuzhiyun {
744*4882a593Smuzhiyun 	struct qlcnic_dcb_mbx_params *mbx = adapter->dcb->param;
745*4882a593Smuzhiyun 	struct qlcnic_dcb_param *each = &mbx->type[idx];
746*4882a593Smuzhiyun 	struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg;
747*4882a593Smuzhiyun 	struct qlcnic_dcb_cee *type = &cfg->type[idx];
748*4882a593Smuzhiyun 
749*4882a593Smuzhiyun 	type->tc_param_valid = false;
750*4882a593Smuzhiyun 	type->pfc_mode_enable = false;
751*4882a593Smuzhiyun 	memset(type->tc_cfg, 0,
752*4882a593Smuzhiyun 	       sizeof(struct qlcnic_dcb_tc_cfg) * QLC_DCB_MAX_TC);
753*4882a593Smuzhiyun 	memset(type->pg_cfg, 0,
754*4882a593Smuzhiyun 	       sizeof(struct qlcnic_dcb_pg_cfg) * QLC_DCB_MAX_TC);
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun 	if (qlcnic_dcb_pfc_hdr_valid(adapter, each->hdr_prio_pfc_map[0]) &&
757*4882a593Smuzhiyun 	    cfg->capability.max_pfc_tc)
758*4882a593Smuzhiyun 		type->pfc_mode_enable = true;
759*4882a593Smuzhiyun 
760*4882a593Smuzhiyun 	if (qlcnic_dcb_tsa_hdr_valid(adapter, each->hdr_prio_pfc_map[0]) &&
761*4882a593Smuzhiyun 	    cfg->capability.max_ets_tc)
762*4882a593Smuzhiyun 		type->tc_param_valid = true;
763*4882a593Smuzhiyun 
764*4882a593Smuzhiyun 	qlcnic_dcb_fill_cee_tc_params(mbx, each, type);
765*4882a593Smuzhiyun 	qlcnic_dcb_fill_cee_pg_params(each, type);
766*4882a593Smuzhiyun 	qlcnic_dcb_fill_cee_app_params(adapter, idx, each, type);
767*4882a593Smuzhiyun }
768*4882a593Smuzhiyun 
qlcnic_dcb_data_cee_param_map(struct qlcnic_adapter * adapter)769*4882a593Smuzhiyun static void qlcnic_dcb_data_cee_param_map(struct qlcnic_adapter *adapter)
770*4882a593Smuzhiyun {
771*4882a593Smuzhiyun 	int i;
772*4882a593Smuzhiyun 
773*4882a593Smuzhiyun 	for (i = 0; i < QLC_DCB_NUM_PARAM; i++)
774*4882a593Smuzhiyun 		qlcnic_dcb_map_cee_params(adapter, i);
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun 	dcbnl_cee_notify(adapter->netdev, RTM_GETDCB, DCB_CMD_CEE_GET, 0, 0);
777*4882a593Smuzhiyun }
778*4882a593Smuzhiyun 
qlcnic_dcb_get_state(struct net_device * netdev)779*4882a593Smuzhiyun static u8 qlcnic_dcb_get_state(struct net_device *netdev)
780*4882a593Smuzhiyun {
781*4882a593Smuzhiyun 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun 	return test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state);
784*4882a593Smuzhiyun }
785*4882a593Smuzhiyun 
qlcnic_dcb_get_perm_hw_addr(struct net_device * netdev,u8 * addr)786*4882a593Smuzhiyun static void qlcnic_dcb_get_perm_hw_addr(struct net_device *netdev, u8 *addr)
787*4882a593Smuzhiyun {
788*4882a593Smuzhiyun 	memcpy(addr, netdev->perm_addr, netdev->addr_len);
789*4882a593Smuzhiyun }
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun static void
qlcnic_dcb_get_pg_tc_cfg_tx(struct net_device * netdev,int tc,u8 * prio,u8 * pgid,u8 * bw_per,u8 * up_tc_map)792*4882a593Smuzhiyun qlcnic_dcb_get_pg_tc_cfg_tx(struct net_device *netdev, int tc, u8 *prio,
793*4882a593Smuzhiyun 			    u8 *pgid, u8 *bw_per, u8 *up_tc_map)
794*4882a593Smuzhiyun {
795*4882a593Smuzhiyun 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
796*4882a593Smuzhiyun 	struct qlcnic_dcb_tc_cfg *tc_cfg, *temp;
797*4882a593Smuzhiyun 	struct qlcnic_dcb_cee *type;
798*4882a593Smuzhiyun 	u8 i, cnt, pg;
799*4882a593Smuzhiyun 
800*4882a593Smuzhiyun 	type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX];
801*4882a593Smuzhiyun 	*prio = *pgid = *bw_per = *up_tc_map = 0;
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun 	if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state) ||
804*4882a593Smuzhiyun 	    !type->tc_param_valid)
805*4882a593Smuzhiyun 		return;
806*4882a593Smuzhiyun 
807*4882a593Smuzhiyun 	if (tc < 0 || (tc >= QLC_DCB_MAX_TC))
808*4882a593Smuzhiyun 		return;
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun 	tc_cfg = &type->tc_cfg[tc];
811*4882a593Smuzhiyun 	if (!tc_cfg->valid)
812*4882a593Smuzhiyun 		return;
813*4882a593Smuzhiyun 
814*4882a593Smuzhiyun 	*pgid = tc_cfg->pgid;
815*4882a593Smuzhiyun 	*prio = tc_cfg->prio_type;
816*4882a593Smuzhiyun 	*up_tc_map = tc_cfg->up_tc_map;
817*4882a593Smuzhiyun 	pg = *pgid;
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun 	for (i = 0, cnt = 0; i < QLC_DCB_MAX_TC; i++) {
820*4882a593Smuzhiyun 		temp = &type->tc_cfg[i];
821*4882a593Smuzhiyun 		if (temp->valid && (pg == temp->pgid))
822*4882a593Smuzhiyun 			cnt++;
823*4882a593Smuzhiyun 	}
824*4882a593Smuzhiyun 
825*4882a593Smuzhiyun 	tc_cfg->bwg_percent = (100 / cnt);
826*4882a593Smuzhiyun 	*bw_per = tc_cfg->bwg_percent;
827*4882a593Smuzhiyun }
828*4882a593Smuzhiyun 
qlcnic_dcb_get_pg_bwg_cfg_tx(struct net_device * netdev,int pgid,u8 * bw_pct)829*4882a593Smuzhiyun static void qlcnic_dcb_get_pg_bwg_cfg_tx(struct net_device *netdev, int pgid,
830*4882a593Smuzhiyun 					 u8 *bw_pct)
831*4882a593Smuzhiyun {
832*4882a593Smuzhiyun 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
833*4882a593Smuzhiyun 	struct qlcnic_dcb_pg_cfg *pgcfg;
834*4882a593Smuzhiyun 	struct qlcnic_dcb_cee *type;
835*4882a593Smuzhiyun 
836*4882a593Smuzhiyun 	*bw_pct = 0;
837*4882a593Smuzhiyun 	type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX];
838*4882a593Smuzhiyun 
839*4882a593Smuzhiyun 	if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state) ||
840*4882a593Smuzhiyun 	    !type->tc_param_valid)
841*4882a593Smuzhiyun 		return;
842*4882a593Smuzhiyun 
843*4882a593Smuzhiyun 	if (pgid < 0 || pgid >= QLC_DCB_MAX_PG)
844*4882a593Smuzhiyun 		return;
845*4882a593Smuzhiyun 
846*4882a593Smuzhiyun 	pgcfg = &type->pg_cfg[pgid];
847*4882a593Smuzhiyun 	if (!pgcfg->valid)
848*4882a593Smuzhiyun 		return;
849*4882a593Smuzhiyun 
850*4882a593Smuzhiyun 	*bw_pct = pgcfg->total_bw_percent;
851*4882a593Smuzhiyun }
852*4882a593Smuzhiyun 
qlcnic_dcb_get_pfc_cfg(struct net_device * netdev,int prio,u8 * setting)853*4882a593Smuzhiyun static void qlcnic_dcb_get_pfc_cfg(struct net_device *netdev, int prio,
854*4882a593Smuzhiyun 				   u8 *setting)
855*4882a593Smuzhiyun {
856*4882a593Smuzhiyun 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
857*4882a593Smuzhiyun 	struct qlcnic_dcb_tc_cfg *tc_cfg;
858*4882a593Smuzhiyun 	u8 val = QLC_DCB_GET_MAP(prio);
859*4882a593Smuzhiyun 	struct qlcnic_dcb_cee *type;
860*4882a593Smuzhiyun 	u8 i;
861*4882a593Smuzhiyun 
862*4882a593Smuzhiyun 	*setting = 0;
863*4882a593Smuzhiyun 	type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX];
864*4882a593Smuzhiyun 
865*4882a593Smuzhiyun 	if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state) ||
866*4882a593Smuzhiyun 	    !type->pfc_mode_enable)
867*4882a593Smuzhiyun 		return;
868*4882a593Smuzhiyun 
869*4882a593Smuzhiyun 	for (i = 0; i < QLC_DCB_MAX_TC; i++) {
870*4882a593Smuzhiyun 		tc_cfg = &type->tc_cfg[i];
871*4882a593Smuzhiyun 		if (!tc_cfg->valid)
872*4882a593Smuzhiyun 			continue;
873*4882a593Smuzhiyun 
874*4882a593Smuzhiyun 		if ((val & tc_cfg->up_tc_map) && (tc_cfg->prio_cfg[prio].valid))
875*4882a593Smuzhiyun 			*setting = tc_cfg->prio_cfg[prio].pfc_type;
876*4882a593Smuzhiyun 	}
877*4882a593Smuzhiyun }
878*4882a593Smuzhiyun 
qlcnic_dcb_get_capability(struct net_device * netdev,int capid,u8 * cap)879*4882a593Smuzhiyun static u8 qlcnic_dcb_get_capability(struct net_device *netdev, int capid,
880*4882a593Smuzhiyun 				    u8 *cap)
881*4882a593Smuzhiyun {
882*4882a593Smuzhiyun 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
883*4882a593Smuzhiyun 
884*4882a593Smuzhiyun 	if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
885*4882a593Smuzhiyun 		return 1;
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun 	switch (capid) {
888*4882a593Smuzhiyun 	case DCB_CAP_ATTR_PG:
889*4882a593Smuzhiyun 	case DCB_CAP_ATTR_UP2TC:
890*4882a593Smuzhiyun 	case DCB_CAP_ATTR_PFC:
891*4882a593Smuzhiyun 	case DCB_CAP_ATTR_GSP:
892*4882a593Smuzhiyun 		*cap = true;
893*4882a593Smuzhiyun 		break;
894*4882a593Smuzhiyun 	case DCB_CAP_ATTR_PG_TCS:
895*4882a593Smuzhiyun 	case DCB_CAP_ATTR_PFC_TCS:
896*4882a593Smuzhiyun 		*cap = 0x80;	/* 8 priorities for PGs */
897*4882a593Smuzhiyun 		break;
898*4882a593Smuzhiyun 	case DCB_CAP_ATTR_DCBX:
899*4882a593Smuzhiyun 		*cap = adapter->dcb->cfg->capability.dcb_capability;
900*4882a593Smuzhiyun 		break;
901*4882a593Smuzhiyun 	default:
902*4882a593Smuzhiyun 		*cap = false;
903*4882a593Smuzhiyun 	}
904*4882a593Smuzhiyun 
905*4882a593Smuzhiyun 	return 0;
906*4882a593Smuzhiyun }
907*4882a593Smuzhiyun 
qlcnic_dcb_get_num_tcs(struct net_device * netdev,int attr,u8 * num)908*4882a593Smuzhiyun static int qlcnic_dcb_get_num_tcs(struct net_device *netdev, int attr, u8 *num)
909*4882a593Smuzhiyun {
910*4882a593Smuzhiyun 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
911*4882a593Smuzhiyun 	struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg;
912*4882a593Smuzhiyun 
913*4882a593Smuzhiyun 	if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
914*4882a593Smuzhiyun 		return -EINVAL;
915*4882a593Smuzhiyun 
916*4882a593Smuzhiyun 	switch (attr) {
917*4882a593Smuzhiyun 	case DCB_NUMTCS_ATTR_PG:
918*4882a593Smuzhiyun 		*num = cfg->capability.max_ets_tc;
919*4882a593Smuzhiyun 		return 0;
920*4882a593Smuzhiyun 	case DCB_NUMTCS_ATTR_PFC:
921*4882a593Smuzhiyun 		*num = cfg->capability.max_pfc_tc;
922*4882a593Smuzhiyun 		return 0;
923*4882a593Smuzhiyun 	default:
924*4882a593Smuzhiyun 		return -EINVAL;
925*4882a593Smuzhiyun 	}
926*4882a593Smuzhiyun }
927*4882a593Smuzhiyun 
qlcnic_dcb_get_app(struct net_device * netdev,u8 idtype,u16 id)928*4882a593Smuzhiyun static int qlcnic_dcb_get_app(struct net_device *netdev, u8 idtype, u16 id)
929*4882a593Smuzhiyun {
930*4882a593Smuzhiyun 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
931*4882a593Smuzhiyun 	struct dcb_app app = {
932*4882a593Smuzhiyun 				.selector = idtype,
933*4882a593Smuzhiyun 				.protocol = id,
934*4882a593Smuzhiyun 			     };
935*4882a593Smuzhiyun 
936*4882a593Smuzhiyun 	if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
937*4882a593Smuzhiyun 		return -EINVAL;
938*4882a593Smuzhiyun 
939*4882a593Smuzhiyun 	return dcb_getapp(netdev, &app);
940*4882a593Smuzhiyun }
941*4882a593Smuzhiyun 
qlcnic_dcb_get_pfc_state(struct net_device * netdev)942*4882a593Smuzhiyun static u8 qlcnic_dcb_get_pfc_state(struct net_device *netdev)
943*4882a593Smuzhiyun {
944*4882a593Smuzhiyun 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
945*4882a593Smuzhiyun 	struct qlcnic_dcb *dcb = adapter->dcb;
946*4882a593Smuzhiyun 
947*4882a593Smuzhiyun 	if (!test_bit(QLCNIC_DCB_STATE, &dcb->state))
948*4882a593Smuzhiyun 		return 0;
949*4882a593Smuzhiyun 
950*4882a593Smuzhiyun 	return dcb->cfg->type[QLC_DCB_OPER_IDX].pfc_mode_enable;
951*4882a593Smuzhiyun }
952*4882a593Smuzhiyun 
qlcnic_dcb_get_dcbx(struct net_device * netdev)953*4882a593Smuzhiyun static u8 qlcnic_dcb_get_dcbx(struct net_device *netdev)
954*4882a593Smuzhiyun {
955*4882a593Smuzhiyun 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
956*4882a593Smuzhiyun 	struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg;
957*4882a593Smuzhiyun 
958*4882a593Smuzhiyun 	if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
959*4882a593Smuzhiyun 		return 0;
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun 	return cfg->capability.dcb_capability;
962*4882a593Smuzhiyun }
963*4882a593Smuzhiyun 
qlcnic_dcb_get_feat_cfg(struct net_device * netdev,int fid,u8 * flag)964*4882a593Smuzhiyun static u8 qlcnic_dcb_get_feat_cfg(struct net_device *netdev, int fid, u8 *flag)
965*4882a593Smuzhiyun {
966*4882a593Smuzhiyun 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
967*4882a593Smuzhiyun 	struct qlcnic_dcb_cee *type;
968*4882a593Smuzhiyun 
969*4882a593Smuzhiyun 	if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
970*4882a593Smuzhiyun 		return 1;
971*4882a593Smuzhiyun 
972*4882a593Smuzhiyun 	type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX];
973*4882a593Smuzhiyun 	*flag = 0;
974*4882a593Smuzhiyun 
975*4882a593Smuzhiyun 	switch (fid) {
976*4882a593Smuzhiyun 	case DCB_FEATCFG_ATTR_PG:
977*4882a593Smuzhiyun 		if (type->tc_param_valid)
978*4882a593Smuzhiyun 			*flag |= DCB_FEATCFG_ENABLE;
979*4882a593Smuzhiyun 		else
980*4882a593Smuzhiyun 			*flag |= DCB_FEATCFG_ERROR;
981*4882a593Smuzhiyun 		break;
982*4882a593Smuzhiyun 	case DCB_FEATCFG_ATTR_PFC:
983*4882a593Smuzhiyun 		if (type->pfc_mode_enable) {
984*4882a593Smuzhiyun 			if (type->tc_cfg[0].prio_cfg[0].pfc_type)
985*4882a593Smuzhiyun 				*flag |= DCB_FEATCFG_ENABLE;
986*4882a593Smuzhiyun 		} else {
987*4882a593Smuzhiyun 			*flag |= DCB_FEATCFG_ERROR;
988*4882a593Smuzhiyun 		}
989*4882a593Smuzhiyun 		break;
990*4882a593Smuzhiyun 	case DCB_FEATCFG_ATTR_APP:
991*4882a593Smuzhiyun 		*flag |= DCB_FEATCFG_ENABLE;
992*4882a593Smuzhiyun 		break;
993*4882a593Smuzhiyun 	default:
994*4882a593Smuzhiyun 		netdev_err(netdev, "Invalid Feature ID %d\n", fid);
995*4882a593Smuzhiyun 		return 1;
996*4882a593Smuzhiyun 	}
997*4882a593Smuzhiyun 
998*4882a593Smuzhiyun 	return 0;
999*4882a593Smuzhiyun }
1000*4882a593Smuzhiyun 
1001*4882a593Smuzhiyun static inline void
qlcnic_dcb_get_pg_tc_cfg_rx(struct net_device * netdev,int prio,u8 * prio_type,u8 * pgid,u8 * bw_pct,u8 * up_map)1002*4882a593Smuzhiyun qlcnic_dcb_get_pg_tc_cfg_rx(struct net_device *netdev, int prio, u8 *prio_type,
1003*4882a593Smuzhiyun 			    u8 *pgid, u8 *bw_pct, u8 *up_map)
1004*4882a593Smuzhiyun {
1005*4882a593Smuzhiyun 	*prio_type = *pgid = *bw_pct = *up_map = 0;
1006*4882a593Smuzhiyun }
1007*4882a593Smuzhiyun 
1008*4882a593Smuzhiyun static inline void
qlcnic_dcb_get_pg_bwg_cfg_rx(struct net_device * netdev,int pgid,u8 * bw_pct)1009*4882a593Smuzhiyun qlcnic_dcb_get_pg_bwg_cfg_rx(struct net_device *netdev, int pgid, u8 *bw_pct)
1010*4882a593Smuzhiyun {
1011*4882a593Smuzhiyun 	*bw_pct = 0;
1012*4882a593Smuzhiyun }
1013*4882a593Smuzhiyun 
qlcnic_dcb_peer_app_info(struct net_device * netdev,struct dcb_peer_app_info * info,u16 * app_count)1014*4882a593Smuzhiyun static int qlcnic_dcb_peer_app_info(struct net_device *netdev,
1015*4882a593Smuzhiyun 				    struct dcb_peer_app_info *info,
1016*4882a593Smuzhiyun 				    u16 *app_count)
1017*4882a593Smuzhiyun {
1018*4882a593Smuzhiyun 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
1019*4882a593Smuzhiyun 	struct qlcnic_dcb_cee *peer;
1020*4882a593Smuzhiyun 	int i;
1021*4882a593Smuzhiyun 
1022*4882a593Smuzhiyun 	memset(info, 0, sizeof(*info));
1023*4882a593Smuzhiyun 	*app_count = 0;
1024*4882a593Smuzhiyun 
1025*4882a593Smuzhiyun 	if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
1026*4882a593Smuzhiyun 		return 0;
1027*4882a593Smuzhiyun 
1028*4882a593Smuzhiyun 	peer = &adapter->dcb->cfg->type[QLC_DCB_PEER_IDX];
1029*4882a593Smuzhiyun 
1030*4882a593Smuzhiyun 	for (i = 0; i < QLC_DCB_MAX_APP; i++) {
1031*4882a593Smuzhiyun 		if (peer->app[i].valid)
1032*4882a593Smuzhiyun 			(*app_count)++;
1033*4882a593Smuzhiyun 	}
1034*4882a593Smuzhiyun 
1035*4882a593Smuzhiyun 	return 0;
1036*4882a593Smuzhiyun }
1037*4882a593Smuzhiyun 
qlcnic_dcb_peer_app_table(struct net_device * netdev,struct dcb_app * table)1038*4882a593Smuzhiyun static int qlcnic_dcb_peer_app_table(struct net_device *netdev,
1039*4882a593Smuzhiyun 				     struct dcb_app *table)
1040*4882a593Smuzhiyun {
1041*4882a593Smuzhiyun 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
1042*4882a593Smuzhiyun 	struct qlcnic_dcb_cee *peer;
1043*4882a593Smuzhiyun 	struct qlcnic_dcb_app *app;
1044*4882a593Smuzhiyun 	int i, j;
1045*4882a593Smuzhiyun 
1046*4882a593Smuzhiyun 	if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
1047*4882a593Smuzhiyun 		return 0;
1048*4882a593Smuzhiyun 
1049*4882a593Smuzhiyun 	peer = &adapter->dcb->cfg->type[QLC_DCB_PEER_IDX];
1050*4882a593Smuzhiyun 
1051*4882a593Smuzhiyun 	for (i = 0, j = 0; i < QLC_DCB_MAX_APP; i++) {
1052*4882a593Smuzhiyun 		app = &peer->app[i];
1053*4882a593Smuzhiyun 		if (!app->valid)
1054*4882a593Smuzhiyun 			continue;
1055*4882a593Smuzhiyun 
1056*4882a593Smuzhiyun 		table[j].selector = app->selector;
1057*4882a593Smuzhiyun 		table[j].priority = app->priority;
1058*4882a593Smuzhiyun 		table[j++].protocol = app->protocol;
1059*4882a593Smuzhiyun 	}
1060*4882a593Smuzhiyun 
1061*4882a593Smuzhiyun 	return 0;
1062*4882a593Smuzhiyun }
1063*4882a593Smuzhiyun 
qlcnic_dcb_cee_peer_get_pg(struct net_device * netdev,struct cee_pg * pg)1064*4882a593Smuzhiyun static int qlcnic_dcb_cee_peer_get_pg(struct net_device *netdev,
1065*4882a593Smuzhiyun 				      struct cee_pg *pg)
1066*4882a593Smuzhiyun {
1067*4882a593Smuzhiyun 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
1068*4882a593Smuzhiyun 	struct qlcnic_dcb_cee *peer;
1069*4882a593Smuzhiyun 	u8 i, j, k, map;
1070*4882a593Smuzhiyun 
1071*4882a593Smuzhiyun 	if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
1072*4882a593Smuzhiyun 		return 0;
1073*4882a593Smuzhiyun 
1074*4882a593Smuzhiyun 	peer = &adapter->dcb->cfg->type[QLC_DCB_PEER_IDX];
1075*4882a593Smuzhiyun 
1076*4882a593Smuzhiyun 	for (i = 0, j = 0; i < QLC_DCB_MAX_PG; i++) {
1077*4882a593Smuzhiyun 		if (!peer->pg_cfg[i].valid)
1078*4882a593Smuzhiyun 			continue;
1079*4882a593Smuzhiyun 
1080*4882a593Smuzhiyun 		pg->pg_bw[j] = peer->pg_cfg[i].total_bw_percent;
1081*4882a593Smuzhiyun 
1082*4882a593Smuzhiyun 		for (k = 0; k < QLC_DCB_MAX_TC; k++) {
1083*4882a593Smuzhiyun 			if (peer->tc_cfg[i].valid &&
1084*4882a593Smuzhiyun 			    (peer->tc_cfg[i].pgid == i)) {
1085*4882a593Smuzhiyun 				map = peer->tc_cfg[i].up_tc_map;
1086*4882a593Smuzhiyun 				pg->prio_pg[j++] = map;
1087*4882a593Smuzhiyun 				break;
1088*4882a593Smuzhiyun 			}
1089*4882a593Smuzhiyun 		}
1090*4882a593Smuzhiyun 	}
1091*4882a593Smuzhiyun 
1092*4882a593Smuzhiyun 	return 0;
1093*4882a593Smuzhiyun }
1094*4882a593Smuzhiyun 
qlcnic_dcb_cee_peer_get_pfc(struct net_device * netdev,struct cee_pfc * pfc)1095*4882a593Smuzhiyun static int qlcnic_dcb_cee_peer_get_pfc(struct net_device *netdev,
1096*4882a593Smuzhiyun 				       struct cee_pfc *pfc)
1097*4882a593Smuzhiyun {
1098*4882a593Smuzhiyun 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
1099*4882a593Smuzhiyun 	struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg;
1100*4882a593Smuzhiyun 	struct qlcnic_dcb_tc_cfg *tc;
1101*4882a593Smuzhiyun 	struct qlcnic_dcb_cee *peer;
1102*4882a593Smuzhiyun 	u8 i, setting, prio;
1103*4882a593Smuzhiyun 
1104*4882a593Smuzhiyun 	pfc->pfc_en = 0;
1105*4882a593Smuzhiyun 
1106*4882a593Smuzhiyun 	if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
1107*4882a593Smuzhiyun 		return 0;
1108*4882a593Smuzhiyun 
1109*4882a593Smuzhiyun 	peer = &cfg->type[QLC_DCB_PEER_IDX];
1110*4882a593Smuzhiyun 
1111*4882a593Smuzhiyun 	for (i = 0; i < QLC_DCB_MAX_TC; i++) {
1112*4882a593Smuzhiyun 		tc = &peer->tc_cfg[i];
1113*4882a593Smuzhiyun 		prio = qlcnic_dcb_prio_count(tc->up_tc_map);
1114*4882a593Smuzhiyun 
1115*4882a593Smuzhiyun 		setting = 0;
1116*4882a593Smuzhiyun 		qlcnic_dcb_get_pfc_cfg(netdev, prio, &setting);
1117*4882a593Smuzhiyun 		if (setting)
1118*4882a593Smuzhiyun 			pfc->pfc_en |= QLC_DCB_GET_MAP(i);
1119*4882a593Smuzhiyun 	}
1120*4882a593Smuzhiyun 
1121*4882a593Smuzhiyun 	pfc->tcs_supported = cfg->capability.max_pfc_tc;
1122*4882a593Smuzhiyun 
1123*4882a593Smuzhiyun 	return 0;
1124*4882a593Smuzhiyun }
1125*4882a593Smuzhiyun 
1126*4882a593Smuzhiyun static const struct dcbnl_rtnl_ops qlcnic_dcbnl_ops = {
1127*4882a593Smuzhiyun 	.getstate		= qlcnic_dcb_get_state,
1128*4882a593Smuzhiyun 	.getpermhwaddr		= qlcnic_dcb_get_perm_hw_addr,
1129*4882a593Smuzhiyun 	.getpgtccfgtx		= qlcnic_dcb_get_pg_tc_cfg_tx,
1130*4882a593Smuzhiyun 	.getpgbwgcfgtx		= qlcnic_dcb_get_pg_bwg_cfg_tx,
1131*4882a593Smuzhiyun 	.getpfccfg		= qlcnic_dcb_get_pfc_cfg,
1132*4882a593Smuzhiyun 	.getcap			= qlcnic_dcb_get_capability,
1133*4882a593Smuzhiyun 	.getnumtcs		= qlcnic_dcb_get_num_tcs,
1134*4882a593Smuzhiyun 	.getapp			= qlcnic_dcb_get_app,
1135*4882a593Smuzhiyun 	.getpfcstate		= qlcnic_dcb_get_pfc_state,
1136*4882a593Smuzhiyun 	.getdcbx		= qlcnic_dcb_get_dcbx,
1137*4882a593Smuzhiyun 	.getfeatcfg		= qlcnic_dcb_get_feat_cfg,
1138*4882a593Smuzhiyun 
1139*4882a593Smuzhiyun 	.getpgtccfgrx		= qlcnic_dcb_get_pg_tc_cfg_rx,
1140*4882a593Smuzhiyun 	.getpgbwgcfgrx		= qlcnic_dcb_get_pg_bwg_cfg_rx,
1141*4882a593Smuzhiyun 
1142*4882a593Smuzhiyun 	.peer_getappinfo	= qlcnic_dcb_peer_app_info,
1143*4882a593Smuzhiyun 	.peer_getapptable	= qlcnic_dcb_peer_app_table,
1144*4882a593Smuzhiyun 	.cee_peer_getpg		= qlcnic_dcb_cee_peer_get_pg,
1145*4882a593Smuzhiyun 	.cee_peer_getpfc	= qlcnic_dcb_cee_peer_get_pfc,
1146*4882a593Smuzhiyun };
1147