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