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