1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2/* Copyright (c) 2021, Mellanox Technologies inc. All rights reserved. */
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/* max() doesn't work inside square brackets. */
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 if (!builder)
27 return NULL;
28
29 builder->modify = modify;
30
31 return builder;
32}
33
34void mlx5e_tir_builder_free(struct mlx5e_tir_builder *builder)
35{
36 kvfree(addr: builder);
37}
38
39void mlx5e_tir_builder_clear(struct mlx5e_tir_builder *builder)
40{
41 memset(builder->in, 0, sizeof(builder->in));
42}
43
44static void *mlx5e_tir_builder_get_tirc(struct mlx5e_tir_builder *builder)
45{
46 if (builder->modify)
47 return MLX5_ADDR_OF(modify_tir_in, builder->in, ctx);
48 return MLX5_ADDR_OF(create_tir_in, builder->in, ctx);
49}
50
51void mlx5e_tir_builder_build_inline(struct mlx5e_tir_builder *builder, u32 tdn, u32 rqn)
52{
53 void *tirc = mlx5e_tir_builder_get_tirc(builder);
54
55 WARN_ON(builder->modify);
56
57 MLX5_SET(tirc, tirc, transport_domain, tdn);
58 MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_DIRECT);
59 MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_NONE);
60 MLX5_SET(tirc, tirc, inline_rqn, rqn);
61}
62
63void mlx5e_tir_builder_build_rqt(struct mlx5e_tir_builder *builder, u32 tdn,
64 u32 rqtn, bool inner_ft_support)
65{
66 void *tirc = mlx5e_tir_builder_get_tirc(builder);
67
68 WARN_ON(builder->modify);
69
70 MLX5_SET(tirc, tirc, transport_domain, tdn);
71 MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
72 MLX5_SET(tirc, tirc, indirect_table, rqtn);
73 MLX5_SET(tirc, tirc, tunneled_offload_en, inner_ft_support);
74}
75
76void mlx5e_tir_builder_build_packet_merge(struct mlx5e_tir_builder *builder,
77 const struct mlx5e_packet_merge_param *pkt_merge_param)
78{
79 void *tirc = mlx5e_tir_builder_get_tirc(builder);
80 const unsigned int rough_max_l2_l3_hdr_sz = 256;
81
82 if (builder->modify)
83 MLX5_SET(modify_tir_in, builder->in, bitmask.packet_merge, 1);
84
85 switch (pkt_merge_param->type) {
86 case MLX5E_PACKET_MERGE_LRO:
87 MLX5_SET(tirc, tirc, packet_merge_mask,
88 MLX5_TIRC_PACKET_MERGE_MASK_IPV4_LRO |
89 MLX5_TIRC_PACKET_MERGE_MASK_IPV6_LRO);
90 MLX5_SET(tirc, tirc, lro_max_ip_payload_size,
91 (MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ - rough_max_l2_l3_hdr_sz) >> 8);
92 MLX5_SET(tirc, tirc, lro_timeout_period_usecs, pkt_merge_param->timeout);
93 break;
94 default:
95 break;
96 }
97}
98
99static int mlx5e_hfunc_to_hw(u8 hfunc)
100{
101 switch (hfunc) {
102 case ETH_RSS_HASH_TOP:
103 return MLX5_RX_HASH_FN_TOEPLITZ;
104 case ETH_RSS_HASH_XOR:
105 return MLX5_RX_HASH_FN_INVERTED_XOR8;
106 default:
107 return MLX5_RX_HASH_FN_NONE;
108 }
109}
110
111void mlx5e_tir_builder_build_rss(struct mlx5e_tir_builder *builder,
112 const struct mlx5e_rss_params_hash *rss_hash,
113 const struct mlx5e_rss_params_traffic_type *rss_tt,
114 bool inner)
115{
116 void *tirc = mlx5e_tir_builder_get_tirc(builder);
117 void *hfso;
118
119 if (builder->modify)
120 MLX5_SET(modify_tir_in, builder->in, bitmask.hash, 1);
121
122 MLX5_SET(tirc, tirc, rx_hash_fn, mlx5e_hfunc_to_hw(rss_hash->hfunc));
123 if (rss_hash->hfunc == ETH_RSS_HASH_TOP) {
124 const size_t len = MLX5_FLD_SZ_BYTES(tirc, rx_hash_toeplitz_key);
125 void *rss_key = MLX5_ADDR_OF(tirc, tirc, rx_hash_toeplitz_key);
126
127 MLX5_SET(tirc, tirc, rx_hash_symmetric, rss_hash->symmetric);
128 memcpy(rss_key, rss_hash->toeplitz_hash_key, len);
129 }
130
131 if (inner)
132 hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_inner);
133 else
134 hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);
135 MLX5_SET(rx_hash_field_select, hfso, l3_prot_type, rss_tt->l3_prot_type);
136 MLX5_SET(rx_hash_field_select, hfso, l4_prot_type, rss_tt->l4_prot_type);
137 MLX5_SET(rx_hash_field_select, hfso, selected_fields, rss_tt->rx_hash_fields);
138}
139
140void mlx5e_tir_builder_build_direct(struct mlx5e_tir_builder *builder)
141{
142 void *tirc = mlx5e_tir_builder_get_tirc(builder);
143
144 WARN_ON(builder->modify);
145
146 MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_INVERTED_XOR8);
147}
148
149void mlx5e_tir_builder_build_tls(struct mlx5e_tir_builder *builder)
150{
151 void *tirc = mlx5e_tir_builder_get_tirc(builder);
152
153 WARN_ON(builder->modify);
154
155 MLX5_SET(tirc, tirc, tls_en, 1);
156 MLX5_SET(tirc, tirc, self_lb_block,
157 MLX5_TIRC_SELF_LB_BLOCK_BLOCK_UNICAST |
158 MLX5_TIRC_SELF_LB_BLOCK_BLOCK_MULTICAST);
159}
160
161int mlx5e_tir_init(struct mlx5e_tir *tir, struct mlx5e_tir_builder *builder,
162 struct mlx5_core_dev *mdev, bool reg)
163{
164 int err;
165
166 tir->mdev = mdev;
167
168 err = mlx5_core_create_tir(dev: tir->mdev, in: builder->in, tirn: &tir->tirn);
169 if (err)
170 return err;
171
172 if (reg) {
173 struct mlx5e_hw_objs *res = &tir->mdev->mlx5e_res.hw_objs;
174
175 mutex_lock(&res->td.list_lock);
176 list_add(new: &tir->list, head: &res->td.tirs_list);
177 mutex_unlock(lock: &res->td.list_lock);
178 } else {
179 INIT_LIST_HEAD(list: &tir->list);
180 }
181
182 return 0;
183}
184
185void mlx5e_tir_destroy(struct mlx5e_tir *tir)
186{
187 struct mlx5e_hw_objs *res = &tir->mdev->mlx5e_res.hw_objs;
188
189 /* Skip mutex if list_del is no-op (the TIR wasn't registered in the
190 * list). list_empty will never return true for an item of tirs_list,
191 * and READ_ONCE/WRITE_ONCE in list_empty/list_del guarantee consistency
192 * of the list->next value.
193 */
194 if (!list_empty(head: &tir->list)) {
195 mutex_lock(&res->td.list_lock);
196 list_del(entry: &tir->list);
197 mutex_unlock(lock: &res->td.list_lock);
198 }
199
200 mlx5_core_destroy_tir(dev: tir->mdev, tirn: tir->tirn);
201}
202
203int mlx5e_tir_modify(struct mlx5e_tir *tir, struct mlx5e_tir_builder *builder)
204{
205 return mlx5_core_modify_tir(dev: tir->mdev, tirn: tir->tirn, in: builder->in);
206}
207

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of linux/drivers/net/ethernet/mellanox/mlx5/core/en/tir.c