1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2020 Advanced Micro Devices, Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * Contact Information :
28 * Rajesh Kumar <rajesh1.kumar@amd.com>
29 * Arpan Palit <Arpan.Palit@amd.com>
30 */
31
32 #include <sys/param.h>
33 #include <sys/sysctl.h>
34 #include <sys/sbuf.h>
35
36 #include "xgbe.h"
37 #include "xgbe-common.h"
38
39 #define SYSCTL_BUF_LEN 64
40
41 typedef enum{
42 /* Coalesce flag */
43 rx_coalesce_usecs = 1,
44 rx_max_coalesced_frames,
45 rx_coalesce_usecs_irq,
46 rx_max_coalesced_frames_irq,
47 tx_coalesce_usecs,
48 tx_max_coalesced_frames,
49 tx_coalesce_usecs_irq,
50 tx_max_coalesced_frames_irq,
51 stats_block_coalesce_usecs,
52 use_adaptive_rx_coalesce,
53 use_adaptive_tx_coalesce,
54 pkt_rate_low,
55 rx_coalesce_usecs_low,
56 rx_max_coalesced_frames_low,
57 tx_coalesce_usecs_low,
58 tx_max_coalesced_frames_low,
59 pkt_rate_high,
60 rx_coalesce_usecs_high,
61 rx_max_coalesced_frames_high,
62 tx_coalesce_usecs_high,
63 tx_max_coalesced_frames_high,
64 rate_sample_interval,
65
66 /* Pasue flag */
67 autoneg,
68 tx_pause,
69 rx_pause,
70
71 /* link settings */
72 speed,
73 duplex,
74
75 /* Ring settings */
76 rx_pending,
77 rx_mini_pending,
78 rx_jumbo_pending,
79 tx_pending,
80
81 /* Channels settings */
82 rx_count,
83 tx_count,
84 other_count,
85 combined_count,
86 } sysctl_variable_t;
87
88 typedef enum {
89 SYSL_NONE,
90 SYSL_BOOL,
91 SYSL_S32,
92 SYSL_U8,
93 SYSL_U16,
94 SYSL_U32,
95 SYSL_U64,
96 SYSL_BE16,
97 SYSL_IP4,
98 SYSL_STR,
99 SYSL_FLAG,
100 SYSL_MAC,
101 } sysctl_type_t;
102
103 struct sysctl_info {
104 uint8_t name[32];
105 sysctl_type_t type;
106 sysctl_variable_t flag;
107 uint8_t support[16];
108 };
109
110 struct sysctl_op {
111 /* Coalesce options */
112 unsigned int rx_coalesce_usecs;
113 unsigned int rx_max_coalesced_frames;
114 unsigned int rx_coalesce_usecs_irq;
115 unsigned int rx_max_coalesced_frames_irq;
116 unsigned int tx_coalesce_usecs;
117 unsigned int tx_max_coalesced_frames;
118 unsigned int tx_coalesce_usecs_irq;
119 unsigned int tx_max_coalesced_frames_irq;
120 unsigned int stats_block_coalesce_usecs;
121 unsigned int use_adaptive_rx_coalesce;
122 unsigned int use_adaptive_tx_coalesce;
123 unsigned int pkt_rate_low;
124 unsigned int rx_coalesce_usecs_low;
125 unsigned int rx_max_coalesced_frames_low;
126 unsigned int tx_coalesce_usecs_low;
127 unsigned int tx_max_coalesced_frames_low;
128 unsigned int pkt_rate_high;
129 unsigned int rx_coalesce_usecs_high;
130 unsigned int rx_max_coalesced_frames_high;
131 unsigned int tx_coalesce_usecs_high;
132 unsigned int tx_max_coalesced_frames_high;
133 unsigned int rate_sample_interval;
134
135 /* Pasue options */
136 unsigned int autoneg;
137 unsigned int tx_pause;
138 unsigned int rx_pause;
139
140 /* Link settings options */
141 unsigned int speed;
142 unsigned int duplex;
143
144 /* Ring param options */
145 unsigned int rx_max_pending;
146 unsigned int rx_mini_max_pending;
147 unsigned int rx_jumbo_max_pending;
148 unsigned int tx_max_pending;
149 unsigned int rx_pending;
150 unsigned int rx_mini_pending;
151 unsigned int rx_jumbo_pending;
152 unsigned int tx_pending;
153
154 /* Channels options */
155 unsigned int max_rx;
156 unsigned int max_tx;
157 unsigned int max_other;
158 unsigned int max_combined;
159 unsigned int rx_count;
160 unsigned int tx_count;
161 unsigned int other_count;
162 unsigned int combined_count;
163 } sys_op;
164
165 #define GSTRING_LEN 32
166
167 struct xgbe_stats {
168 char stat_string[GSTRING_LEN];
169 int stat_size;
170 int stat_offset;
171 };
172
173 #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
174
175 #define XGMAC_MMC_STAT(_string, _var) \
176 { _string, \
177 FIELD_SIZEOF(struct xgbe_mmc_stats, _var), \
178 offsetof(struct xgbe_prv_data, mmc_stats._var), \
179 }
180
181 #define XGMAC_EXT_STAT(_string, _var) \
182 { _string, \
183 FIELD_SIZEOF(struct xgbe_ext_stats, _var), \
184 offsetof(struct xgbe_prv_data, ext_stats._var), \
185 }
186 static const struct xgbe_stats xgbe_gstring_stats[] = {
187 XGMAC_MMC_STAT("tx_bytes", txoctetcount_gb),
188 XGMAC_MMC_STAT("tx_packets", txframecount_gb),
189 XGMAC_MMC_STAT("tx_unicast_packets", txunicastframes_gb),
190 XGMAC_MMC_STAT("tx_broadcast_packets", txbroadcastframes_gb),
191 XGMAC_MMC_STAT("tx_multicast_packets", txmulticastframes_gb),
192 XGMAC_MMC_STAT("tx_vlan_packets", txvlanframes_g),
193 XGMAC_EXT_STAT("tx_vxlan_packets", tx_vxlan_packets),
194 XGMAC_EXT_STAT("tx_tso_packets", tx_tso_packets),
195 XGMAC_MMC_STAT("tx_64_byte_packets", tx64octets_gb),
196 XGMAC_MMC_STAT("tx_65_to_127_byte_packets", tx65to127octets_gb),
197 XGMAC_MMC_STAT("tx_128_to_255_byte_packets", tx128to255octets_gb),
198 XGMAC_MMC_STAT("tx_256_to_511_byte_packets", tx256to511octets_gb),
199 XGMAC_MMC_STAT("tx_512_to_1023_byte_packets", tx512to1023octets_gb),
200 XGMAC_MMC_STAT("tx_1024_to_max_byte_packets", tx1024tomaxoctets_gb),
201 XGMAC_MMC_STAT("tx_underflow_errors", txunderflowerror),
202 XGMAC_MMC_STAT("tx_pause_frames", txpauseframes),
203
204 XGMAC_MMC_STAT("rx_bytes", rxoctetcount_gb),
205 XGMAC_MMC_STAT("rx_packets", rxframecount_gb),
206 XGMAC_MMC_STAT("rx_unicast_packets", rxunicastframes_g),
207 XGMAC_MMC_STAT("rx_broadcast_packets", rxbroadcastframes_g),
208 XGMAC_MMC_STAT("rx_multicast_packets", rxmulticastframes_g),
209 XGMAC_MMC_STAT("rx_vlan_packets", rxvlanframes_gb),
210 XGMAC_EXT_STAT("rx_vxlan_packets", rx_vxlan_packets),
211 XGMAC_MMC_STAT("rx_64_byte_packets", rx64octets_gb),
212 XGMAC_MMC_STAT("rx_65_to_127_byte_packets", rx65to127octets_gb),
213 XGMAC_MMC_STAT("rx_128_to_255_byte_packets", rx128to255octets_gb),
214 XGMAC_MMC_STAT("rx_256_to_511_byte_packets", rx256to511octets_gb),
215 XGMAC_MMC_STAT("rx_512_to_1023_byte_packets", rx512to1023octets_gb),
216 XGMAC_MMC_STAT("rx_1024_to_max_byte_packets", rx1024tomaxoctets_gb),
217 XGMAC_MMC_STAT("rx_undersize_packets", rxundersize_g),
218 XGMAC_MMC_STAT("rx_oversize_packets", rxoversize_g),
219 XGMAC_MMC_STAT("rx_crc_errors", rxcrcerror),
220 XGMAC_MMC_STAT("rx_crc_errors_small_packets", rxrunterror),
221 XGMAC_MMC_STAT("rx_crc_errors_giant_packets", rxjabbererror),
222 XGMAC_MMC_STAT("rx_length_errors", rxlengtherror),
223 XGMAC_MMC_STAT("rx_out_of_range_errors", rxoutofrangetype),
224 XGMAC_MMC_STAT("rx_fifo_overflow_errors", rxfifooverflow),
225 XGMAC_MMC_STAT("rx_watchdog_errors", rxwatchdogerror),
226 XGMAC_EXT_STAT("rx_csum_errors", rx_csum_errors),
227 XGMAC_EXT_STAT("rx_vxlan_csum_errors", rx_vxlan_csum_errors),
228 XGMAC_MMC_STAT("rx_pause_frames", rxpauseframes),
229 XGMAC_EXT_STAT("rx_split_header_packets", rx_split_header_packets),
230 XGMAC_EXT_STAT("rx_buffer_unavailable", rx_buffer_unavailable),
231 };
232
233 #define XGBE_STATS_COUNT ARRAY_SIZE(xgbe_gstring_stats)
234
235 char** alloc_sysctl_buffer(void);
236 void get_val(char *buf, char **op, char **val, int *n_op);
237 void fill_data(struct sysctl_op *sys_op, int flag, unsigned int value);
238
239 static int
exit_bad_op(void)240 exit_bad_op(void)
241 {
242
243 printf("SYSCTL: bad command line option (s)\n");
244 return(-EINVAL);
245 }
246
247 static inline int
get_ubuf(struct sysctl_req * req,char * ubuf)248 get_ubuf(struct sysctl_req *req, char *ubuf)
249 {
250 int rc;
251
252 printf("%s: len:0x%li idx:0x%li\n", __func__, req->newlen,
253 req->newidx);
254 if (req->newlen >= SYSCTL_BUF_LEN)
255 return (-EINVAL);
256
257 rc = SYSCTL_IN(req, ubuf, req->newlen);
258 if (rc)
259 return (rc);
260 ubuf[req->newlen] = '\0';
261
262 return (0);
263 }
264
265 char**
alloc_sysctl_buffer(void)266 alloc_sysctl_buffer(void)
267 {
268 char **buffer;
269 int i;
270
271 buffer = malloc(sizeof(char *)*32, M_AXGBE, M_WAITOK | M_ZERO);
272 for(i = 0; i < 32; i++)
273 buffer[i] = malloc(sizeof(char)*32, M_AXGBE, M_WAITOK | M_ZERO);
274
275 return (buffer);
276 }
277
278 void
get_val(char * buf,char ** op,char ** val,int * n_op)279 get_val(char *buf, char **op, char **val, int *n_op)
280 {
281 int blen = strlen(buf);
282 int count = 0;
283 int i, j;
284
285 *n_op = 0;
286 for (i = 0; i < blen; i++) {
287 count++;
288 /* Get sysctl command option */
289 for (j = 0; buf[i] != ' '; j++) {
290 if (i >= blen)
291 break;
292 op[*n_op][j] = buf[i++];
293 }
294 op[*n_op][j+1] = '\0';
295 if (i >= strlen(buf))
296 goto out;
297
298 /* Get sysctl value*/
299 i++;
300 for (j = 0; buf[i] != ' '; j++) {
301 if (i >= blen)
302 break;
303 val[*n_op][j] = buf[i++];
304 }
305 val[*n_op][j+1] = '\0';
306 if (i >= strlen(buf))
307 goto out;
308
309 *n_op = count;
310 }
311
312 out:
313 *n_op = count;
314 }
315
316 void
fill_data(struct sysctl_op * sys_op,int flag,unsigned int value)317 fill_data(struct sysctl_op *sys_op, int flag, unsigned int value)
318 {
319
320 switch(flag) {
321 case 1:
322 sys_op->rx_coalesce_usecs = value;
323 break;
324 case 2:
325 sys_op->rx_max_coalesced_frames = value;
326 break;
327 case 3:
328 sys_op->rx_coalesce_usecs_irq = value;
329 break;
330 case 4:
331 sys_op->rx_max_coalesced_frames_irq = value;
332 break;
333 case 5:
334 sys_op->tx_coalesce_usecs = value;
335 break;
336 case 6:
337 sys_op->tx_max_coalesced_frames = value;
338 break;
339 case 7:
340 sys_op->tx_coalesce_usecs_irq = value;
341 break;
342 case 8:
343 sys_op->tx_max_coalesced_frames_irq = value;
344 break;
345 case 9:
346 sys_op->stats_block_coalesce_usecs = value;
347 break;
348 case 10:
349 sys_op->use_adaptive_rx_coalesce = value;
350 break;
351 case 11:
352 sys_op->use_adaptive_tx_coalesce = value;
353 break;
354 case 12:
355 sys_op->pkt_rate_low = value;
356 break;
357 case 13:
358 sys_op->rx_coalesce_usecs_low = value;
359 break;
360 case 14:
361 sys_op->rx_max_coalesced_frames_low = value;
362 break;
363 case 15:
364 sys_op->tx_coalesce_usecs_low = value;
365 break;
366 case 16:
367 sys_op->tx_max_coalesced_frames_low = value;
368 break;
369 case 17:
370 sys_op->pkt_rate_high = value;
371 break;
372 case 18:
373 sys_op->rx_coalesce_usecs_high = value;
374 break;
375 case 19:
376 sys_op->rx_max_coalesced_frames_high = value;
377 break;
378 case 20:
379 sys_op->tx_coalesce_usecs_high = value;
380 break;
381 case 21:
382 sys_op->tx_max_coalesced_frames_high = value;
383 break;
384 case 22:
385 sys_op->rate_sample_interval = value;
386 break;
387 case 23:
388 sys_op->autoneg = value;
389 break;
390 case 24:
391 sys_op->rx_pause = value;
392 break;
393 case 25:
394 sys_op->tx_pause = value;
395 break;
396 case 26:
397 sys_op->speed = value;
398 break;
399 case 27:
400 sys_op->duplex = value;
401 break;
402 case 28:
403 sys_op->rx_pending = value;
404 break;
405 case 29:
406 sys_op->rx_mini_pending = value;
407 break;
408 case 30:
409 sys_op->rx_jumbo_pending = value;
410 break;
411 case 31:
412 sys_op->tx_pending = value;
413 break;
414 default:
415 printf("Option error\n");
416 }
417 }
418
419 static int
parse_generic_sysctl(struct xgbe_prv_data * pdata,char * buf,struct sysctl_info * info,unsigned int n_info)420 parse_generic_sysctl(struct xgbe_prv_data *pdata, char *buf,
421 struct sysctl_info *info, unsigned int n_info)
422 {
423 struct sysctl_op *sys_op = pdata->sys_op;
424 unsigned int value;
425 char **op, **val;
426 int n_op = 0;
427 int rc = 0;
428 int i, idx;
429
430 op = alloc_sysctl_buffer();
431 val = alloc_sysctl_buffer();
432 get_val(buf, op, val, &n_op);
433
434 for (i = 0; i < n_op; i++) {
435 for (idx = 0; idx < n_info; idx++) {
436 if (strcmp(info[idx].name, op[i]) == 0) {
437 if (strcmp(info[idx].support,
438 "not-supported") == 0){
439 axgbe_printf(1, "ignoring not-supported "
440 "option \"%s\"\n", info[idx].name);
441 break;
442 }
443 switch(info[idx].type) {
444 case SYSL_BOOL: {
445 if (!strcmp(val[i], "on"))
446 fill_data(sys_op,
447 info[idx].flag, 1);
448 else if (!strcmp(val[i], "off"))
449 fill_data(sys_op,
450 info[idx].flag, 0);
451 else
452 rc = exit_bad_op();
453 break;
454 }
455 case SYSL_S32:
456 sscanf(val[i], "%u", &value);
457 fill_data(sys_op, info[idx].flag, value);
458 break;
459 case SYSL_U8:
460 if (!strcmp(val[i], "half"))
461 fill_data(sys_op,
462 info[idx].flag, DUPLEX_HALF);
463 else if (!strcmp(val[i], "full"))
464 fill_data(sys_op,
465 info[idx].flag, DUPLEX_FULL);
466 else
467 exit_bad_op();
468 default:
469 rc = exit_bad_op();
470 }
471 }
472 }
473 }
474
475 for(i = 0; i < 32; i++)
476 free(op[i], M_AXGBE);
477 free(op, M_AXGBE);
478
479 for(i = 0; i < 32; i++)
480 free(val[i], M_AXGBE);
481 free(val, M_AXGBE);
482 return (rc);
483 }
484
485
486 static int
sysctl_xgmac_reg_addr_handler(SYSCTL_HANDLER_ARGS)487 sysctl_xgmac_reg_addr_handler(SYSCTL_HANDLER_ARGS)
488 {
489 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1;
490 ssize_t buf_size = 64;
491 char buf[buf_size];
492 struct sbuf *sb;
493 unsigned int reg;
494 int rc = 0;
495
496 if (req->newptr == NULL) {
497 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
498 if (sb == NULL) {
499 rc = ENOMEM;
500 return (rc);
501 }
502
503 axgbe_printf(2, "READ: %s: sysctl_xgmac_reg: 0x%x\n", __func__,
504 pdata->sysctl_xgmac_reg);
505 sbuf_printf(sb, "\nXGMAC reg_addr: 0x%x\n",
506 pdata->sysctl_xgmac_reg);
507 rc = sbuf_finish(sb);
508 sbuf_delete(sb);
509 return (rc);
510 }
511
512 rc = get_ubuf(req, buf);
513 if (rc == 0) {
514 sscanf(buf, "%x", ®);
515 axgbe_printf(2, "WRITE: %s: reg: 0x%x\n", __func__, reg);
516 pdata->sysctl_xgmac_reg = reg;
517 }
518
519 axgbe_printf(2, "%s: rc= %d\n", __func__, rc);
520 return (rc);
521 }
522
523 static int
sysctl_get_drv_info_handler(SYSCTL_HANDLER_ARGS)524 sysctl_get_drv_info_handler(SYSCTL_HANDLER_ARGS)
525 {
526 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1;
527 struct xgbe_hw_features *hw_feat = &pdata->hw_feat;
528 ssize_t buf_size = 64;
529 struct sbuf *sb;
530 int rc = 0;
531
532 if (req->newptr == NULL) {
533 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
534 if (sb == NULL) {
535 rc = ENOMEM;
536 return (rc);
537 }
538
539 sbuf_printf(sb, "\ndriver: %s", XGBE_DRV_NAME);
540 sbuf_printf(sb, "\nversion: %s", XGBE_DRV_VERSION);
541 sbuf_printf(sb, "\nfirmware-version: %d.%d.%d",
542 XGMAC_GET_BITS(hw_feat->version, MAC_VR, USERVER),
543 XGMAC_GET_BITS(hw_feat->version, MAC_VR, DEVID),
544 XGMAC_GET_BITS(hw_feat->version, MAC_VR, SNPSVER));
545 sbuf_printf(sb, "\nbus-info: %04d:%02d:%02d",
546 pdata->pcie_bus, pdata->pcie_device, pdata->pcie_func);
547
548 rc = sbuf_finish(sb);
549 sbuf_delete(sb);
550 return (rc);
551 }
552
553 return (-EINVAL);
554 }
555
556 static int
sysctl_get_link_info_handler(SYSCTL_HANDLER_ARGS)557 sysctl_get_link_info_handler(SYSCTL_HANDLER_ARGS)
558 {
559 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1;
560 ssize_t buf_size = 64;
561 struct sbuf *sb;
562 int rc = 0;
563
564 if (req->newptr == NULL) {
565 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
566 if (sb == NULL) {
567 rc = ENOMEM;
568 return (rc);
569 }
570
571 sbuf_printf(sb, "\nLink is %s", pdata->phy.link ? "Up" : "Down");
572 rc = sbuf_finish(sb);
573 sbuf_delete(sb);
574 return (0);
575 }
576
577 return (-EINVAL);
578 }
579
580 #define COALESCE_SYSCTL_INFO(__coalop) \
581 { \
582 { "adaptive-rx", SYSL_BOOL, use_adaptive_rx_coalesce, "not-supported" }, \
583 { "adaptive-tx", SYSL_BOOL, use_adaptive_tx_coalesce, "not-supported" }, \
584 { "sample-interval", SYSL_S32, rate_sample_interval, "not-supported" }, \
585 { "stats-block-usecs", SYSL_S32, stats_block_coalesce_usecs, "not-supported" }, \
586 { "pkt-rate-low", SYSL_S32, pkt_rate_low, "not-supported" }, \
587 { "pkt-rate-high", SYSL_S32, pkt_rate_high, "not-supported" }, \
588 { "rx-usecs", SYSL_S32, rx_coalesce_usecs, "supported" }, \
589 { "rx-frames", SYSL_S32, rx_max_coalesced_frames, "supported" }, \
590 { "rx-usecs-irq", SYSL_S32, rx_coalesce_usecs_irq, "not-supported" }, \
591 { "rx-frames-irq", SYSL_S32, rx_max_coalesced_frames_irq, "not-supported" }, \
592 { "tx-usecs", SYSL_S32, tx_coalesce_usecs, "not-supported" }, \
593 { "tx-frames", SYSL_S32, tx_max_coalesced_frames, "supported" }, \
594 { "tx-usecs-irq", SYSL_S32, tx_coalesce_usecs_irq, "not-supported" }, \
595 { "tx-frames-irq", SYSL_S32, tx_max_coalesced_frames_irq, "not-supported" }, \
596 { "rx-usecs-low", SYSL_S32, rx_coalesce_usecs_low, "not-supported" }, \
597 { "rx-frames-low", SYSL_S32, rx_max_coalesced_frames_low, "not-supported"}, \
598 { "tx-usecs-low", SYSL_S32, tx_coalesce_usecs_low, "not-supported" }, \
599 { "tx-frames-low", SYSL_S32, tx_max_coalesced_frames_low, "not-supported" }, \
600 { "rx-usecs-high", SYSL_S32, rx_coalesce_usecs_high, "not-supported" }, \
601 { "rx-frames-high", SYSL_S32, rx_max_coalesced_frames_high, "not-supported" }, \
602 { "tx-usecs-high", SYSL_S32, tx_coalesce_usecs_high, "not-supported" }, \
603 { "tx-frames-high", SYSL_S32, tx_max_coalesced_frames_high, "not-supported" }, \
604 }
605
606 static int
sysctl_coalesce_handler(SYSCTL_HANDLER_ARGS)607 sysctl_coalesce_handler(SYSCTL_HANDLER_ARGS)
608 {
609 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1;
610 struct xgbe_hw_if *hw_if = &pdata->hw_if;
611 struct sysctl_op *sys_op = pdata->sys_op;
612 struct sysctl_info sysctl_coalesce[] = COALESCE_SYSCTL_INFO(coalop);
613 unsigned int rx_frames, rx_riwt, rx_usecs;
614 unsigned int tx_frames;
615 ssize_t buf_size = 64;
616 char buf[buf_size];
617 struct sbuf *sb;
618 int rc = 0;
619
620 if (req->newptr == NULL) {
621 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
622 if (sb == NULL) {
623 rc = ENOMEM;
624 return (rc);
625 }
626 sys_op->rx_coalesce_usecs = pdata->rx_usecs;
627 sys_op->rx_max_coalesced_frames = pdata->rx_frames;
628 sys_op->tx_max_coalesced_frames = pdata->tx_frames;
629
630 sbuf_printf(sb, "\nAdaptive RX: %s TX: %s\n",
631 sys_op->use_adaptive_rx_coalesce ? "on" : "off",
632 sys_op->use_adaptive_tx_coalesce ? "on" : "off");
633
634 sbuf_printf(sb, "stats-block-usecs: %u\n"
635 "sample-interval: %u\n"
636 "pkt-rate-low: %u\n"
637 "pkt-rate-high: %u\n"
638 "\n"
639 "rx-usecs: %u\n"
640 "rx-frames: %u\n"
641 "rx-usecs-irq: %u\n"
642 "rx-frames-irq: %u\n"
643 "\n"
644 "tx-usecs: %u\n"
645 "tx-frames: %u\n"
646 "tx-usecs-irq: %u\n"
647 "tx-frames-irq: %u\n"
648 "\n"
649 "rx-usecs-low: %u\n"
650 "rx-frames-low: %u\n"
651 "tx-usecs-low: %u\n"
652 "tx-frames-low: %u\n"
653 "\n"
654 "rx-usecs-high: %u\n"
655 "rx-frames-high: %u\n"
656 "tx-usecs-high: %u\n"
657 "tx-frames-high: %u\n",
658 sys_op->stats_block_coalesce_usecs,
659 sys_op->rate_sample_interval,
660 sys_op->pkt_rate_low,
661 sys_op->pkt_rate_high,
662
663 sys_op->rx_coalesce_usecs,
664 sys_op->rx_max_coalesced_frames,
665 sys_op->rx_coalesce_usecs_irq,
666 sys_op->rx_max_coalesced_frames_irq,
667
668 sys_op->tx_coalesce_usecs,
669 sys_op->tx_max_coalesced_frames,
670 sys_op->tx_coalesce_usecs_irq,
671 sys_op->tx_max_coalesced_frames_irq,
672
673 sys_op->rx_coalesce_usecs_low,
674 sys_op->rx_max_coalesced_frames_low,
675 sys_op->tx_coalesce_usecs_low,
676 sys_op->tx_max_coalesced_frames_low,
677
678 sys_op->rx_coalesce_usecs_high,
679 sys_op->rx_max_coalesced_frames_high,
680 sys_op->tx_coalesce_usecs_high,
681 sys_op->tx_max_coalesced_frames_high);
682
683 rc = sbuf_finish(sb);
684 sbuf_delete(sb);
685 return (0);
686 }
687
688 rc = get_ubuf(req, buf);
689 if (rc == 0) {
690 parse_generic_sysctl(pdata, buf, sysctl_coalesce,
691 ARRAY_SIZE(sysctl_coalesce));
692
693 rx_riwt = hw_if->usec_to_riwt(pdata, sys_op->rx_coalesce_usecs);
694 rx_usecs = sys_op->rx_coalesce_usecs;
695 rx_frames = sys_op->rx_max_coalesced_frames;
696
697 /* Use smallest possible value if conversion resulted in zero */
698 if (rx_usecs && !rx_riwt)
699 rx_riwt = 1;
700
701 /* Check the bounds of values for Rx */
702 if (rx_riwt > XGMAC_MAX_DMA_RIWT) {
703 axgbe_printf(2, "rx-usec is limited to %d usecs\n",
704 hw_if->riwt_to_usec(pdata, XGMAC_MAX_DMA_RIWT));
705 return (-EINVAL);
706 }
707 if (rx_frames > pdata->rx_desc_count) {
708 axgbe_printf(2, "rx-frames is limited to %d frames\n",
709 pdata->rx_desc_count);
710 return (-EINVAL);
711 }
712
713 tx_frames = sys_op->tx_max_coalesced_frames;
714
715 /* Check the bounds of values for Tx */
716 if (tx_frames > pdata->tx_desc_count) {
717 axgbe_printf(2, "tx-frames is limited to %d frames\n",
718 pdata->tx_desc_count);
719 return (-EINVAL);
720 }
721
722 pdata->rx_riwt = rx_riwt;
723 pdata->rx_usecs = rx_usecs;
724 pdata->rx_frames = rx_frames;
725 hw_if->config_rx_coalesce(pdata);
726
727 pdata->tx_frames = tx_frames;
728 hw_if->config_tx_coalesce(pdata);
729 }
730
731 axgbe_printf(2, "%s: rc= %d\n", __func__, rc);
732
733 return (rc);
734 }
735
736 static int
sysctl_pauseparam_handler(SYSCTL_HANDLER_ARGS)737 sysctl_pauseparam_handler(SYSCTL_HANDLER_ARGS)
738 {
739 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1;
740 struct sysctl_op *sys_op = pdata->sys_op;
741 struct sysctl_info sysctl_pauseparam[] = {
742 { "autoneg", SYSL_BOOL, autoneg, "supported" },
743 { "rx", SYSL_BOOL, rx_pause, "supported" },
744 { "tx", SYSL_BOOL, tx_pause, "supported" },
745 };
746 ssize_t buf_size = 512;
747 char buf[buf_size];
748 struct sbuf *sb;
749 int rc = 0;
750
751 if (req->newptr == NULL) {
752 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
753 if (sb == NULL) {
754 rc = ENOMEM;
755 return (rc);
756 }
757 sys_op->autoneg = pdata->phy.pause_autoneg;
758 sys_op->tx_pause = pdata->phy.tx_pause;
759 sys_op->rx_pause = pdata->phy.rx_pause;
760
761 sbuf_printf(sb,
762 "\nAutonegotiate: %s\n"
763 "RX: %s\n"
764 "TX: %s\n",
765 sys_op->autoneg ? "on" : "off",
766 sys_op->rx_pause ? "on" : "off",
767 sys_op->tx_pause ? "on" : "off");
768
769 if (pdata->phy.lp_advertising) {
770 int an_rx = 0, an_tx = 0;
771
772 if (pdata->phy.advertising & pdata->phy.lp_advertising &
773 ADVERTISED_Pause) {
774 an_tx = 1;
775 an_rx = 1;
776 } else if (pdata->phy.advertising &
777 pdata->phy.lp_advertising & ADVERTISED_Asym_Pause) {
778 if (pdata->phy.advertising & ADVERTISED_Pause)
779 an_rx = 1;
780 else if (pdata->phy.lp_advertising &
781 ADVERTISED_Pause)
782 an_tx = 1;
783 }
784 sbuf_printf(sb,
785 "\n->\nRX negotiated: %s\n"
786 "TX negotiated: %s\n",
787 an_rx ? "on" : "off",
788 an_tx ? "on" : "off");
789 }
790 rc = sbuf_finish(sb);
791 sbuf_delete(sb);
792 return (0);
793 }
794
795 rc = get_ubuf(req, buf);
796 if (rc == 0) {
797 parse_generic_sysctl(pdata, buf, sysctl_pauseparam,
798 ARRAY_SIZE(sysctl_pauseparam));
799
800 if (sys_op->autoneg && (pdata->phy.autoneg != AUTONEG_ENABLE)) {
801 axgbe_error("autoneg disabled, pause autoneg not available\n");
802 return (-EINVAL);
803 }
804
805 pdata->phy.pause_autoneg = sys_op->autoneg;
806 pdata->phy.tx_pause = sys_op->tx_pause;
807 pdata->phy.rx_pause = sys_op->rx_pause;
808
809 XGBE_CLR_ADV(&pdata->phy, Pause);
810 XGBE_CLR_ADV(&pdata->phy, Asym_Pause);
811
812 if (sys_op->rx_pause) {
813 XGBE_SET_ADV(&pdata->phy, Pause);
814 XGBE_SET_ADV(&pdata->phy, Asym_Pause);
815 }
816
817 if (sys_op->tx_pause) {
818 /* Equivalent to XOR of Asym_Pause */
819 if (XGBE_ADV(&pdata->phy, Asym_Pause))
820 XGBE_CLR_ADV(&pdata->phy, Asym_Pause);
821 else
822 XGBE_SET_ADV(&pdata->phy, Asym_Pause);
823 }
824
825 if (test_bit(XGBE_LINK_INIT, &pdata->dev_state))
826 rc = pdata->phy_if.phy_config_aneg(pdata);
827
828 }
829
830 return (rc);
831 }
832
833 static int
sysctl_link_ksettings_handler(SYSCTL_HANDLER_ARGS)834 sysctl_link_ksettings_handler(SYSCTL_HANDLER_ARGS)
835 {
836 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1;
837 struct sysctl_op *sys_op = pdata->sys_op;
838 struct sysctl_info sysctl_linksettings[] = {
839 { "autoneg", SYSL_BOOL, autoneg, "supported" },
840 { "speed", SYSL_U32, speed, "supported" },
841 { "duplex", SYSL_U8, duplex, "supported" },
842 };
843 ssize_t buf_size = 512;
844 char buf[buf_size], link_modes[16], speed_modes[16];
845 struct sbuf *sb;
846 uint32_t speed;
847 int rc = 0;
848
849 if (req->newptr == NULL) {
850 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
851 if (sb == NULL) {
852 rc = ENOMEM;
853 return (rc);
854 }
855 sys_op->autoneg = pdata->phy.autoneg;
856 sys_op->speed = pdata->phy.speed;
857 sys_op->duplex = pdata->phy.duplex;
858
859 XGBE_LM_COPY(&pdata->phy, supported, &pdata->phy, supported);
860 XGBE_LM_COPY(&pdata->phy, advertising, &pdata->phy, advertising);
861 XGBE_LM_COPY(&pdata->phy, lp_advertising, &pdata->phy, lp_advertising);
862
863 switch (sys_op->speed) {
864 case 1:
865 strcpy(link_modes, "Unknown");
866 strcpy(speed_modes, "Unknown");
867 break;
868 case 2:
869 strcpy(link_modes, "10Gbps/Full");
870 strcpy(speed_modes, "10000");
871 break;
872 case 3:
873 strcpy(link_modes, "2.5Gbps/Full");
874 strcpy(speed_modes, "2500");
875 break;
876 case 4:
877 strcpy(link_modes, "1Gbps/Full");
878 strcpy(speed_modes, "1000");
879 break;
880 case 5:
881 strcpy(link_modes, "100Mbps/Full");
882 strcpy(speed_modes, "100");
883 break;
884 case 6:
885 strcpy(link_modes, "10Mbps/Full");
886 strcpy(speed_modes, "10");
887 break;
888 }
889
890 sbuf_printf(sb,
891 "\nlink_modes: %s\n"
892 "autonegotiation: %s\n"
893 "speed: %sMbps\n",
894 link_modes,
895 (sys_op->autoneg == AUTONEG_DISABLE) ? "off" : "on",
896 speed_modes);
897
898 switch (sys_op->duplex) {
899 case DUPLEX_HALF:
900 sbuf_printf(sb, "Duplex: Half\n");
901 break;
902 case DUPLEX_FULL:
903 sbuf_printf(sb, "Duplex: Full\n");
904 break;
905 default:
906 sbuf_printf(sb, "Duplex: Unknown\n");
907 break;
908 }
909 rc = sbuf_finish(sb);
910 sbuf_delete(sb);
911 return (0);
912 }
913
914 rc = get_ubuf(req, buf);
915 if (rc == 0) {
916 parse_generic_sysctl(pdata, buf, sysctl_linksettings,
917 ARRAY_SIZE(sysctl_linksettings));
918
919 speed = sys_op->speed;
920
921 if ((sys_op->autoneg != AUTONEG_ENABLE) &&
922 (sys_op->autoneg != AUTONEG_DISABLE)) {
923 axgbe_error("unsupported autoneg %hhu\n",
924 (unsigned char)sys_op->autoneg);
925 return (-EINVAL);
926 }
927
928 if (sys_op->autoneg == AUTONEG_DISABLE) {
929 if (!pdata->phy_if.phy_valid_speed(pdata, speed)) {
930 axgbe_error("unsupported speed %u\n", speed);
931 return (-EINVAL);
932 }
933
934 if (sys_op->duplex != DUPLEX_FULL) {
935 axgbe_error("unsupported duplex %hhu\n",
936 (unsigned char)sys_op->duplex);
937 return (-EINVAL);
938 }
939 }
940
941 pdata->phy.autoneg = sys_op->autoneg;
942 pdata->phy.speed = speed;
943 pdata->phy.duplex = sys_op->duplex;
944
945 if (sys_op->autoneg == AUTONEG_ENABLE)
946 XGBE_SET_ADV(&pdata->phy, Autoneg);
947 else
948 XGBE_CLR_ADV(&pdata->phy, Autoneg);
949
950 if (test_bit(XGBE_LINK_INIT, &pdata->dev_state))
951 rc = pdata->phy_if.phy_config_aneg(pdata);
952 }
953
954 return (rc);
955 }
956
957 static int
sysctl_ringparam_handler(SYSCTL_HANDLER_ARGS)958 sysctl_ringparam_handler(SYSCTL_HANDLER_ARGS)
959 {
960 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1;
961 struct sysctl_op *sys_op = pdata->sys_op;
962 struct sysctl_info sysctl_ringparam[] = {
963 { "rx", SYSL_S32, rx_pending, "supported" },
964 { "rx-mini", SYSL_S32, rx_mini_pending, "supported" },
965 { "rx-jumbo", SYSL_S32, rx_jumbo_pending, "supported" },
966 { "tx", SYSL_S32, tx_pending, "supported" },
967 };
968 ssize_t buf_size = 512;
969 unsigned int rx, tx;
970 char buf[buf_size];
971 struct sbuf *sb;
972 int rc = 0;
973
974 if (req->newptr == NULL) {
975 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
976 if (sb == NULL) {
977 rc = ENOMEM;
978 return (rc);
979 }
980 sys_op->rx_max_pending = XGBE_RX_DESC_CNT_MAX;
981 sys_op->tx_max_pending = XGBE_TX_DESC_CNT_MAX;
982 sys_op->rx_pending = pdata->rx_desc_count;
983 sys_op->tx_pending = pdata->tx_desc_count;
984
985 sbuf_printf(sb,
986 "\nPre-set maximums:\n"
987 "RX: %u\n"
988 "RX Mini: %u\n"
989 "RX Jumbo: %u\n"
990 "TX: %u\n",
991 sys_op->rx_max_pending,
992 sys_op->rx_mini_max_pending,
993 sys_op->rx_jumbo_max_pending,
994 sys_op->tx_max_pending);
995
996 sbuf_printf(sb,
997 "\nCurrent hardware settings:\n"
998 "RX: %u\n"
999 "RX Mini: %u\n"
1000 "RX Jumbo: %u\n"
1001 "TX: %u\n",
1002 sys_op->rx_pending,
1003 sys_op->rx_mini_pending,
1004 sys_op->rx_jumbo_pending,
1005 sys_op->tx_pending);
1006
1007 rc = sbuf_finish(sb);
1008 sbuf_delete(sb);
1009 return (0);
1010 }
1011
1012 rc = get_ubuf(req, buf);
1013 if (rc == 0) {
1014 parse_generic_sysctl(pdata, buf, sysctl_ringparam,
1015 ARRAY_SIZE(sysctl_ringparam));
1016
1017 if (sys_op->rx_mini_pending || sys_op->rx_jumbo_pending) {
1018 axgbe_error("unsupported ring parameter\n");
1019 return (-EINVAL);
1020 }
1021
1022 if ((sys_op->rx_pending < XGBE_RX_DESC_CNT_MIN) ||
1023 (sys_op->rx_pending > XGBE_RX_DESC_CNT_MAX)) {
1024 axgbe_error("rx ring param must be between %u and %u\n",
1025 XGBE_RX_DESC_CNT_MIN, XGBE_RX_DESC_CNT_MAX);
1026 return (-EINVAL);
1027 }
1028
1029 if ((sys_op->tx_pending < XGBE_TX_DESC_CNT_MIN) ||
1030 (sys_op->tx_pending > XGBE_TX_DESC_CNT_MAX)) {
1031 axgbe_error("tx ring param must be between %u and %u\n",
1032 XGBE_TX_DESC_CNT_MIN, XGBE_TX_DESC_CNT_MAX);
1033 return (-EINVAL);
1034 }
1035
1036 rx = rounddown_pow_of_two(sys_op->rx_pending);
1037 if (rx != sys_op->rx_pending)
1038 axgbe_printf(1, "rx ring param rounded to power of 2: %u\n",
1039 rx);
1040
1041 tx = rounddown_pow_of_two(sys_op->tx_pending);
1042 if (tx != sys_op->tx_pending)
1043 axgbe_printf(1, "tx ring param rounded to power of 2: %u\n",
1044 tx);
1045
1046 if ((rx == pdata->rx_desc_count) &&
1047 (tx == pdata->tx_desc_count))
1048 goto out;
1049
1050 pdata->rx_desc_count = rx;
1051 pdata->tx_desc_count = tx;
1052
1053 /* TODO - restart dev */
1054 }
1055
1056 out:
1057 return (0);
1058 }
1059
1060 static int
sysctl_channels_handler(SYSCTL_HANDLER_ARGS)1061 sysctl_channels_handler(SYSCTL_HANDLER_ARGS)
1062 {
1063 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1;
1064 struct sysctl_op *sys_op = pdata->sys_op;
1065 struct sysctl_info sysctl_channels[] = {
1066 { "rx", SYSL_S32, rx_count, "supported" },
1067 { "tx", SYSL_S32, tx_count, "supported" },
1068 { "other", SYSL_S32, other_count, "supported" },
1069 { "combined", SYSL_S32, combined_count, "supported" },
1070 };
1071 unsigned int rx, tx, combined;
1072 ssize_t buf_size = 512;
1073 char buf[buf_size];
1074 struct sbuf *sb;
1075 int rc = 0;
1076
1077 if (req->newptr == NULL) {
1078 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
1079 if (sb == NULL) {
1080 rc = ENOMEM;
1081 return (rc);
1082 }
1083 rx = min(pdata->hw_feat.rx_ch_cnt, pdata->rx_max_channel_count);
1084 rx = min(rx, pdata->channel_irq_count);
1085 tx = min(pdata->hw_feat.tx_ch_cnt, pdata->tx_max_channel_count);
1086 tx = min(tx, pdata->channel_irq_count);
1087 tx = min(tx, pdata->tx_max_q_count);
1088
1089 combined = min(rx, tx);
1090
1091 sys_op->max_combined = combined;
1092 sys_op->max_rx = rx ? rx - 1 : 0;
1093 sys_op->max_tx = tx ? tx - 1 : 0;
1094
1095 /* Get current settings based on device state */
1096 rx = pdata->rx_ring_count;
1097 tx = pdata->tx_ring_count;
1098
1099 combined = min(rx, tx);
1100 rx -= combined;
1101 tx -= combined;
1102
1103 sys_op->combined_count = combined;
1104 sys_op->rx_count = rx;
1105 sys_op->tx_count = tx;
1106
1107 sbuf_printf(sb,
1108 "\nPre-set maximums:\n"
1109 "RX: %u\n"
1110 "TX: %u\n"
1111 "Other: %u\n"
1112 "Combined: %u\n",
1113 sys_op->max_rx, sys_op->max_tx,
1114 sys_op->max_other,
1115 sys_op->max_combined);
1116
1117 sbuf_printf(sb,
1118 "\nCurrent hardware settings:\n"
1119 "RX: %u\n"
1120 "TX: %u\n"
1121 "Other: %u\n"
1122 "Combined: %u\n",
1123 sys_op->rx_count, sys_op->tx_count,
1124 sys_op->other_count,
1125 sys_op->combined_count);
1126
1127 rc = sbuf_finish(sb);
1128 sbuf_delete(sb);
1129 return (0);
1130 }
1131
1132 rc = get_ubuf(req, buf);
1133 if (rc == 0) {
1134 parse_generic_sysctl(pdata, buf, sysctl_channels,
1135 ARRAY_SIZE(sysctl_channels));
1136
1137 axgbe_error( "channel inputs: combined=%u, rx-only=%u,"
1138 " tx-only=%u\n", sys_op->combined_count,
1139 sys_op->rx_count, sys_op->tx_count);
1140 }
1141
1142 return (rc);
1143 }
1144
1145
1146 static int
sysctl_mac_stats_handler(SYSCTL_HANDLER_ARGS)1147 sysctl_mac_stats_handler(SYSCTL_HANDLER_ARGS)
1148 {
1149 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1;
1150 ssize_t buf_size = 64;
1151 struct sbuf *sb;
1152 int rc = 0;
1153 int i;
1154
1155 if (req->newptr == NULL) {
1156 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
1157 if (sb == NULL) {
1158 rc = ENOMEM;
1159 return (rc);
1160 }
1161
1162 pdata->hw_if.read_mmc_stats(pdata);
1163 for (i = 0; i < XGBE_STATS_COUNT; i++) {
1164 sbuf_printf(sb, "\n %s: %lu",
1165 xgbe_gstring_stats[i].stat_string,
1166 *(uint64_t *)((uint8_t *)pdata + xgbe_gstring_stats[i].stat_offset));
1167 }
1168 for (i = 0; i < pdata->tx_ring_count; i++) {
1169 sbuf_printf(sb,
1170 "\n txq_packets[%d]: %lu"
1171 "\n txq_bytes[%d]: %lu",
1172 i, pdata->ext_stats.txq_packets[i],
1173 i, pdata->ext_stats.txq_bytes[i]);
1174 }
1175 for (i = 0; i < pdata->rx_ring_count; i++) {
1176 sbuf_printf(sb,
1177 "\n rxq_packets[%d]: %lu"
1178 "\n rxq_bytes[%d]: %lu",
1179 i, pdata->ext_stats.rxq_packets[i],
1180 i, pdata->ext_stats.rxq_bytes[i]);
1181 }
1182
1183 rc = sbuf_finish(sb);
1184 sbuf_delete(sb);
1185 return (rc);
1186 }
1187
1188 return (-EINVAL);
1189 }
1190
1191 static int
sysctl_xgmac_reg_value_handler(SYSCTL_HANDLER_ARGS)1192 sysctl_xgmac_reg_value_handler(SYSCTL_HANDLER_ARGS)
1193 {
1194 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1;
1195 ssize_t buf_size = 64;
1196 char buf[buf_size];
1197 unsigned int value;
1198 struct sbuf *sb;
1199 int rc = 0;
1200
1201 if (req->newptr == NULL) {
1202 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
1203 if (sb == NULL) {
1204 rc = ENOMEM;
1205 return (rc);
1206 }
1207
1208 value = XGMAC_IOREAD(pdata, pdata->sysctl_xgmac_reg);
1209 axgbe_printf(2, "READ: %s: value: 0x%x\n", __func__, value);
1210 sbuf_printf(sb, "\nXGMAC reg_value: 0x%x\n", value);
1211 rc = sbuf_finish(sb);
1212 sbuf_delete(sb);
1213 return (rc);
1214 }
1215
1216 rc = get_ubuf(req, buf);
1217 if (rc == 0) {
1218 sscanf(buf, "%x", &value);
1219 axgbe_printf(2, "WRITE: %s: value: 0x%x\n", __func__, value);
1220 XGMAC_IOWRITE(pdata, pdata->sysctl_xgmac_reg, value);
1221 }
1222
1223 axgbe_printf(2, "%s: rc= %d\n", __func__, rc);
1224 return (rc);
1225 }
1226
1227 static int
sysctl_xpcs_mmd_reg_handler(SYSCTL_HANDLER_ARGS)1228 sysctl_xpcs_mmd_reg_handler(SYSCTL_HANDLER_ARGS)
1229 {
1230 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1;
1231 ssize_t buf_size = 64;
1232 char buf[buf_size];
1233 struct sbuf *sb;
1234 unsigned int reg;
1235 int rc = 0;
1236
1237 if (req->newptr == NULL) {
1238 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
1239 if (sb == NULL) {
1240 rc = ENOMEM;
1241 return (rc);
1242 }
1243
1244 axgbe_printf(2, "READ: %s: xpcs_mmd: 0x%x\n", __func__,
1245 pdata->sysctl_xpcs_mmd);
1246 sbuf_printf(sb, "\nXPCS mmd_reg: 0x%x\n",
1247 pdata->sysctl_xpcs_mmd);
1248 rc = sbuf_finish(sb);
1249 sbuf_delete(sb);
1250 return (rc);
1251 }
1252
1253 rc = get_ubuf(req, buf);
1254 if (rc == 0) {
1255 sscanf(buf, "%x", ®);
1256 axgbe_printf(2, "WRITE: %s: mmd_reg: 0x%x\n", __func__, reg);
1257 pdata->sysctl_xpcs_mmd = reg;
1258 }
1259
1260 axgbe_printf(2, "%s: rc= %d\n", __func__, rc);
1261 return (rc);
1262 }
1263
1264 static int
sysctl_xpcs_reg_addr_handler(SYSCTL_HANDLER_ARGS)1265 sysctl_xpcs_reg_addr_handler(SYSCTL_HANDLER_ARGS)
1266 {
1267 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1;
1268 ssize_t buf_size = 64;
1269 char buf[buf_size];
1270 struct sbuf *sb;
1271 unsigned int reg;
1272 int rc = 0;
1273
1274 if (req->newptr == NULL) {
1275 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
1276 if (sb == NULL) {
1277 rc = ENOMEM;
1278 return (rc);
1279 }
1280
1281 axgbe_printf(2, "READ: %s: sysctl_xpcs_reg: 0x%x\n", __func__,
1282 pdata->sysctl_xpcs_reg);
1283 sbuf_printf(sb, "\nXPCS reg_addr: 0x%x\n",
1284 pdata->sysctl_xpcs_reg);
1285 rc = sbuf_finish(sb);
1286 sbuf_delete(sb);
1287 return (rc);
1288 }
1289
1290 rc = get_ubuf(req, buf);
1291 if (rc == 0) {
1292 sscanf(buf, "%x", ®);
1293 axgbe_printf(2, "WRITE: %s: reg: 0x%x\n", __func__, reg);
1294 pdata->sysctl_xpcs_reg = reg;
1295 }
1296
1297 axgbe_printf(2, "%s: rc= %d\n", __func__, rc);
1298 return (rc);
1299 }
1300
1301 static int
sysctl_xpcs_reg_value_handler(SYSCTL_HANDLER_ARGS)1302 sysctl_xpcs_reg_value_handler(SYSCTL_HANDLER_ARGS)
1303 {
1304 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1;
1305 ssize_t buf_size = 64;
1306 char buf[buf_size];
1307 unsigned int value;
1308 struct sbuf *sb;
1309 int rc = 0;
1310
1311 if (req->newptr == NULL) {
1312 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
1313 if (sb == NULL) {
1314 rc = ENOMEM;
1315 return (rc);
1316 }
1317
1318 value = XMDIO_READ(pdata, pdata->sysctl_xpcs_mmd,
1319 pdata->sysctl_xpcs_reg);
1320 axgbe_printf(2, "READ: %s: value: 0x%x\n", __func__, value);
1321 sbuf_printf(sb, "\nXPCS reg_value: 0x%x\n", value);
1322 rc = sbuf_finish(sb);
1323 sbuf_delete(sb);
1324 return (rc);
1325 }
1326
1327 rc = get_ubuf(req, buf);
1328 if (rc == 0) {
1329 sscanf(buf, "%x", &value);
1330 axgbe_printf(2, "WRITE: %s: value: 0x%x\n", __func__, value);
1331 XMDIO_WRITE(pdata, pdata->sysctl_xpcs_mmd,
1332 pdata->sysctl_xpcs_reg, value);
1333 }
1334
1335 axgbe_printf(2, "%s: rc= %d\n", __func__, rc);
1336 return (rc);
1337 }
1338
1339 static int
sysctl_xprop_reg_addr_handler(SYSCTL_HANDLER_ARGS)1340 sysctl_xprop_reg_addr_handler(SYSCTL_HANDLER_ARGS)
1341 {
1342 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1;
1343 ssize_t buf_size = 64;
1344 char buf[buf_size];
1345 struct sbuf *sb;
1346 unsigned int reg;
1347 int rc = 0;
1348
1349 if (req->newptr == NULL) {
1350 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
1351 if (sb == NULL) {
1352 rc = ENOMEM;
1353 return (rc);
1354 }
1355
1356 axgbe_printf(2, "READ: %s: sysctl_xprop_reg: 0x%x\n", __func__,
1357 pdata->sysctl_xprop_reg);
1358 sbuf_printf(sb, "\nXPROP reg_addr: 0x%x\n",
1359 pdata->sysctl_xprop_reg);
1360 rc = sbuf_finish(sb);
1361 sbuf_delete(sb);
1362 return (rc);
1363 }
1364
1365 rc = get_ubuf(req, buf);
1366 if (rc == 0) {
1367 sscanf(buf, "%x", ®);
1368 axgbe_printf(2, "WRITE: %s: reg: 0x%x\n", __func__, reg);
1369 pdata->sysctl_xprop_reg = reg;
1370 }
1371
1372 axgbe_printf(2, "%s: rc= %d\n", __func__, rc);
1373 return (rc);
1374 }
1375
1376 static int
sysctl_xprop_reg_value_handler(SYSCTL_HANDLER_ARGS)1377 sysctl_xprop_reg_value_handler(SYSCTL_HANDLER_ARGS)
1378 {
1379 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1;
1380 ssize_t buf_size = 64;
1381 char buf[buf_size];
1382 unsigned int value;
1383 struct sbuf *sb;
1384 int rc = 0;
1385
1386 if (req->newptr == NULL) {
1387 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
1388 if (sb == NULL) {
1389 rc = ENOMEM;
1390 return (rc);
1391 }
1392
1393 value = XP_IOREAD(pdata, pdata->sysctl_xprop_reg);
1394 axgbe_printf(2, "READ: %s: value: 0x%x\n", __func__, value);
1395 sbuf_printf(sb, "\nXPROP reg_value: 0x%x\n", value);
1396 rc = sbuf_finish(sb);
1397 sbuf_delete(sb);
1398 return (rc);
1399 }
1400
1401 rc = get_ubuf(req, buf);
1402 if (rc == 0) {
1403 sscanf(buf, "%x", &value);
1404 axgbe_printf(2, "WRITE: %s: value: 0x%x\n", __func__, value);
1405 XP_IOWRITE(pdata, pdata->sysctl_xprop_reg, value);
1406 }
1407
1408 axgbe_printf(2, "%s: rc= %d\n", __func__, rc);
1409 return (rc);
1410 }
1411
1412 static int
sysctl_xi2c_reg_addr_handler(SYSCTL_HANDLER_ARGS)1413 sysctl_xi2c_reg_addr_handler(SYSCTL_HANDLER_ARGS)
1414 {
1415 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1;
1416 ssize_t buf_size = 64;
1417 char buf[buf_size];
1418 struct sbuf *sb;
1419 unsigned int reg;
1420 int rc = 0;
1421
1422 if (req->newptr == NULL) {
1423 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
1424 if (sb == NULL) {
1425 rc = ENOMEM;
1426 return (rc);
1427 }
1428
1429 axgbe_printf(2, "READ: %s: sysctl_xi2c_reg: 0x%x\n", __func__,
1430 pdata->sysctl_xi2c_reg);
1431 sbuf_printf(sb, "\nXI2C reg_addr: 0x%x\n",
1432 pdata->sysctl_xi2c_reg);
1433 rc = sbuf_finish(sb);
1434 sbuf_delete(sb);
1435 return (rc);
1436 }
1437
1438 rc = get_ubuf(req, buf);
1439 if (rc == 0) {
1440 sscanf(buf, "%x", ®);
1441 axgbe_printf(2, "WRITE: %s: reg: 0x%x\n", __func__, reg);
1442 pdata->sysctl_xi2c_reg = reg;
1443 }
1444
1445 axgbe_printf(2, "%s: rc= %d\n", __func__, rc);
1446 return (rc);
1447 }
1448
1449 static int
sysctl_xi2c_reg_value_handler(SYSCTL_HANDLER_ARGS)1450 sysctl_xi2c_reg_value_handler(SYSCTL_HANDLER_ARGS)
1451 {
1452 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1;
1453 ssize_t buf_size = 64;
1454 char buf[buf_size];
1455 unsigned int value;
1456 struct sbuf *sb;
1457 int rc = 0;
1458
1459 if (req->newptr == NULL) {
1460 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
1461 if (sb == NULL) {
1462 rc = ENOMEM;
1463 return (rc);
1464 }
1465
1466 value = XI2C_IOREAD(pdata, pdata->sysctl_xi2c_reg);
1467 axgbe_printf(2, "READ: %s: value: 0x%x\n", __func__, value);
1468 sbuf_printf(sb, "\nXI2C reg_value: 0x%x\n", value);
1469 rc = sbuf_finish(sb);
1470 sbuf_delete(sb);
1471 return (rc);
1472 }
1473
1474 rc = get_ubuf(req, buf);
1475 if (rc == 0) {
1476 sscanf(buf, "%x", &value);
1477 axgbe_printf(2, "WRITE: %s: value: 0x%x\n", __func__, value);
1478 XI2C_IOWRITE(pdata, pdata->sysctl_xi2c_reg, value);
1479 }
1480
1481 axgbe_printf(2, "%s: rc= %d\n", __func__, rc);
1482 return (rc);
1483 }
1484
1485 static int
sysctl_an_cdr_wr_handler(SYSCTL_HANDLER_ARGS)1486 sysctl_an_cdr_wr_handler(SYSCTL_HANDLER_ARGS)
1487 {
1488 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1;
1489 unsigned int an_cdr_wr = 0;
1490 ssize_t buf_size = 64;
1491 char buf[buf_size];
1492 struct sbuf *sb;
1493 int rc = 0;
1494
1495 if (req->newptr == NULL) {
1496 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
1497 if (sb == NULL) {
1498 rc = ENOMEM;
1499 return (rc);
1500 }
1501
1502 axgbe_printf(2, "READ: %s: an_cdr_wr: %d\n", __func__,
1503 pdata->sysctl_an_cdr_workaround);
1504 sbuf_printf(sb, "%d\n", pdata->sysctl_an_cdr_workaround);
1505 rc = sbuf_finish(sb);
1506 sbuf_delete(sb);
1507 return (rc);
1508 }
1509
1510 rc = get_ubuf(req, buf);
1511 if (rc == 0) {
1512 sscanf(buf, "%u", &an_cdr_wr);
1513 axgbe_printf(2, "WRITE: %s: an_cdr_wr: 0x%d\n", __func__,
1514 an_cdr_wr);
1515
1516 if (an_cdr_wr)
1517 pdata->sysctl_an_cdr_workaround = 1;
1518 else
1519 pdata->sysctl_an_cdr_workaround = 0;
1520 }
1521
1522 axgbe_printf(2, "%s: rc= %d\n", __func__, rc);
1523 return (rc);
1524 }
1525
1526 static int
sysctl_an_cdr_track_early_handler(SYSCTL_HANDLER_ARGS)1527 sysctl_an_cdr_track_early_handler(SYSCTL_HANDLER_ARGS)
1528 {
1529 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1;
1530 unsigned int an_cdr_track_early = 0;
1531 ssize_t buf_size = 64;
1532 char buf[buf_size];
1533 struct sbuf *sb;
1534 int rc = 0;
1535
1536 if (req->newptr == NULL) {
1537 sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req);
1538 if (sb == NULL) {
1539 rc = ENOMEM;
1540 return (rc);
1541 }
1542
1543 axgbe_printf(2, "READ: %s: an_cdr_track_early %d\n", __func__,
1544 pdata->sysctl_an_cdr_track_early);
1545 sbuf_printf(sb, "%d\n", pdata->sysctl_an_cdr_track_early);
1546 rc = sbuf_finish(sb);
1547 sbuf_delete(sb);
1548 return (rc);
1549 }
1550
1551 rc = get_ubuf(req, buf);
1552 if (rc == 0) {
1553 sscanf(buf, "%u", &an_cdr_track_early);
1554 axgbe_printf(2, "WRITE: %s: an_cdr_track_early: %d\n", __func__,
1555 an_cdr_track_early);
1556
1557 if (an_cdr_track_early)
1558 pdata->sysctl_an_cdr_track_early = 1;
1559 else
1560 pdata->sysctl_an_cdr_track_early = 0;
1561 }
1562
1563 axgbe_printf(2, "%s: rc= %d\n", __func__, rc);
1564 return (rc);
1565 }
1566
1567 void
axgbe_sysctl_exit(struct xgbe_prv_data * pdata)1568 axgbe_sysctl_exit(struct xgbe_prv_data *pdata)
1569 {
1570
1571 if (pdata->sys_op)
1572 free(pdata->sys_op, M_AXGBE);
1573 }
1574
1575 void
axgbe_sysctl_init(struct xgbe_prv_data * pdata)1576 axgbe_sysctl_init(struct xgbe_prv_data *pdata)
1577 {
1578 struct sysctl_ctx_list *clist;
1579 struct sysctl_oid_list *top;
1580 struct sysctl_oid *parent;
1581 struct sysctl_op *sys_op;
1582
1583 sys_op = malloc(sizeof(*sys_op), M_AXGBE, M_WAITOK | M_ZERO);
1584 pdata->sys_op = sys_op;
1585
1586 clist = device_get_sysctl_ctx(pdata->dev);
1587 parent = device_get_sysctl_tree(pdata->dev);
1588 top = SYSCTL_CHILDREN(parent);
1589
1590 /* Set defaults */
1591 pdata->sysctl_xgmac_reg = 0;
1592 pdata->sysctl_xpcs_mmd = 1;
1593 pdata->sysctl_xpcs_reg = 0;
1594 pdata->link_workaround = 1;
1595 pdata->tx_pause = 1;
1596 pdata->rx_pause = 1;
1597 pdata->enable_rss = 1;
1598
1599 SYSCTL_ADD_UINT(clist, top, OID_AUTO, "axgbe_debug_level", CTLFLAG_RWTUN,
1600 &pdata->debug_level, 0, "axgbe log level -- higher is verbose");
1601
1602 SYSCTL_ADD_UINT(clist, top, OID_AUTO, "sph_enable",
1603 CTLFLAG_RDTUN, &pdata->sph_enable, 1,
1604 "shows the split header feature state (1 - enable, 0 - disable");
1605
1606 SYSCTL_ADD_UINT(clist, top, OID_AUTO, "link_workaround",
1607 CTLFLAG_RWTUN, &pdata->link_workaround, 0,
1608 "enable the workaround for link issue in coming up");
1609
1610 SYSCTL_ADD_UINT(clist, top, OID_AUTO, "rss_enabled",
1611 CTLFLAG_RDTUN, &pdata->enable_rss, 1,
1612 "shows the RSS feature state (1 - enable, 0 - disable)");
1613
1614 SYSCTL_ADD_UINT(clist, top, OID_AUTO, "tx_pause",
1615 CTLFLAG_RDTUN, &pdata->tx_pause, 1,
1616 "shows the Flow Control TX pause feature state (1 - enable, 0 - disable)");
1617
1618 SYSCTL_ADD_UINT(clist, top, OID_AUTO, "rx_pause",
1619 CTLFLAG_RDTUN, &pdata->rx_pause, 1,
1620 "shows the Flow Control RX pause feature state (1 - enable, 0 - disable)");
1621
1622 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xgmac_register",
1623 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1624 pdata, 0, sysctl_xgmac_reg_addr_handler, "IU",
1625 "xgmac register addr");
1626
1627 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xgmac_register_value",
1628 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1629 pdata, 0, sysctl_xgmac_reg_value_handler, "IU",
1630 "xgmac register value");
1631
1632 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xpcs_mmd",
1633 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1634 pdata, 0, sysctl_xpcs_mmd_reg_handler, "IU", "xpcs mmd register");
1635
1636 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xpcs_register",
1637 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1638 pdata, 0, sysctl_xpcs_reg_addr_handler, "IU", "xpcs register");
1639
1640 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xpcs_register_value",
1641 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1642 pdata, 0, sysctl_xpcs_reg_value_handler, "IU",
1643 "xpcs register value");
1644
1645 if (pdata->xpcs_res) {
1646 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xprop_register",
1647 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1648 pdata, 0, sysctl_xprop_reg_addr_handler,
1649 "IU", "xprop register");
1650
1651 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xprop_register_value",
1652 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1653 pdata, 0, sysctl_xprop_reg_value_handler,
1654 "IU", "xprop register value");
1655 }
1656
1657 if (pdata->xpcs_res) {
1658 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xi2c_register",
1659 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1660 pdata, 0, sysctl_xi2c_reg_addr_handler,
1661 "IU", "xi2c register");
1662
1663 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xi2c_register_value",
1664 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1665 pdata, 0, sysctl_xi2c_reg_value_handler,
1666 "IU", "xi2c register value");
1667 }
1668
1669 if (pdata->vdata->an_cdr_workaround) {
1670 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "an_cdr_workaround",
1671 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1672 pdata, 0, sysctl_an_cdr_wr_handler, "IU",
1673 "an cdr workaround");
1674
1675 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "an_cdr_track_early",
1676 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1677 pdata, 0, sysctl_an_cdr_track_early_handler, "IU",
1678 "an cdr track early");
1679 }
1680
1681 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "drv_info",
1682 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1683 pdata, 0, sysctl_get_drv_info_handler, "IU",
1684 "xgbe drv info");
1685
1686 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "link_info",
1687 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1688 pdata, 0, sysctl_get_link_info_handler, "IU",
1689 "xgbe link info");
1690
1691 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "coalesce_info",
1692 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1693 pdata, 0, sysctl_coalesce_handler, "IU",
1694 "xgbe coalesce info");
1695
1696 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "pauseparam_info",
1697 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1698 pdata, 0, sysctl_pauseparam_handler, "IU",
1699 "xgbe pauseparam info");
1700
1701 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "link_ksettings_info",
1702 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1703 pdata, 0, sysctl_link_ksettings_handler, "IU",
1704 "xgbe link_ksettings info");
1705
1706 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "ringparam_info",
1707 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1708 pdata, 0, sysctl_ringparam_handler, "IU",
1709 "xgbe ringparam info");
1710
1711 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "channels_info",
1712 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1713 pdata, 0, sysctl_channels_handler, "IU",
1714 "xgbe channels info");
1715
1716 SYSCTL_ADD_PROC(clist, top, OID_AUTO, "mac_stats",
1717 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1718 pdata, 0, sysctl_mac_stats_handler, "IU",
1719 "xgbe mac stats");
1720 }
1721