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 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
lio_cn23xx_pf_read_csr_reg(char * s,struct octeon_device * oct)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
lio_get_ringparam(SYSCTL_HANDLER_ARGS)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
lio_reset_queues(if_t ifp,uint32_t num_qs)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
lio_set_ringparam(SYSCTL_HANDLER_ARGS)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
lio_get_channels(SYSCTL_HANDLER_ARGS)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
lio_irq_reallocate_irqs(struct octeon_device * oct,uint32_t num_ioqs)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
lio_set_channels(SYSCTL_HANDLER_ARGS)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
lio_get_set_fwmsglevel(SYSCTL_HANDLER_ARGS)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
lio_set_stats_interval(SYSCTL_HANDLER_ARGS)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
lio_fw_stats_callback(struct octeon_device * oct_dev,uint32_t status,void * ptr)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
lio_get_fw_stats(void * arg)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
lio_get_intrmod_callback(struct octeon_device * oct_dev,uint32_t status,void * ptr)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
lio_get_intrmod_cfg(struct lio * lio,struct octeon_intrmod_cfg * intr_cfg)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
lio_set_intrmod_callback(struct octeon_device * oct_dev,uint32_t status,void * ptr)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
lio_set_intrmod_cfg(struct lio * lio,struct octeon_intrmod_cfg * intr_cfg)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
lio_intrmod_cfg_rx_intrcnt(struct lio * lio,struct octeon_intrmod_cfg * intrmod,uint32_t rx_max_frames)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
lio_intrmod_cfg_rx_intrtime(struct lio * lio,struct octeon_intrmod_cfg * intrmod,uint32_t rx_usecs)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
lio_intrmod_cfg_tx_intrcnt(struct lio * lio,struct octeon_intrmod_cfg * intrmod,uint32_t tx_max_frames)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
lio_get_set_intr_coalesce(SYSCTL_HANDLER_ARGS)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 }
1973