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
lio_send_queue_count_update(if_t ifp,uint32_t num_queues)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
lio_add_hw_stats(struct lio * lio)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
lio_get_eeprom(SYSCTL_HANDLER_ARGS)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
lio_get_set_pauseparam(SYSCTL_HANDLER_ARGS)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
lio_get_regs(SYSCTL_HANDLER_ARGS)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 switch (oct->chip_id) {
748 case LIO_CN23XX_PF_VID:
749 len += lio_cn23xx_pf_read_csr_reg(regbuf, oct);
750 break;
751 default:
752 len += sprintf(regbuf, "%s Unknown chipid: %d\n",
753 __func__, oct->chip_id);
754 }
755
756 error = sysctl_handle_string(oidp, regbuf, len, req);
757 free(regbuf, M_DEVBUF);
758
759 return (error);
760 }
761
762 static int
lio_cn23xx_pf_read_csr_reg(char * s,struct octeon_device * oct)763 lio_cn23xx_pf_read_csr_reg(char *s, struct octeon_device *oct)
764 {
765 uint32_t reg;
766 int i, len = 0;
767 uint8_t pf_num = oct->pf_num;
768
769 /* PCI Window Registers */
770
771 len += sprintf(s + len, "\t Octeon CSR Registers\n\n");
772
773 /* 0x29030 or 0x29040 */
774 reg = LIO_CN23XX_SLI_PKT_MAC_RINFO64(oct->pcie_port, oct->pf_num);
775 len += sprintf(s + len, "[%08x] (SLI_PKT_MAC%d_PF%d_RINFO): %016llx\n",
776 reg, oct->pcie_port, oct->pf_num,
777 LIO_CAST64(lio_read_csr64(oct, reg)));
778
779 /* 0x27080 or 0x27090 */
780 reg = LIO_CN23XX_SLI_MAC_PF_INT_ENB64(oct->pcie_port, oct->pf_num);
781 len += sprintf(s + len, "[%08x] (SLI_MAC%d_PF%d_INT_ENB): %016llx\n",
782 reg, oct->pcie_port, oct->pf_num,
783 LIO_CAST64(lio_read_csr64(oct, reg)));
784
785 /* 0x27000 or 0x27010 */
786 reg = LIO_CN23XX_SLI_MAC_PF_INT_SUM64(oct->pcie_port, oct->pf_num);
787 len += sprintf(s + len, "[%08x] (SLI_MAC%d_PF%d_INT_SUM): %016llx\n",
788 reg, oct->pcie_port, oct->pf_num,
789 LIO_CAST64(lio_read_csr64(oct, reg)));
790
791 /* 0x29120 */
792 reg = 0x29120;
793 len += sprintf(s + len, "[%08x] (SLI_PKT_MEM_CTL): %016llx\n", reg,
794 LIO_CAST64(lio_read_csr64(oct, reg)));
795
796 /* 0x27300 */
797 reg = 0x27300 + oct->pcie_port * LIO_CN23XX_MAC_INT_OFFSET +
798 (oct->pf_num) * LIO_CN23XX_PF_INT_OFFSET;
799 len += sprintf(s + len, "[%08x] (SLI_MAC%d_PF%d_PKT_VF_INT): %016llx\n",
800 reg, oct->pcie_port, oct->pf_num,
801 LIO_CAST64(lio_read_csr64(oct, reg)));
802
803 /* 0x27200 */
804 reg = 0x27200 + 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_PP_VF_INT): %016llx\n",
807 reg, oct->pcie_port, oct->pf_num,
808 LIO_CAST64(lio_read_csr64(oct, reg)));
809
810 /* 29130 */
811 reg = LIO_CN23XX_SLI_PKT_CNT_INT;
812 len += sprintf(s + len, "[%08x] (SLI_PKT_CNT_INT): %016llx\n", reg,
813 LIO_CAST64(lio_read_csr64(oct, reg)));
814
815 /* 0x29140 */
816 reg = LIO_CN23XX_SLI_PKT_TIME_INT;
817 len += sprintf(s + len, "[%08x] (SLI_PKT_TIME_INT): %016llx\n", reg,
818 LIO_CAST64(lio_read_csr64(oct, reg)));
819
820 /* 0x29160 */
821 reg = 0x29160;
822 len += sprintf(s + len, "[%08x] (SLI_PKT_INT): %016llx\n", reg,
823 LIO_CAST64(lio_read_csr64(oct, reg)));
824
825 /* 0x29180 */
826 reg = LIO_CN23XX_SLI_OQ_WMARK;
827 len += sprintf(s + len, "[%08x] (SLI_PKT_OUTPUT_WMARK): %016llx\n",
828 reg, LIO_CAST64(lio_read_csr64(oct, reg)));
829
830 /* 0x291E0 */
831 reg = LIO_CN23XX_SLI_PKT_IOQ_RING_RST;
832 len += sprintf(s + len, "[%08x] (SLI_PKT_RING_RST): %016llx\n", reg,
833 LIO_CAST64(lio_read_csr64(oct, reg)));
834
835 /* 0x29210 */
836 reg = LIO_CN23XX_SLI_GBL_CONTROL;
837 len += sprintf(s + len, "[%08x] (SLI_PKT_GBL_CONTROL): %016llx\n", reg,
838 LIO_CAST64(lio_read_csr64(oct, reg)));
839
840 /* 0x29220 */
841 reg = 0x29220;
842 len += sprintf(s + len, "[%08x] (SLI_PKT_BIST_STATUS): %016llx\n",
843 reg, LIO_CAST64(lio_read_csr64(oct, reg)));
844
845 /* PF only */
846 if (pf_num == 0) {
847 /* 0x29260 */
848 reg = LIO_CN23XX_SLI_OUT_BP_EN_W1S;
849 len += sprintf(s + len, "[%08x] (SLI_PKT_OUT_BP_EN_W1S): %016llx\n",
850 reg, LIO_CAST64(lio_read_csr64(oct, reg)));
851 } else if (pf_num == 1) {
852 /* 0x29270 */
853 reg = LIO_CN23XX_SLI_OUT_BP_EN2_W1S;
854 len += sprintf(s + len, "[%08x] (SLI_PKT_OUT_BP_EN2_W1S): %016llx\n",
855 reg, LIO_CAST64(lio_read_csr64(oct, reg)));
856 }
857
858 for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
859 reg = LIO_CN23XX_SLI_OQ_BUFF_INFO_SIZE(i);
860 len += sprintf(s + len, "[%08x] (SLI_PKT%d_OUT_SIZE): %016llx\n",
861 reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
862 }
863
864 /* 0x10040 */
865 for (i = 0; i < LIO_CN23XX_PF_MAX_INPUT_QUEUES; i++) {
866 reg = LIO_CN23XX_SLI_IQ_INSTR_COUNT64(i);
867 len += sprintf(s + len, "[%08x] (SLI_PKT_IN_DONE%d_CNTS): %016llx\n",
868 reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
869 }
870
871 /* 0x10080 */
872 for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
873 reg = LIO_CN23XX_SLI_OQ_PKTS_CREDIT(i);
874 len += sprintf(s + len, "[%08x] (SLI_PKT%d_SLIST_BAOFF_DBELL): %016llx\n",
875 reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
876 }
877
878 /* 0x10090 */
879 for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
880 reg = LIO_CN23XX_SLI_OQ_SIZE(i);
881 len += sprintf(s + len, "[%08x] (SLI_PKT%d_SLIST_FIFO_RSIZE): %016llx\n",
882 reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
883 }
884
885 /* 0x10050 */
886 for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
887 reg = LIO_CN23XX_SLI_OQ_PKT_CONTROL(i);
888 len += sprintf(s + len, "[%08x] (SLI_PKT%d__OUTPUT_CONTROL): %016llx\n",
889 reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
890 }
891
892 /* 0x10070 */
893 for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
894 reg = LIO_CN23XX_SLI_OQ_BASE_ADDR64(i);
895 len += sprintf(s + len, "[%08x] (SLI_PKT%d_SLIST_BADDR): %016llx\n",
896 reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
897 }
898
899 /* 0x100a0 */
900 for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
901 reg = LIO_CN23XX_SLI_OQ_PKT_INT_LEVELS(i);
902 len += sprintf(s + len, "[%08x] (SLI_PKT%d_INT_LEVELS): %016llx\n",
903 reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
904 }
905
906 /* 0x100b0 */
907 for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
908 reg = LIO_CN23XX_SLI_OQ_PKTS_SENT(i);
909 len += sprintf(s + len, "[%08x] (SLI_PKT%d_CNTS): %016llx\n",
910 reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
911 }
912
913 /* 0x100c0 */
914 for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
915 reg = 0x100c0 + i * LIO_CN23XX_OQ_OFFSET;
916 len += sprintf(s + len, "[%08x] (SLI_PKT%d_ERROR_INFO): %016llx\n",
917 reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
918 }
919
920 /* 0x10000 */
921 for (i = 0; i < LIO_CN23XX_PF_MAX_INPUT_QUEUES; i++) {
922 reg = LIO_CN23XX_SLI_IQ_PKT_CONTROL64(i);
923 len += sprintf(s + len, "[%08x] (SLI_PKT%d_INPUT_CONTROL): %016llx\n",
924 reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
925 }
926
927 /* 0x10010 */
928 for (i = 0; i < LIO_CN23XX_PF_MAX_INPUT_QUEUES; i++) {
929 reg = LIO_CN23XX_SLI_IQ_BASE_ADDR64(i);
930 len += sprintf(s + len, "[%08x] (SLI_PKT%d_INSTR_BADDR): %016llx\n",
931 reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
932 }
933
934 /* 0x10020 */
935 for (i = 0; i < LIO_CN23XX_PF_MAX_INPUT_QUEUES; i++) {
936 reg = LIO_CN23XX_SLI_IQ_DOORBELL(i);
937 len += sprintf(s + len, "[%08x] (SLI_PKT%d_INSTR_BAOFF_DBELL): %016llx\n",
938 reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
939 }
940
941 /* 0x10030 */
942 for (i = 0; i < LIO_CN23XX_PF_MAX_INPUT_QUEUES; i++) {
943 reg = LIO_CN23XX_SLI_IQ_SIZE(i);
944 len += sprintf(s + len, "[%08x] (SLI_PKT%d_INSTR_FIFO_RSIZE): %016llx\n",
945 reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
946 }
947
948 /* 0x10040 */
949 for (i = 0; i < LIO_CN23XX_PF_MAX_INPUT_QUEUES; i++)
950 reg = LIO_CN23XX_SLI_IQ_INSTR_COUNT64(i);
951 len += sprintf(s + len, "[%08x] (SLI_PKT_IN_DONE%d_CNTS): %016llx\n",
952 reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
953
954 return (len);
955 }
956
957 static int
lio_get_ringparam(SYSCTL_HANDLER_ARGS)958 lio_get_ringparam(SYSCTL_HANDLER_ARGS)
959 {
960 struct lio *lio = (struct lio *)arg1;
961 struct octeon_device *oct = lio->oct_dev;
962 uint32_t rx_max_pending = 0, tx_max_pending = 0;
963 int err;
964
965 if (LIO_CN23XX_PF(oct)) {
966 tx_max_pending = LIO_CN23XX_MAX_IQ_DESCRIPTORS;
967 rx_max_pending = LIO_CN23XX_MAX_OQ_DESCRIPTORS;
968 }
969
970 switch (arg2) {
971 case LIO_SET_RING_RX:
972 err = sysctl_handle_int(oidp, &rx_max_pending, 0, req);
973 break;
974 case LIO_SET_RING_TX:
975 err = sysctl_handle_int(oidp, &tx_max_pending, 0, req);
976 break;
977 }
978
979 return (err);
980 }
981
982 static int
lio_reset_queues(if_t ifp,uint32_t num_qs)983 lio_reset_queues(if_t ifp, uint32_t num_qs)
984 {
985 struct lio *lio = if_getsoftc(ifp);
986 struct octeon_device *oct = lio->oct_dev;
987 int i, update = 0;
988
989 if (lio_wait_for_pending_requests(oct))
990 lio_dev_err(oct, "There were pending requests\n");
991
992 if (lio_wait_for_instr_fetch(oct))
993 lio_dev_err(oct, "IQ had pending instructions\n");
994
995
996 /*
997 * Disable the input and output queues now. No more packets will
998 * arrive from Octeon.
999 */
1000 oct->fn_list.disable_io_queues(oct);
1001
1002 if (num_qs != oct->num_iqs)
1003 update = 1;
1004
1005 for (i = 0; i < LIO_MAX_OUTPUT_QUEUES(oct); i++) {
1006 if (!(oct->io_qmask.oq & BIT_ULL(i)))
1007 continue;
1008
1009 lio_delete_droq(oct, i);
1010 }
1011
1012 for (i = 0; i < LIO_MAX_INSTR_QUEUES(oct); i++) {
1013 if (!(oct->io_qmask.iq & BIT_ULL(i)))
1014 continue;
1015
1016 lio_delete_instr_queue(oct, i);
1017 }
1018
1019 if (oct->fn_list.setup_device_regs(oct)) {
1020 lio_dev_err(oct, "Failed to configure device registers\n");
1021 return (-1);
1022 }
1023
1024 if (lio_setup_io_queues(oct, 0, num_qs, num_qs)) {
1025 lio_dev_err(oct, "IO queues initialization failed\n");
1026 return (-1);
1027 }
1028
1029 if (update && lio_send_queue_count_update(ifp, num_qs))
1030 return (-1);
1031
1032 return (0);
1033 }
1034
1035 static int
lio_set_ringparam(SYSCTL_HANDLER_ARGS)1036 lio_set_ringparam(SYSCTL_HANDLER_ARGS)
1037 {
1038 struct lio *lio = (struct lio *)arg1;
1039 struct octeon_device *oct = lio->oct_dev;
1040 uint32_t rx_count, rx_count_old, tx_count, tx_count_old;
1041 int err, stopped = 0;
1042
1043 if (!LIO_CN23XX_PF(oct))
1044 return (EINVAL);
1045
1046 switch (arg2) {
1047 case LIO_SET_RING_RX:
1048 rx_count = rx_count_old = oct->droq[0]->max_count;
1049 err = sysctl_handle_int(oidp, &rx_count, 0, req);
1050
1051 if ((err) || (req->newptr == NULL))
1052 return (err);
1053
1054 rx_count = min(max(rx_count, LIO_CN23XX_MIN_OQ_DESCRIPTORS),
1055 LIO_CN23XX_MAX_OQ_DESCRIPTORS);
1056
1057 if (rx_count == rx_count_old)
1058 return (0);
1059
1060 lio_ifstate_set(lio, LIO_IFSTATE_RESETTING);
1061
1062 if (if_getdrvflags(lio->ifp) & IFF_DRV_RUNNING) {
1063 lio_stop(lio->ifp);
1064 stopped = 1;
1065 }
1066
1067 /* Change RX DESCS count */
1068 LIO_SET_NUM_RX_DESCS_NIC_IF(lio_get_conf(oct),
1069 lio->ifidx, rx_count);
1070 break;
1071 case LIO_SET_RING_TX:
1072 tx_count = tx_count_old = oct->instr_queue[0]->max_count;
1073 err = sysctl_handle_int(oidp, &tx_count, 0, req);
1074
1075 if ((err) || (req->newptr == NULL))
1076 return (err);
1077
1078 tx_count = min(max(tx_count, LIO_CN23XX_MIN_IQ_DESCRIPTORS),
1079 LIO_CN23XX_MAX_IQ_DESCRIPTORS);
1080
1081 if (tx_count == tx_count_old)
1082 return (0);
1083
1084 lio_ifstate_set(lio, LIO_IFSTATE_RESETTING);
1085
1086 if (if_getdrvflags(lio->ifp) & IFF_DRV_RUNNING) {
1087 lio_stop(lio->ifp);
1088 stopped = 1;
1089 }
1090
1091 /* Change TX DESCS count */
1092 LIO_SET_NUM_TX_DESCS_NIC_IF(lio_get_conf(oct),
1093 lio->ifidx, tx_count);
1094 break;
1095 }
1096
1097 if (lio_reset_queues(lio->ifp, lio->linfo.num_txpciq))
1098 goto err_lio_reset_queues;
1099
1100 lio_irq_reallocate_irqs(oct, lio->linfo.num_txpciq);
1101 if (stopped)
1102 lio_open(lio);
1103
1104 lio_ifstate_reset(lio, LIO_IFSTATE_RESETTING);
1105
1106 return (0);
1107
1108 err_lio_reset_queues:
1109 if (arg2 == LIO_SET_RING_RX && rx_count != rx_count_old)
1110 LIO_SET_NUM_RX_DESCS_NIC_IF(lio_get_conf(oct), lio->ifidx,
1111 rx_count_old);
1112
1113 if (arg2 == LIO_SET_RING_TX && tx_count != tx_count_old)
1114 LIO_SET_NUM_TX_DESCS_NIC_IF(lio_get_conf(oct), lio->ifidx,
1115 tx_count_old);
1116
1117 return (EINVAL);
1118 }
1119
1120 static int
lio_get_channels(SYSCTL_HANDLER_ARGS)1121 lio_get_channels(SYSCTL_HANDLER_ARGS)
1122 {
1123 struct lio *lio = (struct lio *)arg1;
1124 struct octeon_device *oct = lio->oct_dev;
1125 uint32_t max_combined = 0;
1126
1127 if (LIO_CN23XX_PF(oct))
1128 max_combined = lio->linfo.num_txpciq;
1129 return (sysctl_handle_int(oidp, &max_combined, 0, req));
1130 }
1131
1132 static int
lio_irq_reallocate_irqs(struct octeon_device * oct,uint32_t num_ioqs)1133 lio_irq_reallocate_irqs(struct octeon_device *oct, uint32_t num_ioqs)
1134 {
1135 int i, num_msix_irqs = 0;
1136
1137 if (!oct->msix_on)
1138 return (0);
1139
1140 /*
1141 * Disable the input and output queues now. No more packets will
1142 * arrive from Octeon.
1143 */
1144 oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR);
1145
1146 if (oct->msix_on) {
1147 if (LIO_CN23XX_PF(oct))
1148 num_msix_irqs = oct->num_msix_irqs - 1;
1149
1150 for (i = 0; i < num_msix_irqs; i++) {
1151 if (oct->ioq_vector[i].tag != NULL) {
1152 bus_teardown_intr(oct->device,
1153 oct->ioq_vector[i].msix_res,
1154 oct->ioq_vector[i].tag);
1155 oct->ioq_vector[i].tag = NULL;
1156 }
1157
1158 if (oct->ioq_vector[i].msix_res != NULL) {
1159 bus_release_resource(oct->device, SYS_RES_IRQ,
1160 oct->ioq_vector[i].vector,
1161 oct->ioq_vector[i].msix_res);
1162 oct->ioq_vector[i].msix_res = NULL;
1163 }
1164 }
1165
1166
1167 if (oct->tag != NULL) {
1168 bus_teardown_intr(oct->device, oct->msix_res, oct->tag);
1169 oct->tag = NULL;
1170 }
1171
1172 if (oct->msix_res != NULL) {
1173 bus_release_resource(oct->device, SYS_RES_IRQ,
1174 oct->aux_vector,
1175 oct->msix_res);
1176 oct->msix_res = NULL;
1177 }
1178
1179 pci_release_msi(oct->device);
1180
1181 }
1182
1183 if (lio_setup_interrupt(oct, num_ioqs)) {
1184 lio_dev_info(oct, "Setup interuupt failed\n");
1185 return (1);
1186 }
1187
1188 /* Enable Octeon device interrupts */
1189 oct->fn_list.enable_interrupt(oct, OCTEON_ALL_INTR);
1190
1191 return (0);
1192 }
1193
1194 static int
lio_set_channels(SYSCTL_HANDLER_ARGS)1195 lio_set_channels(SYSCTL_HANDLER_ARGS)
1196 {
1197 struct lio *lio = (struct lio *)arg1;
1198 struct octeon_device *oct = lio->oct_dev;
1199 uint32_t combined_count, max_combined;
1200 int err, stopped = 0;
1201
1202 if (strcmp(oct->fw_info.lio_firmware_version, "1.6.1") < 0) {
1203 lio_dev_err(oct,
1204 "Minimum firmware version required is 1.6.1\n");
1205 return (EINVAL);
1206 }
1207
1208 combined_count = oct->num_iqs;
1209 err = sysctl_handle_int(oidp, &combined_count, 0, req);
1210
1211 if ((err) || (req->newptr == NULL))
1212 return (err);
1213
1214 if (!combined_count)
1215 return (EINVAL);
1216
1217 if (LIO_CN23XX_PF(oct)) {
1218 max_combined = lio->linfo.num_txpciq;
1219 } else {
1220 return (EINVAL);
1221 }
1222
1223 if ((combined_count > max_combined) || (combined_count < 1))
1224 return (EINVAL);
1225
1226 if (combined_count == oct->num_iqs)
1227 return (0);
1228
1229 lio_ifstate_set(lio, LIO_IFSTATE_RESETTING);
1230
1231 if (if_getdrvflags(lio->ifp) & IFF_DRV_RUNNING) {
1232 lio_stop(lio->ifp);
1233 stopped = 1;
1234 }
1235
1236 if (lio_reset_queues(lio->ifp, combined_count))
1237 return (EINVAL);
1238
1239 lio_irq_reallocate_irqs(oct, combined_count);
1240 if (stopped)
1241 lio_open(lio);
1242
1243 lio_ifstate_reset(lio, LIO_IFSTATE_RESETTING);
1244
1245 return (0);
1246 }
1247
1248
1249 static int
lio_get_set_fwmsglevel(SYSCTL_HANDLER_ARGS)1250 lio_get_set_fwmsglevel(SYSCTL_HANDLER_ARGS)
1251 {
1252 struct lio *lio = (struct lio *)arg1;
1253 if_t ifp = lio->ifp;
1254 int err, new_msglvl = 0, old_msglvl = 0;
1255
1256 if (lio_ifstate_check(lio, LIO_IFSTATE_RESETTING))
1257 return (ENXIO);
1258
1259 old_msglvl = new_msglvl = lio->msg_enable;
1260 err = sysctl_handle_int(oidp, &new_msglvl, 0, req);
1261
1262 if ((err) || (req->newptr == NULL))
1263 return (err);
1264
1265 if (old_msglvl == new_msglvl)
1266 return (0);
1267
1268 if (new_msglvl ^ lio->msg_enable) {
1269 if (new_msglvl)
1270 err = lio_set_feature(ifp, LIO_CMD_VERBOSE_ENABLE, 0);
1271 else
1272 err = lio_set_feature(ifp, LIO_CMD_VERBOSE_DISABLE, 0);
1273 }
1274
1275 lio->msg_enable = new_msglvl;
1276
1277 return ((err) ? EINVAL : 0);
1278 }
1279
1280 static int
lio_set_stats_interval(SYSCTL_HANDLER_ARGS)1281 lio_set_stats_interval(SYSCTL_HANDLER_ARGS)
1282 {
1283 struct lio *lio = (struct lio *)arg1;
1284 int err, new_time = 0, old_time = 0;
1285
1286 old_time = new_time = lio->stats_interval;
1287 err = sysctl_handle_int(oidp, &new_time, 0, req);
1288
1289 if ((err) || (req->newptr == NULL))
1290 return (err);
1291
1292 if (old_time == new_time)
1293 return (0);
1294
1295 lio->stats_interval = new_time;
1296
1297 return (0);
1298 }
1299
1300 static void
lio_fw_stats_callback(struct octeon_device * oct_dev,uint32_t status,void * ptr)1301 lio_fw_stats_callback(struct octeon_device *oct_dev, uint32_t status, void *ptr)
1302 {
1303 struct lio_soft_command *sc = (struct lio_soft_command *)ptr;
1304 struct lio_fw_stats_resp *resp =
1305 (struct lio_fw_stats_resp *)sc->virtrptr;
1306 struct octeon_rx_stats *rsp_rstats = &resp->stats.fromwire;
1307 struct octeon_tx_stats *rsp_tstats = &resp->stats.fromhost;
1308 struct octeon_rx_stats *rstats = &oct_dev->link_stats.fromwire;
1309 struct octeon_tx_stats *tstats = &oct_dev->link_stats.fromhost;
1310 if_t ifp = oct_dev->props.ifp;
1311 struct lio *lio = if_getsoftc(ifp);
1312
1313 if ((status != LIO_REQUEST_TIMEOUT) && !resp->status) {
1314 lio_swap_8B_data((uint64_t *)&resp->stats,
1315 (sizeof(struct octeon_link_stats)) >> 3);
1316
1317 /* RX link-level stats */
1318 rstats->total_rcvd = rsp_rstats->total_rcvd;
1319 rstats->bytes_rcvd = rsp_rstats->bytes_rcvd;
1320 rstats->total_bcst = rsp_rstats->total_bcst;
1321 rstats->total_mcst = rsp_rstats->total_mcst;
1322 rstats->runts = rsp_rstats->runts;
1323 rstats->ctl_rcvd = rsp_rstats->ctl_rcvd;
1324 /* Accounts for over/under-run of buffers */
1325 rstats->fifo_err = rsp_rstats->fifo_err;
1326 rstats->dmac_drop = rsp_rstats->dmac_drop;
1327 rstats->fcs_err = rsp_rstats->fcs_err;
1328 rstats->jabber_err = rsp_rstats->jabber_err;
1329 rstats->l2_err = rsp_rstats->l2_err;
1330 rstats->frame_err = rsp_rstats->frame_err;
1331
1332 /* RX firmware stats */
1333 rstats->fw_total_rcvd = rsp_rstats->fw_total_rcvd;
1334 rstats->fw_total_fwd = rsp_rstats->fw_total_fwd;
1335 rstats->fw_err_pko = rsp_rstats->fw_err_pko;
1336 rstats->fw_err_link = rsp_rstats->fw_err_link;
1337 rstats->fw_err_drop = rsp_rstats->fw_err_drop;
1338 rstats->fw_rx_vxlan = rsp_rstats->fw_rx_vxlan;
1339 rstats->fw_rx_vxlan_err = rsp_rstats->fw_rx_vxlan_err;
1340
1341 /* Number of packets that are LROed */
1342 rstats->fw_lro_pkts = rsp_rstats->fw_lro_pkts;
1343 /* Number of octets that are LROed */
1344 rstats->fw_lro_octs = rsp_rstats->fw_lro_octs;
1345 /* Number of LRO packets formed */
1346 rstats->fw_total_lro = rsp_rstats->fw_total_lro;
1347 /* Number of times lRO of packet aborted */
1348 rstats->fw_lro_aborts = rsp_rstats->fw_lro_aborts;
1349 rstats->fw_lro_aborts_port = rsp_rstats->fw_lro_aborts_port;
1350 rstats->fw_lro_aborts_seq = rsp_rstats->fw_lro_aborts_seq;
1351 rstats->fw_lro_aborts_tsval = rsp_rstats->fw_lro_aborts_tsval;
1352 rstats->fw_lro_aborts_timer = rsp_rstats->fw_lro_aborts_timer;
1353 /* intrmod: packet forward rate */
1354 rstats->fwd_rate = rsp_rstats->fwd_rate;
1355
1356 /* TX link-level stats */
1357 tstats->total_pkts_sent = rsp_tstats->total_pkts_sent;
1358 tstats->total_bytes_sent = rsp_tstats->total_bytes_sent;
1359 tstats->mcast_pkts_sent = rsp_tstats->mcast_pkts_sent;
1360 tstats->bcast_pkts_sent = rsp_tstats->bcast_pkts_sent;
1361 tstats->ctl_sent = rsp_tstats->ctl_sent;
1362 /* Packets sent after one collision */
1363 tstats->one_collision_sent = rsp_tstats->one_collision_sent;
1364 /* Packets sent after multiple collision */
1365 tstats->multi_collision_sent = rsp_tstats->multi_collision_sent;
1366 /* Packets not sent due to max collisions */
1367 tstats->max_collision_fail = rsp_tstats->max_collision_fail;
1368 /* Packets not sent due to max deferrals */
1369 tstats->max_deferral_fail = rsp_tstats->max_deferral_fail;
1370 /* Accounts for over/under-run of buffers */
1371 tstats->fifo_err = rsp_tstats->fifo_err;
1372 tstats->runts = rsp_tstats->runts;
1373 /* Total number of collisions detected */
1374 tstats->total_collisions = rsp_tstats->total_collisions;
1375
1376 /* firmware stats */
1377 tstats->fw_total_sent = rsp_tstats->fw_total_sent;
1378 tstats->fw_total_fwd = rsp_tstats->fw_total_fwd;
1379 tstats->fw_err_pko = rsp_tstats->fw_err_pko;
1380 tstats->fw_err_pki = rsp_tstats->fw_err_pki;
1381 tstats->fw_err_link = rsp_tstats->fw_err_link;
1382 tstats->fw_err_drop = rsp_tstats->fw_err_drop;
1383 tstats->fw_tso = rsp_tstats->fw_tso;
1384 tstats->fw_tso_fwd = rsp_tstats->fw_tso_fwd;
1385 tstats->fw_err_tso = rsp_tstats->fw_err_tso;
1386 tstats->fw_tx_vxlan = rsp_tstats->fw_tx_vxlan;
1387 }
1388 lio_free_soft_command(oct_dev, sc);
1389 callout_schedule(&lio->stats_timer,
1390 lio_ms_to_ticks(lio->stats_interval));
1391 }
1392
1393 /* Configure interrupt moderation parameters */
1394 static void
lio_get_fw_stats(void * arg)1395 lio_get_fw_stats(void *arg)
1396 {
1397 struct lio *lio = arg;
1398 struct octeon_device *oct_dev = lio->oct_dev;
1399 struct lio_soft_command *sc;
1400 struct lio_fw_stats_resp *resp;
1401 int retval;
1402
1403 if (callout_pending(&lio->stats_timer) ||
1404 callout_active(&lio->stats_timer) == 0)
1405 return;
1406
1407 /* Alloc soft command */
1408 sc = lio_alloc_soft_command(oct_dev, 0,
1409 sizeof(struct lio_fw_stats_resp), 0);
1410
1411 if (sc == NULL)
1412 goto alloc_sc_failed;
1413
1414 resp = (struct lio_fw_stats_resp *)sc->virtrptr;
1415 bzero(resp, sizeof(struct lio_fw_stats_resp));
1416
1417 sc->iq_no = lio->linfo.txpciq[0].s.q_no;
1418
1419 lio_prepare_soft_command(oct_dev, sc, LIO_OPCODE_NIC,
1420 LIO_OPCODE_NIC_PORT_STATS, 0, 0, 0);
1421
1422 sc->callback = lio_fw_stats_callback;
1423 sc->callback_arg = sc;
1424 sc->wait_time = 500; /* in milli seconds */
1425
1426 retval = lio_send_soft_command(oct_dev, sc);
1427 if (retval == LIO_IQ_SEND_FAILED)
1428 goto send_sc_failed;
1429
1430 return;
1431
1432 send_sc_failed:
1433 lio_free_soft_command(oct_dev, sc);
1434 alloc_sc_failed:
1435 callout_schedule(&lio->stats_timer,
1436 lio_ms_to_ticks(lio->stats_interval));
1437 }
1438
1439 /* Callback function for intrmod */
1440 static void
lio_get_intrmod_callback(struct octeon_device * oct_dev,uint32_t status,void * ptr)1441 lio_get_intrmod_callback(struct octeon_device *oct_dev, uint32_t status,
1442 void *ptr)
1443 {
1444 struct lio_soft_command *sc = (struct lio_soft_command *)ptr;
1445 if_t ifp = oct_dev->props.ifp;
1446 struct lio *lio = if_getsoftc(ifp);
1447 struct lio_intrmod_resp *resp;
1448
1449 if (status) {
1450 lio_dev_err(oct_dev, "Failed to get intrmod\n");
1451 } else {
1452 resp = (struct lio_intrmod_resp *)sc->virtrptr;
1453 lio_swap_8B_data((uint64_t *)&resp->intrmod,
1454 (sizeof(struct octeon_intrmod_cfg)) / 8);
1455 memcpy(&lio->intrmod_cfg, &resp->intrmod,
1456 sizeof(struct octeon_intrmod_cfg));
1457 }
1458
1459 lio_free_soft_command(oct_dev, sc);
1460 }
1461
1462 /* get interrupt moderation parameters */
1463 static int
lio_get_intrmod_cfg(struct lio * lio,struct octeon_intrmod_cfg * intr_cfg)1464 lio_get_intrmod_cfg(struct lio *lio, struct octeon_intrmod_cfg *intr_cfg)
1465 {
1466 struct lio_soft_command *sc;
1467 struct lio_intrmod_resp *resp;
1468 struct octeon_device *oct_dev = lio->oct_dev;
1469 int retval;
1470
1471 /* Alloc soft command */
1472 sc = lio_alloc_soft_command(oct_dev, 0, sizeof(struct lio_intrmod_resp),
1473 0);
1474
1475 if (sc == NULL)
1476 return (ENOMEM);
1477
1478 resp = (struct lio_intrmod_resp *)sc->virtrptr;
1479 bzero(resp, sizeof(struct lio_intrmod_resp));
1480 sc->iq_no = lio->linfo.txpciq[0].s.q_no;
1481
1482 lio_prepare_soft_command(oct_dev, sc, LIO_OPCODE_NIC,
1483 LIO_OPCODE_NIC_INTRMOD_PARAMS, 0, 0, 0);
1484
1485 sc->callback = lio_get_intrmod_callback;
1486 sc->callback_arg = sc;
1487 sc->wait_time = 1000;
1488
1489 retval = lio_send_soft_command(oct_dev, sc);
1490 if (retval == LIO_IQ_SEND_FAILED) {
1491 lio_free_soft_command(oct_dev, sc);
1492 return (EINVAL);
1493 }
1494
1495 return (0);
1496 }
1497
1498 static void
lio_set_intrmod_callback(struct octeon_device * oct_dev,uint32_t status,void * ptr)1499 lio_set_intrmod_callback(struct octeon_device *oct_dev, uint32_t status,
1500 void *ptr)
1501 {
1502 struct lio_soft_command *sc = (struct lio_soft_command *)ptr;
1503 struct lio_intrmod_context *ctx;
1504
1505 ctx = (struct lio_intrmod_context *)sc->ctxptr;
1506
1507 ctx->status = status;
1508
1509 ctx->cond = 1;
1510
1511 /*
1512 * This barrier is required to be sure that the response has been
1513 * written fully before waking up the handler
1514 */
1515 wmb();
1516 }
1517
1518 /* Configure interrupt moderation parameters */
1519 static int
lio_set_intrmod_cfg(struct lio * lio,struct octeon_intrmod_cfg * intr_cfg)1520 lio_set_intrmod_cfg(struct lio *lio, struct octeon_intrmod_cfg *intr_cfg)
1521 {
1522 struct lio_soft_command *sc;
1523 struct lio_intrmod_context *ctx;
1524 struct octeon_intrmod_cfg *cfg;
1525 struct octeon_device *oct_dev = lio->oct_dev;
1526 int retval;
1527
1528 /* Alloc soft command */
1529 sc = lio_alloc_soft_command(oct_dev, sizeof(struct octeon_intrmod_cfg),
1530 0, sizeof(struct lio_intrmod_context));
1531
1532 if (sc == NULL)
1533 return (ENOMEM);
1534
1535 ctx = (struct lio_intrmod_context *)sc->ctxptr;
1536
1537 ctx->cond = 0;
1538 ctx->octeon_id = lio_get_device_id(oct_dev);
1539
1540 cfg = (struct octeon_intrmod_cfg *)sc->virtdptr;
1541
1542 memcpy(cfg, intr_cfg, sizeof(struct octeon_intrmod_cfg));
1543 lio_swap_8B_data((uint64_t *)cfg,
1544 (sizeof(struct octeon_intrmod_cfg)) / 8);
1545
1546 sc->iq_no = lio->linfo.txpciq[0].s.q_no;
1547
1548 lio_prepare_soft_command(oct_dev, sc, LIO_OPCODE_NIC,
1549 LIO_OPCODE_NIC_INTRMOD_CFG, 0, 0, 0);
1550
1551 sc->callback = lio_set_intrmod_callback;
1552 sc->callback_arg = sc;
1553 sc->wait_time = 1000;
1554
1555 retval = lio_send_soft_command(oct_dev, sc);
1556 if (retval == LIO_IQ_SEND_FAILED) {
1557 lio_free_soft_command(oct_dev, sc);
1558 return (EINVAL);
1559 }
1560
1561 /*
1562 * Sleep on a wait queue till the cond flag indicates that the
1563 * response arrived or timed-out.
1564 */
1565 lio_sleep_cond(oct_dev, &ctx->cond);
1566
1567 retval = ctx->status;
1568 if (retval)
1569 lio_dev_err(oct_dev, "intrmod config failed. Status: %llx\n",
1570 LIO_CAST64(retval));
1571 else
1572 lio_dev_info(oct_dev, "Rx-Adaptive Interrupt moderation enabled:%llx\n",
1573 LIO_CAST64(intr_cfg->rx_enable));
1574
1575 lio_free_soft_command(oct_dev, sc);
1576
1577 return ((retval) ? ETIMEDOUT : 0);
1578 }
1579
1580 static int
lio_intrmod_cfg_rx_intrcnt(struct lio * lio,struct octeon_intrmod_cfg * intrmod,uint32_t rx_max_frames)1581 lio_intrmod_cfg_rx_intrcnt(struct lio *lio, struct octeon_intrmod_cfg *intrmod,
1582 uint32_t rx_max_frames)
1583 {
1584 struct octeon_device *oct = lio->oct_dev;
1585 uint32_t rx_max_coalesced_frames;
1586
1587 /* Config Cnt based interrupt values */
1588 switch (oct->chip_id) {
1589 case LIO_CN23XX_PF_VID:{
1590 int q_no;
1591
1592 if (!rx_max_frames)
1593 rx_max_coalesced_frames = intrmod->rx_frames;
1594 else
1595 rx_max_coalesced_frames = rx_max_frames;
1596
1597 for (q_no = 0; q_no < oct->num_oqs; q_no++) {
1598 q_no += oct->sriov_info.pf_srn;
1599 lio_write_csr64(oct,
1600 LIO_CN23XX_SLI_OQ_PKT_INT_LEVELS(q_no),
1601 (lio_read_csr64(oct,
1602 LIO_CN23XX_SLI_OQ_PKT_INT_LEVELS(q_no)) &
1603 (0x3fffff00000000UL)) |
1604 (rx_max_coalesced_frames - 1));
1605 /* consider setting resend bit */
1606 }
1607
1608 intrmod->rx_frames = rx_max_coalesced_frames;
1609 oct->rx_max_coalesced_frames = rx_max_coalesced_frames;
1610 break;
1611 }
1612 default:
1613 return (EINVAL);
1614 }
1615 return (0);
1616 }
1617
1618 static int
lio_intrmod_cfg_rx_intrtime(struct lio * lio,struct octeon_intrmod_cfg * intrmod,uint32_t rx_usecs)1619 lio_intrmod_cfg_rx_intrtime(struct lio *lio, struct octeon_intrmod_cfg *intrmod,
1620 uint32_t rx_usecs)
1621 {
1622 struct octeon_device *oct = lio->oct_dev;
1623 uint32_t rx_coalesce_usecs;
1624
1625 /* Config Time based interrupt values */
1626 switch (oct->chip_id) {
1627 case LIO_CN23XX_PF_VID:{
1628 uint64_t time_threshold;
1629 int q_no;
1630
1631 if (!rx_usecs)
1632 rx_coalesce_usecs = intrmod->rx_usecs;
1633 else
1634 rx_coalesce_usecs = rx_usecs;
1635
1636 time_threshold =
1637 lio_cn23xx_pf_get_oq_ticks(oct, rx_coalesce_usecs);
1638 for (q_no = 0; q_no < oct->num_oqs; q_no++) {
1639 q_no += oct->sriov_info.pf_srn;
1640 lio_write_csr64(oct,
1641 LIO_CN23XX_SLI_OQ_PKT_INT_LEVELS(q_no),
1642 (intrmod->rx_frames |
1643 ((uint64_t)time_threshold << 32)));
1644 /* consider writing to resend bit here */
1645 }
1646
1647 intrmod->rx_usecs = rx_coalesce_usecs;
1648 oct->rx_coalesce_usecs = rx_coalesce_usecs;
1649 break;
1650 }
1651 default:
1652 return (EINVAL);
1653 }
1654
1655 return (0);
1656 }
1657
1658 static int
lio_intrmod_cfg_tx_intrcnt(struct lio * lio,struct octeon_intrmod_cfg * intrmod,uint32_t tx_max_frames)1659 lio_intrmod_cfg_tx_intrcnt(struct lio *lio, struct octeon_intrmod_cfg *intrmod,
1660 uint32_t tx_max_frames)
1661 {
1662 struct octeon_device *oct = lio->oct_dev;
1663 uint64_t val;
1664 uint32_t iq_intr_pkt;
1665 uint32_t inst_cnt_reg;
1666
1667 /* Config Cnt based interrupt values */
1668 switch (oct->chip_id) {
1669 case LIO_CN23XX_PF_VID:{
1670 int q_no;
1671
1672 if (!tx_max_frames)
1673 iq_intr_pkt = LIO_CN23XX_DEF_IQ_INTR_THRESHOLD &
1674 LIO_CN23XX_PKT_IN_DONE_WMARK_MASK;
1675 else
1676 iq_intr_pkt = tx_max_frames &
1677 LIO_CN23XX_PKT_IN_DONE_WMARK_MASK;
1678 for (q_no = 0; q_no < oct->num_iqs; q_no++) {
1679 inst_cnt_reg =
1680 (oct->instr_queue[q_no])->inst_cnt_reg;
1681 val = lio_read_csr64(oct, inst_cnt_reg);
1682 /*
1683 * clear wmark and count.dont want to write
1684 * count back
1685 */
1686 val = (val & 0xFFFF000000000000ULL) |
1687 ((uint64_t)(iq_intr_pkt - 1)
1688 << LIO_CN23XX_PKT_IN_DONE_WMARK_BIT_POS);
1689 lio_write_csr64(oct, inst_cnt_reg, val);
1690 /* consider setting resend bit */
1691 }
1692
1693 intrmod->tx_frames = iq_intr_pkt;
1694 oct->tx_max_coalesced_frames = iq_intr_pkt;
1695 break;
1696 }
1697 default:
1698 return (-EINVAL);
1699 }
1700 return (0);
1701 }
1702
1703 static int
lio_get_set_intr_coalesce(SYSCTL_HANDLER_ARGS)1704 lio_get_set_intr_coalesce(SYSCTL_HANDLER_ARGS)
1705 {
1706 struct lio *lio = (struct lio *)arg1;
1707 struct octeon_device *oct = lio->oct_dev;
1708 uint64_t new_val = 0, old_val = 0;
1709 uint32_t rx_coalesce_usecs = 0;
1710 uint32_t rx_max_coalesced_frames = 0;
1711 uint32_t tx_coalesce_usecs = 0;
1712 int err, ret;
1713
1714 switch (arg2) {
1715 case LIO_USE_ADAPTIVE_RX_COALESCE:
1716 if (lio->intrmod_cfg.rx_enable)
1717 new_val = old_val = lio->intrmod_cfg.rx_enable;
1718
1719 err = sysctl_handle_64(oidp, &new_val, 0, req);
1720 if ((err) || (req->newptr == NULL))
1721 return (err);
1722
1723 if (old_val == new_val)
1724 return (0);
1725
1726 lio->intrmod_cfg.rx_enable = new_val ? 1 : 0;
1727 break;
1728
1729 case LIO_USE_ADAPTIVE_TX_COALESCE:
1730 if (lio->intrmod_cfg.tx_enable)
1731 new_val = old_val = lio->intrmod_cfg.tx_enable;
1732
1733 err = sysctl_handle_64(oidp, &new_val, 0, req);
1734 if ((err) || (req->newptr == NULL))
1735 return (err);
1736
1737 if (old_val == new_val)
1738 return (0);
1739
1740 lio->intrmod_cfg.tx_enable = new_val ? 1 : 0;
1741 break;
1742
1743 case LIO_RX_COALESCE_USECS:
1744 if (!lio->intrmod_cfg.rx_enable)
1745 new_val = old_val = oct->rx_coalesce_usecs;
1746
1747 err = sysctl_handle_64(oidp, &new_val, 0, req);
1748 if ((err) || (req->newptr == NULL))
1749 return (err);
1750
1751 if (old_val == new_val)
1752 return (0);
1753
1754 rx_coalesce_usecs = new_val;
1755 break;
1756
1757 case LIO_RX_MAX_COALESCED_FRAMES:
1758 if (!lio->intrmod_cfg.rx_enable)
1759 new_val = old_val = oct->rx_max_coalesced_frames;
1760
1761 err = sysctl_handle_64(oidp, &new_val, 0, req);
1762 if ((err) || (req->newptr == NULL))
1763 return (err);
1764
1765 if (old_val == new_val)
1766 return (0);
1767
1768 rx_max_coalesced_frames = new_val;
1769 break;
1770
1771 case LIO_TX_MAX_COALESCED_FRAMES:
1772 if (!lio->intrmod_cfg.tx_enable)
1773 new_val = old_val = oct->tx_max_coalesced_frames;
1774
1775 err = sysctl_handle_64(oidp, &new_val, 0, req);
1776 if ((err) || (req->newptr == NULL))
1777 return (err);
1778
1779 if (old_val == new_val)
1780 return (0);
1781
1782 tx_coalesce_usecs = new_val;
1783 break;
1784
1785 case LIO_PKT_RATE_LOW:
1786 if (lio->intrmod_cfg.rx_enable)
1787 new_val = old_val = lio->intrmod_cfg.minpkt_ratethr;
1788
1789 err = sysctl_handle_64(oidp, &new_val, 0, req);
1790 if ((err) || (req->newptr == NULL))
1791 return (err);
1792
1793 if (old_val == new_val)
1794 return (0);
1795
1796 if (lio->intrmod_cfg.rx_enable || lio->intrmod_cfg.tx_enable)
1797 lio->intrmod_cfg.minpkt_ratethr = new_val;
1798 break;
1799
1800 case LIO_RX_COALESCE_USECS_LOW:
1801 if (lio->intrmod_cfg.rx_enable)
1802 new_val = old_val = lio->intrmod_cfg.rx_mintmr_trigger;
1803
1804 err = sysctl_handle_64(oidp, &new_val, 0, req);
1805 if ((err) || (req->newptr == NULL))
1806 return (err);
1807
1808 if (old_val == new_val)
1809 return (0);
1810
1811 if (lio->intrmod_cfg.rx_enable)
1812 lio->intrmod_cfg.rx_mintmr_trigger = new_val;
1813 break;
1814
1815 case LIO_RX_MAX_COALESCED_FRAMES_LOW:
1816 if (lio->intrmod_cfg.rx_enable)
1817 new_val = old_val = lio->intrmod_cfg.rx_mincnt_trigger;
1818
1819 err = sysctl_handle_64(oidp, &new_val, 0, req);
1820 if ((err) || (req->newptr == NULL))
1821 return (err);
1822
1823 if (old_val == new_val)
1824 return (0);
1825
1826 if (lio->intrmod_cfg.rx_enable)
1827 lio->intrmod_cfg.rx_mincnt_trigger = new_val;
1828 break;
1829
1830 case LIO_TX_MAX_COALESCED_FRAMES_LOW:
1831 if (lio->intrmod_cfg.tx_enable)
1832 new_val = old_val = lio->intrmod_cfg.tx_mincnt_trigger;
1833
1834 err = sysctl_handle_64(oidp, &new_val, 0, req);
1835 if ((err) || (req->newptr == NULL))
1836 return (err);
1837
1838 if (old_val == new_val)
1839 return (0);
1840
1841 if (lio->intrmod_cfg.tx_enable)
1842 lio->intrmod_cfg.tx_mincnt_trigger = new_val;
1843 break;
1844
1845 case LIO_PKT_RATE_HIGH:
1846 if (lio->intrmod_cfg.rx_enable)
1847 new_val = old_val = lio->intrmod_cfg.maxpkt_ratethr;
1848
1849 err = sysctl_handle_64(oidp, &new_val, 0, req);
1850 if ((err) || (req->newptr == NULL))
1851 return (err);
1852
1853 if (old_val == new_val)
1854 return (0);
1855
1856 if (lio->intrmod_cfg.rx_enable || lio->intrmod_cfg.tx_enable)
1857 lio->intrmod_cfg.maxpkt_ratethr = new_val;
1858 break;
1859
1860 case LIO_RX_COALESCE_USECS_HIGH:
1861 if (lio->intrmod_cfg.rx_enable)
1862 new_val = old_val = lio->intrmod_cfg.rx_maxtmr_trigger;
1863
1864 err = sysctl_handle_64(oidp, &new_val, 0, req);
1865 if ((err) || (req->newptr == NULL))
1866 return (err);
1867
1868 if (old_val == new_val)
1869 return (0);
1870
1871 if (lio->intrmod_cfg.rx_enable)
1872 lio->intrmod_cfg.rx_maxtmr_trigger = new_val;
1873 break;
1874
1875 case LIO_RX_MAX_COALESCED_FRAMES_HIGH:
1876 if (lio->intrmod_cfg.rx_enable)
1877 new_val = old_val = lio->intrmod_cfg.rx_maxcnt_trigger;
1878
1879 err = sysctl_handle_64(oidp, &new_val, 0, req);
1880 if ((err) || (req->newptr == NULL))
1881 return (err);
1882
1883 if (old_val == new_val)
1884 return (0);
1885
1886 if (lio->intrmod_cfg.rx_enable)
1887 lio->intrmod_cfg.rx_maxcnt_trigger = new_val;
1888 break;
1889
1890 case LIO_TX_MAX_COALESCED_FRAMES_HIGH:
1891 if (lio->intrmod_cfg.tx_enable)
1892 new_val = old_val = lio->intrmod_cfg.tx_maxcnt_trigger;
1893
1894 err = sysctl_handle_64(oidp, &new_val, 0, req);
1895 if ((err) || (req->newptr == NULL))
1896 return (err);
1897
1898 if (old_val == new_val)
1899 return (0);
1900
1901 if (lio->intrmod_cfg.tx_enable)
1902 lio->intrmod_cfg.tx_maxcnt_trigger = new_val;
1903 break;
1904
1905 case LIO_RATE_SAMPLE_INTERVAL:
1906 if (lio->intrmod_cfg.rx_enable)
1907 new_val = old_val = lio->intrmod_cfg.check_intrvl;
1908
1909 err = sysctl_handle_64(oidp, &new_val, 0, req);
1910 if ((err) || (req->newptr == NULL))
1911 return (err);
1912
1913 if (old_val == new_val)
1914 return (0);
1915
1916 if (lio->intrmod_cfg.rx_enable || lio->intrmod_cfg.tx_enable)
1917 lio->intrmod_cfg.check_intrvl = new_val;
1918 break;
1919
1920 default:
1921 return (EINVAL);
1922 }
1923
1924 lio->intrmod_cfg.rx_usecs = LIO_GET_OQ_INTR_TIME_CFG(lio_get_conf(oct));
1925 lio->intrmod_cfg.rx_frames = LIO_GET_OQ_INTR_PKT_CFG(lio_get_conf(oct));
1926 lio->intrmod_cfg.tx_frames = LIO_GET_IQ_INTR_PKT_CFG(lio_get_conf(oct));
1927
1928 ret = lio_set_intrmod_cfg(lio, &lio->intrmod_cfg);
1929 if (ret)
1930 lio_dev_err(oct, "Interrupt coalescing updation to Firmware failed!\n");
1931
1932 if (!lio->intrmod_cfg.rx_enable) {
1933 if (!rx_coalesce_usecs)
1934 rx_coalesce_usecs = oct->rx_coalesce_usecs;
1935
1936 if (!rx_max_coalesced_frames)
1937 rx_max_coalesced_frames = oct->rx_max_coalesced_frames;
1938
1939 ret = lio_intrmod_cfg_rx_intrtime(lio, &lio->intrmod_cfg,
1940 rx_coalesce_usecs);
1941 if (ret)
1942 return (ret);
1943
1944 ret = lio_intrmod_cfg_rx_intrcnt(lio, &lio->intrmod_cfg,
1945 rx_max_coalesced_frames);
1946 if (ret)
1947 return (ret);
1948 } else {
1949 oct->rx_coalesce_usecs =
1950 LIO_GET_OQ_INTR_TIME_CFG(lio_get_conf(oct));
1951 oct->rx_max_coalesced_frames =
1952 LIO_GET_OQ_INTR_PKT_CFG(lio_get_conf(oct));
1953 }
1954
1955 if (!lio->intrmod_cfg.tx_enable) {
1956 if (!tx_coalesce_usecs)
1957 tx_coalesce_usecs = oct->tx_max_coalesced_frames;
1958
1959 ret = lio_intrmod_cfg_tx_intrcnt(lio, &lio->intrmod_cfg,
1960 tx_coalesce_usecs);
1961 if (ret)
1962 return (ret);
1963 } else {
1964 oct->tx_max_coalesced_frames =
1965 LIO_GET_IQ_INTR_PKT_CFG(lio_get_conf(oct));
1966 }
1967
1968 return (0);
1969 }
1970