]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
bnxt_en: Add PHY retry logic.
authorMichael Chan <michael.chan@broadcom.com>
Sun, 5 Aug 2018 20:51:49 +0000 (16:51 -0400)
committerDavid S. Miller <davem@davemloft.net>
Mon, 6 Aug 2018 00:08:26 +0000 (17:08 -0700)
During hotplug, the driver's open function can be called almost
immediately after power on reset.  The PHY may not be ready and the
firmware may return failure when the driver tries to update PHY
settings.  Add retry logic fired from the driver's timer to retry
the operation for 5 seconds.

Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h

index d9fc905c599670a51ed191a84cecf5510cc3cfae..fd936c5e8760bd329474f0234be4a1ff5718ac4a 100644 (file)
@@ -6898,8 +6898,14 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
                mutex_lock(&bp->link_lock);
                rc = bnxt_update_phy_setting(bp);
                mutex_unlock(&bp->link_lock);
-               if (rc)
+               if (rc) {
                        netdev_warn(bp->dev, "failed to update phy settings\n");
+                       if (BNXT_SINGLE_PF(bp)) {
+                               bp->link_info.phy_retry = true;
+                               bp->link_info.phy_retry_expires =
+                                       jiffies + 5 * HZ;
+                       }
+               }
        }
 
        if (irq_re_init)
@@ -7583,6 +7589,16 @@ static void bnxt_timer(struct timer_list *t)
                set_bit(BNXT_FLOW_STATS_SP_EVENT, &bp->sp_event);
                bnxt_queue_sp_work(bp);
        }
+
+       if (bp->link_info.phy_retry) {
+               if (time_after(jiffies, bp->link_info.phy_retry_expires)) {
+                       bp->link_info.phy_retry = 0;
+                       netdev_warn(bp->dev, "failed to update phy settings after maximum retries.\n");
+               } else {
+                       set_bit(BNXT_UPDATE_PHY_SP_EVENT, &bp->sp_event);
+                       bnxt_queue_sp_work(bp);
+               }
+       }
 bnxt_restart_timer:
        mod_timer(&bp->timer, jiffies + bp->current_interval);
 }
@@ -7670,6 +7686,19 @@ static void bnxt_sp_task(struct work_struct *work)
                        netdev_err(bp->dev, "SP task can't update link (rc: %x)\n",
                                   rc);
        }
+       if (test_and_clear_bit(BNXT_UPDATE_PHY_SP_EVENT, &bp->sp_event)) {
+               int rc;
+
+               mutex_lock(&bp->link_lock);
+               rc = bnxt_update_phy_setting(bp);
+               mutex_unlock(&bp->link_lock);
+               if (rc) {
+                       netdev_warn(bp->dev, "update phy settings retry failed\n");
+               } else {
+                       bp->link_info.phy_retry = false;
+                       netdev_info(bp->dev, "update phy settings retry succeeded\n");
+               }
+       }
        if (test_and_clear_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event)) {
                mutex_lock(&bp->link_lock);
                bnxt_get_port_module_status(bp);
index 0d49fe015ba90cf269d68337bafa566cf38ba1fb..47eec148e745e583425ea5dca2f3d5a96fa82a6a 100644 (file)
@@ -959,6 +959,9 @@ struct bnxt_link_info {
        u16                     advertising;    /* user adv setting */
        bool                    force_link_chng;
 
+       bool                    phy_retry;
+       unsigned long           phy_retry_expires;
+
        /* a copy of phy_qcfg output used to report link
         * info to VF
         */
@@ -1344,6 +1347,7 @@ struct bnxt {
 #define BNXT_GENEVE_DEL_PORT_SP_EVENT  13
 #define BNXT_LINK_SPEED_CHNG_SP_EVENT  14
 #define BNXT_FLOW_STATS_SP_EVENT       15
+#define BNXT_UPDATE_PHY_SP_EVENT       16
 
        struct bnxt_hw_resc     hw_resc;
        struct bnxt_pf_info     pf;