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/10/sys/dev/qlnx/qlnxe/qlnx_ioctl.c 337519 2018-08-09 01:39:47Z 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"
62337519Sdavidcs#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) {
125318662Sdavidcs		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
136318662Sdavidcs		QL_DPRINT1(ha,"ecore_dbg_grc_dump failed [%d, 0x%x]\n",
137318662Sdavidcs			   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
179318662Sdavidcs		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) {
214318662Sdavidcs		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
225318662Sdavidcs		QL_DPRINT1(ha,"ecore_dbg_idle_chk_dump failed [%d, 0x%x]\n",
226318662Sdavidcs			   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
270318662Sdavidcs		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) {
297318662Sdavidcs                QL_DPRINT1(ha, "ecore_ptt_acquire [%d, 0x%x]failed\n",
298318662Sdavidcs                           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) {
331318662Sdavidcs                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) {
365318662Sdavidcs                QL_DPRINT1(ha,"qlnx_zalloc [%d, 0x%x]failed\n",
366318662Sdavidcs                           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) {
375318662Sdavidcs                QL_DPRINT1(ha, "ecore_ptt_acquire [%d, 0x%x]failed\n",
376318662Sdavidcs                           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) {
414318662Sdavidcs                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
538316485Sdavidcsstatic int
539316485Sdavidcsqlnx_drv_info(qlnx_host_t *ha, qlnx_drvinfo_t *drv_info)
540316485Sdavidcs{
541316485Sdavidcs	int i;
542316485Sdavidcs	extern char qlnx_name_str[];
543316485Sdavidcs	extern char qlnx_ver_str[];
544316485Sdavidcs
545316485Sdavidcs	bzero(drv_info, sizeof(qlnx_drvinfo_t));
546316485Sdavidcs
547316485Sdavidcs	snprintf(drv_info->drv_name, sizeof(drv_info->drv_name), "%s",
548316485Sdavidcs		qlnx_name_str);
549316485Sdavidcs	snprintf(drv_info->drv_version, sizeof(drv_info->drv_version), "%s",
550316485Sdavidcs		qlnx_ver_str);
551316485Sdavidcs	snprintf(drv_info->mfw_version, sizeof(drv_info->mfw_version), "%s",
552316485Sdavidcs		ha->mfw_ver);
553316485Sdavidcs	snprintf(drv_info->stormfw_version, sizeof(drv_info->stormfw_version),
554316485Sdavidcs		"%s", ha->stormfw_ver);
555316485Sdavidcs
556316485Sdavidcs	drv_info->eeprom_dump_len = ha->flash_size;
557316485Sdavidcs
558316485Sdavidcs	for (i = 0; i < ha->cdev.num_hwfns; i++) {
559316485Sdavidcs		drv_info->reg_dump_len += ha->grcdump_size[i];
560316485Sdavidcs	}
561316485Sdavidcs
562316485Sdavidcs	snprintf(drv_info->bus_info, sizeof(drv_info->bus_info),
563316485Sdavidcs		"%d:%d:%d", pci_get_bus(ha->pci_dev),
564316485Sdavidcs		pci_get_slot(ha->pci_dev), ha->pci_func);
565316485Sdavidcs
566316485Sdavidcs	return (0);
567316485Sdavidcs}
568316485Sdavidcs
569316485Sdavidcsstatic int
570316485Sdavidcsqlnx_dev_settings(qlnx_host_t *ha, qlnx_dev_setting_t *dev_info)
571316485Sdavidcs{
572316485Sdavidcs	struct ecore_hwfn *p_hwfn;
573316485Sdavidcs	struct qlnx_link_output if_link;
574316485Sdavidcs
575316485Sdavidcs	p_hwfn = &ha->cdev.hwfns[0];
576316485Sdavidcs
577337519Sdavidcs	qlnx_fill_link(ha, p_hwfn, &if_link);
578316485Sdavidcs
579316485Sdavidcs	dev_info->supported = if_link.supported_caps;
580316485Sdavidcs	dev_info->advertising = if_link.advertised_caps;
581316485Sdavidcs	dev_info->speed = if_link.speed;
582316485Sdavidcs	dev_info->duplex = if_link.duplex;
583316485Sdavidcs	dev_info->port = ha->pci_func & 0x1;
584316485Sdavidcs	dev_info->autoneg = if_link.autoneg;
585316485Sdavidcs
586316485Sdavidcs	return (0);
587316485Sdavidcs}
588316485Sdavidcs
589316485Sdavidcsstatic int
590316485Sdavidcsqlnx_write_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram, uint32_t cmd)
591316485Sdavidcs{
592316485Sdavidcs	uint8_t *buf;
593316485Sdavidcs	int ret = 0;
594316485Sdavidcs
595316485Sdavidcs	if ((nvram->data == NULL) || (nvram->data_len == 0))
596316485Sdavidcs		return (EINVAL);
597316485Sdavidcs
598316485Sdavidcs	buf = qlnx_zalloc(nvram->data_len);
599316485Sdavidcs
600316485Sdavidcs	ret = copyin(nvram->data, buf, nvram->data_len);
601316485Sdavidcs
602318662Sdavidcs	QL_DPRINT9(ha, "issue cmd = 0x%x data = %p \
603318662Sdavidcs		 data_len = 0x%x ret = 0x%x exit\n",
604318662Sdavidcs		cmd, nvram->data, nvram->data_len, ret);
605316485Sdavidcs
606316485Sdavidcs	if (ret == 0) {
607316485Sdavidcs		ret = ecore_mcp_nvm_write(&ha->cdev, cmd,
608316485Sdavidcs			nvram->offset, buf, nvram->data_len);
609316485Sdavidcs	}
610316485Sdavidcs
611318662Sdavidcs	QL_DPRINT9(ha, "cmd = 0x%x data = %p \
612318662Sdavidcs		 data_len = 0x%x resp = 0x%x ret = 0x%x exit\n",
613318662Sdavidcs		cmd, nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret);
614316485Sdavidcs
615316485Sdavidcs	free(buf, M_QLNXBUF);
616316485Sdavidcs
617316485Sdavidcs	return (ret);
618316485Sdavidcs}
619316485Sdavidcs
620316485Sdavidcsstatic int
621316485Sdavidcsqlnx_read_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram)
622316485Sdavidcs{
623316485Sdavidcs	uint8_t *buf;
624316485Sdavidcs	int ret = 0;
625316485Sdavidcs
626316485Sdavidcs	if ((nvram->data == NULL) || (nvram->data_len == 0))
627316485Sdavidcs		return (EINVAL);
628316485Sdavidcs
629316485Sdavidcs	buf = qlnx_zalloc(nvram->data_len);
630316485Sdavidcs
631316485Sdavidcs	ret = ecore_mcp_nvm_read(&ha->cdev, nvram->offset, buf,
632316485Sdavidcs		nvram->data_len);
633316485Sdavidcs
634318662Sdavidcs	QL_DPRINT9(ha, " data = %p data_len = 0x%x \
635318662Sdavidcs		 resp = 0x%x ret = 0x%x exit\n",
636318662Sdavidcs		nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret);
637316485Sdavidcs
638316485Sdavidcs	if (ret == 0) {
639316485Sdavidcs		ret = copyout(buf, nvram->data, nvram->data_len);
640316485Sdavidcs	}
641316485Sdavidcs
642316485Sdavidcs	free(buf, M_QLNXBUF);
643316485Sdavidcs
644316485Sdavidcs	return (ret);
645316485Sdavidcs}
646316485Sdavidcs
647316485Sdavidcsstatic int
648316485Sdavidcsqlnx_get_nvram_resp(qlnx_host_t *ha, qlnx_nvram_t *nvram)
649316485Sdavidcs{
650316485Sdavidcs	uint8_t *buf;
651316485Sdavidcs	int ret = 0;
652316485Sdavidcs
653316485Sdavidcs	if ((nvram->data == NULL) || (nvram->data_len == 0))
654316485Sdavidcs		return (EINVAL);
655316485Sdavidcs
656316485Sdavidcs	buf = qlnx_zalloc(nvram->data_len);
657316485Sdavidcs
658316485Sdavidcs
659316485Sdavidcs	ret = ecore_mcp_nvm_resp(&ha->cdev, buf);
660316485Sdavidcs
661318662Sdavidcs	QL_DPRINT9(ha, "data = %p data_len = 0x%x \
662318662Sdavidcs		 resp = 0x%x ret = 0x%x exit\n",
663318662Sdavidcs		nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret);
664316485Sdavidcs
665316485Sdavidcs	if (ret == 0) {
666316485Sdavidcs		ret = copyout(buf, nvram->data, nvram->data_len);
667316485Sdavidcs	}
668316485Sdavidcs
669316485Sdavidcs	free(buf, M_QLNXBUF);
670316485Sdavidcs
671316485Sdavidcs	return (ret);
672316485Sdavidcs}
673316485Sdavidcs
674316485Sdavidcsstatic int
675316485Sdavidcsqlnx_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram)
676316485Sdavidcs{
677316485Sdavidcs	int ret = 0;
678316485Sdavidcs
679316485Sdavidcs	switch (nvram->cmd) {
680316485Sdavidcs
681316485Sdavidcs	case QLNX_NVRAM_CMD_WRITE_NVRAM:
682316485Sdavidcs		ret = qlnx_write_nvram(ha, nvram, ECORE_NVM_WRITE_NVRAM);
683316485Sdavidcs		break;
684316485Sdavidcs
685316485Sdavidcs	case QLNX_NVRAM_CMD_PUT_FILE_DATA:
686316485Sdavidcs		ret = qlnx_write_nvram(ha, nvram, ECORE_PUT_FILE_DATA);
687316485Sdavidcs		break;
688316485Sdavidcs
689316485Sdavidcs	case QLNX_NVRAM_CMD_READ_NVRAM:
690316485Sdavidcs		ret = qlnx_read_nvram(ha, nvram);
691316485Sdavidcs		break;
692316485Sdavidcs
693316485Sdavidcs	case QLNX_NVRAM_CMD_SET_SECURE_MODE:
694316485Sdavidcs		ret = ecore_mcp_nvm_set_secure_mode(&ha->cdev, nvram->offset);
695316485Sdavidcs
696318662Sdavidcs		QL_DPRINT9(ha, "QLNX_NVRAM_CMD_SET_SECURE_MODE \
697318662Sdavidcs			 resp = 0x%x ret = 0x%x exit\n",
698318662Sdavidcs			 ha->cdev.mcp_nvm_resp, ret);
699316485Sdavidcs		break;
700316485Sdavidcs
701316485Sdavidcs	case QLNX_NVRAM_CMD_DEL_FILE:
702316485Sdavidcs		ret = ecore_mcp_nvm_del_file(&ha->cdev, nvram->offset);
703316485Sdavidcs
704318662Sdavidcs		QL_DPRINT9(ha, "QLNX_NVRAM_CMD_DEL_FILE \
705318662Sdavidcs			 resp = 0x%x ret = 0x%x exit\n",
706318662Sdavidcs			ha->cdev.mcp_nvm_resp, ret);
707316485Sdavidcs		break;
708316485Sdavidcs
709316485Sdavidcs	case QLNX_NVRAM_CMD_PUT_FILE_BEGIN:
710316485Sdavidcs		ret = ecore_mcp_nvm_put_file_begin(&ha->cdev, nvram->offset);
711316485Sdavidcs
712318662Sdavidcs		QL_DPRINT9(ha, "QLNX_NVRAM_CMD_PUT_FILE_BEGIN \
713318662Sdavidcs			 resp = 0x%x ret = 0x%x exit\n",
714318662Sdavidcs			ha->cdev.mcp_nvm_resp, ret);
715316485Sdavidcs		break;
716316485Sdavidcs
717316485Sdavidcs	case QLNX_NVRAM_CMD_GET_NVRAM_RESP:
718316485Sdavidcs		ret = qlnx_get_nvram_resp(ha, nvram);
719316485Sdavidcs		break;
720316485Sdavidcs
721316485Sdavidcs	default:
722316485Sdavidcs		ret = EINVAL;
723316485Sdavidcs		break;
724316485Sdavidcs	}
725316485Sdavidcs
726316485Sdavidcs	return (ret);
727316485Sdavidcs}
728316485Sdavidcs
729316485Sdavidcsstatic void
730316485Sdavidcsqlnx_storm_stats(qlnx_host_t *ha, qlnx_storm_stats_dump_t *s_stats)
731316485Sdavidcs{
732316485Sdavidcs	int i;
733316485Sdavidcs	int index;
734316485Sdavidcs	int ret;
735316485Sdavidcs	int stats_copied = 0;
736316485Sdavidcs
737316485Sdavidcs	s_stats->num_hwfns = ha->cdev.num_hwfns;
738316485Sdavidcs
739316485Sdavidcs//	if (ha->storm_stats_index < QLNX_STORM_STATS_SAMPLES_PER_HWFN)
740316485Sdavidcs//		return;
741316485Sdavidcs
742316485Sdavidcs	s_stats->num_samples = ha->storm_stats_index;
743316485Sdavidcs
744316485Sdavidcs	for (i = 0; i < ha->cdev.num_hwfns; i++) {
745316485Sdavidcs
746316485Sdavidcs		index = (QLNX_STORM_STATS_SAMPLES_PER_HWFN * i);
747316485Sdavidcs
748316485Sdavidcs		if (s_stats->buffer[i]) {
749316485Sdavidcs
750316485Sdavidcs			ret = copyout(&ha->storm_stats[index],
751316485Sdavidcs					s_stats->buffer[i],
752316485Sdavidcs					QLNX_STORM_STATS_BYTES_PER_HWFN);
753316485Sdavidcs			if (ret) {
754316485Sdavidcs				printf("%s [%d]: failed\n", __func__, i);
755316485Sdavidcs			}
756316485Sdavidcs
757316485Sdavidcs			if (s_stats->num_samples ==
758316485Sdavidcs				QLNX_STORM_STATS_SAMPLES_PER_HWFN) {
759316485Sdavidcs
760316485Sdavidcs				bzero((void *)&ha->storm_stats[i],
761316485Sdavidcs					QLNX_STORM_STATS_BYTES_PER_HWFN);
762316485Sdavidcs
763316485Sdavidcs				stats_copied = 1;
764316485Sdavidcs			}
765316485Sdavidcs		}
766316485Sdavidcs	}
767316485Sdavidcs
768316485Sdavidcs	if (stats_copied)
769316485Sdavidcs		ha->storm_stats_index = 0;
770316485Sdavidcs
771316485Sdavidcs	return;
772316485Sdavidcs}
773316485Sdavidcs
774337519Sdavidcs#ifdef QLNX_USER_LLDP
775316485Sdavidcs
776316485Sdavidcsstatic int
777337519Sdavidcsqlnx_lldp_configure(qlnx_host_t *ha, struct ecore_hwfn *p_hwfn,
778337519Sdavidcs	struct ecore_ptt *p_ptt, uint32_t enable)
779337519Sdavidcs{
780337519Sdavidcs	int ret = 0;
781337519Sdavidcs	uint8_t lldp_mac[6] = {0};
782337519Sdavidcs	struct ecore_lldp_config_params lldp_params;
783337519Sdavidcs	struct ecore_lldp_sys_tlvs tlv_params;
784337519Sdavidcs
785337519Sdavidcs	ret = ecore_mcp_get_lldp_mac(p_hwfn, p_ptt, lldp_mac);
786337519Sdavidcs
787337519Sdavidcs	if (ret != ECORE_SUCCESS) {
788337519Sdavidcs                device_printf(ha->pci_dev,
789337519Sdavidcs			"%s: ecore_mcp_get_lldp_mac failed\n", __func__);
790337519Sdavidcs                return (-1);
791337519Sdavidcs	}
792337519Sdavidcs
793337519Sdavidcs	bzero(&lldp_params, sizeof(struct ecore_lldp_config_params));
794337519Sdavidcs	bzero(&tlv_params, sizeof(struct ecore_lldp_sys_tlvs));
795337519Sdavidcs
796337519Sdavidcs	lldp_params.agent = ECORE_LLDP_NEAREST_BRIDGE;
797337519Sdavidcs	lldp_params.tx_interval = 30; //Default value used as suggested by MFW
798337519Sdavidcs	lldp_params.tx_hold = 4; //Default value used as suggested by MFW
799337519Sdavidcs	lldp_params.tx_credit = 5; //Default value used as suggested by MFW
800337519Sdavidcs	lldp_params.rx_enable = enable ? 1 : 0;
801337519Sdavidcs	lldp_params.tx_enable = enable ? 1 : 0;
802337519Sdavidcs
803337519Sdavidcs	lldp_params.chassis_id_tlv[0] = 0;
804337519Sdavidcs	lldp_params.chassis_id_tlv[0] |= (QLNX_LLDP_TYPE_CHASSIS_ID << 1);
805337519Sdavidcs	lldp_params.chassis_id_tlv[0] |=
806337519Sdavidcs		((QLNX_LLDP_CHASSIS_ID_SUBTYPE_OCTETS +
807337519Sdavidcs			QLNX_LLDP_CHASSIS_ID_MAC_ADDR_LEN) << 8);
808337519Sdavidcs	lldp_params.chassis_id_tlv[0] |= (QLNX_LLDP_CHASSIS_ID_SUBTYPE_MAC << 16);
809337519Sdavidcs	lldp_params.chassis_id_tlv[0] |= lldp_mac[0] << 24;
810337519Sdavidcs	lldp_params.chassis_id_tlv[1] = lldp_mac[1] | (lldp_mac[2] << 8) |
811337519Sdavidcs		 (lldp_mac[3] << 16) | (lldp_mac[4] << 24);
812337519Sdavidcs	lldp_params.chassis_id_tlv[2] = lldp_mac[5];
813337519Sdavidcs
814337519Sdavidcs
815337519Sdavidcs	lldp_params.port_id_tlv[0] = 0;
816337519Sdavidcs	lldp_params.port_id_tlv[0] |= (QLNX_LLDP_TYPE_PORT_ID << 1);
817337519Sdavidcs	lldp_params.port_id_tlv[0] |=
818337519Sdavidcs		((QLNX_LLDP_PORT_ID_SUBTYPE_OCTETS +
819337519Sdavidcs			QLNX_LLDP_PORT_ID_MAC_ADDR_LEN) << 8);
820337519Sdavidcs	lldp_params.port_id_tlv[0] |= (QLNX_LLDP_PORT_ID_SUBTYPE_MAC << 16);
821337519Sdavidcs	lldp_params.port_id_tlv[0] |= lldp_mac[0] << 24;
822337519Sdavidcs	lldp_params.port_id_tlv[1] = lldp_mac[1] | (lldp_mac[2] << 8) |
823337519Sdavidcs		 (lldp_mac[3] << 16) | (lldp_mac[4] << 24);
824337519Sdavidcs	lldp_params.port_id_tlv[2] = lldp_mac[5];
825337519Sdavidcs
826337519Sdavidcs	ret = ecore_lldp_set_params(p_hwfn, p_ptt, &lldp_params);
827337519Sdavidcs
828337519Sdavidcs	if (ret != ECORE_SUCCESS) {
829337519Sdavidcs                device_printf(ha->pci_dev,
830337519Sdavidcs			"%s: ecore_lldp_set_params failed\n", __func__);
831337519Sdavidcs                return (-1);
832337519Sdavidcs	}
833337519Sdavidcs
834337519Sdavidcs	//If LLDP is disable then disable discard_mandatory_tlv flag
835337519Sdavidcs	if (!enable) {
836337519Sdavidcs		tlv_params.discard_mandatory_tlv = false;
837337519Sdavidcs		tlv_params.buf_size = 0;
838337519Sdavidcs		ret = ecore_lldp_set_system_tlvs(p_hwfn, p_ptt, &tlv_params);
839337519Sdavidcs    	}
840337519Sdavidcs
841337519Sdavidcs	if (ret != ECORE_SUCCESS) {
842337519Sdavidcs                device_printf(ha->pci_dev,
843337519Sdavidcs			"%s: ecore_lldp_set_system_tlvs failed\n", __func__);
844337519Sdavidcs	}
845337519Sdavidcs
846337519Sdavidcs	return (ret);
847337519Sdavidcs}
848337519Sdavidcs
849337519Sdavidcsstatic int
850337519Sdavidcsqlnx_register_default_lldp_tlvs(qlnx_host_t *ha, struct ecore_hwfn *p_hwfn,
851337519Sdavidcs	struct ecore_ptt *p_ptt)
852337519Sdavidcs{
853337519Sdavidcs	int ret = 0;
854337519Sdavidcs
855337519Sdavidcs	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
856337519Sdavidcs			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_CHASSIS_ID);
857337519Sdavidcs	if (ret != ECORE_SUCCESS) {
858337519Sdavidcs                device_printf(ha->pci_dev,
859337519Sdavidcs			"%s: QLNX_LLDP_TYPE_CHASSIS_ID failed\n", __func__);
860337519Sdavidcs		goto qlnx_register_default_lldp_tlvs_exit;
861337519Sdavidcs	}
862337519Sdavidcs
863337519Sdavidcs	//register Port ID TLV
864337519Sdavidcs	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
865337519Sdavidcs			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_PORT_ID);
866337519Sdavidcs	if (ret != ECORE_SUCCESS) {
867337519Sdavidcs                device_printf(ha->pci_dev,
868337519Sdavidcs			"%s: QLNX_LLDP_TYPE_PORT_ID failed\n", __func__);
869337519Sdavidcs		goto qlnx_register_default_lldp_tlvs_exit;
870337519Sdavidcs	}
871337519Sdavidcs
872337519Sdavidcs	//register TTL TLV
873337519Sdavidcs	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
874337519Sdavidcs			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_TTL);
875337519Sdavidcs	if (ret != ECORE_SUCCESS) {
876337519Sdavidcs                device_printf(ha->pci_dev,
877337519Sdavidcs			"%s: QLNX_LLDP_TYPE_TTL failed\n", __func__);
878337519Sdavidcs		goto qlnx_register_default_lldp_tlvs_exit;
879337519Sdavidcs	}
880337519Sdavidcs
881337519Sdavidcs	//register Port Description TLV
882337519Sdavidcs	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
883337519Sdavidcs			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_PORT_DESC);
884337519Sdavidcs	if (ret != ECORE_SUCCESS) {
885337519Sdavidcs                device_printf(ha->pci_dev,
886337519Sdavidcs			"%s: QLNX_LLDP_TYPE_PORT_DESC failed\n", __func__);
887337519Sdavidcs		goto qlnx_register_default_lldp_tlvs_exit;
888337519Sdavidcs	}
889337519Sdavidcs
890337519Sdavidcs	//register System Name TLV
891337519Sdavidcs	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
892337519Sdavidcs			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_SYS_NAME);
893337519Sdavidcs	if (ret != ECORE_SUCCESS) {
894337519Sdavidcs                device_printf(ha->pci_dev,
895337519Sdavidcs			"%s: QLNX_LLDP_TYPE_SYS_NAME failed\n", __func__);
896337519Sdavidcs		goto qlnx_register_default_lldp_tlvs_exit;
897337519Sdavidcs	}
898337519Sdavidcs
899337519Sdavidcs	//register System Description TLV
900337519Sdavidcs	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
901337519Sdavidcs			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_SYS_DESC);
902337519Sdavidcs	if (ret != ECORE_SUCCESS) {
903337519Sdavidcs                device_printf(ha->pci_dev,
904337519Sdavidcs			"%s: QLNX_LLDP_TYPE_SYS_DESC failed\n", __func__);
905337519Sdavidcs		goto qlnx_register_default_lldp_tlvs_exit;
906337519Sdavidcs	}
907337519Sdavidcs
908337519Sdavidcs	//register System Capabilities TLV
909337519Sdavidcs	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
910337519Sdavidcs			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_SYS_CAPS);
911337519Sdavidcs	if (ret != ECORE_SUCCESS) {
912337519Sdavidcs                device_printf(ha->pci_dev,
913337519Sdavidcs			"%s: QLNX_LLDP_TYPE_SYS_CAPS failed\n", __func__);
914337519Sdavidcs		goto qlnx_register_default_lldp_tlvs_exit;
915337519Sdavidcs	}
916337519Sdavidcs
917337519Sdavidcs	//register Management Address TLV
918337519Sdavidcs	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
919337519Sdavidcs			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_MGMT_ADDR);
920337519Sdavidcs	if (ret != ECORE_SUCCESS) {
921337519Sdavidcs                device_printf(ha->pci_dev,
922337519Sdavidcs			"%s: QLNX_LLDP_TYPE_MGMT_ADDR failed\n", __func__);
923337519Sdavidcs		goto qlnx_register_default_lldp_tlvs_exit;
924337519Sdavidcs	}
925337519Sdavidcs
926337519Sdavidcs	//register Organizationally Specific TLVs
927337519Sdavidcs	ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
928337519Sdavidcs			ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_ORG_SPECIFIC);
929337519Sdavidcs	if (ret != ECORE_SUCCESS) {
930337519Sdavidcs                device_printf(ha->pci_dev,
931337519Sdavidcs			"%s: QLNX_LLDP_TYPE_ORG_SPECIFIC failed\n", __func__);
932337519Sdavidcs	}
933337519Sdavidcs
934337519Sdavidcsqlnx_register_default_lldp_tlvs_exit:
935337519Sdavidcs	return (ret);
936337519Sdavidcs}
937337519Sdavidcs
938337519Sdavidcsint
939337519Sdavidcsqlnx_set_lldp_tlvx(qlnx_host_t *ha, qlnx_lldp_sys_tlvs_t *lldp_tlvs)
940337519Sdavidcs{
941337519Sdavidcs	int ret = 0;
942337519Sdavidcs	struct ecore_hwfn *p_hwfn;
943337519Sdavidcs	struct ecore_ptt *p_ptt;
944337519Sdavidcs	struct ecore_lldp_sys_tlvs tlv_params;
945337519Sdavidcs
946337519Sdavidcs	p_hwfn = &ha->cdev.hwfns[0];
947337519Sdavidcs	p_ptt = ecore_ptt_acquire(p_hwfn);
948337519Sdavidcs
949337519Sdavidcs        if (!p_ptt) {
950337519Sdavidcs                device_printf(ha->pci_dev,
951337519Sdavidcs			"%s: ecore_ptt_acquire failed\n", __func__);
952337519Sdavidcs                return (ENXIO);
953337519Sdavidcs        }
954337519Sdavidcs
955337519Sdavidcs	ret = qlnx_lldp_configure(ha, p_hwfn, p_ptt, 0);
956337519Sdavidcs
957337519Sdavidcs	if (ret) {
958337519Sdavidcs                device_printf(ha->pci_dev,
959337519Sdavidcs			"%s: qlnx_lldp_configure disable failed\n", __func__);
960337519Sdavidcs		goto qlnx_set_lldp_tlvx_exit;
961337519Sdavidcs	}
962337519Sdavidcs
963337519Sdavidcs	ret = qlnx_register_default_lldp_tlvs(ha, p_hwfn, p_ptt);
964337519Sdavidcs
965337519Sdavidcs	if (ret) {
966337519Sdavidcs                device_printf(ha->pci_dev,
967337519Sdavidcs			"%s: qlnx_register_default_lldp_tlvs failed\n",
968337519Sdavidcs			__func__);
969337519Sdavidcs		goto qlnx_set_lldp_tlvx_exit;
970337519Sdavidcs	}
971337519Sdavidcs
972337519Sdavidcs	ret = qlnx_lldp_configure(ha, p_hwfn, p_ptt, 1);
973337519Sdavidcs
974337519Sdavidcs	if (ret) {
975337519Sdavidcs                device_printf(ha->pci_dev,
976337519Sdavidcs			"%s: qlnx_lldp_configure enable failed\n", __func__);
977337519Sdavidcs		goto qlnx_set_lldp_tlvx_exit;
978337519Sdavidcs	}
979337519Sdavidcs
980337519Sdavidcs	if (lldp_tlvs != NULL) {
981337519Sdavidcs		bzero(&tlv_params, sizeof(struct ecore_lldp_sys_tlvs));
982337519Sdavidcs
983337519Sdavidcs		tlv_params.discard_mandatory_tlv =
984337519Sdavidcs			(lldp_tlvs->discard_mandatory_tlv ? true: false);
985337519Sdavidcs		tlv_params.buf_size = lldp_tlvs->buf_size;
986337519Sdavidcs		memcpy(tlv_params.buf, lldp_tlvs->buf, lldp_tlvs->buf_size);
987337519Sdavidcs
988337519Sdavidcs		ret = ecore_lldp_set_system_tlvs(p_hwfn, p_ptt, &tlv_params);
989337519Sdavidcs
990337519Sdavidcs		if (ret) {
991337519Sdavidcs			device_printf(ha->pci_dev,
992337519Sdavidcs				"%s: ecore_lldp_set_system_tlvs failed\n",
993337519Sdavidcs				__func__);
994337519Sdavidcs		}
995337519Sdavidcs	}
996337519Sdavidcsqlnx_set_lldp_tlvx_exit:
997337519Sdavidcs
998337519Sdavidcs	ecore_ptt_release(p_hwfn, p_ptt);
999337519Sdavidcs	return (ret);
1000337519Sdavidcs}
1001337519Sdavidcs
1002337519Sdavidcs#endif /* #ifdef QLNX_USER_LLDP */
1003337519Sdavidcs
1004337519Sdavidcsstatic int
1005316485Sdavidcsqlnx_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
1006316485Sdavidcs	struct thread *td)
1007316485Sdavidcs{
1008316485Sdavidcs	qlnx_host_t	*ha;
1009316485Sdavidcs	int		rval = 0;
1010316485Sdavidcs	struct ifnet	*ifp;
1011316485Sdavidcs	qlnx_trace_t	*trace;
1012316485Sdavidcs	int		i;
1013316485Sdavidcs
1014316485Sdavidcs	if ((ha = (qlnx_host_t *)dev->si_drv1) == NULL)
1015316485Sdavidcs		return ENXIO;
1016316485Sdavidcs
1017316485Sdavidcs	ifp = ha->ifp;
1018316485Sdavidcs
1019316485Sdavidcs	switch (cmd) {
1020316485Sdavidcs
1021316485Sdavidcs	case QLNX_GRC_DUMP_SIZE:
1022316485Sdavidcs		qlnx_get_grc_dump_size(ha, (qlnx_grcdump_t *)data);
1023316485Sdavidcs		break;
1024316485Sdavidcs
1025316485Sdavidcs	case QLNX_GRC_DUMP:
1026316485Sdavidcs		rval = qlnx_get_grc_dump(ha, (qlnx_grcdump_t *)data);
1027316485Sdavidcs		break;
1028316485Sdavidcs
1029316485Sdavidcs	case QLNX_IDLE_CHK_SIZE:
1030316485Sdavidcs		qlnx_get_idle_chk_size(ha, (qlnx_idle_chk_t *)data);
1031316485Sdavidcs		break;
1032316485Sdavidcs
1033316485Sdavidcs	case QLNX_IDLE_CHK:
1034316485Sdavidcs		rval = qlnx_get_idle_chk(ha, (qlnx_idle_chk_t *)data);
1035316485Sdavidcs		break;
1036316485Sdavidcs
1037316485Sdavidcs	case QLNX_DRV_INFO:
1038316485Sdavidcs		rval = qlnx_drv_info(ha, (qlnx_drvinfo_t *)data);
1039316485Sdavidcs		break;
1040316485Sdavidcs
1041316485Sdavidcs	case QLNX_DEV_SETTING:
1042316485Sdavidcs		rval = qlnx_dev_settings(ha, (qlnx_dev_setting_t *)data);
1043316485Sdavidcs		break;
1044316485Sdavidcs
1045316485Sdavidcs	case QLNX_GET_REGS:
1046316485Sdavidcs		rval = qlnx_get_regs(ha, (qlnx_get_regs_t *)data);
1047316485Sdavidcs		break;
1048316485Sdavidcs
1049316485Sdavidcs	case QLNX_NVRAM:
1050316485Sdavidcs		rval = qlnx_nvram(ha, (qlnx_nvram_t *)data);
1051316485Sdavidcs		break;
1052316485Sdavidcs
1053316485Sdavidcs	case QLNX_RD_WR_REG:
1054316485Sdavidcs		rval = qlnx_reg_rd_wr(ha, (qlnx_reg_rd_wr_t *)data);
1055316485Sdavidcs		break;
1056316485Sdavidcs
1057316485Sdavidcs	case QLNX_RD_WR_PCICFG:
1058316485Sdavidcs		rval = qlnx_rd_wr_pci_config(ha, (qlnx_pcicfg_rd_wr_t *)data);
1059316485Sdavidcs		break;
1060316485Sdavidcs
1061316485Sdavidcs	case QLNX_MAC_ADDR:
1062316485Sdavidcs		qlnx_mac_addr(ha, (qlnx_perm_mac_addr_t *)data);
1063316485Sdavidcs		break;
1064316485Sdavidcs
1065316485Sdavidcs	case QLNX_STORM_STATS:
1066316485Sdavidcs		qlnx_storm_stats(ha, (qlnx_storm_stats_dump_t *)data);
1067316485Sdavidcs		break;
1068316485Sdavidcs
1069316485Sdavidcs	case QLNX_TRACE_SIZE:
1070316485Sdavidcs		qlnx_get_trace_size(ha, (qlnx_trace_t *)data);
1071316485Sdavidcs		break;
1072316485Sdavidcs
1073316485Sdavidcs	case QLNX_TRACE:
1074316485Sdavidcs		trace = (qlnx_trace_t *)data;
1075316485Sdavidcs
1076316485Sdavidcs		for (i = 0; i < ha->cdev.num_hwfns; i++) {
1077316485Sdavidcs
1078316485Sdavidcs			if (trace->size[i] && trace->cmd && trace->buffer[i])
1079316485Sdavidcs				rval = qlnx_get_trace(ha, i, trace);
1080316485Sdavidcs
1081316485Sdavidcs			if (rval)
1082316485Sdavidcs				break;
1083316485Sdavidcs		}
1084316485Sdavidcs		break;
1085316485Sdavidcs
1086337519Sdavidcs#ifdef QLNX_USER_LLDP
1087337519Sdavidcs	case QLNX_SET_LLDP_TLVS:
1088337519Sdavidcs		rval = qlnx_set_lldp_tlvx(ha, (qlnx_lldp_sys_tlvs_t *)data);
1089337519Sdavidcs		break;
1090337519Sdavidcs#endif /* #ifdef QLNX_USER_LLDP */
1091337519Sdavidcs
1092316485Sdavidcs	default:
1093316485Sdavidcs		rval = EINVAL;
1094316485Sdavidcs		break;
1095316485Sdavidcs	}
1096316485Sdavidcs
1097316485Sdavidcs	return (rval);
1098316485Sdavidcs}
1099316485Sdavidcs
1100