Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
3 : : */
4 : :
5 : : #include <rte_os.h>
6 : : #include <rte_tailq.h>
7 : : #include <rte_malloc.h>
8 : : #include "sxe2_ethdev.h"
9 : : #include "sxe2_vsi.h"
10 : : #include "sxe2_common_log.h"
11 : : #include "sxe2_cmd_chnl.h"
12 : :
13 : 0 : void sxe2_sw_vsi_ctx_hw_cap_set(struct sxe2_adapter *adapter,
14 : : struct sxe2_drv_vsi_caps *vsi_caps)
15 : : {
16 : 0 : adapter->vsi_ctxt.dpdk_vsi_id = vsi_caps->dpdk_vsi_id;
17 : 0 : adapter->vsi_ctxt.kernel_vsi_id = vsi_caps->kernel_vsi_id;
18 : 0 : adapter->vsi_ctxt.vsi_type = vsi_caps->vsi_type;
19 : 0 : }
20 : :
21 : : static struct sxe2_vsi *
22 : 0 : sxe2_vsi_node_alloc(struct sxe2_adapter *adapter, uint16_t vsi_id, uint16_t vsi_type)
23 : : {
24 : 0 : struct sxe2_vsi *vsi = NULL;
25 : 0 : vsi = rte_zmalloc("sxe2_vsi", sizeof(*vsi), 0);
26 [ # # ]: 0 : if (vsi == NULL) {
27 : 0 : PMD_LOG_ERR(DRV, "Failed to malloc vf vsi struct.");
28 : 0 : goto l_end;
29 : : }
30 : 0 : vsi->adapter = adapter;
31 : :
32 : 0 : vsi->vsi_id = vsi_id;
33 : 0 : vsi->vsi_type = vsi_type;
34 : :
35 : 0 : l_end:
36 : 0 : return vsi;
37 : : }
38 : :
39 : 0 : static void sxe2_vsi_queues_num_set(struct sxe2_vsi *vsi, uint16_t num_queues, uint16_t base_idx)
40 : : {
41 : 0 : vsi->txqs.q_cnt = num_queues;
42 : 0 : vsi->rxqs.q_cnt = num_queues;
43 : 0 : vsi->txqs.base_idx_in_func = base_idx;
44 : 0 : vsi->rxqs.base_idx_in_func = base_idx;
45 : : }
46 : :
47 : 0 : static void sxe2_vsi_queues_cfg(struct sxe2_vsi *vsi)
48 : : {
49 [ # # ]: 0 : vsi->txqs.depth = vsi->txqs.depth ? : SXE2_DFLT_NUM_TX_DESC;
50 [ # # ]: 0 : vsi->rxqs.depth = vsi->rxqs.depth ? : SXE2_DFLT_NUM_RX_DESC;
51 : :
52 : 0 : PMD_LOG_INFO(DRV, "vsi:%u queue_cnt:%u txq_depth:%u rxq_depth:%u.",
53 : : vsi->vsi_id, vsi->txqs.q_cnt,
54 : : vsi->txqs.depth, vsi->rxqs.depth);
55 : 0 : }
56 : :
57 : 0 : static void sxe2_vsi_irqs_cfg(struct sxe2_vsi *vsi, uint16_t num_irqs, uint16_t base_idx)
58 : : {
59 : 0 : vsi->irqs.avail_cnt = num_irqs;
60 : 0 : vsi->irqs.base_idx_in_pf = base_idx;
61 : 0 : }
62 : :
63 : 0 : static struct sxe2_vsi *sxe2_vsi_node_create(struct sxe2_adapter *adapter,
64 : : uint16_t vsi_id,
65 : : uint16_t vsi_type)
66 : : {
67 : 0 : struct sxe2_vsi *vsi = NULL;
68 : 0 : uint16_t num_queues = 0;
69 : 0 : uint16_t queue_base_idx = 0;
70 : 0 : uint16_t num_irqs = 0;
71 : 0 : uint16_t irq_base_idx = 0;
72 : :
73 : 0 : vsi = sxe2_vsi_node_alloc(adapter, vsi_id, vsi_type);
74 [ # # ]: 0 : if (vsi == NULL)
75 : 0 : goto l_end;
76 : :
77 [ # # ]: 0 : if (vsi_type == SXE2_VSI_T_DPDK_PF ||
78 : : vsi_type == SXE2_VSI_T_DPDK_VF) {
79 : 0 : num_queues = adapter->q_ctxt.qp_cnt_assign;
80 : 0 : queue_base_idx = adapter->q_ctxt.base_idx_in_pf;
81 : :
82 : 0 : num_irqs = adapter->irq_ctxt.max_cnt_hw;
83 : 0 : irq_base_idx = adapter->irq_ctxt.base_idx_in_func;
84 [ # # ]: 0 : } else if (vsi_type == SXE2_VSI_T_DPDK_ESW) {
85 : 0 : num_queues = 1;
86 : 0 : num_irqs = 1;
87 : : }
88 : :
89 : 0 : sxe2_vsi_queues_num_set(vsi, num_queues, queue_base_idx);
90 : :
91 : 0 : sxe2_vsi_queues_cfg(vsi);
92 : :
93 : 0 : sxe2_vsi_irqs_cfg(vsi, num_irqs, irq_base_idx);
94 : :
95 : 0 : l_end:
96 : 0 : return vsi;
97 : : }
98 : :
99 : 0 : static void sxe2_vsi_node_free(struct sxe2_vsi *vsi)
100 : : {
101 : 0 : struct sxe2_adapter *adapter;
102 : :
103 [ # # ]: 0 : if (!vsi)
104 : : return;
105 : :
106 : 0 : adapter = vsi->adapter;
107 [ # # ]: 0 : if (vsi->vsi_type == SXE2_VSI_T_ESW)
108 [ # # ]: 0 : TAILQ_REMOVE(&adapter->vsi_ctxt.other_vsi_list, vsi, next);
109 : :
110 : 0 : rte_free(vsi);
111 : 0 : vsi = NULL;
112 : : }
113 : :
114 : 0 : static int32_t sxe2_vsi_destroy(struct sxe2_adapter *adapter, struct sxe2_vsi *vsi)
115 : : {
116 : 0 : int32_t ret = 0;
117 : :
118 [ # # ]: 0 : if (vsi == NULL) {
119 : 0 : PMD_LOG_INFO(DRV, "vsi is not created, no need to destroy.");
120 : 0 : goto l_end;
121 : : }
122 : :
123 [ # # ]: 0 : if (vsi->vsi_type != SXE2_VSI_T_DPDK_ESW) {
124 : 0 : ret = sxe2_drv_vsi_del(adapter, vsi);
125 [ # # ]: 0 : if (ret) {
126 : 0 : PMD_LOG_ERR(DRV, "Failed to del vsi from fw, ret=%d", ret);
127 [ # # ]: 0 : if (ret == -EPERM)
128 : 0 : goto l_free;
129 : 0 : goto l_end;
130 : : }
131 : : }
132 : :
133 : 0 : l_free:
134 : 0 : rte_free(vsi);
135 : 0 : vsi = NULL;
136 : :
137 : 0 : PMD_LOG_DEBUG(DRV, "vsi destroyed.");
138 : 0 : l_end:
139 : 0 : return ret;
140 : : }
141 : :
142 : 0 : static int32_t sxe2_main_vsi_create(struct sxe2_adapter *adapter)
143 : : {
144 : 0 : int32_t ret = 0;
145 : 0 : uint16_t vsi_id = adapter->vsi_ctxt.dpdk_vsi_id;
146 : 0 : uint16_t vsi_type = adapter->vsi_ctxt.vsi_type;
147 : 0 : bool is_reused = (vsi_id != SXE2_INVALID_VSI_ID);
148 : :
149 : 0 : PMD_INIT_FUNC_TRACE();
150 : :
151 [ # # ]: 0 : if (!is_reused)
152 : : vsi_type = SXE2_VSI_T_DPDK_PF;
153 : : else
154 : 0 : PMD_LOG_INFO(DRV, "Reusing existing HW vsi_id:%u", vsi_id);
155 : :
156 : 0 : adapter->vsi_ctxt.main_vsi = sxe2_vsi_node_create(adapter, vsi_id, vsi_type);
157 [ # # ]: 0 : if (adapter->vsi_ctxt.main_vsi == NULL) {
158 : 0 : PMD_LOG_ERR(DRV, "Failed to create vsi struct, ret=%d", ret);
159 : 0 : ret = -ENOMEM;
160 : 0 : goto l_end;
161 : : }
162 : :
163 [ # # ]: 0 : if (!is_reused) {
164 : 0 : ret = sxe2_drv_vsi_add(adapter, adapter->vsi_ctxt.main_vsi);
165 [ # # ]: 0 : if (ret) {
166 : 0 : PMD_LOG_ERR(DRV, "Failed to config vsi to fw, ret=%d", ret);
167 : 0 : goto l_free_vsi;
168 : : }
169 : :
170 : 0 : adapter->vsi_ctxt.dpdk_vsi_id = adapter->vsi_ctxt.main_vsi->vsi_id;
171 : 0 : PMD_LOG_DEBUG(DRV, "Successfully created and synced new VSI");
172 : : }
173 : :
174 : 0 : goto l_end;
175 : :
176 : 0 : l_free_vsi:
177 : 0 : sxe2_vsi_node_free(adapter->vsi_ctxt.main_vsi);
178 : 0 : adapter->vsi_ctxt.main_vsi = NULL;
179 : 0 : l_end:
180 : 0 : return ret;
181 : : }
182 : :
183 : 0 : int32_t sxe2_other_vsi_create(struct sxe2_adapter *adapter, uint16_t cnt_vf)
184 : : {
185 : 0 : int32_t ret = 0;
186 : 0 : struct sxe2_vsi *other_vsi = NULL;
187 : 0 : uint16_t vsi_id = SXE2_INVALID_VSI_ID;
188 : :
189 : 0 : PMD_INIT_FUNC_TRACE();
190 : :
191 : 0 : other_vsi = sxe2_vsi_node_create(adapter, SXE2_INVALID_VSI_ID, SXE2_VSI_T_DPDK_ESW);
192 [ # # ]: 0 : if (other_vsi == NULL) {
193 : 0 : ret = -ENOMEM;
194 : 0 : goto l_end;
195 : : }
196 : :
197 : 0 : ret = sxe2_drv_switchdev_cpvsi_get(adapter, &vsi_id);
198 [ # # ]: 0 : if (ret) {
199 : 0 : PMD_LOG_ERR(DRV, "Failed to query vsi from fw, ret=%d", ret);
200 : 0 : goto l_free_vsi;
201 : : }
202 : :
203 : 0 : other_vsi->vsi_id = vsi_id;
204 : 0 : other_vsi->vsi_type = SXE2_VSI_T_DPDK_ESW;
205 : :
206 : 0 : ret = sxe2_drv_vsi_info_get(adapter, other_vsi);
207 [ # # ]: 0 : if (ret) {
208 : 0 : PMD_LOG_ERR(DRV, "Failed to query vsi info from fw, ret=%d", ret);
209 : 0 : goto l_free_vsi;
210 : : }
211 : :
212 : 0 : other_vsi->txqs.q_cnt = RTE_MIN(cnt_vf, other_vsi->txqs.q_cnt);
213 : 0 : other_vsi->rxqs.q_cnt = RTE_MIN(cnt_vf, other_vsi->rxqs.q_cnt);
214 : 0 : other_vsi->irqs.avail_cnt = RTE_MIN(cnt_vf, other_vsi->irqs.avail_cnt);
215 : :
216 : 0 : TAILQ_INSERT_TAIL(&adapter->vsi_ctxt.other_vsi_list, other_vsi, next);
217 : 0 : goto l_end;
218 : :
219 : 0 : l_free_vsi:
220 : 0 : sxe2_vsi_node_free(other_vsi);
221 : 0 : l_end:
222 : 0 : return ret;
223 : : }
224 : :
225 : 0 : int32_t sxe2_vsi_init(struct rte_eth_dev *dev)
226 : : {
227 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
228 : 0 : int32_t ret = 0;
229 : 0 : uint16_t srcvsi_list[SXE2_SRCVSI_PRUNE_MAX_NUM];
230 : 0 : uint16_t srcvsi_cnt;
231 : :
232 : 0 : PMD_INIT_FUNC_TRACE();
233 : :
234 : 0 : ret = sxe2_main_vsi_create(adapter);
235 [ # # ]: 0 : if (ret) {
236 : 0 : PMD_LOG_ERR(DRV, "Failed to create main VSI, ret=%d", ret);
237 : 0 : goto l_end;
238 : : }
239 : :
240 [ # # ]: 0 : if (adapter->vsi_ctxt.kernel_vsi_id != SXE2_INVALID_VSI_ID) {
241 : 0 : srcvsi_list[0] = adapter->vsi_ctxt.kernel_vsi_id;
242 : 0 : srcvsi_list[1] = adapter->vsi_ctxt.dpdk_vsi_id;
243 : 0 : srcvsi_cnt = 2;
244 : 0 : ret = sxe2_drv_srcvsi_prune_config(adapter, srcvsi_list, srcvsi_cnt, true);
245 [ # # ]: 0 : if (ret) {
246 : 0 : PMD_LOG_ERR(DRV, "Failed to set src vsi to fw, ret=%d", ret);
247 : 0 : goto l_end;
248 : : }
249 : 0 : PMD_LOG_DEBUG(DRV, "Successfully set src vsi");
250 : : }
251 : :
252 : 0 : l_end:
253 : 0 : return ret;
254 : : }
255 : :
256 : 0 : void sxe2_vsi_uninit(struct rte_eth_dev *dev)
257 : : {
258 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
259 : 0 : struct sxe2_vsi *var, *tvar;
260 : 0 : int32_t ret;
261 : 0 : uint16_t srcvsi_list[SXE2_SRCVSI_PRUNE_MAX_NUM];
262 : 0 : uint16_t srcvsi_cnt;
263 : :
264 [ # # ]: 0 : if (adapter->vsi_ctxt.main_vsi == NULL) {
265 : 0 : PMD_LOG_INFO(DRV, "vsi is not created, no need to destroy.");
266 : 0 : goto l_end;
267 : : }
268 : :
269 [ # # ]: 0 : if (adapter->vsi_ctxt.kernel_vsi_id != SXE2_INVALID_VSI_ID) {
270 : 0 : srcvsi_list[0] = adapter->vsi_ctxt.kernel_vsi_id;
271 : 0 : srcvsi_list[1] = adapter->vsi_ctxt.dpdk_vsi_id;
272 : 0 : srcvsi_cnt = 2;
273 : 0 : ret = sxe2_drv_srcvsi_prune_config(adapter, srcvsi_list,
274 : : srcvsi_cnt, false);
275 [ # # ]: 0 : if (ret) {
276 : 0 : PMD_LOG_ERR(DRV, "Failed to clear src vsi to fw, ret=%d", ret);
277 [ # # ]: 0 : if (ret == -EPERM)
278 : 0 : goto l_free;
279 : 0 : goto l_end;
280 : : }
281 : 0 : PMD_LOG_DEBUG(DRV, "Successfully clear src vsi");
282 : : }
283 : :
284 : 0 : l_free:
285 : 0 : ret = sxe2_vsi_destroy(adapter, adapter->vsi_ctxt.main_vsi);
286 [ # # ]: 0 : if (ret) {
287 : 0 : PMD_LOG_ERR(DRV, "Failed to del vsi from fw, ret=%d", ret);
288 : 0 : goto l_end;
289 : : }
290 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(var, &adapter->vsi_ctxt.other_vsi_list, next, tvar) {
291 : 0 : ret = sxe2_vsi_destroy(adapter, var);
292 [ # # ]: 0 : if (ret) {
293 : 0 : PMD_LOG_ERR(DRV, "Failed to del vsi from fw, ret=%d", ret);
294 : 0 : break;
295 : : }
296 : : }
297 : :
298 : 0 : PMD_LOG_DEBUG(DRV, "vsi destroyed.");
299 : :
300 : 0 : l_end:
301 : 0 : return;
302 : : }
303 : :
304 : 0 : int32_t sxe2_vsi_repr_main_vsi_create(struct rte_eth_dev *dev,
305 : : struct sxe2_adapter *parent_adapter,
306 : : uint16_t repr_id)
307 : : {
308 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
309 : 0 : struct sxe2_vsi *vsi = NULL;
310 : 0 : struct sxe2_vsi *pos;
311 : 0 : int32_t ret = 0;
312 : :
313 [ # # ]: 0 : TAILQ_FOREACH(pos, &parent_adapter->vsi_ctxt.other_vsi_list, next) {
314 [ # # ]: 0 : if (pos->vsi_type == SXE2_VSI_T_DPDK_ESW) {
315 : : vsi = pos;
316 : : break;
317 : : }
318 : : }
319 : :
320 [ # # ]: 0 : if (vsi == NULL) {
321 : 0 : PMD_LOG_ERR(INIT, "Failed to get dpdk vsi.");
322 : 0 : ret = -EINVAL;
323 : 0 : goto l_end;
324 : : }
325 : :
326 : 0 : TAILQ_INIT(&adapter->vsi_ctxt.other_vsi_list);
327 : :
328 : 0 : adapter->vsi_ctxt.vsi_type = SXE2_VSI_T_DPDK_ESW;
329 : 0 : adapter->vsi_ctxt.kernel_vsi_id = SXE2_INVALID_VSI_ID;
330 : :
331 : 0 : adapter->cdev = parent_adapter->cdev;
332 : :
333 : 0 : adapter->q_ctxt.base_idx_in_pf = vsi->txqs.base_idx_in_func +
334 : 0 : RTE_MIN(vsi->txqs.q_cnt, repr_id);
335 : 0 : adapter->irq_ctxt.base_idx_in_func = vsi->irqs.base_idx_in_pf +
336 : 0 : RTE_MIN(vsi->irqs.avail_cnt, repr_id);
337 : 0 : adapter->q_ctxt.qp_cnt_assign = RTE_MIN(vsi->txqs.q_cnt, 1);
338 : 0 : adapter->irq_ctxt.max_cnt_hw = RTE_MIN(vsi->irqs.avail_cnt, 1);
339 : :
340 : 0 : adapter->vsi_ctxt.main_vsi =
341 : 0 : sxe2_vsi_node_create(adapter, vsi->vsi_id, SXE2_VSI_T_DPDK_ESW);
342 [ # # ]: 0 : if (adapter->vsi_ctxt.main_vsi == NULL) {
343 : 0 : ret = -ENOMEM;
344 : 0 : PMD_LOG_ERR(DRV, "Failed to create vsi struct, ret=%d", ret);
345 : 0 : goto l_end;
346 : : }
347 : 0 : adapter->vsi_ctxt.dpdk_vsi_id = adapter->vsi_ctxt.main_vsi->vsi_id;
348 : :
349 : 0 : ret = 0;
350 : :
351 : 0 : l_end:
352 : 0 : return ret;
353 : : }
354 : :
355 : 0 : void sxe2_vsi_repr_main_vsi_destroy(struct rte_eth_dev *dev)
356 : : {
357 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
358 : :
359 : 0 : sxe2_vsi_node_free(adapter->vsi_ctxt.main_vsi);
360 : 0 : }
|