4f0099f8ff70bc39234bdc273432729bec517282
[dpdk.git] / drivers / net / sfc / base / efx_tx.c
1 /*
2  * Copyright (c) 2007-2016 Solarflare Communications Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * The views and conclusions contained in the software and documentation are
27  * those of the authors and should not be interpreted as representing official
28  * policies, either expressed or implied, of the FreeBSD Project.
29  */
30
31 #include "efx.h"
32 #include "efx_impl.h"
33
34 #define EFX_TX_QSTAT_INCR(_etp, _stat)
35
36
37         __checkReturn   efx_rc_t
38 efx_tx_init(
39         __in            efx_nic_t *enp)
40 {
41         const efx_tx_ops_t *etxop;
42         efx_rc_t rc;
43
44         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
45         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
46
47         if (!(enp->en_mod_flags & EFX_MOD_EV)) {
48                 rc = EINVAL;
49                 goto fail1;
50         }
51
52         if (enp->en_mod_flags & EFX_MOD_TX) {
53                 rc = EINVAL;
54                 goto fail2;
55         }
56
57         switch (enp->en_family) {
58
59         default:
60                 EFSYS_ASSERT(0);
61                 rc = ENOTSUP;
62                 goto fail3;
63         }
64
65         EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0);
66
67         if ((rc = etxop->etxo_init(enp)) != 0)
68                 goto fail4;
69
70         enp->en_etxop = etxop;
71         enp->en_mod_flags |= EFX_MOD_TX;
72         return (0);
73
74 fail4:
75         EFSYS_PROBE(fail4);
76 fail3:
77         EFSYS_PROBE(fail3);
78 fail2:
79         EFSYS_PROBE(fail2);
80 fail1:
81         EFSYS_PROBE1(fail1, efx_rc_t, rc);
82
83         enp->en_etxop = NULL;
84         enp->en_mod_flags &= ~EFX_MOD_TX;
85         return (rc);
86 }
87
88                         void
89 efx_tx_fini(
90         __in    efx_nic_t *enp)
91 {
92         const efx_tx_ops_t *etxop = enp->en_etxop;
93
94         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
95         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
96         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX);
97         EFSYS_ASSERT3U(enp->en_tx_qcount, ==, 0);
98
99         etxop->etxo_fini(enp);
100
101         enp->en_etxop = NULL;
102         enp->en_mod_flags &= ~EFX_MOD_TX;
103 }
104
105         __checkReturn   efx_rc_t
106 efx_tx_qcreate(
107         __in            efx_nic_t *enp,
108         __in            unsigned int index,
109         __in            unsigned int label,
110         __in            efsys_mem_t *esmp,
111         __in            size_t n,
112         __in            uint32_t id,
113         __in            uint16_t flags,
114         __in            efx_evq_t *eep,
115         __deref_out     efx_txq_t **etpp,
116         __out           unsigned int *addedp)
117 {
118         const efx_tx_ops_t *etxop = enp->en_etxop;
119         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
120         efx_txq_t *etp;
121         efx_rc_t rc;
122
123         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
124         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TX);
125
126         EFSYS_ASSERT3U(enp->en_tx_qcount + 1, <, encp->enc_txq_limit);
127
128         /* Allocate an TXQ object */
129         EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_txq_t), etp);
130
131         if (etp == NULL) {
132                 rc = ENOMEM;
133                 goto fail1;
134         }
135
136         etp->et_magic = EFX_TXQ_MAGIC;
137         etp->et_enp = enp;
138         etp->et_index = index;
139         etp->et_mask = n - 1;
140         etp->et_esmp = esmp;
141
142         /* Initial descriptor index may be modified by etxo_qcreate */
143         *addedp = 0;
144
145         if ((rc = etxop->etxo_qcreate(enp, index, label, esmp,
146             n, id, flags, eep, etp, addedp)) != 0)
147                 goto fail2;
148
149         enp->en_tx_qcount++;
150         *etpp = etp;
151
152         return (0);
153
154 fail2:
155         EFSYS_PROBE(fail2);
156         EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_txq_t), etp);
157 fail1:
158         EFSYS_PROBE1(fail1, efx_rc_t, rc);
159         return (rc);
160 }
161
162                 void
163 efx_tx_qdestroy(
164         __in    efx_txq_t *etp)
165 {
166         efx_nic_t *enp = etp->et_enp;
167         const efx_tx_ops_t *etxop = enp->en_etxop;
168
169         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
170
171         EFSYS_ASSERT(enp->en_tx_qcount != 0);
172         --enp->en_tx_qcount;
173
174         etxop->etxo_qdestroy(etp);
175
176         /* Free the TXQ object */
177         EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_txq_t), etp);
178 }
179
180         __checkReturn   efx_rc_t
181 efx_tx_qpost(
182         __in            efx_txq_t *etp,
183         __in_ecount(n)  efx_buffer_t *eb,
184         __in            unsigned int n,
185         __in            unsigned int completed,
186         __inout         unsigned int *addedp)
187 {
188         efx_nic_t *enp = etp->et_enp;
189         const efx_tx_ops_t *etxop = enp->en_etxop;
190         efx_rc_t rc;
191
192         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
193
194         if ((rc = etxop->etxo_qpost(etp, eb,
195             n, completed, addedp)) != 0)
196                 goto fail1;
197
198         return (0);
199
200 fail1:
201         EFSYS_PROBE1(fail1, efx_rc_t, rc);
202         return (rc);
203 }
204
205                         void
206 efx_tx_qpush(
207         __in    efx_txq_t *etp,
208         __in    unsigned int added,
209         __in    unsigned int pushed)
210 {
211         efx_nic_t *enp = etp->et_enp;
212         const efx_tx_ops_t *etxop = enp->en_etxop;
213
214         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
215
216         etxop->etxo_qpush(etp, added, pushed);
217 }
218
219         __checkReturn   efx_rc_t
220 efx_tx_qpace(
221         __in            efx_txq_t *etp,
222         __in            unsigned int ns)
223 {
224         efx_nic_t *enp = etp->et_enp;
225         const efx_tx_ops_t *etxop = enp->en_etxop;
226         efx_rc_t rc;
227
228         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
229
230         if ((rc = etxop->etxo_qpace(etp, ns)) != 0)
231                 goto fail1;
232
233         return (0);
234
235 fail1:
236         EFSYS_PROBE1(fail1, efx_rc_t, rc);
237         return (rc);
238 }
239
240         __checkReturn   efx_rc_t
241 efx_tx_qflush(
242         __in    efx_txq_t *etp)
243 {
244         efx_nic_t *enp = etp->et_enp;
245         const efx_tx_ops_t *etxop = enp->en_etxop;
246         efx_rc_t rc;
247
248         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
249
250         if ((rc = etxop->etxo_qflush(etp)) != 0)
251                 goto fail1;
252
253         return (0);
254
255 fail1:
256         EFSYS_PROBE1(fail1, efx_rc_t, rc);
257         return (rc);
258 }
259
260                         void
261 efx_tx_qenable(
262         __in    efx_txq_t *etp)
263 {
264         efx_nic_t *enp = etp->et_enp;
265         const efx_tx_ops_t *etxop = enp->en_etxop;
266
267         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
268
269         etxop->etxo_qenable(etp);
270 }
271
272         __checkReturn   efx_rc_t
273 efx_tx_qpio_enable(
274         __in    efx_txq_t *etp)
275 {
276         efx_nic_t *enp = etp->et_enp;
277         const efx_tx_ops_t *etxop = enp->en_etxop;
278         efx_rc_t rc;
279
280         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
281
282         if (~enp->en_features & EFX_FEATURE_PIO_BUFFERS) {
283                 rc = ENOTSUP;
284                 goto fail1;
285         }
286         if (etxop->etxo_qpio_enable == NULL) {
287                 rc = ENOTSUP;
288                 goto fail2;
289         }
290         if ((rc = etxop->etxo_qpio_enable(etp)) != 0)
291                 goto fail3;
292
293         return (0);
294
295 fail3:
296         EFSYS_PROBE(fail3);
297 fail2:
298         EFSYS_PROBE(fail2);
299 fail1:
300         EFSYS_PROBE1(fail1, efx_rc_t, rc);
301         return (rc);
302 }
303
304                 void
305 efx_tx_qpio_disable(
306         __in    efx_txq_t *etp)
307 {
308         efx_nic_t *enp = etp->et_enp;
309         const efx_tx_ops_t *etxop = enp->en_etxop;
310
311         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
312
313         if (etxop->etxo_qpio_disable != NULL)
314                 etxop->etxo_qpio_disable(etp);
315 }
316
317         __checkReturn   efx_rc_t
318 efx_tx_qpio_write(
319         __in                    efx_txq_t *etp,
320         __in_ecount(buf_length) uint8_t *buffer,
321         __in                    size_t buf_length,
322         __in                    size_t pio_buf_offset)
323 {
324         efx_nic_t *enp = etp->et_enp;
325         const efx_tx_ops_t *etxop = enp->en_etxop;
326         efx_rc_t rc;
327
328         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
329
330         if (etxop->etxo_qpio_write != NULL) {
331                 if ((rc = etxop->etxo_qpio_write(etp, buffer, buf_length,
332                                                 pio_buf_offset)) != 0)
333                         goto fail1;
334                 return (0);
335         }
336
337         return (ENOTSUP);
338
339 fail1:
340         EFSYS_PROBE1(fail1, efx_rc_t, rc);
341         return (rc);
342 }
343
344         __checkReturn   efx_rc_t
345 efx_tx_qpio_post(
346         __in                    efx_txq_t *etp,
347         __in                    size_t pkt_length,
348         __in                    unsigned int completed,
349         __inout                 unsigned int *addedp)
350 {
351         efx_nic_t *enp = etp->et_enp;
352         const efx_tx_ops_t *etxop = enp->en_etxop;
353         efx_rc_t rc;
354
355         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
356
357         if (etxop->etxo_qpio_post != NULL) {
358                 if ((rc = etxop->etxo_qpio_post(etp, pkt_length, completed,
359                                                 addedp)) != 0)
360                         goto fail1;
361                 return (0);
362         }
363
364         return (ENOTSUP);
365
366 fail1:
367         EFSYS_PROBE1(fail1, efx_rc_t, rc);
368         return (rc);
369 }
370
371         __checkReturn   efx_rc_t
372 efx_tx_qdesc_post(
373         __in            efx_txq_t *etp,
374         __in_ecount(n)  efx_desc_t *ed,
375         __in            unsigned int n,
376         __in            unsigned int completed,
377         __inout         unsigned int *addedp)
378 {
379         efx_nic_t *enp = etp->et_enp;
380         const efx_tx_ops_t *etxop = enp->en_etxop;
381         efx_rc_t rc;
382
383         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
384
385         if ((rc = etxop->etxo_qdesc_post(etp, ed,
386             n, completed, addedp)) != 0)
387                 goto fail1;
388
389         return (0);
390
391 fail1:
392         EFSYS_PROBE1(fail1, efx_rc_t, rc);
393         return (rc);
394 }
395
396         void
397 efx_tx_qdesc_dma_create(
398         __in    efx_txq_t *etp,
399         __in    efsys_dma_addr_t addr,
400         __in    size_t size,
401         __in    boolean_t eop,
402         __out   efx_desc_t *edp)
403 {
404         efx_nic_t *enp = etp->et_enp;
405         const efx_tx_ops_t *etxop = enp->en_etxop;
406
407         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
408         EFSYS_ASSERT(etxop->etxo_qdesc_dma_create != NULL);
409
410         etxop->etxo_qdesc_dma_create(etp, addr, size, eop, edp);
411 }
412
413         void
414 efx_tx_qdesc_tso_create(
415         __in    efx_txq_t *etp,
416         __in    uint16_t ipv4_id,
417         __in    uint32_t tcp_seq,
418         __in    uint8_t  tcp_flags,
419         __out   efx_desc_t *edp)
420 {
421         efx_nic_t *enp = etp->et_enp;
422         const efx_tx_ops_t *etxop = enp->en_etxop;
423
424         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
425         EFSYS_ASSERT(etxop->etxo_qdesc_tso_create != NULL);
426
427         etxop->etxo_qdesc_tso_create(etp, ipv4_id, tcp_seq, tcp_flags, edp);
428 }
429
430         void
431 efx_tx_qdesc_tso2_create(
432         __in                    efx_txq_t *etp,
433         __in                    uint16_t ipv4_id,
434         __in                    uint32_t tcp_seq,
435         __in                    uint16_t mss,
436         __out_ecount(count)     efx_desc_t *edp,
437         __in                    int count)
438 {
439         efx_nic_t *enp = etp->et_enp;
440         const efx_tx_ops_t *etxop = enp->en_etxop;
441
442         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
443         EFSYS_ASSERT(etxop->etxo_qdesc_tso2_create != NULL);
444
445         etxop->etxo_qdesc_tso2_create(etp, ipv4_id, tcp_seq, mss, edp, count);
446 }
447
448         void
449 efx_tx_qdesc_vlantci_create(
450         __in    efx_txq_t *etp,
451         __in    uint16_t tci,
452         __out   efx_desc_t *edp)
453 {
454         efx_nic_t *enp = etp->et_enp;
455         const efx_tx_ops_t *etxop = enp->en_etxop;
456
457         EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
458         EFSYS_ASSERT(etxop->etxo_qdesc_vlantci_create != NULL);
459
460         etxop->etxo_qdesc_vlantci_create(etp, tci, edp);
461 }
462
463