1 /*- 2 * Copyright (c) 2012-2016 Solarflare Communications Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * The views and conclusions contained in the software and documentation are 27 * those of the authors and should not be interpreted as representing official 28 * policies, either expressed or implied, of the FreeBSD Project. 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include "efx.h" 35 #include "efx_impl.h" 36 37 38 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 39 40 41 static __checkReturn efx_rc_t 42 efx_mcdi_init_rxq( 43 __in efx_nic_t *enp, 44 __in uint32_t ndescs, 45 __in uint32_t target_evq, 46 __in uint32_t label, 47 __in uint32_t instance, 48 __in efsys_mem_t *esmp, 49 __in boolean_t disable_scatter, 50 __in boolean_t want_inner_classes, 51 __in uint32_t ps_bufsize, 52 __in uint32_t es_bufs_per_desc, 53 __in uint32_t es_max_dma_len, 54 __in uint32_t es_buf_stride, 55 __in uint32_t hol_block_timeout) 56 { 57 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 58 efx_mcdi_req_t req; 59 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_INIT_RXQ_V3_IN_LEN, 60 MC_CMD_INIT_RXQ_V3_OUT_LEN); 61 int npages = EFX_RXQ_NBUFS(ndescs); 62 int i; 63 efx_qword_t *dma_addr; 64 uint64_t addr; 65 efx_rc_t rc; 66 uint32_t dma_mode; 67 boolean_t want_outer_classes; 68 69 EFSYS_ASSERT3U(ndescs, <=, EFX_RXQ_MAXNDESCS); 70 71 if ((esmp == NULL) || (EFSYS_MEM_SIZE(esmp) < EFX_RXQ_SIZE(ndescs))) { 72 rc = EINVAL; 73 goto fail1; 74 } 75 76 if (ps_bufsize > 0) 77 dma_mode = MC_CMD_INIT_RXQ_EXT_IN_PACKED_STREAM; 78 else if (es_bufs_per_desc > 0) 79 dma_mode = MC_CMD_INIT_RXQ_V3_IN_EQUAL_STRIDE_SUPER_BUFFER; 80 else 81 dma_mode = MC_CMD_INIT_RXQ_EXT_IN_SINGLE_PACKET; 82 83 if (encp->enc_tunnel_encapsulations_supported != 0 && 84 !want_inner_classes) { 85 /* 86 * WANT_OUTER_CLASSES can only be specified on hardware which 87 * supports tunnel encapsulation offloads, even though it is 88 * effectively the behaviour the hardware gives. 89 * 90 * Also, on hardware which does support such offloads, older 91 * firmware rejects the flag if the offloads are not supported 92 * by the current firmware variant, which means this may fail if 93 * the capabilities are not updated when the firmware variant 94 * changes. This is not an issue on newer firmware, as it was 95 * changed in bug 69842 (v6.4.2.1007) to permit this flag to be 96 * specified on all firmware variants. 97 */ 98 want_outer_classes = B_TRUE; 99 } else { 100 want_outer_classes = B_FALSE; 101 } 102 103 req.emr_cmd = MC_CMD_INIT_RXQ; 104 req.emr_in_buf = payload; 105 req.emr_in_length = MC_CMD_INIT_RXQ_V3_IN_LEN; 106 req.emr_out_buf = payload; 107 req.emr_out_length = MC_CMD_INIT_RXQ_V3_OUT_LEN; 108 109 MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_SIZE, ndescs); 110 MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_TARGET_EVQ, target_evq); 111 MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_LABEL, label); 112 MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_INSTANCE, instance); 113 MCDI_IN_POPULATE_DWORD_9(req, INIT_RXQ_EXT_IN_FLAGS, 114 INIT_RXQ_EXT_IN_FLAG_BUFF_MODE, 0, 115 INIT_RXQ_EXT_IN_FLAG_HDR_SPLIT, 0, 116 INIT_RXQ_EXT_IN_FLAG_TIMESTAMP, 0, 117 INIT_RXQ_EXT_IN_CRC_MODE, 0, 118 INIT_RXQ_EXT_IN_FLAG_PREFIX, 1, 119 INIT_RXQ_EXT_IN_FLAG_DISABLE_SCATTER, disable_scatter, 120 INIT_RXQ_EXT_IN_DMA_MODE, 121 dma_mode, 122 INIT_RXQ_EXT_IN_PACKED_STREAM_BUFF_SIZE, ps_bufsize, 123 INIT_RXQ_EXT_IN_FLAG_WANT_OUTER_CLASSES, want_outer_classes); 124 MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_OWNER_ID, 0); 125 MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_PORT_ID, EVB_PORT_ID_ASSIGNED); 126 127 if (es_bufs_per_desc > 0) { 128 MCDI_IN_SET_DWORD(req, 129 INIT_RXQ_V3_IN_ES_PACKET_BUFFERS_PER_BUCKET, 130 es_bufs_per_desc); 131 MCDI_IN_SET_DWORD(req, 132 INIT_RXQ_V3_IN_ES_MAX_DMA_LEN, es_max_dma_len); 133 MCDI_IN_SET_DWORD(req, 134 INIT_RXQ_V3_IN_ES_PACKET_STRIDE, es_buf_stride); 135 MCDI_IN_SET_DWORD(req, 136 INIT_RXQ_V3_IN_ES_HEAD_OF_LINE_BLOCK_TIMEOUT, 137 hol_block_timeout); 138 } 139 140 dma_addr = MCDI_IN2(req, efx_qword_t, INIT_RXQ_IN_DMA_ADDR); 141 addr = EFSYS_MEM_ADDR(esmp); 142 143 for (i = 0; i < npages; i++) { 144 EFX_POPULATE_QWORD_2(*dma_addr, 145 EFX_DWORD_1, (uint32_t)(addr >> 32), 146 EFX_DWORD_0, (uint32_t)(addr & 0xffffffff)); 147 148 dma_addr++; 149 addr += EFX_BUF_SIZE; 150 } 151 152 efx_mcdi_execute(enp, &req); 153 154 if (req.emr_rc != 0) { 155 rc = req.emr_rc; 156 goto fail2; 157 } 158 159 return (0); 160 161 fail2: 162 EFSYS_PROBE(fail2); 163 fail1: 164 EFSYS_PROBE1(fail1, efx_rc_t, rc); 165 166 return (rc); 167 } 168 169 static __checkReturn efx_rc_t 170 efx_mcdi_fini_rxq( 171 __in efx_nic_t *enp, 172 __in uint32_t instance) 173 { 174 efx_mcdi_req_t req; 175 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FINI_RXQ_IN_LEN, 176 MC_CMD_FINI_RXQ_OUT_LEN); 177 efx_rc_t rc; 178 179 req.emr_cmd = MC_CMD_FINI_RXQ; 180 req.emr_in_buf = payload; 181 req.emr_in_length = MC_CMD_FINI_RXQ_IN_LEN; 182 req.emr_out_buf = payload; 183 req.emr_out_length = MC_CMD_FINI_RXQ_OUT_LEN; 184 185 MCDI_IN_SET_DWORD(req, FINI_RXQ_IN_INSTANCE, instance); 186 187 efx_mcdi_execute_quiet(enp, &req); 188 189 if (req.emr_rc != 0) { 190 rc = req.emr_rc; 191 goto fail1; 192 } 193 194 return (0); 195 196 fail1: 197 /* 198 * EALREADY is not an error, but indicates that the MC has rebooted and 199 * that the RXQ has already been destroyed. 200 */ 201 if (rc != EALREADY) 202 EFSYS_PROBE1(fail1, efx_rc_t, rc); 203 204 return (rc); 205 } 206 207 #if EFSYS_OPT_RX_SCALE 208 static __checkReturn efx_rc_t 209 efx_mcdi_rss_context_alloc( 210 __in efx_nic_t *enp, 211 __in efx_rx_scale_context_type_t type, 212 __in uint32_t num_queues, 213 __out uint32_t *rss_contextp) 214 { 215 efx_mcdi_req_t req; 216 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN, 217 MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN); 218 uint32_t rss_context; 219 uint32_t context_type; 220 efx_rc_t rc; 221 222 if (num_queues > EFX_MAXRSS) { 223 rc = EINVAL; 224 goto fail1; 225 } 226 227 switch (type) { 228 case EFX_RX_SCALE_EXCLUSIVE: 229 context_type = MC_CMD_RSS_CONTEXT_ALLOC_IN_TYPE_EXCLUSIVE; 230 break; 231 case EFX_RX_SCALE_SHARED: 232 context_type = MC_CMD_RSS_CONTEXT_ALLOC_IN_TYPE_SHARED; 233 break; 234 default: 235 rc = EINVAL; 236 goto fail2; 237 } 238 239 req.emr_cmd = MC_CMD_RSS_CONTEXT_ALLOC; 240 req.emr_in_buf = payload; 241 req.emr_in_length = MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN; 242 req.emr_out_buf = payload; 243 req.emr_out_length = MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN; 244 245 MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_UPSTREAM_PORT_ID, 246 EVB_PORT_ID_ASSIGNED); 247 MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_TYPE, context_type); 248 249 /* 250 * For exclusive contexts, NUM_QUEUES is only used to validate 251 * indirection table offsets. 252 * For shared contexts, the provided context will spread traffic over 253 * NUM_QUEUES many queues. 254 */ 255 MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_NUM_QUEUES, num_queues); 256 257 efx_mcdi_execute(enp, &req); 258 259 if (req.emr_rc != 0) { 260 rc = req.emr_rc; 261 goto fail3; 262 } 263 264 if (req.emr_out_length_used < MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN) { 265 rc = EMSGSIZE; 266 goto fail4; 267 } 268 269 rss_context = MCDI_OUT_DWORD(req, RSS_CONTEXT_ALLOC_OUT_RSS_CONTEXT_ID); 270 if (rss_context == EF10_RSS_CONTEXT_INVALID) { 271 rc = ENOENT; 272 goto fail5; 273 } 274 275 *rss_contextp = rss_context; 276 277 return (0); 278 279 fail5: 280 EFSYS_PROBE(fail5); 281 fail4: 282 EFSYS_PROBE(fail4); 283 fail3: 284 EFSYS_PROBE(fail3); 285 fail2: 286 EFSYS_PROBE(fail2); 287 fail1: 288 EFSYS_PROBE1(fail1, efx_rc_t, rc); 289 290 return (rc); 291 } 292 #endif /* EFSYS_OPT_RX_SCALE */ 293 294 #if EFSYS_OPT_RX_SCALE 295 static efx_rc_t 296 efx_mcdi_rss_context_free( 297 __in efx_nic_t *enp, 298 __in uint32_t rss_context) 299 { 300 efx_mcdi_req_t req; 301 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_FREE_IN_LEN, 302 MC_CMD_RSS_CONTEXT_FREE_OUT_LEN); 303 efx_rc_t rc; 304 305 if (rss_context == EF10_RSS_CONTEXT_INVALID) { 306 rc = EINVAL; 307 goto fail1; 308 } 309 310 req.emr_cmd = MC_CMD_RSS_CONTEXT_FREE; 311 req.emr_in_buf = payload; 312 req.emr_in_length = MC_CMD_RSS_CONTEXT_FREE_IN_LEN; 313 req.emr_out_buf = payload; 314 req.emr_out_length = MC_CMD_RSS_CONTEXT_FREE_OUT_LEN; 315 316 MCDI_IN_SET_DWORD(req, RSS_CONTEXT_FREE_IN_RSS_CONTEXT_ID, rss_context); 317 318 efx_mcdi_execute_quiet(enp, &req); 319 320 if (req.emr_rc != 0) { 321 rc = req.emr_rc; 322 goto fail2; 323 } 324 325 return (0); 326 327 fail2: 328 EFSYS_PROBE(fail2); 329 fail1: 330 EFSYS_PROBE1(fail1, efx_rc_t, rc); 331 332 return (rc); 333 } 334 #endif /* EFSYS_OPT_RX_SCALE */ 335 336 #if EFSYS_OPT_RX_SCALE 337 static efx_rc_t 338 efx_mcdi_rss_context_set_flags( 339 __in efx_nic_t *enp, 340 __in uint32_t rss_context, 341 __in efx_rx_hash_type_t type) 342 { 343 efx_nic_cfg_t *encp = &enp->en_nic_cfg; 344 efx_mcdi_req_t req; 345 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN, 346 MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN); 347 efx_rc_t rc; 348 349 EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_TCP_LBN == 350 MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE_LBN); 351 EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_TCP_WIDTH == 352 MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE_WIDTH); 353 EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_LBN == 354 MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE_LBN); 355 EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_WIDTH == 356 MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE_WIDTH); 357 EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_TCP_LBN == 358 MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE_LBN); 359 EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_TCP_WIDTH == 360 MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE_WIDTH); 361 EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_LBN == 362 MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE_LBN); 363 EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_WIDTH == 364 MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE_WIDTH); 365 366 if (rss_context == EF10_RSS_CONTEXT_INVALID) { 367 rc = EINVAL; 368 goto fail1; 369 } 370 371 req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_FLAGS; 372 req.emr_in_buf = payload; 373 req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN; 374 req.emr_out_buf = payload; 375 req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN; 376 377 MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_FLAGS_IN_RSS_CONTEXT_ID, 378 rss_context); 379 380 /* 381 * If the firmware lacks support for additional modes, RSS_MODE 382 * fields must contain zeros, otherwise the operation will fail. 383 */ 384 if (encp->enc_rx_scale_additional_modes_supported == B_FALSE) 385 type &= EFX_RX_HASH_LEGACY_MASK; 386 387 MCDI_IN_POPULATE_DWORD_10(req, RSS_CONTEXT_SET_FLAGS_IN_FLAGS, 388 RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV4_EN, 389 (type & EFX_RX_HASH_IPV4) ? 1 : 0, 390 RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV4_EN, 391 (type & EFX_RX_HASH_TCPIPV4) ? 1 : 0, 392 RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV6_EN, 393 (type & EFX_RX_HASH_IPV6) ? 1 : 0, 394 RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV6_EN, 395 (type & EFX_RX_HASH_TCPIPV6) ? 1 : 0, 396 RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE, 397 (type >> EFX_RX_CLASS_IPV4_TCP_LBN) & 398 EFX_MASK32(EFX_RX_CLASS_IPV4_TCP), 399 RSS_CONTEXT_SET_FLAGS_IN_UDP_IPV4_RSS_MODE, 400 (type >> EFX_RX_CLASS_IPV4_UDP_LBN) & 401 EFX_MASK32(EFX_RX_CLASS_IPV4_UDP), 402 RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE, 403 (type >> EFX_RX_CLASS_IPV4_LBN) & EFX_MASK32(EFX_RX_CLASS_IPV4), 404 RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE, 405 (type >> EFX_RX_CLASS_IPV6_TCP_LBN) & 406 EFX_MASK32(EFX_RX_CLASS_IPV6_TCP), 407 RSS_CONTEXT_SET_FLAGS_IN_UDP_IPV6_RSS_MODE, 408 (type >> EFX_RX_CLASS_IPV6_UDP_LBN) & 409 EFX_MASK32(EFX_RX_CLASS_IPV6_UDP), 410 RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE, 411 (type >> EFX_RX_CLASS_IPV6_LBN) & EFX_MASK32(EFX_RX_CLASS_IPV6)); 412 413 efx_mcdi_execute(enp, &req); 414 415 if (req.emr_rc != 0) { 416 rc = req.emr_rc; 417 goto fail2; 418 } 419 420 return (0); 421 422 fail2: 423 EFSYS_PROBE(fail2); 424 fail1: 425 EFSYS_PROBE1(fail1, efx_rc_t, rc); 426 427 return (rc); 428 } 429 #endif /* EFSYS_OPT_RX_SCALE */ 430 431 #if EFSYS_OPT_RX_SCALE 432 static efx_rc_t 433 efx_mcdi_rss_context_set_key( 434 __in efx_nic_t *enp, 435 __in uint32_t rss_context, 436 __in_ecount(n) uint8_t *key, 437 __in size_t n) 438 { 439 efx_mcdi_req_t req; 440 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_SET_KEY_IN_LEN, 441 MC_CMD_RSS_CONTEXT_SET_KEY_OUT_LEN); 442 efx_rc_t rc; 443 444 if (rss_context == EF10_RSS_CONTEXT_INVALID) { 445 rc = EINVAL; 446 goto fail1; 447 } 448 449 req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_KEY; 450 req.emr_in_buf = payload; 451 req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_KEY_IN_LEN; 452 req.emr_out_buf = payload; 453 req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_KEY_OUT_LEN; 454 455 MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_KEY_IN_RSS_CONTEXT_ID, 456 rss_context); 457 458 EFSYS_ASSERT3U(n, ==, MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN); 459 if (n != MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN) { 460 rc = EINVAL; 461 goto fail2; 462 } 463 464 memcpy(MCDI_IN2(req, uint8_t, RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY), 465 key, n); 466 467 efx_mcdi_execute(enp, &req); 468 469 if (req.emr_rc != 0) { 470 rc = req.emr_rc; 471 goto fail3; 472 } 473 474 return (0); 475 476 fail3: 477 EFSYS_PROBE(fail3); 478 fail2: 479 EFSYS_PROBE(fail2); 480 fail1: 481 EFSYS_PROBE1(fail1, efx_rc_t, rc); 482 483 return (rc); 484 } 485 #endif /* EFSYS_OPT_RX_SCALE */ 486 487 #if EFSYS_OPT_RX_SCALE 488 static efx_rc_t 489 efx_mcdi_rss_context_set_table( 490 __in efx_nic_t *enp, 491 __in uint32_t rss_context, 492 __in_ecount(n) unsigned int *table, 493 __in size_t n) 494 { 495 efx_mcdi_req_t req; 496 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_SET_TABLE_IN_LEN, 497 MC_CMD_RSS_CONTEXT_SET_TABLE_OUT_LEN); 498 uint8_t *req_table; 499 int i, rc; 500 501 if (rss_context == EF10_RSS_CONTEXT_INVALID) { 502 rc = EINVAL; 503 goto fail1; 504 } 505 506 req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_TABLE; 507 req.emr_in_buf = payload; 508 req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_TABLE_IN_LEN; 509 req.emr_out_buf = payload; 510 req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_TABLE_OUT_LEN; 511 512 MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_TABLE_IN_RSS_CONTEXT_ID, 513 rss_context); 514 515 req_table = 516 MCDI_IN2(req, uint8_t, RSS_CONTEXT_SET_TABLE_IN_INDIRECTION_TABLE); 517 518 for (i = 0; 519 i < MC_CMD_RSS_CONTEXT_SET_TABLE_IN_INDIRECTION_TABLE_LEN; 520 i++) { 521 req_table[i] = (n > 0) ? (uint8_t)table[i % n] : 0; 522 } 523 524 efx_mcdi_execute(enp, &req); 525 526 if (req.emr_rc != 0) { 527 rc = req.emr_rc; 528 goto fail2; 529 } 530 531 return (0); 532 533 fail2: 534 EFSYS_PROBE(fail2); 535 fail1: 536 EFSYS_PROBE1(fail1, efx_rc_t, rc); 537 538 return (rc); 539 } 540 #endif /* EFSYS_OPT_RX_SCALE */ 541 542 543 __checkReturn efx_rc_t 544 ef10_rx_init( 545 __in efx_nic_t *enp) 546 { 547 #if EFSYS_OPT_RX_SCALE 548 549 if (efx_mcdi_rss_context_alloc(enp, EFX_RX_SCALE_EXCLUSIVE, EFX_MAXRSS, 550 &enp->en_rss_context) == 0) { 551 /* 552 * Allocated an exclusive RSS context, which allows both the 553 * indirection table and key to be modified. 554 */ 555 enp->en_rss_context_type = EFX_RX_SCALE_EXCLUSIVE; 556 enp->en_hash_support = EFX_RX_HASH_AVAILABLE; 557 } else { 558 /* 559 * Failed to allocate an exclusive RSS context. Continue 560 * operation without support for RSS. The pseudo-header in 561 * received packets will not contain a Toeplitz hash value. 562 */ 563 enp->en_rss_context_type = EFX_RX_SCALE_UNAVAILABLE; 564 enp->en_hash_support = EFX_RX_HASH_UNAVAILABLE; 565 } 566 567 #endif /* EFSYS_OPT_RX_SCALE */ 568 569 return (0); 570 } 571 572 #if EFSYS_OPT_RX_SCATTER 573 __checkReturn efx_rc_t 574 ef10_rx_scatter_enable( 575 __in efx_nic_t *enp, 576 __in unsigned int buf_size) 577 { 578 _NOTE(ARGUNUSED(enp, buf_size)) 579 return (0); 580 } 581 #endif /* EFSYS_OPT_RX_SCATTER */ 582 583 #if EFSYS_OPT_RX_SCALE 584 __checkReturn efx_rc_t 585 ef10_rx_scale_context_alloc( 586 __in efx_nic_t *enp, 587 __in efx_rx_scale_context_type_t type, 588 __in uint32_t num_queues, 589 __out uint32_t *rss_contextp) 590 { 591 efx_rc_t rc; 592 593 rc = efx_mcdi_rss_context_alloc(enp, type, num_queues, rss_contextp); 594 if (rc != 0) 595 goto fail1; 596 597 return (0); 598 599 fail1: 600 EFSYS_PROBE1(fail1, efx_rc_t, rc); 601 return (rc); 602 } 603 #endif /* EFSYS_OPT_RX_SCALE */ 604 605 #if EFSYS_OPT_RX_SCALE 606 __checkReturn efx_rc_t 607 ef10_rx_scale_context_free( 608 __in efx_nic_t *enp, 609 __in uint32_t rss_context) 610 { 611 efx_rc_t rc; 612 613 rc = efx_mcdi_rss_context_free(enp, rss_context); 614 if (rc != 0) 615 goto fail1; 616 617 return (0); 618 619 fail1: 620 EFSYS_PROBE1(fail1, efx_rc_t, rc); 621 return (rc); 622 } 623 #endif /* EFSYS_OPT_RX_SCALE */ 624 625 #if EFSYS_OPT_RX_SCALE 626 __checkReturn efx_rc_t 627 ef10_rx_scale_mode_set( 628 __in efx_nic_t *enp, 629 __in uint32_t rss_context, 630 __in efx_rx_hash_alg_t alg, 631 __in efx_rx_hash_type_t type, 632 __in boolean_t insert) 633 { 634 efx_nic_cfg_t *encp = &enp->en_nic_cfg; 635 efx_rc_t rc; 636 637 EFSYS_ASSERT3U(insert, ==, B_TRUE); 638 639 if ((encp->enc_rx_scale_hash_alg_mask & (1U << alg)) == 0 || 640 insert == B_FALSE) { 641 rc = EINVAL; 642 goto fail1; 643 } 644 645 if (rss_context == EFX_RSS_CONTEXT_DEFAULT) { 646 if (enp->en_rss_context_type == EFX_RX_SCALE_UNAVAILABLE) { 647 rc = ENOTSUP; 648 goto fail2; 649 } 650 rss_context = enp->en_rss_context; 651 } 652 653 if ((rc = efx_mcdi_rss_context_set_flags(enp, 654 rss_context, type)) != 0) 655 goto fail3; 656 657 return (0); 658 659 fail3: 660 EFSYS_PROBE(fail3); 661 fail2: 662 EFSYS_PROBE(fail2); 663 fail1: 664 EFSYS_PROBE1(fail1, efx_rc_t, rc); 665 666 return (rc); 667 } 668 #endif /* EFSYS_OPT_RX_SCALE */ 669 670 #if EFSYS_OPT_RX_SCALE 671 __checkReturn efx_rc_t 672 ef10_rx_scale_key_set( 673 __in efx_nic_t *enp, 674 __in uint32_t rss_context, 675 __in_ecount(n) uint8_t *key, 676 __in size_t n) 677 { 678 efx_rc_t rc; 679 680 EFX_STATIC_ASSERT(EFX_RSS_KEY_SIZE == 681 MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN); 682 683 if (rss_context == EFX_RSS_CONTEXT_DEFAULT) { 684 if (enp->en_rss_context_type == EFX_RX_SCALE_UNAVAILABLE) { 685 rc = ENOTSUP; 686 goto fail1; 687 } 688 rss_context = enp->en_rss_context; 689 } 690 691 if ((rc = efx_mcdi_rss_context_set_key(enp, rss_context, key, n)) != 0) 692 goto fail2; 693 694 return (0); 695 696 fail2: 697 EFSYS_PROBE(fail2); 698 fail1: 699 EFSYS_PROBE1(fail1, efx_rc_t, rc); 700 701 return (rc); 702 } 703 #endif /* EFSYS_OPT_RX_SCALE */ 704 705 #if EFSYS_OPT_RX_SCALE 706 __checkReturn efx_rc_t 707 ef10_rx_scale_tbl_set( 708 __in efx_nic_t *enp, 709 __in uint32_t rss_context, 710 __in_ecount(n) unsigned int *table, 711 __in size_t n) 712 { 713 efx_rc_t rc; 714 715 716 if (rss_context == EFX_RSS_CONTEXT_DEFAULT) { 717 if (enp->en_rss_context_type == EFX_RX_SCALE_UNAVAILABLE) { 718 rc = ENOTSUP; 719 goto fail1; 720 } 721 rss_context = enp->en_rss_context; 722 } 723 724 if ((rc = efx_mcdi_rss_context_set_table(enp, 725 rss_context, table, n)) != 0) 726 goto fail2; 727 728 return (0); 729 730 fail2: 731 EFSYS_PROBE(fail2); 732 fail1: 733 EFSYS_PROBE1(fail1, efx_rc_t, rc); 734 735 return (rc); 736 } 737 #endif /* EFSYS_OPT_RX_SCALE */ 738 739 740 /* 741 * EF10 RX pseudo-header 742 * --------------------- 743 * 744 * Receive packets are prefixed by an (optional) 14 byte pseudo-header: 745 * 746 * +00: Toeplitz hash value. 747 * (32bit little-endian) 748 * +04: Outer VLAN tag. Zero if the packet did not have an outer VLAN tag. 749 * (16bit big-endian) 750 * +06: Inner VLAN tag. Zero if the packet did not have an inner VLAN tag. 751 * (16bit big-endian) 752 * +08: Packet Length. Zero if the RX datapath was in cut-through mode. 753 * (16bit little-endian) 754 * +10: MAC timestamp. Zero if timestamping is not enabled. 755 * (32bit little-endian) 756 * 757 * See "The RX Pseudo-header" in SF-109306-TC. 758 */ 759 760 __checkReturn efx_rc_t 761 ef10_rx_prefix_pktlen( 762 __in efx_nic_t *enp, 763 __in uint8_t *buffer, 764 __out uint16_t *lengthp) 765 { 766 _NOTE(ARGUNUSED(enp)) 767 768 /* 769 * The RX pseudo-header contains the packet length, excluding the 770 * pseudo-header. If the hardware receive datapath was operating in 771 * cut-through mode then the length in the RX pseudo-header will be 772 * zero, and the packet length must be obtained from the DMA length 773 * reported in the RX event. 774 */ 775 *lengthp = buffer[8] | (buffer[9] << 8); 776 return (0); 777 } 778 779 #if EFSYS_OPT_RX_SCALE 780 __checkReturn uint32_t 781 ef10_rx_prefix_hash( 782 __in efx_nic_t *enp, 783 __in efx_rx_hash_alg_t func, 784 __in uint8_t *buffer) 785 { 786 _NOTE(ARGUNUSED(enp)) 787 788 switch (func) { 789 case EFX_RX_HASHALG_PACKED_STREAM: 790 case EFX_RX_HASHALG_TOEPLITZ: 791 return (buffer[0] | 792 (buffer[1] << 8) | 793 (buffer[2] << 16) | 794 (buffer[3] << 24)); 795 796 default: 797 EFSYS_ASSERT(0); 798 return (0); 799 } 800 } 801 #endif /* EFSYS_OPT_RX_SCALE */ 802 803 #if EFSYS_OPT_RX_PACKED_STREAM 804 /* 805 * Fake length for RXQ descriptors in packed stream mode 806 * to make hardware happy 807 */ 808 #define EFX_RXQ_PACKED_STREAM_FAKE_BUF_SIZE 32 809 #endif 810 811 void 812 ef10_rx_qpost( 813 __in efx_rxq_t *erp, 814 __in_ecount(ndescs) efsys_dma_addr_t *addrp, 815 __in size_t size, 816 __in unsigned int ndescs, 817 __in unsigned int completed, 818 __in unsigned int added) 819 { 820 efx_qword_t qword; 821 unsigned int i; 822 unsigned int offset; 823 unsigned int id; 824 825 _NOTE(ARGUNUSED(completed)) 826 827 #if EFSYS_OPT_RX_PACKED_STREAM 828 /* 829 * Real size of the buffer does not fit into ESF_DZ_RX_KER_BYTE_CNT 830 * and equal to 0 after applying mask. Hardware does not like it. 831 */ 832 if (erp->er_ev_qstate->eers_rx_packed_stream) 833 size = EFX_RXQ_PACKED_STREAM_FAKE_BUF_SIZE; 834 #endif 835 836 /* The client driver must not overfill the queue */ 837 EFSYS_ASSERT3U(added - completed + ndescs, <=, 838 EFX_RXQ_LIMIT(erp->er_mask + 1)); 839 840 id = added & (erp->er_mask); 841 for (i = 0; i < ndescs; i++) { 842 EFSYS_PROBE4(rx_post, unsigned int, erp->er_index, 843 unsigned int, id, efsys_dma_addr_t, addrp[i], 844 size_t, size); 845 846 EFX_POPULATE_QWORD_3(qword, 847 ESF_DZ_RX_KER_BYTE_CNT, (uint32_t)(size), 848 ESF_DZ_RX_KER_BUF_ADDR_DW0, 849 (uint32_t)(addrp[i] & 0xffffffff), 850 ESF_DZ_RX_KER_BUF_ADDR_DW1, 851 (uint32_t)(addrp[i] >> 32)); 852 853 offset = id * sizeof (efx_qword_t); 854 EFSYS_MEM_WRITEQ(erp->er_esmp, offset, &qword); 855 856 id = (id + 1) & (erp->er_mask); 857 } 858 } 859 860 void 861 ef10_rx_qpush( 862 __in efx_rxq_t *erp, 863 __in unsigned int added, 864 __inout unsigned int *pushedp) 865 { 866 efx_nic_t *enp = erp->er_enp; 867 unsigned int pushed = *pushedp; 868 uint32_t wptr; 869 efx_dword_t dword; 870 871 /* Hardware has alignment restriction for WPTR */ 872 wptr = EFX_P2ALIGN(unsigned int, added, EF10_RX_WPTR_ALIGN); 873 if (pushed == wptr) 874 return; 875 876 *pushedp = wptr; 877 878 /* Push the populated descriptors out */ 879 wptr &= erp->er_mask; 880 881 EFX_POPULATE_DWORD_1(dword, ERF_DZ_RX_DESC_WPTR, wptr); 882 883 /* Guarantee ordering of memory (descriptors) and PIO (doorbell) */ 884 EFX_DMA_SYNC_QUEUE_FOR_DEVICE(erp->er_esmp, erp->er_mask + 1, 885 wptr, pushed & erp->er_mask); 886 EFSYS_PIO_WRITE_BARRIER(); 887 EFX_BAR_VI_WRITED(enp, ER_DZ_RX_DESC_UPD_REG, 888 erp->er_index, &dword, B_FALSE); 889 } 890 891 #if EFSYS_OPT_RX_PACKED_STREAM 892 893 void 894 ef10_rx_qpush_ps_credits( 895 __in efx_rxq_t *erp) 896 { 897 efx_nic_t *enp = erp->er_enp; 898 efx_dword_t dword; 899 efx_evq_rxq_state_t *rxq_state = erp->er_ev_qstate; 900 uint32_t credits; 901 902 EFSYS_ASSERT(rxq_state->eers_rx_packed_stream); 903 904 if (rxq_state->eers_rx_packed_stream_credits == 0) 905 return; 906 907 /* 908 * It is a bug if we think that FW has utilized more 909 * credits than it is allowed to have (maximum). However, 910 * make sure that we do not credit more than maximum anyway. 911 */ 912 credits = MIN(rxq_state->eers_rx_packed_stream_credits, 913 EFX_RX_PACKED_STREAM_MAX_CREDITS); 914 EFX_POPULATE_DWORD_3(dword, 915 ERF_DZ_RX_DESC_MAGIC_DOORBELL, 1, 916 ERF_DZ_RX_DESC_MAGIC_CMD, 917 ERE_DZ_RX_DESC_MAGIC_CMD_PS_CREDITS, 918 ERF_DZ_RX_DESC_MAGIC_DATA, credits); 919 EFX_BAR_VI_WRITED(enp, ER_DZ_RX_DESC_UPD_REG, 920 erp->er_index, &dword, B_FALSE); 921 922 rxq_state->eers_rx_packed_stream_credits = 0; 923 } 924 925 /* 926 * In accordance with SF-112241-TC the received data has the following layout: 927 * - 8 byte pseudo-header which consist of: 928 * - 4 byte little-endian timestamp 929 * - 2 byte little-endian captured length in bytes 930 * - 2 byte little-endian original packet length in bytes 931 * - captured packet bytes 932 * - optional padding to align to 64 bytes boundary 933 * - 64 bytes scratch space for the host software 934 */ 935 __checkReturn uint8_t * 936 ef10_rx_qps_packet_info( 937 __in efx_rxq_t *erp, 938 __in uint8_t *buffer, 939 __in uint32_t buffer_length, 940 __in uint32_t current_offset, 941 __out uint16_t *lengthp, 942 __out uint32_t *next_offsetp, 943 __out uint32_t *timestamp) 944 { 945 uint16_t buf_len; 946 uint8_t *pkt_start; 947 efx_qword_t *qwordp; 948 efx_evq_rxq_state_t *rxq_state = erp->er_ev_qstate; 949 950 EFSYS_ASSERT(rxq_state->eers_rx_packed_stream); 951 952 buffer += current_offset; 953 pkt_start = buffer + EFX_RX_PACKED_STREAM_RX_PREFIX_SIZE; 954 955 qwordp = (efx_qword_t *)buffer; 956 *timestamp = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_TSTAMP); 957 *lengthp = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_ORIG_LEN); 958 buf_len = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_CAP_LEN); 959 960 buf_len = EFX_P2ROUNDUP(uint16_t, 961 buf_len + EFX_RX_PACKED_STREAM_RX_PREFIX_SIZE, 962 EFX_RX_PACKED_STREAM_ALIGNMENT); 963 *next_offsetp = 964 current_offset + buf_len + EFX_RX_PACKED_STREAM_ALIGNMENT; 965 966 EFSYS_ASSERT3U(*next_offsetp, <=, buffer_length); 967 EFSYS_ASSERT3U(current_offset + *lengthp, <, *next_offsetp); 968 969 if ((*next_offsetp ^ current_offset) & 970 EFX_RX_PACKED_STREAM_MEM_PER_CREDIT) 971 rxq_state->eers_rx_packed_stream_credits++; 972 973 return (pkt_start); 974 } 975 976 977 #endif 978 979 __checkReturn efx_rc_t 980 ef10_rx_qflush( 981 __in efx_rxq_t *erp) 982 { 983 efx_nic_t *enp = erp->er_enp; 984 efx_rc_t rc; 985 986 if ((rc = efx_mcdi_fini_rxq(enp, erp->er_index)) != 0) 987 goto fail1; 988 989 return (0); 990 991 fail1: 992 /* 993 * EALREADY is not an error, but indicates that the MC has rebooted and 994 * that the RXQ has already been destroyed. Callers need to know that 995 * the RXQ flush has completed to avoid waiting until timeout for a 996 * flush done event that will not be delivered. 997 */ 998 if (rc != EALREADY) 999 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1000 1001 return (rc); 1002 } 1003 1004 void 1005 ef10_rx_qenable( 1006 __in efx_rxq_t *erp) 1007 { 1008 /* FIXME */ 1009 _NOTE(ARGUNUSED(erp)) 1010 /* FIXME */ 1011 } 1012 1013 __checkReturn efx_rc_t 1014 ef10_rx_qcreate( 1015 __in efx_nic_t *enp, 1016 __in unsigned int index, 1017 __in unsigned int label, 1018 __in efx_rxq_type_t type, 1019 __in_opt const efx_rxq_type_data_t *type_data, 1020 __in efsys_mem_t *esmp, 1021 __in size_t ndescs, 1022 __in uint32_t id, 1023 __in unsigned int flags, 1024 __in efx_evq_t *eep, 1025 __in efx_rxq_t *erp) 1026 { 1027 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1028 efx_rc_t rc; 1029 boolean_t disable_scatter; 1030 boolean_t want_inner_classes; 1031 unsigned int ps_buf_size; 1032 uint32_t es_bufs_per_desc = 0; 1033 uint32_t es_max_dma_len = 0; 1034 uint32_t es_buf_stride = 0; 1035 uint32_t hol_block_timeout = 0; 1036 1037 _NOTE(ARGUNUSED(id, erp, type_data)) 1038 1039 EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS == (1 << ESF_DZ_RX_QLABEL_WIDTH)); 1040 EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS); 1041 EFSYS_ASSERT3U(enp->en_rx_qcount + 1, <, encp->enc_rxq_limit); 1042 1043 EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MAXNDESCS)); 1044 EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MINNDESCS)); 1045 1046 if (!ISP2(ndescs) || 1047 (ndescs < EFX_RXQ_MINNDESCS) || (ndescs > EFX_RXQ_MAXNDESCS)) { 1048 rc = EINVAL; 1049 goto fail1; 1050 } 1051 if (index >= encp->enc_rxq_limit) { 1052 rc = EINVAL; 1053 goto fail2; 1054 } 1055 1056 switch (type) { 1057 case EFX_RXQ_TYPE_DEFAULT: 1058 ps_buf_size = 0; 1059 break; 1060 #if EFSYS_OPT_RX_PACKED_STREAM 1061 case EFX_RXQ_TYPE_PACKED_STREAM: 1062 if (type_data == NULL) { 1063 rc = EINVAL; 1064 goto fail3; 1065 } 1066 switch (type_data->ertd_packed_stream.eps_buf_size) { 1067 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_1M: 1068 ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_1M; 1069 break; 1070 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_512K: 1071 ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_512K; 1072 break; 1073 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_256K: 1074 ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_256K; 1075 break; 1076 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_128K: 1077 ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_128K; 1078 break; 1079 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_64K: 1080 ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_64K; 1081 break; 1082 default: 1083 rc = ENOTSUP; 1084 goto fail4; 1085 } 1086 break; 1087 #endif /* EFSYS_OPT_RX_PACKED_STREAM */ 1088 #if EFSYS_OPT_RX_ES_SUPER_BUFFER 1089 case EFX_RXQ_TYPE_ES_SUPER_BUFFER: 1090 if (type_data == NULL) { 1091 rc = EINVAL; 1092 goto fail5; 1093 } 1094 ps_buf_size = 0; 1095 es_bufs_per_desc = 1096 type_data->ertd_es_super_buffer.eessb_bufs_per_desc; 1097 es_max_dma_len = 1098 type_data->ertd_es_super_buffer.eessb_max_dma_len; 1099 es_buf_stride = 1100 type_data->ertd_es_super_buffer.eessb_buf_stride; 1101 hol_block_timeout = 1102 type_data->ertd_es_super_buffer.eessb_hol_block_timeout; 1103 break; 1104 #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */ 1105 default: 1106 rc = ENOTSUP; 1107 goto fail6; 1108 } 1109 1110 #if EFSYS_OPT_RX_PACKED_STREAM 1111 if (ps_buf_size != 0) { 1112 /* Check if datapath firmware supports packed stream mode */ 1113 if (encp->enc_rx_packed_stream_supported == B_FALSE) { 1114 rc = ENOTSUP; 1115 goto fail7; 1116 } 1117 /* Check if packed stream allows configurable buffer sizes */ 1118 if ((ps_buf_size != MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_1M) && 1119 (encp->enc_rx_var_packed_stream_supported == B_FALSE)) { 1120 rc = ENOTSUP; 1121 goto fail8; 1122 } 1123 } 1124 #else /* EFSYS_OPT_RX_PACKED_STREAM */ 1125 EFSYS_ASSERT(ps_buf_size == 0); 1126 #endif /* EFSYS_OPT_RX_PACKED_STREAM */ 1127 1128 #if EFSYS_OPT_RX_ES_SUPER_BUFFER 1129 if (es_bufs_per_desc > 0) { 1130 if (encp->enc_rx_es_super_buffer_supported == B_FALSE) { 1131 rc = ENOTSUP; 1132 goto fail9; 1133 } 1134 if (!EFX_IS_P2ALIGNED(uint32_t, es_max_dma_len, 1135 EFX_RX_ES_SUPER_BUFFER_BUF_ALIGNMENT)) { 1136 rc = EINVAL; 1137 goto fail10; 1138 } 1139 if (!EFX_IS_P2ALIGNED(uint32_t, es_buf_stride, 1140 EFX_RX_ES_SUPER_BUFFER_BUF_ALIGNMENT)) { 1141 rc = EINVAL; 1142 goto fail11; 1143 } 1144 } 1145 #else /* EFSYS_OPT_RX_ES_SUPER_BUFFER */ 1146 EFSYS_ASSERT(es_bufs_per_desc == 0); 1147 #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */ 1148 1149 /* Scatter can only be disabled if the firmware supports doing so */ 1150 if (flags & EFX_RXQ_FLAG_SCATTER) 1151 disable_scatter = B_FALSE; 1152 else 1153 disable_scatter = encp->enc_rx_disable_scatter_supported; 1154 1155 if (flags & EFX_RXQ_FLAG_INNER_CLASSES) 1156 want_inner_classes = B_TRUE; 1157 else 1158 want_inner_classes = B_FALSE; 1159 1160 if ((rc = efx_mcdi_init_rxq(enp, ndescs, eep->ee_index, label, index, 1161 esmp, disable_scatter, want_inner_classes, 1162 ps_buf_size, es_bufs_per_desc, es_max_dma_len, 1163 es_buf_stride, hol_block_timeout)) != 0) 1164 goto fail12; 1165 1166 erp->er_eep = eep; 1167 erp->er_label = label; 1168 1169 ef10_ev_rxlabel_init(eep, erp, label, type); 1170 1171 erp->er_ev_qstate = &erp->er_eep->ee_rxq_state[label]; 1172 1173 return (0); 1174 1175 fail12: 1176 EFSYS_PROBE(fail12); 1177 #if EFSYS_OPT_RX_ES_SUPER_BUFFER 1178 fail11: 1179 EFSYS_PROBE(fail11); 1180 fail10: 1181 EFSYS_PROBE(fail10); 1182 fail9: 1183 EFSYS_PROBE(fail9); 1184 #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */ 1185 #if EFSYS_OPT_RX_PACKED_STREAM 1186 fail8: 1187 EFSYS_PROBE(fail8); 1188 fail7: 1189 EFSYS_PROBE(fail7); 1190 #endif /* EFSYS_OPT_RX_PACKED_STREAM */ 1191 fail6: 1192 EFSYS_PROBE(fail6); 1193 #if EFSYS_OPT_RX_ES_SUPER_BUFFER 1194 fail5: 1195 EFSYS_PROBE(fail5); 1196 #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */ 1197 #if EFSYS_OPT_RX_PACKED_STREAM 1198 fail4: 1199 EFSYS_PROBE(fail4); 1200 fail3: 1201 EFSYS_PROBE(fail3); 1202 #endif /* EFSYS_OPT_RX_PACKED_STREAM */ 1203 fail2: 1204 EFSYS_PROBE(fail2); 1205 fail1: 1206 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1207 1208 return (rc); 1209 } 1210 1211 void 1212 ef10_rx_qdestroy( 1213 __in efx_rxq_t *erp) 1214 { 1215 efx_nic_t *enp = erp->er_enp; 1216 efx_evq_t *eep = erp->er_eep; 1217 unsigned int label = erp->er_label; 1218 1219 ef10_ev_rxlabel_fini(eep, label); 1220 1221 EFSYS_ASSERT(enp->en_rx_qcount != 0); 1222 --enp->en_rx_qcount; 1223 1224 EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp); 1225 } 1226 1227 void 1228 ef10_rx_fini( 1229 __in efx_nic_t *enp) 1230 { 1231 #if EFSYS_OPT_RX_SCALE 1232 if (enp->en_rss_context_type != EFX_RX_SCALE_UNAVAILABLE) 1233 (void) efx_mcdi_rss_context_free(enp, enp->en_rss_context); 1234 enp->en_rss_context = 0; 1235 enp->en_rss_context_type = EFX_RX_SCALE_UNAVAILABLE; 1236 #else 1237 _NOTE(ARGUNUSED(enp)) 1238 #endif /* EFSYS_OPT_RX_SCALE */ 1239 } 1240 1241 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */ 1242