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