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