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