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