* for Solarflare) and Solarflare Communications, Inc.
*/
+#include <rte_bitmap.h>
+
#include "efx.h"
#include "sfc.h"
/**
* Update MAC statistics in the buffer.
*
- * @param sa Adapter
+ * @param sa Adapter
+ * @param force_upload Flag to upload MAC stats in any case
*
* @return Status code
* @retval 0 Success
* @retval ENOMEM Memory allocation failure
*/
int
-sfc_port_update_mac_stats(struct sfc_adapter *sa)
+sfc_port_update_mac_stats(struct sfc_adapter *sa, boolean_t force_upload)
{
struct sfc_port *port = &sa->port;
efsys_mem_t *esmp = &port->mac_stats_dma_mem;
SFC_ASSERT(sfc_adapter_is_locked(sa));
if (sa->state != SFC_ADAPTER_STARTED)
- return EINVAL;
+ return 0;
/*
* If periodic statistics DMA'ing is off or if not supported,
* make a manual request and keep an eye on timer if need be
*/
if (!port->mac_stats_periodic_dma_supported ||
- (port->mac_stats_update_period_ms == 0)) {
+ (port->mac_stats_update_period_ms == 0) || force_upload) {
if (port->mac_stats_update_period_ms != 0) {
uint64_t timestamp = sfc_get_system_msecs();
(void)efx_mac_stats_periodic(sa->nic, &sa->port.mac_stats_dma_mem,
0, B_FALSE);
+ sfc_port_update_mac_stats(sa, B_TRUE);
+
efx_port_fini(sa->nic);
efx_filter_fini(sa->nic);
link_info->link_autoneg = ETH_LINK_AUTONEG;
}
+
+int
+sfc_port_get_mac_stats(struct sfc_adapter *sa, struct rte_eth_xstat *xstats,
+ unsigned int xstats_count, unsigned int *nb_written)
+{
+ struct sfc_port *port = &sa->port;
+ uint64_t *mac_stats;
+ unsigned int i;
+ int nstats = 0;
+ int ret;
+
+ sfc_adapter_lock(sa);
+
+ ret = sfc_port_update_mac_stats(sa, B_FALSE);
+ if (ret != 0) {
+ SFC_ASSERT(ret > 0);
+ ret = -ret;
+ goto unlock;
+ }
+
+ mac_stats = port->mac_stats_buf;
+
+ for (i = 0; i < EFX_MAC_NSTATS; ++i) {
+ if (EFX_MAC_STAT_SUPPORTED(port->mac_stats_mask, i)) {
+ if (nstats < (int)xstats_count) {
+ xstats[nstats].id = nstats;
+ xstats[nstats].value = mac_stats[i];
+ (*nb_written)++;
+ }
+ nstats++;
+ }
+ }
+ ret = nstats;
+
+unlock:
+ sfc_adapter_unlock(sa);
+
+ return ret;
+}
+
+int
+sfc_port_get_mac_stats_by_id(struct sfc_adapter *sa, const uint64_t *ids,
+ uint64_t *values, unsigned int n)
+{
+ struct sfc_port *port = &sa->port;
+ uint64_t *mac_stats;
+ unsigned int i;
+ int ret;
+ int rc;
+
+ sfc_adapter_lock(sa);
+
+ rc = sfc_port_update_mac_stats(sa, B_FALSE);
+ if (rc != 0) {
+ SFC_ASSERT(rc > 0);
+ ret = -rc;
+ goto unlock;
+ }
+
+ mac_stats = port->mac_stats_buf;
+
+ SFC_ASSERT(port->mac_stats_nb_supported <=
+ RTE_DIM(port->mac_stats_by_id));
+
+ for (i = 0; i < n; i++) {
+ if (ids[i] < port->mac_stats_nb_supported)
+ values[i] = mac_stats[port->mac_stats_by_id[ids[i]]];
+ }
+
+ ret = 0;
+
+unlock:
+ sfc_adapter_unlock(sa);
+
+ return ret;
+}