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