From: Ivan Malov Date: Thu, 9 Mar 2017 17:22:59 +0000 (+0000) Subject: net/sfc: add kvarg control for MAC statistics update period X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=e56fa9c23e7a;p=dpdk.git net/sfc: add kvarg control for MAC statistics update period The patch is to make MAC statistics update interval tunable by means of 'stats_update_period_ms' kvarg parameter making it possible to use values different from 1000 ms in case of SFN8xxx boards provided that firmware version is 6.2.1.1033 Signed-off-by: Ivan Malov Signed-off-by: Andrew Rybchenko Reviewed-by: Andrew Lee --- diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst index 8229d7d411..c02e1beda1 100644 --- a/doc/guides/nics/sfc_efx.rst +++ b/doc/guides/nics/sfc_efx.rst @@ -242,3 +242,12 @@ boolean parameters value. Enable extra logging of the communication with the NIC's management CPU. The logging is done using RTE_LOG() with INFO level and PMD type. The format is consumed by the Solarflare netlogdecode cross-platform tool. + +- ``stats_update_period_ms`` [long] (default **1000**) + + Adjust period in milliseconds to update port hardware statistics. + The accepted range is 0 to 65535. The value of **0** may be used + to disable periodic statistics update. One should note that it's + only possible to set an arbitrary value on SFN8xxx provided that + firmware version is 6.2.1.1033 or higher, otherwise any positive + value will select a fixed update period of **1000** milliseconds diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h index 6aeeda525d..ca39df0c0f 100644 --- a/drivers/net/sfc/sfc.h +++ b/drivers/net/sfc/sfc.h @@ -160,6 +160,8 @@ struct sfc_port { uint64_t *mac_stats_buf; efsys_mem_t mac_stats_dma_mem; boolean_t mac_stats_reset_pending; + uint16_t mac_stats_update_period_ms; + uint32_t mac_stats_update_generation; uint32_t mac_stats_mask[EFX_MAC_STATS_MASK_NPAGES]; }; diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c index e84731acaf..834ec67679 100644 --- a/drivers/net/sfc/sfc_ethdev.c +++ b/drivers/net/sfc/sfc_ethdev.c @@ -1436,5 +1436,6 @@ RTE_PMD_REGISTER_PCI_TABLE(net_sfc_efx, pci_id_sfc_efx_map); RTE_PMD_REGISTER_KMOD_DEP(net_sfc_efx, "* igb_uio | uio_pci_generic | vfio"); RTE_PMD_REGISTER_PARAM_STRING(net_sfc_efx, SFC_KVARG_PERF_PROFILE "=" SFC_KVARG_VALUES_PERF_PROFILE " " + SFC_KVARG_STATS_UPDATE_PERIOD_MS "= " SFC_KVARG_MCDI_LOGGING "=" SFC_KVARG_VALUES_BOOL " " SFC_KVARG_DEBUG_INIT "=" SFC_KVARG_VALUES_BOOL); diff --git a/drivers/net/sfc/sfc_kvargs.c b/drivers/net/sfc/sfc_kvargs.c index 227a8dbea8..60a7ac1f7a 100644 --- a/drivers/net/sfc/sfc_kvargs.c +++ b/drivers/net/sfc/sfc_kvargs.c @@ -42,6 +42,7 @@ sfc_kvargs_parse(struct sfc_adapter *sa) struct rte_eth_dev *eth_dev = (sa)->eth_dev; struct rte_devargs *devargs = eth_dev->device->devargs; const char **params = (const char *[]){ + SFC_KVARG_STATS_UPDATE_PERIOD_MS, SFC_KVARG_DEBUG_INIT, SFC_KVARG_MCDI_LOGGING, SFC_KVARG_PERF_PROFILE, @@ -110,3 +111,22 @@ sfc_kvarg_bool_handler(__rte_unused const char *key, return 0; } + +int +sfc_kvarg_long_handler(__rte_unused const char *key, + const char *value_str, void *opaque) +{ + long value; + char *endptr; + + if (!value_str || !opaque) + return -EINVAL; + + value = strtol(value_str, &endptr, 0); + if (endptr == value_str) + return -EINVAL; + + *(long *)opaque = value; + + return 0; +} diff --git a/drivers/net/sfc/sfc_kvargs.h b/drivers/net/sfc/sfc_kvargs.h index 2fea9c7a4c..6c6003a5f3 100644 --- a/drivers/net/sfc/sfc_kvargs.h +++ b/drivers/net/sfc/sfc_kvargs.h @@ -52,6 +52,8 @@ extern "C" { SFC_KVARG_PERF_PROFILE_THROUGHPUT "|" \ SFC_KVARG_PERF_PROFILE_LOW_LATENCY "]" +#define SFC_KVARG_STATS_UPDATE_PERIOD_MS "stats_update_period_ms" + struct sfc_adapter; int sfc_kvargs_parse(struct sfc_adapter *sa); @@ -63,6 +65,9 @@ int sfc_kvargs_process(struct sfc_adapter *sa, const char *key_match, int sfc_kvarg_bool_handler(const char *key, const char *value_str, void *opaque); +int sfc_kvarg_long_handler(const char *key, const char *value_str, + void *opaque); + #ifdef __cplusplus } #endif diff --git a/drivers/net/sfc/sfc_port.c b/drivers/net/sfc/sfc_port.c index e77848d426..be754804c1 100644 --- a/drivers/net/sfc/sfc_port.c +++ b/drivers/net/sfc/sfc_port.c @@ -31,6 +31,16 @@ #include "sfc.h" #include "sfc_log.h" +#include "sfc_kvargs.h" + +/** Default MAC statistics update period is 1 second */ +#define SFC_MAC_STATS_UPDATE_PERIOD_MS_DEF MS_PER_S + +/** The number of microseconds to sleep on attempt to get statistics update */ +#define SFC_MAC_STATS_UPDATE_RETRY_INTERVAL_US 10 + +/** The number of attempts to await arrival of freshly generated statistics */ +#define SFC_MAC_STATS_UPDATE_NB_ATTEMPTS 50 /** * Update MAC statistics in the buffer. @@ -46,6 +56,10 @@ int sfc_port_update_mac_stats(struct sfc_adapter *sa) { struct sfc_port *port = &sa->port; + efsys_mem_t *esmp = &port->mac_stats_dma_mem; + uint32_t *genp = NULL; + uint32_t gen_old; + unsigned int nb_attempts = 0; int rc; SFC_ASSERT(rte_spinlock_is_locked(&port->mac_stats_lock)); @@ -53,10 +67,27 @@ sfc_port_update_mac_stats(struct sfc_adapter *sa) if (sa->state != SFC_ADAPTER_STARTED) return EINVAL; - rc = efx_mac_stats_update(sa->nic, &port->mac_stats_dma_mem, - port->mac_stats_buf, NULL); - if (rc != 0) - return rc; + /* If periodic statistics DMA'ing is off, request explicitly */ + if (port->mac_stats_update_period_ms == 0) { + rc = efx_mac_stats_upload(sa->nic, esmp); + if (rc != 0) + return rc; + + genp = &port->mac_stats_update_generation; + gen_old = *genp; + } + + do { + if (nb_attempts > 0) + rte_delay_us(SFC_MAC_STATS_UPDATE_RETRY_INTERVAL_US); + + rc = efx_mac_stats_update(sa->nic, esmp, + port->mac_stats_buf, genp); + if (rc != 0) + return rc; + + } while ((genp != NULL) && (*genp == gen_old) && + (++nb_attempts < SFC_MAC_STATS_UPDATE_NB_ATTEMPTS)); return 0; } @@ -171,15 +202,22 @@ sfc_port_start(struct sfc_adapter *sa) efx_mac_stats_get_mask(sa->nic, port->mac_stats_mask, sizeof(port->mac_stats_mask)); - /* Update MAC stats using periodic DMA. - * Common code always uses 1000ms update period, so period_ms - * parameter only needs to be non-zero to start updates. - */ - sfc_log_init(sa, "request MAC stats DMA'ing"); - rc = efx_mac_stats_periodic(sa->nic, &port->mac_stats_dma_mem, - 1000, B_FALSE); - if (rc != 0) - goto fail_mac_stats_periodic; + port->mac_stats_update_generation = 0; + + if (port->mac_stats_update_period_ms != 0) { + /* + * Update MAC stats using periodic DMA; + * any positive update interval different from + * 1000 ms can be set only on SFN8xxx provided + * that FW version is 6.2.1.1033 or higher + */ + sfc_log_init(sa, "request MAC stats DMA'ing"); + rc = efx_mac_stats_periodic(sa->nic, &port->mac_stats_dma_mem, + port->mac_stats_update_period_ms, + B_FALSE); + if (rc != 0) + goto fail_mac_stats_periodic; + } sfc_log_init(sa, "disable MAC drain"); rc = efx_mac_drain(sa->nic, B_FALSE); @@ -239,6 +277,7 @@ sfc_port_init(struct sfc_adapter *sa) { const struct rte_eth_dev_data *dev_data = sa->eth_dev->data; struct sfc_port *port = &sa->port; + long kvarg_stats_update_period_ms; int rc; sfc_log_init(sa, "entry"); @@ -279,9 +318,30 @@ sfc_port_init(struct sfc_adapter *sa) port->mac_stats_reset_pending = B_FALSE; + kvarg_stats_update_period_ms = SFC_MAC_STATS_UPDATE_PERIOD_MS_DEF; + + rc = sfc_kvargs_process(sa, SFC_KVARG_STATS_UPDATE_PERIOD_MS, + sfc_kvarg_long_handler, + &kvarg_stats_update_period_ms); + if ((rc == 0) && + ((kvarg_stats_update_period_ms < 0) || + (kvarg_stats_update_period_ms > UINT16_MAX))) { + sfc_err(sa, "wrong '" SFC_KVARG_STATS_UPDATE_PERIOD_MS "' " + "was set (%ld);", kvarg_stats_update_period_ms); + sfc_err(sa, "it must not be less than 0 " + "or greater than %" PRIu16, UINT16_MAX); + rc = EINVAL; + goto fail_kvarg_stats_update_period_ms; + } else if (rc != 0) { + goto fail_kvarg_stats_update_period_ms; + } + + port->mac_stats_update_period_ms = kvarg_stats_update_period_ms; + sfc_log_init(sa, "done"); return 0; +fail_kvarg_stats_update_period_ms: fail_mac_stats_dma_alloc: rte_free(port->mac_stats_buf); fail_mac_stats_buf_alloc: