X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_pmd_ixgbe%2Fixgbe_ethdev.c;h=13d0005a0494d72907a64c5d436b4d370ef1e237;hb=0a45657a6794a1dbd0533ecc908367fc81684f1c;hp=bdba7b087365be31ee0243f95745beeb1897e87a;hpb=eee16c964cd6b90622c36a7976ad951313b2ccd3;p=dpdk.git diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c index bdba7b0873..13d0005a04 100644 --- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c +++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c @@ -132,7 +132,7 @@ static int ixgbe_flow_ctrl_set(struct rte_eth_dev *dev, 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, @@ -354,6 +354,18 @@ ixgbe_is_sfp(struct ixgbe_hw *hw) } } +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. */ @@ -577,8 +589,6 @@ eth_ixgbe_dev_init(__attribute__((unused)) struct eth_driver *eth_drv, } 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) { @@ -616,6 +626,9 @@ eth_ixgbe_dev_init(__attribute__((unused)) struct eth_driver *eth_drv, return -EIO; } + /* disable interrupt */ + ixgbe_disable_intr(hw); + /* pick up the PCI bus settings for reporting later */ ixgbe_get_bus_info(hw); @@ -662,6 +675,12 @@ eth_ixgbe_dev_init(__attribute__((unused)) struct eth_driver *eth_drv, 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; } @@ -1117,10 +1136,11 @@ ixgbe_dev_start(struct rte_eth_dev *dev) /* 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) { @@ -1177,11 +1197,11 @@ ixgbe_dev_start(struct rte_eth_dev *dev) 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; @@ -1644,14 +1664,13 @@ ixgbe_dev_allmulticast_disable(struct rte_eth_dev *dev) * - 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; } @@ -1674,12 +1693,14 @@ ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev) 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; @@ -1737,11 +1758,43 @@ ixgbe_dev_interrupt_action(struct rte_eth_dev *dev) { 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; } @@ -1766,19 +1819,17 @@ ixgbe_dev_interrupt_delayed_handler(void *param) 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)); } /** @@ -1797,34 +1848,9 @@ static void 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 @@ -2160,10 +2186,14 @@ ixgbevf_dev_configure(struct rte_eth_dev *dev) 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 */