drivers/net/ethernet/sfc/tc_counters.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/sfc/tc_counters.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/sfc/tc_counters.c
Extension
.c
Size
17129 bytes
Lines
564
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source 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

if (IS_ERR(cnt)) {
			rhashtable_remove_fast(&efx->tc->counter_id_ht,
					       &ctr->linkage,
					       efx_tc_counter_id_ht_params);
			kfree(ctr);
			return ERR_CAST(cnt);
		}
		ctr->cnt = cnt;
		refcount_set(&ctr->ref, 1);
	}
	return ctr;
}

struct efx_tc_counter_index *efx_tc_flower_find_counter_index(
				struct efx_nic *efx, unsigned long cookie)
{
	struct efx_tc_counter_index key = {};

	key.cookie = cookie;
	return rhashtable_lookup_fast(&efx->tc->counter_id_ht, &key,
				      efx_tc_counter_id_ht_params);
}

/* TC Channel.  Counter updates are delivered on this channel's RXQ. */

static void efx_tc_handle_no_channel(struct efx_nic *efx)
{
	netif_warn(efx, drv, efx->net_dev,
		   "MAE counters require MSI-X and 1 additional interrupt vector.\n");
}

static int efx_tc_probe_channel(struct efx_channel *channel)
{
	struct efx_rx_queue *rx_queue = &channel->rx_queue;

	channel->irq_moderation_us = 0;
	rx_queue->core_index = 0;

	INIT_WORK(&rx_queue->grant_work, efx_mae_counters_grant_credits);

	return 0;
}

static int efx_tc_start_channel(struct efx_channel *channel)
{
	struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel);
	struct efx_nic *efx = channel->efx;

	return efx_mae_start_counters(efx, rx_queue);
}

static void efx_tc_stop_channel(struct efx_channel *channel)
{
	struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel);
	struct efx_nic *efx = channel->efx;
	int rc;

	rc = efx_mae_stop_counters(efx, rx_queue);
	if (rc)
		netif_warn(efx, drv, efx->net_dev,
			   "Failed to stop MAE counters streaming, rc=%d.\n",
			   rc);
	rx_queue->grant_credits = false;
	flush_work(&rx_queue->grant_work);
}

static void efx_tc_remove_channel(struct efx_channel *channel)
{
}

static void efx_tc_get_channel_name(struct efx_channel *channel,
				    char *buf, size_t len)
{
	snprintf(buf, len, "%s-mae", channel->efx->name);
}

static void efx_tc_counter_update(struct efx_nic *efx,
				  enum efx_tc_counter_type counter_type,
				  u32 counter_idx, u64 packets, u64 bytes,
				  u32 mark)
{
	struct efx_tc_counter *cnt;

	rcu_read_lock(); /* Protect against deletion of 'cnt' */
	cnt = efx_tc_flower_find_counter_by_fw_id(efx, counter_type, counter_idx);
	if (!cnt) {
		/* This can legitimately happen when a counter is removed,
		 * with updates for the counter still in-flight; however this
		 * should be an infrequent occurrence.
		 */

Annotation

Implementation Notes