Page MenuHomeFreeBSD

D58749.1794814104.diff
No OneTemporary

Authored By
Unknown
Size
18 KB
Referenced Files
None
Subscribers
None

D58749.1794814104.diff

diff --git a/share/man/man4/aq.4 b/share/man/man4/aq.4
--- a/share/man/man4/aq.4
+++ b/share/man/man4/aq.4
@@ -3,7 +3,7 @@
.\"
.\" SPDX-License-Identifier: BSD-2-Clause
.\"
-.Dd July 9, 2026
+.Dd August 6, 2026
.Dt AQ 4
.Os
.Sh NAME
@@ -79,6 +79,35 @@
.It
Marvell AQC116C (10Mb/100Mb/1Gb RJ45)
.El
+.Sh SYSCTL VARIABLES
+The following read-only variables are available per interface as
+.Va dev.aq.%d.%s ,
+where
+.Ar %d
+is the interface number.
+Each is present only when the adapter's firmware supports it.
+.Bl -tag -width indent
+.It Va temperature
+The PHY die temperature.
+.It Va fw_link_up
+The number of link up transitions counted by the firmware.
+.It Va fw_link_down
+The number of link down transitions counted by the firmware.
+Comparing this against the transitions logged by the driver
+distinguishes a single link event from a flapping link.
+.El
+.Pp
+The following variables tune the driver's own tracing:
+.Bl -tag -width indent
+.It Va debug
+Trace verbosity: 0 disables tracing, 3 reports errors, 4 adds warnings,
+5 adds traces and 6 adds detail.
+The default is 3.
+.It Va debug_categories
+Bit mask selecting the traced categories: init 1, config 2, tx 4, rx 8,
+intr 16 and fw 32.
+All categories are enabled by default.
+.El
.Sh SEE ALSO
.Xr arp 4 ,
.Xr miibus 4 ,
diff --git a/sys/dev/aq/aq2_fw.c b/sys/dev/aq/aq2_fw.c
--- a/sys/dev/aq/aq2_fw.c
+++ b/sys/dev/aq/aq2_fw.c
@@ -39,10 +39,14 @@
enum aq_fw_link_speed speed);
static int aq2_fw_get_mode(struct aq_hw *hw, enum aq_hw_fw_mpi_state *mode,
enum aq_fw_link_speed *speed, enum aq_fw_link_fc *fc);
+static int aq2_fw_get_link_info(struct aq_hw *hw, struct aq_hw_link_info *info);
static int aq2_fw_get_mac_addr(struct aq_hw *hw, uint8_t *mac);
static int aq2_fw_get_stats(struct aq_hw *hw, struct aq_hw_stats *stats);
+static int aq2_fw_get_link_counters(struct aq_hw *hw, uint32_t *up,
+ uint32_t *down);
static int aq2_fw_get_temp(struct aq_hw *hw, int *temp_mc);
static int aq2_fw_get_thermal_limit(struct aq_hw *hw, int *limit_mc);
+static int aq2_fw_get_phy_hot_warning(struct aq_hw *hw, bool *hot);
/* Coherent OUT-window read, bracketed by the transaction id. */
static int
@@ -369,6 +373,21 @@
return (0);
}
+static int
+aq2_fw_get_link_info(struct aq_hw *hw, struct aq_hw_link_info *info)
+{
+ uint32_t v;
+
+ v = AQ_READ_REG(hw, AQ2_FW_INTERFACE_OUT_LINK_STATUS_REG);
+
+ info->full_duplex =
+ (v & AQ2_FW_INTERFACE_OUT_LINK_STATUS_DUPLEX) != 0;
+ info->eee = (v & AQ2_FW_INTERFACE_OUT_LINK_STATUS_EEE) != 0;
+ info->state = v & AQ2_FW_INTERFACE_OUT_LINK_STATUS_STATE;
+
+ return (0);
+}
+
/* A2 firmware stats; layout depends on interface version. */
struct aq2_fw_statistics_a0 {
uint32_t link_up;
@@ -474,6 +493,30 @@
return (0);
}
+/* Only the A0 interface layout carries the link transition counters. */
+static int
+aq2_fw_get_link_counters(struct aq_hw *hw, uint32_t *up, uint32_t *down)
+{
+ union aq2_fw_statistics u;
+ int err;
+
+ if (hw->aq2_iface != AQ2_FW_INTERFACE_OUT_VERSION_IFACE_VER_A0)
+ return (ENOTSUP);
+
+ err = aq2_fw_interface_buffer_read(hw, AQ2_FW_INTERFACE_OUT_STATS_REG,
+ (uint32_t *)&u, sizeof(u));
+ if (err != 0) {
+ trace_error(hw, dbg_fw,
+ "aq2> link counter read FAILED, error %d", err);
+ return (err);
+ }
+
+ *up = u.a0.link_up;
+ *down = u.a0.link_down;
+
+ return (0);
+}
+
static int
aq2_fw_get_temp(struct aq_hw *hw, int *temp_mc)
{
@@ -543,14 +586,37 @@
return (0);
}
+static int
+aq2_fw_get_phy_hot_warning(struct aq_hw *hw, bool *hot)
+{
+ uint32_t health;
+ int err;
+
+ err = aq2_fw_interface_buffer_read(hw,
+ AQ2_FW_INTERFACE_OUT_PHY_HEALTH_MONITOR_REG, &health,
+ sizeof(health));
+ if (err != 0)
+ return (err);
+
+ if ((health & AQ2_FW_INTERFACE_OUT_PHY_HEALTH_MONITOR_READY) == 0)
+ return (ENXIO);
+
+ *hot = (health & AQ2_FW_INTERFACE_OUT_PHY_HEALTH_MONITOR_HOT) != 0;
+
+ return (0);
+}
+
const struct aq_firmware_ops aq2_fw_ops = {
.reset = aq2_fw_reset,
.set_mode = aq2_fw_set_mode,
.get_mode = aq2_fw_get_mode,
+ .get_link_info = aq2_fw_get_link_info,
.get_mac_addr = aq2_fw_get_mac_addr,
.get_stats = aq2_fw_get_stats,
+ .get_link_counters = aq2_fw_get_link_counters,
.get_temp = aq2_fw_get_temp,
.get_phy_fault = aq2_fw_get_phy_fault,
+ .get_phy_hot_warning = aq2_fw_get_phy_hot_warning,
.phy_reset = NULL, /* A2 clears thermal shutdown on its own reset */
.thermal_arm = NULL, /* A2 firmware ships thermal shutdown armed */
.get_thermal_limit = aq2_fw_get_thermal_limit,
diff --git a/sys/dev/aq/aq2_hw.h b/sys/dev/aq/aq2_hw.h
--- a/sys/dev/aq/aq2_hw.h
+++ b/sys/dev/aq/aq2_hw.h
@@ -237,6 +237,7 @@
#define AQ2_FW_INTERFACE_OUT_PHY_HEALTH_MONITOR_REG 0x13620
#define AQ2_FW_INTERFACE_OUT_PHY_HEALTH_MONITOR_READY 0x00000001
#define AQ2_FW_INTERFACE_OUT_PHY_HEALTH_MONITOR_FAULT 0x00000002
+#define AQ2_FW_INTERFACE_OUT_PHY_HEALTH_MONITOR_HOT 0x00000004
#define AQ2_FW_INTERFACE_OUT_PHY_TEMPERATURE 0x0000ff00
#define AQ2_FW_INTERFACE_OUT_PHY_TEMPERATURE_S 8
diff --git a/sys/dev/aq/aq_device.h b/sys/dev/aq/aq_device.h
--- a/sys/dev/aq/aq_device.h
+++ b/sys/dev/aq/aq_device.h
@@ -123,6 +123,8 @@
bool linkup;
uint32_t link_speed; /* Mbit/s last announced to the stack */
uint16_t phy_fault_last; /* last fault code reported */
+ bool phy_hot_last; /* last over-temperature warning */
+ bool link_read_failed; /* link state read is failing */
enum aq_thermal_state {
AQ_THERMAL_NORMAL = 0, /* no thermal shutdown pending */
AQ_THERMAL_COOLING, /* shut down; waiting to cool */
diff --git a/sys/dev/aq/aq_fw.h b/sys/dev/aq/aq_fw.h
--- a/sys/dev/aq/aq_fw.h
+++ b/sys/dev/aq/aq_fw.h
@@ -65,15 +65,24 @@
int (*set_mode)(struct aq_hw* hw, enum aq_hw_fw_mpi_state mode, enum aq_fw_link_speed speed);
int (*get_mode)(struct aq_hw* hw, enum aq_hw_fw_mpi_state* mode, enum aq_fw_link_speed* speed, enum aq_fw_link_fc* fc);
+ /* Reports duplex, EEE and the firmware link state beyond the rate. */
+ int (*get_link_info)(struct aq_hw* hw, struct aq_hw_link_info* info);
+
int (*get_mac_addr)(struct aq_hw* hw, uint8_t* mac_addr);
int (*get_stats)(struct aq_hw* hw, struct aq_hw_stats* stats);
+ /* Reports the firmware's own link transition counters. */
+ int (*get_link_counters)(struct aq_hw* hw, uint32_t* up, uint32_t* down);
+
/* Reports millidegrees Celsius. */
int (*get_temp)(struct aq_hw* hw, int* temp_mc);
/* Reports the PHY global fault code; zero means no fault. */
int (*get_phy_fault)(struct aq_hw* hw, uint16_t* fault);
+ /* Reports the pre-shutdown PHY over-temperature warning. */
+ int (*get_phy_hot_warning)(struct aq_hw* hw, bool* hot);
+
/* Resets the PHY (clears a latched thermal shutdown). */
int (*phy_reset)(struct aq_hw* hw);
diff --git a/sys/dev/aq/aq_hw.h b/sys/dev/aq/aq_hw.h
--- a/sys/dev/aq/aq_hw.h
+++ b/sys/dev/aq/aq_hw.h
@@ -162,6 +162,12 @@
bool fc_tx;
};
+struct aq_hw_link_info {
+ bool full_duplex;
+ bool eee;
+ uint8_t state;
+};
+
struct aq_hw {
void *aq_dev;
device_t dev;
diff --git a/sys/dev/aq/aq_irq.c b/sys/dev/aq/aq_irq.c
--- a/sys/dev/aq/aq_irq.c
+++ b/sys/dev/aq/aq_irq.c
@@ -39,6 +39,7 @@
#include <sys/param.h>
#include <sys/bitstring.h>
#include <sys/kernel.h>
+#include <sys/sbuf.h>
#include <sys/socket.h>
#include <net/ethernet.h>
#include <net/if.h>
@@ -149,6 +150,34 @@
"holding link down until it cools\n");
}
+/* Pre-trip warning: the PHY is hot but the firmware has not shut it down. */
+static void
+aq_thermal_report_hot(struct aq_dev *aq_dev)
+{
+ struct aq_hw *hw = &aq_dev->hw;
+ int temp_mc;
+ bool hot;
+
+ if (hw->fw_ops->get_phy_hot_warning == NULL ||
+ hw->fw_ops->get_phy_hot_warning(hw, &hot) != 0)
+ return;
+
+ /* Report each edge once; the bit stays set for the whole excursion. */
+ if (hot == aq_dev->phy_hot_last)
+ return;
+ aq_dev->phy_hot_last = hot;
+
+ if (!hot) {
+ device_printf(aq_dev->dev, "PHY temperature normal again\n");
+ return;
+ }
+ if (hw->fw_ops->get_temp(hw, &temp_mc) == 0)
+ device_printf(aq_dev->dev, "PHY over-temperature warning, "
+ "temp %d C\n", temp_mc / 1000);
+ else
+ device_printf(aq_dev->dev, "PHY over-temperature warning\n");
+}
+
/* Recover after cooldown: A1 needs a PHY reset then re-init, A2 re-inits alone. */
static void
aq_thermal_poll(struct aq_dev *aq_dev)
@@ -159,6 +188,7 @@
switch (aq_dev->thermal_state) {
case AQ_THERMAL_NORMAL:
+ aq_thermal_report_hot(aq_dev);
if (aq_dev->linkup)
return;
/* The F/W raises the fault a poll after it drops the link. */
@@ -211,6 +241,72 @@
iflib_admin_intr_deferred(aq_dev->ctx);
}
+static const char *
+aq_fc_string(const struct aq_hw_fc_info *fc)
+{
+
+ if (fc->fc_rx && fc->fc_tx)
+ return ("rx/tx");
+ if (fc->fc_rx)
+ return ("rx");
+ if (fc->fc_tx)
+ return ("tx");
+ return ("none");
+}
+
+static void
+aq_link_report_up(struct aq_dev *aq_dev, uint32_t link_speed,
+ const struct aq_hw_fc_info *fc)
+{
+ struct aq_hw *hw = &aq_dev->hw;
+ struct aq_hw_link_info info;
+
+ if (hw->fw_ops->get_link_info != NULL &&
+ hw->fw_ops->get_link_info(hw, &info) == 0) {
+ device_printf(aq_dev->dev, "link UP: speed=%u, %s-duplex, "
+ "flowcontrol %s, EEE %s\n", link_speed,
+ info.full_duplex ? "full" : "half", aq_fc_string(fc),
+ info.eee ? "on" : "off");
+ return;
+ }
+ device_printf(aq_dev->dev, "link UP: speed=%u, flowcontrol %s\n",
+ link_speed, aq_fc_string(fc));
+}
+
+/*
+ * The firmware raises a PHY fault a poll after it drops the link, so a
+ * thermal trip usually reports only its temperature here; aq_thermal_poll()
+ * names it on the following poll.
+ */
+static void
+aq_link_report_down(struct aq_dev *aq_dev)
+{
+ struct aq_hw *hw = &aq_dev->hw;
+ struct aq_hw_link_info info;
+ struct sbuf sb;
+ char detail[96];
+ int temp_mc;
+ uint16_t fault;
+
+ sbuf_new(&sb, detail, sizeof(detail), SBUF_FIXEDLEN);
+
+ if (hw->fw_ops->get_phy_fault != NULL &&
+ hw->fw_ops->get_phy_fault(hw, &fault) == 0 && fault != 0)
+ sbuf_printf(&sb, ", PHY fault 0x%04x", fault);
+ if (hw->fw_ops->get_link_info != NULL &&
+ hw->fw_ops->get_link_info(hw, &info) == 0)
+ sbuf_printf(&sb, ", F/W link state %u", info.state);
+ if (hw->fw_ops->get_temp != NULL &&
+ hw->fw_ops->get_temp(hw, &temp_mc) == 0)
+ sbuf_printf(&sb, ", temp %d C", temp_mc / 1000);
+
+ if (sbuf_finish(&sb) != 0)
+ device_printf(aq_dev->dev, "link DOWN\n");
+ else
+ device_printf(aq_dev->dev, "link DOWN%s\n", sbuf_data(&sb));
+ sbuf_delete(&sb);
+}
+
void
aq_if_update_admin_status(if_ctx_t ctx)
{
@@ -221,7 +317,17 @@
struct aq_hw_fc_info fc_neg;
- aq_hw_get_link_state(hw, &link_speed, &fc_neg);
+ int err;
+
+ err = aq_hw_get_link_state(hw, &link_speed, &fc_neg);
+ if (err != 0 && !aq_dev->link_read_failed) {
+ aq_dev->link_read_failed = true;
+ device_printf(aq_dev->dev, "link state read failed, error %d; "
+ "holding the last known state\n", err);
+ } else if (err == 0 && aq_dev->link_read_failed) {
+ aq_dev->link_read_failed = false;
+ device_printf(aq_dev->dev, "link state read recovered\n");
+ }
/* A stopped or half-initialized interface has no link. */
running = (if_getdrvflags(iflib_get_ifp(ctx)) & IFF_DRV_RUNNING) != 0;
@@ -229,12 +335,10 @@
link_speed = 0;
/* A retrain can change the speed without ever dropping the link. */
- if (link_speed != 0U &&
+ if (err == 0 && link_speed != 0U &&
(!aq_dev->linkup || link_speed != aq_dev->link_speed)) {
if (!aq_dev->linkup) {
- if (bootverbose)
- device_printf(aq_dev->dev,
- "link UP: speed=%d\n", link_speed);
+ aq_link_report_up(aq_dev, link_speed, &fc_neg);
aq_dev->phy_fault_last = 0;
} else
device_printf(aq_dev->dev, "link speed=%d\n",
@@ -251,10 +355,11 @@
aq_mediastatus_update(aq_dev, link_speed, &fc_neg);
/* update ITR settings according new link speed */
- aq_hw_interrupt_moderation_set(hw);
- } else if (link_speed == 0U && aq_dev->linkup) { /* link was UP */
- if (bootverbose)
- device_printf(aq_dev->dev, "link DOWN\n");
+ if (aq_hw_interrupt_moderation_set(hw) != 0)
+ device_printf(aq_dev->dev,
+ "could not update interrupt moderation\n");
+ } else if (err == 0 && link_speed == 0U && aq_dev->linkup) {
+ aq_link_report_down(aq_dev);
aq_dev->linkup = 0;
aq_dev->link_speed = 0;
diff --git a/sys/dev/aq/aq_main.c b/sys/dev/aq/aq_main.c
--- a/sys/dev/aq/aq_main.c
+++ b/sys/dev/aq/aq_main.c
@@ -405,7 +405,12 @@
__func__, rc);
goto fail;
}
- aq_hw_capabilities(softc);
+ rc = aq_hw_capabilities(softc);
+ if (rc != 0) {
+ device_printf(softc->dev, "unsupported device %04x:%04x\n",
+ pci_get_vendor(softc->dev), pci_get_device(softc->dev));
+ goto fail;
+ }
rc = aq_hw_get_mac_permanent(hw, hw->mac_addr);
if (rc != 0) {
@@ -525,7 +530,8 @@
sysctl_ctx_free(&softc->aq_sysctl_ctx);
- aq_hw_deinit(&softc->hw);
+ if (aq_hw_deinit(&softc->hw) != 0)
+ device_printf(softc->dev, "could not shut the hardware down\n");
for (i = 0; i < softc->rx_rings_count; i++)
iflib_irq_free(ctx, &softc->rx_rings[i]->irq);
@@ -558,7 +564,9 @@
AQ_DBG_ENTER();
aq_if_stop(ctx);
- aq_hw_deinit(&softc->hw);
+ if (aq_hw_deinit(&softc->hw) != 0)
+ device_printf(softc->dev,
+ "could not shut the hardware down for suspend\n");
/* iflib_device_suspend() does not stop the interface for us. */
if_setdrvflagbits(iflib_get_ifp(ctx), IFF_DRV_OACTIVE, IFF_DRV_RUNNING);
@@ -810,15 +818,28 @@
aq_if_rx_queue_intr_enable(ctx, i);
}
- aq_hw_start(hw);
+ err = aq_hw_start(hw);
+ if (err != 0)
+ device_printf(softc->dev, "could not start the datapath: %d\n",
+ err);
aq_if_enable_intr(ctx);
- aq_hw_rss_hash_set(&softc->hw, softc->rss_key);
- aq_hw_rss_set(&softc->hw, softc->rss_table);
+ err = aq_hw_rss_hash_set(&softc->hw, softc->rss_key);
+ if (err != 0)
+ device_printf(softc->dev, "could not set the RSS key: %d\n",
+ err);
+ err = aq_hw_rss_set(&softc->hw, softc->rss_table);
+ if (err != 0)
+ device_printf(softc->dev,
+ "could not set the RSS indirection table: %d\n", err);
/* A2 selects UDP hashing per-protocol in REDIR2; A1 uses the filter. */
- if (!IS_CHIP_FEATURE(hw, ATLANTIC2))
- aq_hw_udp_rss_enable(hw, (aq_rss_hashconfig() &
+ if (!IS_CHIP_FEATURE(hw, ATLANTIC2)) {
+ err = aq_hw_udp_rss_enable(hw, (aq_rss_hashconfig() &
(RSS_HASHTYPE_RSS_UDP_IPV4 | RSS_HASHTYPE_RSS_UDP_IPV6 |
RSS_HASHTYPE_RSS_UDP_IPV6_EX)) != 0);
+ if (err != 0)
+ device_printf(softc->dev,
+ "could not configure UDP RSS hashing: %d\n", err);
+ }
err = aq_hw_set_link_speed(hw, hw->link_rate);
if (err != 0)
device_printf(softc->dev, "could not set link speed: %d\n", err);
@@ -848,15 +869,20 @@
aq_if_disable_intr(ctx);
for (i = 0; i < softc->tx_rings_count; i++) {
- aq_ring_tx_stop(hw, softc->tx_rings[i]);
+ if (aq_ring_tx_stop(hw, softc->tx_rings[i]) != 0)
+ device_printf(softc->dev,
+ "could not stop TX ring %d\n", i);
softc->tx_rings[i]->tx_head = 0;
softc->tx_rings[i]->tx_tail = 0;
}
for (i = 0; i < softc->rx_rings_count; i++) {
- aq_ring_rx_stop(hw, softc->rx_rings[i]);
+ if (aq_ring_rx_stop(hw, softc->rx_rings[i]) != 0)
+ device_printf(softc->dev,
+ "could not stop RX ring %d\n", i);
}
- aq_hw_reset(&softc->hw, true);
+ if (aq_hw_reset(&softc->hw, true) != 0)
+ device_printf(softc->dev, "could not reset the MAC on stop\n");
memset(&softc->last_stats, 0, sizeof(softc->last_stats));
/* Each bring-up gets its own budget of re-init attempts. */
softc->init_retries = 0;
@@ -897,7 +923,11 @@
return (0);
mac_addr = LLADDR(dl);
- aq_hw_mac_addr_set(hw, mac_addr, count + 1);
+ if (aq_hw_mac_addr_set(hw, mac_addr, count + 1) != 0) {
+ device_printf(softc->dev,
+ "could not program multicast address %6D\n", mac_addr, ":");
+ return (0);
+ }
aq_log_detail(hw, "set %d mc address %6D", count + 1, mac_addr, ":");
return (1);
@@ -1171,7 +1201,9 @@
int vlan_tag = -1;
int i;
- hw_atl_b0_hw_vlan_promisc_set(hw, true);
+ if (hw_atl_b0_hw_vlan_promisc_set(hw, true) != 0)
+ device_printf(softc->dev,
+ "could not open the VLAN filter for update\n");
for (i = 0; i < AQ_HW_VLAN_MAX_FILTERS; i++) {
bit_ffs_at(softc->vlan_tags, bit_pos, 4096, &vlan_tag);
if (vlan_tag != -1) {
@@ -1185,7 +1217,9 @@
}
}
- hw_atl_b0_hw_vlan_set(hw, aq_vlans);
+ if (hw_atl_b0_hw_vlan_set(hw, aq_vlans) != 0)
+ device_printf(softc->dev,
+ "could not program the VLAN filter table\n");
if (hw_atl_b0_hw_vlan_promisc_set(hw,
aq_is_vlan_promisc_required(softc) ||
(if_getflags(iflib_get_ifp(softc->ctx)) & IFF_PROMISC) != 0) != 0)
@@ -1397,6 +1431,25 @@
return (sysctl_handle_int(oidp, &val, 0, req));
}
+/* arg2 selects the counter: 0 = link up, 1 = link down. */
+static int
+aq_sysctl_fw_link_counter(SYSCTL_HANDLER_ARGS)
+{
+ struct aq_dev *softc = arg1;
+ uint32_t up, down;
+ int error;
+
+ if (softc->hw.fw_ops == NULL ||
+ softc->hw.fw_ops->get_link_counters == NULL)
+ return (ENOTSUP);
+
+ error = softc->hw.fw_ops->get_link_counters(&softc->hw, &up, &down);
+ if (error != 0)
+ return (error);
+
+ return (sysctl_handle_32(oidp, arg2 == 0 ? &up : &down, 0, req));
+}
+
static void
aq_add_stats_sysctls(struct aq_dev *softc)
{
@@ -1407,6 +1460,7 @@
struct aq_stats *stats = &softc->curr_stats;
struct sysctl_oid *stat_node, *queue_node;
struct sysctl_oid_list *stat_list, *queue_list;
+ uint32_t link_up, link_down;
int temp_mc;
#define QUEUE_NAME_LEN 32
@@ -1431,6 +1485,21 @@
CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, softc, 0,
aq_sysctl_temperature, "IK", "PHY temperature");
+ /* Only some firmware interface versions count link transitions. */
+ if (softc->hw.fw_ops != NULL &&
+ softc->hw.fw_ops->get_link_counters != NULL &&
+ softc->hw.fw_ops->get_link_counters(&softc->hw, &link_up,
+ &link_down) != ENOTSUP) {
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "fw_link_up",
+ CTLTYPE_U32 | CTLFLAG_RD | CTLFLAG_MPSAFE, softc, 0,
+ aq_sysctl_fw_link_counter, "IU",
+ "Link up transitions counted by the firmware");
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "fw_link_down",
+ CTLTYPE_U32 | CTLFLAG_RD | CTLFLAG_MPSAFE, softc, 1,
+ aq_sysctl_fw_link_counter, "IU",
+ "Link down transitions counted by the firmware");
+ }
+
/* Driver Statistics */
for (int i = 0; i < softc->tx_rings_count; i++) {
struct aq_ring *ring = softc->tx_rings[i];

File Metadata

Mime Type
text/plain
Expires
Mon, Nov 16, 7:28 AM (23 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41742377
Default Alt Text
D58749.1794814104.diff (18 KB)

Event Timeline