1e948693eSPhilip Paeps /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni *
4929c7febSAndrew Rybchenko * Copyright (c) 2007-2016 Solarflare Communications Inc.
53c838a9fSAndrew Rybchenko * All rights reserved.
6e948693eSPhilip Paeps *
7e948693eSPhilip Paeps * Redistribution and use in source and binary forms, with or without
83c838a9fSAndrew Rybchenko * modification, are permitted provided that the following conditions are met:
9e948693eSPhilip Paeps *
103c838a9fSAndrew Rybchenko * 1. Redistributions of source code must retain the above copyright notice,
113c838a9fSAndrew Rybchenko * this list of conditions and the following disclaimer.
123c838a9fSAndrew Rybchenko * 2. Redistributions in binary form must reproduce the above copyright notice,
133c838a9fSAndrew Rybchenko * this list of conditions and the following disclaimer in the documentation
143c838a9fSAndrew Rybchenko * and/or other materials provided with the distribution.
153c838a9fSAndrew Rybchenko *
163c838a9fSAndrew Rybchenko * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
173c838a9fSAndrew Rybchenko * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
183c838a9fSAndrew Rybchenko * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
193c838a9fSAndrew Rybchenko * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
203c838a9fSAndrew Rybchenko * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
213c838a9fSAndrew Rybchenko * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
223c838a9fSAndrew Rybchenko * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
233c838a9fSAndrew Rybchenko * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
243c838a9fSAndrew Rybchenko * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
253c838a9fSAndrew Rybchenko * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
263c838a9fSAndrew Rybchenko * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273c838a9fSAndrew Rybchenko *
283c838a9fSAndrew Rybchenko * The views and conclusions contained in the software and documentation are
293c838a9fSAndrew Rybchenko * those of the authors and should not be interpreted as representing official
303c838a9fSAndrew Rybchenko * policies, either expressed or implied, of the FreeBSD Project.
31e948693eSPhilip Paeps */
32e948693eSPhilip Paeps
335dee87d7SPhilip Paeps #include <sys/cdefs.h>
34e948693eSPhilip Paeps #include "efx.h"
35e948693eSPhilip Paeps #include "efx_impl.h"
36e948693eSPhilip Paeps
37e948693eSPhilip Paeps #if EFSYS_OPT_QSTATS
38e948693eSPhilip Paeps #define EFX_TX_QSTAT_INCR(_etp, _stat) \
39e948693eSPhilip Paeps do { \
40e948693eSPhilip Paeps (_etp)->et_stat[_stat]++; \
41e948693eSPhilip Paeps _NOTE(CONSTANTCONDITION) \
42e948693eSPhilip Paeps } while (B_FALSE)
43e948693eSPhilip Paeps #else
44e948693eSPhilip Paeps #define EFX_TX_QSTAT_INCR(_etp, _stat)
45e948693eSPhilip Paeps #endif
46e948693eSPhilip Paeps
47e75412c9SAndrew Rybchenko #if EFSYS_OPT_SIENA
483c838a9fSAndrew Rybchenko
49460cb568SAndrew Rybchenko static __checkReturn efx_rc_t
5096ffcdeeSAndrew Rybchenko siena_tx_init(
513c838a9fSAndrew Rybchenko __in efx_nic_t *enp);
523c838a9fSAndrew Rybchenko
533c838a9fSAndrew Rybchenko static void
5496ffcdeeSAndrew Rybchenko siena_tx_fini(
553c838a9fSAndrew Rybchenko __in efx_nic_t *enp);
563c838a9fSAndrew Rybchenko
57460cb568SAndrew Rybchenko static __checkReturn efx_rc_t
5896ffcdeeSAndrew Rybchenko siena_tx_qcreate(
593c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
603c838a9fSAndrew Rybchenko __in unsigned int index,
613c838a9fSAndrew Rybchenko __in unsigned int label,
623c838a9fSAndrew Rybchenko __in efsys_mem_t *esmp,
630c9ef1f5SAndrew Rybchenko __in size_t ndescs,
643c838a9fSAndrew Rybchenko __in uint32_t id,
653c838a9fSAndrew Rybchenko __in uint16_t flags,
663c838a9fSAndrew Rybchenko __in efx_evq_t *eep,
673c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
683c838a9fSAndrew Rybchenko __out unsigned int *addedp);
693c838a9fSAndrew Rybchenko
703c838a9fSAndrew Rybchenko static void
7196ffcdeeSAndrew Rybchenko siena_tx_qdestroy(
723c838a9fSAndrew Rybchenko __in efx_txq_t *etp);
733c838a9fSAndrew Rybchenko
74460cb568SAndrew Rybchenko static __checkReturn efx_rc_t
7596ffcdeeSAndrew Rybchenko siena_tx_qpost(
763c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
770c9ef1f5SAndrew Rybchenko __in_ecount(ndescs) efx_buffer_t *eb,
780c9ef1f5SAndrew Rybchenko __in unsigned int ndescs,
793c838a9fSAndrew Rybchenko __in unsigned int completed,
803c838a9fSAndrew Rybchenko __inout unsigned int *addedp);
813c838a9fSAndrew Rybchenko
823c838a9fSAndrew Rybchenko static void
8396ffcdeeSAndrew Rybchenko siena_tx_qpush(
843c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
853c838a9fSAndrew Rybchenko __in unsigned int added,
863c838a9fSAndrew Rybchenko __in unsigned int pushed);
873c838a9fSAndrew Rybchenko
88460cb568SAndrew Rybchenko static __checkReturn efx_rc_t
8996ffcdeeSAndrew Rybchenko siena_tx_qpace(
903c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
913c838a9fSAndrew Rybchenko __in unsigned int ns);
923c838a9fSAndrew Rybchenko
93460cb568SAndrew Rybchenko static __checkReturn efx_rc_t
9496ffcdeeSAndrew Rybchenko siena_tx_qflush(
953c838a9fSAndrew Rybchenko __in efx_txq_t *etp);
963c838a9fSAndrew Rybchenko
973c838a9fSAndrew Rybchenko static void
9896ffcdeeSAndrew Rybchenko siena_tx_qenable(
993c838a9fSAndrew Rybchenko __in efx_txq_t *etp);
1003c838a9fSAndrew Rybchenko
101460cb568SAndrew Rybchenko __checkReturn efx_rc_t
10296ffcdeeSAndrew Rybchenko siena_tx_qdesc_post(
1033c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
1040c9ef1f5SAndrew Rybchenko __in_ecount(ndescs) efx_desc_t *ed,
1050c9ef1f5SAndrew Rybchenko __in unsigned int ndescs,
1063c838a9fSAndrew Rybchenko __in unsigned int completed,
1073c838a9fSAndrew Rybchenko __inout unsigned int *addedp);
1083c838a9fSAndrew Rybchenko
1093c838a9fSAndrew Rybchenko void
11096ffcdeeSAndrew Rybchenko siena_tx_qdesc_dma_create(
1113c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
1123c838a9fSAndrew Rybchenko __in efsys_dma_addr_t addr,
1133c838a9fSAndrew Rybchenko __in size_t size,
1143c838a9fSAndrew Rybchenko __in boolean_t eop,
1153c838a9fSAndrew Rybchenko __out efx_desc_t *edp);
1163c838a9fSAndrew Rybchenko
1173c838a9fSAndrew Rybchenko #if EFSYS_OPT_QSTATS
1183c838a9fSAndrew Rybchenko static void
11996ffcdeeSAndrew Rybchenko siena_tx_qstats_update(
1203c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
1213c838a9fSAndrew Rybchenko __inout_ecount(TX_NQSTATS) efsys_stat_t *stat);
1223c838a9fSAndrew Rybchenko #endif
1233c838a9fSAndrew Rybchenko
124e75412c9SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
1253c838a9fSAndrew Rybchenko
1263c838a9fSAndrew Rybchenko #if EFSYS_OPT_SIENA
127ec831f7fSAndrew Rybchenko static const efx_tx_ops_t __efx_tx_siena_ops = {
12896ffcdeeSAndrew Rybchenko siena_tx_init, /* etxo_init */
12996ffcdeeSAndrew Rybchenko siena_tx_fini, /* etxo_fini */
13096ffcdeeSAndrew Rybchenko siena_tx_qcreate, /* etxo_qcreate */
13196ffcdeeSAndrew Rybchenko siena_tx_qdestroy, /* etxo_qdestroy */
13296ffcdeeSAndrew Rybchenko siena_tx_qpost, /* etxo_qpost */
13396ffcdeeSAndrew Rybchenko siena_tx_qpush, /* etxo_qpush */
13496ffcdeeSAndrew Rybchenko siena_tx_qpace, /* etxo_qpace */
13596ffcdeeSAndrew Rybchenko siena_tx_qflush, /* etxo_qflush */
13696ffcdeeSAndrew Rybchenko siena_tx_qenable, /* etxo_qenable */
1373c838a9fSAndrew Rybchenko NULL, /* etxo_qpio_enable */
1383c838a9fSAndrew Rybchenko NULL, /* etxo_qpio_disable */
1393c838a9fSAndrew Rybchenko NULL, /* etxo_qpio_write */
1403c838a9fSAndrew Rybchenko NULL, /* etxo_qpio_post */
14196ffcdeeSAndrew Rybchenko siena_tx_qdesc_post, /* etxo_qdesc_post */
14296ffcdeeSAndrew Rybchenko siena_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
1433c838a9fSAndrew Rybchenko NULL, /* etxo_qdesc_tso_create */
1444ab49369SAndrew Rybchenko NULL, /* etxo_qdesc_tso2_create */
1453c838a9fSAndrew Rybchenko NULL, /* etxo_qdesc_vlantci_create */
1464effeb9eSAndrew Rybchenko NULL, /* etxo_qdesc_checksum_create */
1473c838a9fSAndrew Rybchenko #if EFSYS_OPT_QSTATS
14896ffcdeeSAndrew Rybchenko siena_tx_qstats_update, /* etxo_qstats_update */
1493c838a9fSAndrew Rybchenko #endif
1503c838a9fSAndrew Rybchenko };
1513c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
1523c838a9fSAndrew Rybchenko
1533c838a9fSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
154ec831f7fSAndrew Rybchenko static const efx_tx_ops_t __efx_tx_hunt_ops = {
155cc62e811SAndrew Rybchenko ef10_tx_init, /* etxo_init */
156cc62e811SAndrew Rybchenko ef10_tx_fini, /* etxo_fini */
157cc62e811SAndrew Rybchenko ef10_tx_qcreate, /* etxo_qcreate */
158cc62e811SAndrew Rybchenko ef10_tx_qdestroy, /* etxo_qdestroy */
159cc62e811SAndrew Rybchenko ef10_tx_qpost, /* etxo_qpost */
160cc62e811SAndrew Rybchenko ef10_tx_qpush, /* etxo_qpush */
161cc62e811SAndrew Rybchenko ef10_tx_qpace, /* etxo_qpace */
162cc62e811SAndrew Rybchenko ef10_tx_qflush, /* etxo_qflush */
163cc62e811SAndrew Rybchenko ef10_tx_qenable, /* etxo_qenable */
164cc62e811SAndrew Rybchenko ef10_tx_qpio_enable, /* etxo_qpio_enable */
165cc62e811SAndrew Rybchenko ef10_tx_qpio_disable, /* etxo_qpio_disable */
166cc62e811SAndrew Rybchenko ef10_tx_qpio_write, /* etxo_qpio_write */
167cc62e811SAndrew Rybchenko ef10_tx_qpio_post, /* etxo_qpio_post */
168cc62e811SAndrew Rybchenko ef10_tx_qdesc_post, /* etxo_qdesc_post */
169cc62e811SAndrew Rybchenko ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
17069fb4e16SAndrew Rybchenko ef10_tx_qdesc_tso_create, /* etxo_qdesc_tso_create */
1714ab49369SAndrew Rybchenko ef10_tx_qdesc_tso2_create, /* etxo_qdesc_tso2_create */
172cc62e811SAndrew Rybchenko ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */
1734effeb9eSAndrew Rybchenko ef10_tx_qdesc_checksum_create, /* etxo_qdesc_checksum_create */
1743c838a9fSAndrew Rybchenko #if EFSYS_OPT_QSTATS
175cc62e811SAndrew Rybchenko ef10_tx_qstats_update, /* etxo_qstats_update */
1763c838a9fSAndrew Rybchenko #endif
1773c838a9fSAndrew Rybchenko };
1783c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */
1793c838a9fSAndrew Rybchenko
180cc62e811SAndrew Rybchenko #if EFSYS_OPT_MEDFORD
181ec831f7fSAndrew Rybchenko static const efx_tx_ops_t __efx_tx_medford_ops = {
182cc62e811SAndrew Rybchenko ef10_tx_init, /* etxo_init */
183cc62e811SAndrew Rybchenko ef10_tx_fini, /* etxo_fini */
184cc62e811SAndrew Rybchenko ef10_tx_qcreate, /* etxo_qcreate */
185cc62e811SAndrew Rybchenko ef10_tx_qdestroy, /* etxo_qdestroy */
186cc62e811SAndrew Rybchenko ef10_tx_qpost, /* etxo_qpost */
187cc62e811SAndrew Rybchenko ef10_tx_qpush, /* etxo_qpush */
188cc62e811SAndrew Rybchenko ef10_tx_qpace, /* etxo_qpace */
189cc62e811SAndrew Rybchenko ef10_tx_qflush, /* etxo_qflush */
190cc62e811SAndrew Rybchenko ef10_tx_qenable, /* etxo_qenable */
191cc62e811SAndrew Rybchenko ef10_tx_qpio_enable, /* etxo_qpio_enable */
192cc62e811SAndrew Rybchenko ef10_tx_qpio_disable, /* etxo_qpio_disable */
193cc62e811SAndrew Rybchenko ef10_tx_qpio_write, /* etxo_qpio_write */
194cc62e811SAndrew Rybchenko ef10_tx_qpio_post, /* etxo_qpio_post */
195cc62e811SAndrew Rybchenko ef10_tx_qdesc_post, /* etxo_qdesc_post */
196cc62e811SAndrew Rybchenko ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
197cc62e811SAndrew Rybchenko NULL, /* etxo_qdesc_tso_create */
1984ab49369SAndrew Rybchenko ef10_tx_qdesc_tso2_create, /* etxo_qdesc_tso2_create */
199cc62e811SAndrew Rybchenko ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */
2004effeb9eSAndrew Rybchenko ef10_tx_qdesc_checksum_create, /* etxo_qdesc_checksum_create */
201cc62e811SAndrew Rybchenko #if EFSYS_OPT_QSTATS
202cc62e811SAndrew Rybchenko ef10_tx_qstats_update, /* etxo_qstats_update */
203cc62e811SAndrew Rybchenko #endif
204cc62e811SAndrew Rybchenko };
205cc62e811SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD */
206cc62e811SAndrew Rybchenko
20720c5aab3SAndrew Rybchenko #if EFSYS_OPT_MEDFORD2
20820c5aab3SAndrew Rybchenko static const efx_tx_ops_t __efx_tx_medford2_ops = {
20920c5aab3SAndrew Rybchenko ef10_tx_init, /* etxo_init */
21020c5aab3SAndrew Rybchenko ef10_tx_fini, /* etxo_fini */
21120c5aab3SAndrew Rybchenko ef10_tx_qcreate, /* etxo_qcreate */
21220c5aab3SAndrew Rybchenko ef10_tx_qdestroy, /* etxo_qdestroy */
21320c5aab3SAndrew Rybchenko ef10_tx_qpost, /* etxo_qpost */
21420c5aab3SAndrew Rybchenko ef10_tx_qpush, /* etxo_qpush */
21520c5aab3SAndrew Rybchenko ef10_tx_qpace, /* etxo_qpace */
21620c5aab3SAndrew Rybchenko ef10_tx_qflush, /* etxo_qflush */
21720c5aab3SAndrew Rybchenko ef10_tx_qenable, /* etxo_qenable */
21820c5aab3SAndrew Rybchenko ef10_tx_qpio_enable, /* etxo_qpio_enable */
21920c5aab3SAndrew Rybchenko ef10_tx_qpio_disable, /* etxo_qpio_disable */
22020c5aab3SAndrew Rybchenko ef10_tx_qpio_write, /* etxo_qpio_write */
22120c5aab3SAndrew Rybchenko ef10_tx_qpio_post, /* etxo_qpio_post */
22220c5aab3SAndrew Rybchenko ef10_tx_qdesc_post, /* etxo_qdesc_post */
22320c5aab3SAndrew Rybchenko ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
22420c5aab3SAndrew Rybchenko NULL, /* etxo_qdesc_tso_create */
22520c5aab3SAndrew Rybchenko ef10_tx_qdesc_tso2_create, /* etxo_qdesc_tso2_create */
22620c5aab3SAndrew Rybchenko ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */
2274effeb9eSAndrew Rybchenko ef10_tx_qdesc_checksum_create, /* etxo_qdesc_checksum_create */
22820c5aab3SAndrew Rybchenko #if EFSYS_OPT_QSTATS
22920c5aab3SAndrew Rybchenko ef10_tx_qstats_update, /* etxo_qstats_update */
23020c5aab3SAndrew Rybchenko #endif
23120c5aab3SAndrew Rybchenko };
23220c5aab3SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD2 */
23320c5aab3SAndrew Rybchenko
234460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_tx_init(__in efx_nic_t * enp)235e948693eSPhilip Paeps efx_tx_init(
236e948693eSPhilip Paeps __in efx_nic_t *enp)
237e948693eSPhilip Paeps {
238ec831f7fSAndrew Rybchenko const efx_tx_ops_t *etxop;
239460cb568SAndrew Rybchenko efx_rc_t rc;
240e948693eSPhilip Paeps
241e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
242e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
243e948693eSPhilip Paeps
244e948693eSPhilip Paeps if (!(enp->en_mod_flags & EFX_MOD_EV)) {
245e948693eSPhilip Paeps rc = EINVAL;
246e948693eSPhilip Paeps goto fail1;
247e948693eSPhilip Paeps }
248e948693eSPhilip Paeps
249e948693eSPhilip Paeps if (enp->en_mod_flags & EFX_MOD_TX) {
250e948693eSPhilip Paeps rc = EINVAL;
251e948693eSPhilip Paeps goto fail2;
252e948693eSPhilip Paeps }
253e948693eSPhilip Paeps
2543c838a9fSAndrew Rybchenko switch (enp->en_family) {
2553c838a9fSAndrew Rybchenko #if EFSYS_OPT_SIENA
2563c838a9fSAndrew Rybchenko case EFX_FAMILY_SIENA:
257ec831f7fSAndrew Rybchenko etxop = &__efx_tx_siena_ops;
2583c838a9fSAndrew Rybchenko break;
2593c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
2603c838a9fSAndrew Rybchenko
2613c838a9fSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
2623c838a9fSAndrew Rybchenko case EFX_FAMILY_HUNTINGTON:
263ec831f7fSAndrew Rybchenko etxop = &__efx_tx_hunt_ops;
2643c838a9fSAndrew Rybchenko break;
2653c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */
2663c838a9fSAndrew Rybchenko
267cc62e811SAndrew Rybchenko #if EFSYS_OPT_MEDFORD
268cc62e811SAndrew Rybchenko case EFX_FAMILY_MEDFORD:
269ec831f7fSAndrew Rybchenko etxop = &__efx_tx_medford_ops;
270cc62e811SAndrew Rybchenko break;
271cc62e811SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD */
272cc62e811SAndrew Rybchenko
27320c5aab3SAndrew Rybchenko #if EFSYS_OPT_MEDFORD2
27420c5aab3SAndrew Rybchenko case EFX_FAMILY_MEDFORD2:
27520c5aab3SAndrew Rybchenko etxop = &__efx_tx_medford2_ops;
27620c5aab3SAndrew Rybchenko break;
27720c5aab3SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD2 */
27820c5aab3SAndrew Rybchenko
2793c838a9fSAndrew Rybchenko default:
2803c838a9fSAndrew Rybchenko EFSYS_ASSERT(0);
2813c838a9fSAndrew Rybchenko rc = ENOTSUP;
2823c838a9fSAndrew Rybchenko goto fail3;
2833c838a9fSAndrew Rybchenko }
2843c838a9fSAndrew Rybchenko
285e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0);
286e948693eSPhilip Paeps
2873c838a9fSAndrew Rybchenko if ((rc = etxop->etxo_init(enp)) != 0)
2883c838a9fSAndrew Rybchenko goto fail4;
2893c838a9fSAndrew Rybchenko
2903c838a9fSAndrew Rybchenko enp->en_etxop = etxop;
2913c838a9fSAndrew Rybchenko enp->en_mod_flags |= EFX_MOD_TX;
2923c838a9fSAndrew Rybchenko return (0);
2933c838a9fSAndrew Rybchenko
2943c838a9fSAndrew Rybchenko fail4:
2953c838a9fSAndrew Rybchenko EFSYS_PROBE(fail4);
2963c838a9fSAndrew Rybchenko fail3:
2973c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3);
2983c838a9fSAndrew Rybchenko fail2:
2993c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2);
3003c838a9fSAndrew Rybchenko fail1:
301460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
3023c838a9fSAndrew Rybchenko
3033c838a9fSAndrew Rybchenko enp->en_etxop = NULL;
3043c838a9fSAndrew Rybchenko enp->en_mod_flags &= ~EFX_MOD_TX;
3053c838a9fSAndrew Rybchenko return (rc);
3063c838a9fSAndrew Rybchenko }
3073c838a9fSAndrew Rybchenko
3083c838a9fSAndrew Rybchenko void
efx_tx_fini(__in efx_nic_t * enp)3093c838a9fSAndrew Rybchenko efx_tx_fini(
3103c838a9fSAndrew Rybchenko __in efx_nic_t *enp)
3113c838a9fSAndrew Rybchenko {
312ec831f7fSAndrew Rybchenko const efx_tx_ops_t *etxop = enp->en_etxop;
3133c838a9fSAndrew Rybchenko
3143c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
3153c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
3163c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX);
3173c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0);
3183c838a9fSAndrew Rybchenko
3193c838a9fSAndrew Rybchenko etxop->etxo_fini(enp);
3203c838a9fSAndrew Rybchenko
3213c838a9fSAndrew Rybchenko enp->en_etxop = NULL;
3223c838a9fSAndrew Rybchenko enp->en_mod_flags &= ~EFX_MOD_TX;
3233c838a9fSAndrew Rybchenko }
3243c838a9fSAndrew Rybchenko
325460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_tx_qcreate(__in efx_nic_t * enp,__in unsigned int index,__in unsigned int label,__in efsys_mem_t * esmp,__in size_t ndescs,__in uint32_t id,__in uint16_t flags,__in efx_evq_t * eep,__deref_out efx_txq_t ** etpp,__out unsigned int * addedp)3263c838a9fSAndrew Rybchenko efx_tx_qcreate(
3273c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
3283c838a9fSAndrew Rybchenko __in unsigned int index,
3293c838a9fSAndrew Rybchenko __in unsigned int label,
3303c838a9fSAndrew Rybchenko __in efsys_mem_t *esmp,
3310c9ef1f5SAndrew Rybchenko __in size_t ndescs,
3323c838a9fSAndrew Rybchenko __in uint32_t id,
3333c838a9fSAndrew Rybchenko __in uint16_t flags,
3343c838a9fSAndrew Rybchenko __in efx_evq_t *eep,
3353c838a9fSAndrew Rybchenko __deref_out efx_txq_t **etpp,
3363c838a9fSAndrew Rybchenko __out unsigned int *addedp)
3373c838a9fSAndrew Rybchenko {
338ec831f7fSAndrew Rybchenko const efx_tx_ops_t *etxop = enp->en_etxop;
3393c838a9fSAndrew Rybchenko efx_txq_t *etp;
340460cb568SAndrew Rybchenko efx_rc_t rc;
3413c838a9fSAndrew Rybchenko
3423c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
3433c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX);
3443c838a9fSAndrew Rybchenko
345cc8d2b23SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_tx_qcount + 1, <,
346cc8d2b23SAndrew Rybchenko enp->en_nic_cfg.enc_txq_limit);
3473c838a9fSAndrew Rybchenko
3483c838a9fSAndrew Rybchenko /* Allocate an TXQ object */
3493c838a9fSAndrew Rybchenko EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_txq_t), etp);
3503c838a9fSAndrew Rybchenko
3513c838a9fSAndrew Rybchenko if (etp == NULL) {
3523c838a9fSAndrew Rybchenko rc = ENOMEM;
3533c838a9fSAndrew Rybchenko goto fail1;
3543c838a9fSAndrew Rybchenko }
3553c838a9fSAndrew Rybchenko
3563c838a9fSAndrew Rybchenko etp->et_magic = EFX_TXQ_MAGIC;
3573c838a9fSAndrew Rybchenko etp->et_enp = enp;
3583c838a9fSAndrew Rybchenko etp->et_index = index;
3590c9ef1f5SAndrew Rybchenko etp->et_mask = ndescs - 1;
3603c838a9fSAndrew Rybchenko etp->et_esmp = esmp;
3613c838a9fSAndrew Rybchenko
3623c838a9fSAndrew Rybchenko /* Initial descriptor index may be modified by etxo_qcreate */
3633c838a9fSAndrew Rybchenko *addedp = 0;
3643c838a9fSAndrew Rybchenko
3653c838a9fSAndrew Rybchenko if ((rc = etxop->etxo_qcreate(enp, index, label, esmp,
3660c9ef1f5SAndrew Rybchenko ndescs, id, flags, eep, etp, addedp)) != 0)
3673c838a9fSAndrew Rybchenko goto fail2;
3683c838a9fSAndrew Rybchenko
3693c838a9fSAndrew Rybchenko enp->en_tx_qcount++;
3703c838a9fSAndrew Rybchenko *etpp = etp;
3713c838a9fSAndrew Rybchenko
3723c838a9fSAndrew Rybchenko return (0);
3733c838a9fSAndrew Rybchenko
3743c838a9fSAndrew Rybchenko fail2:
3753c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2);
3763c838a9fSAndrew Rybchenko EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_txq_t), etp);
3773c838a9fSAndrew Rybchenko fail1:
378460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
3793c838a9fSAndrew Rybchenko return (rc);
3803c838a9fSAndrew Rybchenko }
3813c838a9fSAndrew Rybchenko
3823c838a9fSAndrew Rybchenko void
efx_tx_qdestroy(__in efx_txq_t * etp)3833c838a9fSAndrew Rybchenko efx_tx_qdestroy(
3843c838a9fSAndrew Rybchenko __in efx_txq_t *etp)
3853c838a9fSAndrew Rybchenko {
3863c838a9fSAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
387ec831f7fSAndrew Rybchenko const efx_tx_ops_t *etxop = enp->en_etxop;
3883c838a9fSAndrew Rybchenko
3893c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
3903c838a9fSAndrew Rybchenko
3913c838a9fSAndrew Rybchenko EFSYS_ASSERT(enp->en_tx_qcount != 0);
3923c838a9fSAndrew Rybchenko --enp->en_tx_qcount;
3933c838a9fSAndrew Rybchenko
3943c838a9fSAndrew Rybchenko etxop->etxo_qdestroy(etp);
3953c838a9fSAndrew Rybchenko
3963c838a9fSAndrew Rybchenko /* Free the TXQ object */
3973c838a9fSAndrew Rybchenko EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_txq_t), etp);
3983c838a9fSAndrew Rybchenko }
3993c838a9fSAndrew Rybchenko
400460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_tx_qpost(__in efx_txq_t * etp,__in_ecount (ndescs)efx_buffer_t * eb,__in unsigned int ndescs,__in unsigned int completed,__inout unsigned int * addedp)4013c838a9fSAndrew Rybchenko efx_tx_qpost(
4023c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
4030c9ef1f5SAndrew Rybchenko __in_ecount(ndescs) efx_buffer_t *eb,
4040c9ef1f5SAndrew Rybchenko __in unsigned int ndescs,
4053c838a9fSAndrew Rybchenko __in unsigned int completed,
4063c838a9fSAndrew Rybchenko __inout unsigned int *addedp)
4073c838a9fSAndrew Rybchenko {
4083c838a9fSAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
409ec831f7fSAndrew Rybchenko const efx_tx_ops_t *etxop = enp->en_etxop;
410460cb568SAndrew Rybchenko efx_rc_t rc;
4113c838a9fSAndrew Rybchenko
4123c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
4133c838a9fSAndrew Rybchenko
4140c9ef1f5SAndrew Rybchenko if ((rc = etxop->etxo_qpost(etp, eb, ndescs, completed, addedp)) != 0)
4153c838a9fSAndrew Rybchenko goto fail1;
4163c838a9fSAndrew Rybchenko
4173c838a9fSAndrew Rybchenko return (0);
4183c838a9fSAndrew Rybchenko
4193c838a9fSAndrew Rybchenko fail1:
420460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
4213c838a9fSAndrew Rybchenko return (rc);
4223c838a9fSAndrew Rybchenko }
4233c838a9fSAndrew Rybchenko
4243c838a9fSAndrew Rybchenko void
efx_tx_qpush(__in efx_txq_t * etp,__in unsigned int added,__in unsigned int pushed)4253c838a9fSAndrew Rybchenko efx_tx_qpush(
4263c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
4273c838a9fSAndrew Rybchenko __in unsigned int added,
4283c838a9fSAndrew Rybchenko __in unsigned int pushed)
4293c838a9fSAndrew Rybchenko {
4303c838a9fSAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
431ec831f7fSAndrew Rybchenko const efx_tx_ops_t *etxop = enp->en_etxop;
4323c838a9fSAndrew Rybchenko
4333c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
4343c838a9fSAndrew Rybchenko
4353c838a9fSAndrew Rybchenko etxop->etxo_qpush(etp, added, pushed);
4363c838a9fSAndrew Rybchenko }
4373c838a9fSAndrew Rybchenko
438460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_tx_qpace(__in efx_txq_t * etp,__in unsigned int ns)4393c838a9fSAndrew Rybchenko efx_tx_qpace(
4403c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
4413c838a9fSAndrew Rybchenko __in unsigned int ns)
4423c838a9fSAndrew Rybchenko {
4433c838a9fSAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
444ec831f7fSAndrew Rybchenko const efx_tx_ops_t *etxop = enp->en_etxop;
445460cb568SAndrew Rybchenko efx_rc_t rc;
4463c838a9fSAndrew Rybchenko
4473c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
4483c838a9fSAndrew Rybchenko
4493c838a9fSAndrew Rybchenko if ((rc = etxop->etxo_qpace(etp, ns)) != 0)
4503c838a9fSAndrew Rybchenko goto fail1;
4513c838a9fSAndrew Rybchenko
4523c838a9fSAndrew Rybchenko return (0);
4533c838a9fSAndrew Rybchenko
4543c838a9fSAndrew Rybchenko fail1:
455460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
4563c838a9fSAndrew Rybchenko return (rc);
4573c838a9fSAndrew Rybchenko }
4583c838a9fSAndrew Rybchenko
459460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_tx_qflush(__in efx_txq_t * etp)4603c838a9fSAndrew Rybchenko efx_tx_qflush(
4613c838a9fSAndrew Rybchenko __in efx_txq_t *etp)
4623c838a9fSAndrew Rybchenko {
4633c838a9fSAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
464ec831f7fSAndrew Rybchenko const efx_tx_ops_t *etxop = enp->en_etxop;
465460cb568SAndrew Rybchenko efx_rc_t rc;
4663c838a9fSAndrew Rybchenko
4673c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
4683c838a9fSAndrew Rybchenko
4693c838a9fSAndrew Rybchenko if ((rc = etxop->etxo_qflush(etp)) != 0)
4703c838a9fSAndrew Rybchenko goto fail1;
4713c838a9fSAndrew Rybchenko
4723c838a9fSAndrew Rybchenko return (0);
4733c838a9fSAndrew Rybchenko
4743c838a9fSAndrew Rybchenko fail1:
475460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
4763c838a9fSAndrew Rybchenko return (rc);
4773c838a9fSAndrew Rybchenko }
4783c838a9fSAndrew Rybchenko
4793c838a9fSAndrew Rybchenko void
efx_tx_qenable(__in efx_txq_t * etp)4803c838a9fSAndrew Rybchenko efx_tx_qenable(
4813c838a9fSAndrew Rybchenko __in efx_txq_t *etp)
4823c838a9fSAndrew Rybchenko {
4833c838a9fSAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
484ec831f7fSAndrew Rybchenko const efx_tx_ops_t *etxop = enp->en_etxop;
4853c838a9fSAndrew Rybchenko
4863c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
4873c838a9fSAndrew Rybchenko
4883c838a9fSAndrew Rybchenko etxop->etxo_qenable(etp);
4893c838a9fSAndrew Rybchenko }
4903c838a9fSAndrew Rybchenko
491460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_tx_qpio_enable(__in efx_txq_t * etp)4923c838a9fSAndrew Rybchenko efx_tx_qpio_enable(
4933c838a9fSAndrew Rybchenko __in efx_txq_t *etp)
4943c838a9fSAndrew Rybchenko {
4953c838a9fSAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
496ec831f7fSAndrew Rybchenko const efx_tx_ops_t *etxop = enp->en_etxop;
497460cb568SAndrew Rybchenko efx_rc_t rc;
4983c838a9fSAndrew Rybchenko
4993c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
5003c838a9fSAndrew Rybchenko
5013c838a9fSAndrew Rybchenko if (~enp->en_features & EFX_FEATURE_PIO_BUFFERS) {
5023c838a9fSAndrew Rybchenko rc = ENOTSUP;
5033c838a9fSAndrew Rybchenko goto fail1;
5043c838a9fSAndrew Rybchenko }
5053c838a9fSAndrew Rybchenko if (etxop->etxo_qpio_enable == NULL) {
5063c838a9fSAndrew Rybchenko rc = ENOTSUP;
5073c838a9fSAndrew Rybchenko goto fail2;
5083c838a9fSAndrew Rybchenko }
5093c838a9fSAndrew Rybchenko if ((rc = etxop->etxo_qpio_enable(etp)) != 0)
5103c838a9fSAndrew Rybchenko goto fail3;
5113c838a9fSAndrew Rybchenko
5123c838a9fSAndrew Rybchenko return (0);
5133c838a9fSAndrew Rybchenko
5143c838a9fSAndrew Rybchenko fail3:
5153c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3);
5163c838a9fSAndrew Rybchenko fail2:
5173c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2);
5183c838a9fSAndrew Rybchenko fail1:
519460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
5203c838a9fSAndrew Rybchenko return (rc);
5213c838a9fSAndrew Rybchenko }
5223c838a9fSAndrew Rybchenko
5233c838a9fSAndrew Rybchenko void
efx_tx_qpio_disable(__in efx_txq_t * etp)5243c838a9fSAndrew Rybchenko efx_tx_qpio_disable(
5253c838a9fSAndrew Rybchenko __in efx_txq_t *etp)
5263c838a9fSAndrew Rybchenko {
5273c838a9fSAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
528ec831f7fSAndrew Rybchenko const efx_tx_ops_t *etxop = enp->en_etxop;
5293c838a9fSAndrew Rybchenko
5303c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
5313c838a9fSAndrew Rybchenko
5323c838a9fSAndrew Rybchenko if (etxop->etxo_qpio_disable != NULL)
5333c838a9fSAndrew Rybchenko etxop->etxo_qpio_disable(etp);
5343c838a9fSAndrew Rybchenko }
5353c838a9fSAndrew Rybchenko
536460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_tx_qpio_write(__in efx_txq_t * etp,__in_ecount (buf_length)uint8_t * buffer,__in size_t buf_length,__in size_t pio_buf_offset)5373c838a9fSAndrew Rybchenko efx_tx_qpio_write(
5383c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
5393c838a9fSAndrew Rybchenko __in_ecount(buf_length) uint8_t *buffer,
5403c838a9fSAndrew Rybchenko __in size_t buf_length,
5413c838a9fSAndrew Rybchenko __in size_t pio_buf_offset)
5423c838a9fSAndrew Rybchenko {
5433c838a9fSAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
544ec831f7fSAndrew Rybchenko const efx_tx_ops_t *etxop = enp->en_etxop;
545460cb568SAndrew Rybchenko efx_rc_t rc;
5463c838a9fSAndrew Rybchenko
5473c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
5483c838a9fSAndrew Rybchenko
5493c838a9fSAndrew Rybchenko if (etxop->etxo_qpio_write != NULL) {
5503c838a9fSAndrew Rybchenko if ((rc = etxop->etxo_qpio_write(etp, buffer, buf_length,
5513c838a9fSAndrew Rybchenko pio_buf_offset)) != 0)
5523c838a9fSAndrew Rybchenko goto fail1;
5533c838a9fSAndrew Rybchenko return (0);
5543c838a9fSAndrew Rybchenko }
5553c838a9fSAndrew Rybchenko
5563c838a9fSAndrew Rybchenko return (ENOTSUP);
5573c838a9fSAndrew Rybchenko
5583c838a9fSAndrew Rybchenko fail1:
559460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
5603c838a9fSAndrew Rybchenko return (rc);
5613c838a9fSAndrew Rybchenko }
5623c838a9fSAndrew Rybchenko
563460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_tx_qpio_post(__in efx_txq_t * etp,__in size_t pkt_length,__in unsigned int completed,__inout unsigned int * addedp)5643c838a9fSAndrew Rybchenko efx_tx_qpio_post(
5653c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
5663c838a9fSAndrew Rybchenko __in size_t pkt_length,
5673c838a9fSAndrew Rybchenko __in unsigned int completed,
5683c838a9fSAndrew Rybchenko __inout unsigned int *addedp)
5693c838a9fSAndrew Rybchenko {
5703c838a9fSAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
571ec831f7fSAndrew Rybchenko const efx_tx_ops_t *etxop = enp->en_etxop;
572460cb568SAndrew Rybchenko efx_rc_t rc;
5733c838a9fSAndrew Rybchenko
5743c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
5753c838a9fSAndrew Rybchenko
5763c838a9fSAndrew Rybchenko if (etxop->etxo_qpio_post != NULL) {
5773c838a9fSAndrew Rybchenko if ((rc = etxop->etxo_qpio_post(etp, pkt_length, completed,
5783c838a9fSAndrew Rybchenko addedp)) != 0)
5793c838a9fSAndrew Rybchenko goto fail1;
5803c838a9fSAndrew Rybchenko return (0);
5813c838a9fSAndrew Rybchenko }
5823c838a9fSAndrew Rybchenko
5833c838a9fSAndrew Rybchenko return (ENOTSUP);
5843c838a9fSAndrew Rybchenko
5853c838a9fSAndrew Rybchenko fail1:
586460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
5873c838a9fSAndrew Rybchenko return (rc);
5883c838a9fSAndrew Rybchenko }
5893c838a9fSAndrew Rybchenko
590460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_tx_qdesc_post(__in efx_txq_t * etp,__in_ecount (ndescs)efx_desc_t * ed,__in unsigned int ndescs,__in unsigned int completed,__inout unsigned int * addedp)5913c838a9fSAndrew Rybchenko efx_tx_qdesc_post(
5923c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
5930c9ef1f5SAndrew Rybchenko __in_ecount(ndescs) efx_desc_t *ed,
5940c9ef1f5SAndrew Rybchenko __in unsigned int ndescs,
5953c838a9fSAndrew Rybchenko __in unsigned int completed,
5963c838a9fSAndrew Rybchenko __inout unsigned int *addedp)
5973c838a9fSAndrew Rybchenko {
5983c838a9fSAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
599ec831f7fSAndrew Rybchenko const efx_tx_ops_t *etxop = enp->en_etxop;
6003c838a9fSAndrew Rybchenko
6013c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
6023c838a9fSAndrew Rybchenko
6034c7d5ddbSAndrew Rybchenko return (etxop->etxo_qdesc_post(etp, ed, ndescs, completed, addedp));
6043c838a9fSAndrew Rybchenko }
6053c838a9fSAndrew Rybchenko
6063c838a9fSAndrew Rybchenko void
efx_tx_qdesc_dma_create(__in efx_txq_t * etp,__in efsys_dma_addr_t addr,__in size_t size,__in boolean_t eop,__out efx_desc_t * edp)6073c838a9fSAndrew Rybchenko efx_tx_qdesc_dma_create(
6083c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
6093c838a9fSAndrew Rybchenko __in efsys_dma_addr_t addr,
6103c838a9fSAndrew Rybchenko __in size_t size,
6113c838a9fSAndrew Rybchenko __in boolean_t eop,
6123c838a9fSAndrew Rybchenko __out efx_desc_t *edp)
6133c838a9fSAndrew Rybchenko {
6143c838a9fSAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
615ec831f7fSAndrew Rybchenko const efx_tx_ops_t *etxop = enp->en_etxop;
6163c838a9fSAndrew Rybchenko
6173c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
6183c838a9fSAndrew Rybchenko EFSYS_ASSERT(etxop->etxo_qdesc_dma_create != NULL);
6193c838a9fSAndrew Rybchenko
6203c838a9fSAndrew Rybchenko etxop->etxo_qdesc_dma_create(etp, addr, size, eop, edp);
6213c838a9fSAndrew Rybchenko }
6223c838a9fSAndrew Rybchenko
6233c838a9fSAndrew Rybchenko void
efx_tx_qdesc_tso_create(__in efx_txq_t * etp,__in uint16_t ipv4_id,__in uint32_t tcp_seq,__in uint8_t tcp_flags,__out efx_desc_t * edp)6243c838a9fSAndrew Rybchenko efx_tx_qdesc_tso_create(
6253c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
6263c838a9fSAndrew Rybchenko __in uint16_t ipv4_id,
6273c838a9fSAndrew Rybchenko __in uint32_t tcp_seq,
6283c838a9fSAndrew Rybchenko __in uint8_t tcp_flags,
6293c838a9fSAndrew Rybchenko __out efx_desc_t *edp)
6303c838a9fSAndrew Rybchenko {
6313c838a9fSAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
632ec831f7fSAndrew Rybchenko const efx_tx_ops_t *etxop = enp->en_etxop;
6333c838a9fSAndrew Rybchenko
6343c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
6353c838a9fSAndrew Rybchenko EFSYS_ASSERT(etxop->etxo_qdesc_tso_create != NULL);
6363c838a9fSAndrew Rybchenko
6373c838a9fSAndrew Rybchenko etxop->etxo_qdesc_tso_create(etp, ipv4_id, tcp_seq, tcp_flags, edp);
6383c838a9fSAndrew Rybchenko }
6393c838a9fSAndrew Rybchenko
6403c838a9fSAndrew Rybchenko void
efx_tx_qdesc_tso2_create(__in efx_txq_t * etp,__in uint16_t ipv4_id,__in uint16_t outer_ipv4_id,__in uint32_t tcp_seq,__in uint16_t mss,__out_ecount (count)efx_desc_t * edp,__in int count)6414ab49369SAndrew Rybchenko efx_tx_qdesc_tso2_create(
6424ab49369SAndrew Rybchenko __in efx_txq_t *etp,
6434ab49369SAndrew Rybchenko __in uint16_t ipv4_id,
6444142e8cfSAndrew Rybchenko __in uint16_t outer_ipv4_id,
6454ab49369SAndrew Rybchenko __in uint32_t tcp_seq,
6464ab49369SAndrew Rybchenko __in uint16_t mss,
6474ab49369SAndrew Rybchenko __out_ecount(count) efx_desc_t *edp,
6484ab49369SAndrew Rybchenko __in int count)
6494ab49369SAndrew Rybchenko {
6504ab49369SAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
651ec831f7fSAndrew Rybchenko const efx_tx_ops_t *etxop = enp->en_etxop;
6524ab49369SAndrew Rybchenko
6534ab49369SAndrew Rybchenko EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
6544ab49369SAndrew Rybchenko EFSYS_ASSERT(etxop->etxo_qdesc_tso2_create != NULL);
6554ab49369SAndrew Rybchenko
6564142e8cfSAndrew Rybchenko etxop->etxo_qdesc_tso2_create(etp, ipv4_id, outer_ipv4_id,
6574142e8cfSAndrew Rybchenko tcp_seq, mss, edp, count);
6584ab49369SAndrew Rybchenko }
6594ab49369SAndrew Rybchenko
6604ab49369SAndrew Rybchenko void
efx_tx_qdesc_vlantci_create(__in efx_txq_t * etp,__in uint16_t tci,__out efx_desc_t * edp)6613c838a9fSAndrew Rybchenko efx_tx_qdesc_vlantci_create(
6623c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
6633c838a9fSAndrew Rybchenko __in uint16_t tci,
6643c838a9fSAndrew Rybchenko __out efx_desc_t *edp)
6653c838a9fSAndrew Rybchenko {
6663c838a9fSAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
667ec831f7fSAndrew Rybchenko const efx_tx_ops_t *etxop = enp->en_etxop;
6683c838a9fSAndrew Rybchenko
6693c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
6703c838a9fSAndrew Rybchenko EFSYS_ASSERT(etxop->etxo_qdesc_vlantci_create != NULL);
6713c838a9fSAndrew Rybchenko
6723c838a9fSAndrew Rybchenko etxop->etxo_qdesc_vlantci_create(etp, tci, edp);
6733c838a9fSAndrew Rybchenko }
6743c838a9fSAndrew Rybchenko
6754effeb9eSAndrew Rybchenko void
efx_tx_qdesc_checksum_create(__in efx_txq_t * etp,__in uint16_t flags,__out efx_desc_t * edp)6764effeb9eSAndrew Rybchenko efx_tx_qdesc_checksum_create(
6774effeb9eSAndrew Rybchenko __in efx_txq_t *etp,
6784effeb9eSAndrew Rybchenko __in uint16_t flags,
6794effeb9eSAndrew Rybchenko __out efx_desc_t *edp)
6804effeb9eSAndrew Rybchenko {
6814effeb9eSAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
6824effeb9eSAndrew Rybchenko const efx_tx_ops_t *etxop = enp->en_etxop;
6834effeb9eSAndrew Rybchenko
6844effeb9eSAndrew Rybchenko EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
6854effeb9eSAndrew Rybchenko EFSYS_ASSERT(etxop->etxo_qdesc_checksum_create != NULL);
6864effeb9eSAndrew Rybchenko
6874effeb9eSAndrew Rybchenko etxop->etxo_qdesc_checksum_create(etp, flags, edp);
6884effeb9eSAndrew Rybchenko }
6894effeb9eSAndrew Rybchenko
6903c838a9fSAndrew Rybchenko #if EFSYS_OPT_QSTATS
6913c838a9fSAndrew Rybchenko void
efx_tx_qstats_update(__in efx_txq_t * etp,__inout_ecount (TX_NQSTATS)efsys_stat_t * stat)6923c838a9fSAndrew Rybchenko efx_tx_qstats_update(
6933c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
6943c838a9fSAndrew Rybchenko __inout_ecount(TX_NQSTATS) efsys_stat_t *stat)
6953c838a9fSAndrew Rybchenko {
6963c838a9fSAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
697ec831f7fSAndrew Rybchenko const efx_tx_ops_t *etxop = enp->en_etxop;
6983c838a9fSAndrew Rybchenko
6993c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
7003c838a9fSAndrew Rybchenko
7013c838a9fSAndrew Rybchenko etxop->etxo_qstats_update(etp, stat);
7023c838a9fSAndrew Rybchenko }
7033c838a9fSAndrew Rybchenko #endif
7043c838a9fSAndrew Rybchenko
705e75412c9SAndrew Rybchenko #if EFSYS_OPT_SIENA
7063c838a9fSAndrew Rybchenko
707460cb568SAndrew Rybchenko static __checkReturn efx_rc_t
siena_tx_init(__in efx_nic_t * enp)70896ffcdeeSAndrew Rybchenko siena_tx_init(
7093c838a9fSAndrew Rybchenko __in efx_nic_t *enp)
7103c838a9fSAndrew Rybchenko {
7113c838a9fSAndrew Rybchenko efx_oword_t oword;
7123c838a9fSAndrew Rybchenko
713e948693eSPhilip Paeps /*
714e948693eSPhilip Paeps * Disable the timer-based TX DMA backoff and allow TX DMA to be
715e948693eSPhilip Paeps * controlled by the RX FIFO fill level (although always allow a
716e948693eSPhilip Paeps * minimal trickle).
717e948693eSPhilip Paeps */
718e948693eSPhilip Paeps EFX_BAR_READO(enp, FR_AZ_TX_RESERVED_REG, &oword);
719e948693eSPhilip Paeps EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_RX_SPACER, 0xfe);
720e948693eSPhilip Paeps EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_RX_SPACER_EN, 1);
721e948693eSPhilip Paeps EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_ONE_PKT_PER_Q, 1);
722e948693eSPhilip Paeps EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PUSH_EN, 0);
723e948693eSPhilip Paeps EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DIS_NON_IP_EV, 1);
724e948693eSPhilip Paeps EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PREF_THRESHOLD, 2);
725e948693eSPhilip Paeps EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PREF_WD_TMR, 0x3fffff);
726e948693eSPhilip Paeps
727e948693eSPhilip Paeps /*
728e948693eSPhilip Paeps * Filter all packets less than 14 bytes to avoid parsing
729e948693eSPhilip Paeps * errors.
730e948693eSPhilip Paeps */
731e948693eSPhilip Paeps EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1);
732e948693eSPhilip Paeps EFX_BAR_WRITEO(enp, FR_AZ_TX_RESERVED_REG, &oword);
733e948693eSPhilip Paeps
734e948693eSPhilip Paeps /*
735e948693eSPhilip Paeps * Do not set TX_NO_EOP_DISC_EN, since it limits packets to 16
736e948693eSPhilip Paeps * descriptors (which is bad).
737e948693eSPhilip Paeps */
738e948693eSPhilip Paeps EFX_BAR_READO(enp, FR_AZ_TX_CFG_REG, &oword);
739e948693eSPhilip Paeps EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_NO_EOP_DISC_EN, 0);
740e948693eSPhilip Paeps EFX_BAR_WRITEO(enp, FR_AZ_TX_CFG_REG, &oword);
741e948693eSPhilip Paeps
742e948693eSPhilip Paeps return (0);
743e948693eSPhilip Paeps }
744e948693eSPhilip Paeps
745e948693eSPhilip Paeps #define EFX_TX_DESC(_etp, _addr, _size, _eop, _added) \
746e948693eSPhilip Paeps do { \
747e948693eSPhilip Paeps unsigned int id; \
748e948693eSPhilip Paeps size_t offset; \
749e948693eSPhilip Paeps efx_qword_t qword; \
750e948693eSPhilip Paeps \
751e948693eSPhilip Paeps id = (_added)++ & (_etp)->et_mask; \
752e948693eSPhilip Paeps offset = id * sizeof (efx_qword_t); \
753e948693eSPhilip Paeps \
754e948693eSPhilip Paeps EFSYS_PROBE5(tx_post, unsigned int, (_etp)->et_index, \
755e948693eSPhilip Paeps unsigned int, id, efsys_dma_addr_t, (_addr), \
756e948693eSPhilip Paeps size_t, (_size), boolean_t, (_eop)); \
757e948693eSPhilip Paeps \
758e948693eSPhilip Paeps EFX_POPULATE_QWORD_4(qword, \
759e948693eSPhilip Paeps FSF_AZ_TX_KER_CONT, (_eop) ? 0 : 1, \
760e948693eSPhilip Paeps FSF_AZ_TX_KER_BYTE_COUNT, (uint32_t)(_size), \
761e948693eSPhilip Paeps FSF_AZ_TX_KER_BUF_ADDR_DW0, \
762e948693eSPhilip Paeps (uint32_t)((_addr) & 0xffffffff), \
763e948693eSPhilip Paeps FSF_AZ_TX_KER_BUF_ADDR_DW1, \
764e948693eSPhilip Paeps (uint32_t)((_addr) >> 32)); \
765e948693eSPhilip Paeps EFSYS_MEM_WRITEQ((_etp)->et_esmp, offset, &qword); \
766e948693eSPhilip Paeps \
767e948693eSPhilip Paeps _NOTE(CONSTANTCONDITION) \
768e948693eSPhilip Paeps } while (B_FALSE)
769e948693eSPhilip Paeps
770460cb568SAndrew Rybchenko static __checkReturn efx_rc_t
siena_tx_qpost(__in efx_txq_t * etp,__in_ecount (ndescs)efx_buffer_t * eb,__in unsigned int ndescs,__in unsigned int completed,__inout unsigned int * addedp)77196ffcdeeSAndrew Rybchenko siena_tx_qpost(
772e948693eSPhilip Paeps __in efx_txq_t *etp,
7730c9ef1f5SAndrew Rybchenko __in_ecount(ndescs) efx_buffer_t *eb,
7740c9ef1f5SAndrew Rybchenko __in unsigned int ndescs,
775e948693eSPhilip Paeps __in unsigned int completed,
776e948693eSPhilip Paeps __inout unsigned int *addedp)
777e948693eSPhilip Paeps {
778e948693eSPhilip Paeps unsigned int added = *addedp;
779e948693eSPhilip Paeps unsigned int i;
780e948693eSPhilip Paeps
7810c9ef1f5SAndrew Rybchenko if (added - completed + ndescs > EFX_TXQ_LIMIT(etp->et_mask + 1))
7824c7d5ddbSAndrew Rybchenko return (ENOSPC);
783e948693eSPhilip Paeps
7840c9ef1f5SAndrew Rybchenko for (i = 0; i < ndescs; i++) {
785e948693eSPhilip Paeps efx_buffer_t *ebp = &eb[i];
786e948693eSPhilip Paeps efsys_dma_addr_t start = ebp->eb_addr;
787e948693eSPhilip Paeps size_t size = ebp->eb_size;
788e948693eSPhilip Paeps efsys_dma_addr_t end = start + size;
789e948693eSPhilip Paeps
7906a09b206SAndrew Rybchenko /*
7916a09b206SAndrew Rybchenko * Fragments must not span 4k boundaries.
7926a09b206SAndrew Rybchenko * Here it is a stricter requirement than the maximum length.
7936a09b206SAndrew Rybchenko */
794ec30f0beSAndrew Rybchenko EFSYS_ASSERT(EFX_P2ROUNDUP(efsys_dma_addr_t, start + 1,
7956a09b206SAndrew Rybchenko etp->et_enp->en_nic_cfg.enc_tx_dma_desc_boundary) >= end);
796e948693eSPhilip Paeps
797e948693eSPhilip Paeps EFX_TX_DESC(etp, start, size, ebp->eb_eop, added);
798e948693eSPhilip Paeps }
799e948693eSPhilip Paeps
800e948693eSPhilip Paeps EFX_TX_QSTAT_INCR(etp, TX_POST);
801e948693eSPhilip Paeps
802e948693eSPhilip Paeps *addedp = added;
803e948693eSPhilip Paeps return (0);
804e948693eSPhilip Paeps }
805e948693eSPhilip Paeps
8063c838a9fSAndrew Rybchenko static void
siena_tx_qpush(__in efx_txq_t * etp,__in unsigned int added,__in unsigned int pushed)80796ffcdeeSAndrew Rybchenko siena_tx_qpush(
808e948693eSPhilip Paeps __in efx_txq_t *etp,
8093c838a9fSAndrew Rybchenko __in unsigned int added,
8103c838a9fSAndrew Rybchenko __in unsigned int pushed)
811e948693eSPhilip Paeps {
812e948693eSPhilip Paeps efx_nic_t *enp = etp->et_enp;
813e948693eSPhilip Paeps uint32_t wptr;
814e948693eSPhilip Paeps efx_dword_t dword;
815e948693eSPhilip Paeps efx_oword_t oword;
816e948693eSPhilip Paeps
817e948693eSPhilip Paeps /* Push the populated descriptors out */
818e948693eSPhilip Paeps wptr = added & etp->et_mask;
819e948693eSPhilip Paeps
820e948693eSPhilip Paeps EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_DESC_WPTR, wptr);
821e948693eSPhilip Paeps
822e948693eSPhilip Paeps /* Only write the third DWORD */
823e948693eSPhilip Paeps EFX_POPULATE_DWORD_1(dword,
824e948693eSPhilip Paeps EFX_DWORD_0, EFX_OWORD_FIELD(oword, EFX_DWORD_3));
8253c838a9fSAndrew Rybchenko
8263c838a9fSAndrew Rybchenko /* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
8273c838a9fSAndrew Rybchenko EFX_DMA_SYNC_QUEUE_FOR_DEVICE(etp->et_esmp, etp->et_mask + 1,
8283c838a9fSAndrew Rybchenko wptr, pushed & etp->et_mask);
8293c838a9fSAndrew Rybchenko EFSYS_PIO_WRITE_BARRIER();
830e948693eSPhilip Paeps EFX_BAR_TBL_WRITED3(enp, FR_BZ_TX_DESC_UPD_REGP0,
831e948693eSPhilip Paeps etp->et_index, &dword, B_FALSE);
832e948693eSPhilip Paeps }
833e948693eSPhilip Paeps
8342fc13da6SAndrew Rybchenko #define EFX_MAX_PACE_VALUE 20
8352fc13da6SAndrew Rybchenko #define EFX_TX_PACE_CLOCK_BASE 104
8362fc13da6SAndrew Rybchenko
837460cb568SAndrew Rybchenko static __checkReturn efx_rc_t
siena_tx_qpace(__in efx_txq_t * etp,__in unsigned int ns)83896ffcdeeSAndrew Rybchenko siena_tx_qpace(
8392fc13da6SAndrew Rybchenko __in efx_txq_t *etp,
8402fc13da6SAndrew Rybchenko __in unsigned int ns)
8412fc13da6SAndrew Rybchenko {
8422fc13da6SAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
8432fc13da6SAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
8442fc13da6SAndrew Rybchenko efx_oword_t oword;
8452fc13da6SAndrew Rybchenko unsigned int pace_val;
8462fc13da6SAndrew Rybchenko unsigned int timer_period;
847460cb568SAndrew Rybchenko efx_rc_t rc;
8482fc13da6SAndrew Rybchenko
8492fc13da6SAndrew Rybchenko if (ns == 0) {
8502fc13da6SAndrew Rybchenko pace_val = 0;
8512fc13da6SAndrew Rybchenko } else {
8522fc13da6SAndrew Rybchenko /*
8532fc13da6SAndrew Rybchenko * The pace_val to write into the table is s.t
8542fc13da6SAndrew Rybchenko * ns <= timer_period * (2 ^ pace_val)
8552fc13da6SAndrew Rybchenko */
8562fc13da6SAndrew Rybchenko timer_period = EFX_TX_PACE_CLOCK_BASE / encp->enc_clk_mult;
8572fc13da6SAndrew Rybchenko for (pace_val = 1; pace_val <= EFX_MAX_PACE_VALUE; pace_val++) {
8582fc13da6SAndrew Rybchenko if ((timer_period << pace_val) >= ns)
8592fc13da6SAndrew Rybchenko break;
8602fc13da6SAndrew Rybchenko }
8612fc13da6SAndrew Rybchenko }
8622fc13da6SAndrew Rybchenko if (pace_val > EFX_MAX_PACE_VALUE) {
8632fc13da6SAndrew Rybchenko rc = EINVAL;
8642fc13da6SAndrew Rybchenko goto fail1;
8652fc13da6SAndrew Rybchenko }
8662fc13da6SAndrew Rybchenko
8672fc13da6SAndrew Rybchenko /* Update the pacing table */
8682fc13da6SAndrew Rybchenko EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_PACE, pace_val);
8693c838a9fSAndrew Rybchenko EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_PACE_TBL, etp->et_index,
8703c838a9fSAndrew Rybchenko &oword, B_TRUE);
8712fc13da6SAndrew Rybchenko
8722fc13da6SAndrew Rybchenko return (0);
8732fc13da6SAndrew Rybchenko
8742fc13da6SAndrew Rybchenko fail1:
875460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
8762fc13da6SAndrew Rybchenko
8772fc13da6SAndrew Rybchenko return (rc);
8782fc13da6SAndrew Rybchenko }
8792fc13da6SAndrew Rybchenko
880460cb568SAndrew Rybchenko static __checkReturn efx_rc_t
siena_tx_qflush(__in efx_txq_t * etp)88196ffcdeeSAndrew Rybchenko siena_tx_qflush(
882e948693eSPhilip Paeps __in efx_txq_t *etp)
883e948693eSPhilip Paeps {
884e948693eSPhilip Paeps efx_nic_t *enp = etp->et_enp;
885e948693eSPhilip Paeps efx_oword_t oword;
886e948693eSPhilip Paeps uint32_t label;
887e948693eSPhilip Paeps
8882fc13da6SAndrew Rybchenko efx_tx_qpace(etp, 0);
8892fc13da6SAndrew Rybchenko
890e948693eSPhilip Paeps label = etp->et_index;
891e948693eSPhilip Paeps
892e948693eSPhilip Paeps /* Flush the queue */
893e948693eSPhilip Paeps EFX_POPULATE_OWORD_2(oword, FRF_AZ_TX_FLUSH_DESCQ_CMD, 1,
894e948693eSPhilip Paeps FRF_AZ_TX_FLUSH_DESCQ, label);
895e948693eSPhilip Paeps EFX_BAR_WRITEO(enp, FR_AZ_TX_FLUSH_DESCQ_REG, &oword);
8963c838a9fSAndrew Rybchenko
8973c838a9fSAndrew Rybchenko return (0);
898e948693eSPhilip Paeps }
899e948693eSPhilip Paeps
9003c838a9fSAndrew Rybchenko static void
siena_tx_qenable(__in efx_txq_t * etp)90196ffcdeeSAndrew Rybchenko siena_tx_qenable(
902e948693eSPhilip Paeps __in efx_txq_t *etp)
903e948693eSPhilip Paeps {
904e948693eSPhilip Paeps efx_nic_t *enp = etp->et_enp;
905e948693eSPhilip Paeps efx_oword_t oword;
906e948693eSPhilip Paeps
907e948693eSPhilip Paeps EFX_BAR_TBL_READO(enp, FR_AZ_TX_DESC_PTR_TBL,
9083c838a9fSAndrew Rybchenko etp->et_index, &oword, B_TRUE);
909e948693eSPhilip Paeps
910e948693eSPhilip Paeps EFSYS_PROBE5(tx_descq_ptr, unsigned int, etp->et_index,
911e948693eSPhilip Paeps uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_3),
912e948693eSPhilip Paeps uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_2),
913e948693eSPhilip Paeps uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_1),
914e948693eSPhilip Paeps uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_0));
915e948693eSPhilip Paeps
916e948693eSPhilip Paeps EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DC_HW_RPTR, 0);
917e948693eSPhilip Paeps EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DESCQ_HW_RPTR, 0);
918e948693eSPhilip Paeps EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DESCQ_EN, 1);
919e948693eSPhilip Paeps
920e948693eSPhilip Paeps EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
9213c838a9fSAndrew Rybchenko etp->et_index, &oword, B_TRUE);
922e948693eSPhilip Paeps }
923e948693eSPhilip Paeps
924460cb568SAndrew Rybchenko static __checkReturn efx_rc_t
siena_tx_qcreate(__in efx_nic_t * enp,__in unsigned int index,__in unsigned int label,__in efsys_mem_t * esmp,__in size_t ndescs,__in uint32_t id,__in uint16_t flags,__in efx_evq_t * eep,__in efx_txq_t * etp,__out unsigned int * addedp)92596ffcdeeSAndrew Rybchenko siena_tx_qcreate(
926e948693eSPhilip Paeps __in efx_nic_t *enp,
927e948693eSPhilip Paeps __in unsigned int index,
928e948693eSPhilip Paeps __in unsigned int label,
929e948693eSPhilip Paeps __in efsys_mem_t *esmp,
9300c9ef1f5SAndrew Rybchenko __in size_t ndescs,
931e948693eSPhilip Paeps __in uint32_t id,
932e948693eSPhilip Paeps __in uint16_t flags,
933e948693eSPhilip Paeps __in efx_evq_t *eep,
9343c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
9353c838a9fSAndrew Rybchenko __out unsigned int *addedp)
936e948693eSPhilip Paeps {
937e948693eSPhilip Paeps efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
938e948693eSPhilip Paeps efx_oword_t oword;
939e948693eSPhilip Paeps uint32_t size;
94018b602f9SAndrew Rybchenko uint16_t inner_csum;
941460cb568SAndrew Rybchenko efx_rc_t rc;
942e948693eSPhilip Paeps
943a92a2133SAndrew Rybchenko _NOTE(ARGUNUSED(esmp))
944a92a2133SAndrew Rybchenko
945c071447aSAndrew Rybchenko EFX_STATIC_ASSERT(EFX_EV_TX_NLABELS ==
946c071447aSAndrew Rybchenko (1 << FRF_AZ_TX_DESCQ_LABEL_WIDTH));
947c071447aSAndrew Rybchenko EFSYS_ASSERT3U(label, <, EFX_EV_TX_NLABELS);
948e948693eSPhilip Paeps
949d343a7f4SAndrew Rybchenko EFSYS_ASSERT(ISP2(encp->enc_txq_max_ndescs));
9503c838a9fSAndrew Rybchenko EFX_STATIC_ASSERT(ISP2(EFX_TXQ_MINNDESCS));
9513c838a9fSAndrew Rybchenko
9520c9ef1f5SAndrew Rybchenko if (!ISP2(ndescs) ||
9530c9ef1f5SAndrew Rybchenko (ndescs < EFX_TXQ_MINNDESCS) || (ndescs > EFX_EVQ_MAXNEVS)) {
954e948693eSPhilip Paeps rc = EINVAL;
955e948693eSPhilip Paeps goto fail1;
956e948693eSPhilip Paeps }
957e948693eSPhilip Paeps if (index >= encp->enc_txq_limit) {
958e948693eSPhilip Paeps rc = EINVAL;
959e948693eSPhilip Paeps goto fail2;
960e948693eSPhilip Paeps }
9613c838a9fSAndrew Rybchenko for (size = 0;
962d343a7f4SAndrew Rybchenko (1 << size) <= (int)(encp->enc_txq_max_ndescs / EFX_TXQ_MINNDESCS);
963e948693eSPhilip Paeps size++)
9640c9ef1f5SAndrew Rybchenko if ((1 << size) == (int)(ndescs / EFX_TXQ_MINNDESCS))
965e948693eSPhilip Paeps break;
966e948693eSPhilip Paeps if (id + (1 << size) >= encp->enc_buftbl_limit) {
967e948693eSPhilip Paeps rc = EINVAL;
968e948693eSPhilip Paeps goto fail3;
969e948693eSPhilip Paeps }
970e948693eSPhilip Paeps
97118b602f9SAndrew Rybchenko inner_csum = EFX_TXQ_CKSUM_INNER_IPV4 | EFX_TXQ_CKSUM_INNER_TCPUDP;
97218b602f9SAndrew Rybchenko if ((flags & inner_csum) != 0) {
97318b602f9SAndrew Rybchenko rc = EINVAL;
97418b602f9SAndrew Rybchenko goto fail4;
97518b602f9SAndrew Rybchenko }
97618b602f9SAndrew Rybchenko
977e948693eSPhilip Paeps /* Set up the new descriptor queue */
97845229bd4SAndrew Rybchenko *addedp = 0;
97945229bd4SAndrew Rybchenko
980e948693eSPhilip Paeps EFX_POPULATE_OWORD_6(oword,
981e948693eSPhilip Paeps FRF_AZ_TX_DESCQ_BUF_BASE_ID, id,
982e948693eSPhilip Paeps FRF_AZ_TX_DESCQ_EVQ_ID, eep->ee_index,
983e948693eSPhilip Paeps FRF_AZ_TX_DESCQ_OWNER_ID, 0,
984e948693eSPhilip Paeps FRF_AZ_TX_DESCQ_LABEL, label,
985e948693eSPhilip Paeps FRF_AZ_TX_DESCQ_SIZE, size,
986e948693eSPhilip Paeps FRF_AZ_TX_DESCQ_TYPE, 0);
987e948693eSPhilip Paeps
988e948693eSPhilip Paeps EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_NON_IP_DROP_DIS, 1);
989e948693eSPhilip Paeps EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_IP_CHKSM_DIS,
9909dd0e15fSAndrew Rybchenko (flags & EFX_TXQ_CKSUM_IPV4) ? 0 : 1);
991e948693eSPhilip Paeps EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_TCP_CHKSM_DIS,
9929dd0e15fSAndrew Rybchenko (flags & EFX_TXQ_CKSUM_TCPUDP) ? 0 : 1);
993e948693eSPhilip Paeps
994e948693eSPhilip Paeps EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
9953c838a9fSAndrew Rybchenko etp->et_index, &oword, B_TRUE);
996e948693eSPhilip Paeps
997e948693eSPhilip Paeps return (0);
998e948693eSPhilip Paeps
99918b602f9SAndrew Rybchenko fail4:
100018b602f9SAndrew Rybchenko EFSYS_PROBE(fail4);
1001e948693eSPhilip Paeps fail3:
1002e948693eSPhilip Paeps EFSYS_PROBE(fail3);
1003e948693eSPhilip Paeps fail2:
1004e948693eSPhilip Paeps EFSYS_PROBE(fail2);
1005e948693eSPhilip Paeps fail1:
1006460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
1007e948693eSPhilip Paeps
1008e948693eSPhilip Paeps return (rc);
1009e948693eSPhilip Paeps }
1010e948693eSPhilip Paeps
1011460cb568SAndrew Rybchenko __checkReturn efx_rc_t
siena_tx_qdesc_post(__in efx_txq_t * etp,__in_ecount (ndescs)efx_desc_t * ed,__in unsigned int ndescs,__in unsigned int completed,__inout unsigned int * addedp)101296ffcdeeSAndrew Rybchenko siena_tx_qdesc_post(
10133c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
10140c9ef1f5SAndrew Rybchenko __in_ecount(ndescs) efx_desc_t *ed,
10150c9ef1f5SAndrew Rybchenko __in unsigned int ndescs,
10163c838a9fSAndrew Rybchenko __in unsigned int completed,
10173c838a9fSAndrew Rybchenko __inout unsigned int *addedp)
10183c838a9fSAndrew Rybchenko {
10193c838a9fSAndrew Rybchenko unsigned int added = *addedp;
10203c838a9fSAndrew Rybchenko unsigned int i;
1021460cb568SAndrew Rybchenko efx_rc_t rc;
10223c838a9fSAndrew Rybchenko
10230c9ef1f5SAndrew Rybchenko if (added - completed + ndescs > EFX_TXQ_LIMIT(etp->et_mask + 1)) {
10243c838a9fSAndrew Rybchenko rc = ENOSPC;
10253c838a9fSAndrew Rybchenko goto fail1;
10263c838a9fSAndrew Rybchenko }
10273c838a9fSAndrew Rybchenko
10280c9ef1f5SAndrew Rybchenko for (i = 0; i < ndescs; i++) {
10293c838a9fSAndrew Rybchenko efx_desc_t *edp = &ed[i];
10303c838a9fSAndrew Rybchenko unsigned int id;
10313c838a9fSAndrew Rybchenko size_t offset;
10323c838a9fSAndrew Rybchenko
10333c838a9fSAndrew Rybchenko id = added++ & etp->et_mask;
10343c838a9fSAndrew Rybchenko offset = id * sizeof (efx_desc_t);
10353c838a9fSAndrew Rybchenko
10363c838a9fSAndrew Rybchenko EFSYS_MEM_WRITEQ(etp->et_esmp, offset, &edp->ed_eq);
10373c838a9fSAndrew Rybchenko }
10383c838a9fSAndrew Rybchenko
10393c838a9fSAndrew Rybchenko EFSYS_PROBE3(tx_desc_post, unsigned int, etp->et_index,
10400c9ef1f5SAndrew Rybchenko unsigned int, added, unsigned int, ndescs);
10413c838a9fSAndrew Rybchenko
10423c838a9fSAndrew Rybchenko EFX_TX_QSTAT_INCR(etp, TX_POST);
10433c838a9fSAndrew Rybchenko
10443c838a9fSAndrew Rybchenko *addedp = added;
10453c838a9fSAndrew Rybchenko return (0);
10463c838a9fSAndrew Rybchenko
10473c838a9fSAndrew Rybchenko fail1:
1048460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
10493c838a9fSAndrew Rybchenko return (rc);
10503c838a9fSAndrew Rybchenko }
10513c838a9fSAndrew Rybchenko
10523c838a9fSAndrew Rybchenko void
siena_tx_qdesc_dma_create(__in efx_txq_t * etp,__in efsys_dma_addr_t addr,__in size_t size,__in boolean_t eop,__out efx_desc_t * edp)105396ffcdeeSAndrew Rybchenko siena_tx_qdesc_dma_create(
10543c838a9fSAndrew Rybchenko __in efx_txq_t *etp,
10553c838a9fSAndrew Rybchenko __in efsys_dma_addr_t addr,
10563c838a9fSAndrew Rybchenko __in size_t size,
10573c838a9fSAndrew Rybchenko __in boolean_t eop,
10583c838a9fSAndrew Rybchenko __out efx_desc_t *edp)
10593c838a9fSAndrew Rybchenko {
10606a09b206SAndrew Rybchenko /*
10616a09b206SAndrew Rybchenko * Fragments must not span 4k boundaries.
10626a09b206SAndrew Rybchenko * Here it is a stricter requirement than the maximum length.
10636a09b206SAndrew Rybchenko */
1064ec30f0beSAndrew Rybchenko EFSYS_ASSERT(EFX_P2ROUNDUP(efsys_dma_addr_t, addr + 1,
10656a09b206SAndrew Rybchenko etp->et_enp->en_nic_cfg.enc_tx_dma_desc_boundary) >= addr + size);
10663c838a9fSAndrew Rybchenko
10673c838a9fSAndrew Rybchenko EFSYS_PROBE4(tx_desc_dma_create, unsigned int, etp->et_index,
10683c838a9fSAndrew Rybchenko efsys_dma_addr_t, addr,
10693c838a9fSAndrew Rybchenko size_t, size, boolean_t, eop);
10703c838a9fSAndrew Rybchenko
10713c838a9fSAndrew Rybchenko EFX_POPULATE_QWORD_4(edp->ed_eq,
10723c838a9fSAndrew Rybchenko FSF_AZ_TX_KER_CONT, eop ? 0 : 1,
10733c838a9fSAndrew Rybchenko FSF_AZ_TX_KER_BYTE_COUNT, (uint32_t)size,
10743c838a9fSAndrew Rybchenko FSF_AZ_TX_KER_BUF_ADDR_DW0,
10753c838a9fSAndrew Rybchenko (uint32_t)(addr & 0xffffffff),
10763c838a9fSAndrew Rybchenko FSF_AZ_TX_KER_BUF_ADDR_DW1,
10773c838a9fSAndrew Rybchenko (uint32_t)(addr >> 32));
10783c838a9fSAndrew Rybchenko }
10793c838a9fSAndrew Rybchenko
1080e75412c9SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
10813c838a9fSAndrew Rybchenko
1082fe900081SAndrew Rybchenko #if EFSYS_OPT_QSTATS
1083e948693eSPhilip Paeps #if EFSYS_OPT_NAMES
1084a260bd77SAndrew Rybchenko /* START MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock 2866874ecd7a363b */
1085a260bd77SAndrew Rybchenko static const char * const __efx_tx_qstat_name[] = {
1086e948693eSPhilip Paeps "post",
10873c838a9fSAndrew Rybchenko "post_pio",
1088e948693eSPhilip Paeps };
1089e948693eSPhilip Paeps /* END MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock */
1090e948693eSPhilip Paeps
10913c838a9fSAndrew Rybchenko const char *
efx_tx_qstat_name(__in efx_nic_t * enp,__in unsigned int id)1092e948693eSPhilip Paeps efx_tx_qstat_name(
1093e948693eSPhilip Paeps __in efx_nic_t *enp,
1094e948693eSPhilip Paeps __in unsigned int id)
1095e948693eSPhilip Paeps {
1096e948693eSPhilip Paeps _NOTE(ARGUNUSED(enp))
1097e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1098e948693eSPhilip Paeps EFSYS_ASSERT3U(id, <, TX_NQSTATS);
1099e948693eSPhilip Paeps
1100e948693eSPhilip Paeps return (__efx_tx_qstat_name[id]);
1101e948693eSPhilip Paeps }
1102e948693eSPhilip Paeps #endif /* EFSYS_OPT_NAMES */
1103fe900081SAndrew Rybchenko #endif /* EFSYS_OPT_QSTATS */
1104e948693eSPhilip Paeps
1105e75412c9SAndrew Rybchenko #if EFSYS_OPT_SIENA
11063c838a9fSAndrew Rybchenko
1107e948693eSPhilip Paeps #if EFSYS_OPT_QSTATS
11083c838a9fSAndrew Rybchenko static void
siena_tx_qstats_update(__in efx_txq_t * etp,__inout_ecount (TX_NQSTATS)efsys_stat_t * stat)110996ffcdeeSAndrew Rybchenko siena_tx_qstats_update(
1110e948693eSPhilip Paeps __in efx_txq_t *etp,
1111e948693eSPhilip Paeps __inout_ecount(TX_NQSTATS) efsys_stat_t *stat)
1112e948693eSPhilip Paeps {
1113e948693eSPhilip Paeps unsigned int id;
1114e948693eSPhilip Paeps
1115e948693eSPhilip Paeps for (id = 0; id < TX_NQSTATS; id++) {
1116e948693eSPhilip Paeps efsys_stat_t *essp = &stat[id];
1117e948693eSPhilip Paeps
1118e948693eSPhilip Paeps EFSYS_STAT_INCR(essp, etp->et_stat[id]);
1119e948693eSPhilip Paeps etp->et_stat[id] = 0;
1120e948693eSPhilip Paeps }
1121e948693eSPhilip Paeps }
1122e948693eSPhilip Paeps #endif /* EFSYS_OPT_QSTATS */
1123e948693eSPhilip Paeps
11243c838a9fSAndrew Rybchenko static void
siena_tx_qdestroy(__in efx_txq_t * etp)112596ffcdeeSAndrew Rybchenko siena_tx_qdestroy(
1126e948693eSPhilip Paeps __in efx_txq_t *etp)
1127e948693eSPhilip Paeps {
1128e948693eSPhilip Paeps efx_nic_t *enp = etp->et_enp;
1129e948693eSPhilip Paeps efx_oword_t oword;
1130e948693eSPhilip Paeps
1131e948693eSPhilip Paeps /* Purge descriptor queue */
1132e948693eSPhilip Paeps EFX_ZERO_OWORD(oword);
1133e948693eSPhilip Paeps
1134e948693eSPhilip Paeps EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
11353c838a9fSAndrew Rybchenko etp->et_index, &oword, B_TRUE);
1136e948693eSPhilip Paeps }
1137e948693eSPhilip Paeps
11383c838a9fSAndrew Rybchenko static void
siena_tx_fini(__in efx_nic_t * enp)113996ffcdeeSAndrew Rybchenko siena_tx_fini(
1140e948693eSPhilip Paeps __in efx_nic_t *enp)
1141e948693eSPhilip Paeps {
11423c838a9fSAndrew Rybchenko _NOTE(ARGUNUSED(enp))
1143e948693eSPhilip Paeps }
11443c838a9fSAndrew Rybchenko
1145e75412c9SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
1146