X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fnet%2Fsfc%2Fsfc_ethdev.c;h=acee3e48e4b13e0b952b621e7373440723125114;hb=d0131e49c7fca45f4111eedab71f6dbd73bacd61;hp=dd9897d7018e43d2b35bd3799f67afa693f112af;hpb=538da7a1cad25fbdffe298c8ca76fc4dbd262d1b;p=dpdk.git diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c index dd9897d701..acee3e48e4 100644 --- a/drivers/net/sfc/sfc_ethdev.c +++ b/drivers/net/sfc/sfc_ethdev.c @@ -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); @@ -93,7 +97,7 @@ 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 = ETHER_MIN_MTU; + 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; @@ -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; } @@ -941,7 +992,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; } @@ -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; } @@ -1713,6 +1767,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, @@ -1743,6 +1823,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, @@ -2095,7 +2177,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; @@ -2161,35 +2245,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; }