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 int32_t sxe2_vsi_destroy(struct sxe2_adapter *adapter, struct sxe2_vsi *vsi)
100 : : {
101 : 0 : int32_t ret = 0;
102 : :
103 [ # # ]: 0 : if (vsi == NULL) {
104 : 0 : PMD_LOG_INFO(DRV, "vsi is not created, no need to destroy.");
105 : 0 : goto l_end;
106 : : }
107 : :
108 [ # # ]: 0 : if (vsi->vsi_type != SXE2_VSI_T_DPDK_ESW) {
109 : 0 : ret = sxe2_drv_vsi_del(adapter, vsi);
110 [ # # ]: 0 : if (ret) {
111 : 0 : PMD_LOG_ERR(DRV, "Failed to del vsi from fw, ret=%d", ret);
112 [ # # ]: 0 : if (ret == -EPERM)
113 : 0 : goto l_free;
114 : 0 : goto l_end;
115 : : }
116 : : }
117 : :
118 : 0 : l_free:
119 [ # # ]: 0 : if (vsi->vsi_type == SXE2_VSI_T_DPDK_ESW)
120 [ # # ]: 0 : TAILQ_REMOVE(&adapter->vsi_ctxt.other_vsi_list, vsi, next);
121 : 0 : rte_free(vsi);
122 : 0 : vsi = NULL;
123 : :
124 : 0 : PMD_LOG_DEBUG(DRV, "vsi destroyed.");
125 : 0 : l_end:
126 : 0 : return ret;
127 : : }
128 : :
129 : 0 : static int32_t sxe2_main_vsi_create(struct sxe2_adapter *adapter)
130 : : {
131 : 0 : int32_t ret = 0;
132 : 0 : uint16_t vsi_id = adapter->vsi_ctxt.dpdk_vsi_id;
133 : 0 : uint16_t vsi_type = adapter->vsi_ctxt.vsi_type;
134 : 0 : bool is_reused = (vsi_id != SXE2_INVALID_VSI_ID);
135 : :
136 : 0 : PMD_INIT_FUNC_TRACE();
137 : :
138 [ # # ]: 0 : if (!is_reused)
139 : : vsi_type = SXE2_VSI_T_DPDK_PF;
140 : : else
141 : 0 : PMD_LOG_INFO(DRV, "Reusing existing HW vsi_id:%u", vsi_id);
142 : :
143 : 0 : adapter->vsi_ctxt.main_vsi = sxe2_vsi_node_create(adapter, vsi_id, vsi_type);
144 [ # # ]: 0 : if (adapter->vsi_ctxt.main_vsi == NULL) {
145 : 0 : PMD_LOG_ERR(DRV, "Failed to create vsi struct, ret=%d", ret);
146 : 0 : ret = -ENOMEM;
147 : 0 : goto l_end;
148 : : }
149 : :
150 [ # # ]: 0 : if (!is_reused) {
151 : 0 : ret = sxe2_drv_vsi_add(adapter, adapter->vsi_ctxt.main_vsi);
152 [ # # ]: 0 : if (ret) {
153 : 0 : PMD_LOG_ERR(DRV, "Failed to config vsi to fw, ret=%d", ret);
154 : 0 : goto l_free_vsi;
155 : : }
156 : :
157 : 0 : adapter->vsi_ctxt.dpdk_vsi_id = adapter->vsi_ctxt.main_vsi->vsi_id;
158 : 0 : PMD_LOG_DEBUG(DRV, "Successfully created and synced new VSI");
159 : : }
160 : :
161 : 0 : goto l_end;
162 : :
163 : 0 : l_free_vsi:
164 : 0 : rte_free(adapter->vsi_ctxt.main_vsi);
165 : 0 : adapter->vsi_ctxt.main_vsi = NULL;
166 : 0 : l_end:
167 : 0 : return ret;
168 : : }
169 : :
170 : 0 : int32_t sxe2_other_vsi_create(struct sxe2_adapter *adapter, uint16_t cnt_vf)
171 : : {
172 : 0 : int32_t ret = 0;
173 : 0 : struct sxe2_vsi *other_vsi = NULL;
174 : 0 : uint16_t vsi_id = SXE2_INVALID_VSI_ID;
175 : :
176 : 0 : PMD_INIT_FUNC_TRACE();
177 : :
178 : 0 : other_vsi = sxe2_vsi_node_create(adapter, SXE2_INVALID_VSI_ID, SXE2_VSI_T_DPDK_ESW);
179 [ # # ]: 0 : if (other_vsi == NULL) {
180 : 0 : ret = -ENOMEM;
181 : 0 : goto l_end;
182 : : }
183 : :
184 : 0 : ret = sxe2_drv_switchdev_cpvsi_get(adapter, &vsi_id);
185 [ # # ]: 0 : if (ret) {
186 : 0 : PMD_LOG_ERR(DRV, "Failed to query vsi from fw, ret=%d", ret);
187 : 0 : goto l_free_vsi;
188 : : }
189 : :
190 : 0 : other_vsi->vsi_id = vsi_id;
191 : 0 : other_vsi->vsi_type = SXE2_VSI_T_DPDK_ESW;
192 : :
193 : 0 : ret = sxe2_drv_vsi_info_get(adapter, other_vsi);
194 [ # # ]: 0 : if (ret) {
195 : 0 : PMD_LOG_ERR(DRV, "Failed to query vsi info from fw, ret=%d", ret);
196 : 0 : goto l_free_vsi;
197 : : }
198 : :
199 : 0 : other_vsi->txqs.q_cnt = RTE_MIN(cnt_vf, other_vsi->txqs.q_cnt);
200 : 0 : other_vsi->rxqs.q_cnt = RTE_MIN(cnt_vf, other_vsi->rxqs.q_cnt);
201 : 0 : other_vsi->irqs.avail_cnt = RTE_MIN(cnt_vf, other_vsi->irqs.avail_cnt);
202 : :
203 : 0 : TAILQ_INSERT_TAIL(&adapter->vsi_ctxt.other_vsi_list, other_vsi, next);
204 : 0 : goto l_end;
205 : :
206 : 0 : l_free_vsi:
207 : 0 : rte_free(other_vsi);
208 : 0 : l_end:
209 : 0 : return ret;
210 : : }
211 : :
212 : 0 : int32_t sxe2_vsi_init(struct rte_eth_dev *dev)
213 : : {
214 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
215 : 0 : int32_t ret = 0;
216 : 0 : uint16_t srcvsi_list[SXE2_SRCVSI_PRUNE_MAX_NUM];
217 : 0 : uint16_t srcvsi_cnt;
218 : :
219 : 0 : PMD_INIT_FUNC_TRACE();
220 : 0 : TAILQ_INIT(&adapter->vsi_ctxt.other_vsi_list);
221 : 0 : ret = sxe2_main_vsi_create(adapter);
222 [ # # ]: 0 : if (ret) {
223 : 0 : PMD_LOG_ERR(DRV, "Failed to create main VSI, ret=%d", ret);
224 : 0 : goto l_end;
225 : : }
226 : :
227 [ # # ]: 0 : if (adapter->vsi_ctxt.kernel_vsi_id != SXE2_INVALID_VSI_ID) {
228 : 0 : srcvsi_list[0] = adapter->vsi_ctxt.kernel_vsi_id;
229 : 0 : srcvsi_list[1] = adapter->vsi_ctxt.dpdk_vsi_id;
230 : 0 : srcvsi_cnt = 2;
231 : 0 : ret = sxe2_drv_srcvsi_prune_config(adapter, srcvsi_list, srcvsi_cnt, true);
232 [ # # ]: 0 : if (ret) {
233 : 0 : PMD_LOG_ERR(DRV, "Failed to set src vsi to fw, ret=%d", ret);
234 : 0 : goto l_end;
235 : : }
236 : 0 : PMD_LOG_DEBUG(DRV, "Successfully set src vsi");
237 : : }
238 : :
239 : 0 : l_end:
240 : 0 : return ret;
241 : : }
242 : :
243 : 0 : void sxe2_vsi_uninit(struct rte_eth_dev *dev)
244 : : {
245 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
246 : 0 : struct sxe2_vsi *var, *tvar;
247 : 0 : int32_t ret;
248 : 0 : uint16_t srcvsi_list[SXE2_SRCVSI_PRUNE_MAX_NUM];
249 : 0 : uint16_t srcvsi_cnt;
250 : :
251 [ # # ]: 0 : if (adapter->vsi_ctxt.main_vsi == NULL) {
252 : 0 : PMD_LOG_INFO(DRV, "vsi is not created, no need to destroy.");
253 : 0 : goto l_end;
254 : : }
255 : :
256 [ # # ]: 0 : if (adapter->vsi_ctxt.kernel_vsi_id != SXE2_INVALID_VSI_ID) {
257 : 0 : srcvsi_list[0] = adapter->vsi_ctxt.kernel_vsi_id;
258 : 0 : srcvsi_list[1] = adapter->vsi_ctxt.dpdk_vsi_id;
259 : 0 : srcvsi_cnt = 2;
260 : 0 : ret = sxe2_drv_srcvsi_prune_config(adapter, srcvsi_list,
261 : : srcvsi_cnt, false);
262 [ # # ]: 0 : if (ret) {
263 : 0 : PMD_LOG_ERR(DRV, "Failed to clear src vsi to fw, ret=%d", ret);
264 [ # # ]: 0 : if (ret == -EPERM)
265 : 0 : goto l_free;
266 : 0 : goto l_end;
267 : : }
268 : 0 : PMD_LOG_DEBUG(DRV, "Successfully clear src vsi");
269 : : }
270 : :
271 : 0 : l_free:
272 : 0 : ret = sxe2_vsi_destroy(adapter, adapter->vsi_ctxt.main_vsi);
273 [ # # ]: 0 : if (ret && ret != -EPERM) {
274 : 0 : PMD_LOG_ERR(DRV, "Failed to del vsi from fw, ret=%d", ret);
275 : 0 : goto l_end;
276 : : }
277 : 0 : adapter->vsi_ctxt.main_vsi = NULL;
278 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(var, &adapter->vsi_ctxt.other_vsi_list, next, tvar) {
279 : 0 : ret = sxe2_vsi_destroy(adapter, var);
280 [ # # ]: 0 : if (ret && ret != -EPERM) {
281 : 0 : PMD_LOG_ERR(DRV, "Failed to del vsi from fw, ret=%d", ret);
282 : 0 : break;
283 : : }
284 : : }
285 : :
286 : 0 : PMD_LOG_DEBUG(DRV, "vsi destroyed.");
287 : :
288 : 0 : l_end:
289 : 0 : return;
290 : : }
291 : :
292 : 0 : int32_t sxe2_vsi_repr_main_vsi_create(struct rte_eth_dev *dev,
293 : : struct sxe2_adapter *parent_adapter,
294 : : uint16_t repr_id)
295 : : {
296 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
297 : 0 : struct sxe2_vsi *vsi = NULL;
298 : 0 : struct sxe2_vsi *pos;
299 : 0 : int32_t ret = 0;
300 : :
301 [ # # ]: 0 : TAILQ_FOREACH(pos, &parent_adapter->vsi_ctxt.other_vsi_list, next) {
302 [ # # ]: 0 : if (pos->vsi_type == SXE2_VSI_T_DPDK_ESW) {
303 : : vsi = pos;
304 : : break;
305 : : }
306 : : }
307 : :
308 [ # # ]: 0 : if (vsi == NULL) {
309 : 0 : PMD_LOG_ERR(INIT, "Failed to get dpdk vsi.");
310 : 0 : ret = -EINVAL;
311 : 0 : goto l_end;
312 : : }
313 : :
314 : 0 : TAILQ_INIT(&adapter->vsi_ctxt.other_vsi_list);
315 : :
316 : 0 : adapter->vsi_ctxt.vsi_type = SXE2_VSI_T_DPDK_ESW;
317 : 0 : adapter->vsi_ctxt.kernel_vsi_id = SXE2_INVALID_VSI_ID;
318 : :
319 : 0 : adapter->cdev = parent_adapter->cdev;
320 : :
321 : 0 : adapter->q_ctxt.base_idx_in_pf = vsi->txqs.base_idx_in_func +
322 : 0 : RTE_MIN(vsi->txqs.q_cnt, repr_id);
323 : 0 : adapter->irq_ctxt.base_idx_in_func = vsi->irqs.base_idx_in_pf +
324 : 0 : RTE_MIN(vsi->irqs.avail_cnt, repr_id);
325 : 0 : adapter->q_ctxt.qp_cnt_assign = RTE_MIN(vsi->txqs.q_cnt, 1);
326 : 0 : adapter->irq_ctxt.max_cnt_hw = RTE_MIN(vsi->irqs.avail_cnt, 1);
327 : :
328 : 0 : adapter->vsi_ctxt.main_vsi =
329 : 0 : sxe2_vsi_node_create(adapter, vsi->vsi_id, SXE2_VSI_T_DPDK_ESW);
330 [ # # ]: 0 : if (adapter->vsi_ctxt.main_vsi == NULL) {
331 : 0 : ret = -ENOMEM;
332 : 0 : PMD_LOG_ERR(DRV, "Failed to create vsi struct, ret=%d", ret);
333 : 0 : goto l_end;
334 : : }
335 : 0 : adapter->vsi_ctxt.dpdk_vsi_id = adapter->vsi_ctxt.main_vsi->vsi_id;
336 : :
337 : 0 : ret = 0;
338 : :
339 : 0 : l_end:
340 : 0 : return ret;
341 : : }
342 : :
343 : 0 : void sxe2_vsi_repr_main_vsi_destroy(struct rte_eth_dev *dev)
344 : : {
345 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
346 : :
347 : 0 : rte_free(adapter->vsi_ctxt.main_vsi);
348 : 0 : adapter->vsi_ctxt.main_vsi = NULL;
349 : 0 : }
|