0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include "mae.h"
0013 #include "mcdi.h"
0014 #include "mcdi_pcol_mae.h"
0015
0016 int efx_mae_allocate_mport(struct efx_nic *efx, u32 *id, u32 *label)
0017 {
0018 MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LEN);
0019 MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_LEN);
0020 size_t outlen;
0021 int rc;
0022
0023 if (WARN_ON_ONCE(!id))
0024 return -EINVAL;
0025 if (WARN_ON_ONCE(!label))
0026 return -EINVAL;
0027
0028 MCDI_SET_DWORD(inbuf, MAE_MPORT_ALLOC_ALIAS_IN_TYPE,
0029 MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_MPORT_TYPE_ALIAS);
0030 MCDI_SET_DWORD(inbuf, MAE_MPORT_ALLOC_ALIAS_IN_DELIVER_MPORT,
0031 MAE_MPORT_SELECTOR_ASSIGNED);
0032 rc = efx_mcdi_rpc(efx, MC_CMD_MAE_MPORT_ALLOC, inbuf, sizeof(inbuf),
0033 outbuf, sizeof(outbuf), &outlen);
0034 if (rc)
0035 return rc;
0036 if (outlen < sizeof(outbuf))
0037 return -EIO;
0038 *id = MCDI_DWORD(outbuf, MAE_MPORT_ALLOC_ALIAS_OUT_MPORT_ID);
0039 *label = MCDI_DWORD(outbuf, MAE_MPORT_ALLOC_ALIAS_OUT_LABEL);
0040 return 0;
0041 }
0042
0043 int efx_mae_free_mport(struct efx_nic *efx, u32 id)
0044 {
0045 MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_MPORT_FREE_IN_LEN);
0046
0047 BUILD_BUG_ON(MC_CMD_MAE_MPORT_FREE_OUT_LEN);
0048 MCDI_SET_DWORD(inbuf, MAE_MPORT_FREE_IN_MPORT_ID, id);
0049 return efx_mcdi_rpc(efx, MC_CMD_MAE_MPORT_FREE, inbuf, sizeof(inbuf),
0050 NULL, 0, NULL);
0051 }
0052
0053 void efx_mae_mport_wire(struct efx_nic *efx, u32 *out)
0054 {
0055 efx_dword_t mport;
0056
0057 EFX_POPULATE_DWORD_2(mport,
0058 MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_PPORT,
0059 MAE_MPORT_SELECTOR_PPORT_ID, efx->port_num);
0060 *out = EFX_DWORD_VAL(mport);
0061 }
0062
0063 void efx_mae_mport_uplink(struct efx_nic *efx __always_unused, u32 *out)
0064 {
0065 efx_dword_t mport;
0066
0067 EFX_POPULATE_DWORD_3(mport,
0068 MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_FUNC,
0069 MAE_MPORT_SELECTOR_FUNC_PF_ID, MAE_MPORT_SELECTOR_FUNC_PF_ID_CALLER,
0070 MAE_MPORT_SELECTOR_FUNC_VF_ID, MAE_MPORT_SELECTOR_FUNC_VF_ID_NULL);
0071 *out = EFX_DWORD_VAL(mport);
0072 }
0073
0074 void efx_mae_mport_vf(struct efx_nic *efx __always_unused, u32 vf_id, u32 *out)
0075 {
0076 efx_dword_t mport;
0077
0078 EFX_POPULATE_DWORD_3(mport,
0079 MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_FUNC,
0080 MAE_MPORT_SELECTOR_FUNC_PF_ID, MAE_MPORT_SELECTOR_FUNC_PF_ID_CALLER,
0081 MAE_MPORT_SELECTOR_FUNC_VF_ID, vf_id);
0082 *out = EFX_DWORD_VAL(mport);
0083 }
0084
0085
0086 void efx_mae_mport_mport(struct efx_nic *efx __always_unused, u32 mport_id, u32 *out)
0087 {
0088 efx_dword_t mport;
0089
0090 EFX_POPULATE_DWORD_2(mport,
0091 MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_MPORT_ID,
0092 MAE_MPORT_SELECTOR_MPORT_ID, mport_id);
0093 *out = EFX_DWORD_VAL(mport);
0094 }
0095
0096
0097 int efx_mae_lookup_mport(struct efx_nic *efx, u32 selector, u32 *id)
0098 {
0099 MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_MPORT_LOOKUP_OUT_LEN);
0100 MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_MPORT_LOOKUP_IN_LEN);
0101 size_t outlen;
0102 int rc;
0103
0104 MCDI_SET_DWORD(inbuf, MAE_MPORT_LOOKUP_IN_MPORT_SELECTOR, selector);
0105 rc = efx_mcdi_rpc(efx, MC_CMD_MAE_MPORT_LOOKUP, inbuf, sizeof(inbuf),
0106 outbuf, sizeof(outbuf), &outlen);
0107 if (rc)
0108 return rc;
0109 if (outlen < sizeof(outbuf))
0110 return -EIO;
0111 *id = MCDI_DWORD(outbuf, MAE_MPORT_LOOKUP_OUT_MPORT_ID);
0112 return 0;
0113 }
0114
0115 static bool efx_mae_asl_id(u32 id)
0116 {
0117 return !!(id & BIT(31));
0118 }
0119
0120 int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act)
0121 {
0122 MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN);
0123 MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ACTION_SET_ALLOC_IN_LEN);
0124 size_t outlen;
0125 int rc;
0126
0127 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID,
0128 MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL);
0129 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID,
0130 MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL);
0131 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_COUNTER_ID,
0132 MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_NULL);
0133 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID,
0134 MC_CMD_MAE_COUNTER_LIST_ALLOC_OUT_COUNTER_LIST_ID_NULL);
0135 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID,
0136 MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL);
0137 if (act->deliver)
0138 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DELIVER,
0139 act->dest_mport);
0140 BUILD_BUG_ON(MAE_MPORT_SELECTOR_NULL);
0141 rc = efx_mcdi_rpc(efx, MC_CMD_MAE_ACTION_SET_ALLOC, inbuf, sizeof(inbuf),
0142 outbuf, sizeof(outbuf), &outlen);
0143 if (rc)
0144 return rc;
0145 if (outlen < sizeof(outbuf))
0146 return -EIO;
0147 act->fw_id = MCDI_DWORD(outbuf, MAE_ACTION_SET_ALLOC_OUT_AS_ID);
0148
0149
0150
0151 if (WARN_ON_ONCE(efx_mae_asl_id(act->fw_id))) {
0152 efx_mae_free_action_set(efx, act->fw_id);
0153 return -EIO;
0154 }
0155 return 0;
0156 }
0157
0158 int efx_mae_free_action_set(struct efx_nic *efx, u32 fw_id)
0159 {
0160 MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_SET_FREE_OUT_LEN(1));
0161 MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ACTION_SET_FREE_IN_LEN(1));
0162 size_t outlen;
0163 int rc;
0164
0165 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_FREE_IN_AS_ID, fw_id);
0166 rc = efx_mcdi_rpc(efx, MC_CMD_MAE_ACTION_SET_FREE, inbuf, sizeof(inbuf),
0167 outbuf, sizeof(outbuf), &outlen);
0168 if (rc)
0169 return rc;
0170 if (outlen < sizeof(outbuf))
0171 return -EIO;
0172
0173
0174
0175
0176 if (WARN_ON(MCDI_DWORD(outbuf, MAE_ACTION_SET_FREE_OUT_FREED_AS_ID) != fw_id))
0177 return -EIO;
0178 return 0;
0179 }
0180
0181 int efx_mae_alloc_action_set_list(struct efx_nic *efx,
0182 struct efx_tc_action_set_list *acts)
0183 {
0184 MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_LEN);
0185 struct efx_tc_action_set *act;
0186 size_t inlen, outlen, i = 0;
0187 efx_dword_t *inbuf;
0188 int rc;
0189
0190 list_for_each_entry(act, &acts->list, list)
0191 i++;
0192 if (i == 0)
0193 return -EINVAL;
0194 if (i == 1) {
0195
0196
0197
0198 act = list_first_entry(&acts->list, struct efx_tc_action_set, list);
0199 acts->fw_id = act->fw_id;
0200 return 0;
0201 }
0202 if (i > MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS_MAXNUM_MCDI2)
0203 return -EOPNOTSUPP;
0204 inlen = MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LEN(i);
0205 inbuf = kzalloc(inlen, GFP_KERNEL);
0206 if (!inbuf)
0207 return -ENOMEM;
0208 i = 0;
0209 list_for_each_entry(act, &acts->list, list) {
0210 MCDI_SET_ARRAY_DWORD(inbuf, MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS,
0211 i, act->fw_id);
0212 i++;
0213 }
0214 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_LIST_ALLOC_IN_COUNT, i);
0215 rc = efx_mcdi_rpc(efx, MC_CMD_MAE_ACTION_SET_LIST_ALLOC, inbuf, inlen,
0216 outbuf, sizeof(outbuf), &outlen);
0217 if (rc)
0218 goto out_free;
0219 if (outlen < sizeof(outbuf)) {
0220 rc = -EIO;
0221 goto out_free;
0222 }
0223 acts->fw_id = MCDI_DWORD(outbuf, MAE_ACTION_SET_LIST_ALLOC_OUT_ASL_ID);
0224
0225
0226
0227 if (WARN_ON_ONCE(!efx_mae_asl_id(acts->fw_id))) {
0228 efx_mae_free_action_set_list(efx, acts);
0229 rc = -EIO;
0230 }
0231 out_free:
0232 kfree(inbuf);
0233 return rc;
0234 }
0235
0236 int efx_mae_free_action_set_list(struct efx_nic *efx,
0237 struct efx_tc_action_set_list *acts)
0238 {
0239 MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_LEN(1));
0240 MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_LEN(1));
0241 size_t outlen;
0242 int rc;
0243
0244
0245
0246
0247 if (efx_mae_asl_id(acts->fw_id)) {
0248 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_LIST_FREE_IN_ASL_ID,
0249 acts->fw_id);
0250 rc = efx_mcdi_rpc(efx, MC_CMD_MAE_ACTION_SET_LIST_FREE, inbuf,
0251 sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
0252 if (rc)
0253 return rc;
0254 if (outlen < sizeof(outbuf))
0255 return -EIO;
0256
0257
0258
0259
0260 if (WARN_ON(MCDI_DWORD(outbuf, MAE_ACTION_SET_LIST_FREE_OUT_FREED_ASL_ID) != acts->fw_id))
0261 return -EIO;
0262 }
0263
0264
0265
0266 acts->fw_id = MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL;
0267 return 0;
0268 }
0269
0270 static int efx_mae_populate_match_criteria(MCDI_DECLARE_STRUCT_PTR(match_crit),
0271 const struct efx_tc_match *match)
0272 {
0273 if (match->mask.ingress_port) {
0274 if (~match->mask.ingress_port)
0275 return -EOPNOTSUPP;
0276 MCDI_STRUCT_SET_DWORD(match_crit,
0277 MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR,
0278 match->value.ingress_port);
0279 }
0280 MCDI_STRUCT_SET_DWORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR_MASK,
0281 match->mask.ingress_port);
0282 return 0;
0283 }
0284
0285 int efx_mae_insert_rule(struct efx_nic *efx, const struct efx_tc_match *match,
0286 u32 prio, u32 acts_id, u32 *id)
0287 {
0288 MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ACTION_RULE_INSERT_IN_LEN(MAE_FIELD_MASK_VALUE_PAIRS_V2_LEN));
0289 MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN);
0290 MCDI_DECLARE_STRUCT_PTR(match_crit);
0291 MCDI_DECLARE_STRUCT_PTR(response);
0292 size_t outlen;
0293 int rc;
0294
0295 if (!id)
0296 return -EINVAL;
0297
0298 match_crit = _MCDI_DWORD(inbuf, MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA);
0299 response = _MCDI_DWORD(inbuf, MAE_ACTION_RULE_INSERT_IN_RESPONSE);
0300 if (efx_mae_asl_id(acts_id)) {
0301 MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_ASL_ID, acts_id);
0302 MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_AS_ID,
0303 MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL);
0304 } else {
0305
0306 MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_ASL_ID,
0307 MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL);
0308 MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_AS_ID, acts_id);
0309 }
0310 MCDI_SET_DWORD(inbuf, MAE_ACTION_RULE_INSERT_IN_PRIO, prio);
0311 rc = efx_mae_populate_match_criteria(match_crit, match);
0312 if (rc)
0313 return rc;
0314
0315 rc = efx_mcdi_rpc(efx, MC_CMD_MAE_ACTION_RULE_INSERT, inbuf, sizeof(inbuf),
0316 outbuf, sizeof(outbuf), &outlen);
0317 if (rc)
0318 return rc;
0319 if (outlen < sizeof(outbuf))
0320 return -EIO;
0321 *id = MCDI_DWORD(outbuf, MAE_ACTION_RULE_INSERT_OUT_AR_ID);
0322 return 0;
0323 }
0324
0325 int efx_mae_delete_rule(struct efx_nic *efx, u32 id)
0326 {
0327 MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(1));
0328 MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ACTION_RULE_DELETE_IN_LEN(1));
0329 size_t outlen;
0330 int rc;
0331
0332 MCDI_SET_DWORD(inbuf, MAE_ACTION_RULE_DELETE_IN_AR_ID, id);
0333 rc = efx_mcdi_rpc(efx, MC_CMD_MAE_ACTION_RULE_DELETE, inbuf, sizeof(inbuf),
0334 outbuf, sizeof(outbuf), &outlen);
0335 if (rc)
0336 return rc;
0337 if (outlen < sizeof(outbuf))
0338 return -EIO;
0339
0340
0341
0342
0343 if (WARN_ON(MCDI_DWORD(outbuf, MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID) != id))
0344 return -EIO;
0345 return 0;
0346 }