xref: /freebsd/sys/dev/qlnx/qlnxe/qlnx_ioctl.c (revision 7a377fbeb1b2e2fcfb726d2c9fca568dbbc9c2be)
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) {
124*7a377fbeSDavid 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
135*7a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha,"ecore_dbg_grc_dump failed [%d, 0x%x]\n",
136*7a377fbeSDavid 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 
178*7a377fbeSDavid 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) {
213*7a377fbeSDavid 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
224*7a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha,"ecore_dbg_idle_chk_dump failed [%d, 0x%x]\n",
225*7a377fbeSDavid 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 
269*7a377fbeSDavid 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) {
296*7a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha, "ecore_ptt_acquire [%d, 0x%x]failed\n",
297*7a377fbeSDavid 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) {
330*7a377fbeSDavid 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) {
364*7a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha,"qlnx_zalloc [%d, 0x%x]failed\n",
365*7a377fbeSDavid 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) {
374*7a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha, "ecore_ptt_acquire [%d, 0x%x]failed\n",
375*7a377fbeSDavid 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) {
413*7a377fbeSDavid 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 
53711e25f0dSDavid C Somayajulu static int
53811e25f0dSDavid C Somayajulu qlnx_drv_info(qlnx_host_t *ha, qlnx_drvinfo_t *drv_info)
53911e25f0dSDavid C Somayajulu {
54011e25f0dSDavid C Somayajulu 	int i;
54111e25f0dSDavid C Somayajulu 	extern char qlnx_name_str[];
54211e25f0dSDavid C Somayajulu 	extern char qlnx_ver_str[];
54311e25f0dSDavid C Somayajulu 
54411e25f0dSDavid C Somayajulu 	bzero(drv_info, sizeof(qlnx_drvinfo_t));
54511e25f0dSDavid C Somayajulu 
54611e25f0dSDavid C Somayajulu 	snprintf(drv_info->drv_name, sizeof(drv_info->drv_name), "%s",
54711e25f0dSDavid C Somayajulu 		qlnx_name_str);
54811e25f0dSDavid C Somayajulu 	snprintf(drv_info->drv_version, sizeof(drv_info->drv_version), "%s",
54911e25f0dSDavid C Somayajulu 		qlnx_ver_str);
55011e25f0dSDavid C Somayajulu 	snprintf(drv_info->mfw_version, sizeof(drv_info->mfw_version), "%s",
55111e25f0dSDavid C Somayajulu 		ha->mfw_ver);
55211e25f0dSDavid C Somayajulu 	snprintf(drv_info->stormfw_version, sizeof(drv_info->stormfw_version),
55311e25f0dSDavid C Somayajulu 		"%s", ha->stormfw_ver);
55411e25f0dSDavid C Somayajulu 
55511e25f0dSDavid C Somayajulu 	drv_info->eeprom_dump_len = ha->flash_size;
55611e25f0dSDavid C Somayajulu 
55711e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
55811e25f0dSDavid C Somayajulu 		drv_info->reg_dump_len += ha->grcdump_size[i];
55911e25f0dSDavid C Somayajulu 	}
56011e25f0dSDavid C Somayajulu 
56111e25f0dSDavid C Somayajulu 	snprintf(drv_info->bus_info, sizeof(drv_info->bus_info),
56211e25f0dSDavid C Somayajulu 		"%d:%d:%d", pci_get_bus(ha->pci_dev),
56311e25f0dSDavid C Somayajulu 		pci_get_slot(ha->pci_dev), ha->pci_func);
56411e25f0dSDavid C Somayajulu 
56511e25f0dSDavid C Somayajulu 	return (0);
56611e25f0dSDavid C Somayajulu }
56711e25f0dSDavid C Somayajulu 
56811e25f0dSDavid C Somayajulu static int
56911e25f0dSDavid C Somayajulu qlnx_dev_settings(qlnx_host_t *ha, qlnx_dev_setting_t *dev_info)
57011e25f0dSDavid C Somayajulu {
57111e25f0dSDavid C Somayajulu 	struct ecore_hwfn *p_hwfn;
57211e25f0dSDavid C Somayajulu 	struct qlnx_link_output if_link;
57311e25f0dSDavid C Somayajulu 
57411e25f0dSDavid C Somayajulu 	p_hwfn = &ha->cdev.hwfns[0];
57511e25f0dSDavid C Somayajulu 
57611e25f0dSDavid C Somayajulu 	qlnx_fill_link(p_hwfn, &if_link);
57711e25f0dSDavid C Somayajulu 
57811e25f0dSDavid C Somayajulu 	dev_info->supported = if_link.supported_caps;
57911e25f0dSDavid C Somayajulu 	dev_info->advertising = if_link.advertised_caps;
58011e25f0dSDavid C Somayajulu 	dev_info->speed = if_link.speed;
58111e25f0dSDavid C Somayajulu 	dev_info->duplex = if_link.duplex;
58211e25f0dSDavid C Somayajulu 	dev_info->port = ha->pci_func & 0x1;
58311e25f0dSDavid C Somayajulu 	dev_info->autoneg = if_link.autoneg;
58411e25f0dSDavid C Somayajulu 
58511e25f0dSDavid C Somayajulu 	return (0);
58611e25f0dSDavid C Somayajulu }
58711e25f0dSDavid C Somayajulu 
58811e25f0dSDavid C Somayajulu static int
58911e25f0dSDavid C Somayajulu qlnx_write_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram, uint32_t cmd)
59011e25f0dSDavid C Somayajulu {
59111e25f0dSDavid C Somayajulu 	uint8_t *buf;
59211e25f0dSDavid C Somayajulu 	int ret = 0;
59311e25f0dSDavid C Somayajulu 
59411e25f0dSDavid C Somayajulu 	if ((nvram->data == NULL) || (nvram->data_len == 0))
59511e25f0dSDavid C Somayajulu 		return (EINVAL);
59611e25f0dSDavid C Somayajulu 
59711e25f0dSDavid C Somayajulu 	buf = qlnx_zalloc(nvram->data_len);
59811e25f0dSDavid C Somayajulu 
59911e25f0dSDavid C Somayajulu 	ret = copyin(nvram->data, buf, nvram->data_len);
60011e25f0dSDavid C Somayajulu 
601*7a377fbeSDavid C Somayajulu 	QL_DPRINT9(ha, "issue cmd = 0x%x data = %p \
602*7a377fbeSDavid C Somayajulu 		 data_len = 0x%x ret = 0x%x exit\n",
603*7a377fbeSDavid C Somayajulu 		cmd, nvram->data, nvram->data_len, ret);
60411e25f0dSDavid C Somayajulu 
60511e25f0dSDavid C Somayajulu 	if (ret == 0) {
60611e25f0dSDavid C Somayajulu 		ret = ecore_mcp_nvm_write(&ha->cdev, cmd,
60711e25f0dSDavid C Somayajulu 			nvram->offset, buf, nvram->data_len);
60811e25f0dSDavid C Somayajulu 	}
60911e25f0dSDavid C Somayajulu 
610*7a377fbeSDavid C Somayajulu 	QL_DPRINT9(ha, "cmd = 0x%x data = %p \
611*7a377fbeSDavid C Somayajulu 		 data_len = 0x%x resp = 0x%x ret = 0x%x exit\n",
612*7a377fbeSDavid C Somayajulu 		cmd, nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret);
61311e25f0dSDavid C Somayajulu 
61411e25f0dSDavid C Somayajulu 	free(buf, M_QLNXBUF);
61511e25f0dSDavid C Somayajulu 
61611e25f0dSDavid C Somayajulu 	return (ret);
61711e25f0dSDavid C Somayajulu }
61811e25f0dSDavid C Somayajulu 
61911e25f0dSDavid C Somayajulu static int
62011e25f0dSDavid C Somayajulu qlnx_read_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram)
62111e25f0dSDavid C Somayajulu {
62211e25f0dSDavid C Somayajulu 	uint8_t *buf;
62311e25f0dSDavid C Somayajulu 	int ret = 0;
62411e25f0dSDavid C Somayajulu 
62511e25f0dSDavid C Somayajulu 	if ((nvram->data == NULL) || (nvram->data_len == 0))
62611e25f0dSDavid C Somayajulu 		return (EINVAL);
62711e25f0dSDavid C Somayajulu 
62811e25f0dSDavid C Somayajulu 	buf = qlnx_zalloc(nvram->data_len);
62911e25f0dSDavid C Somayajulu 
63011e25f0dSDavid C Somayajulu 	ret = ecore_mcp_nvm_read(&ha->cdev, nvram->offset, buf,
63111e25f0dSDavid C Somayajulu 		nvram->data_len);
63211e25f0dSDavid C Somayajulu 
633*7a377fbeSDavid C Somayajulu 	QL_DPRINT9(ha, " data = %p data_len = 0x%x \
634*7a377fbeSDavid C Somayajulu 		 resp = 0x%x ret = 0x%x exit\n",
635*7a377fbeSDavid C Somayajulu 		nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret);
63611e25f0dSDavid C Somayajulu 
63711e25f0dSDavid C Somayajulu 	if (ret == 0) {
63811e25f0dSDavid C Somayajulu 		ret = copyout(buf, nvram->data, nvram->data_len);
63911e25f0dSDavid C Somayajulu 	}
64011e25f0dSDavid C Somayajulu 
64111e25f0dSDavid C Somayajulu 	free(buf, M_QLNXBUF);
64211e25f0dSDavid C Somayajulu 
64311e25f0dSDavid C Somayajulu 	return (ret);
64411e25f0dSDavid C Somayajulu }
64511e25f0dSDavid C Somayajulu 
64611e25f0dSDavid C Somayajulu static int
64711e25f0dSDavid C Somayajulu qlnx_get_nvram_resp(qlnx_host_t *ha, qlnx_nvram_t *nvram)
64811e25f0dSDavid C Somayajulu {
64911e25f0dSDavid C Somayajulu 	uint8_t *buf;
65011e25f0dSDavid C Somayajulu 	int ret = 0;
65111e25f0dSDavid C Somayajulu 
65211e25f0dSDavid C Somayajulu 	if ((nvram->data == NULL) || (nvram->data_len == 0))
65311e25f0dSDavid C Somayajulu 		return (EINVAL);
65411e25f0dSDavid C Somayajulu 
65511e25f0dSDavid C Somayajulu 	buf = qlnx_zalloc(nvram->data_len);
65611e25f0dSDavid C Somayajulu 
65711e25f0dSDavid C Somayajulu 
65811e25f0dSDavid C Somayajulu 	ret = ecore_mcp_nvm_resp(&ha->cdev, buf);
65911e25f0dSDavid C Somayajulu 
660*7a377fbeSDavid C Somayajulu 	QL_DPRINT9(ha, "data = %p data_len = 0x%x \
661*7a377fbeSDavid C Somayajulu 		 resp = 0x%x ret = 0x%x exit\n",
662*7a377fbeSDavid C Somayajulu 		nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret);
66311e25f0dSDavid C Somayajulu 
66411e25f0dSDavid C Somayajulu 	if (ret == 0) {
66511e25f0dSDavid C Somayajulu 		ret = copyout(buf, nvram->data, nvram->data_len);
66611e25f0dSDavid C Somayajulu 	}
66711e25f0dSDavid C Somayajulu 
66811e25f0dSDavid C Somayajulu 	free(buf, M_QLNXBUF);
66911e25f0dSDavid C Somayajulu 
67011e25f0dSDavid C Somayajulu 	return (ret);
67111e25f0dSDavid C Somayajulu }
67211e25f0dSDavid C Somayajulu 
67311e25f0dSDavid C Somayajulu static int
67411e25f0dSDavid C Somayajulu qlnx_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram)
67511e25f0dSDavid C Somayajulu {
67611e25f0dSDavid C Somayajulu 	int ret = 0;
67711e25f0dSDavid C Somayajulu 
67811e25f0dSDavid C Somayajulu 	switch (nvram->cmd) {
67911e25f0dSDavid C Somayajulu 
68011e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_WRITE_NVRAM:
68111e25f0dSDavid C Somayajulu 		ret = qlnx_write_nvram(ha, nvram, ECORE_NVM_WRITE_NVRAM);
68211e25f0dSDavid C Somayajulu 		break;
68311e25f0dSDavid C Somayajulu 
68411e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_PUT_FILE_DATA:
68511e25f0dSDavid C Somayajulu 		ret = qlnx_write_nvram(ha, nvram, ECORE_PUT_FILE_DATA);
68611e25f0dSDavid C Somayajulu 		break;
68711e25f0dSDavid C Somayajulu 
68811e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_READ_NVRAM:
68911e25f0dSDavid C Somayajulu 		ret = qlnx_read_nvram(ha, nvram);
69011e25f0dSDavid C Somayajulu 		break;
69111e25f0dSDavid C Somayajulu 
69211e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_SET_SECURE_MODE:
69311e25f0dSDavid C Somayajulu 		ret = ecore_mcp_nvm_set_secure_mode(&ha->cdev, nvram->offset);
69411e25f0dSDavid C Somayajulu 
695*7a377fbeSDavid C Somayajulu 		QL_DPRINT9(ha, "QLNX_NVRAM_CMD_SET_SECURE_MODE \
696*7a377fbeSDavid C Somayajulu 			 resp = 0x%x ret = 0x%x exit\n",
697*7a377fbeSDavid C Somayajulu 			 ha->cdev.mcp_nvm_resp, ret);
69811e25f0dSDavid C Somayajulu 		break;
69911e25f0dSDavid C Somayajulu 
70011e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_DEL_FILE:
70111e25f0dSDavid C Somayajulu 		ret = ecore_mcp_nvm_del_file(&ha->cdev, nvram->offset);
70211e25f0dSDavid C Somayajulu 
703*7a377fbeSDavid C Somayajulu 		QL_DPRINT9(ha, "QLNX_NVRAM_CMD_DEL_FILE \
704*7a377fbeSDavid C Somayajulu 			 resp = 0x%x ret = 0x%x exit\n",
705*7a377fbeSDavid C Somayajulu 			ha->cdev.mcp_nvm_resp, ret);
70611e25f0dSDavid C Somayajulu 		break;
70711e25f0dSDavid C Somayajulu 
70811e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_PUT_FILE_BEGIN:
70911e25f0dSDavid C Somayajulu 		ret = ecore_mcp_nvm_put_file_begin(&ha->cdev, nvram->offset);
71011e25f0dSDavid C Somayajulu 
711*7a377fbeSDavid C Somayajulu 		QL_DPRINT9(ha, "QLNX_NVRAM_CMD_PUT_FILE_BEGIN \
712*7a377fbeSDavid C Somayajulu 			 resp = 0x%x ret = 0x%x exit\n",
713*7a377fbeSDavid C Somayajulu 			ha->cdev.mcp_nvm_resp, ret);
71411e25f0dSDavid C Somayajulu 		break;
71511e25f0dSDavid C Somayajulu 
71611e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_GET_NVRAM_RESP:
71711e25f0dSDavid C Somayajulu 		ret = qlnx_get_nvram_resp(ha, nvram);
71811e25f0dSDavid C Somayajulu 		break;
71911e25f0dSDavid C Somayajulu 
72011e25f0dSDavid C Somayajulu 	default:
72111e25f0dSDavid C Somayajulu 		ret = EINVAL;
72211e25f0dSDavid C Somayajulu 		break;
72311e25f0dSDavid C Somayajulu 	}
72411e25f0dSDavid C Somayajulu 
72511e25f0dSDavid C Somayajulu 	return (ret);
72611e25f0dSDavid C Somayajulu }
72711e25f0dSDavid C Somayajulu 
72811e25f0dSDavid C Somayajulu static void
72911e25f0dSDavid C Somayajulu qlnx_storm_stats(qlnx_host_t *ha, qlnx_storm_stats_dump_t *s_stats)
73011e25f0dSDavid C Somayajulu {
73111e25f0dSDavid C Somayajulu 	int i;
73211e25f0dSDavid C Somayajulu 	int index;
73311e25f0dSDavid C Somayajulu 	int ret;
73411e25f0dSDavid C Somayajulu 	int stats_copied = 0;
73511e25f0dSDavid C Somayajulu 
73611e25f0dSDavid C Somayajulu 	s_stats->num_hwfns = ha->cdev.num_hwfns;
73711e25f0dSDavid C Somayajulu 
73811e25f0dSDavid C Somayajulu //	if (ha->storm_stats_index < QLNX_STORM_STATS_SAMPLES_PER_HWFN)
73911e25f0dSDavid C Somayajulu //		return;
74011e25f0dSDavid C Somayajulu 
74111e25f0dSDavid C Somayajulu 	s_stats->num_samples = ha->storm_stats_index;
74211e25f0dSDavid C Somayajulu 
74311e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
74411e25f0dSDavid C Somayajulu 
74511e25f0dSDavid C Somayajulu 		index = (QLNX_STORM_STATS_SAMPLES_PER_HWFN * i);
74611e25f0dSDavid C Somayajulu 
74711e25f0dSDavid C Somayajulu 		if (s_stats->buffer[i]) {
74811e25f0dSDavid C Somayajulu 
74911e25f0dSDavid C Somayajulu 			ret = copyout(&ha->storm_stats[index],
75011e25f0dSDavid C Somayajulu 					s_stats->buffer[i],
75111e25f0dSDavid C Somayajulu 					QLNX_STORM_STATS_BYTES_PER_HWFN);
75211e25f0dSDavid C Somayajulu 			if (ret) {
75311e25f0dSDavid C Somayajulu 				printf("%s [%d]: failed\n", __func__, i);
75411e25f0dSDavid C Somayajulu 			}
75511e25f0dSDavid C Somayajulu 
75611e25f0dSDavid C Somayajulu 			if (s_stats->num_samples ==
75711e25f0dSDavid C Somayajulu 				QLNX_STORM_STATS_SAMPLES_PER_HWFN) {
75811e25f0dSDavid C Somayajulu 
75911e25f0dSDavid C Somayajulu 				bzero((void *)&ha->storm_stats[i],
76011e25f0dSDavid C Somayajulu 					QLNX_STORM_STATS_BYTES_PER_HWFN);
76111e25f0dSDavid C Somayajulu 
76211e25f0dSDavid C Somayajulu 				stats_copied = 1;
76311e25f0dSDavid C Somayajulu 			}
76411e25f0dSDavid C Somayajulu 		}
76511e25f0dSDavid C Somayajulu 	}
76611e25f0dSDavid C Somayajulu 
76711e25f0dSDavid C Somayajulu 	if (stats_copied)
76811e25f0dSDavid C Somayajulu 		ha->storm_stats_index = 0;
76911e25f0dSDavid C Somayajulu 
77011e25f0dSDavid C Somayajulu 	return;
77111e25f0dSDavid C Somayajulu }
77211e25f0dSDavid C Somayajulu 
77311e25f0dSDavid C Somayajulu 
77411e25f0dSDavid C Somayajulu static int
77511e25f0dSDavid C Somayajulu qlnx_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
77611e25f0dSDavid C Somayajulu 	struct thread *td)
77711e25f0dSDavid C Somayajulu {
77811e25f0dSDavid C Somayajulu 	qlnx_host_t	*ha;
77911e25f0dSDavid C Somayajulu 	int		rval = 0;
78011e25f0dSDavid C Somayajulu 	struct ifnet	*ifp;
78111e25f0dSDavid C Somayajulu 	qlnx_trace_t	*trace;
78211e25f0dSDavid C Somayajulu 	int		i;
78311e25f0dSDavid C Somayajulu 
78411e25f0dSDavid C Somayajulu 	if ((ha = (qlnx_host_t *)dev->si_drv1) == NULL)
78511e25f0dSDavid C Somayajulu 		return ENXIO;
78611e25f0dSDavid C Somayajulu 
78711e25f0dSDavid C Somayajulu 	ifp = ha->ifp;
78811e25f0dSDavid C Somayajulu 
78911e25f0dSDavid C Somayajulu 	switch (cmd) {
79011e25f0dSDavid C Somayajulu 
79111e25f0dSDavid C Somayajulu 	case QLNX_GRC_DUMP_SIZE:
79211e25f0dSDavid C Somayajulu 		qlnx_get_grc_dump_size(ha, (qlnx_grcdump_t *)data);
79311e25f0dSDavid C Somayajulu 		break;
79411e25f0dSDavid C Somayajulu 
79511e25f0dSDavid C Somayajulu 	case QLNX_GRC_DUMP:
79611e25f0dSDavid C Somayajulu 		rval = qlnx_get_grc_dump(ha, (qlnx_grcdump_t *)data);
79711e25f0dSDavid C Somayajulu 		break;
79811e25f0dSDavid C Somayajulu 
79911e25f0dSDavid C Somayajulu 	case QLNX_IDLE_CHK_SIZE:
80011e25f0dSDavid C Somayajulu 		qlnx_get_idle_chk_size(ha, (qlnx_idle_chk_t *)data);
80111e25f0dSDavid C Somayajulu 		break;
80211e25f0dSDavid C Somayajulu 
80311e25f0dSDavid C Somayajulu 	case QLNX_IDLE_CHK:
80411e25f0dSDavid C Somayajulu 		rval = qlnx_get_idle_chk(ha, (qlnx_idle_chk_t *)data);
80511e25f0dSDavid C Somayajulu 		break;
80611e25f0dSDavid C Somayajulu 
80711e25f0dSDavid C Somayajulu 	case QLNX_DRV_INFO:
80811e25f0dSDavid C Somayajulu 		rval = qlnx_drv_info(ha, (qlnx_drvinfo_t *)data);
80911e25f0dSDavid C Somayajulu 		break;
81011e25f0dSDavid C Somayajulu 
81111e25f0dSDavid C Somayajulu 	case QLNX_DEV_SETTING:
81211e25f0dSDavid C Somayajulu 		rval = qlnx_dev_settings(ha, (qlnx_dev_setting_t *)data);
81311e25f0dSDavid C Somayajulu 		break;
81411e25f0dSDavid C Somayajulu 
81511e25f0dSDavid C Somayajulu 	case QLNX_GET_REGS:
81611e25f0dSDavid C Somayajulu 		rval = qlnx_get_regs(ha, (qlnx_get_regs_t *)data);
81711e25f0dSDavid C Somayajulu 		break;
81811e25f0dSDavid C Somayajulu 
81911e25f0dSDavid C Somayajulu 	case QLNX_NVRAM:
82011e25f0dSDavid C Somayajulu 		rval = qlnx_nvram(ha, (qlnx_nvram_t *)data);
82111e25f0dSDavid C Somayajulu 		break;
82211e25f0dSDavid C Somayajulu 
82311e25f0dSDavid C Somayajulu 	case QLNX_RD_WR_REG:
82411e25f0dSDavid C Somayajulu 		rval = qlnx_reg_rd_wr(ha, (qlnx_reg_rd_wr_t *)data);
82511e25f0dSDavid C Somayajulu 		break;
82611e25f0dSDavid C Somayajulu 
82711e25f0dSDavid C Somayajulu 	case QLNX_RD_WR_PCICFG:
82811e25f0dSDavid C Somayajulu 		rval = qlnx_rd_wr_pci_config(ha, (qlnx_pcicfg_rd_wr_t *)data);
82911e25f0dSDavid C Somayajulu 		break;
83011e25f0dSDavid C Somayajulu 
83111e25f0dSDavid C Somayajulu 	case QLNX_MAC_ADDR:
83211e25f0dSDavid C Somayajulu 		qlnx_mac_addr(ha, (qlnx_perm_mac_addr_t *)data);
83311e25f0dSDavid C Somayajulu 		break;
83411e25f0dSDavid C Somayajulu 
83511e25f0dSDavid C Somayajulu 	case QLNX_STORM_STATS:
83611e25f0dSDavid C Somayajulu 		qlnx_storm_stats(ha, (qlnx_storm_stats_dump_t *)data);
83711e25f0dSDavid C Somayajulu 		break;
83811e25f0dSDavid C Somayajulu 
83911e25f0dSDavid C Somayajulu 	case QLNX_TRACE_SIZE:
84011e25f0dSDavid C Somayajulu 		qlnx_get_trace_size(ha, (qlnx_trace_t *)data);
84111e25f0dSDavid C Somayajulu 		break;
84211e25f0dSDavid C Somayajulu 
84311e25f0dSDavid C Somayajulu 	case QLNX_TRACE:
84411e25f0dSDavid C Somayajulu 		trace = (qlnx_trace_t *)data;
84511e25f0dSDavid C Somayajulu 
84611e25f0dSDavid C Somayajulu 		for (i = 0; i < ha->cdev.num_hwfns; i++) {
84711e25f0dSDavid C Somayajulu 
84811e25f0dSDavid C Somayajulu 			if (trace->size[i] && trace->cmd && trace->buffer[i])
84911e25f0dSDavid C Somayajulu 				rval = qlnx_get_trace(ha, i, trace);
85011e25f0dSDavid C Somayajulu 
85111e25f0dSDavid C Somayajulu 			if (rval)
85211e25f0dSDavid C Somayajulu 				break;
85311e25f0dSDavid C Somayajulu 		}
85411e25f0dSDavid C Somayajulu 		break;
85511e25f0dSDavid C Somayajulu 
85611e25f0dSDavid C Somayajulu 	default:
85711e25f0dSDavid C Somayajulu 		rval = EINVAL;
85811e25f0dSDavid C Somayajulu 		break;
85911e25f0dSDavid C Somayajulu 	}
86011e25f0dSDavid C Somayajulu 
86111e25f0dSDavid C Somayajulu 	return (rval);
86211e25f0dSDavid C Somayajulu }
86311e25f0dSDavid C Somayajulu 
864