diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h index ca39df0c0f..09c9ca59aa 100644 --- a/drivers/net/sfc/sfc.h +++ b/drivers/net/sfc/sfc.h @@ -162,6 +162,8 @@ struct sfc_port { boolean_t mac_stats_reset_pending; uint16_t mac_stats_update_period_ms; uint32_t mac_stats_update_generation; + boolean_t mac_stats_periodic_dma_supported; + uint64_t mac_stats_last_request_timestamp; uint32_t mac_stats_mask[EFX_MAC_STATS_MASK_NPAGES]; }; @@ -262,6 +264,13 @@ sfc_adapter_lock_fini(__rte_unused struct sfc_adapter *sa) /* Just for symmetry of the API */ } +/** Get the number of milliseconds since boot from the default timer */ +static inline uint64_t +sfc_get_system_msecs(void) +{ + return rte_get_timer_cycles() * MS_PER_S / rte_get_timer_hz(); +} + int sfc_dma_alloc(const struct sfc_adapter *sa, const char *name, uint16_t id, size_t len, int socket_id, efsys_mem_t *esmp); void sfc_dma_free(const struct sfc_adapter *sa, efsys_mem_t *esmp); diff --git a/drivers/net/sfc/sfc_port.c b/drivers/net/sfc/sfc_port.c index be754804c1..d4498fa80d 100644 --- a/drivers/net/sfc/sfc_port.c +++ b/drivers/net/sfc/sfc_port.c @@ -67,8 +67,23 @@ sfc_port_update_mac_stats(struct sfc_adapter *sa) if (sa->state != SFC_ADAPTER_STARTED) return EINVAL; - /* If periodic statistics DMA'ing is off, request explicitly */ - if (port->mac_stats_update_period_ms == 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)) { + if (port->mac_stats_update_period_ms != 0) { + uint64_t timestamp = sfc_get_system_msecs(); + + if ((timestamp - + port->mac_stats_last_request_timestamp) < + port->mac_stats_update_period_ms) + return 0; + + port->mac_stats_last_request_timestamp = timestamp; + } + rc = efx_mac_stats_upload(sa->nic, esmp); if (rc != 0) return rc; @@ -215,8 +230,14 @@ sfc_port_start(struct sfc_adapter *sa) rc = efx_mac_stats_periodic(sa->nic, &port->mac_stats_dma_mem, port->mac_stats_update_period_ms, B_FALSE); - if (rc != 0) + if (rc == 0) { + port->mac_stats_periodic_dma_supported = B_TRUE; + } else if (rc == EOPNOTSUPP) { + port->mac_stats_periodic_dma_supported = B_FALSE; + port->mac_stats_last_request_timestamp = 0; + } else { goto fail_mac_stats_periodic; + } } sfc_log_init(sa, "disable MAC drain");