X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsfc%2Fsfc.c;h=cc81fd9988c6aebc33cbe28798e7c3648ce324cf;hb=24c14430cdc4556a30a1e608f67230e881718f7f;hp=8d18def2d14d874b73a958af8bfbcab09f469cd6;hpb=06bc197796e233bacb0d90cc8a56ebd4165077e3;p=dpdk.git diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c index 8d18def2d1..cc81fd9988 100644 --- a/drivers/net/sfc/sfc.c +++ b/drivers/net/sfc/sfc.c @@ -1,5 +1,7 @@ /*- - * Copyright (c) 2016 Solarflare Communications Inc. + * BSD LICENSE + * + * Copyright (c) 2016-2017 Solarflare Communications Inc. * All rights reserved. * * This software was jointly developed between OKTET Labs (under contract @@ -36,6 +38,9 @@ #include "sfc.h" #include "sfc_log.h" +#include "sfc_ev.h" +#include "sfc_rx.h" +#include "sfc_tx.h" int @@ -82,6 +87,33 @@ sfc_dma_free(const struct sfc_adapter *sa, efsys_mem_t *esmp) memset(esmp, 0, sizeof(*esmp)); } +static uint32_t +sfc_phy_cap_from_link_speeds(uint32_t speeds) +{ + uint32_t phy_caps = 0; + + if (~speeds & ETH_LINK_SPEED_FIXED) { + phy_caps |= (1 << EFX_PHY_CAP_AN); + /* + * If no speeds are specified in the mask, any supported + * may be negotiated + */ + if (speeds == ETH_LINK_SPEED_AUTONEG) + phy_caps |= + (1 << EFX_PHY_CAP_1000FDX) | + (1 << EFX_PHY_CAP_10000FDX) | + (1 << EFX_PHY_CAP_40000FDX); + } + if (speeds & ETH_LINK_SPEED_1G) + phy_caps |= (1 << EFX_PHY_CAP_1000FDX); + if (speeds & ETH_LINK_SPEED_10G) + phy_caps |= (1 << EFX_PHY_CAP_10000FDX); + if (speeds & ETH_LINK_SPEED_40G) + phy_caps |= (1 << EFX_PHY_CAP_40000FDX); + + return phy_caps; +} + /* * Check requested device level configuration. * Receive and transmit configuration is checked in corresponding @@ -93,8 +125,12 @@ sfc_check_conf(struct sfc_adapter *sa) const struct rte_eth_conf *conf = &sa->eth_dev->data->dev_conf; int rc = 0; - if (conf->link_speeds != ETH_LINK_SPEED_AUTONEG) { - sfc_err(sa, "Manual link speed/duplex choice not supported"); + sa->port.phy_adv_cap = + sfc_phy_cap_from_link_speeds(conf->link_speeds) & + sa->port.phy_adv_cap_mask; + if ((sa->port.phy_adv_cap & ~(1 << EFX_PHY_CAP_AN)) == 0) { + sfc_err(sa, "No link speeds from mask %#x are supported", + conf->link_speeds); rc = EINVAL; } @@ -113,7 +149,9 @@ sfc_check_conf(struct sfc_adapter *sa) rc = EINVAL; } - if (conf->intr_conf.lsc != 0) { + if ((conf->intr_conf.lsc != 0) && + (sa->intr.type != EFX_INTR_LINE) && + (sa->intr.type != EFX_INTR_MESSAGE)) { sfc_err(sa, "Link status change interrupt not supported"); rc = EINVAL; } @@ -167,6 +205,13 @@ sfc_estimate_resource_limits(struct sfc_adapter *sa) limits.edl_max_txq_count = MIN(encp->enc_txq_limit, limits.edl_max_evq_count - 1 - limits.edl_max_rxq_count); + + if (sa->tso) + limits.edl_max_txq_count = + MIN(limits.edl_max_txq_count, + encp->enc_fw_assisted_tso_v2_n_contexts / + encp->enc_hw_pf_count); + SFC_ASSERT(limits.edl_max_txq_count >= limits.edl_min_rxq_count); /* Configure the minimum required resources needed for the @@ -261,10 +306,45 @@ sfc_start(struct sfc_adapter *sa) if (rc != 0) goto fail_intr_start; + rc = sfc_ev_start(sa); + if (rc != 0) + goto fail_ev_start; + + rc = sfc_port_start(sa); + if (rc != 0) + goto fail_port_start; + + rc = sfc_rx_start(sa); + if (rc != 0) + goto fail_rx_start; + + rc = sfc_tx_start(sa); + if (rc != 0) + goto fail_tx_start; + + rc = sfc_flow_start(sa); + if (rc != 0) + goto fail_flows_insert; + sa->state = SFC_ADAPTER_STARTED; sfc_log_init(sa, "done"); return 0; +fail_flows_insert: + sfc_tx_stop(sa); + +fail_tx_start: + sfc_rx_stop(sa); + +fail_rx_start: + sfc_port_stop(sa); + +fail_port_start: + sfc_ev_stop(sa); + +fail_ev_start: + sfc_intr_stop(sa); + fail_intr_start: efx_nic_fini(sa->nic); @@ -297,6 +377,11 @@ sfc_stop(struct sfc_adapter *sa) sa->state = SFC_ADAPTER_STOPPING; + sfc_flow_stop(sa); + sfc_tx_stop(sa); + sfc_rx_stop(sa); + sfc_port_stop(sa); + sfc_ev_stop(sa); sfc_intr_stop(sa); efx_nic_fini(sa->nic); @@ -313,22 +398,44 @@ 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); if (rc != 0) goto fail_check_conf; - rc = sfc_intr_init(sa); + rc = sfc_intr_configure(sa); if (rc != 0) - goto fail_intr_init; + goto fail_intr_configure; + + rc = sfc_port_configure(sa); + if (rc != 0) + goto fail_port_configure; + + rc = sfc_rx_configure(sa); + if (rc != 0) + goto fail_rx_configure; + + rc = sfc_tx_configure(sa); + if (rc != 0) + goto fail_tx_configure; sa->state = SFC_ADAPTER_CONFIGURED; sfc_log_init(sa, "done"); return 0; -fail_intr_init: +fail_tx_configure: + sfc_rx_close(sa); + +fail_rx_configure: + sfc_port_close(sa); + +fail_port_configure: + sfc_intr_close(sa); + +fail_intr_configure: fail_check_conf: sa->state = SFC_ADAPTER_INITIALIZED; sfc_log_init(sa, "failed %d", rc); @@ -345,7 +452,10 @@ sfc_close(struct sfc_adapter *sa) SFC_ASSERT(sa->state == SFC_ADAPTER_CONFIGURED); sa->state = SFC_ADAPTER_CLOSING; - sfc_intr_fini(sa); + sfc_tx_close(sa); + sfc_rx_close(sa); + sfc_port_close(sa); + sfc_intr_close(sa); sa->state = SFC_ADAPTER_INITIALIZED; sfc_log_init(sa, "done"); @@ -355,7 +465,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; @@ -384,10 +494,183 @@ sfc_mem_bar_fini(struct sfc_adapter *sa) memset(ebp, 0, sizeof(*ebp)); } +#if EFSYS_OPT_RX_SCALE +/* + * A fixed RSS key which has a property of being symmetric + * (symmetrical flows are distributed to the same CPU) + * and also known to give a uniform distribution + * (a good distribution of traffic between different CPUs) + */ +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, + 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, + 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, +}; +#endif + +#if EFSYS_OPT_RX_SCALE +static int +sfc_set_rss_defaults(struct sfc_adapter *sa) +{ + int rc; + + rc = efx_intr_init(sa->nic, sa->intr.type, NULL); + if (rc != 0) + goto fail_intr_init; + + rc = efx_ev_init(sa->nic); + if (rc != 0) + goto fail_ev_init; + + rc = efx_rx_init(sa->nic); + if (rc != 0) + goto fail_rx_init; + + rc = efx_rx_scale_default_support_get(sa->nic, &sa->rss_support); + if (rc != 0) + goto fail_scale_support_get; + + rc = efx_rx_hash_default_support_get(sa->nic, &sa->hash_support); + if (rc != 0) + goto fail_hash_support_get; + + efx_rx_fini(sa->nic); + efx_ev_fini(sa->nic); + efx_intr_fini(sa->nic); + + sa->rss_hash_types = sfc_rte_to_efx_hash_type(SFC_RSS_OFFLOADS); + + rte_memcpy(sa->rss_key, default_rss_key, sizeof(sa->rss_key)); + + return 0; + +fail_hash_support_get: +fail_scale_support_get: +fail_rx_init: + efx_ev_fini(sa->nic); + +fail_ev_init: + efx_intr_fini(sa->nic); + +fail_intr_init: + return rc; +} +#else +static int +sfc_set_rss_defaults(__rte_unused struct sfc_adapter *sa) +{ + return 0; +} +#endif + int sfc_attach(struct sfc_adapter *sa) { - struct rte_pci_device *pci_dev = SFC_DEV_TO_PCI(sa->eth_dev); + const efx_nic_cfg_t *encp; + efx_nic_t *enp = sa->nic; + int rc; + + sfc_log_init(sa, "entry"); + + SFC_ASSERT(sfc_adapter_is_locked(sa)); + + efx_mcdi_new_epoch(enp); + + sfc_log_init(sa, "reset nic"); + rc = efx_nic_reset(enp); + if (rc != 0) + goto fail_nic_reset; + + encp = efx_nic_cfg_get(sa->nic); + + if (sa->dp_tx->features & SFC_DP_TX_FEAT_TSO) { + sa->tso = encp->enc_fw_assisted_tso_v2_enabled; + if (!sa->tso) + sfc_warn(sa, + "TSO support isn't available on this adapter"); + } + + sfc_log_init(sa, "estimate resource limits"); + rc = sfc_estimate_resource_limits(sa); + if (rc != 0) + goto fail_estimate_rsrc_limits; + + sa->txq_max_entries = encp->enc_txq_max_ndescs; + SFC_ASSERT(rte_is_power_of_2(sa->txq_max_entries)); + + rc = sfc_intr_attach(sa); + if (rc != 0) + goto fail_intr_attach; + + 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) + goto fail_set_rss_defaults; + + rc = sfc_filter_attach(sa); + if (rc != 0) + goto fail_filter_attach; + + sfc_log_init(sa, "fini nic"); + efx_nic_fini(enp); + + sfc_flow_init(sa); + + sa->state = SFC_ADAPTER_INITIALIZED; + + sfc_log_init(sa, "done"); + return 0; + +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_nic_reset: + + sfc_log_init(sa, "failed %d", rc); + return rc; +} + +void +sfc_detach(struct sfc_adapter *sa) +{ + sfc_log_init(sa, "entry"); + + SFC_ASSERT(sfc_adapter_is_locked(sa)); + + sfc_flow_fini(sa); + + sfc_filter_detach(sa); + sfc_port_detach(sa); + sfc_ev_detach(sa); + sfc_intr_detach(sa); + + sa->state = SFC_ADAPTER_UNINITIALIZED; +} + +int +sfc_probe(struct sfc_adapter *sa) +{ + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(sa->eth_dev); efx_nic_t *enp; int rc; @@ -426,36 +709,9 @@ sfc_attach(struct sfc_adapter *sa) if (rc != 0) goto fail_nic_probe; - efx_mcdi_new_epoch(enp); - - sfc_log_init(sa, "reset nic"); - rc = efx_nic_reset(enp); - if (rc != 0) - goto fail_nic_reset; - - sfc_log_init(sa, "estimate resource limits"); - rc = sfc_estimate_resource_limits(sa); - if (rc != 0) - goto fail_estimate_rsrc_limits; - - rc = sfc_intr_attach(sa); - if (rc != 0) - goto fail_intr_attach; - - sfc_log_init(sa, "fini nic"); - efx_nic_fini(enp); - - sa->state = SFC_ADAPTER_INITIALIZED; - sfc_log_init(sa, "done"); return 0; -fail_intr_attach: -fail_estimate_rsrc_limits: -fail_nic_reset: - sfc_log_init(sa, "unprobe nic"); - efx_nic_unprobe(enp); - fail_nic_probe: sfc_mcdi_fini(sa); @@ -474,7 +730,7 @@ fail_mem_bar_init: } void -sfc_detach(struct sfc_adapter *sa) +sfc_unprobe(struct sfc_adapter *sa) { efx_nic_t *enp = sa->nic; @@ -482,8 +738,6 @@ sfc_detach(struct sfc_adapter *sa) SFC_ASSERT(sfc_adapter_is_locked(sa)); - sfc_intr_detach(sa); - sfc_log_init(sa, "unprobe nic"); efx_nic_unprobe(enp); @@ -495,5 +749,6 @@ sfc_detach(struct sfc_adapter *sa) sfc_mem_bar_fini(sa); + sfc_flow_fini(sa); sa->state = SFC_ADAPTER_UNINITIALIZED; }