.. | .. |
---|
32 | 32 | #ifndef __MLX5_EN_XDP_H__ |
---|
33 | 33 | #define __MLX5_EN_XDP_H__ |
---|
34 | 34 | |
---|
| 35 | +#include <linux/indirect_call_wrapper.h> |
---|
| 36 | + |
---|
35 | 37 | #include "en.h" |
---|
| 38 | +#include "en/txrx.h" |
---|
36 | 39 | |
---|
37 | 40 | #define MLX5E_XDP_MIN_INLINE (ETH_HLEN + VLAN_HLEN) |
---|
38 | | -#define MLX5E_XDP_TX_DS_COUNT \ |
---|
39 | | - ((sizeof(struct mlx5e_tx_wqe) / MLX5_SEND_WQE_DS) + 1 /* SG DS */) |
---|
| 41 | +#define MLX5E_XDP_TX_DS_COUNT (MLX5E_TX_WQE_EMPTY_DS_COUNT + 1 /* SG DS */) |
---|
40 | 42 | |
---|
41 | | -int mlx5e_xdp_max_mtu(struct mlx5e_params *params); |
---|
| 43 | +#define MLX5E_XDP_INLINE_WQE_MAX_DS_CNT 16 |
---|
| 44 | +#define MLX5E_XDP_INLINE_WQE_SZ_THRSD \ |
---|
| 45 | + (MLX5E_XDP_INLINE_WQE_MAX_DS_CNT * MLX5_SEND_WQE_DS - \ |
---|
| 46 | + sizeof(struct mlx5_wqe_inline_seg)) |
---|
| 47 | + |
---|
| 48 | +struct mlx5e_xsk_param; |
---|
| 49 | +int mlx5e_xdp_max_mtu(struct mlx5e_params *params, struct mlx5e_xsk_param *xsk); |
---|
42 | 50 | bool mlx5e_xdp_handle(struct mlx5e_rq *rq, struct mlx5e_dma_info *di, |
---|
43 | | - void *va, u16 *rx_headroom, u32 *len); |
---|
| 51 | + u32 *len, struct xdp_buff *xdp); |
---|
| 52 | +void mlx5e_xdp_mpwqe_complete(struct mlx5e_xdpsq *sq); |
---|
44 | 53 | bool mlx5e_poll_xdpsq_cq(struct mlx5e_cq *cq); |
---|
45 | 54 | void mlx5e_free_xdpsq_descs(struct mlx5e_xdpsq *sq); |
---|
46 | | - |
---|
47 | | -bool mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xdp_info *xdpi); |
---|
| 55 | +void mlx5e_set_xmit_fp(struct mlx5e_xdpsq *sq, bool is_mpw); |
---|
| 56 | +void mlx5e_xdp_rx_poll_complete(struct mlx5e_rq *rq); |
---|
48 | 57 | int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames, |
---|
49 | 58 | u32 flags); |
---|
| 59 | + |
---|
| 60 | +INDIRECT_CALLABLE_DECLARE(bool mlx5e_xmit_xdp_frame_mpwqe(struct mlx5e_xdpsq *sq, |
---|
| 61 | + struct mlx5e_xmit_data *xdptxd, |
---|
| 62 | + struct mlx5e_xdp_info *xdpi, |
---|
| 63 | + int check_result)); |
---|
| 64 | +INDIRECT_CALLABLE_DECLARE(bool mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, |
---|
| 65 | + struct mlx5e_xmit_data *xdptxd, |
---|
| 66 | + struct mlx5e_xdp_info *xdpi, |
---|
| 67 | + int check_result)); |
---|
| 68 | +INDIRECT_CALLABLE_DECLARE(int mlx5e_xmit_xdp_frame_check_mpwqe(struct mlx5e_xdpsq *sq)); |
---|
| 69 | +INDIRECT_CALLABLE_DECLARE(int mlx5e_xmit_xdp_frame_check(struct mlx5e_xdpsq *sq)); |
---|
50 | 70 | |
---|
51 | 71 | static inline void mlx5e_xdp_tx_enable(struct mlx5e_priv *priv) |
---|
52 | 72 | { |
---|
53 | 73 | set_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state); |
---|
| 74 | + |
---|
| 75 | + if (priv->channels.params.xdp_prog) |
---|
| 76 | + set_bit(MLX5E_STATE_XDP_ACTIVE, &priv->state); |
---|
54 | 77 | } |
---|
55 | 78 | |
---|
56 | 79 | static inline void mlx5e_xdp_tx_disable(struct mlx5e_priv *priv) |
---|
57 | 80 | { |
---|
| 81 | + if (priv->channels.params.xdp_prog) |
---|
| 82 | + clear_bit(MLX5E_STATE_XDP_ACTIVE, &priv->state); |
---|
| 83 | + |
---|
58 | 84 | clear_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state); |
---|
59 | | - /* let other device's napi(s) see our new state */ |
---|
60 | | - synchronize_rcu(); |
---|
| 85 | + /* Let other device's napi(s) and XSK wakeups see our new state. */ |
---|
| 86 | + synchronize_net(); |
---|
61 | 87 | } |
---|
62 | 88 | |
---|
63 | 89 | static inline bool mlx5e_xdp_tx_is_enabled(struct mlx5e_priv *priv) |
---|
.. | .. |
---|
65 | 91 | return test_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state); |
---|
66 | 92 | } |
---|
67 | 93 | |
---|
68 | | -static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_xdpsq *sq) |
---|
| 94 | +static inline bool mlx5e_xdp_is_active(struct mlx5e_priv *priv) |
---|
69 | 95 | { |
---|
70 | | - struct mlx5_wq_cyc *wq = &sq->wq; |
---|
71 | | - struct mlx5e_tx_wqe *wqe; |
---|
72 | | - u16 pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc - 1); /* last pi */ |
---|
73 | | - |
---|
74 | | - wqe = mlx5_wq_cyc_get_wqe(wq, pi); |
---|
75 | | - |
---|
76 | | - mlx5e_notify_hw(wq, sq->pc, sq->uar_map, &wqe->ctrl); |
---|
| 96 | + return test_bit(MLX5E_STATE_XDP_ACTIVE, &priv->state); |
---|
77 | 97 | } |
---|
78 | 98 | |
---|
| 99 | +static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_xdpsq *sq) |
---|
| 100 | +{ |
---|
| 101 | + if (sq->doorbell_cseg) { |
---|
| 102 | + mlx5e_notify_hw(&sq->wq, sq->pc, sq->uar_map, sq->doorbell_cseg); |
---|
| 103 | + sq->doorbell_cseg = NULL; |
---|
| 104 | + } |
---|
| 105 | +} |
---|
| 106 | + |
---|
| 107 | +/* Enable inline WQEs to shift some load from a congested HCA (HW) to |
---|
| 108 | + * a less congested cpu (SW). |
---|
| 109 | + */ |
---|
| 110 | +static inline bool mlx5e_xdp_get_inline_state(struct mlx5e_xdpsq *sq, bool cur) |
---|
| 111 | +{ |
---|
| 112 | + u16 outstanding = sq->xdpi_fifo_pc - sq->xdpi_fifo_cc; |
---|
| 113 | + |
---|
| 114 | +#define MLX5E_XDP_INLINE_WATERMARK_LOW 10 |
---|
| 115 | +#define MLX5E_XDP_INLINE_WATERMARK_HIGH 128 |
---|
| 116 | + |
---|
| 117 | + if (cur && outstanding <= MLX5E_XDP_INLINE_WATERMARK_LOW) |
---|
| 118 | + return false; |
---|
| 119 | + |
---|
| 120 | + if (!cur && outstanding >= MLX5E_XDP_INLINE_WATERMARK_HIGH) |
---|
| 121 | + return true; |
---|
| 122 | + |
---|
| 123 | + return cur; |
---|
| 124 | +} |
---|
| 125 | + |
---|
| 126 | +static inline bool mlx5e_xdp_mpqwe_is_full(struct mlx5e_tx_mpwqe *session) |
---|
| 127 | +{ |
---|
| 128 | + if (session->inline_on) |
---|
| 129 | + return session->ds_count + MLX5E_XDP_INLINE_WQE_MAX_DS_CNT > |
---|
| 130 | + MLX5E_TX_MPW_MAX_NUM_DS; |
---|
| 131 | + return mlx5e_tx_mpwqe_is_full(session); |
---|
| 132 | +} |
---|
| 133 | + |
---|
| 134 | +struct mlx5e_xdp_wqe_info { |
---|
| 135 | + u8 num_wqebbs; |
---|
| 136 | + u8 num_pkts; |
---|
| 137 | +}; |
---|
| 138 | + |
---|
| 139 | +static inline void |
---|
| 140 | +mlx5e_xdp_mpwqe_add_dseg(struct mlx5e_xdpsq *sq, |
---|
| 141 | + struct mlx5e_xmit_data *xdptxd, |
---|
| 142 | + struct mlx5e_xdpsq_stats *stats) |
---|
| 143 | +{ |
---|
| 144 | + struct mlx5e_tx_mpwqe *session = &sq->mpwqe; |
---|
| 145 | + struct mlx5_wqe_data_seg *dseg = |
---|
| 146 | + (struct mlx5_wqe_data_seg *)session->wqe + session->ds_count; |
---|
| 147 | + u32 dma_len = xdptxd->len; |
---|
| 148 | + |
---|
| 149 | + session->pkt_count++; |
---|
| 150 | + session->bytes_count += dma_len; |
---|
| 151 | + |
---|
| 152 | + if (session->inline_on && dma_len <= MLX5E_XDP_INLINE_WQE_SZ_THRSD) { |
---|
| 153 | + struct mlx5_wqe_inline_seg *inline_dseg = |
---|
| 154 | + (struct mlx5_wqe_inline_seg *)dseg; |
---|
| 155 | + u16 ds_len = sizeof(*inline_dseg) + dma_len; |
---|
| 156 | + u16 ds_cnt = DIV_ROUND_UP(ds_len, MLX5_SEND_WQE_DS); |
---|
| 157 | + |
---|
| 158 | + inline_dseg->byte_count = cpu_to_be32(dma_len | MLX5_INLINE_SEG); |
---|
| 159 | + memcpy(inline_dseg->data, xdptxd->data, dma_len); |
---|
| 160 | + |
---|
| 161 | + session->ds_count += ds_cnt; |
---|
| 162 | + stats->inlnw++; |
---|
| 163 | + return; |
---|
| 164 | + } |
---|
| 165 | + |
---|
| 166 | + dseg->addr = cpu_to_be64(xdptxd->dma_addr); |
---|
| 167 | + dseg->byte_count = cpu_to_be32(dma_len); |
---|
| 168 | + dseg->lkey = sq->mkey_be; |
---|
| 169 | + session->ds_count++; |
---|
| 170 | +} |
---|
| 171 | + |
---|
| 172 | +static inline void |
---|
| 173 | +mlx5e_xdpi_fifo_push(struct mlx5e_xdp_info_fifo *fifo, |
---|
| 174 | + struct mlx5e_xdp_info *xi) |
---|
| 175 | +{ |
---|
| 176 | + u32 i = (*fifo->pc)++ & fifo->mask; |
---|
| 177 | + |
---|
| 178 | + fifo->xi[i] = *xi; |
---|
| 179 | +} |
---|
| 180 | + |
---|
| 181 | +static inline struct mlx5e_xdp_info |
---|
| 182 | +mlx5e_xdpi_fifo_pop(struct mlx5e_xdp_info_fifo *fifo) |
---|
| 183 | +{ |
---|
| 184 | + return fifo->xi[(*fifo->cc)++ & fifo->mask]; |
---|
| 185 | +} |
---|
79 | 186 | #endif |
---|