[dpdk-dev] [PATCH 3/6] net/sfc: add kvarg control for MAC statistics update period

Andrew Rybchenko arybchenko at solarflare.com
Thu Mar 2 16:46:45 CET 2017


From: Ivan Malov <ivan.malov at oktetlabs.ru>

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 <ivan.malov at oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko at solarflare.com>
Reviewed-by: Andrew Lee <alee at solarflare.com>
---
 doc/guides/nics/sfc_efx.rst  |  9 +++++
 drivers/net/sfc/sfc.h        |  2 ++
 drivers/net/sfc/sfc_ethdev.c |  1 +
 drivers/net/sfc/sfc_kvargs.c | 20 +++++++++++
 drivers/net/sfc/sfc_kvargs.h |  5 +++
 drivers/net/sfc/sfc_port.c   | 86 +++++++++++++++++++++++++++++++++++++-------
 6 files changed, 110 insertions(+), 13 deletions(-)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index 0a05a0a..0130290 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -197,3 +197,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 8c6c02f..8e094e0 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -153,6 +153,8 @@ struct sfc_port {
 	rte_spinlock_t			mac_stats_lock;
 	uint64_t			*mac_stats_buf;
 	efsys_mem_t			mac_stats_dma_mem;
+	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 be19453..07f126f 100644
--- a/drivers/net/sfc/sfc_ethdev.c
+++ b/drivers/net/sfc/sfc_ethdev.c
@@ -1362,5 +1362,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 "=<long> "
 	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 227a8db..60a7ac1 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 2fea9c7..6c6003a 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 5998a99..07a61c4 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;
 }
@@ -143,15 +174,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);
@@ -210,6 +248,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");
@@ -237,9 +276,30 @@ sfc_port_init(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_mac_stats_dma_alloc;
 
+	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:
-- 
2.9.3



More information about the dev mailing list