Deleted Added
full compact
1/*
2 * Copyright (c) 2017-2018 Cavium, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28
29/*
30 * File: qlnx_ioctl.c
31 * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: head/sys/dev/qlnx/qlnxe/qlnx_ioctl.c 316485 2017-04-04 06:16:59Z davidcs $");
35__FBSDID("$FreeBSD: stable/11/sys/dev/qlnx/qlnxe/qlnx_ioctl.c 316485 2017-04-04 06:16:59Z davidcs $");
36
37#include "qlnx_os.h"
38#include "bcm_osal.h"
39
40#include "reg_addr.h"
41#include "ecore_gtt_reg_addr.h"
42#include "ecore.h"
43#include "ecore_chain.h"
44#include "ecore_status.h"
45#include "ecore_hw.h"
46#include "ecore_rt_defs.h"
47#include "ecore_init_ops.h"
48#include "ecore_int.h"
49#include "ecore_cxt.h"
50#include "ecore_spq.h"
51#include "ecore_init_fw_funcs.h"
52#include "ecore_sp_commands.h"
53#include "ecore_dev_api.h"
54#include "ecore_l2_api.h"
55#include "ecore_mcp.h"
56#include "ecore_hw_defs.h"
57#include "mcp_public.h"
58#include "ecore_iro.h"
59#include "nvm_cfg.h"
60#include "ecore_dev_api.h"
61#include "ecore_dbg_fw_funcs.h"
62
63#include "qlnx_ioctl.h"
64#include "qlnx_def.h"
65#include "qlnx_ver.h"
66#include <sys/smp.h>
67
68
69static int qlnx_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
70 struct thread *td);
71
72static struct cdevsw qlnx_cdevsw = {
73 .d_version = D_VERSION,
74 .d_ioctl = qlnx_eioctl,
75 .d_name = "qlnxioctl",
76};
77
78int
79qlnx_make_cdev(qlnx_host_t *ha)
80{
81 ha->ioctl_dev = make_dev(&qlnx_cdevsw,
82 ha->ifp->if_dunit,
83 UID_ROOT,
84 GID_WHEEL,
85 0600,
86 "%s",
87 if_name(ha->ifp));
88
89 if (ha->ioctl_dev == NULL)
90 return (-1);
91
92 ha->ioctl_dev->si_drv1 = ha;
93
94 return (0);
95}
96
97void
98qlnx_del_cdev(qlnx_host_t *ha)
99{
100 if (ha->ioctl_dev != NULL)
101 destroy_dev(ha->ioctl_dev);
102 return;
103}
104
105int
106qlnx_grc_dump(qlnx_host_t *ha, uint32_t *num_dumped_dwords, int hwfn_index)
107{
108 int rval = EINVAL;
109 struct ecore_hwfn *p_hwfn;
110 struct ecore_ptt *p_ptt;
111
112 if (ha->grcdump_dwords[hwfn_index]) {
113 /* the grcdump is already available */
114 *num_dumped_dwords = ha->grcdump_dwords[hwfn_index];
115 return (0);
116 }
117
118 ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver());
119
120 p_hwfn = &ha->cdev.hwfns[hwfn_index];
121 p_ptt = ecore_ptt_acquire(p_hwfn);
122
123 if (!p_ptt) {
124 QL_DPRINT1(ha, (ha->pci_dev, "%s : ecore_ptt_acquire failed\n",
125 __func__));
126 return (rval);
127 }
128
129 if ((rval = ecore_dbg_grc_dump(p_hwfn, p_ptt,
130 ha->grcdump[hwfn_index],
131 (ha->grcdump_size[hwfn_index] >> 2),
132 num_dumped_dwords)) == DBG_STATUS_OK) {
133 rval = 0;
134 ha->grcdump_taken = 1;
135 } else
136 QL_DPRINT1(ha, (ha->pci_dev,
137 "%s : ecore_dbg_grc_dump failed [%d, 0x%x]\n",
138 __func__, hwfn_index, rval));
139
140 ecore_ptt_release(p_hwfn, p_ptt);
141
142 return (rval);
143}
144
145static void
146qlnx_get_grc_dump_size(qlnx_host_t *ha, qlnx_grcdump_t *grcdump)
147{
148 int i;
149
150 grcdump->pci_func = ha->pci_func;
151
152 for (i = 0; i < ha->cdev.num_hwfns; i++)
153 grcdump->grcdump_size[i] = ha->grcdump_size[i];
154
155 return;
156}
157
158static int
159qlnx_get_grc_dump(qlnx_host_t *ha, qlnx_grcdump_t *grcdump)
160{
161 int i;
162 int rval = 0;
163 uint32_t dwords = 0;
164
165 grcdump->pci_func = ha->pci_func;
166
167 for (i = 0; i < ha->cdev.num_hwfns; i++) {
168
169 if ((ha->grcdump[i] == NULL) || (grcdump->grcdump[i] == NULL) ||
170 (grcdump->grcdump_size[i] < ha->grcdump_size[i]))
171 return (EINVAL);
172
173 rval = qlnx_grc_dump(ha, &dwords, i);
174
175 if (rval)
176 break;
177
178 grcdump->grcdump_dwords[i] = dwords;
179
180 QL_DPRINT1(ha, (ha->pci_dev, "%s: grcdump_dwords[%d] = 0x%x\n",
181 __func__, i, dwords));
182
183 rval = copyout(ha->grcdump[i], grcdump->grcdump[i],
184 ha->grcdump_size[i]);
185
186 if (rval)
187 break;
188
189 ha->grcdump_dwords[i] = 0;
190 }
191
192 ha->grcdump_taken = 0;
193
194 return (rval);
195}
196
197int
198qlnx_idle_chk(qlnx_host_t *ha, uint32_t *num_dumped_dwords, int hwfn_index)
199{
200 int rval = EINVAL;
201 struct ecore_hwfn *p_hwfn;
202 struct ecore_ptt *p_ptt;
203
204 if (ha->idle_chk_dwords[hwfn_index]) {
205 /* the idle check is already available */
206 *num_dumped_dwords = ha->idle_chk_dwords[hwfn_index];
207 return (0);
208 }
209
210 ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver());
211
212 p_hwfn = &ha->cdev.hwfns[hwfn_index];
213 p_ptt = ecore_ptt_acquire(p_hwfn);
214
215 if (!p_ptt) {
216 QL_DPRINT1(ha, (ha->pci_dev,
217 "%s : ecore_ptt_acquire failed\n", __func__));
218 return (rval);
219 }
220
221 if ((rval = ecore_dbg_idle_chk_dump(p_hwfn, p_ptt,
222 ha->idle_chk[hwfn_index],
223 (ha->idle_chk_size[hwfn_index] >> 2),
224 num_dumped_dwords)) == DBG_STATUS_OK) {
225 rval = 0;
226 ha->idle_chk_taken = 1;
227 } else
228 QL_DPRINT1(ha, (ha->pci_dev,
229 "%s : ecore_dbg_idle_chk_dump failed [%d, 0x%x]\n",
230 __func__, hwfn_index, rval));
231
232 ecore_ptt_release(p_hwfn, p_ptt);
233
234 return (rval);
235}
236
237static void
238qlnx_get_idle_chk_size(qlnx_host_t *ha, qlnx_idle_chk_t *idle_chk)
239{
240 int i;
241
242 idle_chk->pci_func = ha->pci_func;
243
244 for (i = 0; i < ha->cdev.num_hwfns; i++)
245 idle_chk->idle_chk_size[i] = ha->idle_chk_size[i];
246
247 return;
248}
249
250static int
251qlnx_get_idle_chk(qlnx_host_t *ha, qlnx_idle_chk_t *idle_chk)
252{
253 int i;
254 int rval = 0;
255 uint32_t dwords = 0;
256
257 idle_chk->pci_func = ha->pci_func;
258
259 for (i = 0; i < ha->cdev.num_hwfns; i++) {
260
261 if ((ha->idle_chk[i] == NULL) ||
262 (idle_chk->idle_chk[i] == NULL) ||
263 (idle_chk->idle_chk_size[i] <
264 ha->idle_chk_size[i]))
265 return (EINVAL);
266
267 rval = qlnx_idle_chk(ha, &dwords, i);
268
269 if (rval)
270 break;
271
272 idle_chk->idle_chk_dwords[i] = dwords;
273
274 QL_DPRINT1(ha, (ha->pci_dev, "%s: idle_chk_dwords[%d] = 0x%x\n",
275 __func__, i, dwords));
276
277 rval = copyout(ha->idle_chk[i], idle_chk->idle_chk[i],
278 ha->idle_chk_size[i]);
279
280 if (rval)
281 break;
282
283 ha->idle_chk_dwords[i] = 0;
284 }
285 ha->idle_chk_taken = 0;
286
287 return (rval);
288}
289
290static uint32_t
291qlnx_get_trace_cmd_size(qlnx_host_t *ha, int hwfn_index, uint16_t cmd)
292{
293 int rval = -1;
294 struct ecore_hwfn *p_hwfn;
295 struct ecore_ptt *p_ptt;
296 uint32_t num_dwords = 0;
297
298 p_hwfn = &ha->cdev.hwfns[hwfn_index];
299 p_ptt = ecore_ptt_acquire(p_hwfn);
300
301 if (!p_ptt) {
302 QL_DPRINT1(ha, (ha->pci_dev,
303 "%s: ecore_ptt_acquire [%d, 0x%x]failed\n",
304 __func__, hwfn_index, cmd));
305 return (0);
306 }
307
308 switch (cmd) {
309
310 case QLNX_MCP_TRACE:
311 rval = ecore_dbg_mcp_trace_get_dump_buf_size(p_hwfn,
312 p_ptt, &num_dwords);
313 break;
314
315 case QLNX_REG_FIFO:
316 rval = ecore_dbg_reg_fifo_get_dump_buf_size(p_hwfn,
317 p_ptt, &num_dwords);
318 break;
319
320 case QLNX_IGU_FIFO:
321 rval = ecore_dbg_igu_fifo_get_dump_buf_size(p_hwfn,
322 p_ptt, &num_dwords);
323 break;
324
325 case QLNX_PROTECTION_OVERRIDE:
326 rval = ecore_dbg_protection_override_get_dump_buf_size(p_hwfn,
327 p_ptt, &num_dwords);
328 break;
329
330 case QLNX_FW_ASSERTS:
331 rval = ecore_dbg_fw_asserts_get_dump_buf_size(p_hwfn,
332 p_ptt, &num_dwords);
333 break;
334 }
335
336 if (rval != DBG_STATUS_OK) {
337 QL_DPRINT1(ha, (ha->pci_dev, "%s : cmd = 0x%x failed [0x%x]\n",
338 __func__, cmd, rval));
339 num_dwords = 0;
340 }
341
342 ecore_ptt_release(p_hwfn, p_ptt);
343
344 return ((num_dwords * sizeof (uint32_t)));
345}
346
347static void
348qlnx_get_trace_size(qlnx_host_t *ha, qlnx_trace_t *trace)
349{
350 int i;
351
352 trace->pci_func = ha->pci_func;
353
354 for (i = 0; i < ha->cdev.num_hwfns; i++) {
355 trace->size[i] = qlnx_get_trace_cmd_size(ha, i, trace->cmd);
356 }
357
358 return;
359}
360
361static int
362qlnx_get_trace(qlnx_host_t *ha, int hwfn_index, qlnx_trace_t *trace)
363{
364 int rval = -1;
365 struct ecore_hwfn *p_hwfn;
366 struct ecore_ptt *p_ptt;
367 uint32_t num_dwords = 0;
368 void *buffer;
369
370 buffer = qlnx_zalloc(trace->size[hwfn_index]);
371 if (buffer == NULL) {
372 QL_DPRINT1(ha, (ha->pci_dev,
373 "%s: qlnx_zalloc [%d, 0x%x]failed\n",
374 __func__, hwfn_index, trace->cmd));
375 return (ENXIO);
376 }
377 ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver());
378
379 p_hwfn = &ha->cdev.hwfns[hwfn_index];
380 p_ptt = ecore_ptt_acquire(p_hwfn);
381
382 if (!p_ptt) {
383 QL_DPRINT1(ha, (ha->pci_dev,
384 "%s: ecore_ptt_acquire [%d, 0x%x]failed\n",
385 __func__, hwfn_index, trace->cmd));
386 return (ENXIO);
387 }
388
389 switch (trace->cmd) {
390
391 case QLNX_MCP_TRACE:
392 rval = ecore_dbg_mcp_trace_dump(p_hwfn, p_ptt,
393 buffer, (trace->size[hwfn_index] >> 2),
394 &num_dwords);
395 break;
396
397 case QLNX_REG_FIFO:
398 rval = ecore_dbg_reg_fifo_dump(p_hwfn, p_ptt,
399 buffer, (trace->size[hwfn_index] >> 2),
400 &num_dwords);
401 break;
402
403 case QLNX_IGU_FIFO:
404 rval = ecore_dbg_igu_fifo_dump(p_hwfn, p_ptt,
405 buffer, (trace->size[hwfn_index] >> 2),
406 &num_dwords);
407 break;
408
409 case QLNX_PROTECTION_OVERRIDE:
410 rval = ecore_dbg_protection_override_dump(p_hwfn, p_ptt,
411 buffer, (trace->size[hwfn_index] >> 2),
412 &num_dwords);
413 break;
414
415 case QLNX_FW_ASSERTS:
416 rval = ecore_dbg_fw_asserts_dump(p_hwfn, p_ptt,
417 buffer, (trace->size[hwfn_index] >> 2),
418 &num_dwords);
419 break;
420 }
421
422 if (rval != DBG_STATUS_OK) {
423 QL_DPRINT1(ha, (ha->pci_dev, "%s : cmd = 0x%x failed [0x%x]\n",
424 __func__, trace->cmd, rval));
425 num_dwords = 0;
426 }
427
428 ecore_ptt_release(p_hwfn, p_ptt);
429
430 trace->dwords[hwfn_index] = num_dwords;
431
432 if (num_dwords) {
433 rval = copyout(buffer, trace->buffer[hwfn_index],
434 (num_dwords << 2));
435 }
436
437 return (rval);
438}
439
440static int
441qlnx_reg_rd_wr(qlnx_host_t *ha, qlnx_reg_rd_wr_t *reg_rd_wr)
442{
443 int rval = 0;
444 struct ecore_hwfn *p_hwfn;
445
446 if (reg_rd_wr->hwfn_index >= QLNX_MAX_HW_FUNCS) {
447 return (EINVAL);
448 }
449
450 p_hwfn = &ha->cdev.hwfns[reg_rd_wr->hwfn_index];
451
452 switch (reg_rd_wr->cmd) {
453
454 case QLNX_REG_READ_CMD:
455 if (reg_rd_wr->access_type == QLNX_REG_ACCESS_DIRECT) {
456 reg_rd_wr->val = qlnx_reg_rd32(p_hwfn,
457 reg_rd_wr->addr);
458 }
459 break;
460
461 case QLNX_REG_WRITE_CMD:
462 if (reg_rd_wr->access_type == QLNX_REG_ACCESS_DIRECT) {
463 qlnx_reg_wr32(p_hwfn, reg_rd_wr->addr,
464 reg_rd_wr->val);
465 }
466 break;
467
468 default:
469 rval = EINVAL;
470 break;
471 }
472
473 return (rval);
474}
475
476static int
477qlnx_rd_wr_pci_config(qlnx_host_t *ha, qlnx_pcicfg_rd_wr_t *pci_cfg_rd_wr)
478{
479 int rval = 0;
480
481 switch (pci_cfg_rd_wr->cmd) {
482
483 case QLNX_PCICFG_READ:
484 pci_cfg_rd_wr->val = pci_read_config(ha->pci_dev,
485 pci_cfg_rd_wr->reg,
486 pci_cfg_rd_wr->width);
487 break;
488
489 case QLNX_PCICFG_WRITE:
490 pci_write_config(ha->pci_dev, pci_cfg_rd_wr->reg,
491 pci_cfg_rd_wr->val, pci_cfg_rd_wr->width);
492 break;
493
494 default:
495 rval = EINVAL;
496 break;
497 }
498
499 return (rval);
500}
501
502static void
503qlnx_mac_addr(qlnx_host_t *ha, qlnx_perm_mac_addr_t *mac_addr)
504{
505 bzero(mac_addr->addr, sizeof(mac_addr->addr));
506 snprintf(mac_addr->addr, sizeof(mac_addr->addr),
507 "%02x:%02x:%02x:%02x:%02x:%02x",
508 ha->primary_mac[0], ha->primary_mac[1], ha->primary_mac[2],
509 ha->primary_mac[3], ha->primary_mac[4], ha->primary_mac[5]);
510
511 return;
512}
513
514static int
515qlnx_get_regs(qlnx_host_t *ha, qlnx_get_regs_t *regs)
516{
517 int i;
518 int rval = 0;
519 uint32_t dwords = 0;
520 uint8_t *outb;
521
522 regs->reg_buf_len = 0;
523 outb = regs->reg_buf;
524
525 for (i = 0; i < ha->cdev.num_hwfns; i++) {
526
527 rval = qlnx_grc_dump(ha, &dwords, i);
528
529 if (rval)
530 break;
531
532 regs->reg_buf_len += (dwords << 2);
533
534 rval = copyout(ha->grcdump[i], outb, ha->grcdump_size[i]);
535
536 if (rval)
537 break;
538
539 ha->grcdump_dwords[i] = 0;
540 outb += regs->reg_buf_len;
541 }
542
543 ha->grcdump_taken = 0;
544
545 return (rval);
546}
547
548static int
549qlnx_drv_info(qlnx_host_t *ha, qlnx_drvinfo_t *drv_info)
550{
551 int i;
552 extern char qlnx_name_str[];
553 extern char qlnx_ver_str[];
554
555 bzero(drv_info, sizeof(qlnx_drvinfo_t));
556
557 snprintf(drv_info->drv_name, sizeof(drv_info->drv_name), "%s",
558 qlnx_name_str);
559 snprintf(drv_info->drv_version, sizeof(drv_info->drv_version), "%s",
560 qlnx_ver_str);
561 snprintf(drv_info->mfw_version, sizeof(drv_info->mfw_version), "%s",
562 ha->mfw_ver);
563 snprintf(drv_info->stormfw_version, sizeof(drv_info->stormfw_version),
564 "%s", ha->stormfw_ver);
565
566 drv_info->eeprom_dump_len = ha->flash_size;
567
568 for (i = 0; i < ha->cdev.num_hwfns; i++) {
569 drv_info->reg_dump_len += ha->grcdump_size[i];
570 }
571
572 snprintf(drv_info->bus_info, sizeof(drv_info->bus_info),
573 "%d:%d:%d", pci_get_bus(ha->pci_dev),
574 pci_get_slot(ha->pci_dev), ha->pci_func);
575
576 return (0);
577}
578
579static int
580qlnx_dev_settings(qlnx_host_t *ha, qlnx_dev_setting_t *dev_info)
581{
582 struct ecore_hwfn *p_hwfn;
583 struct qlnx_link_output if_link;
584
585 p_hwfn = &ha->cdev.hwfns[0];
586
587 qlnx_fill_link(p_hwfn, &if_link);
588
589 dev_info->supported = if_link.supported_caps;
590 dev_info->advertising = if_link.advertised_caps;
591 dev_info->speed = if_link.speed;
592 dev_info->duplex = if_link.duplex;
593 dev_info->port = ha->pci_func & 0x1;
594 dev_info->autoneg = if_link.autoneg;
595
596 return (0);
597}
598
599static int
600qlnx_write_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram, uint32_t cmd)
601{
602 uint8_t *buf;
603 int ret = 0;
604
605 if ((nvram->data == NULL) || (nvram->data_len == 0))
606 return (EINVAL);
607
608 buf = qlnx_zalloc(nvram->data_len);
609
610 ret = copyin(nvram->data, buf, nvram->data_len);
611
612 QL_DPRINT9(ha,
613 (ha->pci_dev, "%s: issue cmd = 0x%x data = %p "
614 " data_len = 0x%x ret = 0x%x exit\n", __func__,
615 cmd, nvram->data, nvram->data_len, ret));
616
617 if (ret == 0) {
618 ret = ecore_mcp_nvm_write(&ha->cdev, cmd,
619 nvram->offset, buf, nvram->data_len);
620 }
621
622 QL_DPRINT9(ha,
623 (ha->pci_dev, "%s: cmd = 0x%x data = %p "
624 " data_len = 0x%x resp = 0x%x ret = 0x%x exit\n",
625 __func__, cmd, nvram->data, nvram->data_len,
626 ha->cdev.mcp_nvm_resp, ret));
627
628 free(buf, M_QLNXBUF);
629
630 return (ret);
631}
632
633static int
634qlnx_read_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram)
635{
636 uint8_t *buf;
637 int ret = 0;
638
639 if ((nvram->data == NULL) || (nvram->data_len == 0))
640 return (EINVAL);
641
642 buf = qlnx_zalloc(nvram->data_len);
643
644 ret = ecore_mcp_nvm_read(&ha->cdev, nvram->offset, buf,
645 nvram->data_len);
646
647 QL_DPRINT9(ha, (ha->pci_dev, "%s: data = %p data_len = 0x%x "
648 " resp = 0x%x ret = 0x%x exit\n", __func__,
649 nvram->data, nvram->data_len,
650 ha->cdev.mcp_nvm_resp, ret));
651
652 if (ret == 0) {
653 ret = copyout(buf, nvram->data, nvram->data_len);
654 }
655
656 free(buf, M_QLNXBUF);
657
658 return (ret);
659}
660
661static int
662qlnx_get_nvram_resp(qlnx_host_t *ha, qlnx_nvram_t *nvram)
663{
664 uint8_t *buf;
665 int ret = 0;
666
667 if ((nvram->data == NULL) || (nvram->data_len == 0))
668 return (EINVAL);
669
670 buf = qlnx_zalloc(nvram->data_len);
671
672
673 ret = ecore_mcp_nvm_resp(&ha->cdev, buf);
674
675 QL_DPRINT9(ha, (ha->pci_dev, "%s: data = %p data_len = 0x%x "
676 " resp = 0x%x ret = 0x%x exit\n", __func__,
677 nvram->data, nvram->data_len,
678 ha->cdev.mcp_nvm_resp, ret));
679
680 if (ret == 0) {
681 ret = copyout(buf, nvram->data, nvram->data_len);
682 }
683
684 free(buf, M_QLNXBUF);
685
686 return (ret);
687}
688
689static int
690qlnx_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram)
691{
692 int ret = 0;
693
694 switch (nvram->cmd) {
695
696 case QLNX_NVRAM_CMD_WRITE_NVRAM:
697 ret = qlnx_write_nvram(ha, nvram, ECORE_NVM_WRITE_NVRAM);
698 break;
699
700 case QLNX_NVRAM_CMD_PUT_FILE_DATA:
701 ret = qlnx_write_nvram(ha, nvram, ECORE_PUT_FILE_DATA);
702 break;
703
704 case QLNX_NVRAM_CMD_READ_NVRAM:
705 ret = qlnx_read_nvram(ha, nvram);
706 break;
707
708 case QLNX_NVRAM_CMD_SET_SECURE_MODE:
709 ret = ecore_mcp_nvm_set_secure_mode(&ha->cdev, nvram->offset);
710
711 QL_DPRINT9(ha, (ha->pci_dev,
712 "%s: QLNX_NVRAM_CMD_SET_SECURE_MODE "
713 " resp = 0x%x ret = 0x%x exit\n", __func__,
714 ha->cdev.mcp_nvm_resp, ret));
715 break;
716
717 case QLNX_NVRAM_CMD_DEL_FILE:
718 ret = ecore_mcp_nvm_del_file(&ha->cdev, nvram->offset);
719
720 QL_DPRINT9(ha, (ha->pci_dev,
721 "%s: QLNX_NVRAM_CMD_DEL_FILE "
722 " resp = 0x%x ret = 0x%x exit\n", __func__,
723 ha->cdev.mcp_nvm_resp, ret));
724 break;
725
726 case QLNX_NVRAM_CMD_PUT_FILE_BEGIN:
727 ret = ecore_mcp_nvm_put_file_begin(&ha->cdev, nvram->offset);
728
729 QL_DPRINT9(ha, (ha->pci_dev,
730 "%s: QLNX_NVRAM_CMD_PUT_FILE_BEGIN "
731 " resp = 0x%x ret = 0x%x exit\n", __func__,
732 ha->cdev.mcp_nvm_resp, ret));
733 break;
734
735 case QLNX_NVRAM_CMD_GET_NVRAM_RESP:
736 ret = qlnx_get_nvram_resp(ha, nvram);
737 break;
738
739 default:
740 ret = EINVAL;
741 break;
742 }
743
744 return (ret);
745}
746
747static void
748qlnx_storm_stats(qlnx_host_t *ha, qlnx_storm_stats_dump_t *s_stats)
749{
750 int i;
751 int index;
752 int ret;
753 int stats_copied = 0;
754
755 s_stats->num_hwfns = ha->cdev.num_hwfns;
756
757// if (ha->storm_stats_index < QLNX_STORM_STATS_SAMPLES_PER_HWFN)
758// return;
759
760 s_stats->num_samples = ha->storm_stats_index;
761
762 for (i = 0; i < ha->cdev.num_hwfns; i++) {
763
764 index = (QLNX_STORM_STATS_SAMPLES_PER_HWFN * i);
765
766 if (s_stats->buffer[i]) {
767
768 ret = copyout(&ha->storm_stats[index],
769 s_stats->buffer[i],
770 QLNX_STORM_STATS_BYTES_PER_HWFN);
771 if (ret) {
772 printf("%s [%d]: failed\n", __func__, i);
773 }
774
775 if (s_stats->num_samples ==
776 QLNX_STORM_STATS_SAMPLES_PER_HWFN) {
777
778 bzero((void *)&ha->storm_stats[i],
779 QLNX_STORM_STATS_BYTES_PER_HWFN);
780
781 stats_copied = 1;
782 }
783 }
784 }
785
786 if (stats_copied)
787 ha->storm_stats_index = 0;
788
789 return;
790}
791
792
793static int
794qlnx_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
795 struct thread *td)
796{
797 qlnx_host_t *ha;
798 int rval = 0;
799 struct ifnet *ifp;
800 qlnx_trace_t *trace;
801 int i;
802
803 if ((ha = (qlnx_host_t *)dev->si_drv1) == NULL)
804 return ENXIO;
805
806 ifp = ha->ifp;
807
808 switch (cmd) {
809
810 case QLNX_GRC_DUMP_SIZE:
811 qlnx_get_grc_dump_size(ha, (qlnx_grcdump_t *)data);
812 break;
813
814 case QLNX_GRC_DUMP:
815 rval = qlnx_get_grc_dump(ha, (qlnx_grcdump_t *)data);
816 break;
817
818 case QLNX_IDLE_CHK_SIZE:
819 qlnx_get_idle_chk_size(ha, (qlnx_idle_chk_t *)data);
820 break;
821
822 case QLNX_IDLE_CHK:
823 rval = qlnx_get_idle_chk(ha, (qlnx_idle_chk_t *)data);
824 break;
825
826 case QLNX_DRV_INFO:
827 rval = qlnx_drv_info(ha, (qlnx_drvinfo_t *)data);
828 break;
829
830 case QLNX_DEV_SETTING:
831 rval = qlnx_dev_settings(ha, (qlnx_dev_setting_t *)data);
832 break;
833
834 case QLNX_GET_REGS:
835 rval = qlnx_get_regs(ha, (qlnx_get_regs_t *)data);
836 break;
837
838 case QLNX_NVRAM:
839 rval = qlnx_nvram(ha, (qlnx_nvram_t *)data);
840 break;
841
842 case QLNX_RD_WR_REG:
843 rval = qlnx_reg_rd_wr(ha, (qlnx_reg_rd_wr_t *)data);
844 break;
845
846 case QLNX_RD_WR_PCICFG:
847 rval = qlnx_rd_wr_pci_config(ha, (qlnx_pcicfg_rd_wr_t *)data);
848 break;
849
850 case QLNX_MAC_ADDR:
851 qlnx_mac_addr(ha, (qlnx_perm_mac_addr_t *)data);
852 break;
853
854 case QLNX_STORM_STATS:
855 qlnx_storm_stats(ha, (qlnx_storm_stats_dump_t *)data);
856 break;
857
858 case QLNX_TRACE_SIZE:
859 qlnx_get_trace_size(ha, (qlnx_trace_t *)data);
860 break;
861
862 case QLNX_TRACE:
863 trace = (qlnx_trace_t *)data;
864
865 for (i = 0; i < ha->cdev.num_hwfns; i++) {
866
867 if (trace->size[i] && trace->cmd && trace->buffer[i])
868 rval = qlnx_get_trace(ha, i, trace);
869
870 if (rval)
871 break;
872 }
873 break;
874
875 default:
876 rval = EINVAL;
877 break;
878 }
879
880 return (rval);
881}
882