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