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