Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2018-2021,2023 NXP
3 : : */
4 : :
5 : : #include <sys/queue.h>
6 : : #include <stdio.h>
7 : : #include <errno.h>
8 : : #include <stdint.h>
9 : : #include <string.h>
10 : : #include <unistd.h>
11 : : #include <stdarg.h>
12 : :
13 : : #include <eal_export.h>
14 : : #include <rte_ethdev.h>
15 : : #include <rte_log.h>
16 : : #include <rte_malloc.h>
17 : : #include <rte_flow_driver.h>
18 : : #include <rte_tailq.h>
19 : :
20 : : #include <bus_fslmc_driver.h>
21 : : #include <fsl_dpdmux.h>
22 : : #include <fsl_dpkg.h>
23 : :
24 : : #include <dpaa2_ethdev.h>
25 : : #include <dpaa2_pmd_logs.h>
26 : :
27 : : struct dpaa2_dpdmux_dev {
28 : : TAILQ_ENTRY(dpaa2_dpdmux_dev) next;
29 : : /**< Pointer to Next device instance */
30 : : struct fsl_mc_io dpdmux; /** handle to DPDMUX portal object */
31 : : uint16_t token;
32 : : uint32_t dpdmux_id; /*HW ID for DPDMUX object */
33 : : uint8_t num_ifs; /* Number of interfaces in DPDMUX */
34 : : };
35 : :
36 : : #define DPAA2_MUX_FLOW_MAX_RULE_NUM 8
37 : : struct dpaa2_mux_flow {
38 : : struct dpdmux_rule_cfg rule[DPAA2_MUX_FLOW_MAX_RULE_NUM];
39 : : };
40 : :
41 : : TAILQ_HEAD(dpdmux_dev_list, dpaa2_dpdmux_dev);
42 : : static struct dpdmux_dev_list dpdmux_dev_list =
43 : : TAILQ_HEAD_INITIALIZER(dpdmux_dev_list); /*!< DPDMUX device list */
44 : :
45 : : static struct dpaa2_dpdmux_dev *get_dpdmux_from_id(uint32_t dpdmux_id)
46 : : {
47 : : struct dpaa2_dpdmux_dev *dpdmux_dev = NULL;
48 : :
49 : : /* Get DPDMUX dev handle from list using index */
50 [ # # # # : 0 : TAILQ_FOREACH(dpdmux_dev, &dpdmux_dev_list, next) {
# # # # #
# ]
51 [ # # # # : 0 : if (dpdmux_dev->dpdmux_id == dpdmux_id)
# # # # #
# ]
52 : : break;
53 : : }
54 : :
55 : : return dpdmux_dev;
56 : : }
57 : :
58 : : RTE_EXPORT_SYMBOL(rte_pmd_dpaa2_mux_flow_create)
59 : : int
60 : 0 : rte_pmd_dpaa2_mux_flow_create(uint32_t dpdmux_id,
61 : : struct rte_flow_item pattern[],
62 : : struct rte_flow_action actions[])
63 : : {
64 : : struct dpaa2_dpdmux_dev *dpdmux_dev;
65 : : static struct dpkg_profile_cfg s_kg_cfg;
66 : : struct dpkg_profile_cfg kg_cfg;
67 : : const struct rte_flow_action_vf *vf_conf;
68 : : struct dpdmux_cls_action dpdmux_action;
69 : : uint8_t *key_va = NULL, *mask_va = NULL;
70 : : void *key_cfg_va = NULL;
71 : : uint64_t key_iova, mask_iova, key_cfg_iova;
72 : : uint8_t key_size = 0;
73 : : int ret = 0, loop = 0;
74 : : static int s_i;
75 : : struct dpkg_extract *extract;
76 : : struct dpdmux_rule_cfg rule;
77 : :
78 : : memset(&kg_cfg, 0, sizeof(struct dpkg_profile_cfg));
79 : :
80 : : /* Find the DPDMUX from dpdmux_id in our list */
81 : : dpdmux_dev = get_dpdmux_from_id(dpdmux_id);
82 [ # # ]: 0 : if (!dpdmux_dev) {
83 : 0 : DPAA2_PMD_ERR("Invalid dpdmux_id: %d", dpdmux_id);
84 : : ret = -ENODEV;
85 : 0 : goto creation_error;
86 : : }
87 : :
88 : 0 : key_cfg_va = rte_zmalloc(NULL, DIST_PARAM_IOVA_SIZE,
89 : : RTE_CACHE_LINE_SIZE);
90 [ # # ]: 0 : if (!key_cfg_va) {
91 : 0 : DPAA2_PMD_ERR("Unable to allocate key configure buffer");
92 : : ret = -ENOMEM;
93 : 0 : goto creation_error;
94 : : }
95 : :
96 : 0 : key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(key_cfg_va,
97 : : DIST_PARAM_IOVA_SIZE);
98 [ # # ]: 0 : if (key_cfg_iova == RTE_BAD_IOVA) {
99 : 0 : DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)",
100 : : __func__, key_cfg_va);
101 : : ret = -ENOBUFS;
102 : 0 : goto creation_error;
103 : : }
104 : :
105 : 0 : key_va = rte_zmalloc(NULL, (2 * DIST_PARAM_IOVA_SIZE),
106 : : RTE_CACHE_LINE_SIZE);
107 [ # # ]: 0 : if (!key_va) {
108 : 0 : DPAA2_PMD_ERR("Unable to allocate flow dist parameter");
109 : : ret = -ENOMEM;
110 : 0 : goto creation_error;
111 : : }
112 : :
113 : 0 : key_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(key_va,
114 : : (2 * DIST_PARAM_IOVA_SIZE));
115 [ # # ]: 0 : if (key_iova == RTE_BAD_IOVA) {
116 : 0 : DPAA2_PMD_ERR("%s: No IOMMU mapping for address(%p)",
117 : : __func__, key_va);
118 : : ret = -ENOBUFS;
119 : 0 : goto creation_error;
120 : : }
121 : :
122 : 0 : mask_va = key_va + DIST_PARAM_IOVA_SIZE;
123 : 0 : mask_iova = key_iova + DIST_PARAM_IOVA_SIZE;
124 : :
125 : : /* Currently taking only IP protocol as an extract type.
126 : : * This can be extended to other fields using pattern->type.
127 : : */
128 : : memset(&kg_cfg, 0, sizeof(struct dpkg_profile_cfg));
129 : :
130 [ # # ]: 0 : while (pattern[loop].type != RTE_FLOW_ITEM_TYPE_END) {
131 [ # # ]: 0 : if (kg_cfg.num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) {
132 : 0 : DPAA2_PMD_ERR("Too many extracts(%d)",
133 : : kg_cfg.num_extracts);
134 : : ret = -ENOTSUP;
135 : 0 : goto creation_error;
136 : : }
137 [ # # # # : 0 : switch (pattern[loop].type) {
# # ]
138 : 0 : case RTE_FLOW_ITEM_TYPE_IPV4:
139 : : {
140 : : const struct rte_flow_item_ipv4 *spec;
141 : : const struct rte_flow_item_ipv4 *mask;
142 : :
143 : 0 : extract = &kg_cfg.extracts[kg_cfg.num_extracts];
144 : 0 : extract->type = DPKG_EXTRACT_FROM_HDR;
145 : 0 : extract->extract.from_hdr.prot = NET_PROT_IP;
146 : 0 : extract->extract.from_hdr.field = NH_FLD_IP_PROTO;
147 : 0 : extract->extract.from_hdr.type = DPKG_FULL_FIELD;
148 : :
149 : 0 : kg_cfg.num_extracts++;
150 : :
151 : 0 : spec = pattern[loop].spec;
152 : 0 : mask = pattern[loop].mask;
153 : 0 : rte_memcpy(&key_va[key_size],
154 [ # # ]: 0 : &spec->hdr.next_proto_id, sizeof(uint8_t));
155 [ # # ]: 0 : if (mask) {
156 : 0 : rte_memcpy(&mask_va[key_size],
157 [ # # ]: 0 : &mask->hdr.next_proto_id,
158 : : sizeof(uint8_t));
159 : : } else {
160 : 0 : mask_va[key_size] = 0xff;
161 : : }
162 : 0 : key_size += sizeof(uint8_t);
163 : : }
164 : 0 : break;
165 : :
166 : 0 : case RTE_FLOW_ITEM_TYPE_VLAN:
167 : : {
168 : : const struct rte_flow_item_vlan *spec;
169 : : const struct rte_flow_item_vlan *mask;
170 : :
171 : 0 : extract = &kg_cfg.extracts[kg_cfg.num_extracts];
172 : 0 : extract->type = DPKG_EXTRACT_FROM_HDR;
173 : 0 : extract->extract.from_hdr.prot = NET_PROT_VLAN;
174 : 0 : extract->extract.from_hdr.field = NH_FLD_VLAN_TCI;
175 : 0 : extract->extract.from_hdr.type = DPKG_FULL_FIELD;
176 : :
177 : 0 : kg_cfg.num_extracts++;
178 : :
179 : 0 : spec = pattern[loop].spec;
180 : 0 : mask = pattern[loop].mask;
181 : 0 : rte_memcpy(&key_va[key_size],
182 [ # # ]: 0 : &spec->tci, sizeof(uint16_t));
183 [ # # ]: 0 : if (mask) {
184 : 0 : rte_memcpy(&mask_va[key_size],
185 [ # # ]: 0 : &mask->tci, sizeof(uint16_t));
186 : : } else {
187 : 0 : memset(&mask_va[key_size], 0xff,
188 : : sizeof(rte_be16_t));
189 : : }
190 : 0 : key_size += sizeof(uint16_t);
191 : : }
192 : 0 : break;
193 : :
194 : 0 : case RTE_FLOW_ITEM_TYPE_UDP:
195 : : {
196 : : const struct rte_flow_item_udp *spec;
197 : : const struct rte_flow_item_udp *mask;
198 : :
199 : 0 : extract = &kg_cfg.extracts[kg_cfg.num_extracts];
200 : 0 : extract->type = DPKG_EXTRACT_FROM_HDR;
201 : 0 : extract->extract.from_hdr.prot = NET_PROT_UDP;
202 : 0 : extract->extract.from_hdr.type = DPKG_FULL_FIELD;
203 : 0 : extract->extract.from_hdr.field = NH_FLD_UDP_PORT_DST;
204 : 0 : kg_cfg.num_extracts++;
205 : :
206 : 0 : spec = pattern[loop].spec;
207 : 0 : mask = pattern[loop].mask;
208 : 0 : rte_memcpy(&key_va[key_size],
209 [ # # ]: 0 : &spec->hdr.dst_port, sizeof(rte_be16_t));
210 [ # # ]: 0 : if (mask) {
211 : 0 : rte_memcpy(&mask_va[key_size],
212 [ # # ]: 0 : &mask->hdr.dst_port,
213 : : sizeof(rte_be16_t));
214 : : } else {
215 : 0 : memset(&mask_va[key_size], 0xff,
216 : : sizeof(rte_be16_t));
217 : : }
218 : 0 : key_size += sizeof(rte_be16_t);
219 : : }
220 : 0 : break;
221 : :
222 : 0 : case RTE_FLOW_ITEM_TYPE_ETH:
223 : : {
224 : : const struct rte_flow_item_eth *spec;
225 : : const struct rte_flow_item_eth *mask;
226 : :
227 : 0 : extract = &kg_cfg.extracts[kg_cfg.num_extracts];
228 : 0 : extract->type = DPKG_EXTRACT_FROM_HDR;
229 : 0 : extract->extract.from_hdr.prot = NET_PROT_ETH;
230 : 0 : extract->extract.from_hdr.type = DPKG_FULL_FIELD;
231 : 0 : extract->extract.from_hdr.field = NH_FLD_ETH_TYPE;
232 : 0 : kg_cfg.num_extracts++;
233 : :
234 : 0 : spec = pattern[loop].spec;
235 : 0 : mask = pattern[loop].mask;
236 : 0 : rte_memcpy(&key_va[key_size],
237 [ # # ]: 0 : &spec->type, sizeof(rte_be16_t));
238 [ # # ]: 0 : if (mask) {
239 : 0 : rte_memcpy(&mask_va[key_size],
240 [ # # ]: 0 : &mask->type, sizeof(rte_be16_t));
241 : : } else {
242 : 0 : memset(&mask_va[key_size], 0xff,
243 : : sizeof(rte_be16_t));
244 : : }
245 : 0 : key_size += sizeof(rte_be16_t);
246 : : }
247 : 0 : break;
248 : :
249 : 0 : case RTE_FLOW_ITEM_TYPE_RAW:
250 : : {
251 : : const struct rte_flow_item_raw *spec;
252 : : const struct rte_flow_item_raw *mask;
253 : :
254 : 0 : spec = pattern[loop].spec;
255 : 0 : mask = pattern[loop].mask;
256 : 0 : extract = &kg_cfg.extracts[kg_cfg.num_extracts];
257 : 0 : extract->type = DPKG_EXTRACT_FROM_DATA;
258 : 0 : extract->extract.from_data.offset = spec->offset;
259 : 0 : extract->extract.from_data.size = spec->length;
260 : 0 : kg_cfg.num_extracts++;
261 : :
262 : 0 : rte_memcpy(&key_va[key_size],
263 [ # # ]: 0 : spec->pattern, spec->length);
264 [ # # # # ]: 0 : if (mask && mask->pattern) {
265 : 0 : rte_memcpy(&mask_va[key_size],
266 [ # # ]: 0 : mask->pattern, spec->length);
267 : : } else {
268 : 0 : memset(&mask_va[key_size], 0xff, spec->length);
269 : : }
270 : :
271 : 0 : key_size += spec->length;
272 : : }
273 : 0 : break;
274 : :
275 : 0 : default:
276 : 0 : DPAA2_PMD_ERR("Not supported pattern[%d] type: %d",
277 : : loop, pattern[loop].type);
278 : : ret = -ENOTSUP;
279 : 0 : goto creation_error;
280 : : }
281 : 0 : loop++;
282 : : }
283 : :
284 : 0 : ret = dpkg_prepare_key_cfg(&kg_cfg, key_cfg_va);
285 [ # # ]: 0 : if (ret) {
286 : 0 : DPAA2_PMD_ERR("dpkg_prepare_key_cfg failed: err(%d)", ret);
287 : 0 : goto creation_error;
288 : : }
289 : :
290 [ # # ]: 0 : if (!s_i) {
291 : 0 : ret = dpdmux_set_custom_key(&dpdmux_dev->dpdmux,
292 : 0 : CMD_PRI_LOW, dpdmux_dev->token, key_cfg_iova);
293 [ # # ]: 0 : if (ret) {
294 : 0 : DPAA2_PMD_ERR("dpdmux_set_custom_key failed: err(%d)",
295 : : ret);
296 : 0 : goto creation_error;
297 : : }
298 : : rte_memcpy(&s_kg_cfg, &kg_cfg, sizeof(struct dpkg_profile_cfg));
299 : : } else {
300 [ # # ]: 0 : if (memcmp(&s_kg_cfg, &kg_cfg,
301 : : sizeof(struct dpkg_profile_cfg))) {
302 : 0 : DPAA2_PMD_ERR("%s: Single flow support only.",
303 : : __func__);
304 : : ret = -ENOTSUP;
305 : 0 : goto creation_error;
306 : : }
307 : : }
308 : :
309 : 0 : vf_conf = actions[0].conf;
310 [ # # # # ]: 0 : if (vf_conf->id == 0 || vf_conf->id > dpdmux_dev->num_ifs) {
311 : 0 : DPAA2_PMD_ERR("Invalid destination id(%d)", vf_conf->id);
312 : 0 : goto creation_error;
313 : : }
314 : 0 : dpdmux_action.dest_if = vf_conf->id;
315 : :
316 : 0 : rule.key_iova = key_iova;
317 : 0 : rule.mask_iova = mask_iova;
318 : 0 : rule.key_size = key_size;
319 : 0 : rule.entry_index = s_i;
320 : 0 : s_i++;
321 : :
322 : : /* As now our key extract parameters are set, let us configure
323 : : * the rule.
324 : : */
325 : 0 : ret = dpdmux_add_custom_cls_entry(&dpdmux_dev->dpdmux,
326 : 0 : CMD_PRI_LOW, dpdmux_dev->token,
327 : : &rule, &dpdmux_action);
328 [ # # ]: 0 : if (ret) {
329 : 0 : DPAA2_PMD_ERR("Add classification entry failed:err(%d)", ret);
330 : 0 : goto creation_error;
331 : : }
332 : :
333 : 0 : creation_error:
334 : 0 : rte_free(key_cfg_va);
335 : 0 : rte_free(key_va);
336 : :
337 : 0 : return ret;
338 : : }
339 : :
340 : : int
341 : 0 : rte_pmd_dpaa2_mux_flow_l2(uint32_t dpdmux_id,
342 : : uint8_t mac_addr[6], uint16_t vlan_id, int dest_if)
343 : : {
344 : : struct dpaa2_dpdmux_dev *dpdmux_dev;
345 : : struct dpdmux_l2_rule rule;
346 : : int ret, i;
347 : :
348 : : /* Find the DPDMUX from dpdmux_id in our list */
349 : : dpdmux_dev = get_dpdmux_from_id(dpdmux_id);
350 [ # # ]: 0 : if (!dpdmux_dev) {
351 : 0 : DPAA2_PMD_ERR("Invalid dpdmux_id: %d", dpdmux_id);
352 : 0 : return -ENODEV;
353 : : }
354 : :
355 [ # # ]: 0 : for (i = 0; i < 6; i++)
356 : 0 : rule.mac_addr[i] = mac_addr[i];
357 : 0 : rule.vlan_id = vlan_id;
358 : :
359 : 0 : ret = dpdmux_if_add_l2_rule(&dpdmux_dev->dpdmux, CMD_PRI_LOW,
360 : 0 : dpdmux_dev->token, dest_if, &rule);
361 [ # # ]: 0 : if (ret) {
362 : 0 : DPAA2_PMD_ERR("dpdmux_if_add_l2_rule failed:err(%d)", ret);
363 : 0 : return ret;
364 : : }
365 : :
366 : : return 0;
367 : : }
368 : :
369 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_dpaa2_mux_rx_frame_len, 21.05)
370 : : int
371 : 0 : rte_pmd_dpaa2_mux_rx_frame_len(uint32_t dpdmux_id, uint16_t max_rx_frame_len)
372 : : {
373 : : struct dpaa2_dpdmux_dev *dpdmux_dev;
374 : : int ret;
375 : :
376 : : /* Find the DPDMUX from dpdmux_id in our list */
377 : : dpdmux_dev = get_dpdmux_from_id(dpdmux_id);
378 [ # # ]: 0 : if (!dpdmux_dev) {
379 : 0 : DPAA2_PMD_ERR("Invalid dpdmux_id: %d", dpdmux_id);
380 : 0 : return -1;
381 : : }
382 : :
383 : 0 : ret = dpdmux_set_max_frame_length(&dpdmux_dev->dpdmux,
384 : 0 : CMD_PRI_LOW, dpdmux_dev->token, max_rx_frame_len);
385 [ # # ]: 0 : if (ret) {
386 : 0 : DPAA2_PMD_ERR("DPDMUX:Unable to set mtu. check config %d", ret);
387 : 0 : return ret;
388 : : }
389 : :
390 : 0 : DPAA2_PMD_INFO("dpdmux mtu set as %u",
391 : : DPAA2_MAX_RX_PKT_LEN - RTE_ETHER_CRC_LEN);
392 : :
393 : 0 : return ret;
394 : : }
395 : :
396 : : /* dump the status of the dpaa2_mux counters on the console */
397 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_dpaa2_mux_dump_counter, 24.11)
398 : : void
399 : 0 : rte_pmd_dpaa2_mux_dump_counter(FILE *f, uint32_t dpdmux_id, int num_if)
400 : : {
401 : : struct dpaa2_dpdmux_dev *dpdmux;
402 : : uint64_t counter;
403 : : int ret;
404 : : int if_id;
405 : :
406 : : /* Find the DPDMUX from dpdmux_id in our list */
407 : : dpdmux = get_dpdmux_from_id(dpdmux_id);
408 [ # # ]: 0 : if (!dpdmux) {
409 : 0 : DPAA2_PMD_ERR("Invalid dpdmux_id: %d", dpdmux_id);
410 : 0 : return;
411 : : }
412 : :
413 [ # # ]: 0 : for (if_id = 0; if_id < num_if; if_id++) {
414 : : fprintf(f, "dpdmux.%d\n", if_id);
415 : :
416 : 0 : ret = dpdmux_if_get_counter(&dpdmux->dpdmux, CMD_PRI_LOW,
417 : 0 : dpdmux->token, if_id, DPDMUX_CNT_ING_FRAME, &counter);
418 [ # # ]: 0 : if (!ret)
419 : 0 : fprintf(f, "DPDMUX_CNT_ING_FRAME %" PRIu64 "\n",
420 : : counter);
421 : 0 : ret = dpdmux_if_get_counter(&dpdmux->dpdmux, CMD_PRI_LOW,
422 : 0 : dpdmux->token, if_id, DPDMUX_CNT_ING_BYTE, &counter);
423 [ # # ]: 0 : if (!ret)
424 : 0 : fprintf(f, "DPDMUX_CNT_ING_BYTE %" PRIu64 "\n",
425 : : counter);
426 : 0 : ret = dpdmux_if_get_counter(&dpdmux->dpdmux, CMD_PRI_LOW,
427 : 0 : dpdmux->token, if_id, DPDMUX_CNT_ING_FLTR_FRAME,
428 : : &counter);
429 [ # # ]: 0 : if (!ret)
430 : 0 : fprintf(f, "DPDMUX_CNT_ING_FLTR_FRAME %" PRIu64 "\n",
431 : : counter);
432 : 0 : ret = dpdmux_if_get_counter(&dpdmux->dpdmux, CMD_PRI_LOW,
433 : 0 : dpdmux->token, if_id, DPDMUX_CNT_ING_FRAME_DISCARD,
434 : : &counter);
435 [ # # ]: 0 : if (!ret)
436 : 0 : fprintf(f, "DPDMUX_CNT_ING_FRAME_DISCARD %" PRIu64 "\n",
437 : : counter);
438 : 0 : ret = dpdmux_if_get_counter(&dpdmux->dpdmux, CMD_PRI_LOW,
439 : 0 : dpdmux->token, if_id, DPDMUX_CNT_ING_MCAST_FRAME,
440 : : &counter);
441 [ # # ]: 0 : if (!ret)
442 : 0 : fprintf(f, "DPDMUX_CNT_ING_MCAST_FRAME %" PRIu64 "\n",
443 : : counter);
444 : 0 : ret = dpdmux_if_get_counter(&dpdmux->dpdmux, CMD_PRI_LOW,
445 : 0 : dpdmux->token, if_id, DPDMUX_CNT_ING_MCAST_BYTE,
446 : : &counter);
447 [ # # ]: 0 : if (!ret)
448 : 0 : fprintf(f, "DPDMUX_CNT_ING_MCAST_BYTE %" PRIu64 "\n",
449 : : counter);
450 : 0 : ret = dpdmux_if_get_counter(&dpdmux->dpdmux, CMD_PRI_LOW,
451 : 0 : dpdmux->token, if_id, DPDMUX_CNT_ING_BCAST_FRAME,
452 : : &counter);
453 [ # # ]: 0 : if (!ret)
454 : 0 : fprintf(f, "DPDMUX_CNT_ING_BCAST_FRAME %" PRIu64 "\n",
455 : : counter);
456 : 0 : ret = dpdmux_if_get_counter(&dpdmux->dpdmux, CMD_PRI_LOW,
457 : 0 : dpdmux->token, if_id, DPDMUX_CNT_ING_BCAST_BYTES,
458 : : &counter);
459 [ # # ]: 0 : if (!ret)
460 : 0 : fprintf(f, "DPDMUX_CNT_ING_BCAST_BYTES %" PRIu64 "\n",
461 : : counter);
462 : 0 : ret = dpdmux_if_get_counter(&dpdmux->dpdmux, CMD_PRI_LOW,
463 : 0 : dpdmux->token, if_id, DPDMUX_CNT_EGR_FRAME, &counter);
464 [ # # ]: 0 : if (!ret)
465 : 0 : fprintf(f, "DPDMUX_CNT_EGR_FRAME %" PRIu64 "\n",
466 : : counter);
467 : 0 : ret = dpdmux_if_get_counter(&dpdmux->dpdmux, CMD_PRI_LOW,
468 : 0 : dpdmux->token, if_id, DPDMUX_CNT_EGR_BYTE, &counter);
469 [ # # ]: 0 : if (!ret)
470 : 0 : fprintf(f, "DPDMUX_CNT_EGR_BYTE %" PRIu64 "\n",
471 : : counter);
472 : 0 : ret = dpdmux_if_get_counter(&dpdmux->dpdmux, CMD_PRI_LOW,
473 : 0 : dpdmux->token, if_id, DPDMUX_CNT_EGR_FRAME_DISCARD,
474 : : &counter);
475 [ # # ]: 0 : if (!ret)
476 : 0 : fprintf(f, "DPDMUX_CNT_EGR_FRAME_DISCARD %" PRIu64 "\n",
477 : : counter);
478 : : }
479 : : }
480 : :
481 : : static int
482 : 0 : dpaa2_create_dpdmux_device(int vdev_fd __rte_unused,
483 : : struct vfio_device_info *obj_info __rte_unused,
484 : : struct rte_dpaa2_device *obj)
485 : : {
486 : : struct dpaa2_dpdmux_dev *dpdmux_dev;
487 : : struct dpdmux_attr attr;
488 : 0 : int ret, dpdmux_id = obj->object_id;
489 : : uint16_t maj_ver;
490 : : uint16_t min_ver;
491 : : uint8_t skip_reset_flags;
492 : :
493 : 0 : PMD_INIT_FUNC_TRACE();
494 : :
495 : : /* Allocate DPAA2 dpdmux handle */
496 : 0 : dpdmux_dev = rte_zmalloc(NULL,
497 : : sizeof(struct dpaa2_dpdmux_dev), RTE_CACHE_LINE_SIZE);
498 [ # # ]: 0 : if (!dpdmux_dev) {
499 : 0 : DPAA2_PMD_ERR("Memory allocation failed for DPDMUX Device");
500 : 0 : return -ENOMEM;
501 : : }
502 : :
503 : : /* Open the dpdmux object */
504 : 0 : dpdmux_dev->dpdmux.regs = dpaa2_get_mcp_ptr(MC_PORTAL_INDEX);
505 : 0 : ret = dpdmux_open(&dpdmux_dev->dpdmux, CMD_PRI_LOW, dpdmux_id,
506 : : &dpdmux_dev->token);
507 [ # # ]: 0 : if (ret) {
508 : 0 : DPAA2_PMD_ERR("Unable to open dpdmux object: err(%d)", ret);
509 : 0 : goto init_err;
510 : : }
511 : :
512 : 0 : ret = dpdmux_get_attributes(&dpdmux_dev->dpdmux, CMD_PRI_LOW,
513 : 0 : dpdmux_dev->token, &attr);
514 [ # # ]: 0 : if (ret) {
515 : 0 : DPAA2_PMD_ERR("Unable to get dpdmux attr: err(%d)", ret);
516 : 0 : goto init_err;
517 : : }
518 : :
519 [ # # ]: 0 : if (attr.method != DPDMUX_METHOD_C_VLAN_MAC) {
520 : 0 : ret = dpdmux_if_set_default(&dpdmux_dev->dpdmux, CMD_PRI_LOW,
521 : 0 : dpdmux_dev->token, attr.default_if);
522 [ # # ]: 0 : if (ret) {
523 : 0 : DPAA2_PMD_ERR("setting default interface failed in %s",
524 : : __func__);
525 : 0 : goto init_err;
526 : : }
527 : : skip_reset_flags = DPDMUX_SKIP_DEFAULT_INTERFACE
528 : : | DPDMUX_SKIP_UNICAST_RULES | DPDMUX_SKIP_MULTICAST_RULES;
529 : : } else {
530 : : skip_reset_flags = DPDMUX_SKIP_DEFAULT_INTERFACE;
531 : : }
532 : :
533 : 0 : ret = dpdmux_get_api_version(&dpdmux_dev->dpdmux, CMD_PRI_LOW,
534 : : &maj_ver, &min_ver);
535 [ # # ]: 0 : if (ret) {
536 : 0 : DPAA2_PMD_ERR("setting version failed in %s",
537 : : __func__);
538 : 0 : goto init_err;
539 : : }
540 : :
541 : : /* The new dpdmux_set/get_resetable() API are available starting with
542 : : * DPDMUX_VER_MAJOR==6 and DPDMUX_VER_MINOR==6
543 : : */
544 [ # # # # ]: 0 : if (maj_ver >= 6 && min_ver >= 6) {
545 : 0 : ret = dpdmux_set_resetable(&dpdmux_dev->dpdmux, CMD_PRI_LOW,
546 : 0 : dpdmux_dev->token, skip_reset_flags);
547 [ # # ]: 0 : if (ret) {
548 : 0 : DPAA2_PMD_ERR("setting default interface failed in %s",
549 : : __func__);
550 : 0 : goto init_err;
551 : : }
552 : : }
553 : :
554 [ # # # # ]: 0 : if (maj_ver >= 6 && min_ver >= 9) {
555 : : struct dpdmux_error_cfg mux_err_cfg;
556 : :
557 : : memset(&mux_err_cfg, 0, sizeof(mux_err_cfg));
558 : : /* Note: Discarded flag(DPDMUX_ERROR_DISC) has effect only when
559 : : * ERROR_ACTION is set to DPNI_ERROR_ACTION_SEND_TO_ERROR_QUEUE.
560 : : */
561 : 0 : mux_err_cfg.errors = DPDMUX_ALL_ERRORS;
562 : 0 : mux_err_cfg.error_action = DPDMUX_ERROR_ACTION_CONTINUE;
563 : :
564 : 0 : ret = dpdmux_if_set_errors_behavior(&dpdmux_dev->dpdmux,
565 : : CMD_PRI_LOW,
566 : 0 : dpdmux_dev->token, DPAA2_DPDMUX_DPMAC_IDX,
567 : : &mux_err_cfg);
568 [ # # ]: 0 : if (ret) {
569 : 0 : DPAA2_PMD_ERR("dpdmux_if_set_errors_behavior %s err %d",
570 : : __func__, ret);
571 : 0 : goto init_err;
572 : : }
573 : : }
574 : :
575 : 0 : dpdmux_dev->dpdmux_id = dpdmux_id;
576 : 0 : dpdmux_dev->num_ifs = attr.num_ifs;
577 : :
578 : 0 : TAILQ_INSERT_TAIL(&dpdmux_dev_list, dpdmux_dev, next);
579 : :
580 : 0 : return 0;
581 : :
582 : 0 : init_err:
583 : 0 : rte_free(dpdmux_dev);
584 : :
585 : 0 : return -1;
586 : : }
587 : :
588 : : static void
589 : 0 : dpaa2_close_dpdmux_device(int object_id)
590 : : {
591 : : struct dpaa2_dpdmux_dev *dpdmux_dev;
592 : :
593 : 0 : dpdmux_dev = get_dpdmux_from_id((uint32_t)object_id);
594 : :
595 [ # # ]: 0 : if (dpdmux_dev) {
596 : 0 : dpdmux_close(&dpdmux_dev->dpdmux, CMD_PRI_LOW,
597 : 0 : dpdmux_dev->token);
598 [ # # ]: 0 : TAILQ_REMOVE(&dpdmux_dev_list, dpdmux_dev, next);
599 : 0 : rte_free(dpdmux_dev);
600 : : }
601 : 0 : }
602 : :
603 : : static struct rte_dpaa2_object rte_dpaa2_dpdmux_obj = {
604 : : .dev_type = DPAA2_MUX,
605 : : .create = dpaa2_create_dpdmux_device,
606 : : .close = dpaa2_close_dpdmux_device,
607 : : };
608 : :
609 : 252 : RTE_PMD_REGISTER_DPAA2_OBJECT(dpdmux, rte_dpaa2_dpdmux_obj);
|