New upstream version 18.11-rc1
[deb_dpdk.git] / drivers / net / sfc / base / ef10_tx.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright (c) 2012-2018 Solarflare Communications Inc.
4  * All rights reserved.
5  */
6
7 #include "efx.h"
8 #include "efx_impl.h"
9
10
11 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
12
13 #if EFSYS_OPT_QSTATS
14 #define EFX_TX_QSTAT_INCR(_etp, _stat)                                  \
15         do {                                                            \
16                 (_etp)->et_stat[_stat]++;                               \
17         _NOTE(CONSTANTCONDITION)                                        \
18         } while (B_FALSE)
19 #else
20 #define EFX_TX_QSTAT_INCR(_etp, _stat)
21 #endif
22
23 static  __checkReturn   efx_rc_t
24 efx_mcdi_init_txq(
25         __in            efx_nic_t *enp,
26         __in            uint32_t ndescs,
27         __in            uint32_t target_evq,
28         __in            uint32_t label,
29         __in            uint32_t instance,
30         __in            uint16_t flags,
31         __in            efsys_mem_t *esmp)
32 {
33         efx_mcdi_req_t req;
34         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_INIT_TXQ_IN_LEN(EFX_TXQ_MAX_BUFS),
35                 MC_CMD_INIT_TXQ_OUT_LEN);
36         efx_qword_t *dma_addr;
37         uint64_t addr;
38         int npages;
39         int i;
40         efx_rc_t rc;
41
42         EFSYS_ASSERT(EFX_TXQ_MAX_BUFS >=
43             EFX_TXQ_NBUFS(enp->en_nic_cfg.enc_txq_max_ndescs));
44
45         if ((esmp == NULL) || (EFSYS_MEM_SIZE(esmp) < EFX_TXQ_SIZE(ndescs))) {
46                 rc = EINVAL;
47                 goto fail1;
48         }
49
50         npages = EFX_TXQ_NBUFS(ndescs);
51         if (MC_CMD_INIT_TXQ_IN_LEN(npages) > sizeof (payload)) {
52                 rc = EINVAL;
53                 goto fail2;
54         }
55
56         req.emr_cmd = MC_CMD_INIT_TXQ;
57         req.emr_in_buf = payload;
58         req.emr_in_length = MC_CMD_INIT_TXQ_IN_LEN(npages);
59         req.emr_out_buf = payload;
60         req.emr_out_length = MC_CMD_INIT_TXQ_OUT_LEN;
61
62         MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_SIZE, ndescs);
63         MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_TARGET_EVQ, target_evq);
64         MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_LABEL, label);
65         MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_INSTANCE, instance);
66
67         MCDI_IN_POPULATE_DWORD_9(req, INIT_TXQ_IN_FLAGS,
68             INIT_TXQ_IN_FLAG_BUFF_MODE, 0,
69             INIT_TXQ_IN_FLAG_IP_CSUM_DIS,
70             (flags & EFX_TXQ_CKSUM_IPV4) ? 0 : 1,
71             INIT_TXQ_IN_FLAG_TCP_CSUM_DIS,
72             (flags & EFX_TXQ_CKSUM_TCPUDP) ? 0 : 1,
73             INIT_TXQ_EXT_IN_FLAG_INNER_IP_CSUM_EN,
74             (flags & EFX_TXQ_CKSUM_INNER_IPV4) ? 1 : 0,
75             INIT_TXQ_EXT_IN_FLAG_INNER_TCP_CSUM_EN,
76             (flags & EFX_TXQ_CKSUM_INNER_TCPUDP) ? 1 : 0,
77             INIT_TXQ_EXT_IN_FLAG_TSOV2_EN, (flags & EFX_TXQ_FATSOV2) ? 1 : 0,
78             INIT_TXQ_IN_FLAG_TCP_UDP_ONLY, 0,
79             INIT_TXQ_IN_CRC_MODE, 0,
80             INIT_TXQ_IN_FLAG_TIMESTAMP, 0);
81
82         MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_OWNER_ID, 0);
83         MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_PORT_ID, EVB_PORT_ID_ASSIGNED);
84
85         dma_addr = MCDI_IN2(req, efx_qword_t, INIT_TXQ_IN_DMA_ADDR);
86         addr = EFSYS_MEM_ADDR(esmp);
87
88         for (i = 0; i < npages; i++) {
89                 EFX_POPULATE_QWORD_2(*dma_addr,
90                     EFX_DWORD_1, (uint32_t)(addr >> 32),
91                     EFX_DWORD_0, (uint32_t)(addr & 0xffffffff));
92
93                 dma_addr++;
94                 addr += EFX_BUF_SIZE;
95         }
96
97         efx_mcdi_execute(enp, &req);
98
99         if (req.emr_rc != 0) {
100                 rc = req.emr_rc;
101                 goto fail3;
102         }
103
104         return (0);
105
106 fail3:
107         EFSYS_PROBE(fail3);
108 fail2:
109         EFSYS_PROBE(fail2);
110 fail1:
111         EFSYS_PROBE1(fail1, efx_rc_t, rc);
112
113         return (rc);
114 }
115
116 static  __checkReturn   efx_rc_t
117 efx_mcdi_fini_txq(
118         __in            efx_nic_t *enp,
119         __in            uint32_t instance)
120 {
121         efx_mcdi_req_t req;
122         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FINI_TXQ_IN_LEN,
123                 MC_CMD_FINI_TXQ_OUT_LEN);
124         efx_rc_t rc;
125
126         req.emr_cmd = MC_CMD_FINI_TXQ;
127         req.emr_in_buf = payload;
128         req.emr_in_length = MC_CMD_FINI_TXQ_IN_LEN;
129         req.emr_out_buf = payload;
130         req.emr_out_length = MC_CMD_FINI_TXQ_OUT_LEN;
131
132         MCDI_IN_SET_DWORD(req, FINI_TXQ_IN_INSTANCE, instance);
133
134         efx_mcdi_execute_quiet(enp, &req);
135
136         if (req.emr_rc != 0) {
137                 rc = req.emr_rc;
138                 goto fail1;
139         }
140
141         return (0);
142
143 fail1:
144         /*
145          * EALREADY is not an error, but indicates that the MC has rebooted and
146          * that the TXQ has already been destroyed.
147          */
148         if (rc != EALREADY)
149                 EFSYS_PROBE1(fail1, efx_rc_t, rc);
150
151         return (rc);
152 }
153
154         __checkReturn   efx_rc_t
155 ef10_tx_init(
156         __in            efx_nic_t *enp)
157 {
158         _NOTE(ARGUNUSED(enp))
159         return (0);
160 }
161
162                         void
163 ef10_tx_fini(
164         __in            efx_nic_t *enp)
165 {
166         _NOTE(ARGUNUSED(enp))
167 }
168
169         __checkReturn   efx_rc_t
170 ef10_tx_qcreate(
171         __in            efx_nic_t *enp,
172         __in            unsigned int index,
173         __in            unsigned int label,
174         __in            efsys_mem_t *esmp,
175         __in            size_t ndescs,
176         __in            uint32_t id,
177         __in            uint16_t flags,
178         __in            efx_evq_t *eep,
179         __in            efx_txq_t *etp,
180         __out           unsigned int *addedp)
181 {
182         efx_nic_cfg_t *encp = &enp->en_nic_cfg;
183         uint16_t inner_csum;
184         efx_desc_t desc;
185         efx_rc_t rc;
186
187         _NOTE(ARGUNUSED(id))
188
189         inner_csum = EFX_TXQ_CKSUM_INNER_IPV4 | EFX_TXQ_CKSUM_INNER_TCPUDP;
190         if (((flags & inner_csum) != 0) &&
191             (encp->enc_tunnel_encapsulations_supported == 0)) {
192                 rc = EINVAL;
193                 goto fail1;
194         }
195
196         if ((rc = efx_mcdi_init_txq(enp, ndescs, eep->ee_index, label, index,
197             flags, esmp)) != 0)
198                 goto fail2;
199
200         /*
201          * A previous user of this TX queue may have written a descriptor to the
202          * TX push collector, but not pushed the doorbell (e.g. after a crash).
203          * The next doorbell write would then push the stale descriptor.
204          *
205          * Ensure the (per network port) TX push collector is cleared by writing
206          * a no-op TX option descriptor. See bug29981 for details.
207          */
208         *addedp = 1;
209         ef10_tx_qdesc_checksum_create(etp, flags, &desc);
210
211         EFSYS_MEM_WRITEQ(etp->et_esmp, 0, &desc.ed_eq);
212         ef10_tx_qpush(etp, *addedp, 0);
213
214         return (0);
215
216 fail2:
217         EFSYS_PROBE(fail2);
218 fail1:
219         EFSYS_PROBE1(fail1, efx_rc_t, rc);
220
221         return (rc);
222 }
223
224                 void
225 ef10_tx_qdestroy(
226         __in    efx_txq_t *etp)
227 {
228         /* FIXME */
229         _NOTE(ARGUNUSED(etp))
230         /* FIXME */
231 }
232
233         __checkReturn   efx_rc_t
234 ef10_tx_qpio_enable(
235         __in            efx_txq_t *etp)
236 {
237         efx_nic_t *enp = etp->et_enp;
238         efx_piobuf_handle_t handle;
239         efx_rc_t rc;
240
241         if (etp->et_pio_size != 0) {
242                 rc = EALREADY;
243                 goto fail1;
244         }
245
246         /* Sub-allocate a PIO block from a piobuf */
247         if ((rc = ef10_nic_pio_alloc(enp,
248                     &etp->et_pio_bufnum,
249                     &handle,
250                     &etp->et_pio_blknum,
251                     &etp->et_pio_offset,
252                     &etp->et_pio_size)) != 0) {
253                 goto fail2;
254         }
255         EFSYS_ASSERT3U(etp->et_pio_size, !=, 0);
256
257         /* Link the piobuf to this TXQ */
258         if ((rc = ef10_nic_pio_link(enp, etp->et_index, handle)) != 0) {
259                 goto fail3;
260         }
261
262         /*
263          * et_pio_offset is the offset of the sub-allocated block within the
264          * hardware PIO buffer. It is used as the buffer address in the PIO
265          * option descriptor.
266          *
267          * et_pio_write_offset is the offset of the sub-allocated block from the
268          * start of the write-combined memory mapping, and is used for writing
269          * data into the PIO buffer.
270          */
271         etp->et_pio_write_offset =
272             (etp->et_pio_bufnum * ER_DZ_TX_PIOBUF_STEP) +
273             ER_DZ_TX_PIOBUF_OFST + etp->et_pio_offset;
274
275         return (0);
276
277 fail3:
278         EFSYS_PROBE(fail3);
279         (void) ef10_nic_pio_free(enp, etp->et_pio_bufnum, etp->et_pio_blknum);
280 fail2:
281         EFSYS_PROBE(fail2);
282         etp->et_pio_size = 0;
283 fail1:
284         EFSYS_PROBE1(fail1, efx_rc_t, rc);
285
286         return (rc);
287 }
288
289                         void
290 ef10_tx_qpio_disable(
291         __in            efx_txq_t *etp)
292 {
293         efx_nic_t *enp = etp->et_enp;
294
295         if (etp->et_pio_size != 0) {
296                 /* Unlink the piobuf from this TXQ */
297                 if (ef10_nic_pio_unlink(enp, etp->et_index) != 0)
298                         return;
299
300                 /* Free the sub-allocated PIO block */
301                 (void) ef10_nic_pio_free(enp, etp->et_pio_bufnum,
302                     etp->et_pio_blknum);
303                 etp->et_pio_size = 0;
304                 etp->et_pio_write_offset = 0;
305         }
306 }
307
308         __checkReturn   efx_rc_t
309 ef10_tx_qpio_write(
310         __in                    efx_txq_t *etp,
311         __in_ecount(length)     uint8_t *buffer,
312         __in                    size_t length,
313         __in                    size_t offset)
314 {
315         efx_nic_t *enp = etp->et_enp;
316         efsys_bar_t *esbp = enp->en_esbp;
317         uint32_t write_offset;
318         uint32_t write_offset_limit;
319         efx_qword_t *eqp;
320         efx_rc_t rc;
321
322         EFSYS_ASSERT(length % sizeof (efx_qword_t) == 0);
323
324         if (etp->et_pio_size == 0) {
325                 rc = ENOENT;
326                 goto fail1;
327         }
328         if (offset + length > etp->et_pio_size) {
329                 rc = ENOSPC;
330                 goto fail2;
331         }
332
333         /*
334          * Writes to PIO buffers must be 64 bit aligned, and multiples of
335          * 64 bits.
336          */
337         write_offset = etp->et_pio_write_offset + offset;
338         write_offset_limit = write_offset + length;
339         eqp = (efx_qword_t *)buffer;
340         while (write_offset < write_offset_limit) {
341                 EFSYS_BAR_WC_WRITEQ(esbp, write_offset, eqp);
342                 eqp++;
343                 write_offset += sizeof (efx_qword_t);
344         }
345
346         return (0);
347
348 fail2:
349         EFSYS_PROBE(fail2);
350 fail1:
351         EFSYS_PROBE1(fail1, efx_rc_t, rc);
352
353         return (rc);
354 }
355
356         __checkReturn   efx_rc_t
357 ef10_tx_qpio_post(
358         __in                    efx_txq_t *etp,
359         __in                    size_t pkt_length,
360         __in                    unsigned int completed,
361         __inout                 unsigned int *addedp)
362 {
363         efx_qword_t pio_desc;
364         unsigned int id;
365         size_t offset;
366         unsigned int added = *addedp;
367         efx_rc_t rc;
368
369
370         if (added - completed + 1 > EFX_TXQ_LIMIT(etp->et_mask + 1)) {
371                 rc = ENOSPC;
372                 goto fail1;
373         }
374
375         if (etp->et_pio_size == 0) {
376                 rc = ENOENT;
377                 goto fail2;
378         }
379
380         id = added++ & etp->et_mask;
381         offset = id * sizeof (efx_qword_t);
382
383         EFSYS_PROBE4(tx_pio_post, unsigned int, etp->et_index,
384                     unsigned int, id, uint32_t, etp->et_pio_offset,
385                     size_t, pkt_length);
386
387         EFX_POPULATE_QWORD_5(pio_desc,
388                         ESF_DZ_TX_DESC_IS_OPT, 1,
389                         ESF_DZ_TX_OPTION_TYPE, 1,
390                         ESF_DZ_TX_PIO_CONT, 0,
391                         ESF_DZ_TX_PIO_BYTE_CNT, pkt_length,
392                         ESF_DZ_TX_PIO_BUF_ADDR, etp->et_pio_offset);
393
394         EFSYS_MEM_WRITEQ(etp->et_esmp, offset, &pio_desc);
395
396         EFX_TX_QSTAT_INCR(etp, TX_POST_PIO);
397
398         *addedp = added;
399         return (0);
400
401 fail2:
402         EFSYS_PROBE(fail2);
403 fail1:
404         EFSYS_PROBE1(fail1, efx_rc_t, rc);
405
406         return (rc);
407 }
408
409         __checkReturn           efx_rc_t
410 ef10_tx_qpost(
411         __in                    efx_txq_t *etp,
412         __in_ecount(ndescs)     efx_buffer_t *eb,
413         __in                    unsigned int ndescs,
414         __in                    unsigned int completed,
415         __inout                 unsigned int *addedp)
416 {
417         unsigned int added = *addedp;
418         unsigned int i;
419         efx_rc_t rc;
420
421         if (added - completed + ndescs > EFX_TXQ_LIMIT(etp->et_mask + 1)) {
422                 rc = ENOSPC;
423                 goto fail1;
424         }
425
426         for (i = 0; i < ndescs; i++) {
427                 efx_buffer_t *ebp = &eb[i];
428                 efsys_dma_addr_t addr = ebp->eb_addr;
429                 size_t size = ebp->eb_size;
430                 boolean_t eop = ebp->eb_eop;
431                 unsigned int id;
432                 size_t offset;
433                 efx_qword_t qword;
434
435                 /* No limitations on boundary crossing */
436                 EFSYS_ASSERT(size <=
437                     etp->et_enp->en_nic_cfg.enc_tx_dma_desc_size_max);
438
439                 id = added++ & etp->et_mask;
440                 offset = id * sizeof (efx_qword_t);
441
442                 EFSYS_PROBE5(tx_post, unsigned int, etp->et_index,
443                     unsigned int, id, efsys_dma_addr_t, addr,
444                     size_t, size, boolean_t, eop);
445
446                 EFX_POPULATE_QWORD_5(qword,
447                     ESF_DZ_TX_KER_TYPE, 0,
448                     ESF_DZ_TX_KER_CONT, (eop) ? 0 : 1,
449                     ESF_DZ_TX_KER_BYTE_CNT, (uint32_t)(size),
450                     ESF_DZ_TX_KER_BUF_ADDR_DW0, (uint32_t)(addr & 0xffffffff),
451                     ESF_DZ_TX_KER_BUF_ADDR_DW1, (uint32_t)(addr >> 32));
452
453                 EFSYS_MEM_WRITEQ(etp->et_esmp, offset, &qword);
454         }
455
456         EFX_TX_QSTAT_INCR(etp, TX_POST);
457
458         *addedp = added;
459         return (0);
460
461 fail1:
462         EFSYS_PROBE1(fail1, efx_rc_t, rc);
463
464         return (rc);
465 }
466
467 /*
468  * This improves performance by, when possible, pushing a TX descriptor at the
469  * same time as the doorbell. The descriptor must be added to the TXQ, so that
470  * can be used if the hardware decides not to use the pushed descriptor.
471  */
472                         void
473 ef10_tx_qpush(
474         __in            efx_txq_t *etp,
475         __in            unsigned int added,
476         __in            unsigned int pushed)
477 {
478         efx_nic_t *enp = etp->et_enp;
479         unsigned int wptr;
480         unsigned int id;
481         size_t offset;
482         efx_qword_t desc;
483         efx_oword_t oword;
484
485         wptr = added & etp->et_mask;
486         id = pushed & etp->et_mask;
487         offset = id * sizeof (efx_qword_t);
488
489         EFSYS_MEM_READQ(etp->et_esmp, offset, &desc);
490
491         /*
492          * Bug 65776: TSO option descriptors cannot be pushed if pacer bypass is
493          * enabled on the event queue this transmit queue is attached to.
494          *
495          * To ensure the code is safe, it is easiest to simply test the type of
496          * the descriptor to push, and only push it is if it not a TSO option
497          * descriptor.
498          */
499         if ((EFX_QWORD_FIELD(desc, ESF_DZ_TX_DESC_IS_OPT) != 1) ||
500             (EFX_QWORD_FIELD(desc, ESF_DZ_TX_OPTION_TYPE) !=
501             ESE_DZ_TX_OPTION_DESC_TSO)) {
502                 /* Push the descriptor and update the wptr. */
503                 EFX_POPULATE_OWORD_3(oword, ERF_DZ_TX_DESC_WPTR, wptr,
504                     ERF_DZ_TX_DESC_HWORD, EFX_QWORD_FIELD(desc, EFX_DWORD_1),
505                     ERF_DZ_TX_DESC_LWORD, EFX_QWORD_FIELD(desc, EFX_DWORD_0));
506
507                 /* Ensure ordering of memory (descriptors) and PIO (doorbell) */
508                 EFX_DMA_SYNC_QUEUE_FOR_DEVICE(etp->et_esmp, etp->et_mask + 1,
509                                             wptr, id);
510                 EFSYS_PIO_WRITE_BARRIER();
511                 EFX_BAR_VI_DOORBELL_WRITEO(enp, ER_DZ_TX_DESC_UPD_REG,
512                     etp->et_index, &oword);
513         } else {
514                 efx_dword_t dword;
515
516                 /*
517                  * Only update the wptr. This is signalled to the hardware by
518                  * only writing one DWORD of the doorbell register.
519                  */
520                 EFX_POPULATE_OWORD_1(oword, ERF_DZ_TX_DESC_WPTR, wptr);
521                 dword = oword.eo_dword[2];
522
523                 /* Ensure ordering of memory (descriptors) and PIO (doorbell) */
524                 EFX_DMA_SYNC_QUEUE_FOR_DEVICE(etp->et_esmp, etp->et_mask + 1,
525                                             wptr, id);
526                 EFSYS_PIO_WRITE_BARRIER();
527                 EFX_BAR_VI_WRITED2(enp, ER_DZ_TX_DESC_UPD_REG,
528                     etp->et_index, &dword, B_FALSE);
529         }
530 }
531
532         __checkReturn           efx_rc_t
533 ef10_tx_qdesc_post(
534         __in                    efx_txq_t *etp,
535         __in_ecount(ndescs)     efx_desc_t *ed,
536         __in                    unsigned int ndescs,
537         __in                    unsigned int completed,
538         __inout                 unsigned int *addedp)
539 {
540         unsigned int added = *addedp;
541         unsigned int i;
542
543         if (added - completed + ndescs > EFX_TXQ_LIMIT(etp->et_mask + 1))
544                 return (ENOSPC);
545
546         for (i = 0; i < ndescs; i++) {
547                 efx_desc_t *edp = &ed[i];
548                 unsigned int id;
549                 size_t offset;
550
551                 id = added++ & etp->et_mask;
552                 offset = id * sizeof (efx_desc_t);
553
554                 EFSYS_MEM_WRITEQ(etp->et_esmp, offset, &edp->ed_eq);
555         }
556
557         EFSYS_PROBE3(tx_desc_post, unsigned int, etp->et_index,
558                     unsigned int, added, unsigned int, ndescs);
559
560         EFX_TX_QSTAT_INCR(etp, TX_POST);
561
562         *addedp = added;
563         return (0);
564 }
565
566         void
567 ef10_tx_qdesc_dma_create(
568         __in    efx_txq_t *etp,
569         __in    efsys_dma_addr_t addr,
570         __in    size_t size,
571         __in    boolean_t eop,
572         __out   efx_desc_t *edp)
573 {
574         _NOTE(ARGUNUSED(etp))
575
576         /* No limitations on boundary crossing */
577         EFSYS_ASSERT(size <= etp->et_enp->en_nic_cfg.enc_tx_dma_desc_size_max);
578
579         EFSYS_PROBE4(tx_desc_dma_create, unsigned int, etp->et_index,
580                     efsys_dma_addr_t, addr,
581                     size_t, size, boolean_t, eop);
582
583         EFX_POPULATE_QWORD_5(edp->ed_eq,
584                     ESF_DZ_TX_KER_TYPE, 0,
585                     ESF_DZ_TX_KER_CONT, (eop) ? 0 : 1,
586                     ESF_DZ_TX_KER_BYTE_CNT, (uint32_t)(size),
587                     ESF_DZ_TX_KER_BUF_ADDR_DW0, (uint32_t)(addr & 0xffffffff),
588                     ESF_DZ_TX_KER_BUF_ADDR_DW1, (uint32_t)(addr >> 32));
589 }
590
591         void
592 ef10_tx_qdesc_tso_create(
593         __in    efx_txq_t *etp,
594         __in    uint16_t ipv4_id,
595         __in    uint32_t tcp_seq,
596         __in    uint8_t  tcp_flags,
597         __out   efx_desc_t *edp)
598 {
599         _NOTE(ARGUNUSED(etp))
600
601         EFSYS_PROBE4(tx_desc_tso_create, unsigned int, etp->et_index,
602                     uint16_t, ipv4_id, uint32_t, tcp_seq,
603                     uint8_t, tcp_flags);
604
605         EFX_POPULATE_QWORD_5(edp->ed_eq,
606                             ESF_DZ_TX_DESC_IS_OPT, 1,
607                             ESF_DZ_TX_OPTION_TYPE,
608                             ESE_DZ_TX_OPTION_DESC_TSO,
609                             ESF_DZ_TX_TSO_TCP_FLAGS, tcp_flags,
610                             ESF_DZ_TX_TSO_IP_ID, ipv4_id,
611                             ESF_DZ_TX_TSO_TCP_SEQNO, tcp_seq);
612 }
613
614         void
615 ef10_tx_qdesc_tso2_create(
616         __in                    efx_txq_t *etp,
617         __in                    uint16_t ipv4_id,
618         __in                    uint16_t outer_ipv4_id,
619         __in                    uint32_t tcp_seq,
620         __in                    uint16_t tcp_mss,
621         __out_ecount(count)     efx_desc_t *edp,
622         __in                    int count)
623 {
624         _NOTE(ARGUNUSED(etp, count))
625
626         EFSYS_PROBE4(tx_desc_tso2_create, unsigned int, etp->et_index,
627                     uint16_t, ipv4_id, uint32_t, tcp_seq,
628                     uint16_t, tcp_mss);
629
630         EFSYS_ASSERT(count >= EFX_TX_FATSOV2_OPT_NDESCS);
631
632         EFX_POPULATE_QWORD_5(edp[0].ed_eq,
633                             ESF_DZ_TX_DESC_IS_OPT, 1,
634                             ESF_DZ_TX_OPTION_TYPE,
635                             ESE_DZ_TX_OPTION_DESC_TSO,
636                             ESF_DZ_TX_TSO_OPTION_TYPE,
637                             ESE_DZ_TX_TSO_OPTION_DESC_FATSO2A,
638                             ESF_DZ_TX_TSO_IP_ID, ipv4_id,
639                             ESF_DZ_TX_TSO_TCP_SEQNO, tcp_seq);
640         EFX_POPULATE_QWORD_5(edp[1].ed_eq,
641                             ESF_DZ_TX_DESC_IS_OPT, 1,
642                             ESF_DZ_TX_OPTION_TYPE,
643                             ESE_DZ_TX_OPTION_DESC_TSO,
644                             ESF_DZ_TX_TSO_OPTION_TYPE,
645                             ESE_DZ_TX_TSO_OPTION_DESC_FATSO2B,
646                             ESF_DZ_TX_TSO_TCP_MSS, tcp_mss,
647                             ESF_DZ_TX_TSO_OUTER_IPID, outer_ipv4_id);
648 }
649
650         void
651 ef10_tx_qdesc_vlantci_create(
652         __in    efx_txq_t *etp,
653         __in    uint16_t  tci,
654         __out   efx_desc_t *edp)
655 {
656         _NOTE(ARGUNUSED(etp))
657
658         EFSYS_PROBE2(tx_desc_vlantci_create, unsigned int, etp->et_index,
659                     uint16_t, tci);
660
661         EFX_POPULATE_QWORD_4(edp->ed_eq,
662                             ESF_DZ_TX_DESC_IS_OPT, 1,
663                             ESF_DZ_TX_OPTION_TYPE,
664                             ESE_DZ_TX_OPTION_DESC_VLAN,
665                             ESF_DZ_TX_VLAN_OP, tci ? 1 : 0,
666                             ESF_DZ_TX_VLAN_TAG1, tci);
667 }
668
669         void
670 ef10_tx_qdesc_checksum_create(
671         __in    efx_txq_t *etp,
672         __in    uint16_t flags,
673         __out   efx_desc_t *edp)
674 {
675         _NOTE(ARGUNUSED(etp));
676
677         EFSYS_PROBE2(tx_desc_checksum_create, unsigned int, etp->et_index,
678                     uint32_t, flags);
679
680         EFX_POPULATE_QWORD_6(edp->ed_eq,
681             ESF_DZ_TX_DESC_IS_OPT, 1,
682             ESF_DZ_TX_OPTION_TYPE, ESE_DZ_TX_OPTION_DESC_CRC_CSUM,
683             ESF_DZ_TX_OPTION_UDP_TCP_CSUM,
684             (flags & EFX_TXQ_CKSUM_TCPUDP) ? 1 : 0,
685             ESF_DZ_TX_OPTION_IP_CSUM,
686             (flags & EFX_TXQ_CKSUM_IPV4) ? 1 : 0,
687             ESF_DZ_TX_OPTION_INNER_UDP_TCP_CSUM,
688             (flags & EFX_TXQ_CKSUM_INNER_TCPUDP) ? 1 : 0,
689             ESF_DZ_TX_OPTION_INNER_IP_CSUM,
690             (flags & EFX_TXQ_CKSUM_INNER_IPV4) ? 1 : 0);
691 }
692
693
694         __checkReturn   efx_rc_t
695 ef10_tx_qpace(
696         __in            efx_txq_t *etp,
697         __in            unsigned int ns)
698 {
699         efx_rc_t rc;
700
701         /* FIXME */
702         _NOTE(ARGUNUSED(etp, ns))
703         _NOTE(CONSTANTCONDITION)
704         if (B_FALSE) {
705                 rc = ENOTSUP;
706                 goto fail1;
707         }
708         /* FIXME */
709
710         return (0);
711
712 fail1:
713         EFSYS_PROBE1(fail1, efx_rc_t, rc);
714
715         return (rc);
716 }
717
718         __checkReturn   efx_rc_t
719 ef10_tx_qflush(
720         __in            efx_txq_t *etp)
721 {
722         efx_nic_t *enp = etp->et_enp;
723         efx_rc_t rc;
724
725         if ((rc = efx_mcdi_fini_txq(enp, etp->et_index)) != 0)
726                 goto fail1;
727
728         return (0);
729
730 fail1:
731         /*
732          * EALREADY is not an error, but indicates that the MC has rebooted and
733          * that the TXQ has already been destroyed. Callers need to know that
734          * the TXQ flush has completed to avoid waiting until timeout for a
735          * flush done event that will not be delivered.
736          */
737         if (rc != EALREADY)
738                 EFSYS_PROBE1(fail1, efx_rc_t, rc);
739
740         return (rc);
741 }
742
743                         void
744 ef10_tx_qenable(
745         __in            efx_txq_t *etp)
746 {
747         /* FIXME */
748         _NOTE(ARGUNUSED(etp))
749         /* FIXME */
750 }
751
752 #if EFSYS_OPT_QSTATS
753                         void
754 ef10_tx_qstats_update(
755         __in                            efx_txq_t *etp,
756         __inout_ecount(TX_NQSTATS)      efsys_stat_t *stat)
757 {
758         unsigned int id;
759
760         for (id = 0; id < TX_NQSTATS; id++) {
761                 efsys_stat_t *essp = &stat[id];
762
763                 EFSYS_STAT_INCR(essp, etp->et_stat[id]);
764                 etp->et_stat[id] = 0;
765         }
766 }
767
768 #endif /* EFSYS_OPT_QSTATS */
769
770 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */