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