1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2007-2016 Solarflare Communications Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright notice, 11 * this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * The views and conclusions contained in the software and documentation are 29 * those of the authors and should not be interpreted as representing official 30 * policies, either expressed or implied, of the FreeBSD Project. 31 */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #include "efx.h" 37 #include "efx_impl.h" 38 39 #if EFSYS_OPT_QSTATS 40 #define EFX_TX_QSTAT_INCR(_etp, _stat) \ 41 do { \ 42 (_etp)->et_stat[_stat]++; \ 43 _NOTE(CONSTANTCONDITION) \ 44 } while (B_FALSE) 45 #else 46 #define EFX_TX_QSTAT_INCR(_etp, _stat) 47 #endif 48 49 #if EFSYS_OPT_SIENA 50 51 static __checkReturn efx_rc_t 52 siena_tx_init( 53 __in efx_nic_t *enp); 54 55 static void 56 siena_tx_fini( 57 __in efx_nic_t *enp); 58 59 static __checkReturn efx_rc_t 60 siena_tx_qcreate( 61 __in efx_nic_t *enp, 62 __in unsigned int index, 63 __in unsigned int label, 64 __in efsys_mem_t *esmp, 65 __in size_t ndescs, 66 __in uint32_t id, 67 __in uint16_t flags, 68 __in efx_evq_t *eep, 69 __in efx_txq_t *etp, 70 __out unsigned int *addedp); 71 72 static void 73 siena_tx_qdestroy( 74 __in efx_txq_t *etp); 75 76 static __checkReturn efx_rc_t 77 siena_tx_qpost( 78 __in efx_txq_t *etp, 79 __in_ecount(ndescs) efx_buffer_t *eb, 80 __in unsigned int ndescs, 81 __in unsigned int completed, 82 __inout unsigned int *addedp); 83 84 static void 85 siena_tx_qpush( 86 __in efx_txq_t *etp, 87 __in unsigned int added, 88 __in unsigned int pushed); 89 90 static __checkReturn efx_rc_t 91 siena_tx_qpace( 92 __in efx_txq_t *etp, 93 __in unsigned int ns); 94 95 static __checkReturn efx_rc_t 96 siena_tx_qflush( 97 __in efx_txq_t *etp); 98 99 static void 100 siena_tx_qenable( 101 __in efx_txq_t *etp); 102 103 __checkReturn efx_rc_t 104 siena_tx_qdesc_post( 105 __in efx_txq_t *etp, 106 __in_ecount(ndescs) efx_desc_t *ed, 107 __in unsigned int ndescs, 108 __in unsigned int completed, 109 __inout unsigned int *addedp); 110 111 void 112 siena_tx_qdesc_dma_create( 113 __in efx_txq_t *etp, 114 __in efsys_dma_addr_t addr, 115 __in size_t size, 116 __in boolean_t eop, 117 __out efx_desc_t *edp); 118 119 #if EFSYS_OPT_QSTATS 120 static void 121 siena_tx_qstats_update( 122 __in efx_txq_t *etp, 123 __inout_ecount(TX_NQSTATS) efsys_stat_t *stat); 124 #endif 125 126 #endif /* EFSYS_OPT_SIENA */ 127 128 129 #if EFSYS_OPT_SIENA 130 static const efx_tx_ops_t __efx_tx_siena_ops = { 131 siena_tx_init, /* etxo_init */ 132 siena_tx_fini, /* etxo_fini */ 133 siena_tx_qcreate, /* etxo_qcreate */ 134 siena_tx_qdestroy, /* etxo_qdestroy */ 135 siena_tx_qpost, /* etxo_qpost */ 136 siena_tx_qpush, /* etxo_qpush */ 137 siena_tx_qpace, /* etxo_qpace */ 138 siena_tx_qflush, /* etxo_qflush */ 139 siena_tx_qenable, /* etxo_qenable */ 140 NULL, /* etxo_qpio_enable */ 141 NULL, /* etxo_qpio_disable */ 142 NULL, /* etxo_qpio_write */ 143 NULL, /* etxo_qpio_post */ 144 siena_tx_qdesc_post, /* etxo_qdesc_post */ 145 siena_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */ 146 NULL, /* etxo_qdesc_tso_create */ 147 NULL, /* etxo_qdesc_tso2_create */ 148 NULL, /* etxo_qdesc_vlantci_create */ 149 NULL, /* etxo_qdesc_checksum_create */ 150 #if EFSYS_OPT_QSTATS 151 siena_tx_qstats_update, /* etxo_qstats_update */ 152 #endif 153 }; 154 #endif /* EFSYS_OPT_SIENA */ 155 156 #if EFSYS_OPT_HUNTINGTON 157 static const efx_tx_ops_t __efx_tx_hunt_ops = { 158 ef10_tx_init, /* etxo_init */ 159 ef10_tx_fini, /* etxo_fini */ 160 ef10_tx_qcreate, /* etxo_qcreate */ 161 ef10_tx_qdestroy, /* etxo_qdestroy */ 162 ef10_tx_qpost, /* etxo_qpost */ 163 ef10_tx_qpush, /* etxo_qpush */ 164 ef10_tx_qpace, /* etxo_qpace */ 165 ef10_tx_qflush, /* etxo_qflush */ 166 ef10_tx_qenable, /* etxo_qenable */ 167 ef10_tx_qpio_enable, /* etxo_qpio_enable */ 168 ef10_tx_qpio_disable, /* etxo_qpio_disable */ 169 ef10_tx_qpio_write, /* etxo_qpio_write */ 170 ef10_tx_qpio_post, /* etxo_qpio_post */ 171 ef10_tx_qdesc_post, /* etxo_qdesc_post */ 172 ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */ 173 ef10_tx_qdesc_tso_create, /* etxo_qdesc_tso_create */ 174 ef10_tx_qdesc_tso2_create, /* etxo_qdesc_tso2_create */ 175 ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */ 176 ef10_tx_qdesc_checksum_create, /* etxo_qdesc_checksum_create */ 177 #if EFSYS_OPT_QSTATS 178 ef10_tx_qstats_update, /* etxo_qstats_update */ 179 #endif 180 }; 181 #endif /* EFSYS_OPT_HUNTINGTON */ 182 183 #if EFSYS_OPT_MEDFORD 184 static const efx_tx_ops_t __efx_tx_medford_ops = { 185 ef10_tx_init, /* etxo_init */ 186 ef10_tx_fini, /* etxo_fini */ 187 ef10_tx_qcreate, /* etxo_qcreate */ 188 ef10_tx_qdestroy, /* etxo_qdestroy */ 189 ef10_tx_qpost, /* etxo_qpost */ 190 ef10_tx_qpush, /* etxo_qpush */ 191 ef10_tx_qpace, /* etxo_qpace */ 192 ef10_tx_qflush, /* etxo_qflush */ 193 ef10_tx_qenable, /* etxo_qenable */ 194 ef10_tx_qpio_enable, /* etxo_qpio_enable */ 195 ef10_tx_qpio_disable, /* etxo_qpio_disable */ 196 ef10_tx_qpio_write, /* etxo_qpio_write */ 197 ef10_tx_qpio_post, /* etxo_qpio_post */ 198 ef10_tx_qdesc_post, /* etxo_qdesc_post */ 199 ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */ 200 NULL, /* etxo_qdesc_tso_create */ 201 ef10_tx_qdesc_tso2_create, /* etxo_qdesc_tso2_create */ 202 ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */ 203 ef10_tx_qdesc_checksum_create, /* etxo_qdesc_checksum_create */ 204 #if EFSYS_OPT_QSTATS 205 ef10_tx_qstats_update, /* etxo_qstats_update */ 206 #endif 207 }; 208 #endif /* EFSYS_OPT_MEDFORD */ 209 210 #if EFSYS_OPT_MEDFORD2 211 static const efx_tx_ops_t __efx_tx_medford2_ops = { 212 ef10_tx_init, /* etxo_init */ 213 ef10_tx_fini, /* etxo_fini */ 214 ef10_tx_qcreate, /* etxo_qcreate */ 215 ef10_tx_qdestroy, /* etxo_qdestroy */ 216 ef10_tx_qpost, /* etxo_qpost */ 217 ef10_tx_qpush, /* etxo_qpush */ 218 ef10_tx_qpace, /* etxo_qpace */ 219 ef10_tx_qflush, /* etxo_qflush */ 220 ef10_tx_qenable, /* etxo_qenable */ 221 ef10_tx_qpio_enable, /* etxo_qpio_enable */ 222 ef10_tx_qpio_disable, /* etxo_qpio_disable */ 223 ef10_tx_qpio_write, /* etxo_qpio_write */ 224 ef10_tx_qpio_post, /* etxo_qpio_post */ 225 ef10_tx_qdesc_post, /* etxo_qdesc_post */ 226 ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */ 227 NULL, /* etxo_qdesc_tso_create */ 228 ef10_tx_qdesc_tso2_create, /* etxo_qdesc_tso2_create */ 229 ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */ 230 ef10_tx_qdesc_checksum_create, /* etxo_qdesc_checksum_create */ 231 #if EFSYS_OPT_QSTATS 232 ef10_tx_qstats_update, /* etxo_qstats_update */ 233 #endif 234 }; 235 #endif /* EFSYS_OPT_MEDFORD2 */ 236 237 238 __checkReturn efx_rc_t 239 efx_tx_init( 240 __in efx_nic_t *enp) 241 { 242 const efx_tx_ops_t *etxop; 243 efx_rc_t rc; 244 245 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 246 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 247 248 if (!(enp->en_mod_flags & EFX_MOD_EV)) { 249 rc = EINVAL; 250 goto fail1; 251 } 252 253 if (enp->en_mod_flags & EFX_MOD_TX) { 254 rc = EINVAL; 255 goto fail2; 256 } 257 258 switch (enp->en_family) { 259 #if EFSYS_OPT_SIENA 260 case EFX_FAMILY_SIENA: 261 etxop = &__efx_tx_siena_ops; 262 break; 263 #endif /* EFSYS_OPT_SIENA */ 264 265 #if EFSYS_OPT_HUNTINGTON 266 case EFX_FAMILY_HUNTINGTON: 267 etxop = &__efx_tx_hunt_ops; 268 break; 269 #endif /* EFSYS_OPT_HUNTINGTON */ 270 271 #if EFSYS_OPT_MEDFORD 272 case EFX_FAMILY_MEDFORD: 273 etxop = &__efx_tx_medford_ops; 274 break; 275 #endif /* EFSYS_OPT_MEDFORD */ 276 277 #if EFSYS_OPT_MEDFORD2 278 case EFX_FAMILY_MEDFORD2: 279 etxop = &__efx_tx_medford2_ops; 280 break; 281 #endif /* EFSYS_OPT_MEDFORD2 */ 282 283 default: 284 EFSYS_ASSERT(0); 285 rc = ENOTSUP; 286 goto fail3; 287 } 288 289 EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0); 290 291 if ((rc = etxop->etxo_init(enp)) != 0) 292 goto fail4; 293 294 enp->en_etxop = etxop; 295 enp->en_mod_flags |= EFX_MOD_TX; 296 return (0); 297 298 fail4: 299 EFSYS_PROBE(fail4); 300 fail3: 301 EFSYS_PROBE(fail3); 302 fail2: 303 EFSYS_PROBE(fail2); 304 fail1: 305 EFSYS_PROBE1(fail1, efx_rc_t, rc); 306 307 enp->en_etxop = NULL; 308 enp->en_mod_flags &= ~EFX_MOD_TX; 309 return (rc); 310 } 311 312 void 313 efx_tx_fini( 314 __in efx_nic_t *enp) 315 { 316 const efx_tx_ops_t *etxop = enp->en_etxop; 317 318 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 319 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 320 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX); 321 EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0); 322 323 etxop->etxo_fini(enp); 324 325 enp->en_etxop = NULL; 326 enp->en_mod_flags &= ~EFX_MOD_TX; 327 } 328 329 __checkReturn efx_rc_t 330 efx_tx_qcreate( 331 __in efx_nic_t *enp, 332 __in unsigned int index, 333 __in unsigned int label, 334 __in efsys_mem_t *esmp, 335 __in size_t ndescs, 336 __in uint32_t id, 337 __in uint16_t flags, 338 __in efx_evq_t *eep, 339 __deref_out efx_txq_t **etpp, 340 __out unsigned int *addedp) 341 { 342 const efx_tx_ops_t *etxop = enp->en_etxop; 343 efx_txq_t *etp; 344 efx_rc_t rc; 345 346 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 347 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX); 348 349 EFSYS_ASSERT3U(enp->en_tx_qcount + 1, <, 350 enp->en_nic_cfg.enc_txq_limit); 351 352 /* Allocate an TXQ object */ 353 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_txq_t), etp); 354 355 if (etp == NULL) { 356 rc = ENOMEM; 357 goto fail1; 358 } 359 360 etp->et_magic = EFX_TXQ_MAGIC; 361 etp->et_enp = enp; 362 etp->et_index = index; 363 etp->et_mask = ndescs - 1; 364 etp->et_esmp = esmp; 365 366 /* Initial descriptor index may be modified by etxo_qcreate */ 367 *addedp = 0; 368 369 if ((rc = etxop->etxo_qcreate(enp, index, label, esmp, 370 ndescs, id, flags, eep, etp, addedp)) != 0) 371 goto fail2; 372 373 enp->en_tx_qcount++; 374 *etpp = etp; 375 376 return (0); 377 378 fail2: 379 EFSYS_PROBE(fail2); 380 EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_txq_t), etp); 381 fail1: 382 EFSYS_PROBE1(fail1, efx_rc_t, rc); 383 return (rc); 384 } 385 386 void 387 efx_tx_qdestroy( 388 __in efx_txq_t *etp) 389 { 390 efx_nic_t *enp = etp->et_enp; 391 const efx_tx_ops_t *etxop = enp->en_etxop; 392 393 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 394 395 EFSYS_ASSERT(enp->en_tx_qcount != 0); 396 --enp->en_tx_qcount; 397 398 etxop->etxo_qdestroy(etp); 399 400 /* Free the TXQ object */ 401 EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_txq_t), etp); 402 } 403 404 __checkReturn efx_rc_t 405 efx_tx_qpost( 406 __in efx_txq_t *etp, 407 __in_ecount(ndescs) efx_buffer_t *eb, 408 __in unsigned int ndescs, 409 __in unsigned int completed, 410 __inout unsigned int *addedp) 411 { 412 efx_nic_t *enp = etp->et_enp; 413 const efx_tx_ops_t *etxop = enp->en_etxop; 414 efx_rc_t rc; 415 416 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 417 418 if ((rc = etxop->etxo_qpost(etp, eb, ndescs, completed, addedp)) != 0) 419 goto fail1; 420 421 return (0); 422 423 fail1: 424 EFSYS_PROBE1(fail1, efx_rc_t, rc); 425 return (rc); 426 } 427 428 void 429 efx_tx_qpush( 430 __in efx_txq_t *etp, 431 __in unsigned int added, 432 __in unsigned int pushed) 433 { 434 efx_nic_t *enp = etp->et_enp; 435 const efx_tx_ops_t *etxop = enp->en_etxop; 436 437 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 438 439 etxop->etxo_qpush(etp, added, pushed); 440 } 441 442 __checkReturn efx_rc_t 443 efx_tx_qpace( 444 __in efx_txq_t *etp, 445 __in unsigned int ns) 446 { 447 efx_nic_t *enp = etp->et_enp; 448 const efx_tx_ops_t *etxop = enp->en_etxop; 449 efx_rc_t rc; 450 451 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 452 453 if ((rc = etxop->etxo_qpace(etp, ns)) != 0) 454 goto fail1; 455 456 return (0); 457 458 fail1: 459 EFSYS_PROBE1(fail1, efx_rc_t, rc); 460 return (rc); 461 } 462 463 __checkReturn efx_rc_t 464 efx_tx_qflush( 465 __in efx_txq_t *etp) 466 { 467 efx_nic_t *enp = etp->et_enp; 468 const efx_tx_ops_t *etxop = enp->en_etxop; 469 efx_rc_t rc; 470 471 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 472 473 if ((rc = etxop->etxo_qflush(etp)) != 0) 474 goto fail1; 475 476 return (0); 477 478 fail1: 479 EFSYS_PROBE1(fail1, efx_rc_t, rc); 480 return (rc); 481 } 482 483 void 484 efx_tx_qenable( 485 __in efx_txq_t *etp) 486 { 487 efx_nic_t *enp = etp->et_enp; 488 const efx_tx_ops_t *etxop = enp->en_etxop; 489 490 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 491 492 etxop->etxo_qenable(etp); 493 } 494 495 __checkReturn efx_rc_t 496 efx_tx_qpio_enable( 497 __in efx_txq_t *etp) 498 { 499 efx_nic_t *enp = etp->et_enp; 500 const efx_tx_ops_t *etxop = enp->en_etxop; 501 efx_rc_t rc; 502 503 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 504 505 if (~enp->en_features & EFX_FEATURE_PIO_BUFFERS) { 506 rc = ENOTSUP; 507 goto fail1; 508 } 509 if (etxop->etxo_qpio_enable == NULL) { 510 rc = ENOTSUP; 511 goto fail2; 512 } 513 if ((rc = etxop->etxo_qpio_enable(etp)) != 0) 514 goto fail3; 515 516 return (0); 517 518 fail3: 519 EFSYS_PROBE(fail3); 520 fail2: 521 EFSYS_PROBE(fail2); 522 fail1: 523 EFSYS_PROBE1(fail1, efx_rc_t, rc); 524 return (rc); 525 } 526 527 void 528 efx_tx_qpio_disable( 529 __in efx_txq_t *etp) 530 { 531 efx_nic_t *enp = etp->et_enp; 532 const efx_tx_ops_t *etxop = enp->en_etxop; 533 534 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 535 536 if (etxop->etxo_qpio_disable != NULL) 537 etxop->etxo_qpio_disable(etp); 538 } 539 540 __checkReturn efx_rc_t 541 efx_tx_qpio_write( 542 __in efx_txq_t *etp, 543 __in_ecount(buf_length) uint8_t *buffer, 544 __in size_t buf_length, 545 __in size_t pio_buf_offset) 546 { 547 efx_nic_t *enp = etp->et_enp; 548 const efx_tx_ops_t *etxop = enp->en_etxop; 549 efx_rc_t rc; 550 551 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 552 553 if (etxop->etxo_qpio_write != NULL) { 554 if ((rc = etxop->etxo_qpio_write(etp, buffer, buf_length, 555 pio_buf_offset)) != 0) 556 goto fail1; 557 return (0); 558 } 559 560 return (ENOTSUP); 561 562 fail1: 563 EFSYS_PROBE1(fail1, efx_rc_t, rc); 564 return (rc); 565 } 566 567 __checkReturn efx_rc_t 568 efx_tx_qpio_post( 569 __in efx_txq_t *etp, 570 __in size_t pkt_length, 571 __in unsigned int completed, 572 __inout unsigned int *addedp) 573 { 574 efx_nic_t *enp = etp->et_enp; 575 const efx_tx_ops_t *etxop = enp->en_etxop; 576 efx_rc_t rc; 577 578 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 579 580 if (etxop->etxo_qpio_post != NULL) { 581 if ((rc = etxop->etxo_qpio_post(etp, pkt_length, completed, 582 addedp)) != 0) 583 goto fail1; 584 return (0); 585 } 586 587 return (ENOTSUP); 588 589 fail1: 590 EFSYS_PROBE1(fail1, efx_rc_t, rc); 591 return (rc); 592 } 593 594 __checkReturn efx_rc_t 595 efx_tx_qdesc_post( 596 __in efx_txq_t *etp, 597 __in_ecount(ndescs) efx_desc_t *ed, 598 __in unsigned int ndescs, 599 __in unsigned int completed, 600 __inout unsigned int *addedp) 601 { 602 efx_nic_t *enp = etp->et_enp; 603 const efx_tx_ops_t *etxop = enp->en_etxop; 604 605 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 606 607 return (etxop->etxo_qdesc_post(etp, ed, ndescs, completed, addedp)); 608 } 609 610 void 611 efx_tx_qdesc_dma_create( 612 __in efx_txq_t *etp, 613 __in efsys_dma_addr_t addr, 614 __in size_t size, 615 __in boolean_t eop, 616 __out efx_desc_t *edp) 617 { 618 efx_nic_t *enp = etp->et_enp; 619 const efx_tx_ops_t *etxop = enp->en_etxop; 620 621 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 622 EFSYS_ASSERT(etxop->etxo_qdesc_dma_create != NULL); 623 624 etxop->etxo_qdesc_dma_create(etp, addr, size, eop, edp); 625 } 626 627 void 628 efx_tx_qdesc_tso_create( 629 __in efx_txq_t *etp, 630 __in uint16_t ipv4_id, 631 __in uint32_t tcp_seq, 632 __in uint8_t tcp_flags, 633 __out efx_desc_t *edp) 634 { 635 efx_nic_t *enp = etp->et_enp; 636 const efx_tx_ops_t *etxop = enp->en_etxop; 637 638 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 639 EFSYS_ASSERT(etxop->etxo_qdesc_tso_create != NULL); 640 641 etxop->etxo_qdesc_tso_create(etp, ipv4_id, tcp_seq, tcp_flags, edp); 642 } 643 644 void 645 efx_tx_qdesc_tso2_create( 646 __in efx_txq_t *etp, 647 __in uint16_t ipv4_id, 648 __in uint16_t outer_ipv4_id, 649 __in uint32_t tcp_seq, 650 __in uint16_t mss, 651 __out_ecount(count) efx_desc_t *edp, 652 __in int count) 653 { 654 efx_nic_t *enp = etp->et_enp; 655 const efx_tx_ops_t *etxop = enp->en_etxop; 656 657 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 658 EFSYS_ASSERT(etxop->etxo_qdesc_tso2_create != NULL); 659 660 etxop->etxo_qdesc_tso2_create(etp, ipv4_id, outer_ipv4_id, 661 tcp_seq, mss, edp, count); 662 } 663 664 void 665 efx_tx_qdesc_vlantci_create( 666 __in efx_txq_t *etp, 667 __in uint16_t tci, 668 __out efx_desc_t *edp) 669 { 670 efx_nic_t *enp = etp->et_enp; 671 const efx_tx_ops_t *etxop = enp->en_etxop; 672 673 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 674 EFSYS_ASSERT(etxop->etxo_qdesc_vlantci_create != NULL); 675 676 etxop->etxo_qdesc_vlantci_create(etp, tci, edp); 677 } 678 679 void 680 efx_tx_qdesc_checksum_create( 681 __in efx_txq_t *etp, 682 __in uint16_t flags, 683 __out efx_desc_t *edp) 684 { 685 efx_nic_t *enp = etp->et_enp; 686 const efx_tx_ops_t *etxop = enp->en_etxop; 687 688 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 689 EFSYS_ASSERT(etxop->etxo_qdesc_checksum_create != NULL); 690 691 etxop->etxo_qdesc_checksum_create(etp, flags, edp); 692 } 693 694 695 #if EFSYS_OPT_QSTATS 696 void 697 efx_tx_qstats_update( 698 __in efx_txq_t *etp, 699 __inout_ecount(TX_NQSTATS) efsys_stat_t *stat) 700 { 701 efx_nic_t *enp = etp->et_enp; 702 const efx_tx_ops_t *etxop = enp->en_etxop; 703 704 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 705 706 etxop->etxo_qstats_update(etp, stat); 707 } 708 #endif 709 710 711 #if EFSYS_OPT_SIENA 712 713 static __checkReturn efx_rc_t 714 siena_tx_init( 715 __in efx_nic_t *enp) 716 { 717 efx_oword_t oword; 718 719 /* 720 * Disable the timer-based TX DMA backoff and allow TX DMA to be 721 * controlled by the RX FIFO fill level (although always allow a 722 * minimal trickle). 723 */ 724 EFX_BAR_READO(enp, FR_AZ_TX_RESERVED_REG, &oword); 725 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_RX_SPACER, 0xfe); 726 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_RX_SPACER_EN, 1); 727 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_ONE_PKT_PER_Q, 1); 728 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PUSH_EN, 0); 729 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DIS_NON_IP_EV, 1); 730 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PREF_THRESHOLD, 2); 731 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PREF_WD_TMR, 0x3fffff); 732 733 /* 734 * Filter all packets less than 14 bytes to avoid parsing 735 * errors. 736 */ 737 EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1); 738 EFX_BAR_WRITEO(enp, FR_AZ_TX_RESERVED_REG, &oword); 739 740 /* 741 * Do not set TX_NO_EOP_DISC_EN, since it limits packets to 16 742 * descriptors (which is bad). 743 */ 744 EFX_BAR_READO(enp, FR_AZ_TX_CFG_REG, &oword); 745 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_NO_EOP_DISC_EN, 0); 746 EFX_BAR_WRITEO(enp, FR_AZ_TX_CFG_REG, &oword); 747 748 return (0); 749 } 750 751 #define EFX_TX_DESC(_etp, _addr, _size, _eop, _added) \ 752 do { \ 753 unsigned int id; \ 754 size_t offset; \ 755 efx_qword_t qword; \ 756 \ 757 id = (_added)++ & (_etp)->et_mask; \ 758 offset = id * sizeof (efx_qword_t); \ 759 \ 760 EFSYS_PROBE5(tx_post, unsigned int, (_etp)->et_index, \ 761 unsigned int, id, efsys_dma_addr_t, (_addr), \ 762 size_t, (_size), boolean_t, (_eop)); \ 763 \ 764 EFX_POPULATE_QWORD_4(qword, \ 765 FSF_AZ_TX_KER_CONT, (_eop) ? 0 : 1, \ 766 FSF_AZ_TX_KER_BYTE_COUNT, (uint32_t)(_size), \ 767 FSF_AZ_TX_KER_BUF_ADDR_DW0, \ 768 (uint32_t)((_addr) & 0xffffffff), \ 769 FSF_AZ_TX_KER_BUF_ADDR_DW1, \ 770 (uint32_t)((_addr) >> 32)); \ 771 EFSYS_MEM_WRITEQ((_etp)->et_esmp, offset, &qword); \ 772 \ 773 _NOTE(CONSTANTCONDITION) \ 774 } while (B_FALSE) 775 776 static __checkReturn efx_rc_t 777 siena_tx_qpost( 778 __in efx_txq_t *etp, 779 __in_ecount(ndescs) efx_buffer_t *eb, 780 __in unsigned int ndescs, 781 __in unsigned int completed, 782 __inout unsigned int *addedp) 783 { 784 unsigned int added = *addedp; 785 unsigned int i; 786 787 if (added - completed + ndescs > EFX_TXQ_LIMIT(etp->et_mask + 1)) 788 return (ENOSPC); 789 790 for (i = 0; i < ndescs; i++) { 791 efx_buffer_t *ebp = &eb[i]; 792 efsys_dma_addr_t start = ebp->eb_addr; 793 size_t size = ebp->eb_size; 794 efsys_dma_addr_t end = start + size; 795 796 /* 797 * Fragments must not span 4k boundaries. 798 * Here it is a stricter requirement than the maximum length. 799 */ 800 EFSYS_ASSERT(EFX_P2ROUNDUP(efsys_dma_addr_t, start + 1, 801 etp->et_enp->en_nic_cfg.enc_tx_dma_desc_boundary) >= end); 802 803 EFX_TX_DESC(etp, start, size, ebp->eb_eop, added); 804 } 805 806 EFX_TX_QSTAT_INCR(etp, TX_POST); 807 808 *addedp = added; 809 return (0); 810 } 811 812 static void 813 siena_tx_qpush( 814 __in efx_txq_t *etp, 815 __in unsigned int added, 816 __in unsigned int pushed) 817 { 818 efx_nic_t *enp = etp->et_enp; 819 uint32_t wptr; 820 efx_dword_t dword; 821 efx_oword_t oword; 822 823 /* Push the populated descriptors out */ 824 wptr = added & etp->et_mask; 825 826 EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_DESC_WPTR, wptr); 827 828 /* Only write the third DWORD */ 829 EFX_POPULATE_DWORD_1(dword, 830 EFX_DWORD_0, EFX_OWORD_FIELD(oword, EFX_DWORD_3)); 831 832 /* Guarantee ordering of memory (descriptors) and PIO (doorbell) */ 833 EFX_DMA_SYNC_QUEUE_FOR_DEVICE(etp->et_esmp, etp->et_mask + 1, 834 wptr, pushed & etp->et_mask); 835 EFSYS_PIO_WRITE_BARRIER(); 836 EFX_BAR_TBL_WRITED3(enp, FR_BZ_TX_DESC_UPD_REGP0, 837 etp->et_index, &dword, B_FALSE); 838 } 839 840 #define EFX_MAX_PACE_VALUE 20 841 #define EFX_TX_PACE_CLOCK_BASE 104 842 843 static __checkReturn efx_rc_t 844 siena_tx_qpace( 845 __in efx_txq_t *etp, 846 __in unsigned int ns) 847 { 848 efx_nic_t *enp = etp->et_enp; 849 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 850 efx_oword_t oword; 851 unsigned int pace_val; 852 unsigned int timer_period; 853 efx_rc_t rc; 854 855 if (ns == 0) { 856 pace_val = 0; 857 } else { 858 /* 859 * The pace_val to write into the table is s.t 860 * ns <= timer_period * (2 ^ pace_val) 861 */ 862 timer_period = EFX_TX_PACE_CLOCK_BASE / encp->enc_clk_mult; 863 for (pace_val = 1; pace_val <= EFX_MAX_PACE_VALUE; pace_val++) { 864 if ((timer_period << pace_val) >= ns) 865 break; 866 } 867 } 868 if (pace_val > EFX_MAX_PACE_VALUE) { 869 rc = EINVAL; 870 goto fail1; 871 } 872 873 /* Update the pacing table */ 874 EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_PACE, pace_val); 875 EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_PACE_TBL, etp->et_index, 876 &oword, B_TRUE); 877 878 return (0); 879 880 fail1: 881 EFSYS_PROBE1(fail1, efx_rc_t, rc); 882 883 return (rc); 884 } 885 886 static __checkReturn efx_rc_t 887 siena_tx_qflush( 888 __in efx_txq_t *etp) 889 { 890 efx_nic_t *enp = etp->et_enp; 891 efx_oword_t oword; 892 uint32_t label; 893 894 efx_tx_qpace(etp, 0); 895 896 label = etp->et_index; 897 898 /* Flush the queue */ 899 EFX_POPULATE_OWORD_2(oword, FRF_AZ_TX_FLUSH_DESCQ_CMD, 1, 900 FRF_AZ_TX_FLUSH_DESCQ, label); 901 EFX_BAR_WRITEO(enp, FR_AZ_TX_FLUSH_DESCQ_REG, &oword); 902 903 return (0); 904 } 905 906 static void 907 siena_tx_qenable( 908 __in efx_txq_t *etp) 909 { 910 efx_nic_t *enp = etp->et_enp; 911 efx_oword_t oword; 912 913 EFX_BAR_TBL_READO(enp, FR_AZ_TX_DESC_PTR_TBL, 914 etp->et_index, &oword, B_TRUE); 915 916 EFSYS_PROBE5(tx_descq_ptr, unsigned int, etp->et_index, 917 uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_3), 918 uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_2), 919 uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_1), 920 uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_0)); 921 922 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DC_HW_RPTR, 0); 923 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DESCQ_HW_RPTR, 0); 924 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DESCQ_EN, 1); 925 926 EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL, 927 etp->et_index, &oword, B_TRUE); 928 } 929 930 static __checkReturn efx_rc_t 931 siena_tx_qcreate( 932 __in efx_nic_t *enp, 933 __in unsigned int index, 934 __in unsigned int label, 935 __in efsys_mem_t *esmp, 936 __in size_t ndescs, 937 __in uint32_t id, 938 __in uint16_t flags, 939 __in efx_evq_t *eep, 940 __in efx_txq_t *etp, 941 __out unsigned int *addedp) 942 { 943 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 944 efx_oword_t oword; 945 uint32_t size; 946 uint16_t inner_csum; 947 efx_rc_t rc; 948 949 _NOTE(ARGUNUSED(esmp)) 950 951 EFX_STATIC_ASSERT(EFX_EV_TX_NLABELS == 952 (1 << FRF_AZ_TX_DESCQ_LABEL_WIDTH)); 953 EFSYS_ASSERT3U(label, <, EFX_EV_TX_NLABELS); 954 955 EFSYS_ASSERT(ISP2(encp->enc_txq_max_ndescs)); 956 EFX_STATIC_ASSERT(ISP2(EFX_TXQ_MINNDESCS)); 957 958 if (!ISP2(ndescs) || 959 (ndescs < EFX_TXQ_MINNDESCS) || (ndescs > EFX_EVQ_MAXNEVS)) { 960 rc = EINVAL; 961 goto fail1; 962 } 963 if (index >= encp->enc_txq_limit) { 964 rc = EINVAL; 965 goto fail2; 966 } 967 for (size = 0; 968 (1 << size) <= (int)(encp->enc_txq_max_ndescs / EFX_TXQ_MINNDESCS); 969 size++) 970 if ((1 << size) == (int)(ndescs / EFX_TXQ_MINNDESCS)) 971 break; 972 if (id + (1 << size) >= encp->enc_buftbl_limit) { 973 rc = EINVAL; 974 goto fail3; 975 } 976 977 inner_csum = EFX_TXQ_CKSUM_INNER_IPV4 | EFX_TXQ_CKSUM_INNER_TCPUDP; 978 if ((flags & inner_csum) != 0) { 979 rc = EINVAL; 980 goto fail4; 981 } 982 983 /* Set up the new descriptor queue */ 984 *addedp = 0; 985 986 EFX_POPULATE_OWORD_6(oword, 987 FRF_AZ_TX_DESCQ_BUF_BASE_ID, id, 988 FRF_AZ_TX_DESCQ_EVQ_ID, eep->ee_index, 989 FRF_AZ_TX_DESCQ_OWNER_ID, 0, 990 FRF_AZ_TX_DESCQ_LABEL, label, 991 FRF_AZ_TX_DESCQ_SIZE, size, 992 FRF_AZ_TX_DESCQ_TYPE, 0); 993 994 EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_NON_IP_DROP_DIS, 1); 995 EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_IP_CHKSM_DIS, 996 (flags & EFX_TXQ_CKSUM_IPV4) ? 0 : 1); 997 EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_TCP_CHKSM_DIS, 998 (flags & EFX_TXQ_CKSUM_TCPUDP) ? 0 : 1); 999 1000 EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL, 1001 etp->et_index, &oword, B_TRUE); 1002 1003 return (0); 1004 1005 fail4: 1006 EFSYS_PROBE(fail4); 1007 fail3: 1008 EFSYS_PROBE(fail3); 1009 fail2: 1010 EFSYS_PROBE(fail2); 1011 fail1: 1012 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1013 1014 return (rc); 1015 } 1016 1017 __checkReturn efx_rc_t 1018 siena_tx_qdesc_post( 1019 __in efx_txq_t *etp, 1020 __in_ecount(ndescs) efx_desc_t *ed, 1021 __in unsigned int ndescs, 1022 __in unsigned int completed, 1023 __inout unsigned int *addedp) 1024 { 1025 unsigned int added = *addedp; 1026 unsigned int i; 1027 efx_rc_t rc; 1028 1029 if (added - completed + ndescs > EFX_TXQ_LIMIT(etp->et_mask + 1)) { 1030 rc = ENOSPC; 1031 goto fail1; 1032 } 1033 1034 for (i = 0; i < ndescs; i++) { 1035 efx_desc_t *edp = &ed[i]; 1036 unsigned int id; 1037 size_t offset; 1038 1039 id = added++ & etp->et_mask; 1040 offset = id * sizeof (efx_desc_t); 1041 1042 EFSYS_MEM_WRITEQ(etp->et_esmp, offset, &edp->ed_eq); 1043 } 1044 1045 EFSYS_PROBE3(tx_desc_post, unsigned int, etp->et_index, 1046 unsigned int, added, unsigned int, ndescs); 1047 1048 EFX_TX_QSTAT_INCR(etp, TX_POST); 1049 1050 *addedp = added; 1051 return (0); 1052 1053 fail1: 1054 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1055 return (rc); 1056 } 1057 1058 void 1059 siena_tx_qdesc_dma_create( 1060 __in efx_txq_t *etp, 1061 __in efsys_dma_addr_t addr, 1062 __in size_t size, 1063 __in boolean_t eop, 1064 __out efx_desc_t *edp) 1065 { 1066 /* 1067 * Fragments must not span 4k boundaries. 1068 * Here it is a stricter requirement than the maximum length. 1069 */ 1070 EFSYS_ASSERT(EFX_P2ROUNDUP(efsys_dma_addr_t, addr + 1, 1071 etp->et_enp->en_nic_cfg.enc_tx_dma_desc_boundary) >= addr + size); 1072 1073 EFSYS_PROBE4(tx_desc_dma_create, unsigned int, etp->et_index, 1074 efsys_dma_addr_t, addr, 1075 size_t, size, boolean_t, eop); 1076 1077 EFX_POPULATE_QWORD_4(edp->ed_eq, 1078 FSF_AZ_TX_KER_CONT, eop ? 0 : 1, 1079 FSF_AZ_TX_KER_BYTE_COUNT, (uint32_t)size, 1080 FSF_AZ_TX_KER_BUF_ADDR_DW0, 1081 (uint32_t)(addr & 0xffffffff), 1082 FSF_AZ_TX_KER_BUF_ADDR_DW1, 1083 (uint32_t)(addr >> 32)); 1084 } 1085 1086 #endif /* EFSYS_OPT_SIENA */ 1087 1088 #if EFSYS_OPT_QSTATS 1089 #if EFSYS_OPT_NAMES 1090 /* START MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock 2866874ecd7a363b */ 1091 static const char * const __efx_tx_qstat_name[] = { 1092 "post", 1093 "post_pio", 1094 }; 1095 /* END MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock */ 1096 1097 const char * 1098 efx_tx_qstat_name( 1099 __in efx_nic_t *enp, 1100 __in unsigned int id) 1101 { 1102 _NOTE(ARGUNUSED(enp)) 1103 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1104 EFSYS_ASSERT3U(id, <, TX_NQSTATS); 1105 1106 return (__efx_tx_qstat_name[id]); 1107 } 1108 #endif /* EFSYS_OPT_NAMES */ 1109 #endif /* EFSYS_OPT_QSTATS */ 1110 1111 #if EFSYS_OPT_SIENA 1112 1113 #if EFSYS_OPT_QSTATS 1114 static void 1115 siena_tx_qstats_update( 1116 __in efx_txq_t *etp, 1117 __inout_ecount(TX_NQSTATS) efsys_stat_t *stat) 1118 { 1119 unsigned int id; 1120 1121 for (id = 0; id < TX_NQSTATS; id++) { 1122 efsys_stat_t *essp = &stat[id]; 1123 1124 EFSYS_STAT_INCR(essp, etp->et_stat[id]); 1125 etp->et_stat[id] = 0; 1126 } 1127 } 1128 #endif /* EFSYS_OPT_QSTATS */ 1129 1130 static void 1131 siena_tx_qdestroy( 1132 __in efx_txq_t *etp) 1133 { 1134 efx_nic_t *enp = etp->et_enp; 1135 efx_oword_t oword; 1136 1137 /* Purge descriptor queue */ 1138 EFX_ZERO_OWORD(oword); 1139 1140 EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL, 1141 etp->et_index, &oword, B_TRUE); 1142 } 1143 1144 static void 1145 siena_tx_fini( 1146 __in efx_nic_t *enp) 1147 { 1148 _NOTE(ARGUNUSED(enp)) 1149 } 1150 1151 #endif /* EFSYS_OPT_SIENA */ 1152