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: stable/10/sys/dev/sfxge/common/ef10_tx.c 342516 2018-12-26 10:25:01Z arybchik $"); 33 34#include "efx.h" 35#include "efx_impl.h" 36 37 38#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 39 40#if EFSYS_OPT_QSTATS 41#define EFX_TX_QSTAT_INCR(_etp, _stat) \ 42 do { \ 43 (_etp)->et_stat[_stat]++; \ 44 _NOTE(CONSTANTCONDITION) \ 45 } while (B_FALSE) 46#else 47#define EFX_TX_QSTAT_INCR(_etp, _stat) 48#endif 49 50static __checkReturn efx_rc_t 51efx_mcdi_init_txq( 52 __in efx_nic_t *enp, 53 __in uint32_t size, 54 __in uint32_t target_evq, 55 __in uint32_t label, 56 __in uint32_t instance, 57 __in uint16_t flags, 58 __in efsys_mem_t *esmp) 59{ 60 efx_mcdi_req_t req; 61 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_INIT_TXQ_IN_LEN(EFX_TXQ_MAX_BUFS), 62 MC_CMD_INIT_TXQ_OUT_LEN); 63 efx_qword_t *dma_addr; 64 uint64_t addr; 65 int npages; 66 int i; 67 efx_rc_t rc; 68 69 EFSYS_ASSERT(EFX_TXQ_MAX_BUFS >= 70 EFX_TXQ_NBUFS(enp->en_nic_cfg.enc_txq_max_ndescs)); 71 72 npages = EFX_TXQ_NBUFS(size); 73 if (npages > MC_CMD_INIT_TXQ_IN_DMA_ADDR_MAXNUM) { 74 rc = EINVAL; 75 goto fail1; 76 } 77 78 req.emr_cmd = MC_CMD_INIT_TXQ; 79 req.emr_in_buf = payload; 80 req.emr_in_length = MC_CMD_INIT_TXQ_IN_LEN(npages); 81 req.emr_out_buf = payload; 82 req.emr_out_length = MC_CMD_INIT_TXQ_OUT_LEN; 83 84 MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_SIZE, size); 85 MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_TARGET_EVQ, target_evq); 86 MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_LABEL, label); 87 MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_INSTANCE, instance); 88 89 MCDI_IN_POPULATE_DWORD_9(req, INIT_TXQ_IN_FLAGS, 90 INIT_TXQ_IN_FLAG_BUFF_MODE, 0, 91 INIT_TXQ_IN_FLAG_IP_CSUM_DIS, 92 (flags & EFX_TXQ_CKSUM_IPV4) ? 0 : 1, 93 INIT_TXQ_IN_FLAG_TCP_CSUM_DIS, 94 (flags & EFX_TXQ_CKSUM_TCPUDP) ? 0 : 1, 95 INIT_TXQ_EXT_IN_FLAG_INNER_IP_CSUM_EN, 96 (flags & EFX_TXQ_CKSUM_INNER_IPV4) ? 1 : 0, 97 INIT_TXQ_EXT_IN_FLAG_INNER_TCP_CSUM_EN, 98 (flags & EFX_TXQ_CKSUM_INNER_TCPUDP) ? 1 : 0, 99 INIT_TXQ_EXT_IN_FLAG_TSOV2_EN, (flags & EFX_TXQ_FATSOV2) ? 1 : 0, 100 INIT_TXQ_IN_FLAG_TCP_UDP_ONLY, 0, 101 INIT_TXQ_IN_CRC_MODE, 0, 102 INIT_TXQ_IN_FLAG_TIMESTAMP, 0); 103 104 MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_OWNER_ID, 0); 105 MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_PORT_ID, EVB_PORT_ID_ASSIGNED); 106 107 dma_addr = MCDI_IN2(req, efx_qword_t, INIT_TXQ_IN_DMA_ADDR); 108 addr = EFSYS_MEM_ADDR(esmp); 109 110 for (i = 0; i < npages; i++) { 111 EFX_POPULATE_QWORD_2(*dma_addr, 112 EFX_DWORD_1, (uint32_t)(addr >> 32), 113 EFX_DWORD_0, (uint32_t)(addr & 0xffffffff)); 114 115 dma_addr++; 116 addr += EFX_BUF_SIZE; 117 } 118 119 efx_mcdi_execute(enp, &req); 120 121 if (req.emr_rc != 0) { 122 rc = req.emr_rc; 123 goto fail2; 124 } 125 126 return (0); 127 128fail2: 129 EFSYS_PROBE(fail2); 130fail1: 131 EFSYS_PROBE1(fail1, efx_rc_t, rc); 132 133 return (rc); 134} 135 136static __checkReturn efx_rc_t 137efx_mcdi_fini_txq( 138 __in efx_nic_t *enp, 139 __in uint32_t instance) 140{ 141 efx_mcdi_req_t req; 142 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FINI_TXQ_IN_LEN, 143 MC_CMD_FINI_TXQ_OUT_LEN); 144 efx_rc_t rc; 145 146 req.emr_cmd = MC_CMD_FINI_TXQ; 147 req.emr_in_buf = payload; 148 req.emr_in_length = MC_CMD_FINI_TXQ_IN_LEN; 149 req.emr_out_buf = payload; 150 req.emr_out_length = MC_CMD_FINI_TXQ_OUT_LEN; 151 152 MCDI_IN_SET_DWORD(req, FINI_TXQ_IN_INSTANCE, instance); 153 154 efx_mcdi_execute_quiet(enp, &req); 155 156 if (req.emr_rc != 0) { 157 rc = req.emr_rc; 158 goto fail1; 159 } 160 161 return (0); 162 163fail1: 164 /* 165 * EALREADY is not an error, but indicates that the MC has rebooted and 166 * that the TXQ has already been destroyed. 167 */ 168 if (rc != EALREADY) 169 EFSYS_PROBE1(fail1, efx_rc_t, rc); 170 171 return (rc); 172} 173 174 __checkReturn efx_rc_t 175ef10_tx_init( 176 __in efx_nic_t *enp) 177{ 178 _NOTE(ARGUNUSED(enp)) 179 return (0); 180} 181 182 void 183ef10_tx_fini( 184 __in efx_nic_t *enp) 185{ 186 _NOTE(ARGUNUSED(enp)) 187} 188 189 __checkReturn efx_rc_t 190ef10_tx_qcreate( 191 __in efx_nic_t *enp, 192 __in unsigned int index, 193 __in unsigned int label, 194 __in efsys_mem_t *esmp, 195 __in size_t n, 196 __in uint32_t id, 197 __in uint16_t flags, 198 __in efx_evq_t *eep, 199 __in efx_txq_t *etp, 200 __out unsigned int *addedp) 201{ 202 efx_nic_cfg_t *encp = &enp->en_nic_cfg; 203 uint16_t inner_csum; 204 efx_desc_t desc; 205 efx_rc_t rc; 206 207 _NOTE(ARGUNUSED(id)) 208 209 inner_csum = EFX_TXQ_CKSUM_INNER_IPV4 | EFX_TXQ_CKSUM_INNER_TCPUDP; 210 if (((flags & inner_csum) != 0) && 211 (encp->enc_tunnel_encapsulations_supported == 0)) { 212 rc = EINVAL; 213 goto fail1; 214 } 215 216 if ((rc = efx_mcdi_init_txq(enp, n, eep->ee_index, label, index, flags, 217 esmp)) != 0) 218 goto fail2; 219 220 /* 221 * A previous user of this TX queue may have written a descriptor to the 222 * TX push collector, but not pushed the doorbell (e.g. after a crash). 223 * The next doorbell write would then push the stale descriptor. 224 * 225 * Ensure the (per network port) TX push collector is cleared by writing 226 * a no-op TX option descriptor. See bug29981 for details. 227 */ 228 *addedp = 1; 229 ef10_tx_qdesc_checksum_create(etp, flags, &desc); 230 231 EFSYS_MEM_WRITEQ(etp->et_esmp, 0, &desc.ed_eq); 232 ef10_tx_qpush(etp, *addedp, 0); 233 234 return (0); 235 236fail2: 237 EFSYS_PROBE(fail2); 238fail1: 239 EFSYS_PROBE1(fail1, efx_rc_t, rc); 240 241 return (rc); 242} 243 244 void 245ef10_tx_qdestroy( 246 __in efx_txq_t *etp) 247{ 248 /* FIXME */ 249 _NOTE(ARGUNUSED(etp)) 250 /* FIXME */ 251} 252 253 __checkReturn efx_rc_t 254ef10_tx_qpio_enable( 255 __in efx_txq_t *etp) 256{ 257 efx_nic_t *enp = etp->et_enp; 258 efx_piobuf_handle_t handle; 259 efx_rc_t rc; 260 261 if (etp->et_pio_size != 0) { 262 rc = EALREADY; 263 goto fail1; 264 } 265 266 /* Sub-allocate a PIO block from a piobuf */ 267 if ((rc = ef10_nic_pio_alloc(enp, 268 &etp->et_pio_bufnum, 269 &handle, 270 &etp->et_pio_blknum, 271 &etp->et_pio_offset, 272 &etp->et_pio_size)) != 0) { 273 goto fail2; 274 } 275 EFSYS_ASSERT3U(etp->et_pio_size, !=, 0); 276 277 /* Link the piobuf to this TXQ */ 278 if ((rc = ef10_nic_pio_link(enp, etp->et_index, handle)) != 0) { 279 goto fail3; 280 } 281 282 /* 283 * et_pio_offset is the offset of the sub-allocated block within the 284 * hardware PIO buffer. It is used as the buffer address in the PIO 285 * option descriptor. 286 * 287 * et_pio_write_offset is the offset of the sub-allocated block from the 288 * start of the write-combined memory mapping, and is used for writing 289 * data into the PIO buffer. 290 */ 291 etp->et_pio_write_offset = 292 (etp->et_pio_bufnum * ER_DZ_TX_PIOBUF_STEP) + 293 ER_DZ_TX_PIOBUF_OFST + etp->et_pio_offset; 294 295 return (0); 296 297fail3: 298 EFSYS_PROBE(fail3); 299 (void) ef10_nic_pio_free(enp, etp->et_pio_bufnum, etp->et_pio_blknum); 300 etp->et_pio_size = 0; 301fail2: 302 EFSYS_PROBE(fail2); 303fail1: 304 EFSYS_PROBE1(fail1, efx_rc_t, rc); 305 306 return (rc); 307} 308 309 void 310ef10_tx_qpio_disable( 311 __in efx_txq_t *etp) 312{ 313 efx_nic_t *enp = etp->et_enp; 314 315 if (etp->et_pio_size != 0) { 316 /* Unlink the piobuf from this TXQ */ 317 if (ef10_nic_pio_unlink(enp, etp->et_index) != 0) 318 return; 319 320 /* Free the sub-allocated PIO block */ 321 (void) ef10_nic_pio_free(enp, etp->et_pio_bufnum, 322 etp->et_pio_blknum); 323 etp->et_pio_size = 0; 324 etp->et_pio_write_offset = 0; 325 } 326} 327 328 __checkReturn efx_rc_t 329ef10_tx_qpio_write( 330 __in efx_txq_t *etp, 331 __in_ecount(length) uint8_t *buffer, 332 __in size_t length, 333 __in size_t offset) 334{ 335 efx_nic_t *enp = etp->et_enp; 336 efsys_bar_t *esbp = enp->en_esbp; 337 uint32_t write_offset; 338 uint32_t write_offset_limit; 339 efx_qword_t *eqp; 340 efx_rc_t rc; 341 342 EFSYS_ASSERT(length % sizeof (efx_qword_t) == 0); 343 344 if (etp->et_pio_size == 0) { 345 rc = ENOENT; 346 goto fail1; 347 } 348 if (offset + length > etp->et_pio_size) { 349 rc = ENOSPC; 350 goto fail2; 351 } 352 353 /* 354 * Writes to PIO buffers must be 64 bit aligned, and multiples of 355 * 64 bits. 356 */ 357 write_offset = etp->et_pio_write_offset + offset; 358 write_offset_limit = write_offset + length; 359 eqp = (efx_qword_t *)buffer; 360 while (write_offset < write_offset_limit) { 361 EFSYS_BAR_WC_WRITEQ(esbp, write_offset, eqp); 362 eqp++; 363 write_offset += sizeof (efx_qword_t); 364 } 365 366 return (0); 367 368fail2: 369 EFSYS_PROBE(fail2); 370fail1: 371 EFSYS_PROBE1(fail1, efx_rc_t, rc); 372 373 return (rc); 374} 375 376 __checkReturn efx_rc_t 377ef10_tx_qpio_post( 378 __in efx_txq_t *etp, 379 __in size_t pkt_length, 380 __in unsigned int completed, 381 __inout unsigned int *addedp) 382{ 383 efx_qword_t pio_desc; 384 unsigned int id; 385 size_t offset; 386 unsigned int added = *addedp; 387 efx_rc_t rc; 388 389 390 if (added - completed + 1 > EFX_TXQ_LIMIT(etp->et_mask + 1)) { 391 rc = ENOSPC; 392 goto fail1; 393 } 394 395 if (etp->et_pio_size == 0) { 396 rc = ENOENT; 397 goto fail2; 398 } 399 400 id = added++ & etp->et_mask; 401 offset = id * sizeof (efx_qword_t); 402 403 EFSYS_PROBE4(tx_pio_post, unsigned int, etp->et_index, 404 unsigned int, id, uint32_t, etp->et_pio_offset, 405 size_t, pkt_length); 406 407 EFX_POPULATE_QWORD_5(pio_desc, 408 ESF_DZ_TX_DESC_IS_OPT, 1, 409 ESF_DZ_TX_OPTION_TYPE, 1, 410 ESF_DZ_TX_PIO_CONT, 0, 411 ESF_DZ_TX_PIO_BYTE_CNT, pkt_length, 412 ESF_DZ_TX_PIO_BUF_ADDR, etp->et_pio_offset); 413 414 EFSYS_MEM_WRITEQ(etp->et_esmp, offset, &pio_desc); 415 416 EFX_TX_QSTAT_INCR(etp, TX_POST_PIO); 417 418 *addedp = added; 419 return (0); 420 421fail2: 422 EFSYS_PROBE(fail2); 423fail1: 424 EFSYS_PROBE1(fail1, efx_rc_t, rc); 425 426 return (rc); 427} 428 429 __checkReturn efx_rc_t 430ef10_tx_qpost( 431 __in efx_txq_t *etp, 432 __in_ecount(n) efx_buffer_t *eb, 433 __in unsigned int n, 434 __in unsigned int completed, 435 __inout unsigned int *addedp) 436{ 437 unsigned int added = *addedp; 438 unsigned int i; 439 efx_rc_t rc; 440 441 if (added - completed + n > EFX_TXQ_LIMIT(etp->et_mask + 1)) { 442 rc = ENOSPC; 443 goto fail1; 444 } 445 446 for (i = 0; i < n; i++) { 447 efx_buffer_t *ebp = &eb[i]; 448 efsys_dma_addr_t addr = ebp->eb_addr; 449 size_t size = ebp->eb_size; 450 boolean_t eop = ebp->eb_eop; 451 unsigned int id; 452 size_t offset; 453 efx_qword_t qword; 454 455 /* No limitations on boundary crossing */ 456 EFSYS_ASSERT(size <= 457 etp->et_enp->en_nic_cfg.enc_tx_dma_desc_size_max); 458 459 id = added++ & etp->et_mask; 460 offset = id * sizeof (efx_qword_t); 461 462 EFSYS_PROBE5(tx_post, unsigned int, etp->et_index, 463 unsigned int, id, efsys_dma_addr_t, addr, 464 size_t, size, boolean_t, eop); 465 466 EFX_POPULATE_QWORD_5(qword, 467 ESF_DZ_TX_KER_TYPE, 0, 468 ESF_DZ_TX_KER_CONT, (eop) ? 0 : 1, 469 ESF_DZ_TX_KER_BYTE_CNT, (uint32_t)(size), 470 ESF_DZ_TX_KER_BUF_ADDR_DW0, (uint32_t)(addr & 0xffffffff), 471 ESF_DZ_TX_KER_BUF_ADDR_DW1, (uint32_t)(addr >> 32)); 472 473 EFSYS_MEM_WRITEQ(etp->et_esmp, offset, &qword); 474 } 475 476 EFX_TX_QSTAT_INCR(etp, TX_POST); 477 478 *addedp = added; 479 return (0); 480 481fail1: 482 EFSYS_PROBE1(fail1, efx_rc_t, rc); 483 484 return (rc); 485} 486 487/* 488 * This improves performance by, when possible, pushing a TX descriptor at the 489 * same time as the doorbell. The descriptor must be added to the TXQ, so that 490 * can be used if the hardware decides not to use the pushed descriptor. 491 */ 492 void 493ef10_tx_qpush( 494 __in efx_txq_t *etp, 495 __in unsigned int added, 496 __in unsigned int pushed) 497{ 498 efx_nic_t *enp = etp->et_enp; 499 unsigned int wptr; 500 unsigned int id; 501 size_t offset; 502 efx_qword_t desc; 503 efx_oword_t oword; 504 505 wptr = added & etp->et_mask; 506 id = pushed & etp->et_mask; 507 offset = id * sizeof (efx_qword_t); 508 509 EFSYS_MEM_READQ(etp->et_esmp, offset, &desc); 510 511 /* 512 * SF Bug 65776: TSO option descriptors cannot be pushed if pacer bypass 513 * is enabled on the event queue this transmit queue is attached to. 514 * 515 * To ensure the code is safe, it is easiest to simply test the type of 516 * the descriptor to push, and only push it is if it not a TSO option 517 * descriptor. 518 */ 519 if ((EFX_QWORD_FIELD(desc, ESF_DZ_TX_DESC_IS_OPT) != 1) || 520 (EFX_QWORD_FIELD(desc, ESF_DZ_TX_OPTION_TYPE) != 521 ESE_DZ_TX_OPTION_DESC_TSO)) { 522 /* Push the descriptor and update the wptr. */ 523 EFX_POPULATE_OWORD_3(oword, ERF_DZ_TX_DESC_WPTR, wptr, 524 ERF_DZ_TX_DESC_HWORD, EFX_QWORD_FIELD(desc, EFX_DWORD_1), 525 ERF_DZ_TX_DESC_LWORD, EFX_QWORD_FIELD(desc, EFX_DWORD_0)); 526 527 /* Ensure ordering of memory (descriptors) and PIO (doorbell) */ 528 EFX_DMA_SYNC_QUEUE_FOR_DEVICE(etp->et_esmp, etp->et_mask + 1, 529 wptr, id); 530 EFSYS_PIO_WRITE_BARRIER(); 531 EFX_BAR_TBL_DOORBELL_WRITEO(enp, ER_DZ_TX_DESC_UPD_REG, 532 etp->et_index, &oword); 533 } else { 534 efx_dword_t dword; 535 536 /* 537 * Only update the wptr. This is signalled to the hardware by 538 * only writing one DWORD of the doorbell register. 539 */ 540 EFX_POPULATE_OWORD_1(oword, ERF_DZ_TX_DESC_WPTR, wptr); 541 dword = oword.eo_dword[2]; 542 543 /* Ensure ordering of memory (descriptors) and PIO (doorbell) */ 544 EFX_DMA_SYNC_QUEUE_FOR_DEVICE(etp->et_esmp, etp->et_mask + 1, 545 wptr, id); 546 EFSYS_PIO_WRITE_BARRIER(); 547 EFX_BAR_TBL_WRITED2(enp, ER_DZ_TX_DESC_UPD_REG, 548 etp->et_index, &dword, B_FALSE); 549 } 550} 551 552 __checkReturn efx_rc_t 553ef10_tx_qdesc_post( 554 __in efx_txq_t *etp, 555 __in_ecount(n) efx_desc_t *ed, 556 __in unsigned int n, 557 __in unsigned int completed, 558 __inout unsigned int *addedp) 559{ 560 unsigned int added = *addedp; 561 unsigned int i; 562 efx_rc_t rc; 563 564 if (added - completed + n > EFX_TXQ_LIMIT(etp->et_mask + 1)) { 565 rc = ENOSPC; 566 goto fail1; 567 } 568 569 for (i = 0; i < n; i++) { 570 efx_desc_t *edp = &ed[i]; 571 unsigned int id; 572 size_t offset; 573 574 id = added++ & etp->et_mask; 575 offset = id * sizeof (efx_desc_t); 576 577 EFSYS_MEM_WRITEQ(etp->et_esmp, offset, &edp->ed_eq); 578 } 579 580 EFSYS_PROBE3(tx_desc_post, unsigned int, etp->et_index, 581 unsigned int, added, unsigned int, n); 582 583 EFX_TX_QSTAT_INCR(etp, TX_POST); 584 585 *addedp = added; 586 return (0); 587 588fail1: 589 EFSYS_PROBE1(fail1, efx_rc_t, rc); 590 591 return (rc); 592} 593 594 void 595ef10_tx_qdesc_dma_create( 596 __in efx_txq_t *etp, 597 __in efsys_dma_addr_t addr, 598 __in size_t size, 599 __in boolean_t eop, 600 __out efx_desc_t *edp) 601{ 602 _NOTE(ARGUNUSED(etp)) 603 604 /* No limitations on boundary crossing */ 605 EFSYS_ASSERT(size <= etp->et_enp->en_nic_cfg.enc_tx_dma_desc_size_max); 606 607 EFSYS_PROBE4(tx_desc_dma_create, unsigned int, etp->et_index, 608 efsys_dma_addr_t, addr, 609 size_t, size, boolean_t, eop); 610 611 EFX_POPULATE_QWORD_5(edp->ed_eq, 612 ESF_DZ_TX_KER_TYPE, 0, 613 ESF_DZ_TX_KER_CONT, (eop) ? 0 : 1, 614 ESF_DZ_TX_KER_BYTE_CNT, (uint32_t)(size), 615 ESF_DZ_TX_KER_BUF_ADDR_DW0, (uint32_t)(addr & 0xffffffff), 616 ESF_DZ_TX_KER_BUF_ADDR_DW1, (uint32_t)(addr >> 32)); 617} 618 619 void 620ef10_tx_qdesc_tso_create( 621 __in efx_txq_t *etp, 622 __in uint16_t ipv4_id, 623 __in uint32_t tcp_seq, 624 __in uint8_t tcp_flags, 625 __out efx_desc_t *edp) 626{ 627 _NOTE(ARGUNUSED(etp)) 628 629 EFSYS_PROBE4(tx_desc_tso_create, unsigned int, etp->et_index, 630 uint16_t, ipv4_id, uint32_t, tcp_seq, 631 uint8_t, tcp_flags); 632 633 EFX_POPULATE_QWORD_5(edp->ed_eq, 634 ESF_DZ_TX_DESC_IS_OPT, 1, 635 ESF_DZ_TX_OPTION_TYPE, 636 ESE_DZ_TX_OPTION_DESC_TSO, 637 ESF_DZ_TX_TSO_TCP_FLAGS, tcp_flags, 638 ESF_DZ_TX_TSO_IP_ID, ipv4_id, 639 ESF_DZ_TX_TSO_TCP_SEQNO, tcp_seq); 640} 641 642 void 643ef10_tx_qdesc_tso2_create( 644 __in efx_txq_t *etp, 645 __in uint16_t ipv4_id, 646 __in uint32_t tcp_seq, 647 __in uint16_t tcp_mss, 648 __out_ecount(count) efx_desc_t *edp, 649 __in int count) 650{ 651 _NOTE(ARGUNUSED(etp, count)) 652 653 EFSYS_PROBE4(tx_desc_tso2_create, unsigned int, etp->et_index, 654 uint16_t, ipv4_id, uint32_t, tcp_seq, 655 uint16_t, tcp_mss); 656 657 EFSYS_ASSERT(count >= EFX_TX_FATSOV2_OPT_NDESCS); 658 659 EFX_POPULATE_QWORD_5(edp[0].ed_eq, 660 ESF_DZ_TX_DESC_IS_OPT, 1, 661 ESF_DZ_TX_OPTION_TYPE, 662 ESE_DZ_TX_OPTION_DESC_TSO, 663 ESF_DZ_TX_TSO_OPTION_TYPE, 664 ESE_DZ_TX_TSO_OPTION_DESC_FATSO2A, 665 ESF_DZ_TX_TSO_IP_ID, ipv4_id, 666 ESF_DZ_TX_TSO_TCP_SEQNO, tcp_seq); 667 EFX_POPULATE_QWORD_4(edp[1].ed_eq, 668 ESF_DZ_TX_DESC_IS_OPT, 1, 669 ESF_DZ_TX_OPTION_TYPE, 670 ESE_DZ_TX_OPTION_DESC_TSO, 671 ESF_DZ_TX_TSO_OPTION_TYPE, 672 ESE_DZ_TX_TSO_OPTION_DESC_FATSO2B, 673 ESF_DZ_TX_TSO_TCP_MSS, tcp_mss); 674} 675 676 void 677ef10_tx_qdesc_vlantci_create( 678 __in efx_txq_t *etp, 679 __in uint16_t tci, 680 __out efx_desc_t *edp) 681{ 682 _NOTE(ARGUNUSED(etp)) 683 684 EFSYS_PROBE2(tx_desc_vlantci_create, unsigned int, etp->et_index, 685 uint16_t, tci); 686 687 EFX_POPULATE_QWORD_4(edp->ed_eq, 688 ESF_DZ_TX_DESC_IS_OPT, 1, 689 ESF_DZ_TX_OPTION_TYPE, 690 ESE_DZ_TX_OPTION_DESC_VLAN, 691 ESF_DZ_TX_VLAN_OP, tci ? 1 : 0, 692 ESF_DZ_TX_VLAN_TAG1, tci); 693} 694 695 void 696ef10_tx_qdesc_checksum_create( 697 __in efx_txq_t *etp, 698 __in uint16_t flags, 699 __out efx_desc_t *edp) 700{ 701 _NOTE(ARGUNUSED(etp)); 702 703 EFSYS_PROBE2(tx_desc_checksum_create, unsigned int, etp->et_index, 704 uint32_t, flags); 705 706 EFX_POPULATE_QWORD_6(edp->ed_eq, 707 ESF_DZ_TX_DESC_IS_OPT, 1, 708 ESF_DZ_TX_OPTION_TYPE, ESE_DZ_TX_OPTION_DESC_CRC_CSUM, 709 ESF_DZ_TX_OPTION_UDP_TCP_CSUM, 710 (flags & EFX_TXQ_CKSUM_TCPUDP) ? 1 : 0, 711 ESF_DZ_TX_OPTION_IP_CSUM, 712 (flags & EFX_TXQ_CKSUM_IPV4) ? 1 : 0, 713 ESF_DZ_TX_OPTION_INNER_UDP_TCP_CSUM, 714 (flags & EFX_TXQ_CKSUM_INNER_TCPUDP) ? 1 : 0, 715 ESF_DZ_TX_OPTION_INNER_IP_CSUM, 716 (flags & EFX_TXQ_CKSUM_INNER_IPV4) ? 1 : 0); 717} 718 719 720 __checkReturn efx_rc_t 721ef10_tx_qpace( 722 __in efx_txq_t *etp, 723 __in unsigned int ns) 724{ 725 efx_rc_t rc; 726 727 /* FIXME */ 728 _NOTE(ARGUNUSED(etp, ns)) 729 _NOTE(CONSTANTCONDITION) 730 if (B_FALSE) { 731 rc = ENOTSUP; 732 goto fail1; 733 } 734 /* FIXME */ 735 736 return (0); 737 738fail1: 739 /* 740 * EALREADY is not an error, but indicates that the MC has rebooted and 741 * that the TXQ has already been destroyed. Callers need to know that 742 * the TXQ flush has completed to avoid waiting until timeout for a 743 * flush done event that will not be delivered. 744 */ 745 if (rc != EALREADY) 746 EFSYS_PROBE1(fail1, efx_rc_t, rc); 747 748 return (rc); 749} 750 751 __checkReturn efx_rc_t 752ef10_tx_qflush( 753 __in efx_txq_t *etp) 754{ 755 efx_nic_t *enp = etp->et_enp; 756 efx_rc_t rc; 757 758 if ((rc = efx_mcdi_fini_txq(enp, etp->et_index)) != 0) 759 goto fail1; 760 761 return (0); 762 763fail1: 764 EFSYS_PROBE1(fail1, efx_rc_t, rc); 765 766 return (rc); 767} 768 769 void 770ef10_tx_qenable( 771 __in efx_txq_t *etp) 772{ 773 /* FIXME */ 774 _NOTE(ARGUNUSED(etp)) 775 /* FIXME */ 776} 777 778#if EFSYS_OPT_QSTATS 779 void 780ef10_tx_qstats_update( 781 __in efx_txq_t *etp, 782 __inout_ecount(TX_NQSTATS) efsys_stat_t *stat) 783{ 784 unsigned int id; 785 786 for (id = 0; id < TX_NQSTATS; id++) { 787 efsys_stat_t *essp = &stat[id]; 788 789 EFSYS_STAT_INCR(essp, etp->et_stat[id]); 790 etp->et_stat[id] = 0; 791 } 792} 793 794#endif /* EFSYS_OPT_QSTATS */ 795 796#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 797