net/ixgbe: fix TM hierarchy commit check
[dpdk.git] / drivers / net / ixgbe / ixgbe_ethdev.c
index 41c7d25..e436dca 100644 (file)
@@ -57,7 +57,6 @@
 #include <rte_ether.h>
 #include <rte_ethdev.h>
 #include <rte_ethdev_pci.h>
-#include <rte_atomic.h>
 #include <rte_malloc.h>
 #include <rte_random.h>
 #include <rte_dev.h>
@@ -240,7 +239,7 @@ static int ixgbe_dev_rss_reta_query(struct rte_eth_dev *dev,
                        struct rte_eth_rss_reta_entry64 *reta_conf,
                        uint16_t reta_size);
 static void ixgbe_dev_link_status_print(struct rte_eth_dev *dev);
-static int ixgbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev);
+static int ixgbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev, uint8_t on);
 static int ixgbe_dev_macsec_interrupt_setup(struct rte_eth_dev *dev);
 static int ixgbe_dev_rxq_interrupt_setup(struct rte_eth_dev *dev);
 static int ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev);
@@ -262,6 +261,8 @@ static int eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev);
 static int  ixgbevf_dev_configure(struct rte_eth_dev *dev);
 static int  ixgbevf_dev_start(struct rte_eth_dev *dev);
+static int ixgbevf_dev_link_update(struct rte_eth_dev *dev,
+                                  int wait_to_complete);
 static void ixgbevf_dev_stop(struct rte_eth_dev *dev);
 static void ixgbevf_dev_close(struct rte_eth_dev *dev);
 static void ixgbevf_intr_disable(struct ixgbe_hw *hw);
@@ -302,9 +303,6 @@ static void ixgbe_set_ivar_map(struct ixgbe_hw *hw, int8_t direction,
                               uint8_t queue, uint8_t msix_vector);
 static void ixgbe_configure_msix(struct rte_eth_dev *dev);
 
-static int ixgbe_set_queue_rate_limit(struct rte_eth_dev *dev,
-               uint16_t queue_idx, uint16_t tx_rate);
-
 static int ixgbevf_add_mac_addr(struct rte_eth_dev *dev,
                                struct ether_addr *mac_addr,
                                uint32_t index, uint32_t pool);
@@ -597,6 +595,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
        .l2_tunnel_offload_set   = ixgbe_dev_l2_tunnel_offload_set,
        .udp_tunnel_port_add  = ixgbe_dev_udp_tunnel_port_add,
        .udp_tunnel_port_del  = ixgbe_dev_udp_tunnel_port_del,
+       .tm_ops_get           = ixgbe_tm_ops_get,
 };
 
 /*
@@ -607,7 +606,7 @@ static const struct eth_dev_ops ixgbevf_eth_dev_ops = {
        .dev_configure        = ixgbevf_dev_configure,
        .dev_start            = ixgbevf_dev_start,
        .dev_stop             = ixgbevf_dev_stop,
-       .link_update          = ixgbe_dev_link_update,
+       .link_update          = ixgbevf_dev_link_update,
        .stats_get            = ixgbevf_dev_stats_get,
        .xstats_get           = ixgbevf_dev_xstats_get,
        .stats_reset          = ixgbevf_dev_stats_reset,
@@ -1348,6 +1347,9 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
        /* initialize bandwidth configuration info */
        memset(bw_conf, 0, sizeof(struct ixgbe_bw_conf));
 
+       /* initialize Traffic Manager configuration */
+       ixgbe_tm_conf_init(eth_dev);
+
        return 0;
 }
 
@@ -1401,6 +1403,9 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
        /* clear all the filters list */
        ixgbe_filterlist_flush();
 
+       /* Remove all Traffic Manager configuration */
+       ixgbe_tm_conf_uninit(eth_dev);
+
        return 0;
 }
 
@@ -2494,6 +2499,8 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
        int status;
        uint16_t vf, idx;
        uint32_t *link_speeds;
+       struct ixgbe_tm_conf *tm_conf =
+               IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private);
 
        PMD_INIT_FUNC_TRACE();
 
@@ -2661,7 +2668,9 @@ skip_link_setup:
        if (rte_intr_allow_others(intr_handle)) {
                /* check if lsc interrupt is enabled */
                if (dev->data->dev_conf.intr_conf.lsc != 0)
-                       ixgbe_dev_lsc_interrupt_setup(dev);
+                       ixgbe_dev_lsc_interrupt_setup(dev, TRUE);
+               else
+                       ixgbe_dev_lsc_interrupt_setup(dev, FALSE);
                ixgbe_dev_macsec_interrupt_setup(dev);
        } else {
                rte_intr_callback_unregister(intr_handle,
@@ -2684,6 +2693,11 @@ skip_link_setup:
        ixgbe_l2_tunnel_conf(dev);
        ixgbe_filter_restore(dev);
 
+       if (tm_conf->root && !tm_conf->committed)
+               PMD_DRV_LOG(WARNING,
+                           "please call hierarchy_commit() "
+                           "before starting the port");
+
        return 0;
 
 error:
@@ -2706,6 +2720,8 @@ ixgbe_dev_stop(struct rte_eth_dev *dev)
        struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        int vf;
+       struct ixgbe_tm_conf *tm_conf =
+               IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private);
 
        PMD_INIT_FUNC_TRACE();
 
@@ -2752,6 +2768,9 @@ ixgbe_dev_stop(struct rte_eth_dev *dev)
                rte_free(intr_handle->intr_vec);
                intr_handle->intr_vec = NULL;
        }
+
+       /* reset hierarchy commit */
+       tm_conf->committed = false;
 }
 
 /*
@@ -3706,6 +3725,12 @@ ixgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev)
            dev->rx_pkt_burst == ixgbe_recv_pkts_lro_bulk_alloc ||
            dev->rx_pkt_burst == ixgbe_recv_pkts_bulk_alloc)
                return ptypes;
+
+#if defined(RTE_ARCH_X86)
+       if (dev->rx_pkt_burst == ixgbe_recv_pkts_vec ||
+           dev->rx_pkt_burst == ixgbe_recv_scattered_pkts_vec)
+               return ptypes;
+#endif
        return NULL;
 }
 
@@ -3765,9 +3790,116 @@ ixgbevf_dev_info_get(struct rte_eth_dev *dev,
        dev_info->tx_desc_lim = tx_desc_lim;
 }
 
+static int
+ixgbevf_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
+                  int *link_up, int wait_to_complete)
+{
+       /**
+        * for a quick link status checking, wait_to_compelet == 0,
+        * skip PF link status checking
+        */
+       bool no_pflink_check = wait_to_complete == 0;
+       struct ixgbe_mbx_info *mbx = &hw->mbx;
+       struct ixgbe_mac_info *mac = &hw->mac;
+       uint32_t links_reg, in_msg;
+       int ret_val = 0;
+
+       /* If we were hit with a reset drop the link */
+       if (!mbx->ops.check_for_rst(hw, 0) || !mbx->timeout)
+               mac->get_link_status = true;
+
+       if (!mac->get_link_status)
+               goto out;
+
+       /* if link status is down no point in checking to see if pf is up */
+       links_reg = IXGBE_READ_REG(hw, IXGBE_VFLINKS);
+       if (!(links_reg & IXGBE_LINKS_UP))
+               goto out;
+
+       /* for SFP+ modules and DA cables on 82599 it can take up to 500usecs
+        * before the link status is correct
+        */
+       if (mac->type == ixgbe_mac_82599_vf) {
+               int i;
+
+               for (i = 0; i < 5; i++) {
+                       rte_delay_us(100);
+                       links_reg = IXGBE_READ_REG(hw, IXGBE_VFLINKS);
+
+                       if (!(links_reg & IXGBE_LINKS_UP))
+                               goto out;
+               }
+       }
+
+       switch (links_reg & IXGBE_LINKS_SPEED_82599) {
+       case IXGBE_LINKS_SPEED_10G_82599:
+               *speed = IXGBE_LINK_SPEED_10GB_FULL;
+               if (hw->mac.type >= ixgbe_mac_X550) {
+                       if (links_reg & IXGBE_LINKS_SPEED_NON_STD)
+                               *speed = IXGBE_LINK_SPEED_2_5GB_FULL;
+               }
+               break;
+       case IXGBE_LINKS_SPEED_1G_82599:
+               *speed = IXGBE_LINK_SPEED_1GB_FULL;
+               break;
+       case IXGBE_LINKS_SPEED_100_82599:
+               *speed = IXGBE_LINK_SPEED_100_FULL;
+               if (hw->mac.type == ixgbe_mac_X550) {
+                       if (links_reg & IXGBE_LINKS_SPEED_NON_STD)
+                               *speed = IXGBE_LINK_SPEED_5GB_FULL;
+               }
+               break;
+       case IXGBE_LINKS_SPEED_10_X550EM_A:
+               *speed = IXGBE_LINK_SPEED_UNKNOWN;
+               /* Since Reserved in older MAC's */
+               if (hw->mac.type >= ixgbe_mac_X550)
+                       *speed = IXGBE_LINK_SPEED_10_FULL;
+               break;
+       default:
+               *speed = IXGBE_LINK_SPEED_UNKNOWN;
+       }
+
+       if (no_pflink_check) {
+               if (*speed == IXGBE_LINK_SPEED_UNKNOWN)
+                       mac->get_link_status = true;
+               else
+                       mac->get_link_status = false;
+
+               goto out;
+       }
+       /* if the read failed it could just be a mailbox collision, best wait
+        * until we are called again and don't report an error
+        */
+       if (mbx->ops.read(hw, &in_msg, 1, 0))
+               goto out;
+
+       if (!(in_msg & IXGBE_VT_MSGTYPE_CTS)) {
+               /* msg is not CTS and is NACK we must have lost CTS status */
+               if (in_msg & IXGBE_VT_MSGTYPE_NACK)
+                       ret_val = -1;
+               goto out;
+       }
+
+       /* the pf is talking, if we timed out in the past we reinit */
+       if (!mbx->timeout) {
+               ret_val = -1;
+               goto out;
+       }
+
+       /* if we passed all the tests above then the link is up and we no
+        * longer need to check for link
+        */
+       mac->get_link_status = false;
+
+out:
+       *link_up = !mac->get_link_status;
+       return ret_val;
+}
+
 /* return 0 means link status changed, -1 means not changed */
 static int
-ixgbe_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete)
+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;
@@ -3777,6 +3909,7 @@ ixgbe_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete)
        int link_up;
        int diag;
        u32 speed = 0;
+       int wait = 1;
        bool autoneg = false;
 
        link.link_status = ETH_LINK_DOWN;
@@ -3797,9 +3930,12 @@ ixgbe_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete)
 
        /* check if it needs to wait to complete, if lsc interrupt is enabled */
        if (wait_to_complete == 0 || dev->data->dev_conf.intr_conf.lsc != 0)
-               diag = ixgbe_check_link(hw, &link_speed, &link_up, 0);
+               wait = 0;
+
+       if (vf)
+               diag = ixgbevf_check_link(hw, &link_speed, &link_up, wait);
        else
-               diag = ixgbe_check_link(hw, &link_speed, &link_up, 1);
+               diag = ixgbe_check_link(hw, &link_speed, &link_up, wait);
 
        if (diag != 0) {
                link.link_speed = ETH_SPEED_NUM_100M;
@@ -3848,6 +3984,18 @@ ixgbe_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete)
        return 0;
 }
 
+static int
+ixgbe_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete)
+{
+       return ixgbe_dev_link_update_share(dev, wait_to_complete, 0);
+}
+
+static int
+ixgbevf_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete)
+{
+       return ixgbe_dev_link_update_share(dev, wait_to_complete, 1);
+}
+
 static void
 ixgbe_dev_promiscuous_enable(struct rte_eth_dev *dev)
 {
@@ -3905,19 +4053,24 @@ ixgbe_dev_allmulticast_disable(struct rte_eth_dev *dev)
  *
  * @param dev
  *  Pointer to struct rte_eth_dev.
+ * @param on
+ *  Enable or Disable.
  *
  * @return
  *  - On success, zero.
  *  - On failure, a negative value.
  */
 static int
-ixgbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev)
+ixgbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev, uint8_t on)
 {
        struct ixgbe_interrupt *intr =
                IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
 
        ixgbe_dev_link_status_print(dev);
-       intr->mask |= IXGBE_EICR_LSC;
+       if (on)
+               intr->mask |= IXGBE_EICR_LSC;
+       else
+               intr->mask &= ~IXGBE_EICR_LSC;
 
        return 0;
 }
@@ -4680,7 +4833,7 @@ ixgbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
        struct ixgbe_hw *hw;
        struct rte_eth_dev_info dev_info;
        uint32_t frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
-       struct rte_eth_rxmode *rx_conf = &dev->data->dev_conf.rxmode;
+       struct rte_eth_dev_data *dev_data = dev->data;
 
        ixgbe_dev_info_get(dev, &dev_info);
 
@@ -4688,13 +4841,15 @@ ixgbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
        if ((mtu < ETHER_MIN_MTU) || (frame_size > dev_info.max_rx_pktlen))
                return -EINVAL;
 
-       /* refuse mtu that requires the support of scattered packets when this
-        * feature has not been enabled before.
+       /* If device is started, refuse mtu that requires the support of
+        * scattered packets when this feature has not been enabled before.
         */
-       if (!rx_conf->enable_scatter &&
+       if (dev_data->dev_started && !dev_data->scattered_rx &&
            (frame_size + 2 * IXGBE_VLAN_TAG_SIZE >
-            dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM))
+            dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM)) {
+               PMD_INIT_LOG(ERR, "Stop port first.");
                return -EINVAL;
+       }
 
        hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
@@ -5463,7 +5618,8 @@ ixgbe_set_ivar_map(struct ixgbe_hw *hw, int8_t direction,
                tmp |= (msix_vector << (8 * (queue & 0x3)));
                IXGBE_WRITE_REG(hw, IXGBE_IVAR(idx), tmp);
        } else if ((hw->mac.type == ixgbe_mac_82599EB) ||
-                       (hw->mac.type == ixgbe_mac_X540)) {
+                       (hw->mac.type == ixgbe_mac_X540) ||
+                       (hw->mac.type == ixgbe_mac_X550)) {
                if (direction == -1) {
                        /* other causes */
                        idx = ((queue & 1) * 8);
@@ -5571,6 +5727,7 @@ ixgbe_configure_msix(struct rte_eth_dev *dev)
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
                ixgbe_set_ivar_map(hw, -1, 1, IXGBE_MISC_VEC_ID);
                break;
        default:
@@ -5588,8 +5745,9 @@ ixgbe_configure_msix(struct rte_eth_dev *dev)
        IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask);
 }
 
-static int ixgbe_set_queue_rate_limit(struct rte_eth_dev *dev,
-       uint16_t queue_idx, uint16_t tx_rate)
+int
+ixgbe_set_queue_rate_limit(struct rte_eth_dev *dev,
+                          uint16_t queue_idx, uint16_t tx_rate)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        uint32_t rf_dec, rf_int;