mwl8k: remove usage of deprecated noise value
[safe/jmp/linux-2.6] / drivers / net / ixgbe / ixgbe_common.c
index 6f79409..eb49020 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2009 Intel Corporation.
+  Copyright(c) 1999 - 2010 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -28,7 +28,6 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
-#include <linux/list.h>
 #include <linux/netdevice.h>
 
 #include "ixgbe.h"
@@ -53,6 +52,7 @@ static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index);
 static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index);
 static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);
 static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq);
+static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num);
 
 /**
  *  ixgbe_start_hw_generic - Prepare hardware for Tx/Rx
@@ -85,6 +85,9 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
        IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
        IXGBE_WRITE_FLUSH(hw);
 
+       /* Setup flow control */
+       ixgbe_setup_fc(hw, 0);
+
        /* Clear adapter stopped flag */
        hw->adapter_stopped = false;
 
@@ -103,13 +106,17 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
  **/
 s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw)
 {
+       s32 status;
+
        /* Reset the hardware */
-       hw->mac.ops.reset_hw(hw);
+       status = hw->mac.ops.reset_hw(hw);
 
-       /* Start the HW */
-       hw->mac.ops.start_hw(hw);
+       if (status == 0) {
+               /* Start the HW */
+               status = hw->mac.ops.start_hw(hw);
+       }
 
-       return 0;
+       return status;
 }
 
 /**
@@ -1270,19 +1277,11 @@ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw)
                /* Get the MAC address from the RAR0 for later reference */
                hw->mac.ops.get_mac_addr(hw, hw->mac.addr);
 
-               hw_dbg(hw, " Keeping Current RAR0 Addr =%.2X %.2X %.2X ",
-                      hw->mac.addr[0], hw->mac.addr[1],
-                      hw->mac.addr[2]);
-               hw_dbg(hw, "%.2X %.2X %.2X\n", hw->mac.addr[3],
-                      hw->mac.addr[4], hw->mac.addr[5]);
+               hw_dbg(hw, " Keeping Current RAR0 Addr =%pM\n", hw->mac.addr);
        } else {
                /* Setup the receive address. */
                hw_dbg(hw, "Overriding MAC Address in RAR[0]\n");
-               hw_dbg(hw, " New MAC Addr =%.2X %.2X %.2X ",
-                      hw->mac.addr[0], hw->mac.addr[1],
-                      hw->mac.addr[2]);
-               hw_dbg(hw, "%.2X %.2X %.2X\n", hw->mac.addr[3],
-                      hw->mac.addr[4], hw->mac.addr[5]);
+               hw_dbg(hw, " New MAC Addr =%pM\n", hw->mac.addr);
 
                hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
        }
@@ -1347,9 +1346,7 @@ static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
 /**
  *  ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses
  *  @hw: pointer to hardware structure
- *  @addr_list: the list of new addresses
- *  @addr_count: number of addresses
- *  @next: iterator function to walk the address list
+ *  @netdev: pointer to net device structure
  *
  *  The given list replaces any existing list.  Clears the secondary addrs from
  *  receive address registers.  Uses unused receive address registers for the
@@ -1359,7 +1356,7 @@ static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
  *  manually putting the device into promiscuous mode.
  **/
 s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw,
-                                     struct list_head *uc_list)
+                                     struct net_device *netdev)
 {
        u32 i;
        u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc;
@@ -1376,14 +1373,14 @@ s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw,
        hw->addr_ctrl.overflow_promisc = 0;
 
        /* Zero out the other receive addresses */
-       hw_dbg(hw, "Clearing RAR[1-%d]\n", uc_addr_in_use);
-       for (i = 1; i <= uc_addr_in_use; i++) {
-               IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
-               IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
+       hw_dbg(hw, "Clearing RAR[1-%d]\n", uc_addr_in_use + 1);
+       for (i = 0; i < uc_addr_in_use; i++) {
+               IXGBE_WRITE_REG(hw, IXGBE_RAL(1+i), 0);
+               IXGBE_WRITE_REG(hw, IXGBE_RAH(1+i), 0);
        }
 
        /* Add the new addresses */
-       list_for_each_entry(ha, uc_list, list) {
+       netdev_for_each_uc_addr(ha, netdev) {
                hw_dbg(hw, " Adding the secondary addresses:\n");
                ixgbe_add_uc_addr(hw, ha->addr, 0);
        }
@@ -1577,17 +1574,16 @@ s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw)
 }
 
 /**
- *  ixgbe_fc_enable - Enable flow control
+ *  ixgbe_fc_enable_generic - Enable flow control
  *  @hw: pointer to hardware structure
  *  @packetbuf_num: packet buffer number (0-7)
  *
  *  Enable flow control according to the current settings.
  **/
-s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packetbuf_num)
+s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
 {
        s32 ret_val = 0;
-       u32 mflcn_reg;
-       u32 fccfg_reg;
+       u32 mflcn_reg, fccfg_reg;
        u32 reg;
        u32 rx_pba_size;
 
@@ -1596,7 +1592,12 @@ s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packetbuf_num)
                goto out;
 
 #endif /* CONFIG_DCB */
+       /* Negotiate the fc mode to use */
+       ret_val = ixgbe_fc_autoneg(hw);
+       if (ret_val)
+               goto out;
 
+       /* Disable any previous flow control settings */
        mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
        mflcn_reg &= ~(IXGBE_MFLCN_RFCE | IXGBE_MFLCN_RPFCE);
 
@@ -1616,7 +1617,10 @@ s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packetbuf_num)
         */
        switch (hw->fc.current_mode) {
        case ixgbe_fc_none:
-               /* Flow control completely disabled by software override. */
+               /*
+                * Flow control is disabled by software override or autoneg.
+                * The code below will actually disable it in the HW.
+                */
                break;
        case ixgbe_fc_rx_pause:
                /*
@@ -1645,15 +1649,15 @@ s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packetbuf_num)
        case ixgbe_fc_pfc:
                goto out;
                break;
-#endif
+#endif /* CONFIG_DCB */
        default:
                hw_dbg(hw, "Flow control param set incorrectly\n");
-               ret_val = -IXGBE_ERR_CONFIG;
+               ret_val = IXGBE_ERR_CONFIG;
                goto out;
                break;
        }
 
-       /* Enable 802.3x based flow control settings. */
+       /* Set 802.3x based flow control settings. */
        mflcn_reg |= IXGBE_MFLCN_DPF;
        IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg);
        IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg);
@@ -1661,10 +1665,12 @@ s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packetbuf_num)
        reg = IXGBE_READ_REG(hw, IXGBE_MTQC);
        /* Thresholds are different for link flow control when in DCB mode */
        if (reg & IXGBE_MTQC_RT_ENA) {
+               rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num));
+
                /* Always disable XON for LFC when in DCB mode */
-               IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), 0);
+               reg = (rx_pba_size >> 5) & 0xFFE0;
+               IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), reg);
 
-               rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num));
                reg = (rx_pba_size >> 2) & 0xFFE0;
                if (hw->fc.current_mode & ixgbe_fc_tx_pause)
                        reg |= IXGBE_FCRTH_FCEN;
@@ -1709,100 +1715,83 @@ out:
  *  ixgbe_fc_autoneg - Configure flow control
  *  @hw: pointer to hardware structure
  *
- *  Negotiates flow control capabilities with link partner using autoneg and
- *  applies the results.
+ *  Compares our advertised flow control capabilities to those advertised by
+ *  our link partner, and determines the proper flow control mode to use.
  **/
 s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
 {
        s32 ret_val = 0;
-       u32 i, reg, pcs_anadv_reg, pcs_lpab_reg;
-
-       reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+       ixgbe_link_speed speed;
+       u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
+       u32 links2, anlp1_reg, autoc_reg, links;
+       bool link_up;
 
        /*
-        * The possible values of fc.current_mode are:
-        * 0:  Flow control is completely disabled
-        * 1:  Rx flow control is enabled (we can receive pause frames,
-        *     but not send pause frames).
-        * 2:  Tx flow control is enabled (we can send pause frames but
-        *     we do not support receiving pause frames).
-        * 3:  Both Rx and Tx flow control (symmetric) are enabled.
-        * 4:  Priority Flow Control is enabled.
-        * other: Invalid.
+        * AN should have completed when the cable was plugged in.
+        * Look for reasons to bail out.  Bail out if:
+        * - FC autoneg is disabled, or if
+        * - link is not up.
+        *
+        * Since we're being called from an LSC, link is already known to be up.
+        * So use link_up_wait_to_complete=false.
         */
-       switch (hw->fc.current_mode) {
-       case ixgbe_fc_none:
-               /* Flow control completely disabled by software override. */
-               reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
-               break;
-       case ixgbe_fc_rx_pause:
-               /*
-                * Rx Flow control is enabled and Tx Flow control is
-                * disabled by software override. Since there really
-                * isn't a way to advertise that we are capable of RX
-                * Pause ONLY, we will advertise that we support both
-                * symmetric and asymmetric Rx PAUSE.  Later, we will
-                * disable the adapter's ability to send PAUSE frames.
-                */
-               reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
-               break;
-       case ixgbe_fc_tx_pause:
-               /*
-                * Tx Flow control is enabled, and Rx Flow control is
-                * disabled by software override.
-                */
-               reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
-               reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
-               break;
-       case ixgbe_fc_full:
-               /* Flow control (both Rx and Tx) is enabled by SW override. */
-               reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
-               break;
-#ifdef CONFIG_DCB
-       case ixgbe_fc_pfc:
-               goto out;
-               break;
-#endif
-       default:
-               hw_dbg(hw, "Flow control param set incorrectly\n");
-               ret_val = -IXGBE_ERR_CONFIG;
+       hw->mac.ops.check_link(hw, &speed, &link_up, false);
+
+       if (hw->fc.disable_fc_autoneg || (!link_up)) {
+               hw->fc.fc_was_autonegged = false;
+               hw->fc.current_mode = hw->fc.requested_mode;
                goto out;
-               break;
        }
 
-       IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
-       reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
-
-       /* Set PCS register for autoneg */
-       /* Enable and restart autoneg */
-       reg |= IXGBE_PCS1GLCTL_AN_ENABLE | IXGBE_PCS1GLCTL_AN_RESTART;
-
-       /* Disable AN timeout */
-       if (hw->fc.strict_ieee)
-               reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
+       /*
+        * On backplane, bail out if
+        * - backplane autoneg was not completed, or if
+        * - we are 82599 and link partner is not AN enabled
+        */
+       if (hw->phy.media_type == ixgbe_media_type_backplane) {
+               links = IXGBE_READ_REG(hw, IXGBE_LINKS);
+               if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) {
+                       hw->fc.fc_was_autonegged = false;
+                       hw->fc.current_mode = hw->fc.requested_mode;
+                       goto out;
+               }
 
-       hw_dbg(hw, "Configuring Autoneg; PCS_LCTL = 0x%08X\n", reg);
-       IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
+               if (hw->mac.type == ixgbe_mac_82599EB) {
+                       links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
+                       if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) {
+                               hw->fc.fc_was_autonegged = false;
+                               hw->fc.current_mode = hw->fc.requested_mode;
+                               goto out;
+                       }
+               }
+       }
 
-       /* See if autonegotiation has succeeded */
-       hw->mac.autoneg_succeeded = 0;
-       for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) {
-               msleep(10);
-               reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
-               if ((reg & (IXGBE_PCS1GLSTA_LINK_OK |
-                    IXGBE_PCS1GLSTA_AN_COMPLETE)) ==
-                   (IXGBE_PCS1GLSTA_LINK_OK |
-                    IXGBE_PCS1GLSTA_AN_COMPLETE)) {
-                       if (!(reg & IXGBE_PCS1GLSTA_AN_TIMED_OUT))
-                               hw->mac.autoneg_succeeded = 1;
-                       break;
+       /*
+        * On multispeed fiber at 1g, bail out if
+        * - link is up but AN did not complete, or if
+        * - link is up and AN completed but timed out
+        */
+       if (hw->phy.multispeed_fiber && (speed == IXGBE_LINK_SPEED_1GB_FULL)) {
+               linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
+               if (((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
+                   ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
+                       hw->fc.fc_was_autonegged = false;
+                       hw->fc.current_mode = hw->fc.requested_mode;
+                       goto out;
                }
        }
 
-       if (!hw->mac.autoneg_succeeded) {
-               /* Autoneg failed to achieve a link, so we turn fc off */
-               hw->fc.current_mode = ixgbe_fc_none;
-               hw_dbg(hw, "Flow Control = NONE.\n");
+       /*
+        * Bail out on
+        * - copper or CX4 adapters
+        * - fiber adapters running at 10gig
+        */
+       if ((hw->phy.media_type == ixgbe_media_type_copper) ||
+            (hw->phy.media_type == ixgbe_media_type_cx4) ||
+            ((hw->phy.media_type == ixgbe_media_type_fiber) &&
+            (speed == IXGBE_LINK_SPEED_10GB_FULL))) {
+               hw->fc.fc_was_autonegged = false;
+               hw->fc.current_mode = hw->fc.requested_mode;
                goto out;
        }
 
@@ -1810,56 +1799,102 @@ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
         * Read the AN advertisement and LP ability registers and resolve
         * local flow control settings accordingly
         */
-       pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
-       pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
-       if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-               (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) {
+       if ((speed == IXGBE_LINK_SPEED_1GB_FULL) &&
+           (hw->phy.media_type != ixgbe_media_type_backplane)) {
+               pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+               pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
+               if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+                   (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) {
+                       /*
+                        * Now we need to check if the user selected Rx ONLY
+                        * of pause frames.  In this case, we had to advertise
+                        * FULL flow control because we could not advertise RX
+                        * ONLY. Hence, we must now check to see if we need to
+                        * turn OFF the TRANSMISSION of PAUSE frames.
+                        */
+                       if (hw->fc.requested_mode == ixgbe_fc_full) {
+                               hw->fc.current_mode = ixgbe_fc_full;
+                               hw_dbg(hw, "Flow Control = FULL.\n");
+                       } else {
+                               hw->fc.current_mode = ixgbe_fc_rx_pause;
+                               hw_dbg(hw, "Flow Control=RX PAUSE only\n");
+                       }
+               } else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+                          (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
+                          (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+                          (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
+                       hw->fc.current_mode = ixgbe_fc_tx_pause;
+                       hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
+               } else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+                          (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
+                          !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
+                          (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
+                       hw->fc.current_mode = ixgbe_fc_rx_pause;
+                       hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
+               } else {
+                       hw->fc.current_mode = ixgbe_fc_none;
+                       hw_dbg(hw, "Flow Control = NONE.\n");
+               }
+       }
+
+       if (hw->phy.media_type == ixgbe_media_type_backplane) {
                /*
-                * Now we need to check if the user selected Rx ONLY
-                * of pause frames.  In this case, we had to advertise
-                * FULL flow control because we could not advertise RX
-                * ONLY. Hence, we must now check to see if we need to
-                * turn OFF the TRANSMISSION of PAUSE frames.
+                * Read the 10g AN autoc and LP ability registers and resolve
+                * local flow control settings accordingly
                 */
-               if (hw->fc.requested_mode == ixgbe_fc_full) {
-                       hw->fc.current_mode = ixgbe_fc_full;
-                       hw_dbg(hw, "Flow Control = FULL.\n");
-               } else {
+               autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+               anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
+
+               if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
+                   (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE)) {
+                       /*
+                        * Now we need to check if the user selected Rx ONLY
+                        * of pause frames.  In this case, we had to advertise
+                        * FULL flow control because we could not advertise RX
+                        * ONLY. Hence, we must now check to see if we need to
+                        * turn OFF the TRANSMISSION of PAUSE frames.
+                        */
+                       if (hw->fc.requested_mode == ixgbe_fc_full) {
+                               hw->fc.current_mode = ixgbe_fc_full;
+                               hw_dbg(hw, "Flow Control = FULL.\n");
+                       } else {
+                               hw->fc.current_mode = ixgbe_fc_rx_pause;
+                               hw_dbg(hw, "Flow Control=RX PAUSE only\n");
+                       }
+               } else if (!(autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
+                          (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) &&
+                          (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) &&
+                          (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) {
+                       hw->fc.current_mode = ixgbe_fc_tx_pause;
+                       hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
+               } else if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
+                          (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) &&
+                          !(anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) &&
+                          (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) {
                        hw->fc.current_mode = ixgbe_fc_rx_pause;
                        hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
+               } else {
+                       hw->fc.current_mode = ixgbe_fc_none;
+                       hw_dbg(hw, "Flow Control = NONE.\n");
                }
-       } else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-                  (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
-                  (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-                  (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
-               hw->fc.current_mode = ixgbe_fc_tx_pause;
-               hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
-       } else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-                  (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
-                  !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-                  (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
-               hw->fc.current_mode = ixgbe_fc_rx_pause;
-               hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
-       } else {
-               hw->fc.current_mode = ixgbe_fc_none;
-               hw_dbg(hw, "Flow Control = NONE.\n");
        }
+       /* Record that current_mode is the result of a successful autoneg */
+       hw->fc.fc_was_autonegged = true;
 
 out:
        return ret_val;
 }
 
 /**
- *  ixgbe_setup_fc_generic - Set up flow control
+ *  ixgbe_setup_fc - Set up flow control
  *  @hw: pointer to hardware structure
  *
- *  Sets up flow control.
+ *  Called at init time to set up flow control.
  **/
-s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
+static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
 {
        s32 ret_val = 0;
-       ixgbe_link_speed speed;
-       bool link_up;
+       u32 reg;
 
 #ifdef CONFIG_DCB
        if (hw->fc.requested_mode == ixgbe_fc_pfc) {
@@ -1881,16 +1916,14 @@ s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
         * because it causes the controller to just blast out fc packets.
         */
        if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) {
-               if (hw->fc.requested_mode != ixgbe_fc_none) {
-                       hw_dbg(hw, "Invalid water mark configuration\n");
-                       ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
-                       goto out;
-               }
+               hw_dbg(hw, "Invalid water mark configuration\n");
+               ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+               goto out;
        }
 
        /*
         * Validate the requested mode.  Strict IEEE mode does not allow
-        * ixgbe_fc_rx_pause because it will cause testing anomalies.
+        * ixgbe_fc_rx_pause because it will cause us to fail at UNH.
         */
        if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
                hw_dbg(hw, "ixgbe_fc_rx_pause not valid in strict "
@@ -1907,21 +1940,138 @@ s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
                hw->fc.requested_mode = ixgbe_fc_full;
 
        /*
-        * Save off the requested flow control mode for use later.  Depending
-        * on the link partner's capabilities, we may or may not use this mode.
+        * Set up the 1G flow control advertisement registers so the HW will be
+        * able to do fc autoneg once the cable is plugged in.  If we end up
+        * using 10g instead, this is harmless.
         */
-       hw->fc.current_mode = hw->fc.requested_mode;
-
-       /* Decide whether to use autoneg or not. */
-       hw->mac.ops.check_link(hw, &speed, &link_up, false);
-       if (!hw->fc.disable_fc_autoneg && hw->phy.multispeed_fiber &&
-           (speed == IXGBE_LINK_SPEED_1GB_FULL))
-               ret_val = ixgbe_fc_autoneg(hw);
+       reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
 
-       if (ret_val)
+       /*
+        * The possible values of fc.requested_mode are:
+        * 0: Flow control is completely disabled
+        * 1: Rx flow control is enabled (we can receive pause frames,
+        *    but not send pause frames).
+        * 2: Tx flow control is enabled (we can send pause frames but
+        *    we do not support receiving pause frames).
+        * 3: Both Rx and Tx flow control (symmetric) are enabled.
+#ifdef CONFIG_DCB
+        * 4: Priority Flow Control is enabled.
+#endif
+        * other: Invalid.
+        */
+       switch (hw->fc.requested_mode) {
+       case ixgbe_fc_none:
+               /* Flow control completely disabled by software override. */
+               reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+               break;
+       case ixgbe_fc_rx_pause:
+               /*
+                * Rx Flow control is enabled and Tx Flow control is
+                * disabled by software override. Since there really
+                * isn't a way to advertise that we are capable of RX
+                * Pause ONLY, we will advertise that we support both
+                * symmetric and asymmetric Rx PAUSE.  Later, we will
+                * disable the adapter's ability to send PAUSE frames.
+                */
+               reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+               break;
+       case ixgbe_fc_tx_pause:
+               /*
+                * Tx Flow control is enabled, and Rx Flow control is
+                * disabled by software override.
+                */
+               reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
+               reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
+               break;
+       case ixgbe_fc_full:
+               /* Flow control (both Rx and Tx) is enabled by SW override. */
+               reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+               break;
+#ifdef CONFIG_DCB
+       case ixgbe_fc_pfc:
                goto out;
+               break;
+#endif /* CONFIG_DCB */
+       default:
+               hw_dbg(hw, "Flow control param set incorrectly\n");
+               ret_val = IXGBE_ERR_CONFIG;
+               goto out;
+               break;
+       }
 
-       ret_val = ixgbe_fc_enable(hw, packetbuf_num);
+       IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
+       reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
+
+       /* Disable AN timeout */
+       if (hw->fc.strict_ieee)
+               reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
+
+       IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
+       hw_dbg(hw, "Set up FC; PCS1GLCTL = 0x%08X\n", reg);
+
+       /*
+        * Set up the 10G flow control advertisement registers so the HW
+        * can do fc autoneg once the cable is plugged in.  If we end up
+        * using 1g instead, this is harmless.
+        */
+       reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+
+       /*
+        * The possible values of fc.requested_mode are:
+        * 0: Flow control is completely disabled
+        * 1: Rx flow control is enabled (we can receive pause frames,
+        *    but not send pause frames).
+        * 2: Tx flow control is enabled (we can send pause frames but
+        *    we do not support receiving pause frames).
+        * 3: Both Rx and Tx flow control (symmetric) are enabled.
+        * other: Invalid.
+        */
+       switch (hw->fc.requested_mode) {
+       case ixgbe_fc_none:
+               /* Flow control completely disabled by software override. */
+               reg &= ~(IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE);
+               break;
+       case ixgbe_fc_rx_pause:
+               /*
+                * Rx Flow control is enabled and Tx Flow control is
+                * disabled by software override. Since there really
+                * isn't a way to advertise that we are capable of RX
+                * Pause ONLY, we will advertise that we support both
+                * symmetric and asymmetric Rx PAUSE.  Later, we will
+                * disable the adapter's ability to send PAUSE frames.
+                */
+               reg |= (IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE);
+               break;
+       case ixgbe_fc_tx_pause:
+               /*
+                * Tx Flow control is enabled, and Rx Flow control is
+                * disabled by software override.
+                */
+               reg |= (IXGBE_AUTOC_ASM_PAUSE);
+               reg &= ~(IXGBE_AUTOC_SYM_PAUSE);
+               break;
+       case ixgbe_fc_full:
+               /* Flow control (both Rx and Tx) is enabled by SW override. */
+               reg |= (IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE);
+               break;
+#ifdef CONFIG_DCB
+       case ixgbe_fc_pfc:
+               goto out;
+               break;
+#endif /* CONFIG_DCB */
+       default:
+               hw_dbg(hw, "Flow control param set incorrectly\n");
+               ret_val = IXGBE_ERR_CONFIG;
+               goto out;
+               break;
+       }
+       /*
+        * AUTOC restart handles negotiation of 1G and 10G. There is
+        * no need to set the PCS1GCTL register.
+        */
+       reg |= IXGBE_AUTOC_AN_RESTART;
+       IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg);
+       hw_dbg(hw, "Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
 
 out:
        return ret_val;
@@ -1986,7 +2136,7 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
 
        while (timeout) {
                if (ixgbe_get_eeprom_semaphore(hw))
-                       return -IXGBE_ERR_SWFW_SYNC;
+                       return IXGBE_ERR_SWFW_SYNC;
 
                gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
                if (!(gssr & (fwmask | swmask)))
@@ -2003,7 +2153,7 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
 
        if (!timeout) {
                hw_dbg(hw, "Driver can't access resource, GSSR timeout.\n");
-               return -IXGBE_ERR_SWFW_SYNC;
+               return IXGBE_ERR_SWFW_SYNC;
        }
 
        gssr |= swmask;
@@ -2068,6 +2218,7 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
        hw->mac.ops.check_link(hw, &speed, &link_up, false);
 
        if (!link_up) {
+               autoc_reg |= IXGBE_AUTOC_AN_RESTART;
                autoc_reg |= IXGBE_AUTOC_FLU;
                IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
                msleep(10);