drivers/net/ethernet/netronome/nfp/flower/metadata.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/netronome/nfp/flower/metadata.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/netronome/nfp/flower/metadata.c
Extension
.c
Size
20142 bytes
Lines
726
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

struct nfp_mask_id_table {
	struct hlist_node link;
	u32 hash_key;
	u32 ref_cnt;
	u8 mask_id;
};

struct nfp_fl_flow_table_cmp_arg {
	struct net_device *netdev;
	unsigned long cookie;
};

struct nfp_fl_stats_ctx_to_flow {
	struct rhash_head ht_node;
	u32 stats_cxt;
	struct nfp_fl_payload *flow;
};

static const struct rhashtable_params stats_ctx_table_params = {
	.key_offset	= offsetof(struct nfp_fl_stats_ctx_to_flow, stats_cxt),
	.head_offset	= offsetof(struct nfp_fl_stats_ctx_to_flow, ht_node),
	.key_len	= sizeof(u32),
};

static int nfp_release_stats_entry(struct nfp_app *app, u32 stats_context_id)
{
	struct nfp_flower_priv *priv = app->priv;
	struct circ_buf *ring;

	ring = &priv->stats_ids.free_list;
	/* Check if buffer is full, stats_ring_size must be power of 2 */
	if (!CIRC_SPACE(ring->head, ring->tail, priv->stats_ring_size))
		return -ENOBUFS;

	/* Each increment of head represents size of NFP_FL_STATS_ELEM_RS */
	memcpy(&ring->buf[ring->head * NFP_FL_STATS_ELEM_RS],
	       &stats_context_id, NFP_FL_STATS_ELEM_RS);
	ring->head = (ring->head + 1) & (priv->stats_ring_size - 1);

	return 0;
}

static int nfp_get_stats_entry(struct nfp_app *app, u32 *stats_context_id)
{
	struct nfp_flower_priv *priv = app->priv;
	u32 freed_stats_id, temp_stats_id;
	struct circ_buf *ring;

	ring = &priv->stats_ids.free_list;
	freed_stats_id = priv->stats_ring_size;
	/* Check for unallocated entries first. */
	if (priv->stats_ids.init_unalloc > 0) {
		*stats_context_id =
			FIELD_PREP(NFP_FL_STAT_ID_STAT,
				   priv->stats_ids.init_unalloc - 1) |
			FIELD_PREP(NFP_FL_STAT_ID_MU_NUM,
				   priv->active_mem_unit);

		if (++priv->active_mem_unit == priv->total_mem_units) {
			priv->stats_ids.init_unalloc--;
			priv->active_mem_unit = 0;
		}

		return 0;
	}

	/* Check if buffer is empty. */
	if (ring->head == ring->tail) {
		*stats_context_id = freed_stats_id;
		return -ENOENT;
	}

	/* Each increment of tail represents size of NFP_FL_STATS_ELEM_RS */
	memcpy(&temp_stats_id, &ring->buf[ring->tail * NFP_FL_STATS_ELEM_RS],
	       NFP_FL_STATS_ELEM_RS);
	*stats_context_id = temp_stats_id;
	memcpy(&ring->buf[ring->tail * NFP_FL_STATS_ELEM_RS], &freed_stats_id,
	       NFP_FL_STATS_ELEM_RS);
	/* stats_ring_size must be power of 2 */
	ring->tail = (ring->tail + 1) & (priv->stats_ring_size - 1);

	return 0;
}

/* Must be called with either RTNL or rcu_read_lock */
struct nfp_fl_payload *
nfp_flower_search_fl_table(struct nfp_app *app, unsigned long tc_flower_cookie,
			   struct net_device *netdev)
{
	struct nfp_fl_flow_table_cmp_arg flower_cmp_arg;

Annotation

Implementation Notes