Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F164160578
D58437.id182663.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D58437.id182663.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D58437: aq(4): mailbox, flow-control and firmware error-handling fixes
Attached
Detach File
Event Timeline
Log In to Comment