net/ixgbe: fix DCB configuration
[dpdk.git] / drivers / net / ixgbe / ixgbe_ethdev.c
index a05527a..5ecf129 100644 (file)
@@ -59,9 +59,6 @@
  */
 #define IXGBE_FC_LO    0x40
 
-/* Default minimum inter-interrupt interval for EITR configuration */
-#define IXGBE_MIN_INTER_INTERRUPT_INTERVAL_DEFAULT    0x79E
-
 /* Timer value included in XOFF frames. */
 #define IXGBE_FC_PAUSE 0x680
 
@@ -240,8 +237,8 @@ static int ixgbevf_dev_link_update(struct rte_eth_dev *dev,
 static void ixgbevf_dev_stop(struct rte_eth_dev *dev);
 static void ixgbevf_dev_close(struct rte_eth_dev *dev);
 static int  ixgbevf_dev_reset(struct rte_eth_dev *dev);
-static void ixgbevf_intr_disable(struct ixgbe_hw *hw);
-static void ixgbevf_intr_enable(struct ixgbe_hw *hw);
+static void ixgbevf_intr_disable(struct rte_eth_dev *dev);
+static void ixgbevf_intr_enable(struct rte_eth_dev *dev);
 static int ixgbevf_dev_stats_get(struct rte_eth_dev *dev,
                struct rte_eth_stats *stats);
 static void ixgbevf_dev_stats_reset(struct rte_eth_dev *dev);
@@ -1606,7 +1603,7 @@ eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev)
        ixgbevf_dev_stats_reset(eth_dev);
 
        /* Disable the interrupts for VF */
-       ixgbevf_intr_disable(hw);
+       ixgbevf_intr_disable(eth_dev);
 
        hw->mac.num_rar_entries = 128; /* The MAX of the underlying PF */
        diag = hw->mac.ops.reset_hw(hw);
@@ -1675,7 +1672,7 @@ eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev)
        rte_intr_callback_register(intr_handle,
                                   ixgbevf_dev_interrupt_handler, eth_dev);
        rte_intr_enable(intr_handle);
-       ixgbevf_intr_enable(hw);
+       ixgbevf_intr_enable(eth_dev);
 
        PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x mac.type=%s",
                     eth_dev->data->port_id, pci_dev->id.vendor_id,
@@ -1708,7 +1705,7 @@ eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev)
        eth_dev->tx_pkt_burst = NULL;
 
        /* Disable the interrupts for VF */
-       ixgbevf_intr_disable(hw);
+       ixgbevf_intr_disable(eth_dev);
 
        rte_free(eth_dev->data->mac_addrs);
        eth_dev->data->mac_addrs = NULL;
@@ -1745,9 +1742,11 @@ eth_ixgbe_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
        if (retval || eth_da.nb_representor_ports < 1)
                return retval;
 
-       /* probe VF representor ports */
        pf_ethdev = rte_eth_dev_allocated(pci_dev->device.name);
+       if (pf_ethdev == NULL)
+               return -ENODEV;
 
+       /* probe VF representor ports */
        for (i = 0; i < eth_da.nb_representor_ports; i++) {
                struct ixgbe_vf_info *vfinfo;
                struct ixgbe_vf_representor representor;
@@ -2305,11 +2304,6 @@ ixgbe_check_mq_mode(struct rte_eth_dev *dev)
                if (dev_conf->rxmode.mq_mode == ETH_MQ_RX_DCB) {
                        const struct rte_eth_dcb_rx_conf *conf;
 
-                       if (nb_rx_q != IXGBE_DCB_NB_QUEUES) {
-                               PMD_INIT_LOG(ERR, "DCB selected, nb_rx_q != %d.",
-                                                IXGBE_DCB_NB_QUEUES);
-                               return -EINVAL;
-                       }
                        conf = &dev_conf->rx_adv_conf.dcb_rx_conf;
                        if (!(conf->nb_tcs == ETH_4_TCS ||
                               conf->nb_tcs == ETH_8_TCS)) {
@@ -2323,11 +2317,6 @@ ixgbe_check_mq_mode(struct rte_eth_dev *dev)
                if (dev_conf->txmode.mq_mode == ETH_MQ_TX_DCB) {
                        const struct rte_eth_dcb_tx_conf *conf;
 
-                       if (nb_tx_q != IXGBE_DCB_NB_QUEUES) {
-                               PMD_INIT_LOG(ERR, "DCB, nb_tx_q != %d.",
-                                                IXGBE_DCB_NB_QUEUES);
-                               return -EINVAL;
-                       }
                        conf = &dev_conf->tx_adv_conf.dcb_tx_conf;
                        if (!(conf->nb_tcs == ETH_4_TCS ||
                               conf->nb_tcs == ETH_8_TCS)) {
@@ -2363,9 +2352,6 @@ ixgbe_dev_configure(struct rte_eth_dev *dev)
                IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
        struct ixgbe_adapter *adapter =
                (struct ixgbe_adapter *)dev->data->dev_private;
-       struct rte_eth_dev_info dev_info;
-       uint64_t rx_offloads;
-       uint64_t tx_offloads;
        int ret;
 
        PMD_INIT_FUNC_TRACE();
@@ -2377,22 +2363,6 @@ ixgbe_dev_configure(struct rte_eth_dev *dev)
                return ret;
        }
 
-       ixgbe_dev_info_get(dev, &dev_info);
-       rx_offloads = dev->data->dev_conf.rxmode.offloads;
-       if ((rx_offloads & dev_info.rx_offload_capa) != rx_offloads) {
-               PMD_DRV_LOG(ERR, "Some Rx offloads are not supported "
-                           "requested 0x%" PRIx64 " supported 0x%" PRIx64,
-                           rx_offloads, dev_info.rx_offload_capa);
-               return -ENOTSUP;
-       }
-       tx_offloads = dev->data->dev_conf.txmode.offloads;
-       if ((tx_offloads & dev_info.tx_offload_capa) != tx_offloads) {
-               PMD_DRV_LOG(ERR, "Some Tx offloads are not supported "
-                           "requested 0x%" PRIx64 " supported 0x%" PRIx64,
-                           tx_offloads, dev_info.tx_offload_capa);
-               return -ENOTSUP;
-       }
-
        /* set flag to update link status after init */
        intr->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
 
@@ -3725,9 +3695,6 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
                },
                .tx_free_thresh = IXGBE_DEFAULT_TX_FREE_THRESH,
                .tx_rs_thresh = IXGBE_DEFAULT_TX_RSBIT_THRESH,
-               .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS |
-                            ETH_TXQ_FLAGS_NOOFFLOADS |
-                            ETH_TXQ_FLAGS_IGNORE,
                .offloads = 0,
        };
 
@@ -3833,9 +3800,6 @@ ixgbevf_dev_info_get(struct rte_eth_dev *dev,
                },
                .tx_free_thresh = IXGBE_DEFAULT_TX_FREE_THRESH,
                .tx_rs_thresh = IXGBE_DEFAULT_TX_RSBIT_THRESH,
-               .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS |
-                            ETH_TXQ_FLAGS_NOOFFLOADS |
-                            ETH_TXQ_FLAGS_IGNORE,
                .offloads = 0,
        };
 
@@ -4934,19 +4898,32 @@ ixgbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
  * Virtual Function operations
  */
 static void
-ixgbevf_intr_disable(struct ixgbe_hw *hw)
+ixgbevf_intr_disable(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);
+
        PMD_INIT_FUNC_TRACE();
 
        /* Clear interrupt mask to stop from interrupts being generated */
        IXGBE_WRITE_REG(hw, IXGBE_VTEIMC, IXGBE_VF_IRQ_CLEAR_MASK);
 
        IXGBE_WRITE_FLUSH(hw);
+
+       /* Clear mask value. */
+       intr->mask = 0;
 }
 
 static void
-ixgbevf_intr_enable(struct ixgbe_hw *hw)
+ixgbevf_intr_enable(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);
+
        PMD_INIT_FUNC_TRACE();
 
        /* VF enable interrupt autoclean */
@@ -4955,6 +4932,9 @@ ixgbevf_intr_enable(struct ixgbe_hw *hw)
        IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, IXGBE_VF_IRQ_ENABLE_MASK);
 
        IXGBE_WRITE_FLUSH(hw);
+
+       /* Save IXGBE_VTEIMS value to mask. */
+       intr->mask = IXGBE_VF_IRQ_ENABLE_MASK;
 }
 
 static int
@@ -4963,29 +4943,10 @@ ixgbevf_dev_configure(struct rte_eth_dev *dev)
        struct rte_eth_conf *conf = &dev->data->dev_conf;
        struct ixgbe_adapter *adapter =
                        (struct ixgbe_adapter *)dev->data->dev_private;
-       struct rte_eth_dev_info dev_info;
-       uint64_t rx_offloads;
-       uint64_t tx_offloads;
 
        PMD_INIT_LOG(DEBUG, "Configured Virtual Function port id: %d",
                     dev->data->port_id);
 
-       ixgbevf_dev_info_get(dev, &dev_info);
-       rx_offloads = dev->data->dev_conf.rxmode.offloads;
-       if ((rx_offloads & dev_info.rx_offload_capa) != rx_offloads) {
-               PMD_DRV_LOG(ERR, "Some Rx offloads are not supported "
-                           "requested 0x%" PRIx64 " supported 0x%" PRIx64,
-                           rx_offloads, dev_info.rx_offload_capa);
-               return -ENOTSUP;
-       }
-       tx_offloads = dev->data->dev_conf.txmode.offloads;
-       if ((tx_offloads & dev_info.tx_offload_capa) != tx_offloads) {
-               PMD_DRV_LOG(ERR, "Some Tx offloads are not supported "
-                           "requested 0x%" PRIx64 " supported 0x%" PRIx64,
-                           tx_offloads, dev_info.tx_offload_capa);
-               return -ENOTSUP;
-       }
-
        /*
         * VF has no ability to enable/disable HW CRC
         * Keep the persistent behavior the same as Host PF
@@ -5097,7 +5058,7 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)
        rte_intr_enable(intr_handle);
 
        /* Re-enable interrupt for VF */
-       ixgbevf_intr_enable(hw);
+       ixgbevf_intr_enable(dev);
 
        return 0;
 }
@@ -5111,7 +5072,7 @@ ixgbevf_dev_stop(struct rte_eth_dev *dev)
 
        PMD_INIT_FUNC_TRACE();
 
-       ixgbevf_intr_disable(hw);
+       ixgbevf_intr_disable(dev);
 
        hw->adapter_stopped = 1;
        ixgbe_stop_adapter(hw);
@@ -5603,17 +5564,17 @@ ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
 {
        struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
-       uint32_t mask;
+       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);
        uint32_t vec = IXGBE_MISC_VEC_ID;
 
-       mask = IXGBE_READ_REG(hw, IXGBE_VTEIMS);
        if (rte_intr_allow_others(intr_handle))
                vec = IXGBE_RX_VEC_START;
-       mask |= (1 << vec);
+       intr->mask |= (1 << vec);
        RTE_SET_USED(queue_id);
-       IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask);
+       IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, intr->mask);
 
        rte_intr_enable(intr_handle);
 
@@ -5623,19 +5584,19 @@ ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
 static int
 ixgbevf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
 {
-       uint32_t mask;
+       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);
        struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        uint32_t vec = IXGBE_MISC_VEC_ID;
 
-       mask = IXGBE_READ_REG(hw, IXGBE_VTEIMS);
        if (rte_intr_allow_others(intr_handle))
                vec = IXGBE_RX_VEC_START;
-       mask &= ~(1 << vec);
+       intr->mask &= ~(1 << vec);
        RTE_SET_USED(queue_id);
-       IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask);
+       IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, intr->mask);
 
        return 0;
 }
@@ -5801,6 +5762,13 @@ ixgbevf_configure_msix(struct rte_eth_dev *dev)
                if (vector_idx < base + intr_handle->nb_efd - 1)
                        vector_idx++;
        }
+
+       /* As RX queue setting above show, all queues use the vector 0.
+        * Set only the ITR value of IXGBE_MISC_VEC_ID.
+        */
+       IXGBE_WRITE_REG(hw, IXGBE_VTEITR(IXGBE_MISC_VEC_ID),
+                       IXGBE_EITR_INTERVAL_US(IXGBE_QUEUE_ITR_INTERVAL_DEFAULT)
+                       | IXGBE_EITR_CNT_WDIS);
 }
 
 /**
@@ -5822,8 +5790,12 @@ ixgbe_configure_msix(struct rte_eth_dev *dev)
 
        /* won't configure msix register if no mapping is done
         * between intr vector and event fd
+        * but if misx has been enabled already, need to configure
+        * auto clean, auto mask and throttling.
         */
-       if (!rte_intr_dp_is_en(intr_handle))
+       gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
+       if (!rte_intr_dp_is_en(intr_handle) &&
+           !(gpie & (IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_PBA_SUPPORT)))
                return;
 
        if (rte_intr_allow_others(intr_handle))
@@ -5847,30 +5819,34 @@ ixgbe_configure_msix(struct rte_eth_dev *dev)
        /* Populate the IVAR table and set the ITR values to the
         * corresponding register.
         */
-       for (queue_id = 0; queue_id < dev->data->nb_rx_queues;
-            queue_id++) {
-               /* by default, 1:1 mapping */
-               ixgbe_set_ivar_map(hw, 0, queue_id, vec);
-               intr_handle->intr_vec[queue_id] = vec;
-               if (vec < base + intr_handle->nb_efd - 1)
-                       vec++;
-       }
+       if (rte_intr_dp_is_en(intr_handle)) {
+               for (queue_id = 0; queue_id < dev->data->nb_rx_queues;
+                       queue_id++) {
+                       /* by default, 1:1 mapping */
+                       ixgbe_set_ivar_map(hw, 0, queue_id, vec);
+                       intr_handle->intr_vec[queue_id] = vec;
+                       if (vec < base + intr_handle->nb_efd - 1)
+                               vec++;
+               }
 
-       switch (hw->mac.type) {
-       case ixgbe_mac_82598EB:
-               ixgbe_set_ivar_map(hw, -1, IXGBE_IVAR_OTHER_CAUSES_INDEX,
-                                  IXGBE_MISC_VEC_ID);
-               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:
-               break;
+               switch (hw->mac.type) {
+               case ixgbe_mac_82598EB:
+                       ixgbe_set_ivar_map(hw, -1,
+                                          IXGBE_IVAR_OTHER_CAUSES_INDEX,
+                                          IXGBE_MISC_VEC_ID);
+                       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:
+                       break;
+               }
        }
        IXGBE_WRITE_REG(hw, IXGBE_EITR(IXGBE_MISC_VEC_ID),
-                       IXGBE_MIN_INTER_INTERRUPT_INTERVAL_DEFAULT & 0xFFF);
+                       IXGBE_EITR_INTERVAL_US(IXGBE_QUEUE_ITR_INTERVAL_DEFAULT)
+                       | IXGBE_EITR_CNT_WDIS);
 
        /* set up to autoclear timer, and the vectors */
        mask = IXGBE_EIMS_ENABLE_MASK;
@@ -8266,7 +8242,7 @@ ixgbevf_dev_interrupt_get_status(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);
-       ixgbevf_intr_disable(hw);
+       ixgbevf_intr_disable(dev);
 
        /* read-on-clear nic registers here */
        eicr = IXGBE_READ_REG(hw, IXGBE_VTEICR);
@@ -8283,7 +8259,6 @@ ixgbevf_dev_interrupt_get_status(struct rte_eth_dev *dev)
 static int
 ixgbevf_dev_interrupt_action(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);
 
@@ -8292,7 +8267,7 @@ ixgbevf_dev_interrupt_action(struct rte_eth_dev *dev)
                intr->flags &= ~IXGBE_FLAG_MAILBOX;
        }
 
-       ixgbevf_intr_enable(hw);
+       ixgbevf_intr_enable(dev);
 
        return 0;
 }