xref: /freebsd/sys/dev/mlx5/mlx5_en/mlx5_en_tx.c (revision 59c8e88e72633afbc47a4ace0d2170d00d51f7dc)
1 /*-
2  * Copyright (c) 2015-2021 Mellanox Technologies. All rights reserved.
3  * Copyright (c) 2022 NVIDIA corporation & affiliates.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include "opt_kern_tls.h"
28 #include "opt_rss.h"
29 #include "opt_ratelimit.h"
30 
31 #include <dev/mlx5/mlx5_en/en.h>
32 #include <machine/atomic.h>
33 
34 static inline bool
35 mlx5e_do_send_cqe_inline(struct mlx5e_sq *sq)
36 {
37 	sq->cev_counter++;
38 	/* interleave the CQEs */
39 	if (sq->cev_counter >= sq->cev_factor) {
40 		sq->cev_counter = 0;
41 		return (true);
42 	}
43 	return (false);
44 }
45 
46 bool
47 mlx5e_do_send_cqe(struct mlx5e_sq *sq)
48 {
49 
50 	return (mlx5e_do_send_cqe_inline(sq));
51 }
52 
53 void
54 mlx5e_send_nop(struct mlx5e_sq *sq, u32 ds_cnt)
55 {
56 	u16 pi = sq->pc & sq->wq.sz_m1;
57 	struct mlx5e_tx_wqe *wqe = mlx5_wq_cyc_get_wqe(&sq->wq, pi);
58 
59 	memset(&wqe->ctrl, 0, sizeof(wqe->ctrl));
60 
61 	wqe->ctrl.opmod_idx_opcode = cpu_to_be32((sq->pc << 8) | MLX5_OPCODE_NOP);
62 	wqe->ctrl.qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_cnt);
63 	if (mlx5e_do_send_cqe_inline(sq))
64 		wqe->ctrl.fm_ce_se = MLX5_WQE_CTRL_CQ_UPDATE;
65 	else
66 		wqe->ctrl.fm_ce_se = 0;
67 
68 	/* Copy data for doorbell */
69 	memcpy(sq->doorbell.d32, &wqe->ctrl, sizeof(sq->doorbell.d32));
70 
71 	sq->mbuf[pi].mbuf = NULL;
72 	sq->mbuf[pi].num_bytes = 0;
73 	sq->mbuf[pi].num_wqebbs = DIV_ROUND_UP(ds_cnt, MLX5_SEND_WQEBB_NUM_DS);
74 	sq->pc += sq->mbuf[pi].num_wqebbs;
75 }
76 
77 static uint32_t mlx5e_hash_value;
78 
79 static void
80 mlx5e_hash_init(void *arg)
81 {
82 	mlx5e_hash_value = m_ether_tcpip_hash_init();
83 }
84 
85 /* Make kernel call mlx5e_hash_init after the random stack finished initializing */
86 SYSINIT(mlx5e_hash_init, SI_SUB_RANDOM, SI_ORDER_ANY, &mlx5e_hash_init, NULL);
87 
88 static struct mlx5e_sq *
89 mlx5e_select_queue_by_send_tag(if_t ifp, struct mbuf *mb)
90 {
91 	struct m_snd_tag *mb_tag;
92 	struct mlx5e_sq *sq;
93 
94 	mb_tag = mb->m_pkthdr.snd_tag;
95 
96 #ifdef KERN_TLS
97 top:
98 #endif
99 	/* get pointer to sendqueue */
100 	switch (mb_tag->sw->type) {
101 #ifdef RATELIMIT
102 	case IF_SND_TAG_TYPE_RATE_LIMIT:
103 		sq = container_of(mb_tag,
104 		    struct mlx5e_rl_channel, tag)->sq;
105 		break;
106 #ifdef KERN_TLS
107 	case IF_SND_TAG_TYPE_TLS_RATE_LIMIT:
108 		mb_tag = container_of(mb_tag, struct mlx5e_tls_tag, tag)->rl_tag;
109 		goto top;
110 #endif
111 #endif
112 	case IF_SND_TAG_TYPE_UNLIMITED:
113 		sq = &container_of(mb_tag,
114 		    struct mlx5e_channel, tag)->sq[0];
115 		KASSERT((mb_tag->refcount > 0),
116 		    ("mlx5e_select_queue: Channel refs are zero for unlimited tag"));
117 		break;
118 #ifdef KERN_TLS
119 	case IF_SND_TAG_TYPE_TLS:
120 		mb_tag = container_of(mb_tag, struct mlx5e_tls_tag, tag)->rl_tag;
121 		goto top;
122 #endif
123 	default:
124 		sq = NULL;
125 		break;
126 	}
127 
128 	/* check if valid */
129 	if (sq != NULL && READ_ONCE(sq->running) != 0)
130 		return (sq);
131 
132 	return (NULL);
133 }
134 
135 static struct mlx5e_sq *
136 mlx5e_select_queue(if_t ifp, struct mbuf *mb)
137 {
138 	struct mlx5e_priv *priv = if_getsoftc(ifp);
139 	struct mlx5e_sq *sq;
140 	u32 ch;
141 	u32 tc;
142 
143 	/* obtain VLAN information if present */
144 	if (mb->m_flags & M_VLANTAG) {
145 		tc = (mb->m_pkthdr.ether_vtag >> 13);
146 		if (tc >= priv->num_tc)
147 			tc = priv->default_vlan_prio;
148 	} else {
149 		tc = priv->default_vlan_prio;
150 	}
151 
152 	ch = priv->params.num_channels;
153 
154 	/* check if flowid is set */
155 	if (M_HASHTYPE_GET(mb) != M_HASHTYPE_NONE) {
156 #ifdef RSS
157 		u32 temp;
158 
159 		if (rss_hash2bucket(mb->m_pkthdr.flowid,
160 		    M_HASHTYPE_GET(mb), &temp) == 0)
161 			ch = temp % ch;
162 		else
163 #endif
164 			ch = (mb->m_pkthdr.flowid % 128) % ch;
165 	} else {
166 		ch = m_ether_tcpip_hash(MBUF_HASHFLAG_L3 |
167 		    MBUF_HASHFLAG_L4, mb, mlx5e_hash_value) % ch;
168 	}
169 
170 	/* check if send queue is running */
171 	sq = &priv->channel[ch].sq[tc];
172 	if (likely(READ_ONCE(sq->running) != 0))
173 		return (sq);
174 	return (NULL);
175 }
176 
177 static inline u16
178 mlx5e_get_l2_header_size(struct mlx5e_sq *sq, struct mbuf *mb)
179 {
180 	struct ether_vlan_header *eh;
181 	uint16_t eth_type;
182 	int min_inline;
183 
184 	eh = mtod(mb, struct ether_vlan_header *);
185 	if (unlikely(mb->m_len < ETHER_HDR_LEN)) {
186 		goto max_inline;
187 	} else if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
188 		if (unlikely(mb->m_len < (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN)))
189 			goto max_inline;
190 		eth_type = ntohs(eh->evl_proto);
191 		min_inline = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
192 	} else {
193 		eth_type = ntohs(eh->evl_encap_proto);
194 		min_inline = ETHER_HDR_LEN;
195 	}
196 
197 	switch (eth_type) {
198 	case ETHERTYPE_IP:
199 	case ETHERTYPE_IPV6:
200 		/*
201 		 * Make sure the TOS(IPv4) or traffic class(IPv6)
202 		 * field gets inlined. Else the SQ may stall.
203 		 */
204 		min_inline += 4;
205 		break;
206 	default:
207 		goto max_inline;
208 	}
209 
210 	/*
211 	 * m_copydata() will be used on the remaining header which
212 	 * does not need to reside within the first m_len bytes of
213 	 * data:
214 	 */
215 	if (mb->m_pkthdr.len < min_inline)
216 		goto max_inline;
217 	return (min_inline);
218 
219 max_inline:
220 	return (MIN(mb->m_pkthdr.len, sq->max_inline));
221 }
222 
223 /*
224  * This function parse IPv4 and IPv6 packets looking for TCP and UDP
225  * headers.
226  *
227  * Upon return the pointer at which the "ppth" argument points, is set
228  * to the location of the TCP header. NULL is used if no TCP header is
229  * present.
230  *
231  * The return value indicates the number of bytes from the beginning
232  * of the packet until the first byte after the TCP or UDP header. If
233  * this function returns zero, the parsing failed.
234  */
235 int
236 mlx5e_get_full_header_size(const struct mbuf *mb, const struct tcphdr **ppth)
237 {
238 	const struct ether_vlan_header *eh;
239 	const struct tcphdr *th;
240 	const struct ip *ip;
241 	int ip_hlen, tcp_hlen;
242 	const struct ip6_hdr *ip6;
243 	uint16_t eth_type;
244 	int eth_hdr_len;
245 
246 	eh = mtod(mb, const struct ether_vlan_header *);
247 	if (unlikely(mb->m_len < ETHER_HDR_LEN))
248 		goto failure;
249 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
250 		if (unlikely(mb->m_len < ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN))
251 			goto failure;
252 		eth_type = ntohs(eh->evl_proto);
253 		eth_hdr_len = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
254 	} else {
255 		eth_type = ntohs(eh->evl_encap_proto);
256 		eth_hdr_len = ETHER_HDR_LEN;
257 	}
258 
259 	switch (eth_type) {
260 	case ETHERTYPE_IP:
261 		ip = (const struct ip *)(mb->m_data + eth_hdr_len);
262 		if (unlikely(mb->m_len < eth_hdr_len + sizeof(*ip)))
263 			goto failure;
264 		switch (ip->ip_p) {
265 		case IPPROTO_TCP:
266 			ip_hlen = ip->ip_hl << 2;
267 			eth_hdr_len += ip_hlen;
268 			goto tcp_packet;
269 		case IPPROTO_UDP:
270 			ip_hlen = ip->ip_hl << 2;
271 			eth_hdr_len += ip_hlen + sizeof(struct udphdr);
272 			th = NULL;
273 			goto udp_packet;
274 		default:
275 			goto failure;
276 		}
277 		break;
278 	case ETHERTYPE_IPV6:
279 		ip6 = (const struct ip6_hdr *)(mb->m_data + eth_hdr_len);
280 		if (unlikely(mb->m_len < eth_hdr_len + sizeof(*ip6)))
281 			goto failure;
282 		switch (ip6->ip6_nxt) {
283 		case IPPROTO_TCP:
284 			eth_hdr_len += sizeof(*ip6);
285 			goto tcp_packet;
286 		case IPPROTO_UDP:
287 			eth_hdr_len += sizeof(*ip6) + sizeof(struct udphdr);
288 			th = NULL;
289 			goto udp_packet;
290 		default:
291 			goto failure;
292 		}
293 		break;
294 	default:
295 		goto failure;
296 	}
297 tcp_packet:
298 	if (unlikely(mb->m_len < eth_hdr_len + sizeof(*th))) {
299 		const struct mbuf *m_th = mb->m_next;
300 		if (unlikely(mb->m_len != eth_hdr_len ||
301 		    m_th == NULL || m_th->m_len < sizeof(*th)))
302 			goto failure;
303 		th = (const struct tcphdr *)(m_th->m_data);
304 	} else {
305 		th = (const struct tcphdr *)(mb->m_data + eth_hdr_len);
306 	}
307 	tcp_hlen = th->th_off << 2;
308 	eth_hdr_len += tcp_hlen;
309 udp_packet:
310 	/*
311 	 * m_copydata() will be used on the remaining header which
312 	 * does not need to reside within the first m_len bytes of
313 	 * data:
314 	 */
315 	if (unlikely(mb->m_pkthdr.len < eth_hdr_len))
316 		goto failure;
317 	if (ppth != NULL)
318 		*ppth = th;
319 	return (eth_hdr_len);
320 failure:
321 	if (ppth != NULL)
322 		*ppth = NULL;
323 	return (0);
324 }
325 
326 /*
327  * Locate a pointer inside a mbuf chain. Returns NULL upon failure.
328  */
329 static inline void *
330 mlx5e_parse_mbuf_chain(const struct mbuf **mb, int *poffset, int eth_hdr_len,
331     int min_len)
332 {
333 	if (unlikely(mb[0]->m_len == eth_hdr_len)) {
334 		poffset[0] = eth_hdr_len;
335 		if (unlikely((mb[0] = mb[0]->m_next) == NULL))
336 			return (NULL);
337 	}
338 	if (unlikely(mb[0]->m_len < eth_hdr_len - poffset[0] + min_len))
339 		return (NULL);
340 	return (mb[0]->m_data + eth_hdr_len - poffset[0]);
341 }
342 
343 /*
344  * This function parse IPv4 and IPv6 packets looking for UDP, VXLAN
345  * and TCP headers.
346  *
347  * The return value indicates the number of bytes from the beginning
348  * of the packet until the first byte after the TCP header. If this
349  * function returns zero, the parsing failed.
350  */
351 static int
352 mlx5e_get_vxlan_header_size(const struct mbuf *mb, struct mlx5e_tx_wqe *wqe,
353     uint8_t cs_mask, uint8_t opcode)
354 {
355 	const struct ether_vlan_header *eh;
356 	struct ip *ip4;
357 	struct ip6_hdr *ip6;
358 	struct tcphdr *th;
359 	struct udphdr *udp;
360 	bool has_outer_vlan_tag;
361 	uint16_t eth_type;
362 	uint8_t ip_type;
363 	int pkt_hdr_len;
364 	int eth_hdr_len;
365 	int tcp_hlen;
366 	int ip_hlen;
367 	int offset;
368 
369 	pkt_hdr_len = mb->m_pkthdr.len;
370 	has_outer_vlan_tag = (mb->m_flags & M_VLANTAG) != 0;
371 	offset = 0;
372 
373 	eh = mtod(mb, const struct ether_vlan_header *);
374 	if (unlikely(mb->m_len < ETHER_HDR_LEN))
375 		return (0);
376 
377 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
378 		if (unlikely(mb->m_len < ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN))
379 			return (0);
380 		eth_type = eh->evl_proto;
381 		eth_hdr_len = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
382 	} else {
383 		eth_type = eh->evl_encap_proto;
384 		eth_hdr_len = ETHER_HDR_LEN;
385 	}
386 
387 	switch (eth_type) {
388 	case htons(ETHERTYPE_IP):
389 		ip4 = mlx5e_parse_mbuf_chain(&mb, &offset, eth_hdr_len,
390 		    sizeof(*ip4));
391 		if (unlikely(ip4 == NULL))
392 			return (0);
393 		ip_type = ip4->ip_p;
394 		if (unlikely(ip_type != IPPROTO_UDP))
395 			return (0);
396 		wqe->eth.swp_outer_l3_offset = eth_hdr_len / 2;
397 		wqe->eth.cs_flags = MLX5_ETH_WQE_L3_CSUM | MLX5_ETH_WQE_L4_CSUM;
398 		ip_hlen = ip4->ip_hl << 2;
399 		eth_hdr_len += ip_hlen;
400 		udp = mlx5e_parse_mbuf_chain(&mb, &offset, eth_hdr_len,
401 		    sizeof(*udp));
402 		if (unlikely(udp == NULL))
403 			return (0);
404 		wqe->eth.swp_outer_l4_offset = eth_hdr_len / 2;
405 		wqe->eth.swp_flags |= MLX5_ETH_WQE_SWP_OUTER_L4_TYPE;
406 		eth_hdr_len += sizeof(*udp);
407 		break;
408 	case htons(ETHERTYPE_IPV6):
409 		ip6 = mlx5e_parse_mbuf_chain(&mb, &offset, eth_hdr_len,
410 		    sizeof(*ip6));
411 		if (unlikely(ip6 == NULL))
412 			return (0);
413 		ip_type = ip6->ip6_nxt;
414 		if (unlikely(ip_type != IPPROTO_UDP))
415 			return (0);
416 		wqe->eth.swp_outer_l3_offset = eth_hdr_len / 2;
417 		wqe->eth.cs_flags = MLX5_ETH_WQE_L4_CSUM;
418 		eth_hdr_len += sizeof(*ip6);
419 		udp = mlx5e_parse_mbuf_chain(&mb, &offset, eth_hdr_len,
420 		    sizeof(*udp));
421 		if (unlikely(udp == NULL))
422 			return (0);
423 		wqe->eth.swp_outer_l4_offset = eth_hdr_len / 2;
424 		wqe->eth.swp_flags |= MLX5_ETH_WQE_SWP_OUTER_L4_TYPE |
425 		    MLX5_ETH_WQE_SWP_OUTER_L3_TYPE;
426 		eth_hdr_len += sizeof(*udp);
427 		break;
428 	default:
429 		return (0);
430 	}
431 
432 	/*
433 	 * If the hardware is not computing inner IP checksum, then
434 	 * skip inlining the inner outer UDP and VXLAN header:
435 	 */
436 	if (unlikely((cs_mask & MLX5_ETH_WQE_L3_INNER_CSUM) == 0))
437 		goto done;
438 	if (unlikely(mlx5e_parse_mbuf_chain(&mb, &offset, eth_hdr_len,
439 	    8) == NULL))
440 		return (0);
441 	eth_hdr_len += 8;
442 
443 	/* Check for ethernet header again. */
444 	eh = mlx5e_parse_mbuf_chain(&mb, &offset, eth_hdr_len, ETHER_HDR_LEN);
445 	if (unlikely(eh == NULL))
446 		return (0);
447 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
448 		if (unlikely(mb->m_len < eth_hdr_len - offset + ETHER_HDR_LEN +
449 		    ETHER_VLAN_ENCAP_LEN))
450 			return (0);
451 		eth_type = eh->evl_proto;
452 		eth_hdr_len += ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
453 	} else {
454 		eth_type = eh->evl_encap_proto;
455 		eth_hdr_len += ETHER_HDR_LEN;
456 	}
457 
458 	/* Check for IP header again. */
459 	switch (eth_type) {
460 	case htons(ETHERTYPE_IP):
461 		ip4 = mlx5e_parse_mbuf_chain(&mb, &offset, eth_hdr_len,
462 		    sizeof(*ip4));
463 		if (unlikely(ip4 == NULL))
464 			return (0);
465 		wqe->eth.swp_inner_l3_offset = eth_hdr_len / 2;
466 		wqe->eth.cs_flags |= MLX5_ETH_WQE_L3_INNER_CSUM;
467 		ip_type = ip4->ip_p;
468 		ip_hlen = ip4->ip_hl << 2;
469 		eth_hdr_len += ip_hlen;
470 		break;
471 	case htons(ETHERTYPE_IPV6):
472 		ip6 = mlx5e_parse_mbuf_chain(&mb, &offset, eth_hdr_len,
473 		    sizeof(*ip6));
474 		if (unlikely(ip6 == NULL))
475 			return (0);
476 		wqe->eth.swp_inner_l3_offset = eth_hdr_len / 2;
477 		wqe->eth.swp_flags |= MLX5_ETH_WQE_SWP_INNER_L3_TYPE;
478 		ip_type = ip6->ip6_nxt;
479 		eth_hdr_len += sizeof(*ip6);
480 		break;
481 	default:
482 		return (0);
483 	}
484 
485 	/*
486 	 * If the hardware is not computing inner UDP/TCP checksum,
487 	 * then skip inlining the inner UDP/TCP header:
488 	 */
489 	if (unlikely((cs_mask & MLX5_ETH_WQE_L4_INNER_CSUM) == 0))
490 		goto done;
491 
492 	switch (ip_type) {
493 	case IPPROTO_UDP:
494 		udp = mlx5e_parse_mbuf_chain(&mb, &offset, eth_hdr_len,
495 		    sizeof(*udp));
496 		if (unlikely(udp == NULL))
497 			return (0);
498 		wqe->eth.swp_inner_l4_offset = (eth_hdr_len / 2);
499 		wqe->eth.cs_flags |= MLX5_ETH_WQE_L4_INNER_CSUM;
500 		wqe->eth.swp_flags |= MLX5_ETH_WQE_SWP_INNER_L4_TYPE;
501 		eth_hdr_len += sizeof(*udp);
502 		break;
503 	case IPPROTO_TCP:
504 		th = mlx5e_parse_mbuf_chain(&mb, &offset, eth_hdr_len,
505 		    sizeof(*th));
506 		if (unlikely(th == NULL))
507 			return (0);
508 		wqe->eth.swp_inner_l4_offset = eth_hdr_len / 2;
509 		wqe->eth.cs_flags |= MLX5_ETH_WQE_L4_INNER_CSUM;
510 		tcp_hlen = th->th_off << 2;
511 		eth_hdr_len += tcp_hlen;
512 		break;
513 	default:
514 		return (0);
515 	}
516 done:
517 	if (unlikely(pkt_hdr_len < eth_hdr_len))
518 		return (0);
519 
520 	/* Account for software inserted VLAN tag, if any. */
521 	if (unlikely(has_outer_vlan_tag)) {
522 		wqe->eth.swp_outer_l3_offset += ETHER_VLAN_ENCAP_LEN / 2;
523 		wqe->eth.swp_outer_l4_offset += ETHER_VLAN_ENCAP_LEN / 2;
524 		wqe->eth.swp_inner_l3_offset += ETHER_VLAN_ENCAP_LEN / 2;
525 		wqe->eth.swp_inner_l4_offset += ETHER_VLAN_ENCAP_LEN / 2;
526 	}
527 
528 	/*
529 	 * When inner checksums are set, outer L4 checksum flag must
530 	 * be disabled.
531 	 */
532 	if (wqe->eth.cs_flags & (MLX5_ETH_WQE_L3_INNER_CSUM |
533 	    MLX5_ETH_WQE_L4_INNER_CSUM))
534 		wqe->eth.cs_flags &= ~MLX5_ETH_WQE_L4_CSUM;
535 
536 	return (eth_hdr_len);
537 }
538 
539 struct mlx5_wqe_dump_seg {
540 	struct mlx5_wqe_ctrl_seg ctrl;
541 	struct mlx5_wqe_data_seg data;
542 } __aligned(MLX5_SEND_WQE_BB);
543 
544 CTASSERT(DIV_ROUND_UP(2, MLX5_SEND_WQEBB_NUM_DS) == 1);
545 
546 int
547 mlx5e_sq_dump_xmit(struct mlx5e_sq *sq, struct mlx5e_xmit_args *parg, struct mbuf **mbp)
548 {
549 	bus_dma_segment_t segs[MLX5E_MAX_TX_MBUF_FRAGS];
550 	struct mlx5_wqe_dump_seg *wqe;
551 	struct mlx5_wqe_dump_seg *wqe_last;
552 	int nsegs;
553 	int xsegs;
554 	u32 off;
555 	u32 msb;
556 	int err;
557 	int x;
558 	struct mbuf *mb;
559 	const u32 ds_cnt = 2;
560 	u16 pi;
561 	const u8 opcode = MLX5_OPCODE_DUMP;
562 
563 	/* get pointer to mbuf */
564 	mb = *mbp;
565 
566 	/* get producer index */
567 	pi = sq->pc & sq->wq.sz_m1;
568 
569 	sq->mbuf[pi].num_bytes = mb->m_pkthdr.len;
570 	sq->mbuf[pi].num_wqebbs = 0;
571 
572 	/* check number of segments in mbuf */
573 	err = bus_dmamap_load_mbuf_sg(sq->dma_tag, sq->mbuf[pi].dma_map,
574 	    mb, segs, &nsegs, BUS_DMA_NOWAIT);
575 	if (err == EFBIG) {
576 		/* update statistics */
577 		sq->stats.defragged++;
578 		/* too many mbuf fragments */
579 		mb = m_defrag(*mbp, M_NOWAIT);
580 		if (mb == NULL) {
581 			mb = *mbp;
582 			goto tx_drop;
583 		}
584 		/* try again */
585 		err = bus_dmamap_load_mbuf_sg(sq->dma_tag, sq->mbuf[pi].dma_map,
586 		    mb, segs, &nsegs, BUS_DMA_NOWAIT);
587 	}
588 
589 	if (err != 0)
590 		goto tx_drop;
591 
592 	/* make sure all mbuf data, if any, is visible to the bus */
593 	bus_dmamap_sync(sq->dma_tag, sq->mbuf[pi].dma_map,
594 	    BUS_DMASYNC_PREWRITE);
595 
596 	/* compute number of real DUMP segments */
597 	msb = sq->priv->params_ethtool.hw_mtu_msb;
598 	for (x = xsegs = 0; x != nsegs; x++)
599 		xsegs += howmany((u32)segs[x].ds_len, msb);
600 
601 	/* check if there are no segments */
602 	if (unlikely(xsegs == 0)) {
603 		bus_dmamap_unload(sq->dma_tag, sq->mbuf[pi].dma_map);
604 		m_freem(mb);
605 		*mbp = NULL;	/* safety clear */
606 		return (0);
607 	}
608 
609 	/* return ENOBUFS if the queue is full */
610 	if (unlikely(!mlx5e_sq_has_room_for(sq, xsegs))) {
611 		sq->stats.enobuf++;
612 		bus_dmamap_unload(sq->dma_tag, sq->mbuf[pi].dma_map);
613 		m_freem(mb);
614 		*mbp = NULL;	/* safety clear */
615 		return (ENOBUFS);
616 	}
617 
618 	wqe = mlx5_wq_cyc_get_wqe(&sq->wq, pi);
619 	wqe_last = mlx5_wq_cyc_get_wqe(&sq->wq, sq->wq.sz_m1);
620 
621 	for (x = 0; x != nsegs; x++) {
622 		for (off = 0; off < segs[x].ds_len; off += msb) {
623 			u32 len = segs[x].ds_len - off;
624 
625 			/* limit length */
626 			if (likely(len > msb))
627 				len = msb;
628 
629 			memset(&wqe->ctrl, 0, sizeof(wqe->ctrl));
630 
631 			/* fill control segment */
632 			wqe->ctrl.opmod_idx_opcode = cpu_to_be32((sq->pc << 8) | opcode);
633 			wqe->ctrl.qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_cnt);
634 			wqe->ctrl.imm = cpu_to_be32(parg->tisn << 8);
635 
636 			/* fill data segment */
637 			wqe->data.addr = cpu_to_be64((uint64_t)segs[x].ds_addr + off);
638 			wqe->data.lkey = sq->mkey_be;
639 			wqe->data.byte_count = cpu_to_be32(len);
640 
641 			/* advance to next building block */
642 			if (unlikely(wqe == wqe_last))
643 				wqe = mlx5_wq_cyc_get_wqe(&sq->wq, 0);
644 			else
645 				wqe++;
646 
647 			sq->mbuf[pi].num_wqebbs++;
648 			sq->pc++;
649 		}
650 	}
651 
652 	wqe = mlx5_wq_cyc_get_wqe(&sq->wq, pi);
653 	wqe_last = mlx5_wq_cyc_get_wqe(&sq->wq, (sq->pc - 1) & sq->wq.sz_m1);
654 
655 	/* put in place data fence */
656 	wqe->ctrl.fm_ce_se |= MLX5_FENCE_MODE_INITIATOR_SMALL;
657 
658 	/* check if we should generate a completion event */
659 	if (mlx5e_do_send_cqe_inline(sq))
660 		wqe_last->ctrl.fm_ce_se |= MLX5_WQE_CTRL_CQ_UPDATE;
661 
662 	/* copy data for doorbell */
663 	memcpy(sq->doorbell.d32, wqe_last, sizeof(sq->doorbell.d32));
664 
665 	/* store pointer to mbuf */
666 	sq->mbuf[pi].mbuf = mb;
667 	sq->mbuf[pi].mst = m_snd_tag_ref(parg->mst);
668 
669 	/* count all traffic going out */
670 	sq->stats.packets++;
671 	sq->stats.bytes += sq->mbuf[pi].num_bytes;
672 
673 	*mbp = NULL;	/* safety clear */
674 	return (0);
675 
676 tx_drop:
677 	sq->stats.dropped++;
678 	*mbp = NULL;
679 	m_freem(mb);
680 	return err;
681 }
682 
683 int
684 mlx5e_sq_xmit(struct mlx5e_sq *sq, struct mbuf **mbp)
685 {
686 	bus_dma_segment_t segs[MLX5E_MAX_TX_MBUF_FRAGS];
687 	struct mlx5e_xmit_args args = {};
688 	struct mlx5_wqe_data_seg *dseg;
689 	struct mlx5e_tx_wqe *wqe;
690 	if_t ifp;
691 	int nsegs;
692 	int err;
693 	int x;
694 	struct mbuf *mb;
695 	u16 ds_cnt;
696 	u16 pi;
697 	u8 opcode;
698 
699 #ifdef KERN_TLS
700 top:
701 #endif
702 	/* Return ENOBUFS if the queue is full */
703 	if (unlikely(!mlx5e_sq_has_room_for(sq, 2 * MLX5_SEND_WQE_MAX_WQEBBS))) {
704 		sq->stats.enobuf++;
705 		return (ENOBUFS);
706 	}
707 
708 	/* Align SQ edge with NOPs to avoid WQE wrap around */
709 	pi = ((~sq->pc) & sq->wq.sz_m1);
710 	if (pi < (MLX5_SEND_WQE_MAX_WQEBBS - 1)) {
711 		/* Send one multi NOP message instead of many */
712 		mlx5e_send_nop(sq, (pi + 1) * MLX5_SEND_WQEBB_NUM_DS);
713 		pi = ((~sq->pc) & sq->wq.sz_m1);
714 		if (pi < (MLX5_SEND_WQE_MAX_WQEBBS - 1)) {
715 			sq->stats.enobuf++;
716 			return (ENOMEM);
717 		}
718 	}
719 
720 #ifdef KERN_TLS
721 	/* Special handling for TLS packets, if any */
722 	switch (mlx5e_sq_tls_xmit(sq, &args, mbp)) {
723 	case MLX5E_TLS_LOOP:
724 		goto top;
725 	case MLX5E_TLS_FAILURE:
726 		mb = *mbp;
727 		err = ENOMEM;
728 		goto tx_drop;
729 	case MLX5E_TLS_DEFERRED:
730 		return (0);
731 	case MLX5E_TLS_CONTINUE:
732 	default:
733 		break;
734 	}
735 #endif
736 
737 	/* Setup local variables */
738 	pi = sq->pc & sq->wq.sz_m1;
739 	wqe = mlx5_wq_cyc_get_wqe(&sq->wq, pi);
740 	ifp = sq->ifp;
741 
742 	memset(wqe, 0, sizeof(*wqe));
743 
744 	/* get pointer to mbuf */
745 	mb = *mbp;
746 
747 	/* Send a copy of the frame to the BPF listener, if any */
748 	if (ifp != NULL && if_getbpf(ifp) != NULL)
749 		ETHER_BPF_MTAP(ifp, mb);
750 
751 	if (mb->m_pkthdr.csum_flags & (CSUM_IP | CSUM_TSO)) {
752 		wqe->eth.cs_flags |= MLX5_ETH_WQE_L3_CSUM;
753 	}
754 	if (mb->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP | CSUM_UDP_IPV6 | CSUM_TCP_IPV6 | CSUM_TSO)) {
755 		wqe->eth.cs_flags |= MLX5_ETH_WQE_L4_CSUM;
756 	}
757 	if (wqe->eth.cs_flags == 0) {
758 		sq->stats.csum_offload_none++;
759 	}
760 	if (mb->m_pkthdr.csum_flags & CSUM_TSO) {
761 		u32 payload_len;
762 		u32 mss = mb->m_pkthdr.tso_segsz;
763 		u32 num_pkts;
764 
765 		wqe->eth.mss = cpu_to_be16(mss);
766 		opcode = MLX5_OPCODE_LSO;
767 		if (args.ihs == 0)
768 			args.ihs = mlx5e_get_full_header_size(mb, NULL);
769 		if (unlikely(args.ihs == 0)) {
770 			err = EINVAL;
771 			goto tx_drop;
772 		}
773 		payload_len = mb->m_pkthdr.len - args.ihs;
774 		if (payload_len == 0)
775 			num_pkts = 1;
776 		else
777 			num_pkts = DIV_ROUND_UP(payload_len, mss);
778 		sq->mbuf[pi].num_bytes = payload_len + (num_pkts * args.ihs);
779 
780 
781 		sq->stats.tso_packets++;
782 		sq->stats.tso_bytes += payload_len;
783 	} else if (mb->m_pkthdr.csum_flags & CSUM_ENCAP_VXLAN) {
784 		/* check for inner TCP TSO first */
785 		if (mb->m_pkthdr.csum_flags & (CSUM_INNER_IP_TSO |
786 		    CSUM_INNER_IP6_TSO)) {
787 			u32 payload_len;
788 			u32 mss = mb->m_pkthdr.tso_segsz;
789 			u32 num_pkts;
790 
791 			wqe->eth.mss = cpu_to_be16(mss);
792 			opcode = MLX5_OPCODE_LSO;
793 
794 			if (likely(args.ihs == 0)) {
795 				args.ihs = mlx5e_get_vxlan_header_size(mb, wqe,
796 				       MLX5_ETH_WQE_L3_INNER_CSUM |
797 				       MLX5_ETH_WQE_L4_INNER_CSUM |
798 				       MLX5_ETH_WQE_L4_CSUM |
799 				       MLX5_ETH_WQE_L3_CSUM,
800 				       opcode);
801 				if (unlikely(args.ihs == 0)) {
802 					err = EINVAL;
803 					goto tx_drop;
804 				}
805 			}
806 
807 			payload_len = mb->m_pkthdr.len - args.ihs;
808 			if (payload_len == 0)
809 				num_pkts = 1;
810 			else
811 				num_pkts = DIV_ROUND_UP(payload_len, mss);
812 			sq->mbuf[pi].num_bytes = payload_len +
813 			    num_pkts * args.ihs;
814 
815 			sq->stats.tso_packets++;
816 			sq->stats.tso_bytes += payload_len;
817 		} else {
818 			opcode = MLX5_OPCODE_SEND;
819 
820 			if (likely(args.ihs == 0)) {
821 				uint8_t cs_mask;
822 
823 				if (mb->m_pkthdr.csum_flags &
824 				    (CSUM_INNER_IP_TCP | CSUM_INNER_IP_UDP |
825 				     CSUM_INNER_IP6_TCP | CSUM_INNER_IP6_UDP)) {
826 					cs_mask =
827 					    MLX5_ETH_WQE_L3_INNER_CSUM |
828 					    MLX5_ETH_WQE_L4_INNER_CSUM |
829 					    MLX5_ETH_WQE_L4_CSUM |
830 					    MLX5_ETH_WQE_L3_CSUM;
831 				} else if (mb->m_pkthdr.csum_flags & CSUM_INNER_IP) {
832 					cs_mask =
833 					    MLX5_ETH_WQE_L3_INNER_CSUM |
834 					    MLX5_ETH_WQE_L4_CSUM |
835 					    MLX5_ETH_WQE_L3_CSUM;
836 				} else {
837 					cs_mask =
838 					    MLX5_ETH_WQE_L4_CSUM |
839 					    MLX5_ETH_WQE_L3_CSUM;
840 				}
841 				args.ihs = mlx5e_get_vxlan_header_size(mb, wqe,
842 				    cs_mask, opcode);
843 				if (unlikely(args.ihs == 0)) {
844 					err = EINVAL;
845 					goto tx_drop;
846 				}
847 			}
848 
849 			sq->mbuf[pi].num_bytes = max_t (unsigned int,
850 			    mb->m_pkthdr.len, ETHER_MIN_LEN - ETHER_CRC_LEN);
851 		}
852 	} else {
853 		opcode = MLX5_OPCODE_SEND;
854 
855 		if (args.ihs == 0) {
856 			switch (sq->min_inline_mode) {
857 			case MLX5_INLINE_MODE_IP:
858 			case MLX5_INLINE_MODE_TCP_UDP:
859 				args.ihs = mlx5e_get_full_header_size(mb, NULL);
860 				if (unlikely(args.ihs == 0))
861 					args.ihs = mlx5e_get_l2_header_size(sq, mb);
862 				break;
863 			case MLX5_INLINE_MODE_L2:
864 				args.ihs = mlx5e_get_l2_header_size(sq, mb);
865 				break;
866 			case MLX5_INLINE_MODE_NONE:
867 				/* FALLTHROUGH */
868 			default:
869 				if ((mb->m_flags & M_VLANTAG) != 0 &&
870 				    (sq->min_insert_caps & MLX5E_INSERT_VLAN) != 0) {
871 					/* inlining VLAN data is not required */
872 					wqe->eth.vlan_cmd = htons(0x8000); /* bit 0 CVLAN */
873 					wqe->eth.vlan_hdr = htons(mb->m_pkthdr.ether_vtag);
874 					args.ihs = 0;
875 				} else if ((mb->m_flags & M_VLANTAG) == 0 &&
876 				    (sq->min_insert_caps & MLX5E_INSERT_NON_VLAN) != 0) {
877 					/* inlining non-VLAN data is not required */
878 					args.ihs = 0;
879 				} else {
880 					/* we are forced to inlining L2 header, if any */
881 					args.ihs = mlx5e_get_l2_header_size(sq, mb);
882 				}
883 				break;
884 			}
885 		}
886 		sq->mbuf[pi].num_bytes = max_t (unsigned int,
887 		    mb->m_pkthdr.len, ETHER_MIN_LEN - ETHER_CRC_LEN);
888 	}
889 
890 	if (likely(args.ihs == 0)) {
891 		/* nothing to inline */
892 	} else if ((mb->m_flags & M_VLANTAG) != 0) {
893 		struct ether_vlan_header *eh = (struct ether_vlan_header *)
894 		    wqe->eth.inline_hdr_start;
895 
896 		/* Range checks */
897 		if (unlikely(args.ihs > (sq->max_inline - ETHER_VLAN_ENCAP_LEN))) {
898 			if (mb->m_pkthdr.csum_flags & (CSUM_TSO | CSUM_ENCAP_VXLAN)) {
899 				err = EINVAL;
900 				goto tx_drop;
901 			}
902 			args.ihs = (sq->max_inline - ETHER_VLAN_ENCAP_LEN);
903 		} else if (unlikely(args.ihs < ETHER_HDR_LEN)) {
904 			err = EINVAL;
905 			goto tx_drop;
906 		}
907 		m_copydata(mb, 0, ETHER_HDR_LEN, (caddr_t)eh);
908 		m_adj(mb, ETHER_HDR_LEN);
909 		/* Insert 4 bytes VLAN tag into data stream */
910 		eh->evl_proto = eh->evl_encap_proto;
911 		eh->evl_encap_proto = htons(ETHERTYPE_VLAN);
912 		eh->evl_tag = htons(mb->m_pkthdr.ether_vtag);
913 		/* Copy rest of header data, if any */
914 		m_copydata(mb, 0, args.ihs - ETHER_HDR_LEN, (caddr_t)(eh + 1));
915 		m_adj(mb, args.ihs - ETHER_HDR_LEN);
916 		/* Extend header by 4 bytes */
917 		args.ihs += ETHER_VLAN_ENCAP_LEN;
918 		wqe->eth.inline_hdr_sz = cpu_to_be16(args.ihs);
919 	} else {
920 		/* check if inline header size is too big */
921 		if (unlikely(args.ihs > sq->max_inline)) {
922 			if (unlikely(mb->m_pkthdr.csum_flags & (CSUM_TSO |
923 			    CSUM_ENCAP_VXLAN))) {
924 				err = EINVAL;
925 				goto tx_drop;
926 			}
927 			args.ihs = sq->max_inline;
928 		}
929 		m_copydata(mb, 0, args.ihs, wqe->eth.inline_hdr_start);
930 		m_adj(mb, args.ihs);
931 		wqe->eth.inline_hdr_sz = cpu_to_be16(args.ihs);
932 	}
933 
934 	ds_cnt = sizeof(*wqe) / MLX5_SEND_WQE_DS;
935 	if (args.ihs > sizeof(wqe->eth.inline_hdr_start)) {
936 		ds_cnt += DIV_ROUND_UP(args.ihs - sizeof(wqe->eth.inline_hdr_start),
937 		    MLX5_SEND_WQE_DS);
938 	}
939 	dseg = ((struct mlx5_wqe_data_seg *)&wqe->ctrl) + ds_cnt;
940 
941 	err = bus_dmamap_load_mbuf_sg(sq->dma_tag, sq->mbuf[pi].dma_map,
942 	    mb, segs, &nsegs, BUS_DMA_NOWAIT);
943 	if (err == EFBIG) {
944 		/* Update statistics */
945 		sq->stats.defragged++;
946 		/* Too many mbuf fragments */
947 		mb = m_defrag(*mbp, M_NOWAIT);
948 		if (mb == NULL) {
949 			mb = *mbp;
950 			goto tx_drop;
951 		}
952 		/* Try again */
953 		err = bus_dmamap_load_mbuf_sg(sq->dma_tag, sq->mbuf[pi].dma_map,
954 		    mb, segs, &nsegs, BUS_DMA_NOWAIT);
955 	}
956 	/* Catch errors */
957 	if (err != 0)
958 		goto tx_drop;
959 
960 	/* Make sure all mbuf data, if any, is visible to the bus */
961 	if (nsegs != 0) {
962 		bus_dmamap_sync(sq->dma_tag, sq->mbuf[pi].dma_map,
963 		    BUS_DMASYNC_PREWRITE);
964 	} else {
965 		/* All data was inlined, free the mbuf. */
966 		bus_dmamap_unload(sq->dma_tag, sq->mbuf[pi].dma_map);
967 		m_freem(mb);
968 		mb = NULL;
969 	}
970 
971 	for (x = 0; x != nsegs; x++) {
972 		if (segs[x].ds_len == 0)
973 			continue;
974 		dseg->addr = cpu_to_be64((uint64_t)segs[x].ds_addr);
975 		dseg->lkey = sq->mkey_be;
976 		dseg->byte_count = cpu_to_be32((uint32_t)segs[x].ds_len);
977 		dseg++;
978 	}
979 
980 	ds_cnt = (dseg - ((struct mlx5_wqe_data_seg *)&wqe->ctrl));
981 
982 	wqe->ctrl.opmod_idx_opcode = cpu_to_be32((sq->pc << 8) | opcode);
983 	wqe->ctrl.qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_cnt);
984 	wqe->ctrl.imm = cpu_to_be32(args.tisn << 8);
985 
986 	if (mlx5e_do_send_cqe_inline(sq))
987 		wqe->ctrl.fm_ce_se = MLX5_WQE_CTRL_CQ_UPDATE;
988 	else
989 		wqe->ctrl.fm_ce_se = 0;
990 
991 	/* Copy data for doorbell */
992 	memcpy(sq->doorbell.d32, &wqe->ctrl, sizeof(sq->doorbell.d32));
993 
994 	/* Store pointer to mbuf */
995 	sq->mbuf[pi].mbuf = mb;
996 	sq->mbuf[pi].num_wqebbs = DIV_ROUND_UP(ds_cnt, MLX5_SEND_WQEBB_NUM_DS);
997 	if (unlikely(args.mst != NULL))
998 		sq->mbuf[pi].mst = m_snd_tag_ref(args.mst);
999 	else
1000 		MPASS(sq->mbuf[pi].mst == NULL);
1001 
1002 	sq->pc += sq->mbuf[pi].num_wqebbs;
1003 
1004 	/* Count all traffic going out */
1005 	sq->stats.packets++;
1006 	sq->stats.bytes += sq->mbuf[pi].num_bytes;
1007 
1008 	*mbp = NULL;	/* safety clear */
1009 	return (0);
1010 
1011 tx_drop:
1012 	sq->stats.dropped++;
1013 	*mbp = NULL;
1014 	m_freem(mb);
1015 	return err;
1016 }
1017 
1018 static void
1019 mlx5e_poll_tx_cq(struct mlx5e_sq *sq, int budget)
1020 {
1021 	u16 sqcc;
1022 
1023 	/*
1024 	 * sq->cc must be updated only after mlx5_cqwq_update_db_record(),
1025 	 * otherwise a cq overrun may occur
1026 	 */
1027 	sqcc = sq->cc;
1028 
1029 	while (budget > 0) {
1030 		struct mlx5_cqe64 *cqe;
1031 		struct m_snd_tag *mst;
1032 		struct mbuf *mb;
1033 		bool match;
1034 		u16 sqcc_this;
1035 		u16 delta;
1036 		u16 x;
1037 		u16 ci;
1038 
1039 		cqe = mlx5e_get_cqe(&sq->cq);
1040 		if (!cqe)
1041 			break;
1042 
1043 		mlx5_cqwq_pop(&sq->cq.wq);
1044 
1045 		/* check if the completion event indicates an error */
1046 		if (unlikely(get_cqe_opcode(cqe) != MLX5_CQE_REQ)) {
1047 			mlx5e_dump_err_cqe(&sq->cq, sq->sqn, (const void *)cqe);
1048 			sq->stats.cqe_err++;
1049 		}
1050 
1051 		/* setup local variables */
1052 		sqcc_this = be16toh(cqe->wqe_counter);
1053 		match = false;
1054 
1055 		/* update budget according to the event factor */
1056 		budget -= sq->cev_factor;
1057 
1058 		for (x = 0;; x++) {
1059 			if (unlikely(match != false)) {
1060 				break;
1061 			} else if (unlikely(x == sq->cev_factor)) {
1062 				/* WQE counter match not found */
1063 				sq->stats.cqe_err++;
1064 				break;
1065 			}
1066 			ci = sqcc & sq->wq.sz_m1;
1067 			delta = sqcc_this - sqcc;
1068 			match = (delta < sq->mbuf[ci].num_wqebbs);
1069 			mb = sq->mbuf[ci].mbuf;
1070 			sq->mbuf[ci].mbuf = NULL;
1071 			mst = sq->mbuf[ci].mst;
1072 			sq->mbuf[ci].mst = NULL;
1073 
1074 			if (unlikely(mb == NULL)) {
1075 				if (unlikely(sq->mbuf[ci].num_bytes == 0))
1076 					sq->stats.nop++;
1077 			} else {
1078 				bus_dmamap_sync(sq->dma_tag, sq->mbuf[ci].dma_map,
1079 				    BUS_DMASYNC_POSTWRITE);
1080 				bus_dmamap_unload(sq->dma_tag, sq->mbuf[ci].dma_map);
1081 
1082 				/* Free transmitted mbuf */
1083 				m_freem(mb);
1084 			}
1085 
1086 			if (unlikely(mst != NULL))
1087 				m_snd_tag_rele(mst);
1088 
1089 			sqcc += sq->mbuf[ci].num_wqebbs;
1090 		}
1091 	}
1092 
1093 	mlx5_cqwq_update_db_record(&sq->cq.wq);
1094 
1095 	/* Ensure cq space is freed before enabling more cqes */
1096 	atomic_thread_fence_rel();
1097 
1098 	sq->cc = sqcc;
1099 }
1100 
1101 static int
1102 mlx5e_xmit_locked(if_t ifp, struct mlx5e_sq *sq, struct mbuf *mb)
1103 {
1104 	int err = 0;
1105 
1106 	if (unlikely((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0 ||
1107 	    READ_ONCE(sq->running) == 0)) {
1108 		m_freem(mb);
1109 		return (ENETDOWN);
1110 	}
1111 
1112 	/* Do transmit */
1113 	if (mlx5e_sq_xmit(sq, &mb) != 0) {
1114 		/* NOTE: m_freem() is NULL safe */
1115 		m_freem(mb);
1116 		err = ENOBUFS;
1117 	}
1118 
1119 	/* Write the doorbell record, if any. */
1120 	mlx5e_tx_notify_hw(sq, false);
1121 
1122 	/*
1123 	 * Check if we need to start the event timer which flushes the
1124 	 * transmit ring on timeout:
1125 	 */
1126 	if (unlikely(sq->cev_next_state == MLX5E_CEV_STATE_INITIAL &&
1127 	    sq->cev_factor != 1)) {
1128 		/* start the timer */
1129 		mlx5e_sq_cev_timeout(sq);
1130 	} else {
1131 		/* don't send NOPs yet */
1132 		sq->cev_next_state = MLX5E_CEV_STATE_HOLD_NOPS;
1133 	}
1134 	return (err);
1135 }
1136 
1137 int
1138 mlx5e_xmit(if_t ifp, struct mbuf *mb)
1139 {
1140 	struct mlx5e_sq *sq;
1141 	int ret;
1142 
1143 	if (mb->m_pkthdr.csum_flags & CSUM_SND_TAG) {
1144 		MPASS(mb->m_pkthdr.snd_tag->ifp == ifp);
1145 		sq = mlx5e_select_queue_by_send_tag(ifp, mb);
1146 		if (unlikely(sq == NULL)) {
1147 			goto select_queue;
1148 		}
1149 	} else {
1150 select_queue:
1151 		sq = mlx5e_select_queue(ifp, mb);
1152 		if (unlikely(sq == NULL)) {
1153 			/* Free mbuf */
1154 			m_freem(mb);
1155 
1156 			/* Invalid send queue */
1157 			return (ENXIO);
1158 		}
1159 	}
1160 
1161 	mtx_lock(&sq->lock);
1162 	ret = mlx5e_xmit_locked(ifp, sq, mb);
1163 	mtx_unlock(&sq->lock);
1164 
1165 	return (ret);
1166 }
1167 
1168 void
1169 mlx5e_tx_cq_comp(struct mlx5_core_cq *mcq, struct mlx5_eqe *eqe __unused)
1170 {
1171 	struct mlx5e_sq *sq = container_of(mcq, struct mlx5e_sq, cq.mcq);
1172 
1173 	mtx_lock(&sq->comp_lock);
1174 	mlx5e_poll_tx_cq(sq, MLX5E_BUDGET_MAX);
1175 	mlx5e_cq_arm(&sq->cq, MLX5_GET_DOORBELL_LOCK(&sq->priv->doorbell_lock));
1176 	mtx_unlock(&sq->comp_lock);
1177 }
1178