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_free( 2953 __in efx_nic_t *enp, 2954 __in const efx_mae_eh_id_t *eh_idp) 2955 { 2956 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 2957 efx_mcdi_req_t req; 2958 EFX_MCDI_DECLARE_BUF(payload, 2959 MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(1), 2960 MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(1)); 2961 efx_rc_t rc; 2962 2963 if (encp->enc_mae_supported == B_FALSE) { 2964 rc = ENOTSUP; 2965 goto fail1; 2966 } 2967 2968 req.emr_cmd = MC_CMD_MAE_ENCAP_HEADER_FREE; 2969 req.emr_in_buf = payload; 2970 req.emr_in_length = MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(1); 2971 req.emr_out_buf = payload; 2972 req.emr_out_length = MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(1); 2973 2974 MCDI_IN_SET_DWORD(req, MAE_ENCAP_HEADER_FREE_IN_EH_ID, eh_idp->id); 2975 2976 efx_mcdi_execute(enp, &req); 2977 2978 if (req.emr_rc != 0) { 2979 rc = req.emr_rc; 2980 goto fail2; 2981 } 2982 2983 if (MCDI_OUT_DWORD(req, MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID) != 2984 eh_idp->id) { 2985 /* Firmware failed to remove the encap. header. */ 2986 rc = EAGAIN; 2987 goto fail3; 2988 } 2989 2990 return (0); 2991 2992 fail3: 2993 EFSYS_PROBE(fail3); 2994 fail2: 2995 EFSYS_PROBE(fail2); 2996 fail1: 2997 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2998 return (rc); 2999 } 3000 3001 __checkReturn efx_rc_t 3002 efx_mae_action_set_fill_in_eh_id( 3003 __in efx_mae_actions_t *spec, 3004 __in const efx_mae_eh_id_t *eh_idp) 3005 { 3006 efx_rc_t rc; 3007 3008 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_ENCAP)) == 0) { 3009 /* 3010 * The caller has not intended to have action ENCAP originally, 3011 * hence, this attempt to indicate encap. header ID is invalid. 3012 */ 3013 rc = EINVAL; 3014 goto fail1; 3015 } 3016 3017 if (spec->ema_rsrc.emar_eh_id.id != EFX_MAE_RSRC_ID_INVALID) { 3018 /* The caller attempts to indicate encap. header ID twice. */ 3019 rc = EINVAL; 3020 goto fail2; 3021 } 3022 3023 if (eh_idp->id == EFX_MAE_RSRC_ID_INVALID) { 3024 rc = EINVAL; 3025 goto fail3; 3026 } 3027 3028 spec->ema_rsrc.emar_eh_id.id = eh_idp->id; 3029 3030 return (0); 3031 3032 fail3: 3033 EFSYS_PROBE(fail3); 3034 fail2: 3035 EFSYS_PROBE(fail2); 3036 fail1: 3037 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3038 return (rc); 3039 } 3040 3041 __checkReturn efx_rc_t 3042 efx_mae_action_set_alloc( 3043 __in efx_nic_t *enp, 3044 __in const efx_mae_actions_t *spec, 3045 __out efx_mae_aset_id_t *aset_idp) 3046 { 3047 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 3048 efx_mcdi_req_t req; 3049 EFX_MCDI_DECLARE_BUF(payload, 3050 MC_CMD_MAE_ACTION_SET_ALLOC_IN_LEN, 3051 MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN); 3052 efx_mae_aset_id_t aset_id; 3053 efx_rc_t rc; 3054 3055 if (encp->enc_mae_supported == B_FALSE) { 3056 rc = ENOTSUP; 3057 goto fail1; 3058 } 3059 3060 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_SET_DST_MAC)) != 0 && 3061 spec->ema_rsrc.emar_dst_mac_id.id == EFX_MAE_RSRC_ID_INVALID) { 3062 rc = EINVAL; 3063 goto fail2; 3064 } 3065 3066 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_SET_SRC_MAC)) != 0 && 3067 spec->ema_rsrc.emar_src_mac_id.id == EFX_MAE_RSRC_ID_INVALID) { 3068 rc = EINVAL; 3069 goto fail3; 3070 } 3071 3072 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_ENCAP)) != 0 && 3073 spec->ema_rsrc.emar_eh_id.id == EFX_MAE_RSRC_ID_INVALID) { 3074 rc = EINVAL; 3075 goto fail4; 3076 } 3077 3078 if (spec->ema_n_count_actions == 1 && 3079 spec->ema_rsrc.emar_counter_id.id == EFX_MAE_RSRC_ID_INVALID) { 3080 rc = EINVAL; 3081 goto fail5; 3082 } 3083 3084 req.emr_cmd = MC_CMD_MAE_ACTION_SET_ALLOC; 3085 req.emr_in_buf = payload; 3086 req.emr_in_length = MC_CMD_MAE_ACTION_SET_ALLOC_IN_LEN; 3087 req.emr_out_buf = payload; 3088 req.emr_out_length = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN; 3089 3090 /* 3091 * TODO: Remove these EFX_MAE_RSRC_ID_INVALID assignments once the 3092 * corresponding resource types are supported by the implementation. 3093 * Use proper resource ID assignments instead. 3094 */ 3095 MCDI_IN_SET_DWORD(req, 3096 MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID, EFX_MAE_RSRC_ID_INVALID); 3097 3098 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_DECAP)) != 0) { 3099 MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS, 3100 MAE_ACTION_SET_ALLOC_IN_DECAP, 1); 3101 } 3102 3103 MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS, 3104 MAE_ACTION_SET_ALLOC_IN_VLAN_POP, spec->ema_n_vlan_tags_to_pop); 3105 3106 MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID, 3107 spec->ema_rsrc.emar_dst_mac_id.id); 3108 3109 MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID, 3110 spec->ema_rsrc.emar_src_mac_id.id); 3111 3112 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_DECR_IP_TTL)) != 0) { 3113 MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS, 3114 MAE_ACTION_SET_ALLOC_IN_DO_DECR_IP_TTL, 1); 3115 } 3116 3117 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_NAT)) != 0) { 3118 MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS, 3119 MAE_ACTION_SET_ALLOC_IN_DO_NAT, 1); 3120 } 3121 3122 if (spec->ema_n_vlan_tags_to_push > 0) { 3123 unsigned int outer_tag_idx; 3124 3125 MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS, 3126 MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH, 3127 spec->ema_n_vlan_tags_to_push); 3128 3129 if (spec->ema_n_vlan_tags_to_push == 3130 EFX_MAE_VLAN_PUSH_MAX_NTAGS) { 3131 MCDI_IN_SET_WORD(req, 3132 MAE_ACTION_SET_ALLOC_IN_VLAN1_PROTO_BE, 3133 spec->ema_vlan_push_descs[0].emavp_tpid_be); 3134 MCDI_IN_SET_WORD(req, 3135 MAE_ACTION_SET_ALLOC_IN_VLAN1_TCI_BE, 3136 spec->ema_vlan_push_descs[0].emavp_tci_be); 3137 } 3138 3139 outer_tag_idx = spec->ema_n_vlan_tags_to_push - 1; 3140 3141 MCDI_IN_SET_WORD(req, MAE_ACTION_SET_ALLOC_IN_VLAN0_PROTO_BE, 3142 spec->ema_vlan_push_descs[outer_tag_idx].emavp_tpid_be); 3143 MCDI_IN_SET_WORD(req, MAE_ACTION_SET_ALLOC_IN_VLAN0_TCI_BE, 3144 spec->ema_vlan_push_descs[outer_tag_idx].emavp_tci_be); 3145 } 3146 3147 MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID, 3148 spec->ema_rsrc.emar_eh_id.id); 3149 MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_COUNTER_ID, 3150 spec->ema_rsrc.emar_counter_id.id); 3151 3152 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_FLAG)) != 0) { 3153 MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS, 3154 MAE_ACTION_SET_ALLOC_IN_FLAG, 1); 3155 } 3156 3157 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_MARK)) != 0) { 3158 MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS, 3159 MAE_ACTION_SET_ALLOC_IN_MARK, 1); 3160 3161 MCDI_IN_SET_DWORD(req, 3162 MAE_ACTION_SET_ALLOC_IN_MARK_VALUE, spec->ema_mark_value); 3163 } 3164 3165 MCDI_IN_SET_DWORD(req, 3166 MAE_ACTION_SET_ALLOC_IN_DELIVER, spec->ema_deliver_mport.sel); 3167 3168 efx_mcdi_execute(enp, &req); 3169 3170 if (req.emr_rc != 0) { 3171 rc = req.emr_rc; 3172 goto fail6; 3173 } 3174 3175 if (req.emr_out_length_used < MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN) { 3176 rc = EMSGSIZE; 3177 goto fail7; 3178 } 3179 3180 aset_id.id = MCDI_OUT_DWORD(req, MAE_ACTION_SET_ALLOC_OUT_AS_ID); 3181 if (aset_id.id == EFX_MAE_RSRC_ID_INVALID) { 3182 rc = ENOENT; 3183 goto fail8; 3184 } 3185 3186 aset_idp->id = aset_id.id; 3187 3188 return (0); 3189 3190 fail8: 3191 EFSYS_PROBE(fail8); 3192 fail7: 3193 EFSYS_PROBE(fail7); 3194 fail6: 3195 EFSYS_PROBE(fail6); 3196 fail5: 3197 EFSYS_PROBE(fail5); 3198 fail4: 3199 EFSYS_PROBE(fail4); 3200 fail3: 3201 EFSYS_PROBE(fail3); 3202 fail2: 3203 EFSYS_PROBE(fail2); 3204 fail1: 3205 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3206 return (rc); 3207 } 3208 3209 __checkReturn unsigned int 3210 efx_mae_action_set_get_nb_count( 3211 __in const efx_mae_actions_t *spec) 3212 { 3213 return (spec->ema_n_count_actions); 3214 } 3215 3216 __checkReturn efx_rc_t 3217 efx_mae_action_set_fill_in_counter_id( 3218 __in efx_mae_actions_t *spec, 3219 __in const efx_counter_t *counter_idp) 3220 { 3221 efx_rc_t rc; 3222 3223 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_COUNT)) == 0) { 3224 /* 3225 * Invalid to add counter ID if spec does not have COUNT action. 3226 */ 3227 rc = EINVAL; 3228 goto fail1; 3229 } 3230 3231 if (spec->ema_n_count_actions != 1) { 3232 /* 3233 * Having multiple COUNT actions in the spec requires a counter 3234 * list to be used. This API must only be used for a single 3235 * counter per spec. Turn down the request as inappropriate. 3236 */ 3237 rc = EINVAL; 3238 goto fail2; 3239 } 3240 3241 if (spec->ema_rsrc.emar_counter_id.id != EFX_MAE_RSRC_ID_INVALID) { 3242 /* The caller attempts to indicate counter ID twice. */ 3243 rc = EALREADY; 3244 goto fail3; 3245 } 3246 3247 if (counter_idp->id == EFX_MAE_RSRC_ID_INVALID) { 3248 rc = EINVAL; 3249 goto fail4; 3250 } 3251 3252 spec->ema_rsrc.emar_counter_id.id = counter_idp->id; 3253 3254 return (0); 3255 3256 fail4: 3257 EFSYS_PROBE(fail4); 3258 fail3: 3259 EFSYS_PROBE(fail3); 3260 fail2: 3261 EFSYS_PROBE(fail2); 3262 fail1: 3263 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3264 return (rc); 3265 } 3266 3267 void 3268 efx_mae_action_set_clear_fw_rsrc_ids( 3269 __in efx_mae_actions_t *spec) 3270 { 3271 spec->ema_rsrc.emar_dst_mac_id.id = EFX_MAE_RSRC_ID_INVALID; 3272 spec->ema_rsrc.emar_src_mac_id.id = EFX_MAE_RSRC_ID_INVALID; 3273 spec->ema_rsrc.emar_eh_id.id = EFX_MAE_RSRC_ID_INVALID; 3274 spec->ema_rsrc.emar_counter_id.id = EFX_MAE_RSRC_ID_INVALID; 3275 } 3276 3277 __checkReturn efx_rc_t 3278 efx_mae_counters_alloc_type( 3279 __in efx_nic_t *enp, 3280 __in efx_counter_type_t type, 3281 __in uint32_t n_counters, 3282 __out uint32_t *n_allocatedp, 3283 __out_ecount(n_counters) efx_counter_t *countersp, 3284 __out_opt uint32_t *gen_countp) 3285 { 3286 EFX_MCDI_DECLARE_BUF(payload, 3287 MC_CMD_MAE_COUNTER_ALLOC_V2_IN_LEN, 3288 MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMAX_MCDI2); 3289 efx_mae_t *maep = enp->en_maep; 3290 uint32_t max_n_counters; 3291 uint32_t n_allocated; 3292 efx_mcdi_req_t req; 3293 unsigned int i; 3294 efx_rc_t rc; 3295 3296 EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_ACTION == MAE_COUNTER_TYPE_AR); 3297 EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_CONNTRACK == MAE_COUNTER_TYPE_CT); 3298 3299 switch (type) { 3300 case EFX_COUNTER_TYPE_ACTION: 3301 max_n_counters = maep->em_max_n_action_counters; 3302 break; 3303 case EFX_COUNTER_TYPE_CONNTRACK: 3304 max_n_counters = maep->em_max_n_conntrack_counters; 3305 break; 3306 default: 3307 rc = EINVAL; 3308 goto fail1; 3309 } 3310 3311 if (n_counters > max_n_counters || 3312 n_counters < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM || 3313 n_counters > MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MAXNUM_MCDI2) { 3314 rc = EINVAL; 3315 goto fail2; 3316 } 3317 3318 req.emr_cmd = MC_CMD_MAE_COUNTER_ALLOC; 3319 req.emr_in_buf = payload; 3320 req.emr_in_length = MC_CMD_MAE_COUNTER_ALLOC_V2_IN_LEN; 3321 req.emr_out_buf = payload; 3322 req.emr_out_length = MC_CMD_MAE_COUNTER_ALLOC_OUT_LEN(n_counters); 3323 3324 MCDI_IN_SET_DWORD(req, MAE_COUNTER_ALLOC_IN_REQUESTED_COUNT, 3325 n_counters); 3326 3327 MCDI_IN_SET_DWORD(req, MAE_COUNTER_ALLOC_V2_IN_COUNTER_TYPE, type); 3328 3329 efx_mcdi_execute(enp, &req); 3330 3331 if (req.emr_rc != 0) { 3332 rc = req.emr_rc; 3333 goto fail3; 3334 } 3335 3336 if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMIN) { 3337 rc = EMSGSIZE; 3338 goto fail4; 3339 } 3340 3341 n_allocated = MCDI_OUT_DWORD(req, 3342 MAE_COUNTER_ALLOC_OUT_COUNTER_ID_COUNT); 3343 if (n_allocated < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM) { 3344 rc = EFAULT; 3345 goto fail5; 3346 } 3347 3348 for (i = 0; i < n_allocated; i++) { 3349 countersp[i].id = MCDI_OUT_INDEXED_DWORD(req, 3350 MAE_COUNTER_ALLOC_OUT_COUNTER_ID, i); 3351 } 3352 3353 if (gen_countp != NULL) { 3354 *gen_countp = MCDI_OUT_DWORD(req, 3355 MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT); 3356 } 3357 3358 *n_allocatedp = n_allocated; 3359 3360 return (0); 3361 3362 fail5: 3363 EFSYS_PROBE(fail5); 3364 fail4: 3365 EFSYS_PROBE(fail4); 3366 fail3: 3367 EFSYS_PROBE(fail3); 3368 fail2: 3369 EFSYS_PROBE(fail2); 3370 fail1: 3371 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3372 3373 return (rc); 3374 } 3375 3376 __checkReturn efx_rc_t 3377 efx_mae_counters_alloc( 3378 __in efx_nic_t *enp, 3379 __in uint32_t n_counters, 3380 __out uint32_t *n_allocatedp, 3381 __out_ecount(n_counters) efx_counter_t *countersp, 3382 __out_opt uint32_t *gen_countp) 3383 { 3384 efx_rc_t rc; 3385 3386 rc = efx_mae_counters_alloc_type(enp, EFX_COUNTER_TYPE_ACTION, 3387 n_counters, n_allocatedp, 3388 countersp, gen_countp); 3389 if (rc != 0) 3390 goto fail1; 3391 3392 return (0); 3393 3394 fail1: 3395 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3396 return (rc); 3397 } 3398 3399 __checkReturn efx_rc_t 3400 efx_mae_counters_free_type( 3401 __in efx_nic_t *enp, 3402 __in efx_counter_type_t type, 3403 __in uint32_t n_counters, 3404 __out uint32_t *n_freedp, 3405 __in_ecount(n_counters) const efx_counter_t *countersp, 3406 __out_opt uint32_t *gen_countp) 3407 { 3408 EFX_MCDI_DECLARE_BUF(payload, 3409 MC_CMD_MAE_COUNTER_FREE_V2_IN_LEN, 3410 MC_CMD_MAE_COUNTER_FREE_OUT_LENMAX_MCDI2); 3411 efx_mae_t *maep = enp->en_maep; 3412 uint32_t max_n_counters; 3413 efx_mcdi_req_t req; 3414 uint32_t n_freed; 3415 unsigned int i; 3416 efx_rc_t rc; 3417 3418 switch (type) { 3419 case EFX_COUNTER_TYPE_ACTION: 3420 max_n_counters = maep->em_max_n_action_counters; 3421 break; 3422 case EFX_COUNTER_TYPE_CONNTRACK: 3423 max_n_counters = maep->em_max_n_conntrack_counters; 3424 break; 3425 default: 3426 rc = EINVAL; 3427 goto fail1; 3428 } 3429 3430 if (n_counters > max_n_counters || 3431 n_counters < MC_CMD_MAE_COUNTER_FREE_V2_IN_FREE_COUNTER_ID_MINNUM || 3432 n_counters > 3433 MC_CMD_MAE_COUNTER_FREE_V2_IN_FREE_COUNTER_ID_MAXNUM_MCDI2) { 3434 rc = EINVAL; 3435 goto fail2; 3436 } 3437 3438 req.emr_cmd = MC_CMD_MAE_COUNTER_FREE; 3439 req.emr_in_buf = payload; 3440 req.emr_in_length = MC_CMD_MAE_COUNTER_FREE_V2_IN_LEN; 3441 req.emr_out_buf = payload; 3442 req.emr_out_length = MC_CMD_MAE_COUNTER_FREE_OUT_LEN(n_counters); 3443 3444 for (i = 0; i < n_counters; i++) { 3445 MCDI_IN_SET_INDEXED_DWORD(req, 3446 MAE_COUNTER_FREE_IN_FREE_COUNTER_ID, i, countersp[i].id); 3447 } 3448 MCDI_IN_SET_DWORD(req, MAE_COUNTER_FREE_IN_COUNTER_ID_COUNT, 3449 n_counters); 3450 3451 MCDI_IN_SET_DWORD(req, MAE_COUNTER_FREE_V2_IN_COUNTER_TYPE, type); 3452 3453 efx_mcdi_execute(enp, &req); 3454 3455 if (req.emr_rc != 0) { 3456 rc = req.emr_rc; 3457 goto fail3; 3458 } 3459 3460 if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_FREE_OUT_LENMIN) { 3461 rc = EMSGSIZE; 3462 goto fail4; 3463 } 3464 3465 n_freed = MCDI_OUT_DWORD(req, MAE_COUNTER_FREE_OUT_COUNTER_ID_COUNT); 3466 3467 if (n_freed < MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_MINNUM) { 3468 rc = EFAULT; 3469 goto fail5; 3470 } 3471 3472 if (gen_countp != NULL) { 3473 *gen_countp = MCDI_OUT_DWORD(req, 3474 MAE_COUNTER_FREE_OUT_GENERATION_COUNT); 3475 } 3476 3477 *n_freedp = n_freed; 3478 3479 return (0); 3480 3481 fail5: 3482 EFSYS_PROBE(fail5); 3483 fail4: 3484 EFSYS_PROBE(fail4); 3485 fail3: 3486 EFSYS_PROBE(fail3); 3487 fail2: 3488 EFSYS_PROBE(fail2); 3489 fail1: 3490 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3491 3492 return (rc); 3493 } 3494 3495 __checkReturn efx_rc_t 3496 efx_mae_counters_free( 3497 __in efx_nic_t *enp, 3498 __in uint32_t n_counters, 3499 __out uint32_t *n_freedp, 3500 __in_ecount(n_counters) const efx_counter_t *countersp, 3501 __out_opt uint32_t *gen_countp) 3502 { 3503 efx_rc_t rc; 3504 3505 rc = efx_mae_counters_free_type(enp, EFX_COUNTER_TYPE_ACTION, 3506 n_counters, n_freedp, 3507 countersp, gen_countp); 3508 if (rc != 0) 3509 goto fail1; 3510 3511 return (0); 3512 3513 fail1: 3514 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3515 return (rc); 3516 } 3517 3518 __checkReturn efx_rc_t 3519 efx_mae_counters_stream_start( 3520 __in efx_nic_t *enp, 3521 __in uint16_t rxq_id, 3522 __in uint16_t packet_size, 3523 __in uint32_t flags_in, 3524 __out uint32_t *flags_out) 3525 { 3526 efx_mcdi_req_t req; 3527 EFX_MCDI_DECLARE_BUF(payload, 3528 MC_CMD_MAE_COUNTERS_STREAM_START_V2_IN_LEN, 3529 MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN); 3530 struct efx_mae_s *maep = enp->en_maep; 3531 uint32_t counter_types; 3532 efx_rc_t rc; 3533 3534 EFX_STATIC_ASSERT(EFX_MAE_COUNTERS_STREAM_IN_ZERO_SQUASH_DISABLE == 3535 1U << MC_CMD_MAE_COUNTERS_STREAM_START_IN_ZERO_SQUASH_DISABLE_LBN); 3536 3537 EFX_STATIC_ASSERT(EFX_MAE_COUNTERS_STREAM_OUT_USES_CREDITS == 3538 1U << MC_CMD_MAE_COUNTERS_STREAM_START_OUT_USES_CREDITS_LBN); 3539 3540 req.emr_cmd = MC_CMD_MAE_COUNTERS_STREAM_START; 3541 req.emr_in_buf = payload; 3542 req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_START_V2_IN_LEN; 3543 req.emr_out_buf = payload; 3544 req.emr_out_length = MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN; 3545 3546 MCDI_IN_SET_WORD(req, MAE_COUNTERS_STREAM_START_IN_QID, rxq_id); 3547 MCDI_IN_SET_WORD(req, MAE_COUNTERS_STREAM_START_IN_PACKET_SIZE, 3548 packet_size); 3549 MCDI_IN_SET_DWORD(req, MAE_COUNTERS_STREAM_START_IN_FLAGS, flags_in); 3550 3551 counter_types = (1U << MAE_COUNTER_TYPE_AR); 3552 3553 if (maep->em_max_n_conntrack_counters != 0) 3554 counter_types |= (1U << MAE_COUNTER_TYPE_CT); 3555 3556 MCDI_IN_SET_DWORD(req, 3557 MAE_COUNTERS_STREAM_START_V2_IN_COUNTER_TYPES_MASK, 3558 counter_types); 3559 3560 efx_mcdi_execute(enp, &req); 3561 3562 if (req.emr_rc != 0) { 3563 rc = req.emr_rc; 3564 goto fail1; 3565 } 3566 3567 if (req.emr_out_length_used < 3568 MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN) { 3569 rc = EMSGSIZE; 3570 goto fail2; 3571 } 3572 3573 *flags_out = MCDI_OUT_DWORD(req, MAE_COUNTERS_STREAM_START_OUT_FLAGS); 3574 3575 return (0); 3576 3577 fail2: 3578 EFSYS_PROBE(fail2); 3579 fail1: 3580 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3581 3582 return (rc); 3583 } 3584 3585 __checkReturn efx_rc_t 3586 efx_mae_counters_stream_stop( 3587 __in efx_nic_t *enp, 3588 __in uint16_t rxq_id, 3589 __out_opt uint32_t *gen_countp) 3590 { 3591 efx_mcdi_req_t req; 3592 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_MAE_COUNTERS_STREAM_STOP_IN_LEN, 3593 MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_LEN); 3594 efx_rc_t rc; 3595 3596 req.emr_cmd = MC_CMD_MAE_COUNTERS_STREAM_STOP; 3597 req.emr_in_buf = payload; 3598 req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_STOP_IN_LEN; 3599 req.emr_out_buf = payload; 3600 req.emr_out_length = MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_LEN; 3601 3602 MCDI_IN_SET_WORD(req, MAE_COUNTERS_STREAM_STOP_IN_QID, rxq_id); 3603 3604 efx_mcdi_execute(enp, &req); 3605 3606 if (req.emr_rc != 0) { 3607 rc = req.emr_rc; 3608 goto fail1; 3609 } 3610 3611 if (req.emr_out_length_used < 3612 MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_LEN) { 3613 rc = EMSGSIZE; 3614 goto fail2; 3615 } 3616 3617 if (gen_countp != NULL) { 3618 *gen_countp = MCDI_OUT_DWORD(req, 3619 MAE_COUNTERS_STREAM_STOP_OUT_GENERATION_COUNT); 3620 } 3621 3622 return (0); 3623 3624 fail2: 3625 EFSYS_PROBE(fail2); 3626 fail1: 3627 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3628 3629 return (rc); 3630 } 3631 3632 __checkReturn efx_rc_t 3633 efx_mae_counters_stream_give_credits( 3634 __in efx_nic_t *enp, 3635 __in uint32_t n_credits) 3636 { 3637 efx_mcdi_req_t req; 3638 EFX_MCDI_DECLARE_BUF(payload, 3639 MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_LEN, 3640 MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_OUT_LEN); 3641 efx_rc_t rc; 3642 3643 req.emr_cmd = MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS; 3644 req.emr_in_buf = payload; 3645 req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_LEN; 3646 req.emr_out_buf = payload; 3647 req.emr_out_length = MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_OUT_LEN; 3648 3649 MCDI_IN_SET_DWORD(req, MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_NUM_CREDITS, 3650 n_credits); 3651 3652 efx_mcdi_execute(enp, &req); 3653 3654 if (req.emr_rc != 0) { 3655 rc = req.emr_rc; 3656 goto fail1; 3657 } 3658 3659 return (0); 3660 3661 fail1: 3662 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3663 3664 return (rc); 3665 } 3666 3667 __checkReturn efx_rc_t 3668 efx_mae_action_set_free( 3669 __in efx_nic_t *enp, 3670 __in const efx_mae_aset_id_t *aset_idp) 3671 { 3672 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 3673 efx_mcdi_req_t req; 3674 EFX_MCDI_DECLARE_BUF(payload, 3675 MC_CMD_MAE_ACTION_SET_FREE_IN_LEN(1), 3676 MC_CMD_MAE_ACTION_SET_FREE_OUT_LEN(1)); 3677 efx_rc_t rc; 3678 3679 if (encp->enc_mae_supported == B_FALSE) { 3680 rc = ENOTSUP; 3681 goto fail1; 3682 } 3683 3684 req.emr_cmd = MC_CMD_MAE_ACTION_SET_FREE; 3685 req.emr_in_buf = payload; 3686 req.emr_in_length = MC_CMD_MAE_ACTION_SET_FREE_IN_LEN(1); 3687 req.emr_out_buf = payload; 3688 req.emr_out_length = MC_CMD_MAE_ACTION_SET_FREE_OUT_LEN(1); 3689 3690 MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_FREE_IN_AS_ID, aset_idp->id); 3691 3692 efx_mcdi_execute(enp, &req); 3693 3694 if (req.emr_rc != 0) { 3695 rc = req.emr_rc; 3696 goto fail2; 3697 } 3698 3699 if (req.emr_out_length_used < MC_CMD_MAE_ACTION_SET_FREE_OUT_LENMIN) { 3700 rc = EMSGSIZE; 3701 goto fail3; 3702 } 3703 3704 if (MCDI_OUT_DWORD(req, MAE_ACTION_SET_FREE_OUT_FREED_AS_ID) != 3705 aset_idp->id) { 3706 /* Firmware failed to free the action set. */ 3707 rc = EAGAIN; 3708 goto fail4; 3709 } 3710 3711 return (0); 3712 3713 fail4: 3714 EFSYS_PROBE(fail4); 3715 fail3: 3716 EFSYS_PROBE(fail3); 3717 fail2: 3718 EFSYS_PROBE(fail2); 3719 fail1: 3720 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3721 return (rc); 3722 } 3723 3724 __checkReturn efx_rc_t 3725 efx_mae_action_rule_insert( 3726 __in efx_nic_t *enp, 3727 __in const efx_mae_match_spec_t *spec, 3728 __in const efx_mae_aset_list_id_t *asl_idp, 3729 __in const efx_mae_aset_id_t *as_idp, 3730 __out efx_mae_rule_id_t *ar_idp) 3731 { 3732 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 3733 efx_mcdi_req_t req; 3734 EFX_MCDI_DECLARE_BUF(payload, 3735 MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMAX_MCDI2, 3736 MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN); 3737 efx_oword_t *rule_response; 3738 efx_mae_rule_id_t ar_id; 3739 size_t offset; 3740 efx_rc_t rc; 3741 3742 EFX_STATIC_ASSERT(sizeof (ar_idp->id) == 3743 MC_CMD_MAE_ACTION_RULE_INSERT_OUT_AR_ID_LEN); 3744 3745 EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID == 3746 MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL); 3747 3748 if (encp->enc_mae_supported == B_FALSE) { 3749 rc = ENOTSUP; 3750 goto fail1; 3751 } 3752 3753 if (spec->emms_type != EFX_MAE_RULE_ACTION || 3754 (asl_idp != NULL && as_idp != NULL) || 3755 (asl_idp == NULL && as_idp == NULL)) { 3756 rc = EINVAL; 3757 goto fail2; 3758 } 3759 3760 req.emr_cmd = MC_CMD_MAE_ACTION_RULE_INSERT; 3761 req.emr_in_buf = payload; 3762 req.emr_in_length = MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMAX_MCDI2; 3763 req.emr_out_buf = payload; 3764 req.emr_out_length = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN; 3765 3766 EFX_STATIC_ASSERT(sizeof (*rule_response) <= 3767 MC_CMD_MAE_ACTION_RULE_INSERT_IN_RESPONSE_LEN); 3768 offset = MC_CMD_MAE_ACTION_RULE_INSERT_IN_RESPONSE_OFST; 3769 rule_response = (efx_oword_t *)(payload + offset); 3770 EFX_POPULATE_OWORD_3(*rule_response, 3771 MAE_ACTION_RULE_RESPONSE_ASL_ID, 3772 (asl_idp != NULL) ? asl_idp->id : EFX_MAE_RSRC_ID_INVALID, 3773 MAE_ACTION_RULE_RESPONSE_AS_ID, 3774 (as_idp != NULL) ? as_idp->id : EFX_MAE_RSRC_ID_INVALID, 3775 MAE_ACTION_RULE_RESPONSE_COUNTER_ID, EFX_MAE_RSRC_ID_INVALID); 3776 3777 MCDI_IN_SET_DWORD(req, MAE_ACTION_RULE_INSERT_IN_PRIO, spec->emms_prio); 3778 3779 /* 3780 * Mask-value pairs have been stored in the byte order needed for the 3781 * MCDI request and are thus safe to be copied directly to the buffer. 3782 */ 3783 EFX_STATIC_ASSERT(sizeof (spec->emms_mask_value_pairs.action) >= 3784 MAE_FIELD_MASK_VALUE_PAIRS_V2_LEN); 3785 offset = MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_OFST; 3786 memcpy(payload + offset, spec->emms_mask_value_pairs.action, 3787 MAE_FIELD_MASK_VALUE_PAIRS_V2_LEN); 3788 3789 efx_mcdi_execute(enp, &req); 3790 3791 if (req.emr_rc != 0) { 3792 rc = req.emr_rc; 3793 goto fail3; 3794 } 3795 3796 if (req.emr_out_length_used < MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN) { 3797 rc = EMSGSIZE; 3798 goto fail4; 3799 } 3800 3801 ar_id.id = MCDI_OUT_DWORD(req, MAE_ACTION_RULE_INSERT_OUT_AR_ID); 3802 if (ar_id.id == EFX_MAE_RSRC_ID_INVALID) { 3803 rc = ENOENT; 3804 goto fail5; 3805 } 3806 3807 ar_idp->id = ar_id.id; 3808 3809 return (0); 3810 3811 fail5: 3812 EFSYS_PROBE(fail5); 3813 fail4: 3814 EFSYS_PROBE(fail4); 3815 fail3: 3816 EFSYS_PROBE(fail3); 3817 fail2: 3818 EFSYS_PROBE(fail2); 3819 fail1: 3820 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3821 return (rc); 3822 } 3823 3824 __checkReturn efx_rc_t 3825 efx_mae_action_rule_remove( 3826 __in efx_nic_t *enp, 3827 __in const efx_mae_rule_id_t *ar_idp) 3828 { 3829 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 3830 efx_mcdi_req_t req; 3831 EFX_MCDI_DECLARE_BUF(payload, 3832 MC_CMD_MAE_ACTION_RULE_DELETE_IN_LEN(1), 3833 MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(1)); 3834 efx_rc_t rc; 3835 3836 if (encp->enc_mae_supported == B_FALSE) { 3837 rc = ENOTSUP; 3838 goto fail1; 3839 } 3840 3841 req.emr_cmd = MC_CMD_MAE_ACTION_RULE_DELETE; 3842 req.emr_in_buf = payload; 3843 req.emr_in_length = MC_CMD_MAE_ACTION_RULE_DELETE_IN_LEN(1); 3844 req.emr_out_buf = payload; 3845 req.emr_out_length = MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(1); 3846 3847 MCDI_IN_SET_DWORD(req, MAE_ACTION_RULE_DELETE_IN_AR_ID, ar_idp->id); 3848 3849 efx_mcdi_execute(enp, &req); 3850 3851 if (req.emr_rc != 0) { 3852 rc = req.emr_rc; 3853 goto fail2; 3854 } 3855 3856 if (req.emr_out_length_used < 3857 MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LENMIN) { 3858 rc = EMSGSIZE; 3859 goto fail3; 3860 } 3861 3862 if (MCDI_OUT_DWORD(req, MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID) != 3863 ar_idp->id) { 3864 /* Firmware failed to delete the action rule. */ 3865 rc = EAGAIN; 3866 goto fail4; 3867 } 3868 3869 return (0); 3870 3871 fail4: 3872 EFSYS_PROBE(fail4); 3873 fail3: 3874 EFSYS_PROBE(fail3); 3875 fail2: 3876 EFSYS_PROBE(fail2); 3877 fail1: 3878 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3879 return (rc); 3880 } 3881 3882 __checkReturn efx_rc_t 3883 efx_mcdi_mport_alloc_alias( 3884 __in efx_nic_t *enp, 3885 __out efx_mport_id_t *mportp, 3886 __out_opt uint32_t *labelp) 3887 { 3888 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 3889 efx_mcdi_req_t req; 3890 EFX_MCDI_DECLARE_BUF(payload, 3891 MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_LEN, 3892 MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LEN); 3893 efx_rc_t rc; 3894 3895 if (encp->enc_mae_supported == B_FALSE) { 3896 rc = ENOTSUP; 3897 goto fail1; 3898 } 3899 3900 req.emr_cmd = MC_CMD_MAE_MPORT_ALLOC; 3901 req.emr_in_buf = payload; 3902 req.emr_in_length = MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_LEN; 3903 req.emr_out_buf = payload; 3904 req.emr_out_length = MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LEN; 3905 3906 MCDI_IN_SET_DWORD(req, MAE_MPORT_ALLOC_IN_TYPE, 3907 MC_CMD_MAE_MPORT_ALLOC_IN_MPORT_TYPE_ALIAS); 3908 MCDI_IN_SET_DWORD(req, MAE_MPORT_ALLOC_ALIAS_IN_DELIVER_MPORT, 3909 MAE_MPORT_SELECTOR_ASSIGNED); 3910 3911 efx_mcdi_execute(enp, &req); 3912 3913 if (req.emr_rc != 0) { 3914 rc = req.emr_rc; 3915 goto fail2; 3916 } 3917 3918 mportp->id = MCDI_OUT_DWORD(req, MAE_MPORT_ALLOC_OUT_MPORT_ID); 3919 if (labelp != NULL) 3920 *labelp = MCDI_OUT_DWORD(req, MAE_MPORT_ALLOC_ALIAS_OUT_LABEL); 3921 3922 return (0); 3923 3924 fail2: 3925 EFSYS_PROBE(fail2); 3926 fail1: 3927 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3928 return (rc); 3929 } 3930 3931 __checkReturn efx_rc_t 3932 efx_mae_mport_free( 3933 __in efx_nic_t *enp, 3934 __in const efx_mport_id_t *mportp) 3935 { 3936 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 3937 efx_mcdi_req_t req; 3938 EFX_MCDI_DECLARE_BUF(payload, 3939 MC_CMD_MAE_MPORT_FREE_IN_LEN, 3940 MC_CMD_MAE_MPORT_FREE_OUT_LEN); 3941 efx_rc_t rc; 3942 3943 if (encp->enc_mae_supported == B_FALSE) { 3944 rc = ENOTSUP; 3945 goto fail1; 3946 } 3947 3948 req.emr_cmd = MC_CMD_MAE_MPORT_FREE; 3949 req.emr_in_buf = payload; 3950 req.emr_in_length = MC_CMD_MAE_MPORT_FREE_IN_LEN; 3951 req.emr_out_buf = payload; 3952 req.emr_out_length = MC_CMD_MAE_MPORT_FREE_OUT_LEN; 3953 3954 MCDI_IN_SET_DWORD(req, MAE_MPORT_FREE_IN_MPORT_ID, mportp->id); 3955 3956 efx_mcdi_execute(enp, &req); 3957 3958 if (req.emr_rc != 0) { 3959 rc = req.emr_rc; 3960 goto fail2; 3961 } 3962 3963 return (0); 3964 3965 fail2: 3966 EFSYS_PROBE(fail2); 3967 fail1: 3968 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3969 return (rc); 3970 } 3971 3972 static __checkReturn efx_rc_t 3973 efx_mae_read_mport_journal_single( 3974 __in uint8_t *entry_buf, 3975 __out efx_mport_desc_t *desc) 3976 { 3977 uint32_t pcie_intf; 3978 efx_rc_t rc; 3979 3980 memset(desc, 0, sizeof (*desc)); 3981 3982 desc->emd_id.id = MCDI_STRUCT_DWORD(entry_buf, 3983 MAE_MPORT_DESC_V2_MPORT_ID); 3984 3985 desc->emd_can_receive_on = MCDI_STRUCT_DWORD_FIELD(entry_buf, 3986 MAE_MPORT_DESC_V2_FLAGS, 3987 MAE_MPORT_DESC_V2_CAN_RECEIVE_ON); 3988 3989 desc->emd_can_deliver_to = MCDI_STRUCT_DWORD_FIELD(entry_buf, 3990 MAE_MPORT_DESC_V2_FLAGS, 3991 MAE_MPORT_DESC_V2_CAN_DELIVER_TO); 3992 3993 desc->emd_can_delete = MCDI_STRUCT_DWORD_FIELD(entry_buf, 3994 MAE_MPORT_DESC_V2_FLAGS, 3995 MAE_MPORT_DESC_V2_CAN_DELETE); 3996 3997 desc->emd_zombie = MCDI_STRUCT_DWORD_FIELD(entry_buf, 3998 MAE_MPORT_DESC_V2_FLAGS, 3999 MAE_MPORT_DESC_V2_IS_ZOMBIE); 4000 4001 desc->emd_type = MCDI_STRUCT_DWORD(entry_buf, 4002 MAE_MPORT_DESC_V2_MPORT_TYPE); 4003 4004 /* 4005 * We can't check everything here. If some additional checks are 4006 * required, they should be performed by the callback function. 4007 */ 4008 switch (desc->emd_type) { 4009 case EFX_MPORT_TYPE_NET_PORT: 4010 desc->emd_net_port.ep_index = 4011 MCDI_STRUCT_DWORD(entry_buf, 4012 MAE_MPORT_DESC_V2_NET_PORT_IDX); 4013 break; 4014 case EFX_MPORT_TYPE_ALIAS: 4015 desc->emd_alias.ea_target_mport_id.id = 4016 MCDI_STRUCT_DWORD(entry_buf, 4017 MAE_MPORT_DESC_V2_ALIAS_DELIVER_MPORT_ID); 4018 break; 4019 case EFX_MPORT_TYPE_VNIC: 4020 desc->emd_vnic.ev_client_type = 4021 MCDI_STRUCT_DWORD(entry_buf, 4022 MAE_MPORT_DESC_V2_VNIC_CLIENT_TYPE); 4023 if (desc->emd_vnic.ev_client_type != 4024 EFX_MPORT_VNIC_CLIENT_FUNCTION) 4025 break; 4026 4027 pcie_intf = MCDI_STRUCT_DWORD(entry_buf, 4028 MAE_MPORT_DESC_V2_VNIC_FUNCTION_INTERFACE); 4029 rc = efx_mcdi_intf_from_pcie(pcie_intf, 4030 &desc->emd_vnic.ev_intf); 4031 if (rc != 0) 4032 goto fail1; 4033 4034 desc->emd_vnic.ev_pf = MCDI_STRUCT_WORD(entry_buf, 4035 MAE_MPORT_DESC_V2_VNIC_FUNCTION_PF_IDX); 4036 desc->emd_vnic.ev_vf = MCDI_STRUCT_WORD(entry_buf, 4037 MAE_MPORT_DESC_V2_VNIC_FUNCTION_VF_IDX); 4038 desc->emd_vnic.ev_handle = MCDI_STRUCT_DWORD(entry_buf, 4039 MAE_MPORT_DESC_V2_VNIC_CLIENT_HANDLE); 4040 break; 4041 default: 4042 rc = EINVAL; 4043 goto fail2; 4044 } 4045 4046 return (0); 4047 4048 fail2: 4049 EFSYS_PROBE(fail2); 4050 fail1: 4051 EFSYS_PROBE1(fail1, efx_rc_t, rc); 4052 return (rc); 4053 } 4054 4055 static __checkReturn efx_rc_t 4056 efx_mae_read_mport_journal_batch( 4057 __in efx_nic_t *enp, 4058 __in efx_mae_read_mport_journal_cb *cbp, 4059 __in void *cb_datap, 4060 __out uint32_t *morep) 4061 { 4062 efx_mcdi_req_t req; 4063 EFX_MCDI_DECLARE_BUF(payload, 4064 MC_CMD_MAE_MPORT_READ_JOURNAL_IN_LEN, 4065 MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMAX_MCDI2); 4066 uint32_t n_entries; 4067 uint32_t entry_sz; 4068 uint8_t *entry_buf; 4069 unsigned int i; 4070 efx_rc_t rc; 4071 4072 EFX_STATIC_ASSERT(EFX_MPORT_TYPE_NET_PORT == 4073 MAE_MPORT_DESC_V2_MPORT_TYPE_NET_PORT); 4074 EFX_STATIC_ASSERT(EFX_MPORT_TYPE_ALIAS == 4075 MAE_MPORT_DESC_V2_MPORT_TYPE_ALIAS); 4076 EFX_STATIC_ASSERT(EFX_MPORT_TYPE_VNIC == 4077 MAE_MPORT_DESC_V2_MPORT_TYPE_VNIC); 4078 4079 EFX_STATIC_ASSERT(EFX_MPORT_VNIC_CLIENT_FUNCTION == 4080 MAE_MPORT_DESC_V2_VNIC_CLIENT_TYPE_FUNCTION); 4081 EFX_STATIC_ASSERT(EFX_MPORT_VNIC_CLIENT_PLUGIN == 4082 MAE_MPORT_DESC_V2_VNIC_CLIENT_TYPE_PLUGIN); 4083 4084 if (cbp == NULL) { 4085 rc = EINVAL; 4086 goto fail1; 4087 } 4088 4089 req.emr_cmd = MC_CMD_MAE_MPORT_READ_JOURNAL; 4090 req.emr_in_buf = payload; 4091 req.emr_in_length = MC_CMD_MAE_MPORT_READ_JOURNAL_IN_LEN; 4092 req.emr_out_buf = payload; 4093 req.emr_out_length = MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMAX_MCDI2; 4094 4095 MCDI_IN_SET_DWORD(req, MAE_MPORT_READ_JOURNAL_IN_FLAGS, 0); 4096 4097 efx_mcdi_execute(enp, &req); 4098 4099 if (req.emr_rc != 0) { 4100 rc = req.emr_rc; 4101 goto fail2; 4102 } 4103 4104 if (req.emr_out_length_used < 4105 MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMIN) { 4106 rc = EMSGSIZE; 4107 goto fail3; 4108 } 4109 4110 if (morep != NULL) { 4111 *morep = MCDI_OUT_DWORD_FIELD(req, 4112 MAE_MPORT_READ_JOURNAL_OUT_FLAGS, 4113 MAE_MPORT_READ_JOURNAL_OUT_MORE); 4114 } 4115 n_entries = MCDI_OUT_DWORD(req, 4116 MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_COUNT); 4117 entry_sz = MCDI_OUT_DWORD(req, 4118 MAE_MPORT_READ_JOURNAL_OUT_SIZEOF_MPORT_DESC); 4119 entry_buf = MCDI_OUT2(req, uint8_t, 4120 MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_DATA); 4121 4122 if (entry_sz < MAE_MPORT_DESC_V2_VNIC_CLIENT_HANDLE_OFST + 4123 MAE_MPORT_DESC_V2_VNIC_CLIENT_HANDLE_LEN) { 4124 rc = EINVAL; 4125 goto fail4; 4126 } 4127 if (n_entries * entry_sz / entry_sz != n_entries) { 4128 rc = EINVAL; 4129 goto fail5; 4130 } 4131 if (req.emr_out_length_used != 4132 MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMIN + n_entries * entry_sz) { 4133 rc = EINVAL; 4134 goto fail6; 4135 } 4136 4137 for (i = 0; i < n_entries; i++) { 4138 efx_mport_desc_t desc; 4139 4140 rc = efx_mae_read_mport_journal_single(entry_buf, &desc); 4141 if (rc != 0) 4142 continue; 4143 4144 (*cbp)(cb_datap, &desc, sizeof (desc)); 4145 entry_buf += entry_sz; 4146 } 4147 4148 return (0); 4149 4150 fail6: 4151 EFSYS_PROBE(fail6); 4152 fail5: 4153 EFSYS_PROBE(fail5); 4154 fail4: 4155 EFSYS_PROBE(fail4); 4156 fail3: 4157 EFSYS_PROBE(fail3); 4158 fail2: 4159 EFSYS_PROBE(fail2); 4160 fail1: 4161 EFSYS_PROBE1(fail1, efx_rc_t, rc); 4162 return (rc); 4163 } 4164 4165 __checkReturn efx_rc_t 4166 efx_mae_read_mport_journal( 4167 __in efx_nic_t *enp, 4168 __in efx_mae_read_mport_journal_cb *cbp, 4169 __in void *cb_datap) 4170 { 4171 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 4172 uint32_t more = 0; 4173 efx_rc_t rc; 4174 4175 if (encp->enc_mae_supported == B_FALSE) { 4176 rc = ENOTSUP; 4177 goto fail1; 4178 } 4179 4180 do { 4181 rc = efx_mae_read_mport_journal_batch(enp, cbp, cb_datap, 4182 &more); 4183 if (rc != 0) 4184 goto fail2; 4185 } while (more != 0); 4186 4187 return (0); 4188 4189 fail2: 4190 EFSYS_PROBE(fail2); 4191 fail1: 4192 EFSYS_PROBE1(fail1, efx_rc_t, rc); 4193 return (rc); 4194 } 4195 4196 #endif /* EFSYS_OPT_MAE */ 4197