]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/liquidio/lio_sysctl.c
MFV r356163,r356197:
[FreeBSD/FreeBSD.git] / sys / dev / liquidio / lio_sysctl.c
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$*/
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
78 static int      lio_get_eeprom(SYSCTL_HANDLER_ARGS);
79 static int      lio_get_set_pauseparam(SYSCTL_HANDLER_ARGS);
80 static int      lio_get_regs(SYSCTL_HANDLER_ARGS);
81 static int      lio_cn23xx_pf_read_csr_reg(char *s, struct octeon_device *oct);
82 static int      lio_get_set_fwmsglevel(SYSCTL_HANDLER_ARGS);
83 static int      lio_set_stats_interval(SYSCTL_HANDLER_ARGS);
84 static void     lio_get_fw_stats(void *arg);
85 static int      lio_get_set_intr_coalesce(SYSCTL_HANDLER_ARGS);
86 static int      lio_get_intrmod_cfg(struct lio *lio,
87                                     struct octeon_intrmod_cfg *intr_cfg);
88 static int      lio_get_ringparam(SYSCTL_HANDLER_ARGS);
89 static int      lio_set_ringparam(SYSCTL_HANDLER_ARGS);
90 static int      lio_get_channels(SYSCTL_HANDLER_ARGS);
91 static int      lio_set_channels(SYSCTL_HANDLER_ARGS);
92 static int      lio_irq_reallocate_irqs(struct octeon_device *oct,
93                                         uint32_t num_ioqs);
94
95 struct lio_intrmod_context {
96         int     octeon_id;
97         volatile int cond;
98         int     status;
99 };
100
101 struct lio_intrmod_resp {
102         uint64_t        rh;
103         struct octeon_intrmod_cfg intrmod;
104         uint64_t        status;
105 };
106
107 static int
108 lio_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. */
137 void
138 lio_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
627 static int
628 lio_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  */
659 static int
660 lio_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.  */
733 static int
734 lio_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
769 static int
770 lio_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
964 static int
965 lio_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
989 static int
990 lio_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
1042 static int
1043 lio_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
1115 err_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
1127 static int
1128 lio_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
1139 static int
1140 lio_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
1201 static int
1202 lio_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
1256 static int
1257 lio_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
1287 static int
1288 lio_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
1307 static void
1308 lio_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 */
1401 static void
1402 lio_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
1439 send_sc_failed:
1440         lio_free_soft_command(oct_dev, sc);
1441 alloc_sc_failed:
1442         callout_schedule(&lio->stats_timer,
1443                          lio_ms_to_ticks(lio->stats_interval));
1444 }
1445
1446 /* Callback function for intrmod */
1447 static void
1448 lio_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 */
1470 static int
1471 lio_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
1505 static void
1506 lio_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 */
1526 static int
1527 lio_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
1587 static int
1588 lio_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
1625 static int
1626 lio_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
1665 static int
1666 lio_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
1710 static int
1711 lio_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 }