0001
0002
0003
0004
0005
0006
0007
0008
0009
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
0021
0022
0023
0024 if (in_hw) {
0025 efx_mae_free_action_set(efx, act->fw_id);
0026
0027
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
0041
0042
0043
0044 if (in_hw)
0045 efx_mae_free_action_set_list(efx, acts);
0046
0047 list_for_each_entry_safe(act, next, &acts->list, list)
0048 efx_tc_free_action_set(efx, act, true);
0049
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
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
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
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 }