net/sfc: fix promiscuous and allmulticast toggles errors
[dpdk.git] / drivers / net / sfc / sfc_ethdev.c
index 2865508..f8867b0 100644 (file)
@@ -14,6 +14,7 @@
 #include <rte_bus_pci.h>
 #include <rte_errno.h>
 #include <rte_string_fns.h>
+#include <rte_ether.h>
 
 #include "efx.h"
 
@@ -33,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)
 {
@@ -81,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);
@@ -92,21 +97,24 @@ sfc_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 
        sfc_log_init(sa, "entry");
 
+       dev_info->min_mtu = RTE_ETHER_MIN_MTU;
+       dev_info->max_mtu = EFX_MAC_SDU_MAX;
+
        dev_info->max_rx_pktlen = EFX_MAC_PDU_MAX;
 
        /* Autonegotiation may be disabled */
        dev_info->speed_capa = ETH_LINK_SPEED_FIXED;
-       if (sa->port.phy_adv_cap_mask & EFX_PHY_CAP_1000FDX)
+       if (sa->port.phy_adv_cap_mask & (1u << EFX_PHY_CAP_1000FDX))
                dev_info->speed_capa |= ETH_LINK_SPEED_1G;
-       if (sa->port.phy_adv_cap_mask & EFX_PHY_CAP_10000FDX)
+       if (sa->port.phy_adv_cap_mask & (1u << EFX_PHY_CAP_10000FDX))
                dev_info->speed_capa |= ETH_LINK_SPEED_10G;
-       if (sa->port.phy_adv_cap_mask & EFX_PHY_CAP_25000FDX)
+       if (sa->port.phy_adv_cap_mask & (1u << EFX_PHY_CAP_25000FDX))
                dev_info->speed_capa |= ETH_LINK_SPEED_25G;
-       if (sa->port.phy_adv_cap_mask & EFX_PHY_CAP_40000FDX)
+       if (sa->port.phy_adv_cap_mask & (1u << EFX_PHY_CAP_40000FDX))
                dev_info->speed_capa |= ETH_LINK_SPEED_40G;
-       if (sa->port.phy_adv_cap_mask & EFX_PHY_CAP_50000FDX)
+       if (sa->port.phy_adv_cap_mask & (1u << EFX_PHY_CAP_50000FDX))
                dev_info->speed_capa |= ETH_LINK_SPEED_50G;
-       if (sa->port.phy_adv_cap_mask & EFX_PHY_CAP_100000FDX)
+       if (sa->port.phy_adv_cap_mask & (1u << EFX_PHY_CAP_100000FDX))
                dev_info->speed_capa |= ETH_LINK_SPEED_100G;
 
        dev_info->max_rx_queues = sa->rxq_max;
@@ -153,21 +161,21 @@ sfc_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
        }
 
        /* Initialize to hardware limits */
-       dev_info->rx_desc_lim.nb_max = EFX_RXQ_MAXNDESCS;
-       dev_info->rx_desc_lim.nb_min = EFX_RXQ_MINNDESCS;
+       dev_info->rx_desc_lim.nb_max = sa->rxq_max_entries;
+       dev_info->rx_desc_lim.nb_min = sa->rxq_min_entries;
        /* The RXQ hardware requires that the descriptor count is a power
         * of 2, but rx_desc_lim cannot properly describe that constraint.
         */
-       dev_info->rx_desc_lim.nb_align = EFX_RXQ_MINNDESCS;
+       dev_info->rx_desc_lim.nb_align = sa->rxq_min_entries;
 
        /* Initialize to hardware limits */
        dev_info->tx_desc_lim.nb_max = sa->txq_max_entries;
-       dev_info->tx_desc_lim.nb_min = EFX_TXQ_MINNDESCS;
+       dev_info->tx_desc_lim.nb_min = sa->txq_min_entries;
        /*
         * The TXQ hardware requires that the descriptor count is a power
         * of 2, but tx_desc_lim cannot properly describe that constraint
         */
-       dev_info->tx_desc_lim.nb_align = EFX_TXQ_MINNDESCS;
+       dev_info->tx_desc_lim.nb_align = sa->txq_min_entries;
 
        if (sap->dp_rx->get_dev_info != NULL)
                sap->dp_rx->get_dev_info(dev_info);
@@ -176,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 *
@@ -331,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)
 {
@@ -345,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);
 
@@ -360,7 +391,7 @@ 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);
@@ -368,30 +399,43 @@ sfc_dev_filter_set(struct rte_eth_dev *dev, enum sfc_dev_filter_mode mode,
        }
 
        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
@@ -605,7 +649,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);
@@ -618,12 +662,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
@@ -861,6 +908,34 @@ fail_inval:
        return -rc;
 }
 
+static int
+sfc_check_scatter_on_all_rx_queues(struct sfc_adapter *sa, size_t pdu)
+{
+       struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
+       const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+       boolean_t scatter_enabled;
+       const char *error;
+       unsigned int i;
+
+       for (i = 0; i < sas->rxq_count; i++) {
+               if ((sas->rxq_info[i].state & SFC_RXQ_INITIALIZED) == 0)
+                       continue;
+
+               scatter_enabled = (sas->rxq_info[i].type_flags &
+                                  EFX_RXQ_FLAG_SCATTER);
+
+               if (!sfc_rx_check_scatter(pdu, sa->rxq_ctrl[i].buf_size,
+                                         encp->enc_rx_prefix_size,
+                                         scatter_enabled, &error)) {
+                       sfc_err(sa, "MTU check for RxQ %u failed: %s", i,
+                               error);
+                       return EINVAL;
+               }
+       }
+
+       return 0;
+}
+
 static int
 sfc_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
 {
@@ -881,12 +956,16 @@ 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;
        }
 
        sfc_adapter_lock(sa);
 
+       rc = sfc_check_scatter_on_all_rx_queues(sa, pdu);
+       if (rc != 0)
+               goto fail_check_scatter;
+
        if (pdu != sa->port.pdu) {
                if (sa->state == SFC_ADAPTER_STARTED) {
                        sfc_stop(sa);
@@ -905,7 +984,7 @@ sfc_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
         * The driver does not use it, but other PMDs update jumbo frame
         * flag and max_rx_pkt_len when MTU is set.
         */
-       if (mtu > ETHER_MAX_LEN) {
+       if (mtu > RTE_ETHER_MAX_LEN) {
                struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
                rxmode->offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME;
        }
@@ -923,6 +1002,8 @@ fail_start:
                sfc_err(sa, "cannot start with neither new (%u) nor old (%u) "
                        "PDU max size - port is stopped",
                        (unsigned int)pdu, (unsigned int)old_pdu);
+
+fail_check_scatter:
        sfc_adapter_unlock(sa);
 
 fail_inval:
@@ -931,12 +1012,12 @@ fail_inval:
        return -rc;
 }
 static int
-sfc_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
+sfc_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr)
 {
        struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
        const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
        struct sfc_port *port = &sa->port;
-       struct ether_addr *old_addr = &dev->data->mac_addrs[0];
+       struct rte_ether_addr *old_addr = &dev->data->mac_addrs[0];
        int rc = 0;
 
        sfc_adapter_lock(sa);
@@ -945,7 +1026,7 @@ sfc_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
         * Copy the address to the device private data so that
         * it could be recalled in the case of adapter restart.
         */
-       ether_addr_copy(mac_addr, &port->default_mac_addr);
+       rte_ether_addr_copy(mac_addr, &port->default_mac_addr);
 
        /*
         * Neither of the two following checks can return
@@ -1005,7 +1086,7 @@ sfc_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
 
 unlock:
        if (rc != 0)
-               ether_addr_copy(old_addr, &port->default_mac_addr);
+               rte_ether_addr_copy(old_addr, &port->default_mac_addr);
 
        sfc_adapter_unlock(sa);
 
@@ -1015,8 +1096,8 @@ unlock:
 
 
 static int
-sfc_set_mc_addr_list(struct rte_eth_dev *dev, struct ether_addr *mc_addr_set,
-                    uint32_t nb_mc_addr)
+sfc_set_mc_addr_list(struct rte_eth_dev *dev,
+               struct rte_ether_addr *mc_addr_set, uint32_t nb_mc_addr)
 {
        struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
        struct sfc_port *port = &sa->port;
@@ -1451,7 +1532,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;
        }
@@ -1675,6 +1756,32 @@ sfc_pool_ops_supported(struct rte_eth_dev *dev, const char *pool)
        return sap->dp_rx->pool_ops_supported(pool);
 }
 
+static int
+sfc_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+       const struct sfc_adapter_priv *sap = sfc_adapter_priv_by_eth_dev(dev);
+       struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev);
+       struct sfc_rxq_info *rxq_info;
+
+       SFC_ASSERT(queue_id < sas->rxq_count);
+       rxq_info = &sas->rxq_info[queue_id];
+
+       return sap->dp_rx->intr_enable(rxq_info->dp);
+}
+
+static int
+sfc_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+       const struct sfc_adapter_priv *sap = sfc_adapter_priv_by_eth_dev(dev);
+       struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev);
+       struct sfc_rxq_info *rxq_info;
+
+       SFC_ASSERT(queue_id < sas->rxq_count);
+       rxq_info = &sas->rxq_info[queue_id];
+
+       return sap->dp_rx->intr_disable(rxq_info->dp);
+}
+
 static const struct eth_dev_ops sfc_eth_dev_ops = {
        .dev_configure                  = sfc_dev_configure,
        .dev_start                      = sfc_dev_start,
@@ -1705,6 +1812,8 @@ static const struct eth_dev_ops sfc_eth_dev_ops = {
        .rx_descriptor_done             = sfc_rx_descriptor_done,
        .rx_descriptor_status           = sfc_rx_descriptor_status,
        .tx_descriptor_status           = sfc_tx_descriptor_status,
+       .rx_queue_intr_enable           = sfc_rx_queue_intr_enable,
+       .rx_queue_intr_disable          = sfc_rx_queue_intr_disable,
        .tx_queue_setup                 = sfc_tx_queue_setup,
        .tx_queue_release               = sfc_tx_queue_release,
        .flow_ctrl_get                  = sfc_flow_ctrl_get,
@@ -1854,6 +1963,7 @@ sfc_eth_dev_set_ops(struct rte_eth_dev *dev)
        sa->priv.dp_tx = dp_tx;
 
        dev->rx_pkt_burst = dp_rx->pkt_burst;
+       dev->tx_pkt_prepare = dp_tx->pkt_prepare;
        dev->tx_pkt_burst = dp_tx->pkt_burst;
 
        dev->dev_ops = &sfc_eth_dev_ops;
@@ -1881,6 +1991,7 @@ sfc_eth_dev_clear_ops(struct rte_eth_dev *dev)
        struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev);
 
        dev->dev_ops = NULL;
+       dev->tx_pkt_prepare = NULL;
        dev->rx_pkt_burst = NULL;
        dev->tx_pkt_burst = NULL;
 
@@ -1961,6 +2072,7 @@ sfc_eth_dev_secondary_init(struct rte_eth_dev *dev, uint32_t logtype_main)
 
        dev->process_private = sap;
        dev->rx_pkt_burst = dp_rx->pkt_burst;
+       dev->tx_pkt_prepare = dp_tx->pkt_prepare;
        dev->tx_pkt_burst = dp_tx->pkt_burst;
        dev->dev_ops = &sfc_eth_dev_secondary_ops;
 
@@ -1982,6 +2094,7 @@ sfc_eth_dev_secondary_clear_ops(struct rte_eth_dev *dev)
        free(dev->process_private);
        dev->process_private = NULL;
        dev->dev_ops = NULL;
+       dev->tx_pkt_prepare = NULL;
        dev->tx_pkt_burst = NULL;
        dev->rx_pkt_burst = NULL;
 }
@@ -2011,7 +2124,7 @@ sfc_eth_dev_init(struct rte_eth_dev *dev)
        struct sfc_adapter *sa;
        int rc;
        const efx_nic_cfg_t *encp;
-       const struct ether_addr *from;
+       const struct rte_ether_addr *from;
 
        sfc_register_dp();
 
@@ -2053,7 +2166,9 @@ sfc_eth_dev_init(struct rte_eth_dev *dev)
 
        sfc_log_init(sa, "entry");
 
-       dev->data->mac_addrs = rte_zmalloc("sfc", ETHER_ADDR_LEN, 0);
+       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;
                goto fail_mac_addrs;
@@ -2083,8 +2198,8 @@ sfc_eth_dev_init(struct rte_eth_dev *dev)
         * The arguments are really reverse order in comparison to
         * Linux kernel. Copy from NIC config to Ethernet device data.
         */
-       from = (const struct ether_addr *)(encp->enc_mac_addr);
-       ether_addr_copy(from, &dev->data->mac_addrs[0]);
+       from = (const struct rte_ether_addr *)(encp->enc_mac_addr);
+       rte_ether_addr_copy(from, &dev->data->mac_addrs[0]);
 
        sfc_adapter_unlock(sa);
 
@@ -2119,35 +2234,12 @@ 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;
        }
 
-       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);
+       sfc_dev_close(dev);
 
        return 0;
 }