169fb4e16SAndrew Rybchenko /*-
2929c7febSAndrew Rybchenko * Copyright (c) 2012-2016 Solarflare Communications Inc.
369fb4e16SAndrew Rybchenko * All rights reserved.
469fb4e16SAndrew Rybchenko *
569fb4e16SAndrew Rybchenko * Redistribution and use in source and binary forms, with or without
669fb4e16SAndrew Rybchenko * modification, are permitted provided that the following conditions are met:
769fb4e16SAndrew Rybchenko *
869fb4e16SAndrew Rybchenko * 1. Redistributions of source code must retain the above copyright notice,
969fb4e16SAndrew Rybchenko * this list of conditions and the following disclaimer.
1069fb4e16SAndrew Rybchenko * 2. Redistributions in binary form must reproduce the above copyright notice,
1169fb4e16SAndrew Rybchenko * this list of conditions and the following disclaimer in the documentation
1269fb4e16SAndrew Rybchenko * and/or other materials provided with the distribution.
1369fb4e16SAndrew Rybchenko *
1469fb4e16SAndrew Rybchenko * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1569fb4e16SAndrew Rybchenko * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
1669fb4e16SAndrew Rybchenko * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1769fb4e16SAndrew Rybchenko * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
1869fb4e16SAndrew Rybchenko * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1969fb4e16SAndrew Rybchenko * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2069fb4e16SAndrew Rybchenko * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2169fb4e16SAndrew Rybchenko * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2269fb4e16SAndrew Rybchenko * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2369fb4e16SAndrew Rybchenko * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
2469fb4e16SAndrew Rybchenko * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2569fb4e16SAndrew Rybchenko *
2669fb4e16SAndrew Rybchenko * The views and conclusions contained in the software and documentation are
2769fb4e16SAndrew Rybchenko * those of the authors and should not be interpreted as representing official
2869fb4e16SAndrew Rybchenko * policies, either expressed or implied, of the FreeBSD Project.
2969fb4e16SAndrew Rybchenko */
3069fb4e16SAndrew Rybchenko
3169fb4e16SAndrew Rybchenko #include <sys/cdefs.h>
3269fb4e16SAndrew Rybchenko #include "efx.h"
3369fb4e16SAndrew Rybchenko #include "efx_impl.h"
3469fb4e16SAndrew Rybchenko
3520c5aab3SAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
3669fb4e16SAndrew Rybchenko
3769fb4e16SAndrew Rybchenko #if EFSYS_OPT_QSTATS
3869fb4e16SAndrew Rybchenko #define EFX_TX_QSTAT_INCR(_etp, _stat) \
3969fb4e16SAndrew Rybchenko do { \
4069fb4e16SAndrew Rybchenko (_etp)->et_stat[_stat]++; \
4169fb4e16SAndrew Rybchenko _NOTE(CONSTANTCONDITION) \
4269fb4e16SAndrew Rybchenko } while (B_FALSE)
4369fb4e16SAndrew Rybchenko #else
4469fb4e16SAndrew Rybchenko #define EFX_TX_QSTAT_INCR(_etp, _stat)
4569fb4e16SAndrew Rybchenko #endif
4669fb4e16SAndrew Rybchenko
4769fb4e16SAndrew Rybchenko static __checkReturn efx_rc_t
efx_mcdi_init_txq(__in efx_nic_t * enp,__in uint32_t ndescs,__in uint32_t target_evq,__in uint32_t label,__in uint32_t instance,__in uint16_t flags,__in efsys_mem_t * esmp)4869fb4e16SAndrew Rybchenko efx_mcdi_init_txq(
4969fb4e16SAndrew Rybchenko __in efx_nic_t *enp,
500c9ef1f5SAndrew Rybchenko __in uint32_t ndescs,
5169fb4e16SAndrew Rybchenko __in uint32_t target_evq,
5269fb4e16SAndrew Rybchenko __in uint32_t label,
5369fb4e16SAndrew Rybchenko __in uint32_t instance,
5469fb4e16SAndrew Rybchenko __in uint16_t flags,
5569fb4e16SAndrew Rybchenko __in efsys_mem_t *esmp)
5669fb4e16SAndrew Rybchenko {
5769fb4e16SAndrew Rybchenko efx_mcdi_req_t req;
58*315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_INIT_TXQ_IN_LEN(EFX_TXQ_MAX_BUFS),
59*315bbbaaSAndrew Rybchenko MC_CMD_INIT_TXQ_OUT_LEN);
6069fb4e16SAndrew Rybchenko efx_qword_t *dma_addr;
6169fb4e16SAndrew Rybchenko uint64_t addr;
6269fb4e16SAndrew Rybchenko int npages;
6369fb4e16SAndrew Rybchenko int i;
6469fb4e16SAndrew Rybchenko efx_rc_t rc;
6569fb4e16SAndrew Rybchenko
6669fb4e16SAndrew Rybchenko EFSYS_ASSERT(EFX_TXQ_MAX_BUFS >=
67d343a7f4SAndrew Rybchenko EFX_TXQ_NBUFS(enp->en_nic_cfg.enc_txq_max_ndescs));
6869fb4e16SAndrew Rybchenko
694aaefb95SAndrew Rybchenko if ((esmp == NULL) || (EFSYS_MEM_SIZE(esmp) < EFX_TXQ_SIZE(ndescs))) {
704aaefb95SAndrew Rybchenko rc = EINVAL;
714aaefb95SAndrew Rybchenko goto fail1;
724aaefb95SAndrew Rybchenko }
734aaefb95SAndrew Rybchenko
740c9ef1f5SAndrew Rybchenko npages = EFX_TXQ_NBUFS(ndescs);
758302d100SAndrew Rybchenko if (MC_CMD_INIT_TXQ_IN_LEN(npages) > sizeof (payload)) {
7669fb4e16SAndrew Rybchenko rc = EINVAL;
774aaefb95SAndrew Rybchenko goto fail2;
7869fb4e16SAndrew Rybchenko }
7969fb4e16SAndrew Rybchenko
8069fb4e16SAndrew Rybchenko req.emr_cmd = MC_CMD_INIT_TXQ;
8169fb4e16SAndrew Rybchenko req.emr_in_buf = payload;
8269fb4e16SAndrew Rybchenko req.emr_in_length = MC_CMD_INIT_TXQ_IN_LEN(npages);
8369fb4e16SAndrew Rybchenko req.emr_out_buf = payload;
8469fb4e16SAndrew Rybchenko req.emr_out_length = MC_CMD_INIT_TXQ_OUT_LEN;
8569fb4e16SAndrew Rybchenko
860c9ef1f5SAndrew Rybchenko MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_SIZE, ndescs);
8769fb4e16SAndrew Rybchenko MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_TARGET_EVQ, target_evq);
8869fb4e16SAndrew Rybchenko MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_LABEL, label);
8969fb4e16SAndrew Rybchenko MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_INSTANCE, instance);
9069fb4e16SAndrew Rybchenko
9118b602f9SAndrew Rybchenko MCDI_IN_POPULATE_DWORD_9(req, INIT_TXQ_IN_FLAGS,
9269fb4e16SAndrew Rybchenko INIT_TXQ_IN_FLAG_BUFF_MODE, 0,
9369fb4e16SAndrew Rybchenko INIT_TXQ_IN_FLAG_IP_CSUM_DIS,
9469fb4e16SAndrew Rybchenko (flags & EFX_TXQ_CKSUM_IPV4) ? 0 : 1,
9569fb4e16SAndrew Rybchenko INIT_TXQ_IN_FLAG_TCP_CSUM_DIS,
9669fb4e16SAndrew Rybchenko (flags & EFX_TXQ_CKSUM_TCPUDP) ? 0 : 1,
9718b602f9SAndrew Rybchenko INIT_TXQ_EXT_IN_FLAG_INNER_IP_CSUM_EN,
9818b602f9SAndrew Rybchenko (flags & EFX_TXQ_CKSUM_INNER_IPV4) ? 1 : 0,
9918b602f9SAndrew Rybchenko INIT_TXQ_EXT_IN_FLAG_INNER_TCP_CSUM_EN,
10018b602f9SAndrew Rybchenko (flags & EFX_TXQ_CKSUM_INNER_TCPUDP) ? 1 : 0,
10169fb4e16SAndrew Rybchenko INIT_TXQ_EXT_IN_FLAG_TSOV2_EN, (flags & EFX_TXQ_FATSOV2) ? 1 : 0,
10269fb4e16SAndrew Rybchenko INIT_TXQ_IN_FLAG_TCP_UDP_ONLY, 0,
10369fb4e16SAndrew Rybchenko INIT_TXQ_IN_CRC_MODE, 0,
10469fb4e16SAndrew Rybchenko INIT_TXQ_IN_FLAG_TIMESTAMP, 0);
10569fb4e16SAndrew Rybchenko
10669fb4e16SAndrew Rybchenko MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_OWNER_ID, 0);
10769fb4e16SAndrew Rybchenko MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_PORT_ID, EVB_PORT_ID_ASSIGNED);
10869fb4e16SAndrew Rybchenko
10969fb4e16SAndrew Rybchenko dma_addr = MCDI_IN2(req, efx_qword_t, INIT_TXQ_IN_DMA_ADDR);
11069fb4e16SAndrew Rybchenko addr = EFSYS_MEM_ADDR(esmp);
11169fb4e16SAndrew Rybchenko
11269fb4e16SAndrew Rybchenko for (i = 0; i < npages; i++) {
11369fb4e16SAndrew Rybchenko EFX_POPULATE_QWORD_2(*dma_addr,
11469fb4e16SAndrew Rybchenko EFX_DWORD_1, (uint32_t)(addr >> 32),
11569fb4e16SAndrew Rybchenko EFX_DWORD_0, (uint32_t)(addr & 0xffffffff));
11669fb4e16SAndrew Rybchenko
11769fb4e16SAndrew Rybchenko dma_addr++;
11869fb4e16SAndrew Rybchenko addr += EFX_BUF_SIZE;
11969fb4e16SAndrew Rybchenko }
12069fb4e16SAndrew Rybchenko
12169fb4e16SAndrew Rybchenko efx_mcdi_execute(enp, &req);
12269fb4e16SAndrew Rybchenko
12369fb4e16SAndrew Rybchenko if (req.emr_rc != 0) {
12469fb4e16SAndrew Rybchenko rc = req.emr_rc;
1254aaefb95SAndrew Rybchenko goto fail3;
12669fb4e16SAndrew Rybchenko }
12769fb4e16SAndrew Rybchenko
12869fb4e16SAndrew Rybchenko return (0);
12969fb4e16SAndrew Rybchenko
1304aaefb95SAndrew Rybchenko fail3:
1314aaefb95SAndrew Rybchenko EFSYS_PROBE(fail3);
13269fb4e16SAndrew Rybchenko fail2:
13369fb4e16SAndrew Rybchenko EFSYS_PROBE(fail2);
13469fb4e16SAndrew Rybchenko fail1:
13569fb4e16SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
13669fb4e16SAndrew Rybchenko
13769fb4e16SAndrew Rybchenko return (rc);
13869fb4e16SAndrew Rybchenko }
13969fb4e16SAndrew Rybchenko
14069fb4e16SAndrew Rybchenko static __checkReturn efx_rc_t
efx_mcdi_fini_txq(__in efx_nic_t * enp,__in uint32_t instance)14169fb4e16SAndrew Rybchenko efx_mcdi_fini_txq(
14269fb4e16SAndrew Rybchenko __in efx_nic_t *enp,
14369fb4e16SAndrew Rybchenko __in uint32_t instance)
14469fb4e16SAndrew Rybchenko {
14569fb4e16SAndrew Rybchenko efx_mcdi_req_t req;
146*315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FINI_TXQ_IN_LEN,
147*315bbbaaSAndrew Rybchenko MC_CMD_FINI_TXQ_OUT_LEN);
14869fb4e16SAndrew Rybchenko efx_rc_t rc;
14969fb4e16SAndrew Rybchenko
15069fb4e16SAndrew Rybchenko req.emr_cmd = MC_CMD_FINI_TXQ;
15169fb4e16SAndrew Rybchenko req.emr_in_buf = payload;
15269fb4e16SAndrew Rybchenko req.emr_in_length = MC_CMD_FINI_TXQ_IN_LEN;
15369fb4e16SAndrew Rybchenko req.emr_out_buf = payload;
15469fb4e16SAndrew Rybchenko req.emr_out_length = MC_CMD_FINI_TXQ_OUT_LEN;
15569fb4e16SAndrew Rybchenko
15669fb4e16SAndrew Rybchenko MCDI_IN_SET_DWORD(req, FINI_TXQ_IN_INSTANCE, instance);
15769fb4e16SAndrew Rybchenko
158bba8dcbcSAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req);
15969fb4e16SAndrew Rybchenko
1607e1059e8SAndrew Rybchenko if (req.emr_rc != 0) {
16169fb4e16SAndrew Rybchenko rc = req.emr_rc;
16269fb4e16SAndrew Rybchenko goto fail1;
16369fb4e16SAndrew Rybchenko }
16469fb4e16SAndrew Rybchenko
16569fb4e16SAndrew Rybchenko return (0);
16669fb4e16SAndrew Rybchenko
16769fb4e16SAndrew Rybchenko fail1:
1687e1059e8SAndrew Rybchenko /*
1697e1059e8SAndrew Rybchenko * EALREADY is not an error, but indicates that the MC has rebooted and
1707e1059e8SAndrew Rybchenko * that the TXQ has already been destroyed.
1717e1059e8SAndrew Rybchenko */
1727e1059e8SAndrew Rybchenko if (rc != EALREADY)
17369fb4e16SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
17469fb4e16SAndrew Rybchenko
17569fb4e16SAndrew Rybchenko return (rc);
17669fb4e16SAndrew Rybchenko }
17769fb4e16SAndrew Rybchenko
17869fb4e16SAndrew Rybchenko __checkReturn efx_rc_t
ef10_tx_init(__in efx_nic_t * enp)17969fb4e16SAndrew Rybchenko ef10_tx_init(
18069fb4e16SAndrew Rybchenko __in efx_nic_t *enp)
18169fb4e16SAndrew Rybchenko {
18269fb4e16SAndrew Rybchenko _NOTE(ARGUNUSED(enp))
18369fb4e16SAndrew Rybchenko return (0);
18469fb4e16SAndrew Rybchenko }
18569fb4e16SAndrew Rybchenko
18669fb4e16SAndrew Rybchenko void
ef10_tx_fini(__in efx_nic_t * enp)18769fb4e16SAndrew Rybchenko ef10_tx_fini(
18869fb4e16SAndrew Rybchenko __in efx_nic_t *enp)
18969fb4e16SAndrew Rybchenko {
19069fb4e16SAndrew Rybchenko _NOTE(ARGUNUSED(enp))
19169fb4e16SAndrew Rybchenko }
19269fb4e16SAndrew Rybchenko
19369fb4e16SAndrew Rybchenko __checkReturn efx_rc_t
ef10_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)19469fb4e16SAndrew Rybchenko ef10_tx_qcreate(
19569fb4e16SAndrew Rybchenko __in efx_nic_t *enp,
19669fb4e16SAndrew Rybchenko __in unsigned int index,
19769fb4e16SAndrew Rybchenko __in unsigned int label,
19869fb4e16SAndrew Rybchenko __in efsys_mem_t *esmp,
1990c9ef1f5SAndrew Rybchenko __in size_t ndescs,
20069fb4e16SAndrew Rybchenko __in uint32_t id,
20169fb4e16SAndrew Rybchenko __in uint16_t flags,
20269fb4e16SAndrew Rybchenko __in efx_evq_t *eep,
20369fb4e16SAndrew Rybchenko __in efx_txq_t *etp,
20469fb4e16SAndrew Rybchenko __out unsigned int *addedp)
20569fb4e16SAndrew Rybchenko {
20618b602f9SAndrew Rybchenko efx_nic_cfg_t *encp = &enp->en_nic_cfg;
20718b602f9SAndrew Rybchenko uint16_t inner_csum;
2084effeb9eSAndrew Rybchenko efx_desc_t desc;
20969fb4e16SAndrew Rybchenko efx_rc_t rc;
21069fb4e16SAndrew Rybchenko
211a92a2133SAndrew Rybchenko _NOTE(ARGUNUSED(id))
21269fb4e16SAndrew Rybchenko
21318b602f9SAndrew Rybchenko inner_csum = EFX_TXQ_CKSUM_INNER_IPV4 | EFX_TXQ_CKSUM_INNER_TCPUDP;
21418b602f9SAndrew Rybchenko if (((flags & inner_csum) != 0) &&
21518b602f9SAndrew Rybchenko (encp->enc_tunnel_encapsulations_supported == 0)) {
21618b602f9SAndrew Rybchenko rc = EINVAL;
21718b602f9SAndrew Rybchenko goto fail1;
21818b602f9SAndrew Rybchenko }
21918b602f9SAndrew Rybchenko
2200c9ef1f5SAndrew Rybchenko if ((rc = efx_mcdi_init_txq(enp, ndescs, eep->ee_index, label, index,
2210c9ef1f5SAndrew Rybchenko flags, esmp)) != 0)
22218b602f9SAndrew Rybchenko goto fail2;
22369fb4e16SAndrew Rybchenko
22469fb4e16SAndrew Rybchenko /*
22569fb4e16SAndrew Rybchenko * A previous user of this TX queue may have written a descriptor to the
22669fb4e16SAndrew Rybchenko * TX push collector, but not pushed the doorbell (e.g. after a crash).
22769fb4e16SAndrew Rybchenko * The next doorbell write would then push the stale descriptor.
22869fb4e16SAndrew Rybchenko *
22969fb4e16SAndrew Rybchenko * Ensure the (per network port) TX push collector is cleared by writing
23069fb4e16SAndrew Rybchenko * a no-op TX option descriptor. See bug29981 for details.
23169fb4e16SAndrew Rybchenko */
23269fb4e16SAndrew Rybchenko *addedp = 1;
2334effeb9eSAndrew Rybchenko ef10_tx_qdesc_checksum_create(etp, flags, &desc);
23469fb4e16SAndrew Rybchenko
2354effeb9eSAndrew Rybchenko EFSYS_MEM_WRITEQ(etp->et_esmp, 0, &desc.ed_eq);
23669fb4e16SAndrew Rybchenko ef10_tx_qpush(etp, *addedp, 0);
23769fb4e16SAndrew Rybchenko
23869fb4e16SAndrew Rybchenko return (0);
23969fb4e16SAndrew Rybchenko
24018b602f9SAndrew Rybchenko fail2:
24118b602f9SAndrew Rybchenko EFSYS_PROBE(fail2);
24269fb4e16SAndrew Rybchenko fail1:
24369fb4e16SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
24469fb4e16SAndrew Rybchenko
24569fb4e16SAndrew Rybchenko return (rc);
24669fb4e16SAndrew Rybchenko }
24769fb4e16SAndrew Rybchenko
24869fb4e16SAndrew Rybchenko void
ef10_tx_qdestroy(__in efx_txq_t * etp)24969fb4e16SAndrew Rybchenko ef10_tx_qdestroy(
25069fb4e16SAndrew Rybchenko __in efx_txq_t *etp)
25169fb4e16SAndrew Rybchenko {
25269fb4e16SAndrew Rybchenko /* FIXME */
25369fb4e16SAndrew Rybchenko _NOTE(ARGUNUSED(etp))
25469fb4e16SAndrew Rybchenko /* FIXME */
25569fb4e16SAndrew Rybchenko }
25669fb4e16SAndrew Rybchenko
25769fb4e16SAndrew Rybchenko __checkReturn efx_rc_t
ef10_tx_qpio_enable(__in efx_txq_t * etp)25869fb4e16SAndrew Rybchenko ef10_tx_qpio_enable(
25969fb4e16SAndrew Rybchenko __in efx_txq_t *etp)
26069fb4e16SAndrew Rybchenko {
26169fb4e16SAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
26269fb4e16SAndrew Rybchenko efx_piobuf_handle_t handle;
26369fb4e16SAndrew Rybchenko efx_rc_t rc;
26469fb4e16SAndrew Rybchenko
26569fb4e16SAndrew Rybchenko if (etp->et_pio_size != 0) {
26669fb4e16SAndrew Rybchenko rc = EALREADY;
26769fb4e16SAndrew Rybchenko goto fail1;
26869fb4e16SAndrew Rybchenko }
26969fb4e16SAndrew Rybchenko
27069fb4e16SAndrew Rybchenko /* Sub-allocate a PIO block from a piobuf */
27169fb4e16SAndrew Rybchenko if ((rc = ef10_nic_pio_alloc(enp,
27269fb4e16SAndrew Rybchenko &etp->et_pio_bufnum,
27369fb4e16SAndrew Rybchenko &handle,
27469fb4e16SAndrew Rybchenko &etp->et_pio_blknum,
27569fb4e16SAndrew Rybchenko &etp->et_pio_offset,
27669fb4e16SAndrew Rybchenko &etp->et_pio_size)) != 0) {
27769fb4e16SAndrew Rybchenko goto fail2;
27869fb4e16SAndrew Rybchenko }
27969fb4e16SAndrew Rybchenko EFSYS_ASSERT3U(etp->et_pio_size, !=, 0);
28069fb4e16SAndrew Rybchenko
28169fb4e16SAndrew Rybchenko /* Link the piobuf to this TXQ */
28269fb4e16SAndrew Rybchenko if ((rc = ef10_nic_pio_link(enp, etp->et_index, handle)) != 0) {
28369fb4e16SAndrew Rybchenko goto fail3;
28469fb4e16SAndrew Rybchenko }
28569fb4e16SAndrew Rybchenko
28669fb4e16SAndrew Rybchenko /*
28769fb4e16SAndrew Rybchenko * et_pio_offset is the offset of the sub-allocated block within the
28869fb4e16SAndrew Rybchenko * hardware PIO buffer. It is used as the buffer address in the PIO
28969fb4e16SAndrew Rybchenko * option descriptor.
29069fb4e16SAndrew Rybchenko *
29169fb4e16SAndrew Rybchenko * et_pio_write_offset is the offset of the sub-allocated block from the
29269fb4e16SAndrew Rybchenko * start of the write-combined memory mapping, and is used for writing
29369fb4e16SAndrew Rybchenko * data into the PIO buffer.
29469fb4e16SAndrew Rybchenko */
29569fb4e16SAndrew Rybchenko etp->et_pio_write_offset =
29669fb4e16SAndrew Rybchenko (etp->et_pio_bufnum * ER_DZ_TX_PIOBUF_STEP) +
29769fb4e16SAndrew Rybchenko ER_DZ_TX_PIOBUF_OFST + etp->et_pio_offset;
29869fb4e16SAndrew Rybchenko
29969fb4e16SAndrew Rybchenko return (0);
30069fb4e16SAndrew Rybchenko
30169fb4e16SAndrew Rybchenko fail3:
30269fb4e16SAndrew Rybchenko EFSYS_PROBE(fail3);
303e4ddd4ccSAndrew Rybchenko (void) ef10_nic_pio_free(enp, etp->et_pio_bufnum, etp->et_pio_blknum);
30469fb4e16SAndrew Rybchenko fail2:
30569fb4e16SAndrew Rybchenko EFSYS_PROBE(fail2);
3061695ac20SAndrew Rybchenko etp->et_pio_size = 0;
30769fb4e16SAndrew Rybchenko fail1:
30869fb4e16SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
30969fb4e16SAndrew Rybchenko
31069fb4e16SAndrew Rybchenko return (rc);
31169fb4e16SAndrew Rybchenko }
31269fb4e16SAndrew Rybchenko
31369fb4e16SAndrew Rybchenko void
ef10_tx_qpio_disable(__in efx_txq_t * etp)31469fb4e16SAndrew Rybchenko ef10_tx_qpio_disable(
31569fb4e16SAndrew Rybchenko __in efx_txq_t *etp)
31669fb4e16SAndrew Rybchenko {
31769fb4e16SAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
31869fb4e16SAndrew Rybchenko
31969fb4e16SAndrew Rybchenko if (etp->et_pio_size != 0) {
32069fb4e16SAndrew Rybchenko /* Unlink the piobuf from this TXQ */
321e4ddd4ccSAndrew Rybchenko if (ef10_nic_pio_unlink(enp, etp->et_index) != 0)
322e4ddd4ccSAndrew Rybchenko return;
32369fb4e16SAndrew Rybchenko
32469fb4e16SAndrew Rybchenko /* Free the sub-allocated PIO block */
325e4ddd4ccSAndrew Rybchenko (void) ef10_nic_pio_free(enp, etp->et_pio_bufnum,
326e4ddd4ccSAndrew Rybchenko etp->et_pio_blknum);
32769fb4e16SAndrew Rybchenko etp->et_pio_size = 0;
32869fb4e16SAndrew Rybchenko etp->et_pio_write_offset = 0;
32969fb4e16SAndrew Rybchenko }
33069fb4e16SAndrew Rybchenko }
33169fb4e16SAndrew Rybchenko
33269fb4e16SAndrew Rybchenko __checkReturn efx_rc_t
ef10_tx_qpio_write(__in efx_txq_t * etp,__in_ecount (length)uint8_t * buffer,__in size_t length,__in size_t offset)33369fb4e16SAndrew Rybchenko ef10_tx_qpio_write(
33469fb4e16SAndrew Rybchenko __in efx_txq_t *etp,
33569fb4e16SAndrew Rybchenko __in_ecount(length) uint8_t *buffer,
33669fb4e16SAndrew Rybchenko __in size_t length,
33769fb4e16SAndrew Rybchenko __in size_t offset)
33869fb4e16SAndrew Rybchenko {
33969fb4e16SAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
34069fb4e16SAndrew Rybchenko efsys_bar_t *esbp = enp->en_esbp;
34169fb4e16SAndrew Rybchenko uint32_t write_offset;
34269fb4e16SAndrew Rybchenko uint32_t write_offset_limit;
34369fb4e16SAndrew Rybchenko efx_qword_t *eqp;
34469fb4e16SAndrew Rybchenko efx_rc_t rc;
34569fb4e16SAndrew Rybchenko
34669fb4e16SAndrew Rybchenko EFSYS_ASSERT(length % sizeof (efx_qword_t) == 0);
34769fb4e16SAndrew Rybchenko
34869fb4e16SAndrew Rybchenko if (etp->et_pio_size == 0) {
34969fb4e16SAndrew Rybchenko rc = ENOENT;
35069fb4e16SAndrew Rybchenko goto fail1;
35169fb4e16SAndrew Rybchenko }
35269fb4e16SAndrew Rybchenko if (offset + length > etp->et_pio_size) {
35369fb4e16SAndrew Rybchenko rc = ENOSPC;
35469fb4e16SAndrew Rybchenko goto fail2;
35569fb4e16SAndrew Rybchenko }
35669fb4e16SAndrew Rybchenko
35769fb4e16SAndrew Rybchenko /*
35869fb4e16SAndrew Rybchenko * Writes to PIO buffers must be 64 bit aligned, and multiples of
35969fb4e16SAndrew Rybchenko * 64 bits.
36069fb4e16SAndrew Rybchenko */
36169fb4e16SAndrew Rybchenko write_offset = etp->et_pio_write_offset + offset;
36269fb4e16SAndrew Rybchenko write_offset_limit = write_offset + length;
36369fb4e16SAndrew Rybchenko eqp = (efx_qword_t *)buffer;
36469fb4e16SAndrew Rybchenko while (write_offset < write_offset_limit) {
36569fb4e16SAndrew Rybchenko EFSYS_BAR_WC_WRITEQ(esbp, write_offset, eqp);
36669fb4e16SAndrew Rybchenko eqp++;
36769fb4e16SAndrew Rybchenko write_offset += sizeof (efx_qword_t);
36869fb4e16SAndrew Rybchenko }
36969fb4e16SAndrew Rybchenko
37069fb4e16SAndrew Rybchenko return (0);
37169fb4e16SAndrew Rybchenko
37269fb4e16SAndrew Rybchenko fail2:
37369fb4e16SAndrew Rybchenko EFSYS_PROBE(fail2);
37469fb4e16SAndrew Rybchenko fail1:
37569fb4e16SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
37669fb4e16SAndrew Rybchenko
37769fb4e16SAndrew Rybchenko return (rc);
37869fb4e16SAndrew Rybchenko }
37969fb4e16SAndrew Rybchenko
38069fb4e16SAndrew Rybchenko __checkReturn efx_rc_t
ef10_tx_qpio_post(__in efx_txq_t * etp,__in size_t pkt_length,__in unsigned int completed,__inout unsigned int * addedp)38169fb4e16SAndrew Rybchenko ef10_tx_qpio_post(
38269fb4e16SAndrew Rybchenko __in efx_txq_t *etp,
38369fb4e16SAndrew Rybchenko __in size_t pkt_length,
38469fb4e16SAndrew Rybchenko __in unsigned int completed,
38569fb4e16SAndrew Rybchenko __inout unsigned int *addedp)
38669fb4e16SAndrew Rybchenko {
38769fb4e16SAndrew Rybchenko efx_qword_t pio_desc;
38869fb4e16SAndrew Rybchenko unsigned int id;
38969fb4e16SAndrew Rybchenko size_t offset;
39069fb4e16SAndrew Rybchenko unsigned int added = *addedp;
39169fb4e16SAndrew Rybchenko efx_rc_t rc;
39269fb4e16SAndrew Rybchenko
39369fb4e16SAndrew Rybchenko if (added - completed + 1 > EFX_TXQ_LIMIT(etp->et_mask + 1)) {
39469fb4e16SAndrew Rybchenko rc = ENOSPC;
39569fb4e16SAndrew Rybchenko goto fail1;
39669fb4e16SAndrew Rybchenko }
39769fb4e16SAndrew Rybchenko
39869fb4e16SAndrew Rybchenko if (etp->et_pio_size == 0) {
39969fb4e16SAndrew Rybchenko rc = ENOENT;
40069fb4e16SAndrew Rybchenko goto fail2;
40169fb4e16SAndrew Rybchenko }
40269fb4e16SAndrew Rybchenko
40369fb4e16SAndrew Rybchenko id = added++ & etp->et_mask;
40469fb4e16SAndrew Rybchenko offset = id * sizeof (efx_qword_t);
40569fb4e16SAndrew Rybchenko
40669fb4e16SAndrew Rybchenko EFSYS_PROBE4(tx_pio_post, unsigned int, etp->et_index,
40769fb4e16SAndrew Rybchenko unsigned int, id, uint32_t, etp->et_pio_offset,
40869fb4e16SAndrew Rybchenko size_t, pkt_length);
40969fb4e16SAndrew Rybchenko
41069fb4e16SAndrew Rybchenko EFX_POPULATE_QWORD_5(pio_desc,
41169fb4e16SAndrew Rybchenko ESF_DZ_TX_DESC_IS_OPT, 1,
41269fb4e16SAndrew Rybchenko ESF_DZ_TX_OPTION_TYPE, 1,
41369fb4e16SAndrew Rybchenko ESF_DZ_TX_PIO_CONT, 0,
41469fb4e16SAndrew Rybchenko ESF_DZ_TX_PIO_BYTE_CNT, pkt_length,
41569fb4e16SAndrew Rybchenko ESF_DZ_TX_PIO_BUF_ADDR, etp->et_pio_offset);
41669fb4e16SAndrew Rybchenko
41769fb4e16SAndrew Rybchenko EFSYS_MEM_WRITEQ(etp->et_esmp, offset, &pio_desc);
41869fb4e16SAndrew Rybchenko
41969fb4e16SAndrew Rybchenko EFX_TX_QSTAT_INCR(etp, TX_POST_PIO);
42069fb4e16SAndrew Rybchenko
42169fb4e16SAndrew Rybchenko *addedp = added;
42269fb4e16SAndrew Rybchenko return (0);
42369fb4e16SAndrew Rybchenko
42469fb4e16SAndrew Rybchenko fail2:
42569fb4e16SAndrew Rybchenko EFSYS_PROBE(fail2);
42669fb4e16SAndrew Rybchenko fail1:
42769fb4e16SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
42869fb4e16SAndrew Rybchenko
42969fb4e16SAndrew Rybchenko return (rc);
43069fb4e16SAndrew Rybchenko }
43169fb4e16SAndrew Rybchenko
43269fb4e16SAndrew Rybchenko __checkReturn efx_rc_t
ef10_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)43369fb4e16SAndrew Rybchenko ef10_tx_qpost(
43469fb4e16SAndrew Rybchenko __in efx_txq_t *etp,
4350c9ef1f5SAndrew Rybchenko __in_ecount(ndescs) efx_buffer_t *eb,
4360c9ef1f5SAndrew Rybchenko __in unsigned int ndescs,
43769fb4e16SAndrew Rybchenko __in unsigned int completed,
43869fb4e16SAndrew Rybchenko __inout unsigned int *addedp)
43969fb4e16SAndrew Rybchenko {
44069fb4e16SAndrew Rybchenko unsigned int added = *addedp;
44169fb4e16SAndrew Rybchenko unsigned int i;
44269fb4e16SAndrew Rybchenko efx_rc_t rc;
44369fb4e16SAndrew Rybchenko
4440c9ef1f5SAndrew Rybchenko if (added - completed + ndescs > EFX_TXQ_LIMIT(etp->et_mask + 1)) {
44569fb4e16SAndrew Rybchenko rc = ENOSPC;
44669fb4e16SAndrew Rybchenko goto fail1;
44769fb4e16SAndrew Rybchenko }
44869fb4e16SAndrew Rybchenko
4490c9ef1f5SAndrew Rybchenko for (i = 0; i < ndescs; i++) {
45069fb4e16SAndrew Rybchenko efx_buffer_t *ebp = &eb[i];
45169fb4e16SAndrew Rybchenko efsys_dma_addr_t addr = ebp->eb_addr;
45269fb4e16SAndrew Rybchenko size_t size = ebp->eb_size;
45369fb4e16SAndrew Rybchenko boolean_t eop = ebp->eb_eop;
45469fb4e16SAndrew Rybchenko unsigned int id;
45569fb4e16SAndrew Rybchenko size_t offset;
45669fb4e16SAndrew Rybchenko efx_qword_t qword;
45769fb4e16SAndrew Rybchenko
4586a09b206SAndrew Rybchenko /* No limitations on boundary crossing */
4596a09b206SAndrew Rybchenko EFSYS_ASSERT(size <=
4606a09b206SAndrew Rybchenko etp->et_enp->en_nic_cfg.enc_tx_dma_desc_size_max);
46169fb4e16SAndrew Rybchenko
46269fb4e16SAndrew Rybchenko id = added++ & etp->et_mask;
46369fb4e16SAndrew Rybchenko offset = id * sizeof (efx_qword_t);
46469fb4e16SAndrew Rybchenko
46569fb4e16SAndrew Rybchenko EFSYS_PROBE5(tx_post, unsigned int, etp->et_index,
46669fb4e16SAndrew Rybchenko unsigned int, id, efsys_dma_addr_t, addr,
46769fb4e16SAndrew Rybchenko size_t, size, boolean_t, eop);
46869fb4e16SAndrew Rybchenko
46969fb4e16SAndrew Rybchenko EFX_POPULATE_QWORD_5(qword,
47069fb4e16SAndrew Rybchenko ESF_DZ_TX_KER_TYPE, 0,
47169fb4e16SAndrew Rybchenko ESF_DZ_TX_KER_CONT, (eop) ? 0 : 1,
47269fb4e16SAndrew Rybchenko ESF_DZ_TX_KER_BYTE_CNT, (uint32_t)(size),
47369fb4e16SAndrew Rybchenko ESF_DZ_TX_KER_BUF_ADDR_DW0, (uint32_t)(addr & 0xffffffff),
47469fb4e16SAndrew Rybchenko ESF_DZ_TX_KER_BUF_ADDR_DW1, (uint32_t)(addr >> 32));
47569fb4e16SAndrew Rybchenko
47669fb4e16SAndrew Rybchenko EFSYS_MEM_WRITEQ(etp->et_esmp, offset, &qword);
47769fb4e16SAndrew Rybchenko }
47869fb4e16SAndrew Rybchenko
47969fb4e16SAndrew Rybchenko EFX_TX_QSTAT_INCR(etp, TX_POST);
48069fb4e16SAndrew Rybchenko
48169fb4e16SAndrew Rybchenko *addedp = added;
48269fb4e16SAndrew Rybchenko return (0);
48369fb4e16SAndrew Rybchenko
48469fb4e16SAndrew Rybchenko fail1:
48569fb4e16SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
48669fb4e16SAndrew Rybchenko
48769fb4e16SAndrew Rybchenko return (rc);
48869fb4e16SAndrew Rybchenko }
48969fb4e16SAndrew Rybchenko
49069fb4e16SAndrew Rybchenko /*
491fd4fbb71SAndrew Rybchenko * This improves performance by, when possible, pushing a TX descriptor at the
492fd4fbb71SAndrew Rybchenko * same time as the doorbell. The descriptor must be added to the TXQ, so that
493fd4fbb71SAndrew Rybchenko * can be used if the hardware decides not to use the pushed descriptor.
49469fb4e16SAndrew Rybchenko */
49569fb4e16SAndrew Rybchenko void
ef10_tx_qpush(__in efx_txq_t * etp,__in unsigned int added,__in unsigned int pushed)49669fb4e16SAndrew Rybchenko ef10_tx_qpush(
49769fb4e16SAndrew Rybchenko __in efx_txq_t *etp,
49869fb4e16SAndrew Rybchenko __in unsigned int added,
49969fb4e16SAndrew Rybchenko __in unsigned int pushed)
50069fb4e16SAndrew Rybchenko {
50169fb4e16SAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
50269fb4e16SAndrew Rybchenko unsigned int wptr;
50369fb4e16SAndrew Rybchenko unsigned int id;
50469fb4e16SAndrew Rybchenko size_t offset;
50569fb4e16SAndrew Rybchenko efx_qword_t desc;
50669fb4e16SAndrew Rybchenko efx_oword_t oword;
50769fb4e16SAndrew Rybchenko
50869fb4e16SAndrew Rybchenko wptr = added & etp->et_mask;
50969fb4e16SAndrew Rybchenko id = pushed & etp->et_mask;
51069fb4e16SAndrew Rybchenko offset = id * sizeof (efx_qword_t);
51169fb4e16SAndrew Rybchenko
51269fb4e16SAndrew Rybchenko EFSYS_MEM_READQ(etp->et_esmp, offset, &desc);
513fd4fbb71SAndrew Rybchenko
514fd4fbb71SAndrew Rybchenko /*
515fd4fbb71SAndrew Rybchenko * SF Bug 65776: TSO option descriptors cannot be pushed if pacer bypass
516fd4fbb71SAndrew Rybchenko * is enabled on the event queue this transmit queue is attached to.
517fd4fbb71SAndrew Rybchenko *
518fd4fbb71SAndrew Rybchenko * To ensure the code is safe, it is easiest to simply test the type of
519fd4fbb71SAndrew Rybchenko * the descriptor to push, and only push it is if it not a TSO option
520fd4fbb71SAndrew Rybchenko * descriptor.
521fd4fbb71SAndrew Rybchenko */
522fd4fbb71SAndrew Rybchenko if ((EFX_QWORD_FIELD(desc, ESF_DZ_TX_DESC_IS_OPT) != 1) ||
523fd4fbb71SAndrew Rybchenko (EFX_QWORD_FIELD(desc, ESF_DZ_TX_OPTION_TYPE) !=
524fd4fbb71SAndrew Rybchenko ESE_DZ_TX_OPTION_DESC_TSO)) {
525fd4fbb71SAndrew Rybchenko /* Push the descriptor and update the wptr. */
526fd4fbb71SAndrew Rybchenko EFX_POPULATE_OWORD_3(oword, ERF_DZ_TX_DESC_WPTR, wptr,
52769fb4e16SAndrew Rybchenko ERF_DZ_TX_DESC_HWORD, EFX_QWORD_FIELD(desc, EFX_DWORD_1),
52869fb4e16SAndrew Rybchenko ERF_DZ_TX_DESC_LWORD, EFX_QWORD_FIELD(desc, EFX_DWORD_0));
52969fb4e16SAndrew Rybchenko
530fd4fbb71SAndrew Rybchenko /* Ensure ordering of memory (descriptors) and PIO (doorbell) */
531fd4fbb71SAndrew Rybchenko EFX_DMA_SYNC_QUEUE_FOR_DEVICE(etp->et_esmp, etp->et_mask + 1,
532fd4fbb71SAndrew Rybchenko wptr, id);
53369fb4e16SAndrew Rybchenko EFSYS_PIO_WRITE_BARRIER();
534c63c8369SAndrew Rybchenko EFX_BAR_VI_DOORBELL_WRITEO(enp, ER_DZ_TX_DESC_UPD_REG,
535fd4fbb71SAndrew Rybchenko etp->et_index, &oword);
536fd4fbb71SAndrew Rybchenko } else {
537fd4fbb71SAndrew Rybchenko efx_dword_t dword;
538fd4fbb71SAndrew Rybchenko
539fd4fbb71SAndrew Rybchenko /*
540fd4fbb71SAndrew Rybchenko * Only update the wptr. This is signalled to the hardware by
541fd4fbb71SAndrew Rybchenko * only writing one DWORD of the doorbell register.
542fd4fbb71SAndrew Rybchenko */
543fd4fbb71SAndrew Rybchenko EFX_POPULATE_OWORD_1(oword, ERF_DZ_TX_DESC_WPTR, wptr);
544fd4fbb71SAndrew Rybchenko dword = oword.eo_dword[2];
545fd4fbb71SAndrew Rybchenko
546fd4fbb71SAndrew Rybchenko /* Ensure ordering of memory (descriptors) and PIO (doorbell) */
547fd4fbb71SAndrew Rybchenko EFX_DMA_SYNC_QUEUE_FOR_DEVICE(etp->et_esmp, etp->et_mask + 1,
548fd4fbb71SAndrew Rybchenko wptr, id);
549fd4fbb71SAndrew Rybchenko EFSYS_PIO_WRITE_BARRIER();
550c63c8369SAndrew Rybchenko EFX_BAR_VI_WRITED2(enp, ER_DZ_TX_DESC_UPD_REG,
551fd4fbb71SAndrew Rybchenko etp->et_index, &dword, B_FALSE);
552fd4fbb71SAndrew Rybchenko }
55369fb4e16SAndrew Rybchenko }
55469fb4e16SAndrew Rybchenko
55569fb4e16SAndrew Rybchenko __checkReturn efx_rc_t
ef10_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)55669fb4e16SAndrew Rybchenko ef10_tx_qdesc_post(
55769fb4e16SAndrew Rybchenko __in efx_txq_t *etp,
5580c9ef1f5SAndrew Rybchenko __in_ecount(ndescs) efx_desc_t *ed,
5590c9ef1f5SAndrew Rybchenko __in unsigned int ndescs,
56069fb4e16SAndrew Rybchenko __in unsigned int completed,
56169fb4e16SAndrew Rybchenko __inout unsigned int *addedp)
56269fb4e16SAndrew Rybchenko {
56369fb4e16SAndrew Rybchenko unsigned int added = *addedp;
56469fb4e16SAndrew Rybchenko unsigned int i;
56569fb4e16SAndrew Rybchenko
5664c7d5ddbSAndrew Rybchenko if (added - completed + ndescs > EFX_TXQ_LIMIT(etp->et_mask + 1))
5674c7d5ddbSAndrew Rybchenko return (ENOSPC);
56869fb4e16SAndrew Rybchenko
5690c9ef1f5SAndrew Rybchenko for (i = 0; i < ndescs; i++) {
57069fb4e16SAndrew Rybchenko efx_desc_t *edp = &ed[i];
57169fb4e16SAndrew Rybchenko unsigned int id;
57269fb4e16SAndrew Rybchenko size_t offset;
57369fb4e16SAndrew Rybchenko
57469fb4e16SAndrew Rybchenko id = added++ & etp->et_mask;
57569fb4e16SAndrew Rybchenko offset = id * sizeof (efx_desc_t);
57669fb4e16SAndrew Rybchenko
57769fb4e16SAndrew Rybchenko EFSYS_MEM_WRITEQ(etp->et_esmp, offset, &edp->ed_eq);
57869fb4e16SAndrew Rybchenko }
57969fb4e16SAndrew Rybchenko
58069fb4e16SAndrew Rybchenko EFSYS_PROBE3(tx_desc_post, unsigned int, etp->et_index,
5810c9ef1f5SAndrew Rybchenko unsigned int, added, unsigned int, ndescs);
58269fb4e16SAndrew Rybchenko
58369fb4e16SAndrew Rybchenko EFX_TX_QSTAT_INCR(etp, TX_POST);
58469fb4e16SAndrew Rybchenko
58569fb4e16SAndrew Rybchenko *addedp = added;
58669fb4e16SAndrew Rybchenko return (0);
58769fb4e16SAndrew Rybchenko }
58869fb4e16SAndrew Rybchenko
58969fb4e16SAndrew Rybchenko void
ef10_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)59069fb4e16SAndrew Rybchenko ef10_tx_qdesc_dma_create(
59169fb4e16SAndrew Rybchenko __in efx_txq_t *etp,
59269fb4e16SAndrew Rybchenko __in efsys_dma_addr_t addr,
59369fb4e16SAndrew Rybchenko __in size_t size,
59469fb4e16SAndrew Rybchenko __in boolean_t eop,
59569fb4e16SAndrew Rybchenko __out efx_desc_t *edp)
59669fb4e16SAndrew Rybchenko {
597bbea9604SAndrew Rybchenko _NOTE(ARGUNUSED(etp))
598bbea9604SAndrew Rybchenko
5996a09b206SAndrew Rybchenko /* No limitations on boundary crossing */
6006a09b206SAndrew Rybchenko EFSYS_ASSERT(size <= etp->et_enp->en_nic_cfg.enc_tx_dma_desc_size_max);
60169fb4e16SAndrew Rybchenko
60269fb4e16SAndrew Rybchenko EFSYS_PROBE4(tx_desc_dma_create, unsigned int, etp->et_index,
60369fb4e16SAndrew Rybchenko efsys_dma_addr_t, addr,
60469fb4e16SAndrew Rybchenko size_t, size, boolean_t, eop);
60569fb4e16SAndrew Rybchenko
60669fb4e16SAndrew Rybchenko EFX_POPULATE_QWORD_5(edp->ed_eq,
60769fb4e16SAndrew Rybchenko ESF_DZ_TX_KER_TYPE, 0,
60869fb4e16SAndrew Rybchenko ESF_DZ_TX_KER_CONT, (eop) ? 0 : 1,
60969fb4e16SAndrew Rybchenko ESF_DZ_TX_KER_BYTE_CNT, (uint32_t)(size),
61069fb4e16SAndrew Rybchenko ESF_DZ_TX_KER_BUF_ADDR_DW0, (uint32_t)(addr & 0xffffffff),
61169fb4e16SAndrew Rybchenko ESF_DZ_TX_KER_BUF_ADDR_DW1, (uint32_t)(addr >> 32));
61269fb4e16SAndrew Rybchenko }
61369fb4e16SAndrew Rybchenko
61469fb4e16SAndrew Rybchenko void
ef10_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)61569fb4e16SAndrew Rybchenko ef10_tx_qdesc_tso_create(
61669fb4e16SAndrew Rybchenko __in efx_txq_t *etp,
61769fb4e16SAndrew Rybchenko __in uint16_t ipv4_id,
61869fb4e16SAndrew Rybchenko __in uint32_t tcp_seq,
61969fb4e16SAndrew Rybchenko __in uint8_t tcp_flags,
62069fb4e16SAndrew Rybchenko __out efx_desc_t *edp)
62169fb4e16SAndrew Rybchenko {
622bbea9604SAndrew Rybchenko _NOTE(ARGUNUSED(etp))
623bbea9604SAndrew Rybchenko
62469fb4e16SAndrew Rybchenko EFSYS_PROBE4(tx_desc_tso_create, unsigned int, etp->et_index,
62569fb4e16SAndrew Rybchenko uint16_t, ipv4_id, uint32_t, tcp_seq,
62669fb4e16SAndrew Rybchenko uint8_t, tcp_flags);
62769fb4e16SAndrew Rybchenko
62869fb4e16SAndrew Rybchenko EFX_POPULATE_QWORD_5(edp->ed_eq,
62969fb4e16SAndrew Rybchenko ESF_DZ_TX_DESC_IS_OPT, 1,
63069fb4e16SAndrew Rybchenko ESF_DZ_TX_OPTION_TYPE,
63169fb4e16SAndrew Rybchenko ESE_DZ_TX_OPTION_DESC_TSO,
63269fb4e16SAndrew Rybchenko ESF_DZ_TX_TSO_TCP_FLAGS, tcp_flags,
63369fb4e16SAndrew Rybchenko ESF_DZ_TX_TSO_IP_ID, ipv4_id,
63469fb4e16SAndrew Rybchenko ESF_DZ_TX_TSO_TCP_SEQNO, tcp_seq);
63569fb4e16SAndrew Rybchenko }
63669fb4e16SAndrew Rybchenko
63769fb4e16SAndrew Rybchenko void
ef10_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 tcp_mss,__out_ecount (count)efx_desc_t * edp,__in int count)63869fb4e16SAndrew Rybchenko ef10_tx_qdesc_tso2_create(
63969fb4e16SAndrew Rybchenko __in efx_txq_t *etp,
64069fb4e16SAndrew Rybchenko __in uint16_t ipv4_id,
6414142e8cfSAndrew Rybchenko __in uint16_t outer_ipv4_id,
64269fb4e16SAndrew Rybchenko __in uint32_t tcp_seq,
64369fb4e16SAndrew Rybchenko __in uint16_t tcp_mss,
64469fb4e16SAndrew Rybchenko __out_ecount(count) efx_desc_t *edp,
64569fb4e16SAndrew Rybchenko __in int count)
64669fb4e16SAndrew Rybchenko {
647bbea9604SAndrew Rybchenko _NOTE(ARGUNUSED(etp, count))
648bbea9604SAndrew Rybchenko
64969fb4e16SAndrew Rybchenko EFSYS_PROBE4(tx_desc_tso2_create, unsigned int, etp->et_index,
65069fb4e16SAndrew Rybchenko uint16_t, ipv4_id, uint32_t, tcp_seq,
65169fb4e16SAndrew Rybchenko uint16_t, tcp_mss);
65269fb4e16SAndrew Rybchenko
65369fb4e16SAndrew Rybchenko EFSYS_ASSERT(count >= EFX_TX_FATSOV2_OPT_NDESCS);
65469fb4e16SAndrew Rybchenko
65569fb4e16SAndrew Rybchenko EFX_POPULATE_QWORD_5(edp[0].ed_eq,
65669fb4e16SAndrew Rybchenko ESF_DZ_TX_DESC_IS_OPT, 1,
65769fb4e16SAndrew Rybchenko ESF_DZ_TX_OPTION_TYPE,
65869fb4e16SAndrew Rybchenko ESE_DZ_TX_OPTION_DESC_TSO,
65969fb4e16SAndrew Rybchenko ESF_DZ_TX_TSO_OPTION_TYPE,
66069fb4e16SAndrew Rybchenko ESE_DZ_TX_TSO_OPTION_DESC_FATSO2A,
66169fb4e16SAndrew Rybchenko ESF_DZ_TX_TSO_IP_ID, ipv4_id,
66269fb4e16SAndrew Rybchenko ESF_DZ_TX_TSO_TCP_SEQNO, tcp_seq);
6634142e8cfSAndrew Rybchenko EFX_POPULATE_QWORD_5(edp[1].ed_eq,
66469fb4e16SAndrew Rybchenko ESF_DZ_TX_DESC_IS_OPT, 1,
66569fb4e16SAndrew Rybchenko ESF_DZ_TX_OPTION_TYPE,
66669fb4e16SAndrew Rybchenko ESE_DZ_TX_OPTION_DESC_TSO,
66769fb4e16SAndrew Rybchenko ESF_DZ_TX_TSO_OPTION_TYPE,
66869fb4e16SAndrew Rybchenko ESE_DZ_TX_TSO_OPTION_DESC_FATSO2B,
6694142e8cfSAndrew Rybchenko ESF_DZ_TX_TSO_TCP_MSS, tcp_mss,
6704142e8cfSAndrew Rybchenko ESF_DZ_TX_TSO_OUTER_IPID, outer_ipv4_id);
67169fb4e16SAndrew Rybchenko }
67269fb4e16SAndrew Rybchenko
67369fb4e16SAndrew Rybchenko void
ef10_tx_qdesc_vlantci_create(__in efx_txq_t * etp,__in uint16_t tci,__out efx_desc_t * edp)67469fb4e16SAndrew Rybchenko ef10_tx_qdesc_vlantci_create(
67569fb4e16SAndrew Rybchenko __in efx_txq_t *etp,
67669fb4e16SAndrew Rybchenko __in uint16_t tci,
67769fb4e16SAndrew Rybchenko __out efx_desc_t *edp)
67869fb4e16SAndrew Rybchenko {
679bbea9604SAndrew Rybchenko _NOTE(ARGUNUSED(etp))
680bbea9604SAndrew Rybchenko
68169fb4e16SAndrew Rybchenko EFSYS_PROBE2(tx_desc_vlantci_create, unsigned int, etp->et_index,
68269fb4e16SAndrew Rybchenko uint16_t, tci);
68369fb4e16SAndrew Rybchenko
68469fb4e16SAndrew Rybchenko EFX_POPULATE_QWORD_4(edp->ed_eq,
68569fb4e16SAndrew Rybchenko ESF_DZ_TX_DESC_IS_OPT, 1,
68669fb4e16SAndrew Rybchenko ESF_DZ_TX_OPTION_TYPE,
68769fb4e16SAndrew Rybchenko ESE_DZ_TX_OPTION_DESC_VLAN,
68869fb4e16SAndrew Rybchenko ESF_DZ_TX_VLAN_OP, tci ? 1 : 0,
68969fb4e16SAndrew Rybchenko ESF_DZ_TX_VLAN_TAG1, tci);
69069fb4e16SAndrew Rybchenko }
69169fb4e16SAndrew Rybchenko
6924effeb9eSAndrew Rybchenko void
ef10_tx_qdesc_checksum_create(__in efx_txq_t * etp,__in uint16_t flags,__out efx_desc_t * edp)6934effeb9eSAndrew Rybchenko ef10_tx_qdesc_checksum_create(
6944effeb9eSAndrew Rybchenko __in efx_txq_t *etp,
6954effeb9eSAndrew Rybchenko __in uint16_t flags,
6964effeb9eSAndrew Rybchenko __out efx_desc_t *edp)
6974effeb9eSAndrew Rybchenko {
6984effeb9eSAndrew Rybchenko _NOTE(ARGUNUSED(etp));
6994effeb9eSAndrew Rybchenko
7004effeb9eSAndrew Rybchenko EFSYS_PROBE2(tx_desc_checksum_create, unsigned int, etp->et_index,
7014effeb9eSAndrew Rybchenko uint32_t, flags);
7024effeb9eSAndrew Rybchenko
7034effeb9eSAndrew Rybchenko EFX_POPULATE_QWORD_6(edp->ed_eq,
7044effeb9eSAndrew Rybchenko ESF_DZ_TX_DESC_IS_OPT, 1,
7054effeb9eSAndrew Rybchenko ESF_DZ_TX_OPTION_TYPE, ESE_DZ_TX_OPTION_DESC_CRC_CSUM,
7064effeb9eSAndrew Rybchenko ESF_DZ_TX_OPTION_UDP_TCP_CSUM,
7074effeb9eSAndrew Rybchenko (flags & EFX_TXQ_CKSUM_TCPUDP) ? 1 : 0,
7084effeb9eSAndrew Rybchenko ESF_DZ_TX_OPTION_IP_CSUM,
7094effeb9eSAndrew Rybchenko (flags & EFX_TXQ_CKSUM_IPV4) ? 1 : 0,
7104effeb9eSAndrew Rybchenko ESF_DZ_TX_OPTION_INNER_UDP_TCP_CSUM,
7114effeb9eSAndrew Rybchenko (flags & EFX_TXQ_CKSUM_INNER_TCPUDP) ? 1 : 0,
7124effeb9eSAndrew Rybchenko ESF_DZ_TX_OPTION_INNER_IP_CSUM,
7134effeb9eSAndrew Rybchenko (flags & EFX_TXQ_CKSUM_INNER_IPV4) ? 1 : 0);
7144effeb9eSAndrew Rybchenko }
7154effeb9eSAndrew Rybchenko
71669fb4e16SAndrew Rybchenko __checkReturn efx_rc_t
ef10_tx_qpace(__in efx_txq_t * etp,__in unsigned int ns)71769fb4e16SAndrew Rybchenko ef10_tx_qpace(
71869fb4e16SAndrew Rybchenko __in efx_txq_t *etp,
71969fb4e16SAndrew Rybchenko __in unsigned int ns)
72069fb4e16SAndrew Rybchenko {
72169fb4e16SAndrew Rybchenko efx_rc_t rc;
72269fb4e16SAndrew Rybchenko
72369fb4e16SAndrew Rybchenko /* FIXME */
72469fb4e16SAndrew Rybchenko _NOTE(ARGUNUSED(etp, ns))
7255e951ea7SAndrew Rybchenko _NOTE(CONSTANTCONDITION)
72669fb4e16SAndrew Rybchenko if (B_FALSE) {
72769fb4e16SAndrew Rybchenko rc = ENOTSUP;
72869fb4e16SAndrew Rybchenko goto fail1;
72969fb4e16SAndrew Rybchenko }
73069fb4e16SAndrew Rybchenko /* FIXME */
73169fb4e16SAndrew Rybchenko
73269fb4e16SAndrew Rybchenko return (0);
73369fb4e16SAndrew Rybchenko
73469fb4e16SAndrew Rybchenko fail1:
7357e1059e8SAndrew Rybchenko /*
7367e1059e8SAndrew Rybchenko * EALREADY is not an error, but indicates that the MC has rebooted and
7377e1059e8SAndrew Rybchenko * that the TXQ has already been destroyed. Callers need to know that
7387e1059e8SAndrew Rybchenko * the TXQ flush has completed to avoid waiting until timeout for a
7397e1059e8SAndrew Rybchenko * flush done event that will not be delivered.
7407e1059e8SAndrew Rybchenko */
7417e1059e8SAndrew Rybchenko if (rc != EALREADY)
74269fb4e16SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
74369fb4e16SAndrew Rybchenko
74469fb4e16SAndrew Rybchenko return (rc);
74569fb4e16SAndrew Rybchenko }
74669fb4e16SAndrew Rybchenko
74769fb4e16SAndrew Rybchenko __checkReturn efx_rc_t
ef10_tx_qflush(__in efx_txq_t * etp)74869fb4e16SAndrew Rybchenko ef10_tx_qflush(
74969fb4e16SAndrew Rybchenko __in efx_txq_t *etp)
75069fb4e16SAndrew Rybchenko {
75169fb4e16SAndrew Rybchenko efx_nic_t *enp = etp->et_enp;
75269fb4e16SAndrew Rybchenko efx_rc_t rc;
75369fb4e16SAndrew Rybchenko
75469fb4e16SAndrew Rybchenko if ((rc = efx_mcdi_fini_txq(enp, etp->et_index)) != 0)
75569fb4e16SAndrew Rybchenko goto fail1;
75669fb4e16SAndrew Rybchenko
75769fb4e16SAndrew Rybchenko return (0);
75869fb4e16SAndrew Rybchenko
75969fb4e16SAndrew Rybchenko fail1:
76069fb4e16SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
76169fb4e16SAndrew Rybchenko
76269fb4e16SAndrew Rybchenko return (rc);
76369fb4e16SAndrew Rybchenko }
76469fb4e16SAndrew Rybchenko
76569fb4e16SAndrew Rybchenko void
ef10_tx_qenable(__in efx_txq_t * etp)76669fb4e16SAndrew Rybchenko ef10_tx_qenable(
76769fb4e16SAndrew Rybchenko __in efx_txq_t *etp)
76869fb4e16SAndrew Rybchenko {
76969fb4e16SAndrew Rybchenko /* FIXME */
77069fb4e16SAndrew Rybchenko _NOTE(ARGUNUSED(etp))
77169fb4e16SAndrew Rybchenko /* FIXME */
77269fb4e16SAndrew Rybchenko }
77369fb4e16SAndrew Rybchenko
77469fb4e16SAndrew Rybchenko #if EFSYS_OPT_QSTATS
77569fb4e16SAndrew Rybchenko void
ef10_tx_qstats_update(__in efx_txq_t * etp,__inout_ecount (TX_NQSTATS)efsys_stat_t * stat)77669fb4e16SAndrew Rybchenko ef10_tx_qstats_update(
77769fb4e16SAndrew Rybchenko __in efx_txq_t *etp,
77869fb4e16SAndrew Rybchenko __inout_ecount(TX_NQSTATS) efsys_stat_t *stat)
77969fb4e16SAndrew Rybchenko {
78069fb4e16SAndrew Rybchenko unsigned int id;
78169fb4e16SAndrew Rybchenko
78269fb4e16SAndrew Rybchenko for (id = 0; id < TX_NQSTATS; id++) {
78369fb4e16SAndrew Rybchenko efsys_stat_t *essp = &stat[id];
78469fb4e16SAndrew Rybchenko
78569fb4e16SAndrew Rybchenko EFSYS_STAT_INCR(essp, etp->et_stat[id]);
78669fb4e16SAndrew Rybchenko etp->et_stat[id] = 0;
78769fb4e16SAndrew Rybchenko }
78869fb4e16SAndrew Rybchenko }
78969fb4e16SAndrew Rybchenko
79069fb4e16SAndrew Rybchenko #endif /* EFSYS_OPT_QSTATS */
79169fb4e16SAndrew Rybchenko
79220c5aab3SAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
793