]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/dev/qlnx/qlnxe/qlnx_ioctl.c
MFC r316485
[FreeBSD/stable/10.git] / sys / dev / qlnx / qlnxe / qlnx_ioctl.c
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$");
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
69 static int qlnx_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
70                 struct thread *td);
71
72 static struct cdevsw qlnx_cdevsw = {
73         .d_version = D_VERSION,
74         .d_ioctl = qlnx_eioctl,
75         .d_name = "qlnxioctl",
76 };
77
78 int
79 qlnx_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
97 void
98 qlnx_del_cdev(qlnx_host_t *ha)
99 {
100         if (ha->ioctl_dev != NULL)
101                 destroy_dev(ha->ioctl_dev);
102         return;
103 }
104
105 int
106 qlnx_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
145 static void
146 qlnx_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
158 static int
159 qlnx_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
197 int
198 qlnx_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
237 static void
238 qlnx_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
250 static int
251 qlnx_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
290 static uint32_t
291 qlnx_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
347 static void
348 qlnx_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
361 static int
362 qlnx_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
440 static int
441 qlnx_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
476 static int
477 qlnx_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
502 static void
503 qlnx_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
514 static int
515 qlnx_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
548 static int
549 qlnx_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
579 static int
580 qlnx_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
599 static int
600 qlnx_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
633 static int
634 qlnx_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
661 static int
662 qlnx_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
689 static int
690 qlnx_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
747 static void
748 qlnx_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
793 static int
794 qlnx_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