Page MenuHomeFreeBSD

D58473.diff
No OneTemporary

D58473.diff

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
@@ -121,6 +121,7 @@
uint32_t tx_rings_count;
uint32_t rx_rings_count;
bool linkup;
+ uint32_t link_speed; /* Mbit/s last announced to the stack */
uint16_t phy_fault_last; /* last fault code reported */
enum aq_thermal_state {
AQ_THERMAL_NORMAL = 0, /* no thermal shutdown pending */
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
@@ -217,20 +217,31 @@
struct aq_dev *aq_dev = iflib_get_softc(ctx);
struct aq_hw *hw = &aq_dev->hw;
uint32_t link_speed;
+ bool running;
struct aq_hw_fc_info fc_neg;
aq_hw_get_link_state(hw, &link_speed, &fc_neg);
- /* An interface whose initialization did not complete has no link. */
- if (aq_dev->init_failed)
+ /* A stopped or half-initialized interface has no link. */
+ running = (if_getdrvflags(iflib_get_ifp(ctx)) & IFF_DRV_RUNNING) != 0;
+ if (!running || aq_dev->init_failed)
link_speed = 0;
- if (link_speed && !aq_dev->linkup) { /* link was DOWN */
- device_printf(aq_dev->dev, "link UP: speed=%d\n", link_speed);
+ /* A retrain can change the speed without ever dropping the link. */
+ if (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_dev->phy_fault_last = 0;
+ } else
+ device_printf(aq_dev->dev, "link speed=%d\n",
+ link_speed);
aq_dev->linkup = 1;
- aq_dev->phy_fault_last = 0;
+ aq_dev->link_speed = link_speed;
/* turn on/off RX Pause in RPB */
rpb_rx_xoff_en_per_tc_set(hw, fc_neg.fc_rx, 0);
@@ -242,9 +253,11 @@
/* update ITR settings according new link speed */
aq_hw_interrupt_moderation_set(hw);
} else if (link_speed == 0U && aq_dev->linkup) { /* link was UP */
- device_printf(aq_dev->dev, "link DOWN\n");
+ if (bootverbose)
+ device_printf(aq_dev->dev, "link DOWN\n");
aq_dev->linkup = 0;
+ aq_dev->link_speed = 0;
/* turn off RX Pause in RPB */
rpb_rx_xoff_en_per_tc_set(hw, 0, 0);
@@ -253,6 +266,10 @@
aq_mediastatus_update(aq_dev, link_speed, &fc_neg);
}
+ /* A stopped interface must not be re-initialized behind the operator. */
+ if (!running)
+ return;
+
/* Re-arming while a reset is queued would re-init once too often. */
if (aq_dev->init_failed) {
if (aq_dev->reset_pending)
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
@@ -559,6 +559,8 @@
aq_if_stop(ctx);
aq_hw_deinit(&softc->hw);
+ /* iflib_device_suspend() does not stop the interface for us. */
+ if_setdrvflagbits(iflib_get_ifp(ctx), IFF_DRV_OACTIVE, IFF_DRV_RUNNING);
AQ_DBG_EXIT(0);
return (0);
@@ -755,6 +757,9 @@
softc->reset_pending = false;
hw->tx_rings_count = softc->tx_rings_count;
+ /* Pick up a locally administered address set since the last init. */
+ bcopy(if_getlladdr(iflib_get_ifp(ctx)), hw->mac_addr, ETHER_ADDR_LEN);
+
err = aq_hw_init(&softc->hw, softc->hw.mac_addr, softc->msix,
softc->scctx->isc_intr == IFLIB_INTR_MSIX);
if (err != 0) {
@@ -855,8 +860,11 @@
memset(&softc->last_stats, 0, sizeof(softc->last_stats));
/* Each bring-up gets its own budget of re-init attempts. */
softc->init_retries = 0;
- softc->linkup = false;
- aq_if_update_admin_status(ctx);
+ if (softc->linkup) {
+ softc->linkup = false;
+ softc->link_speed = 0;
+ iflib_link_state_change(ctx, LINK_STATE_DOWN, 0);
+ }
AQ_DBG_EXIT(0);
}

File Metadata

Mime Type
text/plain
Expires
Sat, Aug 1, 7:00 AM (13 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35733624
Default Alt Text
D58473.diff (3 KB)

Event Timeline