drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
Extension
.c
Size
16961 bytes
Lines
619
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct mlx5_fc_stats {
	struct xarray counters;

	struct workqueue_struct *wq;
	struct delayed_work work;
	unsigned long sampling_interval; /* jiffies */
	u32 *bulk_query_out;
	int bulk_query_len;
	bool bulk_query_alloc_failed;
	unsigned long next_bulk_query_alloc;
	struct mlx5_fs_pool fc_pool;
};

static void mlx5_fc_pool_init(struct mlx5_fs_pool *fc_pool, struct mlx5_core_dev *dev);
static void mlx5_fc_pool_cleanup(struct mlx5_fs_pool *fc_pool);
static struct mlx5_fc *mlx5_fc_pool_acquire_counter(struct mlx5_fs_pool *fc_pool);
static void mlx5_fc_pool_release_counter(struct mlx5_fs_pool *fc_pool, struct mlx5_fc *fc);

static int get_init_bulk_query_len(struct mlx5_core_dev *dev)
{
	return min_t(int, MLX5_INIT_COUNTERS_BULK,
		     (1 << MLX5_CAP_GEN(dev, log_max_flow_counter_bulk)));
}

static int get_max_bulk_query_len(struct mlx5_core_dev *dev)
{
	return min_t(int, MLX5_SW_MAX_COUNTERS_BULK,
		     (1 << MLX5_CAP_GEN(dev, log_max_flow_counter_bulk)));
}

static void update_counter_cache(int index, u32 *bulk_raw_data,
				 struct mlx5_fc_cache *cache)
{
	void *stats = MLX5_ADDR_OF(query_flow_counter_out, bulk_raw_data,
			     flow_statistics[index]);
	u64 packets = MLX5_GET64(traffic_counter, stats, packets);
	u64 bytes = MLX5_GET64(traffic_counter, stats, octets);

	if (cache->packets == packets)
		return;

	cache->packets = packets;
	cache->bytes = bytes;
	cache->lastuse = jiffies;
}

/* Synchronization notes
 *
 * Access to counter array:
 * - create - mlx5_fc_create() (user context)
 *   - inserts the counter into the xarray.
 *
 * - destroy - mlx5_fc_destroy() (user context)
 *   - erases the counter from the xarray and releases it.
 *
 * - query mlx5_fc_query(), mlx5_fc_query_cached{,_raw}() (user context)
 *   - user should not access a counter after destroy.
 *
 * - bulk query (single thread workqueue context)
 *   - create: query relies on 'lastuse' to avoid updating counters added
 *             around the same time as the current bulk cmd.
 *   - destroy: destroyed counters will not be accessed, even if they are
 *              destroyed during a bulk query command.
 */
static void mlx5_fc_stats_query_all_counters(struct mlx5_core_dev *dev)
{
	struct mlx5_fc_stats *fc_stats = dev->priv.fc_stats;
	u32 bulk_len = fc_stats->bulk_query_len;
	XA_STATE(xas, &fc_stats->counters, 0);
	u32 *data = fc_stats->bulk_query_out;
	struct mlx5_fc *counter;
	u32 last_bulk_id = 0;
	u64 bulk_query_time;
	u32 bulk_base_id;
	int err;

	xas_lock(&xas);
	xas_for_each(&xas, counter, U32_MAX) {
		if (xas_retry(&xas, counter))
			continue;
		if (unlikely(counter->id >= last_bulk_id)) {
			/* Start new bulk query. */
			/* First id must be aligned to 4 when using bulk query. */
			bulk_base_id = counter->id & ~0x3;
			last_bulk_id = bulk_base_id + bulk_len;
			/* The lock is released while querying the hw and reacquired after. */
			xas_unlock(&xas);
			/* The same id needs to be processed again in the next loop iteration. */
			xas_reset(&xas);
			bulk_query_time = jiffies;

Annotation

Implementation Notes