1/*
2 *   BSD LICENSE
3 *
4 *   Copyright(c) 2017 Cavium, Inc.. All rights reserved.
5 *   All rights reserved.
6 *
7 *   Redistribution and use in source and binary forms, with or without
8 *   modification, are permitted provided that the following conditions
9 *   are met:
10 *
11 *     * Redistributions of source code must retain the above copyright
12 *       notice, this list of conditions and the following disclaimer.
13 *     * Redistributions in binary form must reproduce the above copyright
14 *       notice, this list of conditions and the following disclaimer in
15 *       the documentation and/or other materials provided with the
16 *       distribution.
17 *     * Neither the name of Cavium, Inc. nor the names of its
18 *       contributors may be used to endorse or promote products derived
19 *       from this software without specific prior written permission.
20 *
21 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 *   OWNER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33/*$FreeBSD: stable/11/sys/dev/liquidio/lio_sysctl.c 325618 2017-11-09 19:52:56Z sbruno $*/
34
35#include <sys/types.h>
36
37#include "lio_bsd.h"
38#include "lio_common.h"
39#include "lio_droq.h"
40#include "lio_iq.h"
41#include "lio_response_manager.h"
42#include "lio_device.h"
43#include "lio_network.h"
44#include "lio_ctrl.h"
45#include "cn23xx_pf_device.h"
46#include "lio_image.h"
47#include "lio_main.h"
48#include "lio_rxtx.h"
49#include "lio_ioctl.h"
50
51#define LIO_OFF_PAUSE	0
52#define LIO_RX_PAUSE	1
53#define LIO_TX_PAUSE	2
54
55#define LIO_REGDUMP_LEN		4096
56#define LIO_REGDUMP_LEN_23XX	49248
57
58#define LIO_REGDUMP_LEN_XXXX	LIO_REGDUMP_LEN_23XX
59
60#define LIO_USE_ADAPTIVE_RX_COALESCE		1
61#define LIO_USE_ADAPTIVE_TX_COALESCE		2
62#define LIO_RX_COALESCE_USECS			3
63#define LIO_RX_MAX_COALESCED_FRAMES		4
64#define LIO_TX_MAX_COALESCED_FRAMES		8
65#define LIO_PKT_RATE_LOW			12
66#define LIO_RX_COALESCE_USECS_LOW		13
67#define LIO_RX_MAX_COALESCED_FRAMES_LOW		14
68#define LIO_TX_MAX_COALESCED_FRAMES_LOW		16
69#define LIO_PKT_RATE_HIGH			17
70#define LIO_RX_COALESCE_USECS_HIGH		18
71#define LIO_RX_MAX_COALESCED_FRAMES_HIGH	19
72#define LIO_TX_MAX_COALESCED_FRAMES_HIGH	21
73#define LIO_RATE_SAMPLE_INTERVAL		22
74
75#define LIO_SET_RING_RX				1
76#define LIO_SET_RING_TX				2
77
78static int	lio_get_eeprom(SYSCTL_HANDLER_ARGS);
79static int	lio_get_set_pauseparam(SYSCTL_HANDLER_ARGS);
80static int	lio_get_regs(SYSCTL_HANDLER_ARGS);
81static int	lio_cn23xx_pf_read_csr_reg(char *s, struct octeon_device *oct);
82static int	lio_get_set_fwmsglevel(SYSCTL_HANDLER_ARGS);
83static int	lio_set_stats_interval(SYSCTL_HANDLER_ARGS);
84static void	lio_get_fw_stats(void *arg);
85static int	lio_get_set_intr_coalesce(SYSCTL_HANDLER_ARGS);
86static int	lio_get_intrmod_cfg(struct lio *lio,
87				    struct octeon_intrmod_cfg *intr_cfg);
88static int	lio_get_ringparam(SYSCTL_HANDLER_ARGS);
89static int	lio_set_ringparam(SYSCTL_HANDLER_ARGS);
90static int	lio_get_channels(SYSCTL_HANDLER_ARGS);
91static int	lio_set_channels(SYSCTL_HANDLER_ARGS);
92static int	lio_irq_reallocate_irqs(struct octeon_device *oct,
93					uint32_t num_ioqs);
94
95struct lio_intrmod_context {
96	int	octeon_id;
97	volatile int cond;
98	int	status;
99};
100
101struct lio_intrmod_resp {
102	uint64_t	rh;
103	struct octeon_intrmod_cfg intrmod;
104	uint64_t	status;
105};
106
107static int
108lio_send_queue_count_update(struct ifnet *ifp, uint32_t num_queues)
109{
110	struct lio_ctrl_pkt	nctrl;
111	struct lio		*lio = if_getsoftc(ifp);
112	struct octeon_device	*oct = lio->oct_dev;
113	int ret = 0;
114
115	bzero(&nctrl, sizeof(struct lio_ctrl_pkt));
116
117	nctrl.ncmd.cmd64 = 0;
118	nctrl.ncmd.s.cmd = LIO_CMD_QUEUE_COUNT_CTL;
119	nctrl.ncmd.s.param1 = num_queues;
120	nctrl.ncmd.s.param2 = num_queues;
121	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
122	nctrl.wait_time = 100;
123	nctrl.lio = lio;
124	nctrl.cb_fn = lio_ctrl_cmd_completion;
125
126	ret = lio_send_ctrl_pkt(lio->oct_dev, &nctrl);
127	if (ret < 0) {
128		lio_dev_err(oct, "Failed to send Queue reset command (ret: 0x%x)\n",
129			    ret);
130		return (-1);
131	}
132
133	return (0);
134}
135
136/* Add sysctl variables to the system, one per statistic. */
137void
138lio_add_hw_stats(struct lio *lio)
139{
140	struct octeon_device	*oct_dev = lio->oct_dev;
141	device_t dev = oct_dev->device;
142
143	struct sysctl_ctx_list	*ctx = device_get_sysctl_ctx(dev);
144	struct sysctl_oid	*tree = device_get_sysctl_tree(dev);
145	struct sysctl_oid_list	*child = SYSCTL_CHILDREN(tree);
146	struct sysctl_oid	*stat_node, *queue_node, *root_node;
147	struct sysctl_oid_list	*stat_list, *queue_list, *root_list;
148#define QUEUE_NAME_LEN 32
149	char namebuf[QUEUE_NAME_LEN];
150
151	callout_reset(&lio->stats_timer, lio_ms_to_ticks(lio->stats_interval),
152		      lio_get_fw_stats, lio);
153
154	SYSCTL_ADD_STRING(ctx, child, OID_AUTO, "fwversion", CTLFLAG_RD,
155			  oct_dev->fw_info.lio_firmware_version, 0,
156			  "Firmware version");
157	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "stats_interval",
158			CTLTYPE_INT | CTLFLAG_RW, lio, 0,
159			lio_set_stats_interval,	"I",
160			"Set Stats Updation Timer in milli seconds");
161	SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "link_state_changes",
162			 CTLFLAG_RD, &lio->link_changes, "Link Change Counter");
163	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "eeprom-dump",
164			CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, lio, 0,
165			lio_get_eeprom, "A", "EEPROM information");
166	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "fc",
167			CTLTYPE_INT | CTLFLAG_RW, lio, 0,
168			lio_get_set_pauseparam, "I",
169			"Get and set pause parameters.\n" \
170			"0 - off\n" \
171			"1 - rx pause\n" \
172			"2 - tx pause \n" \
173			"3 - rx and tx pause");
174	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "register-dump",
175			CTLTYPE_STRING | CTLFLAG_RD,
176			lio, 0, lio_get_regs, "A",
177			"Dump registers in raw format");
178	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "fwmsglevel",
179			CTLTYPE_INT | CTLFLAG_RW, lio, 0,
180			lio_get_set_fwmsglevel,
181			"I", "Get or set firmware message level");
182	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rxq_descriptors",
183			CTLTYPE_INT | CTLFLAG_RW, lio, LIO_SET_RING_RX,
184			lio_set_ringparam, "I", "Set RX ring parameter");
185	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "txq_descriptors",
186			CTLTYPE_INT | CTLFLAG_RW, lio, LIO_SET_RING_TX,
187			lio_set_ringparam, "I", "Set TX ring parameter");
188	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "max_rxq_descriptors",
189			CTLTYPE_INT | CTLFLAG_RD, lio, LIO_SET_RING_RX,
190			lio_get_ringparam, "I", "Max RX descriptors");
191	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "max_txq_descriptors",
192			CTLTYPE_INT | CTLFLAG_RD, lio, LIO_SET_RING_TX,
193			lio_get_ringparam, "I", "Max TX descriptors");
194	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "active_queues",
195			CTLTYPE_INT | CTLFLAG_RW, lio, 0, lio_set_channels,
196			"I", "Set channels information");
197	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "max_queues",
198			CTLTYPE_INT | CTLFLAG_RD, lio, 0, lio_get_channels,
199			"I", "Get channels information");
200	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_budget",
201			CTLFLAG_RW, &oct_dev->tx_budget,
202			0, "TX process pkt budget");
203	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_budget",
204			CTLFLAG_RW, &oct_dev->rx_budget,
205			0, "RX process pkt budget");
206
207	/* IRQ Coalescing Parameters */
208	root_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "coalesce",
209				    CTLFLAG_RD, NULL, "Get and Set Coalesce");
210
211	root_list = SYSCTL_CHILDREN(root_node);
212
213	if (lio_get_intrmod_cfg(lio, &lio->intrmod_cfg))
214		lio_dev_info(oct_dev, "Coalescing driver update failed!\n");
215
216	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "sample-interval",
217			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
218			LIO_RATE_SAMPLE_INTERVAL, lio_get_set_intr_coalesce,
219			"QU", NULL);
220	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "tx-frame-high",
221			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
222			LIO_TX_MAX_COALESCED_FRAMES_HIGH,
223			lio_get_set_intr_coalesce, "QU", NULL);
224	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "rx-frame-high",
225			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
226			LIO_RX_MAX_COALESCED_FRAMES_HIGH,
227			lio_get_set_intr_coalesce, "QU", NULL);
228	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "rx-usecs-high",
229			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
230			LIO_RX_COALESCE_USECS_HIGH, lio_get_set_intr_coalesce,
231			"QU", NULL);
232	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "pkt-rate-high",
233			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
234			LIO_PKT_RATE_HIGH, lio_get_set_intr_coalesce,
235			"QU", NULL);
236	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "tx-frame-low",
237			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
238			LIO_TX_MAX_COALESCED_FRAMES_LOW,
239			lio_get_set_intr_coalesce, "QU", NULL);
240	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "rx-frame-low",
241			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
242			LIO_RX_MAX_COALESCED_FRAMES_LOW,
243			lio_get_set_intr_coalesce, "QU", NULL);
244	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "rx-usecs-low",
245			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
246			LIO_RX_COALESCE_USECS_LOW, lio_get_set_intr_coalesce,
247			"QU", NULL);
248	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "pkt-rate-low",
249			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
250			LIO_PKT_RATE_LOW, lio_get_set_intr_coalesce,
251			"QU", NULL);
252	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "tx-frames",
253			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
254			LIO_TX_MAX_COALESCED_FRAMES, lio_get_set_intr_coalesce,
255			"QU", NULL);
256	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "rx-frames",
257			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
258			LIO_RX_MAX_COALESCED_FRAMES, lio_get_set_intr_coalesce,
259			"QU", NULL);
260	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "rx-usecs",
261			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
262			LIO_RX_COALESCE_USECS, lio_get_set_intr_coalesce,
263			"QU", NULL);
264	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "adaptive-tx",
265			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
266			LIO_USE_ADAPTIVE_TX_COALESCE, lio_get_set_intr_coalesce,
267			"QU", NULL);
268	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "adaptive-rx",
269			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
270			LIO_USE_ADAPTIVE_RX_COALESCE, lio_get_set_intr_coalesce,
271			"QU", NULL);
272
273	/* Root Node of all the Stats */
274	root_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD,
275				    NULL, "Root Node of all the Stats");
276	root_list = SYSCTL_CHILDREN(root_node);
277
278	/* Firmware Tx Stats */
279	stat_node = SYSCTL_ADD_NODE(ctx, root_list, OID_AUTO, "fwtx",CTLFLAG_RD,
280				    NULL, "Firmware Tx Statistics");
281	stat_list = SYSCTL_CHILDREN(stat_node);
282
283	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_total_sent", CTLFLAG_RD,
284			 &oct_dev->link_stats.fromhost.fw_total_sent,
285			 "Firmware Total Packets Sent");
286	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_total_fwd", CTLFLAG_RD,
287			 &oct_dev->link_stats.fromhost.fw_total_fwd,
288			 "Firmware Total Packets Forwarded");
289	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_total_fwd_bytes",
290			 CTLFLAG_RD,
291			 &oct_dev->link_stats.fromhost.fw_total_fwd_bytes,
292			 "Firmware Total Bytes Forwarded");
293	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_err_pko", CTLFLAG_RD,
294			 &oct_dev->link_stats.fromhost.fw_err_pko,
295			 "Firmware Tx PKO Errors");
296	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_err_pki", CTLFLAG_RD,
297			 &oct_dev->link_stats.fromhost.fw_err_pki,
298			 "Firmware Tx PKI Errors");
299	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_err_link", CTLFLAG_RD,
300			 &oct_dev->link_stats.fromhost.fw_err_link,
301			 "Firmware Tx Link Errors");
302	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_err_drop", CTLFLAG_RD,
303			 &oct_dev->link_stats.fromhost.fw_err_drop,
304			 "Firmware Tx Packets Dropped");
305	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "fw_tso", CTLFLAG_RD,
306			 &oct_dev->link_stats.fromhost.fw_tso,
307			 "Firmware Tx TSO");
308	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_tso_packets", CTLFLAG_RD,
309			 &oct_dev->link_stats.fromhost.fw_tso_fwd,
310			 "Firmware Tx TSO Packets");
311	//SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_tso_err", CTLFLAG_RD,
312			   //&oct_dev->link_stats.fromhost.fw_tso_err,
313			   //"Firmware Tx TSO Errors");
314	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_vxlan", CTLFLAG_RD,
315			 &oct_dev->link_stats.fromhost.fw_tx_vxlan,
316			 "Firmware Tx VXLAN");
317
318	/* MAC Tx Stats */
319	stat_node = SYSCTL_ADD_NODE(ctx, root_list, OID_AUTO, "mactx",
320				    CTLFLAG_RD, NULL, "MAC Tx Statistics");
321	stat_list = SYSCTL_CHILDREN(stat_node);
322
323	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_total_pkts",
324			 CTLFLAG_RD,
325			 &oct_dev->link_stats.fromhost.total_pkts_sent,
326			 "Link-Level Total Packets Sent");
327	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_total_bytes",
328			 CTLFLAG_RD,
329			 &oct_dev->link_stats.fromhost.total_bytes_sent,
330			 "Link-Level Total Bytes Sent");
331	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_mcast_pkts",
332			 CTLFLAG_RD,
333			 &oct_dev->link_stats.fromhost.mcast_pkts_sent,
334			 "Link-Level Multicast Packets Sent");
335	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_bcast_pkts",
336			 CTLFLAG_RD,
337			 &oct_dev->link_stats.fromhost.bcast_pkts_sent,
338			 "Link-Level Broadcast Packets Sent");
339	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_ctl_packets",
340			 CTLFLAG_RD,
341			 &oct_dev->link_stats.fromhost.ctl_sent,
342			 "Link-Level Control Packets Sent");
343	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_total_collisions",
344			 CTLFLAG_RD,
345			 &oct_dev->link_stats.fromhost.total_collisions,
346			 "Link-Level Tx Total Collisions");
347	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_one_collision",
348			 CTLFLAG_RD,
349			 &oct_dev->link_stats.fromhost.one_collision_sent,
350			 "Link-Level Tx One Collision Sent");
351	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_multi_collison",
352			 CTLFLAG_RD,
353			 &oct_dev->link_stats.fromhost.multi_collision_sent,
354			 "Link-Level Tx Multi-Collision Sent");
355	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_max_collision_fail",
356			 CTLFLAG_RD,
357			 &oct_dev->link_stats.fromhost.max_collision_fail,
358			 "Link-Level Tx Max Collision Failed");
359	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_max_deferal_fail",
360			 CTLFLAG_RD,
361			 &oct_dev->link_stats.fromhost.max_deferral_fail,
362			 "Link-Level Tx Max Deferral Failed");
363	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_fifo_err",
364			 CTLFLAG_RD,
365			 &oct_dev->link_stats.fromhost.fifo_err,
366			 "Link-Level Tx FIFO Errors");
367	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_runts", CTLFLAG_RD,
368			 &oct_dev->link_stats.fromhost.runts,
369			 "Link-Level Tx Runts");
370
371	/* Firmware Rx Stats */
372	stat_node = SYSCTL_ADD_NODE(ctx, root_list, OID_AUTO, "fwrx",
373				    CTLFLAG_RD, NULL, "Firmware Rx Statistics");
374	stat_list = SYSCTL_CHILDREN(stat_node);
375
376	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_total_rcvd", CTLFLAG_RD,
377			 &oct_dev->link_stats.fromwire.fw_total_rcvd,
378			 "Firmware Total Packets Received");
379	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_total_fwd", CTLFLAG_RD,
380			 &oct_dev->link_stats.fromwire.fw_total_fwd,
381			 "Firmware Total Packets Forwarded");
382	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_jabber_err", CTLFLAG_RD,
383			 &oct_dev->link_stats.fromwire.jabber_err,
384			 "Firmware Rx Jabber Errors");
385	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_l2_err", CTLFLAG_RD,
386			 &oct_dev->link_stats.fromwire.l2_err,
387			 "Firmware Rx L2 Errors");
388	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frame_err", CTLFLAG_RD,
389			 &oct_dev->link_stats.fromwire.frame_err,
390			 "Firmware Rx Frame Errors");
391	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_err_pko", CTLFLAG_RD,
392			 &oct_dev->link_stats.fromwire.fw_err_pko,
393			 "Firmware Rx PKO Errors");
394	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_err_link", CTLFLAG_RD,
395			 &oct_dev->link_stats.fromwire.fw_err_link,
396			 "Firmware Rx Link Errors");
397	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_err_drop", CTLFLAG_RD,
398			 &oct_dev->link_stats.fromwire.fw_err_drop,
399			 "Firmware Rx Dropped");
400	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_vxlan", CTLFLAG_RD,
401			 &oct_dev->link_stats.fromwire.fw_rx_vxlan,
402			 "Firmware Rx VXLAN");
403	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_vxlan_err", CTLFLAG_RD,
404			 &oct_dev->link_stats.fromwire.fw_rx_vxlan_err,
405			 "Firmware Rx VXLAN Errors");
406	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_lro_pkts", CTLFLAG_RD,
407			 &oct_dev->link_stats.fromwire.fw_lro_pkts,
408			 "Firmware Rx LRO Packets");
409	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_lro_bytes", CTLFLAG_RD,
410			 &oct_dev->link_stats.fromwire.fw_lro_octs,
411			 "Firmware Rx LRO Bytes");
412	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_total_lro", CTLFLAG_RD,
413			 &oct_dev->link_stats.fromwire.fw_total_lro,
414			 "Firmware Rx Total LRO");
415	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_lro_aborts", CTLFLAG_RD,
416			 &oct_dev->link_stats.fromwire.fw_lro_aborts,
417			 "Firmware Rx LRO Aborts");
418	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_lro_aborts_port",
419			 CTLFLAG_RD,
420			 &oct_dev->link_stats.fromwire.fw_lro_aborts_port,
421			 "Firmware Rx LRO Aborts Port");
422	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_lro_aborts_seq",
423			 CTLFLAG_RD,
424			 &oct_dev->link_stats.fromwire.fw_lro_aborts_seq,
425			 "Firmware Rx LRO Aborts Sequence");
426	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_lro_aborts_tsval",
427			 CTLFLAG_RD,
428			 &oct_dev->link_stats.fromwire.fw_lro_aborts_tsval,
429			 "Firmware Rx LRO Aborts tsval");
430	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_lro_aborts_timer",
431			 CTLFLAG_RD,
432			 &oct_dev->link_stats.fromwire.fw_lro_aborts_timer,
433			 "Firmware Rx LRO Aborts Timer");
434	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_fwd_rate",
435			 CTLFLAG_RD,
436			 &oct_dev->link_stats.fromwire.fwd_rate,
437			 "Firmware Rx Packets Forward Rate");
438	/* MAC Rx Stats */
439	stat_node = SYSCTL_ADD_NODE(ctx, root_list, OID_AUTO, "macrx",
440				    CTLFLAG_RD, NULL, "MAC Rx Statistics");
441	stat_list = SYSCTL_CHILDREN(stat_node);
442
443	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_rx_total_rcvd",
444			 CTLFLAG_RD,
445			 &oct_dev->link_stats.fromwire.total_rcvd,
446			 "Link-Level Total Packets Received");
447	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_rx_bytes",
448			 CTLFLAG_RD,
449			 &oct_dev->link_stats.fromwire.bytes_rcvd,
450			 "Link-Level Total Bytes Received");
451	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_rx_total_bcst",
452			 CTLFLAG_RD,
453			 &oct_dev->link_stats.fromwire.total_bcst,
454			 "Link-Level Total Broadcast");
455	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_rx_total_mcst",
456			 CTLFLAG_RD,
457			 &oct_dev->link_stats.fromwire.total_mcst,
458			 "Link-Level Total Multicast");
459	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_rx_runts",
460			 CTLFLAG_RD,
461			 &oct_dev->link_stats.fromwire.runts,
462			 "Link-Level Rx Runts");
463	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_rx_ctl_packets",
464			 CTLFLAG_RD,
465			 &oct_dev->link_stats.fromwire.ctl_rcvd,
466			 "Link-Level Rx Control Packets");
467	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_rx_fifo_err",
468			 CTLFLAG_RD,
469			 &oct_dev->link_stats.fromwire.fifo_err,
470			 "Link-Level Rx FIFO Errors");
471	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_rx_dma_drop",
472			 CTLFLAG_RD,
473			 &oct_dev->link_stats.fromwire.dmac_drop,
474			 "Link-Level Rx DMA Dropped");
475	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_rx_fcs_err",
476			 CTLFLAG_RD,
477			 &oct_dev->link_stats.fromwire.fcs_err,
478			 "Link-Level Rx FCS Errors");
479
480	/* TX */
481	for (int i = 0; i < oct_dev->num_iqs; i++) {
482		if (!(oct_dev->io_qmask.iq & BIT_ULL(i)))
483			continue;
484
485		snprintf(namebuf, QUEUE_NAME_LEN, "tx-%d", i);
486		queue_node = SYSCTL_ADD_NODE(ctx, root_list, OID_AUTO, namebuf,
487					     CTLFLAG_RD, NULL, "Input Queue Name");
488		queue_list = SYSCTL_CHILDREN(queue_node);
489
490		/* packets to network port */
491		/* # of packets tx to network */
492		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "packets",
493				 CTLFLAG_RD,
494				 &oct_dev->instr_queue[i]->stats.tx_done,
495				 "Number of Packets Tx to Network");
496		/* # of bytes tx to network */
497		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "bytes",
498				 CTLFLAG_RD,
499				 &oct_dev->instr_queue[i]->stats.tx_tot_bytes,
500				 "Number of Bytes Tx to Network");
501		/* # of packets dropped */
502		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "dropped",
503				 CTLFLAG_RD,
504				 &oct_dev->instr_queue[i]->stats.tx_dropped,
505				 "Number of Tx Packets Dropped");
506		/* # of tx fails due to queue full */
507		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "iq_busy",
508				 CTLFLAG_RD,
509				 &oct_dev->instr_queue[i]->stats.tx_iq_busy,
510				 "Number of Tx Fails Due to Queue Full");
511		/* scatter gather entries sent */
512		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "sgentry_sent",
513				 CTLFLAG_RD,
514				 &oct_dev->instr_queue[i]->stats.sgentry_sent,
515				 "Scatter Gather Entries Sent");
516
517		/* instruction to firmware: data and control */
518		/* # of instructions to the queue */
519		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "fw_instr_posted",
520				 CTLFLAG_RD,
521				 &oct_dev->instr_queue[i]->stats.instr_posted,
522				 "Number of Instructions to The Queue");
523		/* # of instructions processed */
524		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO,
525				 "fw_instr_processed", CTLFLAG_RD,
526			      &oct_dev->instr_queue[i]->stats.instr_processed,
527				 "Number of Instructions Processed");
528		/* # of instructions could not be processed */
529		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "fw_instr_dropped",
530				 CTLFLAG_RD,
531				 &oct_dev->instr_queue[i]->stats.instr_dropped,
532				 "Number of Instructions Dropped");
533		/* bytes sent through the queue */
534		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "fw_bytes_sent",
535				 CTLFLAG_RD,
536				 &oct_dev->instr_queue[i]->stats.bytes_sent,
537				 "Bytes Sent Through The Queue");
538		/* tso request */
539		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tso",
540				 CTLFLAG_RD,
541				 &oct_dev->instr_queue[i]->stats.tx_gso,
542				 "TSO Request");
543		/* vxlan request */
544		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "vxlan",
545				 CTLFLAG_RD,
546				 &oct_dev->instr_queue[i]->stats.tx_vxlan,
547				 "VXLAN Request");
548		/* txq restart */
549		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "txq_restart",
550				 CTLFLAG_RD,
551				 &oct_dev->instr_queue[i]->stats.tx_restart,
552				 "TxQ Restart");
553		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_dmamap_fail",
554				 CTLFLAG_RD,
555			       &oct_dev->instr_queue[i]->stats.tx_dmamap_fail,
556				 "TxQ DMA Map Failed");
557		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO,
558				 "mbuf_defrag_failed", CTLFLAG_RD,
559			   &oct_dev->instr_queue[i]->stats.mbuf_defrag_failed,
560				 "TxQ defrag Failed");
561	}
562
563	/* RX */
564	for (int i = 0; i < oct_dev->num_oqs; i++) {
565		if (!(oct_dev->io_qmask.oq & BIT_ULL(i)))
566			continue;
567
568		snprintf(namebuf, QUEUE_NAME_LEN, "rx-%d", i);
569		queue_node = SYSCTL_ADD_NODE(ctx, root_list, OID_AUTO, namebuf,
570					     CTLFLAG_RD, NULL,
571					     "Output Queue Name");
572		queue_list = SYSCTL_CHILDREN(queue_node);
573
574		/* packets send to TCP/IP network stack */
575		/* # of packets to network stack */
576		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "packets",
577				 CTLFLAG_RD,
578				 &oct_dev->droq[i]->stats.rx_pkts_received,
579				 "Number of Packets to Network Stack");
580		/* # of bytes to network stack */
581		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "bytes",
582				 CTLFLAG_RD,
583				 &oct_dev->droq[i]->stats.rx_bytes_received,
584				 "Number of Bytes to Network Stack");
585		/* # of packets dropped */
586		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "dropped_nomem",
587				 CTLFLAG_RD,
588				 &oct_dev->droq[i]->stats.dropped_nomem,
589				 "Packets Dropped Due to No Memory");
590		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "dropped_toomany",
591				 CTLFLAG_RD,
592				 &oct_dev->droq[i]->stats.dropped_toomany,
593				 "Packets dropped, Too Many Pkts to Process");
594		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "fw_dropped",
595				 CTLFLAG_RD,
596				 &oct_dev->droq[i]->stats.rx_dropped,
597				"Packets Dropped due to Receive path failures");
598		/* control and data path */
599		/* # packets  sent to stack from this queue. */
600		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "fw_pkts_received",
601				 CTLFLAG_RD,
602				 &oct_dev->droq[i]->stats.pkts_received,
603				 "Number of Packets Received");
604		/* # Bytes sent to stack from this queue. */
605		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "fw_bytes_received",
606				 CTLFLAG_RD,
607				 &oct_dev->droq[i]->stats.bytes_received,
608				 "Number of Bytes Received");
609		/* Packets dropped due to no dispatch function. */
610		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO,
611				 "fw_dropped_nodispatch", CTLFLAG_RD,
612				 &oct_dev->droq[i]->stats.dropped_nodispatch,
613				 "Packets Dropped, No Dispatch Function");
614		/* Rx VXLAN */
615		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "vxlan",
616				 CTLFLAG_RD,
617				 &oct_dev->droq[i]->stats.rx_vxlan,
618				 "Rx VXLAN");
619		/* # failures of lio_recv_buffer_alloc */
620		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO,
621				 "buffer_alloc_failure", CTLFLAG_RD,
622				 &oct_dev->droq[i]->stats.rx_alloc_failure,
623			       "Number of Failures of lio_recv_buffer_alloc");
624	}
625}
626
627static int
628lio_get_eeprom(SYSCTL_HANDLER_ARGS)
629{
630	struct lio		*lio = (struct lio *)arg1;
631	struct octeon_device	*oct_dev = lio->oct_dev;
632	struct lio_board_info	*board_info;
633	char	buf[512];
634
635	board_info = (struct lio_board_info *)(&oct_dev->boardinfo);
636	if (oct_dev->uboot_len == 0)
637		sprintf(buf, "boardname:%s serialnum:%s maj:%lld min:%lld",
638			board_info->name, board_info->serial_number,
639			LIO_CAST64(board_info->major),
640		       	LIO_CAST64(board_info->minor));
641	else {
642		sprintf(buf, "boardname:%s serialnum:%s maj:%lld min:%lld\n%s",
643			board_info->name, board_info->serial_number,
644			LIO_CAST64(board_info->major),
645		        LIO_CAST64(board_info->minor),
646			&oct_dev->uboot_version[oct_dev->uboot_sidx]);
647	}
648
649	return (sysctl_handle_string(oidp, buf, strlen(buf), req));
650}
651
652/*
653 * Get and set pause parameters or flow control using sysctl:
654 * 0 - off
655 * 1 - rx pause
656 * 2 - tx pause
657 * 3 - full
658 */
659static int
660lio_get_set_pauseparam(SYSCTL_HANDLER_ARGS)
661{
662	/* Notes: Not supporting any auto negotiation in these drivers. */
663	struct lio_ctrl_pkt	nctrl;
664	struct lio		*lio = (struct lio *)arg1;
665	struct octeon_device	*oct = lio->oct_dev;
666	struct octeon_link_info	*linfo = &lio->linfo;
667
668	int	err, new_pause = LIO_OFF_PAUSE, old_pause = LIO_OFF_PAUSE;
669	int	ret = 0;
670
671	if (oct->chip_id != LIO_CN23XX_PF_VID)
672		return (EINVAL);
673
674	if (oct->rx_pause)
675		old_pause |= LIO_RX_PAUSE;
676
677	if (oct->tx_pause)
678		old_pause |= LIO_TX_PAUSE;
679
680	new_pause = old_pause;
681	err = sysctl_handle_int(oidp, &new_pause, 0, req);
682
683	if ((err) || (req->newptr == NULL))
684		return (err);
685
686	if (old_pause == new_pause)
687		return (0);
688
689	if (linfo->link.s.duplex == 0) {
690		/* no flow control for half duplex */
691		if (new_pause)
692			return (EINVAL);
693	}
694
695	bzero(&nctrl, sizeof(struct lio_ctrl_pkt));
696
697	nctrl.ncmd.cmd64 = 0;
698	nctrl.ncmd.s.cmd = LIO_CMD_SET_FLOW_CTL;
699	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
700	nctrl.wait_time = 100;
701	nctrl.lio = lio;
702	nctrl.cb_fn = lio_ctrl_cmd_completion;
703
704	if (new_pause & LIO_RX_PAUSE) {
705		/* enable rx pause */
706		nctrl.ncmd.s.param1 = 1;
707	} else {
708		/* disable rx pause */
709		nctrl.ncmd.s.param1 = 0;
710	}
711
712	if (new_pause & LIO_TX_PAUSE) {
713		/* enable tx pause */
714		nctrl.ncmd.s.param2 = 1;
715	} else {
716		/* disable tx pause */
717		nctrl.ncmd.s.param2 = 0;
718	}
719
720	ret = lio_send_ctrl_pkt(lio->oct_dev, &nctrl);
721	if (ret < 0) {
722		lio_dev_err(oct, "Failed to set pause parameter\n");
723		return (EINVAL);
724	}
725
726	oct->rx_pause = new_pause & LIO_RX_PAUSE;
727	oct->tx_pause = new_pause & LIO_TX_PAUSE;
728
729	return (0);
730}
731
732/*  Return register dump user app.  */
733static int
734lio_get_regs(SYSCTL_HANDLER_ARGS)
735{
736	struct lio		*lio = (struct lio *)arg1;
737	struct octeon_device	*oct = lio->oct_dev;
738	struct ifnet		*ifp = lio->ifp;
739	char	*regbuf;
740	int	error = EINVAL, len = 0;
741
742	if (!(if_getflags(ifp) & IFF_DEBUG)) {
743		char debug_info[30] = "Debugging is disabled";
744
745		return (sysctl_handle_string(oidp, debug_info,
746					     strlen(debug_info), req));
747	}
748	regbuf = malloc(sizeof(char) * LIO_REGDUMP_LEN_XXXX, M_DEVBUF,
749			M_WAITOK | M_ZERO);
750
751	if (regbuf == NULL)
752		return (error);
753
754	switch (oct->chip_id) {
755	case LIO_CN23XX_PF_VID:
756		len += lio_cn23xx_pf_read_csr_reg(regbuf, oct);
757		break;
758	default:
759		len += sprintf(regbuf, "%s Unknown chipid: %d\n",
760			       __func__, oct->chip_id);
761	}
762
763	error = sysctl_handle_string(oidp, regbuf, len, req);
764	free(regbuf, M_DEVBUF);
765
766	return (error);
767}
768
769static int
770lio_cn23xx_pf_read_csr_reg(char *s, struct octeon_device *oct)
771{
772	uint32_t	reg;
773	int	i, len = 0;
774	uint8_t	pf_num = oct->pf_num;
775
776	/* PCI  Window Registers */
777
778	len += sprintf(s + len, "\t Octeon CSR Registers\n\n");
779
780	/* 0x29030 or 0x29040 */
781	reg = LIO_CN23XX_SLI_PKT_MAC_RINFO64(oct->pcie_port, oct->pf_num);
782	len += sprintf(s + len, "[%08x] (SLI_PKT_MAC%d_PF%d_RINFO): %016llx\n",
783		       reg, oct->pcie_port, oct->pf_num,
784		       LIO_CAST64(lio_read_csr64(oct, reg)));
785
786	/* 0x27080 or 0x27090 */
787	reg = LIO_CN23XX_SLI_MAC_PF_INT_ENB64(oct->pcie_port, oct->pf_num);
788	len += sprintf(s + len, "[%08x] (SLI_MAC%d_PF%d_INT_ENB): %016llx\n",
789		       reg, oct->pcie_port, oct->pf_num,
790		       LIO_CAST64(lio_read_csr64(oct, reg)));
791
792	/* 0x27000 or 0x27010 */
793	reg = LIO_CN23XX_SLI_MAC_PF_INT_SUM64(oct->pcie_port, oct->pf_num);
794	len += sprintf(s + len, "[%08x] (SLI_MAC%d_PF%d_INT_SUM): %016llx\n",
795		       reg, oct->pcie_port, oct->pf_num,
796		       LIO_CAST64(lio_read_csr64(oct, reg)));
797
798	/* 0x29120 */
799	reg = 0x29120;
800	len += sprintf(s + len, "[%08x] (SLI_PKT_MEM_CTL): %016llx\n", reg,
801		       LIO_CAST64(lio_read_csr64(oct, reg)));
802
803	/* 0x27300 */
804	reg = 0x27300 + oct->pcie_port * LIO_CN23XX_MAC_INT_OFFSET +
805	    (oct->pf_num) * LIO_CN23XX_PF_INT_OFFSET;
806	len += sprintf(s + len, "[%08x] (SLI_MAC%d_PF%d_PKT_VF_INT): %016llx\n",
807		       reg, oct->pcie_port, oct->pf_num,
808		       LIO_CAST64(lio_read_csr64(oct, reg)));
809
810	/* 0x27200 */
811	reg = 0x27200 + oct->pcie_port * LIO_CN23XX_MAC_INT_OFFSET +
812	    (oct->pf_num) * LIO_CN23XX_PF_INT_OFFSET;
813	len += sprintf(s + len, "[%08x] (SLI_MAC%d_PF%d_PP_VF_INT): %016llx\n",
814		       reg, oct->pcie_port, oct->pf_num,
815		       LIO_CAST64(lio_read_csr64(oct, reg)));
816
817	/* 29130 */
818	reg = LIO_CN23XX_SLI_PKT_CNT_INT;
819	len += sprintf(s + len, "[%08x] (SLI_PKT_CNT_INT): %016llx\n", reg,
820		       LIO_CAST64(lio_read_csr64(oct, reg)));
821
822	/* 0x29140 */
823	reg = LIO_CN23XX_SLI_PKT_TIME_INT;
824	len += sprintf(s + len, "[%08x] (SLI_PKT_TIME_INT): %016llx\n", reg,
825		       LIO_CAST64(lio_read_csr64(oct, reg)));
826
827	/* 0x29160 */
828	reg = 0x29160;
829	len += sprintf(s + len, "[%08x] (SLI_PKT_INT): %016llx\n", reg,
830		       LIO_CAST64(lio_read_csr64(oct, reg)));
831
832	/* 0x29180 */
833	reg = LIO_CN23XX_SLI_OQ_WMARK;
834	len += sprintf(s + len, "[%08x] (SLI_PKT_OUTPUT_WMARK): %016llx\n",
835		       reg, LIO_CAST64(lio_read_csr64(oct, reg)));
836
837	/* 0x291E0 */
838	reg = LIO_CN23XX_SLI_PKT_IOQ_RING_RST;
839	len += sprintf(s + len, "[%08x] (SLI_PKT_RING_RST): %016llx\n", reg,
840		       LIO_CAST64(lio_read_csr64(oct, reg)));
841
842	/* 0x29210 */
843	reg = LIO_CN23XX_SLI_GBL_CONTROL;
844	len += sprintf(s + len, "[%08x] (SLI_PKT_GBL_CONTROL): %016llx\n", reg,
845		       LIO_CAST64(lio_read_csr64(oct, reg)));
846
847	/* 0x29220 */
848	reg = 0x29220;
849	len += sprintf(s + len, "[%08x] (SLI_PKT_BIST_STATUS): %016llx\n",
850		       reg, LIO_CAST64(lio_read_csr64(oct, reg)));
851
852	/* PF only */
853	if (pf_num == 0) {
854		/* 0x29260 */
855		reg = LIO_CN23XX_SLI_OUT_BP_EN_W1S;
856		len += sprintf(s + len, "[%08x] (SLI_PKT_OUT_BP_EN_W1S):  %016llx\n",
857			       reg, LIO_CAST64(lio_read_csr64(oct, reg)));
858	} else if (pf_num == 1) {
859		/* 0x29270 */
860		reg = LIO_CN23XX_SLI_OUT_BP_EN2_W1S;
861		len += sprintf(s + len, "[%08x] (SLI_PKT_OUT_BP_EN2_W1S): %016llx\n",
862			       reg, LIO_CAST64(lio_read_csr64(oct, reg)));
863	}
864
865	for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
866		reg = LIO_CN23XX_SLI_OQ_BUFF_INFO_SIZE(i);
867		len += sprintf(s + len, "[%08x] (SLI_PKT%d_OUT_SIZE): %016llx\n",
868			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
869	}
870
871	/* 0x10040 */
872	for (i = 0; i < LIO_CN23XX_PF_MAX_INPUT_QUEUES; i++) {
873		reg = LIO_CN23XX_SLI_IQ_INSTR_COUNT64(i);
874		len += sprintf(s + len, "[%08x] (SLI_PKT_IN_DONE%d_CNTS): %016llx\n",
875			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
876	}
877
878	/* 0x10080 */
879	for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
880		reg = LIO_CN23XX_SLI_OQ_PKTS_CREDIT(i);
881		len += sprintf(s + len, "[%08x] (SLI_PKT%d_SLIST_BAOFF_DBELL): %016llx\n",
882			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
883	}
884
885	/* 0x10090 */
886	for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
887		reg = LIO_CN23XX_SLI_OQ_SIZE(i);
888		len += sprintf(s + len, "[%08x] (SLI_PKT%d_SLIST_FIFO_RSIZE): %016llx\n",
889			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
890	}
891
892	/* 0x10050 */
893	for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
894		reg = LIO_CN23XX_SLI_OQ_PKT_CONTROL(i);
895		len += sprintf(s + len, "[%08x] (SLI_PKT%d__OUTPUT_CONTROL): %016llx\n",
896			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
897	}
898
899	/* 0x10070 */
900	for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
901		reg = LIO_CN23XX_SLI_OQ_BASE_ADDR64(i);
902		len += sprintf(s + len, "[%08x] (SLI_PKT%d_SLIST_BADDR): %016llx\n",
903			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
904	}
905
906	/* 0x100a0 */
907	for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
908		reg = LIO_CN23XX_SLI_OQ_PKT_INT_LEVELS(i);
909		len += sprintf(s + len, "[%08x] (SLI_PKT%d_INT_LEVELS): %016llx\n",
910			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
911	}
912
913	/* 0x100b0 */
914	for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
915		reg = LIO_CN23XX_SLI_OQ_PKTS_SENT(i);
916		len += sprintf(s + len, "[%08x] (SLI_PKT%d_CNTS): %016llx\n",
917			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
918	}
919
920	/* 0x100c0 */
921	for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
922		reg = 0x100c0 + i * LIO_CN23XX_OQ_OFFSET;
923		len += sprintf(s + len, "[%08x] (SLI_PKT%d_ERROR_INFO): %016llx\n",
924			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
925	}
926
927	/* 0x10000 */
928	for (i = 0; i < LIO_CN23XX_PF_MAX_INPUT_QUEUES; i++) {
929		reg = LIO_CN23XX_SLI_IQ_PKT_CONTROL64(i);
930		len += sprintf(s + len, "[%08x] (SLI_PKT%d_INPUT_CONTROL): %016llx\n",
931			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
932	}
933
934	/* 0x10010 */
935	for (i = 0; i < LIO_CN23XX_PF_MAX_INPUT_QUEUES; i++) {
936		reg = LIO_CN23XX_SLI_IQ_BASE_ADDR64(i);
937		len += sprintf(s + len, "[%08x] (SLI_PKT%d_INSTR_BADDR): %016llx\n",
938			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
939	}
940
941	/* 0x10020 */
942	for (i = 0; i < LIO_CN23XX_PF_MAX_INPUT_QUEUES; i++) {
943		reg = LIO_CN23XX_SLI_IQ_DOORBELL(i);
944		len += sprintf(s + len, "[%08x] (SLI_PKT%d_INSTR_BAOFF_DBELL): %016llx\n",
945			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
946	}
947
948	/* 0x10030 */
949	for (i = 0; i < LIO_CN23XX_PF_MAX_INPUT_QUEUES; i++) {
950		reg = LIO_CN23XX_SLI_IQ_SIZE(i);
951		len += sprintf(s + len, "[%08x] (SLI_PKT%d_INSTR_FIFO_RSIZE): %016llx\n",
952			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
953	}
954
955	/* 0x10040 */
956	for (i = 0; i < LIO_CN23XX_PF_MAX_INPUT_QUEUES; i++)
957		reg = LIO_CN23XX_SLI_IQ_INSTR_COUNT64(i);
958	len += sprintf(s + len, "[%08x] (SLI_PKT_IN_DONE%d_CNTS): %016llx\n",
959		       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
960
961	return (len);
962}
963
964static int
965lio_get_ringparam(SYSCTL_HANDLER_ARGS)
966{
967	struct lio		*lio = (struct lio *)arg1;
968	struct octeon_device	*oct = lio->oct_dev;
969	uint32_t		rx_max_pending = 0, tx_max_pending = 0;
970	int	err;
971
972	if (LIO_CN23XX_PF(oct)) {
973		tx_max_pending = LIO_CN23XX_MAX_IQ_DESCRIPTORS;
974		rx_max_pending = LIO_CN23XX_MAX_OQ_DESCRIPTORS;
975	}
976
977	switch (arg2) {
978	case LIO_SET_RING_RX:
979		err = sysctl_handle_int(oidp, &rx_max_pending, 0, req);
980		break;
981	case LIO_SET_RING_TX:
982		err = sysctl_handle_int(oidp, &tx_max_pending, 0, req);
983		break;
984	}
985
986	return (err);
987}
988
989static int
990lio_reset_queues(struct ifnet *ifp, uint32_t num_qs)
991{
992	struct lio		*lio = if_getsoftc(ifp);
993	struct octeon_device	*oct = lio->oct_dev;
994	int	i, update = 0;
995
996	if (lio_wait_for_pending_requests(oct))
997		lio_dev_err(oct, "There were pending requests\n");
998
999	if (lio_wait_for_instr_fetch(oct))
1000		lio_dev_err(oct, "IQ had pending instructions\n");
1001
1002
1003	/*
1004	 * Disable the input and output queues now. No more packets will
1005	 * arrive from Octeon.
1006	 */
1007	oct->fn_list.disable_io_queues(oct);
1008
1009	if (num_qs != oct->num_iqs)
1010		update = 1;
1011
1012	for (i = 0; i < LIO_MAX_OUTPUT_QUEUES(oct); i++) {
1013		if (!(oct->io_qmask.oq & BIT_ULL(i)))
1014			continue;
1015
1016		lio_delete_droq(oct, i);
1017	}
1018
1019	for (i = 0; i < LIO_MAX_INSTR_QUEUES(oct); i++) {
1020		if (!(oct->io_qmask.iq & BIT_ULL(i)))
1021			continue;
1022
1023		lio_delete_instr_queue(oct, i);
1024	}
1025
1026	if (oct->fn_list.setup_device_regs(oct)) {
1027		lio_dev_err(oct, "Failed to configure device registers\n");
1028		return (-1);
1029	}
1030
1031	if (lio_setup_io_queues(oct, 0, num_qs, num_qs)) {
1032		lio_dev_err(oct, "IO queues initialization failed\n");
1033		return (-1);
1034	}
1035
1036	if (update && lio_send_queue_count_update(ifp, num_qs))
1037		return (-1);
1038
1039	return (0);
1040}
1041
1042static int
1043lio_set_ringparam(SYSCTL_HANDLER_ARGS)
1044{
1045	struct lio		*lio = (struct lio *)arg1;
1046	struct octeon_device	*oct = lio->oct_dev;
1047	uint32_t		rx_count, rx_count_old, tx_count, tx_count_old;
1048	int	err, stopped = 0;
1049
1050	if (!LIO_CN23XX_PF(oct))
1051		return (EINVAL);
1052
1053	switch (arg2) {
1054	case LIO_SET_RING_RX:
1055		rx_count = rx_count_old = oct->droq[0]->max_count;
1056		err = sysctl_handle_int(oidp, &rx_count, 0, req);
1057
1058		if ((err) || (req->newptr == NULL))
1059			return (err);
1060
1061		rx_count = min(max(rx_count, LIO_CN23XX_MIN_OQ_DESCRIPTORS),
1062			       LIO_CN23XX_MAX_OQ_DESCRIPTORS);
1063
1064		if (rx_count == rx_count_old)
1065			return (0);
1066
1067		lio_ifstate_set(lio, LIO_IFSTATE_RESETTING);
1068
1069		if (if_getdrvflags(lio->ifp) & IFF_DRV_RUNNING) {
1070			lio_stop(lio->ifp);
1071			stopped = 1;
1072		}
1073
1074		/* Change RX DESCS  count */
1075		LIO_SET_NUM_RX_DESCS_NIC_IF(lio_get_conf(oct),
1076					    lio->ifidx, rx_count);
1077		break;
1078	case LIO_SET_RING_TX:
1079		tx_count = tx_count_old = oct->instr_queue[0]->max_count;
1080		err = sysctl_handle_int(oidp, &tx_count, 0, req);
1081
1082		if ((err) || (req->newptr == NULL))
1083			return (err);
1084
1085		tx_count = min(max(tx_count, LIO_CN23XX_MIN_IQ_DESCRIPTORS),
1086			       LIO_CN23XX_MAX_IQ_DESCRIPTORS);
1087
1088		if (tx_count == tx_count_old)
1089			return (0);
1090
1091		lio_ifstate_set(lio, LIO_IFSTATE_RESETTING);
1092
1093		if (if_getdrvflags(lio->ifp) & IFF_DRV_RUNNING) {
1094			lio_stop(lio->ifp);
1095			stopped = 1;
1096		}
1097
1098		/* Change TX DESCS  count */
1099		LIO_SET_NUM_TX_DESCS_NIC_IF(lio_get_conf(oct),
1100					    lio->ifidx, tx_count);
1101		break;
1102	}
1103
1104	if (lio_reset_queues(lio->ifp, lio->linfo.num_txpciq))
1105		goto err_lio_reset_queues;
1106
1107	lio_irq_reallocate_irqs(oct, lio->linfo.num_txpciq);
1108	if (stopped)
1109		lio_open(lio);
1110
1111	lio_ifstate_reset(lio, LIO_IFSTATE_RESETTING);
1112
1113	return (0);
1114
1115err_lio_reset_queues:
1116	if (arg2 == LIO_SET_RING_RX && rx_count != rx_count_old)
1117		LIO_SET_NUM_RX_DESCS_NIC_IF(lio_get_conf(oct), lio->ifidx,
1118					    rx_count_old);
1119
1120	if (arg2 == LIO_SET_RING_TX && tx_count != tx_count_old)
1121		LIO_SET_NUM_TX_DESCS_NIC_IF(lio_get_conf(oct), lio->ifidx,
1122					    tx_count_old);
1123
1124	return (EINVAL);
1125}
1126
1127static int
1128lio_get_channels(SYSCTL_HANDLER_ARGS)
1129{
1130	struct lio		*lio = (struct lio *)arg1;
1131	struct octeon_device	*oct = lio->oct_dev;
1132	uint32_t	max_combined = 0;
1133
1134		if (LIO_CN23XX_PF(oct))
1135			max_combined = lio->linfo.num_txpciq;
1136	return (sysctl_handle_int(oidp, &max_combined, 0, req));
1137}
1138
1139static int
1140lio_irq_reallocate_irqs(struct octeon_device *oct, uint32_t num_ioqs)
1141{
1142	int	i, num_msix_irqs = 0;
1143
1144	if (!oct->msix_on)
1145		return (0);
1146
1147	/*
1148	 * Disable the input and output queues now. No more packets will
1149	 * arrive from Octeon.
1150	 */
1151	oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR);
1152
1153	if (oct->msix_on) {
1154		if (LIO_CN23XX_PF(oct))
1155			num_msix_irqs = oct->num_msix_irqs - 1;
1156
1157		for (i = 0; i < num_msix_irqs; i++) {
1158			if (oct->ioq_vector[i].tag != NULL) {
1159				bus_teardown_intr(oct->device,
1160						  oct->ioq_vector[i].msix_res,
1161						  oct->ioq_vector[i].tag);
1162				oct->ioq_vector[i].tag = NULL;
1163			}
1164
1165			if (oct->ioq_vector[i].msix_res != NULL) {
1166				bus_release_resource(oct->device, SYS_RES_IRQ,
1167						     oct->ioq_vector[i].vector,
1168						 oct->ioq_vector[i].msix_res);
1169				oct->ioq_vector[i].msix_res = NULL;
1170			}
1171		}
1172
1173
1174		if (oct->tag != NULL) {
1175			bus_teardown_intr(oct->device, oct->msix_res, oct->tag);
1176			oct->tag = NULL;
1177		}
1178
1179		if (oct->msix_res != NULL) {
1180			bus_release_resource(oct->device, SYS_RES_IRQ,
1181					     oct->aux_vector,
1182					     oct->msix_res);
1183			oct->msix_res = NULL;
1184		}
1185
1186		pci_release_msi(oct->device);
1187
1188	}
1189
1190	if (lio_setup_interrupt(oct, num_ioqs)) {
1191		lio_dev_info(oct, "Setup interuupt failed\n");
1192		return (1);
1193	}
1194
1195	/* Enable Octeon device interrupts */
1196	oct->fn_list.enable_interrupt(oct, OCTEON_ALL_INTR);
1197
1198	return (0);
1199}
1200
1201static int
1202lio_set_channels(SYSCTL_HANDLER_ARGS)
1203{
1204	struct lio		*lio = (struct lio *)arg1;
1205	struct octeon_device	*oct = lio->oct_dev;
1206	uint32_t		combined_count, max_combined;
1207	int	err, stopped = 0;
1208
1209	if (strcmp(oct->fw_info.lio_firmware_version, "1.6.1") < 0) {
1210		lio_dev_err(oct,
1211			    "Minimum firmware version required is 1.6.1\n");
1212		return (EINVAL);
1213	}
1214
1215	combined_count = oct->num_iqs;
1216	err = sysctl_handle_int(oidp, &combined_count, 0, req);
1217
1218	if ((err) || (req->newptr == NULL))
1219		return (err);
1220
1221	if (!combined_count)
1222		return (EINVAL);
1223
1224	if (LIO_CN23XX_PF(oct)) {
1225		max_combined = lio->linfo.num_txpciq;
1226	} else {
1227		return (EINVAL);
1228	}
1229
1230	if ((combined_count > max_combined) || (combined_count < 1))
1231		return (EINVAL);
1232
1233	if (combined_count == oct->num_iqs)
1234		return (0);
1235
1236	lio_ifstate_set(lio, LIO_IFSTATE_RESETTING);
1237
1238	if (if_getdrvflags(lio->ifp) & IFF_DRV_RUNNING) {
1239		lio_stop(lio->ifp);
1240		stopped = 1;
1241	}
1242
1243	if (lio_reset_queues(lio->ifp, combined_count))
1244		return (EINVAL);
1245
1246	lio_irq_reallocate_irqs(oct, combined_count);
1247	if (stopped)
1248		lio_open(lio);
1249
1250	lio_ifstate_reset(lio, LIO_IFSTATE_RESETTING);
1251
1252	return (0);
1253}
1254
1255
1256static int
1257lio_get_set_fwmsglevel(SYSCTL_HANDLER_ARGS)
1258{
1259	struct lio	*lio = (struct lio *)arg1;
1260	struct ifnet	*ifp = lio->ifp;
1261	int	err, new_msglvl = 0, old_msglvl = 0;
1262
1263	if (lio_ifstate_check(lio, LIO_IFSTATE_RESETTING))
1264		return (ENXIO);
1265
1266	old_msglvl = new_msglvl = lio->msg_enable;
1267	err = sysctl_handle_int(oidp, &new_msglvl, 0, req);
1268
1269	if ((err) || (req->newptr == NULL))
1270		return (err);
1271
1272	if (old_msglvl == new_msglvl)
1273		return (0);
1274
1275	if (new_msglvl ^ lio->msg_enable) {
1276		if (new_msglvl)
1277			err = lio_set_feature(ifp, LIO_CMD_VERBOSE_ENABLE, 0);
1278		else
1279			err = lio_set_feature(ifp, LIO_CMD_VERBOSE_DISABLE, 0);
1280	}
1281
1282	lio->msg_enable = new_msglvl;
1283
1284	return ((err) ? EINVAL : 0);
1285}
1286
1287static int
1288lio_set_stats_interval(SYSCTL_HANDLER_ARGS)
1289{
1290	struct lio	*lio = (struct lio *)arg1;
1291	int	err, new_time = 0, old_time = 0;
1292
1293	old_time = new_time = lio->stats_interval;
1294	err = sysctl_handle_int(oidp, &new_time, 0, req);
1295
1296	if ((err) || (req->newptr == NULL))
1297		return (err);
1298
1299	if (old_time == new_time)
1300		return (0);
1301
1302	lio->stats_interval = new_time;
1303
1304	return (0);
1305}
1306
1307static void
1308lio_fw_stats_callback(struct octeon_device *oct_dev, uint32_t status, void *ptr)
1309{
1310	struct lio_soft_command	*sc = (struct lio_soft_command *)ptr;
1311	struct lio_fw_stats_resp *resp =
1312		(struct lio_fw_stats_resp *)sc->virtrptr;
1313	struct octeon_rx_stats	*rsp_rstats = &resp->stats.fromwire;
1314	struct octeon_tx_stats	*rsp_tstats = &resp->stats.fromhost;
1315	struct octeon_rx_stats	*rstats = &oct_dev->link_stats.fromwire;
1316	struct octeon_tx_stats	*tstats = &oct_dev->link_stats.fromhost;
1317	struct ifnet		*ifp = oct_dev->props.ifp;
1318	struct lio		*lio = if_getsoftc(ifp);
1319
1320	if ((status != LIO_REQUEST_TIMEOUT) && !resp->status) {
1321		lio_swap_8B_data((uint64_t *)&resp->stats,
1322				 (sizeof(struct octeon_link_stats)) >> 3);
1323
1324		/* RX link-level stats */
1325		rstats->total_rcvd = rsp_rstats->total_rcvd;
1326		rstats->bytes_rcvd = rsp_rstats->bytes_rcvd;
1327		rstats->total_bcst = rsp_rstats->total_bcst;
1328		rstats->total_mcst = rsp_rstats->total_mcst;
1329		rstats->runts = rsp_rstats->runts;
1330		rstats->ctl_rcvd = rsp_rstats->ctl_rcvd;
1331		/* Accounts for over/under-run of buffers */
1332		rstats->fifo_err = rsp_rstats->fifo_err;
1333		rstats->dmac_drop = rsp_rstats->dmac_drop;
1334		rstats->fcs_err = rsp_rstats->fcs_err;
1335		rstats->jabber_err = rsp_rstats->jabber_err;
1336		rstats->l2_err = rsp_rstats->l2_err;
1337		rstats->frame_err = rsp_rstats->frame_err;
1338
1339		/* RX firmware stats */
1340		rstats->fw_total_rcvd = rsp_rstats->fw_total_rcvd;
1341		rstats->fw_total_fwd = rsp_rstats->fw_total_fwd;
1342		rstats->fw_err_pko = rsp_rstats->fw_err_pko;
1343		rstats->fw_err_link = rsp_rstats->fw_err_link;
1344		rstats->fw_err_drop = rsp_rstats->fw_err_drop;
1345		rstats->fw_rx_vxlan = rsp_rstats->fw_rx_vxlan;
1346		rstats->fw_rx_vxlan_err = rsp_rstats->fw_rx_vxlan_err;
1347
1348		/* Number of packets that are LROed      */
1349		rstats->fw_lro_pkts = rsp_rstats->fw_lro_pkts;
1350		/* Number of octets that are LROed       */
1351		rstats->fw_lro_octs = rsp_rstats->fw_lro_octs;
1352		/* Number of LRO packets formed          */
1353		rstats->fw_total_lro = rsp_rstats->fw_total_lro;
1354		/* Number of times lRO of packet aborted */
1355		rstats->fw_lro_aborts = rsp_rstats->fw_lro_aborts;
1356		rstats->fw_lro_aborts_port = rsp_rstats->fw_lro_aborts_port;
1357		rstats->fw_lro_aborts_seq = rsp_rstats->fw_lro_aborts_seq;
1358		rstats->fw_lro_aborts_tsval = rsp_rstats->fw_lro_aborts_tsval;
1359		rstats->fw_lro_aborts_timer = rsp_rstats->fw_lro_aborts_timer;
1360		/* intrmod: packet forward rate */
1361		rstats->fwd_rate = rsp_rstats->fwd_rate;
1362
1363		/* TX link-level stats */
1364		tstats->total_pkts_sent = rsp_tstats->total_pkts_sent;
1365		tstats->total_bytes_sent = rsp_tstats->total_bytes_sent;
1366		tstats->mcast_pkts_sent = rsp_tstats->mcast_pkts_sent;
1367		tstats->bcast_pkts_sent = rsp_tstats->bcast_pkts_sent;
1368		tstats->ctl_sent = rsp_tstats->ctl_sent;
1369		/* Packets sent after one collision */
1370		tstats->one_collision_sent = rsp_tstats->one_collision_sent;
1371		/* Packets sent after multiple collision */
1372		tstats->multi_collision_sent = rsp_tstats->multi_collision_sent;
1373		/* Packets not sent due to max collisions */
1374		tstats->max_collision_fail = rsp_tstats->max_collision_fail;
1375		/* Packets not sent due to max deferrals */
1376		tstats->max_deferral_fail = rsp_tstats->max_deferral_fail;
1377		/* Accounts for over/under-run of buffers */
1378		tstats->fifo_err = rsp_tstats->fifo_err;
1379		tstats->runts = rsp_tstats->runts;
1380		/* Total number of collisions detected */
1381		tstats->total_collisions = rsp_tstats->total_collisions;
1382
1383		/* firmware stats */
1384		tstats->fw_total_sent = rsp_tstats->fw_total_sent;
1385		tstats->fw_total_fwd = rsp_tstats->fw_total_fwd;
1386		tstats->fw_err_pko = rsp_tstats->fw_err_pko;
1387		tstats->fw_err_pki = rsp_tstats->fw_err_pki;
1388		tstats->fw_err_link = rsp_tstats->fw_err_link;
1389		tstats->fw_err_drop = rsp_tstats->fw_err_drop;
1390		tstats->fw_tso = rsp_tstats->fw_tso;
1391		tstats->fw_tso_fwd = rsp_tstats->fw_tso_fwd;
1392		tstats->fw_err_tso = rsp_tstats->fw_err_tso;
1393		tstats->fw_tx_vxlan = rsp_tstats->fw_tx_vxlan;
1394	}
1395	lio_free_soft_command(oct_dev, sc);
1396	callout_schedule(&lio->stats_timer,
1397			 lio_ms_to_ticks(lio->stats_interval));
1398}
1399
1400/*  Configure interrupt moderation parameters */
1401static void
1402lio_get_fw_stats(void *arg)
1403{
1404	struct lio		*lio = arg;
1405	struct octeon_device	*oct_dev = lio->oct_dev;
1406	struct lio_soft_command	*sc;
1407	struct lio_fw_stats_resp *resp;
1408	int	retval;
1409
1410	if (callout_pending(&lio->stats_timer) ||
1411	    callout_active(&lio->stats_timer) == 0)
1412		return;
1413
1414	/* Alloc soft command */
1415	sc = lio_alloc_soft_command(oct_dev, 0,
1416				    sizeof(struct lio_fw_stats_resp), 0);
1417
1418	if (sc == NULL)
1419		goto alloc_sc_failed;
1420
1421	resp = (struct lio_fw_stats_resp *)sc->virtrptr;
1422	bzero(resp, sizeof(struct lio_fw_stats_resp));
1423
1424	sc->iq_no = lio->linfo.txpciq[0].s.q_no;
1425
1426	lio_prepare_soft_command(oct_dev, sc, LIO_OPCODE_NIC,
1427				 LIO_OPCODE_NIC_PORT_STATS, 0, 0, 0);
1428
1429	sc->callback = lio_fw_stats_callback;
1430	sc->callback_arg = sc;
1431	sc->wait_time = 500;		/* in milli seconds */
1432
1433	retval = lio_send_soft_command(oct_dev, sc);
1434	if (retval == LIO_IQ_SEND_FAILED)
1435		goto send_sc_failed;
1436
1437	return;
1438
1439send_sc_failed:
1440	lio_free_soft_command(oct_dev, sc);
1441alloc_sc_failed:
1442	callout_schedule(&lio->stats_timer,
1443			 lio_ms_to_ticks(lio->stats_interval));
1444}
1445
1446/* Callback function for intrmod */
1447static void
1448lio_get_intrmod_callback(struct octeon_device *oct_dev, uint32_t status,
1449			 void *ptr)
1450{
1451	struct lio_soft_command	*sc = (struct lio_soft_command *)ptr;
1452	struct ifnet		*ifp = oct_dev->props.ifp;
1453	struct lio		*lio = if_getsoftc(ifp);
1454	struct lio_intrmod_resp	*resp;
1455
1456	if (status) {
1457		lio_dev_err(oct_dev, "Failed to get intrmod\n");
1458	} else {
1459		resp = (struct lio_intrmod_resp *)sc->virtrptr;
1460		lio_swap_8B_data((uint64_t *)&resp->intrmod,
1461				 (sizeof(struct octeon_intrmod_cfg)) / 8);
1462		memcpy(&lio->intrmod_cfg, &resp->intrmod,
1463		       sizeof(struct octeon_intrmod_cfg));
1464	}
1465
1466	lio_free_soft_command(oct_dev, sc);
1467}
1468
1469/*  get interrupt moderation parameters */
1470static int
1471lio_get_intrmod_cfg(struct lio *lio, struct octeon_intrmod_cfg *intr_cfg)
1472{
1473	struct lio_soft_command	*sc;
1474	struct lio_intrmod_resp	*resp;
1475	struct octeon_device	*oct_dev = lio->oct_dev;
1476	int	retval;
1477
1478	/* Alloc soft command */
1479	sc = lio_alloc_soft_command(oct_dev, 0, sizeof(struct lio_intrmod_resp),
1480				    0);
1481
1482	if (sc == NULL)
1483		return (ENOMEM);
1484
1485	resp = (struct lio_intrmod_resp *)sc->virtrptr;
1486	bzero(resp, sizeof(struct lio_intrmod_resp));
1487	sc->iq_no = lio->linfo.txpciq[0].s.q_no;
1488
1489	lio_prepare_soft_command(oct_dev, sc, LIO_OPCODE_NIC,
1490				 LIO_OPCODE_NIC_INTRMOD_PARAMS, 0, 0, 0);
1491
1492	sc->callback = lio_get_intrmod_callback;
1493	sc->callback_arg = sc;
1494	sc->wait_time = 1000;
1495
1496	retval = lio_send_soft_command(oct_dev, sc);
1497	if (retval == LIO_IQ_SEND_FAILED) {
1498		lio_free_soft_command(oct_dev, sc);
1499		return (EINVAL);
1500	}
1501
1502	return (0);
1503}
1504
1505static void
1506lio_set_intrmod_callback(struct octeon_device *oct_dev, uint32_t status,
1507			 void *ptr)
1508{
1509	struct lio_soft_command		*sc = (struct lio_soft_command *)ptr;
1510	struct lio_intrmod_context	*ctx;
1511
1512	ctx = (struct lio_intrmod_context *)sc->ctxptr;
1513
1514	ctx->status = status;
1515
1516	ctx->cond = 1;
1517
1518	/*
1519	 * This barrier is required to be sure that the response has been
1520	 * written fully before waking up the handler
1521	 */
1522	wmb();
1523}
1524
1525/*  Configure interrupt moderation parameters */
1526static int
1527lio_set_intrmod_cfg(struct lio *lio, struct octeon_intrmod_cfg *intr_cfg)
1528{
1529	struct lio_soft_command		*sc;
1530	struct lio_intrmod_context	*ctx;
1531	struct octeon_intrmod_cfg	*cfg;
1532	struct octeon_device		*oct_dev = lio->oct_dev;
1533	int	retval;
1534
1535	/* Alloc soft command */
1536	sc = lio_alloc_soft_command(oct_dev, sizeof(struct octeon_intrmod_cfg),
1537				    0, sizeof(struct lio_intrmod_context));
1538
1539	if (sc == NULL)
1540		return (ENOMEM);
1541
1542	ctx = (struct lio_intrmod_context *)sc->ctxptr;
1543
1544	ctx->cond = 0;
1545	ctx->octeon_id = lio_get_device_id(oct_dev);
1546
1547	cfg = (struct octeon_intrmod_cfg *)sc->virtdptr;
1548
1549	memcpy(cfg, intr_cfg, sizeof(struct octeon_intrmod_cfg));
1550	lio_swap_8B_data((uint64_t *)cfg,
1551			 (sizeof(struct octeon_intrmod_cfg)) / 8);
1552
1553	sc->iq_no = lio->linfo.txpciq[0].s.q_no;
1554
1555	lio_prepare_soft_command(oct_dev, sc, LIO_OPCODE_NIC,
1556				 LIO_OPCODE_NIC_INTRMOD_CFG, 0, 0, 0);
1557
1558	sc->callback = lio_set_intrmod_callback;
1559	sc->callback_arg = sc;
1560	sc->wait_time = 1000;
1561
1562	retval = lio_send_soft_command(oct_dev, sc);
1563	if (retval == LIO_IQ_SEND_FAILED) {
1564		lio_free_soft_command(oct_dev, sc);
1565		return (EINVAL);
1566	}
1567
1568	/*
1569	 * Sleep on a wait queue till the cond flag indicates that the
1570	 * response arrived or timed-out.
1571	 */
1572	lio_sleep_cond(oct_dev, &ctx->cond);
1573
1574	retval = ctx->status;
1575	if (retval)
1576		lio_dev_err(oct_dev, "intrmod config failed. Status: %llx\n",
1577			    LIO_CAST64(retval));
1578	else
1579		lio_dev_info(oct_dev, "Rx-Adaptive Interrupt moderation enabled:%llx\n",
1580			     LIO_CAST64(intr_cfg->rx_enable));
1581
1582	lio_free_soft_command(oct_dev, sc);
1583
1584	return ((retval) ? ETIMEDOUT : 0);
1585}
1586
1587static int
1588lio_intrmod_cfg_rx_intrcnt(struct lio *lio, struct octeon_intrmod_cfg *intrmod,
1589			   uint32_t rx_max_frames)
1590{
1591	struct octeon_device	*oct = lio->oct_dev;
1592	uint32_t		rx_max_coalesced_frames;
1593
1594	/* Config Cnt based interrupt values */
1595	switch (oct->chip_id) {
1596	case LIO_CN23XX_PF_VID:{
1597			int	q_no;
1598
1599			if (!rx_max_frames)
1600				rx_max_coalesced_frames = intrmod->rx_frames;
1601			else
1602				rx_max_coalesced_frames = rx_max_frames;
1603
1604			for (q_no = 0; q_no < oct->num_oqs; q_no++) {
1605				q_no += oct->sriov_info.pf_srn;
1606				lio_write_csr64(oct,
1607					LIO_CN23XX_SLI_OQ_PKT_INT_LEVELS(q_no),
1608						(lio_read_csr64(oct,
1609				     LIO_CN23XX_SLI_OQ_PKT_INT_LEVELS(q_no)) &
1610						 (0x3fffff00000000UL)) |
1611						(rx_max_coalesced_frames - 1));
1612				/* consider setting resend bit */
1613			}
1614
1615			intrmod->rx_frames = rx_max_coalesced_frames;
1616			oct->rx_max_coalesced_frames = rx_max_coalesced_frames;
1617			break;
1618		}
1619	default:
1620		return (EINVAL);
1621	}
1622	return (0);
1623}
1624
1625static int
1626lio_intrmod_cfg_rx_intrtime(struct lio *lio, struct octeon_intrmod_cfg *intrmod,
1627			    uint32_t rx_usecs)
1628{
1629	struct octeon_device	*oct = lio->oct_dev;
1630	uint32_t		rx_coalesce_usecs;
1631
1632	/* Config Time based interrupt values */
1633	switch (oct->chip_id) {
1634	case LIO_CN23XX_PF_VID:{
1635			uint64_t	time_threshold;
1636			int	q_no;
1637
1638			if (!rx_usecs)
1639				rx_coalesce_usecs = intrmod->rx_usecs;
1640			else
1641				rx_coalesce_usecs = rx_usecs;
1642
1643			time_threshold =
1644			    lio_cn23xx_pf_get_oq_ticks(oct, rx_coalesce_usecs);
1645			for (q_no = 0; q_no < oct->num_oqs; q_no++) {
1646				q_no += oct->sriov_info.pf_srn;
1647				lio_write_csr64(oct,
1648				       LIO_CN23XX_SLI_OQ_PKT_INT_LEVELS(q_no),
1649						(intrmod->rx_frames |
1650					   ((uint64_t)time_threshold << 32)));
1651				/* consider writing to resend bit here */
1652			}
1653
1654			intrmod->rx_usecs = rx_coalesce_usecs;
1655			oct->rx_coalesce_usecs = rx_coalesce_usecs;
1656			break;
1657		}
1658	default:
1659		return (EINVAL);
1660	}
1661
1662	return (0);
1663}
1664
1665static int
1666lio_intrmod_cfg_tx_intrcnt(struct lio *lio, struct octeon_intrmod_cfg *intrmod,
1667			   uint32_t tx_max_frames)
1668{
1669	struct octeon_device	*oct = lio->oct_dev;
1670	uint64_t	val;
1671	uint32_t	iq_intr_pkt;
1672	uint32_t	inst_cnt_reg;
1673
1674	/* Config Cnt based interrupt values */
1675	switch (oct->chip_id) {
1676	case LIO_CN23XX_PF_VID:{
1677			int	q_no;
1678
1679			if (!tx_max_frames)
1680				iq_intr_pkt = LIO_CN23XX_DEF_IQ_INTR_THRESHOLD &
1681				    LIO_CN23XX_PKT_IN_DONE_WMARK_MASK;
1682			else
1683				iq_intr_pkt = tx_max_frames &
1684				    LIO_CN23XX_PKT_IN_DONE_WMARK_MASK;
1685			for (q_no = 0; q_no < oct->num_iqs; q_no++) {
1686				inst_cnt_reg =
1687					(oct->instr_queue[q_no])->inst_cnt_reg;
1688				val = lio_read_csr64(oct, inst_cnt_reg);
1689				/*
1690				 * clear wmark and count.dont want to write
1691				 * count back
1692				 */
1693				val = (val & 0xFFFF000000000000ULL) |
1694				    ((uint64_t)(iq_intr_pkt - 1)
1695				     << LIO_CN23XX_PKT_IN_DONE_WMARK_BIT_POS);
1696				lio_write_csr64(oct, inst_cnt_reg, val);
1697				/* consider setting resend bit */
1698			}
1699
1700			intrmod->tx_frames = iq_intr_pkt;
1701			oct->tx_max_coalesced_frames = iq_intr_pkt;
1702			break;
1703		}
1704	default:
1705		return (-EINVAL);
1706	}
1707	return (0);
1708}
1709
1710static int
1711lio_get_set_intr_coalesce(SYSCTL_HANDLER_ARGS)
1712{
1713	struct lio		*lio = (struct lio *)arg1;
1714	struct octeon_device	*oct = lio->oct_dev;
1715	uint64_t	new_val = 0, old_val = 0;
1716	uint32_t	rx_coalesce_usecs = 0;
1717	uint32_t	rx_max_coalesced_frames = 0;
1718	uint32_t	tx_coalesce_usecs = 0;
1719	int		err, ret;
1720
1721	switch (arg2) {
1722	case LIO_USE_ADAPTIVE_RX_COALESCE:
1723		if (lio->intrmod_cfg.rx_enable)
1724			new_val = old_val = lio->intrmod_cfg.rx_enable;
1725
1726		err = sysctl_handle_64(oidp, &new_val, 0, req);
1727		if ((err) || (req->newptr == NULL))
1728			return (err);
1729
1730		if (old_val == new_val)
1731			return (0);
1732
1733		lio->intrmod_cfg.rx_enable = new_val ? 1 : 0;
1734		break;
1735
1736	case LIO_USE_ADAPTIVE_TX_COALESCE:
1737		if (lio->intrmod_cfg.tx_enable)
1738			new_val = old_val = lio->intrmod_cfg.tx_enable;
1739
1740		err = sysctl_handle_64(oidp, &new_val, 0, req);
1741		if ((err) || (req->newptr == NULL))
1742			return (err);
1743
1744		if (old_val == new_val)
1745			return (0);
1746
1747		lio->intrmod_cfg.tx_enable = new_val ? 1 : 0;
1748		break;
1749
1750	case LIO_RX_COALESCE_USECS:
1751		if (!lio->intrmod_cfg.rx_enable)
1752			new_val = old_val = oct->rx_coalesce_usecs;
1753
1754		err = sysctl_handle_64(oidp, &new_val, 0, req);
1755		if ((err) || (req->newptr == NULL))
1756			return (err);
1757
1758		if (old_val == new_val)
1759			return (0);
1760
1761		rx_coalesce_usecs = new_val;
1762		break;
1763
1764	case LIO_RX_MAX_COALESCED_FRAMES:
1765		if (!lio->intrmod_cfg.rx_enable)
1766			new_val = old_val = oct->rx_max_coalesced_frames;
1767
1768		err = sysctl_handle_64(oidp, &new_val, 0, req);
1769		if ((err) || (req->newptr == NULL))
1770			return (err);
1771
1772		if (old_val == new_val)
1773			return (0);
1774
1775		rx_max_coalesced_frames = new_val;
1776		break;
1777
1778	case LIO_TX_MAX_COALESCED_FRAMES:
1779		if (!lio->intrmod_cfg.tx_enable)
1780			new_val = old_val = oct->tx_max_coalesced_frames;
1781
1782		err = sysctl_handle_64(oidp, &new_val, 0, req);
1783		if ((err) || (req->newptr == NULL))
1784			return (err);
1785
1786		if (old_val == new_val)
1787			return (0);
1788
1789		tx_coalesce_usecs = new_val;
1790		break;
1791
1792	case LIO_PKT_RATE_LOW:
1793		if (lio->intrmod_cfg.rx_enable)
1794			new_val = old_val = lio->intrmod_cfg.minpkt_ratethr;
1795
1796		err = sysctl_handle_64(oidp, &new_val, 0, req);
1797		if ((err) || (req->newptr == NULL))
1798			return (err);
1799
1800		if (old_val == new_val)
1801			return (0);
1802
1803		if (lio->intrmod_cfg.rx_enable || lio->intrmod_cfg.tx_enable)
1804			lio->intrmod_cfg.minpkt_ratethr = new_val;
1805		break;
1806
1807	case LIO_RX_COALESCE_USECS_LOW:
1808		if (lio->intrmod_cfg.rx_enable)
1809			new_val = old_val = lio->intrmod_cfg.rx_mintmr_trigger;
1810
1811		err = sysctl_handle_64(oidp, &new_val, 0, req);
1812		if ((err) || (req->newptr == NULL))
1813			return (err);
1814
1815		if (old_val == new_val)
1816			return (0);
1817
1818		if (lio->intrmod_cfg.rx_enable)
1819			lio->intrmod_cfg.rx_mintmr_trigger = new_val;
1820		break;
1821
1822	case LIO_RX_MAX_COALESCED_FRAMES_LOW:
1823		if (lio->intrmod_cfg.rx_enable)
1824			new_val = old_val = lio->intrmod_cfg.rx_mincnt_trigger;
1825
1826		err = sysctl_handle_64(oidp, &new_val, 0, req);
1827		if ((err) || (req->newptr == NULL))
1828			return (err);
1829
1830		if (old_val == new_val)
1831			return (0);
1832
1833		if (lio->intrmod_cfg.rx_enable)
1834			lio->intrmod_cfg.rx_mincnt_trigger = new_val;
1835		break;
1836
1837	case LIO_TX_MAX_COALESCED_FRAMES_LOW:
1838		if (lio->intrmod_cfg.tx_enable)
1839			new_val = old_val = lio->intrmod_cfg.tx_mincnt_trigger;
1840
1841		err = sysctl_handle_64(oidp, &new_val, 0, req);
1842		if ((err) || (req->newptr == NULL))
1843			return (err);
1844
1845		if (old_val == new_val)
1846			return (0);
1847
1848		if (lio->intrmod_cfg.tx_enable)
1849			lio->intrmod_cfg.tx_mincnt_trigger = new_val;
1850		break;
1851
1852	case LIO_PKT_RATE_HIGH:
1853		if (lio->intrmod_cfg.rx_enable)
1854			new_val = old_val = lio->intrmod_cfg.maxpkt_ratethr;
1855
1856		err = sysctl_handle_64(oidp, &new_val, 0, req);
1857		if ((err) || (req->newptr == NULL))
1858			return (err);
1859
1860		if (old_val == new_val)
1861			return (0);
1862
1863		if (lio->intrmod_cfg.rx_enable || lio->intrmod_cfg.tx_enable)
1864			lio->intrmod_cfg.maxpkt_ratethr = new_val;
1865		break;
1866
1867	case LIO_RX_COALESCE_USECS_HIGH:
1868		if (lio->intrmod_cfg.rx_enable)
1869			new_val = old_val = lio->intrmod_cfg.rx_maxtmr_trigger;
1870
1871		err = sysctl_handle_64(oidp, &new_val, 0, req);
1872		if ((err) || (req->newptr == NULL))
1873			return (err);
1874
1875		if (old_val == new_val)
1876			return (0);
1877
1878		if (lio->intrmod_cfg.rx_enable)
1879			lio->intrmod_cfg.rx_maxtmr_trigger = new_val;
1880		break;
1881
1882	case LIO_RX_MAX_COALESCED_FRAMES_HIGH:
1883		if (lio->intrmod_cfg.rx_enable)
1884			new_val = old_val = lio->intrmod_cfg.rx_maxcnt_trigger;
1885
1886		err = sysctl_handle_64(oidp, &new_val, 0, req);
1887		if ((err) || (req->newptr == NULL))
1888			return (err);
1889
1890		if (old_val == new_val)
1891			return (0);
1892
1893		if (lio->intrmod_cfg.rx_enable)
1894			lio->intrmod_cfg.rx_maxcnt_trigger = new_val;
1895		break;
1896
1897	case LIO_TX_MAX_COALESCED_FRAMES_HIGH:
1898		if (lio->intrmod_cfg.tx_enable)
1899			new_val = old_val = lio->intrmod_cfg.tx_maxcnt_trigger;
1900
1901		err = sysctl_handle_64(oidp, &new_val, 0, req);
1902		if ((err) || (req->newptr == NULL))
1903			return (err);
1904
1905		if (old_val == new_val)
1906			return (0);
1907
1908		if (lio->intrmod_cfg.tx_enable)
1909			lio->intrmod_cfg.tx_maxcnt_trigger = new_val;
1910		break;
1911
1912	case LIO_RATE_SAMPLE_INTERVAL:
1913		if (lio->intrmod_cfg.rx_enable)
1914			new_val = old_val = lio->intrmod_cfg.check_intrvl;
1915
1916		err = sysctl_handle_64(oidp, &new_val, 0, req);
1917		if ((err) || (req->newptr == NULL))
1918			return (err);
1919
1920		if (old_val == new_val)
1921			return (0);
1922
1923		if (lio->intrmod_cfg.rx_enable || lio->intrmod_cfg.tx_enable)
1924			lio->intrmod_cfg.check_intrvl = new_val;
1925		break;
1926
1927	default:
1928		return (EINVAL);
1929	}
1930
1931	lio->intrmod_cfg.rx_usecs = LIO_GET_OQ_INTR_TIME_CFG(lio_get_conf(oct));
1932	lio->intrmod_cfg.rx_frames = LIO_GET_OQ_INTR_PKT_CFG(lio_get_conf(oct));
1933	lio->intrmod_cfg.tx_frames = LIO_GET_IQ_INTR_PKT_CFG(lio_get_conf(oct));
1934
1935	ret = lio_set_intrmod_cfg(lio, &lio->intrmod_cfg);
1936	if (ret)
1937		lio_dev_err(oct, "Interrupt coalescing updation to Firmware failed!\n");
1938
1939	if (!lio->intrmod_cfg.rx_enable) {
1940		if (!rx_coalesce_usecs)
1941			rx_coalesce_usecs = oct->rx_coalesce_usecs;
1942
1943		if (!rx_max_coalesced_frames)
1944			rx_max_coalesced_frames = oct->rx_max_coalesced_frames;
1945
1946		ret = lio_intrmod_cfg_rx_intrtime(lio, &lio->intrmod_cfg,
1947						  rx_coalesce_usecs);
1948		if (ret)
1949			return (ret);
1950
1951		ret = lio_intrmod_cfg_rx_intrcnt(lio, &lio->intrmod_cfg,
1952						 rx_max_coalesced_frames);
1953		if (ret)
1954			return (ret);
1955	} else {
1956		oct->rx_coalesce_usecs =
1957		    LIO_GET_OQ_INTR_TIME_CFG(lio_get_conf(oct));
1958		oct->rx_max_coalesced_frames =
1959		    LIO_GET_OQ_INTR_PKT_CFG(lio_get_conf(oct));
1960	}
1961
1962	if (!lio->intrmod_cfg.tx_enable) {
1963		if (!tx_coalesce_usecs)
1964			tx_coalesce_usecs = oct->tx_max_coalesced_frames;
1965
1966		ret = lio_intrmod_cfg_tx_intrcnt(lio, &lio->intrmod_cfg,
1967						 tx_coalesce_usecs);
1968		if (ret)
1969			return (ret);
1970	} else {
1971		oct->tx_max_coalesced_frames =
1972			LIO_GET_IQ_INTR_PKT_CFG(lio_get_conf(oct));
1973	}
1974
1975	return (0);
1976}
1977