xref: /freebsd/sys/dev/qlnx/qlnxe/qlnx_ioctl.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
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  * File: qlnx_ioctl.c
3011e25f0dSDavid C Somayajulu  * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
3111e25f0dSDavid C Somayajulu  */
3211e25f0dSDavid C Somayajulu 
3311e25f0dSDavid C Somayajulu #include <sys/cdefs.h>
3411e25f0dSDavid C Somayajulu #include "qlnx_os.h"
3511e25f0dSDavid C Somayajulu #include "bcm_osal.h"
3611e25f0dSDavid C Somayajulu 
3711e25f0dSDavid C Somayajulu #include "reg_addr.h"
3811e25f0dSDavid C Somayajulu #include "ecore_gtt_reg_addr.h"
3911e25f0dSDavid C Somayajulu #include "ecore.h"
4011e25f0dSDavid C Somayajulu #include "ecore_chain.h"
4111e25f0dSDavid C Somayajulu #include "ecore_status.h"
4211e25f0dSDavid C Somayajulu #include "ecore_hw.h"
4311e25f0dSDavid C Somayajulu #include "ecore_rt_defs.h"
4411e25f0dSDavid C Somayajulu #include "ecore_init_ops.h"
4511e25f0dSDavid C Somayajulu #include "ecore_int.h"
4611e25f0dSDavid C Somayajulu #include "ecore_cxt.h"
4711e25f0dSDavid C Somayajulu #include "ecore_spq.h"
4811e25f0dSDavid C Somayajulu #include "ecore_init_fw_funcs.h"
4911e25f0dSDavid C Somayajulu #include "ecore_sp_commands.h"
5011e25f0dSDavid C Somayajulu #include "ecore_dev_api.h"
5111e25f0dSDavid C Somayajulu #include "ecore_l2_api.h"
5211e25f0dSDavid C Somayajulu #include "ecore_mcp.h"
5311e25f0dSDavid C Somayajulu #include "ecore_hw_defs.h"
5411e25f0dSDavid C Somayajulu #include "mcp_public.h"
5511e25f0dSDavid C Somayajulu #include "ecore_iro.h"
5611e25f0dSDavid C Somayajulu #include "nvm_cfg.h"
5711e25f0dSDavid C Somayajulu #include "ecore_dev_api.h"
5811e25f0dSDavid C Somayajulu #include "ecore_dbg_fw_funcs.h"
59217ec208SDavid C Somayajulu #include "ecore_dcbx_api.h"
6011e25f0dSDavid C Somayajulu 
6111e25f0dSDavid C Somayajulu #include "qlnx_ioctl.h"
6211e25f0dSDavid C Somayajulu #include "qlnx_def.h"
6311e25f0dSDavid C Somayajulu #include "qlnx_ver.h"
6411e25f0dSDavid C Somayajulu #include <sys/smp.h>
6511e25f0dSDavid C Somayajulu 
6611e25f0dSDavid C Somayajulu static int qlnx_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
6711e25f0dSDavid C Somayajulu                 struct thread *td);
6811e25f0dSDavid C Somayajulu 
6911e25f0dSDavid C Somayajulu static struct cdevsw qlnx_cdevsw = {
7011e25f0dSDavid C Somayajulu         .d_version = D_VERSION,
7111e25f0dSDavid C Somayajulu         .d_ioctl = qlnx_eioctl,
7211e25f0dSDavid C Somayajulu         .d_name = "qlnxioctl",
7311e25f0dSDavid C Somayajulu };
7411e25f0dSDavid C Somayajulu 
7511e25f0dSDavid C Somayajulu int
qlnx_make_cdev(qlnx_host_t * ha)7611e25f0dSDavid C Somayajulu qlnx_make_cdev(qlnx_host_t *ha)
7711e25f0dSDavid C Somayajulu {
7811e25f0dSDavid C Somayajulu 	ha->ioctl_dev = make_dev(&qlnx_cdevsw,
79*727bfe38SJustin Hibbits 				if_getdunit(ha->ifp),
8011e25f0dSDavid C Somayajulu 				UID_ROOT,
8111e25f0dSDavid C Somayajulu 				GID_WHEEL,
8211e25f0dSDavid C Somayajulu 				0600,
8311e25f0dSDavid C Somayajulu 				"%s",
8411e25f0dSDavid C Somayajulu 				if_name(ha->ifp));
8511e25f0dSDavid C Somayajulu 
8611e25f0dSDavid C Somayajulu 	if (ha->ioctl_dev == NULL)
8711e25f0dSDavid C Somayajulu 		return (-1);
8811e25f0dSDavid C Somayajulu 
8911e25f0dSDavid C Somayajulu 	ha->ioctl_dev->si_drv1 = ha;
9011e25f0dSDavid C Somayajulu 
9111e25f0dSDavid C Somayajulu 	return (0);
9211e25f0dSDavid C Somayajulu }
9311e25f0dSDavid C Somayajulu 
9411e25f0dSDavid C Somayajulu void
qlnx_del_cdev(qlnx_host_t * ha)9511e25f0dSDavid C Somayajulu qlnx_del_cdev(qlnx_host_t *ha)
9611e25f0dSDavid C Somayajulu {
9711e25f0dSDavid C Somayajulu 	if (ha->ioctl_dev != NULL)
9811e25f0dSDavid C Somayajulu 		destroy_dev(ha->ioctl_dev);
9911e25f0dSDavid C Somayajulu 	return;
10011e25f0dSDavid C Somayajulu }
10111e25f0dSDavid C Somayajulu 
10211e25f0dSDavid C Somayajulu int
qlnx_grc_dump(qlnx_host_t * ha,uint32_t * num_dumped_dwords,int hwfn_index)10311e25f0dSDavid C Somayajulu qlnx_grc_dump(qlnx_host_t *ha, uint32_t *num_dumped_dwords, int hwfn_index)
10411e25f0dSDavid C Somayajulu {
10511e25f0dSDavid C Somayajulu 	int rval = EINVAL;
10611e25f0dSDavid C Somayajulu 	struct ecore_hwfn *p_hwfn;
10711e25f0dSDavid C Somayajulu 	struct ecore_ptt *p_ptt;
10811e25f0dSDavid C Somayajulu 
10911e25f0dSDavid C Somayajulu 	if (ha->grcdump_dwords[hwfn_index]) {
11011e25f0dSDavid C Somayajulu 		/* the grcdump is already available */
11111e25f0dSDavid C Somayajulu 		*num_dumped_dwords = ha->grcdump_dwords[hwfn_index];
11211e25f0dSDavid C Somayajulu 		return (0);
11311e25f0dSDavid C Somayajulu 	}
11411e25f0dSDavid C Somayajulu 
11511e25f0dSDavid C Somayajulu 	ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver());
11611e25f0dSDavid C Somayajulu 
11711e25f0dSDavid C Somayajulu 	p_hwfn = &ha->cdev.hwfns[hwfn_index];
11811e25f0dSDavid C Somayajulu 	p_ptt = ecore_ptt_acquire(p_hwfn);
11911e25f0dSDavid C Somayajulu 
12011e25f0dSDavid C Somayajulu 	if (!p_ptt) {
1217a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha,"ecore_ptt_acquire failed\n");
12211e25f0dSDavid C Somayajulu 		return (rval);
12311e25f0dSDavid C Somayajulu 	}
12411e25f0dSDavid C Somayajulu 
12511e25f0dSDavid C Somayajulu 	if ((rval = ecore_dbg_grc_dump(p_hwfn, p_ptt,
12611e25f0dSDavid C Somayajulu 			ha->grcdump[hwfn_index],
12711e25f0dSDavid C Somayajulu 			(ha->grcdump_size[hwfn_index] >> 2),
12811e25f0dSDavid C Somayajulu 			num_dumped_dwords)) == DBG_STATUS_OK) {
12911e25f0dSDavid C Somayajulu 	 	rval = 0;
13011e25f0dSDavid C Somayajulu 		ha->grcdump_taken = 1;
13111e25f0dSDavid C Somayajulu 	} else
1327a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha,"ecore_dbg_grc_dump failed [%d, 0x%x]\n",
1337a377fbeSDavid C Somayajulu 			   hwfn_index, rval);
13411e25f0dSDavid C Somayajulu 
13511e25f0dSDavid C Somayajulu 	ecore_ptt_release(p_hwfn, p_ptt);
13611e25f0dSDavid C Somayajulu 
13711e25f0dSDavid C Somayajulu 	return (rval);
13811e25f0dSDavid C Somayajulu }
13911e25f0dSDavid C Somayajulu 
14011e25f0dSDavid C Somayajulu static void
qlnx_get_grc_dump_size(qlnx_host_t * ha,qlnx_grcdump_t * grcdump)14111e25f0dSDavid C Somayajulu qlnx_get_grc_dump_size(qlnx_host_t *ha, qlnx_grcdump_t *grcdump)
14211e25f0dSDavid C Somayajulu {
14311e25f0dSDavid C Somayajulu 	int i;
14411e25f0dSDavid C Somayajulu 
14511e25f0dSDavid C Somayajulu 	grcdump->pci_func = ha->pci_func;
14611e25f0dSDavid C Somayajulu 
14711e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++)
14811e25f0dSDavid C Somayajulu 		grcdump->grcdump_size[i] = ha->grcdump_size[i];
14911e25f0dSDavid C Somayajulu 
15011e25f0dSDavid C Somayajulu 	return;
15111e25f0dSDavid C Somayajulu }
15211e25f0dSDavid C Somayajulu 
15311e25f0dSDavid C Somayajulu static int
qlnx_get_grc_dump(qlnx_host_t * ha,qlnx_grcdump_t * grcdump)15411e25f0dSDavid C Somayajulu qlnx_get_grc_dump(qlnx_host_t *ha, qlnx_grcdump_t *grcdump)
15511e25f0dSDavid C Somayajulu {
15611e25f0dSDavid C Somayajulu 	int		i;
15711e25f0dSDavid C Somayajulu 	int		rval = 0;
15811e25f0dSDavid C Somayajulu 	uint32_t	dwords = 0;
15911e25f0dSDavid C Somayajulu 
16011e25f0dSDavid C Somayajulu 	grcdump->pci_func = ha->pci_func;
16111e25f0dSDavid C Somayajulu 
16211e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
16311e25f0dSDavid C Somayajulu 		if ((ha->grcdump[i] == NULL) || (grcdump->grcdump[i] == NULL) ||
16411e25f0dSDavid C Somayajulu 			(grcdump->grcdump_size[i] < ha->grcdump_size[i]))
16511e25f0dSDavid C Somayajulu 			return (EINVAL);
16611e25f0dSDavid C Somayajulu 
16711e25f0dSDavid C Somayajulu 		rval = qlnx_grc_dump(ha, &dwords, i);
16811e25f0dSDavid C Somayajulu 
16911e25f0dSDavid C Somayajulu 		if (rval)
17011e25f0dSDavid C Somayajulu 			break;
17111e25f0dSDavid C Somayajulu 
17211e25f0dSDavid C Somayajulu 		grcdump->grcdump_dwords[i] = dwords;
17311e25f0dSDavid C Somayajulu 
1747a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha,"grcdump_dwords[%d] = 0x%x\n", i, dwords);
17511e25f0dSDavid C Somayajulu 
17611e25f0dSDavid C Somayajulu 		rval = copyout(ha->grcdump[i], grcdump->grcdump[i],
17711e25f0dSDavid C Somayajulu 				ha->grcdump_size[i]);
17811e25f0dSDavid C Somayajulu 
17911e25f0dSDavid C Somayajulu 		if (rval)
18011e25f0dSDavid C Somayajulu 			break;
18111e25f0dSDavid C Somayajulu 
18211e25f0dSDavid C Somayajulu 		ha->grcdump_dwords[i] = 0;
18311e25f0dSDavid C Somayajulu 	}
18411e25f0dSDavid C Somayajulu 
18511e25f0dSDavid C Somayajulu 	ha->grcdump_taken = 0;
18611e25f0dSDavid C Somayajulu 
18711e25f0dSDavid C Somayajulu 	return (rval);
18811e25f0dSDavid C Somayajulu }
18911e25f0dSDavid C Somayajulu 
19011e25f0dSDavid C Somayajulu int
qlnx_idle_chk(qlnx_host_t * ha,uint32_t * num_dumped_dwords,int hwfn_index)19111e25f0dSDavid C Somayajulu qlnx_idle_chk(qlnx_host_t *ha, uint32_t *num_dumped_dwords, int hwfn_index)
19211e25f0dSDavid C Somayajulu {
19311e25f0dSDavid C Somayajulu 	int rval = EINVAL;
19411e25f0dSDavid C Somayajulu 	struct ecore_hwfn *p_hwfn;
19511e25f0dSDavid C Somayajulu 	struct ecore_ptt *p_ptt;
19611e25f0dSDavid C Somayajulu 
19711e25f0dSDavid C Somayajulu 	if (ha->idle_chk_dwords[hwfn_index]) {
19811e25f0dSDavid C Somayajulu 		/* the idle check is already available */
19911e25f0dSDavid C Somayajulu 		*num_dumped_dwords = ha->idle_chk_dwords[hwfn_index];
20011e25f0dSDavid C Somayajulu 		return (0);
20111e25f0dSDavid C Somayajulu 	}
20211e25f0dSDavid C Somayajulu 
20311e25f0dSDavid C Somayajulu 	ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver());
20411e25f0dSDavid C Somayajulu 
20511e25f0dSDavid C Somayajulu 	p_hwfn = &ha->cdev.hwfns[hwfn_index];
20611e25f0dSDavid C Somayajulu 	p_ptt = ecore_ptt_acquire(p_hwfn);
20711e25f0dSDavid C Somayajulu 
20811e25f0dSDavid C Somayajulu 	if (!p_ptt) {
2097a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha,"ecore_ptt_acquire failed\n");
21011e25f0dSDavid C Somayajulu 		return (rval);
21111e25f0dSDavid C Somayajulu 	}
21211e25f0dSDavid C Somayajulu 
21311e25f0dSDavid C Somayajulu 	if ((rval = ecore_dbg_idle_chk_dump(p_hwfn, p_ptt,
21411e25f0dSDavid C Somayajulu 			ha->idle_chk[hwfn_index],
21511e25f0dSDavid C Somayajulu 			(ha->idle_chk_size[hwfn_index] >> 2),
21611e25f0dSDavid C Somayajulu 			num_dumped_dwords)) == DBG_STATUS_OK) {
21711e25f0dSDavid C Somayajulu 	 	rval = 0;
21811e25f0dSDavid C Somayajulu 		ha->idle_chk_taken = 1;
21911e25f0dSDavid C Somayajulu 	} else
2207a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha,"ecore_dbg_idle_chk_dump failed [%d, 0x%x]\n",
2217a377fbeSDavid C Somayajulu 			   hwfn_index, rval);
22211e25f0dSDavid C Somayajulu 
22311e25f0dSDavid C Somayajulu 	ecore_ptt_release(p_hwfn, p_ptt);
22411e25f0dSDavid C Somayajulu 
22511e25f0dSDavid C Somayajulu 	return (rval);
22611e25f0dSDavid C Somayajulu }
22711e25f0dSDavid C Somayajulu 
22811e25f0dSDavid C Somayajulu static void
qlnx_get_idle_chk_size(qlnx_host_t * ha,qlnx_idle_chk_t * idle_chk)22911e25f0dSDavid C Somayajulu qlnx_get_idle_chk_size(qlnx_host_t *ha, qlnx_idle_chk_t *idle_chk)
23011e25f0dSDavid C Somayajulu {
23111e25f0dSDavid C Somayajulu 	int i;
23211e25f0dSDavid C Somayajulu 
23311e25f0dSDavid C Somayajulu 	idle_chk->pci_func = ha->pci_func;
23411e25f0dSDavid C Somayajulu 
23511e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++)
23611e25f0dSDavid C Somayajulu 		idle_chk->idle_chk_size[i] = ha->idle_chk_size[i];
23711e25f0dSDavid C Somayajulu 
23811e25f0dSDavid C Somayajulu 	return;
23911e25f0dSDavid C Somayajulu }
24011e25f0dSDavid C Somayajulu 
24111e25f0dSDavid C Somayajulu static int
qlnx_get_idle_chk(qlnx_host_t * ha,qlnx_idle_chk_t * idle_chk)24211e25f0dSDavid C Somayajulu qlnx_get_idle_chk(qlnx_host_t *ha, qlnx_idle_chk_t *idle_chk)
24311e25f0dSDavid C Somayajulu {
24411e25f0dSDavid C Somayajulu 	int		i;
24511e25f0dSDavid C Somayajulu 	int		rval = 0;
24611e25f0dSDavid C Somayajulu 	uint32_t	dwords = 0;
24711e25f0dSDavid C Somayajulu 
24811e25f0dSDavid C Somayajulu 	idle_chk->pci_func = ha->pci_func;
24911e25f0dSDavid C Somayajulu 
25011e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
25111e25f0dSDavid C Somayajulu 		if ((ha->idle_chk[i] == NULL) ||
25211e25f0dSDavid C Somayajulu 				(idle_chk->idle_chk[i] == NULL) ||
25311e25f0dSDavid C Somayajulu 				(idle_chk->idle_chk_size[i] <
25411e25f0dSDavid C Somayajulu 					ha->idle_chk_size[i]))
25511e25f0dSDavid C Somayajulu 			return (EINVAL);
25611e25f0dSDavid C Somayajulu 
25711e25f0dSDavid C Somayajulu 		rval = qlnx_idle_chk(ha, &dwords, i);
25811e25f0dSDavid C Somayajulu 
25911e25f0dSDavid C Somayajulu 		if (rval)
26011e25f0dSDavid C Somayajulu 			break;
26111e25f0dSDavid C Somayajulu 
26211e25f0dSDavid C Somayajulu 		idle_chk->idle_chk_dwords[i] = dwords;
26311e25f0dSDavid C Somayajulu 
2647a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha,"idle_chk_dwords[%d] = 0x%x\n", i, dwords);
26511e25f0dSDavid C Somayajulu 
26611e25f0dSDavid C Somayajulu                	rval = copyout(ha->idle_chk[i], idle_chk->idle_chk[i],
26711e25f0dSDavid C Somayajulu 				ha->idle_chk_size[i]);
26811e25f0dSDavid C Somayajulu 
26911e25f0dSDavid C Somayajulu 		if (rval)
27011e25f0dSDavid C Somayajulu 			break;
27111e25f0dSDavid C Somayajulu 
27211e25f0dSDavid C Somayajulu 		ha->idle_chk_dwords[i] = 0;
27311e25f0dSDavid C Somayajulu 	}
27411e25f0dSDavid C Somayajulu 	ha->idle_chk_taken = 0;
27511e25f0dSDavid C Somayajulu 
27611e25f0dSDavid C Somayajulu 	return (rval);
27711e25f0dSDavid C Somayajulu }
27811e25f0dSDavid C Somayajulu 
27911e25f0dSDavid C Somayajulu static uint32_t
qlnx_get_trace_cmd_size(qlnx_host_t * ha,int hwfn_index,uint16_t cmd)28011e25f0dSDavid C Somayajulu qlnx_get_trace_cmd_size(qlnx_host_t *ha, int hwfn_index, uint16_t cmd)
28111e25f0dSDavid C Somayajulu {
28211e25f0dSDavid C Somayajulu         int rval = -1;
28311e25f0dSDavid C Somayajulu         struct ecore_hwfn *p_hwfn;
28411e25f0dSDavid C Somayajulu         struct ecore_ptt *p_ptt;
28511e25f0dSDavid C Somayajulu 	uint32_t num_dwords = 0;
28611e25f0dSDavid C Somayajulu 
28711e25f0dSDavid C Somayajulu         p_hwfn = &ha->cdev.hwfns[hwfn_index];
28811e25f0dSDavid C Somayajulu         p_ptt = ecore_ptt_acquire(p_hwfn);
28911e25f0dSDavid C Somayajulu 
29011e25f0dSDavid C Somayajulu         if (!p_ptt) {
2917a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha, "ecore_ptt_acquire [%d, 0x%x]failed\n",
2927a377fbeSDavid C Somayajulu                            hwfn_index, cmd);
29311e25f0dSDavid C Somayajulu                 return (0);
29411e25f0dSDavid C Somayajulu         }
29511e25f0dSDavid C Somayajulu 
29611e25f0dSDavid C Somayajulu 	switch (cmd) {
29711e25f0dSDavid C Somayajulu 	case QLNX_MCP_TRACE:
29811e25f0dSDavid C Somayajulu         	rval = ecore_dbg_mcp_trace_get_dump_buf_size(p_hwfn,
29911e25f0dSDavid C Somayajulu 				p_ptt, &num_dwords);
30011e25f0dSDavid C Somayajulu 		break;
30111e25f0dSDavid C Somayajulu 
30211e25f0dSDavid C Somayajulu 	case QLNX_REG_FIFO:
30311e25f0dSDavid C Somayajulu         	rval = ecore_dbg_reg_fifo_get_dump_buf_size(p_hwfn,
30411e25f0dSDavid C Somayajulu 				p_ptt, &num_dwords);
30511e25f0dSDavid C Somayajulu 		break;
30611e25f0dSDavid C Somayajulu 
30711e25f0dSDavid C Somayajulu 	case QLNX_IGU_FIFO:
30811e25f0dSDavid C Somayajulu         	rval = ecore_dbg_igu_fifo_get_dump_buf_size(p_hwfn,
30911e25f0dSDavid C Somayajulu 				p_ptt, &num_dwords);
31011e25f0dSDavid C Somayajulu 		break;
31111e25f0dSDavid C Somayajulu 
31211e25f0dSDavid C Somayajulu 	case QLNX_PROTECTION_OVERRIDE:
31311e25f0dSDavid C Somayajulu         	rval = ecore_dbg_protection_override_get_dump_buf_size(p_hwfn,
31411e25f0dSDavid C Somayajulu 				p_ptt, &num_dwords);
31511e25f0dSDavid C Somayajulu 		break;
31611e25f0dSDavid C Somayajulu 
31711e25f0dSDavid C Somayajulu 	case QLNX_FW_ASSERTS:
31811e25f0dSDavid C Somayajulu         	rval = ecore_dbg_fw_asserts_get_dump_buf_size(p_hwfn,
31911e25f0dSDavid C Somayajulu 				p_ptt, &num_dwords);
32011e25f0dSDavid C Somayajulu 		break;
32111e25f0dSDavid C Somayajulu 	}
32211e25f0dSDavid C Somayajulu 
32311e25f0dSDavid C Somayajulu         if (rval != DBG_STATUS_OK) {
3247a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha,"cmd = 0x%x failed [0x%x]\n", cmd, rval);
32511e25f0dSDavid C Somayajulu 		num_dwords = 0;
32611e25f0dSDavid C Somayajulu         }
32711e25f0dSDavid C Somayajulu 
32811e25f0dSDavid C Somayajulu         ecore_ptt_release(p_hwfn, p_ptt);
32911e25f0dSDavid C Somayajulu 
33011e25f0dSDavid C Somayajulu         return ((num_dwords * sizeof (uint32_t)));
33111e25f0dSDavid C Somayajulu }
33211e25f0dSDavid C Somayajulu 
33311e25f0dSDavid C Somayajulu static void
qlnx_get_trace_size(qlnx_host_t * ha,qlnx_trace_t * trace)33411e25f0dSDavid C Somayajulu qlnx_get_trace_size(qlnx_host_t *ha, qlnx_trace_t *trace)
33511e25f0dSDavid C Somayajulu {
33611e25f0dSDavid C Somayajulu 	int i;
33711e25f0dSDavid C Somayajulu 
33811e25f0dSDavid C Somayajulu 	trace->pci_func = ha->pci_func;
33911e25f0dSDavid C Somayajulu 
34011e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
34111e25f0dSDavid C Somayajulu 		trace->size[i] = qlnx_get_trace_cmd_size(ha, i, trace->cmd);
34211e25f0dSDavid C Somayajulu 	}
34311e25f0dSDavid C Somayajulu 
34411e25f0dSDavid C Somayajulu 	return;
34511e25f0dSDavid C Somayajulu }
34611e25f0dSDavid C Somayajulu 
34711e25f0dSDavid C Somayajulu static int
qlnx_get_trace(qlnx_host_t * ha,int hwfn_index,qlnx_trace_t * trace)34811e25f0dSDavid C Somayajulu qlnx_get_trace(qlnx_host_t *ha, int hwfn_index, qlnx_trace_t *trace)
34911e25f0dSDavid C Somayajulu {
35011e25f0dSDavid C Somayajulu         int rval = -1;
35111e25f0dSDavid C Somayajulu         struct ecore_hwfn *p_hwfn;
35211e25f0dSDavid C Somayajulu         struct ecore_ptt *p_ptt;
35311e25f0dSDavid C Somayajulu 	uint32_t num_dwords = 0;
35411e25f0dSDavid C Somayajulu 	void *buffer;
35511e25f0dSDavid C Somayajulu 
35611e25f0dSDavid C Somayajulu 	buffer = qlnx_zalloc(trace->size[hwfn_index]);
35711e25f0dSDavid C Somayajulu 	if (buffer == NULL) {
3587a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha,"qlnx_zalloc [%d, 0x%x]failed\n",
3597a377fbeSDavid C Somayajulu                            hwfn_index, trace->cmd);
36011e25f0dSDavid C Somayajulu                 return (ENXIO);
36111e25f0dSDavid C Somayajulu 	}
36211e25f0dSDavid C Somayajulu 	ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver());
36311e25f0dSDavid C Somayajulu 
36411e25f0dSDavid C Somayajulu         p_hwfn = &ha->cdev.hwfns[hwfn_index];
36511e25f0dSDavid C Somayajulu         p_ptt = ecore_ptt_acquire(p_hwfn);
36611e25f0dSDavid C Somayajulu 
36711e25f0dSDavid C Somayajulu         if (!p_ptt) {
3687a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha, "ecore_ptt_acquire [%d, 0x%x]failed\n",
3697a377fbeSDavid C Somayajulu                            hwfn_index, trace->cmd);
37011e25f0dSDavid C Somayajulu                 return (ENXIO);
37111e25f0dSDavid C Somayajulu         }
37211e25f0dSDavid C Somayajulu 
37311e25f0dSDavid C Somayajulu 	switch (trace->cmd) {
37411e25f0dSDavid C Somayajulu 	case QLNX_MCP_TRACE:
37511e25f0dSDavid C Somayajulu         	rval = ecore_dbg_mcp_trace_dump(p_hwfn, p_ptt,
37611e25f0dSDavid C Somayajulu 				buffer, (trace->size[hwfn_index] >> 2),
37711e25f0dSDavid C Somayajulu 				&num_dwords);
37811e25f0dSDavid C Somayajulu 		break;
37911e25f0dSDavid C Somayajulu 
38011e25f0dSDavid C Somayajulu 	case QLNX_REG_FIFO:
38111e25f0dSDavid C Somayajulu         	rval = ecore_dbg_reg_fifo_dump(p_hwfn, p_ptt,
38211e25f0dSDavid C Somayajulu 				buffer, (trace->size[hwfn_index] >> 2),
38311e25f0dSDavid C Somayajulu 				&num_dwords);
38411e25f0dSDavid C Somayajulu 		break;
38511e25f0dSDavid C Somayajulu 
38611e25f0dSDavid C Somayajulu 	case QLNX_IGU_FIFO:
38711e25f0dSDavid C Somayajulu         	rval = ecore_dbg_igu_fifo_dump(p_hwfn, p_ptt,
38811e25f0dSDavid C Somayajulu 				buffer, (trace->size[hwfn_index] >> 2),
38911e25f0dSDavid C Somayajulu 				&num_dwords);
39011e25f0dSDavid C Somayajulu 		break;
39111e25f0dSDavid C Somayajulu 
39211e25f0dSDavid C Somayajulu 	case QLNX_PROTECTION_OVERRIDE:
39311e25f0dSDavid C Somayajulu         	rval = ecore_dbg_protection_override_dump(p_hwfn, p_ptt,
39411e25f0dSDavid C Somayajulu 				buffer, (trace->size[hwfn_index] >> 2),
39511e25f0dSDavid C Somayajulu 				&num_dwords);
39611e25f0dSDavid C Somayajulu 		break;
39711e25f0dSDavid C Somayajulu 
39811e25f0dSDavid C Somayajulu 	case QLNX_FW_ASSERTS:
39911e25f0dSDavid C Somayajulu         	rval = ecore_dbg_fw_asserts_dump(p_hwfn, p_ptt,
40011e25f0dSDavid C Somayajulu 				buffer, (trace->size[hwfn_index] >> 2),
40111e25f0dSDavid C Somayajulu 				&num_dwords);
40211e25f0dSDavid C Somayajulu 		break;
40311e25f0dSDavid C Somayajulu 	}
40411e25f0dSDavid C Somayajulu 
40511e25f0dSDavid C Somayajulu         if (rval != DBG_STATUS_OK) {
4067a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha,"cmd = 0x%x failed [0x%x]\n", trace->cmd, rval);
40711e25f0dSDavid C Somayajulu 		num_dwords = 0;
40811e25f0dSDavid C Somayajulu         }
40911e25f0dSDavid C Somayajulu 
41011e25f0dSDavid C Somayajulu         ecore_ptt_release(p_hwfn, p_ptt);
41111e25f0dSDavid C Somayajulu 
41211e25f0dSDavid C Somayajulu 	trace->dwords[hwfn_index] = num_dwords;
41311e25f0dSDavid C Somayajulu 
41411e25f0dSDavid C Somayajulu 	if (num_dwords) {
41511e25f0dSDavid C Somayajulu                	rval = copyout(buffer, trace->buffer[hwfn_index],
41611e25f0dSDavid C Somayajulu 				(num_dwords << 2));
41711e25f0dSDavid C Somayajulu 	}
41811e25f0dSDavid C Somayajulu 
41911e25f0dSDavid C Somayajulu         return (rval);
42011e25f0dSDavid C Somayajulu }
42111e25f0dSDavid C Somayajulu 
42211e25f0dSDavid C Somayajulu static int
qlnx_reg_rd_wr(qlnx_host_t * ha,qlnx_reg_rd_wr_t * reg_rd_wr)42311e25f0dSDavid C Somayajulu qlnx_reg_rd_wr(qlnx_host_t *ha, qlnx_reg_rd_wr_t *reg_rd_wr)
42411e25f0dSDavid C Somayajulu {
42511e25f0dSDavid C Somayajulu 	int			rval = 0;
42611e25f0dSDavid C Somayajulu 	struct ecore_hwfn	*p_hwfn;
42711e25f0dSDavid C Somayajulu 
42811e25f0dSDavid C Somayajulu 	if (reg_rd_wr->hwfn_index >= QLNX_MAX_HW_FUNCS) {
42911e25f0dSDavid C Somayajulu 		return (EINVAL);
43011e25f0dSDavid C Somayajulu 	}
43111e25f0dSDavid C Somayajulu 
43211e25f0dSDavid C Somayajulu 	p_hwfn = &ha->cdev.hwfns[reg_rd_wr->hwfn_index];
43311e25f0dSDavid C Somayajulu 
43411e25f0dSDavid C Somayajulu 	switch (reg_rd_wr->cmd) {
43511e25f0dSDavid C Somayajulu 		case QLNX_REG_READ_CMD:
43611e25f0dSDavid C Somayajulu 			if (reg_rd_wr->access_type == QLNX_REG_ACCESS_DIRECT) {
43711e25f0dSDavid C Somayajulu 				reg_rd_wr->val = qlnx_reg_rd32(p_hwfn,
43811e25f0dSDavid C Somayajulu 							reg_rd_wr->addr);
43911e25f0dSDavid C Somayajulu 			}
44011e25f0dSDavid C Somayajulu 			break;
44111e25f0dSDavid C Somayajulu 
44211e25f0dSDavid C Somayajulu 		case QLNX_REG_WRITE_CMD:
44311e25f0dSDavid C Somayajulu 			if (reg_rd_wr->access_type == QLNX_REG_ACCESS_DIRECT) {
44411e25f0dSDavid C Somayajulu 				qlnx_reg_wr32(p_hwfn, reg_rd_wr->addr,
44511e25f0dSDavid C Somayajulu 					reg_rd_wr->val);
44611e25f0dSDavid C Somayajulu 			}
44711e25f0dSDavid C Somayajulu 			break;
44811e25f0dSDavid C Somayajulu 
44911e25f0dSDavid C Somayajulu 		default:
45011e25f0dSDavid C Somayajulu 			rval = EINVAL;
45111e25f0dSDavid C Somayajulu 			break;
45211e25f0dSDavid C Somayajulu 	}
45311e25f0dSDavid C Somayajulu 
45411e25f0dSDavid C Somayajulu 	return (rval);
45511e25f0dSDavid C Somayajulu }
45611e25f0dSDavid C Somayajulu 
45711e25f0dSDavid C Somayajulu static int
qlnx_rd_wr_pci_config(qlnx_host_t * ha,qlnx_pcicfg_rd_wr_t * pci_cfg_rd_wr)45811e25f0dSDavid C Somayajulu qlnx_rd_wr_pci_config(qlnx_host_t *ha, qlnx_pcicfg_rd_wr_t *pci_cfg_rd_wr)
45911e25f0dSDavid C Somayajulu {
46011e25f0dSDavid C Somayajulu 	int rval = 0;
46111e25f0dSDavid C Somayajulu 
46211e25f0dSDavid C Somayajulu 	switch (pci_cfg_rd_wr->cmd) {
46311e25f0dSDavid C Somayajulu 		case QLNX_PCICFG_READ:
46411e25f0dSDavid C Somayajulu 			pci_cfg_rd_wr->val = pci_read_config(ha->pci_dev,
46511e25f0dSDavid C Somayajulu 						pci_cfg_rd_wr->reg,
46611e25f0dSDavid C Somayajulu 						pci_cfg_rd_wr->width);
46711e25f0dSDavid C Somayajulu 			break;
46811e25f0dSDavid C Somayajulu 
46911e25f0dSDavid C Somayajulu 		case QLNX_PCICFG_WRITE:
47011e25f0dSDavid C Somayajulu 			pci_write_config(ha->pci_dev, pci_cfg_rd_wr->reg,
47111e25f0dSDavid C Somayajulu 				pci_cfg_rd_wr->val, pci_cfg_rd_wr->width);
47211e25f0dSDavid C Somayajulu 			break;
47311e25f0dSDavid C Somayajulu 
47411e25f0dSDavid C Somayajulu 		default:
47511e25f0dSDavid C Somayajulu 			rval = EINVAL;
47611e25f0dSDavid C Somayajulu 			break;
47711e25f0dSDavid C Somayajulu 	}
47811e25f0dSDavid C Somayajulu 
47911e25f0dSDavid C Somayajulu 	return (rval);
48011e25f0dSDavid C Somayajulu }
48111e25f0dSDavid C Somayajulu 
48211e25f0dSDavid C Somayajulu static void
qlnx_mac_addr(qlnx_host_t * ha,qlnx_perm_mac_addr_t * mac_addr)48311e25f0dSDavid C Somayajulu qlnx_mac_addr(qlnx_host_t *ha, qlnx_perm_mac_addr_t *mac_addr)
48411e25f0dSDavid C Somayajulu {
48511e25f0dSDavid C Somayajulu 	bzero(mac_addr->addr, sizeof(mac_addr->addr));
48611e25f0dSDavid C Somayajulu 	snprintf(mac_addr->addr, sizeof(mac_addr->addr),
48711e25f0dSDavid C Somayajulu 		"%02x:%02x:%02x:%02x:%02x:%02x",
48811e25f0dSDavid C Somayajulu 		ha->primary_mac[0], ha->primary_mac[1], ha->primary_mac[2],
48911e25f0dSDavid C Somayajulu 		ha->primary_mac[3], ha->primary_mac[4], ha->primary_mac[5]);
49011e25f0dSDavid C Somayajulu 
49111e25f0dSDavid C Somayajulu 	return;
49211e25f0dSDavid C Somayajulu }
49311e25f0dSDavid C Somayajulu 
49411e25f0dSDavid C Somayajulu static int
qlnx_get_regs(qlnx_host_t * ha,qlnx_get_regs_t * regs)49511e25f0dSDavid C Somayajulu qlnx_get_regs(qlnx_host_t *ha, qlnx_get_regs_t *regs)
49611e25f0dSDavid C Somayajulu {
49711e25f0dSDavid C Somayajulu 	int		i;
49811e25f0dSDavid C Somayajulu 	int		rval = 0;
49911e25f0dSDavid C Somayajulu 	uint32_t	dwords = 0;
50011e25f0dSDavid C Somayajulu 	uint8_t		*outb;
50111e25f0dSDavid C Somayajulu 
50211e25f0dSDavid C Somayajulu 	regs->reg_buf_len = 0;
50311e25f0dSDavid C Somayajulu 	outb = regs->reg_buf;
50411e25f0dSDavid C Somayajulu 
50511e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
50611e25f0dSDavid C Somayajulu 		rval = qlnx_grc_dump(ha, &dwords, i);
50711e25f0dSDavid C Somayajulu 
50811e25f0dSDavid C Somayajulu 		if (rval)
50911e25f0dSDavid C Somayajulu 			break;
51011e25f0dSDavid C Somayajulu 
51111e25f0dSDavid C Somayajulu 		regs->reg_buf_len += (dwords << 2);
51211e25f0dSDavid C Somayajulu 
51311e25f0dSDavid C Somayajulu 		rval = copyout(ha->grcdump[i], outb, ha->grcdump_size[i]);
51411e25f0dSDavid C Somayajulu 
51511e25f0dSDavid C Somayajulu 		if (rval)
51611e25f0dSDavid C Somayajulu 			break;
51711e25f0dSDavid C Somayajulu 
51811e25f0dSDavid C Somayajulu 		ha->grcdump_dwords[i] = 0;
51911e25f0dSDavid C Somayajulu 		outb += regs->reg_buf_len;
52011e25f0dSDavid C Somayajulu 	}
52111e25f0dSDavid C Somayajulu 
52211e25f0dSDavid C Somayajulu 	ha->grcdump_taken = 0;
52311e25f0dSDavid C Somayajulu 
52411e25f0dSDavid C Somayajulu 	return (rval);
52511e25f0dSDavid C Somayajulu }
52611e25f0dSDavid C Somayajulu 
527d576ccdfSRyan Libby extern char qlnx_name_str[];
528d576ccdfSRyan Libby extern char qlnx_ver_str[];
529d576ccdfSRyan Libby 
53011e25f0dSDavid C Somayajulu static int
qlnx_drv_info(qlnx_host_t * ha,qlnx_drvinfo_t * drv_info)53111e25f0dSDavid C Somayajulu qlnx_drv_info(qlnx_host_t *ha, qlnx_drvinfo_t *drv_info)
53211e25f0dSDavid C Somayajulu {
53311e25f0dSDavid C Somayajulu 	int i;
53411e25f0dSDavid C Somayajulu 
53511e25f0dSDavid C Somayajulu 	bzero(drv_info, sizeof(qlnx_drvinfo_t));
53611e25f0dSDavid C Somayajulu 
53711e25f0dSDavid C Somayajulu 	snprintf(drv_info->drv_name, sizeof(drv_info->drv_name), "%s",
53811e25f0dSDavid C Somayajulu 		qlnx_name_str);
53911e25f0dSDavid C Somayajulu 	snprintf(drv_info->drv_version, sizeof(drv_info->drv_version), "%s",
54011e25f0dSDavid C Somayajulu 		qlnx_ver_str);
54111e25f0dSDavid C Somayajulu 	snprintf(drv_info->mfw_version, sizeof(drv_info->mfw_version), "%s",
54211e25f0dSDavid C Somayajulu 		ha->mfw_ver);
54311e25f0dSDavid C Somayajulu 	snprintf(drv_info->stormfw_version, sizeof(drv_info->stormfw_version),
54411e25f0dSDavid C Somayajulu 		"%s", ha->stormfw_ver);
54511e25f0dSDavid C Somayajulu 
54611e25f0dSDavid C Somayajulu 	drv_info->eeprom_dump_len = ha->flash_size;
54711e25f0dSDavid C Somayajulu 
54811e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
54911e25f0dSDavid C Somayajulu 		drv_info->reg_dump_len += ha->grcdump_size[i];
55011e25f0dSDavid C Somayajulu 	}
55111e25f0dSDavid C Somayajulu 
55211e25f0dSDavid C Somayajulu 	snprintf(drv_info->bus_info, sizeof(drv_info->bus_info),
55311e25f0dSDavid C Somayajulu 		"%d:%d:%d", pci_get_bus(ha->pci_dev),
55411e25f0dSDavid C Somayajulu 		pci_get_slot(ha->pci_dev), ha->pci_func);
55511e25f0dSDavid C Somayajulu 
55611e25f0dSDavid C Somayajulu 	return (0);
55711e25f0dSDavid C Somayajulu }
55811e25f0dSDavid C Somayajulu 
55911e25f0dSDavid C Somayajulu static int
qlnx_dev_settings(qlnx_host_t * ha,qlnx_dev_setting_t * dev_info)56011e25f0dSDavid C Somayajulu qlnx_dev_settings(qlnx_host_t *ha, qlnx_dev_setting_t *dev_info)
56111e25f0dSDavid C Somayajulu {
56211e25f0dSDavid C Somayajulu 	struct ecore_hwfn *p_hwfn;
56311e25f0dSDavid C Somayajulu 	struct qlnx_link_output if_link;
56411e25f0dSDavid C Somayajulu 
56511e25f0dSDavid C Somayajulu 	p_hwfn = &ha->cdev.hwfns[0];
56611e25f0dSDavid C Somayajulu 
567217ec208SDavid C Somayajulu 	qlnx_fill_link(ha, p_hwfn, &if_link);
56811e25f0dSDavid C Somayajulu 
56911e25f0dSDavid C Somayajulu 	dev_info->supported = if_link.supported_caps;
57011e25f0dSDavid C Somayajulu 	dev_info->advertising = if_link.advertised_caps;
57111e25f0dSDavid C Somayajulu 	dev_info->speed = if_link.speed;
57211e25f0dSDavid C Somayajulu 	dev_info->duplex = if_link.duplex;
57311e25f0dSDavid C Somayajulu 	dev_info->port = ha->pci_func & 0x1;
57411e25f0dSDavid C Somayajulu 	dev_info->autoneg = if_link.autoneg;
57511e25f0dSDavid C Somayajulu 
57611e25f0dSDavid C Somayajulu 	return (0);
57711e25f0dSDavid C Somayajulu }
57811e25f0dSDavid C Somayajulu 
57911e25f0dSDavid C Somayajulu static int
qlnx_write_nvram(qlnx_host_t * ha,qlnx_nvram_t * nvram,uint32_t cmd)58011e25f0dSDavid C Somayajulu qlnx_write_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram, uint32_t cmd)
58111e25f0dSDavid C Somayajulu {
58211e25f0dSDavid C Somayajulu 	uint8_t *buf;
58311e25f0dSDavid C Somayajulu 	int ret = 0;
58411e25f0dSDavid C Somayajulu 
58511e25f0dSDavid C Somayajulu 	if ((nvram->data == NULL) || (nvram->data_len == 0))
58611e25f0dSDavid C Somayajulu 		return (EINVAL);
58711e25f0dSDavid C Somayajulu 
58811e25f0dSDavid C Somayajulu 	buf = qlnx_zalloc(nvram->data_len);
58911e25f0dSDavid C Somayajulu 
59011e25f0dSDavid C Somayajulu 	ret = copyin(nvram->data, buf, nvram->data_len);
59111e25f0dSDavid C Somayajulu 
5927a377fbeSDavid C Somayajulu 	QL_DPRINT9(ha, "issue cmd = 0x%x data = %p \
5937a377fbeSDavid C Somayajulu 		 data_len = 0x%x ret = 0x%x exit\n",
5947a377fbeSDavid C Somayajulu 		cmd, nvram->data, nvram->data_len, ret);
59511e25f0dSDavid C Somayajulu 
59611e25f0dSDavid C Somayajulu 	if (ret == 0) {
59711e25f0dSDavid C Somayajulu 		ret = ecore_mcp_nvm_write(&ha->cdev, cmd,
59811e25f0dSDavid C Somayajulu 			nvram->offset, buf, nvram->data_len);
59911e25f0dSDavid C Somayajulu 	}
60011e25f0dSDavid C Somayajulu 
6017a377fbeSDavid C Somayajulu 	QL_DPRINT9(ha, "cmd = 0x%x data = %p \
6027a377fbeSDavid C Somayajulu 		 data_len = 0x%x resp = 0x%x ret = 0x%x exit\n",
6037a377fbeSDavid C Somayajulu 		cmd, nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret);
60411e25f0dSDavid C Somayajulu 
60511e25f0dSDavid C Somayajulu 	free(buf, M_QLNXBUF);
60611e25f0dSDavid C Somayajulu 
60711e25f0dSDavid C Somayajulu 	return (ret);
60811e25f0dSDavid C Somayajulu }
60911e25f0dSDavid C Somayajulu 
61011e25f0dSDavid C Somayajulu static int
qlnx_read_nvram(qlnx_host_t * ha,qlnx_nvram_t * nvram)61111e25f0dSDavid C Somayajulu qlnx_read_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram)
61211e25f0dSDavid C Somayajulu {
61311e25f0dSDavid C Somayajulu 	uint8_t *buf;
61411e25f0dSDavid C Somayajulu 	int ret = 0;
61511e25f0dSDavid C Somayajulu 
61611e25f0dSDavid C Somayajulu 	if ((nvram->data == NULL) || (nvram->data_len == 0))
61711e25f0dSDavid C Somayajulu 		return (EINVAL);
61811e25f0dSDavid C Somayajulu 
61911e25f0dSDavid C Somayajulu 	buf = qlnx_zalloc(nvram->data_len);
62011e25f0dSDavid C Somayajulu 
62111e25f0dSDavid C Somayajulu 	ret = ecore_mcp_nvm_read(&ha->cdev, nvram->offset, buf,
62211e25f0dSDavid C Somayajulu 		nvram->data_len);
62311e25f0dSDavid C Somayajulu 
6247a377fbeSDavid C Somayajulu 	QL_DPRINT9(ha, " data = %p data_len = 0x%x \
6257a377fbeSDavid C Somayajulu 		 resp = 0x%x ret = 0x%x exit\n",
6267a377fbeSDavid C Somayajulu 		nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret);
62711e25f0dSDavid C Somayajulu 
62811e25f0dSDavid C Somayajulu 	if (ret == 0) {
62911e25f0dSDavid C Somayajulu 		ret = copyout(buf, nvram->data, nvram->data_len);
63011e25f0dSDavid C Somayajulu 	}
63111e25f0dSDavid C Somayajulu 
63211e25f0dSDavid C Somayajulu 	free(buf, M_QLNXBUF);
63311e25f0dSDavid C Somayajulu 
63411e25f0dSDavid C Somayajulu 	return (ret);
63511e25f0dSDavid C Somayajulu }
63611e25f0dSDavid C Somayajulu 
63711e25f0dSDavid C Somayajulu static int
qlnx_get_nvram_resp(qlnx_host_t * ha,qlnx_nvram_t * nvram)63811e25f0dSDavid C Somayajulu qlnx_get_nvram_resp(qlnx_host_t *ha, qlnx_nvram_t *nvram)
63911e25f0dSDavid C Somayajulu {
64011e25f0dSDavid C Somayajulu 	uint8_t *buf;
64111e25f0dSDavid C Somayajulu 	int ret = 0;
64211e25f0dSDavid C Somayajulu 
64311e25f0dSDavid C Somayajulu 	if ((nvram->data == NULL) || (nvram->data_len == 0))
64411e25f0dSDavid C Somayajulu 		return (EINVAL);
64511e25f0dSDavid C Somayajulu 
64611e25f0dSDavid C Somayajulu 	buf = qlnx_zalloc(nvram->data_len);
64711e25f0dSDavid C Somayajulu 
64811e25f0dSDavid C Somayajulu 	ret = ecore_mcp_nvm_resp(&ha->cdev, buf);
64911e25f0dSDavid C Somayajulu 
6507a377fbeSDavid C Somayajulu 	QL_DPRINT9(ha, "data = %p data_len = 0x%x \
6517a377fbeSDavid C Somayajulu 		 resp = 0x%x ret = 0x%x exit\n",
6527a377fbeSDavid C Somayajulu 		nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret);
65311e25f0dSDavid C Somayajulu 
65411e25f0dSDavid C Somayajulu 	if (ret == 0) {
65511e25f0dSDavid C Somayajulu 		ret = copyout(buf, nvram->data, nvram->data_len);
65611e25f0dSDavid C Somayajulu 	}
65711e25f0dSDavid C Somayajulu 
65811e25f0dSDavid C Somayajulu 	free(buf, M_QLNXBUF);
65911e25f0dSDavid C Somayajulu 
66011e25f0dSDavid C Somayajulu 	return (ret);
66111e25f0dSDavid C Somayajulu }
66211e25f0dSDavid C Somayajulu 
66311e25f0dSDavid C Somayajulu static int
qlnx_nvram(qlnx_host_t * ha,qlnx_nvram_t * nvram)66411e25f0dSDavid C Somayajulu qlnx_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram)
66511e25f0dSDavid C Somayajulu {
66611e25f0dSDavid C Somayajulu 	int ret = 0;
66711e25f0dSDavid C Somayajulu 
66811e25f0dSDavid C Somayajulu 	switch (nvram->cmd) {
66911e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_WRITE_NVRAM:
67011e25f0dSDavid C Somayajulu 		ret = qlnx_write_nvram(ha, nvram, ECORE_NVM_WRITE_NVRAM);
67111e25f0dSDavid C Somayajulu 		break;
67211e25f0dSDavid C Somayajulu 
67311e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_PUT_FILE_DATA:
67411e25f0dSDavid C Somayajulu 		ret = qlnx_write_nvram(ha, nvram, ECORE_PUT_FILE_DATA);
67511e25f0dSDavid C Somayajulu 		break;
67611e25f0dSDavid C Somayajulu 
67711e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_READ_NVRAM:
67811e25f0dSDavid C Somayajulu 		ret = qlnx_read_nvram(ha, nvram);
67911e25f0dSDavid C Somayajulu 		break;
68011e25f0dSDavid C Somayajulu 
68111e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_SET_SECURE_MODE:
68211e25f0dSDavid C Somayajulu 		ret = ecore_mcp_nvm_set_secure_mode(&ha->cdev, nvram->offset);
68311e25f0dSDavid C Somayajulu 
6847a377fbeSDavid C Somayajulu 		QL_DPRINT9(ha, "QLNX_NVRAM_CMD_SET_SECURE_MODE \
6857a377fbeSDavid C Somayajulu 			 resp = 0x%x ret = 0x%x exit\n",
6867a377fbeSDavid C Somayajulu 			 ha->cdev.mcp_nvm_resp, ret);
68711e25f0dSDavid C Somayajulu 		break;
68811e25f0dSDavid C Somayajulu 
68911e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_DEL_FILE:
69011e25f0dSDavid C Somayajulu 		ret = ecore_mcp_nvm_del_file(&ha->cdev, nvram->offset);
69111e25f0dSDavid C Somayajulu 
6927a377fbeSDavid C Somayajulu 		QL_DPRINT9(ha, "QLNX_NVRAM_CMD_DEL_FILE \
6937a377fbeSDavid C Somayajulu 			 resp = 0x%x ret = 0x%x exit\n",
6947a377fbeSDavid C Somayajulu 			ha->cdev.mcp_nvm_resp, ret);
69511e25f0dSDavid C Somayajulu 		break;
69611e25f0dSDavid C Somayajulu 
69711e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_PUT_FILE_BEGIN:
69811e25f0dSDavid C Somayajulu 		ret = ecore_mcp_nvm_put_file_begin(&ha->cdev, nvram->offset);
69911e25f0dSDavid C Somayajulu 
7007a377fbeSDavid C Somayajulu 		QL_DPRINT9(ha, "QLNX_NVRAM_CMD_PUT_FILE_BEGIN \
7017a377fbeSDavid C Somayajulu 			 resp = 0x%x ret = 0x%x exit\n",
7027a377fbeSDavid C Somayajulu 			ha->cdev.mcp_nvm_resp, ret);
70311e25f0dSDavid C Somayajulu 		break;
70411e25f0dSDavid C Somayajulu 
70511e25f0dSDavid C Somayajulu 	case QLNX_NVRAM_CMD_GET_NVRAM_RESP:
70611e25f0dSDavid C Somayajulu 		ret = qlnx_get_nvram_resp(ha, nvram);
70711e25f0dSDavid C Somayajulu 		break;
70811e25f0dSDavid C Somayajulu 
70911e25f0dSDavid C Somayajulu 	default:
71011e25f0dSDavid C Somayajulu 		ret = EINVAL;
71111e25f0dSDavid C Somayajulu 		break;
71211e25f0dSDavid C Somayajulu 	}
71311e25f0dSDavid C Somayajulu 
71411e25f0dSDavid C Somayajulu 	return (ret);
71511e25f0dSDavid C Somayajulu }
71611e25f0dSDavid C Somayajulu 
71711e25f0dSDavid C Somayajulu static void
qlnx_storm_stats(qlnx_host_t * ha,qlnx_storm_stats_dump_t * s_stats)71811e25f0dSDavid C Somayajulu qlnx_storm_stats(qlnx_host_t *ha, qlnx_storm_stats_dump_t *s_stats)
71911e25f0dSDavid C Somayajulu {
72011e25f0dSDavid C Somayajulu 	int i;
72111e25f0dSDavid C Somayajulu 	int index;
72211e25f0dSDavid C Somayajulu 	int ret;
72311e25f0dSDavid C Somayajulu 	int stats_copied = 0;
72411e25f0dSDavid C Somayajulu 
72511e25f0dSDavid C Somayajulu 	s_stats->num_hwfns = ha->cdev.num_hwfns;
72611e25f0dSDavid C Somayajulu 
72711e25f0dSDavid C Somayajulu //	if (ha->storm_stats_index < QLNX_STORM_STATS_SAMPLES_PER_HWFN)
72811e25f0dSDavid C Somayajulu //		return;
72911e25f0dSDavid C Somayajulu 
73011e25f0dSDavid C Somayajulu 	s_stats->num_samples = ha->storm_stats_index;
73111e25f0dSDavid C Somayajulu 
73211e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
73311e25f0dSDavid C Somayajulu 		index = (QLNX_STORM_STATS_SAMPLES_PER_HWFN * i);
73411e25f0dSDavid C Somayajulu 
73511e25f0dSDavid C Somayajulu 		if (s_stats->buffer[i]) {
73611e25f0dSDavid C Somayajulu 			ret = copyout(&ha->storm_stats[index],
73711e25f0dSDavid C Somayajulu 					s_stats->buffer[i],
73811e25f0dSDavid C Somayajulu 					QLNX_STORM_STATS_BYTES_PER_HWFN);
73911e25f0dSDavid C Somayajulu 			if (ret) {
74011e25f0dSDavid C Somayajulu 				printf("%s [%d]: failed\n", __func__, i);
74111e25f0dSDavid C Somayajulu 			}
74211e25f0dSDavid C Somayajulu 
74311e25f0dSDavid C Somayajulu 			if (s_stats->num_samples ==
74411e25f0dSDavid C Somayajulu 				QLNX_STORM_STATS_SAMPLES_PER_HWFN) {
74511e25f0dSDavid C Somayajulu 				bzero((void *)&ha->storm_stats[i],
74611e25f0dSDavid C Somayajulu 					QLNX_STORM_STATS_BYTES_PER_HWFN);
74711e25f0dSDavid C Somayajulu 
74811e25f0dSDavid C Somayajulu 				stats_copied = 1;
74911e25f0dSDavid C Somayajulu 			}
75011e25f0dSDavid C Somayajulu 		}
75111e25f0dSDavid C Somayajulu 	}
75211e25f0dSDavid C Somayajulu 
75311e25f0dSDavid C Somayajulu 	if (stats_copied)
75411e25f0dSDavid C Somayajulu 		ha->storm_stats_index = 0;
75511e25f0dSDavid C Somayajulu 
75611e25f0dSDavid C Somayajulu 	return;
75711e25f0dSDavid C Somayajulu }
75811e25f0dSDavid C Somayajulu 
759217ec208SDavid C Somayajulu #ifdef QLNX_USER_LLDP
760217ec208SDavid C Somayajulu 
761217ec208SDavid C Somayajulu static int
qlnx_lldp_configure(qlnx_host_t * ha,struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,uint32_t enable)762217ec208SDavid C Somayajulu qlnx_lldp_configure(qlnx_host_t *ha, struct ecore_hwfn *p_hwfn,
763217ec208SDavid C Somayajulu 	struct ecore_ptt *p_ptt, uint32_t enable)
764217ec208SDavid C Somayajulu {
765217ec208SDavid C Somayajulu 	int ret = 0;
766217ec208SDavid C Somayajulu 	uint8_t lldp_mac[6] = {0};
767217ec208SDavid C Somayajulu 	struct ecore_lldp_config_params lldp_params;
768217ec208SDavid C Somayajulu 	struct ecore_lldp_sys_tlvs tlv_params;
769217ec208SDavid C Somayajulu 
770217ec208SDavid C Somayajulu 	ret = ecore_mcp_get_lldp_mac(p_hwfn, p_ptt, lldp_mac);
771217ec208SDavid C Somayajulu 
772217ec208SDavid C Somayajulu 	if (ret != ECORE_SUCCESS) {
773217ec208SDavid C Somayajulu                 device_printf(ha->pci_dev,
774217ec208SDavid C Somayajulu 			"%s: ecore_mcp_get_lldp_mac failed\n", __func__);
775217ec208SDavid C Somayajulu                 return (-1);
776217ec208SDavid C Somayajulu 	}
777217ec208SDavid C Somayajulu 
778217ec208SDavid C Somayajulu 	bzero(&lldp_params, sizeof(struct ecore_lldp_config_params));
779217ec208SDavid C Somayajulu 	bzero(&tlv_params, sizeof(struct ecore_lldp_sys_tlvs));
780217ec208SDavid C Somayajulu 
781217ec208SDavid C Somayajulu 	lldp_params.agent = ECORE_LLDP_NEAREST_BRIDGE;
782217ec208SDavid C Somayajulu 	lldp_params.tx_interval = 30; //Default value used as suggested by MFW
783217ec208SDavid C Somayajulu 	lldp_params.tx_hold = 4; //Default value used as suggested by MFW
784217ec208SDavid C Somayajulu 	lldp_params.tx_credit = 5; //Default value used as suggested by MFW
785217ec208SDavid C Somayajulu 	lldp_params.rx_enable = enable ? 1 : 0;
786217ec208SDavid C Somayajulu 	lldp_params.tx_enable = enable ? 1 : 0;
787217ec208SDavid C Somayajulu 
788217ec208SDavid C Somayajulu 	lldp_params.chassis_id_tlv[0] = 0;
789217ec208SDavid C Somayajulu 	lldp_params.chassis_id_tlv[0] |= (QLNX_LLDP_TYPE_CHASSIS_ID << 1);
790217ec208SDavid C Somayajulu 	lldp_params.chassis_id_tlv[0] |=
791217ec208SDavid C Somayajulu 		((QLNX_LLDP_CHASSIS_ID_SUBTYPE_OCTETS +
792217ec208SDavid C Somayajulu 			QLNX_LLDP_CHASSIS_ID_MAC_ADDR_LEN) << 8);
793217ec208SDavid C Somayajulu 	lldp_params.chassis_id_tlv[0] |= (QLNX_LLDP_CHASSIS_ID_SUBTYPE_MAC << 16);
794217ec208SDavid C Somayajulu 	lldp_params.chassis_id_tlv[0] |= lldp_mac[0] << 24;
795217ec208SDavid C Somayajulu 	lldp_params.chassis_id_tlv[1] = lldp_mac[1] | (lldp_mac[2] << 8) |
796217ec208SDavid C Somayajulu 		 (lldp_mac[3] << 16) | (lldp_mac[4] << 24);
797217ec208SDavid C Somayajulu 	lldp_params.chassis_id_tlv[2] = lldp_mac[5];
798217ec208SDavid C Somayajulu 
799217ec208SDavid C Somayajulu 	lldp_params.port_id_tlv[0] = 0;
800217ec208SDavid C Somayajulu 	lldp_params.port_id_tlv[0] |= (QLNX_LLDP_TYPE_PORT_ID << 1);
801217ec208SDavid C Somayajulu 	lldp_params.port_id_tlv[0] |=
802217ec208SDavid C Somayajulu 		((QLNX_LLDP_PORT_ID_SUBTYPE_OCTETS +
803217ec208SDavid C Somayajulu 			QLNX_LLDP_PORT_ID_MAC_ADDR_LEN) << 8);
804217ec208SDavid C Somayajulu 	lldp_params.port_id_tlv[0] |= (QLNX_LLDP_PORT_ID_SUBTYPE_MAC << 16);
805217ec208SDavid C Somayajulu 	lldp_params.port_id_tlv[0] |= lldp_mac[0] << 24;
806217ec208SDavid C Somayajulu 	lldp_params.port_id_tlv[1] = lldp_mac[1] | (lldp_mac[2] << 8) |
807217ec208SDavid C Somayajulu 		 (lldp_mac[3] << 16) | (lldp_mac[4] << 24);
808217ec208SDavid C Somayajulu 	lldp_params.port_id_tlv[2] = lldp_mac[5];
809217ec208SDavid C Somayajulu 
810217ec208SDavid C Somayajulu 	ret = ecore_lldp_set_params(p_hwfn, p_ptt, &lldp_params);
811217ec208SDavid C Somayajulu 
812217ec208SDavid C Somayajulu 	if (ret != ECORE_SUCCESS) {
813217ec208SDavid C Somayajulu                 device_printf(ha->pci_dev,
814217ec208SDavid C Somayajulu 			"%s: ecore_lldp_set_params failed\n", __func__);
815217ec208SDavid C Somayajulu                 return (-1);
816217ec208SDavid C Somayajulu 	}
817217ec208SDavid C Somayajulu 
818217ec208SDavid C Somayajulu 	//If LLDP is disable then disable discard_mandatory_tlv flag
819217ec208SDavid C Somayajulu 	if (!enable) {
820217ec208SDavid C Somayajulu 		tlv_params.discard_mandatory_tlv = false;
821217ec208SDavid C Somayajulu 		tlv_params.buf_size = 0;
822217ec208SDavid C Somayajulu 		ret = ecore_lldp_set_system_tlvs(p_hwfn, p_ptt, &tlv_params);
823217ec208SDavid C Somayajulu     	}
824217ec208SDavid C Somayajulu 
825217ec208SDavid C Somayajulu 	if (ret != ECORE_SUCCESS) {
826217ec208SDavid C Somayajulu                 device_printf(ha->pci_dev,
827217ec208SDavid C Somayajulu 			"%s: ecore_lldp_set_system_tlvs failed\n", __func__);
828217ec208SDavid C Somayajulu 	}
829217ec208SDavid C Somayajulu 
830217ec208SDavid C Somayajulu 	return (ret);
831217ec208SDavid C Somayajulu }
832217ec208SDavid C Somayajulu 
833217ec208SDavid C Somayajulu static int
qlnx_register_default_lldp_tlvs(qlnx_host_t * ha,struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)834217ec208SDavid C Somayajulu qlnx_register_default_lldp_tlvs(qlnx_host_t *ha, struct ecore_hwfn *p_hwfn,
835217ec208SDavid C Somayajulu 	struct ecore_ptt *p_ptt)
836217ec208SDavid C Somayajulu {
837217ec208SDavid C Somayajulu 	int ret = 0;
838217ec208SDavid C Somayajulu 
839217ec208SDavid C Somayajulu 	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
840217ec208SDavid C Somayajulu 			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_CHASSIS_ID);
841217ec208SDavid C Somayajulu 	if (ret != ECORE_SUCCESS) {
842217ec208SDavid C Somayajulu                 device_printf(ha->pci_dev,
843217ec208SDavid C Somayajulu 			"%s: QLNX_LLDP_TYPE_CHASSIS_ID failed\n", __func__);
844217ec208SDavid C Somayajulu 		goto qlnx_register_default_lldp_tlvs_exit;
845217ec208SDavid C Somayajulu 	}
846217ec208SDavid C Somayajulu 
847217ec208SDavid C Somayajulu 	//register Port ID TLV
848217ec208SDavid C Somayajulu 	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
849217ec208SDavid C Somayajulu 			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_PORT_ID);
850217ec208SDavid C Somayajulu 	if (ret != ECORE_SUCCESS) {
851217ec208SDavid C Somayajulu                 device_printf(ha->pci_dev,
852217ec208SDavid C Somayajulu 			"%s: QLNX_LLDP_TYPE_PORT_ID failed\n", __func__);
853217ec208SDavid C Somayajulu 		goto qlnx_register_default_lldp_tlvs_exit;
854217ec208SDavid C Somayajulu 	}
855217ec208SDavid C Somayajulu 
856217ec208SDavid C Somayajulu 	//register TTL TLV
857217ec208SDavid C Somayajulu 	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
858217ec208SDavid C Somayajulu 			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_TTL);
859217ec208SDavid C Somayajulu 	if (ret != ECORE_SUCCESS) {
860217ec208SDavid C Somayajulu                 device_printf(ha->pci_dev,
861217ec208SDavid C Somayajulu 			"%s: QLNX_LLDP_TYPE_TTL failed\n", __func__);
862217ec208SDavid C Somayajulu 		goto qlnx_register_default_lldp_tlvs_exit;
863217ec208SDavid C Somayajulu 	}
864217ec208SDavid C Somayajulu 
865217ec208SDavid C Somayajulu 	//register Port Description TLV
866217ec208SDavid C Somayajulu 	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
867217ec208SDavid C Somayajulu 			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_PORT_DESC);
868217ec208SDavid C Somayajulu 	if (ret != ECORE_SUCCESS) {
869217ec208SDavid C Somayajulu                 device_printf(ha->pci_dev,
870217ec208SDavid C Somayajulu 			"%s: QLNX_LLDP_TYPE_PORT_DESC failed\n", __func__);
871217ec208SDavid C Somayajulu 		goto qlnx_register_default_lldp_tlvs_exit;
872217ec208SDavid C Somayajulu 	}
873217ec208SDavid C Somayajulu 
874217ec208SDavid C Somayajulu 	//register System Name TLV
875217ec208SDavid C Somayajulu 	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
876217ec208SDavid C Somayajulu 			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_SYS_NAME);
877217ec208SDavid C Somayajulu 	if (ret != ECORE_SUCCESS) {
878217ec208SDavid C Somayajulu                 device_printf(ha->pci_dev,
879217ec208SDavid C Somayajulu 			"%s: QLNX_LLDP_TYPE_SYS_NAME failed\n", __func__);
880217ec208SDavid C Somayajulu 		goto qlnx_register_default_lldp_tlvs_exit;
881217ec208SDavid C Somayajulu 	}
882217ec208SDavid C Somayajulu 
883217ec208SDavid C Somayajulu 	//register System Description TLV
884217ec208SDavid C Somayajulu 	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
885217ec208SDavid C Somayajulu 			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_SYS_DESC);
886217ec208SDavid C Somayajulu 	if (ret != ECORE_SUCCESS) {
887217ec208SDavid C Somayajulu                 device_printf(ha->pci_dev,
888217ec208SDavid C Somayajulu 			"%s: QLNX_LLDP_TYPE_SYS_DESC failed\n", __func__);
889217ec208SDavid C Somayajulu 		goto qlnx_register_default_lldp_tlvs_exit;
890217ec208SDavid C Somayajulu 	}
891217ec208SDavid C Somayajulu 
892217ec208SDavid C Somayajulu 	//register System Capabilities TLV
893217ec208SDavid C Somayajulu 	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
894217ec208SDavid C Somayajulu 			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_SYS_CAPS);
895217ec208SDavid C Somayajulu 	if (ret != ECORE_SUCCESS) {
896217ec208SDavid C Somayajulu                 device_printf(ha->pci_dev,
897217ec208SDavid C Somayajulu 			"%s: QLNX_LLDP_TYPE_SYS_CAPS failed\n", __func__);
898217ec208SDavid C Somayajulu 		goto qlnx_register_default_lldp_tlvs_exit;
899217ec208SDavid C Somayajulu 	}
900217ec208SDavid C Somayajulu 
901217ec208SDavid C Somayajulu 	//register Management Address TLV
902217ec208SDavid C Somayajulu 	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
903217ec208SDavid C Somayajulu 			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_MGMT_ADDR);
904217ec208SDavid C Somayajulu 	if (ret != ECORE_SUCCESS) {
905217ec208SDavid C Somayajulu                 device_printf(ha->pci_dev,
906217ec208SDavid C Somayajulu 			"%s: QLNX_LLDP_TYPE_MGMT_ADDR failed\n", __func__);
907217ec208SDavid C Somayajulu 		goto qlnx_register_default_lldp_tlvs_exit;
908217ec208SDavid C Somayajulu 	}
909217ec208SDavid C Somayajulu 
910217ec208SDavid C Somayajulu 	//register Organizationally Specific TLVs
911217ec208SDavid C Somayajulu 	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
912217ec208SDavid C Somayajulu 			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_ORG_SPECIFIC);
913217ec208SDavid C Somayajulu 	if (ret != ECORE_SUCCESS) {
914217ec208SDavid C Somayajulu                 device_printf(ha->pci_dev,
915217ec208SDavid C Somayajulu 			"%s: QLNX_LLDP_TYPE_ORG_SPECIFIC failed\n", __func__);
916217ec208SDavid C Somayajulu 	}
917217ec208SDavid C Somayajulu 
918217ec208SDavid C Somayajulu qlnx_register_default_lldp_tlvs_exit:
919217ec208SDavid C Somayajulu 	return (ret);
920217ec208SDavid C Somayajulu }
921217ec208SDavid C Somayajulu 
922217ec208SDavid C Somayajulu int
qlnx_set_lldp_tlvx(qlnx_host_t * ha,qlnx_lldp_sys_tlvs_t * lldp_tlvs)923217ec208SDavid C Somayajulu qlnx_set_lldp_tlvx(qlnx_host_t *ha, qlnx_lldp_sys_tlvs_t *lldp_tlvs)
924217ec208SDavid C Somayajulu {
925217ec208SDavid C Somayajulu 	int ret = 0;
926217ec208SDavid C Somayajulu 	struct ecore_hwfn *p_hwfn;
927217ec208SDavid C Somayajulu 	struct ecore_ptt *p_ptt;
928217ec208SDavid C Somayajulu 	struct ecore_lldp_sys_tlvs tlv_params;
929217ec208SDavid C Somayajulu 
930217ec208SDavid C Somayajulu 	p_hwfn = &ha->cdev.hwfns[0];
931217ec208SDavid C Somayajulu 	p_ptt = ecore_ptt_acquire(p_hwfn);
932217ec208SDavid C Somayajulu 
933217ec208SDavid C Somayajulu         if (!p_ptt) {
934217ec208SDavid C Somayajulu                 device_printf(ha->pci_dev,
935217ec208SDavid C Somayajulu 			"%s: ecore_ptt_acquire failed\n", __func__);
936217ec208SDavid C Somayajulu                 return (ENXIO);
937217ec208SDavid C Somayajulu         }
938217ec208SDavid C Somayajulu 
939217ec208SDavid C Somayajulu 	ret = qlnx_lldp_configure(ha, p_hwfn, p_ptt, 0);
940217ec208SDavid C Somayajulu 
941217ec208SDavid C Somayajulu 	if (ret) {
942217ec208SDavid C Somayajulu                 device_printf(ha->pci_dev,
943217ec208SDavid C Somayajulu 			"%s: qlnx_lldp_configure disable failed\n", __func__);
944217ec208SDavid C Somayajulu 		goto qlnx_set_lldp_tlvx_exit;
945217ec208SDavid C Somayajulu 	}
946217ec208SDavid C Somayajulu 
947217ec208SDavid C Somayajulu 	ret = qlnx_register_default_lldp_tlvs(ha, p_hwfn, p_ptt);
948217ec208SDavid C Somayajulu 
949217ec208SDavid C Somayajulu 	if (ret) {
950217ec208SDavid C Somayajulu                 device_printf(ha->pci_dev,
951217ec208SDavid C Somayajulu 			"%s: qlnx_register_default_lldp_tlvs failed\n",
952217ec208SDavid C Somayajulu 			__func__);
953217ec208SDavid C Somayajulu 		goto qlnx_set_lldp_tlvx_exit;
954217ec208SDavid C Somayajulu 	}
955217ec208SDavid C Somayajulu 
956217ec208SDavid C Somayajulu 	ret = qlnx_lldp_configure(ha, p_hwfn, p_ptt, 1);
957217ec208SDavid C Somayajulu 
958217ec208SDavid C Somayajulu 	if (ret) {
959217ec208SDavid C Somayajulu                 device_printf(ha->pci_dev,
960217ec208SDavid C Somayajulu 			"%s: qlnx_lldp_configure enable failed\n", __func__);
961217ec208SDavid C Somayajulu 		goto qlnx_set_lldp_tlvx_exit;
962217ec208SDavid C Somayajulu 	}
963217ec208SDavid C Somayajulu 
964217ec208SDavid C Somayajulu 	if (lldp_tlvs != NULL) {
965217ec208SDavid C Somayajulu 		bzero(&tlv_params, sizeof(struct ecore_lldp_sys_tlvs));
966217ec208SDavid C Somayajulu 
967217ec208SDavid C Somayajulu 		tlv_params.discard_mandatory_tlv =
968217ec208SDavid C Somayajulu 			(lldp_tlvs->discard_mandatory_tlv ? true: false);
969217ec208SDavid C Somayajulu 		tlv_params.buf_size = lldp_tlvs->buf_size;
970217ec208SDavid C Somayajulu 		memcpy(tlv_params.buf, lldp_tlvs->buf, lldp_tlvs->buf_size);
971217ec208SDavid C Somayajulu 
972217ec208SDavid C Somayajulu 		ret = ecore_lldp_set_system_tlvs(p_hwfn, p_ptt, &tlv_params);
973217ec208SDavid C Somayajulu 
974217ec208SDavid C Somayajulu 		if (ret) {
975217ec208SDavid C Somayajulu 			device_printf(ha->pci_dev,
976217ec208SDavid C Somayajulu 				"%s: ecore_lldp_set_system_tlvs failed\n",
977217ec208SDavid C Somayajulu 				__func__);
978217ec208SDavid C Somayajulu 		}
979217ec208SDavid C Somayajulu 	}
980217ec208SDavid C Somayajulu qlnx_set_lldp_tlvx_exit:
981217ec208SDavid C Somayajulu 
982217ec208SDavid C Somayajulu 	ecore_ptt_release(p_hwfn, p_ptt);
983217ec208SDavid C Somayajulu 	return (ret);
984217ec208SDavid C Somayajulu }
985217ec208SDavid C Somayajulu 
986217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_USER_LLDP */
98711e25f0dSDavid C Somayajulu 
98811e25f0dSDavid C Somayajulu static int
qlnx_eioctl(struct cdev * dev,u_long cmd,caddr_t data,int fflag,struct thread * td)98911e25f0dSDavid C Somayajulu qlnx_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
99011e25f0dSDavid C Somayajulu 	struct thread *td)
99111e25f0dSDavid C Somayajulu {
99211e25f0dSDavid C Somayajulu 	qlnx_host_t	*ha;
99311e25f0dSDavid C Somayajulu 	int		rval = 0;
99411e25f0dSDavid C Somayajulu 	qlnx_trace_t	*trace;
99511e25f0dSDavid C Somayajulu 	int		i;
99611e25f0dSDavid C Somayajulu 
99711e25f0dSDavid C Somayajulu 	if ((ha = (qlnx_host_t *)dev->si_drv1) == NULL)
99811e25f0dSDavid C Somayajulu 		return ENXIO;
99911e25f0dSDavid C Somayajulu 
100011e25f0dSDavid C Somayajulu 	switch (cmd) {
100111e25f0dSDavid C Somayajulu 	case QLNX_GRC_DUMP_SIZE:
100211e25f0dSDavid C Somayajulu 		qlnx_get_grc_dump_size(ha, (qlnx_grcdump_t *)data);
100311e25f0dSDavid C Somayajulu 		break;
100411e25f0dSDavid C Somayajulu 
100511e25f0dSDavid C Somayajulu 	case QLNX_GRC_DUMP:
100611e25f0dSDavid C Somayajulu 		rval = qlnx_get_grc_dump(ha, (qlnx_grcdump_t *)data);
100711e25f0dSDavid C Somayajulu 		break;
100811e25f0dSDavid C Somayajulu 
100911e25f0dSDavid C Somayajulu 	case QLNX_IDLE_CHK_SIZE:
101011e25f0dSDavid C Somayajulu 		qlnx_get_idle_chk_size(ha, (qlnx_idle_chk_t *)data);
101111e25f0dSDavid C Somayajulu 		break;
101211e25f0dSDavid C Somayajulu 
101311e25f0dSDavid C Somayajulu 	case QLNX_IDLE_CHK:
101411e25f0dSDavid C Somayajulu 		rval = qlnx_get_idle_chk(ha, (qlnx_idle_chk_t *)data);
101511e25f0dSDavid C Somayajulu 		break;
101611e25f0dSDavid C Somayajulu 
101711e25f0dSDavid C Somayajulu 	case QLNX_DRV_INFO:
101811e25f0dSDavid C Somayajulu 		rval = qlnx_drv_info(ha, (qlnx_drvinfo_t *)data);
101911e25f0dSDavid C Somayajulu 		break;
102011e25f0dSDavid C Somayajulu 
102111e25f0dSDavid C Somayajulu 	case QLNX_DEV_SETTING:
102211e25f0dSDavid C Somayajulu 		rval = qlnx_dev_settings(ha, (qlnx_dev_setting_t *)data);
102311e25f0dSDavid C Somayajulu 		break;
102411e25f0dSDavid C Somayajulu 
102511e25f0dSDavid C Somayajulu 	case QLNX_GET_REGS:
102611e25f0dSDavid C Somayajulu 		rval = qlnx_get_regs(ha, (qlnx_get_regs_t *)data);
102711e25f0dSDavid C Somayajulu 		break;
102811e25f0dSDavid C Somayajulu 
102911e25f0dSDavid C Somayajulu 	case QLNX_NVRAM:
103011e25f0dSDavid C Somayajulu 		rval = qlnx_nvram(ha, (qlnx_nvram_t *)data);
103111e25f0dSDavid C Somayajulu 		break;
103211e25f0dSDavid C Somayajulu 
103311e25f0dSDavid C Somayajulu 	case QLNX_RD_WR_REG:
103411e25f0dSDavid C Somayajulu 		rval = qlnx_reg_rd_wr(ha, (qlnx_reg_rd_wr_t *)data);
103511e25f0dSDavid C Somayajulu 		break;
103611e25f0dSDavid C Somayajulu 
103711e25f0dSDavid C Somayajulu 	case QLNX_RD_WR_PCICFG:
103811e25f0dSDavid C Somayajulu 		rval = qlnx_rd_wr_pci_config(ha, (qlnx_pcicfg_rd_wr_t *)data);
103911e25f0dSDavid C Somayajulu 		break;
104011e25f0dSDavid C Somayajulu 
104111e25f0dSDavid C Somayajulu 	case QLNX_MAC_ADDR:
104211e25f0dSDavid C Somayajulu 		qlnx_mac_addr(ha, (qlnx_perm_mac_addr_t *)data);
104311e25f0dSDavid C Somayajulu 		break;
104411e25f0dSDavid C Somayajulu 
104511e25f0dSDavid C Somayajulu 	case QLNX_STORM_STATS:
104611e25f0dSDavid C Somayajulu 		qlnx_storm_stats(ha, (qlnx_storm_stats_dump_t *)data);
104711e25f0dSDavid C Somayajulu 		break;
104811e25f0dSDavid C Somayajulu 
104911e25f0dSDavid C Somayajulu 	case QLNX_TRACE_SIZE:
105011e25f0dSDavid C Somayajulu 		qlnx_get_trace_size(ha, (qlnx_trace_t *)data);
105111e25f0dSDavid C Somayajulu 		break;
105211e25f0dSDavid C Somayajulu 
105311e25f0dSDavid C Somayajulu 	case QLNX_TRACE:
105411e25f0dSDavid C Somayajulu 		trace = (qlnx_trace_t *)data;
105511e25f0dSDavid C Somayajulu 
105611e25f0dSDavid C Somayajulu 		for (i = 0; i < ha->cdev.num_hwfns; i++) {
105711e25f0dSDavid C Somayajulu 			if (trace->size[i] && trace->cmd && trace->buffer[i])
105811e25f0dSDavid C Somayajulu 				rval = qlnx_get_trace(ha, i, trace);
105911e25f0dSDavid C Somayajulu 
106011e25f0dSDavid C Somayajulu 			if (rval)
106111e25f0dSDavid C Somayajulu 				break;
106211e25f0dSDavid C Somayajulu 		}
106311e25f0dSDavid C Somayajulu 		break;
106411e25f0dSDavid C Somayajulu 
1065217ec208SDavid C Somayajulu #ifdef QLNX_USER_LLDP
1066217ec208SDavid C Somayajulu 	case QLNX_SET_LLDP_TLVS:
1067217ec208SDavid C Somayajulu 		rval = qlnx_set_lldp_tlvx(ha, (qlnx_lldp_sys_tlvs_t *)data);
1068217ec208SDavid C Somayajulu 		break;
1069217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_USER_LLDP */
1070217ec208SDavid C Somayajulu 
107111e25f0dSDavid C Somayajulu 	default:
107211e25f0dSDavid C Somayajulu 		rval = EINVAL;
107311e25f0dSDavid C Somayajulu 		break;
107411e25f0dSDavid C Somayajulu 	}
107511e25f0dSDavid C Somayajulu 
107611e25f0dSDavid C Somayajulu 	return (rval);
107711e25f0dSDavid C Somayajulu }
1078