New upstream version 18.02
[deb_dpdk.git] / drivers / net / fm10k / fm10k_ethdev.c
index 7363def..9423761 100644 (file)
@@ -1,37 +1,8 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2013-2016 Intel Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2013-2016 Intel Corporation
  */
 
-#include <rte_ethdev.h>
+#include <rte_ethdev_driver.h>
 #include <rte_ethdev_pci.h>
 #include <rte_malloc.h>
 #include <rte_memzone.h>
@@ -54,7 +25,7 @@
 /* Wait interval to get switch status */
 #define WAIT_SWITCH_MSG_US    100000
 /* A period of quiescence for switch */
-#define FM10K_SWITCH_QUIESCE_US 10000
+#define FM10K_SWITCH_QUIESCE_US 100000
 /* Number of chars per uint32 type */
 #define CHARS_PER_UINT32 (sizeof(uint32_t))
 #define BIT_MASK_PER_UINT32 ((1 << CHARS_PER_UINT32) - 1)
@@ -69,6 +40,9 @@
 #define GLORT_FD_MASK    GLORT_PF_MASK
 #define GLORT_FD_INDEX   GLORT_FD_Q_BASE
 
+int fm10k_logtype_init;
+int fm10k_logtype_driver;
+
 static void fm10k_close_mbx_service(struct fm10k_hw *hw);
 static void fm10k_dev_promiscuous_enable(struct rte_eth_dev *dev);
 static void fm10k_dev_promiscuous_disable(struct rte_eth_dev *dev);
@@ -84,6 +58,7 @@ static void fm10k_rx_queue_release(void *queue);
 static void fm10k_set_rx_function(struct rte_eth_dev *dev);
 static void fm10k_set_tx_function(struct rte_eth_dev *dev);
 static int fm10k_check_ftag(struct rte_devargs *devargs);
+static int fm10k_link_update(struct rte_eth_dev *dev, int wait_to_complete);
 
 struct fm10k_xstats_name_off {
        char name[RTE_ETH_XSTATS_NAME_SIZE];
@@ -532,9 +507,8 @@ fm10k_dev_rss_configure(struct rte_eth_dev *dev)
                0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA,
        };
 
-       if (dev->data->nb_rx_queues == 1 ||
-           dev_conf->rxmode.mq_mode != ETH_MQ_RX_RSS ||
-           dev_conf->rx_adv_conf.rss_conf.rss_hf == 0) {
+       if (dev_conf->rxmode.mq_mode != ETH_MQ_RX_RSS ||
+               dev_conf->rx_adv_conf.rss_conf.rss_hf == 0) {
                FM10K_WRITE_REG(hw, FM10K_MRQC(0), 0);
                return;
        }
@@ -712,7 +686,7 @@ fm10k_dev_rx_init(struct rte_eth_dev *dev)
 {
        struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct fm10k_macvlan_filter_info *macvlan;
-       struct rte_pci_device *pdev = RTE_DEV_TO_PCI(dev->device);
+       struct rte_pci_device *pdev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_intr_handle *intr_handle = &pdev->intr_handle;
        int i, ret;
        struct fm10k_rx_queue *rxq;
@@ -1166,6 +1140,8 @@ fm10k_dev_start(struct rte_eth_dev *dev)
        if (!(dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_VMDQ_FLAG))
                fm10k_vlan_filter_set(dev, hw->mac.default_vid, true);
 
+       fm10k_link_update(dev, 0);
+
        return 0;
 }
 
@@ -1173,7 +1149,7 @@ static void
 fm10k_dev_stop(struct rte_eth_dev *dev)
 {
        struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       struct rte_pci_device *pdev = RTE_DEV_TO_PCI(dev->device);
+       struct rte_pci_device *pdev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_intr_handle *intr_handle = &pdev->intr_handle;
        int i;
 
@@ -1239,7 +1215,7 @@ fm10k_dev_close(struct rte_eth_dev *dev)
                MAX_LPORT_NUM, false);
        fm10k_mbx_unlock(hw);
 
-       /* allow 10ms for device to quiesce */
+       /* allow 100ms for device to quiesce */
        rte_delay_us(FM10K_SWITCH_QUIESCE_US);
 
        /* Stop mailbox service first */
@@ -1253,14 +1229,17 @@ static int
 fm10k_link_update(struct rte_eth_dev *dev,
        __rte_unused int wait_to_complete)
 {
+       struct fm10k_dev_info *dev_info =
+               FM10K_DEV_PRIVATE_TO_INFO(dev->data->dev_private);
        PMD_INIT_FUNC_TRACE();
 
-       /* The host-interface link is always up.  The speed is ~50Gbps per Gen3
-        * x8 PCIe interface. For now, we leave the speed undefined since there
-        * is no 50Gbps Ethernet. */
+       /* The speed is ~50Gbps per Gen3 x8 PCIe interface. For now, we
+        * leave the speed undefined since there is no 50Gbps Ethernet.
+        */
        dev->data->dev_link.link_speed  = 0;
        dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX;
-       dev->data->dev_link.link_status = ETH_LINK_UP;
+       dev->data->dev_link.link_status =
+               dev_info->sm_down ? ETH_LINK_DOWN : ETH_LINK_UP;
 
        return 0;
 }
@@ -1343,7 +1322,7 @@ fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
        return FM10K_NB_XSTATS;
 }
 
-static void
+static int
 fm10k_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 {
        uint64_t ipackets, opackets, ibytes, obytes;
@@ -1373,6 +1352,7 @@ fm10k_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
        stats->opackets = opackets;
        stats->ibytes = ibytes;
        stats->obytes = obytes;
+       return 0;
 }
 
 static void
@@ -1393,7 +1373,7 @@ fm10k_dev_infos_get(struct rte_eth_dev *dev,
        struct rte_eth_dev_info *dev_info)
 {
        struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       struct rte_pci_device *pdev = RTE_DEV_TO_PCI(dev->device);
+       struct rte_pci_device *pdev = RTE_ETH_DEV_TO_PCI(dev);
 
        PMD_INIT_FUNC_TRACE();
 
@@ -1587,8 +1567,8 @@ fm10k_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
        return 0;
 }
 
-static void
-fm10k_vlan_offload_set(__rte_unused struct rte_eth_dev *dev, int mask)
+static int
+fm10k_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
        if (mask & ETH_VLAN_STRIP_MASK) {
                if (!dev->data->dev_conf.rxmode.hw_vlan_strip)
@@ -1606,6 +1586,8 @@ fm10k_vlan_offload_set(__rte_unused struct rte_eth_dev *dev, int mask)
                if (!dev->data->dev_conf.rxmode.hw_vlan_filter)
                        PMD_INIT_LOG(ERR, "VLAN filter is always on in fm10k");
        }
+
+       return 0;
 }
 
 /* Add/Remove a MAC address, and update filters to main VSI */
@@ -1884,7 +1866,7 @@ fm10k_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id,
                return -ENOMEM;
        }
        q->hw_ring = mz->addr;
-       q->hw_ring_phys_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);
+       q->hw_ring_phys_addr = mz->iova;
 
        /* Check if number of descs satisfied Vector requirement */
        if (!rte_is_power_of_2(nb_desc)) {
@@ -2044,7 +2026,7 @@ fm10k_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id,
                return -ENOMEM;
        }
        q->hw_ring = mz->addr;
-       q->hw_ring_phys_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);
+       q->hw_ring_phys_addr = mz->iova;
 
        /*
         * allocate memory for the RS bit tracker. Enough slots to hold the
@@ -2345,7 +2327,7 @@ static int
 fm10k_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
 {
        struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       struct rte_pci_device *pdev = RTE_DEV_TO_PCI(dev->device);
+       struct rte_pci_device *pdev = RTE_ETH_DEV_TO_PCI(dev);
 
        /* Enable ITR */
        if (hw->mac.type == fm10k_mac_pf)
@@ -2362,7 +2344,7 @@ static int
 fm10k_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
 {
        struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       struct rte_pci_device *pdev = RTE_DEV_TO_PCI(dev->device);
+       struct rte_pci_device *pdev = RTE_ETH_DEV_TO_PCI(dev);
 
        /* Disable ITR */
        if (hw->mac.type == fm10k_mac_pf)
@@ -2378,7 +2360,7 @@ static int
 fm10k_dev_rxq_interrupt_setup(struct rte_eth_dev *dev)
 {
        struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       struct rte_pci_device *pdev = RTE_DEV_TO_PCI(dev->device);
+       struct rte_pci_device *pdev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_intr_handle *intr_handle = &pdev->intr_handle;
        uint32_t intr_vector, vec;
        uint16_t queue_id;
@@ -2549,6 +2531,10 @@ fm10k_dev_interrupt_handler_pf(void *param)
        struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
        struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        uint32_t cause, status;
+       struct fm10k_dev_info *dev_info =
+               FM10K_DEV_PRIVATE_TO_INFO(dev->data->dev_private);
+       int status_mbx;
+       s32 err;
 
        if (hw->mac.type != fm10k_mac_pf)
                return;
@@ -2565,14 +2551,69 @@ fm10k_dev_interrupt_handler_pf(void *param)
        if (cause & FM10K_EICR_SWITCHNOTREADY)
                PMD_INIT_LOG(ERR, "INT: Switch is not ready");
 
-       if (cause & FM10K_EICR_SWITCHREADY)
+       if (cause & FM10K_EICR_SWITCHREADY) {
                PMD_INIT_LOG(INFO, "INT: Switch is ready");
+               if (dev_info->sm_down == 1) {
+                       fm10k_mbx_lock(hw);
+
+                       /* For recreating logical ports */
+                       status_mbx = hw->mac.ops.update_lport_state(hw,
+                                       hw->mac.dglort_map, MAX_LPORT_NUM, 1);
+                       if (status_mbx == FM10K_SUCCESS)
+                               PMD_INIT_LOG(INFO,
+                                       "INT: Recreated Logical port");
+                       else
+                               PMD_INIT_LOG(INFO,
+                                       "INT: Logical ports weren't recreated");
+
+                       status_mbx = hw->mac.ops.update_xcast_mode(hw,
+                               hw->mac.dglort_map, FM10K_XCAST_MODE_NONE);
+                       if (status_mbx != FM10K_SUCCESS)
+                               PMD_INIT_LOG(ERR, "Failed to set XCAST mode");
+
+                       fm10k_mbx_unlock(hw);
+
+                       /* first clear the internal SW recording structure */
+                       if (!(dev->data->dev_conf.rxmode.mq_mode &
+                                               ETH_MQ_RX_VMDQ_FLAG))
+                               fm10k_vlan_filter_set(dev, hw->mac.default_vid,
+                                       false);
+
+                       fm10k_MAC_filter_set(dev, hw->mac.addr, false,
+                                       MAIN_VSI_POOL_NUMBER);
+
+                       /*
+                        * Add default mac address and vlan for the logical
+                        * ports that have been created, leave to the
+                        * application to fully recover Rx filtering.
+                        */
+                       fm10k_MAC_filter_set(dev, hw->mac.addr, true,
+                                       MAIN_VSI_POOL_NUMBER);
+
+                       if (!(dev->data->dev_conf.rxmode.mq_mode &
+                                               ETH_MQ_RX_VMDQ_FLAG))
+                               fm10k_vlan_filter_set(dev, hw->mac.default_vid,
+                                       true);
+
+                       dev_info->sm_down = 0;
+                       _rte_eth_dev_callback_process(dev,
+                                       RTE_ETH_EVENT_INTR_LSC,
+                                       NULL);
+               }
+       }
 
        /* Handle mailbox message */
        fm10k_mbx_lock(hw);
-       hw->mbx.ops.process(hw, &hw->mbx);
+       err = hw->mbx.ops.process(hw, &hw->mbx);
        fm10k_mbx_unlock(hw);
 
+       if (err == FM10K_ERR_RESET_REQUESTED) {
+               PMD_INIT_LOG(INFO, "INT: Switch is down");
+               dev_info->sm_down = 1;
+               _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC,
+                               NULL);
+       }
+
        /* Handle SRAM error */
        if (cause & FM10K_EICR_SRAMERROR) {
                PMD_INIT_LOG(ERR, "INT: SRAM error on PEP");
@@ -2613,6 +2654,11 @@ fm10k_dev_interrupt_handler_vf(void *param)
 {
        struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
        struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct fm10k_mbx_info *mbx = &hw->mbx;
+       struct fm10k_dev_info *dev_info =
+               FM10K_DEV_PRIVATE_TO_INFO(dev->data->dev_private);
+       const enum fm10k_mbx_state state = mbx->state;
+       int status_mbx;
 
        if (hw->mac.type != fm10k_mac_vf)
                return;
@@ -2622,6 +2668,49 @@ fm10k_dev_interrupt_handler_vf(void *param)
        hw->mbx.ops.process(hw, &hw->mbx);
        fm10k_mbx_unlock(hw);
 
+       if (state == FM10K_STATE_OPEN && mbx->state == FM10K_STATE_CONNECT) {
+               PMD_INIT_LOG(INFO, "INT: Switch has gone down");
+
+               fm10k_mbx_lock(hw);
+               hw->mac.ops.update_lport_state(hw, hw->mac.dglort_map,
+                               MAX_LPORT_NUM, 1);
+               fm10k_mbx_unlock(hw);
+
+               /* Setting reset flag */
+               dev_info->sm_down = 1;
+               _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC,
+                               NULL);
+       }
+
+       if (dev_info->sm_down == 1 &&
+                       hw->mac.dglort_map == FM10K_DGLORTMAP_ZERO) {
+               PMD_INIT_LOG(INFO, "INT: Switch has gone up");
+               fm10k_mbx_lock(hw);
+               status_mbx = hw->mac.ops.update_xcast_mode(hw,
+                               hw->mac.dglort_map, FM10K_XCAST_MODE_NONE);
+               if (status_mbx != FM10K_SUCCESS)
+                       PMD_INIT_LOG(ERR, "Failed to set XCAST mode");
+               fm10k_mbx_unlock(hw);
+
+               /* first clear the internal SW recording structure */
+               fm10k_vlan_filter_set(dev, hw->mac.default_vid, false);
+               fm10k_MAC_filter_set(dev, hw->mac.addr, false,
+                               MAIN_VSI_POOL_NUMBER);
+
+               /*
+                * Add default mac address and vlan for the logical ports that
+                * have been created, leave to the application to fully recover
+                * Rx filtering.
+                */
+               fm10k_MAC_filter_set(dev, hw->mac.addr, true,
+                               MAIN_VSI_POOL_NUMBER);
+               fm10k_vlan_filter_set(dev, hw->mac.default_vid, true);
+
+               dev_info->sm_down = 0;
+               _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC,
+                               NULL);
+       }
+
        /* Re-enable interrupt from device side */
        FM10K_WRITE_REG(hw, FM10K_VFITR(0), FM10K_ITR_AUTOMASK |
                                        FM10K_ITR_MASK_CLEAR);
@@ -2882,7 +2971,7 @@ static int
 eth_fm10k_dev_init(struct rte_eth_dev *dev)
 {
        struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       struct rte_pci_device *pdev = RTE_DEV_TO_PCI(dev->device);
+       struct rte_pci_device *pdev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_intr_handle *intr_handle = &pdev->intr_handle;
        int diag, i;
        struct fm10k_macvlan_filter_info *macvlan;
@@ -2905,7 +2994,6 @@ eth_fm10k_dev_init(struct rte_eth_dev *dev)
        }
 
        rte_eth_copy_pci_info(dev, pdev);
-       dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE;
 
        macvlan = FM10K_DEV_PRIVATE_TO_MACVLAN(dev->data->dev_private);
        memset(macvlan, 0, sizeof(*macvlan));
@@ -3069,7 +3157,7 @@ static int
 eth_fm10k_dev_uninit(struct rte_eth_dev *dev)
 {
        struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       struct rte_pci_device *pdev = RTE_DEV_TO_PCI(dev->device);
+       struct rte_pci_device *pdev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_intr_handle *intr_handle = &pdev->intr_handle;
        PMD_INIT_FUNC_TRACE();
 
@@ -3139,7 +3227,8 @@ static const struct rte_pci_id pci_id_fm10k_map[] = {
 
 static struct rte_pci_driver rte_pmd_fm10k = {
        .id_table = pci_id_fm10k_map,
-       .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
+       .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
+                    RTE_PCI_DRV_IOVA_AS_VA,
        .probe = eth_fm10k_pci_probe,
        .remove = eth_fm10k_pci_remove,
 };
@@ -3147,3 +3236,15 @@ static struct rte_pci_driver rte_pmd_fm10k = {
 RTE_PMD_REGISTER_PCI(net_fm10k, rte_pmd_fm10k);
 RTE_PMD_REGISTER_PCI_TABLE(net_fm10k, pci_id_fm10k_map);
 RTE_PMD_REGISTER_KMOD_DEP(net_fm10k, "* igb_uio | uio_pci_generic | vfio-pci");
+
+RTE_INIT(fm10k_init_log);
+static void
+fm10k_init_log(void)
+{
+       fm10k_logtype_init = rte_log_register("pmd.net.fm10k.init");
+       if (fm10k_logtype_init >= 0)
+               rte_log_set_level(fm10k_logtype_init, RTE_LOG_NOTICE);
+       fm10k_logtype_driver = rte_log_register("pmd.net.fm10k.driver");
+       if (fm10k_logtype_driver >= 0)
+               rte_log_set_level(fm10k_logtype_driver, RTE_LOG_NOTICE);
+}