X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsfc%2Fsfc.c;h=ac5fdcaa5902e0472fa3d01f6a2de6bb739a4fbf;hb=cebe3d7b3d2066981d9179b52b79966e69e68fd7;hp=ad3dab136e303bdf4ed5c22c8f65ebb06fc61f07;hpb=525973967757b67497ba0cc5b03528062d7f6f82;p=dpdk.git diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c index ad3dab136e..ac5fdcaa59 100644 --- a/drivers/net/sfc/sfc.c +++ b/drivers/net/sfc/sfc.c @@ -1,38 +1,17 @@ -/*- - * BSD LICENSE +/* SPDX-License-Identifier: BSD-3-Clause * - * Copyright (c) 2016-2017 Solarflare Communications Inc. + * Copyright (c) 2016-2018 Solarflare Communications Inc. * All rights reserved. * * This software was jointly developed between OKTET Labs (under contract * for Solarflare) and Solarflare Communications, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. 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. - * - * 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. */ /* sysconf() */ #include #include +#include #include "efx.h" @@ -61,8 +40,8 @@ sfc_dma_alloc(const struct sfc_adapter *sa, const char *name, uint16_t id, return ENOMEM; } - esmp->esm_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr); - if (esmp->esm_addr == RTE_BAD_PHYS_ADDR) { + esmp->esm_addr = mz->iova; + if (esmp->esm_addr == RTE_BAD_IOVA) { (void)rte_memzone_free(mz); return EFAULT; } @@ -270,27 +249,16 @@ sfc_set_drv_limits(struct sfc_adapter *sa) return efx_nic_set_drv_limits(sa->nic, &lim); } -int -sfc_start(struct sfc_adapter *sa) +static int +sfc_try_start(struct sfc_adapter *sa) { + const efx_nic_cfg_t *encp; int rc; sfc_log_init(sa, "entry"); SFC_ASSERT(sfc_adapter_is_locked(sa)); - - switch (sa->state) { - case SFC_ADAPTER_CONFIGURED: - break; - case SFC_ADAPTER_STARTED: - sfc_info(sa, "already started"); - return 0; - default: - rc = EINVAL; - goto fail_bad_state; - } - - sa->state = SFC_ADAPTER_STARTING; + SFC_ASSERT(sa->state == SFC_ADAPTER_STARTING); sfc_log_init(sa, "set resource limits"); rc = sfc_set_drv_limits(sa); @@ -302,6 +270,14 @@ sfc_start(struct sfc_adapter *sa) if (rc != 0) goto fail_nic_init; + encp = efx_nic_cfg_get(sa->nic); + if (encp->enc_tunnel_encapsulations_supported != 0) { + sfc_log_init(sa, "apply tunnel config"); + rc = efx_tunnel_reconfigure(sa->nic); + if (rc != 0) + goto fail_tunnel_reconfigure; + } + rc = sfc_intr_start(sa); if (rc != 0) goto fail_intr_start; @@ -326,7 +302,6 @@ sfc_start(struct sfc_adapter *sa) if (rc != 0) goto fail_flows_insert; - sa->state = SFC_ADAPTER_STARTED; sfc_log_init(sa, "done"); return 0; @@ -346,10 +321,51 @@ fail_ev_start: sfc_intr_stop(sa); fail_intr_start: +fail_tunnel_reconfigure: efx_nic_fini(sa->nic); fail_nic_init: fail_set_drv_limits: + sfc_log_init(sa, "failed %d", rc); + return rc; +} + +int +sfc_start(struct sfc_adapter *sa) +{ + unsigned int start_tries = 3; + int rc; + + sfc_log_init(sa, "entry"); + + SFC_ASSERT(sfc_adapter_is_locked(sa)); + + switch (sa->state) { + case SFC_ADAPTER_CONFIGURED: + break; + case SFC_ADAPTER_STARTED: + sfc_info(sa, "already started"); + return 0; + default: + rc = EINVAL; + goto fail_bad_state; + } + + sa->state = SFC_ADAPTER_STARTING; + + do { + rc = sfc_try_start(sa); + } while ((--start_tries > 0) && + (rc == EIO || rc == EAGAIN || rc == ENOENT || rc == EINVAL)); + + if (rc != 0) + goto fail_try_start; + + sa->state = SFC_ADAPTER_STARTED; + sfc_log_init(sa, "done"); + return 0; + +fail_try_start: sa->state = SFC_ADAPTER_CONFIGURED; fail_bad_state: sfc_log_init(sa, "failed %d", rc); @@ -389,6 +405,58 @@ sfc_stop(struct sfc_adapter *sa) sfc_log_init(sa, "done"); } +static int +sfc_restart(struct sfc_adapter *sa) +{ + int rc; + + SFC_ASSERT(sfc_adapter_is_locked(sa)); + + if (sa->state != SFC_ADAPTER_STARTED) + return EINVAL; + + sfc_stop(sa); + + rc = sfc_start(sa); + if (rc != 0) + sfc_err(sa, "restart failed"); + + return rc; +} + +static void +sfc_restart_if_required(void *arg) +{ + struct sfc_adapter *sa = arg; + + /* If restart is scheduled, clear the flag and do it */ + if (rte_atomic32_cmpset((volatile uint32_t *)&sa->restart_required, + 1, 0)) { + sfc_adapter_lock(sa); + if (sa->state == SFC_ADAPTER_STARTED) + (void)sfc_restart(sa); + sfc_adapter_unlock(sa); + } +} + +void +sfc_schedule_restart(struct sfc_adapter *sa) +{ + int rc; + + /* Schedule restart alarm if it is not scheduled yet */ + if (!rte_atomic32_test_and_set(&sa->restart_required)) + return; + + rc = rte_eal_alarm_set(1, sfc_restart_if_required, sa); + if (rc == -ENOTSUP) + sfc_warn(sa, "alarms are not supported, restart is pending"); + else if (rc != 0) + sfc_err(sa, "cannot arm restart alarm (rc=%d)", rc); + else + sfc_info(sa, "restart scheduled"); +} + int sfc_configure(struct sfc_adapter *sa) { @@ -398,7 +466,8 @@ sfc_configure(struct sfc_adapter *sa) SFC_ASSERT(sfc_adapter_is_locked(sa)); - SFC_ASSERT(sa->state == SFC_ADAPTER_INITIALIZED); + SFC_ASSERT(sa->state == SFC_ADAPTER_INITIALIZED || + sa->state == SFC_ADAPTER_CONFIGURED); sa->state = SFC_ADAPTER_CONFIGURING; rc = sfc_check_conf(sa); @@ -409,36 +478,29 @@ sfc_configure(struct sfc_adapter *sa) if (rc != 0) goto fail_intr_configure; - rc = sfc_ev_init(sa); + rc = sfc_port_configure(sa); if (rc != 0) - goto fail_ev_init; + goto fail_port_configure; - rc = sfc_port_init(sa); + rc = sfc_rx_configure(sa); if (rc != 0) - goto fail_port_init; + goto fail_rx_configure; - rc = sfc_rx_init(sa); + rc = sfc_tx_configure(sa); if (rc != 0) - goto fail_rx_init; - - rc = sfc_tx_init(sa); - if (rc != 0) - goto fail_tx_init; + goto fail_tx_configure; sa->state = SFC_ADAPTER_CONFIGURED; sfc_log_init(sa, "done"); return 0; -fail_tx_init: - sfc_rx_fini(sa); - -fail_rx_init: - sfc_port_fini(sa); +fail_tx_configure: + sfc_rx_close(sa); -fail_port_init: - sfc_ev_fini(sa); +fail_rx_configure: + sfc_port_close(sa); -fail_ev_init: +fail_port_configure: sfc_intr_close(sa); fail_intr_configure: @@ -458,10 +520,9 @@ sfc_close(struct sfc_adapter *sa) SFC_ASSERT(sa->state == SFC_ADAPTER_CONFIGURED); sa->state = SFC_ADAPTER_CLOSING; - sfc_tx_fini(sa); - sfc_rx_fini(sa); - sfc_port_fini(sa); - sfc_ev_fini(sa); + sfc_tx_close(sa); + sfc_rx_close(sa); + sfc_port_close(sa); sfc_intr_close(sa); sa->state = SFC_ADAPTER_INITIALIZED; @@ -472,7 +533,7 @@ static int sfc_mem_bar_init(struct sfc_adapter *sa) { struct rte_eth_dev *eth_dev = sa->eth_dev; - struct rte_pci_device *pci_dev = SFC_DEV_TO_PCI(eth_dev); + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); efsys_bar_t *ebp = &sa->mem_bar; unsigned int i; struct rte_mem_resource *res; @@ -508,7 +569,7 @@ sfc_mem_bar_fini(struct sfc_adapter *sa) * and also known to give a uniform distribution * (a good distribution of traffic between different CPUs) */ -static const uint8_t default_rss_key[SFC_RSS_KEY_SIZE] = { +static const uint8_t default_rss_key[EFX_RSS_KEY_SIZE] = { 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, @@ -517,10 +578,10 @@ static const uint8_t default_rss_key[SFC_RSS_KEY_SIZE] = { }; #endif +#if EFSYS_OPT_RX_SCALE static int sfc_set_rss_defaults(struct sfc_adapter *sa) { -#if EFSYS_OPT_RX_SCALE int rc; rc = efx_intr_init(sa->nic, sa->intr.type, NULL); @@ -535,11 +596,11 @@ sfc_set_rss_defaults(struct sfc_adapter *sa) if (rc != 0) goto fail_rx_init; - rc = efx_rx_scale_support_get(sa->nic, &sa->rss_support); + rc = efx_rx_scale_default_support_get(sa->nic, &sa->rss_support); if (rc != 0) goto fail_scale_support_get; - rc = efx_rx_hash_support_get(sa->nic, &sa->hash_support); + rc = efx_rx_hash_default_support_get(sa->nic, &sa->hash_support); if (rc != 0) goto fail_hash_support_get; @@ -563,10 +624,14 @@ fail_ev_init: fail_intr_init: return rc; +} #else +static int +sfc_set_rss_defaults(__rte_unused struct sfc_adapter *sa) +{ return 0; -#endif } +#endif int sfc_attach(struct sfc_adapter *sa) @@ -586,6 +651,16 @@ sfc_attach(struct sfc_adapter *sa) if (rc != 0) goto fail_nic_reset; + /* + * Probed NIC is sufficient for tunnel init. + * Initialize tunnel support to be able to use libefx + * efx_tunnel_config_udp_{add,remove}() in any state and + * efx_tunnel_reconfigure() on start up. + */ + rc = efx_tunnel_init(enp); + if (rc != 0) + goto fail_tunnel_init; + encp = efx_nic_cfg_get(sa->nic); if (sa->dp_tx->features & SFC_DP_TX_FEAT_TSO) { @@ -607,8 +682,13 @@ sfc_attach(struct sfc_adapter *sa) if (rc != 0) goto fail_intr_attach; - efx_phy_adv_cap_get(sa->nic, EFX_PHY_CAP_PERM, - &sa->port.phy_adv_cap_mask); + rc = sfc_ev_attach(sa); + if (rc != 0) + goto fail_ev_attach; + + rc = sfc_port_attach(sa); + if (rc != 0) + goto fail_port_attach; rc = sfc_set_rss_defaults(sa); if (rc != 0) @@ -630,12 +710,21 @@ sfc_attach(struct sfc_adapter *sa) fail_filter_attach: fail_set_rss_defaults: + sfc_port_detach(sa); + +fail_port_attach: + sfc_ev_detach(sa); + +fail_ev_attach: sfc_intr_detach(sa); fail_intr_attach: efx_nic_fini(sa->nic); fail_estimate_rsrc_limits: +fail_tunnel_init: + efx_tunnel_fini(sa->nic); + fail_nic_reset: sfc_log_init(sa, "failed %d", rc); @@ -652,8 +741,10 @@ sfc_detach(struct sfc_adapter *sa) sfc_flow_fini(sa); sfc_filter_detach(sa); - + sfc_port_detach(sa); + sfc_ev_detach(sa); sfc_intr_detach(sa); + efx_tunnel_fini(sa->nic); sa->state = SFC_ADAPTER_UNINITIALIZED; } @@ -661,7 +752,7 @@ sfc_detach(struct sfc_adapter *sa) int sfc_probe(struct sfc_adapter *sa) { - struct rte_pci_device *pci_dev = SFC_DEV_TO_PCI(sa->eth_dev); + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(sa->eth_dev); efx_nic_t *enp; int rc; @@ -670,6 +761,7 @@ sfc_probe(struct sfc_adapter *sa) SFC_ASSERT(sfc_adapter_is_locked(sa)); sa->socket_id = rte_socket_id(); + rte_atomic32_init(&sa->restart_required); sfc_log_init(sa, "init mem bar"); rc = sfc_mem_bar_init(sa); @@ -734,6 +826,14 @@ sfc_unprobe(struct sfc_adapter *sa) sfc_mcdi_fini(sa); + /* + * Make sure there is no pending alarm to restart since we are + * going to free device private which is passed as the callback + * opaque data. A new alarm cannot be scheduled since MCDI is + * shut down. + */ + rte_eal_alarm_cancel(sfc_restart_if_required, sa); + sfc_log_init(sa, "destroy nic"); sa->nic = NULL; efx_nic_destroy(enp);