drivers/net/ethernet/marvell/prestera/prestera_flower.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/marvell/prestera/prestera_flower.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/marvell/prestera/prestera_flower.c
Extension
.c
Size
16087 bytes
Lines
586
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 prestera_flower_template {
	struct prestera_acl_ruleset *ruleset;
	struct list_head list;
	u32 chain_index;
};

static void
prestera_flower_template_free(struct prestera_flower_template *template)
{
	prestera_acl_ruleset_put(template->ruleset);
	list_del(&template->list);
	kfree(template);
}

void prestera_flower_template_cleanup(struct prestera_flow_block *block)
{
	struct prestera_flower_template *template, *tmp;

	/* put the reference to all rulesets kept in tmpl create */
	list_for_each_entry_safe(template, tmp, &block->template_list, list)
		prestera_flower_template_free(template);
}

static int
prestera_flower_parse_goto_action(struct prestera_flow_block *block,
				  struct prestera_acl_rule *rule,
				  u32 chain_index,
				  const struct flow_action_entry *act)
{
	struct prestera_acl_ruleset *ruleset;

	if (act->chain_index <= chain_index)
		/* we can jump only forward */
		return -EINVAL;

	if (rule->re_arg.jump.valid)
		return -EEXIST;

	ruleset = prestera_acl_ruleset_get(block->sw->acl, block,
					   act->chain_index);
	if (IS_ERR(ruleset))
		return PTR_ERR(ruleset);

	rule->re_arg.jump.valid = 1;
	rule->re_arg.jump.i.index = prestera_acl_ruleset_index_get(ruleset);

	rule->jump_ruleset = ruleset;

	return 0;
}

static int prestera_flower_parse_actions(struct prestera_flow_block *block,
					 struct prestera_acl_rule *rule,
					 struct flow_action *flow_action,
					 u32 chain_index,
					 struct netlink_ext_ack *extack)
{
	const struct flow_action_entry *act;
	int err, i;

	/* whole struct (rule->re_arg) must be initialized with 0 */
	if (!flow_action_has_entries(flow_action))
		return 0;

	if (!flow_action_mixed_hw_stats_check(flow_action, extack))
		return -EOPNOTSUPP;

	act = flow_action_first_entry_get(flow_action);
	if (act->hw_stats & FLOW_ACTION_HW_STATS_DISABLED) {
		/* Nothing to do */
	} else if (act->hw_stats & FLOW_ACTION_HW_STATS_DELAYED) {
		/* setup counter first */
		rule->re_arg.count.valid = true;
		err = prestera_acl_chain_to_client(chain_index, block->ingress,
						   &rule->re_arg.count.client);
		if (err)
			return err;
	} else {
		NL_SET_ERR_MSG_MOD(extack, "Unsupported action HW stats type");
		return -EOPNOTSUPP;
	}

	flow_action_for_each(i, act, flow_action) {
		switch (act->id) {
		case FLOW_ACTION_ACCEPT:
			if (rule->re_arg.accept.valid)
				return -EEXIST;

			rule->re_arg.accept.valid = 1;
			break;

Annotation

Implementation Notes