/* 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.
#include "sfc_rx.h"
#include "sfc_tx.h"
#include "sfc_kvargs.h"
+#include "sfc_tweak.h"
int
{
const struct rte_memzone *mz;
- sfc_log_init(sa, "name=%s id=%u len=%lu socket_id=%d",
+ sfc_log_init(sa, "name=%s id=%u len=%zu socket_id=%d",
name, id, len, socket_id);
mz = rte_eth_dma_zone_reserve(sa->eth_dev, name, id, len,
rc = EINVAL;
}
+#if !EFSYS_OPT_LOOPBACK
if (conf->lpbk_mode != 0) {
sfc_err(sa, "Loopback not supported");
rc = EINVAL;
}
+#endif
if (conf->dcb_capability_en != 0) {
sfc_err(sa, "Priority-based flow control not supported");
rc = EINVAL;
}
- if (conf->intr_conf.rxq != 0) {
+ if (conf->intr_conf.rxq != 0 &&
+ (sa->priv.dp_rx->features & SFC_DP_RX_FEAT_INTR) == 0) {
sfc_err(sa, "Receive queue interrupt not supported");
rc = EINVAL;
}
return 0;
fail_get_vi_pool:
-fail_nic_init:
efx_nic_fini(sa->nic);
+fail_nic_init:
return rc;
}
return efx_nic_set_drv_limits(sa->nic, &lim);
}
+static int
+sfc_set_fw_subvariant(struct sfc_adapter *sa)
+{
+ struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
+ const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+ uint64_t tx_offloads = sa->eth_dev->data->dev_conf.txmode.offloads;
+ unsigned int txq_index;
+ efx_nic_fw_subvariant_t req_fw_subvariant;
+ efx_nic_fw_subvariant_t cur_fw_subvariant;
+ int rc;
+
+ if (!encp->enc_fw_subvariant_no_tx_csum_supported) {
+ sfc_info(sa, "no-Tx-checksum subvariant not supported");
+ return 0;
+ }
+
+ for (txq_index = 0; txq_index < sas->txq_count; ++txq_index) {
+ struct sfc_txq_info *txq_info = &sas->txq_info[txq_index];
+
+ if (txq_info->state & SFC_TXQ_INITIALIZED)
+ tx_offloads |= txq_info->offloads;
+ }
+
+ if (tx_offloads & (DEV_TX_OFFLOAD_IPV4_CKSUM |
+ DEV_TX_OFFLOAD_TCP_CKSUM |
+ DEV_TX_OFFLOAD_UDP_CKSUM |
+ DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM))
+ req_fw_subvariant = EFX_NIC_FW_SUBVARIANT_DEFAULT;
+ else
+ req_fw_subvariant = EFX_NIC_FW_SUBVARIANT_NO_TX_CSUM;
+
+ rc = efx_nic_get_fw_subvariant(sa->nic, &cur_fw_subvariant);
+ if (rc != 0) {
+ sfc_err(sa, "failed to get FW subvariant: %d", rc);
+ return rc;
+ }
+ sfc_info(sa, "FW subvariant is %u vs required %u",
+ cur_fw_subvariant, req_fw_subvariant);
+
+ if (cur_fw_subvariant == req_fw_subvariant)
+ return 0;
+
+ rc = efx_nic_set_fw_subvariant(sa->nic, req_fw_subvariant);
+ if (rc != 0) {
+ sfc_err(sa, "failed to set FW subvariant %u: %d",
+ req_fw_subvariant, rc);
+ return rc;
+ }
+ sfc_info(sa, "FW subvariant set to %u", req_fw_subvariant);
+
+ return 0;
+}
+
static int
sfc_try_start(struct sfc_adapter *sa)
{
SFC_ASSERT(sfc_adapter_is_locked(sa));
SFC_ASSERT(sa->state == SFC_ADAPTER_STARTING);
+ sfc_log_init(sa, "set FW subvariant");
+ rc = sfc_set_fw_subvariant(sa);
+ if (rc != 0)
+ goto fail_set_fw_subvariant;
+
sfc_log_init(sa, "set resource limits");
rc = sfc_set_drv_limits(sa);
if (rc != 0)
goto fail_nic_init;
encp = efx_nic_cfg_get(sa->nic);
+
+ /*
+ * Refresh (since it may change on NIC reset/restart) a copy of
+ * supported tunnel encapsulations in shared memory to be used
+ * on supported Rx packet type classes get.
+ */
+ sa->priv.shared->tunnel_encaps =
+ encp->enc_tunnel_encapsulations_supported;
+
if (encp->enc_tunnel_encapsulations_supported != 0) {
sfc_log_init(sa, "apply tunnel config");
rc = efx_tunnel_reconfigure(sa->nic);
fail_nic_init:
fail_set_drv_limits:
+fail_set_fw_subvariant:
sfc_log_init(sa, "failed %d", rc);
return rc;
}
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)
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)
+sfc_rss_attach(struct sfc_adapter *sa)
{
+ struct sfc_rss *rss = &sfc_sa2shared(sa)->rss;
int rc;
rc = efx_intr_init(sa->nic, sa->intr.type, NULL);
if (rc != 0)
goto fail_rx_init;
- rc = efx_rx_scale_default_support_get(sa->nic, &sa->rss_support);
+ rc = efx_rx_scale_default_support_get(sa->nic, &rss->context_type);
if (rc != 0)
goto fail_scale_support_get;
- rc = efx_rx_hash_default_support_get(sa->nic, &sa->hash_support);
+ rc = efx_rx_hash_default_support_get(sa->nic, &rss->hash_support);
if (rc != 0)
goto fail_hash_support_get;
+ rc = sfc_rx_hash_init(sa);
+ if (rc != 0)
+ goto fail_rx_hash_init;
+
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));
+ rte_memcpy(rss->key, default_rss_key, sizeof(rss->key));
return 0;
+fail_rx_hash_init:
fail_hash_support_get:
fail_scale_support_get:
+ efx_rx_fini(sa->nic);
+
fail_rx_init:
efx_ev_fini(sa->nic);
fail_intr_init:
return rc;
}
-#else
-static int
-sfc_set_rss_defaults(__rte_unused struct sfc_adapter *sa)
+
+static void
+sfc_rss_detach(struct sfc_adapter *sa)
{
- return 0;
+ sfc_rx_hash_fini(sa);
}
-#endif
int
sfc_attach(struct sfc_adapter *sa)
encp = efx_nic_cfg_get(sa->nic);
- if (sa->dp_tx->features & SFC_DP_TX_FEAT_TSO) {
+ /*
+ * Make a copy of supported tunnel encapsulations in shared
+ * memory to be used on supported Rx packet type classes get.
+ */
+ sa->priv.shared->tunnel_encaps =
+ encp->enc_tunnel_encapsulations_supported;
+
+ if (sfc_dp_tx_offload_capa(sa->priv.dp_tx) & DEV_TX_OFFLOAD_TCP_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_info(sa, "TSO support isn't available on this adapter");
+ }
+
+ if (sa->tso &&
+ (sfc_dp_tx_offload_capa(sa->priv.dp_tx) &
+ (DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
+ DEV_TX_OFFLOAD_GENEVE_TNL_TSO)) != 0) {
+ sa->tso_encap = encp->enc_fw_assisted_tso_v2_encap_enabled;
+ if (!sa->tso_encap)
+ sfc_info(sa, "Encapsulated TSO support isn't available on this adapter");
}
sfc_log_init(sa, "estimate resource limits");
if (rc != 0)
goto fail_estimate_rsrc_limits;
+ sa->evq_max_entries = encp->enc_evq_max_nevs;
+ SFC_ASSERT(rte_is_power_of_2(sa->evq_max_entries));
+
+ sa->evq_min_entries = encp->enc_evq_min_nevs;
+ SFC_ASSERT(rte_is_power_of_2(sa->evq_min_entries));
+
+ sa->rxq_max_entries = encp->enc_rxq_max_ndescs;
+ SFC_ASSERT(rte_is_power_of_2(sa->rxq_max_entries));
+
+ sa->rxq_min_entries = encp->enc_rxq_min_ndescs;
+ SFC_ASSERT(rte_is_power_of_2(sa->rxq_min_entries));
+
sa->txq_max_entries = encp->enc_txq_max_ndescs;
SFC_ASSERT(rte_is_power_of_2(sa->txq_max_entries));
+ sa->txq_min_entries = encp->enc_txq_min_ndescs;
+ SFC_ASSERT(rte_is_power_of_2(sa->txq_min_entries));
+
rc = sfc_intr_attach(sa);
if (rc != 0)
goto fail_intr_attach;
if (rc != 0)
goto fail_port_attach;
- rc = sfc_set_rss_defaults(sa);
+ rc = sfc_rss_attach(sa);
if (rc != 0)
- goto fail_set_rss_defaults;
+ goto fail_rss_attach;
rc = sfc_filter_attach(sa);
if (rc != 0)
return 0;
fail_filter_attach:
-fail_set_rss_defaults:
+ sfc_rss_detach(sa);
+
+fail_rss_attach:
sfc_port_detach(sa);
fail_port_attach:
sfc_flow_fini(sa);
sfc_filter_detach(sa);
+ sfc_rss_detach(sa);
sfc_port_detach(sa);
sfc_ev_detach(sa);
sfc_intr_detach(sa);
*value = EFX_FW_VARIANT_LOW_LATENCY;
else if (strcasecmp(value_str, SFC_KVARG_FW_VARIANT_PACKED_STREAM) == 0)
*value = EFX_FW_VARIANT_PACKED_STREAM;
+ else if (strcasecmp(value_str, SFC_KVARG_FW_VARIANT_DPDK) == 0)
+ *value = EFX_FW_VARIANT_DPDK;
else
return -EINVAL;
*efv = EFX_FW_VARIANT_PACKED_STREAM;
break;
+ case EFX_RXDP_DPDK_FW_ID:
+ *efv = EFX_FW_VARIANT_DPDK;
+ break;
+
default:
/*
* Other firmware variants are not considered, since they are
return SFC_KVARG_FW_VARIANT_LOW_LATENCY;
case EFX_RXDP_PACKED_STREAM_FW_ID:
return SFC_KVARG_FW_VARIANT_PACKED_STREAM;
+ case EFX_RXDP_DPDK_FW_ID:
+ return SFC_KVARG_FW_VARIANT_DPDK;
default:
return "unknown";
}
}
+static int
+sfc_kvarg_rxd_wait_timeout_ns(struct sfc_adapter *sa)
+{
+ int rc;
+ long value;
+
+ value = SFC_RXD_WAIT_TIMEOUT_NS_DEF;
+
+ rc = sfc_kvargs_process(sa, SFC_KVARG_RXD_WAIT_TIMEOUT_NS,
+ sfc_kvarg_long_handler, &value);
+ if (rc != 0)
+ return rc;
+
+ if (value < 0 ||
+ (unsigned long)value > EFX_RXQ_ES_SUPER_BUFFER_HOL_BLOCK_MAX) {
+ sfc_err(sa, "wrong '" SFC_KVARG_RXD_WAIT_TIMEOUT_NS "' "
+ "was set (%ld);", value);
+ sfc_err(sa, "it must not be less than 0 or greater than %u",
+ EFX_RXQ_ES_SUPER_BUFFER_HOL_BLOCK_MAX);
+ return EINVAL;
+ }
+
+ sa->rxd_wait_timeout_ns = value;
+ return 0;
+}
+
static int
sfc_nic_probe(struct sfc_adapter *sa)
{
return rc;
}
+ rc = sfc_kvarg_rxd_wait_timeout_ns(sa);
+ if (rc != 0)
+ return rc;
+
rc = efx_nic_probe(enp, preferred_efv);
if (rc == EACCES) {
/* Unprivileged functions cannot set FW variant */
}
uint32_t
-sfc_register_logtype(struct sfc_adapter *sa, const char *lt_prefix_str,
- uint32_t ll_default)
+sfc_register_logtype(const struct rte_pci_addr *pci_addr,
+ const char *lt_prefix_str, uint32_t ll_default)
{
size_t lt_prefix_str_size = strlen(lt_prefix_str);
size_t lt_str_size_max;
++lt_prefix_str_size; /* Reserve space for prefix separator */
lt_str_size_max = lt_prefix_str_size + PCI_PRI_STR_SIZE + 1;
} else {
- return RTE_LOGTYPE_PMD;
+ return sfc_logtype_driver;
}
lt_str = rte_zmalloc("logtype_str", lt_str_size_max, 0);
if (lt_str == NULL)
- return RTE_LOGTYPE_PMD;
+ return sfc_logtype_driver;
strncpy(lt_str, lt_prefix_str, lt_prefix_str_size);
lt_str[lt_prefix_str_size - 1] = '.';
- rte_pci_device_name(&sa->pci_addr, lt_str + lt_prefix_str_size,
+ rte_pci_device_name(pci_addr, lt_str + lt_prefix_str_size,
lt_str_size_max - lt_prefix_str_size);
lt_str[lt_str_size_max - 1] = '\0';
ret = rte_log_register_type_and_pick_level(lt_str, ll_default);
rte_free(lt_str);
- return (ret < 0) ? RTE_LOGTYPE_PMD : ret;
+ if (ret < 0)
+ return sfc_logtype_driver;
+
+ return ret;
}