1
2
3
4#include "tir.h"
5#include "params.h"
6#include <linux/mlx5/transobj.h>
7
8#define MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ (64 * 1024)
9
10
11#define MLX5E_TIR_CMD_IN_SZ_DW ( \
12 MLX5_ST_SZ_DW(create_tir_in) > MLX5_ST_SZ_DW(modify_tir_in) ? \
13 MLX5_ST_SZ_DW(create_tir_in) : MLX5_ST_SZ_DW(modify_tir_in) \
14)
15
16struct mlx5e_tir_builder {
17 u32 in[MLX5E_TIR_CMD_IN_SZ_DW];
18 bool modify;
19};
20
21struct mlx5e_tir_builder *mlx5e_tir_builder_alloc(bool modify)
22{
23 struct mlx5e_tir_builder *builder;
24
25 builder = kvzalloc(sizeof(*builder), GFP_KERNEL);
26 builder->modify = modify;
27
28 return builder;
29}
30
31void mlx5e_tir_builder_free(struct mlx5e_tir_builder *builder)
32{
33 kvfree(builder);
34}
35
36void mlx5e_tir_builder_clear(struct mlx5e_tir_builder *builder)
37{
38 memset(builder->in, 0, sizeof(builder->in));
39}
40
41static void *mlx5e_tir_builder_get_tirc(struct mlx5e_tir_builder *builder)
42{
43 if (builder->modify)
44 return MLX5_ADDR_OF(modify_tir_in, builder->in, ctx);
45 return MLX5_ADDR_OF(create_tir_in, builder->in, ctx);
46}
47
48void mlx5e_tir_builder_build_inline(struct mlx5e_tir_builder *builder, u32 tdn, u32 rqn)
49{
50 void *tirc = mlx5e_tir_builder_get_tirc(builder);
51
52 WARN_ON(builder->modify);
53
54 MLX5_SET(tirc, tirc, transport_domain, tdn);
55 MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_DIRECT);
56 MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_NONE);
57 MLX5_SET(tirc, tirc, inline_rqn, rqn);
58}
59
60void mlx5e_tir_builder_build_rqt(struct mlx5e_tir_builder *builder, u32 tdn,
61 u32 rqtn, bool inner_ft_support)
62{
63 void *tirc = mlx5e_tir_builder_get_tirc(builder);
64
65 WARN_ON(builder->modify);
66
67 MLX5_SET(tirc, tirc, transport_domain, tdn);
68 MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
69 MLX5_SET(tirc, tirc, indirect_table, rqtn);
70 MLX5_SET(tirc, tirc, tunneled_offload_en, inner_ft_support);
71}
72
73void mlx5e_tir_builder_build_lro(struct mlx5e_tir_builder *builder,
74 const struct mlx5e_lro_param *lro_param)
75{
76 void *tirc = mlx5e_tir_builder_get_tirc(builder);
77 const unsigned int rough_max_l2_l3_hdr_sz = 256;
78
79 if (builder->modify)
80 MLX5_SET(modify_tir_in, builder->in, bitmask.lro, 1);
81
82 if (!lro_param->enabled)
83 return;
84
85 MLX5_SET(tirc, tirc, lro_enable_mask,
86 MLX5_TIRC_LRO_ENABLE_MASK_IPV4_LRO |
87 MLX5_TIRC_LRO_ENABLE_MASK_IPV6_LRO);
88 MLX5_SET(tirc, tirc, lro_max_ip_payload_size,
89 (MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ - rough_max_l2_l3_hdr_sz) >> 8);
90 MLX5_SET(tirc, tirc, lro_timeout_period_usecs, lro_param->timeout);
91}
92
93static int mlx5e_hfunc_to_hw(u8 hfunc)
94{
95 switch (hfunc) {
96 case ETH_RSS_HASH_TOP:
97 return MLX5_RX_HASH_FN_TOEPLITZ;
98 case ETH_RSS_HASH_XOR:
99 return MLX5_RX_HASH_FN_INVERTED_XOR8;
100 default:
101 return MLX5_RX_HASH_FN_NONE;
102 }
103}
104
105void mlx5e_tir_builder_build_rss(struct mlx5e_tir_builder *builder,
106 const struct mlx5e_rss_params_hash *rss_hash,
107 const struct mlx5e_rss_params_traffic_type *rss_tt,
108 bool inner)
109{
110 void *tirc = mlx5e_tir_builder_get_tirc(builder);
111 void *hfso;
112
113 if (builder->modify)
114 MLX5_SET(modify_tir_in, builder->in, bitmask.hash, 1);
115
116 MLX5_SET(tirc, tirc, rx_hash_fn, mlx5e_hfunc_to_hw(rss_hash->hfunc));
117 if (rss_hash->hfunc == ETH_RSS_HASH_TOP) {
118 const size_t len = MLX5_FLD_SZ_BYTES(tirc, rx_hash_toeplitz_key);
119 void *rss_key = MLX5_ADDR_OF(tirc, tirc, rx_hash_toeplitz_key);
120
121 MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
122 memcpy(rss_key, rss_hash->toeplitz_hash_key, len);
123 }
124
125 if (inner)
126 hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_inner);
127 else
128 hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);
129 MLX5_SET(rx_hash_field_select, hfso, l3_prot_type, rss_tt->l3_prot_type);
130 MLX5_SET(rx_hash_field_select, hfso, l4_prot_type, rss_tt->l4_prot_type);
131 MLX5_SET(rx_hash_field_select, hfso, selected_fields, rss_tt->rx_hash_fields);
132}
133
134void mlx5e_tir_builder_build_direct(struct mlx5e_tir_builder *builder)
135{
136 void *tirc = mlx5e_tir_builder_get_tirc(builder);
137
138 WARN_ON(builder->modify);
139
140 MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_INVERTED_XOR8);
141}
142
143void mlx5e_tir_builder_build_tls(struct mlx5e_tir_builder *builder)
144{
145 void *tirc = mlx5e_tir_builder_get_tirc(builder);
146
147 WARN_ON(builder->modify);
148
149 MLX5_SET(tirc, tirc, tls_en, 1);
150 MLX5_SET(tirc, tirc, self_lb_block,
151 MLX5_TIRC_SELF_LB_BLOCK_BLOCK_UNICAST |
152 MLX5_TIRC_SELF_LB_BLOCK_BLOCK_MULTICAST);
153}
154
155int mlx5e_tir_init(struct mlx5e_tir *tir, struct mlx5e_tir_builder *builder,
156 struct mlx5_core_dev *mdev, bool reg)
157{
158 int err;
159
160 tir->mdev = mdev;
161
162 err = mlx5_core_create_tir(tir->mdev, builder->in, &tir->tirn);
163 if (err)
164 return err;
165
166 if (reg) {
167 struct mlx5e_hw_objs *res = &tir->mdev->mlx5e_res.hw_objs;
168
169 mutex_lock(&res->td.list_lock);
170 list_add(&tir->list, &res->td.tirs_list);
171 mutex_unlock(&res->td.list_lock);
172 } else {
173 INIT_LIST_HEAD(&tir->list);
174 }
175
176 return 0;
177}
178
179void mlx5e_tir_destroy(struct mlx5e_tir *tir)
180{
181 struct mlx5e_hw_objs *res = &tir->mdev->mlx5e_res.hw_objs;
182
183
184
185
186
187
188 if (!list_empty(&tir->list)) {
189 mutex_lock(&res->td.list_lock);
190 list_del(&tir->list);
191 mutex_unlock(&res->td.list_lock);
192 }
193
194 mlx5_core_destroy_tir(tir->mdev, tir->tirn);
195}
196
197int mlx5e_tir_modify(struct mlx5e_tir *tir, struct mlx5e_tir_builder *builder)
198{
199 return mlx5_core_modify_tir(tir->mdev, tir->tirn, builder->in);
200}
201