diff options
author | Sucheta Chakraborty <sucheta.chakraborty@qlogic.com> | 2013-08-23 13:38:26 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-08-27 15:21:14 -0400 |
commit | fb859ed6916faeae6b44027d2e0738836a11e8c1 (patch) | |
tree | 400c0a70c692e8f6ea78ee9635ad21a57ff6ec86 /drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c | |
parent | 14d385b9905920cc0136721316c185c45ee6e26c (diff) |
qlcnic: dcb: Get DCB parameters from the adapter.
o Populate driver data structures with local, operational, and peer
DCB parameters.
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c')
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c index 121e492f2f87..e43866f20bbb 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c | |||
@@ -5,9 +5,14 @@ | |||
5 | * See LICENSE.qlcnic for copyright and licensing details. | 5 | * See LICENSE.qlcnic for copyright and licensing details. |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/types.h> | ||
8 | #include "qlcnic.h" | 9 | #include "qlcnic.h" |
9 | 10 | ||
11 | #define QLC_DCB_NUM_PARAM 3 | ||
12 | |||
13 | #define QLC_DCB_FW_VER 0x2 | ||
10 | #define QLC_DCB_MAX_TC 0x8 | 14 | #define QLC_DCB_MAX_TC 0x8 |
15 | #define QLC_DCB_MAX_APP 0x8 | ||
11 | 16 | ||
12 | #define QLC_DCB_TSA_SUPPORT(V) (V & 0x1) | 17 | #define QLC_DCB_TSA_SUPPORT(V) (V & 0x1) |
13 | #define QLC_DCB_ETS_SUPPORT(V) ((V >> 1) & 0x1) | 18 | #define QLC_DCB_ETS_SUPPORT(V) ((V >> 1) & 0x1) |
@@ -15,6 +20,29 @@ | |||
15 | #define QLC_DCB_MAX_NUM_TC(V) ((V >> 20) & 0xf) | 20 | #define QLC_DCB_MAX_NUM_TC(V) ((V >> 20) & 0xf) |
16 | #define QLC_DCB_MAX_NUM_ETS_TC(V) ((V >> 24) & 0xf) | 21 | #define QLC_DCB_MAX_NUM_ETS_TC(V) ((V >> 24) & 0xf) |
17 | #define QLC_DCB_MAX_NUM_PFC_TC(V) ((V >> 28) & 0xf) | 22 | #define QLC_DCB_MAX_NUM_PFC_TC(V) ((V >> 28) & 0xf) |
23 | #define QLC_DCB_GET_TC_PRIO(X, P) ((X >> (P * 3)) & 0x7) | ||
24 | #define QLC_DCB_GET_PGID_PRIO(X, P) ((X >> (P * 8)) & 0xff) | ||
25 | #define QLC_DCB_GET_BWPER_PG(X, P) ((X >> (P * 8)) & 0xff) | ||
26 | #define QLC_DCB_GET_TSA_PG(X, P) ((X >> (P * 8)) & 0xff) | ||
27 | #define QLC_DCB_GET_PFC_PRIO(X, P) (((X >> 24) >> P) & 0x1) | ||
28 | #define QLC_DCB_GET_PROTO_ID_APP(X) ((X >> 8) & 0xffff) | ||
29 | #define QLC_DCB_GET_SELECTOR_APP(X) (X & 0xff) | ||
30 | |||
31 | #define QLC_DCB_LOCAL_PARAM_FWID 0x3 | ||
32 | #define QLC_DCB_OPER_PARAM_FWID 0x1 | ||
33 | #define QLC_DCB_PEER_PARAM_FWID 0x2 | ||
34 | |||
35 | #define QLC_83XX_DCB_GET_NUMAPP(X) ((X >> 2) & 0xf) | ||
36 | #define QLC_83XX_DCB_TSA_VALID(X) (X & 0x1) | ||
37 | #define QLC_83XX_DCB_PFC_VALID(X) ((X >> 1) & 0x1) | ||
38 | #define QLC_83XX_DCB_GET_PRIOMAP_APP(X) (X >> 24) | ||
39 | |||
40 | #define QLC_82XX_DCB_GET_NUMAPP(X) ((X >> 12) & 0xf) | ||
41 | #define QLC_82XX_DCB_TSA_VALID(X) ((X >> 4) & 0x1) | ||
42 | #define QLC_82XX_DCB_PFC_VALID(X) ((X >> 5) & 0x1) | ||
43 | #define QLC_82XX_DCB_GET_PRIOVAL_APP(X) ((X >> 24) & 0x7) | ||
44 | #define QLC_82XX_DCB_GET_PRIOMAP_APP(X) (1 << X) | ||
45 | #define QLC_82XX_DCB_PRIO_TC_MAP (0x76543210) | ||
18 | 46 | ||
19 | static void __qlcnic_dcb_free(struct qlcnic_adapter *); | 47 | static void __qlcnic_dcb_free(struct qlcnic_adapter *); |
20 | static int __qlcnic_dcb_attach(struct qlcnic_adapter *); | 48 | static int __qlcnic_dcb_attach(struct qlcnic_adapter *); |
@@ -22,8 +50,12 @@ static int __qlcnic_dcb_query_hw_capability(struct qlcnic_adapter *, char *); | |||
22 | static void __qlcnic_dcb_get_info(struct qlcnic_adapter *); | 50 | static void __qlcnic_dcb_get_info(struct qlcnic_adapter *); |
23 | 51 | ||
24 | static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_adapter *); | 52 | static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_adapter *); |
53 | static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_adapter *, char *, u8); | ||
54 | static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_adapter *); | ||
25 | 55 | ||
26 | static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *); | 56 | static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *); |
57 | static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_adapter *, char *, u8); | ||
58 | static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_adapter *); | ||
27 | 59 | ||
28 | struct qlcnic_dcb_capability { | 60 | struct qlcnic_dcb_capability { |
29 | bool tsa_capability; | 61 | bool tsa_capability; |
@@ -34,6 +66,28 @@ struct qlcnic_dcb_capability { | |||
34 | u8 dcb_capability; | 66 | u8 dcb_capability; |
35 | }; | 67 | }; |
36 | 68 | ||
69 | struct qlcnic_dcb_param { | ||
70 | u32 hdr_prio_pfc_map[2]; | ||
71 | u32 prio_pg_map[2]; | ||
72 | u32 pg_bw_map[2]; | ||
73 | u32 pg_tsa_map[2]; | ||
74 | u32 app[QLC_DCB_MAX_APP]; | ||
75 | }; | ||
76 | |||
77 | struct qlcnic_dcb_mbx_params { | ||
78 | /* 1st local, 2nd operational 3rd remote */ | ||
79 | struct qlcnic_dcb_param type[3]; | ||
80 | u32 prio_tc_map; | ||
81 | }; | ||
82 | |||
83 | struct qlcnic_82xx_dcb_param_mbx_le { | ||
84 | __le32 hdr_prio_pfc_map[2]; | ||
85 | __le32 prio_pg_map[2]; | ||
86 | __le32 pg_bw_map[2]; | ||
87 | __le32 pg_tsa_map[2]; | ||
88 | __le32 app[QLC_DCB_MAX_APP]; | ||
89 | }; | ||
90 | |||
37 | struct qlcnic_dcb_cfg { | 91 | struct qlcnic_dcb_cfg { |
38 | struct qlcnic_dcb_capability capability; | 92 | struct qlcnic_dcb_capability capability; |
39 | u32 version; | 93 | u32 version; |
@@ -46,6 +100,8 @@ static struct qlcnic_dcb_ops qlcnic_83xx_dcb_ops = { | |||
46 | .get_info = __qlcnic_dcb_get_info, | 100 | .get_info = __qlcnic_dcb_get_info, |
47 | 101 | ||
48 | .get_hw_capability = qlcnic_83xx_dcb_get_hw_capability, | 102 | .get_hw_capability = qlcnic_83xx_dcb_get_hw_capability, |
103 | .query_cee_param = qlcnic_83xx_dcb_query_cee_param, | ||
104 | .get_cee_cfg = qlcnic_83xx_dcb_get_cee_cfg, | ||
49 | }; | 105 | }; |
50 | 106 | ||
51 | static struct qlcnic_dcb_ops qlcnic_82xx_dcb_ops = { | 107 | static struct qlcnic_dcb_ops qlcnic_82xx_dcb_ops = { |
@@ -55,8 +111,18 @@ static struct qlcnic_dcb_ops qlcnic_82xx_dcb_ops = { | |||
55 | .get_info = __qlcnic_dcb_get_info, | 111 | .get_info = __qlcnic_dcb_get_info, |
56 | 112 | ||
57 | .get_hw_capability = qlcnic_82xx_dcb_get_hw_capability, | 113 | .get_hw_capability = qlcnic_82xx_dcb_get_hw_capability, |
114 | .query_cee_param = qlcnic_82xx_dcb_query_cee_param, | ||
115 | .get_cee_cfg = qlcnic_82xx_dcb_get_cee_cfg, | ||
58 | }; | 116 | }; |
59 | 117 | ||
118 | static u8 qlcnic_dcb_get_num_app(struct qlcnic_adapter *adapter, u32 val) | ||
119 | { | ||
120 | if (qlcnic_82xx_check(adapter)) | ||
121 | return QLC_82XX_DCB_GET_NUMAPP(val); | ||
122 | else | ||
123 | return QLC_83XX_DCB_GET_NUMAPP(val); | ||
124 | } | ||
125 | |||
60 | void qlcnic_set_dcb_ops(struct qlcnic_adapter *adapter) | 126 | void qlcnic_set_dcb_ops(struct qlcnic_adapter *adapter) |
61 | { | 127 | { |
62 | if (qlcnic_82xx_check(adapter)) | 128 | if (qlcnic_82xx_check(adapter)) |
@@ -88,6 +154,8 @@ static void __qlcnic_dcb_free(struct qlcnic_adapter *adapter) | |||
88 | 154 | ||
89 | kfree(dcb->cfg); | 155 | kfree(dcb->cfg); |
90 | dcb->cfg = NULL; | 156 | dcb->cfg = NULL; |
157 | kfree(dcb->param); | ||
158 | dcb->param = NULL; | ||
91 | kfree(dcb); | 159 | kfree(dcb); |
92 | adapter->dcb = NULL; | 160 | adapter->dcb = NULL; |
93 | } | 161 | } |
@@ -95,19 +163,32 @@ static void __qlcnic_dcb_free(struct qlcnic_adapter *adapter) | |||
95 | static void __qlcnic_dcb_get_info(struct qlcnic_adapter *adapter) | 163 | static void __qlcnic_dcb_get_info(struct qlcnic_adapter *adapter) |
96 | { | 164 | { |
97 | qlcnic_dcb_get_hw_capability(adapter); | 165 | qlcnic_dcb_get_hw_capability(adapter); |
166 | qlcnic_dcb_get_cee_cfg(adapter); | ||
98 | } | 167 | } |
99 | 168 | ||
100 | static int __qlcnic_dcb_attach(struct qlcnic_adapter *adapter) | 169 | static int __qlcnic_dcb_attach(struct qlcnic_adapter *adapter) |
101 | { | 170 | { |
102 | struct qlcnic_dcb *dcb = adapter->dcb; | 171 | struct qlcnic_dcb *dcb = adapter->dcb; |
172 | int err = 0; | ||
103 | 173 | ||
104 | dcb->cfg = kzalloc(sizeof(struct qlcnic_dcb_cfg), GFP_ATOMIC); | 174 | dcb->cfg = kzalloc(sizeof(struct qlcnic_dcb_cfg), GFP_ATOMIC); |
105 | if (!dcb->cfg) | 175 | if (!dcb->cfg) |
106 | return -ENOMEM; | 176 | return -ENOMEM; |
107 | 177 | ||
178 | dcb->param = kzalloc(sizeof(struct qlcnic_dcb_mbx_params), GFP_ATOMIC); | ||
179 | if (!dcb->param) { | ||
180 | err = -ENOMEM; | ||
181 | goto out_free_cfg; | ||
182 | } | ||
183 | |||
108 | qlcnic_dcb_get_info(adapter); | 184 | qlcnic_dcb_get_info(adapter); |
109 | 185 | ||
110 | return 0; | 186 | return 0; |
187 | out_free_cfg: | ||
188 | kfree(dcb->cfg); | ||
189 | dcb->cfg = NULL; | ||
190 | |||
191 | return err; | ||
111 | } | 192 | } |
112 | 193 | ||
113 | static int __qlcnic_dcb_query_hw_capability(struct qlcnic_adapter *adapter, | 194 | static int __qlcnic_dcb_query_hw_capability(struct qlcnic_adapter *adapter, |
@@ -189,6 +270,104 @@ static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_adapter *adapter) | |||
189 | return err; | 270 | return err; |
190 | } | 271 | } |
191 | 272 | ||
273 | static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_adapter *adapter, | ||
274 | char *buf, u8 type) | ||
275 | { | ||
276 | u16 size = sizeof(struct qlcnic_82xx_dcb_param_mbx_le); | ||
277 | struct qlcnic_82xx_dcb_param_mbx_le *prsp_le; | ||
278 | struct device *dev = &adapter->pdev->dev; | ||
279 | dma_addr_t cardrsp_phys_addr; | ||
280 | struct qlcnic_dcb_param rsp; | ||
281 | struct qlcnic_cmd_args cmd; | ||
282 | u64 phys_addr; | ||
283 | void *addr; | ||
284 | int err, i; | ||
285 | |||
286 | switch (type) { | ||
287 | case QLC_DCB_LOCAL_PARAM_FWID: | ||
288 | case QLC_DCB_OPER_PARAM_FWID: | ||
289 | case QLC_DCB_PEER_PARAM_FWID: | ||
290 | break; | ||
291 | default: | ||
292 | dev_err(dev, "Invalid parameter type %d\n", type); | ||
293 | return -EINVAL; | ||
294 | } | ||
295 | |||
296 | addr = dma_alloc_coherent(&adapter->pdev->dev, size, &cardrsp_phys_addr, | ||
297 | GFP_KERNEL); | ||
298 | if (addr == NULL) | ||
299 | return -ENOMEM; | ||
300 | |||
301 | prsp_le = addr; | ||
302 | |||
303 | err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_PARAM); | ||
304 | if (err) | ||
305 | goto out_free_rsp; | ||
306 | |||
307 | phys_addr = cardrsp_phys_addr; | ||
308 | cmd.req.arg[1] = size | (type << 16); | ||
309 | cmd.req.arg[2] = MSD(phys_addr); | ||
310 | cmd.req.arg[3] = LSD(phys_addr); | ||
311 | |||
312 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
313 | if (err) { | ||
314 | dev_err(dev, "Failed to query DCBX parameter, err %d\n", err); | ||
315 | goto out; | ||
316 | } | ||
317 | |||
318 | memset(&rsp, 0, sizeof(struct qlcnic_dcb_param)); | ||
319 | rsp.hdr_prio_pfc_map[0] = le32_to_cpu(prsp_le->hdr_prio_pfc_map[0]); | ||
320 | rsp.hdr_prio_pfc_map[1] = le32_to_cpu(prsp_le->hdr_prio_pfc_map[1]); | ||
321 | rsp.prio_pg_map[0] = le32_to_cpu(prsp_le->prio_pg_map[0]); | ||
322 | rsp.prio_pg_map[1] = le32_to_cpu(prsp_le->prio_pg_map[1]); | ||
323 | rsp.pg_bw_map[0] = le32_to_cpu(prsp_le->pg_bw_map[0]); | ||
324 | rsp.pg_bw_map[1] = le32_to_cpu(prsp_le->pg_bw_map[1]); | ||
325 | rsp.pg_tsa_map[0] = le32_to_cpu(prsp_le->pg_tsa_map[0]); | ||
326 | rsp.pg_tsa_map[1] = le32_to_cpu(prsp_le->pg_tsa_map[1]); | ||
327 | |||
328 | for (i = 0; i < QLC_DCB_MAX_APP; i++) | ||
329 | rsp.app[i] = le32_to_cpu(prsp_le->app[i]); | ||
330 | |||
331 | if (buf) | ||
332 | memcpy(buf, &rsp, size); | ||
333 | out: | ||
334 | qlcnic_free_mbx_args(&cmd); | ||
335 | |||
336 | out_free_rsp: | ||
337 | dma_free_coherent(&adapter->pdev->dev, size, addr, cardrsp_phys_addr); | ||
338 | |||
339 | return err; | ||
340 | } | ||
341 | |||
342 | static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_adapter *adapter) | ||
343 | { | ||
344 | struct qlcnic_dcb_mbx_params *mbx; | ||
345 | int err; | ||
346 | |||
347 | mbx = adapter->dcb->param; | ||
348 | if (!mbx) | ||
349 | return 0; | ||
350 | |||
351 | err = qlcnic_dcb_query_cee_param(adapter, (char *)&mbx->type[0], | ||
352 | QLC_DCB_LOCAL_PARAM_FWID); | ||
353 | if (err) | ||
354 | return err; | ||
355 | |||
356 | err = qlcnic_dcb_query_cee_param(adapter, (char *)&mbx->type[1], | ||
357 | QLC_DCB_OPER_PARAM_FWID); | ||
358 | if (err) | ||
359 | return err; | ||
360 | |||
361 | err = qlcnic_dcb_query_cee_param(adapter, (char *)&mbx->type[2], | ||
362 | QLC_DCB_PEER_PARAM_FWID); | ||
363 | if (err) | ||
364 | return err; | ||
365 | |||
366 | mbx->prio_tc_map = QLC_82XX_DCB_PRIO_TC_MAP; | ||
367 | |||
368 | return err; | ||
369 | } | ||
370 | |||
192 | static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *adapter) | 371 | static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *adapter) |
193 | { | 372 | { |
194 | struct qlcnic_dcb_capability *cap = &adapter->dcb->cfg->capability; | 373 | struct qlcnic_dcb_capability *cap = &adapter->dcb->cfg->capability; |
@@ -211,3 +390,72 @@ static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *adapter) | |||
211 | 390 | ||
212 | return err; | 391 | return err; |
213 | } | 392 | } |
393 | |||
394 | static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_adapter *adapter, | ||
395 | char *buf, u8 idx) | ||
396 | { | ||
397 | struct qlcnic_dcb_mbx_params mbx_out; | ||
398 | int err, i, j, k, max_app, size; | ||
399 | struct qlcnic_dcb_param *each; | ||
400 | struct qlcnic_cmd_args cmd; | ||
401 | u32 val; | ||
402 | char *p; | ||
403 | |||
404 | size = 0; | ||
405 | memset(&mbx_out, 0, sizeof(struct qlcnic_dcb_mbx_params)); | ||
406 | memset(buf, 0, sizeof(struct qlcnic_dcb_mbx_params)); | ||
407 | |||
408 | err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_PARAM); | ||
409 | if (err) | ||
410 | return err; | ||
411 | |||
412 | cmd.req.arg[0] |= QLC_DCB_FW_VER << 29; | ||
413 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
414 | if (err) { | ||
415 | dev_err(&adapter->pdev->dev, | ||
416 | "Failed to query DCBX param, err %d\n", err); | ||
417 | goto out; | ||
418 | } | ||
419 | |||
420 | mbx_out.prio_tc_map = cmd.rsp.arg[1]; | ||
421 | p = memcpy(buf, &mbx_out, sizeof(u32)); | ||
422 | k = 2; | ||
423 | p += sizeof(u32); | ||
424 | |||
425 | for (j = 0; j < QLC_DCB_NUM_PARAM; j++) { | ||
426 | each = &mbx_out.type[j]; | ||
427 | |||
428 | each->hdr_prio_pfc_map[0] = cmd.rsp.arg[k++]; | ||
429 | each->hdr_prio_pfc_map[1] = cmd.rsp.arg[k++]; | ||
430 | each->prio_pg_map[0] = cmd.rsp.arg[k++]; | ||
431 | each->prio_pg_map[1] = cmd.rsp.arg[k++]; | ||
432 | each->pg_bw_map[0] = cmd.rsp.arg[k++]; | ||
433 | each->pg_bw_map[1] = cmd.rsp.arg[k++]; | ||
434 | each->pg_tsa_map[0] = cmd.rsp.arg[k++]; | ||
435 | each->pg_tsa_map[1] = cmd.rsp.arg[k++]; | ||
436 | val = each->hdr_prio_pfc_map[0]; | ||
437 | |||
438 | max_app = qlcnic_dcb_get_num_app(adapter, val); | ||
439 | for (i = 0; i < max_app; i++) | ||
440 | each->app[i] = cmd.rsp.arg[i + k]; | ||
441 | |||
442 | size = 16 * sizeof(u32); | ||
443 | memcpy(p, &each->hdr_prio_pfc_map[0], size); | ||
444 | p += size; | ||
445 | if (j == 0) | ||
446 | k = 18; | ||
447 | else | ||
448 | k = 34; | ||
449 | } | ||
450 | out: | ||
451 | qlcnic_free_mbx_args(&cmd); | ||
452 | |||
453 | return err; | ||
454 | } | ||
455 | |||
456 | static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_adapter *adapter) | ||
457 | { | ||
458 | struct qlcnic_dcb *dcb = adapter->dcb; | ||
459 | |||
460 | return qlcnic_dcb_query_cee_param(adapter, (char *)dcb->param, 0); | ||
461 | } | ||