xref: /freebsd/sys/dev/qlnx/qlnxe/qlnx_ioctl.c (revision d576ccdf01a4c6f8f02e8ed7e72290c729d68de6)
111e25f0dSDavid C Somayajulu /*
211e25f0dSDavid C Somayajulu  * Copyright (c) 2017-2018 Cavium, Inc.
311e25f0dSDavid C Somayajulu  * All rights reserved.
411e25f0dSDavid C Somayajulu  *
511e25f0dSDavid C Somayajulu  *  Redistribution and use in source and binary forms, with or without
611e25f0dSDavid C Somayajulu  *  modification, are permitted provided that the following conditions
711e25f0dSDavid C Somayajulu  *  are met:
811e25f0dSDavid C Somayajulu  *
911e25f0dSDavid C Somayajulu  *  1. Redistributions of source code must retain the above copyright
1011e25f0dSDavid C Somayajulu  *     notice, this list of conditions and the following disclaimer.
1111e25f0dSDavid C Somayajulu  *  2. Redistributions in binary form must reproduce the above copyright
1211e25f0dSDavid C Somayajulu  *     notice, this list of conditions and the following disclaimer in the
1311e25f0dSDavid C Somayajulu  *     documentation and/or other materials provided with the distribution.
1411e25f0dSDavid C Somayajulu  *
1511e25f0dSDavid C Somayajulu  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1611e25f0dSDavid C Somayajulu  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1711e25f0dSDavid C Somayajulu  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1811e25f0dSDavid C Somayajulu  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
1911e25f0dSDavid C Somayajulu  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2011e25f0dSDavid C Somayajulu  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2111e25f0dSDavid C Somayajulu  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2211e25f0dSDavid C Somayajulu  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2311e25f0dSDavid C Somayajulu  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2411e25f0dSDavid C Somayajulu  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2511e25f0dSDavid C Somayajulu  *  POSSIBILITY OF SUCH DAMAGE.
2611e25f0dSDavid C Somayajulu  */
2711e25f0dSDavid C Somayajulu 
2811e25f0dSDavid C Somayajulu 
2911e25f0dSDavid C Somayajulu /*
3011e25f0dSDavid C Somayajulu  * File: qlnx_ioctl.c
3111e25f0dSDavid C Somayajulu  * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
3211e25f0dSDavid C Somayajulu  */
3311e25f0dSDavid C Somayajulu 
3411e25f0dSDavid C Somayajulu #include <sys/cdefs.h>
3511e25f0dSDavid C Somayajulu __FBSDID("$FreeBSD$");
3611e25f0dSDavid C Somayajulu 
3711e25f0dSDavid C Somayajulu #include "qlnx_os.h"
3811e25f0dSDavid C Somayajulu #include "bcm_osal.h"
3911e25f0dSDavid C Somayajulu 
4011e25f0dSDavid C Somayajulu #include "reg_addr.h"
4111e25f0dSDavid C Somayajulu #include "ecore_gtt_reg_addr.h"
4211e25f0dSDavid C Somayajulu #include "ecore.h"
4311e25f0dSDavid C Somayajulu #include "ecore_chain.h"
4411e25f0dSDavid C Somayajulu #include "ecore_status.h"
4511e25f0dSDavid C Somayajulu #include "ecore_hw.h"
4611e25f0dSDavid C Somayajulu #include "ecore_rt_defs.h"
4711e25f0dSDavid C Somayajulu #include "ecore_init_ops.h"
4811e25f0dSDavid C Somayajulu #include "ecore_int.h"
4911e25f0dSDavid C Somayajulu #include "ecore_cxt.h"
5011e25f0dSDavid C Somayajulu #include "ecore_spq.h"
5111e25f0dSDavid C Somayajulu #include "ecore_init_fw_funcs.h"
5211e25f0dSDavid C Somayajulu #include "ecore_sp_commands.h"
5311e25f0dSDavid C Somayajulu #include "ecore_dev_api.h"
5411e25f0dSDavid C Somayajulu #include "ecore_l2_api.h"
5511e25f0dSDavid C Somayajulu #include "ecore_mcp.h"
5611e25f0dSDavid C Somayajulu #include "ecore_hw_defs.h"
5711e25f0dSDavid C Somayajulu #include "mcp_public.h"
5811e25f0dSDavid C Somayajulu #include "ecore_iro.h"
5911e25f0dSDavid C Somayajulu #include "nvm_cfg.h"
6011e25f0dSDavid C Somayajulu #include "ecore_dev_api.h"
6111e25f0dSDavid C Somayajulu #include "ecore_dbg_fw_funcs.h"
6211e25f0dSDavid C Somayajulu 
6311e25f0dSDavid C Somayajulu #include "qlnx_ioctl.h"
6411e25f0dSDavid C Somayajulu #include "qlnx_def.h"
6511e25f0dSDavid C Somayajulu #include "qlnx_ver.h"
6611e25f0dSDavid C Somayajulu #include <sys/smp.h>
6711e25f0dSDavid C Somayajulu 
6811e25f0dSDavid C Somayajulu 
6911e25f0dSDavid C Somayajulu static int qlnx_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
7011e25f0dSDavid C Somayajulu                 struct thread *td);
7111e25f0dSDavid C Somayajulu 
7211e25f0dSDavid C Somayajulu static struct cdevsw qlnx_cdevsw = {
7311e25f0dSDavid C Somayajulu         .d_version = D_VERSION,
7411e25f0dSDavid C Somayajulu         .d_ioctl = qlnx_eioctl,
7511e25f0dSDavid C Somayajulu         .d_name = "qlnxioctl",
7611e25f0dSDavid C Somayajulu };
7711e25f0dSDavid C Somayajulu 
7811e25f0dSDavid C Somayajulu int
7911e25f0dSDavid C Somayajulu qlnx_make_cdev(qlnx_host_t *ha)
8011e25f0dSDavid C Somayajulu {
8111e25f0dSDavid C Somayajulu 	ha->ioctl_dev = make_dev(&qlnx_cdevsw,
8211e25f0dSDavid C Somayajulu 				ha->ifp->if_dunit,
8311e25f0dSDavid C Somayajulu 				UID_ROOT,
8411e25f0dSDavid C Somayajulu 				GID_WHEEL,
8511e25f0dSDavid C Somayajulu 				0600,
8611e25f0dSDavid C Somayajulu 				"%s",
8711e25f0dSDavid C Somayajulu 				if_name(ha->ifp));
8811e25f0dSDavid C Somayajulu 
8911e25f0dSDavid C Somayajulu 	if (ha->ioctl_dev == NULL)
9011e25f0dSDavid C Somayajulu 		return (-1);
9111e25f0dSDavid C Somayajulu 
9211e25f0dSDavid C Somayajulu 	ha->ioctl_dev->si_drv1 = ha;
9311e25f0dSDavid C Somayajulu 
9411e25f0dSDavid C Somayajulu 	return (0);
9511e25f0dSDavid C Somayajulu }
9611e25f0dSDavid C Somayajulu 
9711e25f0dSDavid C Somayajulu void
9811e25f0dSDavid C Somayajulu qlnx_del_cdev(qlnx_host_t *ha)
9911e25f0dSDavid C Somayajulu {
10011e25f0dSDavid C Somayajulu 	if (ha->ioctl_dev != NULL)
10111e25f0dSDavid C Somayajulu 		destroy_dev(ha->ioctl_dev);
10211e25f0dSDavid C Somayajulu 	return;
10311e25f0dSDavid C Somayajulu }
10411e25f0dSDavid C Somayajulu 
10511e25f0dSDavid C Somayajulu int
10611e25f0dSDavid C Somayajulu qlnx_grc_dump(qlnx_host_t *ha, uint32_t *num_dumped_dwords, int hwfn_index)
10711e25f0dSDavid C Somayajulu {
10811e25f0dSDavid C Somayajulu 	int rval = EINVAL;
10911e25f0dSDavid C Somayajulu 	struct ecore_hwfn *p_hwfn;
11011e25f0dSDavid C Somayajulu 	struct ecore_ptt *p_ptt;
11111e25f0dSDavid C Somayajulu 
11211e25f0dSDavid C Somayajulu 	if (ha->grcdump_dwords[hwfn_index]) {
11311e25f0dSDavid C Somayajulu 		/* the grcdump is already available */
11411e25f0dSDavid C Somayajulu 		*num_dumped_dwords = ha->grcdump_dwords[hwfn_index];
11511e25f0dSDavid C Somayajulu 		return (0);
11611e25f0dSDavid C Somayajulu 	}
11711e25f0dSDavid C Somayajulu 
11811e25f0dSDavid C Somayajulu 	ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver());
11911e25f0dSDavid C Somayajulu 
12011e25f0dSDavid C Somayajulu 	p_hwfn = &ha->cdev.hwfns[hwfn_index];
12111e25f0dSDavid C Somayajulu 	p_ptt = ecore_ptt_acquire(p_hwfn);
12211e25f0dSDavid C Somayajulu 
12311e25f0dSDavid C Somayajulu 	if (!p_ptt) {
1247a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha,"ecore_ptt_acquire failed\n");
12511e25f0dSDavid C Somayajulu 		return (rval);
12611e25f0dSDavid C Somayajulu 	}
12711e25f0dSDavid C Somayajulu 
12811e25f0dSDavid C Somayajulu 	if ((rval = ecore_dbg_grc_dump(p_hwfn, p_ptt,
12911e25f0dSDavid C Somayajulu 			ha->grcdump[hwfn_index],
13011e25f0dSDavid C Somayajulu 			(ha->grcdump_size[hwfn_index] >> 2),
13111e25f0dSDavid C Somayajulu 			num_dumped_dwords)) == DBG_STATUS_OK) {
13211e25f0dSDavid C Somayajulu 	 	rval = 0;
13311e25f0dSDavid C Somayajulu 		ha->grcdump_taken = 1;
13411e25f0dSDavid C Somayajulu 	} else
1357a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha,"ecore_dbg_grc_dump failed [%d, 0x%x]\n",
1367a377fbeSDavid C Somayajulu 			   hwfn_index, rval);
13711e25f0dSDavid C Somayajulu 
13811e25f0dSDavid C Somayajulu 	ecore_ptt_release(p_hwfn, p_ptt);
13911e25f0dSDavid C Somayajulu 
14011e25f0dSDavid C Somayajulu 	return (rval);
14111e25f0dSDavid C Somayajulu }
14211e25f0dSDavid C Somayajulu 
14311e25f0dSDavid C Somayajulu static void
14411e25f0dSDavid C Somayajulu qlnx_get_grc_dump_size(qlnx_host_t *ha, qlnx_grcdump_t *grcdump)
14511e25f0dSDavid C Somayajulu {
14611e25f0dSDavid C Somayajulu 	int i;
14711e25f0dSDavid C Somayajulu 
14811e25f0dSDavid C Somayajulu 	grcdump->pci_func = ha->pci_func;
14911e25f0dSDavid C Somayajulu 
15011e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++)
15111e25f0dSDavid C Somayajulu 		grcdump->grcdump_size[i] = ha->grcdump_size[i];
15211e25f0dSDavid C Somayajulu 
15311e25f0dSDavid C Somayajulu 	return;
15411e25f0dSDavid C Somayajulu }
15511e25f0dSDavid C Somayajulu 
15611e25f0dSDavid C Somayajulu static int
15711e25f0dSDavid C Somayajulu qlnx_get_grc_dump(qlnx_host_t *ha, qlnx_grcdump_t *grcdump)
15811e25f0dSDavid C Somayajulu {
15911e25f0dSDavid C Somayajulu 	int		i;
16011e25f0dSDavid C Somayajulu 	int		rval = 0;
16111e25f0dSDavid C Somayajulu 	uint32_t	dwords = 0;
16211e25f0dSDavid C Somayajulu 
16311e25f0dSDavid C Somayajulu 	grcdump->pci_func = ha->pci_func;
16411e25f0dSDavid C Somayajulu 
16511e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
16611e25f0dSDavid C Somayajulu 
16711e25f0dSDavid C Somayajulu 		if ((ha->grcdump[i] == NULL) || (grcdump->grcdump[i] == NULL) ||
16811e25f0dSDavid C Somayajulu 			(grcdump->grcdump_size[i] < ha->grcdump_size[i]))
16911e25f0dSDavid C Somayajulu 			return (EINVAL);
17011e25f0dSDavid C Somayajulu 
17111e25f0dSDavid C Somayajulu 		rval = qlnx_grc_dump(ha, &dwords, i);
17211e25f0dSDavid C Somayajulu 
17311e25f0dSDavid C Somayajulu 		if (rval)
17411e25f0dSDavid C Somayajulu 			break;
17511e25f0dSDavid C Somayajulu 
17611e25f0dSDavid C Somayajulu 		grcdump->grcdump_dwords[i] = dwords;
17711e25f0dSDavid C Somayajulu 
1787a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha,"grcdump_dwords[%d] = 0x%x\n", i, dwords);
17911e25f0dSDavid C Somayajulu 
18011e25f0dSDavid C Somayajulu 		rval = copyout(ha->grcdump[i], grcdump->grcdump[i],
18111e25f0dSDavid C Somayajulu 				ha->grcdump_size[i]);
18211e25f0dSDavid C Somayajulu 
18311e25f0dSDavid C Somayajulu 		if (rval)
18411e25f0dSDavid C Somayajulu 			break;
18511e25f0dSDavid C Somayajulu 
18611e25f0dSDavid C Somayajulu 		ha->grcdump_dwords[i] = 0;
18711e25f0dSDavid C Somayajulu 	}
18811e25f0dSDavid C Somayajulu 
18911e25f0dSDavid C Somayajulu 	ha->grcdump_taken = 0;
19011e25f0dSDavid C Somayajulu 
19111e25f0dSDavid C Somayajulu 	return (rval);
19211e25f0dSDavid C Somayajulu }
19311e25f0dSDavid C Somayajulu 
19411e25f0dSDavid C Somayajulu int
19511e25f0dSDavid C Somayajulu qlnx_idle_chk(qlnx_host_t *ha, uint32_t *num_dumped_dwords, int hwfn_index)
19611e25f0dSDavid C Somayajulu {
19711e25f0dSDavid C Somayajulu 	int rval = EINVAL;
19811e25f0dSDavid C Somayajulu 	struct ecore_hwfn *p_hwfn;
19911e25f0dSDavid C Somayajulu 	struct ecore_ptt *p_ptt;
20011e25f0dSDavid C Somayajulu 
20111e25f0dSDavid C Somayajulu 	if (ha->idle_chk_dwords[hwfn_index]) {
20211e25f0dSDavid C Somayajulu 		/* the idle check is already available */
20311e25f0dSDavid C Somayajulu 		*num_dumped_dwords = ha->idle_chk_dwords[hwfn_index];
20411e25f0dSDavid C Somayajulu 		return (0);
20511e25f0dSDavid C Somayajulu 	}
20611e25f0dSDavid C Somayajulu 
20711e25f0dSDavid C Somayajulu 	ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver());
20811e25f0dSDavid C Somayajulu 
20911e25f0dSDavid C Somayajulu 	p_hwfn = &ha->cdev.hwfns[hwfn_index];
21011e25f0dSDavid C Somayajulu 	p_ptt = ecore_ptt_acquire(p_hwfn);
21111e25f0dSDavid C Somayajulu 
21211e25f0dSDavid C Somayajulu 	if (!p_ptt) {
2137a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha,"ecore_ptt_acquire failed\n");
21411e25f0dSDavid C Somayajulu 		return (rval);
21511e25f0dSDavid C Somayajulu 	}
21611e25f0dSDavid C Somayajulu 
21711e25f0dSDavid C Somayajulu 	if ((rval = ecore_dbg_idle_chk_dump(p_hwfn, p_ptt,
21811e25f0dSDavid C Somayajulu 			ha->idle_chk[hwfn_index],
21911e25f0dSDavid C Somayajulu 			(ha->idle_chk_size[hwfn_index] >> 2),
22011e25f0dSDavid C Somayajulu 			num_dumped_dwords)) == DBG_STATUS_OK) {
22111e25f0dSDavid C Somayajulu 	 	rval = 0;
22211e25f0dSDavid C Somayajulu 		ha->idle_chk_taken = 1;
22311e25f0dSDavid C Somayajulu 	} else
2247a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha,"ecore_dbg_idle_chk_dump failed [%d, 0x%x]\n",
2257a377fbeSDavid C Somayajulu 			   hwfn_index, rval);
22611e25f0dSDavid C Somayajulu 
22711e25f0dSDavid C Somayajulu 	ecore_ptt_release(p_hwfn, p_ptt);
22811e25f0dSDavid C Somayajulu 
22911e25f0dSDavid C Somayajulu 	return (rval);
23011e25f0dSDavid C Somayajulu }
23111e25f0dSDavid C Somayajulu 
23211e25f0dSDavid C Somayajulu static void
23311e25f0dSDavid C Somayajulu qlnx_get_idle_chk_size(qlnx_host_t *ha, qlnx_idle_chk_t *idle_chk)
23411e25f0dSDavid C Somayajulu {
23511e25f0dSDavid C Somayajulu 	int i;
23611e25f0dSDavid C Somayajulu 
23711e25f0dSDavid C Somayajulu 	idle_chk->pci_func = ha->pci_func;
23811e25f0dSDavid C Somayajulu 
23911e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++)
24011e25f0dSDavid C Somayajulu 		idle_chk->idle_chk_size[i] = ha->idle_chk_size[i];
24111e25f0dSDavid C Somayajulu 
24211e25f0dSDavid C Somayajulu 	return;
24311e25f0dSDavid C Somayajulu }
24411e25f0dSDavid C Somayajulu 
24511e25f0dSDavid C Somayajulu static int
24611e25f0dSDavid C Somayajulu qlnx_get_idle_chk(qlnx_host_t *ha, qlnx_idle_chk_t *idle_chk)
24711e25f0dSDavid C Somayajulu {
24811e25f0dSDavid C Somayajulu 	int		i;
24911e25f0dSDavid C Somayajulu 	int		rval = 0;
25011e25f0dSDavid C Somayajulu 	uint32_t	dwords = 0;
25111e25f0dSDavid C Somayajulu 
25211e25f0dSDavid C Somayajulu 	idle_chk->pci_func = ha->pci_func;
25311e25f0dSDavid C Somayajulu 
25411e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
25511e25f0dSDavid C Somayajulu 
25611e25f0dSDavid C Somayajulu 		if ((ha->idle_chk[i] == NULL) ||
25711e25f0dSDavid C Somayajulu 				(idle_chk->idle_chk[i] == NULL) ||
25811e25f0dSDavid C Somayajulu 				(idle_chk->idle_chk_size[i] <
25911e25f0dSDavid C Somayajulu 					ha->idle_chk_size[i]))
26011e25f0dSDavid C Somayajulu 			return (EINVAL);
26111e25f0dSDavid C Somayajulu 
26211e25f0dSDavid C Somayajulu 		rval = qlnx_idle_chk(ha, &dwords, i);
26311e25f0dSDavid C Somayajulu 
26411e25f0dSDavid C Somayajulu 		if (rval)
26511e25f0dSDavid C Somayajulu 			break;
26611e25f0dSDavid C Somayajulu 
26711e25f0dSDavid C Somayajulu 		idle_chk->idle_chk_dwords[i] = dwords;
26811e25f0dSDavid C Somayajulu 
2697a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha,"idle_chk_dwords[%d] = 0x%x\n", i, dwords);
27011e25f0dSDavid C Somayajulu 
27111e25f0dSDavid C Somayajulu                	rval = copyout(ha->idle_chk[i], idle_chk->idle_chk[i],
27211e25f0dSDavid C Somayajulu 				ha->idle_chk_size[i]);
27311e25f0dSDavid C Somayajulu 
27411e25f0dSDavid C Somayajulu 		if (rval)
27511e25f0dSDavid C Somayajulu 			break;
27611e25f0dSDavid C Somayajulu 
27711e25f0dSDavid C Somayajulu 		ha->idle_chk_dwords[i] = 0;
27811e25f0dSDavid C Somayajulu 	}
27911e25f0dSDavid C Somayajulu 	ha->idle_chk_taken = 0;
28011e25f0dSDavid C Somayajulu 
28111e25f0dSDavid C Somayajulu 	return (rval);
28211e25f0dSDavid C Somayajulu }
28311e25f0dSDavid C Somayajulu 
28411e25f0dSDavid C Somayajulu static uint32_t
28511e25f0dSDavid C Somayajulu qlnx_get_trace_cmd_size(qlnx_host_t *ha, int hwfn_index, uint16_t cmd)
28611e25f0dSDavid C Somayajulu {
28711e25f0dSDavid C Somayajulu         int rval = -1;
28811e25f0dSDavid C Somayajulu         struct ecore_hwfn *p_hwfn;
28911e25f0dSDavid C Somayajulu         struct ecore_ptt *p_ptt;
29011e25f0dSDavid C Somayajulu 	uint32_t num_dwords = 0;
29111e25f0dSDavid C Somayajulu 
29211e25f0dSDavid C Somayajulu         p_hwfn = &ha->cdev.hwfns[hwfn_index];
29311e25f0dSDavid C Somayajulu         p_ptt = ecore_ptt_acquire(p_hwfn);
29411e25f0dSDavid C Somayajulu 
29511e25f0dSDavid C Somayajulu         if (!p_ptt) {
2967a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha, "ecore_ptt_acquire [%d, 0x%x]failed\n",
2977a377fbeSDavid C Somayajulu                            hwfn_index, cmd);
29811e25f0dSDavid C Somayajulu                 return (0);
29911e25f0dSDavid C Somayajulu         }
30011e25f0dSDavid C Somayajulu 
30111e25f0dSDavid C Somayajulu 	switch (cmd) {
30211e25f0dSDavid C Somayajulu 
30311e25f0dSDavid C Somayajulu 	case QLNX_MCP_TRACE:
30411e25f0dSDavid C Somayajulu         	rval = ecore_dbg_mcp_trace_get_dump_buf_size(p_hwfn,
30511e25f0dSDavid C Somayajulu 				p_ptt, &num_dwords);
30611e25f0dSDavid C Somayajulu 		break;
30711e25f0dSDavid C Somayajulu 
30811e25f0dSDavid C Somayajulu 	case QLNX_REG_FIFO:
30911e25f0dSDavid C Somayajulu         	rval = ecore_dbg_reg_fifo_get_dump_buf_size(p_hwfn,
31011e25f0dSDavid C Somayajulu 				p_ptt, &num_dwords);
31111e25f0dSDavid C Somayajulu 		break;
31211e25f0dSDavid C Somayajulu 
31311e25f0dSDavid C Somayajulu 	case QLNX_IGU_FIFO:
31411e25f0dSDavid C Somayajulu         	rval = ecore_dbg_igu_fifo_get_dump_buf_size(p_hwfn,
31511e25f0dSDavid C Somayajulu 				p_ptt, &num_dwords);
31611e25f0dSDavid C Somayajulu 		break;
31711e25f0dSDavid C Somayajulu 
31811e25f0dSDavid C Somayajulu 	case QLNX_PROTECTION_OVERRIDE:
31911e25f0dSDavid C Somayajulu         	rval = ecore_dbg_protection_override_get_dump_buf_size(p_hwfn,
32011e25f0dSDavid C Somayajulu 				p_ptt, &num_dwords);
32111e25f0dSDavid C Somayajulu 		break;
32211e25f0dSDavid C Somayajulu 
32311e25f0dSDavid C Somayajulu 	case QLNX_FW_ASSERTS:
32411e25f0dSDavid C Somayajulu         	rval = ecore_dbg_fw_asserts_get_dump_buf_size(p_hwfn,
32511e25f0dSDavid C Somayajulu 				p_ptt, &num_dwords);
32611e25f0dSDavid C Somayajulu 		break;
32711e25f0dSDavid C Somayajulu 	}
32811e25f0dSDavid C Somayajulu 
32911e25f0dSDavid C Somayajulu         if (rval != DBG_STATUS_OK) {
3307a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha,"cmd = 0x%x failed [0x%x]\n", cmd, rval);
33111e25f0dSDavid C Somayajulu 		num_dwords = 0;
33211e25f0dSDavid C Somayajulu         }
33311e25f0dSDavid C Somayajulu 
33411e25f0dSDavid C Somayajulu         ecore_ptt_release(p_hwfn, p_ptt);
33511e25f0dSDavid C Somayajulu 
33611e25f0dSDavid C Somayajulu         return ((num_dwords * sizeof (uint32_t)));
33711e25f0dSDavid C Somayajulu }
33811e25f0dSDavid C Somayajulu 
33911e25f0dSDavid C Somayajulu static void
34011e25f0dSDavid C Somayajulu qlnx_get_trace_size(qlnx_host_t *ha, qlnx_trace_t *trace)
34111e25f0dSDavid C Somayajulu {
34211e25f0dSDavid C Somayajulu 	int i;
34311e25f0dSDavid C Somayajulu 
34411e25f0dSDavid C Somayajulu 	trace->pci_func = ha->pci_func;
34511e25f0dSDavid C Somayajulu 
34611e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
34711e25f0dSDavid C Somayajulu 		trace->size[i] = qlnx_get_trace_cmd_size(ha, i, trace->cmd);
34811e25f0dSDavid C Somayajulu 	}
34911e25f0dSDavid C Somayajulu 
35011e25f0dSDavid C Somayajulu 	return;
35111e25f0dSDavid C Somayajulu }
35211e25f0dSDavid C Somayajulu 
35311e25f0dSDavid C Somayajulu static int
35411e25f0dSDavid C Somayajulu qlnx_get_trace(qlnx_host_t *ha, int hwfn_index, qlnx_trace_t *trace)
35511e25f0dSDavid C Somayajulu {
35611e25f0dSDavid C Somayajulu         int rval = -1;
35711e25f0dSDavid C Somayajulu         struct ecore_hwfn *p_hwfn;
35811e25f0dSDavid C Somayajulu         struct ecore_ptt *p_ptt;
35911e25f0dSDavid C Somayajulu 	uint32_t num_dwords = 0;
36011e25f0dSDavid C Somayajulu 	void *buffer;
36111e25f0dSDavid C Somayajulu 
36211e25f0dSDavid C Somayajulu 	buffer = qlnx_zalloc(trace->size[hwfn_index]);
36311e25f0dSDavid C Somayajulu 	if (buffer == NULL) {
3647a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha,"qlnx_zalloc [%d, 0x%x]failed\n",
3657a377fbeSDavid C Somayajulu                            hwfn_index, trace->cmd);
36611e25f0dSDavid C Somayajulu                 return (ENXIO);
36711e25f0dSDavid C Somayajulu 	}
36811e25f0dSDavid C Somayajulu 	ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver());
36911e25f0dSDavid C Somayajulu 
37011e25f0dSDavid C Somayajulu         p_hwfn = &ha->cdev.hwfns[hwfn_index];
37111e25f0dSDavid C Somayajulu         p_ptt = ecore_ptt_acquire(p_hwfn);
37211e25f0dSDavid C Somayajulu 
37311e25f0dSDavid C Somayajulu         if (!p_ptt) {
3747a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha, "ecore_ptt_acquire [%d, 0x%x]failed\n",
3757a377fbeSDavid C Somayajulu                            hwfn_index, trace->cmd);
37611e25f0dSDavid C Somayajulu                 return (ENXIO);
37711e25f0dSDavid C Somayajulu         }
37811e25f0dSDavid C Somayajulu 
37911e25f0dSDavid C Somayajulu 	switch (trace->cmd) {
38011e25f0dSDavid C Somayajulu 
38111e25f0dSDavid C Somayajulu 	case QLNX_MCP_TRACE:
38211e25f0dSDavid C Somayajulu         	rval = ecore_dbg_mcp_trace_dump(p_hwfn, p_ptt,
38311e25f0dSDavid C Somayajulu 				buffer, (trace->size[hwfn_index] >> 2),
38411e25f0dSDavid C Somayajulu 				&num_dwords);
38511e25f0dSDavid C Somayajulu 		break;
38611e25f0dSDavid C Somayajulu 
38711e25f0dSDavid C Somayajulu 	case QLNX_REG_FIFO:
38811e25f0dSDavid C Somayajulu         	rval = ecore_dbg_reg_fifo_dump(p_hwfn, p_ptt,
38911e25f0dSDavid C Somayajulu 				buffer, (trace->size[hwfn_index] >> 2),
39011e25f0dSDavid C Somayajulu 				&num_dwords);
39111e25f0dSDavid C Somayajulu 		break;
39211e25f0dSDavid C Somayajulu 
39311e25f0dSDavid C Somayajulu 	case QLNX_IGU_FIFO:
39411e25f0dSDavid C Somayajulu         	rval = ecore_dbg_igu_fifo_dump(p_hwfn, p_ptt,
39511e25f0dSDavid C Somayajulu 				buffer, (trace->size[hwfn_index] >> 2),
39611e25f0dSDavid C Somayajulu 				&num_dwords);
39711e25f0dSDavid C Somayajulu 		break;
39811e25f0dSDavid C Somayajulu 
39911e25f0dSDavid C Somayajulu 	case QLNX_PROTECTION_OVERRIDE:
40011e25f0dSDavid C Somayajulu         	rval = ecore_dbg_protection_override_dump(p_hwfn, p_ptt,
40111e25f0dSDavid C Somayajulu 				buffer, (trace->size[hwfn_index] >> 2),
40211e25f0dSDavid C Somayajulu 				&num_dwords);
40311e25f0dSDavid C Somayajulu 		break;
40411e25f0dSDavid C Somayajulu 
40511e25f0dSDavid C Somayajulu 	case QLNX_FW_ASSERTS:
40611e25f0dSDavid C Somayajulu         	rval = ecore_dbg_fw_asserts_dump(p_hwfn, p_ptt,
40711e25f0dSDavid C Somayajulu 				buffer, (trace->size[hwfn_index] >> 2),
40811e25f0dSDavid C Somayajulu 				&num_dwords);
40911e25f0dSDavid C Somayajulu 		break;
41011e25f0dSDavid C Somayajulu 	}
41111e25f0dSDavid C Somayajulu 
41211e25f0dSDavid C Somayajulu         if (rval != DBG_STATUS_OK) {
4137a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha,"cmd = 0x%x failed [0x%x]\n", trace->cmd, rval);
41411e25f0dSDavid C Somayajulu 		num_dwords = 0;
41511e25f0dSDavid C Somayajulu         }
41611e25f0dSDavid C Somayajulu 
41711e25f0dSDavid C Somayajulu         ecore_ptt_release(p_hwfn, p_ptt);
41811e25f0dSDavid C Somayajulu 
41911e25f0dSDavid C Somayajulu 	trace->dwords[hwfn_index] = num_dwords;
42011e25f0dSDavid C Somayajulu 
42111e25f0dSDavid C Somayajulu 	if (num_dwords) {
42211e25f0dSDavid C Somayajulu                	rval = copyout(buffer, trace->buffer[hwfn_index],
42311e25f0dSDavid C Somayajulu 				(num_dwords << 2));
42411e25f0dSDavid C Somayajulu 	}
42511e25f0dSDavid C Somayajulu 
42611e25f0dSDavid C Somayajulu         return (rval);
42711e25f0dSDavid C Somayajulu }
42811e25f0dSDavid C Somayajulu 
42911e25f0dSDavid C Somayajulu static int
43011e25f0dSDavid C Somayajulu qlnx_reg_rd_wr(qlnx_host_t *ha, qlnx_reg_rd_wr_t *reg_rd_wr)
43111e25f0dSDavid C Somayajulu {
43211e25f0dSDavid C Somayajulu 	int			rval = 0;
43311e25f0dSDavid C Somayajulu 	struct ecore_hwfn	*p_hwfn;
43411e25f0dSDavid C Somayajulu 
43511e25f0dSDavid C Somayajulu 	if (reg_rd_wr->hwfn_index >= QLNX_MAX_HW_FUNCS) {
43611e25f0dSDavid C Somayajulu 		return (EINVAL);
43711e25f0dSDavid C Somayajulu 	}
43811e25f0dSDavid C Somayajulu 
43911e25f0dSDavid C Somayajulu 	p_hwfn = &ha->cdev.hwfns[reg_rd_wr->hwfn_index];
44011e25f0dSDavid C Somayajulu 
44111e25f0dSDavid C Somayajulu 	switch (reg_rd_wr->cmd) {
44211e25f0dSDavid C Somayajulu 
44311e25f0dSDavid C Somayajulu 		case QLNX_REG_READ_CMD:
44411e25f0dSDavid C Somayajulu 			if (reg_rd_wr->access_type == QLNX_REG_ACCESS_DIRECT) {
44511e25f0dSDavid C Somayajulu 				reg_rd_wr->val = qlnx_reg_rd32(p_hwfn,
44611e25f0dSDavid C Somayajulu 							reg_rd_wr->addr);
44711e25f0dSDavid C Somayajulu 			}
44811e25f0dSDavid C Somayajulu 			break;
44911e25f0dSDavid C Somayajulu 
45011e25f0dSDavid C Somayajulu 		case QLNX_REG_WRITE_CMD:
45111e25f0dSDavid C Somayajulu 			if (reg_rd_wr->access_type == QLNX_REG_ACCESS_DIRECT) {
45211e25f0dSDavid C Somayajulu 				qlnx_reg_wr32(p_hwfn, reg_rd_wr->addr,
45311e25f0dSDavid C Somayajulu 					reg_rd_wr->val);
45411e25f0dSDavid C Somayajulu 			}
45511e25f0dSDavid C Somayajulu 			break;
45611e25f0dSDavid C Somayajulu 
45711e25f0dSDavid C Somayajulu 		default:
45811e25f0dSDavid C Somayajulu 			rval = EINVAL;
45911e25f0dSDavid C Somayajulu 			break;
46011e25f0dSDavid C Somayajulu 	}
46111e25f0dSDavid C Somayajulu 
46211e25f0dSDavid C Somayajulu 	return (rval);
46311e25f0dSDavid C Somayajulu }
46411e25f0dSDavid C Somayajulu 
46511e25f0dSDavid C Somayajulu static int
46611e25f0dSDavid C Somayajulu qlnx_rd_wr_pci_config(qlnx_host_t *ha, qlnx_pcicfg_rd_wr_t *pci_cfg_rd_wr)
46711e25f0dSDavid C Somayajulu {
46811e25f0dSDavid C Somayajulu 	int rval = 0;
46911e25f0dSDavid C Somayajulu 
47011e25f0dSDavid C Somayajulu 	switch (pci_cfg_rd_wr->cmd) {
47111e25f0dSDavid C Somayajulu 
47211e25f0dSDavid C Somayajulu 		case QLNX_PCICFG_READ:
47311e25f0dSDavid C Somayajulu 			pci_cfg_rd_wr->val = pci_read_config(ha->pci_dev,
47411e25f0dSDavid C Somayajulu 						pci_cfg_rd_wr->reg,
47511e25f0dSDavid C Somayajulu 						pci_cfg_rd_wr->width);
47611e25f0dSDavid C Somayajulu 			break;
47711e25f0dSDavid C Somayajulu 
47811e25f0dSDavid C Somayajulu 		case QLNX_PCICFG_WRITE:
47911e25f0dSDavid C Somayajulu 			pci_write_config(ha->pci_dev, pci_cfg_rd_wr->reg,
48011e25f0dSDavid C Somayajulu 				pci_cfg_rd_wr->val, pci_cfg_rd_wr->width);
48111e25f0dSDavid C Somayajulu 			break;
48211e25f0dSDavid C Somayajulu 
48311e25f0dSDavid C Somayajulu 		default:
48411e25f0dSDavid C Somayajulu 			rval = EINVAL;
48511e25f0dSDavid C Somayajulu 			break;
48611e25f0dSDavid C Somayajulu 	}
48711e25f0dSDavid C Somayajulu 
48811e25f0dSDavid C Somayajulu 	return (rval);
48911e25f0dSDavid C Somayajulu }
49011e25f0dSDavid C Somayajulu 
49111e25f0dSDavid C Somayajulu static void
49211e25f0dSDavid C Somayajulu qlnx_mac_addr(qlnx_host_t *ha, qlnx_perm_mac_addr_t *mac_addr)
49311e25f0dSDavid C Somayajulu {
49411e25f0dSDavid C Somayajulu 	bzero(mac_addr->addr, sizeof(mac_addr->addr));
49511e25f0dSDavid C Somayajulu 	snprintf(mac_addr->addr, sizeof(mac_addr->addr),
49611e25f0dSDavid C Somayajulu 		"%02x:%02x:%02x:%02x:%02x:%02x",
49711e25f0dSDavid C Somayajulu 		ha->primary_mac[0], ha->primary_mac[1], ha->primary_mac[2],
49811e25f0dSDavid C Somayajulu 		ha->primary_mac[3], ha->primary_mac[4], ha->primary_mac[5]);
49911e25f0dSDavid C Somayajulu 
50011e25f0dSDavid C Somayajulu 	return;
50111e25f0dSDavid C Somayajulu }
50211e25f0dSDavid C Somayajulu 
50311e25f0dSDavid C Somayajulu static int
50411e25f0dSDavid C Somayajulu qlnx_get_regs(qlnx_host_t *ha, qlnx_get_regs_t *regs)
50511e25f0dSDavid C Somayajulu {
50611e25f0dSDavid C Somayajulu 	int		i;
50711e25f0dSDavid C Somayajulu 	int		rval = 0;
50811e25f0dSDavid C Somayajulu 	uint32_t	dwords = 0;
50911e25f0dSDavid C Somayajulu 	uint8_t		*outb;
51011e25f0dSDavid C Somayajulu 
51111e25f0dSDavid C Somayajulu 	regs->reg_buf_len = 0;
51211e25f0dSDavid C Somayajulu 	outb = regs->reg_buf;
51311e25f0dSDavid C Somayajulu 
51411e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
51511e25f0dSDavid C Somayajulu 
51611e25f0dSDavid C Somayajulu 		rval = qlnx_grc_dump(ha, &dwords, i);
51711e25f0dSDavid C Somayajulu 
51811e25f0dSDavid C Somayajulu 		if (rval)
51911e25f0dSDavid C Somayajulu 			break;
52011e25f0dSDavid C Somayajulu 
52111e25f0dSDavid C Somayajulu 		regs->reg_buf_len += (dwords << 2);
52211e25f0dSDavid C Somayajulu 
52311e25f0dSDavid C Somayajulu 		rval = copyout(ha->grcdump[i], outb, ha->grcdump_size[i]);
52411e25f0dSDavid C Somayajulu 
52511e25f0dSDavid C Somayajulu 		if (rval)
52611e25f0dSDavid C Somayajulu 			break;
52711e25f0dSDavid C Somayajulu 
52811e25f0dSDavid C Somayajulu 		ha->grcdump_dwords[i] = 0;
52911e25f0dSDavid C Somayajulu 		outb += regs->reg_buf_len;
53011e25f0dSDavid C Somayajulu 	}
53111e25f0dSDavid C Somayajulu 
53211e25f0dSDavid C Somayajulu 	ha->grcdump_taken = 0;
53311e25f0dSDavid C Somayajulu 
53411e25f0dSDavid C Somayajulu 	return (rval);
53511e25f0dSDavid C Somayajulu }
53611e25f0dSDavid C Somayajulu 
537*d576ccdfSRyan Libby extern char qlnx_name_str[];
538*d576ccdfSRyan Libby extern char qlnx_ver_str[];
539*d576ccdfSRyan Libby 
54011e25f0dSDavid C Somayajulu static int
54111e25f0dSDavid C Somayajulu qlnx_drv_info(qlnx_host_t *ha, qlnx_drvinfo_t *drv_info)
54211e25f0dSDavid C Somayajulu {
54311e25f0dSDavid C Somayajulu 	int i;
54411e25f0dSDavid C Somayajulu 
54511e25f0dSDavid C Somayajulu 	bzero(drv_info, sizeof(qlnx_drvinfo_t));
54611e25f0dSDavid C Somayajulu 
54711e25f0dSDavid C Somayajulu 	snprintf(drv_info->drv_name, sizeof(drv_info->drv_name), "%s",
54811e25f0dSDavid C Somayajulu 		qlnx_name_str);
54911e25f0dSDavid C Somayajulu 	snprintf(drv_info->drv_version, sizeof(drv_info->drv_version), "%s",
55011e25f0dSDavid C Somayajulu 		qlnx_ver_str);
55111e25f0dSDavid C Somayajulu 	snprintf(drv_info->mfw_version, sizeof(drv_info->mfw_version), "%s",
55211e25f0dSDavid C Somayajulu 		ha->mfw_ver);
55311e25f0dSDavid C Somayajulu 	snprintf(drv_info->stormfw_version, sizeof(drv_info->stormfw_version),
55411e25f0dSDavid C Somayajulu 		"%s", ha->stormfw_ver);
55511e25f0dSDavid C Somayajulu 
55611e25f0dSDavid C Somayajulu 	drv_info->eeprom_dump_len = ha->flash_size;
55711e25f0dSDavid C Somayajulu 
55811e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
55911e25f0dSDavid C Somayajulu 		drv_info->reg_dump_len += ha->grcdump_size[i];
56011e25f0dSDavid C Somayajulu 	}
56111e25f0dSDavid C Somayajulu 
56211e25f0dSDavid C Somayajulu 	snprintf(drv_info->bus_info, sizeof(drv_info->bus_info),
56311e25f0dSDavid C Somayajulu 		"%d:%d:%d", pci_get_bus(ha->pci_dev),
56411e25f0dSDavid C Somayajulu 		pci_get_slot(ha->pci_dev), ha->pci_func);
56511e25f0dSDavid C Somayajulu 
56611e25f0dSDavid C Somayajulu 	return (0);
56711e25f0dSDavid C Somayajulu }
56811e25f0dSDavid C Somayajulu 
56911e25f0dSDavid C Somayajulu static int
57011e25f0dSDavid C Somayajulu qlnx_dev_settings(qlnx_host_t *ha, qlnx_dev_setting_t *dev_info)
57111e25f0dSDavid C Somayajulu {
57211e25f0dSDavid C Somayajulu 	struct ecore_hwfn *p_hwfn;
57311e25f0dSDavid C Somayajulu 	struct qlnx_link_output if_link;
57411e25f0dSDavid C Somayajulu 
57511e25f0dSDavid C Somayajulu 	p_hwfn = &ha->cdev.hwfns[0];
57611e25f0dSDavid C Somayajulu 
57711e25f0dSDavid C Somayajulu 	qlnx_fill_link(p_hwfn, &if_link);
57811e25f0dSDavid C Somayajulu 
57911e25f0dSDavid C Somayajulu 	dev_info->supported = if_link.supported_caps;
58011e25f0dSDavid C Somayajulu 	dev_info->advertising = if_link.advertised_caps;
58111e25f0dSDavid C Somayajulu 	dev_info->speed = if_link.speed;
58211e25f0dSDavid C Somayajulu 	dev_info->duplex = if_link.duplex;
58311e25f0dSDavid C Somayajulu 	dev_info->port = ha->pci_func & 0x1;
58411e25f0dSDavid C Somayajulu 	dev_info->autoneg = if_link.autoneg;
58511e25f0dSDavid C Somayajulu 
58611e25f0dSDavid C Somayajulu 	return (0);
58711e25f0dSDavid C Somayajulu }
58811e25f0dSDavid C Somayajulu 
58911e25f0dSDavid C Somayajulu static int
59011e25f0dSDavid C Somayajulu qlnx_write_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram, uint32_t cmd)
59111e25f0dSDavid C Somayajulu {
59211e25f0dSDavid C Somayajulu 	uint8_t *buf;
59311e25f0dSDavid C Somayajulu 	int ret = 0;
59411e25f0dSDavid C Somayajulu 
59511e25f0dSDavid C Somayajulu 	if ((nvram->data == NULL) || (nvram->data_len == 0))
59611e25f0dSDavid C Somayajulu 		return (EINVAL);
59711e25f0dSDavid C Somayajulu 
59811e25f0dSDavid C Somayajulu 	buf = qlnx_zalloc(nvram->data_len);
59911e25f0dSDavid C Somayajulu 
60011e25f0dSDavid C Somayajulu 	ret = copyin(nvram->data, buf, nvram->data_len);
60111e25f0dSDavid C Somayajulu 
6027a377fbeSDavid C Somayajulu 	QL_DPRINT9(ha, "issue cmd = 0x%x data = %p \
6037a377fbeSDavid C Somayajulu 		 data_len = 0x%x ret = 0x%x exit\n",
6047a377fbeSDavid C Somayajulu 		cmd, nvram->data, nvram->data_len, ret);
60511e25f0dSDavid C Somayajulu 
60611e25f0dSDavid C Somayajulu 	if (ret == 0) {
60711e25f0dSDavid C Somayajulu 		ret = ecore_mcp_nvm_write(&ha->cdev, cmd,
60811e25f0dSDavid C Somayajulu 			nvram->offset, buf, nvram->data_len);
60911e25f0dSDavid C Somayajulu 	}
61011e25f0dSDavid C Somayajulu 
6117a377fbeSDavid C Somayajulu 	QL_DPRINT9(ha, "cmd = 0x%x data = %p \
6127a377fbeSDavid C Somayajulu 		 data_len = 0x%x resp = 0x%x ret = 0x%x exit\n",
6137a377fbeSDavid C Somayajulu 		cmd, nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret);
61411e25f0dSDavid C Somayajulu 
61511e25f0dSDavid C Somayajulu 	free(buf, M_QLNXBUF);
61611e25f0dSDavid C Somayajulu 
61711e25f0dSDavid C Somayajulu 	return (ret);
61811e25f0dSDavid C Somayajulu }
61911e25f0dSDavid C Somayajulu 
62011e25f0dSDavid C Somayajulu static int
62111e25f0dSDavid C Somayajulu qlnx_read_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram)
62211e25f0dSDavid C Somayajulu {
62311e25f0dSDavid C Somayajulu 	uint8_t *buf;
62411e25f0dSDavid C Somayajulu 	int ret = 0;
62511e25f0dSDavid C Somayajulu 
62611e25f0dSDavid C Somayajulu 	if ((nvram->data == NULL) || (nvram->data_len == 0))
62711e25f0dSDavid C Somayajulu 		return (EINVAL);
62811e25f0dSDavid C Somayajulu 
62911e25f0dSDavid C Somayajulu 	buf = qlnx_zalloc(nvram->data_len);
63011e25f0dSDavid C Somayajulu 
63111e25f0dSDavid C Somayajulu 	ret = ecore_mcp_nvm_read(&ha->cdev, nvram->offset, buf,
63211e25f0dSDavid C Somayajulu 		nvram->data_len);
63311e25f0dSDavid C Somayajulu 
6347a377fbeSDavid C Somayajulu 	QL_DPRINT9(ha, " data = %p data_len = 0x%x \
6357a377fbeSDavid C Somayajulu 		 resp = 0x%x ret = 0x%x exit\n",
6367a377fbeSDavid C Somayajulu 		nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret);
63711e25f0dSDavid C Somayajulu 
63811e25f0dSDavid C Somayajulu 	if (ret == 0) {
63911e25f0dSDavid C Somayajulu 		ret = copyout(buf, nvram->data, nvram->data_len);
64011e25f0dSDavid C Somayajulu 	}
64111e25f0dSDavid C Somayajulu 
64211e25f0dSDavid C Somayajulu 	free(buf, M_QLNXBUF);
64311e25f0dSDavid C Somayajulu 
64411e25f0dSDavid C Somayajulu 	return (ret);
64511e25f0dSDavid C Somayajulu }
64611e25f0dSDavid C Somayajulu 
64711e25f0dSDavid C Somayajulu static int
64811e25f0dSDavid C Somayajulu qlnx_get_nvram_resp(qlnx_host_t *ha, qlnx_nvram_t *nvram)
64911e25f0dSDavid C Somayajulu {
65011e25f0dSDavid C Somayajulu 	uint8_t *buf;
65111e25f0dSDavid C Somayajulu 	int ret = 0;
65211e25f0dSDavid C Somayajulu 
65311e25f0dSDavid C Somayajulu 	if ((nvram->data == NULL) || (nvram->data_len == 0))
65411e25f0dSDavid C Somayajulu 		return (EINVAL);
65511e25f0dSDavid C Somayajulu 
65611e25f0dSDavid C Somayajulu 	buf = qlnx_zalloc(nvram->data_len);
65711e25f0dSDavid C Somayajulu 
65811e25f0dSDavid C Somayajulu 
65911e25f0dSDavid C Somayajulu 	ret = ecore_mcp_nvm_resp(&ha->cdev, buf);
66011e25f0dSDavid C Somayajulu 
6617a377fbeSDavid C Somayajulu 	QL_DPRINT9(ha, "data = %p data_len = 0x%x \
6627a377fbeSDavid C Somayajulu 		 resp = 0x%x ret = 0x%x exit\n",
6637a377fbeSDavid C Somayajulu 		nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret);
66411e25f0dSDavid C Somayajulu 
66511e25f0dSDavid C Somayajulu 	if (ret == 0) {
66611e25f0dSDavid C Somayajulu 		ret = copyout(buf, nvram->data, nvram->data_len);
66711e25f0dSDavid C Somayajulu 	}
66811e25f0dSDavid C Somayajulu 
66911e25f0dSDavid C Somayajulu 	free(buf, M_QLNXBUF);
67011e25f0dSDavid C Somayajulu 
67111e25f0dSDavid C Somayajulu 	return (ret);
67211e25f0dSDavid C Somayajulu }
67311e25f0dSDavid C Somayajulu 
67411e25f0dSDavid C Somayajulu static int
67511e25f0dSDavid C Somayajulu qlnx_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram)
67611e25f0dSDavid C Somayajulu {
67711e25f0dSDavid C Somayajulu 	int ret = 0;
67811e25f0dSDavid C Somayajulu 
67911e25f0dSDavid C Somayajulu 	switch (nvram->cmd) {
68011e25f0dSDavid C Somayajulu 
68111e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_WRITE_NVRAM:
68211e25f0dSDavid C Somayajulu 		ret = qlnx_write_nvram(ha, nvram, ECORE_NVM_WRITE_NVRAM);
68311e25f0dSDavid C Somayajulu 		break;
68411e25f0dSDavid C Somayajulu 
68511e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_PUT_FILE_DATA:
68611e25f0dSDavid C Somayajulu 		ret = qlnx_write_nvram(ha, nvram, ECORE_PUT_FILE_DATA);
68711e25f0dSDavid C Somayajulu 		break;
68811e25f0dSDavid C Somayajulu 
68911e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_READ_NVRAM:
69011e25f0dSDavid C Somayajulu 		ret = qlnx_read_nvram(ha, nvram);
69111e25f0dSDavid C Somayajulu 		break;
69211e25f0dSDavid C Somayajulu 
69311e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_SET_SECURE_MODE:
69411e25f0dSDavid C Somayajulu 		ret = ecore_mcp_nvm_set_secure_mode(&ha->cdev, nvram->offset);
69511e25f0dSDavid C Somayajulu 
6967a377fbeSDavid C Somayajulu 		QL_DPRINT9(ha, "QLNX_NVRAM_CMD_SET_SECURE_MODE \
6977a377fbeSDavid C Somayajulu 			 resp = 0x%x ret = 0x%x exit\n",
6987a377fbeSDavid C Somayajulu 			 ha->cdev.mcp_nvm_resp, ret);
69911e25f0dSDavid C Somayajulu 		break;
70011e25f0dSDavid C Somayajulu 
70111e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_DEL_FILE:
70211e25f0dSDavid C Somayajulu 		ret = ecore_mcp_nvm_del_file(&ha->cdev, nvram->offset);
70311e25f0dSDavid C Somayajulu 
7047a377fbeSDavid C Somayajulu 		QL_DPRINT9(ha, "QLNX_NVRAM_CMD_DEL_FILE \
7057a377fbeSDavid C Somayajulu 			 resp = 0x%x ret = 0x%x exit\n",
7067a377fbeSDavid C Somayajulu 			ha->cdev.mcp_nvm_resp, ret);
70711e25f0dSDavid C Somayajulu 		break;
70811e25f0dSDavid C Somayajulu 
70911e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_PUT_FILE_BEGIN:
71011e25f0dSDavid C Somayajulu 		ret = ecore_mcp_nvm_put_file_begin(&ha->cdev, nvram->offset);
71111e25f0dSDavid C Somayajulu 
7127a377fbeSDavid C Somayajulu 		QL_DPRINT9(ha, "QLNX_NVRAM_CMD_PUT_FILE_BEGIN \
7137a377fbeSDavid C Somayajulu 			 resp = 0x%x ret = 0x%x exit\n",
7147a377fbeSDavid C Somayajulu 			ha->cdev.mcp_nvm_resp, ret);
71511e25f0dSDavid C Somayajulu 		break;
71611e25f0dSDavid C Somayajulu 
71711e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_GET_NVRAM_RESP:
71811e25f0dSDavid C Somayajulu 		ret = qlnx_get_nvram_resp(ha, nvram);
71911e25f0dSDavid C Somayajulu 		break;
72011e25f0dSDavid C Somayajulu 
72111e25f0dSDavid C Somayajulu 	default:
72211e25f0dSDavid C Somayajulu 		ret = EINVAL;
72311e25f0dSDavid C Somayajulu 		break;
72411e25f0dSDavid C Somayajulu 	}
72511e25f0dSDavid C Somayajulu 
72611e25f0dSDavid C Somayajulu 	return (ret);
72711e25f0dSDavid C Somayajulu }
72811e25f0dSDavid C Somayajulu 
72911e25f0dSDavid C Somayajulu static void
73011e25f0dSDavid C Somayajulu qlnx_storm_stats(qlnx_host_t *ha, qlnx_storm_stats_dump_t *s_stats)
73111e25f0dSDavid C Somayajulu {
73211e25f0dSDavid C Somayajulu 	int i;
73311e25f0dSDavid C Somayajulu 	int index;
73411e25f0dSDavid C Somayajulu 	int ret;
73511e25f0dSDavid C Somayajulu 	int stats_copied = 0;
73611e25f0dSDavid C Somayajulu 
73711e25f0dSDavid C Somayajulu 	s_stats->num_hwfns = ha->cdev.num_hwfns;
73811e25f0dSDavid C Somayajulu 
73911e25f0dSDavid C Somayajulu //	if (ha->storm_stats_index < QLNX_STORM_STATS_SAMPLES_PER_HWFN)
74011e25f0dSDavid C Somayajulu //		return;
74111e25f0dSDavid C Somayajulu 
74211e25f0dSDavid C Somayajulu 	s_stats->num_samples = ha->storm_stats_index;
74311e25f0dSDavid C Somayajulu 
74411e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
74511e25f0dSDavid C Somayajulu 
74611e25f0dSDavid C Somayajulu 		index = (QLNX_STORM_STATS_SAMPLES_PER_HWFN * i);
74711e25f0dSDavid C Somayajulu 
74811e25f0dSDavid C Somayajulu 		if (s_stats->buffer[i]) {
74911e25f0dSDavid C Somayajulu 
75011e25f0dSDavid C Somayajulu 			ret = copyout(&ha->storm_stats[index],
75111e25f0dSDavid C Somayajulu 					s_stats->buffer[i],
75211e25f0dSDavid C Somayajulu 					QLNX_STORM_STATS_BYTES_PER_HWFN);
75311e25f0dSDavid C Somayajulu 			if (ret) {
75411e25f0dSDavid C Somayajulu 				printf("%s [%d]: failed\n", __func__, i);
75511e25f0dSDavid C Somayajulu 			}
75611e25f0dSDavid C Somayajulu 
75711e25f0dSDavid C Somayajulu 			if (s_stats->num_samples ==
75811e25f0dSDavid C Somayajulu 				QLNX_STORM_STATS_SAMPLES_PER_HWFN) {
75911e25f0dSDavid C Somayajulu 
76011e25f0dSDavid C Somayajulu 				bzero((void *)&ha->storm_stats[i],
76111e25f0dSDavid C Somayajulu 					QLNX_STORM_STATS_BYTES_PER_HWFN);
76211e25f0dSDavid C Somayajulu 
76311e25f0dSDavid C Somayajulu 				stats_copied = 1;
76411e25f0dSDavid C Somayajulu 			}
76511e25f0dSDavid C Somayajulu 		}
76611e25f0dSDavid C Somayajulu 	}
76711e25f0dSDavid C Somayajulu 
76811e25f0dSDavid C Somayajulu 	if (stats_copied)
76911e25f0dSDavid C Somayajulu 		ha->storm_stats_index = 0;
77011e25f0dSDavid C Somayajulu 
77111e25f0dSDavid C Somayajulu 	return;
77211e25f0dSDavid C Somayajulu }
77311e25f0dSDavid C Somayajulu 
77411e25f0dSDavid C Somayajulu 
77511e25f0dSDavid C Somayajulu static int
77611e25f0dSDavid C Somayajulu qlnx_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
77711e25f0dSDavid C Somayajulu 	struct thread *td)
77811e25f0dSDavid C Somayajulu {
77911e25f0dSDavid C Somayajulu 	qlnx_host_t	*ha;
78011e25f0dSDavid C Somayajulu 	int		rval = 0;
78111e25f0dSDavid C Somayajulu 	struct ifnet	*ifp;
78211e25f0dSDavid C Somayajulu 	qlnx_trace_t	*trace;
78311e25f0dSDavid C Somayajulu 	int		i;
78411e25f0dSDavid C Somayajulu 
78511e25f0dSDavid C Somayajulu 	if ((ha = (qlnx_host_t *)dev->si_drv1) == NULL)
78611e25f0dSDavid C Somayajulu 		return ENXIO;
78711e25f0dSDavid C Somayajulu 
78811e25f0dSDavid C Somayajulu 	ifp = ha->ifp;
78911e25f0dSDavid C Somayajulu 
79011e25f0dSDavid C Somayajulu 	switch (cmd) {
79111e25f0dSDavid C Somayajulu 
79211e25f0dSDavid C Somayajulu 	case QLNX_GRC_DUMP_SIZE:
79311e25f0dSDavid C Somayajulu 		qlnx_get_grc_dump_size(ha, (qlnx_grcdump_t *)data);
79411e25f0dSDavid C Somayajulu 		break;
79511e25f0dSDavid C Somayajulu 
79611e25f0dSDavid C Somayajulu 	case QLNX_GRC_DUMP:
79711e25f0dSDavid C Somayajulu 		rval = qlnx_get_grc_dump(ha, (qlnx_grcdump_t *)data);
79811e25f0dSDavid C Somayajulu 		break;
79911e25f0dSDavid C Somayajulu 
80011e25f0dSDavid C Somayajulu 	case QLNX_IDLE_CHK_SIZE:
80111e25f0dSDavid C Somayajulu 		qlnx_get_idle_chk_size(ha, (qlnx_idle_chk_t *)data);
80211e25f0dSDavid C Somayajulu 		break;
80311e25f0dSDavid C Somayajulu 
80411e25f0dSDavid C Somayajulu 	case QLNX_IDLE_CHK:
80511e25f0dSDavid C Somayajulu 		rval = qlnx_get_idle_chk(ha, (qlnx_idle_chk_t *)data);
80611e25f0dSDavid C Somayajulu 		break;
80711e25f0dSDavid C Somayajulu 
80811e25f0dSDavid C Somayajulu 	case QLNX_DRV_INFO:
80911e25f0dSDavid C Somayajulu 		rval = qlnx_drv_info(ha, (qlnx_drvinfo_t *)data);
81011e25f0dSDavid C Somayajulu 		break;
81111e25f0dSDavid C Somayajulu 
81211e25f0dSDavid C Somayajulu 	case QLNX_DEV_SETTING:
81311e25f0dSDavid C Somayajulu 		rval = qlnx_dev_settings(ha, (qlnx_dev_setting_t *)data);
81411e25f0dSDavid C Somayajulu 		break;
81511e25f0dSDavid C Somayajulu 
81611e25f0dSDavid C Somayajulu 	case QLNX_GET_REGS:
81711e25f0dSDavid C Somayajulu 		rval = qlnx_get_regs(ha, (qlnx_get_regs_t *)data);
81811e25f0dSDavid C Somayajulu 		break;
81911e25f0dSDavid C Somayajulu 
82011e25f0dSDavid C Somayajulu 	case QLNX_NVRAM:
82111e25f0dSDavid C Somayajulu 		rval = qlnx_nvram(ha, (qlnx_nvram_t *)data);
82211e25f0dSDavid C Somayajulu 		break;
82311e25f0dSDavid C Somayajulu 
82411e25f0dSDavid C Somayajulu 	case QLNX_RD_WR_REG:
82511e25f0dSDavid C Somayajulu 		rval = qlnx_reg_rd_wr(ha, (qlnx_reg_rd_wr_t *)data);
82611e25f0dSDavid C Somayajulu 		break;
82711e25f0dSDavid C Somayajulu 
82811e25f0dSDavid C Somayajulu 	case QLNX_RD_WR_PCICFG:
82911e25f0dSDavid C Somayajulu 		rval = qlnx_rd_wr_pci_config(ha, (qlnx_pcicfg_rd_wr_t *)data);
83011e25f0dSDavid C Somayajulu 		break;
83111e25f0dSDavid C Somayajulu 
83211e25f0dSDavid C Somayajulu 	case QLNX_MAC_ADDR:
83311e25f0dSDavid C Somayajulu 		qlnx_mac_addr(ha, (qlnx_perm_mac_addr_t *)data);
83411e25f0dSDavid C Somayajulu 		break;
83511e25f0dSDavid C Somayajulu 
83611e25f0dSDavid C Somayajulu 	case QLNX_STORM_STATS:
83711e25f0dSDavid C Somayajulu 		qlnx_storm_stats(ha, (qlnx_storm_stats_dump_t *)data);
83811e25f0dSDavid C Somayajulu 		break;
83911e25f0dSDavid C Somayajulu 
84011e25f0dSDavid C Somayajulu 	case QLNX_TRACE_SIZE:
84111e25f0dSDavid C Somayajulu 		qlnx_get_trace_size(ha, (qlnx_trace_t *)data);
84211e25f0dSDavid C Somayajulu 		break;
84311e25f0dSDavid C Somayajulu 
84411e25f0dSDavid C Somayajulu 	case QLNX_TRACE:
84511e25f0dSDavid C Somayajulu 		trace = (qlnx_trace_t *)data;
84611e25f0dSDavid C Somayajulu 
84711e25f0dSDavid C Somayajulu 		for (i = 0; i < ha->cdev.num_hwfns; i++) {
84811e25f0dSDavid C Somayajulu 
84911e25f0dSDavid C Somayajulu 			if (trace->size[i] && trace->cmd && trace->buffer[i])
85011e25f0dSDavid C Somayajulu 				rval = qlnx_get_trace(ha, i, trace);
85111e25f0dSDavid C Somayajulu 
85211e25f0dSDavid C Somayajulu 			if (rval)
85311e25f0dSDavid C Somayajulu 				break;
85411e25f0dSDavid C Somayajulu 		}
85511e25f0dSDavid C Somayajulu 		break;
85611e25f0dSDavid C Somayajulu 
85711e25f0dSDavid C Somayajulu 	default:
85811e25f0dSDavid C Somayajulu 		rval = EINVAL;
85911e25f0dSDavid C Somayajulu 		break;
86011e25f0dSDavid C Somayajulu 	}
86111e25f0dSDavid C Somayajulu 
86211e25f0dSDavid C Somayajulu 	return (rval);
86311e25f0dSDavid C Somayajulu }
86411e25f0dSDavid C Somayajulu 
865