net/iavf: delete unsupported RSS types
[dpdk.git] / drivers / net / sfc / sfc_ethdev.c
index 583f31b..acee3e4 100644 (file)
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  *
- * Copyright (c) 2016-2018 Solarflare Communications Inc.
- * All rights reserved.
+ * Copyright(c) 2019-2020 Xilinx, Inc.
+ * Copyright(c) 2016-2019 Solarflare Communications Inc.
  *
  * This software was jointly developed between OKTET Labs (under contract
  * for Solarflare) and Solarflare Communications, Inc.
@@ -34,6 +34,10 @@ uint32_t sfc_logtype_driver;
 static struct sfc_dp_list sfc_dp_head =
        TAILQ_HEAD_INITIALIZER(sfc_dp_head);
 
+
+static void sfc_eth_dev_clear_ops(struct rte_eth_dev *dev);
+
+
 static int
 sfc_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)
 {
@@ -82,7 +86,7 @@ sfc_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)
                return 0;
 }
 
-static void
+static int
 sfc_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
        const struct sfc_adapter_priv *sap = sfc_adapter_priv_by_eth_dev(dev);
@@ -180,6 +184,8 @@ sfc_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 
        dev_info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
                             RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
+
+       return 0;
 }
 
 static const uint32_t *
@@ -335,12 +341,32 @@ sfc_dev_close(struct rte_eth_dev *dev)
                sfc_err(sa, "unexpected adapter state %u on close", sa->state);
                break;
        }
+
+       /*
+        * Cleanup all resources in accordance with RTE_ETH_DEV_CLOSE_REMOVE.
+        * Rollback primary process sfc_eth_dev_init() below.
+        */
+
+       sfc_eth_dev_clear_ops(dev);
+
+       sfc_detach(sa);
+       sfc_unprobe(sa);
+
+       sfc_kvargs_cleanup(sa);
+
        sfc_adapter_unlock(sa);
+       sfc_adapter_lock_fini(sa);
 
        sfc_log_init(sa, "done");
+
+       /* Required for logging, so cleanup last */
+       sa->eth_dev = NULL;
+
+       dev->process_private = NULL;
+       free(sa);
 }
 
-static void
+static int
 sfc_dev_filter_set(struct rte_eth_dev *dev, enum sfc_dev_filter_mode mode,
                   boolean_t enabled)
 {
@@ -349,6 +375,7 @@ sfc_dev_filter_set(struct rte_eth_dev *dev, enum sfc_dev_filter_mode mode,
        struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
        boolean_t allmulti = (mode == SFC_DEV_FILTER_MODE_ALLMULTI);
        const char *desc = (allmulti) ? "all-multi" : "promiscuous";
+       int rc = 0;
 
        sfc_adapter_lock(sa);
 
@@ -364,38 +391,59 @@ sfc_dev_filter_set(struct rte_eth_dev *dev, enum sfc_dev_filter_mode mode,
                                     "start provided that isolated mode is "
                                     "disabled prior the next start");
                } else if ((sa->state == SFC_ADAPTER_STARTED) &&
-                          (sfc_set_rx_mode(sa) != 0)) {
+                          ((rc = sfc_set_rx_mode(sa)) != 0)) {
                        *toggle = !(enabled);
-                       sfc_warn(sa, "Failed to %s %s mode",
-                                ((enabled) ? "enable" : "disable"), desc);
+                       sfc_warn(sa, "Failed to %s %s mode, rc = %d",
+                                ((enabled) ? "enable" : "disable"), desc, rc);
+
+                       /*
+                        * For promiscuous and all-multicast filters a
+                        * permission failure should be reported as an
+                        * unsupported filter.
+                        */
+                       if (rc == EPERM)
+                               rc = ENOTSUP;
                }
        }
 
        sfc_adapter_unlock(sa);
+       return rc;
 }
 
-static void
+static int
 sfc_dev_promisc_enable(struct rte_eth_dev *dev)
 {
-       sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_PROMISC, B_TRUE);
+       int rc = sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_PROMISC, B_TRUE);
+
+       SFC_ASSERT(rc >= 0);
+       return -rc;
 }
 
-static void
+static int
 sfc_dev_promisc_disable(struct rte_eth_dev *dev)
 {
-       sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_PROMISC, B_FALSE);
+       int rc = sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_PROMISC, B_FALSE);
+
+       SFC_ASSERT(rc >= 0);
+       return -rc;
 }
 
-static void
+static int
 sfc_dev_allmulti_enable(struct rte_eth_dev *dev)
 {
-       sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_ALLMULTI, B_TRUE);
+       int rc = sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_ALLMULTI, B_TRUE);
+
+       SFC_ASSERT(rc >= 0);
+       return -rc;
 }
 
-static void
+static int
 sfc_dev_allmulti_disable(struct rte_eth_dev *dev)
 {
-       sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_ALLMULTI, B_FALSE);
+       int rc = sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_ALLMULTI, B_FALSE);
+
+       SFC_ASSERT(rc >= 0);
+       return -rc;
 }
 
 static int
@@ -609,7 +657,7 @@ unlock:
        return -ret;
 }
 
-static void
+static int
 sfc_stats_reset(struct rte_eth_dev *dev)
 {
        struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
@@ -622,12 +670,15 @@ sfc_stats_reset(struct rte_eth_dev *dev)
                 * will be scheduled to be done during the next port start
                 */
                port->mac_stats_reset_pending = B_TRUE;
-               return;
+               return 0;
        }
 
        rc = sfc_port_reset_mac_stats(sa);
        if (rc != 0)
                sfc_err(sa, "failed to reset statistics (rc = %d)", rc);
+
+       SFC_ASSERT(rc >= 0);
+       return -rc;
 }
 
 static int
@@ -913,7 +964,7 @@ sfc_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
        if (pdu > EFX_MAC_PDU_MAX) {
                sfc_err(sa, "too big MTU %u (PDU size %u greater than max %u)",
                        (unsigned int)mtu, (unsigned int)pdu,
-                       EFX_MAC_PDU_MAX);
+                       (unsigned int)EFX_MAC_PDU_MAX);
                goto fail_inval;
        }
 
@@ -979,6 +1030,9 @@ sfc_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr)
 
        sfc_adapter_lock(sa);
 
+       if (rte_is_same_ether_addr(mac_addr, &port->default_mac_addr))
+               goto unlock;
+
        /*
         * Copy the address to the device private data so that
         * it could be recalled in the case of adapter restart.
@@ -1017,12 +1071,12 @@ sfc_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr)
                 * has no effect on received traffic, therefore
                 * we also need to update unicast filters
                 */
-               rc = sfc_set_rx_mode(sa);
+               rc = sfc_set_rx_mode_unchecked(sa);
                if (rc != 0) {
                        sfc_err(sa, "cannot set filter (rc = %u)", rc);
                        /* Rollback the old address */
                        (void)efx_mac_addr_set(sa->nic, old_addr->addr_bytes);
-                       (void)sfc_set_rx_mode(sa);
+                       (void)sfc_set_rx_mode_unchecked(sa);
                }
        } else {
                sfc_warn(sa, "cannot set MAC address with filters installed");
@@ -1489,7 +1543,7 @@ sfc_dev_rss_hash_update(struct rte_eth_dev *dev,
 
        if ((rss_conf->rss_key != NULL) &&
            (rss_conf->rss_key_len != sizeof(rss->key))) {
-               sfc_err(sa, "RSS key size is wrong (should be %lu)",
+               sfc_err(sa, "RSS key size is wrong (should be %zu)",
                        sizeof(rss->key));
                return -EINVAL;
        }
@@ -2123,6 +2177,8 @@ sfc_eth_dev_init(struct rte_eth_dev *dev)
 
        sfc_log_init(sa, "entry");
 
+       dev->data->dev_flags |= RTE_ETH_DEV_CLOSE_REMOVE;
+
        dev->data->mac_addrs = rte_zmalloc("sfc", RTE_ETHER_ADDR_LEN, 0);
        if (dev->data->mac_addrs == NULL) {
                rc = ENOMEM;
@@ -2189,8 +2245,6 @@ fail_alloc_sa:
 static int
 sfc_eth_dev_uninit(struct rte_eth_dev *dev)
 {
-       struct sfc_adapter *sa;
-
        if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
                sfc_eth_dev_secondary_clear_ops(dev);
                return 0;
@@ -2198,29 +2252,6 @@ sfc_eth_dev_uninit(struct rte_eth_dev *dev)
 
        sfc_dev_close(dev);
 
-       sa = sfc_adapter_by_eth_dev(dev);
-       sfc_log_init(sa, "entry");
-
-       sfc_adapter_lock(sa);
-
-       sfc_eth_dev_clear_ops(dev);
-
-       sfc_detach(sa);
-       sfc_unprobe(sa);
-
-       sfc_kvargs_cleanup(sa);
-
-       sfc_adapter_unlock(sa);
-       sfc_adapter_lock_fini(sa);
-
-       sfc_log_init(sa, "done");
-
-       /* Required for logging, so cleanup last */
-       sa->eth_dev = NULL;
-
-       dev->process_private = NULL;
-       free(sa);
-
        return 0;
 }