#include <rte_ethdev.h>
#include <rte_atomic.h>
#include <rte_malloc.h>
+#include <rte_dev.h>
#include "ixgbe_logs.h"
#include "ixgbe/ixgbe_api.h"
}
}
+/*
+ * Ensure that all locks are released before first NVM or PHY access
+ */
+static void
+ixgbe_swfw_lock_reset(struct ixgbe_hw *hw)
+{
+ uint16_t mask;
+
+ /*
+ * Phy lock should not fail in this early stage. If this is the case,
+ * it is due to an improper exit of the application.
+ * So force the release of the faulty lock. Release of common lock
+ * is done automatically by swfw_sync function.
+ */
+ mask = IXGBE_GSSR_PHY0_SM << hw->bus.func;
+ if (ixgbe_acquire_swfw_semaphore(hw, mask) < 0) {
+ DEBUGOUT1("SWFW phy%d lock released", hw->bus.func);
+ }
+ ixgbe_release_swfw_semaphore(hw, mask);
+
+ /*
+ * These ones are more tricky since they are common to all ports; but
+ * swfw_sync retries last long enough (1s) to be almost sure that if
+ * lock can not be taken it is due to an improper lock of the
+ * semaphore.
+ */
+ mask = IXGBE_GSSR_EEP_SM | IXGBE_GSSR_MAC_CSR_SM | IXGBE_GSSR_SW_MNG_SM;
+ if (ixgbe_acquire_swfw_semaphore(hw, mask) < 0) {
+ DEBUGOUT("SWFW common locks released");
+ }
+ ixgbe_release_swfw_semaphore(hw, mask);
+}
+
/*
* This function is based on code in ixgbe_attach() in ixgbe/ixgbe.c.
* It returns 0 on success.
return -EIO;
}
+ /* pick up the PCI bus settings for reporting later */
+ ixgbe_get_bus_info(hw);
+
+ /* Unlock any pending hardware semaphore */
+ ixgbe_swfw_lock_reset(hw);
+
/* Initialize DCB configuration*/
memset(dcb_config, 0, sizeof(struct ixgbe_dcb_config));
ixgbe_dcb_init(hw,dcb_config);
/* disable interrupt */
ixgbe_disable_intr(hw);
- /* pick up the PCI bus settings for reporting later */
- ixgbe_get_bus_info(hw);
-
/* reset mappings for queue statistics hw counters*/
ixgbe_reset_qstat_mappings(hw);
return 0;
}
-static void ixgbevf_get_queue_num(struct ixgbe_hw *hw)
+
+/*
+ * Negotiate mailbox API version with the PF.
+ * After reset API version is always set to the basic one (ixgbe_mbox_api_10).
+ * Then we try to negotiate starting with the most recent one.
+ * If all negotiation attempts fail, then we will proceed with
+ * the default one (ixgbe_mbox_api_10).
+ */
+static void
+ixgbevf_negotiate_api(struct ixgbe_hw *hw)
{
- /* Traffic classes are not supported by now */
- unsigned int tcs, tc;
+ int32_t i;
- /*
- * Must let PF know we are at mailbox API version 1.1.
- * Otherwise PF won't answer properly.
- * In case that PF fails to provide Rx/Tx queue number,
- * max_tx_queues and max_rx_queues remain to be 1.
- */
- if (!ixgbevf_negotiate_api_version(hw, ixgbe_mbox_api_11))
- ixgbevf_get_queues(hw, &tcs, &tc);
+ /* start with highest supported, proceed down */
+ static const enum ixgbe_pfvf_api_rev sup_ver[] = {
+ ixgbe_mbox_api_11,
+ ixgbe_mbox_api_10,
+ };
+
+ for (i = 0;
+ i != RTE_DIM(sup_ver) &&
+ ixgbevf_negotiate_api_version(hw, sup_ver[i]) != 0;
+ i++)
+ ;
}
/*
eth_ixgbevf_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,
struct rte_eth_dev *eth_dev)
{
- struct rte_pci_device *pci_dev;
- struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
int diag;
+ uint32_t tc, tcs;
+ struct rte_pci_device *pci_dev;
+ struct ixgbe_hw *hw =
+ IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
struct ixgbe_vfta * shadow_vfta =
IXGBE_DEV_PRIVATE_TO_VFTA(eth_dev->data->dev_private);
struct ixgbe_hwstrip *hwstrip =
return (diag);
}
+ /* negotiate mailbox API version to use with the PF. */
+ ixgbevf_negotiate_api(hw);
+
/* Get Rx/Tx queue count via mailbox, which is ready after reset_hw */
- ixgbevf_get_queue_num(hw);
+ ixgbevf_get_queues(hw, &tcs, &tc);
/* Allocate memory for storing MAC addresses */
eth_dev->data->mac_addrs = rte_zmalloc("ixgbevf", ETHER_ADDR_LEN *
* Invoked once at EAL init time.
* Register itself as the [Poll Mode] Driver of PCI IXGBE devices.
*/
-int
-rte_ixgbe_pmd_init(void)
+static int
+rte_ixgbe_pmd_init(const char *name __rte_unused, const char *params __rte_unused)
{
PMD_INIT_FUNC_TRACE();
* Invoked one at EAL init time.
* Register itself as the [Virtual Poll Mode] Driver of PCI niantic devices.
*/
-int
-rte_ixgbevf_pmd_init(void)
+static int
+rte_ixgbevf_pmd_init(const char *name __rte_unused, const char *param __rte_unused)
{
DEBUGFUNC("rte_ixgbevf_pmd_init");
stats->oerrors = 0;
+ /* XON/XOFF pause frames */
+ stats->tx_pause_xon = hw_stats->lxontxc;
+ stats->rx_pause_xon = hw_stats->lxonrxc;
+ stats->tx_pause_xoff = hw_stats->lxofftxc;
+ stats->rx_pause_xoff = hw_stats->lxoffrxc;
+
/* Flow Director Stats registers */
hw_stats->fdirmatch += IXGBE_READ_REG(hw, IXGBE_FDIRMATCH);
hw_stats->fdirmiss += IXGBE_READ_REG(hw, IXGBE_FDIRMISS);
}
/*
- * It executes link_update after knowing an interrupt occured.
+ * It executes link_update after knowing an interrupt occurred.
*
* @param dev
* Pointer to struct rte_eth_dev.
hw->mac.ops.reset_hw(hw);
+ /* negotiate mailbox API version to use with the PF. */
+ ixgbevf_negotiate_api(hw);
+
ixgbevf_dev_tx_init(dev);
/* This can fail when allocating mbufs for descriptor rings */
return 0;
}
+
+static struct rte_driver rte_ixgbe_driver = {
+ .type = PMD_PDEV,
+ .init = rte_ixgbe_pmd_init,
+};
+
+static struct rte_driver rte_ixgbevf_driver = {
+ .type = PMD_PDEV,
+ .init = rte_ixgbevf_pmd_init,
+};
+
+PMD_REGISTER_DRIVER(rte_ixgbe_driver);
+PMD_REGISTER_DRIVER(rte_ixgbevf_driver);