Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /****************************************************************************
0003  * Driver for Solarflare network controllers and boards
0004  * Copyright 2019 Solarflare Communications Inc.
0005  * Copyright 2020-2022 Xilinx Inc.
0006  *
0007  * This program is free software; you can redistribute it and/or modify it
0008  * under the terms of the GNU General Public License version 2 as published
0009  * by the Free Software Foundation, incorporated herein by reference.
0010  */
0011 
0012 #include "tc.h"
0013 #include "mae.h"
0014 #include "ef100_rep.h"
0015 #include "efx.h"
0016 
0017 static void efx_tc_free_action_set(struct efx_nic *efx,
0018                    struct efx_tc_action_set *act, bool in_hw)
0019 {
0020     /* Failure paths calling this on the 'running action' set in_hw=false,
0021      * because if the alloc had succeeded we'd've put it in acts.list and
0022      * not still have it in act.
0023      */
0024     if (in_hw) {
0025         efx_mae_free_action_set(efx, act->fw_id);
0026         /* in_hw is true iff we are on an acts.list; make sure to
0027          * remove ourselves from that list before we are freed.
0028          */
0029         list_del(&act->list);
0030     }
0031     kfree(act);
0032 }
0033 
0034 static void efx_tc_free_action_set_list(struct efx_nic *efx,
0035                     struct efx_tc_action_set_list *acts,
0036                     bool in_hw)
0037 {
0038     struct efx_tc_action_set *act, *next;
0039 
0040     /* Failure paths set in_hw=false, because usually the acts didn't get
0041      * to efx_mae_alloc_action_set_list(); if they did, the failure tree
0042      * has a separate efx_mae_free_action_set_list() before calling us.
0043      */
0044     if (in_hw)
0045         efx_mae_free_action_set_list(efx, acts);
0046     /* Any act that's on the list will be in_hw even if the list isn't */
0047     list_for_each_entry_safe(act, next, &acts->list, list)
0048         efx_tc_free_action_set(efx, act, true);
0049     /* Don't kfree, as acts is embedded inside a struct efx_tc_flow_rule */
0050 }
0051 
0052 static void efx_tc_delete_rule(struct efx_nic *efx, struct efx_tc_flow_rule *rule)
0053 {
0054     efx_mae_delete_rule(efx, rule->fw_id);
0055 
0056     /* Release entries in subsidiary tables */
0057     efx_tc_free_action_set_list(efx, &rule->acts, true);
0058     rule->fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL;
0059 }
0060 
0061 static int efx_tc_configure_default_rule(struct efx_nic *efx, u32 ing_port,
0062                      u32 eg_port, struct efx_tc_flow_rule *rule)
0063 {
0064     struct efx_tc_action_set_list *acts = &rule->acts;
0065     struct efx_tc_match *match = &rule->match;
0066     struct efx_tc_action_set *act;
0067     int rc;
0068 
0069     match->value.ingress_port = ing_port;
0070     match->mask.ingress_port = ~0;
0071     act = kzalloc(sizeof(*act), GFP_KERNEL);
0072     if (!act)
0073         return -ENOMEM;
0074     act->deliver = 1;
0075     act->dest_mport = eg_port;
0076     rc = efx_mae_alloc_action_set(efx, act);
0077     if (rc)
0078         goto fail1;
0079     EFX_WARN_ON_PARANOID(!list_empty(&acts->list));
0080     list_add_tail(&act->list, &acts->list);
0081     rc = efx_mae_alloc_action_set_list(efx, acts);
0082     if (rc)
0083         goto fail2;
0084     rc = efx_mae_insert_rule(efx, match, EFX_TC_PRIO_DFLT,
0085                  acts->fw_id, &rule->fw_id);
0086     if (rc)
0087         goto fail3;
0088     return 0;
0089 fail3:
0090     efx_mae_free_action_set_list(efx, acts);
0091 fail2:
0092     list_del(&act->list);
0093     efx_mae_free_action_set(efx, act->fw_id);
0094 fail1:
0095     kfree(act);
0096     return rc;
0097 }
0098 
0099 static int efx_tc_configure_default_rule_pf(struct efx_nic *efx)
0100 {
0101     struct efx_tc_flow_rule *rule = &efx->tc->dflt.pf;
0102     u32 ing_port, eg_port;
0103 
0104     efx_mae_mport_uplink(efx, &ing_port);
0105     efx_mae_mport_wire(efx, &eg_port);
0106     return efx_tc_configure_default_rule(efx, ing_port, eg_port, rule);
0107 }
0108 
0109 static int efx_tc_configure_default_rule_wire(struct efx_nic *efx)
0110 {
0111     struct efx_tc_flow_rule *rule = &efx->tc->dflt.wire;
0112     u32 ing_port, eg_port;
0113 
0114     efx_mae_mport_wire(efx, &ing_port);
0115     efx_mae_mport_uplink(efx, &eg_port);
0116     return efx_tc_configure_default_rule(efx, ing_port, eg_port, rule);
0117 }
0118 
0119 int efx_tc_configure_default_rule_rep(struct efx_rep *efv)
0120 {
0121     struct efx_tc_flow_rule *rule = &efv->dflt;
0122     struct efx_nic *efx = efv->parent;
0123     u32 ing_port, eg_port;
0124 
0125     efx_mae_mport_mport(efx, efv->mport, &ing_port);
0126     efx_mae_mport_mport(efx, efx->tc->reps_mport_id, &eg_port);
0127     return efx_tc_configure_default_rule(efx, ing_port, eg_port, rule);
0128 }
0129 
0130 void efx_tc_deconfigure_default_rule(struct efx_nic *efx,
0131                      struct efx_tc_flow_rule *rule)
0132 {
0133     if (rule->fw_id != MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL)
0134         efx_tc_delete_rule(efx, rule);
0135     rule->fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL;
0136 }
0137 
0138 static int efx_tc_configure_rep_mport(struct efx_nic *efx)
0139 {
0140     u32 rep_mport_label;
0141     int rc;
0142 
0143     rc = efx_mae_allocate_mport(efx, &efx->tc->reps_mport_id, &rep_mport_label);
0144     if (rc)
0145         return rc;
0146     pci_dbg(efx->pci_dev, "created rep mport 0x%08x (0x%04x)\n",
0147         efx->tc->reps_mport_id, rep_mport_label);
0148     /* Use mport *selector* as vport ID */
0149     efx_mae_mport_mport(efx, efx->tc->reps_mport_id,
0150                 &efx->tc->reps_mport_vport_id);
0151     return 0;
0152 }
0153 
0154 static void efx_tc_deconfigure_rep_mport(struct efx_nic *efx)
0155 {
0156     efx_mae_free_mport(efx, efx->tc->reps_mport_id);
0157     efx->tc->reps_mport_id = MAE_MPORT_SELECTOR_NULL;
0158 }
0159 
0160 int efx_tc_insert_rep_filters(struct efx_nic *efx)
0161 {
0162     struct efx_filter_spec promisc, allmulti;
0163     int rc;
0164 
0165     if (efx->type->is_vf)
0166         return 0;
0167     if (!efx->tc)
0168         return 0;
0169     efx_filter_init_rx(&promisc, EFX_FILTER_PRI_REQUIRED, 0, 0);
0170     efx_filter_set_uc_def(&promisc);
0171     efx_filter_set_vport_id(&promisc, efx->tc->reps_mport_vport_id);
0172     rc = efx_filter_insert_filter(efx, &promisc, false);
0173     if (rc < 0)
0174         return rc;
0175     efx->tc->reps_filter_uc = rc;
0176     efx_filter_init_rx(&allmulti, EFX_FILTER_PRI_REQUIRED, 0, 0);
0177     efx_filter_set_mc_def(&allmulti);
0178     efx_filter_set_vport_id(&allmulti, efx->tc->reps_mport_vport_id);
0179     rc = efx_filter_insert_filter(efx, &allmulti, false);
0180     if (rc < 0)
0181         return rc;
0182     efx->tc->reps_filter_mc = rc;
0183     return 0;
0184 }
0185 
0186 void efx_tc_remove_rep_filters(struct efx_nic *efx)
0187 {
0188     if (efx->type->is_vf)
0189         return;
0190     if (!efx->tc)
0191         return;
0192     if (efx->tc->reps_filter_mc >= 0)
0193         efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED, efx->tc->reps_filter_mc);
0194     efx->tc->reps_filter_mc = -1;
0195     if (efx->tc->reps_filter_uc >= 0)
0196         efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED, efx->tc->reps_filter_uc);
0197     efx->tc->reps_filter_uc = -1;
0198 }
0199 
0200 int efx_init_tc(struct efx_nic *efx)
0201 {
0202     int rc;
0203 
0204     rc = efx_tc_configure_default_rule_pf(efx);
0205     if (rc)
0206         return rc;
0207     rc = efx_tc_configure_default_rule_wire(efx);
0208     if (rc)
0209         return rc;
0210     return efx_tc_configure_rep_mport(efx);
0211 }
0212 
0213 void efx_fini_tc(struct efx_nic *efx)
0214 {
0215     /* We can get called even if efx_init_struct_tc() failed */
0216     if (!efx->tc)
0217         return;
0218     efx_tc_deconfigure_rep_mport(efx);
0219     efx_tc_deconfigure_default_rule(efx, &efx->tc->dflt.pf);
0220     efx_tc_deconfigure_default_rule(efx, &efx->tc->dflt.wire);
0221 }
0222 
0223 int efx_init_struct_tc(struct efx_nic *efx)
0224 {
0225     if (efx->type->is_vf)
0226         return 0;
0227 
0228     efx->tc = kzalloc(sizeof(*efx->tc), GFP_KERNEL);
0229     if (!efx->tc)
0230         return -ENOMEM;
0231 
0232     efx->tc->reps_filter_uc = -1;
0233     efx->tc->reps_filter_mc = -1;
0234     INIT_LIST_HEAD(&efx->tc->dflt.pf.acts.list);
0235     efx->tc->dflt.pf.fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL;
0236     INIT_LIST_HEAD(&efx->tc->dflt.wire.acts.list);
0237     efx->tc->dflt.wire.fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL;
0238     return 0;
0239 }
0240 
0241 void efx_fini_struct_tc(struct efx_nic *efx)
0242 {
0243     if (!efx->tc)
0244         return;
0245 
0246     EFX_WARN_ON_PARANOID(efx->tc->dflt.pf.fw_id !=
0247                  MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL);
0248     EFX_WARN_ON_PARANOID(efx->tc->dflt.wire.fw_id !=
0249                  MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL);
0250     kfree(efx->tc);
0251     efx->tc = NULL;
0252 }