0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 #ifndef __MLX5_EN_XDP_H__
0033 #define __MLX5_EN_XDP_H__
0034
0035 #include <linux/indirect_call_wrapper.h>
0036
0037 #include "en.h"
0038 #include "en/txrx.h"
0039
0040 #define MLX5E_XDP_MIN_INLINE (ETH_HLEN + VLAN_HLEN)
0041
0042 #define MLX5E_XDP_INLINE_WQE_MAX_DS_CNT 16
0043 #define MLX5E_XDP_INLINE_WQE_SZ_THRSD \
0044 (MLX5E_XDP_INLINE_WQE_MAX_DS_CNT * MLX5_SEND_WQE_DS - \
0045 sizeof(struct mlx5_wqe_inline_seg))
0046
0047 struct mlx5e_xsk_param;
0048 int mlx5e_xdp_max_mtu(struct mlx5e_params *params, struct mlx5e_xsk_param *xsk);
0049 bool mlx5e_xdp_handle(struct mlx5e_rq *rq, struct page *page,
0050 struct bpf_prog *prog, struct xdp_buff *xdp);
0051 void mlx5e_xdp_mpwqe_complete(struct mlx5e_xdpsq *sq);
0052 bool mlx5e_poll_xdpsq_cq(struct mlx5e_cq *cq);
0053 void mlx5e_free_xdpsq_descs(struct mlx5e_xdpsq *sq);
0054 void mlx5e_set_xmit_fp(struct mlx5e_xdpsq *sq, bool is_mpw);
0055 void mlx5e_xdp_rx_poll_complete(struct mlx5e_rq *rq);
0056 int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
0057 u32 flags);
0058
0059 INDIRECT_CALLABLE_DECLARE(bool mlx5e_xmit_xdp_frame_mpwqe(struct mlx5e_xdpsq *sq,
0060 struct mlx5e_xmit_data *xdptxd,
0061 struct skb_shared_info *sinfo,
0062 int check_result));
0063 INDIRECT_CALLABLE_DECLARE(bool mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq,
0064 struct mlx5e_xmit_data *xdptxd,
0065 struct skb_shared_info *sinfo,
0066 int check_result));
0067 INDIRECT_CALLABLE_DECLARE(int mlx5e_xmit_xdp_frame_check_mpwqe(struct mlx5e_xdpsq *sq));
0068 INDIRECT_CALLABLE_DECLARE(int mlx5e_xmit_xdp_frame_check(struct mlx5e_xdpsq *sq));
0069
0070 static inline void mlx5e_xdp_tx_enable(struct mlx5e_priv *priv)
0071 {
0072 set_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
0073
0074 if (priv->channels.params.xdp_prog)
0075 set_bit(MLX5E_STATE_XDP_ACTIVE, &priv->state);
0076 }
0077
0078 static inline void mlx5e_xdp_tx_disable(struct mlx5e_priv *priv)
0079 {
0080 if (priv->channels.params.xdp_prog)
0081 clear_bit(MLX5E_STATE_XDP_ACTIVE, &priv->state);
0082
0083 clear_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
0084
0085 synchronize_net();
0086 }
0087
0088 static inline bool mlx5e_xdp_tx_is_enabled(struct mlx5e_priv *priv)
0089 {
0090 return test_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
0091 }
0092
0093 static inline bool mlx5e_xdp_is_active(struct mlx5e_priv *priv)
0094 {
0095 return test_bit(MLX5E_STATE_XDP_ACTIVE, &priv->state);
0096 }
0097
0098 static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_xdpsq *sq)
0099 {
0100 if (sq->doorbell_cseg) {
0101 mlx5e_notify_hw(&sq->wq, sq->pc, sq->uar_map, sq->doorbell_cseg);
0102 sq->doorbell_cseg = NULL;
0103 }
0104 }
0105
0106
0107
0108
0109 static inline bool mlx5e_xdp_get_inline_state(struct mlx5e_xdpsq *sq, bool cur)
0110 {
0111 u16 outstanding = sq->xdpi_fifo_pc - sq->xdpi_fifo_cc;
0112
0113 #define MLX5E_XDP_INLINE_WATERMARK_LOW 10
0114 #define MLX5E_XDP_INLINE_WATERMARK_HIGH 128
0115
0116 if (cur && outstanding <= MLX5E_XDP_INLINE_WATERMARK_LOW)
0117 return false;
0118
0119 if (!cur && outstanding >= MLX5E_XDP_INLINE_WATERMARK_HIGH)
0120 return true;
0121
0122 return cur;
0123 }
0124
0125 static inline bool mlx5e_xdp_mpqwe_is_full(struct mlx5e_tx_mpwqe *session, u8 max_sq_mpw_wqebbs)
0126 {
0127 if (session->inline_on)
0128 return session->ds_count + MLX5E_XDP_INLINE_WQE_MAX_DS_CNT >
0129 max_sq_mpw_wqebbs * MLX5_SEND_WQEBB_NUM_DS;
0130
0131 return mlx5e_tx_mpwqe_is_full(session, max_sq_mpw_wqebbs);
0132 }
0133
0134 struct mlx5e_xdp_wqe_info {
0135 u8 num_wqebbs;
0136 u8 num_pkts;
0137 };
0138
0139 static inline void
0140 mlx5e_xdp_mpwqe_add_dseg(struct mlx5e_xdpsq *sq,
0141 struct mlx5e_xmit_data *xdptxd,
0142 struct mlx5e_xdpsq_stats *stats)
0143 {
0144 struct mlx5e_tx_mpwqe *session = &sq->mpwqe;
0145 struct mlx5_wqe_data_seg *dseg =
0146 (struct mlx5_wqe_data_seg *)session->wqe + session->ds_count;
0147 u32 dma_len = xdptxd->len;
0148
0149 session->pkt_count++;
0150 session->bytes_count += dma_len;
0151
0152 if (session->inline_on && dma_len <= MLX5E_XDP_INLINE_WQE_SZ_THRSD) {
0153 struct mlx5_wqe_inline_seg *inline_dseg =
0154 (struct mlx5_wqe_inline_seg *)dseg;
0155 u16 ds_len = sizeof(*inline_dseg) + dma_len;
0156 u16 ds_cnt = DIV_ROUND_UP(ds_len, MLX5_SEND_WQE_DS);
0157
0158 inline_dseg->byte_count = cpu_to_be32(dma_len | MLX5_INLINE_SEG);
0159 memcpy(inline_dseg->data, xdptxd->data, dma_len);
0160
0161 session->ds_count += ds_cnt;
0162 stats->inlnw++;
0163 return;
0164 }
0165
0166 dseg->addr = cpu_to_be64(xdptxd->dma_addr);
0167 dseg->byte_count = cpu_to_be32(dma_len);
0168 dseg->lkey = sq->mkey_be;
0169 session->ds_count++;
0170 }
0171
0172 static inline void
0173 mlx5e_xdpi_fifo_push(struct mlx5e_xdp_info_fifo *fifo,
0174 struct mlx5e_xdp_info *xi)
0175 {
0176 u32 i = (*fifo->pc)++ & fifo->mask;
0177
0178 fifo->xi[i] = *xi;
0179 }
0180
0181 static inline struct mlx5e_xdp_info
0182 mlx5e_xdpi_fifo_pop(struct mlx5e_xdp_info_fifo *fifo)
0183 {
0184 return fifo->xi[(*fifo->cc)++ & fifo->mask];
0185 }
0186 #endif