1 /* SPDX-License-Identifier: BSD-3-Clause 2 * 3 * Copyright(c) 2019-2021 Xilinx, Inc. 4 * Copyright(c) 2018-2019 Solarflare Communications Inc. 5 */ 6 7 #include "efx.h" 8 #include "efx_impl.h" 9 10 #if EFSYS_OPT_EVB 11 12 #if EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10() 13 14 __checkReturn efx_rc_t 15 ef10_evb_init( 16 __in efx_nic_t *enp) 17 { 18 EFSYS_ASSERT(EFX_FAMILY_IS_EF100(enp) || EFX_FAMILY_IS_EF10(enp)); 19 20 return (0); 21 } 22 23 void 24 ef10_evb_fini( 25 __in efx_nic_t *enp) 26 { 27 EFSYS_ASSERT(EFX_FAMILY_IS_EF100(enp) || EFX_FAMILY_IS_EF10(enp)); 28 } 29 30 static __checkReturn efx_rc_t 31 efx_mcdi_vswitch_alloc( 32 __in efx_nic_t *enp, 33 __in efx_vport_id_t vport_id, 34 __in efx_vswitch_type_t vswitch_type) 35 { 36 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VSWITCH_ALLOC_IN_LEN, 37 MC_CMD_VSWITCH_ALLOC_OUT_LEN); 38 efx_mcdi_req_t req; 39 efx_rc_t rc; 40 uint8_t ntags; 41 42 /* Ensure EFX and MCDI use same values for vswitch types */ 43 EFX_STATIC_ASSERT(EFX_VSWITCH_TYPE_VLAN == 44 MC_CMD_VSWITCH_ALLOC_IN_VSWITCH_TYPE_VLAN); 45 EFX_STATIC_ASSERT(EFX_VSWITCH_TYPE_VEB == 46 MC_CMD_VSWITCH_ALLOC_IN_VSWITCH_TYPE_VEB); 47 EFX_STATIC_ASSERT(EFX_VSWITCH_TYPE_MUX == 48 MC_CMD_VSWITCH_ALLOC_IN_VSWITCH_TYPE_MUX); 49 50 /* First try with maximum number of VLAN tags FW supports */ 51 ntags = 2; 52 retry: 53 req.emr_cmd = MC_CMD_VSWITCH_ALLOC; 54 req.emr_in_buf = payload; 55 req.emr_in_length = MC_CMD_VSWITCH_ALLOC_IN_LEN; 56 req.emr_out_buf = payload; 57 req.emr_out_length = MC_CMD_VSWITCH_ALLOC_OUT_LEN; 58 59 MCDI_IN_SET_DWORD(req, VSWITCH_ALLOC_IN_UPSTREAM_PORT_ID, vport_id); 60 MCDI_IN_SET_DWORD(req, VSWITCH_ALLOC_IN_TYPE, vswitch_type); 61 MCDI_IN_SET_DWORD(req, VSWITCH_ALLOC_IN_NUM_VLAN_TAGS, ntags); 62 MCDI_IN_POPULATE_DWORD_1(req, VSWITCH_ALLOC_IN_FLAGS, 63 VSWITCH_ALLOC_IN_FLAG_AUTO_PORT, 0); 64 65 efx_mcdi_execute(enp, &req); 66 67 if (req.emr_rc != 0) { 68 rc = req.emr_rc; 69 /* 70 * efx_rc_t error codes in libefx are translated from MCDI 71 * error codes in efx_mcdi_request_errcode. As this conversion 72 * is not a 1:1, here we check the specific MCDI error code. 73 */ 74 if (req.emr_err_code == MC_CMD_ERR_VLAN_LIMIT) { 75 /* Too many VLAN tags, retry with fewer */ 76 EFSYS_PROBE(vlan_limit); 77 ntags--; 78 if (ntags > 0) { 79 /* 80 * Zero the buffer before reusing it 81 * for another request 82 */ 83 memset(payload, 0, sizeof (payload)); 84 goto retry; 85 } 86 goto fail1; 87 } 88 } 89 90 return (0); 91 92 fail1: 93 EFSYS_PROBE1(fail1, efx_rc_t, rc); 94 return (rc); 95 } 96 97 static __checkReturn efx_rc_t 98 efx_mcdi_vswitch_free( 99 __in efx_nic_t *enp) 100 { 101 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VSWITCH_FREE_IN_LEN, 102 MC_CMD_VSWITCH_FREE_OUT_LEN); 103 efx_mcdi_req_t req; 104 efx_rc_t rc; 105 106 req.emr_cmd = MC_CMD_VSWITCH_FREE; 107 req.emr_in_buf = payload; 108 req.emr_in_length = MC_CMD_VSWITCH_FREE_IN_LEN; 109 req.emr_out_buf = payload; 110 req.emr_out_length = MC_CMD_VSWITCH_FREE_OUT_LEN; 111 112 MCDI_IN_SET_DWORD(req, VSWITCH_FREE_IN_UPSTREAM_PORT_ID, 113 EVB_PORT_ID_ASSIGNED); 114 efx_mcdi_execute(enp, &req); 115 116 if (req.emr_rc != 0) { 117 rc = req.emr_rc; 118 goto fail1; 119 } 120 121 return (0); 122 123 fail1: 124 EFSYS_PROBE1(fail1, efx_rc_t, rc); 125 return (rc); 126 } 127 128 static __checkReturn efx_rc_t 129 efx_mcdi_vport_alloc( 130 __in efx_nic_t *enp, 131 __in efx_vport_type_t vport_type, 132 __in uint16_t vid, 133 __in boolean_t vlan_restrict, 134 __out efx_vport_id_t *vport_idp) 135 { 136 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VPORT_ALLOC_IN_LEN, 137 MC_CMD_VPORT_ALLOC_OUT_LEN); 138 efx_mcdi_req_t req; 139 efx_rc_t rc; 140 141 /* Ensure EFX and MCDI use same values for vport types */ 142 EFX_STATIC_ASSERT(EFX_VPORT_TYPE_NORMAL == 143 MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL); 144 EFX_STATIC_ASSERT(EFX_VPORT_TYPE_EXPANSION == 145 MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_EXPANSION); 146 EFX_STATIC_ASSERT(EFX_VPORT_TYPE_TEST == 147 MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_TEST); 148 149 req.emr_cmd = MC_CMD_VPORT_ALLOC; 150 req.emr_in_buf = payload; 151 req.emr_in_length = MC_CMD_VPORT_ALLOC_IN_LEN; 152 req.emr_out_buf = payload; 153 req.emr_out_length = MC_CMD_VPORT_ALLOC_OUT_LEN; 154 155 MCDI_IN_SET_DWORD(req, VPORT_ALLOC_IN_UPSTREAM_PORT_ID, 156 EVB_PORT_ID_ASSIGNED); 157 MCDI_IN_SET_DWORD(req, VPORT_ALLOC_IN_TYPE, vport_type); 158 MCDI_IN_SET_DWORD(req, VPORT_ALLOC_IN_NUM_VLAN_TAGS, 159 (vid != EFX_FILTER_VID_UNSPEC)); 160 161 MCDI_IN_POPULATE_DWORD_2(req, VPORT_ALLOC_IN_FLAGS, 162 VPORT_ALLOC_IN_FLAG_AUTO_PORT, 0, 163 VPORT_ALLOC_IN_FLAG_VLAN_RESTRICT, vlan_restrict); 164 165 if (vid != EFX_FILTER_VID_UNSPEC) 166 MCDI_IN_POPULATE_DWORD_1(req, VPORT_ALLOC_IN_VLAN_TAGS, 167 VPORT_ALLOC_IN_VLAN_TAG_0, vid); 168 169 efx_mcdi_execute(enp, &req); 170 171 if (req.emr_rc != 0) { 172 rc = req.emr_rc; 173 goto fail1; 174 } 175 176 if (req.emr_out_length_used < MC_CMD_VPORT_ALLOC_OUT_LEN) { 177 rc = EMSGSIZE; 178 goto fail2; 179 } 180 181 *vport_idp = *MCDI_OUT2(req, uint32_t, VPORT_ALLOC_OUT_VPORT_ID); 182 return (0); 183 184 fail2: 185 EFSYS_PROBE(fail2); 186 fail1: 187 EFSYS_PROBE1(fail1, efx_rc_t, rc); 188 return (rc); 189 } 190 191 static __checkReturn efx_rc_t 192 efx_mcdi_vport_free( 193 __in efx_nic_t *enp, 194 __in efx_vport_id_t vport_id) 195 { 196 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VPORT_FREE_IN_LEN, 197 MC_CMD_VPORT_FREE_OUT_LEN); 198 efx_mcdi_req_t req; 199 efx_rc_t rc; 200 201 req.emr_cmd = MC_CMD_VPORT_FREE; 202 req.emr_in_buf = payload; 203 req.emr_in_length = MC_CMD_VPORT_FREE_IN_LEN; 204 req.emr_out_buf = payload; 205 req.emr_out_length = MC_CMD_VPORT_FREE_OUT_LEN; 206 207 MCDI_IN_SET_DWORD(req, VPORT_FREE_IN_VPORT_ID, vport_id); 208 efx_mcdi_execute(enp, &req); 209 210 if (req.emr_rc != 0) { 211 rc = req.emr_rc; 212 goto fail1; 213 } 214 215 return (0); 216 217 fail1: 218 EFSYS_PROBE1(fail1, efx_rc_t, rc); 219 return (rc); 220 } 221 222 static __checkReturn efx_rc_t 223 efx_mcdi_vport_mac_addr_add( 224 __in efx_nic_t *enp, 225 __in efx_vport_id_t vport_id, 226 __in_bcount(EFX_MAC_ADDR_LEN) uint8_t *addrp) 227 { 228 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN, 229 MC_CMD_VPORT_ADD_MAC_ADDRESS_OUT_LEN); 230 efx_mcdi_req_t req; 231 efx_rc_t rc; 232 233 req.emr_cmd = MC_CMD_VPORT_ADD_MAC_ADDRESS; 234 req.emr_in_buf = payload; 235 req.emr_in_length = MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN; 236 req.emr_out_buf = payload; 237 req.emr_out_length = MC_CMD_VPORT_ADD_MAC_ADDRESS_OUT_LEN; 238 239 MCDI_IN_SET_DWORD(req, VPORT_ADD_MAC_ADDRESS_IN_VPORT_ID, vport_id); 240 EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t, 241 VPORT_ADD_MAC_ADDRESS_IN_MACADDR), addrp); 242 243 efx_mcdi_execute(enp, &req); 244 245 if (req.emr_rc != 0) { 246 rc = req.emr_rc; 247 goto fail1; 248 } 249 250 return (0); 251 252 fail1: 253 EFSYS_PROBE1(fail1, efx_rc_t, rc); 254 return (rc); 255 } 256 257 static __checkReturn efx_rc_t 258 efx_mcdi_vport_mac_addr_del( 259 __in efx_nic_t *enp, 260 __in efx_vport_id_t vport_id, 261 __in_bcount(EFX_MAC_ADDR_LEN) uint8_t *addrp) 262 { 263 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN, 264 MC_CMD_VPORT_DEL_MAC_ADDRESS_OUT_LEN); 265 efx_mcdi_req_t req; 266 efx_rc_t rc; 267 268 req.emr_cmd = MC_CMD_VPORT_DEL_MAC_ADDRESS; 269 req.emr_in_buf = payload; 270 req.emr_in_length = MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN; 271 req.emr_out_buf = payload; 272 req.emr_out_length = MC_CMD_VPORT_DEL_MAC_ADDRESS_OUT_LEN; 273 274 MCDI_IN_SET_DWORD(req, VPORT_DEL_MAC_ADDRESS_IN_VPORT_ID, vport_id); 275 EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t, 276 VPORT_DEL_MAC_ADDRESS_IN_MACADDR), addrp); 277 278 efx_mcdi_execute(enp, &req); 279 280 if (req.emr_rc != 0) { 281 rc = req.emr_rc; 282 goto fail1; 283 } 284 285 return (0); 286 287 fail1: 288 EFSYS_PROBE1(fail1, efx_rc_t, rc); 289 return (rc); 290 } 291 292 static __checkReturn efx_rc_t 293 efx_mcdi_port_assign( 294 __in efx_nic_t *enp, 295 __in efx_vport_id_t vport_id, 296 __in uint32_t vf_index) 297 { 298 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_EVB_PORT_ASSIGN_IN_LEN, 299 MC_CMD_EVB_PORT_ASSIGN_OUT_LEN); 300 efx_mcdi_req_t req; 301 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 302 efx_rc_t rc; 303 304 req.emr_cmd = MC_CMD_EVB_PORT_ASSIGN; 305 req.emr_in_buf = payload; 306 req.emr_in_length = MC_CMD_EVB_PORT_ASSIGN_IN_LEN; 307 req.emr_out_buf = payload; 308 req.emr_out_length = MC_CMD_EVB_PORT_ASSIGN_OUT_LEN; 309 310 MCDI_IN_SET_DWORD(req, EVB_PORT_ASSIGN_IN_PORT_ID, vport_id); 311 MCDI_IN_POPULATE_DWORD_2(req, EVB_PORT_ASSIGN_IN_FUNCTION, 312 EVB_PORT_ASSIGN_IN_PF, encp->enc_pf, 313 EVB_PORT_ASSIGN_IN_VF, vf_index); 314 315 efx_mcdi_execute(enp, &req); 316 317 if (req.emr_rc != 0) { 318 rc = req.emr_rc; 319 goto fail1; 320 } 321 322 return (0); 323 324 fail1: 325 EFSYS_PROBE1(fail1, efx_rc_t, rc); 326 return (rc); 327 } 328 329 static __checkReturn efx_rc_t 330 efx_mcdi_vport_reconfigure( 331 __in efx_nic_t *enp, 332 __in efx_vport_id_t vport_id, 333 __in_opt uint16_t *vidp, 334 __in_bcount_opt(EFX_MAC_ADDR_LEN) uint8_t *addrp, 335 __out_opt boolean_t *fn_resetp) 336 { 337 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VPORT_RECONFIGURE_IN_LEN, 338 MC_CMD_VPORT_RECONFIGURE_OUT_LEN); 339 efx_mcdi_req_t req; 340 efx_rc_t rc; 341 uint32_t reset_flag = 0; 342 343 req.emr_cmd = MC_CMD_VPORT_RECONFIGURE; 344 req.emr_in_buf = payload; 345 req.emr_in_length = MC_CMD_VPORT_RECONFIGURE_IN_LEN; 346 req.emr_out_buf = payload; 347 req.emr_out_length = MC_CMD_VPORT_RECONFIGURE_OUT_LEN; 348 349 MCDI_IN_SET_DWORD(req, VPORT_RECONFIGURE_IN_VPORT_ID, vport_id); 350 351 if (vidp != NULL) { 352 MCDI_IN_POPULATE_DWORD_1(req, VPORT_RECONFIGURE_IN_FLAGS, 353 VPORT_RECONFIGURE_IN_REPLACE_VLAN_TAGS, 1); 354 if (*vidp != EFX_FILTER_VID_UNSPEC) { 355 MCDI_IN_SET_DWORD(req, 356 VPORT_RECONFIGURE_IN_NUM_VLAN_TAGS, 1); 357 MCDI_IN_POPULATE_DWORD_1(req, 358 VPORT_RECONFIGURE_IN_VLAN_TAGS, 359 VPORT_RECONFIGURE_IN_VLAN_TAG_0, *vidp); 360 } 361 } 362 363 if ((addrp != NULL) && (efx_is_zero_eth_addr(addrp) == B_FALSE)) { 364 MCDI_IN_POPULATE_DWORD_1(req, VPORT_RECONFIGURE_IN_FLAGS, 365 VPORT_RECONFIGURE_IN_REPLACE_MACADDRS, 1); 366 MCDI_IN_SET_DWORD(req, VPORT_RECONFIGURE_IN_NUM_MACADDRS, 1); 367 EFX_MAC_ADDR_COPY(MCDI_IN2(req, uint8_t, 368 VPORT_RECONFIGURE_IN_MACADDRS), addrp); 369 } 370 371 efx_mcdi_execute(enp, &req); 372 if (req.emr_rc != 0) { 373 rc = req.emr_rc; 374 goto fail1; 375 } 376 377 if (req.emr_out_length_used < MC_CMD_VPORT_RECONFIGURE_OUT_LEN) { 378 rc = EMSGSIZE; 379 goto fail2; 380 } 381 382 reset_flag = MCDI_OUT_DWORD_FIELD(req, VPORT_RECONFIGURE_OUT_FLAGS, 383 VPORT_RECONFIGURE_OUT_RESET_DONE); 384 385 if (fn_resetp != NULL) 386 *fn_resetp = (reset_flag != 0); 387 388 return (0); 389 390 fail2: 391 EFSYS_PROBE(fail2); 392 fail1: 393 EFSYS_PROBE1(fail1, efx_rc_t, rc); 394 return (rc); 395 } 396 397 __checkReturn efx_rc_t 398 ef10_evb_vswitch_alloc( 399 __in efx_nic_t *enp, 400 __out efx_vswitch_id_t *vswitch_idp) 401 { 402 efx_rc_t rc; 403 if (vswitch_idp == NULL) { 404 rc = EINVAL; 405 goto fail1; 406 } 407 408 if ((rc = efx_mcdi_vswitch_alloc(enp, EVB_PORT_ID_ASSIGNED, 409 EFX_VSWITCH_TYPE_VEB)) != 0) { 410 goto fail2; 411 } 412 413 *vswitch_idp = EFX_DEFAULT_VSWITCH_ID; 414 return (0); 415 416 fail2: 417 EFSYS_PROBE(fail2); 418 fail1: 419 EFSYS_PROBE1(fail1, efx_rc_t, rc); 420 return (rc); 421 } 422 423 __checkReturn efx_rc_t 424 ef10_evb_vswitch_free( 425 __in efx_nic_t *enp, 426 __in efx_vswitch_id_t vswitch_id) 427 { 428 _NOTE(ARGUNUSED(vswitch_id)) 429 430 return (efx_mcdi_vswitch_free(enp)); 431 } 432 433 __checkReturn efx_rc_t 434 ef10_evb_vport_alloc( 435 __in efx_nic_t *enp, 436 __in efx_vswitch_id_t vswitch_id, 437 __in efx_vport_type_t vport_type, 438 __in uint16_t vid, 439 __in boolean_t vlan_restrict, 440 __out efx_vport_id_t *vport_idp) 441 { 442 _NOTE(ARGUNUSED(vswitch_id)) 443 444 return (efx_mcdi_vport_alloc(enp, 445 vport_type, vid, 446 vlan_restrict, vport_idp)); 447 } 448 449 __checkReturn efx_rc_t 450 ef10_evb_vport_free( 451 __in efx_nic_t *enp, 452 __in efx_vswitch_id_t vswitch_id, 453 __in efx_vport_id_t vport_id) 454 { 455 _NOTE(ARGUNUSED(vswitch_id)) 456 457 return (efx_mcdi_vport_free(enp, vport_id)); 458 } 459 460 __checkReturn efx_rc_t 461 ef10_evb_vport_mac_addr_add( 462 __in efx_nic_t *enp, 463 __in efx_vswitch_id_t vswitch_id, 464 __in efx_vport_id_t vport_id, 465 __in_bcount(EFX_MAC_ADDR_LEN) uint8_t *addrp) 466 { 467 _NOTE(ARGUNUSED(vswitch_id)) 468 EFSYS_ASSERT(addrp != NULL); 469 470 return (efx_mcdi_vport_mac_addr_add(enp, vport_id, addrp)); 471 } 472 473 __checkReturn efx_rc_t 474 ef10_evb_vport_mac_addr_del( 475 __in efx_nic_t *enp, 476 __in efx_vswitch_id_t vswitch_id, 477 __in efx_vport_id_t vport_id, 478 __in_bcount(EFX_MAC_ADDR_LEN) uint8_t *addrp) 479 { 480 _NOTE(ARGUNUSED(vswitch_id)) 481 EFSYS_ASSERT(addrp != NULL); 482 483 return (efx_mcdi_vport_mac_addr_del(enp, vport_id, addrp)); 484 } 485 486 __checkReturn efx_rc_t 487 ef10_evb_vadaptor_alloc( 488 __in efx_nic_t *enp, 489 __in efx_vswitch_id_t vswitch_id, 490 __in efx_vport_id_t vport_id) 491 { 492 _NOTE(ARGUNUSED(vswitch_id)) 493 494 return (efx_mcdi_vadaptor_alloc(enp, vport_id)); 495 } 496 497 __checkReturn efx_rc_t 498 ef10_evb_vadaptor_free( 499 __in efx_nic_t *enp, 500 __in efx_vswitch_id_t vswitch_id, 501 __in efx_vport_id_t vport_id) 502 { 503 _NOTE(ARGUNUSED(vswitch_id)) 504 505 return (efx_mcdi_vadaptor_free(enp, vport_id)); 506 } 507 508 __checkReturn efx_rc_t 509 ef10_evb_vport_assign( 510 __in efx_nic_t *enp, 511 __in efx_vswitch_id_t vswitch_id, 512 __in efx_vport_id_t vport_id, 513 __in uint32_t vf_index) 514 { 515 _NOTE(ARGUNUSED(vswitch_id)) 516 517 return (efx_mcdi_port_assign(enp, vport_id, vf_index)); 518 } 519 520 __checkReturn efx_rc_t 521 ef10_evb_vport_reconfigure( 522 __in efx_nic_t *enp, 523 __in efx_vswitch_id_t vswitch_id, 524 __in efx_vport_id_t vport_id, 525 __in_opt uint16_t *vidp, 526 __in_bcount_opt(EFX_MAC_ADDR_LEN) uint8_t *addrp, 527 __out_opt boolean_t *fn_resetp) 528 { 529 _NOTE(ARGUNUSED(vswitch_id)) 530 531 return (efx_mcdi_vport_reconfigure(enp, vport_id, vidp, 532 addrp, fn_resetp)); 533 } 534 535 __checkReturn efx_rc_t 536 ef10_evb_vport_stats( 537 __in efx_nic_t *enp, 538 __in efx_vswitch_id_t vswitch_id, 539 __in efx_vport_id_t vport_id, 540 __in efsys_mem_t *esmp) 541 { 542 _NOTE(ARGUNUSED(vswitch_id)) 543 544 return (efx_mcdi_mac_stats(enp, vport_id, esmp, 545 EFX_STATS_UPLOAD, 0)); 546 } 547 548 #endif /* EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10() */ 549 #endif /* EFSYS_OPT_EVB */ 550