From 9e7fc8b8f3be3f7d5595143baa5af5cf7c140c24 Mon Sep 17 00:00:00 2001 From: Roman Zhukov Date: Mon, 26 Mar 2018 13:50:36 +0100 Subject: [PATCH] net/sfc: add device parameter to choose FW variant Add support of choice the preferred firmware variant to use in device parameters. Signed-off-by: Roman Zhukov Signed-off-by: Andrew Rybchenko --- doc/guides/nics/sfc_efx.rst | 15 +++++ drivers/net/sfc/sfc.c | 123 ++++++++++++++++++++++++++++++++++- drivers/net/sfc/sfc_ethdev.c | 1 + drivers/net/sfc/sfc_kvargs.c | 1 + drivers/net/sfc/sfc_kvargs.h | 12 ++++ 5 files changed, 151 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst index 2e4c3d873f..2bd29ccdd2 100644 --- a/doc/guides/nics/sfc_efx.rst +++ b/doc/guides/nics/sfc_efx.rst @@ -330,6 +330,21 @@ boolean parameters value. firmware version is 6.2.1.1033 or higher, otherwise any positive value will select a fixed update period of **1000** milliseconds +- ``fw_variant`` [dont-care|full-feature|ultra-low-latency| + capture-packed-stream] (default **dont-care**) + + Choose the preferred firmware variant to use. In order for the selected + option to have an effect, the **sfboot** utility must be configured with the + **auto** firmware-variant option. The preferred firmware variant applies to + all ports on the NIC. + **dont-care** ensures that the driver can attach to an unprivileged function. + The datapath firmware type to use is controlled by the **sfboot** + utility. + **full-feature** chooses full featured firmware. + **ultra-low-latency** chooses firmware with fewer features but lower latency. + **capture-packed-stream** chooses firmware for SolarCapture packed stream + mode. + Dynamic Logging Parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c index 2a326fc4d9..e2ba7208e2 100644 --- a/drivers/net/sfc/sfc.c +++ b/drivers/net/sfc/sfc.c @@ -20,6 +20,7 @@ #include "sfc_ev.h" #include "sfc_rx.h" #include "sfc_tx.h" +#include "sfc_kvargs.h" int @@ -740,6 +741,126 @@ sfc_detach(struct sfc_adapter *sa) sa->state = SFC_ADAPTER_UNINITIALIZED; } +static int +sfc_kvarg_fv_variant_handler(__rte_unused const char *key, + const char *value_str, void *opaque) +{ + uint32_t *value = opaque; + + if (strcasecmp(value_str, SFC_KVARG_FW_VARIANT_DONT_CARE) == 0) + *value = EFX_FW_VARIANT_DONT_CARE; + else if (strcasecmp(value_str, SFC_KVARG_FW_VARIANT_FULL_FEATURED) == 0) + *value = EFX_FW_VARIANT_FULL_FEATURED; + else if (strcasecmp(value_str, SFC_KVARG_FW_VARIANT_LOW_LATENCY) == 0) + *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 + return -EINVAL; + + return 0; +} + +static int +sfc_get_fw_variant(struct sfc_adapter *sa, efx_fw_variant_t *efv) +{ + efx_nic_fw_info_t enfi; + int rc; + + rc = efx_nic_get_fw_version(sa->nic, &enfi); + if (rc != 0) + return rc; + else if (!enfi.enfi_dpcpu_fw_ids_valid) + return ENOTSUP; + + /* + * Firmware variant can be uniquely identified by the RxDPCPU + * firmware id + */ + switch (enfi.enfi_rx_dpcpu_fw_id) { + case EFX_RXDP_FULL_FEATURED_FW_ID: + *efv = EFX_FW_VARIANT_FULL_FEATURED; + break; + + case EFX_RXDP_LOW_LATENCY_FW_ID: + *efv = EFX_FW_VARIANT_LOW_LATENCY; + break; + + case EFX_RXDP_PACKED_STREAM_FW_ID: + *efv = EFX_FW_VARIANT_PACKED_STREAM; + break; + + default: + /* + * Other firmware variants are not considered, since they are + * not supported in the device parameters + */ + *efv = EFX_FW_VARIANT_DONT_CARE; + break; + } + + return 0; +} + +static const char * +sfc_fw_variant2str(efx_fw_variant_t efv) +{ + switch (efv) { + case EFX_RXDP_FULL_FEATURED_FW_ID: + return SFC_KVARG_FW_VARIANT_FULL_FEATURED; + case EFX_RXDP_LOW_LATENCY_FW_ID: + return SFC_KVARG_FW_VARIANT_LOW_LATENCY; + case EFX_RXDP_PACKED_STREAM_FW_ID: + return SFC_KVARG_FW_VARIANT_PACKED_STREAM; + default: + return "unknown"; + } +} + +static int +sfc_nic_probe(struct sfc_adapter *sa) +{ + efx_nic_t *enp = sa->nic; + efx_fw_variant_t preferred_efv; + efx_fw_variant_t efv; + int rc; + + preferred_efv = EFX_FW_VARIANT_DONT_CARE; + rc = sfc_kvargs_process(sa, SFC_KVARG_FW_VARIANT, + sfc_kvarg_fv_variant_handler, + &preferred_efv); + if (rc != 0) { + sfc_err(sa, "invalid %s parameter value", SFC_KVARG_FW_VARIANT); + return rc; + } + + rc = efx_nic_probe(enp, preferred_efv); + if (rc == EACCES) { + /* Unprivileged functions cannot set FW variant */ + rc = efx_nic_probe(enp, EFX_FW_VARIANT_DONT_CARE); + } + if (rc != 0) + return rc; + + rc = sfc_get_fw_variant(sa, &efv); + if (rc == ENOTSUP) { + sfc_warn(sa, "FW variant can not be obtained"); + return 0; + } + if (rc != 0) + return rc; + + /* Check that firmware variant was changed to the requested one */ + if (preferred_efv != EFX_FW_VARIANT_DONT_CARE && preferred_efv != efv) { + sfc_warn(sa, "FW variant has not changed to the requested %s", + sfc_fw_variant2str(preferred_efv)); + } + + sfc_notice(sa, "running FW variant is %s", sfc_fw_variant2str(efv)); + + return 0; +} + int sfc_probe(struct sfc_adapter *sa) { @@ -780,7 +901,7 @@ sfc_probe(struct sfc_adapter *sa) goto fail_mcdi_init; sfc_log_init(sa, "probe nic"); - rc = efx_nic_probe(enp, EFX_FW_VARIANT_DONT_CARE); + rc = sfc_nic_probe(sa); if (rc != 0) goto fail_nic_probe; diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c index f16d520812..e140f8f760 100644 --- a/drivers/net/sfc/sfc_ethdev.c +++ b/drivers/net/sfc/sfc_ethdev.c @@ -2065,6 +2065,7 @@ RTE_PMD_REGISTER_PARAM_STRING(net_sfc_efx, SFC_KVARG_RX_DATAPATH "=" SFC_KVARG_VALUES_RX_DATAPATH " " SFC_KVARG_TX_DATAPATH "=" SFC_KVARG_VALUES_TX_DATAPATH " " SFC_KVARG_PERF_PROFILE "=" SFC_KVARG_VALUES_PERF_PROFILE " " + SFC_KVARG_FW_VARIANT "=" SFC_KVARG_VALUES_FW_VARIANT " " SFC_KVARG_STATS_UPDATE_PERIOD_MS "="); RTE_INIT(sfc_driver_register_logtype); diff --git a/drivers/net/sfc/sfc_kvargs.c b/drivers/net/sfc/sfc_kvargs.c index 9c08bff6f3..53fa939138 100644 --- a/drivers/net/sfc/sfc_kvargs.c +++ b/drivers/net/sfc/sfc_kvargs.c @@ -26,6 +26,7 @@ sfc_kvargs_parse(struct sfc_adapter *sa) SFC_KVARG_PERF_PROFILE, SFC_KVARG_RX_DATAPATH, SFC_KVARG_TX_DATAPATH, + SFC_KVARG_FW_VARIANT, NULL, }; diff --git a/drivers/net/sfc/sfc_kvargs.h b/drivers/net/sfc/sfc_kvargs.h index a84dc6bff5..1e578e7d4e 100644 --- a/drivers/net/sfc/sfc_kvargs.h +++ b/drivers/net/sfc/sfc_kvargs.h @@ -45,6 +45,18 @@ extern "C" { SFC_KVARG_DATAPATH_EF10 "|" \ SFC_KVARG_DATAPATH_EF10_SIMPLE "]" +#define SFC_KVARG_FW_VARIANT "fw_variant" + +#define SFC_KVARG_FW_VARIANT_DONT_CARE "dont-care" +#define SFC_KVARG_FW_VARIANT_FULL_FEATURED "full-feature" +#define SFC_KVARG_FW_VARIANT_LOW_LATENCY "ultra-low-latency" +#define SFC_KVARG_FW_VARIANT_PACKED_STREAM "capture-packed-stream" +#define SFC_KVARG_VALUES_FW_VARIANT \ + "[" SFC_KVARG_FW_VARIANT_DONT_CARE "|" \ + SFC_KVARG_FW_VARIANT_FULL_FEATURED "|" \ + SFC_KVARG_FW_VARIANT_LOW_LATENCY "|" \ + SFC_KVARG_FW_VARIANT_PACKED_STREAM "]" + struct sfc_adapter; int sfc_kvargs_parse(struct sfc_adapter *sa); -- 2.20.1