+
+static int
+sfc_mae_query_counter(struct sfc_adapter *sa,
+ struct sfc_flow_spec_mae *spec,
+ const struct rte_flow_action *action,
+ struct rte_flow_query_count *data,
+ struct rte_flow_error *error)
+{
+ struct sfc_mae_action_set *action_set = spec->action_set;
+ const struct rte_flow_action_count *conf = action->conf;
+ unsigned int i;
+ int rc;
+
+ if (action_set->n_counters == 0) {
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, action,
+ "Queried flow rule does not have count actions");
+ }
+
+ for (i = 0; i < action_set->n_counters; i++) {
+ /*
+ * Get the first available counter of the flow rule if
+ * counter ID is not specified.
+ */
+ if (conf != NULL && action_set->counters[i].rte_id != conf->id)
+ continue;
+
+ rc = sfc_mae_counter_get(&sa->mae.counter_registry.counters,
+ &action_set->counters[i], data);
+ if (rc != 0) {
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, action,
+ "Queried flow rule counter action is invalid");
+ }
+
+ return 0;
+ }
+
+ return rte_flow_error_set(error, ENOENT,
+ RTE_FLOW_ERROR_TYPE_ACTION, action,
+ "No such flow rule action count ID");
+}
+
+int
+sfc_mae_flow_query(struct rte_eth_dev *dev,
+ struct rte_flow *flow,
+ const struct rte_flow_action *action,
+ void *data,
+ struct rte_flow_error *error)
+{
+ struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+ struct sfc_flow_spec *spec = &flow->spec;
+ struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+
+ switch (action->type) {
+ case RTE_FLOW_ACTION_TYPE_COUNT:
+ return sfc_mae_query_counter(sa, spec_mae, action,
+ data, error);
+ default:
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "Query for action of this type is not supported");
+ }
+}
+
+int
+sfc_mae_switchdev_init(struct sfc_adapter *sa)
+{
+ const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+ struct sfc_mae *mae = &sa->mae;
+ efx_mport_sel_t pf;
+ efx_mport_sel_t phy;
+ int rc;
+
+ sfc_log_init(sa, "entry");
+
+ if (!sa->switchdev) {
+ sfc_log_init(sa, "switchdev is not enabled - skip");
+ return 0;
+ }
+
+ if (mae->status != SFC_MAE_STATUS_SUPPORTED) {
+ rc = ENOTSUP;
+ sfc_err(sa, "failed to init switchdev - no MAE support");
+ goto fail_no_mae;
+ }
+
+ rc = efx_mae_mport_by_pcie_function(encp->enc_pf, EFX_PCI_VF_INVALID,
+ &pf);
+ if (rc != 0) {
+ sfc_err(sa, "failed get PF mport");
+ goto fail_pf_get;
+ }
+
+ rc = efx_mae_mport_by_phy_port(encp->enc_assigned_port, &phy);
+ if (rc != 0) {
+ sfc_err(sa, "failed get PHY mport");
+ goto fail_phy_get;
+ }
+
+ rc = sfc_mae_rule_add_mport_match_deliver(sa, &pf, &phy,
+ SFC_MAE_RULE_PRIO_LOWEST,
+ &mae->switchdev_rule_pf_to_ext);
+ if (rc != 0) {
+ sfc_err(sa, "failed add MAE rule to forward from PF to PHY");
+ goto fail_pf_add;
+ }
+
+ rc = sfc_mae_rule_add_mport_match_deliver(sa, &phy, &pf,
+ SFC_MAE_RULE_PRIO_LOWEST,
+ &mae->switchdev_rule_ext_to_pf);
+ if (rc != 0) {
+ sfc_err(sa, "failed add MAE rule to forward from PHY to PF");
+ goto fail_phy_add;
+ }
+
+ sfc_log_init(sa, "done");
+
+ return 0;
+
+fail_phy_add:
+ sfc_mae_rule_del(sa, mae->switchdev_rule_pf_to_ext);
+
+fail_pf_add:
+fail_phy_get:
+fail_pf_get:
+fail_no_mae:
+ sfc_log_init(sa, "failed: %s", rte_strerror(rc));
+ return rc;
+}
+
+void
+sfc_mae_switchdev_fini(struct sfc_adapter *sa)
+{
+ struct sfc_mae *mae = &sa->mae;
+
+ if (!sa->switchdev)
+ return;
+
+ sfc_mae_rule_del(sa, mae->switchdev_rule_pf_to_ext);
+ sfc_mae_rule_del(sa, mae->switchdev_rule_ext_to_pf);
+}