1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2019 Mellanox Technologies. */
3 
4 #include "en/params.h"
5 
6 u32 mlx5e_rx_get_linear_frag_sz(struct mlx5e_params *params)
7 {
8 	u16 hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu);
9 	u16 linear_rq_headroom = params->xdp_prog ?
10 		XDP_PACKET_HEADROOM : MLX5_RX_HEADROOM;
11 	u32 frag_sz;
12 
13 	linear_rq_headroom += NET_IP_ALIGN;
14 
15 	frag_sz = MLX5_SKB_FRAG_SZ(linear_rq_headroom + hw_mtu);
16 
17 	if (params->xdp_prog && frag_sz < PAGE_SIZE)
18 		frag_sz = PAGE_SIZE;
19 
20 	return frag_sz;
21 }
22 
23 u8 mlx5e_mpwqe_log_pkts_per_wqe(struct mlx5e_params *params)
24 {
25 	u32 linear_frag_sz = mlx5e_rx_get_linear_frag_sz(params);
26 
27 	return MLX5_MPWRQ_LOG_WQE_SZ - order_base_2(linear_frag_sz);
28 }
29 
30 bool mlx5e_rx_is_linear_skb(struct mlx5e_params *params)
31 {
32 	u32 frag_sz = mlx5e_rx_get_linear_frag_sz(params);
33 
34 	return !params->lro_en && frag_sz <= PAGE_SIZE;
35 }
36 
37 #define MLX5_MAX_MPWQE_LOG_WQE_STRIDE_SZ ((BIT(__mlx5_bit_sz(wq, log_wqe_stride_size)) - 1) + \
38 					  MLX5_MPWQE_LOG_STRIDE_SZ_BASE)
39 bool mlx5e_rx_mpwqe_is_linear_skb(struct mlx5_core_dev *mdev,
40 				  struct mlx5e_params *params)
41 {
42 	u32 frag_sz = mlx5e_rx_get_linear_frag_sz(params);
43 	s8 signed_log_num_strides_param;
44 	u8 log_num_strides;
45 
46 	if (!mlx5e_rx_is_linear_skb(params))
47 		return false;
48 
49 	if (order_base_2(frag_sz) > MLX5_MAX_MPWQE_LOG_WQE_STRIDE_SZ)
50 		return false;
51 
52 	if (MLX5_CAP_GEN(mdev, ext_stride_num_range))
53 		return true;
54 
55 	log_num_strides = MLX5_MPWRQ_LOG_WQE_SZ - order_base_2(frag_sz);
56 	signed_log_num_strides_param =
57 		(s8)log_num_strides - MLX5_MPWQE_LOG_NUM_STRIDES_BASE;
58 
59 	return signed_log_num_strides_param >= 0;
60 }
61 
62 u8 mlx5e_mpwqe_get_log_rq_size(struct mlx5e_params *params)
63 {
64 	u8 log_pkts_per_wqe = mlx5e_mpwqe_log_pkts_per_wqe(params);
65 
66 	/* Numbers are unsigned, don't subtract to avoid underflow. */
67 	if (params->log_rq_mtu_frames <
68 	    log_pkts_per_wqe + MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE_MPW)
69 		return MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE_MPW;
70 
71 	return params->log_rq_mtu_frames - log_pkts_per_wqe;
72 }
73 
74 u8 mlx5e_mpwqe_get_log_stride_size(struct mlx5_core_dev *mdev,
75 				   struct mlx5e_params *params)
76 {
77 	if (mlx5e_rx_mpwqe_is_linear_skb(mdev, params))
78 		return order_base_2(mlx5e_rx_get_linear_frag_sz(params));
79 
80 	return MLX5_MPWRQ_DEF_LOG_STRIDE_SZ(mdev);
81 }
82 
83 u8 mlx5e_mpwqe_get_log_num_strides(struct mlx5_core_dev *mdev,
84 				   struct mlx5e_params *params)
85 {
86 	return MLX5_MPWRQ_LOG_WQE_SZ -
87 		mlx5e_mpwqe_get_log_stride_size(mdev, params);
88 }
89 
90 u16 mlx5e_get_rq_headroom(struct mlx5_core_dev *mdev,
91 			  struct mlx5e_params *params)
92 {
93 	u16 linear_rq_headroom = params->xdp_prog ?
94 		XDP_PACKET_HEADROOM : MLX5_RX_HEADROOM;
95 	bool is_linear_skb;
96 
97 	linear_rq_headroom += NET_IP_ALIGN;
98 
99 	is_linear_skb = (params->rq_wq_type == MLX5_WQ_TYPE_CYCLIC) ?
100 		mlx5e_rx_is_linear_skb(params) :
101 		mlx5e_rx_mpwqe_is_linear_skb(mdev, params);
102 
103 	return is_linear_skb ? linear_rq_headroom : 0;
104 }
105