/* Wait for all pending SP commands to complete */
        if (!bnx2x_wait_sp_comp(bp, ~0x0UL)) {
                BNX2X_ERR("Timeout waiting for SP elements to complete\n");
-               bnx2x_nic_unload(bp, UNLOAD_CLOSE);
+               bnx2x_nic_unload(bp, UNLOAD_CLOSE, false);
                return -EBUSY;
        }
 
 }
 
 /* must be called with rtnl_lock */
-int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
+int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
 {
        int i;
        bool global = false;
 
        /* Cleanup the chip if needed */
        if (unload_mode != UNLOAD_RECOVERY)
-               bnx2x_chip_cleanup(bp, unload_mode);
+               bnx2x_chip_cleanup(bp, unload_mode, keep_link);
        else {
                /* Send the UNLOAD_REQUEST to the MCP */
                bnx2x_send_unload_req(bp, unload_mode);
                bnx2x_free_irq(bp);
 
                /* Report UNLOAD_DONE to MCP */
-               bnx2x_send_unload_done(bp);
+               bnx2x_send_unload_done(bp, false);
        }
 
        /*
        if (unlikely(!netif_running(dev)))
                return 0;
 
-       bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+       bnx2x_nic_unload(bp, UNLOAD_NORMAL, true);
        return bnx2x_nic_load(bp, LOAD_NORMAL);
 }
 
 
        netif_device_detach(dev);
 
-       bnx2x_nic_unload(bp, UNLOAD_CLOSE);
+       bnx2x_nic_unload(bp, UNLOAD_CLOSE, false);
 
        bnx2x_set_power_state(bp, pci_choose_state(pdev, state));
 
 
  * bnx2x_send_unload_done - send UNLOAD_DONE command to the MCP.
  *
  * @bp:                driver handle
+ * @keep_link:         true iff link should be kept up
  */
-void bnx2x_send_unload_done(struct bnx2x *bp);
+void bnx2x_send_unload_done(struct bnx2x *bp, bool keep_link);
 
 /**
  * bnx2x_config_rss_pf - configure RSS parameters in a PF.
  */
 void bnx2x_link_set(struct bnx2x *bp);
 
+/**
+ * bnx2x_force_link_reset - Forces link reset, and put the PHY
+ * in reset as well.
+ *
+ * @bp:                driver handle
+ */
+void bnx2x_force_link_reset(struct bnx2x *bp);
+
 /**
  * bnx2x_link_test - query link status.
  *
  *
  * @bp:                        driver handle
  * @unload_mode:       COMMON, PORT, FUNCTION
+ * @keep_link:         true iff link should be kept up.
  *
  * - Cleanup MAC configuration.
  * - Closes clients.
  * - etc.
  */
-void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode);
+void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode, bool keep_link);
 
 /**
  * bnx2x_acquire_hw_lock - acquire HW lock.
 bool bnx2x_test_firmware_version(struct bnx2x *bp, bool is_err);
 
 /* dev_close main block */
-int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode);
+int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link);
 
 /* dev_open main block */
 int bnx2x_nic_load(struct bnx2x *bp, int load_mode);
 
 
        if (netif_running(dev)) {
                bnx2x_stats_handle(bp, STATS_EVENT_STOP);
+               bnx2x_force_link_reset(bp);
                bnx2x_link_set(bp);
        }
 
        /* Restart link to propogate changes */
        if (netif_running(dev)) {
                bnx2x_stats_handle(bp, STATS_EVENT_STOP);
+               bnx2x_force_link_reset(bp);
                bnx2x_link_set(bp);
        }
 
        if (!netif_running(bp->dev))
                return BNX2X_EXT_LOOPBACK_FAILED;
 
-       bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+       bnx2x_nic_unload(bp, UNLOAD_NORMAL, false);
        rc = bnx2x_nic_load(bp, LOAD_LOOPBACK_EXT);
        if (rc) {
                DP(BNX2X_MSG_ETHTOOL,
 
                link_up = bp->link_vars.link_up;
 
-               bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+               bnx2x_nic_unload(bp, UNLOAD_NORMAL, false);
                rc = bnx2x_nic_load(bp, LOAD_DIAG);
                if (rc) {
                        etest->flags |= ETH_TEST_FL_FAILED;
                        etest->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
                }
 
-               bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+               bnx2x_nic_unload(bp, UNLOAD_NORMAL, false);
 
                /* restore input for TX port IF */
                REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, val);
                bnx2x_change_num_queues(bp, channels->combined_count);
                return 0;
        }
-       bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+       bnx2x_nic_unload(bp, UNLOAD_NORMAL, true);
        bnx2x_change_num_queues(bp, channels->combined_count);
        return bnx2x_nic_load(bp, LOAD_NORMAL);
 }
 
        #define DRV_MSG_CODE_SET_MF_BW_MIN_MASK         0x00ff0000
        #define DRV_MSG_CODE_SET_MF_BW_MAX_MASK         0xff000000
 
+       #define DRV_MSG_CODE_UNLOAD_SKIP_LINK_RESET     0x00000002
+
+       #define DRV_MSG_CODE_LOAD_REQ_WITH_LFA          0x0000100a
        u32 fw_mb_header;
        #define FW_MSG_CODE_MASK                        0xffff0000
        #define FW_MSG_CODE_DRV_LOAD_COMMON             0x10100000
 
    to 0 */
 int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
                     u8 reset_ext_phy);
-
+int bnx2x_lfa_reset(struct link_params *params, struct link_vars *vars);
 /* bnx2x_link_update should be called upon link interrupt */
 int bnx2x_link_update(struct link_params *params, struct link_vars *vars);
 
 
 {
        if (!BP_NOMCP(bp)) {
                bnx2x_acquire_phy_lock(bp);
-               bnx2x_link_reset(&bp->link_params, &bp->link_vars, 1);
                bnx2x_phy_init(&bp->link_params, &bp->link_vars);
                bnx2x_release_phy_lock(bp);
 
 {
        if (!BP_NOMCP(bp)) {
                bnx2x_acquire_phy_lock(bp);
-               bnx2x_link_reset(&bp->link_params, &bp->link_vars, 1);
+               bnx2x_lfa_reset(&bp->link_params, &bp->link_vars);
                bnx2x_release_phy_lock(bp);
        } else
                BNX2X_ERR("Bootcode is missing - can not reset link\n");
 }
 
+void bnx2x_force_link_reset(struct bnx2x *bp)
+{
+       bnx2x_acquire_phy_lock(bp);
+       bnx2x_link_reset(&bp->link_params, &bp->link_vars, 1);
+       bnx2x_release_phy_lock(bp);
+}
+
 u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes)
 {
        u8 rc = 0;
        u32 low, high;
        u32 val;
 
-       bnx2x__link_reset(bp);
 
        DP(NETIF_MSG_HW, "starting port init  port %d\n", port);
 
  * bnx2x_send_unload_done - send UNLOAD_DONE command to the MCP.
  *
  * @bp:                driver handle
+ * @keep_link:         true iff link should be kept up
  */
-void bnx2x_send_unload_done(struct bnx2x *bp)
+void bnx2x_send_unload_done(struct bnx2x *bp, bool keep_link)
 {
+       u32 reset_param = keep_link ? DRV_MSG_CODE_UNLOAD_SKIP_LINK_RESET : 0;
+
        /* Report UNLOAD_DONE to MCP */
        if (!BP_NOMCP(bp))
-               bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
+               bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, reset_param);
 }
 
 static int bnx2x_func_wait_started(struct bnx2x *bp)
        return 0;
 }
 
-void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
+void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode, bool keep_link)
 {
        int port = BP_PORT(bp);
        int i, rc = 0;
 
 
        /* Report UNLOAD_DONE to MCP */
-       bnx2x_send_unload_done(bp);
+       bnx2x_send_unload_done(bp, keep_link);
 }
 
 void bnx2x_disable_close_the_gate(struct bnx2x *bp)
         * driver is owner of the HW
         */
        if (!global && !BP_NOMCP(bp)) {
-               load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0);
+               load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ,
+                                            DRV_MSG_CODE_LOAD_REQ_WITH_LFA);
                if (!load_code) {
                        BNX2X_ERR("MCP response failure, aborting\n");
                        rc = -EAGAIN;
 
                        /* Stop the driver */
                        /* If interface has been removed - break */
-                       if (bnx2x_nic_unload(bp, UNLOAD_RECOVERY))
+                       if (bnx2x_nic_unload(bp, UNLOAD_RECOVERY, false))
                                return;
 
                        bp->recovery_state = BNX2X_RECOVERY_WAIT;
                bp->sp_rtnl_state = 0;
                smp_mb();
 
-               bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+               bnx2x_nic_unload(bp, UNLOAD_NORMAL, true);
                bnx2x_nic_load(bp, LOAD_NORMAL);
 
                goto sp_rtnl_exit;
 
 static int __devinit bnx2x_prev_mcp_done(struct bnx2x *bp)
 {
-       u32 rc = bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
+       u32 rc = bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE,
+                                 DRV_MSG_CODE_UNLOAD_SKIP_LINK_RESET);
        if (!rc) {
                BNX2X_ERR("MCP response failure, aborting\n");
                return -EBUSY;
        struct bnx2x *bp = netdev_priv(dev);
 
        /* Unload the driver, release IRQs */
-       bnx2x_nic_unload(bp, UNLOAD_CLOSE);
+       bnx2x_nic_unload(bp, UNLOAD_CLOSE, false);
 
        /* Power off */
        bnx2x_set_power_state(bp, PCI_D3hot);