1 /* SPDX-License-Identifier: BSD-3-Clause 2 * 3 * Copyright(c) 2019-2021 Xilinx, Inc. 4 */ 5 6 #include "efx.h" 7 #include "efx_impl.h" 8 9 10 #if EFSYS_OPT_MAE 11 12 static __checkReturn efx_rc_t 13 efx_mae_get_capabilities( 14 __in efx_nic_t *enp) 15 { 16 efx_mcdi_req_t req; 17 EFX_MCDI_DECLARE_BUF(payload, 18 MC_CMD_MAE_GET_CAPS_IN_LEN, 19 MC_CMD_MAE_GET_CAPS_V2_OUT_LEN); 20 struct efx_mae_s *maep = enp->en_maep; 21 efx_rc_t rc; 22 23 req.emr_cmd = MC_CMD_MAE_GET_CAPS; 24 req.emr_in_buf = payload; 25 req.emr_in_length = MC_CMD_MAE_GET_CAPS_IN_LEN; 26 req.emr_out_buf = payload; 27 req.emr_out_length = MC_CMD_MAE_GET_CAPS_V2_OUT_LEN; 28 29 efx_mcdi_execute(enp, &req); 30 31 if (req.emr_rc != 0) { 32 rc = req.emr_rc; 33 goto fail1; 34 } 35 36 if (req.emr_out_length_used < MC_CMD_MAE_GET_CAPS_OUT_LEN) { 37 rc = EMSGSIZE; 38 goto fail2; 39 } 40 41 maep->em_max_n_outer_prios = 42 MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_OUTER_PRIOS); 43 44 maep->em_max_n_action_prios = 45 MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_ACTION_PRIOS); 46 47 maep->em_encap_types_supported = 0; 48 49 if (MCDI_OUT_DWORD_FIELD(req, MAE_GET_CAPS_OUT_ENCAP_TYPES_SUPPORTED, 50 MAE_GET_CAPS_OUT_ENCAP_TYPE_VXLAN) != 0) { 51 maep->em_encap_types_supported |= 52 (1U << EFX_TUNNEL_PROTOCOL_VXLAN); 53 } 54 55 if (MCDI_OUT_DWORD_FIELD(req, MAE_GET_CAPS_OUT_ENCAP_TYPES_SUPPORTED, 56 MAE_GET_CAPS_OUT_ENCAP_TYPE_GENEVE) != 0) { 57 maep->em_encap_types_supported |= 58 (1U << EFX_TUNNEL_PROTOCOL_GENEVE); 59 } 60 61 if (MCDI_OUT_DWORD_FIELD(req, MAE_GET_CAPS_OUT_ENCAP_TYPES_SUPPORTED, 62 MAE_GET_CAPS_OUT_ENCAP_TYPE_NVGRE) != 0) { 63 maep->em_encap_types_supported |= 64 (1U << EFX_TUNNEL_PROTOCOL_NVGRE); 65 } 66 67 maep->em_max_nfields = 68 MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_MATCH_FIELD_COUNT); 69 70 maep->em_max_n_action_counters = 71 MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_AR_COUNTERS); 72 73 if (req.emr_out_length_used >= MC_CMD_MAE_GET_CAPS_V2_OUT_LEN) { 74 maep->em_max_n_conntrack_counters = 75 MCDI_OUT_DWORD(req, MAE_GET_CAPS_V2_OUT_CT_COUNTERS); 76 } else { 77 maep->em_max_n_conntrack_counters = 0; 78 } 79 80 return (0); 81 82 fail2: 83 EFSYS_PROBE(fail2); 84 fail1: 85 EFSYS_PROBE1(fail1, efx_rc_t, rc); 86 return (rc); 87 } 88 89 static __checkReturn efx_rc_t 90 efx_mae_get_outer_rule_caps( 91 __in efx_nic_t *enp, 92 __in unsigned int field_ncaps, 93 __out_ecount(field_ncaps) efx_mae_field_cap_t *field_caps) 94 { 95 efx_mcdi_req_t req; 96 EFX_MCDI_DECLARE_BUF(payload, 97 MC_CMD_MAE_GET_OR_CAPS_IN_LEN, 98 MC_CMD_MAE_GET_OR_CAPS_OUT_LENMAX_MCDI2); 99 unsigned int mcdi_field_ncaps; 100 unsigned int i; 101 efx_rc_t rc; 102 103 if (MC_CMD_MAE_GET_OR_CAPS_OUT_LEN(field_ncaps) > 104 MC_CMD_MAE_GET_OR_CAPS_OUT_LENMAX_MCDI2) { 105 rc = EINVAL; 106 goto fail1; 107 } 108 109 req.emr_cmd = MC_CMD_MAE_GET_OR_CAPS; 110 req.emr_in_buf = payload; 111 req.emr_in_length = MC_CMD_MAE_GET_OR_CAPS_IN_LEN; 112 req.emr_out_buf = payload; 113 req.emr_out_length = MC_CMD_MAE_GET_OR_CAPS_OUT_LEN(field_ncaps); 114 115 efx_mcdi_execute(enp, &req); 116 117 if (req.emr_rc != 0) { 118 rc = req.emr_rc; 119 goto fail2; 120 } 121 122 if (req.emr_out_length_used < MC_CMD_MAE_GET_OR_CAPS_OUT_LENMIN) { 123 rc = EMSGSIZE; 124 goto fail3; 125 } 126 127 mcdi_field_ncaps = MCDI_OUT_DWORD(req, MAE_GET_OR_CAPS_OUT_COUNT); 128 129 if (req.emr_out_length_used < 130 MC_CMD_MAE_GET_OR_CAPS_OUT_LEN(mcdi_field_ncaps)) { 131 rc = EMSGSIZE; 132 goto fail4; 133 } 134 135 if (mcdi_field_ncaps > field_ncaps) { 136 rc = EMSGSIZE; 137 goto fail5; 138 } 139 140 for (i = 0; i < mcdi_field_ncaps; ++i) { 141 uint32_t match_flag; 142 uint32_t mask_flag; 143 144 field_caps[i].emfc_support = MCDI_OUT_INDEXED_DWORD_FIELD(req, 145 MAE_GET_OR_CAPS_OUT_FIELD_FLAGS, i, 146 MAE_FIELD_FLAGS_SUPPORT_STATUS); 147 148 match_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req, 149 MAE_GET_OR_CAPS_OUT_FIELD_FLAGS, i, 150 MAE_FIELD_FLAGS_MATCH_AFFECTS_CLASS); 151 152 field_caps[i].emfc_match_affects_class = 153 (match_flag != 0) ? B_TRUE : B_FALSE; 154 155 mask_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req, 156 MAE_GET_OR_CAPS_OUT_FIELD_FLAGS, i, 157 MAE_FIELD_FLAGS_MASK_AFFECTS_CLASS); 158 159 field_caps[i].emfc_mask_affects_class = 160 (mask_flag != 0) ? B_TRUE : B_FALSE; 161 } 162 163 return (0); 164 165 fail5: 166 EFSYS_PROBE(fail5); 167 fail4: 168 EFSYS_PROBE(fail4); 169 fail3: 170 EFSYS_PROBE(fail3); 171 fail2: 172 EFSYS_PROBE(fail2); 173 fail1: 174 EFSYS_PROBE1(fail1, efx_rc_t, rc); 175 return (rc); 176 } 177 178 static __checkReturn efx_rc_t 179 efx_mae_get_action_rule_caps( 180 __in efx_nic_t *enp, 181 __in unsigned int field_ncaps, 182 __out_ecount(field_ncaps) efx_mae_field_cap_t *field_caps) 183 { 184 efx_mcdi_req_t req; 185 EFX_MCDI_DECLARE_BUF(payload, 186 MC_CMD_MAE_GET_AR_CAPS_IN_LEN, 187 MC_CMD_MAE_GET_AR_CAPS_OUT_LENMAX_MCDI2); 188 unsigned int mcdi_field_ncaps; 189 unsigned int i; 190 efx_rc_t rc; 191 192 if (MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(field_ncaps) > 193 MC_CMD_MAE_GET_AR_CAPS_OUT_LENMAX_MCDI2) { 194 rc = EINVAL; 195 goto fail1; 196 } 197 198 req.emr_cmd = MC_CMD_MAE_GET_AR_CAPS; 199 req.emr_in_buf = payload; 200 req.emr_in_length = MC_CMD_MAE_GET_AR_CAPS_IN_LEN; 201 req.emr_out_buf = payload; 202 req.emr_out_length = MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(field_ncaps); 203 204 efx_mcdi_execute(enp, &req); 205 206 if (req.emr_rc != 0) { 207 rc = req.emr_rc; 208 goto fail2; 209 } 210 211 if (req.emr_out_length_used < MC_CMD_MAE_GET_AR_CAPS_OUT_LENMIN) { 212 rc = EMSGSIZE; 213 goto fail3; 214 } 215 216 mcdi_field_ncaps = MCDI_OUT_DWORD(req, MAE_GET_AR_CAPS_OUT_COUNT); 217 218 if (req.emr_out_length_used < 219 MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(mcdi_field_ncaps)) { 220 rc = EMSGSIZE; 221 goto fail4; 222 } 223 224 if (mcdi_field_ncaps > field_ncaps) { 225 rc = EMSGSIZE; 226 goto fail5; 227 } 228 229 for (i = 0; i < mcdi_field_ncaps; ++i) { 230 uint32_t match_flag; 231 uint32_t mask_flag; 232 233 field_caps[i].emfc_support = MCDI_OUT_INDEXED_DWORD_FIELD(req, 234 MAE_GET_AR_CAPS_OUT_FIELD_FLAGS, i, 235 MAE_FIELD_FLAGS_SUPPORT_STATUS); 236 237 match_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req, 238 MAE_GET_AR_CAPS_OUT_FIELD_FLAGS, i, 239 MAE_FIELD_FLAGS_MATCH_AFFECTS_CLASS); 240 241 field_caps[i].emfc_match_affects_class = 242 (match_flag != 0) ? B_TRUE : B_FALSE; 243 244 mask_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req, 245 MAE_GET_AR_CAPS_OUT_FIELD_FLAGS, i, 246 MAE_FIELD_FLAGS_MASK_AFFECTS_CLASS); 247 248 field_caps[i].emfc_mask_affects_class = 249 (mask_flag != 0) ? B_TRUE : B_FALSE; 250 } 251 252 return (0); 253 254 fail5: 255 EFSYS_PROBE(fail5); 256 fail4: 257 EFSYS_PROBE(fail4); 258 fail3: 259 EFSYS_PROBE(fail3); 260 fail2: 261 EFSYS_PROBE(fail2); 262 fail1: 263 EFSYS_PROBE1(fail1, efx_rc_t, rc); 264 return (rc); 265 } 266 267 __checkReturn efx_rc_t 268 efx_mae_init( 269 __in efx_nic_t *enp) 270 { 271 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 272 efx_mae_field_cap_t *or_fcaps; 273 size_t or_fcaps_size; 274 efx_mae_field_cap_t *ar_fcaps; 275 size_t ar_fcaps_size; 276 efx_mae_t *maep; 277 efx_rc_t rc; 278 279 if (encp->enc_mae_supported == B_FALSE) { 280 rc = ENOTSUP; 281 goto fail1; 282 } 283 284 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*maep), maep); 285 if (maep == NULL) { 286 rc = ENOMEM; 287 goto fail2; 288 } 289 290 enp->en_maep = maep; 291 292 rc = efx_mae_get_capabilities(enp); 293 if (rc != 0) 294 goto fail3; 295 296 or_fcaps_size = maep->em_max_nfields * sizeof (*or_fcaps); 297 EFSYS_KMEM_ALLOC(enp->en_esip, or_fcaps_size, or_fcaps); 298 if (or_fcaps == NULL) { 299 rc = ENOMEM; 300 goto fail4; 301 } 302 303 maep->em_outer_rule_field_caps_size = or_fcaps_size; 304 maep->em_outer_rule_field_caps = or_fcaps; 305 306 rc = efx_mae_get_outer_rule_caps(enp, maep->em_max_nfields, or_fcaps); 307 if (rc != 0) 308 goto fail5; 309 310 ar_fcaps_size = maep->em_max_nfields * sizeof (*ar_fcaps); 311 EFSYS_KMEM_ALLOC(enp->en_esip, ar_fcaps_size, ar_fcaps); 312 if (ar_fcaps == NULL) { 313 rc = ENOMEM; 314 goto fail6; 315 } 316 317 maep->em_action_rule_field_caps_size = ar_fcaps_size; 318 maep->em_action_rule_field_caps = ar_fcaps; 319 320 rc = efx_mae_get_action_rule_caps(enp, maep->em_max_nfields, ar_fcaps); 321 if (rc != 0) 322 goto fail7; 323 324 return (0); 325 326 fail7: 327 EFSYS_PROBE(fail5); 328 EFSYS_KMEM_FREE(enp->en_esip, ar_fcaps_size, ar_fcaps); 329 fail6: 330 EFSYS_PROBE(fail4); 331 fail5: 332 EFSYS_PROBE(fail5); 333 EFSYS_KMEM_FREE(enp->en_esip, or_fcaps_size, or_fcaps); 334 fail4: 335 EFSYS_PROBE(fail4); 336 fail3: 337 EFSYS_PROBE(fail3); 338 EFSYS_KMEM_FREE(enp->en_esip, sizeof (struct efx_mae_s), enp->en_maep); 339 enp->en_maep = NULL; 340 fail2: 341 EFSYS_PROBE(fail2); 342 fail1: 343 EFSYS_PROBE1(fail1, efx_rc_t, rc); 344 return (rc); 345 } 346 347 void 348 efx_mae_fini( 349 __in efx_nic_t *enp) 350 { 351 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 352 efx_mae_t *maep = enp->en_maep; 353 354 if (encp->enc_mae_supported == B_FALSE) 355 return; 356 357 EFSYS_KMEM_FREE(enp->en_esip, maep->em_action_rule_field_caps_size, 358 maep->em_action_rule_field_caps); 359 EFSYS_KMEM_FREE(enp->en_esip, maep->em_outer_rule_field_caps_size, 360 maep->em_outer_rule_field_caps); 361 EFSYS_KMEM_FREE(enp->en_esip, sizeof (*maep), maep); 362 enp->en_maep = NULL; 363 } 364 365 __checkReturn efx_rc_t 366 efx_mae_get_limits( 367 __in efx_nic_t *enp, 368 __out efx_mae_limits_t *emlp) 369 { 370 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 371 struct efx_mae_s *maep = enp->en_maep; 372 efx_rc_t rc; 373 374 if (encp->enc_mae_supported == B_FALSE) { 375 rc = ENOTSUP; 376 goto fail1; 377 } 378 379 emlp->eml_max_n_outer_prios = maep->em_max_n_outer_prios; 380 emlp->eml_max_n_action_prios = maep->em_max_n_action_prios; 381 emlp->eml_encap_types_supported = maep->em_encap_types_supported; 382 emlp->eml_encap_header_size_limit = 383 MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2; 384 emlp->eml_max_n_action_counters = maep->em_max_n_action_counters; 385 emlp->eml_max_n_conntrack_counters = maep->em_max_n_conntrack_counters; 386 387 return (0); 388 389 fail1: 390 EFSYS_PROBE1(fail1, efx_rc_t, rc); 391 return (rc); 392 } 393 394 __checkReturn efx_rc_t 395 efx_mae_match_spec_init( 396 __in efx_nic_t *enp, 397 __in efx_mae_rule_type_t type, 398 __in uint32_t prio, 399 __out efx_mae_match_spec_t **specp) 400 { 401 efx_mae_match_spec_t *spec; 402 efx_rc_t rc; 403 404 switch (type) { 405 case EFX_MAE_RULE_OUTER: 406 break; 407 case EFX_MAE_RULE_ACTION: 408 break; 409 default: 410 rc = ENOTSUP; 411 goto fail1; 412 } 413 414 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec), spec); 415 if (spec == NULL) { 416 rc = ENOMEM; 417 goto fail2; 418 } 419 420 spec->emms_type = type; 421 spec->emms_prio = prio; 422 423 *specp = spec; 424 425 return (0); 426 427 fail2: 428 EFSYS_PROBE(fail2); 429 fail1: 430 EFSYS_PROBE1(fail1, efx_rc_t, rc); 431 return (rc); 432 } 433 434 void 435 efx_mae_match_spec_fini( 436 __in efx_nic_t *enp, 437 __in efx_mae_match_spec_t *spec) 438 { 439 EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec); 440 } 441 442 /* Named identifiers which are valid indices to efx_mae_field_cap_t */ 443 typedef enum efx_mae_field_cap_id_e { 444 EFX_MAE_FIELD_ID_INGRESS_MPORT_SELECTOR = MAE_FIELD_INGRESS_PORT, 445 EFX_MAE_FIELD_ID_ETHER_TYPE_BE = MAE_FIELD_ETHER_TYPE, 446 EFX_MAE_FIELD_ID_ETH_SADDR_BE = MAE_FIELD_ETH_SADDR, 447 EFX_MAE_FIELD_ID_ETH_DADDR_BE = MAE_FIELD_ETH_DADDR, 448 EFX_MAE_FIELD_ID_VLAN0_TCI_BE = MAE_FIELD_VLAN0_TCI, 449 EFX_MAE_FIELD_ID_VLAN0_PROTO_BE = MAE_FIELD_VLAN0_PROTO, 450 EFX_MAE_FIELD_ID_VLAN1_TCI_BE = MAE_FIELD_VLAN1_TCI, 451 EFX_MAE_FIELD_ID_VLAN1_PROTO_BE = MAE_FIELD_VLAN1_PROTO, 452 EFX_MAE_FIELD_ID_SRC_IP4_BE = MAE_FIELD_SRC_IP4, 453 EFX_MAE_FIELD_ID_DST_IP4_BE = MAE_FIELD_DST_IP4, 454 EFX_MAE_FIELD_ID_IP_PROTO = MAE_FIELD_IP_PROTO, 455 EFX_MAE_FIELD_ID_IP_TOS = MAE_FIELD_IP_TOS, 456 EFX_MAE_FIELD_ID_IP_TTL = MAE_FIELD_IP_TTL, 457 EFX_MAE_FIELD_ID_SRC_IP6_BE = MAE_FIELD_SRC_IP6, 458 EFX_MAE_FIELD_ID_DST_IP6_BE = MAE_FIELD_DST_IP6, 459 EFX_MAE_FIELD_ID_L4_SPORT_BE = MAE_FIELD_L4_SPORT, 460 EFX_MAE_FIELD_ID_L4_DPORT_BE = MAE_FIELD_L4_DPORT, 461 EFX_MAE_FIELD_ID_TCP_FLAGS_BE = MAE_FIELD_TCP_FLAGS, 462 EFX_MAE_FIELD_ID_ENC_ETHER_TYPE_BE = MAE_FIELD_ENC_ETHER_TYPE, 463 EFX_MAE_FIELD_ID_ENC_ETH_SADDR_BE = MAE_FIELD_ENC_ETH_SADDR, 464 EFX_MAE_FIELD_ID_ENC_ETH_DADDR_BE = MAE_FIELD_ENC_ETH_DADDR, 465 EFX_MAE_FIELD_ID_ENC_VLAN0_TCI_BE = MAE_FIELD_ENC_VLAN0_TCI, 466 EFX_MAE_FIELD_ID_ENC_VLAN0_PROTO_BE = MAE_FIELD_ENC_VLAN0_PROTO, 467 EFX_MAE_FIELD_ID_ENC_VLAN1_TCI_BE = MAE_FIELD_ENC_VLAN1_TCI, 468 EFX_MAE_FIELD_ID_ENC_VLAN1_PROTO_BE = MAE_FIELD_ENC_VLAN1_PROTO, 469 EFX_MAE_FIELD_ID_ENC_SRC_IP4_BE = MAE_FIELD_ENC_SRC_IP4, 470 EFX_MAE_FIELD_ID_ENC_DST_IP4_BE = MAE_FIELD_ENC_DST_IP4, 471 EFX_MAE_FIELD_ID_ENC_IP_PROTO = MAE_FIELD_ENC_IP_PROTO, 472 EFX_MAE_FIELD_ID_ENC_IP_TOS = MAE_FIELD_ENC_IP_TOS, 473 EFX_MAE_FIELD_ID_ENC_IP_TTL = MAE_FIELD_ENC_IP_TTL, 474 EFX_MAE_FIELD_ID_ENC_SRC_IP6_BE = MAE_FIELD_ENC_SRC_IP6, 475 EFX_MAE_FIELD_ID_ENC_DST_IP6_BE = MAE_FIELD_ENC_DST_IP6, 476 EFX_MAE_FIELD_ID_ENC_L4_SPORT_BE = MAE_FIELD_ENC_L4_SPORT, 477 EFX_MAE_FIELD_ID_ENC_L4_DPORT_BE = MAE_FIELD_ENC_L4_DPORT, 478 EFX_MAE_FIELD_ID_ENC_VNET_ID_BE = MAE_FIELD_ENC_VNET_ID, 479 EFX_MAE_FIELD_ID_OUTER_RULE_ID = MAE_FIELD_OUTER_RULE_ID, 480 EFX_MAE_FIELD_ID_HAS_OVLAN = MAE_FIELD_HAS_OVLAN, 481 EFX_MAE_FIELD_ID_HAS_IVLAN = MAE_FIELD_HAS_IVLAN, 482 EFX_MAE_FIELD_ID_ENC_HAS_OVLAN = MAE_FIELD_ENC_HAS_OVLAN, 483 EFX_MAE_FIELD_ID_ENC_HAS_IVLAN = MAE_FIELD_ENC_HAS_IVLAN, 484 EFX_MAE_FIELD_ID_RECIRC_ID = MAE_FIELD_RECIRC_ID, 485 EFX_MAE_FIELD_ID_CT_MARK = MAE_FIELD_CT_MARK, 486 EFX_MAE_FIELD_ID_IS_IP_FRAG = MAE_FIELD_IS_IP_FRAG, 487 EFX_MAE_FIELD_ID_IP_FIRST_FRAG = MAE_FIELD_IP_FIRST_FRAG, 488 489 EFX_MAE_FIELD_CAP_NIDS 490 } efx_mae_field_cap_id_t; 491 492 typedef enum efx_mae_field_endianness_e { 493 EFX_MAE_FIELD_LE = 0, 494 EFX_MAE_FIELD_BE, 495 496 EFX_MAE_FIELD_ENDIANNESS_NTYPES 497 } efx_mae_field_endianness_t; 498 499 /* 500 * The following structure is a means to describe an MAE field. 501 * The information in it is meant to be used internally by 502 * APIs for addressing a given field in a mask-value pairs 503 * structure and for validation purposes. 504 * 505 * A field may have an alternative one. This structure 506 * has additional members to reference the alternative 507 * field's mask. See efx_mae_match_spec_is_valid(). 508 */ 509 typedef struct efx_mae_mv_desc_s { 510 efx_mae_field_cap_id_t emmd_field_cap_id; 511 512 size_t emmd_value_size; 513 size_t emmd_value_offset; 514 size_t emmd_mask_size; 515 size_t emmd_mask_offset; 516 517 /* 518 * Having the alternative field's mask size set to 0 519 * means that there's no alternative field specified. 520 */ 521 size_t emmd_alt_mask_size; 522 size_t emmd_alt_mask_offset; 523 524 /* Primary field and the alternative one are of the same endianness. */ 525 efx_mae_field_endianness_t emmd_endianness; 526 } efx_mae_mv_desc_t; 527 528 /* Indices to this array are provided by efx_mae_field_id_t */ 529 static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = { 530 #define EFX_MAE_MV_DESC(_name, _endianness) \ 531 [EFX_MAE_FIELD_##_name] = \ 532 { \ 533 EFX_MAE_FIELD_ID_##_name, \ 534 MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_LEN, \ 535 MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_OFST, \ 536 MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_MASK_LEN, \ 537 MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_MASK_OFST, \ 538 0, 0 /* no alternative field */, \ 539 _endianness \ 540 } 541 542 EFX_MAE_MV_DESC(INGRESS_MPORT_SELECTOR, EFX_MAE_FIELD_LE), 543 EFX_MAE_MV_DESC(ETHER_TYPE_BE, EFX_MAE_FIELD_BE), 544 EFX_MAE_MV_DESC(ETH_SADDR_BE, EFX_MAE_FIELD_BE), 545 EFX_MAE_MV_DESC(ETH_DADDR_BE, EFX_MAE_FIELD_BE), 546 EFX_MAE_MV_DESC(VLAN0_TCI_BE, EFX_MAE_FIELD_BE), 547 EFX_MAE_MV_DESC(VLAN0_PROTO_BE, EFX_MAE_FIELD_BE), 548 EFX_MAE_MV_DESC(VLAN1_TCI_BE, EFX_MAE_FIELD_BE), 549 EFX_MAE_MV_DESC(VLAN1_PROTO_BE, EFX_MAE_FIELD_BE), 550 EFX_MAE_MV_DESC(SRC_IP4_BE, EFX_MAE_FIELD_BE), 551 EFX_MAE_MV_DESC(DST_IP4_BE, EFX_MAE_FIELD_BE), 552 EFX_MAE_MV_DESC(IP_PROTO, EFX_MAE_FIELD_BE), 553 EFX_MAE_MV_DESC(IP_TOS, EFX_MAE_FIELD_BE), 554 EFX_MAE_MV_DESC(IP_TTL, EFX_MAE_FIELD_BE), 555 EFX_MAE_MV_DESC(SRC_IP6_BE, EFX_MAE_FIELD_BE), 556 EFX_MAE_MV_DESC(DST_IP6_BE, EFX_MAE_FIELD_BE), 557 EFX_MAE_MV_DESC(L4_SPORT_BE, EFX_MAE_FIELD_BE), 558 EFX_MAE_MV_DESC(L4_DPORT_BE, EFX_MAE_FIELD_BE), 559 EFX_MAE_MV_DESC(TCP_FLAGS_BE, EFX_MAE_FIELD_BE), 560 EFX_MAE_MV_DESC(ENC_VNET_ID_BE, EFX_MAE_FIELD_BE), 561 EFX_MAE_MV_DESC(OUTER_RULE_ID, EFX_MAE_FIELD_LE), 562 EFX_MAE_MV_DESC(RECIRC_ID, EFX_MAE_FIELD_LE), 563 EFX_MAE_MV_DESC(CT_MARK, EFX_MAE_FIELD_LE), 564 565 #undef EFX_MAE_MV_DESC 566 }; 567 568 /* Indices to this array are provided by efx_mae_field_id_t */ 569 static const efx_mae_mv_desc_t __efx_mae_outer_rule_mv_desc_set[] = { 570 #define EFX_MAE_MV_DESC(_name, _endianness) \ 571 [EFX_MAE_FIELD_##_name] = \ 572 { \ 573 EFX_MAE_FIELD_ID_##_name, \ 574 MAE_ENC_FIELD_PAIRS_##_name##_LEN, \ 575 MAE_ENC_FIELD_PAIRS_##_name##_OFST, \ 576 MAE_ENC_FIELD_PAIRS_##_name##_MASK_LEN, \ 577 MAE_ENC_FIELD_PAIRS_##_name##_MASK_OFST, \ 578 0, 0 /* no alternative field */, \ 579 _endianness \ 580 } 581 582 /* Same as EFX_MAE_MV_DESC(), but also indicates an alternative field. */ 583 #define EFX_MAE_MV_DESC_ALT(_name, _alt_name, _endianness) \ 584 [EFX_MAE_FIELD_##_name] = \ 585 { \ 586 EFX_MAE_FIELD_ID_##_name, \ 587 MAE_ENC_FIELD_PAIRS_##_name##_LEN, \ 588 MAE_ENC_FIELD_PAIRS_##_name##_OFST, \ 589 MAE_ENC_FIELD_PAIRS_##_name##_MASK_LEN, \ 590 MAE_ENC_FIELD_PAIRS_##_name##_MASK_OFST, \ 591 MAE_ENC_FIELD_PAIRS_##_alt_name##_MASK_LEN, \ 592 MAE_ENC_FIELD_PAIRS_##_alt_name##_MASK_OFST, \ 593 _endianness \ 594 } 595 596 EFX_MAE_MV_DESC(INGRESS_MPORT_SELECTOR, EFX_MAE_FIELD_LE), 597 EFX_MAE_MV_DESC(ENC_ETHER_TYPE_BE, EFX_MAE_FIELD_BE), 598 EFX_MAE_MV_DESC(ENC_ETH_SADDR_BE, EFX_MAE_FIELD_BE), 599 EFX_MAE_MV_DESC(ENC_ETH_DADDR_BE, EFX_MAE_FIELD_BE), 600 EFX_MAE_MV_DESC(ENC_VLAN0_TCI_BE, EFX_MAE_FIELD_BE), 601 EFX_MAE_MV_DESC(ENC_VLAN0_PROTO_BE, EFX_MAE_FIELD_BE), 602 EFX_MAE_MV_DESC(ENC_VLAN1_TCI_BE, EFX_MAE_FIELD_BE), 603 EFX_MAE_MV_DESC(ENC_VLAN1_PROTO_BE, EFX_MAE_FIELD_BE), 604 EFX_MAE_MV_DESC_ALT(ENC_SRC_IP4_BE, ENC_SRC_IP6_BE, EFX_MAE_FIELD_BE), 605 EFX_MAE_MV_DESC_ALT(ENC_DST_IP4_BE, ENC_DST_IP6_BE, EFX_MAE_FIELD_BE), 606 EFX_MAE_MV_DESC(ENC_IP_PROTO, EFX_MAE_FIELD_BE), 607 EFX_MAE_MV_DESC(ENC_IP_TOS, EFX_MAE_FIELD_BE), 608 EFX_MAE_MV_DESC(ENC_IP_TTL, EFX_MAE_FIELD_BE), 609 EFX_MAE_MV_DESC_ALT(ENC_SRC_IP6_BE, ENC_SRC_IP4_BE, EFX_MAE_FIELD_BE), 610 EFX_MAE_MV_DESC_ALT(ENC_DST_IP6_BE, ENC_DST_IP4_BE, EFX_MAE_FIELD_BE), 611 EFX_MAE_MV_DESC(ENC_L4_SPORT_BE, EFX_MAE_FIELD_BE), 612 EFX_MAE_MV_DESC(ENC_L4_DPORT_BE, EFX_MAE_FIELD_BE), 613 614 #undef EFX_MAE_MV_DESC_ALT 615 #undef EFX_MAE_MV_DESC 616 }; 617 618 /* 619 * The following structure is a means to describe an MAE bit. 620 * The information in it is meant to be used internally by 621 * APIs for addressing a given flag in a mask-value pairs 622 * structure and for validation purposes. 623 */ 624 typedef struct efx_mae_mv_bit_desc_s { 625 /* 626 * Arrays using this struct are indexed by field IDs. 627 * Fields which aren't meant to be referenced by these 628 * arrays comprise gaps (invalid entries). Below field 629 * helps to identify such entries. 630 */ 631 boolean_t emmbd_entry_is_valid; 632 efx_mae_field_cap_id_t emmbd_bit_cap_id; 633 size_t emmbd_value_ofst; 634 unsigned int emmbd_value_lbn; 635 size_t emmbd_mask_ofst; 636 unsigned int emmbd_mask_lbn; 637 } efx_mae_mv_bit_desc_t; 638 639 static const efx_mae_mv_bit_desc_t __efx_mae_outer_rule_mv_bit_desc_set[] = { 640 #define EFX_MAE_MV_BIT_DESC(_name) \ 641 [EFX_MAE_FIELD_##_name] = \ 642 { \ 643 B_TRUE, \ 644 EFX_MAE_FIELD_ID_##_name, \ 645 MAE_ENC_FIELD_PAIRS_##_name##_OFST, \ 646 MAE_ENC_FIELD_PAIRS_##_name##_LBN, \ 647 MAE_ENC_FIELD_PAIRS_##_name##_MASK_OFST, \ 648 MAE_ENC_FIELD_PAIRS_##_name##_MASK_LBN, \ 649 } 650 651 EFX_MAE_MV_BIT_DESC(ENC_HAS_OVLAN), 652 EFX_MAE_MV_BIT_DESC(ENC_HAS_IVLAN), 653 654 #undef EFX_MAE_MV_BIT_DESC 655 }; 656 657 static const efx_mae_mv_bit_desc_t __efx_mae_action_rule_mv_bit_desc_set[] = { 658 #define EFX_MAE_MV_BIT_DESC(_name) \ 659 [EFX_MAE_FIELD_##_name] = \ 660 { \ 661 B_TRUE, \ 662 EFX_MAE_FIELD_ID_##_name, \ 663 MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_OFST, \ 664 MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_LBN, \ 665 MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_MASK_OFST, \ 666 MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_LBN, \ 667 } 668 669 EFX_MAE_MV_BIT_DESC(HAS_OVLAN), 670 EFX_MAE_MV_BIT_DESC(HAS_IVLAN), 671 EFX_MAE_MV_BIT_DESC(ENC_HAS_OVLAN), 672 EFX_MAE_MV_BIT_DESC(ENC_HAS_IVLAN), 673 EFX_MAE_MV_BIT_DESC(IS_IP_FRAG), 674 EFX_MAE_MV_BIT_DESC(IP_FIRST_FRAG), 675 676 #undef EFX_MAE_MV_BIT_DESC 677 }; 678 679 __checkReturn efx_rc_t 680 efx_mae_mport_invalid( 681 __out efx_mport_sel_t *mportp) 682 { 683 efx_dword_t dword; 684 efx_rc_t rc; 685 686 if (mportp == NULL) { 687 rc = EINVAL; 688 goto fail1; 689 } 690 691 EFX_POPULATE_DWORD_1(dword, 692 MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_INVALID); 693 694 memset(mportp, 0, sizeof (*mportp)); 695 mportp->sel = dword.ed_u32[0]; 696 697 return (0); 698 699 fail1: 700 EFSYS_PROBE1(fail1, efx_rc_t, rc); 701 return (rc); 702 } 703 704 __checkReturn efx_rc_t 705 efx_mae_mport_by_phy_port( 706 __in uint32_t phy_port, 707 __out efx_mport_sel_t *mportp) 708 { 709 efx_dword_t dword; 710 efx_rc_t rc; 711 712 if (phy_port > EFX_MASK32(MAE_MPORT_SELECTOR_PPORT_ID)) { 713 rc = EINVAL; 714 goto fail1; 715 } 716 717 EFX_POPULATE_DWORD_2(dword, 718 MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_PPORT, 719 MAE_MPORT_SELECTOR_PPORT_ID, phy_port); 720 721 memset(mportp, 0, sizeof (*mportp)); 722 /* 723 * The constructed DWORD is little-endian, 724 * but the resulting value is meant to be 725 * passed to MCDIs, where it will undergo 726 * host-order to little endian conversion. 727 */ 728 mportp->sel = EFX_DWORD_FIELD(dword, EFX_DWORD_0); 729 730 return (0); 731 732 fail1: 733 EFSYS_PROBE1(fail1, efx_rc_t, rc); 734 return (rc); 735 } 736 737 __checkReturn efx_rc_t 738 efx_mae_mport_by_pcie_function( 739 __in uint32_t pf, 740 __in uint32_t vf, 741 __out efx_mport_sel_t *mportp) 742 { 743 efx_dword_t dword; 744 efx_rc_t rc; 745 746 rc = efx_mae_mport_by_pcie_mh_function(EFX_PCIE_INTERFACE_CALLER, 747 pf, vf, mportp); 748 if (rc != 0) 749 goto fail1; 750 751 return (0); 752 753 fail1: 754 EFSYS_PROBE1(fail1, efx_rc_t, rc); 755 return (rc); 756 } 757 758 static __checkReturn efx_rc_t 759 efx_mae_intf_to_selector( 760 __in efx_pcie_interface_t intf, 761 __out uint32_t *selector_intfp) 762 { 763 efx_rc_t rc; 764 765 switch (intf) { 766 case EFX_PCIE_INTERFACE_HOST_PRIMARY: 767 EFX_STATIC_ASSERT(MAE_MPORT_SELECTOR_HOST_PRIMARY <= 768 EFX_MASK32(MAE_MPORT_SELECTOR_FUNC_INTF_ID)); 769 *selector_intfp = MAE_MPORT_SELECTOR_HOST_PRIMARY; 770 break; 771 case EFX_PCIE_INTERFACE_NIC_EMBEDDED: 772 EFX_STATIC_ASSERT(MAE_MPORT_SELECTOR_NIC_EMBEDDED <= 773 EFX_MASK32(MAE_MPORT_SELECTOR_FUNC_INTF_ID)); 774 *selector_intfp = MAE_MPORT_SELECTOR_NIC_EMBEDDED; 775 break; 776 case EFX_PCIE_INTERFACE_CALLER: 777 EFX_STATIC_ASSERT(MAE_MPORT_SELECTOR_CALLER_INTF <= 778 EFX_MASK32(MAE_MPORT_SELECTOR_FUNC_INTF_ID)); 779 *selector_intfp = MAE_MPORT_SELECTOR_CALLER_INTF; 780 break; 781 default: 782 rc = EINVAL; 783 goto fail1; 784 } 785 786 return (0); 787 788 fail1: 789 EFSYS_PROBE1(fail1, efx_rc_t, rc); 790 return (rc); 791 } 792 793 __checkReturn efx_rc_t 794 efx_mae_mport_by_pcie_mh_function( 795 __in efx_pcie_interface_t intf, 796 __in uint32_t pf, 797 __in uint32_t vf, 798 __out efx_mport_sel_t *mportp) 799 { 800 uint32_t selector_intf; 801 efx_dword_t dword; 802 efx_rc_t rc; 803 804 EFX_STATIC_ASSERT(EFX_PCI_VF_INVALID == 805 MAE_MPORT_SELECTOR_FUNC_VF_ID_NULL); 806 807 rc = efx_mae_intf_to_selector(intf, &selector_intf); 808 if (rc != 0) 809 goto fail1; 810 811 if (pf > EFX_MASK32(MAE_MPORT_SELECTOR_FUNC_MH_PF_ID)) { 812 rc = EINVAL; 813 goto fail2; 814 } 815 816 if (vf > EFX_MASK32(MAE_MPORT_SELECTOR_FUNC_VF_ID)) { 817 rc = EINVAL; 818 goto fail3; 819 } 820 821 822 EFX_POPULATE_DWORD_4(dword, 823 MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_MH_FUNC, 824 MAE_MPORT_SELECTOR_FUNC_INTF_ID, selector_intf, 825 MAE_MPORT_SELECTOR_FUNC_MH_PF_ID, pf, 826 MAE_MPORT_SELECTOR_FUNC_VF_ID, vf); 827 828 memset(mportp, 0, sizeof (*mportp)); 829 mportp->sel = dword.ed_u32[0]; 830 831 return (0); 832 833 fail3: 834 EFSYS_PROBE(fail3); 835 fail2: 836 EFSYS_PROBE(fail2); 837 fail1: 838 EFSYS_PROBE1(fail1, efx_rc_t, rc); 839 return (rc); 840 } 841 842 static __checkReturn efx_rc_t 843 efx_mcdi_mae_mport_lookup( 844 __in efx_nic_t *enp, 845 __in const efx_mport_sel_t *mport_selectorp, 846 __out efx_mport_id_t *mport_idp) 847 { 848 efx_mcdi_req_t req; 849 EFX_MCDI_DECLARE_BUF(payload, 850 MC_CMD_MAE_MPORT_LOOKUP_IN_LEN, 851 MC_CMD_MAE_MPORT_LOOKUP_OUT_LEN); 852 efx_rc_t rc; 853 854 req.emr_cmd = MC_CMD_MAE_MPORT_LOOKUP; 855 req.emr_in_buf = payload; 856 req.emr_in_length = MC_CMD_MAE_MPORT_LOOKUP_IN_LEN; 857 req.emr_out_buf = payload; 858 req.emr_out_length = MC_CMD_MAE_MPORT_LOOKUP_OUT_LEN; 859 860 MCDI_IN_SET_DWORD(req, MAE_MPORT_LOOKUP_IN_MPORT_SELECTOR, 861 mport_selectorp->sel); 862 863 efx_mcdi_execute(enp, &req); 864 865 if (req.emr_rc != 0) { 866 rc = req.emr_rc; 867 goto fail1; 868 } 869 870 mport_idp->id = MCDI_OUT_DWORD(req, MAE_MPORT_LOOKUP_OUT_MPORT_ID); 871 872 return (0); 873 874 fail1: 875 EFSYS_PROBE1(fail1, efx_rc_t, rc); 876 return (rc); 877 } 878 879 __checkReturn efx_rc_t 880 efx_mae_mport_id_by_selector( 881 __in efx_nic_t *enp, 882 __in const efx_mport_sel_t *mport_selectorp, 883 __out efx_mport_id_t *mport_idp) 884 { 885 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 886 efx_rc_t rc; 887 888 if (encp->enc_mae_supported == B_FALSE) { 889 rc = ENOTSUP; 890 goto fail1; 891 } 892 893 rc = efx_mcdi_mae_mport_lookup(enp, mport_selectorp, mport_idp); 894 if (rc != 0) 895 goto fail2; 896 897 return (0); 898 899 fail2: 900 EFSYS_PROBE(fail2); 901 fail1: 902 EFSYS_PROBE1(fail1, efx_rc_t, rc); 903 return (rc); 904 } 905 906 __checkReturn efx_rc_t 907 efx_mae_match_spec_recirc_id_set( 908 __in efx_mae_match_spec_t *spec, 909 __in uint8_t recirc_id) 910 { 911 uint8_t full_mask = UINT8_MAX; 912 const uint8_t *vp; 913 const uint8_t *mp; 914 efx_rc_t rc; 915 916 vp = (const uint8_t *)&recirc_id; 917 mp = (const uint8_t *)&full_mask; 918 919 rc = efx_mae_match_spec_field_set(spec, EFX_MAE_FIELD_RECIRC_ID, 920 sizeof (recirc_id), vp, 921 sizeof (full_mask), mp); 922 if (rc != 0) 923 goto fail1; 924 925 return (0); 926 927 fail1: 928 EFSYS_PROBE1(fail1, efx_rc_t, rc); 929 return (rc); 930 } 931 932 __checkReturn efx_rc_t 933 efx_mae_match_spec_ct_mark_set( 934 __in efx_mae_match_spec_t *spec, 935 __in uint32_t ct_mark) 936 { 937 uint32_t full_mask = UINT32_MAX; 938 const uint8_t *vp; 939 const uint8_t *mp; 940 efx_rc_t rc; 941 942 mp = (const uint8_t *)&full_mask; 943 vp = (const uint8_t *)&ct_mark; 944 945 rc = efx_mae_match_spec_field_set(spec, EFX_MAE_FIELD_CT_MARK, 946 sizeof (ct_mark), vp, 947 sizeof (full_mask), mp); 948 if (rc != 0) 949 goto fail1; 950 951 return (0); 952 953 fail1: 954 EFSYS_PROBE1(fail1, efx_rc_t, rc); 955 return (rc); 956 } 957 958 __checkReturn efx_rc_t 959 efx_mae_mport_by_id( 960 __in const efx_mport_id_t *mport_idp, 961 __out efx_mport_sel_t *mportp) 962 { 963 efx_dword_t dword; 964 965 EFX_POPULATE_DWORD_2(dword, 966 MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_MPORT_ID, 967 MAE_MPORT_SELECTOR_MPORT_ID, mport_idp->id); 968 969 memset(mportp, 0, sizeof (*mportp)); 970 mportp->sel = __LE_TO_CPU_32(dword.ed_u32[0]); 971 972 return (0); 973 } 974 975 __checkReturn efx_rc_t 976 efx_mae_match_spec_field_set( 977 __in efx_mae_match_spec_t *spec, 978 __in efx_mae_field_id_t field_id, 979 __in size_t value_size, 980 __in_bcount(value_size) const uint8_t *value, 981 __in size_t mask_size, 982 __in_bcount(mask_size) const uint8_t *mask) 983 { 984 const efx_mae_mv_desc_t *descp; 985 unsigned int desc_set_nentries; 986 uint8_t *mvp; 987 efx_rc_t rc; 988 989 switch (spec->emms_type) { 990 case EFX_MAE_RULE_OUTER: 991 desc_set_nentries = 992 EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set); 993 descp = &__efx_mae_outer_rule_mv_desc_set[field_id]; 994 mvp = spec->emms_mask_value_pairs.outer; 995 break; 996 case EFX_MAE_RULE_ACTION: 997 desc_set_nentries = 998 EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set); 999 descp = &__efx_mae_action_rule_mv_desc_set[field_id]; 1000 mvp = spec->emms_mask_value_pairs.action; 1001 break; 1002 default: 1003 rc = ENOTSUP; 1004 goto fail1; 1005 } 1006 1007 if ((unsigned int)field_id >= desc_set_nentries) { 1008 rc = EINVAL; 1009 goto fail2; 1010 } 1011 1012 if (descp->emmd_mask_size == 0) { 1013 /* The ID points to a gap in the array of field descriptors. */ 1014 rc = EINVAL; 1015 goto fail3; 1016 } 1017 1018 if (value_size != descp->emmd_value_size) { 1019 rc = EINVAL; 1020 goto fail4; 1021 } 1022 1023 if (mask_size != descp->emmd_mask_size) { 1024 rc = EINVAL; 1025 goto fail5; 1026 } 1027 1028 if (descp->emmd_endianness == EFX_MAE_FIELD_BE) { 1029 unsigned int i; 1030 1031 /* 1032 * The mask/value are in network (big endian) order. 1033 * The MCDI request field is also big endian. 1034 */ 1035 1036 EFSYS_ASSERT3U(value_size, ==, mask_size); 1037 1038 for (i = 0; i < value_size; ++i) { 1039 uint8_t *v_bytep = mvp + descp->emmd_value_offset + i; 1040 uint8_t *m_bytep = mvp + descp->emmd_mask_offset + i; 1041 1042 /* 1043 * Apply the mask (which may be all-zeros) to the value. 1044 * 1045 * If this API is provided with some value to set for a 1046 * given field in one specification and with some other 1047 * value to set for this field in another specification, 1048 * then, if the two masks are all-zeros, the field will 1049 * avoid being counted as a mismatch when comparing the 1050 * specifications using efx_mae_match_specs_equal() API. 1051 */ 1052 *v_bytep = value[i] & mask[i]; 1053 *m_bytep = mask[i]; 1054 } 1055 } else { 1056 efx_dword_t dword; 1057 1058 /* 1059 * The mask/value are in host byte order. 1060 * The MCDI request field is little endian. 1061 */ 1062 switch (value_size) { 1063 case 4: 1064 EFX_POPULATE_DWORD_1(dword, 1065 EFX_DWORD_0, *(const uint32_t *)value); 1066 1067 memcpy(mvp + descp->emmd_value_offset, 1068 &dword, sizeof (dword)); 1069 break; 1070 case 1: 1071 memcpy(mvp + descp->emmd_value_offset, 1072 value, 1); 1073 break; 1074 default: 1075 EFSYS_ASSERT(B_FALSE); 1076 } 1077 1078 switch (mask_size) { 1079 case 4: 1080 EFX_POPULATE_DWORD_1(dword, 1081 EFX_DWORD_0, *(const uint32_t *)mask); 1082 1083 memcpy(mvp + descp->emmd_mask_offset, 1084 &dword, sizeof (dword)); 1085 break; 1086 case 1: 1087 memcpy(mvp + descp->emmd_mask_offset, 1088 mask, 1); 1089 break; 1090 default: 1091 EFSYS_ASSERT(B_FALSE); 1092 } 1093 } 1094 1095 return (0); 1096 1097 fail5: 1098 EFSYS_PROBE(fail5); 1099 fail4: 1100 EFSYS_PROBE(fail4); 1101 fail3: 1102 EFSYS_PROBE(fail3); 1103 fail2: 1104 EFSYS_PROBE(fail2); 1105 fail1: 1106 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1107 return (rc); 1108 } 1109 1110 __checkReturn efx_rc_t 1111 efx_mae_match_spec_field_get( 1112 __in const efx_mae_match_spec_t *spec, 1113 __in efx_mae_field_id_t field_id, 1114 __in size_t value_size, 1115 __out_bcount_opt(value_size) uint8_t *value, 1116 __in size_t mask_size, 1117 __out_bcount_opt(mask_size) uint8_t *mask) 1118 { 1119 const efx_mae_mv_desc_t *descp; 1120 unsigned int desc_set_nentries; 1121 const uint8_t *mvp; 1122 efx_rc_t rc; 1123 1124 switch (spec->emms_type) { 1125 case EFX_MAE_RULE_OUTER: 1126 desc_set_nentries = 1127 EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set); 1128 descp = &__efx_mae_outer_rule_mv_desc_set[field_id]; 1129 mvp = spec->emms_mask_value_pairs.outer; 1130 break; 1131 case EFX_MAE_RULE_ACTION: 1132 desc_set_nentries = 1133 EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set); 1134 descp = &__efx_mae_action_rule_mv_desc_set[field_id]; 1135 mvp = spec->emms_mask_value_pairs.action; 1136 break; 1137 default: 1138 rc = ENOTSUP; 1139 goto fail1; 1140 } 1141 1142 if ((unsigned int)field_id >= desc_set_nentries) { 1143 rc = EINVAL; 1144 goto fail2; 1145 } 1146 1147 if (descp->emmd_mask_size == 0) { 1148 /* The ID points to a gap in the array of field descriptors. */ 1149 rc = EINVAL; 1150 goto fail3; 1151 } 1152 1153 if (value != NULL && value_size != descp->emmd_value_size) { 1154 rc = EINVAL; 1155 goto fail4; 1156 } 1157 1158 if (mask != NULL && mask_size != descp->emmd_mask_size) { 1159 rc = EINVAL; 1160 goto fail5; 1161 } 1162 1163 if (value == NULL && value_size != 0) { 1164 rc = EINVAL; 1165 goto fail6; 1166 } 1167 1168 if (mask == NULL && mask_size != 0) { 1169 rc = EINVAL; 1170 goto fail7; 1171 } 1172 1173 if (descp->emmd_endianness == EFX_MAE_FIELD_BE) { 1174 /* 1175 * The MCDI request field is in network (big endian) order. 1176 * The mask/value are also big endian. 1177 */ 1178 memcpy(value, mvp + descp->emmd_value_offset, value_size); 1179 memcpy(mask, mvp + descp->emmd_mask_offset, mask_size); 1180 } else { 1181 efx_dword_t dword; 1182 1183 /* 1184 * The MCDI request field is little endian. 1185 * The mask/value are in host byte order. 1186 */ 1187 switch (value_size) { 1188 case 4: 1189 memcpy(&dword, mvp + descp->emmd_value_offset, 1190 sizeof (dword)); 1191 1192 *(uint32_t *)value = 1193 EFX_DWORD_FIELD(dword, EFX_DWORD_0); 1194 break; 1195 case 1: 1196 memcpy(value, mvp + descp->emmd_value_offset, 1); 1197 break; 1198 case 0: 1199 break; 1200 default: 1201 EFSYS_ASSERT(B_FALSE); 1202 } 1203 1204 switch (mask_size) { 1205 case 4: 1206 memcpy(&dword, mvp + descp->emmd_mask_offset, 1207 sizeof (dword)); 1208 1209 *(uint32_t *)mask = 1210 EFX_DWORD_FIELD(dword, EFX_DWORD_0); 1211 break; 1212 case 1: 1213 memcpy(mask, mvp + descp->emmd_mask_offset, 1); 1214 break; 1215 case 0: 1216 break; 1217 default: 1218 EFSYS_ASSERT(B_FALSE); 1219 } 1220 } 1221 1222 return (0); 1223 1224 fail7: 1225 EFSYS_PROBE(fail7); 1226 fail6: 1227 EFSYS_PROBE(fail6); 1228 fail5: 1229 EFSYS_PROBE(fail5); 1230 fail4: 1231 EFSYS_PROBE(fail4); 1232 fail3: 1233 EFSYS_PROBE(fail3); 1234 fail2: 1235 EFSYS_PROBE(fail2); 1236 fail1: 1237 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1238 return (rc); 1239 } 1240 1241 __checkReturn efx_rc_t 1242 efx_mae_match_spec_bit_set( 1243 __in efx_mae_match_spec_t *spec, 1244 __in efx_mae_field_id_t field_id, 1245 __in boolean_t value) 1246 { 1247 const efx_mae_mv_bit_desc_t *bit_descp; 1248 unsigned int bit_desc_set_nentries; 1249 unsigned int byte_idx; 1250 unsigned int bit_idx; 1251 uint8_t *mvp; 1252 efx_rc_t rc; 1253 1254 switch (spec->emms_type) { 1255 case EFX_MAE_RULE_OUTER: 1256 bit_desc_set_nentries = 1257 EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_bit_desc_set); 1258 bit_descp = &__efx_mae_outer_rule_mv_bit_desc_set[field_id]; 1259 mvp = spec->emms_mask_value_pairs.outer; 1260 break; 1261 case EFX_MAE_RULE_ACTION: 1262 bit_desc_set_nentries = 1263 EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_bit_desc_set); 1264 bit_descp = &__efx_mae_action_rule_mv_bit_desc_set[field_id]; 1265 mvp = spec->emms_mask_value_pairs.action; 1266 break; 1267 default: 1268 rc = ENOTSUP; 1269 goto fail1; 1270 } 1271 1272 if ((unsigned int)field_id >= bit_desc_set_nentries) { 1273 rc = EINVAL; 1274 goto fail2; 1275 } 1276 1277 if (bit_descp->emmbd_entry_is_valid == B_FALSE) { 1278 rc = EINVAL; 1279 goto fail3; 1280 } 1281 1282 byte_idx = bit_descp->emmbd_value_ofst + bit_descp->emmbd_value_lbn / 8; 1283 bit_idx = bit_descp->emmbd_value_lbn % 8; 1284 1285 if (value != B_FALSE) 1286 mvp[byte_idx] |= (1U << bit_idx); 1287 else 1288 mvp[byte_idx] &= ~(1U << bit_idx); 1289 1290 byte_idx = bit_descp->emmbd_mask_ofst + bit_descp->emmbd_mask_lbn / 8; 1291 bit_idx = bit_descp->emmbd_mask_lbn % 8; 1292 mvp[byte_idx] |= (1U << bit_idx); 1293 1294 return (0); 1295 1296 fail3: 1297 EFSYS_PROBE(fail3); 1298 fail2: 1299 EFSYS_PROBE(fail2); 1300 fail1: 1301 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1302 return (rc); 1303 } 1304 1305 __checkReturn efx_rc_t 1306 efx_mae_match_spec_mport_set( 1307 __in efx_mae_match_spec_t *spec, 1308 __in const efx_mport_sel_t *valuep, 1309 __in_opt const efx_mport_sel_t *maskp) 1310 { 1311 uint32_t full_mask = UINT32_MAX; 1312 const uint8_t *vp; 1313 const uint8_t *mp; 1314 efx_rc_t rc; 1315 1316 if (valuep == NULL) { 1317 rc = EINVAL; 1318 goto fail1; 1319 } 1320 1321 vp = (const uint8_t *)&valuep->sel; 1322 if (maskp != NULL) 1323 mp = (const uint8_t *)&maskp->sel; 1324 else 1325 mp = (const uint8_t *)&full_mask; 1326 1327 rc = efx_mae_match_spec_field_set(spec, 1328 EFX_MAE_FIELD_INGRESS_MPORT_SELECTOR, 1329 sizeof (valuep->sel), vp, sizeof (maskp->sel), mp); 1330 if (rc != 0) 1331 goto fail2; 1332 1333 return (0); 1334 1335 fail2: 1336 EFSYS_PROBE(fail2); 1337 fail1: 1338 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1339 return (rc); 1340 } 1341 1342 __checkReturn efx_rc_t 1343 efx_mae_match_spec_clone( 1344 __in efx_nic_t *enp, 1345 __in efx_mae_match_spec_t *orig, 1346 __out efx_mae_match_spec_t **clonep) 1347 { 1348 efx_mae_match_spec_t *clone; 1349 efx_rc_t rc; 1350 1351 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*clone), clone); 1352 if (clone == NULL) { 1353 rc = ENOMEM; 1354 goto fail1; 1355 } 1356 1357 memcpy(clone, orig, sizeof (efx_mae_match_spec_t)); 1358 1359 *clonep = clone; 1360 1361 return (0); 1362 1363 fail1: 1364 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1365 return (rc); 1366 } 1367 1368 __checkReturn boolean_t 1369 efx_mae_match_specs_equal( 1370 __in const efx_mae_match_spec_t *left, 1371 __in const efx_mae_match_spec_t *right) 1372 { 1373 return ((memcmp(left, right, sizeof (*left)) == 0) ? B_TRUE : B_FALSE); 1374 } 1375 1376 #define EFX_MASK_BIT_IS_SET(_mask, _mask_page_nbits, _bit) \ 1377 ((_mask)[(_bit) / (_mask_page_nbits)] & \ 1378 (1ULL << ((_bit) & ((_mask_page_nbits) - 1)))) 1379 1380 static boolean_t 1381 efx_mask_is_prefix( 1382 __in size_t mask_nbytes, 1383 __in_bcount(mask_nbytes) const uint8_t *maskp) 1384 { 1385 boolean_t prev_bit_is_set = B_TRUE; 1386 unsigned int i; 1387 1388 for (i = 0; i < 8 * mask_nbytes; ++i) { 1389 boolean_t bit_is_set = EFX_MASK_BIT_IS_SET(maskp, 8, i); 1390 1391 if (!prev_bit_is_set && bit_is_set) 1392 return B_FALSE; 1393 1394 prev_bit_is_set = bit_is_set; 1395 } 1396 1397 return B_TRUE; 1398 } 1399 1400 static boolean_t 1401 efx_mask_is_all_ones( 1402 __in size_t mask_nbytes, 1403 __in_bcount(mask_nbytes) const uint8_t *maskp) 1404 { 1405 unsigned int i; 1406 uint8_t t = ~0; 1407 1408 for (i = 0; i < mask_nbytes; ++i) 1409 t &= maskp[i]; 1410 1411 return (t == (uint8_t)(~0)); 1412 } 1413 1414 static boolean_t 1415 efx_mask_is_all_zeros( 1416 __in size_t mask_nbytes, 1417 __in_bcount(mask_nbytes) const uint8_t *maskp) 1418 { 1419 unsigned int i; 1420 uint8_t t = 0; 1421 1422 for (i = 0; i < mask_nbytes; ++i) 1423 t |= maskp[i]; 1424 1425 return (t == 0); 1426 } 1427 1428 __checkReturn boolean_t 1429 efx_mae_match_spec_is_valid( 1430 __in efx_nic_t *enp, 1431 __in const efx_mae_match_spec_t *spec) 1432 { 1433 efx_mae_t *maep = enp->en_maep; 1434 unsigned int field_ncaps = maep->em_max_nfields; 1435 const efx_mae_field_cap_t *field_caps; 1436 const efx_mae_mv_desc_t *desc_setp; 1437 unsigned int desc_set_nentries; 1438 const efx_mae_mv_bit_desc_t *bit_desc_setp; 1439 unsigned int bit_desc_set_nentries; 1440 boolean_t is_valid = B_TRUE; 1441 efx_mae_field_id_t field_id; 1442 const uint8_t *mvp; 1443 1444 switch (spec->emms_type) { 1445 case EFX_MAE_RULE_OUTER: 1446 field_caps = maep->em_outer_rule_field_caps; 1447 desc_setp = __efx_mae_outer_rule_mv_desc_set; 1448 desc_set_nentries = 1449 EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set); 1450 bit_desc_setp = __efx_mae_outer_rule_mv_bit_desc_set; 1451 bit_desc_set_nentries = 1452 EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_bit_desc_set); 1453 mvp = spec->emms_mask_value_pairs.outer; 1454 break; 1455 case EFX_MAE_RULE_ACTION: 1456 field_caps = maep->em_action_rule_field_caps; 1457 desc_setp = __efx_mae_action_rule_mv_desc_set; 1458 desc_set_nentries = 1459 EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set); 1460 bit_desc_setp = __efx_mae_action_rule_mv_bit_desc_set; 1461 bit_desc_set_nentries = 1462 EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_bit_desc_set); 1463 mvp = spec->emms_mask_value_pairs.action; 1464 break; 1465 default: 1466 return (B_FALSE); 1467 } 1468 1469 if (field_caps == NULL) 1470 return (B_FALSE); 1471 1472 for (field_id = 0; (unsigned int)field_id < desc_set_nentries; 1473 ++field_id) { 1474 const efx_mae_mv_desc_t *descp = &desc_setp[field_id]; 1475 efx_mae_field_cap_id_t field_cap_id = descp->emmd_field_cap_id; 1476 const uint8_t *alt_m_buf = mvp + descp->emmd_alt_mask_offset; 1477 const uint8_t *m_buf = mvp + descp->emmd_mask_offset; 1478 size_t alt_m_size = descp->emmd_alt_mask_size; 1479 size_t m_size = descp->emmd_mask_size; 1480 1481 if (m_size == 0) 1482 continue; /* Skip array gap */ 1483 1484 if ((unsigned int)field_cap_id >= field_ncaps) { 1485 /* 1486 * The FW has not reported capability status for 1487 * this field. Make sure that its mask is zeroed. 1488 */ 1489 is_valid = efx_mask_is_all_zeros(m_size, m_buf); 1490 if (is_valid != B_FALSE) 1491 continue; 1492 else 1493 break; 1494 } 1495 1496 switch (field_caps[field_cap_id].emfc_support) { 1497 case MAE_FIELD_SUPPORTED_MATCH_MASK: 1498 is_valid = B_TRUE; 1499 break; 1500 case MAE_FIELD_SUPPORTED_MATCH_PREFIX: 1501 is_valid = efx_mask_is_prefix(m_size, m_buf); 1502 break; 1503 case MAE_FIELD_SUPPORTED_MATCH_OPTIONAL: 1504 is_valid = (efx_mask_is_all_ones(m_size, m_buf) || 1505 efx_mask_is_all_zeros(m_size, m_buf)); 1506 break; 1507 case MAE_FIELD_SUPPORTED_MATCH_ALWAYS: 1508 is_valid = efx_mask_is_all_ones(m_size, m_buf); 1509 1510 if ((is_valid == B_FALSE) && (alt_m_size != 0)) { 1511 /* 1512 * This field has an alternative one. The FW 1513 * reports ALWAYS for both implying that one 1514 * of them is required to have all-ones mask. 1515 * 1516 * The primary field's mask is incorrect; go 1517 * on to check that of the alternative field. 1518 */ 1519 is_valid = efx_mask_is_all_ones(alt_m_size, 1520 alt_m_buf); 1521 } 1522 break; 1523 case MAE_FIELD_SUPPORTED_MATCH_NEVER: 1524 case MAE_FIELD_UNSUPPORTED: 1525 default: 1526 is_valid = efx_mask_is_all_zeros(m_size, m_buf); 1527 break; 1528 } 1529 1530 if (is_valid == B_FALSE) 1531 return (B_FALSE); 1532 } 1533 1534 for (field_id = 0; (unsigned int)field_id < bit_desc_set_nentries; 1535 ++field_id) { 1536 const efx_mae_mv_bit_desc_t *bit_descp = 1537 &bit_desc_setp[field_id]; 1538 unsigned int byte_idx = 1539 bit_descp->emmbd_mask_ofst + 1540 bit_descp->emmbd_mask_lbn / 8; 1541 unsigned int bit_idx = 1542 bit_descp->emmbd_mask_lbn % 8; 1543 efx_mae_field_cap_id_t bit_cap_id = 1544 bit_descp->emmbd_bit_cap_id; 1545 1546 if (bit_descp->emmbd_entry_is_valid == B_FALSE) 1547 continue; /* Skip array gap */ 1548 1549 if ((unsigned int)bit_cap_id >= field_ncaps) { 1550 /* No capability for this bit = unsupported. */ 1551 is_valid = ((mvp[byte_idx] & (1U << bit_idx)) == 0); 1552 if (is_valid == B_FALSE) 1553 break; 1554 else 1555 continue; 1556 } 1557 1558 switch (field_caps[bit_cap_id].emfc_support) { 1559 case MAE_FIELD_SUPPORTED_MATCH_OPTIONAL: 1560 is_valid = B_TRUE; 1561 break; 1562 case MAE_FIELD_SUPPORTED_MATCH_ALWAYS: 1563 is_valid = ((mvp[byte_idx] & (1U << bit_idx)) != 0); 1564 break; 1565 case MAE_FIELD_SUPPORTED_MATCH_NEVER: 1566 case MAE_FIELD_UNSUPPORTED: 1567 default: 1568 is_valid = ((mvp[byte_idx] & (1U << bit_idx)) == 0); 1569 break; 1570 } 1571 1572 if (is_valid == B_FALSE) 1573 break; 1574 } 1575 1576 return (is_valid); 1577 } 1578 1579 __checkReturn efx_rc_t 1580 efx_mae_action_set_spec_init( 1581 __in efx_nic_t *enp, 1582 __out efx_mae_actions_t **specp) 1583 { 1584 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 1585 efx_mae_actions_t *spec; 1586 efx_rc_t rc; 1587 1588 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec), spec); 1589 if (spec == NULL) { 1590 rc = ENOMEM; 1591 goto fail1; 1592 } 1593 1594 efx_mae_action_set_clear_fw_rsrc_ids(spec); 1595 1596 /* 1597 * Helpers which populate v2 actions must reject them when v2 is not 1598 * supported. As they have no EFX NIC argument, save v2 status here. 1599 */ 1600 spec->ema_v2_is_supported = encp->enc_mae_aset_v2_supported; 1601 1602 *specp = spec; 1603 1604 return (0); 1605 1606 fail1: 1607 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1608 return (rc); 1609 } 1610 1611 void 1612 efx_mae_action_set_spec_fini( 1613 __in efx_nic_t *enp, 1614 __in efx_mae_actions_t *spec) 1615 { 1616 EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec); 1617 } 1618 1619 static __checkReturn efx_rc_t 1620 efx_mae_action_set_no_op( 1621 __in efx_mae_actions_t *spec, 1622 __in size_t arg_size, 1623 __in_bcount(arg_size) const uint8_t *arg) 1624 { 1625 efx_rc_t rc; 1626 1627 _NOTE(ARGUNUSED(spec)) 1628 1629 if (arg_size != 0) { 1630 rc = EINVAL; 1631 goto fail1; 1632 } 1633 1634 if (arg != NULL) { 1635 rc = EINVAL; 1636 goto fail2; 1637 } 1638 1639 /* This action does not have any arguments, so do nothing here. */ 1640 1641 return (0); 1642 1643 fail2: 1644 EFSYS_PROBE(fail2); 1645 fail1: 1646 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1647 return (rc); 1648 } 1649 1650 static __checkReturn efx_rc_t 1651 efx_mae_action_set_add_vlan_pop( 1652 __in efx_mae_actions_t *spec, 1653 __in size_t arg_size, 1654 __in_bcount(arg_size) const uint8_t *arg) 1655 { 1656 efx_rc_t rc; 1657 1658 if (arg_size != 0) { 1659 rc = EINVAL; 1660 goto fail1; 1661 } 1662 1663 if (arg != NULL) { 1664 rc = EINVAL; 1665 goto fail2; 1666 } 1667 1668 if (spec->ema_n_vlan_tags_to_pop == EFX_MAE_VLAN_POP_MAX_NTAGS) { 1669 rc = ENOTSUP; 1670 goto fail3; 1671 } 1672 1673 ++spec->ema_n_vlan_tags_to_pop; 1674 1675 return (0); 1676 1677 fail3: 1678 EFSYS_PROBE(fail3); 1679 fail2: 1680 EFSYS_PROBE(fail2); 1681 fail1: 1682 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1683 return (rc); 1684 } 1685 1686 static __checkReturn efx_rc_t 1687 efx_mae_action_set_add_vlan_push( 1688 __in efx_mae_actions_t *spec, 1689 __in size_t arg_size, 1690 __in_bcount(arg_size) const uint8_t *arg) 1691 { 1692 unsigned int n_tags = spec->ema_n_vlan_tags_to_push; 1693 efx_rc_t rc; 1694 1695 if (arg_size != sizeof (*spec->ema_vlan_push_descs)) { 1696 rc = EINVAL; 1697 goto fail1; 1698 } 1699 1700 if (arg == NULL) { 1701 rc = EINVAL; 1702 goto fail2; 1703 } 1704 1705 if (n_tags == EFX_MAE_VLAN_PUSH_MAX_NTAGS) { 1706 rc = ENOTSUP; 1707 goto fail3; 1708 } 1709 1710 memcpy(&spec->ema_vlan_push_descs[n_tags], arg, arg_size); 1711 ++(spec->ema_n_vlan_tags_to_push); 1712 1713 return (0); 1714 1715 fail3: 1716 EFSYS_PROBE(fail3); 1717 fail2: 1718 EFSYS_PROBE(fail2); 1719 fail1: 1720 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1721 return (rc); 1722 } 1723 1724 static __checkReturn efx_rc_t 1725 efx_mae_action_set_add_count( 1726 __in efx_mae_actions_t *spec, 1727 __in size_t arg_size, 1728 __in_bcount(arg_size) const uint8_t *arg) 1729 { 1730 efx_rc_t rc; 1731 1732 EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID == 1733 MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_NULL); 1734 1735 /* 1736 * Preparing an action set spec to update a counter requires 1737 * two steps: first add this action to the action spec, and then 1738 * add the counter ID to the spec. This allows validity checking 1739 * and resource allocation to be done separately. 1740 * 1741 * In order to fill in the counter ID, the caller is supposed to invoke 1742 * efx_mae_action_set_fill_in_counter_id(). If they do not do that, 1743 * efx_mae_action_set_alloc() invocation will throw an error. 1744 * 1745 * For now, no arguments are supposed to be handled. 1746 */ 1747 1748 if (arg_size != 0) { 1749 rc = EINVAL; 1750 goto fail1; 1751 } 1752 1753 if (arg != NULL) { 1754 rc = EINVAL; 1755 goto fail2; 1756 } 1757 1758 ++(spec->ema_n_count_actions); 1759 1760 return (0); 1761 1762 fail2: 1763 EFSYS_PROBE(fail2); 1764 fail1: 1765 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1766 return (rc); 1767 } 1768 1769 static __checkReturn efx_rc_t 1770 efx_mae_action_set_add_mark( 1771 __in efx_mae_actions_t *spec, 1772 __in size_t arg_size, 1773 __in_bcount(arg_size) const uint8_t *arg) 1774 { 1775 efx_rc_t rc; 1776 1777 if (arg_size != sizeof (spec->ema_mark_value)) { 1778 rc = EINVAL; 1779 goto fail1; 1780 } 1781 1782 if (arg == NULL) { 1783 rc = EINVAL; 1784 goto fail2; 1785 } 1786 1787 memcpy(&spec->ema_mark_value, arg, arg_size); 1788 1789 return (0); 1790 1791 fail2: 1792 EFSYS_PROBE(fail2); 1793 fail1: 1794 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1795 return (rc); 1796 } 1797 1798 static __checkReturn efx_rc_t 1799 efx_mae_action_set_add_deliver( 1800 __in efx_mae_actions_t *spec, 1801 __in size_t arg_size, 1802 __in_bcount(arg_size) const uint8_t *arg) 1803 { 1804 efx_rc_t rc; 1805 1806 if (arg_size != sizeof (spec->ema_deliver_mport)) { 1807 rc = EINVAL; 1808 goto fail1; 1809 } 1810 1811 if (arg == NULL) { 1812 rc = EINVAL; 1813 goto fail2; 1814 } 1815 1816 memcpy(&spec->ema_deliver_mport, arg, arg_size); 1817 1818 return (0); 1819 1820 fail2: 1821 EFSYS_PROBE(fail2); 1822 fail1: 1823 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1824 return (rc); 1825 } 1826 1827 typedef struct efx_mae_action_desc_s { 1828 /* Action specific handler */ 1829 efx_rc_t (*emad_add)(efx_mae_actions_t *, 1830 size_t, const uint8_t *); 1831 } efx_mae_action_desc_t; 1832 1833 static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = { 1834 [EFX_MAE_ACTION_DECAP] = { 1835 .emad_add = efx_mae_action_set_no_op 1836 }, 1837 [EFX_MAE_ACTION_VLAN_POP] = { 1838 .emad_add = efx_mae_action_set_add_vlan_pop 1839 }, 1840 [EFX_MAE_ACTION_SET_DST_MAC] = { 1841 .emad_add = efx_mae_action_set_no_op 1842 }, 1843 [EFX_MAE_ACTION_SET_SRC_MAC] = { 1844 .emad_add = efx_mae_action_set_no_op 1845 }, 1846 [EFX_MAE_ACTION_DECR_IP_TTL] = { 1847 .emad_add = efx_mae_action_set_no_op 1848 }, 1849 [EFX_MAE_ACTION_NAT] = { 1850 .emad_add = efx_mae_action_set_no_op 1851 }, 1852 [EFX_MAE_ACTION_VLAN_PUSH] = { 1853 .emad_add = efx_mae_action_set_add_vlan_push 1854 }, 1855 [EFX_MAE_ACTION_ENCAP] = { 1856 .emad_add = efx_mae_action_set_no_op 1857 }, 1858 [EFX_MAE_ACTION_COUNT] = { 1859 .emad_add = efx_mae_action_set_add_count 1860 }, 1861 [EFX_MAE_ACTION_FLAG] = { 1862 .emad_add = efx_mae_action_set_no_op 1863 }, 1864 [EFX_MAE_ACTION_MARK] = { 1865 .emad_add = efx_mae_action_set_add_mark 1866 }, 1867 [EFX_MAE_ACTION_DELIVER] = { 1868 .emad_add = efx_mae_action_set_add_deliver 1869 } 1870 }; 1871 1872 static const uint32_t efx_mae_action_ordered_map = 1873 (1U << EFX_MAE_ACTION_DECAP) | 1874 (1U << EFX_MAE_ACTION_VLAN_POP) | 1875 (1U << EFX_MAE_ACTION_SET_DST_MAC) | 1876 (1U << EFX_MAE_ACTION_SET_SRC_MAC) | 1877 (1U << EFX_MAE_ACTION_DECR_IP_TTL) | 1878 (1U << EFX_MAE_ACTION_NAT) | 1879 (1U << EFX_MAE_ACTION_VLAN_PUSH) | 1880 /* 1881 * HW will conduct action COUNT after 1882 * the matching packet has been modified by 1883 * length-affecting actions except for ENCAP. 1884 */ 1885 (1U << EFX_MAE_ACTION_COUNT) | 1886 (1U << EFX_MAE_ACTION_ENCAP) | 1887 (1U << EFX_MAE_ACTION_FLAG) | 1888 (1U << EFX_MAE_ACTION_MARK) | 1889 (1U << EFX_MAE_ACTION_DELIVER); 1890 1891 /* 1892 * These actions must not be added after DELIVER, but 1893 * they can have any place among the rest of 1894 * strictly ordered actions. 1895 */ 1896 static const uint32_t efx_mae_action_nonstrict_map = 1897 (1U << EFX_MAE_ACTION_COUNT) | 1898 (1U << EFX_MAE_ACTION_FLAG) | 1899 (1U << EFX_MAE_ACTION_MARK); 1900 1901 static const uint32_t efx_mae_action_repeat_map = 1902 (1U << EFX_MAE_ACTION_VLAN_POP) | 1903 (1U << EFX_MAE_ACTION_VLAN_PUSH) | 1904 (1U << EFX_MAE_ACTION_COUNT); 1905 1906 /* 1907 * Add an action to an action set. 1908 * 1909 * This has to be invoked in the desired action order. 1910 * An out-of-order action request will be turned down. 1911 */ 1912 static __checkReturn efx_rc_t 1913 efx_mae_action_set_spec_populate( 1914 __in efx_mae_actions_t *spec, 1915 __in efx_mae_action_t type, 1916 __in size_t arg_size, 1917 __in_bcount(arg_size) const uint8_t *arg) 1918 { 1919 uint32_t action_mask; 1920 efx_rc_t rc; 1921 1922 EFX_STATIC_ASSERT(EFX_MAE_NACTIONS <= 1923 (sizeof (efx_mae_action_ordered_map) * 8)); 1924 EFX_STATIC_ASSERT(EFX_MAE_NACTIONS <= 1925 (sizeof (efx_mae_action_repeat_map) * 8)); 1926 1927 EFX_STATIC_ASSERT(EFX_MAE_ACTION_DELIVER + 1 == EFX_MAE_NACTIONS); 1928 EFX_STATIC_ASSERT(EFX_MAE_ACTION_FLAG + 1 == EFX_MAE_ACTION_MARK); 1929 EFX_STATIC_ASSERT(EFX_MAE_ACTION_MARK + 1 == EFX_MAE_ACTION_DELIVER); 1930 1931 if (type >= EFX_ARRAY_SIZE(efx_mae_actions)) { 1932 rc = EINVAL; 1933 goto fail1; 1934 } 1935 1936 action_mask = (1U << type); 1937 1938 if ((spec->ema_actions & action_mask) != 0) { 1939 /* The action set already contains this action. */ 1940 if ((efx_mae_action_repeat_map & action_mask) == 0) { 1941 /* Cannot add another non-repeatable action. */ 1942 rc = ENOTSUP; 1943 goto fail2; 1944 } 1945 } 1946 1947 if ((efx_mae_action_ordered_map & action_mask) != 0) { 1948 uint32_t strict_ordered_map = 1949 efx_mae_action_ordered_map & ~efx_mae_action_nonstrict_map; 1950 uint32_t later_actions_mask = 1951 strict_ordered_map & ~(action_mask | (action_mask - 1)); 1952 1953 if ((spec->ema_actions & later_actions_mask) != 0) { 1954 /* Cannot add an action after later ordered actions. */ 1955 rc = ENOTSUP; 1956 goto fail3; 1957 } 1958 } 1959 1960 if (efx_mae_actions[type].emad_add != NULL) { 1961 rc = efx_mae_actions[type].emad_add(spec, arg_size, arg); 1962 if (rc != 0) 1963 goto fail4; 1964 } 1965 1966 spec->ema_actions |= action_mask; 1967 1968 return (0); 1969 1970 fail4: 1971 EFSYS_PROBE(fail4); 1972 fail3: 1973 EFSYS_PROBE(fail3); 1974 fail2: 1975 EFSYS_PROBE(fail2); 1976 fail1: 1977 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1978 return (rc); 1979 } 1980 1981 __checkReturn efx_rc_t 1982 efx_mae_action_set_populate_decap( 1983 __in efx_mae_actions_t *spec) 1984 { 1985 return (efx_mae_action_set_spec_populate(spec, 1986 EFX_MAE_ACTION_DECAP, 0, NULL)); 1987 } 1988 1989 __checkReturn efx_rc_t 1990 efx_mae_action_set_populate_vlan_pop( 1991 __in efx_mae_actions_t *spec) 1992 { 1993 return (efx_mae_action_set_spec_populate(spec, 1994 EFX_MAE_ACTION_VLAN_POP, 0, NULL)); 1995 } 1996 1997 __checkReturn efx_rc_t 1998 efx_mae_action_set_populate_set_dst_mac( 1999 __in efx_mae_actions_t *spec) 2000 { 2001 efx_rc_t rc; 2002 2003 if (spec->ema_v2_is_supported == B_FALSE) { 2004 rc = ENOTSUP; 2005 goto fail1; 2006 } 2007 2008 return (efx_mae_action_set_spec_populate(spec, 2009 EFX_MAE_ACTION_SET_DST_MAC, 0, NULL)); 2010 2011 fail1: 2012 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2013 return (rc); 2014 } 2015 2016 __checkReturn efx_rc_t 2017 efx_mae_action_set_populate_set_src_mac( 2018 __in efx_mae_actions_t *spec) 2019 { 2020 efx_rc_t rc; 2021 2022 if (spec->ema_v2_is_supported == B_FALSE) { 2023 rc = ENOTSUP; 2024 goto fail1; 2025 } 2026 2027 return (efx_mae_action_set_spec_populate(spec, 2028 EFX_MAE_ACTION_SET_SRC_MAC, 0, NULL)); 2029 2030 fail1: 2031 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2032 return (rc); 2033 } 2034 2035 __checkReturn efx_rc_t 2036 efx_mae_action_set_populate_decr_ip_ttl( 2037 __in efx_mae_actions_t *spec) 2038 { 2039 efx_rc_t rc; 2040 2041 if (spec->ema_v2_is_supported == B_FALSE) { 2042 rc = ENOTSUP; 2043 goto fail1; 2044 } 2045 2046 return (efx_mae_action_set_spec_populate(spec, 2047 EFX_MAE_ACTION_DECR_IP_TTL, 0, NULL)); 2048 2049 fail1: 2050 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2051 return (rc); 2052 } 2053 2054 __checkReturn efx_rc_t 2055 efx_mae_action_set_populate_nat( 2056 __in efx_mae_actions_t *spec) 2057 { 2058 return (efx_mae_action_set_spec_populate(spec, 2059 EFX_MAE_ACTION_NAT, 0, NULL)); 2060 } 2061 2062 __checkReturn efx_rc_t 2063 efx_mae_action_set_populate_vlan_push( 2064 __in efx_mae_actions_t *spec, 2065 __in uint16_t tpid_be, 2066 __in uint16_t tci_be) 2067 { 2068 efx_mae_action_vlan_push_t action; 2069 const uint8_t *arg = (const uint8_t *)&action; 2070 2071 action.emavp_tpid_be = tpid_be; 2072 action.emavp_tci_be = tci_be; 2073 2074 return (efx_mae_action_set_spec_populate(spec, 2075 EFX_MAE_ACTION_VLAN_PUSH, sizeof (action), arg)); 2076 } 2077 2078 __checkReturn efx_rc_t 2079 efx_mae_action_set_populate_encap( 2080 __in efx_mae_actions_t *spec) 2081 { 2082 /* 2083 * There is no argument to pass encap. header ID, thus, one does not 2084 * need to allocate an encap. header while parsing application input. 2085 * This is useful since building an action set may be done simply to 2086 * validate a rule, whilst resource allocation usually consumes time. 2087 */ 2088 return (efx_mae_action_set_spec_populate(spec, 2089 EFX_MAE_ACTION_ENCAP, 0, NULL)); 2090 } 2091 2092 __checkReturn efx_rc_t 2093 efx_mae_action_set_populate_count( 2094 __in efx_mae_actions_t *spec) 2095 { 2096 /* 2097 * There is no argument to pass counter ID, thus, one does not 2098 * need to allocate a counter while parsing application input. 2099 * This is useful since building an action set may be done simply to 2100 * validate a rule, whilst resource allocation usually consumes time. 2101 */ 2102 return (efx_mae_action_set_spec_populate(spec, 2103 EFX_MAE_ACTION_COUNT, 0, NULL)); 2104 } 2105 2106 __checkReturn efx_rc_t 2107 efx_mae_action_set_populate_flag( 2108 __in efx_mae_actions_t *spec) 2109 { 2110 return (efx_mae_action_set_spec_populate(spec, 2111 EFX_MAE_ACTION_FLAG, 0, NULL)); 2112 } 2113 2114 __checkReturn efx_rc_t 2115 efx_mae_action_set_populate_mark( 2116 __in efx_mae_actions_t *spec, 2117 __in uint32_t mark_value) 2118 { 2119 const uint8_t *arg = (const uint8_t *)&mark_value; 2120 2121 return (efx_mae_action_set_spec_populate(spec, 2122 EFX_MAE_ACTION_MARK, sizeof (mark_value), arg)); 2123 } 2124 2125 void 2126 efx_mae_action_set_populate_mark_reset( 2127 __in efx_mae_actions_t *spec) 2128 { 2129 uint32_t action_mask = (1U << EFX_MAE_ACTION_MARK); 2130 2131 if ((spec->ema_actions & action_mask) == 0) { 2132 spec->ema_actions |= action_mask; 2133 spec->ema_mark_value = 0; 2134 } 2135 } 2136 2137 __checkReturn efx_rc_t 2138 efx_mae_action_set_populate_deliver( 2139 __in efx_mae_actions_t *spec, 2140 __in const efx_mport_sel_t *mportp) 2141 { 2142 const uint8_t *arg; 2143 efx_rc_t rc; 2144 2145 if (mportp == NULL) { 2146 rc = EINVAL; 2147 goto fail1; 2148 } 2149 2150 arg = (const uint8_t *)&mportp->sel; 2151 2152 return (efx_mae_action_set_spec_populate(spec, 2153 EFX_MAE_ACTION_DELIVER, sizeof (mportp->sel), arg)); 2154 2155 fail1: 2156 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2157 return (rc); 2158 } 2159 2160 __checkReturn efx_rc_t 2161 efx_mae_action_set_populate_drop( 2162 __in efx_mae_actions_t *spec) 2163 { 2164 efx_mport_sel_t mport; 2165 const uint8_t *arg; 2166 efx_dword_t dword; 2167 2168 EFX_POPULATE_DWORD_1(dword, 2169 MAE_MPORT_SELECTOR_FLAT, MAE_MPORT_SELECTOR_NULL); 2170 2171 /* 2172 * The constructed DWORD is little-endian, 2173 * but the resulting value is meant to be 2174 * passed to MCDIs, where it will undergo 2175 * host-order to little endian conversion. 2176 */ 2177 mport.sel = EFX_DWORD_FIELD(dword, EFX_DWORD_0); 2178 2179 arg = (const uint8_t *)&mport.sel; 2180 2181 return (efx_mae_action_set_spec_populate(spec, 2182 EFX_MAE_ACTION_DELIVER, sizeof (mport.sel), arg)); 2183 } 2184 2185 __checkReturn boolean_t 2186 efx_mae_action_set_specs_equal( 2187 __in const efx_mae_actions_t *left, 2188 __in const efx_mae_actions_t *right) 2189 { 2190 size_t cmp_size = EFX_FIELD_OFFSET(efx_mae_actions_t, ema_rsrc); 2191 2192 /* 2193 * An action set specification consists of two parts. The first part 2194 * indicates what actions are included in the action set, as well as 2195 * extra quantitative values (in example, the number of VLAN tags to 2196 * push). The second part comprises resource IDs used by the actions. 2197 * 2198 * A resource, in example, a counter, is allocated from the hardware 2199 * by the client, and it's the client who is responsible for keeping 2200 * track of allocated resources and comparing resource IDs if needed. 2201 * 2202 * In this API, don't compare resource IDs in the two specifications. 2203 */ 2204 2205 return ((memcmp(left, right, cmp_size) == 0) ? B_TRUE : B_FALSE); 2206 } 2207 2208 __checkReturn efx_rc_t 2209 efx_mae_match_specs_class_cmp( 2210 __in efx_nic_t *enp, 2211 __in const efx_mae_match_spec_t *left, 2212 __in const efx_mae_match_spec_t *right, 2213 __out boolean_t *have_same_classp) 2214 { 2215 efx_mae_t *maep = enp->en_maep; 2216 unsigned int field_ncaps = maep->em_max_nfields; 2217 const efx_mae_field_cap_t *field_caps; 2218 const efx_mae_mv_desc_t *desc_setp; 2219 unsigned int desc_set_nentries; 2220 const efx_mae_mv_bit_desc_t *bit_desc_setp; 2221 unsigned int bit_desc_set_nentries; 2222 boolean_t have_same_class = B_TRUE; 2223 efx_mae_field_id_t field_id; 2224 const uint8_t *mvpl; 2225 const uint8_t *mvpr; 2226 efx_rc_t rc; 2227 2228 switch (left->emms_type) { 2229 case EFX_MAE_RULE_OUTER: 2230 field_caps = maep->em_outer_rule_field_caps; 2231 desc_setp = __efx_mae_outer_rule_mv_desc_set; 2232 desc_set_nentries = 2233 EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set); 2234 bit_desc_setp = __efx_mae_outer_rule_mv_bit_desc_set; 2235 bit_desc_set_nentries = 2236 EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_bit_desc_set); 2237 mvpl = left->emms_mask_value_pairs.outer; 2238 mvpr = right->emms_mask_value_pairs.outer; 2239 break; 2240 case EFX_MAE_RULE_ACTION: 2241 field_caps = maep->em_action_rule_field_caps; 2242 desc_setp = __efx_mae_action_rule_mv_desc_set; 2243 desc_set_nentries = 2244 EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set); 2245 bit_desc_setp = __efx_mae_action_rule_mv_bit_desc_set; 2246 bit_desc_set_nentries = 2247 EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_bit_desc_set); 2248 mvpl = left->emms_mask_value_pairs.action; 2249 mvpr = right->emms_mask_value_pairs.action; 2250 break; 2251 default: 2252 rc = ENOTSUP; 2253 goto fail1; 2254 } 2255 2256 if (field_caps == NULL) { 2257 rc = EAGAIN; 2258 goto fail2; 2259 } 2260 2261 if (left->emms_type != right->emms_type || 2262 left->emms_prio != right->emms_prio) { 2263 /* 2264 * Rules of different types can never map to the same class. 2265 * 2266 * The FW can support some set of match criteria for one 2267 * priority and not support the very same set for 2268 * another priority. Thus, two rules which have 2269 * different priorities can never map to 2270 * the same class. 2271 */ 2272 *have_same_classp = B_FALSE; 2273 return (0); 2274 } 2275 2276 for (field_id = 0; (unsigned int)field_id < desc_set_nentries; 2277 ++field_id) { 2278 const efx_mae_mv_desc_t *descp = &desc_setp[field_id]; 2279 efx_mae_field_cap_id_t field_cap_id = descp->emmd_field_cap_id; 2280 const uint8_t *lmaskp = mvpl + descp->emmd_mask_offset; 2281 const uint8_t *rmaskp = mvpr + descp->emmd_mask_offset; 2282 size_t mask_size = descp->emmd_mask_size; 2283 const uint8_t *lvalp = mvpl + descp->emmd_value_offset; 2284 const uint8_t *rvalp = mvpr + descp->emmd_value_offset; 2285 size_t value_size = descp->emmd_value_size; 2286 2287 if (mask_size == 0) 2288 continue; /* Skip array gap */ 2289 2290 if ((unsigned int)field_cap_id >= field_ncaps) { 2291 /* 2292 * The FW has not reported capability status for this 2293 * field. It's unknown whether any difference between 2294 * the two masks / values affects the class. The only 2295 * case when the class must be the same is when these 2296 * mask-value pairs match. Otherwise, report mismatch. 2297 */ 2298 if ((memcmp(lmaskp, rmaskp, mask_size) == 0) && 2299 (memcmp(lvalp, rvalp, value_size) == 0)) 2300 continue; 2301 else 2302 break; 2303 } 2304 2305 if (field_caps[field_cap_id].emfc_mask_affects_class) { 2306 if (memcmp(lmaskp, rmaskp, mask_size) != 0) { 2307 have_same_class = B_FALSE; 2308 break; 2309 } 2310 } 2311 2312 if (field_caps[field_cap_id].emfc_match_affects_class) { 2313 if (memcmp(lvalp, rvalp, value_size) != 0) { 2314 have_same_class = B_FALSE; 2315 break; 2316 } 2317 } 2318 } 2319 2320 if (have_same_class == B_FALSE) 2321 goto done; 2322 2323 for (field_id = 0; (unsigned int)field_id < bit_desc_set_nentries; 2324 ++field_id) { 2325 const efx_mae_mv_bit_desc_t *bit_descp = 2326 &bit_desc_setp[field_id]; 2327 efx_mae_field_cap_id_t bit_cap_id = 2328 bit_descp->emmbd_bit_cap_id; 2329 unsigned int byte_idx; 2330 unsigned int bit_idx; 2331 2332 if (bit_descp->emmbd_entry_is_valid == B_FALSE) 2333 continue; /* Skip array gap */ 2334 2335 if ((unsigned int)bit_cap_id >= field_ncaps) 2336 break; 2337 2338 byte_idx = 2339 bit_descp->emmbd_mask_ofst + 2340 bit_descp->emmbd_mask_lbn / 8; 2341 bit_idx = 2342 bit_descp->emmbd_mask_lbn % 8; 2343 2344 if (field_caps[bit_cap_id].emfc_mask_affects_class && 2345 (mvpl[byte_idx] & (1U << bit_idx)) != 2346 (mvpr[byte_idx] & (1U << bit_idx))) { 2347 have_same_class = B_FALSE; 2348 break; 2349 } 2350 2351 byte_idx = 2352 bit_descp->emmbd_value_ofst + 2353 bit_descp->emmbd_value_lbn / 8; 2354 bit_idx = 2355 bit_descp->emmbd_value_lbn % 8; 2356 2357 if (field_caps[bit_cap_id].emfc_match_affects_class && 2358 (mvpl[byte_idx] & (1U << bit_idx)) != 2359 (mvpr[byte_idx] & (1U << bit_idx))) { 2360 have_same_class = B_FALSE; 2361 break; 2362 } 2363 } 2364 2365 done: 2366 *have_same_classp = have_same_class; 2367 2368 return (0); 2369 2370 fail2: 2371 EFSYS_PROBE(fail2); 2372 fail1: 2373 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2374 return (rc); 2375 } 2376 2377 __checkReturn efx_rc_t 2378 efx_mae_outer_rule_recirc_id_set( 2379 __in efx_mae_match_spec_t *spec, 2380 __in uint8_t recirc_id) 2381 { 2382 efx_rc_t rc; 2383 2384 if (spec->emms_type != EFX_MAE_RULE_OUTER) { 2385 rc = EINVAL; 2386 goto fail1; 2387 } 2388 2389 spec->emms_outer_rule_recirc_id = recirc_id; 2390 2391 return (0); 2392 2393 fail1: 2394 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2395 return (rc); 2396 } 2397 2398 __checkReturn efx_rc_t 2399 efx_mae_outer_rule_do_ct_set( 2400 __in efx_mae_match_spec_t *spec) 2401 { 2402 efx_rc_t rc; 2403 2404 if (spec->emms_type != EFX_MAE_RULE_OUTER) { 2405 rc = EINVAL; 2406 goto fail1; 2407 } 2408 2409 spec->emms_outer_rule_do_ct = B_TRUE; 2410 2411 return (0); 2412 2413 fail1: 2414 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2415 return (rc); 2416 } 2417 2418 __checkReturn efx_rc_t 2419 efx_mae_outer_rule_insert( 2420 __in efx_nic_t *enp, 2421 __in const efx_mae_match_spec_t *spec, 2422 __in efx_tunnel_protocol_t encap_type, 2423 __out efx_mae_rule_id_t *or_idp) 2424 { 2425 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 2426 efx_mcdi_req_t req; 2427 EFX_MCDI_DECLARE_BUF(payload, 2428 MC_CMD_MAE_OUTER_RULE_INSERT_IN_LENMAX_MCDI2, 2429 MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN); 2430 uint32_t encap_type_mcdi; 2431 efx_mae_rule_id_t or_id; 2432 size_t offset; 2433 uint8_t do_ct; 2434 efx_rc_t rc; 2435 2436 EFX_STATIC_ASSERT(sizeof (or_idp->id) == 2437 MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OR_ID_LEN); 2438 2439 EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID == 2440 MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OUTER_RULE_ID_NULL); 2441 2442 if (encp->enc_mae_supported == B_FALSE) { 2443 rc = ENOTSUP; 2444 goto fail1; 2445 } 2446 2447 if (spec->emms_type != EFX_MAE_RULE_OUTER) { 2448 rc = EINVAL; 2449 goto fail2; 2450 } 2451 2452 switch (encap_type) { 2453 case EFX_TUNNEL_PROTOCOL_NONE: 2454 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NONE; 2455 break; 2456 case EFX_TUNNEL_PROTOCOL_VXLAN: 2457 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_VXLAN; 2458 break; 2459 case EFX_TUNNEL_PROTOCOL_GENEVE: 2460 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_GENEVE; 2461 break; 2462 case EFX_TUNNEL_PROTOCOL_NVGRE: 2463 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NVGRE; 2464 break; 2465 default: 2466 rc = ENOTSUP; 2467 goto fail3; 2468 } 2469 2470 req.emr_cmd = MC_CMD_MAE_OUTER_RULE_INSERT; 2471 req.emr_in_buf = payload; 2472 req.emr_in_length = MC_CMD_MAE_OUTER_RULE_INSERT_IN_LENMAX_MCDI2; 2473 req.emr_out_buf = payload; 2474 req.emr_out_length = MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN; 2475 2476 MCDI_IN_SET_DWORD(req, 2477 MAE_OUTER_RULE_INSERT_IN_ENCAP_TYPE, encap_type_mcdi); 2478 2479 MCDI_IN_SET_DWORD(req, MAE_OUTER_RULE_INSERT_IN_PRIO, spec->emms_prio); 2480 2481 /* 2482 * Mask-value pairs have been stored in the byte order needed for the 2483 * MCDI request and are thus safe to be copied directly to the buffer. 2484 * The library cares about byte order in efx_mae_match_spec_field_set(). 2485 */ 2486 EFX_STATIC_ASSERT(sizeof (spec->emms_mask_value_pairs.outer) >= 2487 MAE_ENC_FIELD_PAIRS_LEN); 2488 offset = MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_OFST; 2489 memcpy(payload + offset, spec->emms_mask_value_pairs.outer, 2490 MAE_ENC_FIELD_PAIRS_LEN); 2491 2492 MCDI_IN_SET_DWORD_FIELD(req, MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL, 2493 MAE_OUTER_RULE_INSERT_IN_RECIRC_ID, 2494 spec->emms_outer_rule_recirc_id); 2495 2496 do_ct = (spec->emms_outer_rule_do_ct == B_FALSE) ? 0 : 1; 2497 2498 MCDI_IN_SET_DWORD_FIELD(req, MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL, 2499 MAE_OUTER_RULE_INSERT_IN_DO_CT, do_ct); 2500 2501 efx_mcdi_execute(enp, &req); 2502 2503 if (req.emr_rc != 0) { 2504 rc = req.emr_rc; 2505 goto fail4; 2506 } 2507 2508 if (req.emr_out_length_used < MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN) { 2509 rc = EMSGSIZE; 2510 goto fail5; 2511 } 2512 2513 or_id.id = MCDI_OUT_DWORD(req, MAE_OUTER_RULE_INSERT_OUT_OR_ID); 2514 if (or_id.id == EFX_MAE_RSRC_ID_INVALID) { 2515 rc = ENOENT; 2516 goto fail6; 2517 } 2518 2519 or_idp->id = or_id.id; 2520 2521 return (0); 2522 2523 fail6: 2524 EFSYS_PROBE(fail6); 2525 fail5: 2526 EFSYS_PROBE(fail5); 2527 fail4: 2528 EFSYS_PROBE(fail4); 2529 fail3: 2530 EFSYS_PROBE(fail3); 2531 fail2: 2532 EFSYS_PROBE(fail2); 2533 fail1: 2534 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2535 return (rc); 2536 } 2537 2538 __checkReturn efx_rc_t 2539 efx_mae_outer_rule_remove( 2540 __in efx_nic_t *enp, 2541 __in const efx_mae_rule_id_t *or_idp) 2542 { 2543 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 2544 efx_mcdi_req_t req; 2545 EFX_MCDI_DECLARE_BUF(payload, 2546 MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LEN(1), 2547 MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LEN(1)); 2548 efx_rc_t rc; 2549 2550 if (encp->enc_mae_supported == B_FALSE) { 2551 rc = ENOTSUP; 2552 goto fail1; 2553 } 2554 2555 req.emr_cmd = MC_CMD_MAE_OUTER_RULE_REMOVE; 2556 req.emr_in_buf = payload; 2557 req.emr_in_length = MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LEN(1); 2558 req.emr_out_buf = payload; 2559 req.emr_out_length = MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LEN(1); 2560 2561 MCDI_IN_SET_DWORD(req, MAE_OUTER_RULE_REMOVE_IN_OR_ID, or_idp->id); 2562 2563 efx_mcdi_execute(enp, &req); 2564 2565 if (req.emr_rc != 0) { 2566 rc = req.emr_rc; 2567 goto fail2; 2568 } 2569 2570 if (req.emr_out_length_used < MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LENMIN) { 2571 rc = EMSGSIZE; 2572 goto fail3; 2573 } 2574 2575 if (MCDI_OUT_DWORD(req, MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID) != 2576 or_idp->id) { 2577 /* Firmware failed to remove the outer rule. */ 2578 rc = EAGAIN; 2579 goto fail4; 2580 } 2581 2582 return (0); 2583 2584 fail4: 2585 EFSYS_PROBE(fail4); 2586 fail3: 2587 EFSYS_PROBE(fail3); 2588 fail2: 2589 EFSYS_PROBE(fail2); 2590 fail1: 2591 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2592 return (rc); 2593 } 2594 2595 __checkReturn efx_rc_t 2596 efx_mae_match_spec_outer_rule_id_set( 2597 __in efx_mae_match_spec_t *spec, 2598 __in const efx_mae_rule_id_t *or_idp) 2599 { 2600 uint32_t full_mask = UINT32_MAX; 2601 efx_rc_t rc; 2602 2603 if (spec->emms_type != EFX_MAE_RULE_ACTION) { 2604 rc = EINVAL; 2605 goto fail1; 2606 } 2607 2608 if (or_idp == NULL) { 2609 rc = EINVAL; 2610 goto fail2; 2611 } 2612 2613 rc = efx_mae_match_spec_field_set(spec, EFX_MAE_FIELD_OUTER_RULE_ID, 2614 sizeof (or_idp->id), (const uint8_t *)&or_idp->id, 2615 sizeof (full_mask), (const uint8_t *)&full_mask); 2616 if (rc != 0) 2617 goto fail3; 2618 2619 return (0); 2620 2621 fail3: 2622 EFSYS_PROBE(fail3); 2623 fail2: 2624 EFSYS_PROBE(fail2); 2625 fail1: 2626 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2627 return (rc); 2628 } 2629 2630 __checkReturn efx_rc_t 2631 efx_mae_mac_addr_alloc( 2632 __in efx_nic_t *enp, 2633 __in uint8_t addr_bytes[EFX_MAC_ADDR_LEN], 2634 __out efx_mae_mac_id_t *mac_idp) 2635 { 2636 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 2637 efx_mcdi_req_t req; 2638 EFX_MCDI_DECLARE_BUF(payload, 2639 MC_CMD_MAE_MAC_ADDR_ALLOC_IN_LEN, 2640 MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_LEN); 2641 efx_mae_mac_id_t mac_id; 2642 efx_rc_t rc; 2643 2644 EFX_STATIC_ASSERT(sizeof (mac_idp->id) == 2645 MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_LEN); 2646 2647 EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID == 2648 MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL); 2649 2650 if (encp->enc_mae_supported == B_FALSE) { 2651 rc = ENOTSUP; 2652 goto fail1; 2653 } 2654 2655 if (encp->enc_mae_aset_v2_supported == B_FALSE) { 2656 rc = ENOTSUP; 2657 goto fail2; 2658 } 2659 2660 req.emr_cmd = MC_CMD_MAE_MAC_ADDR_ALLOC; 2661 req.emr_in_buf = payload; 2662 req.emr_in_length = MC_CMD_MAE_MAC_ADDR_ALLOC_IN_LEN; 2663 req.emr_out_buf = payload; 2664 req.emr_out_length = MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_LEN; 2665 2666 memcpy(payload + MC_CMD_MAE_MAC_ADDR_ALLOC_IN_MAC_ADDR_OFST, 2667 addr_bytes, EFX_MAC_ADDR_LEN); 2668 2669 efx_mcdi_execute(enp, &req); 2670 2671 if (req.emr_rc != 0) { 2672 rc = req.emr_rc; 2673 goto fail3; 2674 } 2675 2676 if (req.emr_out_length_used < MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_LEN) { 2677 rc = EMSGSIZE; 2678 goto fail4; 2679 } 2680 2681 mac_id.id = MCDI_OUT_DWORD(req, MAE_MAC_ADDR_ALLOC_OUT_MAC_ID); 2682 if (mac_id.id == EFX_MAE_RSRC_ID_INVALID) { 2683 rc = ENOENT; 2684 goto fail5; 2685 } 2686 2687 mac_idp->id = mac_id.id; 2688 2689 return (0); 2690 2691 fail5: 2692 EFSYS_PROBE(fail5); 2693 fail4: 2694 EFSYS_PROBE(fail4); 2695 fail3: 2696 EFSYS_PROBE(fail3); 2697 fail2: 2698 EFSYS_PROBE(fail2); 2699 fail1: 2700 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2701 return (rc); 2702 } 2703 2704 __checkReturn efx_rc_t 2705 efx_mae_mac_addr_free( 2706 __in efx_nic_t *enp, 2707 __in const efx_mae_mac_id_t *mac_idp) 2708 { 2709 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 2710 efx_mcdi_req_t req; 2711 EFX_MCDI_DECLARE_BUF(payload, 2712 MC_CMD_MAE_MAC_ADDR_FREE_IN_LEN(1), 2713 MC_CMD_MAE_MAC_ADDR_FREE_OUT_LEN(1)); 2714 efx_rc_t rc; 2715 2716 if (encp->enc_mae_supported == B_FALSE) { 2717 rc = ENOTSUP; 2718 goto fail1; 2719 } 2720 2721 if (encp->enc_mae_aset_v2_supported == B_FALSE) { 2722 rc = ENOTSUP; 2723 goto fail2; 2724 } 2725 2726 req.emr_cmd = MC_CMD_MAE_MAC_ADDR_FREE; 2727 req.emr_in_buf = payload; 2728 req.emr_in_length = MC_CMD_MAE_MAC_ADDR_FREE_IN_LEN(1); 2729 req.emr_out_buf = payload; 2730 req.emr_out_length = MC_CMD_MAE_MAC_ADDR_FREE_OUT_LEN(1); 2731 2732 MCDI_IN_SET_DWORD(req, MAE_MAC_ADDR_FREE_IN_MAC_ID, mac_idp->id); 2733 2734 efx_mcdi_execute(enp, &req); 2735 2736 if (req.emr_rc != 0) { 2737 rc = req.emr_rc; 2738 goto fail3; 2739 } 2740 2741 if (req.emr_out_length_used < MC_CMD_MAE_MAC_ADDR_FREE_OUT_LEN(1)) { 2742 rc = EMSGSIZE; 2743 goto fail4; 2744 } 2745 2746 if (MCDI_OUT_DWORD(req, MAE_MAC_ADDR_FREE_OUT_FREED_MAC_ID) != 2747 mac_idp->id) { 2748 /* Firmware failed to remove the MAC address entry. */ 2749 rc = EAGAIN; 2750 goto fail5; 2751 } 2752 2753 return (0); 2754 2755 fail5: 2756 EFSYS_PROBE(fail5); 2757 fail4: 2758 EFSYS_PROBE(fail4); 2759 fail3: 2760 EFSYS_PROBE(fail3); 2761 fail2: 2762 EFSYS_PROBE(fail2); 2763 fail1: 2764 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2765 return (rc); 2766 } 2767 2768 __checkReturn efx_rc_t 2769 efx_mae_action_set_fill_in_dst_mac_id( 2770 __in efx_mae_actions_t *spec, 2771 __in const efx_mae_mac_id_t *mac_idp) 2772 { 2773 efx_rc_t rc; 2774 2775 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_SET_DST_MAC)) == 0) { 2776 /* 2777 * The caller has not intended to have this action originally, 2778 * hence, they cannot indicate the MAC address entry ID. 2779 */ 2780 rc = EINVAL; 2781 goto fail1; 2782 } 2783 2784 if (spec->ema_rsrc.emar_dst_mac_id.id != EFX_MAE_RSRC_ID_INVALID) { 2785 /* An attempt to indicate the MAC address entry ID twice. */ 2786 rc = EINVAL; 2787 goto fail2; 2788 } 2789 2790 if (mac_idp->id == EFX_MAE_RSRC_ID_INVALID) { 2791 rc = EINVAL; 2792 goto fail3; 2793 } 2794 2795 spec->ema_rsrc.emar_dst_mac_id.id = mac_idp->id; 2796 2797 return (0); 2798 2799 fail3: 2800 EFSYS_PROBE(fail3); 2801 fail2: 2802 EFSYS_PROBE(fail2); 2803 fail1: 2804 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2805 return (rc); 2806 } 2807 2808 __checkReturn efx_rc_t 2809 efx_mae_action_set_fill_in_src_mac_id( 2810 __in efx_mae_actions_t *spec, 2811 __in const efx_mae_mac_id_t *mac_idp) 2812 { 2813 efx_rc_t rc; 2814 2815 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_SET_SRC_MAC)) == 0) { 2816 /* 2817 * The caller has not intended to have this action originally, 2818 * hence, they cannot indicate the MAC address entry ID. 2819 */ 2820 rc = EINVAL; 2821 goto fail1; 2822 } 2823 2824 if (spec->ema_rsrc.emar_src_mac_id.id != EFX_MAE_RSRC_ID_INVALID) { 2825 /* An attempt to indicate the MAC address entry ID twice. */ 2826 rc = EINVAL; 2827 goto fail2; 2828 } 2829 2830 if (mac_idp->id == EFX_MAE_RSRC_ID_INVALID) { 2831 rc = EINVAL; 2832 goto fail3; 2833 } 2834 2835 spec->ema_rsrc.emar_src_mac_id.id = mac_idp->id; 2836 2837 return (0); 2838 2839 fail3: 2840 EFSYS_PROBE(fail3); 2841 fail2: 2842 EFSYS_PROBE(fail2); 2843 fail1: 2844 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2845 return (rc); 2846 } 2847 2848 __checkReturn efx_rc_t 2849 efx_mae_encap_header_alloc( 2850 __in efx_nic_t *enp, 2851 __in efx_tunnel_protocol_t encap_type, 2852 __in_bcount(header_size) uint8_t *header_data, 2853 __in size_t header_size, 2854 __out efx_mae_eh_id_t *eh_idp) 2855 { 2856 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 2857 efx_mcdi_req_t req; 2858 EFX_MCDI_DECLARE_BUF(payload, 2859 MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LENMAX_MCDI2, 2860 MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN); 2861 uint32_t encap_type_mcdi; 2862 efx_mae_eh_id_t eh_id; 2863 efx_rc_t rc; 2864 2865 EFX_STATIC_ASSERT(sizeof (eh_idp->id) == 2866 MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_LEN); 2867 2868 EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID == 2869 MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL); 2870 2871 if (encp->enc_mae_supported == B_FALSE) { 2872 rc = ENOTSUP; 2873 goto fail1; 2874 } 2875 2876 switch (encap_type) { 2877 case EFX_TUNNEL_PROTOCOL_NONE: 2878 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NONE; 2879 break; 2880 case EFX_TUNNEL_PROTOCOL_VXLAN: 2881 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_VXLAN; 2882 break; 2883 case EFX_TUNNEL_PROTOCOL_GENEVE: 2884 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_GENEVE; 2885 break; 2886 case EFX_TUNNEL_PROTOCOL_NVGRE: 2887 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NVGRE; 2888 break; 2889 default: 2890 rc = ENOTSUP; 2891 goto fail2; 2892 } 2893 2894 if (header_size > 2895 MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2) { 2896 rc = EINVAL; 2897 goto fail3; 2898 } 2899 2900 req.emr_cmd = MC_CMD_MAE_ENCAP_HEADER_ALLOC; 2901 req.emr_in_buf = payload; 2902 req.emr_in_length = MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LEN(header_size); 2903 req.emr_out_buf = payload; 2904 req.emr_out_length = MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN; 2905 2906 MCDI_IN_SET_DWORD(req, 2907 MAE_ENCAP_HEADER_ALLOC_IN_ENCAP_TYPE, encap_type_mcdi); 2908 2909 memcpy(payload + MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_OFST, 2910 header_data, header_size); 2911 2912 efx_mcdi_execute(enp, &req); 2913 2914 if (req.emr_rc != 0) { 2915 rc = req.emr_rc; 2916 goto fail4; 2917 } 2918 2919 if (req.emr_out_length_used < MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN) { 2920 rc = EMSGSIZE; 2921 goto fail5; 2922 } 2923 2924 eh_id.id = MCDI_OUT_DWORD(req, 2925 MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID); 2926 2927 if (eh_id.id == EFX_MAE_RSRC_ID_INVALID) { 2928 rc = ENOENT; 2929 goto fail6; 2930 } 2931 2932 eh_idp->id = eh_id.id; 2933 2934 return (0); 2935 2936 fail6: 2937 EFSYS_PROBE(fail6); 2938 fail5: 2939 EFSYS_PROBE(fail5); 2940 fail4: 2941 EFSYS_PROBE(fail4); 2942 fail3: 2943 EFSYS_PROBE(fail3); 2944 fail2: 2945 EFSYS_PROBE(fail2); 2946 fail1: 2947 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2948 return (rc); 2949 } 2950 2951 __checkReturn efx_rc_t 2952 efx_mae_encap_header_update( 2953 __in efx_nic_t *enp, 2954 __in efx_mae_eh_id_t *eh_idp, 2955 __in efx_tunnel_protocol_t encap_type, 2956 __in_bcount(header_size) const uint8_t *header_data, 2957 __in size_t header_size) 2958 { 2959 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 2960 efx_mcdi_req_t req; 2961 EFX_MCDI_DECLARE_BUF(payload, 2962 MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LENMAX_MCDI2, 2963 MC_CMD_MAE_ENCAP_HEADER_UPDATE_OUT_LEN); 2964 uint32_t encap_type_mcdi; 2965 efx_rc_t rc; 2966 2967 if (encp->enc_mae_supported == B_FALSE) { 2968 rc = ENOTSUP; 2969 goto fail1; 2970 } 2971 2972 switch (encap_type) { 2973 case EFX_TUNNEL_PROTOCOL_NONE: 2974 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NONE; 2975 break; 2976 case EFX_TUNNEL_PROTOCOL_VXLAN: 2977 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_VXLAN; 2978 break; 2979 case EFX_TUNNEL_PROTOCOL_GENEVE: 2980 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_GENEVE; 2981 break; 2982 case EFX_TUNNEL_PROTOCOL_NVGRE: 2983 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NVGRE; 2984 break; 2985 default: 2986 rc = ENOTSUP; 2987 goto fail2; 2988 } 2989 2990 if (header_size > 2991 MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA_MAXNUM_MCDI2) { 2992 rc = EINVAL; 2993 goto fail3; 2994 } 2995 2996 req.emr_cmd = MC_CMD_MAE_ENCAP_HEADER_UPDATE; 2997 req.emr_in_buf = payload; 2998 req.emr_in_length = MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LEN(header_size); 2999 req.emr_out_buf = payload; 3000 req.emr_out_length = MC_CMD_MAE_ENCAP_HEADER_UPDATE_OUT_LEN; 3001 3002 MCDI_IN_SET_DWORD(req, 3003 MAE_ENCAP_HEADER_UPDATE_IN_EH_ID, eh_idp->id); 3004 3005 MCDI_IN_SET_DWORD(req, 3006 MAE_ENCAP_HEADER_UPDATE_IN_ENCAP_TYPE, encap_type_mcdi); 3007 3008 memcpy(MCDI_IN2(req, uint8_t, MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA), 3009 header_data, header_size); 3010 3011 efx_mcdi_execute(enp, &req); 3012 3013 if (req.emr_rc != 0) { 3014 rc = req.emr_rc; 3015 goto fail4; 3016 } 3017 3018 return (0); 3019 3020 fail4: 3021 EFSYS_PROBE(fail4); 3022 fail3: 3023 EFSYS_PROBE(fail3); 3024 fail2: 3025 EFSYS_PROBE(fail2); 3026 fail1: 3027 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3028 return (rc); 3029 } 3030 3031 __checkReturn efx_rc_t 3032 efx_mae_encap_header_free( 3033 __in efx_nic_t *enp, 3034 __in const efx_mae_eh_id_t *eh_idp) 3035 { 3036 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 3037 efx_mcdi_req_t req; 3038 EFX_MCDI_DECLARE_BUF(payload, 3039 MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(1), 3040 MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(1)); 3041 efx_rc_t rc; 3042 3043 if (encp->enc_mae_supported == B_FALSE) { 3044 rc = ENOTSUP; 3045 goto fail1; 3046 } 3047 3048 req.emr_cmd = MC_CMD_MAE_ENCAP_HEADER_FREE; 3049 req.emr_in_buf = payload; 3050 req.emr_in_length = MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(1); 3051 req.emr_out_buf = payload; 3052 req.emr_out_length = MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(1); 3053 3054 MCDI_IN_SET_DWORD(req, MAE_ENCAP_HEADER_FREE_IN_EH_ID, eh_idp->id); 3055 3056 efx_mcdi_execute(enp, &req); 3057 3058 if (req.emr_rc != 0) { 3059 rc = req.emr_rc; 3060 goto fail2; 3061 } 3062 3063 if (MCDI_OUT_DWORD(req, MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID) != 3064 eh_idp->id) { 3065 /* Firmware failed to remove the encap. header. */ 3066 rc = EAGAIN; 3067 goto fail3; 3068 } 3069 3070 return (0); 3071 3072 fail3: 3073 EFSYS_PROBE(fail3); 3074 fail2: 3075 EFSYS_PROBE(fail2); 3076 fail1: 3077 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3078 return (rc); 3079 } 3080 3081 __checkReturn efx_rc_t 3082 efx_mae_action_set_fill_in_eh_id( 3083 __in efx_mae_actions_t *spec, 3084 __in const efx_mae_eh_id_t *eh_idp) 3085 { 3086 efx_rc_t rc; 3087 3088 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_ENCAP)) == 0) { 3089 /* 3090 * The caller has not intended to have action ENCAP originally, 3091 * hence, this attempt to indicate encap. header ID is invalid. 3092 */ 3093 rc = EINVAL; 3094 goto fail1; 3095 } 3096 3097 if (spec->ema_rsrc.emar_eh_id.id != EFX_MAE_RSRC_ID_INVALID) { 3098 /* The caller attempts to indicate encap. header ID twice. */ 3099 rc = EINVAL; 3100 goto fail2; 3101 } 3102 3103 if (eh_idp->id == EFX_MAE_RSRC_ID_INVALID) { 3104 rc = EINVAL; 3105 goto fail3; 3106 } 3107 3108 spec->ema_rsrc.emar_eh_id.id = eh_idp->id; 3109 3110 return (0); 3111 3112 fail3: 3113 EFSYS_PROBE(fail3); 3114 fail2: 3115 EFSYS_PROBE(fail2); 3116 fail1: 3117 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3118 return (rc); 3119 } 3120 3121 __checkReturn efx_rc_t 3122 efx_mae_action_set_alloc( 3123 __in efx_nic_t *enp, 3124 __in const efx_mae_actions_t *spec, 3125 __out efx_mae_aset_id_t *aset_idp) 3126 { 3127 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 3128 efx_mcdi_req_t req; 3129 EFX_MCDI_DECLARE_BUF(payload, 3130 MC_CMD_MAE_ACTION_SET_ALLOC_IN_LEN, 3131 MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN); 3132 efx_mae_aset_id_t aset_id; 3133 efx_rc_t rc; 3134 3135 if (encp->enc_mae_supported == B_FALSE) { 3136 rc = ENOTSUP; 3137 goto fail1; 3138 } 3139 3140 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_SET_DST_MAC)) != 0 && 3141 spec->ema_rsrc.emar_dst_mac_id.id == EFX_MAE_RSRC_ID_INVALID) { 3142 rc = EINVAL; 3143 goto fail2; 3144 } 3145 3146 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_SET_SRC_MAC)) != 0 && 3147 spec->ema_rsrc.emar_src_mac_id.id == EFX_MAE_RSRC_ID_INVALID) { 3148 rc = EINVAL; 3149 goto fail3; 3150 } 3151 3152 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_ENCAP)) != 0 && 3153 spec->ema_rsrc.emar_eh_id.id == EFX_MAE_RSRC_ID_INVALID) { 3154 rc = EINVAL; 3155 goto fail4; 3156 } 3157 3158 if (spec->ema_n_count_actions == 1 && 3159 spec->ema_rsrc.emar_counter_id.id == EFX_MAE_RSRC_ID_INVALID) { 3160 rc = EINVAL; 3161 goto fail5; 3162 } 3163 3164 req.emr_cmd = MC_CMD_MAE_ACTION_SET_ALLOC; 3165 req.emr_in_buf = payload; 3166 req.emr_in_length = MC_CMD_MAE_ACTION_SET_ALLOC_IN_LEN; 3167 req.emr_out_buf = payload; 3168 req.emr_out_length = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN; 3169 3170 /* 3171 * TODO: Remove these EFX_MAE_RSRC_ID_INVALID assignments once the 3172 * corresponding resource types are supported by the implementation. 3173 * Use proper resource ID assignments instead. 3174 */ 3175 MCDI_IN_SET_DWORD(req, 3176 MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID, EFX_MAE_RSRC_ID_INVALID); 3177 3178 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_DECAP)) != 0) { 3179 MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS, 3180 MAE_ACTION_SET_ALLOC_IN_DECAP, 1); 3181 } 3182 3183 MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS, 3184 MAE_ACTION_SET_ALLOC_IN_VLAN_POP, spec->ema_n_vlan_tags_to_pop); 3185 3186 MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID, 3187 spec->ema_rsrc.emar_dst_mac_id.id); 3188 3189 MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID, 3190 spec->ema_rsrc.emar_src_mac_id.id); 3191 3192 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_DECR_IP_TTL)) != 0) { 3193 MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS, 3194 MAE_ACTION_SET_ALLOC_IN_DO_DECR_IP_TTL, 1); 3195 } 3196 3197 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_NAT)) != 0) { 3198 MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS, 3199 MAE_ACTION_SET_ALLOC_IN_DO_NAT, 1); 3200 } 3201 3202 if (spec->ema_n_vlan_tags_to_push > 0) { 3203 unsigned int outer_tag_idx; 3204 3205 MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS, 3206 MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH, 3207 spec->ema_n_vlan_tags_to_push); 3208 3209 if (spec->ema_n_vlan_tags_to_push == 3210 EFX_MAE_VLAN_PUSH_MAX_NTAGS) { 3211 MCDI_IN_SET_WORD(req, 3212 MAE_ACTION_SET_ALLOC_IN_VLAN1_PROTO_BE, 3213 spec->ema_vlan_push_descs[0].emavp_tpid_be); 3214 MCDI_IN_SET_WORD(req, 3215 MAE_ACTION_SET_ALLOC_IN_VLAN1_TCI_BE, 3216 spec->ema_vlan_push_descs[0].emavp_tci_be); 3217 } 3218 3219 outer_tag_idx = spec->ema_n_vlan_tags_to_push - 1; 3220 3221 MCDI_IN_SET_WORD(req, MAE_ACTION_SET_ALLOC_IN_VLAN0_PROTO_BE, 3222 spec->ema_vlan_push_descs[outer_tag_idx].emavp_tpid_be); 3223 MCDI_IN_SET_WORD(req, MAE_ACTION_SET_ALLOC_IN_VLAN0_TCI_BE, 3224 spec->ema_vlan_push_descs[outer_tag_idx].emavp_tci_be); 3225 } 3226 3227 MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID, 3228 spec->ema_rsrc.emar_eh_id.id); 3229 MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_COUNTER_ID, 3230 spec->ema_rsrc.emar_counter_id.id); 3231 3232 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_FLAG)) != 0) { 3233 MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS, 3234 MAE_ACTION_SET_ALLOC_IN_FLAG, 1); 3235 } 3236 3237 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_MARK)) != 0) { 3238 MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS, 3239 MAE_ACTION_SET_ALLOC_IN_MARK, 1); 3240 3241 MCDI_IN_SET_DWORD(req, 3242 MAE_ACTION_SET_ALLOC_IN_MARK_VALUE, spec->ema_mark_value); 3243 } 3244 3245 MCDI_IN_SET_DWORD(req, 3246 MAE_ACTION_SET_ALLOC_IN_DELIVER, spec->ema_deliver_mport.sel); 3247 3248 efx_mcdi_execute(enp, &req); 3249 3250 if (req.emr_rc != 0) { 3251 rc = req.emr_rc; 3252 goto fail6; 3253 } 3254 3255 if (req.emr_out_length_used < MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN) { 3256 rc = EMSGSIZE; 3257 goto fail7; 3258 } 3259 3260 aset_id.id = MCDI_OUT_DWORD(req, MAE_ACTION_SET_ALLOC_OUT_AS_ID); 3261 if (aset_id.id == EFX_MAE_RSRC_ID_INVALID) { 3262 rc = ENOENT; 3263 goto fail8; 3264 } 3265 3266 aset_idp->id = aset_id.id; 3267 3268 return (0); 3269 3270 fail8: 3271 EFSYS_PROBE(fail8); 3272 fail7: 3273 EFSYS_PROBE(fail7); 3274 fail6: 3275 EFSYS_PROBE(fail6); 3276 fail5: 3277 EFSYS_PROBE(fail5); 3278 fail4: 3279 EFSYS_PROBE(fail4); 3280 fail3: 3281 EFSYS_PROBE(fail3); 3282 fail2: 3283 EFSYS_PROBE(fail2); 3284 fail1: 3285 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3286 return (rc); 3287 } 3288 3289 __checkReturn unsigned int 3290 efx_mae_action_set_get_nb_count( 3291 __in const efx_mae_actions_t *spec) 3292 { 3293 return (spec->ema_n_count_actions); 3294 } 3295 3296 __checkReturn efx_rc_t 3297 efx_mae_action_set_fill_in_counter_id( 3298 __in efx_mae_actions_t *spec, 3299 __in const efx_counter_t *counter_idp) 3300 { 3301 efx_rc_t rc; 3302 3303 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_COUNT)) == 0) { 3304 /* 3305 * Invalid to add counter ID if spec does not have COUNT action. 3306 */ 3307 rc = EINVAL; 3308 goto fail1; 3309 } 3310 3311 if (spec->ema_n_count_actions != 1) { 3312 /* 3313 * Having multiple COUNT actions in the spec requires a counter 3314 * list to be used. This API must only be used for a single 3315 * counter per spec. Turn down the request as inappropriate. 3316 */ 3317 rc = EINVAL; 3318 goto fail2; 3319 } 3320 3321 if (spec->ema_rsrc.emar_counter_id.id != EFX_MAE_RSRC_ID_INVALID) { 3322 /* The caller attempts to indicate counter ID twice. */ 3323 rc = EALREADY; 3324 goto fail3; 3325 } 3326 3327 if (counter_idp->id == EFX_MAE_RSRC_ID_INVALID) { 3328 rc = EINVAL; 3329 goto fail4; 3330 } 3331 3332 spec->ema_rsrc.emar_counter_id.id = counter_idp->id; 3333 3334 return (0); 3335 3336 fail4: 3337 EFSYS_PROBE(fail4); 3338 fail3: 3339 EFSYS_PROBE(fail3); 3340 fail2: 3341 EFSYS_PROBE(fail2); 3342 fail1: 3343 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3344 return (rc); 3345 } 3346 3347 void 3348 efx_mae_action_set_clear_fw_rsrc_ids( 3349 __in efx_mae_actions_t *spec) 3350 { 3351 spec->ema_rsrc.emar_dst_mac_id.id = EFX_MAE_RSRC_ID_INVALID; 3352 spec->ema_rsrc.emar_src_mac_id.id = EFX_MAE_RSRC_ID_INVALID; 3353 spec->ema_rsrc.emar_eh_id.id = EFX_MAE_RSRC_ID_INVALID; 3354 spec->ema_rsrc.emar_counter_id.id = EFX_MAE_RSRC_ID_INVALID; 3355 } 3356 3357 __checkReturn efx_rc_t 3358 efx_mae_counters_alloc_type( 3359 __in efx_nic_t *enp, 3360 __in efx_counter_type_t type, 3361 __in uint32_t n_counters, 3362 __out uint32_t *n_allocatedp, 3363 __out_ecount(n_counters) efx_counter_t *countersp, 3364 __out_opt uint32_t *gen_countp) 3365 { 3366 EFX_MCDI_DECLARE_BUF(payload, 3367 MC_CMD_MAE_COUNTER_ALLOC_V2_IN_LEN, 3368 MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMAX_MCDI2); 3369 efx_mae_t *maep = enp->en_maep; 3370 uint32_t max_n_counters; 3371 uint32_t n_allocated; 3372 efx_mcdi_req_t req; 3373 unsigned int i; 3374 efx_rc_t rc; 3375 3376 EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_ACTION == MAE_COUNTER_TYPE_AR); 3377 EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_CONNTRACK == MAE_COUNTER_TYPE_CT); 3378 3379 switch (type) { 3380 case EFX_COUNTER_TYPE_ACTION: 3381 max_n_counters = maep->em_max_n_action_counters; 3382 break; 3383 case EFX_COUNTER_TYPE_CONNTRACK: 3384 max_n_counters = maep->em_max_n_conntrack_counters; 3385 break; 3386 default: 3387 rc = EINVAL; 3388 goto fail1; 3389 } 3390 3391 if (n_counters > max_n_counters || 3392 n_counters < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM || 3393 n_counters > MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MAXNUM_MCDI2) { 3394 rc = EINVAL; 3395 goto fail2; 3396 } 3397 3398 req.emr_cmd = MC_CMD_MAE_COUNTER_ALLOC; 3399 req.emr_in_buf = payload; 3400 req.emr_in_length = MC_CMD_MAE_COUNTER_ALLOC_V2_IN_LEN; 3401 req.emr_out_buf = payload; 3402 req.emr_out_length = MC_CMD_MAE_COUNTER_ALLOC_OUT_LEN(n_counters); 3403 3404 MCDI_IN_SET_DWORD(req, MAE_COUNTER_ALLOC_IN_REQUESTED_COUNT, 3405 n_counters); 3406 3407 MCDI_IN_SET_DWORD(req, MAE_COUNTER_ALLOC_V2_IN_COUNTER_TYPE, type); 3408 3409 efx_mcdi_execute(enp, &req); 3410 3411 if (req.emr_rc != 0) { 3412 rc = req.emr_rc; 3413 goto fail3; 3414 } 3415 3416 if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMIN) { 3417 rc = EMSGSIZE; 3418 goto fail4; 3419 } 3420 3421 n_allocated = MCDI_OUT_DWORD(req, 3422 MAE_COUNTER_ALLOC_OUT_COUNTER_ID_COUNT); 3423 if (n_allocated < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM) { 3424 rc = EFAULT; 3425 goto fail5; 3426 } 3427 3428 for (i = 0; i < n_allocated; i++) { 3429 countersp[i].id = MCDI_OUT_INDEXED_DWORD(req, 3430 MAE_COUNTER_ALLOC_OUT_COUNTER_ID, i); 3431 } 3432 3433 if (gen_countp != NULL) { 3434 *gen_countp = MCDI_OUT_DWORD(req, 3435 MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT); 3436 } 3437 3438 *n_allocatedp = n_allocated; 3439 3440 return (0); 3441 3442 fail5: 3443 EFSYS_PROBE(fail5); 3444 fail4: 3445 EFSYS_PROBE(fail4); 3446 fail3: 3447 EFSYS_PROBE(fail3); 3448 fail2: 3449 EFSYS_PROBE(fail2); 3450 fail1: 3451 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3452 3453 return (rc); 3454 } 3455 3456 __checkReturn efx_rc_t 3457 efx_mae_counters_alloc( 3458 __in efx_nic_t *enp, 3459 __in uint32_t n_counters, 3460 __out uint32_t *n_allocatedp, 3461 __out_ecount(n_counters) efx_counter_t *countersp, 3462 __out_opt uint32_t *gen_countp) 3463 { 3464 efx_rc_t rc; 3465 3466 rc = efx_mae_counters_alloc_type(enp, EFX_COUNTER_TYPE_ACTION, 3467 n_counters, n_allocatedp, 3468 countersp, gen_countp); 3469 if (rc != 0) 3470 goto fail1; 3471 3472 return (0); 3473 3474 fail1: 3475 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3476 return (rc); 3477 } 3478 3479 __checkReturn efx_rc_t 3480 efx_mae_counters_free_type( 3481 __in efx_nic_t *enp, 3482 __in efx_counter_type_t type, 3483 __in uint32_t n_counters, 3484 __out uint32_t *n_freedp, 3485 __in_ecount(n_counters) const efx_counter_t *countersp, 3486 __out_opt uint32_t *gen_countp) 3487 { 3488 EFX_MCDI_DECLARE_BUF(payload, 3489 MC_CMD_MAE_COUNTER_FREE_V2_IN_LEN, 3490 MC_CMD_MAE_COUNTER_FREE_OUT_LENMAX_MCDI2); 3491 efx_mae_t *maep = enp->en_maep; 3492 uint32_t max_n_counters; 3493 efx_mcdi_req_t req; 3494 uint32_t n_freed; 3495 unsigned int i; 3496 efx_rc_t rc; 3497 3498 switch (type) { 3499 case EFX_COUNTER_TYPE_ACTION: 3500 max_n_counters = maep->em_max_n_action_counters; 3501 break; 3502 case EFX_COUNTER_TYPE_CONNTRACK: 3503 max_n_counters = maep->em_max_n_conntrack_counters; 3504 break; 3505 default: 3506 rc = EINVAL; 3507 goto fail1; 3508 } 3509 3510 if (n_counters > max_n_counters || 3511 n_counters < MC_CMD_MAE_COUNTER_FREE_V2_IN_FREE_COUNTER_ID_MINNUM || 3512 n_counters > 3513 MC_CMD_MAE_COUNTER_FREE_V2_IN_FREE_COUNTER_ID_MAXNUM_MCDI2) { 3514 rc = EINVAL; 3515 goto fail2; 3516 } 3517 3518 req.emr_cmd = MC_CMD_MAE_COUNTER_FREE; 3519 req.emr_in_buf = payload; 3520 req.emr_in_length = MC_CMD_MAE_COUNTER_FREE_V2_IN_LEN; 3521 req.emr_out_buf = payload; 3522 req.emr_out_length = MC_CMD_MAE_COUNTER_FREE_OUT_LEN(n_counters); 3523 3524 for (i = 0; i < n_counters; i++) { 3525 MCDI_IN_SET_INDEXED_DWORD(req, 3526 MAE_COUNTER_FREE_IN_FREE_COUNTER_ID, i, countersp[i].id); 3527 } 3528 MCDI_IN_SET_DWORD(req, MAE_COUNTER_FREE_IN_COUNTER_ID_COUNT, 3529 n_counters); 3530 3531 MCDI_IN_SET_DWORD(req, MAE_COUNTER_FREE_V2_IN_COUNTER_TYPE, type); 3532 3533 efx_mcdi_execute(enp, &req); 3534 3535 if (req.emr_rc != 0) { 3536 rc = req.emr_rc; 3537 goto fail3; 3538 } 3539 3540 if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_FREE_OUT_LENMIN) { 3541 rc = EMSGSIZE; 3542 goto fail4; 3543 } 3544 3545 n_freed = MCDI_OUT_DWORD(req, MAE_COUNTER_FREE_OUT_COUNTER_ID_COUNT); 3546 3547 if (n_freed < MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_MINNUM) { 3548 rc = EFAULT; 3549 goto fail5; 3550 } 3551 3552 if (gen_countp != NULL) { 3553 *gen_countp = MCDI_OUT_DWORD(req, 3554 MAE_COUNTER_FREE_OUT_GENERATION_COUNT); 3555 } 3556 3557 *n_freedp = n_freed; 3558 3559 return (0); 3560 3561 fail5: 3562 EFSYS_PROBE(fail5); 3563 fail4: 3564 EFSYS_PROBE(fail4); 3565 fail3: 3566 EFSYS_PROBE(fail3); 3567 fail2: 3568 EFSYS_PROBE(fail2); 3569 fail1: 3570 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3571 3572 return (rc); 3573 } 3574 3575 __checkReturn efx_rc_t 3576 efx_mae_counters_free( 3577 __in efx_nic_t *enp, 3578 __in uint32_t n_counters, 3579 __out uint32_t *n_freedp, 3580 __in_ecount(n_counters) const efx_counter_t *countersp, 3581 __out_opt uint32_t *gen_countp) 3582 { 3583 efx_rc_t rc; 3584 3585 rc = efx_mae_counters_free_type(enp, EFX_COUNTER_TYPE_ACTION, 3586 n_counters, n_freedp, 3587 countersp, gen_countp); 3588 if (rc != 0) 3589 goto fail1; 3590 3591 return (0); 3592 3593 fail1: 3594 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3595 return (rc); 3596 } 3597 3598 __checkReturn efx_rc_t 3599 efx_mae_counters_stream_start( 3600 __in efx_nic_t *enp, 3601 __in uint16_t rxq_id, 3602 __in uint16_t packet_size, 3603 __in uint32_t flags_in, 3604 __out uint32_t *flags_out) 3605 { 3606 efx_mcdi_req_t req; 3607 EFX_MCDI_DECLARE_BUF(payload, 3608 MC_CMD_MAE_COUNTERS_STREAM_START_V2_IN_LEN, 3609 MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN); 3610 struct efx_mae_s *maep = enp->en_maep; 3611 uint32_t counter_types; 3612 efx_rc_t rc; 3613 3614 EFX_STATIC_ASSERT(EFX_MAE_COUNTERS_STREAM_IN_ZERO_SQUASH_DISABLE == 3615 1U << MC_CMD_MAE_COUNTERS_STREAM_START_IN_ZERO_SQUASH_DISABLE_LBN); 3616 3617 EFX_STATIC_ASSERT(EFX_MAE_COUNTERS_STREAM_OUT_USES_CREDITS == 3618 1U << MC_CMD_MAE_COUNTERS_STREAM_START_OUT_USES_CREDITS_LBN); 3619 3620 req.emr_cmd = MC_CMD_MAE_COUNTERS_STREAM_START; 3621 req.emr_in_buf = payload; 3622 req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_START_V2_IN_LEN; 3623 req.emr_out_buf = payload; 3624 req.emr_out_length = MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN; 3625 3626 MCDI_IN_SET_WORD(req, MAE_COUNTERS_STREAM_START_IN_QID, rxq_id); 3627 MCDI_IN_SET_WORD(req, MAE_COUNTERS_STREAM_START_IN_PACKET_SIZE, 3628 packet_size); 3629 MCDI_IN_SET_DWORD(req, MAE_COUNTERS_STREAM_START_IN_FLAGS, flags_in); 3630 3631 counter_types = (1U << MAE_COUNTER_TYPE_AR); 3632 3633 if (maep->em_max_n_conntrack_counters != 0) 3634 counter_types |= (1U << MAE_COUNTER_TYPE_CT); 3635 3636 MCDI_IN_SET_DWORD(req, 3637 MAE_COUNTERS_STREAM_START_V2_IN_COUNTER_TYPES_MASK, 3638 counter_types); 3639 3640 efx_mcdi_execute(enp, &req); 3641 3642 if (req.emr_rc != 0) { 3643 rc = req.emr_rc; 3644 goto fail1; 3645 } 3646 3647 if (req.emr_out_length_used < 3648 MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN) { 3649 rc = EMSGSIZE; 3650 goto fail2; 3651 } 3652 3653 *flags_out = MCDI_OUT_DWORD(req, MAE_COUNTERS_STREAM_START_OUT_FLAGS); 3654 3655 return (0); 3656 3657 fail2: 3658 EFSYS_PROBE(fail2); 3659 fail1: 3660 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3661 3662 return (rc); 3663 } 3664 3665 __checkReturn efx_rc_t 3666 efx_mae_counters_stream_stop( 3667 __in efx_nic_t *enp, 3668 __in uint16_t rxq_id, 3669 __out_opt uint32_t *gen_countp) 3670 { 3671 efx_mcdi_req_t req; 3672 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_MAE_COUNTERS_STREAM_STOP_IN_LEN, 3673 MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_LEN); 3674 efx_rc_t rc; 3675 3676 req.emr_cmd = MC_CMD_MAE_COUNTERS_STREAM_STOP; 3677 req.emr_in_buf = payload; 3678 req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_STOP_IN_LEN; 3679 req.emr_out_buf = payload; 3680 req.emr_out_length = MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_LEN; 3681 3682 MCDI_IN_SET_WORD(req, MAE_COUNTERS_STREAM_STOP_IN_QID, rxq_id); 3683 3684 efx_mcdi_execute(enp, &req); 3685 3686 if (req.emr_rc != 0) { 3687 rc = req.emr_rc; 3688 goto fail1; 3689 } 3690 3691 if (req.emr_out_length_used < 3692 MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_LEN) { 3693 rc = EMSGSIZE; 3694 goto fail2; 3695 } 3696 3697 if (gen_countp != NULL) { 3698 *gen_countp = MCDI_OUT_DWORD(req, 3699 MAE_COUNTERS_STREAM_STOP_OUT_GENERATION_COUNT); 3700 } 3701 3702 return (0); 3703 3704 fail2: 3705 EFSYS_PROBE(fail2); 3706 fail1: 3707 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3708 3709 return (rc); 3710 } 3711 3712 __checkReturn efx_rc_t 3713 efx_mae_counters_stream_give_credits( 3714 __in efx_nic_t *enp, 3715 __in uint32_t n_credits) 3716 { 3717 efx_mcdi_req_t req; 3718 EFX_MCDI_DECLARE_BUF(payload, 3719 MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_LEN, 3720 MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_OUT_LEN); 3721 efx_rc_t rc; 3722 3723 req.emr_cmd = MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS; 3724 req.emr_in_buf = payload; 3725 req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_LEN; 3726 req.emr_out_buf = payload; 3727 req.emr_out_length = MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_OUT_LEN; 3728 3729 MCDI_IN_SET_DWORD(req, MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_NUM_CREDITS, 3730 n_credits); 3731 3732 efx_mcdi_execute(enp, &req); 3733 3734 if (req.emr_rc != 0) { 3735 rc = req.emr_rc; 3736 goto fail1; 3737 } 3738 3739 return (0); 3740 3741 fail1: 3742 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3743 3744 return (rc); 3745 } 3746 3747 __checkReturn efx_rc_t 3748 efx_mae_action_set_free( 3749 __in efx_nic_t *enp, 3750 __in const efx_mae_aset_id_t *aset_idp) 3751 { 3752 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 3753 efx_mcdi_req_t req; 3754 EFX_MCDI_DECLARE_BUF(payload, 3755 MC_CMD_MAE_ACTION_SET_FREE_IN_LEN(1), 3756 MC_CMD_MAE_ACTION_SET_FREE_OUT_LEN(1)); 3757 efx_rc_t rc; 3758 3759 if (encp->enc_mae_supported == B_FALSE) { 3760 rc = ENOTSUP; 3761 goto fail1; 3762 } 3763 3764 req.emr_cmd = MC_CMD_MAE_ACTION_SET_FREE; 3765 req.emr_in_buf = payload; 3766 req.emr_in_length = MC_CMD_MAE_ACTION_SET_FREE_IN_LEN(1); 3767 req.emr_out_buf = payload; 3768 req.emr_out_length = MC_CMD_MAE_ACTION_SET_FREE_OUT_LEN(1); 3769 3770 MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_FREE_IN_AS_ID, aset_idp->id); 3771 3772 efx_mcdi_execute(enp, &req); 3773 3774 if (req.emr_rc != 0) { 3775 rc = req.emr_rc; 3776 goto fail2; 3777 } 3778 3779 if (req.emr_out_length_used < MC_CMD_MAE_ACTION_SET_FREE_OUT_LENMIN) { 3780 rc = EMSGSIZE; 3781 goto fail3; 3782 } 3783 3784 if (MCDI_OUT_DWORD(req, MAE_ACTION_SET_FREE_OUT_FREED_AS_ID) != 3785 aset_idp->id) { 3786 /* Firmware failed to free the action set. */ 3787 rc = EAGAIN; 3788 goto fail4; 3789 } 3790 3791 return (0); 3792 3793 fail4: 3794 EFSYS_PROBE(fail4); 3795 fail3: 3796 EFSYS_PROBE(fail3); 3797 fail2: 3798 EFSYS_PROBE(fail2); 3799 fail1: 3800 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3801 return (rc); 3802 } 3803 3804 __checkReturn efx_rc_t 3805 efx_mae_action_rule_insert( 3806 __in efx_nic_t *enp, 3807 __in const efx_mae_match_spec_t *spec, 3808 __in const efx_mae_aset_list_id_t *asl_idp, 3809 __in const efx_mae_aset_id_t *as_idp, 3810 __out efx_mae_rule_id_t *ar_idp) 3811 { 3812 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 3813 efx_mcdi_req_t req; 3814 EFX_MCDI_DECLARE_BUF(payload, 3815 MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMAX_MCDI2, 3816 MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN); 3817 efx_oword_t *rule_response; 3818 efx_mae_rule_id_t ar_id; 3819 size_t offset; 3820 efx_rc_t rc; 3821 3822 EFX_STATIC_ASSERT(sizeof (ar_idp->id) == 3823 MC_CMD_MAE_ACTION_RULE_INSERT_OUT_AR_ID_LEN); 3824 3825 EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID == 3826 MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL); 3827 3828 if (encp->enc_mae_supported == B_FALSE) { 3829 rc = ENOTSUP; 3830 goto fail1; 3831 } 3832 3833 if (spec->emms_type != EFX_MAE_RULE_ACTION || 3834 (asl_idp != NULL && as_idp != NULL) || 3835 (asl_idp == NULL && as_idp == NULL)) { 3836 rc = EINVAL; 3837 goto fail2; 3838 } 3839 3840 req.emr_cmd = MC_CMD_MAE_ACTION_RULE_INSERT; 3841 req.emr_in_buf = payload; 3842 req.emr_in_length = MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMAX_MCDI2; 3843 req.emr_out_buf = payload; 3844 req.emr_out_length = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN; 3845 3846 EFX_STATIC_ASSERT(sizeof (*rule_response) <= 3847 MC_CMD_MAE_ACTION_RULE_INSERT_IN_RESPONSE_LEN); 3848 offset = MC_CMD_MAE_ACTION_RULE_INSERT_IN_RESPONSE_OFST; 3849 rule_response = (efx_oword_t *)(payload + offset); 3850 EFX_POPULATE_OWORD_3(*rule_response, 3851 MAE_ACTION_RULE_RESPONSE_ASL_ID, 3852 (asl_idp != NULL) ? asl_idp->id : EFX_MAE_RSRC_ID_INVALID, 3853 MAE_ACTION_RULE_RESPONSE_AS_ID, 3854 (as_idp != NULL) ? as_idp->id : EFX_MAE_RSRC_ID_INVALID, 3855 MAE_ACTION_RULE_RESPONSE_COUNTER_ID, EFX_MAE_RSRC_ID_INVALID); 3856 3857 MCDI_IN_SET_DWORD(req, MAE_ACTION_RULE_INSERT_IN_PRIO, spec->emms_prio); 3858 3859 /* 3860 * Mask-value pairs have been stored in the byte order needed for the 3861 * MCDI request and are thus safe to be copied directly to the buffer. 3862 */ 3863 EFX_STATIC_ASSERT(sizeof (spec->emms_mask_value_pairs.action) >= 3864 MAE_FIELD_MASK_VALUE_PAIRS_V2_LEN); 3865 offset = MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_OFST; 3866 memcpy(payload + offset, spec->emms_mask_value_pairs.action, 3867 MAE_FIELD_MASK_VALUE_PAIRS_V2_LEN); 3868 3869 efx_mcdi_execute(enp, &req); 3870 3871 if (req.emr_rc != 0) { 3872 rc = req.emr_rc; 3873 goto fail3; 3874 } 3875 3876 if (req.emr_out_length_used < MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN) { 3877 rc = EMSGSIZE; 3878 goto fail4; 3879 } 3880 3881 ar_id.id = MCDI_OUT_DWORD(req, MAE_ACTION_RULE_INSERT_OUT_AR_ID); 3882 if (ar_id.id == EFX_MAE_RSRC_ID_INVALID) { 3883 rc = ENOENT; 3884 goto fail5; 3885 } 3886 3887 ar_idp->id = ar_id.id; 3888 3889 return (0); 3890 3891 fail5: 3892 EFSYS_PROBE(fail5); 3893 fail4: 3894 EFSYS_PROBE(fail4); 3895 fail3: 3896 EFSYS_PROBE(fail3); 3897 fail2: 3898 EFSYS_PROBE(fail2); 3899 fail1: 3900 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3901 return (rc); 3902 } 3903 3904 __checkReturn efx_rc_t 3905 efx_mae_action_rule_remove( 3906 __in efx_nic_t *enp, 3907 __in const efx_mae_rule_id_t *ar_idp) 3908 { 3909 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 3910 efx_mcdi_req_t req; 3911 EFX_MCDI_DECLARE_BUF(payload, 3912 MC_CMD_MAE_ACTION_RULE_DELETE_IN_LEN(1), 3913 MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(1)); 3914 efx_rc_t rc; 3915 3916 if (encp->enc_mae_supported == B_FALSE) { 3917 rc = ENOTSUP; 3918 goto fail1; 3919 } 3920 3921 req.emr_cmd = MC_CMD_MAE_ACTION_RULE_DELETE; 3922 req.emr_in_buf = payload; 3923 req.emr_in_length = MC_CMD_MAE_ACTION_RULE_DELETE_IN_LEN(1); 3924 req.emr_out_buf = payload; 3925 req.emr_out_length = MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(1); 3926 3927 MCDI_IN_SET_DWORD(req, MAE_ACTION_RULE_DELETE_IN_AR_ID, ar_idp->id); 3928 3929 efx_mcdi_execute(enp, &req); 3930 3931 if (req.emr_rc != 0) { 3932 rc = req.emr_rc; 3933 goto fail2; 3934 } 3935 3936 if (req.emr_out_length_used < 3937 MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LENMIN) { 3938 rc = EMSGSIZE; 3939 goto fail3; 3940 } 3941 3942 if (MCDI_OUT_DWORD(req, MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID) != 3943 ar_idp->id) { 3944 /* Firmware failed to delete the action rule. */ 3945 rc = EAGAIN; 3946 goto fail4; 3947 } 3948 3949 return (0); 3950 3951 fail4: 3952 EFSYS_PROBE(fail4); 3953 fail3: 3954 EFSYS_PROBE(fail3); 3955 fail2: 3956 EFSYS_PROBE(fail2); 3957 fail1: 3958 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3959 return (rc); 3960 } 3961 3962 __checkReturn efx_rc_t 3963 efx_mcdi_mport_alloc_alias( 3964 __in efx_nic_t *enp, 3965 __out efx_mport_id_t *mportp, 3966 __out_opt uint32_t *labelp) 3967 { 3968 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 3969 efx_mcdi_req_t req; 3970 EFX_MCDI_DECLARE_BUF(payload, 3971 MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_LEN, 3972 MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LEN); 3973 efx_rc_t rc; 3974 3975 if (encp->enc_mae_supported == B_FALSE) { 3976 rc = ENOTSUP; 3977 goto fail1; 3978 } 3979 3980 req.emr_cmd = MC_CMD_MAE_MPORT_ALLOC; 3981 req.emr_in_buf = payload; 3982 req.emr_in_length = MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_LEN; 3983 req.emr_out_buf = payload; 3984 req.emr_out_length = MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LEN; 3985 3986 MCDI_IN_SET_DWORD(req, MAE_MPORT_ALLOC_IN_TYPE, 3987 MC_CMD_MAE_MPORT_ALLOC_IN_MPORT_TYPE_ALIAS); 3988 MCDI_IN_SET_DWORD(req, MAE_MPORT_ALLOC_ALIAS_IN_DELIVER_MPORT, 3989 MAE_MPORT_SELECTOR_ASSIGNED); 3990 3991 efx_mcdi_execute(enp, &req); 3992 3993 if (req.emr_rc != 0) { 3994 rc = req.emr_rc; 3995 goto fail2; 3996 } 3997 3998 mportp->id = MCDI_OUT_DWORD(req, MAE_MPORT_ALLOC_OUT_MPORT_ID); 3999 if (labelp != NULL) 4000 *labelp = MCDI_OUT_DWORD(req, MAE_MPORT_ALLOC_ALIAS_OUT_LABEL); 4001 4002 return (0); 4003 4004 fail2: 4005 EFSYS_PROBE(fail2); 4006 fail1: 4007 EFSYS_PROBE1(fail1, efx_rc_t, rc); 4008 return (rc); 4009 } 4010 4011 __checkReturn efx_rc_t 4012 efx_mae_mport_free( 4013 __in efx_nic_t *enp, 4014 __in const efx_mport_id_t *mportp) 4015 { 4016 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 4017 efx_mcdi_req_t req; 4018 EFX_MCDI_DECLARE_BUF(payload, 4019 MC_CMD_MAE_MPORT_FREE_IN_LEN, 4020 MC_CMD_MAE_MPORT_FREE_OUT_LEN); 4021 efx_rc_t rc; 4022 4023 if (encp->enc_mae_supported == B_FALSE) { 4024 rc = ENOTSUP; 4025 goto fail1; 4026 } 4027 4028 req.emr_cmd = MC_CMD_MAE_MPORT_FREE; 4029 req.emr_in_buf = payload; 4030 req.emr_in_length = MC_CMD_MAE_MPORT_FREE_IN_LEN; 4031 req.emr_out_buf = payload; 4032 req.emr_out_length = MC_CMD_MAE_MPORT_FREE_OUT_LEN; 4033 4034 MCDI_IN_SET_DWORD(req, MAE_MPORT_FREE_IN_MPORT_ID, mportp->id); 4035 4036 efx_mcdi_execute(enp, &req); 4037 4038 if (req.emr_rc != 0) { 4039 rc = req.emr_rc; 4040 goto fail2; 4041 } 4042 4043 return (0); 4044 4045 fail2: 4046 EFSYS_PROBE(fail2); 4047 fail1: 4048 EFSYS_PROBE1(fail1, efx_rc_t, rc); 4049 return (rc); 4050 } 4051 4052 static __checkReturn efx_rc_t 4053 efx_mae_read_mport_journal_single( 4054 __in uint8_t *entry_buf, 4055 __out efx_mport_desc_t *desc) 4056 { 4057 uint32_t pcie_intf; 4058 efx_rc_t rc; 4059 4060 memset(desc, 0, sizeof (*desc)); 4061 4062 desc->emd_id.id = MCDI_STRUCT_DWORD(entry_buf, 4063 MAE_MPORT_DESC_V2_MPORT_ID); 4064 4065 desc->emd_can_receive_on = MCDI_STRUCT_DWORD_FIELD(entry_buf, 4066 MAE_MPORT_DESC_V2_FLAGS, 4067 MAE_MPORT_DESC_V2_CAN_RECEIVE_ON); 4068 4069 desc->emd_can_deliver_to = MCDI_STRUCT_DWORD_FIELD(entry_buf, 4070 MAE_MPORT_DESC_V2_FLAGS, 4071 MAE_MPORT_DESC_V2_CAN_DELIVER_TO); 4072 4073 desc->emd_can_delete = MCDI_STRUCT_DWORD_FIELD(entry_buf, 4074 MAE_MPORT_DESC_V2_FLAGS, 4075 MAE_MPORT_DESC_V2_CAN_DELETE); 4076 4077 desc->emd_zombie = MCDI_STRUCT_DWORD_FIELD(entry_buf, 4078 MAE_MPORT_DESC_V2_FLAGS, 4079 MAE_MPORT_DESC_V2_IS_ZOMBIE); 4080 4081 desc->emd_type = MCDI_STRUCT_DWORD(entry_buf, 4082 MAE_MPORT_DESC_V2_MPORT_TYPE); 4083 4084 /* 4085 * We can't check everything here. If some additional checks are 4086 * required, they should be performed by the callback function. 4087 */ 4088 switch (desc->emd_type) { 4089 case EFX_MPORT_TYPE_NET_PORT: 4090 desc->emd_net_port.ep_index = 4091 MCDI_STRUCT_DWORD(entry_buf, 4092 MAE_MPORT_DESC_V2_NET_PORT_IDX); 4093 break; 4094 case EFX_MPORT_TYPE_ALIAS: 4095 desc->emd_alias.ea_target_mport_id.id = 4096 MCDI_STRUCT_DWORD(entry_buf, 4097 MAE_MPORT_DESC_V2_ALIAS_DELIVER_MPORT_ID); 4098 break; 4099 case EFX_MPORT_TYPE_VNIC: 4100 desc->emd_vnic.ev_client_type = 4101 MCDI_STRUCT_DWORD(entry_buf, 4102 MAE_MPORT_DESC_V2_VNIC_CLIENT_TYPE); 4103 if (desc->emd_vnic.ev_client_type != 4104 EFX_MPORT_VNIC_CLIENT_FUNCTION) 4105 break; 4106 4107 pcie_intf = MCDI_STRUCT_DWORD(entry_buf, 4108 MAE_MPORT_DESC_V2_VNIC_FUNCTION_INTERFACE); 4109 rc = efx_mcdi_intf_from_pcie(pcie_intf, 4110 &desc->emd_vnic.ev_intf); 4111 if (rc != 0) 4112 goto fail1; 4113 4114 desc->emd_vnic.ev_pf = MCDI_STRUCT_WORD(entry_buf, 4115 MAE_MPORT_DESC_V2_VNIC_FUNCTION_PF_IDX); 4116 desc->emd_vnic.ev_vf = MCDI_STRUCT_WORD(entry_buf, 4117 MAE_MPORT_DESC_V2_VNIC_FUNCTION_VF_IDX); 4118 desc->emd_vnic.ev_handle = MCDI_STRUCT_DWORD(entry_buf, 4119 MAE_MPORT_DESC_V2_VNIC_CLIENT_HANDLE); 4120 break; 4121 default: 4122 rc = EINVAL; 4123 goto fail2; 4124 } 4125 4126 return (0); 4127 4128 fail2: 4129 EFSYS_PROBE(fail2); 4130 fail1: 4131 EFSYS_PROBE1(fail1, efx_rc_t, rc); 4132 return (rc); 4133 } 4134 4135 static __checkReturn efx_rc_t 4136 efx_mae_read_mport_journal_batch( 4137 __in efx_nic_t *enp, 4138 __in efx_mae_read_mport_journal_cb *cbp, 4139 __in void *cb_datap, 4140 __out uint32_t *morep) 4141 { 4142 efx_mcdi_req_t req; 4143 EFX_MCDI_DECLARE_BUF(payload, 4144 MC_CMD_MAE_MPORT_READ_JOURNAL_IN_LEN, 4145 MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMAX_MCDI2); 4146 uint32_t n_entries; 4147 uint32_t entry_sz; 4148 uint8_t *entry_buf; 4149 unsigned int i; 4150 efx_rc_t rc; 4151 4152 EFX_STATIC_ASSERT(EFX_MPORT_TYPE_NET_PORT == 4153 MAE_MPORT_DESC_V2_MPORT_TYPE_NET_PORT); 4154 EFX_STATIC_ASSERT(EFX_MPORT_TYPE_ALIAS == 4155 MAE_MPORT_DESC_V2_MPORT_TYPE_ALIAS); 4156 EFX_STATIC_ASSERT(EFX_MPORT_TYPE_VNIC == 4157 MAE_MPORT_DESC_V2_MPORT_TYPE_VNIC); 4158 4159 EFX_STATIC_ASSERT(EFX_MPORT_VNIC_CLIENT_FUNCTION == 4160 MAE_MPORT_DESC_V2_VNIC_CLIENT_TYPE_FUNCTION); 4161 EFX_STATIC_ASSERT(EFX_MPORT_VNIC_CLIENT_PLUGIN == 4162 MAE_MPORT_DESC_V2_VNIC_CLIENT_TYPE_PLUGIN); 4163 4164 if (cbp == NULL) { 4165 rc = EINVAL; 4166 goto fail1; 4167 } 4168 4169 req.emr_cmd = MC_CMD_MAE_MPORT_READ_JOURNAL; 4170 req.emr_in_buf = payload; 4171 req.emr_in_length = MC_CMD_MAE_MPORT_READ_JOURNAL_IN_LEN; 4172 req.emr_out_buf = payload; 4173 req.emr_out_length = MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMAX_MCDI2; 4174 4175 MCDI_IN_SET_DWORD(req, MAE_MPORT_READ_JOURNAL_IN_FLAGS, 0); 4176 4177 efx_mcdi_execute(enp, &req); 4178 4179 if (req.emr_rc != 0) { 4180 rc = req.emr_rc; 4181 goto fail2; 4182 } 4183 4184 if (req.emr_out_length_used < 4185 MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMIN) { 4186 rc = EMSGSIZE; 4187 goto fail3; 4188 } 4189 4190 if (morep != NULL) { 4191 *morep = MCDI_OUT_DWORD_FIELD(req, 4192 MAE_MPORT_READ_JOURNAL_OUT_FLAGS, 4193 MAE_MPORT_READ_JOURNAL_OUT_MORE); 4194 } 4195 n_entries = MCDI_OUT_DWORD(req, 4196 MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_COUNT); 4197 entry_sz = MCDI_OUT_DWORD(req, 4198 MAE_MPORT_READ_JOURNAL_OUT_SIZEOF_MPORT_DESC); 4199 entry_buf = MCDI_OUT2(req, uint8_t, 4200 MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_DATA); 4201 4202 if (entry_sz < MAE_MPORT_DESC_V2_VNIC_CLIENT_HANDLE_OFST + 4203 MAE_MPORT_DESC_V2_VNIC_CLIENT_HANDLE_LEN) { 4204 rc = EINVAL; 4205 goto fail4; 4206 } 4207 if (n_entries * entry_sz / entry_sz != n_entries) { 4208 rc = EINVAL; 4209 goto fail5; 4210 } 4211 if (req.emr_out_length_used != 4212 MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMIN + n_entries * entry_sz) { 4213 rc = EINVAL; 4214 goto fail6; 4215 } 4216 4217 for (i = 0; i < n_entries; i++) { 4218 efx_mport_desc_t desc; 4219 4220 rc = efx_mae_read_mport_journal_single(entry_buf, &desc); 4221 if (rc != 0) 4222 continue; 4223 4224 (*cbp)(cb_datap, &desc, sizeof (desc)); 4225 entry_buf += entry_sz; 4226 } 4227 4228 return (0); 4229 4230 fail6: 4231 EFSYS_PROBE(fail6); 4232 fail5: 4233 EFSYS_PROBE(fail5); 4234 fail4: 4235 EFSYS_PROBE(fail4); 4236 fail3: 4237 EFSYS_PROBE(fail3); 4238 fail2: 4239 EFSYS_PROBE(fail2); 4240 fail1: 4241 EFSYS_PROBE1(fail1, efx_rc_t, rc); 4242 return (rc); 4243 } 4244 4245 __checkReturn efx_rc_t 4246 efx_mae_read_mport_journal( 4247 __in efx_nic_t *enp, 4248 __in efx_mae_read_mport_journal_cb *cbp, 4249 __in void *cb_datap) 4250 { 4251 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 4252 uint32_t more = 0; 4253 efx_rc_t rc; 4254 4255 if (encp->enc_mae_supported == B_FALSE) { 4256 rc = ENOTSUP; 4257 goto fail1; 4258 } 4259 4260 do { 4261 rc = efx_mae_read_mport_journal_batch(enp, cbp, cb_datap, 4262 &more); 4263 if (rc != 0) 4264 goto fail2; 4265 } while (more != 0); 4266 4267 return (0); 4268 4269 fail2: 4270 EFSYS_PROBE(fail2); 4271 fail1: 4272 EFSYS_PROBE1(fail1, efx_rc_t, rc); 4273 return (rc); 4274 } 4275 4276 __checkReturn efx_rc_t 4277 efx_mae_action_set_replay( 4278 __in efx_nic_t *enp, 4279 __in const efx_mae_actions_t *spec_orig, 4280 __out efx_mae_actions_t **spec_clonep) 4281 { 4282 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 4283 efx_mae_actions_t *spec_clone; 4284 efx_rc_t rc; 4285 4286 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec_clone), spec_clone); 4287 if (spec_clone == NULL) { 4288 rc = ENOMEM; 4289 goto fail1; 4290 } 4291 4292 *spec_clone = *spec_orig; 4293 4294 spec_clone->ema_rsrc.emar_counter_id.id = EFX_MAE_RSRC_ID_INVALID; 4295 spec_clone->ema_actions &= ~(1U << EFX_MAE_ACTION_COUNT); 4296 spec_clone->ema_n_count_actions = 0; 4297 4298 (void)efx_mae_mport_invalid(&spec_clone->ema_deliver_mport); 4299 spec_clone->ema_actions &= ~(1U << EFX_MAE_ACTION_DELIVER); 4300 4301 *spec_clonep = spec_clone; 4302 4303 return (0); 4304 4305 fail1: 4306 EFSYS_PROBE1(fail1, efx_rc_t, rc); 4307 return (rc); 4308 } 4309 4310 __checkReturn efx_rc_t 4311 efx_mae_action_set_list_alloc( 4312 __in efx_nic_t *enp, 4313 __in unsigned int n_asets, 4314 __in_ecount(n_asets) const efx_mae_aset_id_t *aset_ids, 4315 __out efx_mae_aset_list_id_t *aset_list_idp) 4316 { 4317 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 4318 EFX_MCDI_DECLARE_BUF(payload, 4319 MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LENMAX_MCDI2, 4320 MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_LEN); 4321 efx_mae_aset_list_id_t aset_list_id; 4322 efx_mcdi_req_t req; 4323 efx_rc_t rc; 4324 4325 EFX_STATIC_ASSERT(EFX_MAE_ACTION_SET_LIST_MAX_NENTRIES == 4326 MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS_MAXNUM_MCDI2); 4327 4328 EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID == 4329 MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL); 4330 4331 EFX_STATIC_ASSERT(sizeof (aset_list_idp->id) == 4332 MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ASL_ID_LEN); 4333 4334 if (encp->enc_mae_supported == B_FALSE) { 4335 rc = ENOTSUP; 4336 goto fail1; 4337 } 4338 4339 if (MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LEN(n_asets) > 4340 MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LENMAX_MCDI2) { 4341 rc = EINVAL; 4342 goto fail2; 4343 } 4344 4345 req.emr_cmd = MC_CMD_MAE_ACTION_SET_LIST_ALLOC; 4346 req.emr_in_buf = payload; 4347 req.emr_in_length = MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LEN(n_asets); 4348 req.emr_out_buf = payload; 4349 req.emr_out_length = MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_LEN; 4350 4351 MCDI_IN_SET_DWORD(req, 4352 MAE_ACTION_SET_LIST_ALLOC_IN_COUNT, n_asets); 4353 4354 memcpy(MCDI_IN2(req, uint8_t, MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS), 4355 aset_ids, n_asets * sizeof (*aset_ids)); 4356 4357 efx_mcdi_execute(enp, &req); 4358 4359 if (req.emr_rc != 0) { 4360 rc = req.emr_rc; 4361 goto fail3; 4362 } 4363 4364 if (req.emr_out_length_used < MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_LEN) { 4365 rc = EMSGSIZE; 4366 goto fail4; 4367 } 4368 4369 aset_list_id.id = 4370 MCDI_OUT_DWORD(req, MAE_ACTION_SET_LIST_ALLOC_OUT_ASL_ID); 4371 if (aset_list_id.id == EFX_MAE_RSRC_ID_INVALID) { 4372 rc = ENOENT; 4373 goto fail5; 4374 } 4375 4376 aset_list_idp->id = aset_list_id.id; 4377 4378 return (0); 4379 4380 fail5: 4381 EFSYS_PROBE(fail5); 4382 fail4: 4383 EFSYS_PROBE(fail4); 4384 fail3: 4385 EFSYS_PROBE(fail3); 4386 fail2: 4387 EFSYS_PROBE(fail2); 4388 fail1: 4389 EFSYS_PROBE1(fail1, efx_rc_t, rc); 4390 return (rc); 4391 } 4392 4393 __checkReturn efx_rc_t 4394 efx_mae_action_set_list_free( 4395 __in efx_nic_t *enp, 4396 __in const efx_mae_aset_list_id_t *aset_list_idp) 4397 { 4398 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 4399 EFX_MCDI_DECLARE_BUF(payload, 4400 MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_LEN(1), 4401 MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_LEN(1)); 4402 efx_mcdi_req_t req; 4403 efx_rc_t rc; 4404 4405 if (encp->enc_mae_supported == B_FALSE) { 4406 rc = ENOTSUP; 4407 goto fail1; 4408 } 4409 4410 req.emr_cmd = MC_CMD_MAE_ACTION_SET_LIST_FREE; 4411 req.emr_in_buf = payload; 4412 req.emr_in_length = MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_LEN(1); 4413 req.emr_out_buf = payload; 4414 req.emr_out_length = MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_LEN(1); 4415 4416 MCDI_IN_SET_DWORD(req, 4417 MAE_ACTION_SET_LIST_FREE_IN_ASL_ID, aset_list_idp->id); 4418 4419 efx_mcdi_execute(enp, &req); 4420 4421 if (req.emr_rc != 0) { 4422 rc = req.emr_rc; 4423 goto fail2; 4424 } 4425 4426 if (req.emr_out_length_used < MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_LENMIN) { 4427 rc = EMSGSIZE; 4428 goto fail3; 4429 } 4430 4431 if (MCDI_OUT_DWORD(req, MAE_ACTION_SET_LIST_FREE_OUT_FREED_ASL_ID) != 4432 aset_list_idp->id) { 4433 /* Firmware failed to free the action set list. */ 4434 rc = EAGAIN; 4435 goto fail4; 4436 } 4437 4438 return (0); 4439 4440 fail4: 4441 EFSYS_PROBE(fail4); 4442 fail3: 4443 EFSYS_PROBE(fail3); 4444 fail2: 4445 EFSYS_PROBE(fail2); 4446 fail1: 4447 EFSYS_PROBE1(fail1, efx_rc_t, rc); 4448 return (rc); 4449 } 4450 4451 #endif /* EFSYS_OPT_MAE */ 4452