Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / drivers / net / ixgbe / ixgbe_common.c
index f67c684..276c2aa 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2008 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,
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
 
+#include "ixgbe.h"
 #include "ixgbe_common.h"
 #include "ixgbe_phy.h"
 
@@ -49,8 +52,8 @@ static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw);
 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_mc_addr(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
@@ -71,18 +74,9 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
        /* Identify the PHY */
        hw->phy.ops.identify(hw);
 
-       /*
-        * Store MAC address from RAR0, clear receive address registers, and
-        * clear the multicast table
-        */
-       hw->mac.ops.init_rx_addrs(hw);
-
        /* Clear the VLAN filter table */
        hw->mac.ops.clear_vfta(hw);
 
-       /* Set up link */
-       hw->mac.ops.setup_link(hw);
-
        /* Clear statistics registers */
        hw->mac.ops.clear_hw_cntrs(hw);
 
@@ -92,6 +86,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;
 
@@ -110,13 +107,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;
 }
 
 /**
@@ -254,6 +255,81 @@ s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr)
 }
 
 /**
+ *  ixgbe_get_bus_info_generic - Generic set PCI bus info
+ *  @hw: pointer to hardware structure
+ *
+ *  Sets the PCI bus info (speed, width, type) within the ixgbe_hw structure
+ **/
+s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw)
+{
+       struct ixgbe_adapter *adapter = hw->back;
+       struct ixgbe_mac_info *mac = &hw->mac;
+       u16 link_status;
+
+       hw->bus.type = ixgbe_bus_type_pci_express;
+
+       /* Get the negotiated link width and speed from PCI config space */
+       pci_read_config_word(adapter->pdev, IXGBE_PCI_LINK_STATUS,
+                            &link_status);
+
+       switch (link_status & IXGBE_PCI_LINK_WIDTH) {
+       case IXGBE_PCI_LINK_WIDTH_1:
+               hw->bus.width = ixgbe_bus_width_pcie_x1;
+               break;
+       case IXGBE_PCI_LINK_WIDTH_2:
+               hw->bus.width = ixgbe_bus_width_pcie_x2;
+               break;
+       case IXGBE_PCI_LINK_WIDTH_4:
+               hw->bus.width = ixgbe_bus_width_pcie_x4;
+               break;
+       case IXGBE_PCI_LINK_WIDTH_8:
+               hw->bus.width = ixgbe_bus_width_pcie_x8;
+               break;
+       default:
+               hw->bus.width = ixgbe_bus_width_unknown;
+               break;
+       }
+
+       switch (link_status & IXGBE_PCI_LINK_SPEED) {
+       case IXGBE_PCI_LINK_SPEED_2500:
+               hw->bus.speed = ixgbe_bus_speed_2500;
+               break;
+       case IXGBE_PCI_LINK_SPEED_5000:
+               hw->bus.speed = ixgbe_bus_speed_5000;
+               break;
+       default:
+               hw->bus.speed = ixgbe_bus_speed_unknown;
+               break;
+       }
+
+       mac->ops.set_lan_id(hw);
+
+       return 0;
+}
+
+/**
+ *  ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices
+ *  @hw: pointer to the HW structure
+ *
+ *  Determines the LAN function id by reading memory-mapped registers
+ *  and swaps the port value if requested.
+ **/
+void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw)
+{
+       struct ixgbe_bus_info *bus = &hw->bus;
+       u32 reg;
+
+       reg = IXGBE_READ_REG(hw, IXGBE_STATUS);
+       bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT;
+       bus->lan_id = bus->func;
+
+       /* check for a port swap */
+       reg = IXGBE_READ_REG(hw, IXGBE_FACTPS);
+       if (reg & IXGBE_FACTPS_LFS)
+               bus->func ^= 0x1;
+}
+
+/**
  *  ixgbe_stop_adapter_generic - Generic stop Tx/Rx units
  *  @hw: pointer to hardware structure
  *
@@ -393,6 +469,73 @@ s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw)
 }
 
 /**
+ *  ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM
+ *  @hw: pointer to hardware structure
+ *  @offset: offset within the EEPROM to be written to
+ *  @data: 16 bit word to be written to the EEPROM
+ *
+ *  If ixgbe_eeprom_update_checksum is not called after this function, the
+ *  EEPROM will most likely contain an invalid checksum.
+ **/
+s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
+{
+       s32 status;
+       u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI;
+
+       hw->eeprom.ops.init_params(hw);
+
+       if (offset >= hw->eeprom.word_size) {
+               status = IXGBE_ERR_EEPROM;
+               goto out;
+       }
+
+       /* Prepare the EEPROM for writing  */
+       status = ixgbe_acquire_eeprom(hw);
+
+       if (status == 0) {
+               if (ixgbe_ready_eeprom(hw) != 0) {
+                       ixgbe_release_eeprom(hw);
+                       status = IXGBE_ERR_EEPROM;
+               }
+       }
+
+       if (status == 0) {
+               ixgbe_standby_eeprom(hw);
+
+               /*  Send the WRITE ENABLE command (8 bit opcode )  */
+               ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_WREN_OPCODE_SPI,
+                                           IXGBE_EEPROM_OPCODE_BITS);
+
+               ixgbe_standby_eeprom(hw);
+
+               /*
+                * Some SPI eeproms use the 8th address bit embedded in the
+                * opcode
+                */
+               if ((hw->eeprom.address_bits == 8) && (offset >= 128))
+                       write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
+
+               /* Send the Write command (8-bit opcode + addr) */
+               ixgbe_shift_out_eeprom_bits(hw, write_opcode,
+                                           IXGBE_EEPROM_OPCODE_BITS);
+               ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2),
+                                           hw->eeprom.address_bits);
+
+               /* Send the data */
+               data = (data >> 8) | (data << 8);
+               ixgbe_shift_out_eeprom_bits(hw, data, 16);
+               ixgbe_standby_eeprom(hw);
+
+               msleep(hw->eeprom.semaphore_delay);
+               /* Done with writing - release the EEPROM */
+               ixgbe_release_eeprom(hw);
+       }
+
+out:
+       return status;
+}
+
+/**
  *  ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang
  *  @hw: pointer to hardware structure
  *  @offset: offset within the EEPROM to be read
@@ -521,7 +664,7 @@ static s32 ixgbe_poll_eeprom_eerd_done(struct ixgbe_hw *hw)
 static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
 {
        s32 status = 0;
-       u32 eec;
+       u32 eec = 0;
        u32 i;
 
        if (ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != 0)
@@ -1135,19 +1278,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);
        }
@@ -1212,9 +1347,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
+ *  @uc_list: the list of new addresses
  *
  *  The given list replaces any existing list.  Clears the secondary addrs from
  *  receive address registers.  Uses unused receive address registers for the
@@ -1223,37 +1356,34 @@ static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
  *  Drivers using secondary unicast addresses must set user_set_promisc when
  *  manually putting the device into promiscuous mode.
  **/
-s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list,
-                              u32 addr_count, ixgbe_mc_addr_itr next)
+s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw,
+                                     struct list_head *uc_list)
 {
-       u8 *addr;
        u32 i;
        u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc;
        u32 uc_addr_in_use;
        u32 fctrl;
-       u32 vmdq;
+       struct netdev_hw_addr *ha;
 
        /*
         * Clear accounting of old secondary address list,
         * don't count RAR[0]
         */
-       uc_addr_in_use = hw->addr_ctrl.rar_used_count -
-                        hw->addr_ctrl.mc_addr_in_rar_count - 1;
+       uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1;
        hw->addr_ctrl.rar_used_count -= uc_addr_in_use;
        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 */
-       for (i = 0; i < addr_count; i++) {
+       list_for_each_entry(ha, uc_list, list) {
                hw_dbg(hw, " Adding the secondary addresses:\n");
-               addr = next(hw, &addr_list, &vmdq);
-               ixgbe_add_uc_addr(hw, addr, vmdq);
+               ixgbe_add_uc_addr(hw, ha->addr, 0);
        }
 
        if (hw->addr_ctrl.overflow_promisc) {
@@ -1353,40 +1483,6 @@ static void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr)
 }
 
 /**
- *  ixgbe_add_mc_addr - Adds a multicast address.
- *  @hw: pointer to hardware structure
- *  @mc_addr: new multicast address
- *
- *  Adds it to unused receive address register or to the multicast table.
- **/
-static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr)
-{
-       u32 rar_entries = hw->mac.num_rar_entries;
-       u32 rar;
-
-       hw_dbg(hw, " MC Addr =%.2X %.2X %.2X %.2X %.2X %.2X\n",
-              mc_addr[0], mc_addr[1], mc_addr[2],
-              mc_addr[3], mc_addr[4], mc_addr[5]);
-
-       /*
-        * Place this multicast address in the RAR if there is room,
-        * else put it in the MTA
-        */
-       if (hw->addr_ctrl.rar_used_count < rar_entries) {
-               /* use RAR from the end up for multicast */
-               rar = rar_entries - hw->addr_ctrl.mc_addr_in_rar_count - 1;
-               hw->mac.ops.set_rar(hw, rar, mc_addr, 0, IXGBE_RAH_AV);
-               hw_dbg(hw, "Added a multicast address to RAR[%d]\n", rar);
-               hw->addr_ctrl.rar_used_count++;
-               hw->addr_ctrl.mc_addr_in_rar_count++;
-       } else {
-               ixgbe_set_mta(hw, mc_addr);
-       }
-
-       hw_dbg(hw, "ixgbe_add_mc_addr Complete\n");
-}
-
-/**
  *  ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses
  *  @hw: pointer to hardware structure
  *  @mc_addr_list: the list of new multicast addresses
@@ -1402,7 +1498,6 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
                                       u32 mc_addr_count, ixgbe_mc_addr_itr next)
 {
        u32 i;
-       u32 rar_entries = hw->mac.num_rar_entries;
        u32 vmdq;
 
        /*
@@ -1410,18 +1505,8 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
         * use.
         */
        hw->addr_ctrl.num_mc_addrs = mc_addr_count;
-       hw->addr_ctrl.rar_used_count -= hw->addr_ctrl.mc_addr_in_rar_count;
-       hw->addr_ctrl.mc_addr_in_rar_count = 0;
        hw->addr_ctrl.mta_in_use = 0;
 
-       /* Zero out the other receive addresses. */
-       hw_dbg(hw, "Clearing RAR[%d-%d]\n", hw->addr_ctrl.rar_used_count,
-                 rar_entries - 1);
-       for (i = hw->addr_ctrl.rar_used_count; i < rar_entries; i++) {
-               IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
-               IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
-       }
-
        /* Clear the MTA */
        hw_dbg(hw, " Clearing MTA\n");
        for (i = 0; i < hw->mac.mcft_size; i++)
@@ -1430,7 +1515,7 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
        /* Add the new addresses */
        for (i = 0; i < mc_addr_count; i++) {
                hw_dbg(hw, " Adding the multicast addresses:\n");
-               ixgbe_add_mc_addr(hw, next(hw, &mc_addr_list, &vmdq));
+               ixgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq));
        }
 
        /* Enable mta */
@@ -1490,6 +1575,510 @@ s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw)
 }
 
 /**
+ *  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_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
+{
+       s32 ret_val = 0;
+       u32 mflcn_reg, fccfg_reg;
+       u32 reg;
+       u32 rx_pba_size;
+
+#ifdef CONFIG_DCB
+       if (hw->fc.requested_mode == ixgbe_fc_pfc)
+               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);
+
+       fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG);
+       fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY);
+
+       /*
+        * 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.
+        */
+       switch (hw->fc.current_mode) {
+       case ixgbe_fc_none:
+               /*
+                * 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:
+               /*
+                * 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.
+                */
+               mflcn_reg |= IXGBE_MFLCN_RFCE;
+               break;
+       case ixgbe_fc_tx_pause:
+               /*
+                * Tx Flow control is enabled, and Rx Flow control is
+                * disabled by software override.
+                */
+               fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X;
+               break;
+       case ixgbe_fc_full:
+               /* Flow control (both Rx and Tx) is enabled by SW override. */
+               mflcn_reg |= IXGBE_MFLCN_RFCE;
+               fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X;
+               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;
+       }
+
+       /* 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);
+
+       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 */
+               reg = (rx_pba_size >> 5) & 0xFFE0;
+               IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), reg);
+
+               reg = (rx_pba_size >> 2) & 0xFFE0;
+               if (hw->fc.current_mode & ixgbe_fc_tx_pause)
+                       reg |= IXGBE_FCRTH_FCEN;
+               IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), reg);
+       } else {
+               /*
+                * Set up and enable Rx high/low water mark thresholds,
+                * enable XON.
+                */
+               if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
+                       if (hw->fc.send_xon) {
+                               IXGBE_WRITE_REG(hw,
+                                             IXGBE_FCRTL_82599(packetbuf_num),
+                                             (hw->fc.low_water |
+                                             IXGBE_FCRTL_XONE));
+                       } else {
+                               IXGBE_WRITE_REG(hw,
+                                             IXGBE_FCRTL_82599(packetbuf_num),
+                                             hw->fc.low_water);
+                       }
+
+                       IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num),
+                                      (hw->fc.high_water | IXGBE_FCRTH_FCEN));
+               }
+       }
+
+       /* Configure pause time (2 TCs per register) */
+       reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num / 2));
+       if ((packetbuf_num & 1) == 0)
+               reg = (reg & 0xFFFF0000) | hw->fc.pause_time;
+       else
+               reg = (reg & 0x0000FFFF) | (hw->fc.pause_time << 16);
+       IXGBE_WRITE_REG(hw, IXGBE_FCTTV(packetbuf_num / 2), reg);
+
+       IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1));
+
+out:
+       return ret_val;
+}
+
+/**
+ *  ixgbe_fc_autoneg - Configure flow control
+ *  @hw: pointer to hardware structure
+ *
+ *  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;
+       ixgbe_link_speed speed;
+       u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
+       u32 links2, anlp1_reg, autoc_reg, links;
+       bool link_up;
+
+       /*
+        * 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.
+        */
+       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;
+       }
+
+       /*
+        * 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;
+               }
+
+               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;
+                       }
+               }
+       }
+
+       /*
+        * 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;
+               }
+       }
+
+       /*
+        * 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;
+       }
+
+       /*
+        * Read the AN advertisement and LP ability registers and resolve
+        * local flow control settings accordingly
+        */
+       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) {
+               /*
+                * Read the 10g AN autoc and LP ability registers and resolve
+                * local flow control settings accordingly
+                */
+               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");
+               }
+       }
+       /* Record that current_mode is the result of a successful autoneg */
+       hw->fc.fc_was_autonegged = true;
+
+out:
+       return ret_val;
+}
+
+/**
+ *  ixgbe_setup_fc - Set up flow control
+ *  @hw: pointer to hardware structure
+ *
+ *  Called at init time to set up flow control.
+ **/
+static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
+{
+       s32 ret_val = 0;
+       u32 reg;
+
+#ifdef CONFIG_DCB
+       if (hw->fc.requested_mode == ixgbe_fc_pfc) {
+               hw->fc.current_mode = hw->fc.requested_mode;
+               goto out;
+       }
+
+#endif
+       /* Validate the packetbuf configuration */
+       if (packetbuf_num < 0 || packetbuf_num > 7) {
+               hw_dbg(hw, "Invalid packet buffer number [%d], expected range "
+                      "is 0-7\n", packetbuf_num);
+               ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+               goto out;
+       }
+
+       /*
+        * Validate the water mark configuration.  Zero water marks are invalid
+        * because it causes the controller to just blast out fc packets.
+        */
+       if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) {
+               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 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 "
+                      "IEEE mode\n");
+               ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+               goto out;
+       }
+
+       /*
+        * 10gig parts do not have a word in the EEPROM to determine the
+        * default flow control setting, so we explicitly set it to full.
+        */
+       if (hw->fc.requested_mode == ixgbe_fc_default)
+               hw->fc.requested_mode = ixgbe_fc_full;
+
+       /*
+        * 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.
+        */
+       reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+
+       /*
+        * 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;
+       }
+
+       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;
+}
+
+/**
  *  ixgbe_disable_pcie_master - Disable PCI-express master access
  *  @hw: pointer to hardware structure
  *
@@ -1548,7 +2137,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)))
@@ -1565,7 +2154,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;
@@ -1597,3 +2186,72 @@ void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask)
        ixgbe_release_eeprom_semaphore(hw);
 }
 
+/**
+ *  ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit
+ *  @hw: pointer to hardware structure
+ *  @regval: register value to write to RXCTRL
+ *
+ *  Enables the Rx DMA unit
+ **/
+s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval)
+{
+       IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval);
+
+       return 0;
+}
+
+/**
+ *  ixgbe_blink_led_start_generic - Blink LED based on index.
+ *  @hw: pointer to hardware structure
+ *  @index: led number to blink
+ **/
+s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
+{
+       ixgbe_link_speed speed = 0;
+       bool link_up = 0;
+       u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+       u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+
+       /*
+        * Link must be up to auto-blink the LEDs;
+        * Force it if link is down.
+        */
+       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);
+       }
+
+       led_reg &= ~IXGBE_LED_MODE_MASK(index);
+       led_reg |= IXGBE_LED_BLINK(index);
+       IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
+       IXGBE_WRITE_FLUSH(hw);
+
+       return 0;
+}
+
+/**
+ *  ixgbe_blink_led_stop_generic - Stop blinking LED based on index.
+ *  @hw: pointer to hardware structure
+ *  @index: led number to stop blinking
+ **/
+s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
+{
+       u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+       u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+
+       autoc_reg &= ~IXGBE_AUTOC_FLU;
+       autoc_reg |= IXGBE_AUTOC_AN_RESTART;
+       IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
+
+       led_reg &= ~IXGBE_LED_MODE_MASK(index);
+       led_reg &= ~IXGBE_LED_BLINK(index);
+       led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
+       IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
+       IXGBE_WRITE_FLUSH(hw);
+
+       return 0;
+}