]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/dev/mlx5/mlx5_en/mlx5_en_tx.c
MFC r300277:
[FreeBSD/stable/10.git] / sys / dev / mlx5 / mlx5_en / mlx5_en_tx.c
1 /*-
2  * Copyright (c) 2015 Mellanox Technologies. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  * $FreeBSD$
26  */
27
28 #include "en.h"
29 #include <machine/atomic.h>
30
31 static inline bool
32 mlx5e_do_send_cqe(struct mlx5e_sq *sq)
33 {
34         sq->cev_counter++;
35         /* interleave the CQEs */
36         if (sq->cev_counter >= sq->cev_factor) {
37                 sq->cev_counter = 0;
38                 return (1);
39         }
40         return (0);
41 }
42
43 void
44 mlx5e_send_nop(struct mlx5e_sq *sq, u32 ds_cnt, bool notify_hw)
45 {
46         u16 pi = sq->pc & sq->wq.sz_m1;
47         struct mlx5e_tx_wqe *wqe = mlx5_wq_cyc_get_wqe(&sq->wq, pi);
48
49         memset(&wqe->ctrl, 0, sizeof(wqe->ctrl));
50
51         wqe->ctrl.opmod_idx_opcode = cpu_to_be32((sq->pc << 8) | MLX5_OPCODE_NOP);
52         wqe->ctrl.qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_cnt);
53         if (mlx5e_do_send_cqe(sq))
54                 wqe->ctrl.fm_ce_se = MLX5_WQE_CTRL_CQ_UPDATE;
55         else
56                 wqe->ctrl.fm_ce_se = 0;
57
58         sq->mbuf[pi].mbuf = NULL;
59         sq->mbuf[pi].num_bytes = 0;
60         sq->mbuf[pi].num_wqebbs = DIV_ROUND_UP(ds_cnt, MLX5_SEND_WQEBB_NUM_DS);
61         sq->pc += sq->mbuf[pi].num_wqebbs;
62         if (notify_hw)
63                 mlx5e_tx_notify_hw(sq, wqe, 0);
64 }
65
66 #if (__FreeBSD_version >= 1100000)
67 static uint32_t mlx5e_hash_value;
68
69 static void
70 mlx5e_hash_init(void *arg)
71 {
72         mlx5e_hash_value = m_ether_tcpip_hash_init();
73 }
74
75 /* Make kernel call mlx5e_hash_init after the random stack finished initializing */
76 SYSINIT(mlx5e_hash_init, SI_SUB_RANDOM, SI_ORDER_ANY, &mlx5e_hash_init, NULL);
77 #endif
78
79 static struct mlx5e_sq *
80 mlx5e_select_queue(struct ifnet *ifp, struct mbuf *mb)
81 {
82         struct mlx5e_priv *priv = ifp->if_softc;
83         u32 ch;
84         u32 tc;
85
86         /* check if channels are successfully opened */
87         if (unlikely(priv->channel == NULL))
88                 return (NULL);
89
90         /* obtain VLAN information if present */
91         if (mb->m_flags & M_VLANTAG) {
92                 tc = (mb->m_pkthdr.ether_vtag >> 13);
93                 if (tc >= priv->num_tc)
94                         tc = priv->default_vlan_prio;
95         } else {
96                 tc = priv->default_vlan_prio;
97         }
98
99         ch = priv->params.num_channels;
100
101         /* check if flowid is set */
102         if (M_HASHTYPE_GET(mb) != M_HASHTYPE_NONE) {
103 #ifdef RSS
104                 u32 temp;
105
106                 if (rss_hash2bucket(mb->m_pkthdr.flowid,
107                     M_HASHTYPE_GET(mb), &temp) == 0)
108                         ch = temp % ch;
109                 else
110 #endif
111                         ch = (mb->m_pkthdr.flowid % 128) % ch;
112         } else {
113 #if (__FreeBSD_version >= 1100000)
114                 ch = m_ether_tcpip_hash(MBUF_HASHFLAG_L3 |
115                     MBUF_HASHFLAG_L4, mb, mlx5e_hash_value) % ch;
116 #else
117                 /*
118                  * m_ether_tcpip_hash not present in stable, so just
119                  * throw unhashed mbufs on queue 0
120                  */
121                 ch = 0;
122 #endif
123         }
124
125         /* check if channel is allocated */
126         if (unlikely(priv->channel[ch] == NULL))
127                 return (NULL);
128
129         return (&priv->channel[ch]->sq[tc]);
130 }
131
132 static inline u16
133 mlx5e_get_inline_hdr_size(struct mlx5e_sq *sq, struct mbuf *mb)
134 {
135         return (MIN(MLX5E_MAX_TX_INLINE, mb->m_len));
136 }
137
138 static int
139 mlx5e_get_header_size(struct mbuf *mb)
140 {
141         struct ether_vlan_header *eh;
142         struct tcphdr *th;
143         struct ip *ip;
144         int ip_hlen, tcp_hlen;
145         struct ip6_hdr *ip6;
146         uint16_t eth_type;
147         int eth_hdr_len;
148
149         eh = mtod(mb, struct ether_vlan_header *);
150         if (mb->m_len < ETHER_HDR_LEN)
151                 return (0);
152         if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
153                 eth_type = ntohs(eh->evl_proto);
154                 eth_hdr_len = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
155         } else {
156                 eth_type = ntohs(eh->evl_encap_proto);
157                 eth_hdr_len = ETHER_HDR_LEN;
158         }
159         if (mb->m_len < eth_hdr_len)
160                 return (0);
161         switch (eth_type) {
162         case ETHERTYPE_IP:
163                 ip = (struct ip *)(mb->m_data + eth_hdr_len);
164                 if (mb->m_len < eth_hdr_len + sizeof(*ip))
165                         return (0);
166                 if (ip->ip_p != IPPROTO_TCP)
167                         return (0);
168                 ip_hlen = ip->ip_hl << 2;
169                 eth_hdr_len += ip_hlen;
170                 break;
171         case ETHERTYPE_IPV6:
172                 ip6 = (struct ip6_hdr *)(mb->m_data + eth_hdr_len);
173                 if (mb->m_len < eth_hdr_len + sizeof(*ip6))
174                         return (0);
175                 if (ip6->ip6_nxt != IPPROTO_TCP)
176                         return (0);
177                 eth_hdr_len += sizeof(*ip6);
178                 break;
179         default:
180                 return (0);
181         }
182         if (mb->m_len < eth_hdr_len + sizeof(*th))
183                 return (0);
184         th = (struct tcphdr *)(mb->m_data + eth_hdr_len);
185         tcp_hlen = th->th_off << 2;
186         eth_hdr_len += tcp_hlen;
187         if (mb->m_len < eth_hdr_len)
188                 return (0);
189         return (eth_hdr_len);
190 }
191
192 /*
193  * The return value is not going back to the stack because of
194  * the drbr
195  */
196 static int
197 mlx5e_sq_xmit(struct mlx5e_sq *sq, struct mbuf **mbp)
198 {
199         bus_dma_segment_t segs[MLX5E_MAX_TX_MBUF_FRAGS];
200         struct mlx5_wqe_data_seg *dseg;
201         struct mlx5e_tx_wqe *wqe;
202         struct ifnet *ifp;
203         int nsegs;
204         int err;
205         int x;
206         struct mbuf *mb = *mbp;
207         u16 ds_cnt;
208         u16 ihs;
209         u16 pi;
210         u8 opcode;
211
212         /*
213          * Return ENOBUFS if the queue is full, this may trigger reinsertion
214          * of the mbuf into the drbr (see mlx5e_xmit_locked)
215          */
216         if (unlikely(!mlx5e_sq_has_room_for(sq, 2 * MLX5_SEND_WQE_MAX_WQEBBS))) {
217                 return (ENOBUFS);
218         }
219
220         /* Align SQ edge with NOPs to avoid WQE wrap around */
221         pi = ((~sq->pc) & sq->wq.sz_m1);
222         if (pi < (MLX5_SEND_WQE_MAX_WQEBBS - 1)) {
223                 /* Send one multi NOP message instead of many */
224                 mlx5e_send_nop(sq, (pi + 1) * MLX5_SEND_WQEBB_NUM_DS, false);
225                 pi = ((~sq->pc) & sq->wq.sz_m1);
226                 if (pi < (MLX5_SEND_WQE_MAX_WQEBBS - 1)) {
227                         m_freem(mb);
228                         return (ENOMEM);
229                 }
230         }
231
232         /* Setup local variables */
233         pi = sq->pc & sq->wq.sz_m1;
234         wqe = mlx5_wq_cyc_get_wqe(&sq->wq, pi);
235         ifp = sq->channel->ifp;
236
237         memset(wqe, 0, sizeof(*wqe));
238
239         /* Send a copy of the frame to the BPF listener, if any */
240         if (ifp != NULL && ifp->if_bpf != NULL)
241                 ETHER_BPF_MTAP(ifp, mb);
242
243         if (mb->m_pkthdr.csum_flags & (CSUM_IP | CSUM_TSO)) {
244                 wqe->eth.cs_flags |= MLX5_ETH_WQE_L3_CSUM;
245         }
246         if (mb->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP | CSUM_UDP_IPV6 | CSUM_TCP_IPV6 | CSUM_TSO)) {
247                 wqe->eth.cs_flags |= MLX5_ETH_WQE_L4_CSUM;
248         }
249         if (wqe->eth.cs_flags == 0) {
250                 sq->stats.csum_offload_none++;
251         }
252         if (mb->m_pkthdr.csum_flags & CSUM_TSO) {
253                 u32 payload_len;
254                 u32 mss = mb->m_pkthdr.tso_segsz;
255                 u32 num_pkts;
256
257                 wqe->eth.mss = cpu_to_be16(mss);
258                 opcode = MLX5_OPCODE_LSO;
259                 ihs = mlx5e_get_header_size(mb);
260                 payload_len = mb->m_pkthdr.len - ihs;
261                 if (payload_len == 0)
262                         num_pkts = 1;
263                 else
264                         num_pkts = DIV_ROUND_UP(payload_len, mss);
265                 sq->mbuf[pi].num_bytes = payload_len + (num_pkts * ihs);
266
267                 sq->stats.tso_packets++;
268                 sq->stats.tso_bytes += payload_len;
269         } else {
270                 opcode = MLX5_OPCODE_SEND;
271                 ihs = mlx5e_get_inline_hdr_size(sq, mb);
272                 sq->mbuf[pi].num_bytes = max_t (unsigned int,
273                     mb->m_pkthdr.len, ETHER_MIN_LEN - ETHER_CRC_LEN);
274         }
275         if (mb->m_flags & M_VLANTAG) {
276                 struct ether_vlan_header *eh =
277                     (struct ether_vlan_header *)wqe->eth.inline_hdr_start;
278
279                 /* Range checks */
280                 if (ihs > (MLX5E_MAX_TX_INLINE - ETHER_VLAN_ENCAP_LEN))
281                         ihs = (MLX5E_MAX_TX_INLINE - ETHER_VLAN_ENCAP_LEN);
282                 else if (ihs < ETHER_HDR_LEN) {
283                         err = EINVAL;
284                         goto tx_drop;
285                 }
286                 m_copydata(mb, 0, ETHER_HDR_LEN, (caddr_t)eh);
287                 m_adj(mb, ETHER_HDR_LEN);
288                 /* Insert 4 bytes VLAN tag into data stream */
289                 eh->evl_proto = eh->evl_encap_proto;
290                 eh->evl_encap_proto = htons(ETHERTYPE_VLAN);
291                 eh->evl_tag = htons(mb->m_pkthdr.ether_vtag);
292                 /* Copy rest of header data, if any */
293                 m_copydata(mb, 0, ihs - ETHER_HDR_LEN, (caddr_t)(eh + 1));
294                 m_adj(mb, ihs - ETHER_HDR_LEN);
295                 /* Extend header by 4 bytes */
296                 ihs += ETHER_VLAN_ENCAP_LEN;
297         } else {
298                 m_copydata(mb, 0, ihs, wqe->eth.inline_hdr_start);
299                 m_adj(mb, ihs);
300         }
301
302         wqe->eth.inline_hdr_sz = cpu_to_be16(ihs);
303
304         ds_cnt = sizeof(*wqe) / MLX5_SEND_WQE_DS;
305         if (likely(ihs > sizeof(wqe->eth.inline_hdr_start))) {
306                 ds_cnt += DIV_ROUND_UP(ihs - sizeof(wqe->eth.inline_hdr_start),
307                     MLX5_SEND_WQE_DS);
308         }
309         dseg = ((struct mlx5_wqe_data_seg *)&wqe->ctrl) + ds_cnt;
310
311         /* Trim off empty mbufs */
312         while (mb->m_len == 0) {
313                 mb = m_free(mb);
314                 /* Check if all data has been inlined */
315                 if (mb == NULL)
316                         goto skip_dma;
317         }
318
319         err = bus_dmamap_load_mbuf_sg(sq->dma_tag, sq->mbuf[pi].dma_map,
320             mb, segs, &nsegs, BUS_DMA_NOWAIT);
321         if (err == EFBIG) {
322                 /*
323                  * Update *mbp before defrag in case it was trimmed in the
324                  * loop above
325                  */
326                 *mbp = mb;
327                 /* Update statistics */
328                 sq->stats.defragged++;
329                 /* Too many mbuf fragments */
330                 mb = m_defrag(*mbp, M_NOWAIT);
331                 if (mb == NULL) {
332                         mb = *mbp;
333                         goto tx_drop;
334                 }
335                 /* Try again */
336                 err = bus_dmamap_load_mbuf_sg(sq->dma_tag, sq->mbuf[pi].dma_map,
337                     mb, segs, &nsegs, BUS_DMA_NOWAIT);
338         }
339         /* Catch errors */
340         if (err != 0) {
341                 goto tx_drop;
342         }
343         *mbp = mb;
344
345         for (x = 0; x != nsegs; x++) {
346                 if (segs[x].ds_len == 0)
347                         continue;
348                 dseg->addr = cpu_to_be64((uint64_t)segs[x].ds_addr);
349                 dseg->lkey = sq->mkey_be;
350                 dseg->byte_count = cpu_to_be32((uint32_t)segs[x].ds_len);
351                 dseg++;
352         }
353 skip_dma:
354         ds_cnt = (dseg - ((struct mlx5_wqe_data_seg *)&wqe->ctrl));
355
356         wqe->ctrl.opmod_idx_opcode = cpu_to_be32((sq->pc << 8) | opcode);
357         wqe->ctrl.qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_cnt);
358         if (mlx5e_do_send_cqe(sq))
359                 wqe->ctrl.fm_ce_se = MLX5_WQE_CTRL_CQ_UPDATE;
360         else
361                 wqe->ctrl.fm_ce_se = 0;
362
363         /* Store pointer to mbuf */
364         sq->mbuf[pi].mbuf = mb;
365         sq->mbuf[pi].num_wqebbs = DIV_ROUND_UP(ds_cnt, MLX5_SEND_WQEBB_NUM_DS);
366         sq->pc += sq->mbuf[pi].num_wqebbs;
367
368         /* Make sure all mbuf data is written to RAM */
369         if (mb != NULL)
370                 bus_dmamap_sync(sq->dma_tag, sq->mbuf[pi].dma_map, BUS_DMASYNC_PREWRITE);
371
372         mlx5e_tx_notify_hw(sq, wqe, 0);
373
374         sq->stats.packets++;
375         return (0);
376
377 tx_drop:
378         sq->stats.dropped++;
379         *mbp = NULL;
380         m_freem(mb);
381         return err;
382 }
383
384 static void
385 mlx5e_poll_tx_cq(struct mlx5e_sq *sq, int budget)
386 {
387         u16 sqcc;
388
389         /*
390          * sq->cc must be updated only after mlx5_cqwq_update_db_record(),
391          * otherwise a cq overrun may occur
392          */
393         sqcc = sq->cc;
394
395         while (budget > 0) {
396                 struct mlx5_cqe64 *cqe;
397                 struct mbuf *mb;
398                 u16 x;
399                 u16 ci;
400
401                 cqe = mlx5e_get_cqe(&sq->cq);
402                 if (!cqe)
403                         break;
404
405                 mlx5_cqwq_pop(&sq->cq.wq);
406
407                 /* update budget according to the event factor */
408                 budget -= sq->cev_factor;
409
410                 for (x = 0; x != sq->cev_factor; x++) {
411                         ci = sqcc & sq->wq.sz_m1;
412                         mb = sq->mbuf[ci].mbuf;
413                         sq->mbuf[ci].mbuf = NULL;       /* Safety clear */
414
415                         if (mb == NULL) {
416                                 if (sq->mbuf[ci].num_bytes == 0) {
417                                         /* NOP */
418                                         sq->stats.nop++;
419                                 }
420                         } else {
421                                 bus_dmamap_sync(sq->dma_tag, sq->mbuf[ci].dma_map,
422                                     BUS_DMASYNC_POSTWRITE);
423                                 bus_dmamap_unload(sq->dma_tag, sq->mbuf[ci].dma_map);
424
425                                 /* Free transmitted mbuf */
426                                 m_freem(mb);
427                         }
428                         sqcc += sq->mbuf[ci].num_wqebbs;
429                 }
430         }
431
432         mlx5_cqwq_update_db_record(&sq->cq.wq);
433
434         /* Ensure cq space is freed before enabling more cqes */
435         wmb();
436
437         sq->cc = sqcc;
438
439         if (atomic_cmpset_int(&sq->queue_state, MLX5E_SQ_FULL, MLX5E_SQ_READY))
440                 taskqueue_enqueue(sq->sq_tq, &sq->sq_task);
441 }
442
443 static int
444 mlx5e_xmit_locked(struct ifnet *ifp, struct mlx5e_sq *sq, struct mbuf *mb)
445 {
446         struct mbuf *next;
447         int err = 0;
448
449         if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
450                 if (mb)
451                         err = drbr_enqueue(ifp, sq->br, mb);
452                 return (err);
453         }
454
455         if (mb != NULL)
456                 /*
457                  * If we can't insert mbuf into drbr, try to xmit anyway.
458                  * We keep the error we got so we could return that after xmit.
459                  */
460                 err = drbr_enqueue(ifp, sq->br, mb);
461
462         /* Process the queue */
463         while ((next = drbr_peek(ifp, sq->br)) != NULL) {
464                 if (mlx5e_sq_xmit(sq, &next) != 0) {
465                         if (next == NULL) {
466                                 drbr_advance(ifp, sq->br);
467                         } else {
468                                 drbr_putback(ifp, sq->br, next);
469                                 atomic_store_rel_int(&sq->queue_state, MLX5E_SQ_FULL);
470                         }
471                         break;
472                 }
473                 drbr_advance(ifp, sq->br);
474                 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
475                         break;
476         }
477         /*
478          * Check if we need to start the event timer which flushes the
479          * transmit ring on timeout:
480          */
481         if (unlikely(sq->cev_next_state == MLX5E_CEV_STATE_INITIAL &&
482             sq->cev_factor != 1)) {
483                 /* start the timer */
484                 mlx5e_sq_cev_timeout(sq);
485         } else {
486                 /* don't send NOPs yet */
487                 sq->cev_next_state = MLX5E_CEV_STATE_HOLD_NOPS;
488         }
489         return (err);
490 }
491
492 int
493 mlx5e_xmit(struct ifnet *ifp, struct mbuf *mb)
494 {
495         struct mlx5e_sq *sq;
496         int ret;
497
498         sq = mlx5e_select_queue(ifp, mb);
499         if (unlikely(sq == NULL)) {
500                 /* Invalid send queue */
501                 m_freem(mb);
502                 return (ENXIO);
503         }
504         if (mtx_trylock(&sq->lock)) {
505                 ret = mlx5e_xmit_locked(ifp, sq, mb);
506                 mtx_unlock(&sq->lock);
507         } else {
508                 ret = drbr_enqueue(ifp, sq->br, mb);
509                 taskqueue_enqueue(sq->sq_tq, &sq->sq_task);
510         }
511
512         return (ret);
513 }
514
515 void
516 mlx5e_tx_cq_comp(struct mlx5_core_cq *mcq)
517 {
518         struct mlx5e_sq *sq = container_of(mcq, struct mlx5e_sq, cq.mcq);
519
520         mtx_lock(&sq->comp_lock);
521         mlx5e_poll_tx_cq(sq, MLX5E_BUDGET_MAX);
522         mlx5e_cq_arm(&sq->cq);
523         mtx_unlock(&sq->comp_lock);
524 }
525
526 void
527 mlx5e_tx_que(void *context, int pending)
528 {
529         struct mlx5e_sq *sq = context;
530         struct ifnet *ifp = sq->channel->ifp;
531
532         if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
533                 mtx_lock(&sq->lock);
534                 if (!drbr_empty(ifp, sq->br))
535                         mlx5e_xmit_locked(ifp, sq, NULL);
536                 mtx_unlock(&sq->lock);
537         }
538 }