static int ixgbe_priority_flow_ctrl_set(struct rte_eth_dev *dev,
struct rte_eth_pfc_conf *pfc_conf);
static void ixgbe_dev_link_status_print(struct rte_eth_dev *dev);
-static int ixgbe_dev_interrupt_setup(struct rte_eth_dev *dev);
+static int ixgbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev);
static int ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev);
static int ixgbe_dev_interrupt_action(struct rte_eth_dev *dev);
static void ixgbe_dev_interrupt_handler(struct rte_intr_handle *handle,
}
}
+static inline void
+ixgbe_enable_intr(struct rte_eth_dev *dev)
+{
+ struct ixgbe_interrupt *intr =
+ IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
+ struct ixgbe_hw *hw =
+ IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+ IXGBE_WRITE_REG(hw, IXGBE_EIMS, intr->mask);
+ IXGBE_WRITE_FLUSH(hw);
+}
+
/*
* This function is based on ixgbe_disable_intr() in ixgbe/ixgbe.h.
*/
/* Vendor and Device ID need to be set before init of shared code */
hw->device_id = pci_dev->id.device_id;
hw->vendor_id = pci_dev->id.vendor_id;
- hw->hw_addr = (void *)pci_dev->mem_resource.addr;
+ hw->hw_addr = (void *)pci_dev->mem_resource[0].addr;
+#ifdef RTE_LIBRTE_IXGBE_ALLOW_UNSUPPORTED_SFP
+ hw->allow_unsupported_sfp = 1;
+#endif
/* Initialize the shared code */
diag = ixgbe_init_shared_code(hw);
}
hw->fc.send_xon = 1;
- ixgbe_disable_intr(hw);
-
/* Make sure we have a good EEPROM before we read from it */
diag = ixgbe_validate_eeprom_checksum(hw, &csum);
if (diag != IXGBE_SUCCESS) {
return -EIO;
}
+ /* disable interrupt */
+ ixgbe_disable_intr(hw);
+
/* pick up the PCI bus settings for reporting later */
ixgbe_get_bus_info(hw);
rte_intr_callback_register(&(pci_dev->intr_handle),
ixgbe_dev_interrupt_handler, (void *)eth_dev);
+ /* enable uio intr after callback register */
+ rte_intr_enable(&(pci_dev->intr_handle));
+
+ /* enable support intr */
+ ixgbe_enable_intr(eth_dev);
+
return 0;
}
hw->device_id = pci_dev->id.device_id;
hw->vendor_id = pci_dev->id.vendor_id;
- hw->hw_addr = (void *)pci_dev->mem_resource.addr;
+ hw->hw_addr = (void *)pci_dev->mem_resource[0].addr;
/* initialize the vfta */
memset(shadow_vfta, 0, sizeof(*shadow_vfta));
{
.name = "rte_ixgbe_pmd",
.id_table = pci_id_ixgbe_map,
+#ifdef RTE_EAL_UNBIND_PORTS
.drv_flags = RTE_PCI_DRV_NEED_IGB_UIO,
+#endif
},
.eth_dev_init = eth_ixgbe_dev_init,
.dev_private_size = sizeof(struct ixgbe_adapter),
{
.name = "rte_ixgbevf_pmd",
.id_table = pci_id_ixgbevf_map,
+#ifdef RTE_EAL_UNBIND_PORTS
.drv_flags = RTE_PCI_DRV_NEED_IGB_UIO,
+#endif
},
.eth_dev_init = eth_ixgbevf_dev_init,
.dev_private_size = sizeof(struct ixgbe_adapter),
/* reinitialize adapter
* this calls reset and start */
ixgbe_init_hw(hw);
+ hw->mac.ops.start_hw(hw);
/* initialize transmission unit */
ixgbe_dev_tx_init(dev);
-
+
/* This can fail when allocating mbufs for descriptor rings */
err = ixgbe_dev_rx_init(dev);
if (err) {
goto error;
/* check if lsc interrupt is enabled */
- if (dev->data->dev_conf.intr_conf.lsc != 0) {
- err = ixgbe_dev_interrupt_setup(dev);
- if (err)
- goto error;
- }
+ if (dev->data->dev_conf.intr_conf.lsc != 0)
+ ixgbe_dev_lsc_interrupt_setup(dev);
+
+ /* resume enabled intr since hw reset */
+ ixgbe_enable_intr(dev);
mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | \
ETH_VLAN_EXTEND_MASK;
* - On failure, a negative value.
*/
static int
-ixgbe_dev_interrupt_setup(struct rte_eth_dev *dev)
+ixgbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev)
{
- struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct ixgbe_interrupt *intr =
+ IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
ixgbe_dev_link_status_print(dev);
- IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_LSC);
- IXGBE_WRITE_FLUSH(hw);
- rte_intr_enable(&(dev->pci_dev->intr_handle));
+ intr->mask |= IXGBE_EICR_LSC;
return 0;
}
struct ixgbe_interrupt *intr =
IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
- IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_LSC);
- IXGBE_WRITE_FLUSH(hw);
+ /* clear all cause mask */
+ ixgbe_disable_intr(hw);
/* read-on-clear nic registers here */
eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
- PMD_INIT_LOG(INFO, "eicr %x", eicr);
+ PMD_DRV_LOG(INFO, "eicr %x", eicr);
+
+ intr->flags = 0;
if (eicr & IXGBE_EICR_LSC) {
/* set flag for async link update */
intr->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
{
struct ixgbe_interrupt *intr =
IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
+ int64_t timeout;
+ struct rte_eth_link link;
+ int intr_enable_delay = false;
- if (!(intr->flags & IXGBE_FLAG_NEED_LINK_UPDATE)) {
- return -1;
+ PMD_DRV_LOG(DEBUG, "intr action type %d\n", intr->flags);
+
+ if (intr->flags & IXGBE_FLAG_NEED_LINK_UPDATE) {
+ /* get the link status before link update, for predicting later */
+ memset(&link, 0, sizeof(link));
+ rte_ixgbe_dev_atomic_read_link_status(dev, &link);
+
+ ixgbe_dev_link_update(dev, 0);
+
+ /* likely to up */
+ if (!link.link_status)
+ /* handle it 1 sec later, wait it being stable */
+ timeout = IXGBE_LINK_UP_CHECK_TIMEOUT;
+ /* likely to down */
+ else
+ /* handle it 4 sec later, wait it being stable */
+ timeout = IXGBE_LINK_DOWN_CHECK_TIMEOUT;
+
+ ixgbe_dev_link_status_print(dev);
+
+ intr_enable_delay = true;
+ }
+
+ if (intr_enable_delay) {
+ if (rte_eal_alarm_set(timeout * 1000,
+ ixgbe_dev_interrupt_delayed_handler, (void*)dev) < 0)
+ PMD_DRV_LOG(ERR, "Error setting alarm");
+ } else {
+ PMD_DRV_LOG(DEBUG, "enable intr immediately");
+ ixgbe_enable_intr(dev);
+ rte_intr_enable(&(dev->pci_dev->intr_handle));
}
- ixgbe_dev_link_update(dev, 0);
+
return 0;
}
struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
struct ixgbe_interrupt *intr =
IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
- struct ixgbe_hw *hw =
- IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- IXGBE_READ_REG(hw, IXGBE_EICR);
- ixgbe_dev_interrupt_action(dev);
if (intr->flags & IXGBE_FLAG_NEED_LINK_UPDATE) {
+ ixgbe_dev_link_update(dev, 0);
intr->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE;
- rte_intr_enable(&(dev->pci_dev->intr_handle));
- IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_LSC);
- IXGBE_WRITE_FLUSH(hw);
ixgbe_dev_link_status_print(dev);
_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC);
}
+
+ PMD_DRV_LOG(DEBUG, "enable intr in delayed handler\n");
+ ixgbe_enable_intr(dev);
+ rte_intr_enable(&(dev->pci_dev->intr_handle));
}
/**
ixgbe_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
void *param)
{
- int64_t timeout;
- struct rte_eth_link link;
struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
- struct ixgbe_interrupt *intr =
- IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
-
- /* get the link status before link update, for predicting later */
- memset(&link, 0, sizeof(link));
- rte_ixgbe_dev_atomic_read_link_status(dev, &link);
ixgbe_dev_interrupt_get_status(dev);
ixgbe_dev_interrupt_action(dev);
-
- if (!(intr->flags & IXGBE_FLAG_NEED_LINK_UPDATE))
- return;
-
- /* likely to up */
- if (!link.link_status)
- /* handle it 1 sec later, wait it being stable */
- timeout = IXGBE_LINK_UP_CHECK_TIMEOUT;
- /* likely to down */
- else
- /* handle it 4 sec later, wait it being stable */
- timeout = IXGBE_LINK_DOWN_CHECK_TIMEOUT;
-
- ixgbe_dev_link_status_print(dev);
- if (rte_eal_alarm_set(timeout * 1000,
- ixgbe_dev_interrupt_delayed_handler, param) < 0)
- PMD_INIT_LOG(ERR, "Error setting alarm");
}
static int
static int
ixgbevf_dev_start(struct rte_eth_dev *dev)
{
+ struct ixgbe_hw *hw =
+ IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
int err, mask = 0;
PMD_INIT_LOG(DEBUG, "ixgbevf_dev_start");
+ hw->mac.ops.reset_hw(hw);
+
ixgbevf_dev_tx_init(dev);
/* This can fail when allocating mbufs for descriptor rings */