diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 2b4c821883..4d3778eaba 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -205,6 +205,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 	TAILQ_INIT(&mae->outer_rules);
 	TAILQ_INIT(&mae->mac_addrs);
 	TAILQ_INIT(&mae->encap_headers);
+	TAILQ_INIT(&mae->counters);
 	TAILQ_INIT(&mae->action_sets);
 	TAILQ_INIT(&mae->action_rules);
 
@@ -816,72 +817,155 @@ sfc_mae_encap_header_disable(struct sfc_adapter *sa,
 }
 
 static int
-sfc_mae_counters_enable(struct sfc_adapter *sa,
-			struct sfc_mae_counter *counters,
-			unsigned int n_counters,
-			efx_mae_actions_t *action_set_spec)
+sfc_mae_counter_add(struct sfc_adapter *sa,
+		    const struct sfc_mae_counter *counter_tmp,
+		    struct sfc_mae_counter **counterp)
 {
-	int rc;
+	struct sfc_mae_counter *counter;
+	struct sfc_mae *mae = &sa->mae;
 
-	sfc_log_init(sa, "entry");
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
-	if (n_counters == 0) {
-		sfc_log_init(sa, "no counters - skip");
-		return 0;
+	counter = rte_zmalloc("sfc_mae_counter", sizeof(*counter), 0);
+	if (counter == NULL)
+		return ENOMEM;
+
+	if (counter_tmp != NULL) {
+		counter->rte_id_valid = counter_tmp->rte_id_valid;
+		counter->rte_id = counter_tmp->rte_id;
 	}
 
-	SFC_ASSERT(sfc_adapter_is_locked(sa));
-	SFC_ASSERT(n_counters == 1);
+	counter->fw_rsrc.counter_id.id = EFX_MAE_RSRC_ID_INVALID;
+	counter->refcnt = 1;
 
-	rc = sfc_mae_counter_fw_rsrc_enable(sa, &counters[0]);
-	if (rc != 0) {
-		sfc_err(sa, "failed to enable MAE counter %u: %s",
-			counters[0].mae_id.id, rte_strerror(rc));
-		goto fail_counter_add;
-	}
+	TAILQ_INSERT_TAIL(&mae->counters, counter, entries);
+	*counterp = counter;
 
-	rc = efx_mae_action_set_fill_in_counter_id(action_set_spec,
-						   &counters[0].mae_id);
-	if (rc != 0) {
-		sfc_err(sa, "failed to fill in MAE counter %u in action set: %s",
-			counters[0].mae_id.id, rte_strerror(rc));
-		goto fail_fill_in_id;
-	}
+	sfc_dbg(sa, "added counter=%p", counter);
 
 	return 0;
+}
+
+static void
+sfc_mae_counter_del(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
+{
+	struct sfc_mae *mae = &sa->mae;
 
-fail_fill_in_id:
-	(void)sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);
+	if (counter == NULL)
+		return;
 
-fail_counter_add:
-	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
-	return rc;
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(counter->refcnt != 0);
+
+	--(counter->refcnt);
+
+	if (counter->refcnt != 0)
+		return;
+
+	if (counter->fw_rsrc.counter_id.id != EFX_MAE_RSRC_ID_INVALID ||
+	    counter->fw_rsrc.refcnt != 0) {
+		sfc_err(sa, "deleting counter=%p abandons its FW resource: COUNTER_ID=0x%08x, refcnt=%u",
+			counter, counter->fw_rsrc.counter_id.id,
+			counter->fw_rsrc.refcnt);
+	}
+
+	TAILQ_REMOVE(&mae->counters, counter, entries);
+	rte_free(counter);
+
+	sfc_dbg(sa, "deleted counter=%p", counter);
 }
 
 static int
-sfc_mae_counters_disable(struct sfc_adapter *sa,
-			 struct sfc_mae_counter *counters,
-			 unsigned int n_counters)
+sfc_mae_counter_enable(struct sfc_adapter *sa, struct sfc_mae_counter *counter,
+		       efx_mae_actions_t *action_set_spec)
 {
-	if (n_counters == 0)
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	if (counter == NULL)
 		return 0;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
-	SFC_ASSERT(n_counters == 1);
 
-	if (counters[0].mae_id.id == EFX_MAE_RSRC_ID_INVALID) {
-		sfc_err(sa, "failed to disable: already disabled");
-		return EALREADY;
+	fw_rsrc = &counter->fw_rsrc;
+
+	if (fw_rsrc->refcnt == 0) {
+		SFC_ASSERT(fw_rsrc->counter_id.id == EFX_MAE_RSRC_ID_INVALID);
+
+		rc = sfc_mae_counter_fw_rsrc_enable(sa, counter);
+		if (rc != 0) {
+			sfc_err(sa, "failed to enable counter=%p: %s",
+				counter, rte_strerror(rc));
+			return rc;
+		}
+	}
+
+	if (action_set_spec != NULL) {
+		rc = efx_mae_action_set_fill_in_counter_id(
+					action_set_spec, &fw_rsrc->counter_id);
+		if (rc != 0) {
+			if (fw_rsrc->refcnt == 0) {
+				(void)sfc_mae_counter_fw_rsrc_disable(sa, counter);
+				fw_rsrc->counter_id.id = EFX_MAE_RSRC_ID_INVALID;
+			}
+
+			sfc_err(sa, "cannot fill in counter ID: %s",
+				strerror(rc));
+			return rc;
+		}
+	}
+
+	if (fw_rsrc->refcnt == 0) {
+		sfc_dbg(sa, "enabled counter=%p: COUNTER_ID=0x%08x",
+			counter, fw_rsrc->counter_id.id);
+	}
+
+	++(fw_rsrc->refcnt);
+
+	return 0;
+}
+
+static void
+sfc_mae_counter_disable(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
+{
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	if (counter == NULL)
+		return;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	fw_rsrc = &counter->fw_rsrc;
+
+	if (fw_rsrc->counter_id.id == EFX_MAE_RSRC_ID_INVALID ||
+	    fw_rsrc->refcnt == 0) {
+		sfc_err(sa, "failed to disable counter=%p: already disabled; COUNTER_ID=0x%08x, refcnt=%u",
+			counter, fw_rsrc->counter_id.id, fw_rsrc->refcnt);
+		return;
+	}
+
+	if (fw_rsrc->refcnt == 1) {
+		uint32_t counter_id = fw_rsrc->counter_id.id;
+
+		rc = sfc_mae_counter_fw_rsrc_disable(sa, counter);
+		if (rc == 0) {
+			sfc_dbg(sa, "disabled counter=%p with COUNTER_ID=0x%08x",
+				counter, counter_id);
+		} else {
+			sfc_err(sa, "failed to disable counter=%p with COUNTER_ID=0x%08x: %s",
+				counter, counter_id, strerror(rc));
+		}
+
+		fw_rsrc->counter_id.id = EFX_MAE_RSRC_ID_INVALID;
 	}
 
-	return sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);
+	--(fw_rsrc->refcnt);
 }
 
 struct sfc_mae_aset_ctx {
-	uint64_t			*ft_switch_hit_counter;
-	struct sfc_ft_ctx		*counter_ft_ctx;
 	struct sfc_mae_encap_header	*encap_header;
-	unsigned int			n_counters;
+	struct sfc_mae_counter		*counter;
 	struct sfc_mae_mac_addr		*dst_mac;
 	struct sfc_mae_mac_addr		*src_mac;
 
@@ -897,17 +981,11 @@ sfc_mae_action_set_attach(struct sfc_adapter *sa,
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
-	/*
-	 * Shared counters are not supported, hence, action
-	 * sets with counters are not attachable.
-	 */
-	if (ctx->n_counters != 0)
-		return NULL;
-
 	TAILQ_FOREACH(action_set, &mae->action_sets, entries) {
 		if (action_set->encap_header == ctx->encap_header &&
 		    action_set->dst_mac_addr == ctx->dst_mac &&
 		    action_set->src_mac_addr == ctx->src_mac &&
+		    action_set->counter == ctx->counter &&
 		    efx_mae_action_set_specs_equal(action_set->spec,
 						   ctx->spec)) {
 			sfc_dbg(sa, "attaching to action_set=%p", action_set);
@@ -921,13 +999,11 @@ sfc_mae_action_set_attach(struct sfc_adapter *sa,
 
 static int
 sfc_mae_action_set_add(struct sfc_adapter *sa,
-		       const struct rte_flow_action actions[],
 		       const struct sfc_mae_aset_ctx *ctx,
 		       struct sfc_mae_action_set **action_setp)
 {
 	struct sfc_mae_action_set *action_set;
 	struct sfc_mae *mae = &sa->mae;
-	unsigned int i;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
@@ -937,49 +1013,12 @@ sfc_mae_action_set_add(struct sfc_adapter *sa,
 		return ENOMEM;
 	}
 
-	if (ctx->n_counters > 0) {
-		const struct rte_flow_action *action;
-
-		action_set->counters = rte_malloc("sfc_mae_counter_ids",
-			sizeof(action_set->counters[0]) * ctx->n_counters, 0);
-		if (action_set->counters == NULL) {
-			rte_free(action_set);
-			sfc_err(sa, "failed to alloc counters");
-			return ENOMEM;
-		}
-
-		for (i = 0; i < ctx->n_counters; ++i) {
-			action_set->counters[i].rte_id_valid = B_FALSE;
-			action_set->counters[i].mae_id.id =
-				EFX_MAE_RSRC_ID_INVALID;
-
-			action_set->counters[i].ft_ctx = ctx->counter_ft_ctx;
-			action_set->counters[i].ft_switch_hit_counter =
-				ctx->ft_switch_hit_counter;
-		}
-
-		for (action = actions, i = 0;
-		     action->type != RTE_FLOW_ACTION_TYPE_END &&
-		     i < ctx->n_counters; ++action) {
-			const struct rte_flow_action_count *conf;
-
-			if (action->type != RTE_FLOW_ACTION_TYPE_COUNT)
-				continue;
-
-			conf = action->conf;
-
-			action_set->counters[i].rte_id_valid = B_TRUE;
-			action_set->counters[i].rte_id = conf->id;
-			i++;
-		}
-		action_set->n_counters = ctx->n_counters;
-	}
-
 	action_set->refcnt = 1;
 	action_set->spec = ctx->spec;
 	action_set->encap_header = ctx->encap_header;
 	action_set->dst_mac_addr = ctx->dst_mac;
 	action_set->src_mac_addr = ctx->src_mac;
+	action_set->counter = ctx->counter;
 
 	action_set->fw_rsrc.aset_id.id = EFX_MAE_RSRC_ID_INVALID;
 
@@ -1020,12 +1059,7 @@ sfc_mae_action_set_del(struct sfc_adapter *sa,
 	sfc_mae_encap_header_del(sa, action_set->encap_header);
 	sfc_mae_mac_addr_del(sa, action_set->dst_mac_addr);
 	sfc_mae_mac_addr_del(sa, action_set->src_mac_addr);
-	if (action_set->n_counters > 0) {
-		SFC_ASSERT(action_set->n_counters == 1);
-		SFC_ASSERT(action_set->counters[0].mae_id.id ==
-			   EFX_MAE_RSRC_ID_INVALID);
-		rte_free(action_set->counters);
-	}
+	sfc_mae_counter_del(sa, action_set->counter);
 	TAILQ_REMOVE(&mae->action_sets, action_set, entries);
 	rte_free(action_set);
 
@@ -1039,7 +1073,7 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 	struct sfc_mae_encap_header *encap_header;
 	struct sfc_mae_mac_addr *dst_mac_addr;
 	struct sfc_mae_mac_addr *src_mac_addr;
-	struct sfc_mae_counter *counters;
+	struct sfc_mae_counter *counter;
 	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
@@ -1051,8 +1085,8 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 	encap_header = action_set->encap_header;
 	dst_mac_addr = action_set->dst_mac_addr;
 	src_mac_addr = action_set->src_mac_addr;
-	counters = action_set->counters;
 	fw_rsrc = &action_set->fw_rsrc;
+	counter = action_set->counter;
 
 	if (fw_rsrc->refcnt == 0) {
 		SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID);
@@ -1080,7 +1114,7 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			return rc;
 		}
 
-		if (action_set->n_counters > 0) {
+		if (counter != NULL) {
 			rc = sfc_mae_counter_start(sa);
 			if (rc != 0) {
 				sfc_err(sa, "failed to start MAE counters support: %s",
@@ -1092,13 +1126,8 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			}
 		}
 
-		rc = sfc_mae_counters_enable(sa, counters,
-					     action_set->n_counters,
-					     action_set->spec);
+		rc = sfc_mae_counter_enable(sa, counter, action_set->spec);
 		if (rc != 0) {
-			sfc_err(sa, "failed to enable %u MAE counters: %s",
-				action_set->n_counters, rte_strerror(rc));
-
 			sfc_mae_encap_header_disable(sa, encap_header);
 			sfc_mae_mac_addr_disable(sa, src_mac_addr);
 			sfc_mae_mac_addr_disable(sa, dst_mac_addr);
@@ -1111,11 +1140,10 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			sfc_err(sa, "failed to enable action_set=%p: %s",
 				action_set, strerror(rc));
 
-			(void)sfc_mae_counters_disable(sa, counters,
-						       action_set->n_counters);
 			sfc_mae_encap_header_disable(sa, encap_header);
 			sfc_mae_mac_addr_disable(sa, src_mac_addr);
 			sfc_mae_mac_addr_disable(sa, dst_mac_addr);
+			sfc_mae_counter_disable(sa, counter);
 			return rc;
 		}
 
@@ -1160,16 +1188,10 @@ sfc_mae_action_set_disable(struct sfc_adapter *sa,
 		}
 		fw_rsrc->aset_id.id = EFX_MAE_RSRC_ID_INVALID;
 
-		rc = sfc_mae_counters_disable(sa, action_set->counters,
-					      action_set->n_counters);
-		if (rc != 0) {
-			sfc_err(sa, "failed to disable %u MAE counters: %s",
-				action_set->n_counters, rte_strerror(rc));
-		}
-
 		sfc_mae_encap_header_disable(sa, action_set->encap_header);
 		sfc_mae_mac_addr_disable(sa, action_set->src_mac_addr);
 		sfc_mae_mac_addr_disable(sa, action_set->dst_mac_addr);
+		sfc_mae_counter_disable(sa, action_set->counter);
 	}
 
 	--(fw_rsrc->refcnt);
@@ -3929,10 +3951,11 @@ sfc_mae_rule_parse_action_mark(struct sfc_adapter *sa,
 
 static int
 sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
-				const struct rte_flow_action_count *conf
-					__rte_unused,
+				const struct rte_flow_action_count *conf,
+				struct sfc_mae_counter **counterp,
 				efx_mae_actions_t *spec)
 {
+	struct sfc_mae_counter counter_tmp = {};
 	int rc;
 
 	if ((sa->counter_rxq.state & SFC_COUNTER_RXQ_INITIALIZED) == 0) {
@@ -3947,17 +3970,33 @@ sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
 		goto fail_no_service_core;
 	}
 
-	rc = efx_mae_action_set_populate_count(spec);
-	if (rc != 0) {
-		sfc_err(sa,
-			"failed to populate counters in MAE action set: %s",
-			rte_strerror(rc));
-		goto fail_populate_count;
+	if (*counterp != NULL) {
+		sfc_err(sa, "cannot request more than 1 action COUNT per flow");
+		rc = EINVAL;
+		goto fail_more_than_one;
+	}
+
+	if (spec != NULL) {
+		rc = efx_mae_action_set_populate_count(spec);
+		if (rc != 0) {
+			sfc_err(sa,
+				"failed to populate counters in MAE action set: %s",
+				rte_strerror(rc));
+			goto fail_populate_count;
+		}
+	}
+
+	if (conf != NULL) {
+		counter_tmp.rte_id_valid = true;
+		counter_tmp.rte_id = conf->id;
 	}
 
+	return sfc_mae_counter_add(sa, &counter_tmp, counterp);
+
 	return 0;
 
 fail_populate_count:
+fail_more_than_one:
 fail_no_service_core:
 fail_counter_queue_uninit:
 
@@ -4124,7 +4163,9 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
+	struct sfc_mae_counter **counterp = &ctx->counter;
 	efx_mae_actions_t *spec = ctx->spec;
+	efx_mae_actions_t *spec_ptr = spec;
 	unsigned int switch_port_type_mask;
 	bool custom_error = B_FALSE;
 	int rc = 0;
@@ -4212,7 +4253,8 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	case RTE_FLOW_ACTION_TYPE_COUNT:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_COUNT,
 				       bundle->actions_mask);
-		rc = sfc_mae_rule_parse_action_count(sa, action->conf, spec);
+		rc = sfc_mae_rule_parse_action_count(sa, action->conf,
+						     counterp, spec_ptr);
 		break;
 	case RTE_FLOW_ACTION_TYPE_FLAG:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,
@@ -4362,19 +4404,23 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_action_set_spec_init;
 
-	for (action = actions;
-	     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
-		if (action->type == RTE_FLOW_ACTION_TYPE_COUNT)
-			++(ctx.n_counters);
-	}
-
 	if (spec_mae->ft_rule_type == SFC_FT_RULE_SWITCH) {
+		bool have_user_action_count = false;
+
 		/* TUNNEL rules don't decapsulate packets. SWITCH rules do. */
 		rc = efx_mae_action_set_populate_decap(ctx.spec);
 		if (rc != 0)
 			goto fail_enforce_ft_decap;
 
-		if (ctx.n_counters == 0 &&
+		for (action = actions;
+		     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
+			if (action->type == RTE_FLOW_ACTION_TYPE_COUNT) {
+				have_user_action_count = true;
+				break;
+			}
+		}
+
+		if (!have_user_action_count &&
 		    sfc_mae_counter_stream_enabled(sa)) {
 			/*
 			 * The user opted not to use action COUNT in this rule,
@@ -4386,7 +4432,9 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			if (rc != 0)
 				goto fail_enforce_ft_count;
 
-			ctx.n_counters = 1;
+			rc = sfc_mae_counter_add(sa, NULL, &ctx.counter);
+			if (rc != 0)
+				goto fail_enforce_ft_count;
 		}
 	}
 
@@ -4416,13 +4464,6 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_process_encap_header;
 
-	if (ctx.n_counters > 1) {
-		rc = ENOTSUP;
-		sfc_err(sa, "too many count actions requested: %u",
-			ctx.n_counters);
-		goto fail_nb_count;
-	}
-
 	switch (spec_mae->ft_rule_type) {
 	case SFC_FT_RULE_NONE:
 		break;
@@ -4432,7 +4473,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		if (rc != 0)
 			goto fail_workaround_tunnel_delivery;
 
-		ctx.counter_ft_ctx = spec_mae->ft_ctx;
+		if (ctx.counter != NULL)
+			(ctx.counter)->ft_ctx = spec_mae->ft_ctx;
 		break;
 	case SFC_FT_RULE_SWITCH:
 		/*
@@ -4441,7 +4483,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		 */
 		efx_mae_action_set_populate_mark_reset(ctx.spec);
 
-		ctx.ft_switch_hit_counter =
+		(ctx.counter)->ft_switch_hit_counter =
 			&spec_mae->ft_ctx->switch_hit_counter;
 		break;
 	default:
@@ -4465,6 +4507,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 
 	action_rule_ctx->action_set = sfc_mae_action_set_attach(sa, &ctx);
 	if (action_rule_ctx->action_set != NULL) {
+		sfc_mae_counter_del(sa, ctx.counter);
 		sfc_mae_mac_addr_del(sa, ctx.src_mac);
 		sfc_mae_mac_addr_del(sa, ctx.dst_mac);
 		sfc_mae_encap_header_del(sa, ctx.encap_header);
@@ -4472,8 +4515,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		return 0;
 	}
 
-	rc = sfc_mae_action_set_add(sa, actions, &ctx,
-				    &action_rule_ctx->action_set);
+	rc = sfc_mae_action_set_add(sa, &ctx, &action_rule_ctx->action_set);
 	if (rc != 0)
 		goto fail_action_set_add;
 
@@ -4482,11 +4524,11 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 fail_action_set_add:
 fail_check_fate_action:
 fail_workaround_tunnel_delivery:
-fail_nb_count:
 	sfc_mae_encap_header_del(sa, ctx.encap_header);
 
 fail_process_encap_header:
 fail_rule_parse_action:
+	sfc_mae_counter_del(sa, ctx.counter);
 	sfc_mae_mac_addr_del(sa, ctx.src_mac);
 	sfc_mae_mac_addr_del(sa, ctx.dst_mac);
 	efx_mae_action_set_spec_fini(sa->nic, ctx.spec);
@@ -4766,28 +4808,22 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 	const struct sfc_mae_action_rule *action_rule = spec->action_rule;
 	const struct rte_flow_action_count *conf = action->conf;
 	struct sfc_mae_action_set *action_set;
-	unsigned int i;
+	struct sfc_mae_counter *counter;
 	int rc;
 
-	if (action_rule == NULL || action_rule->action_set->n_counters == 0) {
+	if (action_rule == NULL || action_rule->action_set->counter == NULL) {
 		return rte_flow_error_set(error, EINVAL,
 			RTE_FLOW_ERROR_TYPE_ACTION, action,
 			"Queried flow rule does not have count actions");
 	}
 
 	action_set = action_rule->action_set;
+	counter = action_set->counter;
 
-	for (i = 0; i < action_set->n_counters; i++) {
-		/*
-		 * Get the first available counter of the flow rule if
-		 * counter ID is not specified, provided that this
-		 * counter is not an automatic (implicit) one.
-		 */
-		if (conf != NULL && action_set->counters[i].rte_id != conf->id)
-			continue;
-
+	if (conf == NULL ||
+	    (counter->rte_id_valid && conf->id == counter->rte_id)) {
 		rc = sfc_mae_counter_get(&sa->mae.counter_registry.counters,
-					 &action_set->counters[i], data);
+					 counter, data);
 		if (rc != 0) {
 			return rte_flow_error_set(error, EINVAL,
 				RTE_FLOW_ERROR_TYPE_ACTION, action,
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 7337fcf14d..c73ce0a5e6 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -27,6 +27,7 @@ struct sfc_mae_fw_rsrc {
 	unsigned int			refcnt;
 	RTE_STD_C11
 	union {
+		efx_counter_t		counter_id;
 		efx_mae_aset_id_t	aset_id;
 		efx_mae_rule_id_t	rule_id;
 		efx_mae_mac_id_t	mac_id;
@@ -67,10 +68,11 @@ struct sfc_mae_encap_header {
 
 TAILQ_HEAD(sfc_mae_encap_headers, sfc_mae_encap_header);
 
-/* Counter ID */
+/* Counter object registry entry */
 struct sfc_mae_counter {
-	/* ID of a counter in MAE */
-	efx_counter_t			mae_id;
+	TAILQ_ENTRY(sfc_mae_counter)	entries;
+	unsigned int			refcnt;
+
 	/* ID of a counter in RTE */
 	uint32_t			rte_id;
 	/* RTE counter ID validity status */
@@ -80,18 +82,21 @@ struct sfc_mae_counter {
 	uint64_t			*ft_switch_hit_counter;
 	/* Flow Tunnel (FT) context (for TUNNEL rules; otherwise, NULL) */
 	struct sfc_ft_ctx		*ft_ctx;
+
+	struct sfc_mae_fw_rsrc		fw_rsrc;
 };
 
+TAILQ_HEAD(sfc_mae_counters, sfc_mae_counter);
+
 /** Action set registry entry */
 struct sfc_mae_action_set {
 	TAILQ_ENTRY(sfc_mae_action_set)	entries;
 	unsigned int			refcnt;
-	struct sfc_mae_counter		*counters;
-	uint32_t			n_counters;
 	efx_mae_actions_t		*spec;
 	struct sfc_mae_encap_header	*encap_header;
 	struct sfc_mae_mac_addr		*dst_mac_addr;
 	struct sfc_mae_mac_addr		*src_mac_addr;
+	struct sfc_mae_counter		*counter;
 	struct sfc_mae_fw_rsrc		fw_rsrc;
 };
 
@@ -221,6 +226,8 @@ struct sfc_mae {
 	bool				counter_rxq_running;
 	/** Counter record registry */
 	struct sfc_mae_counter_registry	counter_registry;
+	/** Counter object registry */
+	struct sfc_mae_counters		counters;
 	/**
 	 * Switchdev default rules. They forward traffic from PHY port
 	 * to PF and vice versa.
diff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c
index 8170175991..90b89e81c6 100644
--- a/drivers/net/sfc/sfc_mae_counter.c
+++ b/drivers/net/sfc/sfc_mae_counter.c
@@ -110,7 +110,7 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 		goto fail_counter_id_range;
 	}
 
-	counterp->mae_id = mae_counter;
+	counterp->fw_rsrc.counter_id.id = mae_counter.id;
 
 	p = &counters->mae_counters[mae_counter.id];
 
@@ -152,29 +152,27 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
 	struct sfc_mae_counter_records *counters = &reg->counters;
+	efx_counter_t *mae_counter = &counter->fw_rsrc.counter_id;
 	struct sfc_mae_counter_record *p;
 	uint32_t unused;
 	int rc;
 
-	if (counter->mae_id.id == EFX_MAE_RSRC_ID_INVALID)
-		return 0;
-
-	SFC_ASSERT(counter->mae_id.id < counters->n_mae_counters);
+	SFC_ASSERT(mae_counter->id < counters->n_mae_counters);
 	/*
 	 * The flag is set at the very end of add operation and reset
 	 * at the beginning of delete operation. Release ordering is
 	 * paired with acquire ordering on load in counter increment operation.
 	 */
-	p = &counters->mae_counters[counter->mae_id.id];
+	p = &counters->mae_counters[mae_counter->id];
 	__atomic_store_n(&p->inuse, false, __ATOMIC_RELEASE);
 
-	rc = efx_mae_counters_free(sa->nic, 1, &unused, &counter->mae_id, NULL);
+	rc = efx_mae_counters_free(sa->nic, 1, &unused, mae_counter, NULL);
 	if (rc != 0)
 		sfc_err(sa, "failed to free MAE counter %u: %s",
-			counter->mae_id.id, rte_strerror(rc));
+			mae_counter->id, rte_strerror(rc));
 
 	sfc_info(sa, "disabled MAE counter #%u with reset pkts=%" PRIu64
-		 " bytes=%" PRIu64, counter->mae_id.id,
+		 " bytes=%" PRIu64, mae_counter->id,
 		 p->reset.pkts, p->reset.bytes);
 
 	/*
@@ -182,7 +180,7 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 	 * If there's some error, the resulting resource leakage is bad, but
 	 * nothing sensible can be done in this case.
 	 */
-	counter->mae_id.id = EFX_MAE_RSRC_ID_INVALID;
+	mae_counter->id = EFX_MAE_RSRC_ID_INVALID;
 
 	return rc;
 }
@@ -952,8 +950,8 @@ sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
 	struct sfc_mae_counter_record *p;
 	union sfc_pkts_bytes value;
 
-	SFC_ASSERT(counter->mae_id.id < counters->n_mae_counters);
-	p = &counters->mae_counters[counter->mae_id.id];
+	SFC_ASSERT(counter->fw_rsrc.counter_id.id < counters->n_mae_counters);
+	p = &counters->mae_counters[counter->fw_rsrc.counter_id.id];
 
 	/*
 	 * Ordering is relaxed since it is the only operation on counter value.
