ixgbe: add 82599 bypass support
authorIntel <intel.com>
Fri, 8 Nov 2013 02:00:00 +0000 (03:00 +0100)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Sun, 24 Nov 2013 00:31:34 +0000 (01:31 +0100)
Signed-off-by: Intel
lib/librte_eal/common/include/rte_pci_dev_ids.h
lib/librte_pmd_ixgbe/Makefile
lib/librte_pmd_ixgbe/ixgbe/ixgbe_osdep.h
lib/librte_pmd_ixgbe/ixgbe_82599_bypass.c [new file with mode: 0644]
lib/librte_pmd_ixgbe/ixgbe_bypass.c [new file with mode: 0644]
lib/librte_pmd_ixgbe/ixgbe_bypass.h [new file with mode: 0644]
lib/librte_pmd_ixgbe/ixgbe_bypass_api.h [new file with mode: 0644]
lib/librte_pmd_ixgbe/ixgbe_bypass_defines.h [new file with mode: 0644]
lib/librte_pmd_ixgbe/ixgbe_ethdev.c
lib/librte_pmd_ixgbe/ixgbe_ethdev.h

index 80e054b..226cb51 100644 (file)
@@ -386,6 +386,10 @@ RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_DH89XXCC_SFP)
 #define IXGBE_DEV_ID_X540T                      0x1528
 #define IXGBE_DEV_ID_X540T1                     0x1560
 
+#ifdef RTE_NIC_BYPASS
+#define IXGBE_DEV_ID_82599_BYPASS               0x155D
+#endif
+
 RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82598)
 RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82598_BX)
 RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82598AF_DUAL_PORT)
@@ -424,6 +428,10 @@ RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_T3_LOM)
 RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_X540T)
 RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_X540T1)
 
+#ifdef RTE_NIC_BYPASS
+RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_BYPASS)
+#endif
+
 /****************** Virtual IGB devices from e1000_hw.h ******************/
 
 #define E1000_DEV_ID_82576_VF                   0x10CA
index ed01cbd..31ae067 100644 (file)
@@ -86,6 +86,11 @@ SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_ethdev.c
 SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_fdir.c
 SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_pf.c
 
+ifeq ($(CONFIG_RTE_NIC_BYPASS),y)
+SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_bypass.c
+SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_82599_bypass.c
+endif
+
 
 # this lib depends upon:
 DEPDIRS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += lib/librte_eal lib/librte_ether
index a0dcc02..312e8d6 100644 (file)
@@ -46,6 +46,7 @@
 #include <rte_byteorder.h>
 
 #include "../ixgbe_logs.h"
+#include "../ixgbe_bypass_defines.h"
 
 #define ASSERT(x) if(!(x)) rte_panic("IXGBE: x")
 
diff --git a/lib/librte_pmd_ixgbe/ixgbe_82599_bypass.c b/lib/librte_pmd_ixgbe/ixgbe_82599_bypass.c
new file mode 100644 (file)
index 0000000..97f883c
--- /dev/null
@@ -0,0 +1,309 @@
+/*-
+ *   BSD LICENSE
+ * 
+ *   Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ * 
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ * 
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ixgbe/ixgbe_type.h"
+#include "ixgbe/ixgbe_82599.h"
+#include "ixgbe/ixgbe_api.h"
+#include "ixgbe/ixgbe_common.h"
+#include "ixgbe/ixgbe_phy.h"
+#include "ixgbe_bypass_defines.h"
+#include "ixgbe_bypass.h"
+
+/**
+ *  ixgbe_set_fiber_fixed_speed - Set module link speed for fixed fiber
+ *  @hw: pointer to hardware structure
+ *  @speed: link speed to set
+ *
+ *  We set the module speed differently for fixed fiber.  For other
+ *  multi-speed devices we don't have an error value so here if we
+ *  detect an error we just log it and exit.
+ */
+static void
+ixgbe_set_fiber_fixed_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed)
+{
+       s32 status;
+       u8 rs, eeprom_data;
+
+       switch (speed) {
+       case IXGBE_LINK_SPEED_10GB_FULL:
+               /* one bit mask same as setting on */
+               rs = IXGBE_SFF_SOFT_RS_SELECT_10G;
+               break;
+       case IXGBE_LINK_SPEED_1GB_FULL:
+               rs = IXGBE_SFF_SOFT_RS_SELECT_1G;
+               break;
+       default:
+               DEBUGOUT("Invalid fixed module speed\n");
+               return;
+       }
+
+       /* Set RS0 */
+       status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB,
+                                          IXGBE_I2C_EEPROM_DEV_ADDR2,
+                                          &eeprom_data);
+       if (status) {
+               DEBUGOUT("Failed to read Rx Rate Select RS0\n");
+               goto out;
+       }
+
+       eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) & rs;
+
+       status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB,
+                                           IXGBE_I2C_EEPROM_DEV_ADDR2,
+                                           eeprom_data);
+       if (status) {
+               DEBUGOUT("Failed to write Rx Rate Select RS0\n");
+               goto out;
+       }
+
+       /* Set RS1 */
+       status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB,
+                                          IXGBE_I2C_EEPROM_DEV_ADDR2,
+                                          &eeprom_data);
+       if (status) {
+               DEBUGOUT("Failed to read Rx Rate Select RS1\n");
+               goto out;
+       }
+
+       eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) & rs;
+
+       status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB,
+                                           IXGBE_I2C_EEPROM_DEV_ADDR2,
+                                           eeprom_data);
+       if (status) {
+               DEBUGOUT("Failed to write Rx Rate Select RS1\n");
+               goto out;
+       }
+out:
+       return;
+}
+
+/**
+ *  ixgbe_setup_mac_link_multispeed_fixed_fiber - Set MAC link speed
+ *  @hw: pointer to hardware structure
+ *  @speed: new link speed
+ *  @autoneg: true if autonegotiation enabled
+ *  @autoneg_wait_to_complete: true when waiting for completion is needed
+ *
+ *  Set the link speed in the AUTOC register and restarts link.
+ **/
+static s32
+ixgbe_setup_mac_link_multispeed_fixed_fiber(struct ixgbe_hw *hw,
+                                    ixgbe_link_speed speed, bool autoneg,
+                                    bool autoneg_wait_to_complete)
+{
+       s32 status = IXGBE_SUCCESS;
+       ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
+       ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN;
+       u32 speedcnt = 0;
+       u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
+       u32 i = 0;
+       bool link_up = false;
+       bool negotiation;
+
+       DEBUGFUNC("");
+
+       /* Mask off requested but non-supported speeds */
+       status = ixgbe_get_link_capabilities(hw, &link_speed, &negotiation);
+       if (status != IXGBE_SUCCESS)
+               return status;
+
+       speed &= link_speed;
+
+       /*
+        * Try each speed one by one, highest priority first.  We do this in
+        * software because 10gb fiber doesn't support speed autonegotiation.
+        */
+       if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
+               speedcnt++;
+               highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL;
+
+               /* If we already have link at this speed, just jump out */
+               status = ixgbe_check_link(hw, &link_speed, &link_up, false);
+               if (status != IXGBE_SUCCESS)
+                       return status;
+
+               if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up)
+                       goto out;
+               /* Set the module link speed */
+               ixgbe_set_fiber_fixed_speed(hw, IXGBE_LINK_SPEED_10GB_FULL);
+                                           
+               /* Set the module link speed */
+               esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
+               IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+               IXGBE_WRITE_FLUSH(hw);
+
+               /* Allow module to change analog characteristics (1G->10G) */
+               msec_delay(40);
+
+               status = ixgbe_setup_mac_link_82599(hw,
+                                                   IXGBE_LINK_SPEED_10GB_FULL,
+                                                   autoneg,
+                                                   autoneg_wait_to_complete);
+               if (status != IXGBE_SUCCESS)
+                       return status;
+
+               /* Flap the tx laser if it has not already been done */
+               ixgbe_flap_tx_laser(hw);
+
+               /*
+                * Wait for the controller to acquire link.  Per IEEE 802.3ap,
+                * Section 73.10.2, we may have to wait up to 500ms if KR is
+                * attempted.  82599 uses the same timing for 10g SFI.
+                */
+               for (i = 0; i < 5; i++) {
+                       /* Wait for the link partner to also set speed */
+                       msec_delay(100);
+
+                       /* If we have link, just jump out */
+                       status = ixgbe_check_link(hw, &link_speed,
+                                                 &link_up, false);
+                       if (status != IXGBE_SUCCESS)
+                               return status;
+
+                       if (link_up)
+                               goto out;
+               }
+       }
+
+       if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
+               speedcnt++;
+               if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN)
+                       highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL;
+
+               /* If we already have link at this speed, just jump out */
+               status = ixgbe_check_link(hw, &link_speed, &link_up, false);
+               if (status != IXGBE_SUCCESS)
+                       return status;
+
+               if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up)
+                       goto out;
+
+               /* Set the module link speed */
+               ixgbe_set_fiber_fixed_speed(hw, IXGBE_LINK_SPEED_1GB_FULL);
+                                                   
+               /* Allow module to change analog characteristics (10G->1G) */
+               msec_delay(40);
+
+               status = ixgbe_setup_mac_link_82599(hw,
+                                                   IXGBE_LINK_SPEED_1GB_FULL,
+                                                   autoneg,
+                                                   autoneg_wait_to_complete);
+               if (status != IXGBE_SUCCESS)
+                       return status;
+
+               /* Flap the tx laser if it has not already been done */
+               ixgbe_flap_tx_laser(hw);
+
+               /* Wait for the link partner to also set speed */
+               msec_delay(100);
+
+               /* If we have link, just jump out */
+               status = ixgbe_check_link(hw, &link_speed, &link_up, false);
+               if (status != IXGBE_SUCCESS)
+                       return status;
+
+               if (link_up)
+                       goto out;
+       }
+
+       /*
+        * We didn't get link.  Configure back to the highest speed we tried,
+        * (if there was more than one).  We call ourselves back with just the
+        * single highest speed that the user requested.
+        */
+       if (speedcnt > 1)
+               status = ixgbe_setup_mac_link_multispeed_fixed_fiber(hw,
+                       highest_link_speed, autoneg, autoneg_wait_to_complete);
+
+out:
+       /* Set autoneg_advertised value based on input link speed */
+       hw->phy.autoneg_advertised = 0;
+
+       if (speed & IXGBE_LINK_SPEED_10GB_FULL)
+               hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
+
+       if (speed & IXGBE_LINK_SPEED_1GB_FULL)
+               hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
+
+       return status;
+}
+
+/*
+ * Wrapper around ND functions to support BYPASS nic.
+ */
+s32
+ixgbe_bypass_init_shared_code(struct ixgbe_hw *hw)
+{
+       if (hw->device_id == IXGBE_DEV_ID_82599_BYPASS) {
+               hw->mac.type = ixgbe_mac_82599EB;
+       }
+
+       return (ixgbe_init_shared_code(hw));
+}
+
+static enum ixgbe_media_type
+ixgbe_bypass_get_media_type(struct ixgbe_hw *hw)
+{
+       enum ixgbe_media_type media_type;
+
+       DEBUGFUNC("");
+
+       if (hw->device_id == IXGBE_DEV_ID_82599_BYPASS) {
+               media_type = ixgbe_media_type_fiber;
+       } else {
+               media_type = ixgbe_get_media_type_82599(hw);
+       }
+       return (media_type);
+}
+
+s32
+ixgbe_bypass_init_hw(struct ixgbe_hw *hw)
+{
+       int rc;
+       
+       if ((rc  = ixgbe_init_hw(hw)) == 0 &&
+                       hw->device_id == IXGBE_DEV_ID_82599_BYPASS) {
+
+               hw->mac.ops.setup_link =
+                       &ixgbe_setup_mac_link_multispeed_fixed_fiber;
+
+               hw->mac.ops.get_media_type = &ixgbe_bypass_get_media_type;
+
+               hw->mac.ops.disable_tx_laser = NULL;
+                hw->mac.ops.enable_tx_laser = NULL;
+                hw->mac.ops.flap_tx_laser = NULL;
+       }
+
+       return (rc);
+}
diff --git a/lib/librte_pmd_ixgbe/ixgbe_bypass.c b/lib/librte_pmd_ixgbe/ixgbe_bypass.c
new file mode 100644 (file)
index 0000000..6e4e408
--- /dev/null
@@ -0,0 +1,414 @@
+/*-
+ *   BSD LICENSE
+ * 
+ *   Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ * 
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ * 
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <time.h>
+#include <rte_atomic.h>
+#include <rte_ethdev.h>
+#include "ixgbe_ethdev.h"
+#include "ixgbe_bypass_api.h"
+
+#define        BYPASS_STATUS_OFF_MASK  3
+
+/* Macros to check for invlaid function pointers. */
+#define        FUNC_PTR_OR_ERR_RET(func, retval) do {             \
+       if ((func) == NULL) {                              \
+               DEBUGOUT("%s:%d function not supported\n", \
+                       __func__, __LINE__);               \
+               return (retval);                           \
+       }                                                  \
+} while(0)
+
+#define        FUNC_PTR_OR_RET(func) do {                         \
+       if ((func) == NULL) {                              \
+               DEBUGOUT("%s:%d function not supported\n", \
+                       __func__, __LINE__);               \
+               return;                                    \
+       }                                                  \
+} while(0)
+
+
+/**
+ *  ixgbe_bypass_set_time - Set bypass FW time epoc.
+ *
+ *  @hw: pointer to hardware structure
+ *
+ *  This function with sync the FW date stamp with that of the
+ *  system clock.
+ **/
+static void
+ixgbe_bypass_set_time(struct ixgbe_adapter *adapter)
+{
+       u32 mask, value;
+       u32 sec;
+       struct ixgbe_hw *hw = &adapter->hw;
+
+       sec = 0;
+
+       /*
+        * Send the FW our current time and turn on time_valid and
+        * timer_reset bits.
+        */
+       mask = BYPASS_CTL1_TIME_M |
+              BYPASS_CTL1_VALID_M |
+              BYPASS_CTL1_OFFTRST_M;
+       value = (sec & BYPASS_CTL1_TIME_M) |
+               BYPASS_CTL1_VALID |
+               BYPASS_CTL1_OFFTRST;
+
+       FUNC_PTR_OR_RET(adapter->bps.ops.bypass_set);
+
+       /* Store FW reset time (in seconds from epoch). */
+       adapter->bps.reset_tm = time(NULL);
+
+       /* reset FW timer. */
+       adapter->bps.ops.bypass_set(hw, BYPASS_PAGE_CTL1, mask, value);
+}
+
+/**
+ * ixgbe_bypass_init - Make some enviroment changes for bypass
+ *
+ * @adapter: pointer to ixgbe_adapter sturcture for access to state bits
+ *
+ * This function collects all the modifications needed by the bypass
+ * driver.
+ **/
+void
+ixgbe_bypass_init(struct rte_eth_dev *dev)
+{
+       struct ixgbe_adapter *adapter;
+       struct ixgbe_hw *hw;
+
+       adapter = IXGBE_DEV_TO_ADPATER(dev);
+       hw = &adapter->hw;
+
+       /* Only allow BYPASS ops on the first port */
+       if (hw->device_id != IXGBE_DEV_ID_82599_BYPASS ||
+                       hw->bus.func != 0) {
+               DEBUGOUT("bypass function is not supported on that device\n");
+               return;
+       }
+
+       /* set bypass ops. */
+       adapter->bps.ops.bypass_rw = &ixgbe_bypass_rw_generic;
+       adapter->bps.ops.bypass_valid_rd = &ixgbe_bypass_valid_rd_generic;
+       adapter->bps.ops.bypass_set = &ixgbe_bypass_set_generic;
+       adapter->bps.ops.bypass_rd_eep = &ixgbe_bypass_rd_eep_generic;
+
+       /* set the time for logging. */
+       ixgbe_bypass_set_time(adapter);
+
+       /* Don't have the SDP to the laser */
+       hw->mac.ops.disable_tx_laser = NULL;
+       hw->mac.ops.enable_tx_laser = NULL;
+       hw->mac.ops.flap_tx_laser = NULL;
+}
+
+s32
+ixgbe_bypass_state_show(struct rte_eth_dev *dev, u32 *state)
+{
+       struct ixgbe_hw *hw;
+       s32 ret_val;
+       u32 cmd;
+       u32 by_ctl = 0;
+       struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev);
+
+       hw = &adapter->hw;
+       FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_rw, -ENOTSUP);
+
+       cmd = BYPASS_PAGE_CTL0;
+       ret_val = adapter->bps.ops.bypass_rw(hw, cmd, &by_ctl);
+
+       /* Assume bypass_rw didn't error out, if it did state will
+        * be ignored anyway.
+        */
+       *state = (by_ctl >> BYPASS_STATUS_OFF_SHIFT) &  BYPASS_STATUS_OFF_MASK;
+
+       return (ret_val);
+}
+
+
+s32
+ixgbe_bypass_state_store(struct rte_eth_dev *dev, u32 *new_state)
+{
+       struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev);
+       struct ixgbe_hw *hw;
+       s32 ret_val;
+
+       hw = &adapter->hw;
+       FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_set, -ENOTSUP);
+
+       /* Set the new state */
+       ret_val = adapter->bps.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
+                                        BYPASS_MODE_OFF_M, *new_state);
+       if (ret_val)
+               goto exit;
+
+       /* Set AUTO back on so FW can recieve events */
+       ret_val = adapter->bps.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
+                                        BYPASS_MODE_OFF_M, BYPASS_AUTO);
+
+exit:
+       return ret_val;
+
+}
+
+s32
+ixgbe_bypass_event_show(struct rte_eth_dev *dev, u32 event,
+                           u32 *state)
+{
+       struct ixgbe_hw *hw;
+       s32 ret_val;
+       u32 shift;
+       u32 cmd;
+       u32 by_ctl = 0;
+       struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev);
+
+       hw = &adapter->hw;
+       FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_rw, -ENOTSUP);
+
+       cmd = BYPASS_PAGE_CTL0;
+       ret_val = adapter->bps.ops.bypass_rw(hw, cmd, &by_ctl);
+
+       /* Assume bypass_rw didn't error out, if it did event will
+        * be ignored anyway.
+        */
+       switch (event) {
+       case BYPASS_EVENT_WDT_TO:
+               shift = BYPASS_WDTIMEOUT_SHIFT;
+               break;
+       case BYPASS_EVENT_MAIN_ON:
+               shift = BYPASS_MAIN_ON_SHIFT;
+               break;
+       case BYPASS_EVENT_MAIN_OFF:
+               shift = BYPASS_MAIN_OFF_SHIFT;
+               break;
+       case BYPASS_EVENT_AUX_ON:
+               shift = BYPASS_AUX_ON_SHIFT;
+               break;
+       case BYPASS_EVENT_AUX_OFF:
+               shift = BYPASS_AUX_OFF_SHIFT;
+               break;
+       default:
+               return EINVAL;
+       }
+
+       *state = (by_ctl >> shift) & 0x3;
+
+       return ret_val;
+}
+
+s32
+ixgbe_bypass_event_store(struct rte_eth_dev *dev, u32 event,
+                            u32 state)
+{
+       struct ixgbe_hw *hw;
+       u32 status;
+       u32 off;
+       s32 ret_val;
+       struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev);
+
+       hw = &adapter->hw;
+       FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_set, -ENOTSUP);
+
+       switch (event) {
+       case BYPASS_EVENT_WDT_TO:
+               off = BYPASS_WDTIMEOUT_M;
+               status = state << BYPASS_WDTIMEOUT_SHIFT;
+               break;
+       case BYPASS_EVENT_MAIN_ON:
+               off = BYPASS_MAIN_ON_M;
+               status = state << BYPASS_MAIN_ON_SHIFT;
+               break;
+       case BYPASS_EVENT_MAIN_OFF:
+               off = BYPASS_MAIN_OFF_M;
+               status = state << BYPASS_MAIN_OFF_SHIFT;
+               break;
+       case BYPASS_EVENT_AUX_ON:
+               off = BYPASS_AUX_ON_M;
+               status = state << BYPASS_AUX_ON_SHIFT;
+               break;
+       case BYPASS_EVENT_AUX_OFF:
+               off = BYPASS_AUX_OFF_M;
+               status = state << BYPASS_AUX_OFF_SHIFT;
+               break;
+       default:
+               return EINVAL;
+       }
+
+       ret_val = adapter->bps.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
+               off, status);
+
+       return ret_val;
+}
+
+s32
+ixgbe_bypass_wd_timeout_store(struct rte_eth_dev *dev, u32 timeout)
+{
+       struct ixgbe_hw *hw;
+        u32 status;
+        u32 mask;
+       s32 ret_val;
+       struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev);
+
+       hw = &adapter->hw;
+       FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_set, -ENOTSUP);
+
+       /* disable the timer with timeout of zero */
+       if (timeout == RTE_BYPASS_TMT_OFF) {
+               status = 0x0;   /* WDG enable off */
+               mask = BYPASS_WDT_ENABLE_M;
+       } else {
+               /* set time out value */
+               mask = BYPASS_WDT_VALUE_M;
+
+               /* enable the timer */
+               status = timeout << BYPASS_WDT_TIME_SHIFT;
+               status |= 0x1 << BYPASS_WDT_ENABLE_SHIFT;
+               mask |= BYPASS_WDT_ENABLE_M;
+       }
+
+       ret_val = adapter->bps.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
+               mask, status);
+
+       return ret_val;
+}
+
+s32
+ixgbe_bypass_ver_show(struct rte_eth_dev *dev, u32 *ver)
+{
+       struct ixgbe_hw *hw;
+       u32 cmd;
+       u32 status;
+       s32 ret_val;
+       struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev);
+
+       hw = &adapter->hw;
+       FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_rw, -ENOTSUP);
+
+       cmd = BYPASS_PAGE_CTL2 | BYPASS_WE;
+       cmd |= (BYPASS_EEPROM_VER_ADD << BYPASS_CTL2_OFFSET_SHIFT) &
+              BYPASS_CTL2_OFFSET_M;
+       ret_val = adapter->bps.ops.bypass_rw(hw, cmd, &status);
+       if (ret_val)
+               goto exit;
+
+       /* wait for the write to stick */
+       msleep(100);
+
+       /* Now read the results */
+       cmd &= ~BYPASS_WE;
+       ret_val = adapter->bps.ops.bypass_rw(hw, cmd, &status);
+       if (ret_val)
+               goto exit;
+
+       *ver = status & BYPASS_CTL2_DATA_M;      /* only one byte of date */
+
+exit:
+       return ret_val;
+}
+
+s32
+ixgbe_bypass_wd_timeout_show(struct rte_eth_dev *dev, u32 *wd_timeout)
+{
+       struct ixgbe_hw *hw;
+       u32 by_ctl = 0;
+       u32 cmd;
+       u32 wdg;
+       s32 ret_val;
+       struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev);
+
+       hw = &adapter->hw;
+       FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_rw, -ENOTSUP);
+
+       cmd = BYPASS_PAGE_CTL0;
+       ret_val = adapter->bps.ops.bypass_rw(hw, cmd, &by_ctl);
+
+       wdg = by_ctl & BYPASS_WDT_ENABLE_M;
+       if (!wdg)
+               *wd_timeout = RTE_BYPASS_TMT_OFF;
+       else
+               *wd_timeout = (by_ctl >> BYPASS_WDT_TIME_SHIFT) &
+                       BYPASS_WDT_MASK;
+
+       return ret_val;
+}
+
+s32
+ixgbe_bypass_wd_reset(struct rte_eth_dev *dev)
+{
+       u32 cmd;
+       u32 status;
+       u32 sec;
+       u32 count = 0;
+       s32 ret_val;
+       struct ixgbe_hw *hw;
+       struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev);
+
+       hw = &adapter->hw;
+
+       FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_rw, -ENOTSUP);
+       FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_valid_rd, -ENOTSUP);
+
+       /* Use the lower level bit-bang functions since we don't need
+        * to read the register first to get it's current state as we
+        * are setting every thing in this write.
+        */
+       /* Set up WD pet */
+       cmd = BYPASS_PAGE_CTL1 | BYPASS_WE | BYPASS_CTL1_WDT_PET;
+
+       /* Resync the FW time while writing to CTL1 anyway */
+       adapter->bps.reset_tm = time(NULL);
+       sec = 0;
+
+       cmd |= (sec & BYPASS_CTL1_TIME_M) | BYPASS_CTL1_VALID;
+
+       /* reset FW timer offset since we are resetting the clock */
+       cmd |= BYPASS_CTL1_OFFTRST;
+
+       ret_val = adapter->bps.ops.bypass_rw(hw, cmd, &status);
+
+       /* Read until it matches what we wrote, or we time out */
+       do {
+               if (count++ > 10) {
+                       ret_val = IXGBE_BYPASS_FW_WRITE_FAILURE;
+                       break;
+               }
+
+               if (adapter->bps.ops.bypass_rw(hw, BYPASS_PAGE_CTL1, &status)) {
+                       ret_val = IXGBE_ERR_INVALID_ARGUMENT;
+                       break;
+               }
+       } while (!adapter->bps.ops.bypass_valid_rd(cmd, status));
+
+       return ret_val;
+}
diff --git a/lib/librte_pmd_ixgbe/ixgbe_bypass.h b/lib/librte_pmd_ixgbe/ixgbe_bypass.h
new file mode 100644 (file)
index 0000000..8708a9a
--- /dev/null
@@ -0,0 +1,68 @@
+/*-
+ *   BSD LICENSE
+ * 
+ *   Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ * 
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ * 
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _IXGBE_BYPASS_H_
+#define _IXGBE_BYPASS_H_
+
+#ifdef RTE_NIC_BYPASS
+
+struct ixgbe_bypass_mac_ops {
+       s32 (*bypass_rw) (struct ixgbe_hw *hw, u32 cmd, u32 *status);
+       bool (*bypass_valid_rd) (u32 in_reg, u32 out_reg);
+       s32 (*bypass_set) (struct ixgbe_hw *hw, u32 cmd, u32 event, u32 action);
+       s32 (*bypass_rd_eep) (struct ixgbe_hw *hw, u32 addr, u8 *value);
+};
+
+struct ixgbe_bypass_info {
+       uint64_t reset_tm;
+       struct ixgbe_bypass_mac_ops ops;
+};
+
+struct rte_eth_dev;
+
+void ixgbe_bypass_init(struct rte_eth_dev *dev);
+s32 ixgbe_bypass_state_show(struct rte_eth_dev *dev, u32 *state);
+s32 ixgbe_bypass_state_store(struct rte_eth_dev *dev, u32 *new_state);
+s32 ixgbe_bypass_event_show(struct rte_eth_dev *dev, u32 event, u32 *state);
+s32 ixgbe_bypass_event_store(struct rte_eth_dev *dev, u32 event, u32 state);
+s32 ixgbe_bypass_wd_timeout_store(struct rte_eth_dev *dev, u32 timeout);
+s32 ixgbe_bypass_ver_show(struct rte_eth_dev *dev, u32 *ver);
+s32 ixgbe_bypass_wd_timeout_show(struct rte_eth_dev *dev, u32 *wd_timeout);
+s32 ixgbe_bypass_wd_reset(struct rte_eth_dev *dev);
+
+s32 ixgbe_bypass_init_shared_code(struct ixgbe_hw *hw);
+s32 ixgbe_bypass_init_hw(struct ixgbe_hw *hw);
+
+#endif /* RTE_NIC_BYPASS */
+
+#endif /*  _IXGBE_BYPASS_H_ */
diff --git a/lib/librte_pmd_ixgbe/ixgbe_bypass_api.h b/lib/librte_pmd_ixgbe/ixgbe_bypass_api.h
new file mode 100644 (file)
index 0000000..1498c85
--- /dev/null
@@ -0,0 +1,290 @@
+/*-
+ *   BSD LICENSE
+ * 
+ *   Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ * 
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ * 
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _IXGBE_BYPASS_API_H_
+#define _IXGBE_BYPASS_API_H_
+
+#ifdef RTE_NIC_BYPASS
+
+#include "ixgbe_bypass_defines.h"
+/**
+ *  ixgbe_bypass_rw_generic - Bit bang data into by_pass FW
+ *
+ *  @hw: pointer to hardware structure
+ *  @cmd: Command we send to the FW
+ *  @status: The reply from the FW
+ *
+ *  Bit-bangs the cmd to the by_pass FW status points to what is returned.
+ **/
+#define IXGBE_BYPASS_BB_WAIT 1
+static s32 ixgbe_bypass_rw_generic(struct ixgbe_hw *hw, u32 cmd, u32 *status)
+{
+       int i;
+       u32 sck, sdi, sdo, dir_sck, dir_sdi, dir_sdo;
+       u32 esdp;
+
+       if (!status)
+               return IXGBE_ERR_PARAM;
+
+       *status = 0;
+
+       /* SDP vary by MAC type */
+       switch (hw->mac.type) {
+       case ixgbe_mac_82599EB:
+               sck = IXGBE_ESDP_SDP7;
+               sdi = IXGBE_ESDP_SDP0;
+               sdo = IXGBE_ESDP_SDP6;
+               dir_sck = IXGBE_ESDP_SDP7_DIR;
+               dir_sdi = IXGBE_ESDP_SDP0_DIR;
+               dir_sdo = IXGBE_ESDP_SDP6_DIR;
+               break;
+       case ixgbe_mac_X540:
+               sck = IXGBE_ESDP_SDP2;
+               sdi = IXGBE_ESDP_SDP0;
+               sdo = IXGBE_ESDP_SDP1;
+               dir_sck = IXGBE_ESDP_SDP2_DIR;
+               dir_sdi = IXGBE_ESDP_SDP0_DIR;
+               dir_sdo = IXGBE_ESDP_SDP1_DIR;
+               break;
+       default:
+               return IXGBE_ERR_DEVICE_NOT_SUPPORTED;
+       }
+
+       /* Set SDP pins direction */
+       esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+       esdp |= dir_sck;        /* SCK as output */
+       esdp |= dir_sdi;        /* SDI as output */
+       esdp &= ~dir_sdo;       /* SDO as input */
+       esdp |= sck;
+       esdp |= sdi;
+       IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+       IXGBE_WRITE_FLUSH(hw);
+  //  TODO:
+       msleep(IXGBE_BYPASS_BB_WAIT);
+
+       /* Generate start condition */
+       esdp &= ~sdi;
+       IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+       IXGBE_WRITE_FLUSH(hw);
+       msleep(IXGBE_BYPASS_BB_WAIT);
+
+       esdp &= ~sck;
+       IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+       IXGBE_WRITE_FLUSH(hw);
+       msleep(IXGBE_BYPASS_BB_WAIT);
+
+       /* Clock out the new control word and clock in the status */
+       for (i = 0; i < 32; i++) {
+               if ((cmd >> (31 - i)) & 0x01) {
+                       esdp |= sdi;
+                       IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+               } else {
+                       esdp &= ~sdi;
+                       IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+               }
+               IXGBE_WRITE_FLUSH(hw);
+               msleep(IXGBE_BYPASS_BB_WAIT);
+
+               esdp |= sck;
+               IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+               IXGBE_WRITE_FLUSH(hw);
+               msleep(IXGBE_BYPASS_BB_WAIT);
+
+               esdp &= ~sck;
+               IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+               IXGBE_WRITE_FLUSH(hw);
+               msleep(IXGBE_BYPASS_BB_WAIT);
+
+               esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+               if (esdp & sdo)
+                       *status = (*status << 1) | 0x01;
+               else
+                       *status = (*status << 1) | 0x00;
+               msleep(IXGBE_BYPASS_BB_WAIT);
+       }
+
+       /* stop condition */
+       esdp |= sck;
+       esdp &= ~sdi;
+       IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+       IXGBE_WRITE_FLUSH(hw);
+       msleep(IXGBE_BYPASS_BB_WAIT);
+
+       esdp |= sdi;
+       IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+       IXGBE_WRITE_FLUSH(hw);
+
+       /* set the page bits to match the cmd that the status it belongs to */
+       *status = (*status & 0x3fffffff) | (cmd & 0xc0000000);
+
+       return 0;
+}
+
+/**
+ * ixgbe_bypass_valid_rd_generic - Verify valid return from bit-bang.
+ *
+ * If we send a write we can't be sure it took until we can read back
+ * that same register.  It can be a problem as some of the feilds may
+ * for valid reasons change inbetween the time wrote the register and
+ * we read it again to verify.  So this function check everything we
+ * can check and then assumes it worked.
+ *
+ * @u32 in_reg - The register cmd for the bit-bang read.
+ * @u32 out_reg - The register returned from a bit-bang read.
+ **/
+static bool ixgbe_bypass_valid_rd_generic(u32 in_reg, u32 out_reg)
+{
+       u32 mask;
+
+       /* Page must match for all control pages */
+       if ((in_reg & BYPASS_PAGE_M) != (out_reg & BYPASS_PAGE_M))
+               return false;
+
+       switch (in_reg & BYPASS_PAGE_M) {
+       case BYPASS_PAGE_CTL0:
+               /* All the following can't change since the last write
+                *  - All the event actions
+                *  - The timeout value
+                */
+               mask = BYPASS_AUX_ON_M | BYPASS_MAIN_ON_M |
+                      BYPASS_MAIN_OFF_M | BYPASS_AUX_OFF_M |
+                      BYPASS_WDTIMEOUT_M |
+                      BYPASS_WDT_VALUE_M;
+               if ((out_reg & mask) != (in_reg & mask))
+                       return false;
+
+               /* 0x0 is never a valid value for bypass status */
+               if (!(out_reg & BYPASS_STATUS_OFF_M))
+                       return false;
+               break;
+       case BYPASS_PAGE_CTL1:
+               /* All the following can't change since the last write
+                *  - time valid bit
+                *  - time we last sent
+                */
+               mask = BYPASS_CTL1_VALID_M | BYPASS_CTL1_TIME_M;
+               if ((out_reg & mask) != (in_reg & mask))
+                       return false;
+               break;
+       case BYPASS_PAGE_CTL2:
+               /* All we can check in this page is control number
+                * which is already done above.
+                */
+               break;
+       }
+
+       /* We are as sure as we can be return true */
+       return true;
+}
+
+/**
+ *  ixgbe_bypass_set_generic - Set a bypass field in the FW CTRL Regiter.
+ *
+ *  @hw: pointer to hardware structure
+ *  @cmd: The control word we are setting.
+ *  @event: The event we are setting in the FW.  This also happens to
+ *         be the mask for the event we are setting (handy)
+ *  @action: The action we set the event to in the FW. This is in a
+ *          bit field that happens to be what we want to put in
+ *          the event spot (also handy)
+ **/
+static s32 ixgbe_bypass_set_generic(struct ixgbe_hw *hw, u32 ctrl, u32 event,
+                            u32 action)
+{
+       u32 by_ctl = 0;
+       u32 cmd, verify;
+       u32 count = 0;
+
+       /* Get current values */
+       cmd = ctrl;     /* just reading only need control number */
+       if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl))
+               return IXGBE_ERR_INVALID_ARGUMENT;
+
+       /* Set to new action */
+       cmd = (by_ctl & ~event) | BYPASS_WE | action;
+       if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl))
+               return IXGBE_ERR_INVALID_ARGUMENT;
+
+       /* Page 0 force a FW eeprom write which is slow so verify */
+       if ((cmd & BYPASS_PAGE_M) == BYPASS_PAGE_CTL0) {
+               verify = BYPASS_PAGE_CTL0;
+               do {
+                       if (count++ > 5)
+                               return IXGBE_BYPASS_FW_WRITE_FAILURE;
+
+                       if (ixgbe_bypass_rw_generic(hw, verify, &by_ctl))
+                               return IXGBE_ERR_INVALID_ARGUMENT;
+               } while (!ixgbe_bypass_valid_rd_generic(cmd, by_ctl));
+       } else {
+               /* We have give the FW time for the write to stick */
+               msleep(100);
+       }
+
+       return 0;
+}
+
+/**
+ *  ixgbe_bypass_rd_eep_generic - Read the bypass FW eeprom addres.
+ *
+ *  @hw: pointer to hardware structure
+ *  @addr: The bypass eeprom address to read.
+ *  @value: The 8b of data at the address above.
+ **/
+static s32 ixgbe_bypass_rd_eep_generic(struct ixgbe_hw *hw, u32 addr, u8 *value)
+{
+       u32 cmd;
+       u32 status;
+
+
+       /* send the request */
+       cmd = BYPASS_PAGE_CTL2 | BYPASS_WE;
+       cmd |= (addr << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M;
+       if (ixgbe_bypass_rw_generic(hw, cmd, &status))
+               return IXGBE_ERR_INVALID_ARGUMENT;
+
+       /* We have give the FW time for the write to stick */
+       msleep(100);
+
+       /* now read the results */
+       cmd &= ~BYPASS_WE;
+       if (ixgbe_bypass_rw_generic(hw, cmd, &status))
+               return IXGBE_ERR_INVALID_ARGUMENT;
+
+       *value = status & BYPASS_CTL2_DATA_M;
+
+       return 0;
+}
+
+#endif /* RTE_NIC_BYPASS */
+
+#endif /* _IXGBE_BYPASS_API_H_ */
diff --git a/lib/librte_pmd_ixgbe/ixgbe_bypass_defines.h b/lib/librte_pmd_ixgbe/ixgbe_bypass_defines.h
new file mode 100644 (file)
index 0000000..47d61f6
--- /dev/null
@@ -0,0 +1,160 @@
+/*-
+ *   BSD LICENSE
+ * 
+ *   Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ * 
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ * 
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _IXGBE_BYPASS_DEFINES_H_
+#define _IXGBE_BYPASS_DEFINES_H_
+
+#ifdef RTE_NIC_BYPASS
+
+#define msleep(x)             rte_delay_us(x*1000)
+#define usleep_range(min, max) rte_delay_us(min)
+
+#define BYPASS_PAGE_CTL0       0x00000000
+#define BYPASS_PAGE_CTL1       0x40000000
+#define BYPASS_PAGE_CTL2       0x80000000
+#define BYPASS_PAGE_M          0xc0000000
+#define BYPASS_WE              0x20000000
+
+#define BYPASS_AUTO    0x0
+#define BYPASS_NOP     0x0
+#define BYPASS_NORM    0x1
+#define BYPASS_BYPASS  0x2
+#define BYPASS_ISOLATE 0x3
+
+#define BYPASS_EVENT_MAIN_ON   0x1
+#define BYPASS_EVENT_AUX_ON    0x2
+#define BYPASS_EVENT_MAIN_OFF  0x3
+#define BYPASS_EVENT_AUX_OFF   0x4
+#define BYPASS_EVENT_WDT_TO    0x5
+#define BYPASS_EVENT_USR       0x6
+
+#define BYPASS_MODE_OFF_M      0x00000003
+#define BYPASS_STATUS_OFF_M    0x0000000c
+#define BYPASS_AUX_ON_M                0x00000030
+#define BYPASS_MAIN_ON_M       0x000000c0
+#define BYPASS_MAIN_OFF_M      0x00000300
+#define BYPASS_AUX_OFF_M       0x00000c00
+#define BYPASS_WDTIMEOUT_M     0x00003000
+#define BYPASS_WDT_ENABLE_M    0x00004000
+#define BYPASS_WDT_VALUE_M     0x00070000
+
+#define BYPASS_MODE_OFF_SHIFT  0
+#define BYPASS_STATUS_OFF_SHIFT        2
+#define BYPASS_AUX_ON_SHIFT    4
+#define BYPASS_MAIN_ON_SHIFT   6
+#define BYPASS_MAIN_OFF_SHIFT  8
+#define BYPASS_AUX_OFF_SHIFT   10
+#define BYPASS_WDTIMEOUT_SHIFT 12
+#define BYPASS_WDT_ENABLE_SHIFT        14
+#define BYPASS_WDT_TIME_SHIFT  16
+
+#define BYPASS_WDT_1   0x0
+#define BYPASS_WDT_1_5 0x1
+#define BYPASS_WDT_2   0x2
+#define BYPASS_WDT_3   0x3
+#define BYPASS_WDT_4   0x4
+#define BYPASS_WDT_8   0x5
+#define BYPASS_WDT_16  0x6
+#define BYPASS_WDT_32  0x7
+#define BYPASS_WDT_OFF 0xffff
+
+#define BYPASS_WDT_MASK        0x7
+
+#define BYPASS_CTL1_TIME_M     0x01ffffff
+#define BYPASS_CTL1_VALID_M    0x02000000
+#define BYPASS_CTL1_OFFTRST_M  0x04000000
+#define BYPASS_CTL1_WDT_PET_M  0x08000000
+
+#define BYPASS_CTL1_VALID      0x02000000
+#define BYPASS_CTL1_OFFTRST    0x04000000
+#define BYPASS_CTL1_WDT_PET    0x08000000
+
+#define BYPASS_CTL2_DATA_M     0x000000ff
+#define BYPASS_CTL2_OFFSET_M   0x0000ff00
+#define BYPASS_CTL2_RW_M       0x00010000
+#define BYPASS_CTL2_HEAD_M     0x0ff00000
+
+#define BYPASS_CTL2_OFFSET_SHIFT       8
+#define BYPASS_CTL2_HEAD_SHIFT         20
+
+#define BYPASS_CTL2_RW         0x00010000
+
+enum ixgbe_state_t {
+       __IXGBE_TESTING,
+       __IXGBE_RESETTING,
+       __IXGBE_DOWN,
+       __IXGBE_SERVICE_SCHED,
+       __IXGBE_IN_SFP_INIT,
+       __IXGBE_IN_BYPASS_LOW,
+       __IXGBE_IN_BYPASS_HIGH,
+       __IXGBE_IN_BYPASS_LOG,
+};
+
+#define BYPASS_MAX_LOGS                43
+#define BYPASS_LOG_SIZE                5
+#define BYPASS_LOG_LINE_SIZE   37
+
+#define BYPASS_EEPROM_VER_ADD  0x02
+
+#define BYPASS_LOG_TIME_M      0x01ffffff
+#define BYPASS_LOG_TIME_VALID_M        0x02000000
+#define BYPASS_LOG_HEAD_M      0x04000000
+#define BYPASS_LOG_CLEAR_M     0x08000000
+#define BYPASS_LOG_EVENT_M     0xf0000000
+#define BYPASS_LOG_ACTION_M    0x03
+
+#define BYPASS_LOG_EVENT_SHIFT 28
+#define BYPASS_LOG_CLEAR_SHIFT 24 /* bit offset */
+#define IXGBE_DEV_TO_ADPATER(dev) \
+       ((struct ixgbe_adapter*)(dev->data->dev_private))
+
+/* extractions from ixgbe_phy.h */
+#define        IXGBE_I2C_EEPROM_DEV_ADDR2      0xA2
+
+#define IXGBE_SFF_SFF_8472_SWAP                0x5C
+#define IXGBE_SFF_SFF_8472_COMP                0x5E
+#define IXGBE_SFF_SFF_8472_OSCB                0x6E
+#define IXGBE_SFF_SFF_8472_ESCB                0x76
+
+#define IXGBE_SFF_SOFT_RS_SELECT_MASK  0x8
+#define IXGBE_SFF_SOFT_RS_SELECT_10G   0x8
+#define IXGBE_SFF_SOFT_RS_SELECT_1G    0x0
+
+/* extractions from ixgbe_type.h */
+#define IXGBE_DEV_ID_82599_BYPASS      0x155D
+
+#define IXGBE_BYPASS_FW_WRITE_FAILURE  -35
+
+#endif /* RTE_NIC_BYPASS */
+
+#endif /* _IXGBE_BYPASS_DEFINES_H_ */
index 040f896..b826008 100644 (file)
@@ -64,6 +64,7 @@
 #include "ixgbe/ixgbe_vf.h"
 #include "ixgbe/ixgbe_common.h"
 #include "ixgbe_ethdev.h"
+#include "ixgbe_bypass.h"
 
 /*
  * High threshold controlling when to start sending XOFF frames. Must be at
@@ -288,6 +289,17 @@ static struct eth_dev_ops ixgbe_eth_dev_ops = {
        .fdir_set_masks               = ixgbe_fdir_set_masks,
        .reta_update          = ixgbe_dev_rss_reta_update,
        .reta_query           = ixgbe_dev_rss_reta_query,
+#ifdef RTE_NIC_BYPASS
+       .bypass_init          = ixgbe_bypass_init,
+       .bypass_state_set     = ixgbe_bypass_state_store,
+       .bypass_state_show    = ixgbe_bypass_state_show,
+       .bypass_event_set     = ixgbe_bypass_event_store,
+       .bypass_event_show    = ixgbe_bypass_event_show,
+       .bypass_wd_timeout_set  = ixgbe_bypass_wd_timeout_store,
+       .bypass_wd_timeout_show = ixgbe_bypass_wd_timeout_show,
+       .bypass_ver_show      = ixgbe_bypass_ver_show,
+       .bypass_wd_reset      = ixgbe_bypass_wd_reset,
+#endif /* RTE_NIC_BYPASS */
 };
 
 /*
@@ -620,7 +632,12 @@ eth_ixgbe_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,
 #endif
 
        /* Initialize the shared code */
+#ifdef RTE_NIC_BYPASS
+       diag = ixgbe_bypass_init_shared_code(hw);
+#else
        diag = ixgbe_init_shared_code(hw);
+#endif /* RTE_NIC_BYPASS */
+
        if (diag != IXGBE_SUCCESS) {
                PMD_INIT_LOG(ERR, "Shared code init failed: %d", diag);
                return -EIO;
@@ -646,7 +663,11 @@ eth_ixgbe_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,
                return -EIO;
        }
 
+#ifdef RTE_NIC_BYPASS
+       diag = ixgbe_bypass_init_hw(hw);
+#else
        diag = ixgbe_init_hw(hw);
+#endif /* RTE_NIC_BYPASS */
 
        /*
         * Devices with copper phys will fail to initialise if ixgbe_init_hw()
index 767fd62..adbecca 100644 (file)
@@ -36,6 +36,7 @@
 #include "ixgbe/ixgbe_dcb.h"
 #include "ixgbe/ixgbe_dcb_82599.h"
 #include "ixgbe/ixgbe_dcb_82598.h"
+#include "ixgbe_bypass.h"
 
 /* need update link, bit flag */
 #define IXGBE_FLAG_NEED_LINK_UPDATE (uint32_t)(1 << 0)
@@ -140,6 +141,9 @@ struct ixgbe_adapter {
        struct ixgbe_mirror_info    mr_data;
        struct ixgbe_vf_info        *vfdata;
        struct ixgbe_uta_info       uta_info;
+#ifdef RTE_NIC_BYPASS
+       struct ixgbe_bypass_info    bps;
+#endif /* RTE_NIC_BYPASS */
 };
 
 #define IXGBE_DEV_PRIVATE_TO_HW(adapter)\