Page MenuHomeFreeBSD

D58437.id182663.diff
No OneTemporary

D58437.id182663.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
@@ -130,6 +130,8 @@
int thermal_settle;
int thermal_temp_mc; /* temp at the last shutdown/cool */
int thermal_recover_mc; /* recover once cooled to here */
+ bool init_failed; /* aq_hw_init() left the hw down */
+ int init_retries;
int media_active;
struct aq_hw_stats last_stats;
diff --git a/sys/dev/aq/aq_fw1x.c b/sys/dev/aq/aq_fw1x.c
--- a/sys/dev/aq/aq_fw1x.c
+++ b/sys/dev/aq/aq_fw1x.c
@@ -167,12 +167,15 @@
uint32_t tid0 = ~0u; /*< Initial value of MBOX transactionId. */
struct aq_hw_fw_mbox mbox;
const int retryCount = 1000;
+ int err;
for (int i = 0; i < retryCount; ++i) {
// Read the beginning of Statistics structure to capture the
// Transaction ID.
- aq_hw_fw_downld_dwords(hw, hw->mbox_addr, (uint32_t*)&mbox,
+ err = aq_hw_fw_downld_dwords(hw, hw->mbox_addr, (uint32_t*)&mbox,
(uint32_t)((char*)&mbox.stats - (char*)&mbox) / sizeof(uint32_t));
+ if (err != 0)
+ return (err);
// Successfully read the stats.
if (tid0 == ~0U) {
diff --git a/sys/dev/aq/aq_fw2x.c b/sys/dev/aq/aq_fw2x.c
--- a/sys/dev/aq/aq_fw2x.c
+++ b/sys/dev/aq/aq_fw2x.c
@@ -245,9 +245,11 @@
{
struct aq_fw2x_capabilities caps = {0};
AQ_DBG_ENTER();
+ mtx_lock(&hw->fw_mtx);
int err = aq_hw_fw_downld_dwords(hw,
hw->mbox_addr + offsetof(struct aq_fw2x_mailbox, caps),
(uint32_t*)&caps, sizeof caps/sizeof(uint32_t));
+ mtx_unlock(&hw->fw_mtx);
if (err == 0) {
hw->fw_caps = caps.caps_lo | ((uint64_t)caps.caps_hi << 32);
trace(hw, dbg_init,
@@ -304,13 +306,14 @@
mpi_ctrl &= ~FW2X_RATE_MASK;
mpi_ctrl |= link_speed_mask_to_fw2x(speed);
mpi_ctrl &= ~FW2X_CAP_LINK_DROP;
+ mpi_ctrl &= ~(FW2X_FW_CAP_PAUSE | FW2X_FW_CAP_ASYM_PAUSE);
#if 0 // #todo #flowcontrol #pause #eee
if (pHal->pCfg->eee)
mpi_ctrl |= FW2X_EEE_MASK;
#endif
if (hw->fc.fc_rx)
- mpi_ctrl |= FW2X_FW_CAP_PAUSE;
- if (hw->fc.fc_tx)
+ mpi_ctrl |= FW2X_FW_CAP_PAUSE | FW2X_FW_CAP_ASYM_PAUSE;
+ else if (hw->fc.fc_tx)
mpi_ctrl |= FW2X_FW_CAP_ASYM_PAUSE;
break;
@@ -539,17 +542,20 @@
#define AQ_PHY_THERMAL_CTRL_REG 0xc478 /* 1E.C478 thermal control */
#define AQ_PHY_THERMAL_SD_EN 0x0400 /* .A thermalShutdownEnable */
-static uint16_t
+static int
aq_fw2x_mdio_op(struct aq_hw* hw, uint16_t mmd, uint16_t addr, int write,
- uint16_t data)
+ uint16_t data, uint16_t* val)
{
uint32_t pa = (((uint32_t)hw->phy_id & 0x1f) << 5) | (mmd & 0x1f);
+ int err;
AQ_WRITE_REG(hw, AQ_MDIO_IFACE(4), addr);
AQ_WRITE_REG(hw, AQ_MDIO_IFACE(2),
AQ_MDIO_EXECUTE | (AQ_MDIO_OP_ADDR << AQ_MDIO_OP_S) | pa);
- AQ_HW_WAIT_FOR((AQ_READ_REG(hw, AQ_MDIO_IFACE(2)) & AQ_MDIO_BUSY) == 0,
- 10, 10000);
+ err = AQ_HW_WAIT_FOR((AQ_READ_REG(hw, AQ_MDIO_IFACE(2)) &
+ AQ_MDIO_BUSY) == 0, 10, 10000);
+ if (err != 0)
+ return (err);
if (write) {
AQ_WRITE_REG(hw, AQ_MDIO_IFACE(3), data);
AQ_WRITE_REG(hw, AQ_MDIO_IFACE(2),
@@ -558,32 +564,45 @@
AQ_WRITE_REG(hw, AQ_MDIO_IFACE(2),
AQ_MDIO_EXECUTE | (AQ_MDIO_OP_READ << AQ_MDIO_OP_S) | pa);
}
- AQ_HW_WAIT_FOR((AQ_READ_REG(hw, AQ_MDIO_IFACE(2)) & AQ_MDIO_BUSY) == 0,
- 10, 10000);
- return ((uint16_t)AQ_READ_REG(hw, AQ_MDIO_IFACE(5)));
+ err = AQ_HW_WAIT_FOR((AQ_READ_REG(hw, AQ_MDIO_IFACE(2)) &
+ AQ_MDIO_BUSY) == 0, 10, 10000);
+ if (err != 0)
+ return (err);
+ if (val != NULL)
+ *val = (uint16_t)AQ_READ_REG(hw, AQ_MDIO_IFACE(5));
+
+ return (0);
}
/* MDIO is serialized against the F/W by cpu semaphore 0. */
-static void
+static int
aq_fw2x_phy_write(struct aq_hw* hw, uint16_t mmd, uint16_t addr, uint16_t data)
{
- if (AQ_HW_WAIT_FOR(reg_glb_cpu_sem_get(hw, AQ_FW_SM_MDIO) == 1U,
- 10, 10000) != 0)
- return;
- aq_fw2x_mdio_op(hw, mmd, addr, 1, data);
+ int err;
+
+ err = AQ_HW_WAIT_FOR(reg_glb_cpu_sem_get(hw, AQ_FW_SM_MDIO) == 1U,
+ 10, 10000);
+ if (err != 0)
+ return (err);
+ err = aq_fw2x_mdio_op(hw, mmd, addr, 1, data, NULL);
reg_glb_cpu_sem_set(hw, 1U, AQ_FW_SM_MDIO);
+
+ return (err);
}
static int
aq_fw2x_phy_read(struct aq_hw* hw, uint16_t mmd, uint16_t addr, uint16_t* val)
{
- if (AQ_HW_WAIT_FOR(reg_glb_cpu_sem_get(hw, AQ_FW_SM_MDIO) == 1U,
- 10, 10000) != 0)
- return (ETIMEDOUT);
- *val = aq_fw2x_mdio_op(hw, mmd, addr, 0, 0);
+ int err;
+
+ err = AQ_HW_WAIT_FOR(reg_glb_cpu_sem_get(hw, AQ_FW_SM_MDIO) == 1U,
+ 10, 10000);
+ if (err != 0)
+ return (err);
+ err = aq_fw2x_mdio_op(hw, mmd, addr, 0, 0, val);
reg_glb_cpu_sem_set(hw, 1U, AQ_FW_SM_MDIO);
- return (0);
+ return (err);
}
/* Discover the PHY's MDIO port address; it is strap-selectable, not fixed at 0. */
@@ -592,12 +611,17 @@
{
uint16_t val;
uint8_t id;
+ int err;
for (id = 0; id < AQ_PHY_ID_MAX; id++) {
hw->phy_id = id;
- if (aq_fw2x_phy_read(hw, AQ_MDIO_MMD_PMAPMD, AQ_PHY_ID2_REG,
- &val) == 0 && val != 0xffff)
+ err = aq_fw2x_phy_read(hw, AQ_MDIO_MMD_PMAPMD, AQ_PHY_ID2_REG,
+ &val);
+ if (err == 0 && val != 0xffff)
return (true);
+ /* A timeout means the controller is wedged, not this port. */
+ if (err == ETIMEDOUT)
+ break;
}
hw->phy_id = 0;
return (false);
@@ -607,11 +631,14 @@
static int
aq_fw2x_phy_reset(struct aq_hw* hw)
{
+ int err;
+
mtx_lock(&hw->fw_mtx);
- aq_fw2x_phy_write(hw, AQ_PHY_MMD_GLOBAL, AQ_PHY_RESET_REG, AQ_PHY_RESET);
+ err = aq_fw2x_phy_write(hw, AQ_PHY_MMD_GLOBAL, AQ_PHY_RESET_REG,
+ AQ_PHY_RESET);
mtx_unlock(&hw->fw_mtx);
- return (0);
+ return (err);
}
/* Arm autonomous thermal shutdown (1E.C478.A), cleared by any PHY reset. */
@@ -619,17 +646,21 @@
aq_fw2x_thermal_arm(struct aq_hw* hw)
{
uint16_t ctrl;
+ int err;
mtx_lock(&hw->fw_mtx);
if (!hw->phy_id_valid && aq_fw2x_init_phy_id(hw))
hw->phy_id_valid = true;
- if (aq_fw2x_phy_read(hw, AQ_PHY_MMD_GLOBAL, AQ_PHY_THERMAL_CTRL_REG,
- &ctrl) == 0 && ctrl != 0xffff && (ctrl & AQ_PHY_THERMAL_SD_EN) == 0)
- aq_fw2x_phy_write(hw, AQ_PHY_MMD_GLOBAL,
+ err = aq_fw2x_phy_read(hw, AQ_PHY_MMD_GLOBAL, AQ_PHY_THERMAL_CTRL_REG,
+ &ctrl);
+ if (err == 0 && ctrl == 0xffff)
+ err = ENXIO;
+ if (err == 0 && (ctrl & AQ_PHY_THERMAL_SD_EN) == 0)
+ err = aq_fw2x_phy_write(hw, AQ_PHY_MMD_GLOBAL,
AQ_PHY_THERMAL_CTRL_REG, ctrl | AQ_PHY_THERMAL_SD_EN);
mtx_unlock(&hw->fw_mtx);
- return (0);
+ return (err);
}
/* 1E.C421 high-temp shutdown threshold, degrees C in Q8.8 fixed point. */
diff --git a/sys/dev/aq/aq_hw.c b/sys/dev/aq/aq_hw.c
--- a/sys/dev/aq/aq_hw.c
+++ b/sys/dev/aq/aq_hw.c
@@ -109,6 +109,7 @@
err = ETIMEDOUT;
goto err_exit;
}
+ err = 0;
}
mif_mcp_up_mailbox_addr_set(hw, a);
@@ -124,6 +125,7 @@
1000U);
*(p++) = mif_mcp_up_mailbox_data_get(hw);
+ a += 4;
}
reg_glb_cpu_sem_set(hw, 1U, AQ_HW_FW_SM_RAM);
@@ -311,6 +313,12 @@
AQ_DBG_ENTER();
err = hw->fw_ops->get_mac_addr(hw, mac);
+ if (err != 0) {
+ device_printf(hw->dev, "could not read the MAC address: %d\n",
+ err);
+ AQ_DBG_EXIT(err);
+ return (err);
+ }
/* Couldn't get MAC address from HW. Use auto-generated one. */
if ((mac[0] & 1) || ((mac[0] | mac[1] | mac[2]) == 0)) {
@@ -815,7 +823,9 @@
aq_hw_mac_addr_set(hw, mac_addr, AQ_HW_MAC);
- aq_hw_mpi_set(hw, MPI_INIT, hw->link_rate);
+ err = aq_hw_mpi_set(hw, MPI_INIT, hw->link_rate);
+ if (err != 0)
+ goto err_exit;
aq_hw_qos_set(hw);
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
@@ -117,6 +117,7 @@
#define AQ_THERMAL_HYSTERESIS_MC 18000 /* recover this far below the limit */
#define AQ_THERMAL_RECOVER_MC 90000 /* fallback when the limit is unreadable */
#define AQ_THERMAL_SETTLE_POLLS 5 /* ~5 s for the PHY reset to settle */
+#define AQ_INIT_MAX_RETRIES 5 /* re-init attempts after a failed init */
/* Temperature here is post-trip; the PHY is already dropping to low power. */
static void
@@ -178,7 +179,8 @@
return;
aq_dev->thermal_temp_mc = temp_mc;
if (hw->fw_ops->phy_reset != NULL) {
- hw->fw_ops->phy_reset(hw);
+ if (hw->fw_ops->phy_reset(hw) != 0)
+ return;
aq_dev->thermal_settle = 0;
aq_dev->thermal_state = AQ_THERMAL_SETTLING;
return;
@@ -236,6 +238,20 @@
aq_mediastatus_update(aq_dev, link_speed, &fc_neg);
}
+ /* Hardware is not initialized: retry a bounded number of times. */
+ if (aq_dev->init_failed) {
+ if (aq_dev->init_retries < AQ_INIT_MAX_RETRIES) {
+ aq_dev->init_retries++;
+ iflib_request_reset(ctx);
+ } else if (aq_dev->init_retries == AQ_INIT_MAX_RETRIES) {
+ aq_dev->init_retries++;
+ device_printf(aq_dev->dev, "initialization failed; "
+ "giving up after %d retries, link held down\n",
+ AQ_INIT_MAX_RETRIES);
+ }
+ return;
+ }
+
if (hw->fw_ops->get_phy_fault != NULL)
aq_thermal_poll(aq_dev);
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
@@ -484,7 +484,8 @@
goto exit;
break;
case IFLIB_INTR_MSI:
- break;
+ rc = EOPNOTSUPP;
+ goto exit;
case IFLIB_INTR_MSIX:
break;
default:
@@ -755,13 +756,18 @@
softc->scctx->isc_intr == IFLIB_INTR_MSIX);
if (err != 0) {
device_printf(softc->dev, "aq_hw_init: %d\n", err);
+ softc->init_failed = true;
AQ_DBG_EXIT(err);
return;
}
+ softc->init_failed = false;
+ softc->init_retries = 0;
/* aq_hw_init reloads the PHY, resetting the thermal-shutdown arming. */
- if (hw->fw_ops->thermal_arm != NULL)
- hw->fw_ops->thermal_arm(hw);
+ if (hw->fw_ops->thermal_arm != NULL &&
+ hw->fw_ops->thermal_arm(hw) != 0)
+ device_printf(softc->dev,
+ "could not arm PHY thermal shutdown\n");
aq_if_media_status(ctx, &ifmr);
@@ -805,7 +811,9 @@
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);
- aq_hw_set_link_speed(hw, hw->link_rate);
+ 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);
/* iflib does not replay filter state after init; aq_hw_init() clears it. */
aq_if_multi_set(ctx);

File Metadata

Mime Type
text/plain
Expires
Thu, Jul 30, 6:25 AM (11 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35675608
Default Alt Text
D58437.id182663.diff (10 KB)

Event Timeline