1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 /* Copyright (c) 2019 Mellanox Technologies. */ 3 4 #include "tx.h" 5 #include "pool.h" 6 #include "en/xdp.h" 7 #include "en/params.h" 8 #include <net/xdp_sock_drv.h> 9 10 int mlx5e_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags) 11 { 12 struct mlx5e_priv *priv = netdev_priv(dev); 13 struct mlx5e_params *params = &priv->channels.params; 14 struct mlx5e_channel *c; 15 u16 ix; 16 17 if (unlikely(!mlx5e_xdp_is_active(priv))) 18 return -ENETDOWN; 19 20 if (unlikely(!mlx5e_qid_get_ch_if_in_group(params, qid, MLX5E_RQ_GROUP_XSK, &ix))) 21 return -EINVAL; 22 23 c = priv->channels.c[ix]; 24 25 if (unlikely(!test_bit(MLX5E_CHANNEL_STATE_XSK, c->state))) 26 return -EINVAL; 27 28 if (!napi_if_scheduled_mark_missed(&c->napi)) { 29 /* To avoid WQE overrun, don't post a NOP if async_icosq is not 30 * active and not polled by NAPI. Return 0, because the upcoming 31 * activate will trigger the IRQ for us. 32 */ 33 if (unlikely(!test_bit(MLX5E_SQ_STATE_ENABLED, &c->async_icosq.state))) 34 return 0; 35 36 if (test_and_set_bit(MLX5E_SQ_STATE_PENDING_XSK_TX, &c->async_icosq.state)) 37 return 0; 38 39 spin_lock_bh(&c->async_icosq_lock); 40 mlx5e_trigger_irq(&c->async_icosq); 41 spin_unlock_bh(&c->async_icosq_lock); 42 } 43 44 return 0; 45 } 46 47 /* When TX fails (because of the size of the packet), we need to get completions 48 * in order, so post a NOP to get a CQE. Since AF_XDP doesn't distinguish 49 * between successful TX and errors, handling in mlx5e_poll_xdpsq_cq is the 50 * same. 51 */ 52 static void mlx5e_xsk_tx_post_err(struct mlx5e_xdpsq *sq, 53 struct mlx5e_xdp_info *xdpi) 54 { 55 u16 pi = mlx5_wq_cyc_ctr2ix(&sq->wq, sq->pc); 56 struct mlx5e_xdp_wqe_info *wi = &sq->db.wqe_info[pi]; 57 struct mlx5e_tx_wqe *nopwqe; 58 59 wi->num_wqebbs = 1; 60 wi->num_pkts = 1; 61 62 nopwqe = mlx5e_post_nop(&sq->wq, sq->sqn, &sq->pc); 63 mlx5e_xdpi_fifo_push(&sq->db.xdpi_fifo, xdpi); 64 sq->doorbell_cseg = &nopwqe->ctrl; 65 } 66 67 bool mlx5e_xsk_tx(struct mlx5e_xdpsq *sq, unsigned int budget) 68 { 69 struct xsk_buff_pool *pool = sq->xsk_pool; 70 struct mlx5e_xmit_data xdptxd; 71 struct mlx5e_xdp_info xdpi; 72 bool work_done = true; 73 bool flush = false; 74 75 xdpi.mode = MLX5E_XDP_XMIT_MODE_XSK; 76 77 for (; budget; budget--) { 78 int check_result = INDIRECT_CALL_2(sq->xmit_xdp_frame_check, 79 mlx5e_xmit_xdp_frame_check_mpwqe, 80 mlx5e_xmit_xdp_frame_check, 81 sq); 82 struct xdp_desc desc; 83 bool ret; 84 85 if (unlikely(check_result < 0)) { 86 work_done = false; 87 break; 88 } 89 90 if (!xsk_tx_peek_desc(pool, &desc)) { 91 /* TX will get stuck until something wakes it up by 92 * triggering NAPI. Currently it's expected that the 93 * application calls sendto() if there are consumed, but 94 * not completed frames. 95 */ 96 break; 97 } 98 99 xdptxd.dma_addr = xsk_buff_raw_get_dma(pool, desc.addr); 100 xdptxd.data = xsk_buff_raw_get_data(pool, desc.addr); 101 xdptxd.len = desc.len; 102 103 xsk_buff_raw_dma_sync_for_device(pool, xdptxd.dma_addr, xdptxd.len); 104 105 ret = INDIRECT_CALL_2(sq->xmit_xdp_frame, mlx5e_xmit_xdp_frame_mpwqe, 106 mlx5e_xmit_xdp_frame, sq, &xdptxd, NULL, 107 check_result); 108 if (unlikely(!ret)) { 109 if (sq->mpwqe.wqe) 110 mlx5e_xdp_mpwqe_complete(sq); 111 112 mlx5e_xsk_tx_post_err(sq, &xdpi); 113 } else { 114 mlx5e_xdpi_fifo_push(&sq->db.xdpi_fifo, &xdpi); 115 } 116 117 flush = true; 118 } 119 120 if (flush) { 121 if (sq->mpwqe.wqe) 122 mlx5e_xdp_mpwqe_complete(sq); 123 mlx5e_xmit_xdp_doorbell(sq); 124 125 xsk_tx_release(pool); 126 } 127 128 return !(budget && work_done); 129 } 130