blob: c23308483ceefbd8367577f9560ab34418bf9ceb [file] [log] [blame]
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -04001/*
2 * QLogic qlcnic NIC Driver
3 * Copyright (c) 2009-2013 QLogic Corporation
4 *
5 * See LICENSE.qlcnic for copyright and licensing details.
6 */
7
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -04008#include <linux/types.h>
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -04009#include "qlcnic.h"
10
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -040011#define QLC_DCB_NUM_PARAM 3
Sucheta Chakraborty48365e42013-08-23 13:38:28 -040012#define QLC_DCB_LOCAL_IDX 0
13#define QLC_DCB_OPER_IDX 1
14#define QLC_DCB_PEER_IDX 2
15
16#define QLC_DCB_GET_MAP(V) (1 << V)
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -040017
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -040018#define QLC_DCB_AEN_BIT 0x2
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -040019#define QLC_DCB_FW_VER 0x2
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -040020#define QLC_DCB_MAX_TC 0x8
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -040021#define QLC_DCB_MAX_APP 0x8
Sucheta Chakraborty48365e42013-08-23 13:38:28 -040022#define QLC_DCB_MAX_PRIO QLC_DCB_MAX_TC
23#define QLC_DCB_MAX_PG QLC_DCB_MAX_TC
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -040024
25#define QLC_DCB_TSA_SUPPORT(V) (V & 0x1)
26#define QLC_DCB_ETS_SUPPORT(V) ((V >> 1) & 0x1)
27#define QLC_DCB_VERSION_SUPPORT(V) ((V >> 2) & 0xf)
28#define QLC_DCB_MAX_NUM_TC(V) ((V >> 20) & 0xf)
29#define QLC_DCB_MAX_NUM_ETS_TC(V) ((V >> 24) & 0xf)
30#define QLC_DCB_MAX_NUM_PFC_TC(V) ((V >> 28) & 0xf)
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -040031#define QLC_DCB_GET_TC_PRIO(X, P) ((X >> (P * 3)) & 0x7)
32#define QLC_DCB_GET_PGID_PRIO(X, P) ((X >> (P * 8)) & 0xff)
33#define QLC_DCB_GET_BWPER_PG(X, P) ((X >> (P * 8)) & 0xff)
34#define QLC_DCB_GET_TSA_PG(X, P) ((X >> (P * 8)) & 0xff)
35#define QLC_DCB_GET_PFC_PRIO(X, P) (((X >> 24) >> P) & 0x1)
36#define QLC_DCB_GET_PROTO_ID_APP(X) ((X >> 8) & 0xffff)
37#define QLC_DCB_GET_SELECTOR_APP(X) (X & 0xff)
38
39#define QLC_DCB_LOCAL_PARAM_FWID 0x3
40#define QLC_DCB_OPER_PARAM_FWID 0x1
41#define QLC_DCB_PEER_PARAM_FWID 0x2
42
43#define QLC_83XX_DCB_GET_NUMAPP(X) ((X >> 2) & 0xf)
44#define QLC_83XX_DCB_TSA_VALID(X) (X & 0x1)
45#define QLC_83XX_DCB_PFC_VALID(X) ((X >> 1) & 0x1)
46#define QLC_83XX_DCB_GET_PRIOMAP_APP(X) (X >> 24)
47
48#define QLC_82XX_DCB_GET_NUMAPP(X) ((X >> 12) & 0xf)
49#define QLC_82XX_DCB_TSA_VALID(X) ((X >> 4) & 0x1)
50#define QLC_82XX_DCB_PFC_VALID(X) ((X >> 5) & 0x1)
51#define QLC_82XX_DCB_GET_PRIOVAL_APP(X) ((X >> 24) & 0x7)
52#define QLC_82XX_DCB_GET_PRIOMAP_APP(X) (1 << X)
53#define QLC_82XX_DCB_PRIO_TC_MAP (0x76543210)
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -040054
Sucheta Chakraborty48365e42013-08-23 13:38:28 -040055static const struct dcbnl_rtnl_ops qlcnic_dcbnl_ops;
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -040056
Sucheta Chakraborty48365e42013-08-23 13:38:28 -040057static void qlcnic_dcb_aen_work(struct work_struct *);
58static void qlcnic_dcb_data_cee_param_map(struct qlcnic_adapter *);
59
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -040060static inline void __qlcnic_init_dcbnl_ops(struct qlcnic_dcb *);
61static void __qlcnic_dcb_free(struct qlcnic_dcb *);
62static int __qlcnic_dcb_attach(struct qlcnic_dcb *);
63static int __qlcnic_dcb_query_hw_capability(struct qlcnic_dcb *, char *);
64static void __qlcnic_dcb_get_info(struct qlcnic_dcb *);
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -040065
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -040066static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_dcb *);
67static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_dcb *, char *, u8);
68static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_dcb *);
69static void qlcnic_82xx_dcb_aen_handler(struct qlcnic_dcb *, void *);
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -040070
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -040071static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_dcb *);
72static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_dcb *, char *, u8);
73static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_dcb *);
74static int qlcnic_83xx_dcb_register_aen(struct qlcnic_dcb *, bool);
75static void qlcnic_83xx_dcb_aen_handler(struct qlcnic_dcb *, void *);
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -040076
77struct qlcnic_dcb_capability {
78 bool tsa_capability;
79 bool ets_capability;
80 u8 max_num_tc;
81 u8 max_ets_tc;
82 u8 max_pfc_tc;
83 u8 dcb_capability;
84};
85
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -040086struct qlcnic_dcb_param {
87 u32 hdr_prio_pfc_map[2];
88 u32 prio_pg_map[2];
89 u32 pg_bw_map[2];
90 u32 pg_tsa_map[2];
91 u32 app[QLC_DCB_MAX_APP];
92};
93
94struct qlcnic_dcb_mbx_params {
95 /* 1st local, 2nd operational 3rd remote */
96 struct qlcnic_dcb_param type[3];
97 u32 prio_tc_map;
98};
99
100struct qlcnic_82xx_dcb_param_mbx_le {
101 __le32 hdr_prio_pfc_map[2];
102 __le32 prio_pg_map[2];
103 __le32 pg_bw_map[2];
104 __le32 pg_tsa_map[2];
105 __le32 app[QLC_DCB_MAX_APP];
106};
107
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400108enum qlcnic_dcb_selector {
109 QLC_SELECTOR_DEF = 0x0,
110 QLC_SELECTOR_ETHER,
111 QLC_SELECTOR_TCP,
112 QLC_SELECTOR_UDP,
113};
114
115enum qlcnic_dcb_prio_type {
116 QLC_PRIO_NONE = 0,
117 QLC_PRIO_GROUP,
118 QLC_PRIO_LINK,
119};
120
121enum qlcnic_dcb_pfc_type {
122 QLC_PFC_DISABLED = 0,
123 QLC_PFC_FULL,
124 QLC_PFC_TX,
125 QLC_PFC_RX
126};
127
128struct qlcnic_dcb_prio_cfg {
129 bool valid;
130 enum qlcnic_dcb_pfc_type pfc_type;
131};
132
133struct qlcnic_dcb_pg_cfg {
134 bool valid;
135 u8 total_bw_percent; /* of Link/ port BW */
136 u8 prio_count;
137 u8 tsa_type;
138};
139
140struct qlcnic_dcb_tc_cfg {
141 bool valid;
142 struct qlcnic_dcb_prio_cfg prio_cfg[QLC_DCB_MAX_PRIO];
143 enum qlcnic_dcb_prio_type prio_type; /* always prio_link */
144 u8 link_percent; /* % of link bandwidth */
145 u8 bwg_percent; /* % of BWG's bandwidth */
146 u8 up_tc_map;
147 u8 pgid;
148};
149
150struct qlcnic_dcb_app {
151 bool valid;
152 enum qlcnic_dcb_selector selector;
153 u16 protocol;
154 u8 priority;
155};
156
157struct qlcnic_dcb_cee {
158 struct qlcnic_dcb_tc_cfg tc_cfg[QLC_DCB_MAX_TC];
159 struct qlcnic_dcb_pg_cfg pg_cfg[QLC_DCB_MAX_PG];
160 struct qlcnic_dcb_app app[QLC_DCB_MAX_APP];
161 bool tc_param_valid;
162 bool pfc_mode_enable;
163};
164
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400165struct qlcnic_dcb_cfg {
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400166 /* 0 - local, 1 - operational, 2 - remote */
167 struct qlcnic_dcb_cee type[QLC_DCB_NUM_PARAM];
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400168 struct qlcnic_dcb_capability capability;
169 u32 version;
170};
171
172static struct qlcnic_dcb_ops qlcnic_83xx_dcb_ops = {
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400173 .init_dcbnl_ops = __qlcnic_init_dcbnl_ops,
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400174 .free = __qlcnic_dcb_free,
175 .attach = __qlcnic_dcb_attach,
176 .query_hw_capability = __qlcnic_dcb_query_hw_capability,
177 .get_info = __qlcnic_dcb_get_info,
178
179 .get_hw_capability = qlcnic_83xx_dcb_get_hw_capability,
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400180 .query_cee_param = qlcnic_83xx_dcb_query_cee_param,
181 .get_cee_cfg = qlcnic_83xx_dcb_get_cee_cfg,
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400182 .register_aen = qlcnic_83xx_dcb_register_aen,
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400183 .aen_handler = qlcnic_83xx_dcb_aen_handler,
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400184};
185
186static struct qlcnic_dcb_ops qlcnic_82xx_dcb_ops = {
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400187 .init_dcbnl_ops = __qlcnic_init_dcbnl_ops,
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400188 .free = __qlcnic_dcb_free,
189 .attach = __qlcnic_dcb_attach,
190 .query_hw_capability = __qlcnic_dcb_query_hw_capability,
191 .get_info = __qlcnic_dcb_get_info,
192
193 .get_hw_capability = qlcnic_82xx_dcb_get_hw_capability,
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400194 .query_cee_param = qlcnic_82xx_dcb_query_cee_param,
195 .get_cee_cfg = qlcnic_82xx_dcb_get_cee_cfg,
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400196 .aen_handler = qlcnic_82xx_dcb_aen_handler,
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400197};
198
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400199static u8 qlcnic_dcb_get_num_app(struct qlcnic_adapter *adapter, u32 val)
200{
201 if (qlcnic_82xx_check(adapter))
202 return QLC_82XX_DCB_GET_NUMAPP(val);
203 else
204 return QLC_83XX_DCB_GET_NUMAPP(val);
205}
206
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400207static inline u8 qlcnic_dcb_pfc_hdr_valid(struct qlcnic_adapter *adapter,
208 u32 val)
209{
210 if (qlcnic_82xx_check(adapter))
211 return QLC_82XX_DCB_PFC_VALID(val);
212 else
213 return QLC_83XX_DCB_PFC_VALID(val);
214}
215
216static inline u8 qlcnic_dcb_tsa_hdr_valid(struct qlcnic_adapter *adapter,
217 u32 val)
218{
219 if (qlcnic_82xx_check(adapter))
220 return QLC_82XX_DCB_TSA_VALID(val);
221 else
222 return QLC_83XX_DCB_TSA_VALID(val);
223}
224
225static inline u8 qlcnic_dcb_get_prio_map_app(struct qlcnic_adapter *adapter,
226 u32 val)
227{
228 if (qlcnic_82xx_check(adapter))
229 return QLC_82XX_DCB_GET_PRIOMAP_APP(val);
230 else
231 return QLC_83XX_DCB_GET_PRIOMAP_APP(val);
232}
233
234static int qlcnic_dcb_prio_count(u8 up_tc_map)
235{
236 int j;
237
238 for (j = 0; j < QLC_DCB_MAX_TC; j++)
239 if (up_tc_map & QLC_DCB_GET_MAP(j))
240 break;
241
242 return j;
243}
244
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400245static inline void __qlcnic_init_dcbnl_ops(struct qlcnic_dcb *dcb)
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400246{
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400247 if (test_bit(QLCNIC_DCB_STATE, &dcb->state))
248 dcb->adapter->netdev->dcbnl_ops = &qlcnic_dcbnl_ops;
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400249}
250
Sucheta Chakraborty0996b7d2013-09-03 05:07:37 -0400251static void qlcnic_set_dcb_ops(struct qlcnic_adapter *adapter)
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400252{
253 if (qlcnic_82xx_check(adapter))
254 adapter->dcb->ops = &qlcnic_82xx_dcb_ops;
255 else if (qlcnic_83xx_check(adapter))
256 adapter->dcb->ops = &qlcnic_83xx_dcb_ops;
257}
258
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400259int qlcnic_register_dcb(struct qlcnic_adapter *adapter)
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400260{
261 struct qlcnic_dcb *dcb;
262
Sucheta Chakraborty3c44bba2013-12-17 09:01:49 -0500263 if (qlcnic_sriov_vf_check(adapter))
264 return 0;
265
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400266 dcb = kzalloc(sizeof(struct qlcnic_dcb), GFP_ATOMIC);
267 if (!dcb)
268 return -ENOMEM;
269
270 adapter->dcb = dcb;
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400271 dcb->adapter = adapter;
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400272 qlcnic_set_dcb_ops(adapter);
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400273 dcb->state = 0;
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400274
275 return 0;
276}
277
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400278static void __qlcnic_dcb_free(struct qlcnic_dcb *dcb)
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400279{
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400280 struct qlcnic_adapter *adapter;
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400281
282 if (!dcb)
283 return;
284
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400285 adapter = dcb->adapter;
286 qlcnic_dcb_register_aen(dcb, 0);
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400287
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400288 while (test_bit(QLCNIC_DCB_AEN_MODE, &dcb->state))
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400289 usleep_range(10000, 11000);
290
291 cancel_delayed_work_sync(&dcb->aen_work);
292
293 if (dcb->wq) {
294 destroy_workqueue(dcb->wq);
295 dcb->wq = NULL;
296 }
297
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400298 kfree(dcb->cfg);
299 dcb->cfg = NULL;
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400300 kfree(dcb->param);
301 dcb->param = NULL;
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400302 kfree(dcb);
303 adapter->dcb = NULL;
304}
305
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400306static void __qlcnic_dcb_get_info(struct qlcnic_dcb *dcb)
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400307{
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400308 qlcnic_dcb_get_hw_capability(dcb);
309 qlcnic_dcb_get_cee_cfg(dcb);
310 qlcnic_dcb_register_aen(dcb, 1);
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400311}
312
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400313static int __qlcnic_dcb_attach(struct qlcnic_dcb *dcb)
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400314{
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400315 int err = 0;
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400316
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400317 INIT_DELAYED_WORK(&dcb->aen_work, qlcnic_dcb_aen_work);
318
319 dcb->wq = create_singlethread_workqueue("qlcnic-dcb");
320 if (!dcb->wq) {
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400321 dev_err(&dcb->adapter->pdev->dev,
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400322 "DCB workqueue allocation failed. DCB will be disabled\n");
323 return -1;
324 }
325
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400326 dcb->cfg = kzalloc(sizeof(struct qlcnic_dcb_cfg), GFP_ATOMIC);
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400327 if (!dcb->cfg) {
328 err = -ENOMEM;
329 goto out_free_wq;
330 }
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400331
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400332 dcb->param = kzalloc(sizeof(struct qlcnic_dcb_mbx_params), GFP_ATOMIC);
333 if (!dcb->param) {
334 err = -ENOMEM;
335 goto out_free_cfg;
336 }
337
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400338 qlcnic_dcb_get_info(dcb);
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400339
340 return 0;
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400341out_free_cfg:
342 kfree(dcb->cfg);
343 dcb->cfg = NULL;
344
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400345out_free_wq:
346 destroy_workqueue(dcb->wq);
347 dcb->wq = NULL;
348
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400349 return err;
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400350}
351
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400352static int __qlcnic_dcb_query_hw_capability(struct qlcnic_dcb *dcb, char *buf)
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400353{
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400354 struct qlcnic_adapter *adapter = dcb->adapter;
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400355 struct qlcnic_cmd_args cmd;
356 u32 mbx_out;
357 int err;
358
359 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_CAP);
360 if (err)
361 return err;
362
363 err = qlcnic_issue_cmd(adapter, &cmd);
364 if (err) {
365 dev_err(&adapter->pdev->dev,
366 "Failed to query DCBX capability, err %d\n", err);
367 } else {
368 mbx_out = cmd.rsp.arg[1];
369 if (buf)
370 memcpy(buf, &mbx_out, sizeof(u32));
371 }
372
373 qlcnic_free_mbx_args(&cmd);
374
375 return err;
376}
377
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400378static int __qlcnic_dcb_get_capability(struct qlcnic_dcb *dcb, u32 *val)
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400379{
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400380 struct qlcnic_dcb_capability *cap = &dcb->cfg->capability;
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400381 u32 mbx_out;
382 int err;
383
384 memset(cap, 0, sizeof(struct qlcnic_dcb_capability));
385
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400386 err = qlcnic_dcb_query_hw_capability(dcb, (char *)val);
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400387 if (err)
388 return err;
389
390 mbx_out = *val;
391 if (QLC_DCB_TSA_SUPPORT(mbx_out))
392 cap->tsa_capability = true;
393
394 if (QLC_DCB_ETS_SUPPORT(mbx_out))
395 cap->ets_capability = true;
396
397 cap->max_num_tc = QLC_DCB_MAX_NUM_TC(mbx_out);
398 cap->max_ets_tc = QLC_DCB_MAX_NUM_ETS_TC(mbx_out);
399 cap->max_pfc_tc = QLC_DCB_MAX_NUM_PFC_TC(mbx_out);
400
401 if (cap->max_num_tc > QLC_DCB_MAX_TC ||
402 cap->max_ets_tc > cap->max_num_tc ||
403 cap->max_pfc_tc > cap->max_num_tc) {
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400404 dev_err(&dcb->adapter->pdev->dev, "Invalid DCB configuration\n");
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400405 return -EINVAL;
406 }
407
408 return err;
409}
410
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400411static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_dcb *dcb)
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400412{
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400413 struct qlcnic_dcb_cfg *cfg = dcb->cfg;
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400414 struct qlcnic_dcb_capability *cap;
415 u32 mbx_out;
416 int err;
417
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400418 err = __qlcnic_dcb_get_capability(dcb, &mbx_out);
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400419 if (err)
420 return err;
421
422 cap = &cfg->capability;
423 cap->dcb_capability = DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_LLD_MANAGED;
424
425 if (cap->dcb_capability && cap->tsa_capability && cap->ets_capability)
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400426 set_bit(QLCNIC_DCB_STATE, &dcb->state);
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400427
428 return err;
429}
430
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400431static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_dcb *dcb,
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400432 char *buf, u8 type)
433{
434 u16 size = sizeof(struct qlcnic_82xx_dcb_param_mbx_le);
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400435 struct qlcnic_adapter *adapter = dcb->adapter;
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400436 struct qlcnic_82xx_dcb_param_mbx_le *prsp_le;
437 struct device *dev = &adapter->pdev->dev;
438 dma_addr_t cardrsp_phys_addr;
439 struct qlcnic_dcb_param rsp;
440 struct qlcnic_cmd_args cmd;
441 u64 phys_addr;
442 void *addr;
443 int err, i;
444
445 switch (type) {
446 case QLC_DCB_LOCAL_PARAM_FWID:
447 case QLC_DCB_OPER_PARAM_FWID:
448 case QLC_DCB_PEER_PARAM_FWID:
449 break;
450 default:
451 dev_err(dev, "Invalid parameter type %d\n", type);
452 return -EINVAL;
453 }
454
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400455 addr = dma_alloc_coherent(dev, size, &cardrsp_phys_addr, GFP_KERNEL);
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400456 if (addr == NULL)
457 return -ENOMEM;
458
459 prsp_le = addr;
460
461 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_PARAM);
462 if (err)
463 goto out_free_rsp;
464
465 phys_addr = cardrsp_phys_addr;
466 cmd.req.arg[1] = size | (type << 16);
467 cmd.req.arg[2] = MSD(phys_addr);
468 cmd.req.arg[3] = LSD(phys_addr);
469
470 err = qlcnic_issue_cmd(adapter, &cmd);
471 if (err) {
472 dev_err(dev, "Failed to query DCBX parameter, err %d\n", err);
473 goto out;
474 }
475
476 memset(&rsp, 0, sizeof(struct qlcnic_dcb_param));
477 rsp.hdr_prio_pfc_map[0] = le32_to_cpu(prsp_le->hdr_prio_pfc_map[0]);
478 rsp.hdr_prio_pfc_map[1] = le32_to_cpu(prsp_le->hdr_prio_pfc_map[1]);
479 rsp.prio_pg_map[0] = le32_to_cpu(prsp_le->prio_pg_map[0]);
480 rsp.prio_pg_map[1] = le32_to_cpu(prsp_le->prio_pg_map[1]);
481 rsp.pg_bw_map[0] = le32_to_cpu(prsp_le->pg_bw_map[0]);
482 rsp.pg_bw_map[1] = le32_to_cpu(prsp_le->pg_bw_map[1]);
483 rsp.pg_tsa_map[0] = le32_to_cpu(prsp_le->pg_tsa_map[0]);
484 rsp.pg_tsa_map[1] = le32_to_cpu(prsp_le->pg_tsa_map[1]);
485
486 for (i = 0; i < QLC_DCB_MAX_APP; i++)
487 rsp.app[i] = le32_to_cpu(prsp_le->app[i]);
488
489 if (buf)
490 memcpy(buf, &rsp, size);
491out:
492 qlcnic_free_mbx_args(&cmd);
493
494out_free_rsp:
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400495 dma_free_coherent(dev, size, addr, cardrsp_phys_addr);
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400496
497 return err;
498}
499
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400500static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_dcb *dcb)
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400501{
502 struct qlcnic_dcb_mbx_params *mbx;
503 int err;
504
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400505 mbx = dcb->param;
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400506 if (!mbx)
507 return 0;
508
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400509 err = qlcnic_dcb_query_cee_param(dcb, (char *)&mbx->type[0],
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400510 QLC_DCB_LOCAL_PARAM_FWID);
511 if (err)
512 return err;
513
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400514 err = qlcnic_dcb_query_cee_param(dcb, (char *)&mbx->type[1],
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400515 QLC_DCB_OPER_PARAM_FWID);
516 if (err)
517 return err;
518
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400519 err = qlcnic_dcb_query_cee_param(dcb, (char *)&mbx->type[2],
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400520 QLC_DCB_PEER_PARAM_FWID);
521 if (err)
522 return err;
523
524 mbx->prio_tc_map = QLC_82XX_DCB_PRIO_TC_MAP;
525
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400526 qlcnic_dcb_data_cee_param_map(dcb->adapter);
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400527
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400528 return err;
529}
530
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400531static void qlcnic_dcb_aen_work(struct work_struct *work)
532{
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400533 struct qlcnic_dcb *dcb;
534
535 dcb = container_of(work, struct qlcnic_dcb, aen_work.work);
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400536
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400537 qlcnic_dcb_get_cee_cfg(dcb);
538 clear_bit(QLCNIC_DCB_AEN_MODE, &dcb->state);
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400539}
540
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400541static void qlcnic_82xx_dcb_aen_handler(struct qlcnic_dcb *dcb, void *data)
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400542{
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400543 if (test_and_set_bit(QLCNIC_DCB_AEN_MODE, &dcb->state))
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400544 return;
545
546 queue_delayed_work(dcb->wq, &dcb->aen_work, 0);
547}
548
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400549static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_dcb *dcb)
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400550{
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400551 struct qlcnic_dcb_capability *cap = &dcb->cfg->capability;
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400552 u32 mbx_out;
553 int err;
554
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400555 err = __qlcnic_dcb_get_capability(dcb, &mbx_out);
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400556 if (err)
557 return err;
558
559 if (mbx_out & BIT_2)
560 cap->dcb_capability = DCB_CAP_DCBX_VER_CEE;
561 if (mbx_out & BIT_3)
562 cap->dcb_capability |= DCB_CAP_DCBX_VER_IEEE;
563 if (cap->dcb_capability)
564 cap->dcb_capability |= DCB_CAP_DCBX_LLD_MANAGED;
565
566 if (cap->dcb_capability && cap->tsa_capability && cap->ets_capability)
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400567 set_bit(QLCNIC_DCB_STATE, &dcb->state);
Sucheta Chakraborty14d385b2013-08-23 13:38:25 -0400568
569 return err;
570}
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400571
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400572static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_dcb *dcb,
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400573 char *buf, u8 idx)
574{
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400575 struct qlcnic_adapter *adapter = dcb->adapter;
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400576 struct qlcnic_dcb_mbx_params mbx_out;
577 int err, i, j, k, max_app, size;
578 struct qlcnic_dcb_param *each;
579 struct qlcnic_cmd_args cmd;
580 u32 val;
581 char *p;
582
583 size = 0;
584 memset(&mbx_out, 0, sizeof(struct qlcnic_dcb_mbx_params));
585 memset(buf, 0, sizeof(struct qlcnic_dcb_mbx_params));
586
587 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_PARAM);
588 if (err)
589 return err;
590
591 cmd.req.arg[0] |= QLC_DCB_FW_VER << 29;
592 err = qlcnic_issue_cmd(adapter, &cmd);
593 if (err) {
594 dev_err(&adapter->pdev->dev,
595 "Failed to query DCBX param, err %d\n", err);
596 goto out;
597 }
598
599 mbx_out.prio_tc_map = cmd.rsp.arg[1];
600 p = memcpy(buf, &mbx_out, sizeof(u32));
601 k = 2;
602 p += sizeof(u32);
603
604 for (j = 0; j < QLC_DCB_NUM_PARAM; j++) {
605 each = &mbx_out.type[j];
606
607 each->hdr_prio_pfc_map[0] = cmd.rsp.arg[k++];
608 each->hdr_prio_pfc_map[1] = cmd.rsp.arg[k++];
609 each->prio_pg_map[0] = cmd.rsp.arg[k++];
610 each->prio_pg_map[1] = cmd.rsp.arg[k++];
611 each->pg_bw_map[0] = cmd.rsp.arg[k++];
612 each->pg_bw_map[1] = cmd.rsp.arg[k++];
613 each->pg_tsa_map[0] = cmd.rsp.arg[k++];
614 each->pg_tsa_map[1] = cmd.rsp.arg[k++];
615 val = each->hdr_prio_pfc_map[0];
616
617 max_app = qlcnic_dcb_get_num_app(adapter, val);
618 for (i = 0; i < max_app; i++)
619 each->app[i] = cmd.rsp.arg[i + k];
620
621 size = 16 * sizeof(u32);
622 memcpy(p, &each->hdr_prio_pfc_map[0], size);
623 p += size;
624 if (j == 0)
625 k = 18;
626 else
627 k = 34;
628 }
629out:
630 qlcnic_free_mbx_args(&cmd);
631
632 return err;
633}
634
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400635static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_dcb *dcb)
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400636{
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400637 int err;
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400638
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400639 err = qlcnic_dcb_query_cee_param(dcb, (char *)dcb->param, 0);
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400640 if (err)
641 return err;
642
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400643 qlcnic_dcb_data_cee_param_map(dcb->adapter);
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400644
645 return err;
Sucheta Chakrabortyfb859ed2013-08-23 13:38:26 -0400646}
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400647
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400648static int qlcnic_83xx_dcb_register_aen(struct qlcnic_dcb *dcb, bool flag)
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400649{
650 u8 val = (flag ? QLCNIC_CMD_INIT_NIC_FUNC : QLCNIC_CMD_STOP_NIC_FUNC);
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400651 struct qlcnic_adapter *adapter = dcb->adapter;
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400652 struct qlcnic_cmd_args cmd;
653 int err;
654
655 err = qlcnic_alloc_mbx_args(&cmd, adapter, val);
656 if (err)
657 return err;
658
659 cmd.req.arg[1] = QLC_DCB_AEN_BIT;
660
661 err = qlcnic_issue_cmd(adapter, &cmd);
662 if (err)
663 dev_err(&adapter->pdev->dev, "Failed to %s DCBX AEN, err %d\n",
664 (flag ? "register" : "unregister"), err);
665
666 qlcnic_free_mbx_args(&cmd);
667
668 return err;
669}
670
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400671static void qlcnic_83xx_dcb_aen_handler(struct qlcnic_dcb *dcb, void *data)
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400672{
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400673 u32 *val = data;
674
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400675 if (test_and_set_bit(QLCNIC_DCB_AEN_MODE, &dcb->state))
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400676 return;
677
678 if (*val & BIT_8)
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400679 set_bit(QLCNIC_DCB_STATE, &dcb->state);
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400680 else
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400681 clear_bit(QLCNIC_DCB_STATE, &dcb->state);
Sucheta Chakraborty2d8ebca2013-08-23 13:38:27 -0400682
683 queue_delayed_work(dcb->wq, &dcb->aen_work, 0);
684}
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400685
686static void qlcnic_dcb_fill_cee_tc_params(struct qlcnic_dcb_mbx_params *mbx,
687 struct qlcnic_dcb_param *each,
688 struct qlcnic_dcb_cee *type)
689{
690 struct qlcnic_dcb_tc_cfg *tc_cfg;
691 u8 i, tc, pgid;
692
693 for (i = 0; i < QLC_DCB_MAX_PRIO; i++) {
694 tc = QLC_DCB_GET_TC_PRIO(mbx->prio_tc_map, i);
695 tc_cfg = &type->tc_cfg[tc];
696 tc_cfg->valid = true;
697 tc_cfg->up_tc_map |= QLC_DCB_GET_MAP(i);
698
699 if (QLC_DCB_GET_PFC_PRIO(each->hdr_prio_pfc_map[1], i) &&
700 type->pfc_mode_enable) {
701 tc_cfg->prio_cfg[i].valid = true;
702 tc_cfg->prio_cfg[i].pfc_type = QLC_PFC_FULL;
703 }
704
705 if (i < 4)
706 pgid = QLC_DCB_GET_PGID_PRIO(each->prio_pg_map[0], i);
707 else
708 pgid = QLC_DCB_GET_PGID_PRIO(each->prio_pg_map[1], i);
709
710 tc_cfg->pgid = pgid;
711
712 tc_cfg->prio_type = QLC_PRIO_LINK;
713 type->pg_cfg[tc_cfg->pgid].prio_count++;
714 }
715}
716
717static void qlcnic_dcb_fill_cee_pg_params(struct qlcnic_dcb_param *each,
718 struct qlcnic_dcb_cee *type)
719{
720 struct qlcnic_dcb_pg_cfg *pg_cfg;
721 u8 i, tsa, bw_per;
722
723 for (i = 0; i < QLC_DCB_MAX_PG; i++) {
724 pg_cfg = &type->pg_cfg[i];
725 pg_cfg->valid = true;
726
727 if (i < 4) {
728 bw_per = QLC_DCB_GET_BWPER_PG(each->pg_bw_map[0], i);
729 tsa = QLC_DCB_GET_TSA_PG(each->pg_tsa_map[0], i);
730 } else {
731 bw_per = QLC_DCB_GET_BWPER_PG(each->pg_bw_map[1], i);
732 tsa = QLC_DCB_GET_TSA_PG(each->pg_tsa_map[1], i);
733 }
734
735 pg_cfg->total_bw_percent = bw_per;
736 pg_cfg->tsa_type = tsa;
737 }
738}
739
740static void
741qlcnic_dcb_fill_cee_app_params(struct qlcnic_adapter *adapter, u8 idx,
742 struct qlcnic_dcb_param *each,
743 struct qlcnic_dcb_cee *type)
744{
745 struct qlcnic_dcb_app *app;
746 u8 i, num_app, map, cnt;
747 struct dcb_app new_app;
748
749 num_app = qlcnic_dcb_get_num_app(adapter, each->hdr_prio_pfc_map[0]);
750 for (i = 0; i < num_app; i++) {
751 app = &type->app[i];
752 app->valid = true;
753
754 /* Only for CEE (-1) */
755 app->selector = QLC_DCB_GET_SELECTOR_APP(each->app[i]) - 1;
756 new_app.selector = app->selector;
757 app->protocol = QLC_DCB_GET_PROTO_ID_APP(each->app[i]);
758 new_app.protocol = app->protocol;
759 map = qlcnic_dcb_get_prio_map_app(adapter, each->app[i]);
760 cnt = qlcnic_dcb_prio_count(map);
761
762 if (cnt >= QLC_DCB_MAX_TC)
763 cnt = 0;
764
765 app->priority = cnt;
766 new_app.priority = cnt;
767
768 if (idx == QLC_DCB_OPER_IDX && adapter->netdev->dcbnl_ops)
769 dcb_setapp(adapter->netdev, &new_app);
770 }
771}
772
773static void qlcnic_dcb_map_cee_params(struct qlcnic_adapter *adapter, u8 idx)
774{
775 struct qlcnic_dcb_mbx_params *mbx = adapter->dcb->param;
776 struct qlcnic_dcb_param *each = &mbx->type[idx];
777 struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg;
778 struct qlcnic_dcb_cee *type = &cfg->type[idx];
779
780 type->tc_param_valid = false;
781 type->pfc_mode_enable = false;
782 memset(type->tc_cfg, 0,
783 sizeof(struct qlcnic_dcb_tc_cfg) * QLC_DCB_MAX_TC);
784 memset(type->pg_cfg, 0,
785 sizeof(struct qlcnic_dcb_pg_cfg) * QLC_DCB_MAX_TC);
786
787 if (qlcnic_dcb_pfc_hdr_valid(adapter, each->hdr_prio_pfc_map[0]) &&
788 cfg->capability.max_pfc_tc)
789 type->pfc_mode_enable = true;
790
791 if (qlcnic_dcb_tsa_hdr_valid(adapter, each->hdr_prio_pfc_map[0]) &&
792 cfg->capability.max_ets_tc)
793 type->tc_param_valid = true;
794
795 qlcnic_dcb_fill_cee_tc_params(mbx, each, type);
796 qlcnic_dcb_fill_cee_pg_params(each, type);
797 qlcnic_dcb_fill_cee_app_params(adapter, idx, each, type);
798}
799
800static void qlcnic_dcb_data_cee_param_map(struct qlcnic_adapter *adapter)
801{
802 int i;
803
804 for (i = 0; i < QLC_DCB_NUM_PARAM; i++)
805 qlcnic_dcb_map_cee_params(adapter, i);
806
807 dcbnl_cee_notify(adapter->netdev, RTM_GETDCB, DCB_CMD_CEE_GET, 0, 0);
808}
809
810static u8 qlcnic_dcb_get_state(struct net_device *netdev)
811{
812 struct qlcnic_adapter *adapter = netdev_priv(netdev);
813
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400814 return test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state);
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400815}
816
817static void qlcnic_dcb_get_perm_hw_addr(struct net_device *netdev, u8 *addr)
818{
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400819 memcpy(addr, netdev->perm_addr, netdev->addr_len);
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400820}
821
822static void
823qlcnic_dcb_get_pg_tc_cfg_tx(struct net_device *netdev, int tc, u8 *prio,
824 u8 *pgid, u8 *bw_per, u8 *up_tc_map)
825{
826 struct qlcnic_adapter *adapter = netdev_priv(netdev);
827 struct qlcnic_dcb_tc_cfg *tc_cfg, *temp;
828 struct qlcnic_dcb_cee *type;
829 u8 i, cnt, pg;
830
831 type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX];
832 *prio = *pgid = *bw_per = *up_tc_map = 0;
833
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400834 if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state) ||
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400835 !type->tc_param_valid)
836 return;
837
838 if (tc < 0 || (tc > QLC_DCB_MAX_TC))
839 return;
840
841 tc_cfg = &type->tc_cfg[tc];
842 if (!tc_cfg->valid)
843 return;
844
845 *pgid = tc_cfg->pgid;
846 *prio = tc_cfg->prio_type;
847 *up_tc_map = tc_cfg->up_tc_map;
848 pg = *pgid;
849
850 for (i = 0, cnt = 0; i < QLC_DCB_MAX_TC; i++) {
851 temp = &type->tc_cfg[i];
852 if (temp->valid && (pg == temp->pgid))
853 cnt++;
854 }
855
856 tc_cfg->bwg_percent = (100 / cnt);
857 *bw_per = tc_cfg->bwg_percent;
858}
859
860static void qlcnic_dcb_get_pg_bwg_cfg_tx(struct net_device *netdev, int pgid,
861 u8 *bw_pct)
862{
863 struct qlcnic_adapter *adapter = netdev_priv(netdev);
864 struct qlcnic_dcb_pg_cfg *pgcfg;
865 struct qlcnic_dcb_cee *type;
866
867 *bw_pct = 0;
868 type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX];
869
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400870 if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state) ||
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400871 !type->tc_param_valid)
872 return;
873
874 if (pgid < 0 || pgid > QLC_DCB_MAX_PG)
875 return;
876
877 pgcfg = &type->pg_cfg[pgid];
878 if (!pgcfg->valid)
879 return;
880
881 *bw_pct = pgcfg->total_bw_percent;
882}
883
884static void qlcnic_dcb_get_pfc_cfg(struct net_device *netdev, int prio,
885 u8 *setting)
886{
887 struct qlcnic_adapter *adapter = netdev_priv(netdev);
888 struct qlcnic_dcb_tc_cfg *tc_cfg;
889 u8 val = QLC_DCB_GET_MAP(prio);
890 struct qlcnic_dcb_cee *type;
891 u8 i;
892
893 *setting = 0;
894 type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX];
895
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400896 if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state) ||
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400897 !type->pfc_mode_enable)
898 return;
899
900 for (i = 0; i < QLC_DCB_MAX_TC; i++) {
901 tc_cfg = &type->tc_cfg[i];
902 if (!tc_cfg->valid)
903 continue;
904
905 if ((val & tc_cfg->up_tc_map) && (tc_cfg->prio_cfg[prio].valid))
906 *setting = tc_cfg->prio_cfg[prio].pfc_type;
907 }
908}
909
910static u8 qlcnic_dcb_get_capability(struct net_device *netdev, int capid,
911 u8 *cap)
912{
913 struct qlcnic_adapter *adapter = netdev_priv(netdev);
914
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400915 if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400916 return 0;
917
918 switch (capid) {
919 case DCB_CAP_ATTR_PG:
920 case DCB_CAP_ATTR_UP2TC:
921 case DCB_CAP_ATTR_PFC:
922 case DCB_CAP_ATTR_GSP:
923 *cap = true;
924 break;
925 case DCB_CAP_ATTR_PG_TCS:
926 case DCB_CAP_ATTR_PFC_TCS:
927 *cap = 0x80; /* 8 priorities for PGs */
928 break;
929 case DCB_CAP_ATTR_DCBX:
930 *cap = adapter->dcb->cfg->capability.dcb_capability;
931 break;
932 default:
933 *cap = false;
934 }
935
936 return 0;
937}
938
939static int qlcnic_dcb_get_num_tcs(struct net_device *netdev, int attr, u8 *num)
940{
941 struct qlcnic_adapter *adapter = netdev_priv(netdev);
942 struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg;
943
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400944 if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400945 return -EINVAL;
946
947 switch (attr) {
948 case DCB_NUMTCS_ATTR_PG:
949 *num = cfg->capability.max_ets_tc;
950 return 0;
951 case DCB_NUMTCS_ATTR_PFC:
952 *num = cfg->capability.max_pfc_tc;
953 return 0;
954 default:
955 return -EINVAL;
956 }
957}
958
959static u8 qlcnic_dcb_get_app(struct net_device *netdev, u8 idtype, u16 id)
960{
961 struct qlcnic_adapter *adapter = netdev_priv(netdev);
962 struct dcb_app app = {
963 .selector = idtype,
964 .protocol = id,
965 };
966
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400967 if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400968 return 0;
969
970 return dcb_getapp(netdev, &app);
971}
972
973static u8 qlcnic_dcb_get_pfc_state(struct net_device *netdev)
974{
975 struct qlcnic_adapter *adapter = netdev_priv(netdev);
976 struct qlcnic_dcb *dcb = adapter->dcb;
977
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400978 if (!test_bit(QLCNIC_DCB_STATE, &dcb->state))
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400979 return 0;
980
981 return dcb->cfg->type[QLC_DCB_OPER_IDX].pfc_mode_enable;
982}
983
984static u8 qlcnic_dcb_get_dcbx(struct net_device *netdev)
985{
986 struct qlcnic_adapter *adapter = netdev_priv(netdev);
987 struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg;
988
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -0400989 if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
Sucheta Chakraborty48365e42013-08-23 13:38:28 -0400990 return 0;
991
992 return cfg->capability.dcb_capability;
993}
994
995static u8 qlcnic_dcb_get_feat_cfg(struct net_device *netdev, int fid, u8 *flag)
996{
997 struct qlcnic_adapter *adapter = netdev_priv(netdev);
998 struct qlcnic_dcb_cee *type;
999
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -04001000 if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
Sucheta Chakraborty48365e42013-08-23 13:38:28 -04001001 return 1;
1002
1003 type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX];
1004 *flag = 0;
1005
1006 switch (fid) {
1007 case DCB_FEATCFG_ATTR_PG:
1008 if (type->tc_param_valid)
1009 *flag |= DCB_FEATCFG_ENABLE;
1010 else
1011 *flag |= DCB_FEATCFG_ERROR;
1012 break;
1013 case DCB_FEATCFG_ATTR_PFC:
1014 if (type->pfc_mode_enable) {
1015 if (type->tc_cfg[0].prio_cfg[0].pfc_type)
1016 *flag |= DCB_FEATCFG_ENABLE;
1017 } else {
1018 *flag |= DCB_FEATCFG_ERROR;
1019 }
1020 break;
1021 case DCB_FEATCFG_ATTR_APP:
1022 *flag |= DCB_FEATCFG_ENABLE;
1023 break;
1024 default:
1025 netdev_err(netdev, "Invalid Feature ID %d\n", fid);
1026 return 1;
1027 }
1028
1029 return 0;
1030}
1031
1032static inline void
1033qlcnic_dcb_get_pg_tc_cfg_rx(struct net_device *netdev, int prio, u8 *prio_type,
1034 u8 *pgid, u8 *bw_pct, u8 *up_map)
1035{
1036 *prio_type = *pgid = *bw_pct = *up_map = 0;
1037}
1038
1039static inline void
1040qlcnic_dcb_get_pg_bwg_cfg_rx(struct net_device *netdev, int pgid, u8 *bw_pct)
1041{
1042 *bw_pct = 0;
1043}
1044
1045static int qlcnic_dcb_peer_app_info(struct net_device *netdev,
1046 struct dcb_peer_app_info *info,
1047 u16 *app_count)
1048{
1049 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1050 struct qlcnic_dcb_cee *peer;
1051 int i;
1052
1053 *app_count = 0;
1054
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -04001055 if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
Sucheta Chakraborty48365e42013-08-23 13:38:28 -04001056 return 0;
1057
1058 peer = &adapter->dcb->cfg->type[QLC_DCB_PEER_IDX];
1059
1060 for (i = 0; i < QLC_DCB_MAX_APP; i++) {
1061 if (peer->app[i].valid)
1062 (*app_count)++;
1063 }
1064
1065 return 0;
1066}
1067
1068static int qlcnic_dcb_peer_app_table(struct net_device *netdev,
1069 struct dcb_app *table)
1070{
1071 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1072 struct qlcnic_dcb_cee *peer;
1073 struct qlcnic_dcb_app *app;
1074 int i, j;
1075
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -04001076 if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
Sucheta Chakraborty48365e42013-08-23 13:38:28 -04001077 return 0;
1078
1079 peer = &adapter->dcb->cfg->type[QLC_DCB_PEER_IDX];
1080
1081 for (i = 0, j = 0; i < QLC_DCB_MAX_APP; i++) {
1082 app = &peer->app[i];
1083 if (!app->valid)
1084 continue;
1085
1086 table[j].selector = app->selector;
1087 table[j].priority = app->priority;
1088 table[j++].protocol = app->protocol;
1089 }
1090
1091 return 0;
1092}
1093
1094static int qlcnic_dcb_cee_peer_get_pg(struct net_device *netdev,
1095 struct cee_pg *pg)
1096{
1097 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1098 struct qlcnic_dcb_cee *peer;
1099 u8 i, j, k, map;
1100
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -04001101 if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
Sucheta Chakraborty48365e42013-08-23 13:38:28 -04001102 return 0;
1103
1104 peer = &adapter->dcb->cfg->type[QLC_DCB_PEER_IDX];
1105
1106 for (i = 0, j = 0; i < QLC_DCB_MAX_PG; i++) {
1107 if (!peer->pg_cfg[i].valid)
1108 continue;
1109
1110 pg->pg_bw[j] = peer->pg_cfg[i].total_bw_percent;
1111
1112 for (k = 0; k < QLC_DCB_MAX_TC; k++) {
1113 if (peer->tc_cfg[i].valid &&
1114 (peer->tc_cfg[i].pgid == i)) {
1115 map = peer->tc_cfg[i].up_tc_map;
1116 pg->prio_pg[j++] = map;
1117 break;
1118 }
1119 }
1120 }
1121
1122 return 0;
1123}
1124
1125static int qlcnic_dcb_cee_peer_get_pfc(struct net_device *netdev,
1126 struct cee_pfc *pfc)
1127{
1128 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1129 struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg;
1130 struct qlcnic_dcb_tc_cfg *tc;
1131 struct qlcnic_dcb_cee *peer;
1132 u8 i, setting, prio;
1133
1134 pfc->pfc_en = 0;
1135
Sucheta Chakraborty1de899d2013-10-18 12:22:33 -04001136 if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
Sucheta Chakraborty48365e42013-08-23 13:38:28 -04001137 return 0;
1138
1139 peer = &cfg->type[QLC_DCB_PEER_IDX];
1140
1141 for (i = 0; i < QLC_DCB_MAX_TC; i++) {
1142 tc = &peer->tc_cfg[i];
1143 prio = qlcnic_dcb_prio_count(tc->up_tc_map);
1144
1145 setting = 0;
1146 qlcnic_dcb_get_pfc_cfg(netdev, prio, &setting);
1147 if (setting)
1148 pfc->pfc_en |= QLC_DCB_GET_MAP(i);
1149 }
1150
1151 pfc->tcs_supported = cfg->capability.max_pfc_tc;
1152
1153 return 0;
1154}
1155
1156static const struct dcbnl_rtnl_ops qlcnic_dcbnl_ops = {
1157 .getstate = qlcnic_dcb_get_state,
1158 .getpermhwaddr = qlcnic_dcb_get_perm_hw_addr,
1159 .getpgtccfgtx = qlcnic_dcb_get_pg_tc_cfg_tx,
1160 .getpgbwgcfgtx = qlcnic_dcb_get_pg_bwg_cfg_tx,
1161 .getpfccfg = qlcnic_dcb_get_pfc_cfg,
1162 .getcap = qlcnic_dcb_get_capability,
1163 .getnumtcs = qlcnic_dcb_get_num_tcs,
1164 .getapp = qlcnic_dcb_get_app,
1165 .getpfcstate = qlcnic_dcb_get_pfc_state,
1166 .getdcbx = qlcnic_dcb_get_dcbx,
1167 .getfeatcfg = qlcnic_dcb_get_feat_cfg,
1168
1169 .getpgtccfgrx = qlcnic_dcb_get_pg_tc_cfg_rx,
1170 .getpgbwgcfgrx = qlcnic_dcb_get_pg_bwg_cfg_rx,
1171
1172 .peer_getappinfo = qlcnic_dcb_peer_app_info,
1173 .peer_getapptable = qlcnic_dcb_peer_app_table,
1174 .cee_peer_getpg = qlcnic_dcb_cee_peer_get_pg,
1175 .cee_peer_getpfc = qlcnic_dcb_cee_peer_get_pfc,
1176};