net/ixgbe: support VF promiscuous by PF driver
[dpdk.git] / drivers / net / ixgbe / ixgbe_rxtx.c
index ddc7efa..e92a70f 100644 (file)
@@ -2867,7 +2867,8 @@ ixgbe_get_rx_port_offloads(struct rte_eth_dev *dev)
         * mode.
         */
        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) &&
            !RTE_ETH_DEV_SRIOV(dev).active)
                offloads |= DEV_RX_OFFLOAD_TCP_LRO;
 
@@ -3167,12 +3168,44 @@ ixgbe_dev_tx_descriptor_status(void *tx_queue, uint16_t offset)
        return RTE_ETH_TX_DESC_FULL;
 }
 
+/*
+ * Set up link loopback for X540/X550 mode Tx->Rx.
+ */
+static inline void __attribute__((cold))
+ixgbe_setup_loopback_link_x540_x550(struct ixgbe_hw *hw, bool enable)
+{
+       uint32_t macc;
+       PMD_INIT_FUNC_TRACE();
+
+       u16 autoneg_reg = IXGBE_MII_AUTONEG_REG;
+
+       hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL,
+                            IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg);
+       macc = IXGBE_READ_REG(hw, IXGBE_MACC);
+
+       if (enable) {
+               /* datasheet 15.2.1: disable AUTONEG (PHY Bit 7.0.C) */
+               autoneg_reg |= IXGBE_MII_AUTONEG_ENABLE;
+               /* datasheet 15.2.1: MACC.FLU = 1 (force link up) */
+               macc |= IXGBE_MACC_FLU;
+       } else {
+               autoneg_reg &= ~IXGBE_MII_AUTONEG_ENABLE;
+               macc &= ~IXGBE_MACC_FLU;
+       }
+
+       hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL,
+                             IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg);
+
+       IXGBE_WRITE_REG(hw, IXGBE_MACC, macc);
+}
+
 void __attribute__((cold))
 ixgbe_dev_clear_queues(struct rte_eth_dev *dev)
 {
        unsigned i;
        struct ixgbe_adapter *adapter =
                (struct ixgbe_adapter *)dev->data->dev_private;
+       struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
        PMD_INIT_FUNC_TRACE();
 
@@ -3193,6 +3226,14 @@ ixgbe_dev_clear_queues(struct rte_eth_dev *dev)
                        ixgbe_reset_rx_queue(adapter, rxq);
                }
        }
+       /* If loopback mode was enabled, reconfigure the link accordingly */
+       if (dev->data->dev_conf.lpbk_mode != 0) {
+               if (hw->mac.type == ixgbe_mac_X540 ||
+                    hw->mac.type == ixgbe_mac_X550 ||
+                    hw->mac.type == ixgbe_mac_X550EM_x ||
+                    hw->mac.type == ixgbe_mac_X550EM_a)
+                       ixgbe_setup_loopback_link_x540_x550(hw, false);
+       }
 }
 
 void
@@ -3417,6 +3458,7 @@ static void
 ixgbe_rss_configure(struct rte_eth_dev *dev)
 {
        struct rte_eth_rss_conf rss_conf;
+       struct ixgbe_adapter *adapter;
        struct ixgbe_hw *hw;
        uint32_t reta;
        uint16_t i;
@@ -3425,6 +3467,7 @@ ixgbe_rss_configure(struct rte_eth_dev *dev)
        uint32_t reta_reg;
 
        PMD_INIT_FUNC_TRACE();
+       adapter = (struct ixgbe_adapter *)dev->data->dev_private;
        hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
        sp_reta_size = ixgbe_reta_size_get(hw->mac.type);
@@ -3434,16 +3477,18 @@ ixgbe_rss_configure(struct rte_eth_dev *dev)
         * The byte-swap is needed because NIC registers are in
         * little-endian order.
         */
-       reta = 0;
-       for (i = 0, j = 0; i < sp_reta_size; i++, j++) {
-               reta_reg = ixgbe_reta_reg_get(hw->mac.type, i);
-
-               if (j == dev->data->nb_rx_queues)
-                       j = 0;
-               reta = (reta << 8) | j;
-               if ((i & 3) == 3)
-                       IXGBE_WRITE_REG(hw, reta_reg,
-                                       rte_bswap32(reta));
+       if (adapter->rss_reta_updated == 0) {
+               reta = 0;
+               for (i = 0, j = 0; i < sp_reta_size; i++, j++) {
+                       reta_reg = ixgbe_reta_reg_get(hw->mac.type, i);
+
+                       if (j == dev->data->nb_rx_queues)
+                               j = 0;
+                       reta = (reta << 8) | j;
+                       if ((i & 3) == 3)
+                               IXGBE_WRITE_REG(hw, reta_reg,
+                                               rte_bswap32(reta));
+               }
        }
 
        /*
@@ -4874,13 +4919,18 @@ ixgbe_dev_rx_init(struct rte_eth_dev *dev)
                hlreg0 &= ~IXGBE_HLREG0_JUMBOEN;
 
        /*
-        * If loopback mode is configured for 82599, set LPBK bit.
+        * If loopback mode is configured, set LPBK bit.
         */
-       if (hw->mac.type == ixgbe_mac_82599EB &&
-                       dev->data->dev_conf.lpbk_mode == IXGBE_LPBK_82599_TX_RX)
+       if (dev->data->dev_conf.lpbk_mode != 0) {
+               rc = ixgbe_check_supported_loopback_mode(dev);
+               if (rc < 0) {
+                       PMD_INIT_LOG(ERR, "Unsupported loopback mode");
+                       return rc;
+               }
                hlreg0 |= IXGBE_HLREG0_LPBK;
-       else
+       } else {
                hlreg0 &= ~IXGBE_HLREG0_LPBK;
+       }
 
        IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
 
@@ -5056,6 +5106,25 @@ ixgbe_dev_tx_init(struct rte_eth_dev *dev)
        ixgbe_dev_mq_tx_configure(dev);
 }
 
+/*
+ * Check if requested loopback mode is supported
+ */
+int
+ixgbe_check_supported_loopback_mode(struct rte_eth_dev *dev)
+{
+       struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+       if (dev->data->dev_conf.lpbk_mode == IXGBE_LPBK_TX_RX)
+               if (hw->mac.type == ixgbe_mac_82599EB ||
+                    hw->mac.type == ixgbe_mac_X540 ||
+                    hw->mac.type == ixgbe_mac_X550 ||
+                    hw->mac.type == ixgbe_mac_X550EM_x ||
+                    hw->mac.type == ixgbe_mac_X550EM_a)
+                       return 0;
+
+       return -ENOTSUP;
+}
+
 /*
  * Set up link for 82599 loopback mode Tx->Rx.
  */
@@ -5143,10 +5212,16 @@ ixgbe_dev_rxtx_start(struct rte_eth_dev *dev)
        rxctrl |= IXGBE_RXCTRL_RXEN;
        hw->mac.ops.enable_rx_dma(hw, rxctrl);
 
-       /* If loopback mode is enabled for 82599, set up the link accordingly */
-       if (hw->mac.type == ixgbe_mac_82599EB &&
-                       dev->data->dev_conf.lpbk_mode == IXGBE_LPBK_82599_TX_RX)
-               ixgbe_setup_loopback_link_82599(hw);
+       /* If loopback mode is enabled, set up the link accordingly */
+       if (dev->data->dev_conf.lpbk_mode != 0) {
+               if (hw->mac.type == ixgbe_mac_82599EB)
+                       ixgbe_setup_loopback_link_82599(hw);
+               else if (hw->mac.type == ixgbe_mac_X540 ||
+                    hw->mac.type == ixgbe_mac_X550 ||
+                    hw->mac.type == ixgbe_mac_X550EM_x ||
+                    hw->mac.type == ixgbe_mac_X550EM_a)
+                       ixgbe_setup_loopback_link_x540_x550(hw, true);
+       }
 
 #ifdef RTE_LIBRTE_SECURITY
        if ((dev->data->dev_conf.rxmode.offloads &