2 * Copyright (c) 2007-2015 Solarflare Communications Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
38 #define EFX_TX_QSTAT_INCR(_etp, _stat) \
40 (_etp)->et_stat[_stat]++; \
41 _NOTE(CONSTANTCONDITION) \
44 #define EFX_TX_QSTAT_INCR(_etp, _stat)
47 #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
49 static __checkReturn efx_rc_t
57 static __checkReturn efx_rc_t
58 falconsiena_tx_qcreate(
60 __in unsigned int index,
61 __in unsigned int label,
62 __in efsys_mem_t *esmp,
68 __out unsigned int *addedp);
71 falconsiena_tx_qdestroy(
74 static __checkReturn efx_rc_t
77 __in_ecount(n) efx_buffer_t *eb,
79 __in unsigned int completed,
80 __inout unsigned int *addedp);
85 __in unsigned int added,
86 __in unsigned int pushed);
88 static __checkReturn efx_rc_t
91 __in unsigned int ns);
93 static __checkReturn efx_rc_t
94 falconsiena_tx_qflush(
98 falconsiena_tx_qenable(
101 __checkReturn efx_rc_t
102 falconsiena_tx_qdesc_post(
104 __in_ecount(n) efx_desc_t *ed,
106 __in unsigned int completed,
107 __inout unsigned int *addedp);
110 falconsiena_tx_qdesc_dma_create(
112 __in efsys_dma_addr_t addr,
115 __out efx_desc_t *edp);
119 falconsiena_tx_qstats_update(
121 __inout_ecount(TX_NQSTATS) efsys_stat_t *stat);
124 #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
128 static efx_tx_ops_t __efx_tx_falcon_ops = {
129 falconsiena_tx_init, /* etxo_init */
130 falconsiena_tx_fini, /* etxo_fini */
131 falconsiena_tx_qcreate, /* etxo_qcreate */
132 falconsiena_tx_qdestroy, /* etxo_qdestroy */
133 falconsiena_tx_qpost, /* etxo_qpost */
134 falconsiena_tx_qpush, /* etxo_qpush */
135 falconsiena_tx_qpace, /* etxo_qpace */
136 falconsiena_tx_qflush, /* etxo_qflush */
137 falconsiena_tx_qenable, /* etxo_qenable */
138 NULL, /* etxo_qpio_enable */
139 NULL, /* etxo_qpio_disable */
140 NULL, /* etxo_qpio_write */
141 NULL, /* etxo_qpio_post */
142 falconsiena_tx_qdesc_post, /* etxo_qdesc_post */
143 falconsiena_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
144 NULL, /* etxo_qdesc_tso_create */
145 NULL, /* etxo_qdesc_tso2_create */
146 NULL, /* etxo_qdesc_vlantci_create */
148 falconsiena_tx_qstats_update, /* etxo_qstats_update */
151 #endif /* EFSYS_OPT_FALCON */
154 static efx_tx_ops_t __efx_tx_siena_ops = {
155 falconsiena_tx_init, /* etxo_init */
156 falconsiena_tx_fini, /* etxo_fini */
157 falconsiena_tx_qcreate, /* etxo_qcreate */
158 falconsiena_tx_qdestroy, /* etxo_qdestroy */
159 falconsiena_tx_qpost, /* etxo_qpost */
160 falconsiena_tx_qpush, /* etxo_qpush */
161 falconsiena_tx_qpace, /* etxo_qpace */
162 falconsiena_tx_qflush, /* etxo_qflush */
163 falconsiena_tx_qenable, /* etxo_qenable */
164 NULL, /* etxo_qpio_enable */
165 NULL, /* etxo_qpio_disable */
166 NULL, /* etxo_qpio_write */
167 NULL, /* etxo_qpio_post */
168 falconsiena_tx_qdesc_post, /* etxo_qdesc_post */
169 falconsiena_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
170 NULL, /* etxo_qdesc_tso_create */
171 NULL, /* etxo_qdesc_tso2_create */
172 NULL, /* etxo_qdesc_vlantci_create */
174 falconsiena_tx_qstats_update, /* etxo_qstats_update */
177 #endif /* EFSYS_OPT_SIENA */
179 #if EFSYS_OPT_HUNTINGTON
180 static efx_tx_ops_t __efx_tx_hunt_ops = {
181 ef10_tx_init, /* etxo_init */
182 ef10_tx_fini, /* etxo_fini */
183 ef10_tx_qcreate, /* etxo_qcreate */
184 ef10_tx_qdestroy, /* etxo_qdestroy */
185 ef10_tx_qpost, /* etxo_qpost */
186 ef10_tx_qpush, /* etxo_qpush */
187 ef10_tx_qpace, /* etxo_qpace */
188 ef10_tx_qflush, /* etxo_qflush */
189 ef10_tx_qenable, /* etxo_qenable */
190 ef10_tx_qpio_enable, /* etxo_qpio_enable */
191 ef10_tx_qpio_disable, /* etxo_qpio_disable */
192 ef10_tx_qpio_write, /* etxo_qpio_write */
193 ef10_tx_qpio_post, /* etxo_qpio_post */
194 ef10_tx_qdesc_post, /* etxo_qdesc_post */
195 ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
196 hunt_tx_qdesc_tso_create, /* etxo_qdesc_tso_create */
197 ef10_tx_qdesc_tso2_create, /* etxo_qdesc_tso2_create */
198 ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */
200 ef10_tx_qstats_update, /* etxo_qstats_update */
203 #endif /* EFSYS_OPT_HUNTINGTON */
205 #if EFSYS_OPT_MEDFORD
206 static efx_tx_ops_t __efx_tx_medford_ops = {
207 ef10_tx_init, /* etxo_init */
208 ef10_tx_fini, /* etxo_fini */
209 ef10_tx_qcreate, /* etxo_qcreate */
210 ef10_tx_qdestroy, /* etxo_qdestroy */
211 ef10_tx_qpost, /* etxo_qpost */
212 ef10_tx_qpush, /* etxo_qpush */
213 ef10_tx_qpace, /* etxo_qpace */
214 ef10_tx_qflush, /* etxo_qflush */
215 ef10_tx_qenable, /* etxo_qenable */
216 ef10_tx_qpio_enable, /* etxo_qpio_enable */
217 ef10_tx_qpio_disable, /* etxo_qpio_disable */
218 ef10_tx_qpio_write, /* etxo_qpio_write */
219 ef10_tx_qpio_post, /* etxo_qpio_post */
220 ef10_tx_qdesc_post, /* etxo_qdesc_post */
221 ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
222 NULL, /* etxo_qdesc_tso_create */
223 ef10_tx_qdesc_tso2_create, /* etxo_qdesc_tso2_create */
224 ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */
226 ef10_tx_qstats_update, /* etxo_qstats_update */
229 #endif /* EFSYS_OPT_MEDFORD */
231 __checkReturn efx_rc_t
238 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
239 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
241 if (!(enp->en_mod_flags & EFX_MOD_EV)) {
246 if (enp->en_mod_flags & EFX_MOD_TX) {
251 switch (enp->en_family) {
253 case EFX_FAMILY_FALCON:
254 etxop = (efx_tx_ops_t *)&__efx_tx_falcon_ops;
256 #endif /* EFSYS_OPT_FALCON */
259 case EFX_FAMILY_SIENA:
260 etxop = (efx_tx_ops_t *)&__efx_tx_siena_ops;
262 #endif /* EFSYS_OPT_SIENA */
264 #if EFSYS_OPT_HUNTINGTON
265 case EFX_FAMILY_HUNTINGTON:
266 etxop = (efx_tx_ops_t *)&__efx_tx_hunt_ops;
268 #endif /* EFSYS_OPT_HUNTINGTON */
270 #if EFSYS_OPT_MEDFORD
271 case EFX_FAMILY_MEDFORD:
272 etxop = (efx_tx_ops_t *)&__efx_tx_medford_ops;
274 #endif /* EFSYS_OPT_MEDFORD */
282 EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0);
284 if ((rc = etxop->etxo_init(enp)) != 0)
287 enp->en_etxop = etxop;
288 enp->en_mod_flags |= EFX_MOD_TX;
298 EFSYS_PROBE1(fail1, efx_rc_t, rc);
300 enp->en_etxop = NULL;
301 enp->en_mod_flags &= ~EFX_MOD_TX;
309 efx_tx_ops_t *etxop = enp->en_etxop;
311 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
312 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
313 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX);
314 EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0);
316 etxop->etxo_fini(enp);
318 enp->en_etxop = NULL;
319 enp->en_mod_flags &= ~EFX_MOD_TX;
322 __checkReturn efx_rc_t
325 __in unsigned int index,
326 __in unsigned int label,
327 __in efsys_mem_t *esmp,
332 __deref_out efx_txq_t **etpp,
333 __out unsigned int *addedp)
335 efx_tx_ops_t *etxop = enp->en_etxop;
336 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
340 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
341 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX);
343 EFSYS_ASSERT3U(enp->en_tx_qcount + 1, <, encp->enc_txq_limit);
345 /* Allocate an TXQ object */
346 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_txq_t), etp);
353 etp->et_magic = EFX_TXQ_MAGIC;
355 etp->et_index = index;
356 etp->et_mask = n - 1;
359 /* Initial descriptor index may be modified by etxo_qcreate */
362 if ((rc = etxop->etxo_qcreate(enp, index, label, esmp,
363 n, id, flags, eep, etp, addedp)) != 0)
373 EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_txq_t), etp);
375 EFSYS_PROBE1(fail1, efx_rc_t, rc);
383 efx_nic_t *enp = etp->et_enp;
384 efx_tx_ops_t *etxop = enp->en_etxop;
386 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
388 EFSYS_ASSERT(enp->en_tx_qcount != 0);
391 etxop->etxo_qdestroy(etp);
393 /* Free the TXQ object */
394 EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_txq_t), etp);
397 __checkReturn efx_rc_t
400 __in_ecount(n) efx_buffer_t *eb,
402 __in unsigned int completed,
403 __inout unsigned int *addedp)
405 efx_nic_t *enp = etp->et_enp;
406 efx_tx_ops_t *etxop = enp->en_etxop;
409 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
411 if ((rc = etxop->etxo_qpost(etp, eb,
412 n, completed, addedp)) != 0)
418 EFSYS_PROBE1(fail1, efx_rc_t, rc);
425 __in unsigned int added,
426 __in unsigned int pushed)
428 efx_nic_t *enp = etp->et_enp;
429 efx_tx_ops_t *etxop = enp->en_etxop;
431 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
433 etxop->etxo_qpush(etp, added, pushed);
436 __checkReturn efx_rc_t
439 __in unsigned int ns)
441 efx_nic_t *enp = etp->et_enp;
442 efx_tx_ops_t *etxop = enp->en_etxop;
445 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
447 if ((rc = etxop->etxo_qpace(etp, ns)) != 0)
453 EFSYS_PROBE1(fail1, efx_rc_t, rc);
457 __checkReturn efx_rc_t
461 efx_nic_t *enp = etp->et_enp;
462 efx_tx_ops_t *etxop = enp->en_etxop;
465 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
467 if ((rc = etxop->etxo_qflush(etp)) != 0)
473 EFSYS_PROBE1(fail1, efx_rc_t, rc);
481 efx_nic_t *enp = etp->et_enp;
482 efx_tx_ops_t *etxop = enp->en_etxop;
484 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
486 etxop->etxo_qenable(etp);
489 __checkReturn efx_rc_t
493 efx_nic_t *enp = etp->et_enp;
494 efx_tx_ops_t *etxop = enp->en_etxop;
497 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
499 if (~enp->en_features & EFX_FEATURE_PIO_BUFFERS) {
503 if (etxop->etxo_qpio_enable == NULL) {
507 if ((rc = etxop->etxo_qpio_enable(etp)) != 0)
517 EFSYS_PROBE1(fail1, efx_rc_t, rc);
525 efx_nic_t *enp = etp->et_enp;
526 efx_tx_ops_t *etxop = enp->en_etxop;
528 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
530 if (etxop->etxo_qpio_disable != NULL)
531 etxop->etxo_qpio_disable(etp);
534 __checkReturn efx_rc_t
537 __in_ecount(buf_length) uint8_t *buffer,
538 __in size_t buf_length,
539 __in size_t pio_buf_offset)
541 efx_nic_t *enp = etp->et_enp;
542 efx_tx_ops_t *etxop = enp->en_etxop;
545 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
547 if (etxop->etxo_qpio_write != NULL) {
548 if ((rc = etxop->etxo_qpio_write(etp, buffer, buf_length,
549 pio_buf_offset)) != 0)
557 EFSYS_PROBE1(fail1, efx_rc_t, rc);
561 __checkReturn efx_rc_t
564 __in size_t pkt_length,
565 __in unsigned int completed,
566 __inout unsigned int *addedp)
568 efx_nic_t *enp = etp->et_enp;
569 efx_tx_ops_t *etxop = enp->en_etxop;
572 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
574 if (etxop->etxo_qpio_post != NULL) {
575 if ((rc = etxop->etxo_qpio_post(etp, pkt_length, completed,
584 EFSYS_PROBE1(fail1, efx_rc_t, rc);
588 __checkReturn efx_rc_t
591 __in_ecount(n) efx_desc_t *ed,
593 __in unsigned int completed,
594 __inout unsigned int *addedp)
596 efx_nic_t *enp = etp->et_enp;
597 efx_tx_ops_t *etxop = enp->en_etxop;
600 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
602 if ((rc = etxop->etxo_qdesc_post(etp, ed,
603 n, completed, addedp)) != 0)
609 EFSYS_PROBE1(fail1, efx_rc_t, rc);
614 efx_tx_qdesc_dma_create(
616 __in efsys_dma_addr_t addr,
619 __out efx_desc_t *edp)
621 efx_nic_t *enp = etp->et_enp;
622 efx_tx_ops_t *etxop = enp->en_etxop;
624 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
625 EFSYS_ASSERT(etxop->etxo_qdesc_dma_create != NULL);
627 etxop->etxo_qdesc_dma_create(etp, addr, size, eop, edp);
631 efx_tx_qdesc_tso_create(
633 __in uint16_t ipv4_id,
634 __in uint32_t tcp_seq,
635 __in uint8_t tcp_flags,
636 __out efx_desc_t *edp)
638 efx_nic_t *enp = etp->et_enp;
639 efx_tx_ops_t *etxop = enp->en_etxop;
641 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
642 EFSYS_ASSERT(etxop->etxo_qdesc_tso_create != NULL);
644 etxop->etxo_qdesc_tso_create(etp, ipv4_id, tcp_seq, tcp_flags, edp);
648 efx_tx_qdesc_tso2_create(
650 __in uint16_t ipv4_id,
651 __in uint32_t tcp_seq,
653 __out_ecount(count) efx_desc_t *edp,
656 efx_nic_t *enp = etp->et_enp;
657 efx_tx_ops_t *etxop = enp->en_etxop;
659 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
660 EFSYS_ASSERT(etxop->etxo_qdesc_tso2_create != NULL);
662 etxop->etxo_qdesc_tso2_create(etp, ipv4_id, tcp_seq, mss, edp, count);
666 efx_tx_qdesc_vlantci_create(
669 __out efx_desc_t *edp)
671 efx_nic_t *enp = etp->et_enp;
672 efx_tx_ops_t *etxop = enp->en_etxop;
674 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
675 EFSYS_ASSERT(etxop->etxo_qdesc_vlantci_create != NULL);
677 etxop->etxo_qdesc_vlantci_create(etp, tci, edp);
683 efx_tx_qstats_update(
685 __inout_ecount(TX_NQSTATS) efsys_stat_t *stat)
687 efx_nic_t *enp = etp->et_enp;
688 efx_tx_ops_t *etxop = enp->en_etxop;
690 EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
692 etxop->etxo_qstats_update(etp, stat);
697 #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
699 static __checkReturn efx_rc_t
706 * Disable the timer-based TX DMA backoff and allow TX DMA to be
707 * controlled by the RX FIFO fill level (although always allow a
710 EFX_BAR_READO(enp, FR_AZ_TX_RESERVED_REG, &oword);
711 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_RX_SPACER, 0xfe);
712 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_RX_SPACER_EN, 1);
713 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_ONE_PKT_PER_Q, 1);
714 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PUSH_EN, 0);
715 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DIS_NON_IP_EV, 1);
716 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PREF_THRESHOLD, 2);
717 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PREF_WD_TMR, 0x3fffff);
720 * Filter all packets less than 14 bytes to avoid parsing
723 EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1);
724 EFX_BAR_WRITEO(enp, FR_AZ_TX_RESERVED_REG, &oword);
727 * Do not set TX_NO_EOP_DISC_EN, since it limits packets to 16
728 * descriptors (which is bad).
730 EFX_BAR_READO(enp, FR_AZ_TX_CFG_REG, &oword);
731 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_NO_EOP_DISC_EN, 0);
732 EFX_BAR_WRITEO(enp, FR_AZ_TX_CFG_REG, &oword);
737 #define EFX_TX_DESC(_etp, _addr, _size, _eop, _added) \
743 id = (_added)++ & (_etp)->et_mask; \
744 offset = id * sizeof (efx_qword_t); \
746 EFSYS_PROBE5(tx_post, unsigned int, (_etp)->et_index, \
747 unsigned int, id, efsys_dma_addr_t, (_addr), \
748 size_t, (_size), boolean_t, (_eop)); \
750 EFX_POPULATE_QWORD_4(qword, \
751 FSF_AZ_TX_KER_CONT, (_eop) ? 0 : 1, \
752 FSF_AZ_TX_KER_BYTE_COUNT, (uint32_t)(_size), \
753 FSF_AZ_TX_KER_BUF_ADDR_DW0, \
754 (uint32_t)((_addr) & 0xffffffff), \
755 FSF_AZ_TX_KER_BUF_ADDR_DW1, \
756 (uint32_t)((_addr) >> 32)); \
757 EFSYS_MEM_WRITEQ((_etp)->et_esmp, offset, &qword); \
759 _NOTE(CONSTANTCONDITION) \
762 static __checkReturn efx_rc_t
763 falconsiena_tx_qpost(
765 __in_ecount(n) efx_buffer_t *eb,
767 __in unsigned int completed,
768 __inout unsigned int *addedp)
770 unsigned int added = *addedp;
774 if (added - completed + n > EFX_TXQ_LIMIT(etp->et_mask + 1))
777 for (i = 0; i < n; i++) {
778 efx_buffer_t *ebp = &eb[i];
779 efsys_dma_addr_t start = ebp->eb_addr;
780 size_t size = ebp->eb_size;
781 efsys_dma_addr_t end = start + size;
783 /* Fragments must not span 4k boundaries. */
784 EFSYS_ASSERT(P2ROUNDUP(start + 1, 4096) >= end);
786 EFX_TX_DESC(etp, start, size, ebp->eb_eop, added);
789 EFX_TX_QSTAT_INCR(etp, TX_POST);
795 EFSYS_PROBE1(fail1, efx_rc_t, rc);
801 falconsiena_tx_qpush(
803 __in unsigned int added,
804 __in unsigned int pushed)
806 efx_nic_t *enp = etp->et_enp;
811 /* Push the populated descriptors out */
812 wptr = added & etp->et_mask;
814 EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_DESC_WPTR, wptr);
816 /* Only write the third DWORD */
817 EFX_POPULATE_DWORD_1(dword,
818 EFX_DWORD_0, EFX_OWORD_FIELD(oword, EFX_DWORD_3));
820 /* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
821 EFX_DMA_SYNC_QUEUE_FOR_DEVICE(etp->et_esmp, etp->et_mask + 1,
822 wptr, pushed & etp->et_mask);
823 EFSYS_PIO_WRITE_BARRIER();
824 EFX_BAR_TBL_WRITED3(enp, FR_BZ_TX_DESC_UPD_REGP0,
825 etp->et_index, &dword, B_FALSE);
828 #define EFX_MAX_PACE_VALUE 20
829 #define EFX_TX_PACE_CLOCK_BASE 104
831 static __checkReturn efx_rc_t
832 falconsiena_tx_qpace(
834 __in unsigned int ns)
836 efx_nic_t *enp = etp->et_enp;
837 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
839 unsigned int pace_val;
840 unsigned int timer_period;
847 * The pace_val to write into the table is s.t
848 * ns <= timer_period * (2 ^ pace_val)
850 timer_period = EFX_TX_PACE_CLOCK_BASE / encp->enc_clk_mult;
851 for (pace_val = 1; pace_val <= EFX_MAX_PACE_VALUE; pace_val++) {
852 if ((timer_period << pace_val) >= ns)
856 if (pace_val > EFX_MAX_PACE_VALUE) {
861 /* Update the pacing table */
862 EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_PACE, pace_val);
863 EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_PACE_TBL, etp->et_index,
869 EFSYS_PROBE1(fail1, efx_rc_t, rc);
874 static __checkReturn efx_rc_t
875 falconsiena_tx_qflush(
878 efx_nic_t *enp = etp->et_enp;
882 efx_tx_qpace(etp, 0);
884 label = etp->et_index;
886 /* Flush the queue */
887 EFX_POPULATE_OWORD_2(oword, FRF_AZ_TX_FLUSH_DESCQ_CMD, 1,
888 FRF_AZ_TX_FLUSH_DESCQ, label);
889 EFX_BAR_WRITEO(enp, FR_AZ_TX_FLUSH_DESCQ_REG, &oword);
895 falconsiena_tx_qenable(
898 efx_nic_t *enp = etp->et_enp;
901 EFX_BAR_TBL_READO(enp, FR_AZ_TX_DESC_PTR_TBL,
902 etp->et_index, &oword, B_TRUE);
904 EFSYS_PROBE5(tx_descq_ptr, unsigned int, etp->et_index,
905 uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_3),
906 uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_2),
907 uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_1),
908 uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_0));
910 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DC_HW_RPTR, 0);
911 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DESCQ_HW_RPTR, 0);
912 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DESCQ_EN, 1);
914 EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
915 etp->et_index, &oword, B_TRUE);
918 static __checkReturn efx_rc_t
919 falconsiena_tx_qcreate(
921 __in unsigned int index,
922 __in unsigned int label,
923 __in efsys_mem_t *esmp,
929 __out unsigned int *addedp)
931 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
936 EFX_STATIC_ASSERT(EFX_EV_TX_NLABELS ==
937 (1 << FRF_AZ_TX_DESCQ_LABEL_WIDTH));
938 EFSYS_ASSERT3U(label, <, EFX_EV_TX_NLABELS);
940 EFSYS_ASSERT(ISP2(EFX_TXQ_MAXNDESCS(encp)));
941 EFX_STATIC_ASSERT(ISP2(EFX_TXQ_MINNDESCS));
943 if (!ISP2(n) || (n < EFX_TXQ_MINNDESCS) || (n > EFX_EVQ_MAXNEVS)) {
947 if (index >= encp->enc_txq_limit) {
952 (1 << size) <= (EFX_TXQ_MAXNDESCS(encp) / EFX_TXQ_MINNDESCS);
954 if ((1 << size) == (int)(n / EFX_TXQ_MINNDESCS))
956 if (id + (1 << size) >= encp->enc_buftbl_limit) {
961 /* Set up the new descriptor queue */
964 EFX_POPULATE_OWORD_6(oword,
965 FRF_AZ_TX_DESCQ_BUF_BASE_ID, id,
966 FRF_AZ_TX_DESCQ_EVQ_ID, eep->ee_index,
967 FRF_AZ_TX_DESCQ_OWNER_ID, 0,
968 FRF_AZ_TX_DESCQ_LABEL, label,
969 FRF_AZ_TX_DESCQ_SIZE, size,
970 FRF_AZ_TX_DESCQ_TYPE, 0);
972 EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_NON_IP_DROP_DIS, 1);
973 EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_IP_CHKSM_DIS,
974 (flags & EFX_TXQ_CKSUM_IPV4) ? 0 : 1);
975 EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_TCP_CHKSM_DIS,
976 (flags & EFX_TXQ_CKSUM_TCPUDP) ? 0 : 1);
978 EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
979 etp->et_index, &oword, B_TRUE);
988 EFSYS_PROBE1(fail1, efx_rc_t, rc);
993 __checkReturn efx_rc_t
994 falconsiena_tx_qdesc_post(
996 __in_ecount(n) efx_desc_t *ed,
998 __in unsigned int completed,
999 __inout unsigned int *addedp)
1001 unsigned int added = *addedp;
1005 if (added - completed + n > EFX_TXQ_LIMIT(etp->et_mask + 1)) {
1010 for (i = 0; i < n; i++) {
1011 efx_desc_t *edp = &ed[i];
1015 id = added++ & etp->et_mask;
1016 offset = id * sizeof (efx_desc_t);
1018 EFSYS_MEM_WRITEQ(etp->et_esmp, offset, &edp->ed_eq);
1021 EFSYS_PROBE3(tx_desc_post, unsigned int, etp->et_index,
1022 unsigned int, added, unsigned int, n);
1024 EFX_TX_QSTAT_INCR(etp, TX_POST);
1030 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1035 falconsiena_tx_qdesc_dma_create(
1036 __in efx_txq_t *etp,
1037 __in efsys_dma_addr_t addr,
1040 __out efx_desc_t *edp)
1042 /* Fragments must not span 4k boundaries. */
1043 EFSYS_ASSERT(P2ROUNDUP(addr + 1, 4096) >= addr + size);
1045 EFSYS_PROBE4(tx_desc_dma_create, unsigned int, etp->et_index,
1046 efsys_dma_addr_t, addr,
1047 size_t, size, boolean_t, eop);
1049 EFX_POPULATE_QWORD_4(edp->ed_eq,
1050 FSF_AZ_TX_KER_CONT, eop ? 0 : 1,
1051 FSF_AZ_TX_KER_BYTE_COUNT, (uint32_t)size,
1052 FSF_AZ_TX_KER_BUF_ADDR_DW0,
1053 (uint32_t)(addr & 0xffffffff),
1054 FSF_AZ_TX_KER_BUF_ADDR_DW1,
1055 (uint32_t)(addr >> 32));
1058 #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
1060 #if EFSYS_OPT_QSTATS
1062 /* START MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock 9d8d26a0a5e2c453 */
1063 static const char *__efx_tx_qstat_name[] = {
1067 /* END MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock */
1071 __in efx_nic_t *enp,
1072 __in unsigned int id)
1074 _NOTE(ARGUNUSED(enp))
1075 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1076 EFSYS_ASSERT3U(id, <, TX_NQSTATS);
1078 return (__efx_tx_qstat_name[id]);
1080 #endif /* EFSYS_OPT_NAMES */
1081 #endif /* EFSYS_OPT_QSTATS */
1083 #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
1085 #if EFSYS_OPT_QSTATS
1087 falconsiena_tx_qstats_update(
1088 __in efx_txq_t *etp,
1089 __inout_ecount(TX_NQSTATS) efsys_stat_t *stat)
1093 for (id = 0; id < TX_NQSTATS; id++) {
1094 efsys_stat_t *essp = &stat[id];
1096 EFSYS_STAT_INCR(essp, etp->et_stat[id]);
1097 etp->et_stat[id] = 0;
1100 #endif /* EFSYS_OPT_QSTATS */
1103 falconsiena_tx_qdestroy(
1104 __in efx_txq_t *etp)
1106 efx_nic_t *enp = etp->et_enp;
1109 /* Purge descriptor queue */
1110 EFX_ZERO_OWORD(oword);
1112 EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
1113 etp->et_index, &oword, B_TRUE);
1117 falconsiena_tx_fini(
1118 __in efx_nic_t *enp)
1120 _NOTE(ARGUNUSED(enp))
1123 #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */