]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/sfxge/common/efx_tx.c
dma: import snapshot 2021-07-10
[FreeBSD/FreeBSD.git] / sys / dev / sfxge / common / efx_tx.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2007-2016 Solarflare Communications Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  *    this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  *    this list of conditions and the following disclaimer in the documentation
14  *    and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * The views and conclusions contained in the software and documentation are
29  * those of the authors and should not be interpreted as representing official
30  * policies, either expressed or implied, of the FreeBSD Project.
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include "efx.h"
37 #include "efx_impl.h"
38
39 #if EFSYS_OPT_QSTATS
40 #define EFX_TX_QSTAT_INCR(_etp, _stat)                                  \
41         do {                                                            \
42                 (_etp)->et_stat[_stat]++;                               \
43         _NOTE(CONSTANTCONDITION)                                        \
44         } while (B_FALSE)
45 #else
46 #define EFX_TX_QSTAT_INCR(_etp, _stat)
47 #endif
48
49 #if EFSYS_OPT_SIENA
50
51 static  __checkReturn   efx_rc_t
52 siena_tx_init(
53         __in            efx_nic_t *enp);
54
55 static                  void
56 siena_tx_fini(
57         __in            efx_nic_t *enp);
58
59 static  __checkReturn   efx_rc_t
60 siena_tx_qcreate(
61         __in            efx_nic_t *enp,
62         __in            unsigned int index,
63         __in            unsigned int label,
64         __in            efsys_mem_t *esmp,
65         __in            size_t ndescs,
66         __in            uint32_t id,
67         __in            uint16_t flags,
68         __in            efx_evq_t *eep,
69         __in            efx_txq_t *etp,
70         __out           unsigned int *addedp);
71
72 static          void
73 siena_tx_qdestroy(
74         __in    efx_txq_t *etp);
75
76 static  __checkReturn           efx_rc_t
77 siena_tx_qpost(
78         __in                    efx_txq_t *etp,
79         __in_ecount(ndescs)     efx_buffer_t *eb,
80         __in                    unsigned int ndescs,
81         __in                    unsigned int completed,
82         __inout                 unsigned int *addedp);
83
84 static                  void
85 siena_tx_qpush(
86         __in    efx_txq_t *etp,
87         __in    unsigned int added,
88         __in    unsigned int pushed);
89
90 static  __checkReturn   efx_rc_t
91 siena_tx_qpace(
92         __in            efx_txq_t *etp,
93         __in            unsigned int ns);
94
95 static  __checkReturn   efx_rc_t
96 siena_tx_qflush(
97         __in            efx_txq_t *etp);
98
99 static                  void
100 siena_tx_qenable(
101         __in    efx_txq_t *etp);
102
103         __checkReturn           efx_rc_t
104 siena_tx_qdesc_post(
105         __in                    efx_txq_t *etp,
106         __in_ecount(ndescs)     efx_desc_t *ed,
107         __in                    unsigned int ndescs,
108         __in                    unsigned int completed,
109         __inout                 unsigned int *addedp);
110
111         void
112 siena_tx_qdesc_dma_create(
113         __in    efx_txq_t *etp,
114         __in    efsys_dma_addr_t addr,
115         __in    size_t size,
116         __in    boolean_t eop,
117         __out   efx_desc_t *edp);
118
119 #if EFSYS_OPT_QSTATS
120 static                  void
121 siena_tx_qstats_update(
122         __in                            efx_txq_t *etp,
123         __inout_ecount(TX_NQSTATS)      efsys_stat_t *stat);
124 #endif
125
126 #endif /* EFSYS_OPT_SIENA */
127
128 #if EFSYS_OPT_SIENA
129 static const efx_tx_ops_t       __efx_tx_siena_ops = {
130         siena_tx_init,                          /* etxo_init */
131         siena_tx_fini,                          /* etxo_fini */
132         siena_tx_qcreate,                       /* etxo_qcreate */
133         siena_tx_qdestroy,                      /* etxo_qdestroy */
134         siena_tx_qpost,                         /* etxo_qpost */
135         siena_tx_qpush,                         /* etxo_qpush */
136         siena_tx_qpace,                         /* etxo_qpace */
137         siena_tx_qflush,                        /* etxo_qflush */
138         siena_tx_qenable,                       /* etxo_qenable */
139         NULL,                                   /* etxo_qpio_enable */
140         NULL,                                   /* etxo_qpio_disable */
141         NULL,                                   /* etxo_qpio_write */
142         NULL,                                   /* etxo_qpio_post */
143         siena_tx_qdesc_post,                    /* etxo_qdesc_post */
144         siena_tx_qdesc_dma_create,              /* etxo_qdesc_dma_create */
145         NULL,                                   /* etxo_qdesc_tso_create */
146         NULL,                                   /* etxo_qdesc_tso2_create */
147         NULL,                                   /* etxo_qdesc_vlantci_create */
148         NULL,                                   /* etxo_qdesc_checksum_create */
149 #if EFSYS_OPT_QSTATS
150         siena_tx_qstats_update,                 /* etxo_qstats_update */
151 #endif
152 };
153 #endif /* EFSYS_OPT_SIENA */
154
155 #if EFSYS_OPT_HUNTINGTON
156 static const efx_tx_ops_t       __efx_tx_hunt_ops = {
157         ef10_tx_init,                           /* etxo_init */
158         ef10_tx_fini,                           /* etxo_fini */
159         ef10_tx_qcreate,                        /* etxo_qcreate */
160         ef10_tx_qdestroy,                       /* etxo_qdestroy */
161         ef10_tx_qpost,                          /* etxo_qpost */
162         ef10_tx_qpush,                          /* etxo_qpush */
163         ef10_tx_qpace,                          /* etxo_qpace */
164         ef10_tx_qflush,                         /* etxo_qflush */
165         ef10_tx_qenable,                        /* etxo_qenable */
166         ef10_tx_qpio_enable,                    /* etxo_qpio_enable */
167         ef10_tx_qpio_disable,                   /* etxo_qpio_disable */
168         ef10_tx_qpio_write,                     /* etxo_qpio_write */
169         ef10_tx_qpio_post,                      /* etxo_qpio_post */
170         ef10_tx_qdesc_post,                     /* etxo_qdesc_post */
171         ef10_tx_qdesc_dma_create,               /* etxo_qdesc_dma_create */
172         ef10_tx_qdesc_tso_create,               /* etxo_qdesc_tso_create */
173         ef10_tx_qdesc_tso2_create,              /* etxo_qdesc_tso2_create */
174         ef10_tx_qdesc_vlantci_create,           /* etxo_qdesc_vlantci_create */
175         ef10_tx_qdesc_checksum_create,          /* etxo_qdesc_checksum_create */
176 #if EFSYS_OPT_QSTATS
177         ef10_tx_qstats_update,                  /* etxo_qstats_update */
178 #endif
179 };
180 #endif /* EFSYS_OPT_HUNTINGTON */
181
182 #if EFSYS_OPT_MEDFORD
183 static const efx_tx_ops_t       __efx_tx_medford_ops = {
184         ef10_tx_init,                           /* etxo_init */
185         ef10_tx_fini,                           /* etxo_fini */
186         ef10_tx_qcreate,                        /* etxo_qcreate */
187         ef10_tx_qdestroy,                       /* etxo_qdestroy */
188         ef10_tx_qpost,                          /* etxo_qpost */
189         ef10_tx_qpush,                          /* etxo_qpush */
190         ef10_tx_qpace,                          /* etxo_qpace */
191         ef10_tx_qflush,                         /* etxo_qflush */
192         ef10_tx_qenable,                        /* etxo_qenable */
193         ef10_tx_qpio_enable,                    /* etxo_qpio_enable */
194         ef10_tx_qpio_disable,                   /* etxo_qpio_disable */
195         ef10_tx_qpio_write,                     /* etxo_qpio_write */
196         ef10_tx_qpio_post,                      /* etxo_qpio_post */
197         ef10_tx_qdesc_post,                     /* etxo_qdesc_post */
198         ef10_tx_qdesc_dma_create,               /* etxo_qdesc_dma_create */
199         NULL,                                   /* etxo_qdesc_tso_create */
200         ef10_tx_qdesc_tso2_create,              /* etxo_qdesc_tso2_create */
201         ef10_tx_qdesc_vlantci_create,           /* etxo_qdesc_vlantci_create */
202         ef10_tx_qdesc_checksum_create,          /* etxo_qdesc_checksum_create */
203 #if EFSYS_OPT_QSTATS
204         ef10_tx_qstats_update,                  /* etxo_qstats_update */
205 #endif
206 };
207 #endif /* EFSYS_OPT_MEDFORD */
208
209 #if EFSYS_OPT_MEDFORD2
210 static const efx_tx_ops_t       __efx_tx_medford2_ops = {
211         ef10_tx_init,                           /* etxo_init */
212         ef10_tx_fini,                           /* etxo_fini */
213         ef10_tx_qcreate,                        /* etxo_qcreate */
214         ef10_tx_qdestroy,                       /* etxo_qdestroy */
215         ef10_tx_qpost,                          /* etxo_qpost */
216         ef10_tx_qpush,                          /* etxo_qpush */
217         ef10_tx_qpace,                          /* etxo_qpace */
218         ef10_tx_qflush,                         /* etxo_qflush */
219         ef10_tx_qenable,                        /* etxo_qenable */
220         ef10_tx_qpio_enable,                    /* etxo_qpio_enable */
221         ef10_tx_qpio_disable,                   /* etxo_qpio_disable */
222         ef10_tx_qpio_write,                     /* etxo_qpio_write */
223         ef10_tx_qpio_post,                      /* etxo_qpio_post */
224         ef10_tx_qdesc_post,                     /* etxo_qdesc_post */
225         ef10_tx_qdesc_dma_create,               /* etxo_qdesc_dma_create */
226         NULL,                                   /* etxo_qdesc_tso_create */
227         ef10_tx_qdesc_tso2_create,              /* etxo_qdesc_tso2_create */
228         ef10_tx_qdesc_vlantci_create,           /* etxo_qdesc_vlantci_create */
229         ef10_tx_qdesc_checksum_create,          /* etxo_qdesc_checksum_create */
230 #if EFSYS_OPT_QSTATS
231         ef10_tx_qstats_update,                  /* etxo_qstats_update */
232 #endif
233 };
234 #endif /* EFSYS_OPT_MEDFORD2 */
235
236         __checkReturn   efx_rc_t
237 efx_tx_init(
238         __in            efx_nic_t *enp)
239 {
240         const efx_tx_ops_t *etxop;
241         efx_rc_t rc;
242
243         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
244         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
245
246         if (!(enp->en_mod_flags & EFX_MOD_EV)) {
247                 rc = EINVAL;
248                 goto fail1;
249         }
250
251         if (enp->en_mod_flags & EFX_MOD_TX) {
252                 rc = EINVAL;
253                 goto fail2;
254         }
255
256         switch (enp->en_family) {
257 #if EFSYS_OPT_SIENA
258         case EFX_FAMILY_SIENA:
259                 etxop = &__efx_tx_siena_ops;
260                 break;
261 #endif /* EFSYS_OPT_SIENA */
262
263 #if EFSYS_OPT_HUNTINGTON
264         case EFX_FAMILY_HUNTINGTON:
265                 etxop = &__efx_tx_hunt_ops;
266                 break;
267 #endif /* EFSYS_OPT_HUNTINGTON */
268
269 #if EFSYS_OPT_MEDFORD
270         case EFX_FAMILY_MEDFORD:
271                 etxop = &__efx_tx_medford_ops;
272                 break;
273 #endif /* EFSYS_OPT_MEDFORD */
274
275 #if EFSYS_OPT_MEDFORD2
276         case EFX_FAMILY_MEDFORD2:
277                 etxop = &__efx_tx_medford2_ops;
278                 break;
279 #endif /* EFSYS_OPT_MEDFORD2 */
280
281         default:
282                 EFSYS_ASSERT(0);
283                 rc = ENOTSUP;
284                 goto fail3;
285         }
286
287         EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0);
288
289         if ((rc = etxop->etxo_init(enp)) != 0)
290                 goto fail4;
291
292         enp->en_etxop = etxop;
293         enp->en_mod_flags |= EFX_MOD_TX;
294         return (0);
295
296 fail4:
297         EFSYS_PROBE(fail4);
298 fail3:
299         EFSYS_PROBE(fail3);
300 fail2:
301         EFSYS_PROBE(fail2);
302 fail1:
303         EFSYS_PROBE1(fail1, efx_rc_t, rc);
304
305         enp->en_etxop = NULL;
306         enp->en_mod_flags &= ~EFX_MOD_TX;
307         return (rc);
308 }
309
310                         void
311 efx_tx_fini(
312         __in    efx_nic_t *enp)
313 {
314         const efx_tx_ops_t *etxop = enp->en_etxop;
315
316         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
317         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
318         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX);
319         EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0);
320
321         etxop->etxo_fini(enp);
322
323         enp->en_etxop = NULL;
324         enp->en_mod_flags &= ~EFX_MOD_TX;
325 }
326
327         __checkReturn   efx_rc_t
328 efx_tx_qcreate(
329         __in            efx_nic_t *enp,
330         __in            unsigned int index,
331         __in            unsigned int label,
332         __in            efsys_mem_t *esmp,
333         __in            size_t ndescs,
334         __in            uint32_t id,
335         __in            uint16_t flags,
336         __in            efx_evq_t *eep,
337         __deref_out     efx_txq_t **etpp,
338         __out           unsigned int *addedp)
339 {
340         const efx_tx_ops_t *etxop = enp->en_etxop;
341         efx_txq_t *etp;
342         efx_rc_t rc;
343
344         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
345         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX);
346
347         EFSYS_ASSERT3U(enp->en_tx_qcount + 1, <,
348             enp->en_nic_cfg.enc_txq_limit);
349
350         /* Allocate an TXQ object */
351         EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_txq_t), etp);
352
353         if (etp == NULL) {
354                 rc = ENOMEM;
355                 goto fail1;
356         }
357
358         etp->et_magic = EFX_TXQ_MAGIC;
359         etp->et_enp = enp;
360         etp->et_index = index;
361         etp->et_mask = ndescs - 1;
362         etp->et_esmp = esmp;
363
364         /* Initial descriptor index may be modified by etxo_qcreate */
365         *addedp = 0;
366
367         if ((rc = etxop->etxo_qcreate(enp, index, label, esmp,
368             ndescs, id, flags, eep, etp, addedp)) != 0)
369                 goto fail2;
370
371         enp->en_tx_qcount++;
372         *etpp = etp;
373
374         return (0);
375
376 fail2:
377         EFSYS_PROBE(fail2);
378         EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_txq_t), etp);
379 fail1:
380         EFSYS_PROBE1(fail1, efx_rc_t, rc);
381         return (rc);
382 }
383
384                 void
385 efx_tx_qdestroy(
386         __in    efx_txq_t *etp)
387 {
388         efx_nic_t *enp = etp->et_enp;
389         const efx_tx_ops_t *etxop = enp->en_etxop;
390
391         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
392
393         EFSYS_ASSERT(enp->en_tx_qcount != 0);
394         --enp->en_tx_qcount;
395
396         etxop->etxo_qdestroy(etp);
397
398         /* Free the TXQ object */
399         EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_txq_t), etp);
400 }
401
402         __checkReturn           efx_rc_t
403 efx_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         efx_nic_t *enp = etp->et_enp;
411         const efx_tx_ops_t *etxop = enp->en_etxop;
412         efx_rc_t rc;
413
414         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
415
416         if ((rc = etxop->etxo_qpost(etp, eb, ndescs, completed, addedp)) != 0)
417                 goto fail1;
418
419         return (0);
420
421 fail1:
422         EFSYS_PROBE1(fail1, efx_rc_t, rc);
423         return (rc);
424 }
425
426                         void
427 efx_tx_qpush(
428         __in    efx_txq_t *etp,
429         __in    unsigned int added,
430         __in    unsigned int pushed)
431 {
432         efx_nic_t *enp = etp->et_enp;
433         const efx_tx_ops_t *etxop = enp->en_etxop;
434
435         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
436
437         etxop->etxo_qpush(etp, added, pushed);
438 }
439
440         __checkReturn   efx_rc_t
441 efx_tx_qpace(
442         __in            efx_txq_t *etp,
443         __in            unsigned int ns)
444 {
445         efx_nic_t *enp = etp->et_enp;
446         const efx_tx_ops_t *etxop = enp->en_etxop;
447         efx_rc_t rc;
448
449         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
450
451         if ((rc = etxop->etxo_qpace(etp, ns)) != 0)
452                 goto fail1;
453
454         return (0);
455
456 fail1:
457         EFSYS_PROBE1(fail1, efx_rc_t, rc);
458         return (rc);
459 }
460
461         __checkReturn   efx_rc_t
462 efx_tx_qflush(
463         __in    efx_txq_t *etp)
464 {
465         efx_nic_t *enp = etp->et_enp;
466         const efx_tx_ops_t *etxop = enp->en_etxop;
467         efx_rc_t rc;
468
469         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
470
471         if ((rc = etxop->etxo_qflush(etp)) != 0)
472                 goto fail1;
473
474         return (0);
475
476 fail1:
477         EFSYS_PROBE1(fail1, efx_rc_t, rc);
478         return (rc);
479 }
480
481                         void
482 efx_tx_qenable(
483         __in    efx_txq_t *etp)
484 {
485         efx_nic_t *enp = etp->et_enp;
486         const efx_tx_ops_t *etxop = enp->en_etxop;
487
488         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
489
490         etxop->etxo_qenable(etp);
491 }
492
493         __checkReturn   efx_rc_t
494 efx_tx_qpio_enable(
495         __in    efx_txq_t *etp)
496 {
497         efx_nic_t *enp = etp->et_enp;
498         const efx_tx_ops_t *etxop = enp->en_etxop;
499         efx_rc_t rc;
500
501         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
502
503         if (~enp->en_features & EFX_FEATURE_PIO_BUFFERS) {
504                 rc = ENOTSUP;
505                 goto fail1;
506         }
507         if (etxop->etxo_qpio_enable == NULL) {
508                 rc = ENOTSUP;
509                 goto fail2;
510         }
511         if ((rc = etxop->etxo_qpio_enable(etp)) != 0)
512                 goto fail3;
513
514         return (0);
515
516 fail3:
517         EFSYS_PROBE(fail3);
518 fail2:
519         EFSYS_PROBE(fail2);
520 fail1:
521         EFSYS_PROBE1(fail1, efx_rc_t, rc);
522         return (rc);
523 }
524
525                 void
526 efx_tx_qpio_disable(
527         __in    efx_txq_t *etp)
528 {
529         efx_nic_t *enp = etp->et_enp;
530         const efx_tx_ops_t *etxop = enp->en_etxop;
531
532         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
533
534         if (etxop->etxo_qpio_disable != NULL)
535                 etxop->etxo_qpio_disable(etp);
536 }
537
538         __checkReturn   efx_rc_t
539 efx_tx_qpio_write(
540         __in                    efx_txq_t *etp,
541         __in_ecount(buf_length) uint8_t *buffer,
542         __in                    size_t buf_length,
543         __in                    size_t pio_buf_offset)
544 {
545         efx_nic_t *enp = etp->et_enp;
546         const efx_tx_ops_t *etxop = enp->en_etxop;
547         efx_rc_t rc;
548
549         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
550
551         if (etxop->etxo_qpio_write != NULL) {
552                 if ((rc = etxop->etxo_qpio_write(etp, buffer, buf_length,
553                                                 pio_buf_offset)) != 0)
554                         goto fail1;
555                 return (0);
556         }
557
558         return (ENOTSUP);
559
560 fail1:
561         EFSYS_PROBE1(fail1, efx_rc_t, rc);
562         return (rc);
563 }
564
565         __checkReturn   efx_rc_t
566 efx_tx_qpio_post(
567         __in                    efx_txq_t *etp,
568         __in                    size_t pkt_length,
569         __in                    unsigned int completed,
570         __inout                 unsigned int *addedp)
571 {
572         efx_nic_t *enp = etp->et_enp;
573         const efx_tx_ops_t *etxop = enp->en_etxop;
574         efx_rc_t rc;
575
576         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
577
578         if (etxop->etxo_qpio_post != NULL) {
579                 if ((rc = etxop->etxo_qpio_post(etp, pkt_length, completed,
580                                                 addedp)) != 0)
581                         goto fail1;
582                 return (0);
583         }
584
585         return (ENOTSUP);
586
587 fail1:
588         EFSYS_PROBE1(fail1, efx_rc_t, rc);
589         return (rc);
590 }
591
592         __checkReturn           efx_rc_t
593 efx_tx_qdesc_post(
594         __in                    efx_txq_t *etp,
595         __in_ecount(ndescs)     efx_desc_t *ed,
596         __in                    unsigned int ndescs,
597         __in                    unsigned int completed,
598         __inout                 unsigned int *addedp)
599 {
600         efx_nic_t *enp = etp->et_enp;
601         const efx_tx_ops_t *etxop = enp->en_etxop;
602
603         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
604
605         return (etxop->etxo_qdesc_post(etp, ed, ndescs, completed, addedp));
606 }
607
608         void
609 efx_tx_qdesc_dma_create(
610         __in    efx_txq_t *etp,
611         __in    efsys_dma_addr_t addr,
612         __in    size_t size,
613         __in    boolean_t eop,
614         __out   efx_desc_t *edp)
615 {
616         efx_nic_t *enp = etp->et_enp;
617         const efx_tx_ops_t *etxop = enp->en_etxop;
618
619         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
620         EFSYS_ASSERT(etxop->etxo_qdesc_dma_create != NULL);
621
622         etxop->etxo_qdesc_dma_create(etp, addr, size, eop, edp);
623 }
624
625         void
626 efx_tx_qdesc_tso_create(
627         __in    efx_txq_t *etp,
628         __in    uint16_t ipv4_id,
629         __in    uint32_t tcp_seq,
630         __in    uint8_t  tcp_flags,
631         __out   efx_desc_t *edp)
632 {
633         efx_nic_t *enp = etp->et_enp;
634         const efx_tx_ops_t *etxop = enp->en_etxop;
635
636         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
637         EFSYS_ASSERT(etxop->etxo_qdesc_tso_create != NULL);
638
639         etxop->etxo_qdesc_tso_create(etp, ipv4_id, tcp_seq, tcp_flags, edp);
640 }
641
642         void
643 efx_tx_qdesc_tso2_create(
644         __in                    efx_txq_t *etp,
645         __in                    uint16_t ipv4_id,
646         __in                    uint16_t outer_ipv4_id,
647         __in                    uint32_t tcp_seq,
648         __in                    uint16_t mss,
649         __out_ecount(count)     efx_desc_t *edp,
650         __in                    int count)
651 {
652         efx_nic_t *enp = etp->et_enp;
653         const efx_tx_ops_t *etxop = enp->en_etxop;
654
655         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
656         EFSYS_ASSERT(etxop->etxo_qdesc_tso2_create != NULL);
657
658         etxop->etxo_qdesc_tso2_create(etp, ipv4_id, outer_ipv4_id,
659             tcp_seq, mss, edp, count);
660 }
661
662         void
663 efx_tx_qdesc_vlantci_create(
664         __in    efx_txq_t *etp,
665         __in    uint16_t tci,
666         __out   efx_desc_t *edp)
667 {
668         efx_nic_t *enp = etp->et_enp;
669         const efx_tx_ops_t *etxop = enp->en_etxop;
670
671         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
672         EFSYS_ASSERT(etxop->etxo_qdesc_vlantci_create != NULL);
673
674         etxop->etxo_qdesc_vlantci_create(etp, tci, edp);
675 }
676
677         void
678 efx_tx_qdesc_checksum_create(
679         __in    efx_txq_t *etp,
680         __in    uint16_t flags,
681         __out   efx_desc_t *edp)
682 {
683         efx_nic_t *enp = etp->et_enp;
684         const efx_tx_ops_t *etxop = enp->en_etxop;
685
686         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
687         EFSYS_ASSERT(etxop->etxo_qdesc_checksum_create != NULL);
688
689         etxop->etxo_qdesc_checksum_create(etp, flags, edp);
690 }
691
692 #if EFSYS_OPT_QSTATS
693                         void
694 efx_tx_qstats_update(
695         __in                            efx_txq_t *etp,
696         __inout_ecount(TX_NQSTATS)      efsys_stat_t *stat)
697 {
698         efx_nic_t *enp = etp->et_enp;
699         const efx_tx_ops_t *etxop = enp->en_etxop;
700
701         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
702
703         etxop->etxo_qstats_update(etp, stat);
704 }
705 #endif
706
707 #if EFSYS_OPT_SIENA
708
709 static  __checkReturn   efx_rc_t
710 siena_tx_init(
711         __in            efx_nic_t *enp)
712 {
713         efx_oword_t oword;
714
715         /*
716          * Disable the timer-based TX DMA backoff and allow TX DMA to be
717          * controlled by the RX FIFO fill level (although always allow a
718          * minimal trickle).
719          */
720         EFX_BAR_READO(enp, FR_AZ_TX_RESERVED_REG, &oword);
721         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_RX_SPACER, 0xfe);
722         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_RX_SPACER_EN, 1);
723         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_ONE_PKT_PER_Q, 1);
724         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PUSH_EN, 0);
725         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DIS_NON_IP_EV, 1);
726         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PREF_THRESHOLD, 2);
727         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_PREF_WD_TMR, 0x3fffff);
728
729         /*
730          * Filter all packets less than 14 bytes to avoid parsing
731          * errors.
732          */
733         EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1);
734         EFX_BAR_WRITEO(enp, FR_AZ_TX_RESERVED_REG, &oword);
735
736         /*
737          * Do not set TX_NO_EOP_DISC_EN, since it limits packets to 16
738          * descriptors (which is bad).
739          */
740         EFX_BAR_READO(enp, FR_AZ_TX_CFG_REG, &oword);
741         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_NO_EOP_DISC_EN, 0);
742         EFX_BAR_WRITEO(enp, FR_AZ_TX_CFG_REG, &oword);
743
744         return (0);
745 }
746
747 #define EFX_TX_DESC(_etp, _addr, _size, _eop, _added)                   \
748         do {                                                            \
749                 unsigned int id;                                        \
750                 size_t offset;                                          \
751                 efx_qword_t qword;                                      \
752                                                                         \
753                 id = (_added)++ & (_etp)->et_mask;                      \
754                 offset = id * sizeof (efx_qword_t);                     \
755                                                                         \
756                 EFSYS_PROBE5(tx_post, unsigned int, (_etp)->et_index,   \
757                     unsigned int, id, efsys_dma_addr_t, (_addr),        \
758                     size_t, (_size), boolean_t, (_eop));                \
759                                                                         \
760                 EFX_POPULATE_QWORD_4(qword,                             \
761                     FSF_AZ_TX_KER_CONT, (_eop) ? 0 : 1,                 \
762                     FSF_AZ_TX_KER_BYTE_COUNT, (uint32_t)(_size),        \
763                     FSF_AZ_TX_KER_BUF_ADDR_DW0,                         \
764                     (uint32_t)((_addr) & 0xffffffff),                   \
765                     FSF_AZ_TX_KER_BUF_ADDR_DW1,                         \
766                     (uint32_t)((_addr) >> 32));                         \
767                 EFSYS_MEM_WRITEQ((_etp)->et_esmp, offset, &qword);      \
768                                                                         \
769                 _NOTE(CONSTANTCONDITION)                                \
770         } while (B_FALSE)
771
772 static  __checkReturn           efx_rc_t
773 siena_tx_qpost(
774         __in                    efx_txq_t *etp,
775         __in_ecount(ndescs)     efx_buffer_t *eb,
776         __in                    unsigned int ndescs,
777         __in                    unsigned int completed,
778         __inout                 unsigned int *addedp)
779 {
780         unsigned int added = *addedp;
781         unsigned int i;
782
783         if (added - completed + ndescs > EFX_TXQ_LIMIT(etp->et_mask + 1))
784                 return (ENOSPC);
785
786         for (i = 0; i < ndescs; i++) {
787                 efx_buffer_t *ebp = &eb[i];
788                 efsys_dma_addr_t start = ebp->eb_addr;
789                 size_t size = ebp->eb_size;
790                 efsys_dma_addr_t end = start + size;
791
792                 /*
793                  * Fragments must not span 4k boundaries.
794                  * Here it is a stricter requirement than the maximum length.
795                  */
796                 EFSYS_ASSERT(EFX_P2ROUNDUP(efsys_dma_addr_t, start + 1,
797                     etp->et_enp->en_nic_cfg.enc_tx_dma_desc_boundary) >= end);
798
799                 EFX_TX_DESC(etp, start, size, ebp->eb_eop, added);
800         }
801
802         EFX_TX_QSTAT_INCR(etp, TX_POST);
803
804         *addedp = added;
805         return (0);
806 }
807
808 static          void
809 siena_tx_qpush(
810         __in    efx_txq_t *etp,
811         __in    unsigned int added,
812         __in    unsigned int pushed)
813 {
814         efx_nic_t *enp = etp->et_enp;
815         uint32_t wptr;
816         efx_dword_t dword;
817         efx_oword_t oword;
818
819         /* Push the populated descriptors out */
820         wptr = added & etp->et_mask;
821
822         EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_DESC_WPTR, wptr);
823
824         /* Only write the third DWORD */
825         EFX_POPULATE_DWORD_1(dword,
826             EFX_DWORD_0, EFX_OWORD_FIELD(oword, EFX_DWORD_3));
827
828         /* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
829         EFX_DMA_SYNC_QUEUE_FOR_DEVICE(etp->et_esmp, etp->et_mask + 1,
830             wptr, pushed & etp->et_mask);
831         EFSYS_PIO_WRITE_BARRIER();
832         EFX_BAR_TBL_WRITED3(enp, FR_BZ_TX_DESC_UPD_REGP0,
833                             etp->et_index, &dword, B_FALSE);
834 }
835
836 #define EFX_MAX_PACE_VALUE 20
837 #define EFX_TX_PACE_CLOCK_BASE  104
838
839 static  __checkReturn   efx_rc_t
840 siena_tx_qpace(
841         __in            efx_txq_t *etp,
842         __in            unsigned int ns)
843 {
844         efx_nic_t *enp = etp->et_enp;
845         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
846         efx_oword_t oword;
847         unsigned int pace_val;
848         unsigned int timer_period;
849         efx_rc_t rc;
850
851         if (ns == 0) {
852                 pace_val = 0;
853         } else {
854                 /*
855                  * The pace_val to write into the table is s.t
856                  * ns <= timer_period * (2 ^ pace_val)
857                  */
858                 timer_period = EFX_TX_PACE_CLOCK_BASE / encp->enc_clk_mult;
859                 for (pace_val = 1; pace_val <= EFX_MAX_PACE_VALUE; pace_val++) {
860                         if ((timer_period << pace_val) >= ns)
861                                 break;
862                 }
863         }
864         if (pace_val > EFX_MAX_PACE_VALUE) {
865                 rc = EINVAL;
866                 goto fail1;
867         }
868
869         /* Update the pacing table */
870         EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_PACE, pace_val);
871         EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_PACE_TBL, etp->et_index,
872             &oword, B_TRUE);
873
874         return (0);
875
876 fail1:
877         EFSYS_PROBE1(fail1, efx_rc_t, rc);
878
879         return (rc);
880 }
881
882 static  __checkReturn   efx_rc_t
883 siena_tx_qflush(
884         __in            efx_txq_t *etp)
885 {
886         efx_nic_t *enp = etp->et_enp;
887         efx_oword_t oword;
888         uint32_t label;
889
890         efx_tx_qpace(etp, 0);
891
892         label = etp->et_index;
893
894         /* Flush the queue */
895         EFX_POPULATE_OWORD_2(oword, FRF_AZ_TX_FLUSH_DESCQ_CMD, 1,
896             FRF_AZ_TX_FLUSH_DESCQ, label);
897         EFX_BAR_WRITEO(enp, FR_AZ_TX_FLUSH_DESCQ_REG, &oword);
898
899         return (0);
900 }
901
902 static          void
903 siena_tx_qenable(
904         __in    efx_txq_t *etp)
905 {
906         efx_nic_t *enp = etp->et_enp;
907         efx_oword_t oword;
908
909         EFX_BAR_TBL_READO(enp, FR_AZ_TX_DESC_PTR_TBL,
910                             etp->et_index, &oword, B_TRUE);
911
912         EFSYS_PROBE5(tx_descq_ptr, unsigned int, etp->et_index,
913             uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_3),
914             uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_2),
915             uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_1),
916             uint32_t, EFX_OWORD_FIELD(oword, EFX_DWORD_0));
917
918         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DC_HW_RPTR, 0);
919         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DESCQ_HW_RPTR, 0);
920         EFX_SET_OWORD_FIELD(oword, FRF_AZ_TX_DESCQ_EN, 1);
921
922         EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
923                             etp->et_index, &oword, B_TRUE);
924 }
925
926 static  __checkReturn   efx_rc_t
927 siena_tx_qcreate(
928         __in            efx_nic_t *enp,
929         __in            unsigned int index,
930         __in            unsigned int label,
931         __in            efsys_mem_t *esmp,
932         __in            size_t ndescs,
933         __in            uint32_t id,
934         __in            uint16_t flags,
935         __in            efx_evq_t *eep,
936         __in            efx_txq_t *etp,
937         __out           unsigned int *addedp)
938 {
939         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
940         efx_oword_t oword;
941         uint32_t size;
942         uint16_t inner_csum;
943         efx_rc_t rc;
944
945         _NOTE(ARGUNUSED(esmp))
946
947         EFX_STATIC_ASSERT(EFX_EV_TX_NLABELS ==
948             (1 << FRF_AZ_TX_DESCQ_LABEL_WIDTH));
949         EFSYS_ASSERT3U(label, <, EFX_EV_TX_NLABELS);
950
951         EFSYS_ASSERT(ISP2(encp->enc_txq_max_ndescs));
952         EFX_STATIC_ASSERT(ISP2(EFX_TXQ_MINNDESCS));
953
954         if (!ISP2(ndescs) ||
955             (ndescs < EFX_TXQ_MINNDESCS) || (ndescs > EFX_EVQ_MAXNEVS)) {
956                 rc = EINVAL;
957                 goto fail1;
958         }
959         if (index >= encp->enc_txq_limit) {
960                 rc = EINVAL;
961                 goto fail2;
962         }
963         for (size = 0;
964             (1 << size) <= (int)(encp->enc_txq_max_ndescs / EFX_TXQ_MINNDESCS);
965             size++)
966                 if ((1 << size) == (int)(ndescs / EFX_TXQ_MINNDESCS))
967                         break;
968         if (id + (1 << size) >= encp->enc_buftbl_limit) {
969                 rc = EINVAL;
970                 goto fail3;
971         }
972
973         inner_csum = EFX_TXQ_CKSUM_INNER_IPV4 | EFX_TXQ_CKSUM_INNER_TCPUDP;
974         if ((flags & inner_csum) != 0) {
975                 rc = EINVAL;
976                 goto fail4;
977         }
978
979         /* Set up the new descriptor queue */
980         *addedp = 0;
981
982         EFX_POPULATE_OWORD_6(oword,
983             FRF_AZ_TX_DESCQ_BUF_BASE_ID, id,
984             FRF_AZ_TX_DESCQ_EVQ_ID, eep->ee_index,
985             FRF_AZ_TX_DESCQ_OWNER_ID, 0,
986             FRF_AZ_TX_DESCQ_LABEL, label,
987             FRF_AZ_TX_DESCQ_SIZE, size,
988             FRF_AZ_TX_DESCQ_TYPE, 0);
989
990         EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_NON_IP_DROP_DIS, 1);
991         EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_IP_CHKSM_DIS,
992             (flags & EFX_TXQ_CKSUM_IPV4) ? 0 : 1);
993         EFX_SET_OWORD_FIELD(oword, FRF_BZ_TX_TCP_CHKSM_DIS,
994             (flags & EFX_TXQ_CKSUM_TCPUDP) ? 0 : 1);
995
996         EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
997             etp->et_index, &oword, B_TRUE);
998
999         return (0);
1000
1001 fail4:
1002         EFSYS_PROBE(fail4);
1003 fail3:
1004         EFSYS_PROBE(fail3);
1005 fail2:
1006         EFSYS_PROBE(fail2);
1007 fail1:
1008         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1009
1010         return (rc);
1011 }
1012
1013         __checkReturn           efx_rc_t
1014 siena_tx_qdesc_post(
1015         __in                    efx_txq_t *etp,
1016         __in_ecount(ndescs)     efx_desc_t *ed,
1017         __in                    unsigned int ndescs,
1018         __in                    unsigned int completed,
1019         __inout                 unsigned int *addedp)
1020 {
1021         unsigned int added = *addedp;
1022         unsigned int i;
1023         efx_rc_t rc;
1024
1025         if (added - completed + ndescs > EFX_TXQ_LIMIT(etp->et_mask + 1)) {
1026                 rc = ENOSPC;
1027                 goto fail1;
1028         }
1029
1030         for (i = 0; i < ndescs; i++) {
1031                 efx_desc_t *edp = &ed[i];
1032                 unsigned int id;
1033                 size_t offset;
1034
1035                 id = added++ & etp->et_mask;
1036                 offset = id * sizeof (efx_desc_t);
1037
1038                 EFSYS_MEM_WRITEQ(etp->et_esmp, offset, &edp->ed_eq);
1039         }
1040
1041         EFSYS_PROBE3(tx_desc_post, unsigned int, etp->et_index,
1042                     unsigned int, added, unsigned int, ndescs);
1043
1044         EFX_TX_QSTAT_INCR(etp, TX_POST);
1045
1046         *addedp = added;
1047         return (0);
1048
1049 fail1:
1050         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1051         return (rc);
1052 }
1053
1054         void
1055 siena_tx_qdesc_dma_create(
1056         __in    efx_txq_t *etp,
1057         __in    efsys_dma_addr_t addr,
1058         __in    size_t size,
1059         __in    boolean_t eop,
1060         __out   efx_desc_t *edp)
1061 {
1062         /*
1063          * Fragments must not span 4k boundaries.
1064          * Here it is a stricter requirement than the maximum length.
1065          */
1066         EFSYS_ASSERT(EFX_P2ROUNDUP(efsys_dma_addr_t, addr + 1,
1067             etp->et_enp->en_nic_cfg.enc_tx_dma_desc_boundary) >= addr + size);
1068
1069         EFSYS_PROBE4(tx_desc_dma_create, unsigned int, etp->et_index,
1070                     efsys_dma_addr_t, addr,
1071                     size_t, size, boolean_t, eop);
1072
1073         EFX_POPULATE_QWORD_4(edp->ed_eq,
1074                             FSF_AZ_TX_KER_CONT, eop ? 0 : 1,
1075                             FSF_AZ_TX_KER_BYTE_COUNT, (uint32_t)size,
1076                             FSF_AZ_TX_KER_BUF_ADDR_DW0,
1077                             (uint32_t)(addr & 0xffffffff),
1078                             FSF_AZ_TX_KER_BUF_ADDR_DW1,
1079                             (uint32_t)(addr >> 32));
1080 }
1081
1082 #endif /* EFSYS_OPT_SIENA */
1083
1084 #if EFSYS_OPT_QSTATS
1085 #if EFSYS_OPT_NAMES
1086 /* START MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock 2866874ecd7a363b */
1087 static const char * const __efx_tx_qstat_name[] = {
1088         "post",
1089         "post_pio",
1090 };
1091 /* END MKCONFIG GENERATED EfxTransmitQueueStatNamesBlock */
1092
1093                 const char *
1094 efx_tx_qstat_name(
1095         __in    efx_nic_t *enp,
1096         __in    unsigned int id)
1097 {
1098         _NOTE(ARGUNUSED(enp))
1099         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1100         EFSYS_ASSERT3U(id, <, TX_NQSTATS);
1101
1102         return (__efx_tx_qstat_name[id]);
1103 }
1104 #endif  /* EFSYS_OPT_NAMES */
1105 #endif /* EFSYS_OPT_QSTATS */
1106
1107 #if EFSYS_OPT_SIENA
1108
1109 #if EFSYS_OPT_QSTATS
1110 static                                  void
1111 siena_tx_qstats_update(
1112         __in                            efx_txq_t *etp,
1113         __inout_ecount(TX_NQSTATS)      efsys_stat_t *stat)
1114 {
1115         unsigned int id;
1116
1117         for (id = 0; id < TX_NQSTATS; id++) {
1118                 efsys_stat_t *essp = &stat[id];
1119
1120                 EFSYS_STAT_INCR(essp, etp->et_stat[id]);
1121                 etp->et_stat[id] = 0;
1122         }
1123 }
1124 #endif  /* EFSYS_OPT_QSTATS */
1125
1126 static          void
1127 siena_tx_qdestroy(
1128         __in    efx_txq_t *etp)
1129 {
1130         efx_nic_t *enp = etp->et_enp;
1131         efx_oword_t oword;
1132
1133         /* Purge descriptor queue */
1134         EFX_ZERO_OWORD(oword);
1135
1136         EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_DESC_PTR_TBL,
1137                             etp->et_index, &oword, B_TRUE);
1138 }
1139
1140 static          void
1141 siena_tx_fini(
1142         __in    efx_nic_t *enp)
1143 {
1144         _NOTE(ARGUNUSED(enp))
1145 }
1146
1147 #endif /* EFSYS_OPT_SIENA */