Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/axgbe/xgbe-sysctl.c
Property | Old Value | New Value |
---|---|---|
svn:eol-style | null | native \ No newline at end of property |
svn:keywords | null | FreeBSD=%H \ No newline at end of property |
svn:mime-type | null | text/plain \ No newline at end of property |
/*- | |||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD | |||||
* | |||||
* Copyright (c) 2020 Advanced Micro Devices, Inc. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions | |||||
* are met: | |||||
* 1. Redistributions of source code must retain the above copyright | |||||
* notice, this list of conditions and the following disclaimer. | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
* SUCH DAMAGE. | |||||
* | |||||
* Contact Information : | |||||
* Rajesh Kumar <rajesh1.kumar@amd.com> | |||||
* Arpan Palit <Arpan.Palit@amd.com> | |||||
*/ | |||||
#include <sys/cdefs.h> | |||||
__FBSDID("$FreeBSD$"); | |||||
#include <sys/param.h> | |||||
#include <sys/sysctl.h> | |||||
#include <sys/sbuf.h> | |||||
#include "xgbe.h" | |||||
#include "xgbe-common.h" | |||||
#define SYSCTL_BUF_LEN 64 | |||||
typedef enum{ | |||||
/* Coalesce flag */ | |||||
rx_coalesce_usecs = 1, | |||||
rx_max_coalesced_frames, | |||||
rx_coalesce_usecs_irq, | |||||
rx_max_coalesced_frames_irq, | |||||
tx_coalesce_usecs, | |||||
tx_max_coalesced_frames, | |||||
tx_coalesce_usecs_irq, | |||||
tx_max_coalesced_frames_irq, | |||||
stats_block_coalesce_usecs, | |||||
use_adaptive_rx_coalesce, | |||||
use_adaptive_tx_coalesce, | |||||
pkt_rate_low, | |||||
rx_coalesce_usecs_low, | |||||
rx_max_coalesced_frames_low, | |||||
tx_coalesce_usecs_low, | |||||
tx_max_coalesced_frames_low, | |||||
pkt_rate_high, | |||||
rx_coalesce_usecs_high, | |||||
rx_max_coalesced_frames_high, | |||||
tx_coalesce_usecs_high, | |||||
tx_max_coalesced_frames_high, | |||||
rate_sample_interval, | |||||
/* Pasue flag */ | |||||
autoneg, | |||||
tx_pause, | |||||
rx_pause, | |||||
/* link settings */ | |||||
speed, | |||||
duplex, | |||||
/* Ring settings */ | |||||
rx_pending, | |||||
rx_mini_pending, | |||||
rx_jumbo_pending, | |||||
tx_pending, | |||||
/* Channels settings */ | |||||
rx_count, | |||||
tx_count, | |||||
other_count, | |||||
combined_count, | |||||
} sysctl_variable_t; | |||||
typedef enum { | |||||
SYSL_NONE, | |||||
SYSL_BOOL, | |||||
SYSL_S32, | |||||
SYSL_U8, | |||||
SYSL_U16, | |||||
SYSL_U32, | |||||
SYSL_U64, | |||||
SYSL_BE16, | |||||
SYSL_IP4, | |||||
SYSL_STR, | |||||
SYSL_FLAG, | |||||
SYSL_MAC, | |||||
} sysctl_type_t; | |||||
struct sysctl_info { | |||||
uint8_t name[32]; | |||||
sysctl_type_t type; | |||||
sysctl_variable_t flag; | |||||
uint8_t support[16]; | |||||
}; | |||||
struct sysctl_op { | |||||
/* Coalesce options */ | |||||
unsigned int rx_coalesce_usecs; | |||||
unsigned int rx_max_coalesced_frames; | |||||
unsigned int rx_coalesce_usecs_irq; | |||||
unsigned int rx_max_coalesced_frames_irq; | |||||
unsigned int tx_coalesce_usecs; | |||||
unsigned int tx_max_coalesced_frames; | |||||
unsigned int tx_coalesce_usecs_irq; | |||||
unsigned int tx_max_coalesced_frames_irq; | |||||
unsigned int stats_block_coalesce_usecs; | |||||
unsigned int use_adaptive_rx_coalesce; | |||||
unsigned int use_adaptive_tx_coalesce; | |||||
unsigned int pkt_rate_low; | |||||
unsigned int rx_coalesce_usecs_low; | |||||
unsigned int rx_max_coalesced_frames_low; | |||||
unsigned int tx_coalesce_usecs_low; | |||||
unsigned int tx_max_coalesced_frames_low; | |||||
unsigned int pkt_rate_high; | |||||
unsigned int rx_coalesce_usecs_high; | |||||
unsigned int rx_max_coalesced_frames_high; | |||||
unsigned int tx_coalesce_usecs_high; | |||||
unsigned int tx_max_coalesced_frames_high; | |||||
unsigned int rate_sample_interval; | |||||
/* Pasue options */ | |||||
unsigned int autoneg; | |||||
unsigned int tx_pause; | |||||
unsigned int rx_pause; | |||||
/* Link settings options */ | |||||
unsigned int speed; | |||||
unsigned int duplex; | |||||
/* Ring param options */ | |||||
unsigned int rx_max_pending; | |||||
unsigned int rx_mini_max_pending; | |||||
unsigned int rx_jumbo_max_pending; | |||||
unsigned int tx_max_pending; | |||||
unsigned int rx_pending; | |||||
unsigned int rx_mini_pending; | |||||
unsigned int rx_jumbo_pending; | |||||
unsigned int tx_pending; | |||||
/* Channels options */ | |||||
unsigned int max_rx; | |||||
unsigned int max_tx; | |||||
unsigned int max_other; | |||||
unsigned int max_combined; | |||||
unsigned int rx_count; | |||||
unsigned int tx_count; | |||||
unsigned int other_count; | |||||
unsigned int combined_count; | |||||
} sys_op; | |||||
#define GSTRING_LEN 32 | |||||
struct xgbe_stats { | |||||
char stat_string[GSTRING_LEN]; | |||||
int stat_size; | |||||
int stat_offset; | |||||
}; | |||||
#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) | |||||
#define XGMAC_MMC_STAT(_string, _var) \ | |||||
{ _string, \ | |||||
FIELD_SIZEOF(struct xgbe_mmc_stats, _var), \ | |||||
offsetof(struct xgbe_prv_data, mmc_stats._var), \ | |||||
} | |||||
#define XGMAC_EXT_STAT(_string, _var) \ | |||||
{ _string, \ | |||||
FIELD_SIZEOF(struct xgbe_ext_stats, _var), \ | |||||
offsetof(struct xgbe_prv_data, ext_stats._var), \ | |||||
} | |||||
static const struct xgbe_stats xgbe_gstring_stats[] = { | |||||
XGMAC_MMC_STAT("tx_bytes", txoctetcount_gb), | |||||
XGMAC_MMC_STAT("tx_packets", txframecount_gb), | |||||
XGMAC_MMC_STAT("tx_unicast_packets", txunicastframes_gb), | |||||
XGMAC_MMC_STAT("tx_broadcast_packets", txbroadcastframes_gb), | |||||
XGMAC_MMC_STAT("tx_multicast_packets", txmulticastframes_gb), | |||||
XGMAC_MMC_STAT("tx_vlan_packets", txvlanframes_g), | |||||
XGMAC_EXT_STAT("tx_vxlan_packets", tx_vxlan_packets), | |||||
XGMAC_EXT_STAT("tx_tso_packets", tx_tso_packets), | |||||
XGMAC_MMC_STAT("tx_64_byte_packets", tx64octets_gb), | |||||
XGMAC_MMC_STAT("tx_65_to_127_byte_packets", tx65to127octets_gb), | |||||
XGMAC_MMC_STAT("tx_128_to_255_byte_packets", tx128to255octets_gb), | |||||
XGMAC_MMC_STAT("tx_256_to_511_byte_packets", tx256to511octets_gb), | |||||
XGMAC_MMC_STAT("tx_512_to_1023_byte_packets", tx512to1023octets_gb), | |||||
XGMAC_MMC_STAT("tx_1024_to_max_byte_packets", tx1024tomaxoctets_gb), | |||||
XGMAC_MMC_STAT("tx_underflow_errors", txunderflowerror), | |||||
XGMAC_MMC_STAT("tx_pause_frames", txpauseframes), | |||||
XGMAC_MMC_STAT("rx_bytes", rxoctetcount_gb), | |||||
XGMAC_MMC_STAT("rx_packets", rxframecount_gb), | |||||
XGMAC_MMC_STAT("rx_unicast_packets", rxunicastframes_g), | |||||
XGMAC_MMC_STAT("rx_broadcast_packets", rxbroadcastframes_g), | |||||
XGMAC_MMC_STAT("rx_multicast_packets", rxmulticastframes_g), | |||||
XGMAC_MMC_STAT("rx_vlan_packets", rxvlanframes_gb), | |||||
XGMAC_EXT_STAT("rx_vxlan_packets", rx_vxlan_packets), | |||||
XGMAC_MMC_STAT("rx_64_byte_packets", rx64octets_gb), | |||||
XGMAC_MMC_STAT("rx_65_to_127_byte_packets", rx65to127octets_gb), | |||||
XGMAC_MMC_STAT("rx_128_to_255_byte_packets", rx128to255octets_gb), | |||||
XGMAC_MMC_STAT("rx_256_to_511_byte_packets", rx256to511octets_gb), | |||||
XGMAC_MMC_STAT("rx_512_to_1023_byte_packets", rx512to1023octets_gb), | |||||
XGMAC_MMC_STAT("rx_1024_to_max_byte_packets", rx1024tomaxoctets_gb), | |||||
XGMAC_MMC_STAT("rx_undersize_packets", rxundersize_g), | |||||
XGMAC_MMC_STAT("rx_oversize_packets", rxoversize_g), | |||||
XGMAC_MMC_STAT("rx_crc_errors", rxcrcerror), | |||||
XGMAC_MMC_STAT("rx_crc_errors_small_packets", rxrunterror), | |||||
XGMAC_MMC_STAT("rx_crc_errors_giant_packets", rxjabbererror), | |||||
XGMAC_MMC_STAT("rx_length_errors", rxlengtherror), | |||||
XGMAC_MMC_STAT("rx_out_of_range_errors", rxoutofrangetype), | |||||
XGMAC_MMC_STAT("rx_fifo_overflow_errors", rxfifooverflow), | |||||
XGMAC_MMC_STAT("rx_watchdog_errors", rxwatchdogerror), | |||||
XGMAC_EXT_STAT("rx_csum_errors", rx_csum_errors), | |||||
XGMAC_EXT_STAT("rx_vxlan_csum_errors", rx_vxlan_csum_errors), | |||||
XGMAC_MMC_STAT("rx_pause_frames", rxpauseframes), | |||||
XGMAC_EXT_STAT("rx_split_header_packets", rx_split_header_packets), | |||||
XGMAC_EXT_STAT("rx_buffer_unavailable", rx_buffer_unavailable), | |||||
}; | |||||
#define XGBE_STATS_COUNT ARRAY_SIZE(xgbe_gstring_stats) | |||||
char** alloc_sysctl_buffer(void); | |||||
void get_val(char *buf, char **op, char **val, int *n_op); | |||||
void fill_data(struct sysctl_op *sys_op, int flag, unsigned int value); | |||||
static int | |||||
exit_bad_op(void) | |||||
{ | |||||
printf("SYSCTL: bad command line option (s)\n"); | |||||
return(-EINVAL); | |||||
} | |||||
static inline unsigned | |||||
fls_long(unsigned long l) | |||||
{ | |||||
if (sizeof(l) == 4) | |||||
return (fls(l)); | |||||
return (fls64(l)); | |||||
} | |||||
static inline __attribute__((const)) | |||||
unsigned long __rounddown_pow_of_two(unsigned long n) | |||||
{ | |||||
return (1UL << (fls_long(n) - 1)); | |||||
} | |||||
static inline int | |||||
get_ubuf(struct sysctl_req *req, char *ubuf) | |||||
{ | |||||
int rc; | |||||
printf("%s: len:0x%li idx:0x%li\n", __func__, req->newlen, | |||||
req->newidx); | |||||
if (req->newlen >= SYSCTL_BUF_LEN) | |||||
return (-EINVAL); | |||||
rc = SYSCTL_IN(req, ubuf, req->newlen); | |||||
if (rc) | |||||
return (rc); | |||||
ubuf[req->newlen] = '\0'; | |||||
return (0); | |||||
} | |||||
char** | |||||
alloc_sysctl_buffer(void) | |||||
{ | |||||
char **buffer; | |||||
int i; | |||||
buffer = malloc(sizeof(char *)*32, M_AXGBE, M_WAITOK | M_ZERO); | |||||
for(i = 0; i < 32; i++) | |||||
buffer[i] = malloc(sizeof(char)*32, M_AXGBE, M_WAITOK | M_ZERO); | |||||
return (buffer); | |||||
} | |||||
void | |||||
get_val(char *buf, char **op, char **val, int *n_op) | |||||
{ | |||||
int blen = strlen(buf); | |||||
int count = 0; | |||||
int i, j; | |||||
*n_op = 0; | |||||
for (i = 0; i < blen; i++) { | |||||
count++; | |||||
/* Get sysctl command option */ | |||||
for (j = 0; buf[i] != ' '; j++) { | |||||
if (i >= blen) | |||||
break; | |||||
op[*n_op][j] = buf[i++]; | |||||
} | |||||
op[*n_op][j+1] = '\0'; | |||||
if (i >= strlen(buf)) | |||||
goto out; | |||||
/* Get sysctl value*/ | |||||
i++; | |||||
for (j = 0; buf[i] != ' '; j++) { | |||||
if (i >= blen) | |||||
break; | |||||
val[*n_op][j] = buf[i++]; | |||||
} | |||||
val[*n_op][j+1] = '\0'; | |||||
if (i >= strlen(buf)) | |||||
goto out; | |||||
*n_op = count; | |||||
} | |||||
out: | |||||
*n_op = count; | |||||
} | |||||
void | |||||
fill_data(struct sysctl_op *sys_op, int flag, unsigned int value) | |||||
{ | |||||
switch(flag) { | |||||
case 1: | |||||
sys_op->rx_coalesce_usecs = value; | |||||
break; | |||||
case 2: | |||||
sys_op->rx_max_coalesced_frames = value; | |||||
break; | |||||
case 3: | |||||
sys_op->rx_coalesce_usecs_irq = value; | |||||
break; | |||||
case 4: | |||||
sys_op->rx_max_coalesced_frames_irq = value; | |||||
break; | |||||
case 5: | |||||
sys_op->tx_coalesce_usecs = value; | |||||
break; | |||||
case 6: | |||||
sys_op->tx_max_coalesced_frames = value; | |||||
break; | |||||
case 7: | |||||
sys_op->tx_coalesce_usecs_irq = value; | |||||
break; | |||||
case 8: | |||||
sys_op->tx_max_coalesced_frames_irq = value; | |||||
break; | |||||
case 9: | |||||
sys_op->stats_block_coalesce_usecs = value; | |||||
break; | |||||
case 10: | |||||
sys_op->use_adaptive_rx_coalesce = value; | |||||
break; | |||||
case 11: | |||||
sys_op->use_adaptive_tx_coalesce = value; | |||||
break; | |||||
case 12: | |||||
sys_op->pkt_rate_low = value; | |||||
break; | |||||
case 13: | |||||
sys_op->rx_coalesce_usecs_low = value; | |||||
break; | |||||
case 14: | |||||
sys_op->rx_max_coalesced_frames_low = value; | |||||
break; | |||||
case 15: | |||||
sys_op->tx_coalesce_usecs_low = value; | |||||
break; | |||||
case 16: | |||||
sys_op->tx_max_coalesced_frames_low = value; | |||||
break; | |||||
case 17: | |||||
sys_op->pkt_rate_high = value; | |||||
break; | |||||
case 18: | |||||
sys_op->rx_coalesce_usecs_high = value; | |||||
break; | |||||
case 19: | |||||
sys_op->rx_max_coalesced_frames_high = value; | |||||
break; | |||||
case 20: | |||||
sys_op->tx_coalesce_usecs_high = value; | |||||
break; | |||||
case 21: | |||||
sys_op->tx_max_coalesced_frames_high = value; | |||||
break; | |||||
case 22: | |||||
sys_op->rate_sample_interval = value; | |||||
break; | |||||
case 23: | |||||
sys_op->autoneg = value; | |||||
break; | |||||
case 24: | |||||
sys_op->rx_pause = value; | |||||
break; | |||||
case 25: | |||||
sys_op->tx_pause = value; | |||||
break; | |||||
case 26: | |||||
sys_op->speed = value; | |||||
break; | |||||
case 27: | |||||
sys_op->duplex = value; | |||||
break; | |||||
case 28: | |||||
sys_op->rx_pending = value; | |||||
break; | |||||
case 29: | |||||
sys_op->rx_mini_pending = value; | |||||
break; | |||||
case 30: | |||||
sys_op->rx_jumbo_pending = value; | |||||
break; | |||||
case 31: | |||||
sys_op->tx_pending = value; | |||||
break; | |||||
default: | |||||
printf("Option error\n"); | |||||
} | |||||
} | |||||
static int | |||||
parse_generic_sysctl(struct xgbe_prv_data *pdata, char *buf, | |||||
struct sysctl_info *info, unsigned int n_info) | |||||
{ | |||||
struct sysctl_op *sys_op = pdata->sys_op; | |||||
unsigned int value; | |||||
char **op, **val; | |||||
int n_op = 0; | |||||
int rc = 0; | |||||
int i, idx; | |||||
op = alloc_sysctl_buffer(); | |||||
val = alloc_sysctl_buffer(); | |||||
get_val(buf, op, val, &n_op); | |||||
for (i = 0; i < n_op; i++) { | |||||
for (idx = 0; idx < n_info; idx++) { | |||||
if (strcmp(info[idx].name, op[i]) == 0) { | |||||
if (strcmp(info[idx].support, | |||||
"not-supported") == 0){ | |||||
axgbe_printf(1, "ignoring not-supported " | |||||
"option \"%s\"\n", info[idx].name); | |||||
break; | |||||
} | |||||
switch(info[idx].type) { | |||||
case SYSL_BOOL: { | |||||
if (!strcmp(val[i], "on")) | |||||
fill_data(sys_op, | |||||
info[idx].flag, 1); | |||||
else if (!strcmp(val[i], "off")) | |||||
fill_data(sys_op, | |||||
info[idx].flag, 0); | |||||
else | |||||
rc = exit_bad_op(); | |||||
break; | |||||
} | |||||
case SYSL_S32: | |||||
sscanf(val[i], "%u", &value); | |||||
fill_data(sys_op, info[idx].flag, value); | |||||
break; | |||||
case SYSL_U8: | |||||
if (!strcmp(val[i], "half")) | |||||
fill_data(sys_op, | |||||
info[idx].flag, DUPLEX_HALF); | |||||
else if (!strcmp(val[i], "full")) | |||||
fill_data(sys_op, | |||||
info[idx].flag, DUPLEX_FULL); | |||||
else | |||||
exit_bad_op(); | |||||
default: | |||||
rc = exit_bad_op(); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
for(i = 0; i < 32; i++) | |||||
free(op[i], M_AXGBE); | |||||
free(op, M_AXGBE); | |||||
for(i = 0; i < 32; i++) | |||||
free(val[i], M_AXGBE); | |||||
free(val, M_AXGBE); | |||||
return (rc); | |||||
} | |||||
static int | |||||
sysctl_xgmac_reg_addr_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; | |||||
ssize_t buf_size = 64; | |||||
char buf[buf_size]; | |||||
struct sbuf *sb; | |||||
unsigned int reg; | |||||
int rc = 0; | |||||
if (req->newptr == NULL) { | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); | |||||
if (sb == NULL) { | |||||
rc = sb->s_error; | |||||
return (rc); | |||||
} | |||||
axgbe_printf(2, "READ: %s: sysctl_xgmac_reg: 0x%x\n", __func__, | |||||
pdata->sysctl_xgmac_reg); | |||||
sbuf_printf(sb, "\nXGMAC reg_addr: 0x%x\n", | |||||
pdata->sysctl_xgmac_reg); | |||||
rc = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (rc); | |||||
} | |||||
rc = get_ubuf(req, buf); | |||||
if (rc == 0) { | |||||
sscanf(buf, "%x", ®); | |||||
axgbe_printf(2, "WRITE: %s: reg: 0x%x\n", __func__, reg); | |||||
pdata->sysctl_xgmac_reg = reg; | |||||
} | |||||
axgbe_printf(2, "%s: rc= %d\n", __func__, rc); | |||||
return (rc); | |||||
} | |||||
static int | |||||
sysctl_get_drv_info_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; | |||||
struct xgbe_hw_features *hw_feat = &pdata->hw_feat; | |||||
ssize_t buf_size = 64; | |||||
struct sbuf *sb; | |||||
int rc = 0; | |||||
if (req->newptr == NULL) { | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); | |||||
if (sb == NULL) { | |||||
rc = sb->s_error; | |||||
return (rc); | |||||
} | |||||
sbuf_printf(sb, "\ndriver: %s", XGBE_DRV_NAME); | |||||
sbuf_printf(sb, "\nversion: %s", XGBE_DRV_VERSION); | |||||
sbuf_printf(sb, "\nfirmware-version: %d.%d.%d", | |||||
XGMAC_GET_BITS(hw_feat->version, MAC_VR, USERVER), | |||||
XGMAC_GET_BITS(hw_feat->version, MAC_VR, DEVID), | |||||
XGMAC_GET_BITS(hw_feat->version, MAC_VR, SNPSVER)); | |||||
sbuf_printf(sb, "\nbus-info: %04d:%02d:%02d", | |||||
pdata->pcie_bus, pdata->pcie_device, pdata->pcie_func); | |||||
rc = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (rc); | |||||
} | |||||
return (-EINVAL); | |||||
} | |||||
static int | |||||
sysctl_get_link_info_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; | |||||
ssize_t buf_size = 64; | |||||
struct sbuf *sb; | |||||
int rc = 0; | |||||
if (req->newptr == NULL) { | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); | |||||
if (sb == NULL) { | |||||
rc = sb->s_error; | |||||
return (rc); | |||||
} | |||||
sbuf_printf(sb, "\nLink is %s", pdata->phy.link ? "Up" : "Down"); | |||||
rc = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (0); | |||||
} | |||||
return (-EINVAL); | |||||
} | |||||
#define COALESCE_SYSCTL_INFO(__coalop) \ | |||||
{ \ | |||||
{ "adaptive-rx", SYSL_BOOL, use_adaptive_rx_coalesce, "not-supported" }, \ | |||||
{ "adaptive-tx", SYSL_BOOL, use_adaptive_tx_coalesce, "not-supported" }, \ | |||||
{ "sample-interval", SYSL_S32, rate_sample_interval, "not-supported" }, \ | |||||
{ "stats-block-usecs", SYSL_S32, stats_block_coalesce_usecs, "not-supported" }, \ | |||||
{ "pkt-rate-low", SYSL_S32, pkt_rate_low, "not-supported" }, \ | |||||
{ "pkt-rate-high", SYSL_S32, pkt_rate_high, "not-supported" }, \ | |||||
{ "rx-usecs", SYSL_S32, rx_coalesce_usecs, "supported" }, \ | |||||
{ "rx-frames", SYSL_S32, rx_max_coalesced_frames, "supported" }, \ | |||||
{ "rx-usecs-irq", SYSL_S32, rx_coalesce_usecs_irq, "not-supported" }, \ | |||||
{ "rx-frames-irq", SYSL_S32, rx_max_coalesced_frames_irq, "not-supported" }, \ | |||||
{ "tx-usecs", SYSL_S32, tx_coalesce_usecs, "not-supported" }, \ | |||||
{ "tx-frames", SYSL_S32, tx_max_coalesced_frames, "supported" }, \ | |||||
{ "tx-usecs-irq", SYSL_S32, tx_coalesce_usecs_irq, "not-supported" }, \ | |||||
{ "tx-frames-irq", SYSL_S32, tx_max_coalesced_frames_irq, "not-supported" }, \ | |||||
{ "rx-usecs-low", SYSL_S32, rx_coalesce_usecs_low, "not-supported" }, \ | |||||
{ "rx-frames-low", SYSL_S32, rx_max_coalesced_frames_low, "not-supported"}, \ | |||||
{ "tx-usecs-low", SYSL_S32, tx_coalesce_usecs_low, "not-supported" }, \ | |||||
{ "tx-frames-low", SYSL_S32, tx_max_coalesced_frames_low, "not-supported" }, \ | |||||
{ "rx-usecs-high", SYSL_S32, rx_coalesce_usecs_high, "not-supported" }, \ | |||||
{ "rx-frames-high", SYSL_S32, rx_max_coalesced_frames_high, "not-supported" }, \ | |||||
{ "tx-usecs-high", SYSL_S32, tx_coalesce_usecs_high, "not-supported" }, \ | |||||
{ "tx-frames-high", SYSL_S32, tx_max_coalesced_frames_high, "not-supported" }, \ | |||||
} | |||||
static int | |||||
sysctl_coalesce_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; | |||||
struct xgbe_hw_if *hw_if = &pdata->hw_if; | |||||
struct sysctl_op *sys_op = pdata->sys_op; | |||||
struct sysctl_info sysctl_coalesce[] = COALESCE_SYSCTL_INFO(coalop); | |||||
unsigned int rx_frames, rx_riwt, rx_usecs; | |||||
unsigned int tx_frames; | |||||
ssize_t buf_size = 64; | |||||
char buf[buf_size]; | |||||
struct sbuf *sb; | |||||
int rc = 0; | |||||
if (req->newptr == NULL) { | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); | |||||
if (sb == NULL) { | |||||
rc = sb->s_error; | |||||
return (rc); | |||||
} | |||||
sys_op->rx_coalesce_usecs = pdata->rx_usecs; | |||||
sys_op->rx_max_coalesced_frames = pdata->rx_frames; | |||||
sys_op->tx_max_coalesced_frames = pdata->tx_frames; | |||||
sbuf_printf(sb, "\nAdaptive RX: %s TX: %s\n", | |||||
sys_op->use_adaptive_rx_coalesce ? "on" : "off", | |||||
sys_op->use_adaptive_tx_coalesce ? "on" : "off"); | |||||
sbuf_printf(sb, "stats-block-usecs: %u\n" | |||||
"sample-interval: %u\n" | |||||
"pkt-rate-low: %u\n" | |||||
"pkt-rate-high: %u\n" | |||||
"\n" | |||||
"rx-usecs: %u\n" | |||||
"rx-frames: %u\n" | |||||
"rx-usecs-irq: %u\n" | |||||
"rx-frames-irq: %u\n" | |||||
"\n" | |||||
"tx-usecs: %u\n" | |||||
"tx-frames: %u\n" | |||||
"tx-usecs-irq: %u\n" | |||||
"tx-frames-irq: %u\n" | |||||
"\n" | |||||
"rx-usecs-low: %u\n" | |||||
"rx-frames-low: %u\n" | |||||
"tx-usecs-low: %u\n" | |||||
"tx-frames-low: %u\n" | |||||
"\n" | |||||
"rx-usecs-high: %u\n" | |||||
"rx-frames-high: %u\n" | |||||
"tx-usecs-high: %u\n" | |||||
"tx-frames-high: %u\n", | |||||
sys_op->stats_block_coalesce_usecs, | |||||
sys_op->rate_sample_interval, | |||||
sys_op->pkt_rate_low, | |||||
sys_op->pkt_rate_high, | |||||
sys_op->rx_coalesce_usecs, | |||||
sys_op->rx_max_coalesced_frames, | |||||
sys_op->rx_coalesce_usecs_irq, | |||||
sys_op->rx_max_coalesced_frames_irq, | |||||
sys_op->tx_coalesce_usecs, | |||||
sys_op->tx_max_coalesced_frames, | |||||
sys_op->tx_coalesce_usecs_irq, | |||||
sys_op->tx_max_coalesced_frames_irq, | |||||
sys_op->rx_coalesce_usecs_low, | |||||
sys_op->rx_max_coalesced_frames_low, | |||||
sys_op->tx_coalesce_usecs_low, | |||||
sys_op->tx_max_coalesced_frames_low, | |||||
sys_op->rx_coalesce_usecs_high, | |||||
sys_op->rx_max_coalesced_frames_high, | |||||
sys_op->tx_coalesce_usecs_high, | |||||
sys_op->tx_max_coalesced_frames_high); | |||||
rc = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (0); | |||||
} | |||||
rc = get_ubuf(req, buf); | |||||
if (rc == 0) { | |||||
parse_generic_sysctl(pdata, buf, sysctl_coalesce, | |||||
ARRAY_SIZE(sysctl_coalesce)); | |||||
rx_riwt = hw_if->usec_to_riwt(pdata, sys_op->rx_coalesce_usecs); | |||||
rx_usecs = sys_op->rx_coalesce_usecs; | |||||
rx_frames = sys_op->rx_max_coalesced_frames; | |||||
/* Use smallest possible value if conversion resulted in zero */ | |||||
if (rx_usecs && !rx_riwt) | |||||
rx_riwt = 1; | |||||
/* Check the bounds of values for Rx */ | |||||
if (rx_riwt > XGMAC_MAX_DMA_RIWT) { | |||||
axgbe_printf(2, "rx-usec is limited to %d usecs\n", | |||||
hw_if->riwt_to_usec(pdata, XGMAC_MAX_DMA_RIWT)); | |||||
return (-EINVAL); | |||||
} | |||||
if (rx_frames > pdata->rx_desc_count) { | |||||
axgbe_printf(2, "rx-frames is limited to %d frames\n", | |||||
pdata->rx_desc_count); | |||||
return (-EINVAL); | |||||
} | |||||
tx_frames = sys_op->tx_max_coalesced_frames; | |||||
/* Check the bounds of values for Tx */ | |||||
if (tx_frames > pdata->tx_desc_count) { | |||||
axgbe_printf(2, "tx-frames is limited to %d frames\n", | |||||
pdata->tx_desc_count); | |||||
return (-EINVAL); | |||||
} | |||||
pdata->rx_riwt = rx_riwt; | |||||
pdata->rx_usecs = rx_usecs; | |||||
pdata->rx_frames = rx_frames; | |||||
hw_if->config_rx_coalesce(pdata); | |||||
pdata->tx_frames = tx_frames; | |||||
hw_if->config_tx_coalesce(pdata); | |||||
} | |||||
axgbe_printf(2, "%s: rc= %d\n", __func__, rc); | |||||
return (rc); | |||||
} | |||||
static int | |||||
sysctl_pauseparam_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; | |||||
struct sysctl_op *sys_op = pdata->sys_op; | |||||
struct sysctl_info sysctl_pauseparam[] = { | |||||
{ "autoneg", SYSL_BOOL, autoneg, "supported" }, | |||||
{ "rx", SYSL_BOOL, rx_pause, "supported" }, | |||||
{ "tx", SYSL_BOOL, tx_pause, "supported" }, | |||||
}; | |||||
ssize_t buf_size = 512; | |||||
char buf[buf_size]; | |||||
struct sbuf *sb; | |||||
int rc = 0; | |||||
if (req->newptr == NULL) { | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); | |||||
if (sb == NULL) { | |||||
rc = sb->s_error; | |||||
return (rc); | |||||
} | |||||
sys_op->autoneg = pdata->phy.pause_autoneg; | |||||
sys_op->tx_pause = pdata->phy.tx_pause; | |||||
sys_op->rx_pause = pdata->phy.rx_pause; | |||||
sbuf_printf(sb, | |||||
"\nAutonegotiate: %s\n" | |||||
"RX: %s\n" | |||||
"TX: %s\n", | |||||
sys_op->autoneg ? "on" : "off", | |||||
sys_op->rx_pause ? "on" : "off", | |||||
sys_op->tx_pause ? "on" : "off"); | |||||
if (pdata->phy.lp_advertising) { | |||||
int an_rx = 0, an_tx = 0; | |||||
if (pdata->phy.advertising & pdata->phy.lp_advertising & | |||||
ADVERTISED_Pause) { | |||||
an_tx = 1; | |||||
an_rx = 1; | |||||
} else if (pdata->phy.advertising & | |||||
pdata->phy.lp_advertising & ADVERTISED_Asym_Pause) { | |||||
if (pdata->phy.advertising & ADVERTISED_Pause) | |||||
an_rx = 1; | |||||
else if (pdata->phy.lp_advertising & | |||||
ADVERTISED_Pause) | |||||
an_tx = 1; | |||||
} | |||||
sbuf_printf(sb, | |||||
"\n->\nRX negotiated: %s\n" | |||||
"TX negotiated: %s\n", | |||||
an_rx ? "on" : "off", | |||||
an_tx ? "on" : "off"); | |||||
} | |||||
rc = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (0); | |||||
} | |||||
rc = get_ubuf(req, buf); | |||||
if (rc == 0) { | |||||
parse_generic_sysctl(pdata, buf, sysctl_pauseparam, | |||||
ARRAY_SIZE(sysctl_pauseparam)); | |||||
if (sys_op->autoneg && (pdata->phy.autoneg != AUTONEG_ENABLE)) { | |||||
axgbe_error("autoneg disabled, pause autoneg not available\n"); | |||||
return (-EINVAL); | |||||
} | |||||
pdata->phy.pause_autoneg = sys_op->autoneg; | |||||
pdata->phy.tx_pause = sys_op->tx_pause; | |||||
pdata->phy.rx_pause = sys_op->rx_pause; | |||||
XGBE_CLR_ADV(&pdata->phy, Pause); | |||||
XGBE_CLR_ADV(&pdata->phy, Asym_Pause); | |||||
if (sys_op->rx_pause) { | |||||
XGBE_SET_ADV(&pdata->phy, Pause); | |||||
XGBE_SET_ADV(&pdata->phy, Asym_Pause); | |||||
} | |||||
if (sys_op->tx_pause) { | |||||
/* Equivalent to XOR of Asym_Pause */ | |||||
if (XGBE_ADV(&pdata->phy, Asym_Pause)) | |||||
XGBE_CLR_ADV(&pdata->phy, Asym_Pause); | |||||
else | |||||
XGBE_SET_ADV(&pdata->phy, Asym_Pause); | |||||
} | |||||
if (test_bit(XGBE_LINK_INIT, &pdata->dev_state)) | |||||
rc = pdata->phy_if.phy_config_aneg(pdata); | |||||
} | |||||
return (rc); | |||||
} | |||||
static int | |||||
sysctl_link_ksettings_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; | |||||
struct sysctl_op *sys_op = pdata->sys_op; | |||||
struct sysctl_info sysctl_linksettings[] = { | |||||
{ "autoneg", SYSL_BOOL, autoneg, "supported" }, | |||||
{ "speed", SYSL_U32, speed, "supported" }, | |||||
{ "duplex", SYSL_U8, duplex, "supported" }, | |||||
}; | |||||
ssize_t buf_size = 512; | |||||
char buf[buf_size], link_modes[16], speed_modes[16]; | |||||
struct sbuf *sb; | |||||
uint32_t speed; | |||||
int rc = 0; | |||||
if (req->newptr == NULL) { | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); | |||||
if (sb == NULL) { | |||||
rc = sb->s_error; | |||||
return (rc); | |||||
} | |||||
sys_op->autoneg = pdata->phy.autoneg; | |||||
sys_op->speed = pdata->phy.speed; | |||||
sys_op->duplex = pdata->phy.duplex; | |||||
XGBE_LM_COPY(&pdata->phy, supported, &pdata->phy, supported); | |||||
XGBE_LM_COPY(&pdata->phy, advertising, &pdata->phy, advertising); | |||||
XGBE_LM_COPY(&pdata->phy, lp_advertising, &pdata->phy, lp_advertising); | |||||
switch (sys_op->speed) { | |||||
case 1: | |||||
strcpy(link_modes, "Unknown"); | |||||
strcpy(speed_modes, "Unknown"); | |||||
break; | |||||
case 2: | |||||
strcpy(link_modes, "10Gbps/Full"); | |||||
strcpy(speed_modes, "10000"); | |||||
break; | |||||
case 3: | |||||
strcpy(link_modes, "2.5Gbps/Full"); | |||||
strcpy(speed_modes, "2500"); | |||||
break; | |||||
case 4: | |||||
strcpy(link_modes, "1Gbps/Full"); | |||||
strcpy(speed_modes, "1000"); | |||||
break; | |||||
case 5: | |||||
strcpy(link_modes, "100Mbps/Full"); | |||||
strcpy(speed_modes, "100"); | |||||
break; | |||||
case 6: | |||||
strcpy(link_modes, "10Mbps/Full"); | |||||
strcpy(speed_modes, "10"); | |||||
break; | |||||
} | |||||
sbuf_printf(sb, | |||||
"\nlink_modes: %s\n" | |||||
"autonegotiation: %s\n" | |||||
"speed: %sMbps\n", | |||||
link_modes, | |||||
(sys_op->autoneg == AUTONEG_DISABLE) ? "off" : "on", | |||||
speed_modes); | |||||
switch (sys_op->duplex) { | |||||
case DUPLEX_HALF: | |||||
sbuf_printf(sb, "Duplex: Half\n"); | |||||
break; | |||||
case DUPLEX_FULL: | |||||
sbuf_printf(sb, "Duplex: Full\n"); | |||||
break; | |||||
default: | |||||
sbuf_printf(sb, "Duplex: Unknown\n"); | |||||
break; | |||||
} | |||||
rc = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (0); | |||||
} | |||||
rc = get_ubuf(req, buf); | |||||
if (rc == 0) { | |||||
parse_generic_sysctl(pdata, buf, sysctl_linksettings, | |||||
ARRAY_SIZE(sysctl_linksettings)); | |||||
speed = sys_op->speed; | |||||
if ((sys_op->autoneg != AUTONEG_ENABLE) && | |||||
(sys_op->autoneg != AUTONEG_DISABLE)) { | |||||
axgbe_error("unsupported autoneg %hhu\n", | |||||
(unsigned char)sys_op->autoneg); | |||||
return (-EINVAL); | |||||
} | |||||
if (sys_op->autoneg == AUTONEG_DISABLE) { | |||||
if (!pdata->phy_if.phy_valid_speed(pdata, speed)) { | |||||
axgbe_error("unsupported speed %u\n", speed); | |||||
return (-EINVAL); | |||||
} | |||||
if (sys_op->duplex != DUPLEX_FULL) { | |||||
axgbe_error("unsupported duplex %hhu\n", | |||||
(unsigned char)sys_op->duplex); | |||||
return (-EINVAL); | |||||
} | |||||
} | |||||
pdata->phy.autoneg = sys_op->autoneg; | |||||
pdata->phy.speed = speed; | |||||
pdata->phy.duplex = sys_op->duplex; | |||||
if (sys_op->autoneg == AUTONEG_ENABLE) | |||||
XGBE_SET_ADV(&pdata->phy, Autoneg); | |||||
else | |||||
XGBE_CLR_ADV(&pdata->phy, Autoneg); | |||||
if (test_bit(XGBE_LINK_INIT, &pdata->dev_state)) | |||||
rc = pdata->phy_if.phy_config_aneg(pdata); | |||||
} | |||||
return (rc); | |||||
} | |||||
static int | |||||
sysctl_ringparam_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; | |||||
struct sysctl_op *sys_op = pdata->sys_op; | |||||
struct sysctl_info sysctl_ringparam[] = { | |||||
{ "rx", SYSL_S32, rx_pending, "supported" }, | |||||
{ "rx-mini", SYSL_S32, rx_mini_pending, "supported" }, | |||||
{ "rx-jumbo", SYSL_S32, rx_jumbo_pending, "supported" }, | |||||
{ "tx", SYSL_S32, tx_pending, "supported" }, | |||||
}; | |||||
ssize_t buf_size = 512; | |||||
unsigned int rx, tx; | |||||
char buf[buf_size]; | |||||
struct sbuf *sb; | |||||
int rc = 0; | |||||
if (req->newptr == NULL) { | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); | |||||
if (sb == NULL) { | |||||
rc = sb->s_error; | |||||
return (rc); | |||||
} | |||||
sys_op->rx_max_pending = XGBE_RX_DESC_CNT_MAX; | |||||
sys_op->tx_max_pending = XGBE_TX_DESC_CNT_MAX; | |||||
sys_op->rx_pending = pdata->rx_desc_count; | |||||
sys_op->tx_pending = pdata->tx_desc_count; | |||||
sbuf_printf(sb, | |||||
"\nPre-set maximums:\n" | |||||
"RX: %u\n" | |||||
"RX Mini: %u\n" | |||||
"RX Jumbo: %u\n" | |||||
"TX: %u\n", | |||||
sys_op->rx_max_pending, | |||||
sys_op->rx_mini_max_pending, | |||||
sys_op->rx_jumbo_max_pending, | |||||
sys_op->tx_max_pending); | |||||
sbuf_printf(sb, | |||||
"\nCurrent hardware settings:\n" | |||||
"RX: %u\n" | |||||
"RX Mini: %u\n" | |||||
"RX Jumbo: %u\n" | |||||
"TX: %u\n", | |||||
sys_op->rx_pending, | |||||
sys_op->rx_mini_pending, | |||||
sys_op->rx_jumbo_pending, | |||||
sys_op->tx_pending); | |||||
rc = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (0); | |||||
} | |||||
rc = get_ubuf(req, buf); | |||||
if (rc == 0) { | |||||
parse_generic_sysctl(pdata, buf, sysctl_ringparam, | |||||
ARRAY_SIZE(sysctl_ringparam)); | |||||
if (sys_op->rx_mini_pending || sys_op->rx_jumbo_pending) { | |||||
axgbe_error("unsupported ring parameter\n"); | |||||
return (-EINVAL); | |||||
} | |||||
if ((sys_op->rx_pending < XGBE_RX_DESC_CNT_MIN) || | |||||
(sys_op->rx_pending > XGBE_RX_DESC_CNT_MAX)) { | |||||
axgbe_error("rx ring param must be between %u and %u\n", | |||||
XGBE_RX_DESC_CNT_MIN, XGBE_RX_DESC_CNT_MAX); | |||||
return (-EINVAL); | |||||
} | |||||
if ((sys_op->tx_pending < XGBE_TX_DESC_CNT_MIN) || | |||||
(sys_op->tx_pending > XGBE_TX_DESC_CNT_MAX)) { | |||||
axgbe_error("tx ring param must be between %u and %u\n", | |||||
XGBE_TX_DESC_CNT_MIN, XGBE_TX_DESC_CNT_MAX); | |||||
return (-EINVAL); | |||||
} | |||||
rx = __rounddown_pow_of_two(sys_op->rx_pending); | |||||
if (rx != sys_op->rx_pending) | |||||
axgbe_printf(1, "rx ring param rounded to power of 2: %u\n", | |||||
rx); | |||||
tx = __rounddown_pow_of_two(sys_op->tx_pending); | |||||
if (tx != sys_op->tx_pending) | |||||
axgbe_printf(1, "tx ring param rounded to power of 2: %u\n", | |||||
tx); | |||||
if ((rx == pdata->rx_desc_count) && | |||||
(tx == pdata->tx_desc_count)) | |||||
goto out; | |||||
pdata->rx_desc_count = rx; | |||||
pdata->tx_desc_count = tx; | |||||
/* TODO - restart dev */ | |||||
} | |||||
out: | |||||
return (0); | |||||
} | |||||
static int | |||||
sysctl_channels_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; | |||||
struct sysctl_op *sys_op = pdata->sys_op; | |||||
struct sysctl_info sysctl_channels[] = { | |||||
{ "rx", SYSL_S32, rx_count, "supported" }, | |||||
{ "tx", SYSL_S32, tx_count, "supported" }, | |||||
{ "other", SYSL_S32, other_count, "supported" }, | |||||
{ "combined", SYSL_S32, combined_count, "supported" }, | |||||
}; | |||||
unsigned int rx, tx, combined; | |||||
ssize_t buf_size = 512; | |||||
char buf[buf_size]; | |||||
struct sbuf *sb; | |||||
int rc = 0; | |||||
if (req->newptr == NULL) { | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); | |||||
if (sb == NULL) { | |||||
rc = sb->s_error; | |||||
return (rc); | |||||
} | |||||
rx = min(pdata->hw_feat.rx_ch_cnt, pdata->rx_max_channel_count); | |||||
rx = min(rx, pdata->channel_irq_count); | |||||
tx = min(pdata->hw_feat.tx_ch_cnt, pdata->tx_max_channel_count); | |||||
tx = min(tx, pdata->channel_irq_count); | |||||
tx = min(tx, pdata->tx_max_q_count); | |||||
combined = min(rx, tx); | |||||
sys_op->max_combined = combined; | |||||
sys_op->max_rx = rx ? rx - 1 : 0; | |||||
sys_op->max_tx = tx ? tx - 1 : 0; | |||||
/* Get current settings based on device state */ | |||||
rx = pdata->rx_ring_count; | |||||
tx = pdata->tx_ring_count; | |||||
combined = min(rx, tx); | |||||
rx -= combined; | |||||
tx -= combined; | |||||
sys_op->combined_count = combined; | |||||
sys_op->rx_count = rx; | |||||
sys_op->tx_count = tx; | |||||
sbuf_printf(sb, | |||||
"\nPre-set maximums:\n" | |||||
"RX: %u\n" | |||||
"TX: %u\n" | |||||
"Other: %u\n" | |||||
"Combined: %u\n", | |||||
sys_op->max_rx, sys_op->max_tx, | |||||
sys_op->max_other, | |||||
sys_op->max_combined); | |||||
sbuf_printf(sb, | |||||
"\nCurrent hardware settings:\n" | |||||
"RX: %u\n" | |||||
"TX: %u\n" | |||||
"Other: %u\n" | |||||
"Combined: %u\n", | |||||
sys_op->rx_count, sys_op->tx_count, | |||||
sys_op->other_count, | |||||
sys_op->combined_count); | |||||
rc = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (0); | |||||
} | |||||
rc = get_ubuf(req, buf); | |||||
if (rc == 0) { | |||||
parse_generic_sysctl(pdata, buf, sysctl_channels, | |||||
ARRAY_SIZE(sysctl_channels)); | |||||
axgbe_error( "channel inputs: combined=%u, rx-only=%u," | |||||
" tx-only=%u\n", sys_op->combined_count, | |||||
sys_op->rx_count, sys_op->tx_count); | |||||
} | |||||
return (rc); | |||||
} | |||||
static int | |||||
sysctl_mac_stats_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; | |||||
ssize_t buf_size = 64; | |||||
struct sbuf *sb; | |||||
int rc = 0; | |||||
int i; | |||||
if (req->newptr == NULL) { | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); | |||||
if (sb == NULL) { | |||||
rc = sb->s_error; | |||||
return (rc); | |||||
} | |||||
pdata->hw_if.read_mmc_stats(pdata); | |||||
for (i = 0; i < XGBE_STATS_COUNT; i++) { | |||||
sbuf_printf(sb, "\n %s: %lu", | |||||
xgbe_gstring_stats[i].stat_string, | |||||
*(uint64_t *)((uint8_t *)pdata + xgbe_gstring_stats[i].stat_offset)); | |||||
} | |||||
for (i = 0; i < pdata->tx_ring_count; i++) { | |||||
sbuf_printf(sb, | |||||
"\n txq_packets[%d]: %lu" | |||||
"\n txq_bytes[%d]: %lu", | |||||
i, pdata->ext_stats.txq_packets[i], | |||||
i, pdata->ext_stats.txq_bytes[i]); | |||||
} | |||||
for (i = 0; i < pdata->rx_ring_count; i++) { | |||||
sbuf_printf(sb, | |||||
"\n rxq_packets[%d]: %lu" | |||||
"\n rxq_bytes[%d]: %lu", | |||||
i, pdata->ext_stats.rxq_packets[i], | |||||
i, pdata->ext_stats.rxq_bytes[i]); | |||||
} | |||||
rc = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (rc); | |||||
} | |||||
return (-EINVAL); | |||||
} | |||||
static int | |||||
sysctl_xgmac_reg_value_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; | |||||
ssize_t buf_size = 64; | |||||
char buf[buf_size]; | |||||
unsigned int value; | |||||
struct sbuf *sb; | |||||
int rc = 0; | |||||
if (req->newptr == NULL) { | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); | |||||
if (sb == NULL) { | |||||
rc = sb->s_error; | |||||
return (rc); | |||||
} | |||||
value = XGMAC_IOREAD(pdata, pdata->sysctl_xgmac_reg); | |||||
axgbe_printf(2, "READ: %s: value: 0x%x\n", __func__, value); | |||||
sbuf_printf(sb, "\nXGMAC reg_value: 0x%x\n", value); | |||||
rc = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (rc); | |||||
} | |||||
rc = get_ubuf(req, buf); | |||||
if (rc == 0) { | |||||
sscanf(buf, "%x", &value); | |||||
axgbe_printf(2, "WRITE: %s: value: 0x%x\n", __func__, value); | |||||
XGMAC_IOWRITE(pdata, pdata->sysctl_xgmac_reg, value); | |||||
} | |||||
axgbe_printf(2, "%s: rc= %d\n", __func__, rc); | |||||
return (rc); | |||||
} | |||||
static int | |||||
sysctl_xpcs_mmd_reg_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; | |||||
ssize_t buf_size = 64; | |||||
char buf[buf_size]; | |||||
struct sbuf *sb; | |||||
unsigned int reg; | |||||
int rc = 0; | |||||
if (req->newptr == NULL) { | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); | |||||
if (sb == NULL) { | |||||
rc = sb->s_error; | |||||
return (rc); | |||||
} | |||||
axgbe_printf(2, "READ: %s: xpcs_mmd: 0x%x\n", __func__, | |||||
pdata->sysctl_xpcs_mmd); | |||||
sbuf_printf(sb, "\nXPCS mmd_reg: 0x%x\n", | |||||
pdata->sysctl_xpcs_mmd); | |||||
rc = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (rc); | |||||
} | |||||
rc = get_ubuf(req, buf); | |||||
if (rc == 0) { | |||||
sscanf(buf, "%x", ®); | |||||
axgbe_printf(2, "WRITE: %s: mmd_reg: 0x%x\n", __func__, reg); | |||||
pdata->sysctl_xpcs_mmd = reg; | |||||
} | |||||
axgbe_printf(2, "%s: rc= %d\n", __func__, rc); | |||||
return (rc); | |||||
} | |||||
static int | |||||
sysctl_xpcs_reg_addr_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; | |||||
ssize_t buf_size = 64; | |||||
char buf[buf_size]; | |||||
struct sbuf *sb; | |||||
unsigned int reg; | |||||
int rc = 0; | |||||
if (req->newptr == NULL) { | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); | |||||
if (sb == NULL) { | |||||
rc = sb->s_error; | |||||
return (rc); | |||||
} | |||||
axgbe_printf(2, "READ: %s: sysctl_xpcs_reg: 0x%x\n", __func__, | |||||
pdata->sysctl_xpcs_reg); | |||||
sbuf_printf(sb, "\nXPCS reg_addr: 0x%x\n", | |||||
pdata->sysctl_xpcs_reg); | |||||
rc = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (rc); | |||||
} | |||||
rc = get_ubuf(req, buf); | |||||
if (rc == 0) { | |||||
sscanf(buf, "%x", ®); | |||||
axgbe_printf(2, "WRITE: %s: reg: 0x%x\n", __func__, reg); | |||||
pdata->sysctl_xpcs_reg = reg; | |||||
} | |||||
axgbe_printf(2, "%s: rc= %d\n", __func__, rc); | |||||
return (rc); | |||||
} | |||||
static int | |||||
sysctl_xpcs_reg_value_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; | |||||
ssize_t buf_size = 64; | |||||
char buf[buf_size]; | |||||
unsigned int value; | |||||
struct sbuf *sb; | |||||
int rc = 0; | |||||
if (req->newptr == NULL) { | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); | |||||
if (sb == NULL) { | |||||
rc = sb->s_error; | |||||
return (rc); | |||||
} | |||||
value = XMDIO_READ(pdata, pdata->sysctl_xpcs_mmd, | |||||
pdata->sysctl_xpcs_reg); | |||||
axgbe_printf(2, "READ: %s: value: 0x%x\n", __func__, value); | |||||
sbuf_printf(sb, "\nXPCS reg_value: 0x%x\n", value); | |||||
rc = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (rc); | |||||
} | |||||
rc = get_ubuf(req, buf); | |||||
if (rc == 0) { | |||||
sscanf(buf, "%x", &value); | |||||
axgbe_printf(2, "WRITE: %s: value: 0x%x\n", __func__, value); | |||||
XMDIO_WRITE(pdata, pdata->sysctl_xpcs_mmd, | |||||
pdata->sysctl_xpcs_reg, value); | |||||
} | |||||
axgbe_printf(2, "%s: rc= %d\n", __func__, rc); | |||||
return (rc); | |||||
} | |||||
static int | |||||
sysctl_xprop_reg_addr_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; | |||||
ssize_t buf_size = 64; | |||||
char buf[buf_size]; | |||||
struct sbuf *sb; | |||||
unsigned int reg; | |||||
int rc = 0; | |||||
if (req->newptr == NULL) { | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); | |||||
if (sb == NULL) { | |||||
rc = sb->s_error; | |||||
return (rc); | |||||
} | |||||
axgbe_printf(2, "READ: %s: sysctl_xprop_reg: 0x%x\n", __func__, | |||||
pdata->sysctl_xprop_reg); | |||||
sbuf_printf(sb, "\nXPROP reg_addr: 0x%x\n", | |||||
pdata->sysctl_xprop_reg); | |||||
rc = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (rc); | |||||
} | |||||
rc = get_ubuf(req, buf); | |||||
if (rc == 0) { | |||||
sscanf(buf, "%x", ®); | |||||
axgbe_printf(2, "WRITE: %s: reg: 0x%x\n", __func__, reg); | |||||
pdata->sysctl_xprop_reg = reg; | |||||
} | |||||
axgbe_printf(2, "%s: rc= %d\n", __func__, rc); | |||||
return (rc); | |||||
} | |||||
static int | |||||
sysctl_xprop_reg_value_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; | |||||
ssize_t buf_size = 64; | |||||
char buf[buf_size]; | |||||
unsigned int value; | |||||
struct sbuf *sb; | |||||
int rc = 0; | |||||
if (req->newptr == NULL) { | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); | |||||
if (sb == NULL) { | |||||
rc = sb->s_error; | |||||
return (rc); | |||||
} | |||||
value = XP_IOREAD(pdata, pdata->sysctl_xprop_reg); | |||||
axgbe_printf(2, "READ: %s: value: 0x%x\n", __func__, value); | |||||
sbuf_printf(sb, "\nXPROP reg_value: 0x%x\n", value); | |||||
rc = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (rc); | |||||
} | |||||
rc = get_ubuf(req, buf); | |||||
if (rc == 0) { | |||||
sscanf(buf, "%x", &value); | |||||
axgbe_printf(2, "WRITE: %s: value: 0x%x\n", __func__, value); | |||||
XP_IOWRITE(pdata, pdata->sysctl_xprop_reg, value); | |||||
} | |||||
axgbe_printf(2, "%s: rc= %d\n", __func__, rc); | |||||
return (rc); | |||||
} | |||||
static int | |||||
sysctl_xi2c_reg_addr_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; | |||||
ssize_t buf_size = 64; | |||||
char buf[buf_size]; | |||||
struct sbuf *sb; | |||||
unsigned int reg; | |||||
int rc = 0; | |||||
if (req->newptr == NULL) { | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); | |||||
if (sb == NULL) { | |||||
rc = sb->s_error; | |||||
return (rc); | |||||
} | |||||
axgbe_printf(2, "READ: %s: sysctl_xi2c_reg: 0x%x\n", __func__, | |||||
pdata->sysctl_xi2c_reg); | |||||
sbuf_printf(sb, "\nXI2C reg_addr: 0x%x\n", | |||||
pdata->sysctl_xi2c_reg); | |||||
rc = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (rc); | |||||
} | |||||
rc = get_ubuf(req, buf); | |||||
if (rc == 0) { | |||||
sscanf(buf, "%x", ®); | |||||
axgbe_printf(2, "WRITE: %s: reg: 0x%x\n", __func__, reg); | |||||
pdata->sysctl_xi2c_reg = reg; | |||||
} | |||||
axgbe_printf(2, "%s: rc= %d\n", __func__, rc); | |||||
return (rc); | |||||
} | |||||
static int | |||||
sysctl_xi2c_reg_value_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; | |||||
ssize_t buf_size = 64; | |||||
char buf[buf_size]; | |||||
unsigned int value; | |||||
struct sbuf *sb; | |||||
int rc = 0; | |||||
if (req->newptr == NULL) { | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); | |||||
if (sb == NULL) { | |||||
rc = sb->s_error; | |||||
return (rc); | |||||
} | |||||
value = XI2C_IOREAD(pdata, pdata->sysctl_xi2c_reg); | |||||
axgbe_printf(2, "READ: %s: value: 0x%x\n", __func__, value); | |||||
sbuf_printf(sb, "\nXI2C reg_value: 0x%x\n", value); | |||||
rc = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (rc); | |||||
} | |||||
rc = get_ubuf(req, buf); | |||||
if (rc == 0) { | |||||
sscanf(buf, "%x", &value); | |||||
axgbe_printf(2, "WRITE: %s: value: 0x%x\n", __func__, value); | |||||
XI2C_IOWRITE(pdata, pdata->sysctl_xi2c_reg, value); | |||||
} | |||||
axgbe_printf(2, "%s: rc= %d\n", __func__, rc); | |||||
return (rc); | |||||
} | |||||
static int | |||||
sysctl_an_cdr_wr_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; | |||||
unsigned int an_cdr_wr = 0; | |||||
ssize_t buf_size = 64; | |||||
char buf[buf_size]; | |||||
struct sbuf *sb; | |||||
int rc = 0; | |||||
if (req->newptr == NULL) { | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); | |||||
if (sb == NULL) { | |||||
rc = sb->s_error; | |||||
return (rc); | |||||
} | |||||
axgbe_printf(2, "READ: %s: an_cdr_wr: %d\n", __func__, | |||||
pdata->sysctl_an_cdr_workaround); | |||||
sbuf_printf(sb, "%d\n", pdata->sysctl_an_cdr_workaround); | |||||
rc = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (rc); | |||||
} | |||||
rc = get_ubuf(req, buf); | |||||
if (rc == 0) { | |||||
sscanf(buf, "%u", &an_cdr_wr); | |||||
axgbe_printf(2, "WRITE: %s: an_cdr_wr: 0x%d\n", __func__, | |||||
an_cdr_wr); | |||||
if (an_cdr_wr) | |||||
pdata->sysctl_an_cdr_workaround = 1; | |||||
else | |||||
pdata->sysctl_an_cdr_workaround = 0; | |||||
} | |||||
axgbe_printf(2, "%s: rc= %d\n", __func__, rc); | |||||
return (rc); | |||||
} | |||||
static int | |||||
sysctl_an_cdr_track_early_handler(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)arg1; | |||||
unsigned int an_cdr_track_early = 0; | |||||
ssize_t buf_size = 64; | |||||
char buf[buf_size]; | |||||
struct sbuf *sb; | |||||
int rc = 0; | |||||
if (req->newptr == NULL) { | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, buf_size, req); | |||||
if (sb == NULL) { | |||||
rc = sb->s_error; | |||||
return (rc); | |||||
} | |||||
axgbe_printf(2, "READ: %s: an_cdr_track_early %d\n", __func__, | |||||
pdata->sysctl_an_cdr_track_early); | |||||
sbuf_printf(sb, "%d\n", pdata->sysctl_an_cdr_track_early); | |||||
rc = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (rc); | |||||
} | |||||
rc = get_ubuf(req, buf); | |||||
if (rc == 0) { | |||||
sscanf(buf, "%u", &an_cdr_track_early); | |||||
axgbe_printf(2, "WRITE: %s: an_cdr_track_early: %d\n", __func__, | |||||
an_cdr_track_early); | |||||
if (an_cdr_track_early) | |||||
pdata->sysctl_an_cdr_track_early = 1; | |||||
else | |||||
pdata->sysctl_an_cdr_track_early = 0; | |||||
} | |||||
axgbe_printf(2, "%s: rc= %d\n", __func__, rc); | |||||
return (rc); | |||||
} | |||||
void | |||||
axgbe_sysctl_exit(struct xgbe_prv_data *pdata) | |||||
{ | |||||
if (pdata->sys_op) | |||||
free(pdata->sys_op, M_AXGBE); | |||||
} | |||||
void | |||||
axgbe_sysctl_init(struct xgbe_prv_data *pdata) | |||||
{ | |||||
struct sysctl_ctx_list *clist; | |||||
struct sysctl_oid_list *top; | |||||
struct sysctl_oid *parent; | |||||
struct sysctl_op *sys_op; | |||||
sys_op = malloc(sizeof(*sys_op), M_AXGBE, M_WAITOK | M_ZERO); | |||||
pdata->sys_op = sys_op; | |||||
clist = device_get_sysctl_ctx(pdata->dev); | |||||
parent = device_get_sysctl_tree(pdata->dev); | |||||
top = SYSCTL_CHILDREN(parent); | |||||
/* Set defaults */ | |||||
pdata->sysctl_xgmac_reg = 0; | |||||
pdata->sysctl_xpcs_mmd = 1; | |||||
pdata->sysctl_xpcs_reg = 0; | |||||
SYSCTL_ADD_UINT(clist, top, OID_AUTO, "axgbe_debug_level", CTLFLAG_RWTUN, | |||||
&pdata->debug_level, 0, "axgbe log level -- higher is verbose"); | |||||
SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xgmac_register", | |||||
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, | |||||
pdata, 0, sysctl_xgmac_reg_addr_handler, "IU", | |||||
"xgmac register addr"); | |||||
SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xgmac_register_value", | |||||
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, | |||||
pdata, 0, sysctl_xgmac_reg_value_handler, "IU", | |||||
"xgmac register value"); | |||||
SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xpcs_mmd", | |||||
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, | |||||
pdata, 0, sysctl_xpcs_mmd_reg_handler, "IU", "xpcs mmd register"); | |||||
SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xpcs_register", | |||||
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, | |||||
pdata, 0, sysctl_xpcs_reg_addr_handler, "IU", "xpcs register"); | |||||
SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xpcs_register_value", | |||||
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, | |||||
pdata, 0, sysctl_xpcs_reg_value_handler, "IU", | |||||
"xpcs register value"); | |||||
if (pdata->xpcs_res) { | |||||
SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xprop_register", | |||||
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, | |||||
pdata, 0, sysctl_xprop_reg_addr_handler, | |||||
"IU", "xprop register"); | |||||
SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xprop_register_value", | |||||
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, | |||||
pdata, 0, sysctl_xprop_reg_value_handler, | |||||
"IU", "xprop register value"); | |||||
} | |||||
if (pdata->xpcs_res) { | |||||
SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xi2c_register", | |||||
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, | |||||
pdata, 0, sysctl_xi2c_reg_addr_handler, | |||||
"IU", "xi2c register"); | |||||
SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xi2c_register_value", | |||||
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, | |||||
pdata, 0, sysctl_xi2c_reg_value_handler, | |||||
"IU", "xi2c register value"); | |||||
} | |||||
if (pdata->vdata->an_cdr_workaround) { | |||||
SYSCTL_ADD_PROC(clist, top, OID_AUTO, "an_cdr_workaround", | |||||
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, | |||||
pdata, 0, sysctl_an_cdr_wr_handler, "IU", | |||||
"an cdr workaround"); | |||||
SYSCTL_ADD_PROC(clist, top, OID_AUTO, "an_cdr_track_early", | |||||
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, | |||||
pdata, 0, sysctl_an_cdr_track_early_handler, "IU", | |||||
"an cdr track early"); | |||||
} | |||||
SYSCTL_ADD_PROC(clist, top, OID_AUTO, "drv_info", | |||||
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, | |||||
pdata, 0, sysctl_get_drv_info_handler, "IU", | |||||
"xgbe drv info"); | |||||
SYSCTL_ADD_PROC(clist, top, OID_AUTO, "link_info", | |||||
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, | |||||
pdata, 0, sysctl_get_link_info_handler, "IU", | |||||
"xgbe link info"); | |||||
SYSCTL_ADD_PROC(clist, top, OID_AUTO, "coalesce_info", | |||||
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, | |||||
pdata, 0, sysctl_coalesce_handler, "IU", | |||||
"xgbe coalesce info"); | |||||
SYSCTL_ADD_PROC(clist, top, OID_AUTO, "pauseparam_info", | |||||
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, | |||||
pdata, 0, sysctl_pauseparam_handler, "IU", | |||||
"xgbe pauseparam info"); | |||||
SYSCTL_ADD_PROC(clist, top, OID_AUTO, "link_ksettings_info", | |||||
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, | |||||
pdata, 0, sysctl_link_ksettings_handler, "IU", | |||||
"xgbe link_ksettings info"); | |||||
SYSCTL_ADD_PROC(clist, top, OID_AUTO, "ringparam_info", | |||||
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, | |||||
pdata, 0, sysctl_ringparam_handler, "IU", | |||||
"xgbe ringparam info"); | |||||
SYSCTL_ADD_PROC(clist, top, OID_AUTO, "channels_info", | |||||
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, | |||||
pdata, 0, sysctl_channels_handler, "IU", | |||||
"xgbe channels info"); | |||||
SYSCTL_ADD_PROC(clist, top, OID_AUTO, "mac_stats", | |||||
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, | |||||
pdata, 0, sysctl_mac_stats_handler, "IU", | |||||
"xgbe mac stats"); | |||||
} |