1316485Sdavidcs/*
2316485Sdavidcs * Copyright (c) 2017-2018 Cavium, Inc.
3316485Sdavidcs * All rights reserved.
4316485Sdavidcs *
5316485Sdavidcs *  Redistribution and use in source and binary forms, with or without
6316485Sdavidcs *  modification, are permitted provided that the following conditions
7316485Sdavidcs *  are met:
8316485Sdavidcs *
9316485Sdavidcs *  1. Redistributions of source code must retain the above copyright
10316485Sdavidcs *     notice, this list of conditions and the following disclaimer.
11316485Sdavidcs *  2. Redistributions in binary form must reproduce the above copyright
12316485Sdavidcs *     notice, this list of conditions and the following disclaimer in the
13316485Sdavidcs *     documentation and/or other materials provided with the distribution.
14316485Sdavidcs *
15316485Sdavidcs *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16316485Sdavidcs *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17316485Sdavidcs *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18316485Sdavidcs *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19316485Sdavidcs *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20316485Sdavidcs *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21316485Sdavidcs *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22316485Sdavidcs *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23316485Sdavidcs *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24316485Sdavidcs *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25316485Sdavidcs *  POSSIBILITY OF SUCH DAMAGE.
26316485Sdavidcs */
27316485Sdavidcs
28316485Sdavidcs
29316485Sdavidcs/*
30316485Sdavidcs * File: qlnx_ioctl.c
31316485Sdavidcs * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
32316485Sdavidcs */
33316485Sdavidcs
34316485Sdavidcs#include <sys/cdefs.h>
35316485Sdavidcs__FBSDID("$FreeBSD: stable/11/sys/dev/qlnx/qlnxe/qlnx_ioctl.c 337517 2018-08-09 01:17:35Z davidcs $");
36316485Sdavidcs
37316485Sdavidcs#include "qlnx_os.h"
38316485Sdavidcs#include "bcm_osal.h"
39316485Sdavidcs
40316485Sdavidcs#include "reg_addr.h"
41316485Sdavidcs#include "ecore_gtt_reg_addr.h"
42316485Sdavidcs#include "ecore.h"
43316485Sdavidcs#include "ecore_chain.h"
44316485Sdavidcs#include "ecore_status.h"
45316485Sdavidcs#include "ecore_hw.h"
46316485Sdavidcs#include "ecore_rt_defs.h"
47316485Sdavidcs#include "ecore_init_ops.h"
48316485Sdavidcs#include "ecore_int.h"
49316485Sdavidcs#include "ecore_cxt.h"
50316485Sdavidcs#include "ecore_spq.h"
51316485Sdavidcs#include "ecore_init_fw_funcs.h"
52316485Sdavidcs#include "ecore_sp_commands.h"
53316485Sdavidcs#include "ecore_dev_api.h"
54316485Sdavidcs#include "ecore_l2_api.h"
55316485Sdavidcs#include "ecore_mcp.h"
56316485Sdavidcs#include "ecore_hw_defs.h"
57316485Sdavidcs#include "mcp_public.h"
58316485Sdavidcs#include "ecore_iro.h"
59316485Sdavidcs#include "nvm_cfg.h"
60316485Sdavidcs#include "ecore_dev_api.h"
61316485Sdavidcs#include "ecore_dbg_fw_funcs.h"
62337517Sdavidcs#include "ecore_dcbx_api.h"
63316485Sdavidcs
64316485Sdavidcs#include "qlnx_ioctl.h"
65316485Sdavidcs#include "qlnx_def.h"
66316485Sdavidcs#include "qlnx_ver.h"
67316485Sdavidcs#include <sys/smp.h>
68316485Sdavidcs
69316485Sdavidcs
70316485Sdavidcsstatic int qlnx_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
71316485Sdavidcs                struct thread *td);
72316485Sdavidcs
73316485Sdavidcsstatic struct cdevsw qlnx_cdevsw = {
74316485Sdavidcs        .d_version = D_VERSION,
75316485Sdavidcs        .d_ioctl = qlnx_eioctl,
76316485Sdavidcs        .d_name = "qlnxioctl",
77316485Sdavidcs};
78316485Sdavidcs
79316485Sdavidcsint
80316485Sdavidcsqlnx_make_cdev(qlnx_host_t *ha)
81316485Sdavidcs{
82316485Sdavidcs	ha->ioctl_dev = make_dev(&qlnx_cdevsw,
83316485Sdavidcs				ha->ifp->if_dunit,
84316485Sdavidcs				UID_ROOT,
85316485Sdavidcs				GID_WHEEL,
86316485Sdavidcs				0600,
87316485Sdavidcs				"%s",
88316485Sdavidcs				if_name(ha->ifp));
89316485Sdavidcs
90316485Sdavidcs	if (ha->ioctl_dev == NULL)
91316485Sdavidcs		return (-1);
92316485Sdavidcs
93316485Sdavidcs	ha->ioctl_dev->si_drv1 = ha;
94316485Sdavidcs
95316485Sdavidcs	return (0);
96316485Sdavidcs}
97316485Sdavidcs
98316485Sdavidcsvoid
99316485Sdavidcsqlnx_del_cdev(qlnx_host_t *ha)
100316485Sdavidcs{
101316485Sdavidcs	if (ha->ioctl_dev != NULL)
102316485Sdavidcs		destroy_dev(ha->ioctl_dev);
103316485Sdavidcs	return;
104316485Sdavidcs}
105316485Sdavidcs
106316485Sdavidcsint
107316485Sdavidcsqlnx_grc_dump(qlnx_host_t *ha, uint32_t *num_dumped_dwords, int hwfn_index)
108316485Sdavidcs{
109316485Sdavidcs	int rval = EINVAL;
110316485Sdavidcs	struct ecore_hwfn *p_hwfn;
111316485Sdavidcs	struct ecore_ptt *p_ptt;
112316485Sdavidcs
113316485Sdavidcs	if (ha->grcdump_dwords[hwfn_index]) {
114316485Sdavidcs		/* the grcdump is already available */
115316485Sdavidcs		*num_dumped_dwords = ha->grcdump_dwords[hwfn_index];
116316485Sdavidcs		return (0);
117316485Sdavidcs	}
118316485Sdavidcs
119316485Sdavidcs	ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver());
120316485Sdavidcs
121316485Sdavidcs	p_hwfn = &ha->cdev.hwfns[hwfn_index];
122316485Sdavidcs	p_ptt = ecore_ptt_acquire(p_hwfn);
123316485Sdavidcs
124316485Sdavidcs	if (!p_ptt) {
125318659Sdavidcs		QL_DPRINT1(ha,"ecore_ptt_acquire failed\n");
126316485Sdavidcs		return (rval);
127316485Sdavidcs	}
128316485Sdavidcs
129316485Sdavidcs	if ((rval = ecore_dbg_grc_dump(p_hwfn, p_ptt,
130316485Sdavidcs			ha->grcdump[hwfn_index],
131316485Sdavidcs			(ha->grcdump_size[hwfn_index] >> 2),
132316485Sdavidcs			num_dumped_dwords)) == DBG_STATUS_OK) {
133316485Sdavidcs	 	rval = 0;
134316485Sdavidcs		ha->grcdump_taken = 1;
135316485Sdavidcs	} else
136318659Sdavidcs		QL_DPRINT1(ha,"ecore_dbg_grc_dump failed [%d, 0x%x]\n",
137318659Sdavidcs			   hwfn_index, rval);
138316485Sdavidcs
139316485Sdavidcs	ecore_ptt_release(p_hwfn, p_ptt);
140316485Sdavidcs
141316485Sdavidcs	return (rval);
142316485Sdavidcs}
143316485Sdavidcs
144316485Sdavidcsstatic void
145316485Sdavidcsqlnx_get_grc_dump_size(qlnx_host_t *ha, qlnx_grcdump_t *grcdump)
146316485Sdavidcs{
147316485Sdavidcs	int i;
148316485Sdavidcs
149316485Sdavidcs	grcdump->pci_func = ha->pci_func;
150316485Sdavidcs
151316485Sdavidcs	for (i = 0; i < ha->cdev.num_hwfns; i++)
152316485Sdavidcs		grcdump->grcdump_size[i] = ha->grcdump_size[i];
153316485Sdavidcs
154316485Sdavidcs	return;
155316485Sdavidcs}
156316485Sdavidcs
157316485Sdavidcsstatic int
158316485Sdavidcsqlnx_get_grc_dump(qlnx_host_t *ha, qlnx_grcdump_t *grcdump)
159316485Sdavidcs{
160316485Sdavidcs	int		i;
161316485Sdavidcs	int		rval = 0;
162316485Sdavidcs	uint32_t	dwords = 0;
163316485Sdavidcs
164316485Sdavidcs	grcdump->pci_func = ha->pci_func;
165316485Sdavidcs
166316485Sdavidcs	for (i = 0; i < ha->cdev.num_hwfns; i++) {
167316485Sdavidcs
168316485Sdavidcs		if ((ha->grcdump[i] == NULL) || (grcdump->grcdump[i] == NULL) ||
169316485Sdavidcs			(grcdump->grcdump_size[i] < ha->grcdump_size[i]))
170316485Sdavidcs			return (EINVAL);
171316485Sdavidcs
172316485Sdavidcs		rval = qlnx_grc_dump(ha, &dwords, i);
173316485Sdavidcs
174316485Sdavidcs		if (rval)
175316485Sdavidcs			break;
176316485Sdavidcs
177316485Sdavidcs		grcdump->grcdump_dwords[i] = dwords;
178316485Sdavidcs
179318659Sdavidcs		QL_DPRINT1(ha,"grcdump_dwords[%d] = 0x%x\n", i, dwords);
180316485Sdavidcs
181316485Sdavidcs		rval = copyout(ha->grcdump[i], grcdump->grcdump[i],
182316485Sdavidcs				ha->grcdump_size[i]);
183316485Sdavidcs
184316485Sdavidcs		if (rval)
185316485Sdavidcs			break;
186316485Sdavidcs
187316485Sdavidcs		ha->grcdump_dwords[i] = 0;
188316485Sdavidcs	}
189316485Sdavidcs
190316485Sdavidcs	ha->grcdump_taken = 0;
191316485Sdavidcs
192316485Sdavidcs	return (rval);
193316485Sdavidcs}
194316485Sdavidcs
195316485Sdavidcsint
196316485Sdavidcsqlnx_idle_chk(qlnx_host_t *ha, uint32_t *num_dumped_dwords, int hwfn_index)
197316485Sdavidcs{
198316485Sdavidcs	int rval = EINVAL;
199316485Sdavidcs	struct ecore_hwfn *p_hwfn;
200316485Sdavidcs	struct ecore_ptt *p_ptt;
201316485Sdavidcs
202316485Sdavidcs	if (ha->idle_chk_dwords[hwfn_index]) {
203316485Sdavidcs		/* the idle check is already available */
204316485Sdavidcs		*num_dumped_dwords = ha->idle_chk_dwords[hwfn_index];
205316485Sdavidcs		return (0);
206316485Sdavidcs	}
207316485Sdavidcs
208316485Sdavidcs	ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver());
209316485Sdavidcs
210316485Sdavidcs	p_hwfn = &ha->cdev.hwfns[hwfn_index];
211316485Sdavidcs	p_ptt = ecore_ptt_acquire(p_hwfn);
212316485Sdavidcs
213316485Sdavidcs	if (!p_ptt) {
214318659Sdavidcs		QL_DPRINT1(ha,"ecore_ptt_acquire failed\n");
215316485Sdavidcs		return (rval);
216316485Sdavidcs	}
217316485Sdavidcs
218316485Sdavidcs	if ((rval = ecore_dbg_idle_chk_dump(p_hwfn, p_ptt,
219316485Sdavidcs			ha->idle_chk[hwfn_index],
220316485Sdavidcs			(ha->idle_chk_size[hwfn_index] >> 2),
221316485Sdavidcs			num_dumped_dwords)) == DBG_STATUS_OK) {
222316485Sdavidcs	 	rval = 0;
223316485Sdavidcs		ha->idle_chk_taken = 1;
224316485Sdavidcs	} else
225318659Sdavidcs		QL_DPRINT1(ha,"ecore_dbg_idle_chk_dump failed [%d, 0x%x]\n",
226318659Sdavidcs			   hwfn_index, rval);
227316485Sdavidcs
228316485Sdavidcs	ecore_ptt_release(p_hwfn, p_ptt);
229316485Sdavidcs
230316485Sdavidcs	return (rval);
231316485Sdavidcs}
232316485Sdavidcs
233316485Sdavidcsstatic void
234316485Sdavidcsqlnx_get_idle_chk_size(qlnx_host_t *ha, qlnx_idle_chk_t *idle_chk)
235316485Sdavidcs{
236316485Sdavidcs	int i;
237316485Sdavidcs
238316485Sdavidcs	idle_chk->pci_func = ha->pci_func;
239316485Sdavidcs
240316485Sdavidcs	for (i = 0; i < ha->cdev.num_hwfns; i++)
241316485Sdavidcs		idle_chk->idle_chk_size[i] = ha->idle_chk_size[i];
242316485Sdavidcs
243316485Sdavidcs	return;
244316485Sdavidcs}
245316485Sdavidcs
246316485Sdavidcsstatic int
247316485Sdavidcsqlnx_get_idle_chk(qlnx_host_t *ha, qlnx_idle_chk_t *idle_chk)
248316485Sdavidcs{
249316485Sdavidcs	int		i;
250316485Sdavidcs	int		rval = 0;
251316485Sdavidcs	uint32_t	dwords = 0;
252316485Sdavidcs
253316485Sdavidcs	idle_chk->pci_func = ha->pci_func;
254316485Sdavidcs
255316485Sdavidcs	for (i = 0; i < ha->cdev.num_hwfns; i++) {
256316485Sdavidcs
257316485Sdavidcs		if ((ha->idle_chk[i] == NULL) ||
258316485Sdavidcs				(idle_chk->idle_chk[i] == NULL) ||
259316485Sdavidcs				(idle_chk->idle_chk_size[i] <
260316485Sdavidcs					ha->idle_chk_size[i]))
261316485Sdavidcs			return (EINVAL);
262316485Sdavidcs
263316485Sdavidcs		rval = qlnx_idle_chk(ha, &dwords, i);
264316485Sdavidcs
265316485Sdavidcs		if (rval)
266316485Sdavidcs			break;
267316485Sdavidcs
268316485Sdavidcs		idle_chk->idle_chk_dwords[i] = dwords;
269316485Sdavidcs
270318659Sdavidcs		QL_DPRINT1(ha,"idle_chk_dwords[%d] = 0x%x\n", i, dwords);
271316485Sdavidcs
272316485Sdavidcs               	rval = copyout(ha->idle_chk[i], idle_chk->idle_chk[i],
273316485Sdavidcs				ha->idle_chk_size[i]);
274316485Sdavidcs
275316485Sdavidcs		if (rval)
276316485Sdavidcs			break;
277316485Sdavidcs
278316485Sdavidcs		ha->idle_chk_dwords[i] = 0;
279316485Sdavidcs	}
280316485Sdavidcs	ha->idle_chk_taken = 0;
281316485Sdavidcs
282316485Sdavidcs	return (rval);
283316485Sdavidcs}
284316485Sdavidcs
285316485Sdavidcsstatic uint32_t
286316485Sdavidcsqlnx_get_trace_cmd_size(qlnx_host_t *ha, int hwfn_index, uint16_t cmd)
287316485Sdavidcs{
288316485Sdavidcs        int rval = -1;
289316485Sdavidcs        struct ecore_hwfn *p_hwfn;
290316485Sdavidcs        struct ecore_ptt *p_ptt;
291316485Sdavidcs	uint32_t num_dwords = 0;
292316485Sdavidcs
293316485Sdavidcs        p_hwfn = &ha->cdev.hwfns[hwfn_index];
294316485Sdavidcs        p_ptt = ecore_ptt_acquire(p_hwfn);
295316485Sdavidcs
296316485Sdavidcs        if (!p_ptt) {
297318659Sdavidcs                QL_DPRINT1(ha, "ecore_ptt_acquire [%d, 0x%x]failed\n",
298318659Sdavidcs                           hwfn_index, cmd);
299316485Sdavidcs                return (0);
300316485Sdavidcs        }
301316485Sdavidcs
302316485Sdavidcs	switch (cmd) {
303316485Sdavidcs
304316485Sdavidcs	case QLNX_MCP_TRACE:
305316485Sdavidcs        	rval = ecore_dbg_mcp_trace_get_dump_buf_size(p_hwfn,
306316485Sdavidcs				p_ptt, &num_dwords);
307316485Sdavidcs		break;
308316485Sdavidcs
309316485Sdavidcs	case QLNX_REG_FIFO:
310316485Sdavidcs        	rval = ecore_dbg_reg_fifo_get_dump_buf_size(p_hwfn,
311316485Sdavidcs				p_ptt, &num_dwords);
312316485Sdavidcs		break;
313316485Sdavidcs
314316485Sdavidcs	case QLNX_IGU_FIFO:
315316485Sdavidcs        	rval = ecore_dbg_igu_fifo_get_dump_buf_size(p_hwfn,
316316485Sdavidcs				p_ptt, &num_dwords);
317316485Sdavidcs		break;
318316485Sdavidcs
319316485Sdavidcs	case QLNX_PROTECTION_OVERRIDE:
320316485Sdavidcs        	rval = ecore_dbg_protection_override_get_dump_buf_size(p_hwfn,
321316485Sdavidcs				p_ptt, &num_dwords);
322316485Sdavidcs		break;
323316485Sdavidcs
324316485Sdavidcs	case QLNX_FW_ASSERTS:
325316485Sdavidcs        	rval = ecore_dbg_fw_asserts_get_dump_buf_size(p_hwfn,
326316485Sdavidcs				p_ptt, &num_dwords);
327316485Sdavidcs		break;
328316485Sdavidcs	}
329316485Sdavidcs
330316485Sdavidcs        if (rval != DBG_STATUS_OK) {
331318659Sdavidcs                QL_DPRINT1(ha,"cmd = 0x%x failed [0x%x]\n", cmd, rval);
332316485Sdavidcs		num_dwords = 0;
333316485Sdavidcs        }
334316485Sdavidcs
335316485Sdavidcs        ecore_ptt_release(p_hwfn, p_ptt);
336316485Sdavidcs
337316485Sdavidcs        return ((num_dwords * sizeof (uint32_t)));
338316485Sdavidcs}
339316485Sdavidcs
340316485Sdavidcsstatic void
341316485Sdavidcsqlnx_get_trace_size(qlnx_host_t *ha, qlnx_trace_t *trace)
342316485Sdavidcs{
343316485Sdavidcs	int i;
344316485Sdavidcs
345316485Sdavidcs	trace->pci_func = ha->pci_func;
346316485Sdavidcs
347316485Sdavidcs	for (i = 0; i < ha->cdev.num_hwfns; i++) {
348316485Sdavidcs		trace->size[i] = qlnx_get_trace_cmd_size(ha, i, trace->cmd);
349316485Sdavidcs	}
350316485Sdavidcs
351316485Sdavidcs	return;
352316485Sdavidcs}
353316485Sdavidcs
354316485Sdavidcsstatic int
355316485Sdavidcsqlnx_get_trace(qlnx_host_t *ha, int hwfn_index, qlnx_trace_t *trace)
356316485Sdavidcs{
357316485Sdavidcs        int rval = -1;
358316485Sdavidcs        struct ecore_hwfn *p_hwfn;
359316485Sdavidcs        struct ecore_ptt *p_ptt;
360316485Sdavidcs	uint32_t num_dwords = 0;
361316485Sdavidcs	void *buffer;
362316485Sdavidcs
363316485Sdavidcs	buffer = qlnx_zalloc(trace->size[hwfn_index]);
364316485Sdavidcs	if (buffer == NULL) {
365318659Sdavidcs                QL_DPRINT1(ha,"qlnx_zalloc [%d, 0x%x]failed\n",
366318659Sdavidcs                           hwfn_index, trace->cmd);
367316485Sdavidcs                return (ENXIO);
368316485Sdavidcs	}
369316485Sdavidcs	ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver());
370316485Sdavidcs
371316485Sdavidcs        p_hwfn = &ha->cdev.hwfns[hwfn_index];
372316485Sdavidcs        p_ptt = ecore_ptt_acquire(p_hwfn);
373316485Sdavidcs
374316485Sdavidcs        if (!p_ptt) {
375318659Sdavidcs                QL_DPRINT1(ha, "ecore_ptt_acquire [%d, 0x%x]failed\n",
376318659Sdavidcs                           hwfn_index, trace->cmd);
377316485Sdavidcs                return (ENXIO);
378316485Sdavidcs        }
379316485Sdavidcs
380316485Sdavidcs	switch (trace->cmd) {
381316485Sdavidcs
382316485Sdavidcs	case QLNX_MCP_TRACE:
383316485Sdavidcs        	rval = ecore_dbg_mcp_trace_dump(p_hwfn, p_ptt,
384316485Sdavidcs				buffer, (trace->size[hwfn_index] >> 2),
385316485Sdavidcs				&num_dwords);
386316485Sdavidcs		break;
387316485Sdavidcs
388316485Sdavidcs	case QLNX_REG_FIFO:
389316485Sdavidcs        	rval = ecore_dbg_reg_fifo_dump(p_hwfn, p_ptt,
390316485Sdavidcs				buffer, (trace->size[hwfn_index] >> 2),
391316485Sdavidcs				&num_dwords);
392316485Sdavidcs		break;
393316485Sdavidcs
394316485Sdavidcs	case QLNX_IGU_FIFO:
395316485Sdavidcs        	rval = ecore_dbg_igu_fifo_dump(p_hwfn, p_ptt,
396316485Sdavidcs				buffer, (trace->size[hwfn_index] >> 2),
397316485Sdavidcs				&num_dwords);
398316485Sdavidcs		break;
399316485Sdavidcs
400316485Sdavidcs	case QLNX_PROTECTION_OVERRIDE:
401316485Sdavidcs        	rval = ecore_dbg_protection_override_dump(p_hwfn, p_ptt,
402316485Sdavidcs				buffer, (trace->size[hwfn_index] >> 2),
403316485Sdavidcs				&num_dwords);
404316485Sdavidcs		break;
405316485Sdavidcs
406316485Sdavidcs	case QLNX_FW_ASSERTS:
407316485Sdavidcs        	rval = ecore_dbg_fw_asserts_dump(p_hwfn, p_ptt,
408316485Sdavidcs				buffer, (trace->size[hwfn_index] >> 2),
409316485Sdavidcs				&num_dwords);
410316485Sdavidcs		break;
411316485Sdavidcs	}
412316485Sdavidcs
413316485Sdavidcs        if (rval != DBG_STATUS_OK) {
414318659Sdavidcs                QL_DPRINT1(ha,"cmd = 0x%x failed [0x%x]\n", trace->cmd, rval);
415316485Sdavidcs		num_dwords = 0;
416316485Sdavidcs        }
417316485Sdavidcs
418316485Sdavidcs        ecore_ptt_release(p_hwfn, p_ptt);
419316485Sdavidcs
420316485Sdavidcs	trace->dwords[hwfn_index] = num_dwords;
421316485Sdavidcs
422316485Sdavidcs	if (num_dwords) {
423316485Sdavidcs               	rval = copyout(buffer, trace->buffer[hwfn_index],
424316485Sdavidcs				(num_dwords << 2));
425316485Sdavidcs	}
426316485Sdavidcs
427316485Sdavidcs        return (rval);
428316485Sdavidcs}
429316485Sdavidcs
430316485Sdavidcsstatic int
431316485Sdavidcsqlnx_reg_rd_wr(qlnx_host_t *ha, qlnx_reg_rd_wr_t *reg_rd_wr)
432316485Sdavidcs{
433316485Sdavidcs	int			rval = 0;
434316485Sdavidcs	struct ecore_hwfn	*p_hwfn;
435316485Sdavidcs
436316485Sdavidcs	if (reg_rd_wr->hwfn_index >= QLNX_MAX_HW_FUNCS) {
437316485Sdavidcs		return (EINVAL);
438316485Sdavidcs	}
439316485Sdavidcs
440316485Sdavidcs	p_hwfn = &ha->cdev.hwfns[reg_rd_wr->hwfn_index];
441316485Sdavidcs
442316485Sdavidcs	switch (reg_rd_wr->cmd) {
443316485Sdavidcs
444316485Sdavidcs		case QLNX_REG_READ_CMD:
445316485Sdavidcs			if (reg_rd_wr->access_type == QLNX_REG_ACCESS_DIRECT) {
446316485Sdavidcs				reg_rd_wr->val = qlnx_reg_rd32(p_hwfn,
447316485Sdavidcs							reg_rd_wr->addr);
448316485Sdavidcs			}
449316485Sdavidcs			break;
450316485Sdavidcs
451316485Sdavidcs		case QLNX_REG_WRITE_CMD:
452316485Sdavidcs			if (reg_rd_wr->access_type == QLNX_REG_ACCESS_DIRECT) {
453316485Sdavidcs				qlnx_reg_wr32(p_hwfn, reg_rd_wr->addr,
454316485Sdavidcs					reg_rd_wr->val);
455316485Sdavidcs			}
456316485Sdavidcs			break;
457316485Sdavidcs
458316485Sdavidcs		default:
459316485Sdavidcs			rval = EINVAL;
460316485Sdavidcs			break;
461316485Sdavidcs	}
462316485Sdavidcs
463316485Sdavidcs	return (rval);
464316485Sdavidcs}
465316485Sdavidcs
466316485Sdavidcsstatic int
467316485Sdavidcsqlnx_rd_wr_pci_config(qlnx_host_t *ha, qlnx_pcicfg_rd_wr_t *pci_cfg_rd_wr)
468316485Sdavidcs{
469316485Sdavidcs	int rval = 0;
470316485Sdavidcs
471316485Sdavidcs	switch (pci_cfg_rd_wr->cmd) {
472316485Sdavidcs
473316485Sdavidcs		case QLNX_PCICFG_READ:
474316485Sdavidcs			pci_cfg_rd_wr->val = pci_read_config(ha->pci_dev,
475316485Sdavidcs						pci_cfg_rd_wr->reg,
476316485Sdavidcs						pci_cfg_rd_wr->width);
477316485Sdavidcs			break;
478316485Sdavidcs
479316485Sdavidcs		case QLNX_PCICFG_WRITE:
480316485Sdavidcs			pci_write_config(ha->pci_dev, pci_cfg_rd_wr->reg,
481316485Sdavidcs				pci_cfg_rd_wr->val, pci_cfg_rd_wr->width);
482316485Sdavidcs			break;
483316485Sdavidcs
484316485Sdavidcs		default:
485316485Sdavidcs			rval = EINVAL;
486316485Sdavidcs			break;
487316485Sdavidcs	}
488316485Sdavidcs
489316485Sdavidcs	return (rval);
490316485Sdavidcs}
491316485Sdavidcs
492316485Sdavidcsstatic void
493316485Sdavidcsqlnx_mac_addr(qlnx_host_t *ha, qlnx_perm_mac_addr_t *mac_addr)
494316485Sdavidcs{
495316485Sdavidcs	bzero(mac_addr->addr, sizeof(mac_addr->addr));
496316485Sdavidcs	snprintf(mac_addr->addr, sizeof(mac_addr->addr),
497316485Sdavidcs		"%02x:%02x:%02x:%02x:%02x:%02x",
498316485Sdavidcs		ha->primary_mac[0], ha->primary_mac[1], ha->primary_mac[2],
499316485Sdavidcs		ha->primary_mac[3], ha->primary_mac[4], ha->primary_mac[5]);
500316485Sdavidcs
501316485Sdavidcs	return;
502316485Sdavidcs}
503316485Sdavidcs
504316485Sdavidcsstatic int
505316485Sdavidcsqlnx_get_regs(qlnx_host_t *ha, qlnx_get_regs_t *regs)
506316485Sdavidcs{
507316485Sdavidcs	int		i;
508316485Sdavidcs	int		rval = 0;
509316485Sdavidcs	uint32_t	dwords = 0;
510316485Sdavidcs	uint8_t		*outb;
511316485Sdavidcs
512316485Sdavidcs	regs->reg_buf_len = 0;
513316485Sdavidcs	outb = regs->reg_buf;
514316485Sdavidcs
515316485Sdavidcs	for (i = 0; i < ha->cdev.num_hwfns; i++) {
516316485Sdavidcs
517316485Sdavidcs		rval = qlnx_grc_dump(ha, &dwords, i);
518316485Sdavidcs
519316485Sdavidcs		if (rval)
520316485Sdavidcs			break;
521316485Sdavidcs
522316485Sdavidcs		regs->reg_buf_len += (dwords << 2);
523316485Sdavidcs
524316485Sdavidcs		rval = copyout(ha->grcdump[i], outb, ha->grcdump_size[i]);
525316485Sdavidcs
526316485Sdavidcs		if (rval)
527316485Sdavidcs			break;
528316485Sdavidcs
529316485Sdavidcs		ha->grcdump_dwords[i] = 0;
530316485Sdavidcs		outb += regs->reg_buf_len;
531316485Sdavidcs	}
532316485Sdavidcs
533316485Sdavidcs	ha->grcdump_taken = 0;
534316485Sdavidcs
535316485Sdavidcs	return (rval);
536316485Sdavidcs}
537316485Sdavidcs
538323213Srlibbyextern char qlnx_name_str[];
539323213Srlibbyextern char qlnx_ver_str[];
540323213Srlibby
541316485Sdavidcsstatic int
542316485Sdavidcsqlnx_drv_info(qlnx_host_t *ha, qlnx_drvinfo_t *drv_info)
543316485Sdavidcs{
544316485Sdavidcs	int i;
545316485Sdavidcs
546316485Sdavidcs	bzero(drv_info, sizeof(qlnx_drvinfo_t));
547316485Sdavidcs
548316485Sdavidcs	snprintf(drv_info->drv_name, sizeof(drv_info->drv_name), "%s",
549316485Sdavidcs		qlnx_name_str);
550316485Sdavidcs	snprintf(drv_info->drv_version, sizeof(drv_info->drv_version), "%s",
551316485Sdavidcs		qlnx_ver_str);
552316485Sdavidcs	snprintf(drv_info->mfw_version, sizeof(drv_info->mfw_version), "%s",
553316485Sdavidcs		ha->mfw_ver);
554316485Sdavidcs	snprintf(drv_info->stormfw_version, sizeof(drv_info->stormfw_version),
555316485Sdavidcs		"%s", ha->stormfw_ver);
556316485Sdavidcs
557316485Sdavidcs	drv_info->eeprom_dump_len = ha->flash_size;
558316485Sdavidcs
559316485Sdavidcs	for (i = 0; i < ha->cdev.num_hwfns; i++) {
560316485Sdavidcs		drv_info->reg_dump_len += ha->grcdump_size[i];
561316485Sdavidcs	}
562316485Sdavidcs
563316485Sdavidcs	snprintf(drv_info->bus_info, sizeof(drv_info->bus_info),
564316485Sdavidcs		"%d:%d:%d", pci_get_bus(ha->pci_dev),
565316485Sdavidcs		pci_get_slot(ha->pci_dev), ha->pci_func);
566316485Sdavidcs
567316485Sdavidcs	return (0);
568316485Sdavidcs}
569316485Sdavidcs
570316485Sdavidcsstatic int
571316485Sdavidcsqlnx_dev_settings(qlnx_host_t *ha, qlnx_dev_setting_t *dev_info)
572316485Sdavidcs{
573316485Sdavidcs	struct ecore_hwfn *p_hwfn;
574316485Sdavidcs	struct qlnx_link_output if_link;
575316485Sdavidcs
576316485Sdavidcs	p_hwfn = &ha->cdev.hwfns[0];
577316485Sdavidcs
578337517Sdavidcs	qlnx_fill_link(ha, p_hwfn, &if_link);
579316485Sdavidcs
580316485Sdavidcs	dev_info->supported = if_link.supported_caps;
581316485Sdavidcs	dev_info->advertising = if_link.advertised_caps;
582316485Sdavidcs	dev_info->speed = if_link.speed;
583316485Sdavidcs	dev_info->duplex = if_link.duplex;
584316485Sdavidcs	dev_info->port = ha->pci_func & 0x1;
585316485Sdavidcs	dev_info->autoneg = if_link.autoneg;
586316485Sdavidcs
587316485Sdavidcs	return (0);
588316485Sdavidcs}
589316485Sdavidcs
590316485Sdavidcsstatic int
591316485Sdavidcsqlnx_write_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram, uint32_t cmd)
592316485Sdavidcs{
593316485Sdavidcs	uint8_t *buf;
594316485Sdavidcs	int ret = 0;
595316485Sdavidcs
596316485Sdavidcs	if ((nvram->data == NULL) || (nvram->data_len == 0))
597316485Sdavidcs		return (EINVAL);
598316485Sdavidcs
599316485Sdavidcs	buf = qlnx_zalloc(nvram->data_len);
600316485Sdavidcs
601316485Sdavidcs	ret = copyin(nvram->data, buf, nvram->data_len);
602316485Sdavidcs
603318659Sdavidcs	QL_DPRINT9(ha, "issue cmd = 0x%x data = %p \
604318659Sdavidcs		 data_len = 0x%x ret = 0x%x exit\n",
605318659Sdavidcs		cmd, nvram->data, nvram->data_len, ret);
606316485Sdavidcs
607316485Sdavidcs	if (ret == 0) {
608316485Sdavidcs		ret = ecore_mcp_nvm_write(&ha->cdev, cmd,
609316485Sdavidcs			nvram->offset, buf, nvram->data_len);
610316485Sdavidcs	}
611316485Sdavidcs
612318659Sdavidcs	QL_DPRINT9(ha, "cmd = 0x%x data = %p \
613318659Sdavidcs		 data_len = 0x%x resp = 0x%x ret = 0x%x exit\n",
614318659Sdavidcs		cmd, nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret);
615316485Sdavidcs
616316485Sdavidcs	free(buf, M_QLNXBUF);
617316485Sdavidcs
618316485Sdavidcs	return (ret);
619316485Sdavidcs}
620316485Sdavidcs
621316485Sdavidcsstatic int
622316485Sdavidcsqlnx_read_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram)
623316485Sdavidcs{
624316485Sdavidcs	uint8_t *buf;
625316485Sdavidcs	int ret = 0;
626316485Sdavidcs
627316485Sdavidcs	if ((nvram->data == NULL) || (nvram->data_len == 0))
628316485Sdavidcs		return (EINVAL);
629316485Sdavidcs
630316485Sdavidcs	buf = qlnx_zalloc(nvram->data_len);
631316485Sdavidcs
632316485Sdavidcs	ret = ecore_mcp_nvm_read(&ha->cdev, nvram->offset, buf,
633316485Sdavidcs		nvram->data_len);
634316485Sdavidcs
635318659Sdavidcs	QL_DPRINT9(ha, " data = %p data_len = 0x%x \
636318659Sdavidcs		 resp = 0x%x ret = 0x%x exit\n",
637318659Sdavidcs		nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret);
638316485Sdavidcs
639316485Sdavidcs	if (ret == 0) {
640316485Sdavidcs		ret = copyout(buf, nvram->data, nvram->data_len);
641316485Sdavidcs	}
642316485Sdavidcs
643316485Sdavidcs	free(buf, M_QLNXBUF);
644316485Sdavidcs
645316485Sdavidcs	return (ret);
646316485Sdavidcs}
647316485Sdavidcs
648316485Sdavidcsstatic int
649316485Sdavidcsqlnx_get_nvram_resp(qlnx_host_t *ha, qlnx_nvram_t *nvram)
650316485Sdavidcs{
651316485Sdavidcs	uint8_t *buf;
652316485Sdavidcs	int ret = 0;
653316485Sdavidcs
654316485Sdavidcs	if ((nvram->data == NULL) || (nvram->data_len == 0))
655316485Sdavidcs		return (EINVAL);
656316485Sdavidcs
657316485Sdavidcs	buf = qlnx_zalloc(nvram->data_len);
658316485Sdavidcs
659316485Sdavidcs
660316485Sdavidcs	ret = ecore_mcp_nvm_resp(&ha->cdev, buf);
661316485Sdavidcs
662318659Sdavidcs	QL_DPRINT9(ha, "data = %p data_len = 0x%x \
663318659Sdavidcs		 resp = 0x%x ret = 0x%x exit\n",
664318659Sdavidcs		nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret);
665316485Sdavidcs
666316485Sdavidcs	if (ret == 0) {
667316485Sdavidcs		ret = copyout(buf, nvram->data, nvram->data_len);
668316485Sdavidcs	}
669316485Sdavidcs
670316485Sdavidcs	free(buf, M_QLNXBUF);
671316485Sdavidcs
672316485Sdavidcs	return (ret);
673316485Sdavidcs}
674316485Sdavidcs
675316485Sdavidcsstatic int
676316485Sdavidcsqlnx_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram)
677316485Sdavidcs{
678316485Sdavidcs	int ret = 0;
679316485Sdavidcs
680316485Sdavidcs	switch (nvram->cmd) {
681316485Sdavidcs
682316485Sdavidcs	case QLNX_NVRAM_CMD_WRITE_NVRAM:
683316485Sdavidcs		ret = qlnx_write_nvram(ha, nvram, ECORE_NVM_WRITE_NVRAM);
684316485Sdavidcs		break;
685316485Sdavidcs
686316485Sdavidcs	case QLNX_NVRAM_CMD_PUT_FILE_DATA:
687316485Sdavidcs		ret = qlnx_write_nvram(ha, nvram, ECORE_PUT_FILE_DATA);
688316485Sdavidcs		break;
689316485Sdavidcs
690316485Sdavidcs	case QLNX_NVRAM_CMD_READ_NVRAM:
691316485Sdavidcs		ret = qlnx_read_nvram(ha, nvram);
692316485Sdavidcs		break;
693316485Sdavidcs
694316485Sdavidcs	case QLNX_NVRAM_CMD_SET_SECURE_MODE:
695316485Sdavidcs		ret = ecore_mcp_nvm_set_secure_mode(&ha->cdev, nvram->offset);
696316485Sdavidcs
697318659Sdavidcs		QL_DPRINT9(ha, "QLNX_NVRAM_CMD_SET_SECURE_MODE \
698318659Sdavidcs			 resp = 0x%x ret = 0x%x exit\n",
699318659Sdavidcs			 ha->cdev.mcp_nvm_resp, ret);
700316485Sdavidcs		break;
701316485Sdavidcs
702316485Sdavidcs	case QLNX_NVRAM_CMD_DEL_FILE:
703316485Sdavidcs		ret = ecore_mcp_nvm_del_file(&ha->cdev, nvram->offset);
704316485Sdavidcs
705318659Sdavidcs		QL_DPRINT9(ha, "QLNX_NVRAM_CMD_DEL_FILE \
706318659Sdavidcs			 resp = 0x%x ret = 0x%x exit\n",
707318659Sdavidcs			ha->cdev.mcp_nvm_resp, ret);
708316485Sdavidcs		break;
709316485Sdavidcs
710316485Sdavidcs	case QLNX_NVRAM_CMD_PUT_FILE_BEGIN:
711316485Sdavidcs		ret = ecore_mcp_nvm_put_file_begin(&ha->cdev, nvram->offset);
712316485Sdavidcs
713318659Sdavidcs		QL_DPRINT9(ha, "QLNX_NVRAM_CMD_PUT_FILE_BEGIN \
714318659Sdavidcs			 resp = 0x%x ret = 0x%x exit\n",
715318659Sdavidcs			ha->cdev.mcp_nvm_resp, ret);
716316485Sdavidcs		break;
717316485Sdavidcs
718316485Sdavidcs	case QLNX_NVRAM_CMD_GET_NVRAM_RESP:
719316485Sdavidcs		ret = qlnx_get_nvram_resp(ha, nvram);
720316485Sdavidcs		break;
721316485Sdavidcs
722316485Sdavidcs	default:
723316485Sdavidcs		ret = EINVAL;
724316485Sdavidcs		break;
725316485Sdavidcs	}
726316485Sdavidcs
727316485Sdavidcs	return (ret);
728316485Sdavidcs}
729316485Sdavidcs
730316485Sdavidcsstatic void
731316485Sdavidcsqlnx_storm_stats(qlnx_host_t *ha, qlnx_storm_stats_dump_t *s_stats)
732316485Sdavidcs{
733316485Sdavidcs	int i;
734316485Sdavidcs	int index;
735316485Sdavidcs	int ret;
736316485Sdavidcs	int stats_copied = 0;
737316485Sdavidcs
738316485Sdavidcs	s_stats->num_hwfns = ha->cdev.num_hwfns;
739316485Sdavidcs
740316485Sdavidcs//	if (ha->storm_stats_index < QLNX_STORM_STATS_SAMPLES_PER_HWFN)
741316485Sdavidcs//		return;
742316485Sdavidcs
743316485Sdavidcs	s_stats->num_samples = ha->storm_stats_index;
744316485Sdavidcs
745316485Sdavidcs	for (i = 0; i < ha->cdev.num_hwfns; i++) {
746316485Sdavidcs
747316485Sdavidcs		index = (QLNX_STORM_STATS_SAMPLES_PER_HWFN * i);
748316485Sdavidcs
749316485Sdavidcs		if (s_stats->buffer[i]) {
750316485Sdavidcs
751316485Sdavidcs			ret = copyout(&ha->storm_stats[index],
752316485Sdavidcs					s_stats->buffer[i],
753316485Sdavidcs					QLNX_STORM_STATS_BYTES_PER_HWFN);
754316485Sdavidcs			if (ret) {
755316485Sdavidcs				printf("%s [%d]: failed\n", __func__, i);
756316485Sdavidcs			}
757316485Sdavidcs
758316485Sdavidcs			if (s_stats->num_samples ==
759316485Sdavidcs				QLNX_STORM_STATS_SAMPLES_PER_HWFN) {
760316485Sdavidcs
761316485Sdavidcs				bzero((void *)&ha->storm_stats[i],
762316485Sdavidcs					QLNX_STORM_STATS_BYTES_PER_HWFN);
763316485Sdavidcs
764316485Sdavidcs				stats_copied = 1;
765316485Sdavidcs			}
766316485Sdavidcs		}
767316485Sdavidcs	}
768316485Sdavidcs
769316485Sdavidcs	if (stats_copied)
770316485Sdavidcs		ha->storm_stats_index = 0;
771316485Sdavidcs
772316485Sdavidcs	return;
773316485Sdavidcs}
774316485Sdavidcs
775337517Sdavidcs#ifdef QLNX_USER_LLDP
776316485Sdavidcs
777316485Sdavidcsstatic int
778337517Sdavidcsqlnx_lldp_configure(qlnx_host_t *ha, struct ecore_hwfn *p_hwfn,
779337517Sdavidcs	struct ecore_ptt *p_ptt, uint32_t enable)
780337517Sdavidcs{
781337517Sdavidcs	int ret = 0;
782337517Sdavidcs	uint8_t lldp_mac[6] = {0};
783337517Sdavidcs	struct ecore_lldp_config_params lldp_params;
784337517Sdavidcs	struct ecore_lldp_sys_tlvs tlv_params;
785337517Sdavidcs
786337517Sdavidcs	ret = ecore_mcp_get_lldp_mac(p_hwfn, p_ptt, lldp_mac);
787337517Sdavidcs
788337517Sdavidcs	if (ret != ECORE_SUCCESS) {
789337517Sdavidcs                device_printf(ha->pci_dev,
790337517Sdavidcs			"%s: ecore_mcp_get_lldp_mac failed\n", __func__);
791337517Sdavidcs                return (-1);
792337517Sdavidcs	}
793337517Sdavidcs
794337517Sdavidcs	bzero(&lldp_params, sizeof(struct ecore_lldp_config_params));
795337517Sdavidcs	bzero(&tlv_params, sizeof(struct ecore_lldp_sys_tlvs));
796337517Sdavidcs
797337517Sdavidcs	lldp_params.agent = ECORE_LLDP_NEAREST_BRIDGE;
798337517Sdavidcs	lldp_params.tx_interval = 30; //Default value used as suggested by MFW
799337517Sdavidcs	lldp_params.tx_hold = 4; //Default value used as suggested by MFW
800337517Sdavidcs	lldp_params.tx_credit = 5; //Default value used as suggested by MFW
801337517Sdavidcs	lldp_params.rx_enable = enable ? 1 : 0;
802337517Sdavidcs	lldp_params.tx_enable = enable ? 1 : 0;
803337517Sdavidcs
804337517Sdavidcs	lldp_params.chassis_id_tlv[0] = 0;
805337517Sdavidcs	lldp_params.chassis_id_tlv[0] |= (QLNX_LLDP_TYPE_CHASSIS_ID << 1);
806337517Sdavidcs	lldp_params.chassis_id_tlv[0] |=
807337517Sdavidcs		((QLNX_LLDP_CHASSIS_ID_SUBTYPE_OCTETS +
808337517Sdavidcs			QLNX_LLDP_CHASSIS_ID_MAC_ADDR_LEN) << 8);
809337517Sdavidcs	lldp_params.chassis_id_tlv[0] |= (QLNX_LLDP_CHASSIS_ID_SUBTYPE_MAC << 16);
810337517Sdavidcs	lldp_params.chassis_id_tlv[0] |= lldp_mac[0] << 24;
811337517Sdavidcs	lldp_params.chassis_id_tlv[1] = lldp_mac[1] | (lldp_mac[2] << 8) |
812337517Sdavidcs		 (lldp_mac[3] << 16) | (lldp_mac[4] << 24);
813337517Sdavidcs	lldp_params.chassis_id_tlv[2] = lldp_mac[5];
814337517Sdavidcs
815337517Sdavidcs
816337517Sdavidcs	lldp_params.port_id_tlv[0] = 0;
817337517Sdavidcs	lldp_params.port_id_tlv[0] |= (QLNX_LLDP_TYPE_PORT_ID << 1);
818337517Sdavidcs	lldp_params.port_id_tlv[0] |=
819337517Sdavidcs		((QLNX_LLDP_PORT_ID_SUBTYPE_OCTETS +
820337517Sdavidcs			QLNX_LLDP_PORT_ID_MAC_ADDR_LEN) << 8);
821337517Sdavidcs	lldp_params.port_id_tlv[0] |= (QLNX_LLDP_PORT_ID_SUBTYPE_MAC << 16);
822337517Sdavidcs	lldp_params.port_id_tlv[0] |= lldp_mac[0] << 24;
823337517Sdavidcs	lldp_params.port_id_tlv[1] = lldp_mac[1] | (lldp_mac[2] << 8) |
824337517Sdavidcs		 (lldp_mac[3] << 16) | (lldp_mac[4] << 24);
825337517Sdavidcs	lldp_params.port_id_tlv[2] = lldp_mac[5];
826337517Sdavidcs
827337517Sdavidcs	ret = ecore_lldp_set_params(p_hwfn, p_ptt, &lldp_params);
828337517Sdavidcs
829337517Sdavidcs	if (ret != ECORE_SUCCESS) {
830337517Sdavidcs                device_printf(ha->pci_dev,
831337517Sdavidcs			"%s: ecore_lldp_set_params failed\n", __func__);
832337517Sdavidcs                return (-1);
833337517Sdavidcs	}
834337517Sdavidcs
835337517Sdavidcs	//If LLDP is disable then disable discard_mandatory_tlv flag
836337517Sdavidcs	if (!enable) {
837337517Sdavidcs		tlv_params.discard_mandatory_tlv = false;
838337517Sdavidcs		tlv_params.buf_size = 0;
839337517Sdavidcs		ret = ecore_lldp_set_system_tlvs(p_hwfn, p_ptt, &tlv_params);
840337517Sdavidcs    	}
841337517Sdavidcs
842337517Sdavidcs	if (ret != ECORE_SUCCESS) {
843337517Sdavidcs                device_printf(ha->pci_dev,
844337517Sdavidcs			"%s: ecore_lldp_set_system_tlvs failed\n", __func__);
845337517Sdavidcs	}
846337517Sdavidcs
847337517Sdavidcs	return (ret);
848337517Sdavidcs}
849337517Sdavidcs
850337517Sdavidcsstatic int
851337517Sdavidcsqlnx_register_default_lldp_tlvs(qlnx_host_t *ha, struct ecore_hwfn *p_hwfn,
852337517Sdavidcs	struct ecore_ptt *p_ptt)
853337517Sdavidcs{
854337517Sdavidcs	int ret = 0;
855337517Sdavidcs
856337517Sdavidcs	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
857337517Sdavidcs			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_CHASSIS_ID);
858337517Sdavidcs	if (ret != ECORE_SUCCESS) {
859337517Sdavidcs                device_printf(ha->pci_dev,
860337517Sdavidcs			"%s: QLNX_LLDP_TYPE_CHASSIS_ID failed\n", __func__);
861337517Sdavidcs		goto qlnx_register_default_lldp_tlvs_exit;
862337517Sdavidcs	}
863337517Sdavidcs
864337517Sdavidcs	//register Port ID TLV
865337517Sdavidcs	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
866337517Sdavidcs			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_PORT_ID);
867337517Sdavidcs	if (ret != ECORE_SUCCESS) {
868337517Sdavidcs                device_printf(ha->pci_dev,
869337517Sdavidcs			"%s: QLNX_LLDP_TYPE_PORT_ID failed\n", __func__);
870337517Sdavidcs		goto qlnx_register_default_lldp_tlvs_exit;
871337517Sdavidcs	}
872337517Sdavidcs
873337517Sdavidcs	//register TTL TLV
874337517Sdavidcs	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
875337517Sdavidcs			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_TTL);
876337517Sdavidcs	if (ret != ECORE_SUCCESS) {
877337517Sdavidcs                device_printf(ha->pci_dev,
878337517Sdavidcs			"%s: QLNX_LLDP_TYPE_TTL failed\n", __func__);
879337517Sdavidcs		goto qlnx_register_default_lldp_tlvs_exit;
880337517Sdavidcs	}
881337517Sdavidcs
882337517Sdavidcs	//register Port Description TLV
883337517Sdavidcs	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
884337517Sdavidcs			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_PORT_DESC);
885337517Sdavidcs	if (ret != ECORE_SUCCESS) {
886337517Sdavidcs                device_printf(ha->pci_dev,
887337517Sdavidcs			"%s: QLNX_LLDP_TYPE_PORT_DESC failed\n", __func__);
888337517Sdavidcs		goto qlnx_register_default_lldp_tlvs_exit;
889337517Sdavidcs	}
890337517Sdavidcs
891337517Sdavidcs	//register System Name TLV
892337517Sdavidcs	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
893337517Sdavidcs			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_SYS_NAME);
894337517Sdavidcs	if (ret != ECORE_SUCCESS) {
895337517Sdavidcs                device_printf(ha->pci_dev,
896337517Sdavidcs			"%s: QLNX_LLDP_TYPE_SYS_NAME failed\n", __func__);
897337517Sdavidcs		goto qlnx_register_default_lldp_tlvs_exit;
898337517Sdavidcs	}
899337517Sdavidcs
900337517Sdavidcs	//register System Description TLV
901337517Sdavidcs	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
902337517Sdavidcs			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_SYS_DESC);
903337517Sdavidcs	if (ret != ECORE_SUCCESS) {
904337517Sdavidcs                device_printf(ha->pci_dev,
905337517Sdavidcs			"%s: QLNX_LLDP_TYPE_SYS_DESC failed\n", __func__);
906337517Sdavidcs		goto qlnx_register_default_lldp_tlvs_exit;
907337517Sdavidcs	}
908337517Sdavidcs
909337517Sdavidcs	//register System Capabilities TLV
910337517Sdavidcs	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
911337517Sdavidcs			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_SYS_CAPS);
912337517Sdavidcs	if (ret != ECORE_SUCCESS) {
913337517Sdavidcs                device_printf(ha->pci_dev,
914337517Sdavidcs			"%s: QLNX_LLDP_TYPE_SYS_CAPS failed\n", __func__);
915337517Sdavidcs		goto qlnx_register_default_lldp_tlvs_exit;
916337517Sdavidcs	}
917337517Sdavidcs
918337517Sdavidcs	//register Management Address TLV
919337517Sdavidcs	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
920337517Sdavidcs			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_MGMT_ADDR);
921337517Sdavidcs	if (ret != ECORE_SUCCESS) {
922337517Sdavidcs                device_printf(ha->pci_dev,
923337517Sdavidcs			"%s: QLNX_LLDP_TYPE_MGMT_ADDR failed\n", __func__);
924337517Sdavidcs		goto qlnx_register_default_lldp_tlvs_exit;
925337517Sdavidcs	}
926337517Sdavidcs
927337517Sdavidcs	//register Organizationally Specific TLVs
928337517Sdavidcs	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
929337517Sdavidcs			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_ORG_SPECIFIC);
930337517Sdavidcs	if (ret != ECORE_SUCCESS) {
931337517Sdavidcs                device_printf(ha->pci_dev,
932337517Sdavidcs			"%s: QLNX_LLDP_TYPE_ORG_SPECIFIC failed\n", __func__);
933337517Sdavidcs	}
934337517Sdavidcs
935337517Sdavidcsqlnx_register_default_lldp_tlvs_exit:
936337517Sdavidcs	return (ret);
937337517Sdavidcs}
938337517Sdavidcs
939337517Sdavidcsint
940337517Sdavidcsqlnx_set_lldp_tlvx(qlnx_host_t *ha, qlnx_lldp_sys_tlvs_t *lldp_tlvs)
941337517Sdavidcs{
942337517Sdavidcs	int ret = 0;
943337517Sdavidcs	struct ecore_hwfn *p_hwfn;
944337517Sdavidcs	struct ecore_ptt *p_ptt;
945337517Sdavidcs	struct ecore_lldp_sys_tlvs tlv_params;
946337517Sdavidcs
947337517Sdavidcs	p_hwfn = &ha->cdev.hwfns[0];
948337517Sdavidcs	p_ptt = ecore_ptt_acquire(p_hwfn);
949337517Sdavidcs
950337517Sdavidcs        if (!p_ptt) {
951337517Sdavidcs                device_printf(ha->pci_dev,
952337517Sdavidcs			"%s: ecore_ptt_acquire failed\n", __func__);
953337517Sdavidcs                return (ENXIO);
954337517Sdavidcs        }
955337517Sdavidcs
956337517Sdavidcs	ret = qlnx_lldp_configure(ha, p_hwfn, p_ptt, 0);
957337517Sdavidcs
958337517Sdavidcs	if (ret) {
959337517Sdavidcs                device_printf(ha->pci_dev,
960337517Sdavidcs			"%s: qlnx_lldp_configure disable failed\n", __func__);
961337517Sdavidcs		goto qlnx_set_lldp_tlvx_exit;
962337517Sdavidcs	}
963337517Sdavidcs
964337517Sdavidcs	ret = qlnx_register_default_lldp_tlvs(ha, p_hwfn, p_ptt);
965337517Sdavidcs
966337517Sdavidcs	if (ret) {
967337517Sdavidcs                device_printf(ha->pci_dev,
968337517Sdavidcs			"%s: qlnx_register_default_lldp_tlvs failed\n",
969337517Sdavidcs			__func__);
970337517Sdavidcs		goto qlnx_set_lldp_tlvx_exit;
971337517Sdavidcs	}
972337517Sdavidcs
973337517Sdavidcs	ret = qlnx_lldp_configure(ha, p_hwfn, p_ptt, 1);
974337517Sdavidcs
975337517Sdavidcs	if (ret) {
976337517Sdavidcs                device_printf(ha->pci_dev,
977337517Sdavidcs			"%s: qlnx_lldp_configure enable failed\n", __func__);
978337517Sdavidcs		goto qlnx_set_lldp_tlvx_exit;
979337517Sdavidcs	}
980337517Sdavidcs
981337517Sdavidcs	if (lldp_tlvs != NULL) {
982337517Sdavidcs		bzero(&tlv_params, sizeof(struct ecore_lldp_sys_tlvs));
983337517Sdavidcs
984337517Sdavidcs		tlv_params.discard_mandatory_tlv =
985337517Sdavidcs			(lldp_tlvs->discard_mandatory_tlv ? true: false);
986337517Sdavidcs		tlv_params.buf_size = lldp_tlvs->buf_size;
987337517Sdavidcs		memcpy(tlv_params.buf, lldp_tlvs->buf, lldp_tlvs->buf_size);
988337517Sdavidcs
989337517Sdavidcs		ret = ecore_lldp_set_system_tlvs(p_hwfn, p_ptt, &tlv_params);
990337517Sdavidcs
991337517Sdavidcs		if (ret) {
992337517Sdavidcs			device_printf(ha->pci_dev,
993337517Sdavidcs				"%s: ecore_lldp_set_system_tlvs failed\n",
994337517Sdavidcs				__func__);
995337517Sdavidcs		}
996337517Sdavidcs	}
997337517Sdavidcsqlnx_set_lldp_tlvx_exit:
998337517Sdavidcs
999337517Sdavidcs	ecore_ptt_release(p_hwfn, p_ptt);
1000337517Sdavidcs	return (ret);
1001337517Sdavidcs}
1002337517Sdavidcs
1003337517Sdavidcs#endif /* #ifdef QLNX_USER_LLDP */
1004337517Sdavidcs
1005337517Sdavidcsstatic int
1006316485Sdavidcsqlnx_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
1007316485Sdavidcs	struct thread *td)
1008316485Sdavidcs{
1009316485Sdavidcs	qlnx_host_t	*ha;
1010316485Sdavidcs	int		rval = 0;
1011316485Sdavidcs	struct ifnet	*ifp;
1012316485Sdavidcs	qlnx_trace_t	*trace;
1013316485Sdavidcs	int		i;
1014316485Sdavidcs
1015316485Sdavidcs	if ((ha = (qlnx_host_t *)dev->si_drv1) == NULL)
1016316485Sdavidcs		return ENXIO;
1017316485Sdavidcs
1018316485Sdavidcs	ifp = ha->ifp;
1019316485Sdavidcs
1020316485Sdavidcs	switch (cmd) {
1021316485Sdavidcs
1022316485Sdavidcs	case QLNX_GRC_DUMP_SIZE:
1023316485Sdavidcs		qlnx_get_grc_dump_size(ha, (qlnx_grcdump_t *)data);
1024316485Sdavidcs		break;
1025316485Sdavidcs
1026316485Sdavidcs	case QLNX_GRC_DUMP:
1027316485Sdavidcs		rval = qlnx_get_grc_dump(ha, (qlnx_grcdump_t *)data);
1028316485Sdavidcs		break;
1029316485Sdavidcs
1030316485Sdavidcs	case QLNX_IDLE_CHK_SIZE:
1031316485Sdavidcs		qlnx_get_idle_chk_size(ha, (qlnx_idle_chk_t *)data);
1032316485Sdavidcs		break;
1033316485Sdavidcs
1034316485Sdavidcs	case QLNX_IDLE_CHK:
1035316485Sdavidcs		rval = qlnx_get_idle_chk(ha, (qlnx_idle_chk_t *)data);
1036316485Sdavidcs		break;
1037316485Sdavidcs
1038316485Sdavidcs	case QLNX_DRV_INFO:
1039316485Sdavidcs		rval = qlnx_drv_info(ha, (qlnx_drvinfo_t *)data);
1040316485Sdavidcs		break;
1041316485Sdavidcs
1042316485Sdavidcs	case QLNX_DEV_SETTING:
1043316485Sdavidcs		rval = qlnx_dev_settings(ha, (qlnx_dev_setting_t *)data);
1044316485Sdavidcs		break;
1045316485Sdavidcs
1046316485Sdavidcs	case QLNX_GET_REGS:
1047316485Sdavidcs		rval = qlnx_get_regs(ha, (qlnx_get_regs_t *)data);
1048316485Sdavidcs		break;
1049316485Sdavidcs
1050316485Sdavidcs	case QLNX_NVRAM:
1051316485Sdavidcs		rval = qlnx_nvram(ha, (qlnx_nvram_t *)data);
1052316485Sdavidcs		break;
1053316485Sdavidcs
1054316485Sdavidcs	case QLNX_RD_WR_REG:
1055316485Sdavidcs		rval = qlnx_reg_rd_wr(ha, (qlnx_reg_rd_wr_t *)data);
1056316485Sdavidcs		break;
1057316485Sdavidcs
1058316485Sdavidcs	case QLNX_RD_WR_PCICFG:
1059316485Sdavidcs		rval = qlnx_rd_wr_pci_config(ha, (qlnx_pcicfg_rd_wr_t *)data);
1060316485Sdavidcs		break;
1061316485Sdavidcs
1062316485Sdavidcs	case QLNX_MAC_ADDR:
1063316485Sdavidcs		qlnx_mac_addr(ha, (qlnx_perm_mac_addr_t *)data);
1064316485Sdavidcs		break;
1065316485Sdavidcs
1066316485Sdavidcs	case QLNX_STORM_STATS:
1067316485Sdavidcs		qlnx_storm_stats(ha, (qlnx_storm_stats_dump_t *)data);
1068316485Sdavidcs		break;
1069316485Sdavidcs
1070316485Sdavidcs	case QLNX_TRACE_SIZE:
1071316485Sdavidcs		qlnx_get_trace_size(ha, (qlnx_trace_t *)data);
1072316485Sdavidcs		break;
1073316485Sdavidcs
1074316485Sdavidcs	case QLNX_TRACE:
1075316485Sdavidcs		trace = (qlnx_trace_t *)data;
1076316485Sdavidcs
1077316485Sdavidcs		for (i = 0; i < ha->cdev.num_hwfns; i++) {
1078316485Sdavidcs
1079316485Sdavidcs			if (trace->size[i] && trace->cmd && trace->buffer[i])
1080316485Sdavidcs				rval = qlnx_get_trace(ha, i, trace);
1081316485Sdavidcs
1082316485Sdavidcs			if (rval)
1083316485Sdavidcs				break;
1084316485Sdavidcs		}
1085316485Sdavidcs		break;
1086316485Sdavidcs
1087337517Sdavidcs#ifdef QLNX_USER_LLDP
1088337517Sdavidcs	case QLNX_SET_LLDP_TLVS:
1089337517Sdavidcs		rval = qlnx_set_lldp_tlvx(ha, (qlnx_lldp_sys_tlvs_t *)data);
1090337517Sdavidcs		break;
1091337517Sdavidcs#endif /* #ifdef QLNX_USER_LLDP */
1092337517Sdavidcs
1093316485Sdavidcs	default:
1094316485Sdavidcs		rval = EINVAL;
1095316485Sdavidcs		break;
1096316485Sdavidcs	}
1097316485Sdavidcs
1098316485Sdavidcs	return (rval);
1099316485Sdavidcs}
1100316485Sdavidcs
1101