1227569Sphilip/*- 2227569Sphilip * Copyright 2007-2009 Solarflare Communications Inc. All rights reserved. 3227569Sphilip * 4227569Sphilip * Redistribution and use in source and binary forms, with or without 5227569Sphilip * modification, are permitted provided that the following conditions 6227569Sphilip * are met: 7227569Sphilip * 1. Redistributions of source code must retain the above copyright 8227569Sphilip * notice, this list of conditions and the following disclaimer. 9227569Sphilip * 2. Redistributions in binary form must reproduce the above copyright 10227569Sphilip * notice, this list of conditions and the following disclaimer in the 11227569Sphilip * documentation and/or other materials provided with the distribution. 12227569Sphilip * 13227569Sphilip * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND 14227569Sphilip * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15227569Sphilip * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16227569Sphilip * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17227569Sphilip * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18227569Sphilip * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19227569Sphilip * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20227569Sphilip * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21227569Sphilip * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22227569Sphilip * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23227569Sphilip * SUCH DAMAGE. 24227569Sphilip */ 25227569Sphilip 26228078Sphilip#include <sys/cdefs.h> 27228078Sphilip__FBSDID("$FreeBSD$"); 28228078Sphilip 29227569Sphilip#include "efsys.h" 30227569Sphilip#include "efx.h" 31227569Sphilip#include "efx_types.h" 32227569Sphilip#include "efx_regs.h" 33227569Sphilip#include "efx_impl.h" 34227569Sphilip 35227569Sphilip#if EFSYS_OPT_QSTATS 36227569Sphilip#define EFX_TX_QSTAT_INCR(_etp, _stat) \ 37227569Sphilip do { \ 38227569Sphilip (_etp)->et_stat[_stat]++; \ 39227569Sphilip _NOTE(CONSTANTCONDITION) \ 40227569Sphilip } while (B_FALSE) 41227569Sphilip#else 42227569Sphilip#define EFX_TX_QSTAT_INCR(_etp, _stat) 43227569Sphilip#endif 44227569Sphilip 45227569Sphilip __checkReturn int 46227569Sphilipefx_tx_init( 47227569Sphilip __in efx_nic_t *enp) 48227569Sphilip{ 49227569Sphilip efx_oword_t oword; 50227569Sphilip int rc; 51227569Sphilip 52227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 53227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 54227569Sphilip 55227569Sphilip if (!(enp->en_mod_flags & EFX_MOD_EV)) { 56227569Sphilip rc = EINVAL; 57227569Sphilip goto fail1; 58227569Sphilip } 59227569Sphilip 60227569Sphilip if (enp->en_mod_flags & EFX_MOD_TX) { 61227569Sphilip rc = EINVAL; 62227569Sphilip goto fail2; 63227569Sphilip } 64227569Sphilip 65227569Sphilip EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0); 66227569Sphilip 67227569Sphilip /* 68227569Sphilip * Disable the timer-based TX DMA backoff and allow TX DMA to be 69227569Sphilip * controlled by the RX FIFO fill level (although always allow a 70227569Sphilip * minimal trickle). 71227569Sphilip */ 72227569Sphilip EFX_BAR_READO(enp, FR_AZ_TX_RESERVED_REG, &oword); 73227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_RX_SPACER, 0xfe); 74227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_RX_SPACER_EN, 1); 75227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_ONE_PKT_PER_Q, 1); 76227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PUSH_EN, 0); 77227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DIS_NON_IP_EV, 1); 78227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PREF_THRESHOLD, 2); 79227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PREF_WD_TMR, 0x3fffff); 80227569Sphilip 81227569Sphilip /* 82227569Sphilip * Filter all packets less than 14 bytes to avoid parsing 83227569Sphilip * errors. 84227569Sphilip */ 85227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1); 86227569Sphilip EFX_BAR_WRITEO(enp, FR_AZ_TX_RESERVED_REG, &oword); 87227569Sphilip 88227569Sphilip /* 89227569Sphilip * Do not set TX_NO_EOP_DISC_EN, since it limits packets to 16 90227569Sphilip * descriptors (which is bad). 91227569Sphilip */ 92227569Sphilip EFX_BAR_READO(enp, FR_AZ_TX_CFG_REG, &oword); 93227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_NO_EOP_DISC_EN, 0); 94227569Sphilip EFX_BAR_WRITEO(enp, FR_AZ_TX_CFG_REG, &oword); 95227569Sphilip 96227569Sphilip enp->en_mod_flags |= EFX_MOD_TX; 97227569Sphilip return (0); 98227569Sphilip 99227569Sphilipfail2: 100227569Sphilip EFSYS_PROBE(fail2); 101227569Sphilipfail1: 102227569Sphilip EFSYS_PROBE1(fail1, int, rc); 103227569Sphilip 104227569Sphilip return (rc); 105227569Sphilip} 106227569Sphilip 107227569Sphilip#if EFSYS_OPT_FILTER 108227569Sphilipextern __checkReturn int 109227569Sphilipefx_tx_filter_insert( 110227569Sphilip __in efx_txq_t *etp, 111227569Sphilip __inout efx_filter_spec_t *spec) 112227569Sphilip{ 113227569Sphilip EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 114227569Sphilip EFSYS_ASSERT3P(spec, !=, NULL); 115227569Sphilip 116227569Sphilip spec->efs_dmaq_id = (uint16_t)etp->et_index; 117227569Sphilip return efx_filter_insert_filter(etp->et_enp, spec, B_FALSE); 118227569Sphilip} 119227569Sphilip#endif 120227569Sphilip 121227569Sphilip#if EFSYS_OPT_FILTER 122227569Sphilipextern __checkReturn int 123227569Sphilipefx_tx_filter_remove( 124227569Sphilip __in efx_txq_t *etp, 125227569Sphilip __inout efx_filter_spec_t *spec) 126227569Sphilip{ 127227569Sphilip EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 128227569Sphilip EFSYS_ASSERT3P(spec, !=, NULL); 129227569Sphilip 130227569Sphilip spec->efs_dmaq_id = (uint16_t)etp->et_index; 131227569Sphilip return efx_filter_remove_filter(etp->et_enp, spec); 132227569Sphilip} 133227569Sphilip#endif 134227569Sphilip 135227569Sphilip#define EFX_TX_DESC(_etp, _addr, _size, _eop, _added) \ 136227569Sphilip do { \ 137227569Sphilip unsigned int id; \ 138227569Sphilip size_t offset; \ 139227569Sphilip efx_qword_t qword; \ 140227569Sphilip \ 141227569Sphilip id = (_added)++ & (_etp)->et_mask; \ 142227569Sphilip offset = id * sizeof (efx_qword_t); \ 143227569Sphilip \ 144227569Sphilip EFSYS_PROBE5(tx_post, unsigned int, (_etp)->et_index, \ 145227569Sphilip unsigned int, id, efsys_dma_addr_t, (_addr), \ 146227569Sphilip size_t, (_size), boolean_t, (_eop)); \ 147227569Sphilip \ 148227569Sphilip EFX_POPULATE_QWORD_4(qword, \ 149227569Sphilip FSF_AZ_TX_KER_CONT, (_eop) ? 0 : 1, \ 150227569Sphilip FSF_AZ_TX_KER_BYTE_COUNT, (uint32_t)(_size), \ 151227569Sphilip FSF_AZ_TX_KER_BUF_ADDR_DW0, \ 152227569Sphilip (uint32_t)((_addr) & 0xffffffff), \ 153227569Sphilip FSF_AZ_TX_KER_BUF_ADDR_DW1, \ 154227569Sphilip (uint32_t)((_addr) >> 32)); \ 155227569Sphilip EFSYS_MEM_WRITEQ((_etp)->et_esmp, offset, &qword); \ 156227569Sphilip \ 157227569Sphilip _NOTE(CONSTANTCONDITION) \ 158227569Sphilip } while (B_FALSE) 159227569Sphilip 160227569Sphilip __checkReturn int 161227569Sphilipefx_tx_qpost( 162227569Sphilip __in efx_txq_t *etp, 163227569Sphilip __in_ecount(n) efx_buffer_t *eb, 164227569Sphilip __in unsigned int n, 165227569Sphilip __in unsigned int completed, 166227569Sphilip __inout unsigned int *addedp) 167227569Sphilip{ 168227569Sphilip unsigned int added = *addedp; 169227569Sphilip unsigned int i; 170227569Sphilip int rc = ENOSPC; 171227569Sphilip 172227569Sphilip EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 173227569Sphilip 174227569Sphilip if (added - completed + n > EFX_TXQ_LIMIT(etp->et_mask + 1)) 175227569Sphilip goto fail1; 176227569Sphilip 177227569Sphilip for (i = 0; i < n; i++) { 178227569Sphilip efx_buffer_t *ebp = &eb[i]; 179227569Sphilip efsys_dma_addr_t start = ebp->eb_addr; 180227569Sphilip size_t size = ebp->eb_size; 181227569Sphilip efsys_dma_addr_t end = start + size; 182227569Sphilip 183227569Sphilip /* Fragments must not span 4k boundaries. */ 184227569Sphilip EFSYS_ASSERT(P2ROUNDUP(start + 1, 4096) >= end); 185227569Sphilip 186227569Sphilip EFX_TX_DESC(etp, start, size, ebp->eb_eop, added); 187227569Sphilip } 188227569Sphilip 189227569Sphilip EFX_TX_QSTAT_INCR(etp, TX_POST); 190227569Sphilip 191227569Sphilip *addedp = added; 192227569Sphilip return (0); 193227569Sphilip 194227569Sphilipfail1: 195227569Sphilip EFSYS_PROBE1(fail1, int, rc); 196227569Sphilip 197227569Sphilip return (rc); 198227569Sphilip} 199227569Sphilip 200227569Sphilip void 201227569Sphilipefx_tx_qpush( 202227569Sphilip __in efx_txq_t *etp, 203227569Sphilip __in unsigned int added) 204227569Sphilip{ 205227569Sphilip efx_nic_t *enp = etp->et_enp; 206227569Sphilip uint32_t wptr; 207227569Sphilip efx_dword_t dword; 208227569Sphilip efx_oword_t oword; 209227569Sphilip 210227569Sphilip EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 211227569Sphilip 212227569Sphilip /* Guarantee ordering of memory (descriptors) and PIO (doorbell) */ 213227569Sphilip EFSYS_PIO_WRITE_BARRIER(); 214227569Sphilip 215227569Sphilip /* Push the populated descriptors out */ 216227569Sphilip wptr = added & etp->et_mask; 217227569Sphilip 218227569Sphilip EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_DESC_WPTR, wptr); 219227569Sphilip 220227569Sphilip /* Only write the third DWORD */ 221227569Sphilip EFX_POPULATE_DWORD_1(dword, 222227569Sphilip EFX_DWORD_0, EFX_OWORD_FIELD(oword, EFX_DWORD_3)); 223227569Sphilip EFX_BAR_TBL_WRITED3(enp, FR_BZ_TX_DESC_UPD_REGP0, 224227569Sphilip etp->et_index, &dword, B_FALSE); 225227569Sphilip} 226227569Sphilip 227227569Sphilip void 228227569Sphilipefx_tx_qflush( 229227569Sphilip __in efx_txq_t *etp) 230227569Sphilip{ 231227569Sphilip efx_nic_t *enp = etp->et_enp; 232227569Sphilip efx_oword_t oword; 233227569Sphilip uint32_t label; 234227569Sphilip 235227569Sphilip EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 236227569Sphilip 237227569Sphilip label = etp->et_index; 238227569Sphilip 239227569Sphilip /* Flush the queue */ 240227569Sphilip EFX_POPULATE_OWORD_2(oword, FRF_AZ_TX_FLUSH_DESCQ_CMD, 1, 241227569Sphilip FRF_AZ_TX_FLUSH_DESCQ, label); 242227569Sphilip EFX_BAR_WRITEO(enp, FR_AZ_TX_FLUSH_DESCQ_REG, &oword); 243227569Sphilip} 244227569Sphilip 245227569Sphilip void 246227569Sphilipefx_tx_qenable( 247227569Sphilip __in efx_txq_t *etp) 248227569Sphilip{ 249227569Sphilip efx_nic_t *enp = etp->et_enp; 250227569Sphilip efx_oword_t oword; 251227569Sphilip 252227569Sphilip EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 253227569Sphilip 254227569Sphilip EFX_BAR_TBL_READO(enp, FR_AZ_TX_DESC_PTR_TBL, 255227569Sphilip etp->et_index, &oword); 256227569Sphilip 257227569Sphilip EFSYS_PROBE5(tx_descq_ptr, unsigned int, etp->et_index, 258227569Sphilip uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_3), 259227569Sphilip uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_2), 260227569Sphilip uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_1), 261227569Sphilip uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_0)); 262227569Sphilip 263227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DC_HW_RPTR, 0); 264227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DESCQ_HW_RPTR, 0); 265227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DESCQ_EN, 1); 266227569Sphilip 267227569Sphilip EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL, 268227569Sphilip etp->et_index, &oword); 269227569Sphilip} 270227569Sphilip 271227569Sphilip __checkReturn int 272227569Sphilipefx_tx_qcreate( 273227569Sphilip __in efx_nic_t *enp, 274227569Sphilip __in unsigned int index, 275227569Sphilip __in unsigned int label, 276227569Sphilip __in efsys_mem_t *esmp, 277227569Sphilip __in size_t n, 278227569Sphilip __in uint32_t id, 279227569Sphilip __in uint16_t flags, 280227569Sphilip __in efx_evq_t *eep, 281227569Sphilip __deref_out efx_txq_t **etpp) 282227569Sphilip{ 283227569Sphilip efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 284227569Sphilip efx_txq_t *etp; 285227569Sphilip efx_oword_t oword; 286227569Sphilip uint32_t size; 287227569Sphilip int rc; 288227569Sphilip 289227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 290227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX); 291227569Sphilip 292227569Sphilip EFX_STATIC_ASSERT(EFX_EV_TX_NLABELS == (1 << FRF_AZ_TX_DESCQ_LABEL_WIDTH)); 293265884Sgnn /* EFSYS_ASSERT3U(label, <, EFX_EV_TX_NLABELS);*/ 294227569Sphilip EFSYS_ASSERT3U(enp->en_tx_qcount + 1, <, encp->enc_txq_limit); 295227569Sphilip 296227569Sphilip if (!ISP2(n) || !(n & EFX_TXQ_NDESCS_MASK)) { 297227569Sphilip rc = EINVAL; 298227569Sphilip goto fail1; 299227569Sphilip } 300227569Sphilip if (index >= encp->enc_txq_limit) { 301227569Sphilip rc = EINVAL; 302227569Sphilip goto fail2; 303227569Sphilip } 304227569Sphilip for (size = 0; (1 << size) <= (EFX_TXQ_MAXNDESCS / EFX_TXQ_MINNDESCS); 305227569Sphilip size++) 306227569Sphilip if ((1 << size) == (int)(n / EFX_TXQ_MINNDESCS)) 307227569Sphilip break; 308227569Sphilip if (id + (1 << size) >= encp->enc_buftbl_limit) { 309227569Sphilip rc = EINVAL; 310227569Sphilip goto fail3; 311227569Sphilip } 312227569Sphilip 313227569Sphilip /* Allocate an TXQ object */ 314227569Sphilip EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_txq_t), etp); 315227569Sphilip 316227569Sphilip if (etp == NULL) { 317227569Sphilip rc = ENOMEM; 318227569Sphilip goto fail4; 319227569Sphilip } 320227569Sphilip 321227569Sphilip etp->et_magic = EFX_TXQ_MAGIC; 322227569Sphilip etp->et_enp = enp; 323227569Sphilip etp->et_index = index; 324227569Sphilip etp->et_mask = n - 1; 325227569Sphilip etp->et_esmp = esmp; 326227569Sphilip 327227569Sphilip /* Set up the new descriptor queue */ 328227569Sphilip EFX_POPULATE_OWORD_6(oword, 329227569Sphilip FRF_AZ_TX_DESCQ_BUF_BASE_ID, id, 330227569Sphilip FRF_AZ_TX_DESCQ_EVQ_ID, eep->ee_index, 331227569Sphilip FRF_AZ_TX_DESCQ_OWNER_ID, 0, 332227569Sphilip FRF_AZ_TX_DESCQ_LABEL, label, 333227569Sphilip FRF_AZ_TX_DESCQ_SIZE, size, 334227569Sphilip FRF_AZ_TX_DESCQ_TYPE, 0); 335227569Sphilip 336227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_NON_IP_DROP_DIS, 1); 337227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_IP_CHKSM_DIS, 338227569Sphilip (flags & EFX_CKSUM_IPV4) ? 0 : 1); 339227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_TCP_CHKSM_DIS, 340227569Sphilip (flags & EFX_CKSUM_TCPUDP) ? 0 : 1); 341227569Sphilip 342227569Sphilip EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL, 343227569Sphilip etp->et_index, &oword); 344227569Sphilip 345227569Sphilip enp->en_tx_qcount++; 346227569Sphilip *etpp = etp; 347227569Sphilip return (0); 348227569Sphilip 349227569Sphilipfail4: 350227569Sphilip EFSYS_PROBE(fail4); 351227569Sphilipfail3: 352227569Sphilip EFSYS_PROBE(fail3); 353227569Sphilipfail2: 354227569Sphilip EFSYS_PROBE(fail2); 355227569Sphilipfail1: 356227569Sphilip EFSYS_PROBE1(fail1, int, rc); 357227569Sphilip 358227569Sphilip return (rc); 359227569Sphilip} 360227569Sphilip 361227569Sphilip#if EFSYS_OPT_NAMES 362227569Sphilip/* START MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock 78ca9ab00287fffb */ 363227569Sphilipstatic const char __cs * __cs __efx_tx_qstat_name[] = { 364227569Sphilip "post", 365227569Sphilip "unaligned_split", 366227569Sphilip}; 367227569Sphilip/* END MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock */ 368227569Sphilip 369227569Sphilip const char __cs * 370227569Sphilipefx_tx_qstat_name( 371227569Sphilip __in efx_nic_t *enp, 372227569Sphilip __in unsigned int id) 373227569Sphilip{ 374227569Sphilip _NOTE(ARGUNUSED(enp)) 375227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 376227569Sphilip EFSYS_ASSERT3U(id, <, TX_NQSTATS); 377227569Sphilip 378227569Sphilip return (__efx_tx_qstat_name[id]); 379227569Sphilip} 380227569Sphilip#endif /* EFSYS_OPT_NAMES */ 381227569Sphilip 382227569Sphilip#if EFSYS_OPT_QSTATS 383227569Sphilip void 384227569Sphilipefx_tx_qstats_update( 385227569Sphilip __in efx_txq_t *etp, 386227569Sphilip __inout_ecount(TX_NQSTATS) efsys_stat_t *stat) 387227569Sphilip{ 388227569Sphilip unsigned int id; 389227569Sphilip 390227569Sphilip EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 391227569Sphilip 392227569Sphilip for (id = 0; id < TX_NQSTATS; id++) { 393227569Sphilip efsys_stat_t *essp = &stat[id]; 394227569Sphilip 395227569Sphilip EFSYS_STAT_INCR(essp, etp->et_stat[id]); 396227569Sphilip etp->et_stat[id] = 0; 397227569Sphilip } 398227569Sphilip} 399227569Sphilip#endif /* EFSYS_OPT_QSTATS */ 400227569Sphilip 401227569Sphilip void 402227569Sphilipefx_tx_qdestroy( 403227569Sphilip __in efx_txq_t *etp) 404227569Sphilip{ 405227569Sphilip efx_nic_t *enp = etp->et_enp; 406227569Sphilip efx_oword_t oword; 407227569Sphilip 408227569Sphilip EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC); 409227569Sphilip 410227569Sphilip EFSYS_ASSERT(enp->en_tx_qcount != 0); 411227569Sphilip --enp->en_tx_qcount; 412227569Sphilip 413227569Sphilip /* Purge descriptor queue */ 414227569Sphilip EFX_ZERO_OWORD(oword); 415227569Sphilip 416227569Sphilip EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL, 417227569Sphilip etp->et_index, &oword); 418227569Sphilip 419227569Sphilip /* Free the TXQ object */ 420227569Sphilip EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_txq_t), etp); 421227569Sphilip} 422227569Sphilip 423227569Sphilip void 424227569Sphilipefx_tx_fini( 425227569Sphilip __in efx_nic_t *enp) 426227569Sphilip{ 427227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 428227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); 429227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX); 430227569Sphilip EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0); 431227569Sphilip 432227569Sphilip enp->en_mod_flags &= ~EFX_MOD_TX; 433227569Sphilip} 434