net/ixgbe: fix intr callback unregister by adding retry
[dpdk.git] / drivers / net / ixgbe / ixgbe_ethdev.c
index 2fb9d52..4df5c75 100644 (file)
 #include <rte_debug.h>
 #include <rte_pci.h>
 #include <rte_bus_pci.h>
-#include <rte_atomic.h>
 #include <rte_branch_prediction.h>
 #include <rte_memory.h>
 #include <rte_eal.h>
 #include <rte_alarm.h>
 #include <rte_ether.h>
-#include <rte_ethdev.h>
+#include <rte_ethdev_driver.h>
 #include <rte_ethdev_pci.h>
 #include <rte_malloc.h>
 #include <rte_random.h>
@@ -787,58 +786,6 @@ static const struct rte_ixgbe_xstats_name_off rte_ixgbevf_stats_strings[] = {
 #define IXGBEVF_NB_XSTATS (sizeof(rte_ixgbevf_stats_strings) / \
                sizeof(rte_ixgbevf_stats_strings[0]))
 
-/**
- * Atomically reads the link status information from global
- * structure rte_eth_dev.
- *
- * @param dev
- *   - Pointer to the structure rte_eth_dev to read from.
- *   - Pointer to the buffer to be saved with the link status.
- *
- * @return
- *   - On success, zero.
- *   - On failure, negative value.
- */
-static inline int
-rte_ixgbe_dev_atomic_read_link_status(struct rte_eth_dev *dev,
-                               struct rte_eth_link *link)
-{
-       struct rte_eth_link *dst = link;
-       struct rte_eth_link *src = &(dev->data->dev_link);
-
-       if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst,
-                                       *(uint64_t *)src) == 0)
-               return -1;
-
-       return 0;
-}
-
-/**
- * Atomically writes the link status information into global
- * structure rte_eth_dev.
- *
- * @param dev
- *   - Pointer to the structure rte_eth_dev to read from.
- *   - Pointer to the buffer to be saved with the link status.
- *
- * @return
- *   - On success, zero.
- *   - On failure, negative value.
- */
-static inline int
-rte_ixgbe_dev_atomic_write_link_status(struct rte_eth_dev *dev,
-                               struct rte_eth_link *link)
-{
-       struct rte_eth_link *dst = &(dev->data->dev_link);
-       struct rte_eth_link *src = link;
-
-       if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst,
-                                       *(uint64_t *)src) == 0)
-               return -1;
-
-       return 0;
-}
-
 /*
  * This function is the same as ixgbe_is_sfp() in base/ixgbe.h.
  */
@@ -1147,13 +1094,6 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
                return 0;
        }
 
-#ifdef RTE_LIBRTE_SECURITY
-       /* Initialize security_ctx only for primary process*/
-       eth_dev->security_ctx = ixgbe_ipsec_ctx_create(eth_dev);
-       if (eth_dev->security_ctx == NULL)
-               return -ENOMEM;
-#endif
-
        rte_eth_copy_pci_info(eth_dev, pci_dev);
 
        /* Vendor and Device ID need to be set before init of shared code */
@@ -1180,6 +1120,12 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
        /* Unlock any pending hardware semaphore */
        ixgbe_swfw_lock_reset(hw);
 
+#ifdef RTE_LIBRTE_SECURITY
+       /* Initialize security_ctx only for primary process*/
+       if (ixgbe_ipsec_ctx_create(eth_dev))
+               return -ENOMEM;
+#endif
+
        /* Initialize DCB configuration*/
        memset(dcb_config, 0, sizeof(struct ixgbe_dcb_config));
        ixgbe_dcb_init(hw, dcb_config);
@@ -1340,6 +1286,8 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
        struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        struct ixgbe_hw *hw;
+       int retries = 0;
+       int ret;
 
        PMD_INIT_FUNC_TRACE();
 
@@ -1360,8 +1308,20 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 
        /* disable uio intr before callback unregister */
        rte_intr_disable(intr_handle);
-       rte_intr_callback_unregister(intr_handle,
-                                    ixgbe_dev_interrupt_handler, eth_dev);
+
+       do {
+               ret = rte_intr_callback_unregister(intr_handle,
+                               ixgbe_dev_interrupt_handler, eth_dev);
+               if (ret >= 0) {
+                       break;
+               } else if (ret != -EAGAIN) {
+                       PMD_INIT_LOG(ERR,
+                               "intr callback unregister failed: %d",
+                               ret);
+                       return ret;
+               }
+               rte_delay_ms(100);
+       } while (retries++ < (10 + IXGBE_LINK_UP_TIME));
 
        /* uninitialize PF if max_vfs not zero */
        ixgbe_pf_host_uninit(eth_dev);
@@ -2214,8 +2174,6 @@ ixgbe_check_mq_mode(struct rte_eth_dev *dev)
                case ETH_MQ_RX_NONE:
                        /* if nothing mq mode configure, use default scheme */
                        dev->data->dev_conf.rxmode.mq_mode = ETH_MQ_RX_VMDQ_ONLY;
-                       if (RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool > 1)
-                               RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool = 1;
                        break;
                default: /* ETH_MQ_RX_DCB, ETH_MQ_RX_DCB_RSS or ETH_MQ_TX_DCB*/
                        /* SRIOV only works in VMDq enable mode */
@@ -2760,7 +2718,7 @@ ixgbe_dev_stop(struct rte_eth_dev *dev)
 
        /* Clear recorded link status */
        memset(&link, 0, sizeof(link));
-       rte_ixgbe_dev_atomic_write_link_status(dev, &link);
+       rte_eth_linkstatus_set(dev, &link);
 
        if (!rte_intr_allow_others(intr_handle))
                /* resume to the default handler */
@@ -3654,7 +3612,8 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
                DEV_RX_OFFLOAD_VLAN_STRIP |
                DEV_RX_OFFLOAD_IPV4_CKSUM |
                DEV_RX_OFFLOAD_UDP_CKSUM  |
-               DEV_RX_OFFLOAD_TCP_CKSUM;
+               DEV_RX_OFFLOAD_TCP_CKSUM  |
+               DEV_RX_OFFLOAD_CRC_STRIP;
 
        /*
         * RSC is only supported by 82599 and x540 PF devices in a non-SR-IOV
@@ -3692,8 +3651,10 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
                dev_info->tx_offload_capa |= DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM;
 
 #ifdef RTE_LIBRTE_SECURITY
-       dev_info->rx_offload_capa |= DEV_RX_OFFLOAD_SECURITY;
-       dev_info->tx_offload_capa |= DEV_TX_OFFLOAD_SECURITY;
+       if (dev->security_ctx) {
+               dev_info->rx_offload_capa |= DEV_RX_OFFLOAD_SECURITY;
+               dev_info->tx_offload_capa |= DEV_TX_OFFLOAD_SECURITY;
+       }
 #endif
 
        dev_info->default_rxconf = (struct rte_eth_rxconf) {
@@ -3799,7 +3760,8 @@ ixgbevf_dev_info_get(struct rte_eth_dev *dev,
        dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP |
                                DEV_RX_OFFLOAD_IPV4_CKSUM |
                                DEV_RX_OFFLOAD_UDP_CKSUM  |
-                               DEV_RX_OFFLOAD_TCP_CKSUM;
+                               DEV_RX_OFFLOAD_TCP_CKSUM  |
+                               DEV_RX_OFFLOAD_CRC_STRIP;
        dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT |
                                DEV_TX_OFFLOAD_IPV4_CKSUM  |
                                DEV_TX_OFFLOAD_UDP_CKSUM   |
@@ -3945,7 +3907,7 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
                            int wait_to_complete, int vf)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       struct rte_eth_link link, old;
+       struct rte_eth_link link;
        ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
        struct ixgbe_interrupt *intr =
                IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
@@ -3955,12 +3917,11 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
        int wait = 1;
        bool autoneg = false;
 
+       memset(&link, 0, sizeof(link));
        link.link_status = ETH_LINK_DOWN;
        link.link_speed = 0;
        link.link_duplex = ETH_LINK_HALF_DUPLEX;
        link.link_autoneg = ETH_LINK_AUTONEG;
-       memset(&old, 0, sizeof(old));
-       rte_ixgbe_dev_atomic_read_link_status(dev, &old);
 
        hw->mac.get_link_status = true;
 
@@ -3984,19 +3945,14 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
        if (diag != 0) {
                link.link_speed = ETH_SPEED_NUM_100M;
                link.link_duplex = ETH_LINK_FULL_DUPLEX;
-               rte_ixgbe_dev_atomic_write_link_status(dev, &link);
-               if (link.link_status == old.link_status)
-                       return -1;
-               return 0;
+               return rte_eth_linkstatus_set(dev, &link);
        }
 
        if (link_up == 0) {
-               rte_ixgbe_dev_atomic_write_link_status(dev, &link);
                intr->flags |= IXGBE_FLAG_NEED_LINK_CONFIG;
-               if (link.link_status == old.link_status)
-                       return -1;
-               return 0;
+               return rte_eth_linkstatus_set(dev, &link);
        }
+
        intr->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG;
        link.link_status = ETH_LINK_UP;
        link.link_duplex = ETH_LINK_FULL_DUPLEX;
@@ -4028,12 +3984,8 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
                link.link_speed = ETH_SPEED_NUM_10G;
                break;
        }
-       rte_ixgbe_dev_atomic_write_link_status(dev, &link);
-
-       if (link.link_status == old.link_status)
-               return -1;
 
-       return 0;
+       return rte_eth_linkstatus_set(dev, &link);
 }
 
 static int
@@ -4232,8 +4184,8 @@ ixgbe_dev_link_status_print(struct rte_eth_dev *dev)
        struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_eth_link link;
 
-       memset(&link, 0, sizeof(link));
-       rte_ixgbe_dev_atomic_read_link_status(dev, &link);
+       rte_eth_linkstatus_get(dev, &link);
+
        if (link.link_status) {
                PMD_INIT_LOG(INFO, "Port %d: Link Up - speed %u Mbps - %s",
                                        (int)(dev->data->port_id),
@@ -4268,7 +4220,6 @@ 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;
        struct ixgbe_hw *hw =
                IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
@@ -4285,9 +4236,10 @@ ixgbe_dev_interrupt_action(struct rte_eth_dev *dev,
        }
 
        if (intr->flags & IXGBE_FLAG_NEED_LINK_UPDATE) {
+               struct rte_eth_link link;
+
                /* get the link status before link update, for predicting later */
-               memset(&link, 0, sizeof(link));
-               rte_ixgbe_dev_atomic_read_link_status(dev, &link);
+               rte_eth_linkstatus_get(dev, &link);
 
                ixgbe_dev_link_update(dev, 0);
 
@@ -5003,7 +4955,11 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)
 
        PMD_INIT_FUNC_TRACE();
 
-       hw->mac.ops.reset_hw(hw);
+       err = hw->mac.ops.reset_hw(hw);
+       if (err) {
+               PMD_INIT_LOG(ERR, "Unable to reset vf hardware (%d)", err);
+               return err;
+       }
        hw->mac.get_link_status = true;
 
        /* negotiate mailbox API version to use with the PF. */
@@ -5035,7 +4991,8 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)
        ixgbevf_dev_rxtx_start(dev);
 
        /* check and configure queue intr-vector mapping */
-       if (dev->data->dev_conf.intr_conf.rxq != 0) {
+       if (rte_intr_cap_multiple(intr_handle) &&
+           dev->data->dev_conf.intr_conf.rxq) {
                /* According to datasheet, only vector 0/1/2 can be used,
                 * now only one vector is used for Rx queue
                 */
@@ -6806,9 +6763,8 @@ ixgbe_start_timecounters(struct rte_eth_dev *dev)
        uint32_t shift = 0;
 
        /* Get current link speed. */
-       memset(&link, 0, sizeof(link));
        ixgbe_dev_link_update(dev, 1);
-       rte_ixgbe_dev_atomic_read_link_status(dev, &link);
+       rte_eth_linkstatus_get(dev, &link);
 
        switch (link.link_speed) {
        case ETH_SPEED_NUM_100M:
@@ -8143,13 +8099,17 @@ static void ixgbevf_mbx_process(struct rte_eth_dev *dev)
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        u32 in_msg = 0;
 
-       if (ixgbe_read_mbx(hw, &in_msg, 1, 0))
-               return;
+       /* peek the message first */
+       in_msg = IXGBE_READ_REG(hw, IXGBE_VFMBMEM);
 
        /* PF reset VF event */
-       if (in_msg == IXGBE_PF_CONTROL_MSG)
+       if (in_msg == IXGBE_PF_CONTROL_MSG) {
+               /* dummy mbx read to ack pf */
+               if (ixgbe_read_mbx(hw, &in_msg, 1, 0))
+                       return;
                _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RESET,
                                              NULL);
+       }
 }
 
 static int
@@ -8440,10 +8400,10 @@ RTE_INIT(ixgbe_init_log);
 static void
 ixgbe_init_log(void)
 {
-       ixgbe_logtype_init = rte_log_register("pmd.ixgbe.init");
+       ixgbe_logtype_init = rte_log_register("pmd.net.ixgbe.init");
        if (ixgbe_logtype_init >= 0)
                rte_log_set_level(ixgbe_logtype_init, RTE_LOG_NOTICE);
-       ixgbe_logtype_driver = rte_log_register("pmd.ixgbe.driver");
+       ixgbe_logtype_driver = rte_log_register("pmd.net.ixgbe.driver");
        if (ixgbe_logtype_driver >= 0)
                rte_log_set_level(ixgbe_logtype_driver, RTE_LOG_NOTICE);
 }