]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.31/patches.drivers/ixgbe-sfp.patch
Revert "Move xen patchset to new version's subdir."
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.drivers / ixgbe-sfp.patch
diff --git a/src/patches/suse-2.6.27.31/patches.drivers/ixgbe-sfp.patch b/src/patches/suse-2.6.27.31/patches.drivers/ixgbe-sfp.patch
deleted file mode 100644 (file)
index 7fa7a0a..0000000
+++ /dev/null
@@ -1,802 +0,0 @@
-From: John Ronciak <john.ronciak@intel.com>
-Subject: ixgbe driver update to add Longcove (SFP+) NIC support for FCoE needs
-Acked-by: Karsten Keil <kkeil@novell.com>
-Reference: bnc#442411
-
-
-The patch that will be attached is to update the ixgbe driver to add SFP+ NIC
-support to SLES11 beta4 version of the ixgbe driver.  NIC have been sent to
-Nurnberg for testing purposes.  We have already been testing the patch with
-both our test lab and in our FCoE testing.
-
-
----
- drivers/net/ixgbe/ixgbe.h       |    5 
- drivers/net/ixgbe/ixgbe_82598.c |  161 ++++++++++++++++++++++++
- drivers/net/ixgbe/ixgbe_main.c  |   92 +++++++++++++-
- drivers/net/ixgbe/ixgbe_phy.c   |  258 ++++++++++++++++++++++++++++++++++++++++
- drivers/net/ixgbe/ixgbe_phy.h   |   18 ++
- drivers/net/ixgbe/ixgbe_type.h  |   19 ++
- 6 files changed, 546 insertions(+), 7 deletions(-)
-
---- a/drivers/net/ixgbe/ixgbe_82598.c
-+++ b/drivers/net/ixgbe/ixgbe_82598.c
-@@ -46,6 +46,8 @@ static s32 ixgbe_setup_copper_link_speed
-                                                ixgbe_link_speed speed,
-                                                bool autoneg,
-                                                bool autoneg_wait_to_complete);
-+static s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
-+                                     u8 *eeprom_data);
- /**
-  */
-@@ -53,12 +55,35 @@ static s32 ixgbe_get_invariants_82598(st
- {
-       struct ixgbe_mac_info *mac = &hw->mac;
-       struct ixgbe_phy_info *phy = &hw->phy;
-+      s32 ret_val = 0;
-+      u16 list_offset, data_offset;
-       /* Call PHY identify routine to get the phy type */
-       ixgbe_identify_phy_generic(hw);
-       /* PHY Init */
-       switch (phy->type) {
-+      case ixgbe_phy_nl:
-+              phy->ops.reset = &ixgbe_reset_phy_nl;
-+
-+              /* Call SFP+ identify routine to get the SFP+ module type */
-+              ret_val = phy->ops.identify_sfp(hw);
-+              if (ret_val != 0)
-+                      goto out;
-+              else if (hw->phy.sfp_type == ixgbe_sfp_type_unknown) {
-+                      ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED;
-+                      goto out;
-+              }
-+
-+              /* Check to see if SFP+ module is supported */
-+              ret_val = ixgbe_get_sfp_init_sequence_offsets(hw,
-+                                                            &list_offset,
-+                                                            &data_offset);
-+              if (ret_val != 0) {
-+                      ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED;
-+                      goto out;
-+              }
-+              break;
-       case ixgbe_phy_tn:
-               phy->ops.check_link = &ixgbe_check_phy_link_tnx;
-               phy->ops.get_firmware_version =
-@@ -82,7 +107,8 @@ static s32 ixgbe_get_invariants_82598(st
-       mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES;
-       mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES;
--      return 0;
-+out:
-+      return ret_val;
- }
- /**
-@@ -191,7 +217,10 @@ static enum ixgbe_media_type ixgbe_get_m
-       case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
-       case IXGBE_DEV_ID_82598EB_CX4:
-       case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
-+      case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
-+      case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
-       case IXGBE_DEV_ID_82598EB_XF_LR:
-+      case IXGBE_DEV_ID_82598EB_SFP_LOM:
-               media_type = ixgbe_media_type_fiber;
-               break;
-       case IXGBE_DEV_ID_82598AT:
-@@ -399,6 +428,47 @@ static s32 ixgbe_check_mac_link_82598(st
- {
-       u32 links_reg;
-       u32 i;
-+      u16 link_reg, adapt_comp_reg;
-+
-+      /*
-+       * SERDES PHY requires us to read link status from register 0xC79F.
-+       * Bit 0 set indicates link is up/ready; clear indicates link down.
-+       * OxC00C is read to check that the XAUI lanes are active.  Bit 0
-+       * clear indicates active; set indicates inactive.
-+       */
-+      if (hw->phy.type == ixgbe_phy_nl) {
-+              hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg);
-+              hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg);
-+              hw->phy.ops.read_reg(hw, 0xC00C, IXGBE_TWINAX_DEV,
-+                                   &adapt_comp_reg);
-+              if (link_up_wait_to_complete) {
-+                      for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
-+                              if ((link_reg & 1) &&
-+                                  ((adapt_comp_reg & 1) == 0)) {
-+                                      *link_up = true;
-+                                      break;
-+                              } else {
-+                                      *link_up = false;
-+                              }
-+                              msleep(100);
-+                              hw->phy.ops.read_reg(hw, 0xC79F,
-+                                                   IXGBE_TWINAX_DEV,
-+                                                   &link_reg);
-+                              hw->phy.ops.read_reg(hw, 0xC00C,
-+                                                   IXGBE_TWINAX_DEV,
-+                                                   &adapt_comp_reg);
-+                      }
-+              } else {
-+                      if ((link_reg & 1) &&
-+                          ((adapt_comp_reg & 1) == 0))
-+                              *link_up = true;
-+                      else
-+                              *link_up = false;
-+              }
-+
-+              if (*link_up == false)
-+                      goto out;
-+      }
-       links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
-       if (link_up_wait_to_complete) {
-@@ -424,6 +494,7 @@ static s32 ixgbe_check_mac_link_82598(st
-       else
-               *speed = IXGBE_LINK_SPEED_1GB_FULL;
-+out:
-       return 0;
- }
-@@ -859,6 +930,69 @@ s32 ixgbe_write_analog_reg8_82598(struct
- }
- /**
-+ *  ixgbe_read_i2c_eeprom_82598 - Reads 8 bit EEPROM word of an SFP+ module
-+ *  over I2C interface through an intermediate phy.
-+ *  @hw: pointer to hardware structure
-+ *  @byte_offset: EEPROM byte offset to read
-+ *  @eeprom_data: value read
-+ *
-+ *  Performs byte read operation to SFP module's EEPROM over I2C interface.
-+ **/
-+s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
-+                              u8 *eeprom_data)
-+{
-+      s32 status = 0;
-+      u16 sfp_addr = 0;
-+      u16 sfp_data = 0;
-+      u16 sfp_stat = 0;
-+      u32 i;
-+
-+      if (hw->phy.type == ixgbe_phy_nl) {
-+              /*
-+               * phy SDA/SCL registers are at addresses 0xC30A to
-+               * 0xC30D. These registers are used to talk to the SFP+
-+               * module's EEPROM through the SDA/SCL (I2C) interface.
-+               */
-+              sfp_addr = (IXGBE_I2C_EEPROM_DEV_ADDR << 8) + byte_offset;
-+              sfp_addr = (sfp_addr | IXGBE_I2C_EEPROM_READ_MASK);
-+              hw->phy.ops.write_reg(hw,
-+                                    IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR,
-+                                    IXGBE_MDIO_PMA_PMD_DEV_TYPE,
-+                                    sfp_addr);
-+
-+              /* Poll status */
-+              for (i = 0; i < 100; i++) {
-+                      hw->phy.ops.read_reg(hw,
-+                                           IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT,
-+                                           IXGBE_MDIO_PMA_PMD_DEV_TYPE,
-+                                           &sfp_stat);
-+                      sfp_stat = sfp_stat & IXGBE_I2C_EEPROM_STATUS_MASK;
-+                      if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS)
-+                              break;
-+                      msleep(10);
-+              }
-+
-+              if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_PASS) {
-+                      hw_dbg(hw, "EEPROM read did not pass.\n");
-+                      status = IXGBE_ERR_SFP_NOT_PRESENT;
-+                      goto out;
-+              }
-+
-+              /* Read data */
-+              hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA,
-+                                   IXGBE_MDIO_PMA_PMD_DEV_TYPE, &sfp_data);
-+
-+              *eeprom_data = (u8)(sfp_data >> 8);
-+      } else {
-+              status = IXGBE_ERR_PHY;
-+              goto out;
-+      }
-+
-+out:
-+      return status;
-+}
-+
-+/**
-  *  ixgbe_get_supported_physical_layer_82598 - Returns physical layer type
-  *  @hw: pointer to hardware structure
-  *
-@@ -873,13 +1007,35 @@ s32 ixgbe_get_supported_physical_layer_8
-       case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
-               physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
-               break;
-+      case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
-+              physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
-+              break;
-       case IXGBE_DEV_ID_82598AF_DUAL_PORT:
-       case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
-+      case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
-               physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
-               break;
-       case IXGBE_DEV_ID_82598EB_XF_LR:
-               physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
-               break;
-+      case IXGBE_DEV_ID_82598EB_SFP_LOM:
-+              hw->phy.ops.identify_sfp(hw);
-+
-+              switch (hw->phy.sfp_type) {
-+              case ixgbe_sfp_type_da_cu:
-+                      physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
-+                      break;
-+              case ixgbe_sfp_type_sr:
-+                      physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
-+                      break;
-+              case ixgbe_sfp_type_lr:
-+                      physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
-+                      break;
-+              default:
-+                      physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
-+                      break;
-+              }
-+              break;
-       case IXGBE_DEV_ID_82598AT:
-               physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_T |
-                                 IXGBE_PHYSICAL_LAYER_1000BASE_T);
-@@ -935,12 +1091,13 @@ static struct ixgbe_eeprom_operations ee
- static struct ixgbe_phy_operations phy_ops_82598 = {
-       .identify               = &ixgbe_identify_phy_generic,
--      /* .identify_sfp        = &ixgbe_identify_sfp_module_generic, */
-+      .identify_sfp           = &ixgbe_identify_sfp_module_generic,
-       .reset                  = &ixgbe_reset_phy_generic,
-       .read_reg               = &ixgbe_read_phy_reg_generic,
-       .write_reg              = &ixgbe_write_phy_reg_generic,
-       .setup_link             = &ixgbe_setup_phy_link_generic,
-       .setup_link_speed       = &ixgbe_setup_phy_link_speed_generic,
-+      .read_i2c_eeprom        = &ixgbe_read_i2c_eeprom_82598,
- };
- struct ixgbe_info ixgbe_82598_info = {
---- a/drivers/net/ixgbe/ixgbe.h
-+++ b/drivers/net/ixgbe/ixgbe.h
-@@ -318,12 +318,15 @@ struct ixgbe_adapter {
-       unsigned long link_check_timeout;
-       struct work_struct watchdog_task;
-+      struct work_struct sfp_task;
-+      struct timer_list sfp_timer;
- };
- enum ixbge_state_t {
-       __IXGBE_TESTING,
-       __IXGBE_RESETTING,
--      __IXGBE_DOWN
-+      __IXGBE_DOWN,
-+      __IXGBE_SFP_MODULE_NOT_FOUND
- };
- enum ixgbe_boards {
---- a/drivers/net/ixgbe/ixgbe_main.c
-+++ b/drivers/net/ixgbe/ixgbe_main.c
-@@ -74,8 +74,14 @@ static struct pci_device_id ixgbe_pci_tb
-        board_82598 },
-       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_CX4_DUAL_PORT),
-        board_82598 },
-+      {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_DA_DUAL_PORT),
-+       board_82598 },
-+      {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM),
-+       board_82598 },
-       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_XF_LR),
-        board_82598 },
-+      {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_SFP_LOM),
-+       board_82598 },
-       /* required last entry */
-       {0, }
-@@ -2678,6 +2684,56 @@ err_alloc_queues:
- }
- /**
-+ * ixgbe_sfp_timer - worker thread to find a missing module
-+ * @data: pointer to our adapter struct
-+ **/
-+static void ixgbe_sfp_timer(unsigned long data)
-+{
-+      struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data;
-+
-+      /* Do the sfp_timer outside of interrupt context due to the
-+       * delays that sfp+ detection requires */
-+      schedule_work(&adapter->sfp_task);
-+}
-+
-+/**
-+ * ixgbe_sfp_task - worker thread to find a missing module
-+ * @work: pointer to work_struct containing our data
-+ **/
-+static void ixgbe_sfp_task(struct work_struct *work)
-+{
-+      struct ixgbe_adapter *adapter = container_of(work,
-+                                                   struct ixgbe_adapter,
-+                                                   sfp_task);
-+      struct ixgbe_hw *hw = &adapter->hw;
-+
-+      if ((hw->phy.type == ixgbe_phy_nl) &&
-+          (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) {
-+              s32 ret = hw->phy.ops.identify_sfp(hw);
-+              if (ret)
-+                      goto reschedule;
-+              ret = hw->phy.ops.reset(hw);
-+              if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) {
-+                      DPRINTK(PROBE, ERR, "failed to initialize because an "
-+                              "unsupported SFP+ module type was detected.\n"
-+                              "Reload the driver after installing a "
-+                              "supported module.\n");
-+                      unregister_netdev(adapter->netdev);
-+              } else {
-+                      DPRINTK(PROBE, INFO, "detected SFP+: %d\n",
-+                              hw->phy.sfp_type);
-+              }
-+              /* don't need this routine any more */
-+              clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
-+      }
-+      return;
-+reschedule:
-+      if (test_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state))
-+              mod_timer(&adapter->sfp_timer,
-+                        round_jiffies(jiffies + (2 * HZ)));
-+}
-+
-+/**
-  * ixgbe_sw_init - Initialize general software structures (struct ixgbe_adapter)
-  * @adapter: board private structure to initialize
-  *
-@@ -4002,11 +4058,30 @@ static int __devinit ixgbe_probe(struct 
-       /* PHY */
-       memcpy(&hw->phy.ops, ii->phy_ops, sizeof(hw->phy.ops));
--      /* phy->sfp_type = ixgbe_sfp_type_unknown; */
-+      hw->phy.sfp_type = ixgbe_sfp_type_unknown;
-+
-+      /* set up this timer and work struct before calling get_invariants
-+       * which might start the timer */
-+      init_timer(&adapter->sfp_timer);
-+      adapter->sfp_timer.function = &ixgbe_sfp_timer;
-+      adapter->sfp_timer.data = (unsigned long) adapter;
-+
-+      INIT_WORK(&adapter->sfp_task, ixgbe_sfp_task);
-       err = ii->get_invariants(hw);
--      if (err)
-+      if (err == IXGBE_ERR_SFP_NOT_PRESENT) {
-+              /* start a kernel thread to watch for a module to arrive */
-+              set_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
-+              mod_timer(&adapter->sfp_timer,
-+                        round_jiffies(jiffies + (2 * HZ)));
-+              err = 0;
-+      } else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
-+              DPRINTK(PROBE, ERR, "failed to load because an "
-+                      "unsupported SFP+ module type was detected.\n");
-+              goto err_hw_init;
-+      } else if (err) {
-               goto err_hw_init;
-+      }
-       /* setup the private structure */
-       err = ixgbe_sw_init(adapter);
-@@ -4144,6 +4219,9 @@ err_hw_init:
- err_sw_init:
-       ixgbe_reset_interrupt_capability(adapter);
- err_eeprom:
-+      clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
-+      del_timer_sync(&adapter->sfp_timer);
-+      cancel_work_sync(&adapter->sfp_task);
-       iounmap(hw->hw_addr);
- err_ioremap:
-       free_netdev(netdev);
-@@ -4170,8 +4248,13 @@ static void __devexit ixgbe_remove(struc
-       struct ixgbe_adapter *adapter = netdev_priv(netdev);
-       set_bit(__IXGBE_DOWN, &adapter->state);
-+      /* clear the module not found bit to make sure the worker won't
-+       * reschedule */
-+      clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
-       del_timer_sync(&adapter->watchdog_timer);
--
-+      del_timer_sync(&adapter->sfp_timer);
-+      cancel_work_sync(&adapter->watchdog_task);
-+      cancel_work_sync(&adapter->sfp_task);
-       flush_scheduled_work();
- #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
-@@ -4182,7 +4265,8 @@ static void __devexit ixgbe_remove(struc
-       }
- #endif
--      unregister_netdev(netdev);
-+      if (netdev->reg_state == NETREG_REGISTERED)
-+              unregister_netdev(netdev);
-       ixgbe_reset_interrupt_capability(adapter);
---- a/drivers/net/ixgbe/ixgbe_phy.c
-+++ b/drivers/net/ixgbe/ixgbe_phy.c
-@@ -127,6 +127,9 @@ static enum ixgbe_phy_type ixgbe_get_phy
-       case QT2022_PHY_ID:
-               phy_type = ixgbe_phy_qt;
-               break;
-+      case ATH_PHY_ID:
-+              phy_type = ixgbe_phy_nl;
-+              break;
-       default:
-               phy_type = ixgbe_phy_unknown;
-               break;
-@@ -430,6 +433,261 @@ s32 ixgbe_setup_phy_link_speed_generic(s
- }
- /**
-+ *  ixgbe_reset_phy_nl - Performs a PHY reset
-+ *  @hw: pointer to hardware structure
-+ **/
-+s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw)
-+{
-+      u16 phy_offset, control, eword, edata, block_crc;
-+      bool end_data = false;
-+      u16 list_offset, data_offset;
-+      u16 phy_data = 0;
-+      s32 ret_val = 0;
-+      u32 i;
-+
-+      hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
-+                           IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data);
-+
-+      /* reset the PHY and poll for completion */
-+      hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
-+                            IXGBE_MDIO_PHY_XS_DEV_TYPE,
-+                            (phy_data | IXGBE_MDIO_PHY_XS_RESET));
-+
-+      for (i = 0; i < 100; i++) {
-+              hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
-+                                   IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data);
-+              if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) == 0)
-+                      break;
-+              msleep(10);
-+      }
-+
-+      if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) != 0) {
-+              hw_dbg(hw, "PHY reset did not complete.\n");
-+              ret_val = IXGBE_ERR_PHY;
-+              goto out;
-+      }
-+
-+      /* Get init offsets */
-+      ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset,
-+                                                    &data_offset);
-+      if (ret_val != 0)
-+              goto out;
-+
-+      ret_val = hw->eeprom.ops.read(hw, data_offset, &block_crc);
-+      data_offset++;
-+      while (!end_data) {
-+              /*
-+               * Read control word from PHY init contents offset
-+               */
-+              ret_val = hw->eeprom.ops.read(hw, data_offset, &eword);
-+              control = (eword & IXGBE_CONTROL_MASK_NL) >>
-+                              IXGBE_CONTROL_SHIFT_NL;
-+              edata = eword & IXGBE_DATA_MASK_NL;
-+              switch (control) {
-+              case IXGBE_DELAY_NL:
-+                      data_offset++;
-+                      hw_dbg(hw, "DELAY: %d MS\n", edata);
-+                      msleep(edata);
-+                      break;
-+              case IXGBE_DATA_NL:
-+                      hw_dbg(hw, "DATA:  \n");
-+                      data_offset++;
-+                      hw->eeprom.ops.read(hw, data_offset++,
-+                                          &phy_offset);
-+                      for (i = 0; i < edata; i++) {
-+                              hw->eeprom.ops.read(hw, data_offset, &eword);
-+                              hw->phy.ops.write_reg(hw, phy_offset,
-+                                                    IXGBE_TWINAX_DEV, eword);
-+                              hw_dbg(hw, "Wrote %4.4x to %4.4x\n", eword,
-+                                     phy_offset);
-+                              data_offset++;
-+                              phy_offset++;
-+                      }
-+                      break;
-+              case IXGBE_CONTROL_NL:
-+                      data_offset++;
-+                      hw_dbg(hw, "CONTROL: \n");
-+                      if (edata == IXGBE_CONTROL_EOL_NL) {
-+                              hw_dbg(hw, "EOL\n");
-+                              end_data = true;
-+                      } else if (edata == IXGBE_CONTROL_SOL_NL) {
-+                              hw_dbg(hw, "SOL\n");
-+                      } else {
-+                              hw_dbg(hw, "Bad control value\n");
-+                              ret_val = IXGBE_ERR_PHY;
-+                              goto out;
-+                      }
-+                      break;
-+              default:
-+                      hw_dbg(hw, "Bad control type\n");
-+                      ret_val = IXGBE_ERR_PHY;
-+                      goto out;
-+              }
-+      }
-+
-+out:
-+      return ret_val;
-+}
-+
-+/**
-+ *  ixgbe_identify_sfp_module_generic - Identifies SFP module and assigns
-+ *                                      the PHY type.
-+ *  @hw: pointer to hardware structure
-+ *
-+ *  Searches for and identifies the SFP module.  Assigns appropriate PHY type.
-+ **/
-+s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
-+{
-+      s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
-+      u32 vendor_oui = 0;
-+      u8 identifier = 0;
-+      u8 comp_codes_1g = 0;
-+      u8 comp_codes_10g = 0;
-+      u8 oui_bytes[4] = {0, 0, 0, 0};
-+      u8 transmission_media = 0;
-+
-+      status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER,
-+                                           &identifier);
-+
-+      if (status == IXGBE_ERR_SFP_NOT_PRESENT) {
-+              hw->phy.sfp_type = ixgbe_sfp_type_not_present;
-+              goto out;
-+      }
-+
-+      if (identifier == IXGBE_SFF_IDENTIFIER_SFP) {
-+              hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_1GBE_COMP_CODES,
-+                                          &comp_codes_1g);
-+              hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_10GBE_COMP_CODES,
-+                                          &comp_codes_10g);
-+              hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_TRANSMISSION_MEDIA,
-+                                          &transmission_media);
-+
-+               /* ID  Module
-+               * ============
-+               * 0    SFP_DA_CU
-+               * 1    SFP_SR
-+               * 2    SFP_LR
-+               */
-+              if (transmission_media & IXGBE_SFF_TWIN_AX_CAPABLE)
-+                      hw->phy.sfp_type = ixgbe_sfp_type_da_cu;
-+              else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
-+                      hw->phy.sfp_type = ixgbe_sfp_type_sr;
-+              else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
-+                      hw->phy.sfp_type = ixgbe_sfp_type_lr;
-+              else
-+                      hw->phy.sfp_type = ixgbe_sfp_type_unknown;
-+
-+              /* Determine PHY vendor */
-+              if (hw->phy.type == ixgbe_phy_unknown) {
-+                      hw->phy.id = identifier;
-+                      hw->phy.ops.read_i2c_eeprom(hw,
-+                                                  IXGBE_SFF_VENDOR_OUI_BYTE0,
-+                                                  &oui_bytes[0]);
-+                      hw->phy.ops.read_i2c_eeprom(hw,
-+                                                  IXGBE_SFF_VENDOR_OUI_BYTE1,
-+                                                  &oui_bytes[1]);
-+                      hw->phy.ops.read_i2c_eeprom(hw,
-+                                                  IXGBE_SFF_VENDOR_OUI_BYTE2,
-+                                                  &oui_bytes[2]);
-+
-+                      vendor_oui =
-+                         ((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) |
-+                          (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) |
-+                          (oui_bytes[2] << IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT));
-+
-+                      switch (vendor_oui) {
-+                      case IXGBE_SFF_VENDOR_OUI_TYCO:
-+                              if (transmission_media &
-+                                  IXGBE_SFF_TWIN_AX_CAPABLE)
-+                                      hw->phy.type = ixgbe_phy_tw_tyco;
-+                              break;
-+                      case IXGBE_SFF_VENDOR_OUI_FTL:
-+                              hw->phy.type = ixgbe_phy_sfp_ftl;
-+                              break;
-+                      case IXGBE_SFF_VENDOR_OUI_AVAGO:
-+                              hw->phy.type = ixgbe_phy_sfp_avago;
-+                              break;
-+                      default:
-+                              if (transmission_media &
-+                                  IXGBE_SFF_TWIN_AX_CAPABLE)
-+                                      hw->phy.type = ixgbe_phy_tw_unknown;
-+                              else
-+                                      hw->phy.type = ixgbe_phy_sfp_unknown;
-+                              break;
-+                      }
-+              }
-+              status = 0;
-+      }
-+
-+out:
-+      return status;
-+}
-+
-+/**
-+ *  ixgbe_get_sfp_init_sequence_offsets - Checks the MAC's EEPROM to see
-+ *  if it supports a given SFP+ module type, if so it returns the offsets to the
-+ *  phy init sequence block.
-+ *  @hw: pointer to hardware structure
-+ *  @list_offset: offset to the SFP ID list
-+ *  @data_offset: offset to the SFP data block
-+ **/
-+s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
-+                                      u16 *list_offset,
-+                                      u16 *data_offset)
-+{
-+      u16 sfp_id;
-+
-+      if (hw->phy.sfp_type == ixgbe_sfp_type_unknown)
-+              return IXGBE_ERR_SFP_NOT_SUPPORTED;
-+
-+      if (hw->phy.sfp_type == ixgbe_sfp_type_not_present)
-+              return IXGBE_ERR_SFP_NOT_PRESENT;
-+
-+      if ((hw->device_id == IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM) &&
-+          (hw->phy.sfp_type == ixgbe_sfp_type_da_cu))
-+              return IXGBE_ERR_SFP_NOT_SUPPORTED;
-+
-+      /* Read offset to PHY init contents */
-+      hw->eeprom.ops.read(hw, IXGBE_PHY_INIT_OFFSET_NL, list_offset);
-+
-+      if ((!*list_offset) || (*list_offset == 0xFFFF))
-+              return IXGBE_ERR_PHY;
-+
-+      /* Shift offset to first ID word */
-+      (*list_offset)++;
-+
-+      /*
-+       * Find the matching SFP ID in the EEPROM
-+       * and program the init sequence
-+       */
-+      hw->eeprom.ops.read(hw, *list_offset, &sfp_id);
-+
-+      while (sfp_id != IXGBE_PHY_INIT_END_NL) {
-+              if (sfp_id == hw->phy.sfp_type) {
-+                      (*list_offset)++;
-+                      hw->eeprom.ops.read(hw, *list_offset, data_offset);
-+                      if ((!*data_offset) || (*data_offset == 0xFFFF)) {
-+                              hw_dbg(hw, "SFP+ module not supported\n");
-+                              return IXGBE_ERR_SFP_NOT_SUPPORTED;
-+                      } else {
-+                              break;
-+                      }
-+              } else {
-+                      (*list_offset) += 2;
-+                      if (hw->eeprom.ops.read(hw, *list_offset, &sfp_id))
-+                              return IXGBE_ERR_PHY;
-+              }
-+      }
-+
-+      if (sfp_id == IXGBE_PHY_INIT_END_NL) {
-+              hw_dbg(hw, "No matching SFP+ module found\n");
-+              return IXGBE_ERR_SFP_NOT_SUPPORTED;
-+      }
-+
-+      return 0;
-+}
-+
-+/**
-  *  ixgbe_check_phy_link_tnx - Determine link and speed status
-  *  @hw: pointer to hardware structure
-  *
---- a/drivers/net/ixgbe/ixgbe_phy.h
-+++ b/drivers/net/ixgbe/ixgbe_phy.h
-@@ -63,6 +63,18 @@
- #define IXGBE_SFF_VENDOR_OUI_FTL      0x00906500
- #define IXGBE_SFF_VENDOR_OUI_AVAGO    0x00176A00
-+/* I2C SDA and SCL timing parameters for standard mode */
-+#define IXGBE_I2C_T_HD_STA  4
-+#define IXGBE_I2C_T_LOW     5
-+#define IXGBE_I2C_T_HIGH    4
-+#define IXGBE_I2C_T_SU_STA  5
-+#define IXGBE_I2C_T_HD_DATA 5
-+#define IXGBE_I2C_T_SU_DATA 1
-+#define IXGBE_I2C_T_RISE    1
-+#define IXGBE_I2C_T_FALL    1
-+#define IXGBE_I2C_T_SU_STO  4
-+#define IXGBE_I2C_T_BUF     5
-+
- s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw);
- s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw);
-@@ -84,4 +96,10 @@ s32 ixgbe_check_phy_link_tnx(struct ixgb
- s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
-                                        u16 *firmware_version);
-+/* PHY specific */
-+s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw);
-+s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw);
-+s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
-+                                      u16 *list_offset,
-+                                      u16 *data_offset);
- #endif /* _IXGBE_PHY_H_ */
---- a/drivers/net/ixgbe/ixgbe_type.h
-+++ b/drivers/net/ixgbe/ixgbe_type.h
-@@ -36,9 +36,12 @@
- /* Device IDs */
- #define IXGBE_DEV_ID_82598AF_DUAL_PORT   0x10C6
- #define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7
-+#define IXGBE_DEV_ID_82598EB_SFP_LOM     0x10DB
- #define IXGBE_DEV_ID_82598AT             0x10C8
- #define IXGBE_DEV_ID_82598EB_CX4         0x10DD
- #define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC
-+#define IXGBE_DEV_ID_82598_DA_DUAL_PORT  0x10F1
-+#define IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM      0x10E1
- #define IXGBE_DEV_ID_82598EB_XF_LR       0x10F4
- /* General Registers */
-@@ -453,6 +456,7 @@
- #define IXGBE_MDIO_PHY_XS_DEV_TYPE                0x4
- #define IXGBE_MDIO_AUTO_NEG_DEV_TYPE              0x7
- #define IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE     0x1E   /* Device 30 */
-+#define IXGBE_TWINAX_DEV                          1
- #define IXGBE_MDIO_COMMAND_TIMEOUT     100 /* PHY Timeout for 1 GB mode */
-@@ -492,9 +496,21 @@
- #define TN1010_PHY_ID    0x00A19410
- #define TNX_FW_REV       0xB
- #define QT2022_PHY_ID    0x0043A400
-+#define ATH_PHY_ID       0x03429050
- /* PHY Types */
- #define IXGBE_M88E1145_E_PHY_ID  0x01410CD0
-+/* Special PHY Init Routine */
-+#define IXGBE_PHY_INIT_OFFSET_NL 0x002B
-+#define IXGBE_PHY_INIT_END_NL    0xFFFF
-+#define IXGBE_CONTROL_MASK_NL    0xF000
-+#define IXGBE_DATA_MASK_NL       0x0FFF
-+#define IXGBE_CONTROL_SHIFT_NL   12
-+#define IXGBE_DELAY_NL           0
-+#define IXGBE_DATA_NL            1
-+#define IXGBE_CONTROL_NL         0x000F
-+#define IXGBE_CONTROL_EOL_NL     0x0FFF
-+#define IXGBE_CONTROL_SOL_NL     0x0000
- /* General purpose Interrupt Enable */
- #define IXGBE_SDP0_GPIEN         0x00000001 /* SDP0 */
-@@ -1208,6 +1224,7 @@ enum ixgbe_phy_type {
-       ixgbe_phy_tn,
-       ixgbe_phy_qt,
-       ixgbe_phy_xaui,
-+      ixgbe_phy_nl,
-       ixgbe_phy_tw_tyco,
-       ixgbe_phy_tw_unknown,
-       ixgbe_phy_sfp_avago,
-@@ -1229,6 +1246,7 @@ enum ixgbe_sfp_type {
-       ixgbe_sfp_type_da_cu = 0,
-       ixgbe_sfp_type_sr = 1,
-       ixgbe_sfp_type_lr = 2,
-+      ixgbe_sfp_type_not_present = 0xFFFE,
-       ixgbe_sfp_type_unknown = 0xFFFF
- };
-@@ -1492,6 +1510,7 @@ struct ixgbe_info {
- #define IXGBE_ERR_PHY_ADDR_INVALID              -17
- #define IXGBE_ERR_I2C                           -18
- #define IXGBE_ERR_SFP_NOT_SUPPORTED             -19
-+#define IXGBE_ERR_SFP_NOT_PRESENT               -20
- #define IXGBE_NOT_IMPLEMENTED                   0x7FFFFFFF
- #endif /* _IXGBE_TYPE_H_ */