1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#include <linux/tcp.h>
34#include <linux/if_vlan.h>
35#include <net/geneve.h>
36#include <net/dsfield.h>
37#include "en.h"
38#include "en/txrx.h"
39#include "ipoib/ipoib.h"
40#include "en_accel/en_accel.h"
41#include "en/ptp.h"
42
43static void mlx5e_dma_unmap_wqe_err(struct mlx5e_txqsq *sq, u8 num_dma)
44{
45 int i;
46
47 for (i = 0; i < num_dma; i++) {
48 struct mlx5e_sq_dma *last_pushed_dma =
49 mlx5e_dma_get(sq, --sq->dma_fifo_pc);
50
51 mlx5e_tx_dma_unmap(sq->pdev, last_pushed_dma);
52 }
53}
54
55#ifdef CONFIG_MLX5_CORE_EN_DCB
56static inline int mlx5e_get_dscp_up(struct mlx5e_priv *priv, struct sk_buff *skb)
57{
58 int dscp_cp = 0;
59
60 if (skb->protocol == htons(ETH_P_IP))
61 dscp_cp = ipv4_get_dsfield(ip_hdr(skb)) >> 2;
62 else if (skb->protocol == htons(ETH_P_IPV6))
63 dscp_cp = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2;
64
65 return priv->dcbx_dp.dscp2prio[dscp_cp];
66}
67#endif
68
69static u16 mlx5e_select_ptpsq(struct net_device *dev, struct sk_buff *skb)
70{
71 struct mlx5e_priv *priv = netdev_priv(dev);
72 int up = 0;
73
74 if (!netdev_get_num_tc(dev))
75 goto return_txq;
76
77#ifdef CONFIG_MLX5_CORE_EN_DCB
78 if (priv->dcbx_dp.trust_state == MLX5_QPTS_TRUST_DSCP)
79 up = mlx5e_get_dscp_up(priv, skb);
80 else
81#endif
82 if (skb_vlan_tag_present(skb))
83 up = skb_vlan_tag_get_prio(skb);
84
85return_txq:
86 return priv->port_ptp_tc2realtxq[up];
87}
88
89static int mlx5e_select_htb_queue(struct mlx5e_priv *priv, struct sk_buff *skb,
90 u16 htb_maj_id)
91{
92 u16 classid;
93
94 if ((TC_H_MAJ(skb->priority) >> 16) == htb_maj_id)
95 classid = TC_H_MIN(skb->priority);
96 else
97 classid = READ_ONCE(priv->htb.defcls);
98
99 if (!classid)
100 return 0;
101
102 return mlx5e_get_txq_by_classid(priv, classid);
103}
104
105u16 mlx5e_select_queue(struct net_device *dev, struct sk_buff *skb,
106 struct net_device *sb_dev)
107{
108 struct mlx5e_priv *priv = netdev_priv(dev);
109 int num_tc_x_num_ch;
110 int txq_ix;
111 int up = 0;
112 int ch_ix;
113
114
115 num_tc_x_num_ch = READ_ONCE(priv->num_tc_x_num_ch);
116 if (unlikely(dev->real_num_tx_queues > num_tc_x_num_ch)) {
117 struct mlx5e_ptp *ptp_channel;
118
119
120 u16 htb_maj_id = smp_load_acquire(&priv->htb.maj_id);
121
122 if (unlikely(htb_maj_id)) {
123 txq_ix = mlx5e_select_htb_queue(priv, skb, htb_maj_id);
124 if (txq_ix > 0)
125 return txq_ix;
126 }
127
128 ptp_channel = READ_ONCE(priv->channels.ptp);
129 if (unlikely(ptp_channel &&
130 test_bit(MLX5E_PTP_STATE_TX, ptp_channel->state) &&
131 mlx5e_use_ptpsq(skb)))
132 return mlx5e_select_ptpsq(dev, skb);
133
134 txq_ix = netdev_pick_tx(dev, skb, NULL);
135
136
137
138
139
140 if (unlikely(txq_ix >= num_tc_x_num_ch))
141 txq_ix %= num_tc_x_num_ch;
142 } else {
143 txq_ix = netdev_pick_tx(dev, skb, NULL);
144 }
145
146 if (!netdev_get_num_tc(dev))
147 return txq_ix;
148
149#ifdef CONFIG_MLX5_CORE_EN_DCB
150 if (priv->dcbx_dp.trust_state == MLX5_QPTS_TRUST_DSCP)
151 up = mlx5e_get_dscp_up(priv, skb);
152 else
153#endif
154 if (skb_vlan_tag_present(skb))
155 up = skb_vlan_tag_get_prio(skb);
156
157
158
159
160
161 ch_ix = priv->txq2sq[txq_ix]->ch_ix;
162
163 return priv->channel_tc2realtxq[ch_ix][up];
164}
165
166static inline int mlx5e_skb_l2_header_offset(struct sk_buff *skb)
167{
168#define MLX5E_MIN_INLINE (ETH_HLEN + VLAN_HLEN)
169
170 return max(skb_network_offset(skb), MLX5E_MIN_INLINE);
171}
172
173static inline int mlx5e_skb_l3_header_offset(struct sk_buff *skb)
174{
175 if (skb_transport_header_was_set(skb))
176 return skb_transport_offset(skb);
177 else
178 return mlx5e_skb_l2_header_offset(skb);
179}
180
181static inline u16 mlx5e_calc_min_inline(enum mlx5_inline_modes mode,
182 struct sk_buff *skb)
183{
184 u16 hlen;
185
186 switch (mode) {
187 case MLX5_INLINE_MODE_NONE:
188 return 0;
189 case MLX5_INLINE_MODE_TCP_UDP:
190 hlen = eth_get_headlen(skb->dev, skb->data, skb_headlen(skb));
191 if (hlen == ETH_HLEN && !skb_vlan_tag_present(skb))
192 hlen += VLAN_HLEN;
193 break;
194 case MLX5_INLINE_MODE_IP:
195 hlen = mlx5e_skb_l3_header_offset(skb);
196 break;
197 case MLX5_INLINE_MODE_L2:
198 default:
199 hlen = mlx5e_skb_l2_header_offset(skb);
200 }
201 return min_t(u16, hlen, skb_headlen(skb));
202}
203
204static inline void mlx5e_insert_vlan(void *start, struct sk_buff *skb, u16 ihs)
205{
206 struct vlan_ethhdr *vhdr = (struct vlan_ethhdr *)start;
207 int cpy1_sz = 2 * ETH_ALEN;
208 int cpy2_sz = ihs - cpy1_sz;
209
210 memcpy(vhdr, skb->data, cpy1_sz);
211 vhdr->h_vlan_proto = skb->vlan_proto;
212 vhdr->h_vlan_TCI = cpu_to_be16(skb_vlan_tag_get(skb));
213 memcpy(&vhdr->h_vlan_encapsulated_proto, skb->data + cpy1_sz, cpy2_sz);
214}
215
216
217
218
219static void
220ipsec_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb,
221 struct mlx5_wqe_eth_seg *eseg)
222{
223 eseg->cs_flags = MLX5_ETH_WQE_L3_CSUM;
224 if (skb->encapsulation) {
225 eseg->cs_flags |= MLX5_ETH_WQE_L3_INNER_CSUM;
226 sq->stats->csum_partial_inner++;
227 } else {
228 sq->stats->csum_partial++;
229 }
230}
231
232static inline void
233mlx5e_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb,
234 struct mlx5e_accel_tx_state *accel,
235 struct mlx5_wqe_eth_seg *eseg)
236{
237 if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
238 eseg->cs_flags = MLX5_ETH_WQE_L3_CSUM;
239 if (skb->encapsulation) {
240 eseg->cs_flags |= MLX5_ETH_WQE_L3_INNER_CSUM |
241 MLX5_ETH_WQE_L4_INNER_CSUM;
242 sq->stats->csum_partial_inner++;
243 } else {
244 eseg->cs_flags |= MLX5_ETH_WQE_L4_CSUM;
245 sq->stats->csum_partial++;
246 }
247#ifdef CONFIG_MLX5_EN_TLS
248 } else if (unlikely(accel && accel->tls.tls_tisn)) {
249 eseg->cs_flags = MLX5_ETH_WQE_L3_CSUM | MLX5_ETH_WQE_L4_CSUM;
250 sq->stats->csum_partial++;
251#endif
252 } else if (unlikely(mlx5e_ipsec_eseg_meta(eseg))) {
253 ipsec_txwqe_build_eseg_csum(sq, skb, eseg);
254 } else
255 sq->stats->csum_none++;
256}
257
258static inline u16
259mlx5e_tx_get_gso_ihs(struct mlx5e_txqsq *sq, struct sk_buff *skb)
260{
261 struct mlx5e_sq_stats *stats = sq->stats;
262 u16 ihs;
263
264 if (skb->encapsulation) {
265 ihs = skb_inner_transport_offset(skb) + inner_tcp_hdrlen(skb);
266 stats->tso_inner_packets++;
267 stats->tso_inner_bytes += skb->len - ihs;
268 } else {
269 if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
270 ihs = skb_transport_offset(skb) + sizeof(struct udphdr);
271 else
272 ihs = skb_transport_offset(skb) + tcp_hdrlen(skb);
273 stats->tso_packets++;
274 stats->tso_bytes += skb->len - ihs;
275 }
276
277 return ihs;
278}
279
280static inline int
281mlx5e_txwqe_build_dsegs(struct mlx5e_txqsq *sq, struct sk_buff *skb,
282 unsigned char *skb_data, u16 headlen,
283 struct mlx5_wqe_data_seg *dseg)
284{
285 dma_addr_t dma_addr = 0;
286 u8 num_dma = 0;
287 int i;
288
289 if (headlen) {
290 dma_addr = dma_map_single(sq->pdev, skb_data, headlen,
291 DMA_TO_DEVICE);
292 if (unlikely(dma_mapping_error(sq->pdev, dma_addr)))
293 goto dma_unmap_wqe_err;
294
295 dseg->addr = cpu_to_be64(dma_addr);
296 dseg->lkey = sq->mkey_be;
297 dseg->byte_count = cpu_to_be32(headlen);
298
299 mlx5e_dma_push(sq, dma_addr, headlen, MLX5E_DMA_MAP_SINGLE);
300 num_dma++;
301 dseg++;
302 }
303
304 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
305 skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
306 int fsz = skb_frag_size(frag);
307
308 dma_addr = skb_frag_dma_map(sq->pdev, frag, 0, fsz,
309 DMA_TO_DEVICE);
310 if (unlikely(dma_mapping_error(sq->pdev, dma_addr)))
311 goto dma_unmap_wqe_err;
312
313 dseg->addr = cpu_to_be64(dma_addr);
314 dseg->lkey = sq->mkey_be;
315 dseg->byte_count = cpu_to_be32(fsz);
316
317 mlx5e_dma_push(sq, dma_addr, fsz, MLX5E_DMA_MAP_PAGE);
318 num_dma++;
319 dseg++;
320 }
321
322 return num_dma;
323
324dma_unmap_wqe_err:
325 mlx5e_dma_unmap_wqe_err(sq, num_dma);
326 return -ENOMEM;
327}
328
329struct mlx5e_tx_attr {
330 u32 num_bytes;
331 u16 headlen;
332 u16 ihs;
333 __be16 mss;
334 u16 insz;
335 u8 opcode;
336};
337
338struct mlx5e_tx_wqe_attr {
339 u16 ds_cnt;
340 u16 ds_cnt_inl;
341 u16 ds_cnt_ids;
342 u8 num_wqebbs;
343};
344
345static u8
346mlx5e_tx_wqe_inline_mode(struct mlx5e_txqsq *sq, struct sk_buff *skb,
347 struct mlx5e_accel_tx_state *accel)
348{
349 u8 mode;
350
351#ifdef CONFIG_MLX5_EN_TLS
352 if (accel && accel->tls.tls_tisn)
353 return MLX5_INLINE_MODE_TCP_UDP;
354#endif
355
356 mode = sq->min_inline_mode;
357
358 if (skb_vlan_tag_present(skb) &&
359 test_bit(MLX5E_SQ_STATE_VLAN_NEED_L2_INLINE, &sq->state))
360 mode = max_t(u8, MLX5_INLINE_MODE_L2, mode);
361
362 return mode;
363}
364
365static void mlx5e_sq_xmit_prepare(struct mlx5e_txqsq *sq, struct sk_buff *skb,
366 struct mlx5e_accel_tx_state *accel,
367 struct mlx5e_tx_attr *attr)
368{
369 struct mlx5e_sq_stats *stats = sq->stats;
370
371 if (skb_is_gso(skb)) {
372 u16 ihs = mlx5e_tx_get_gso_ihs(sq, skb);
373
374 *attr = (struct mlx5e_tx_attr) {
375 .opcode = MLX5_OPCODE_LSO,
376 .mss = cpu_to_be16(skb_shinfo(skb)->gso_size),
377 .ihs = ihs,
378 .num_bytes = skb->len + (skb_shinfo(skb)->gso_segs - 1) * ihs,
379 .headlen = skb_headlen(skb) - ihs,
380 };
381
382 stats->packets += skb_shinfo(skb)->gso_segs;
383 } else {
384 u8 mode = mlx5e_tx_wqe_inline_mode(sq, skb, accel);
385 u16 ihs = mlx5e_calc_min_inline(mode, skb);
386
387 *attr = (struct mlx5e_tx_attr) {
388 .opcode = MLX5_OPCODE_SEND,
389 .mss = cpu_to_be16(0),
390 .ihs = ihs,
391 .num_bytes = max_t(unsigned int, skb->len, ETH_ZLEN),
392 .headlen = skb_headlen(skb) - ihs,
393 };
394
395 stats->packets++;
396 }
397
398 attr->insz = mlx5e_accel_tx_ids_len(sq, accel);
399 stats->bytes += attr->num_bytes;
400}
401
402static void mlx5e_sq_calc_wqe_attr(struct sk_buff *skb, const struct mlx5e_tx_attr *attr,
403 struct mlx5e_tx_wqe_attr *wqe_attr)
404{
405 u16 ds_cnt = MLX5E_TX_WQE_EMPTY_DS_COUNT;
406 u16 ds_cnt_inl = 0;
407 u16 ds_cnt_ids = 0;
408
409 if (attr->insz)
410 ds_cnt_ids = DIV_ROUND_UP(sizeof(struct mlx5_wqe_inline_seg) + attr->insz,
411 MLX5_SEND_WQE_DS);
412
413 ds_cnt += !!attr->headlen + skb_shinfo(skb)->nr_frags + ds_cnt_ids;
414 if (attr->ihs) {
415 u16 inl = attr->ihs - INL_HDR_START_SZ;
416
417 if (skb_vlan_tag_present(skb))
418 inl += VLAN_HLEN;
419
420 ds_cnt_inl = DIV_ROUND_UP(inl, MLX5_SEND_WQE_DS);
421 ds_cnt += ds_cnt_inl;
422 }
423
424 *wqe_attr = (struct mlx5e_tx_wqe_attr) {
425 .ds_cnt = ds_cnt,
426 .ds_cnt_inl = ds_cnt_inl,
427 .ds_cnt_ids = ds_cnt_ids,
428 .num_wqebbs = DIV_ROUND_UP(ds_cnt, MLX5_SEND_WQEBB_NUM_DS),
429 };
430}
431
432static void mlx5e_tx_skb_update_hwts_flags(struct sk_buff *skb)
433{
434 if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))
435 skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
436}
437
438static void mlx5e_tx_check_stop(struct mlx5e_txqsq *sq)
439{
440 if (unlikely(!mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, sq->stop_room))) {
441 netif_tx_stop_queue(sq->txq);
442 sq->stats->stopped++;
443 }
444}
445
446static inline void
447mlx5e_txwqe_complete(struct mlx5e_txqsq *sq, struct sk_buff *skb,
448 const struct mlx5e_tx_attr *attr,
449 const struct mlx5e_tx_wqe_attr *wqe_attr, u8 num_dma,
450 struct mlx5e_tx_wqe_info *wi, struct mlx5_wqe_ctrl_seg *cseg,
451 bool xmit_more)
452{
453 struct mlx5_wq_cyc *wq = &sq->wq;
454 bool send_doorbell;
455
456 *wi = (struct mlx5e_tx_wqe_info) {
457 .skb = skb,
458 .num_bytes = attr->num_bytes,
459 .num_dma = num_dma,
460 .num_wqebbs = wqe_attr->num_wqebbs,
461 .num_fifo_pkts = 0,
462 };
463
464 cseg->opmod_idx_opcode = cpu_to_be32((sq->pc << 8) | attr->opcode);
465 cseg->qpn_ds = cpu_to_be32((sq->sqn << 8) | wqe_attr->ds_cnt);
466
467 mlx5e_tx_skb_update_hwts_flags(skb);
468
469 sq->pc += wi->num_wqebbs;
470
471 mlx5e_tx_check_stop(sq);
472
473 if (unlikely(sq->ptpsq)) {
474 mlx5e_skb_cb_hwtstamp_init(skb);
475 mlx5e_skb_fifo_push(&sq->ptpsq->skb_fifo, skb);
476 skb_get(skb);
477 }
478
479 send_doorbell = __netdev_tx_sent_queue(sq->txq, attr->num_bytes, xmit_more);
480 if (send_doorbell)
481 mlx5e_notify_hw(wq, sq->pc, sq->uar_map, cseg);
482}
483
484static void
485mlx5e_sq_xmit_wqe(struct mlx5e_txqsq *sq, struct sk_buff *skb,
486 const struct mlx5e_tx_attr *attr, const struct mlx5e_tx_wqe_attr *wqe_attr,
487 struct mlx5e_tx_wqe *wqe, u16 pi, bool xmit_more)
488{
489 struct mlx5_wqe_ctrl_seg *cseg;
490 struct mlx5_wqe_eth_seg *eseg;
491 struct mlx5_wqe_data_seg *dseg;
492 struct mlx5e_tx_wqe_info *wi;
493
494 struct mlx5e_sq_stats *stats = sq->stats;
495 int num_dma;
496
497 stats->xmit_more += xmit_more;
498
499
500 wi = &sq->db.wqe_info[pi];
501 cseg = &wqe->ctrl;
502 eseg = &wqe->eth;
503 dseg = wqe->data;
504
505 eseg->mss = attr->mss;
506
507 if (attr->ihs) {
508 if (skb_vlan_tag_present(skb)) {
509 eseg->inline_hdr.sz |= cpu_to_be16(attr->ihs + VLAN_HLEN);
510 mlx5e_insert_vlan(eseg->inline_hdr.start, skb, attr->ihs);
511 stats->added_vlan_packets++;
512 } else {
513 eseg->inline_hdr.sz |= cpu_to_be16(attr->ihs);
514 memcpy(eseg->inline_hdr.start, skb->data, attr->ihs);
515 }
516 dseg += wqe_attr->ds_cnt_inl;
517 } else if (skb_vlan_tag_present(skb)) {
518 eseg->insert.type = cpu_to_be16(MLX5_ETH_WQE_INSERT_VLAN);
519 if (skb->vlan_proto == cpu_to_be16(ETH_P_8021AD))
520 eseg->insert.type |= cpu_to_be16(MLX5_ETH_WQE_SVLAN);
521 eseg->insert.vlan_tci = cpu_to_be16(skb_vlan_tag_get(skb));
522 stats->added_vlan_packets++;
523 }
524
525 dseg += wqe_attr->ds_cnt_ids;
526 num_dma = mlx5e_txwqe_build_dsegs(sq, skb, skb->data + attr->ihs,
527 attr->headlen, dseg);
528 if (unlikely(num_dma < 0))
529 goto err_drop;
530
531 mlx5e_txwqe_complete(sq, skb, attr, wqe_attr, num_dma, wi, cseg, xmit_more);
532
533 return;
534
535err_drop:
536 stats->dropped++;
537 dev_kfree_skb_any(skb);
538}
539
540static bool mlx5e_tx_skb_supports_mpwqe(struct sk_buff *skb, struct mlx5e_tx_attr *attr)
541{
542 return !skb_is_nonlinear(skb) && !skb_vlan_tag_present(skb) && !attr->ihs &&
543 !attr->insz;
544}
545
546static bool mlx5e_tx_mpwqe_same_eseg(struct mlx5e_txqsq *sq, struct mlx5_wqe_eth_seg *eseg)
547{
548 struct mlx5e_tx_mpwqe *session = &sq->mpwqe;
549
550
551 return !memcmp(&session->wqe->eth, eseg, MLX5E_ACCEL_ESEG_LEN);
552}
553
554static void mlx5e_tx_mpwqe_session_start(struct mlx5e_txqsq *sq,
555 struct mlx5_wqe_eth_seg *eseg)
556{
557 struct mlx5e_tx_mpwqe *session = &sq->mpwqe;
558 struct mlx5e_tx_wqe *wqe;
559 u16 pi;
560
561 pi = mlx5e_txqsq_get_next_pi(sq, MLX5E_TX_MPW_MAX_WQEBBS);
562 wqe = MLX5E_TX_FETCH_WQE(sq, pi);
563 net_prefetchw(wqe->data);
564
565 *session = (struct mlx5e_tx_mpwqe) {
566 .wqe = wqe,
567 .bytes_count = 0,
568 .ds_count = MLX5E_TX_WQE_EMPTY_DS_COUNT,
569 .pkt_count = 0,
570 .inline_on = 0,
571 };
572
573 memcpy(&session->wqe->eth, eseg, MLX5E_ACCEL_ESEG_LEN);
574
575 sq->stats->mpwqe_blks++;
576}
577
578static bool mlx5e_tx_mpwqe_session_is_active(struct mlx5e_txqsq *sq)
579{
580 return sq->mpwqe.wqe;
581}
582
583static void mlx5e_tx_mpwqe_add_dseg(struct mlx5e_txqsq *sq, struct mlx5e_xmit_data *txd)
584{
585 struct mlx5e_tx_mpwqe *session = &sq->mpwqe;
586 struct mlx5_wqe_data_seg *dseg;
587
588 dseg = (struct mlx5_wqe_data_seg *)session->wqe + session->ds_count;
589
590 session->pkt_count++;
591 session->bytes_count += txd->len;
592
593 dseg->addr = cpu_to_be64(txd->dma_addr);
594 dseg->byte_count = cpu_to_be32(txd->len);
595 dseg->lkey = sq->mkey_be;
596 session->ds_count++;
597
598 sq->stats->mpwqe_pkts++;
599}
600
601static struct mlx5_wqe_ctrl_seg *mlx5e_tx_mpwqe_session_complete(struct mlx5e_txqsq *sq)
602{
603 struct mlx5e_tx_mpwqe *session = &sq->mpwqe;
604 u8 ds_count = session->ds_count;
605 struct mlx5_wqe_ctrl_seg *cseg;
606 struct mlx5e_tx_wqe_info *wi;
607 u16 pi;
608
609 cseg = &session->wqe->ctrl;
610 cseg->opmod_idx_opcode = cpu_to_be32((sq->pc << 8) | MLX5_OPCODE_ENHANCED_MPSW);
611 cseg->qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_count);
612
613 pi = mlx5_wq_cyc_ctr2ix(&sq->wq, sq->pc);
614 wi = &sq->db.wqe_info[pi];
615 *wi = (struct mlx5e_tx_wqe_info) {
616 .skb = NULL,
617 .num_bytes = session->bytes_count,
618 .num_wqebbs = DIV_ROUND_UP(ds_count, MLX5_SEND_WQEBB_NUM_DS),
619 .num_dma = session->pkt_count,
620 .num_fifo_pkts = session->pkt_count,
621 };
622
623 sq->pc += wi->num_wqebbs;
624
625 session->wqe = NULL;
626
627 mlx5e_tx_check_stop(sq);
628
629 return cseg;
630}
631
632static void
633mlx5e_sq_xmit_mpwqe(struct mlx5e_txqsq *sq, struct sk_buff *skb,
634 struct mlx5_wqe_eth_seg *eseg, bool xmit_more)
635{
636 struct mlx5_wqe_ctrl_seg *cseg;
637 struct mlx5e_xmit_data txd;
638
639 if (!mlx5e_tx_mpwqe_session_is_active(sq)) {
640 mlx5e_tx_mpwqe_session_start(sq, eseg);
641 } else if (!mlx5e_tx_mpwqe_same_eseg(sq, eseg)) {
642 mlx5e_tx_mpwqe_session_complete(sq);
643 mlx5e_tx_mpwqe_session_start(sq, eseg);
644 }
645
646 sq->stats->xmit_more += xmit_more;
647
648 txd.data = skb->data;
649 txd.len = skb->len;
650
651 txd.dma_addr = dma_map_single(sq->pdev, txd.data, txd.len, DMA_TO_DEVICE);
652 if (unlikely(dma_mapping_error(sq->pdev, txd.dma_addr)))
653 goto err_unmap;
654 mlx5e_dma_push(sq, txd.dma_addr, txd.len, MLX5E_DMA_MAP_SINGLE);
655
656 mlx5e_skb_fifo_push(&sq->db.skb_fifo, skb);
657
658 mlx5e_tx_mpwqe_add_dseg(sq, &txd);
659
660 mlx5e_tx_skb_update_hwts_flags(skb);
661
662 if (unlikely(mlx5e_tx_mpwqe_is_full(&sq->mpwqe))) {
663
664 cseg = mlx5e_tx_mpwqe_session_complete(sq);
665
666 if (__netdev_tx_sent_queue(sq->txq, txd.len, xmit_more))
667 mlx5e_notify_hw(&sq->wq, sq->pc, sq->uar_map, cseg);
668 } else if (__netdev_tx_sent_queue(sq->txq, txd.len, xmit_more)) {
669
670 cseg = mlx5e_tx_mpwqe_session_complete(sq);
671
672 mlx5e_notify_hw(&sq->wq, sq->pc, sq->uar_map, cseg);
673 }
674
675 return;
676
677err_unmap:
678 mlx5e_dma_unmap_wqe_err(sq, 1);
679 sq->stats->dropped++;
680 dev_kfree_skb_any(skb);
681}
682
683void mlx5e_tx_mpwqe_ensure_complete(struct mlx5e_txqsq *sq)
684{
685
686 if (unlikely(mlx5e_tx_mpwqe_session_is_active(sq)))
687 mlx5e_tx_mpwqe_session_complete(sq);
688}
689
690static void mlx5e_txwqe_build_eseg(struct mlx5e_priv *priv, struct mlx5e_txqsq *sq,
691 struct sk_buff *skb, struct mlx5e_accel_tx_state *accel,
692 struct mlx5_wqe_eth_seg *eseg, u16 ihs)
693{
694 mlx5e_accel_tx_eseg(priv, skb, eseg, ihs);
695 mlx5e_txwqe_build_eseg_csum(sq, skb, accel, eseg);
696}
697
698netdev_tx_t mlx5e_xmit(struct sk_buff *skb, struct net_device *dev)
699{
700 struct mlx5e_priv *priv = netdev_priv(dev);
701 struct mlx5e_accel_tx_state accel = {};
702 struct mlx5e_tx_wqe_attr wqe_attr;
703 struct mlx5e_tx_attr attr;
704 struct mlx5e_tx_wqe *wqe;
705 struct mlx5e_txqsq *sq;
706 u16 pi;
707
708 sq = priv->txq2sq[skb_get_queue_mapping(skb)];
709 if (unlikely(!sq)) {
710 dev_kfree_skb_any(skb);
711 return NETDEV_TX_OK;
712 }
713
714
715 if (unlikely(!mlx5e_accel_tx_begin(dev, sq, skb, &accel)))
716 return NETDEV_TX_OK;
717
718 mlx5e_sq_xmit_prepare(sq, skb, &accel, &attr);
719
720 if (test_bit(MLX5E_SQ_STATE_MPWQE, &sq->state)) {
721 if (mlx5e_tx_skb_supports_mpwqe(skb, &attr)) {
722 struct mlx5_wqe_eth_seg eseg = {};
723
724 mlx5e_txwqe_build_eseg(priv, sq, skb, &accel, &eseg, attr.ihs);
725 mlx5e_sq_xmit_mpwqe(sq, skb, &eseg, netdev_xmit_more());
726 return NETDEV_TX_OK;
727 }
728
729 mlx5e_tx_mpwqe_ensure_complete(sq);
730 }
731
732 mlx5e_sq_calc_wqe_attr(skb, &attr, &wqe_attr);
733 pi = mlx5e_txqsq_get_next_pi(sq, wqe_attr.num_wqebbs);
734 wqe = MLX5E_TX_FETCH_WQE(sq, pi);
735
736
737 mlx5e_accel_tx_finish(sq, wqe, &accel,
738 (struct mlx5_wqe_inline_seg *)(wqe->data + wqe_attr.ds_cnt_inl));
739 mlx5e_txwqe_build_eseg(priv, sq, skb, &accel, &wqe->eth, attr.ihs);
740 mlx5e_sq_xmit_wqe(sq, skb, &attr, &wqe_attr, wqe, pi, netdev_xmit_more());
741
742 return NETDEV_TX_OK;
743}
744
745void mlx5e_sq_xmit_simple(struct mlx5e_txqsq *sq, struct sk_buff *skb, bool xmit_more)
746{
747 struct mlx5e_tx_wqe_attr wqe_attr;
748 struct mlx5e_tx_attr attr;
749 struct mlx5e_tx_wqe *wqe;
750 u16 pi;
751
752 mlx5e_sq_xmit_prepare(sq, skb, NULL, &attr);
753 mlx5e_sq_calc_wqe_attr(skb, &attr, &wqe_attr);
754 pi = mlx5e_txqsq_get_next_pi(sq, wqe_attr.num_wqebbs);
755 wqe = MLX5E_TX_FETCH_WQE(sq, pi);
756 mlx5e_txwqe_build_eseg_csum(sq, skb, NULL, &wqe->eth);
757 mlx5e_sq_xmit_wqe(sq, skb, &attr, &wqe_attr, wqe, pi, xmit_more);
758}
759
760static void mlx5e_tx_wi_dma_unmap(struct mlx5e_txqsq *sq, struct mlx5e_tx_wqe_info *wi,
761 u32 *dma_fifo_cc)
762{
763 int i;
764
765 for (i = 0; i < wi->num_dma; i++) {
766 struct mlx5e_sq_dma *dma = mlx5e_dma_get(sq, (*dma_fifo_cc)++);
767
768 mlx5e_tx_dma_unmap(sq->pdev, dma);
769 }
770}
771
772static void mlx5e_consume_skb(struct mlx5e_txqsq *sq, struct sk_buff *skb,
773 struct mlx5_cqe64 *cqe, int napi_budget)
774{
775 if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
776 struct skb_shared_hwtstamps hwts = {};
777 u64 ts = get_cqe_ts(cqe);
778
779 hwts.hwtstamp = mlx5e_cqe_ts_to_ns(sq->ptp_cyc2time, sq->clock, ts);
780 if (sq->ptpsq)
781 mlx5e_skb_cb_hwtstamp_handler(skb, MLX5E_SKB_CB_CQE_HWTSTAMP,
782 hwts.hwtstamp, sq->ptpsq->cq_stats);
783 else
784 skb_tstamp_tx(skb, &hwts);
785 }
786
787 napi_consume_skb(skb, napi_budget);
788}
789
790static void mlx5e_tx_wi_consume_fifo_skbs(struct mlx5e_txqsq *sq, struct mlx5e_tx_wqe_info *wi,
791 struct mlx5_cqe64 *cqe, int napi_budget)
792{
793 int i;
794
795 for (i = 0; i < wi->num_fifo_pkts; i++) {
796 struct sk_buff *skb = mlx5e_skb_fifo_pop(&sq->db.skb_fifo);
797
798 mlx5e_consume_skb(sq, skb, cqe, napi_budget);
799 }
800}
801
802bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget)
803{
804 struct mlx5e_sq_stats *stats;
805 struct mlx5e_txqsq *sq;
806 struct mlx5_cqe64 *cqe;
807 u32 dma_fifo_cc;
808 u32 nbytes;
809 u16 npkts;
810 u16 sqcc;
811 int i;
812
813 sq = container_of(cq, struct mlx5e_txqsq, cq);
814
815 if (unlikely(!test_bit(MLX5E_SQ_STATE_ENABLED, &sq->state)))
816 return false;
817
818 cqe = mlx5_cqwq_get_cqe(&cq->wq);
819 if (!cqe)
820 return false;
821
822 stats = sq->stats;
823
824 npkts = 0;
825 nbytes = 0;
826
827
828
829
830 sqcc = sq->cc;
831
832
833 dma_fifo_cc = sq->dma_fifo_cc;
834
835 i = 0;
836 do {
837 struct mlx5e_tx_wqe_info *wi;
838 u16 wqe_counter;
839 bool last_wqe;
840 u16 ci;
841
842 mlx5_cqwq_pop(&cq->wq);
843
844 wqe_counter = be16_to_cpu(cqe->wqe_counter);
845
846 do {
847 last_wqe = (sqcc == wqe_counter);
848
849 ci = mlx5_wq_cyc_ctr2ix(&sq->wq, sqcc);
850 wi = &sq->db.wqe_info[ci];
851
852 sqcc += wi->num_wqebbs;
853
854 if (likely(wi->skb)) {
855 mlx5e_tx_wi_dma_unmap(sq, wi, &dma_fifo_cc);
856 mlx5e_consume_skb(sq, wi->skb, cqe, napi_budget);
857
858 npkts++;
859 nbytes += wi->num_bytes;
860 continue;
861 }
862
863 if (unlikely(mlx5e_ktls_tx_try_handle_resync_dump_comp(sq, wi,
864 &dma_fifo_cc)))
865 continue;
866
867 if (wi->num_fifo_pkts) {
868 mlx5e_tx_wi_dma_unmap(sq, wi, &dma_fifo_cc);
869 mlx5e_tx_wi_consume_fifo_skbs(sq, wi, cqe, napi_budget);
870
871 npkts += wi->num_fifo_pkts;
872 nbytes += wi->num_bytes;
873 }
874 } while (!last_wqe);
875
876 if (unlikely(get_cqe_opcode(cqe) == MLX5_CQE_REQ_ERR)) {
877 if (!test_and_set_bit(MLX5E_SQ_STATE_RECOVERING,
878 &sq->state)) {
879 mlx5e_dump_error_cqe(&sq->cq, sq->sqn,
880 (struct mlx5_err_cqe *)cqe);
881 mlx5_wq_cyc_wqe_dump(&sq->wq, ci, wi->num_wqebbs);
882 queue_work(cq->priv->wq, &sq->recover_work);
883 }
884 stats->cqe_err++;
885 }
886
887 } while ((++i < MLX5E_TX_CQ_POLL_BUDGET) && (cqe = mlx5_cqwq_get_cqe(&cq->wq)));
888
889 stats->cqes += i;
890
891 mlx5_cqwq_update_db_record(&cq->wq);
892
893
894 wmb();
895
896 sq->dma_fifo_cc = dma_fifo_cc;
897 sq->cc = sqcc;
898
899 netdev_tx_completed_queue(sq->txq, npkts, nbytes);
900
901 if (netif_tx_queue_stopped(sq->txq) &&
902 mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, sq->stop_room) &&
903 !test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state)) {
904 netif_tx_wake_queue(sq->txq);
905 stats->wake++;
906 }
907
908 return (i == MLX5E_TX_CQ_POLL_BUDGET);
909}
910
911static void mlx5e_tx_wi_kfree_fifo_skbs(struct mlx5e_txqsq *sq, struct mlx5e_tx_wqe_info *wi)
912{
913 int i;
914
915 for (i = 0; i < wi->num_fifo_pkts; i++)
916 dev_kfree_skb_any(mlx5e_skb_fifo_pop(&sq->db.skb_fifo));
917}
918
919void mlx5e_free_txqsq_descs(struct mlx5e_txqsq *sq)
920{
921 struct mlx5e_tx_wqe_info *wi;
922 u32 dma_fifo_cc, nbytes = 0;
923 u16 ci, sqcc, npkts = 0;
924
925 sqcc = sq->cc;
926 dma_fifo_cc = sq->dma_fifo_cc;
927
928 while (sqcc != sq->pc) {
929 ci = mlx5_wq_cyc_ctr2ix(&sq->wq, sqcc);
930 wi = &sq->db.wqe_info[ci];
931
932 sqcc += wi->num_wqebbs;
933
934 if (likely(wi->skb)) {
935 mlx5e_tx_wi_dma_unmap(sq, wi, &dma_fifo_cc);
936 dev_kfree_skb_any(wi->skb);
937
938 npkts++;
939 nbytes += wi->num_bytes;
940 continue;
941 }
942
943 if (unlikely(mlx5e_ktls_tx_try_handle_resync_dump_comp(sq, wi, &dma_fifo_cc)))
944 continue;
945
946 if (wi->num_fifo_pkts) {
947 mlx5e_tx_wi_dma_unmap(sq, wi, &dma_fifo_cc);
948 mlx5e_tx_wi_kfree_fifo_skbs(sq, wi);
949
950 npkts += wi->num_fifo_pkts;
951 nbytes += wi->num_bytes;
952 }
953 }
954
955 sq->dma_fifo_cc = dma_fifo_cc;
956 sq->cc = sqcc;
957
958 netdev_tx_completed_queue(sq->txq, npkts, nbytes);
959}
960
961#ifdef CONFIG_MLX5_CORE_IPOIB
962static inline void
963mlx5i_txwqe_build_datagram(struct mlx5_av *av, u32 dqpn, u32 dqkey,
964 struct mlx5_wqe_datagram_seg *dseg)
965{
966 memcpy(&dseg->av, av, sizeof(struct mlx5_av));
967 dseg->av.dqp_dct = cpu_to_be32(dqpn | MLX5_EXTENDED_UD_AV);
968 dseg->av.key.qkey.qkey = cpu_to_be32(dqkey);
969}
970
971static void mlx5i_sq_calc_wqe_attr(struct sk_buff *skb,
972 const struct mlx5e_tx_attr *attr,
973 struct mlx5e_tx_wqe_attr *wqe_attr)
974{
975 u16 ds_cnt = sizeof(struct mlx5i_tx_wqe) / MLX5_SEND_WQE_DS;
976 u16 ds_cnt_inl = 0;
977
978 ds_cnt += !!attr->headlen + skb_shinfo(skb)->nr_frags;
979
980 if (attr->ihs) {
981 u16 inl = attr->ihs - INL_HDR_START_SZ;
982
983 ds_cnt_inl = DIV_ROUND_UP(inl, MLX5_SEND_WQE_DS);
984 ds_cnt += ds_cnt_inl;
985 }
986
987 *wqe_attr = (struct mlx5e_tx_wqe_attr) {
988 .ds_cnt = ds_cnt,
989 .ds_cnt_inl = ds_cnt_inl,
990 .num_wqebbs = DIV_ROUND_UP(ds_cnt, MLX5_SEND_WQEBB_NUM_DS),
991 };
992}
993
994void mlx5i_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb,
995 struct mlx5_av *av, u32 dqpn, u32 dqkey, bool xmit_more)
996{
997 struct mlx5e_tx_wqe_attr wqe_attr;
998 struct mlx5e_tx_attr attr;
999 struct mlx5i_tx_wqe *wqe;
1000
1001 struct mlx5_wqe_datagram_seg *datagram;
1002 struct mlx5_wqe_ctrl_seg *cseg;
1003 struct mlx5_wqe_eth_seg *eseg;
1004 struct mlx5_wqe_data_seg *dseg;
1005 struct mlx5e_tx_wqe_info *wi;
1006
1007 struct mlx5e_sq_stats *stats = sq->stats;
1008 int num_dma;
1009 u16 pi;
1010
1011 mlx5e_sq_xmit_prepare(sq, skb, NULL, &attr);
1012 mlx5i_sq_calc_wqe_attr(skb, &attr, &wqe_attr);
1013
1014 pi = mlx5e_txqsq_get_next_pi(sq, wqe_attr.num_wqebbs);
1015 wqe = MLX5I_SQ_FETCH_WQE(sq, pi);
1016
1017 stats->xmit_more += xmit_more;
1018
1019
1020 wi = &sq->db.wqe_info[pi];
1021 cseg = &wqe->ctrl;
1022 datagram = &wqe->datagram;
1023 eseg = &wqe->eth;
1024 dseg = wqe->data;
1025
1026 mlx5i_txwqe_build_datagram(av, dqpn, dqkey, datagram);
1027
1028 mlx5e_txwqe_build_eseg_csum(sq, skb, NULL, eseg);
1029
1030 eseg->mss = attr.mss;
1031
1032 if (attr.ihs) {
1033 memcpy(eseg->inline_hdr.start, skb->data, attr.ihs);
1034 eseg->inline_hdr.sz = cpu_to_be16(attr.ihs);
1035 dseg += wqe_attr.ds_cnt_inl;
1036 }
1037
1038 num_dma = mlx5e_txwqe_build_dsegs(sq, skb, skb->data + attr.ihs,
1039 attr.headlen, dseg);
1040 if (unlikely(num_dma < 0))
1041 goto err_drop;
1042
1043 mlx5e_txwqe_complete(sq, skb, &attr, &wqe_attr, num_dma, wi, cseg, xmit_more);
1044
1045 return;
1046
1047err_drop:
1048 stats->dropped++;
1049 dev_kfree_skb_any(skb);
1050}
1051#endif
1052