]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright (c) 2015-2018 Atomic Rules LLC | |
3 | */ | |
4 | ||
5 | #include <unistd.h> | |
6 | #include <sys/stat.h> | |
7 | #include <dlfcn.h> | |
8 | ||
9 | #include <rte_bus_pci.h> | |
10 | #include <rte_ethdev_pci.h> | |
11 | #include <rte_kvargs.h> | |
12 | ||
13 | #include "ark_global.h" | |
14 | #include "ark_logs.h" | |
15 | #include "ark_ethdev_tx.h" | |
16 | #include "ark_ethdev_rx.h" | |
17 | #include "ark_mpu.h" | |
18 | #include "ark_ddm.h" | |
19 | #include "ark_udm.h" | |
20 | #include "ark_rqp.h" | |
21 | #include "ark_pktdir.h" | |
22 | #include "ark_pktgen.h" | |
23 | #include "ark_pktchkr.h" | |
24 | ||
25 | /* Internal prototypes */ | |
26 | static int eth_ark_check_args(struct ark_adapter *ark, const char *params); | |
27 | static int eth_ark_dev_init(struct rte_eth_dev *dev); | |
28 | static int ark_config_device(struct rte_eth_dev *dev); | |
29 | static int eth_ark_dev_uninit(struct rte_eth_dev *eth_dev); | |
30 | static int eth_ark_dev_configure(struct rte_eth_dev *dev); | |
31 | static int eth_ark_dev_start(struct rte_eth_dev *dev); | |
32 | static void eth_ark_dev_stop(struct rte_eth_dev *dev); | |
33 | static void eth_ark_dev_close(struct rte_eth_dev *dev); | |
f67539c2 TL |
34 | static int eth_ark_dev_info_get(struct rte_eth_dev *dev, |
35 | struct rte_eth_dev_info *dev_info); | |
11fdf7f2 TL |
36 | static int eth_ark_dev_link_update(struct rte_eth_dev *dev, |
37 | int wait_to_complete); | |
38 | static int eth_ark_dev_set_link_up(struct rte_eth_dev *dev); | |
39 | static int eth_ark_dev_set_link_down(struct rte_eth_dev *dev); | |
40 | static int eth_ark_dev_stats_get(struct rte_eth_dev *dev, | |
41 | struct rte_eth_stats *stats); | |
f67539c2 | 42 | static int eth_ark_dev_stats_reset(struct rte_eth_dev *dev); |
11fdf7f2 | 43 | static int eth_ark_set_default_mac_addr(struct rte_eth_dev *dev, |
f67539c2 | 44 | struct rte_ether_addr *mac_addr); |
11fdf7f2 | 45 | static int eth_ark_macaddr_add(struct rte_eth_dev *dev, |
f67539c2 | 46 | struct rte_ether_addr *mac_addr, |
11fdf7f2 TL |
47 | uint32_t index, |
48 | uint32_t pool); | |
49 | static void eth_ark_macaddr_remove(struct rte_eth_dev *dev, | |
50 | uint32_t index); | |
51 | static int eth_ark_set_mtu(struct rte_eth_dev *dev, uint16_t size); | |
52 | ||
53 | /* | |
54 | * The packet generator is a functional block used to generate packet | |
55 | * patterns for testing. It is not intended for nominal use. | |
56 | */ | |
57 | #define ARK_PKTGEN_ARG "Pkt_gen" | |
58 | ||
59 | /* | |
60 | * The packet checker is a functional block used to verify packet | |
61 | * patterns for testing. It is not intended for nominal use. | |
62 | */ | |
63 | #define ARK_PKTCHKR_ARG "Pkt_chkr" | |
64 | ||
65 | /* | |
66 | * The packet director is used to select the internal ingress and | |
67 | * egress packets paths during testing. It is not intended for | |
68 | * nominal use. | |
69 | */ | |
70 | #define ARK_PKTDIR_ARG "Pkt_dir" | |
71 | ||
72 | /* Devinfo configurations */ | |
73 | #define ARK_RX_MAX_QUEUE (4096 * 4) | |
74 | #define ARK_RX_MIN_QUEUE (512) | |
75 | #define ARK_RX_MAX_PKT_LEN ((16 * 1024) - 128) | |
76 | #define ARK_RX_MIN_BUFSIZE (1024) | |
77 | ||
78 | #define ARK_TX_MAX_QUEUE (4096 * 4) | |
79 | #define ARK_TX_MIN_QUEUE (256) | |
80 | ||
f67539c2 TL |
81 | int ark_logtype; |
82 | ||
11fdf7f2 TL |
83 | static const char * const valid_arguments[] = { |
84 | ARK_PKTGEN_ARG, | |
85 | ARK_PKTCHKR_ARG, | |
86 | ARK_PKTDIR_ARG, | |
87 | NULL | |
88 | }; | |
89 | ||
90 | static const struct rte_pci_id pci_id_ark_map[] = { | |
91 | {RTE_PCI_DEVICE(0x1d6c, 0x100d)}, | |
92 | {RTE_PCI_DEVICE(0x1d6c, 0x100e)}, | |
93 | {.vendor_id = 0, /* sentinel */ }, | |
94 | }; | |
95 | ||
96 | static int | |
97 | eth_ark_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, | |
98 | struct rte_pci_device *pci_dev) | |
99 | { | |
100 | struct rte_eth_dev *eth_dev; | |
101 | int ret; | |
102 | ||
103 | eth_dev = rte_eth_dev_pci_allocate(pci_dev, sizeof(struct ark_adapter)); | |
104 | ||
105 | if (eth_dev == NULL) | |
106 | return -ENOMEM; | |
107 | ||
108 | ret = eth_ark_dev_init(eth_dev); | |
109 | if (ret) | |
110 | rte_eth_dev_pci_release(eth_dev); | |
111 | ||
112 | return ret; | |
113 | } | |
114 | ||
115 | static int | |
116 | eth_ark_pci_remove(struct rte_pci_device *pci_dev) | |
117 | { | |
118 | return rte_eth_dev_pci_generic_remove(pci_dev, eth_ark_dev_uninit); | |
119 | } | |
120 | ||
121 | static struct rte_pci_driver rte_ark_pmd = { | |
122 | .id_table = pci_id_ark_map, | |
123 | .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, | |
124 | .probe = eth_ark_pci_probe, | |
125 | .remove = eth_ark_pci_remove, | |
126 | }; | |
127 | ||
128 | static const struct eth_dev_ops ark_eth_dev_ops = { | |
129 | .dev_configure = eth_ark_dev_configure, | |
130 | .dev_start = eth_ark_dev_start, | |
131 | .dev_stop = eth_ark_dev_stop, | |
132 | .dev_close = eth_ark_dev_close, | |
133 | ||
134 | .dev_infos_get = eth_ark_dev_info_get, | |
135 | ||
136 | .rx_queue_setup = eth_ark_dev_rx_queue_setup, | |
137 | .rx_queue_count = eth_ark_dev_rx_queue_count, | |
138 | .tx_queue_setup = eth_ark_tx_queue_setup, | |
139 | ||
140 | .link_update = eth_ark_dev_link_update, | |
141 | .dev_set_link_up = eth_ark_dev_set_link_up, | |
142 | .dev_set_link_down = eth_ark_dev_set_link_down, | |
143 | ||
144 | .rx_queue_start = eth_ark_rx_start_queue, | |
145 | .rx_queue_stop = eth_ark_rx_stop_queue, | |
146 | ||
147 | .tx_queue_start = eth_ark_tx_queue_start, | |
148 | .tx_queue_stop = eth_ark_tx_queue_stop, | |
149 | ||
150 | .stats_get = eth_ark_dev_stats_get, | |
151 | .stats_reset = eth_ark_dev_stats_reset, | |
152 | ||
153 | .mac_addr_add = eth_ark_macaddr_add, | |
154 | .mac_addr_remove = eth_ark_macaddr_remove, | |
155 | .mac_addr_set = eth_ark_set_default_mac_addr, | |
156 | ||
157 | .mtu_set = eth_ark_set_mtu, | |
158 | }; | |
159 | ||
160 | static int | |
161 | check_for_ext(struct ark_adapter *ark) | |
162 | { | |
163 | int found = 0; | |
164 | ||
165 | /* Get the env */ | |
166 | const char *dllpath = getenv("ARK_EXT_PATH"); | |
167 | ||
168 | if (dllpath == NULL) { | |
169 | PMD_DEBUG_LOG(DEBUG, "ARK EXT NO dll path specified\n"); | |
170 | return 0; | |
171 | } | |
172 | PMD_DRV_LOG(INFO, "ARK EXT found dll path at %s\n", dllpath); | |
173 | ||
174 | /* Open and load the .so */ | |
175 | ark->d_handle = dlopen(dllpath, RTLD_LOCAL | RTLD_LAZY); | |
176 | if (ark->d_handle == NULL) { | |
177 | PMD_DRV_LOG(ERR, "Could not load user extension %s\n", | |
178 | dllpath); | |
179 | return -1; | |
180 | } | |
181 | PMD_DRV_LOG(INFO, "SUCCESS: loaded user extension %s\n", | |
182 | dllpath); | |
183 | ||
184 | /* Get the entry points */ | |
185 | ark->user_ext.dev_init = | |
186 | (void *(*)(struct rte_eth_dev *, void *, int)) | |
187 | dlsym(ark->d_handle, "dev_init"); | |
188 | PMD_DEBUG_LOG(DEBUG, "device ext init pointer = %p\n", | |
189 | ark->user_ext.dev_init); | |
190 | ark->user_ext.dev_get_port_count = | |
191 | (int (*)(struct rte_eth_dev *, void *)) | |
192 | dlsym(ark->d_handle, "dev_get_port_count"); | |
193 | ark->user_ext.dev_uninit = | |
194 | (void (*)(struct rte_eth_dev *, void *)) | |
195 | dlsym(ark->d_handle, "dev_uninit"); | |
196 | ark->user_ext.dev_configure = | |
197 | (int (*)(struct rte_eth_dev *, void *)) | |
198 | dlsym(ark->d_handle, "dev_configure"); | |
199 | ark->user_ext.dev_start = | |
200 | (int (*)(struct rte_eth_dev *, void *)) | |
201 | dlsym(ark->d_handle, "dev_start"); | |
202 | ark->user_ext.dev_stop = | |
203 | (void (*)(struct rte_eth_dev *, void *)) | |
204 | dlsym(ark->d_handle, "dev_stop"); | |
205 | ark->user_ext.dev_close = | |
206 | (void (*)(struct rte_eth_dev *, void *)) | |
207 | dlsym(ark->d_handle, "dev_close"); | |
208 | ark->user_ext.link_update = | |
209 | (int (*)(struct rte_eth_dev *, int, void *)) | |
210 | dlsym(ark->d_handle, "link_update"); | |
211 | ark->user_ext.dev_set_link_up = | |
212 | (int (*)(struct rte_eth_dev *, void *)) | |
213 | dlsym(ark->d_handle, "dev_set_link_up"); | |
214 | ark->user_ext.dev_set_link_down = | |
215 | (int (*)(struct rte_eth_dev *, void *)) | |
216 | dlsym(ark->d_handle, "dev_set_link_down"); | |
217 | ark->user_ext.stats_get = | |
218 | (int (*)(struct rte_eth_dev *, struct rte_eth_stats *, | |
219 | void *)) | |
220 | dlsym(ark->d_handle, "stats_get"); | |
221 | ark->user_ext.stats_reset = | |
222 | (void (*)(struct rte_eth_dev *, void *)) | |
223 | dlsym(ark->d_handle, "stats_reset"); | |
224 | ark->user_ext.mac_addr_add = | |
f67539c2 TL |
225 | (void (*)(struct rte_eth_dev *, struct rte_ether_addr *, |
226 | uint32_t, uint32_t, void *)) | |
11fdf7f2 TL |
227 | dlsym(ark->d_handle, "mac_addr_add"); |
228 | ark->user_ext.mac_addr_remove = | |
229 | (void (*)(struct rte_eth_dev *, uint32_t, void *)) | |
230 | dlsym(ark->d_handle, "mac_addr_remove"); | |
231 | ark->user_ext.mac_addr_set = | |
f67539c2 | 232 | (void (*)(struct rte_eth_dev *, struct rte_ether_addr *, |
11fdf7f2 TL |
233 | void *)) |
234 | dlsym(ark->d_handle, "mac_addr_set"); | |
235 | ark->user_ext.set_mtu = | |
236 | (int (*)(struct rte_eth_dev *, uint16_t, | |
237 | void *)) | |
238 | dlsym(ark->d_handle, "set_mtu"); | |
239 | ||
240 | return found; | |
241 | } | |
242 | ||
243 | static int | |
244 | eth_ark_dev_init(struct rte_eth_dev *dev) | |
245 | { | |
f67539c2 | 246 | struct ark_adapter *ark = dev->data->dev_private; |
11fdf7f2 TL |
247 | struct rte_pci_device *pci_dev; |
248 | int ret; | |
249 | int port_count = 1; | |
250 | int p; | |
251 | ||
252 | ark->eth_dev = dev; | |
253 | ||
254 | PMD_FUNC_LOG(DEBUG, "\n"); | |
255 | ||
256 | /* Check to see if there is an extension that we need to load */ | |
257 | ret = check_for_ext(ark); | |
258 | if (ret) | |
259 | return ret; | |
260 | pci_dev = RTE_ETH_DEV_TO_PCI(dev); | |
261 | rte_eth_copy_pci_info(dev, pci_dev); | |
262 | ||
263 | /* Use dummy function until setup */ | |
264 | dev->rx_pkt_burst = ð_ark_recv_pkts_noop; | |
265 | dev->tx_pkt_burst = ð_ark_xmit_pkts_noop; | |
f67539c2 TL |
266 | /* Let rte_eth_dev_close() release the port resources */ |
267 | dev->data->dev_flags |= RTE_ETH_DEV_CLOSE_REMOVE; | |
11fdf7f2 TL |
268 | |
269 | ark->bar0 = (uint8_t *)pci_dev->mem_resource[0].addr; | |
270 | ark->a_bar = (uint8_t *)pci_dev->mem_resource[2].addr; | |
271 | ||
272 | ark->sysctrl.v = (void *)&ark->bar0[ARK_SYSCTRL_BASE]; | |
273 | ark->mpurx.v = (void *)&ark->bar0[ARK_MPU_RX_BASE]; | |
274 | ark->udm.v = (void *)&ark->bar0[ARK_UDM_BASE]; | |
275 | ark->mputx.v = (void *)&ark->bar0[ARK_MPU_TX_BASE]; | |
276 | ark->ddm.v = (void *)&ark->bar0[ARK_DDM_BASE]; | |
277 | ark->cmac.v = (void *)&ark->bar0[ARK_CMAC_BASE]; | |
278 | ark->external.v = (void *)&ark->bar0[ARK_EXTERNAL_BASE]; | |
279 | ark->pktdir.v = (void *)&ark->bar0[ARK_PKTDIR_BASE]; | |
280 | ark->pktgen.v = (void *)&ark->bar0[ARK_PKTGEN_BASE]; | |
281 | ark->pktchkr.v = (void *)&ark->bar0[ARK_PKTCHKR_BASE]; | |
282 | ||
283 | ark->rqpacing = | |
284 | (struct ark_rqpace_t *)(ark->bar0 + ARK_RCPACING_BASE); | |
285 | ark->started = 0; | |
286 | ||
287 | PMD_DEBUG_LOG(INFO, "Sys Ctrl Const = 0x%x HW Commit_ID: %08x\n", | |
288 | ark->sysctrl.t32[4], | |
289 | rte_be_to_cpu_32(ark->sysctrl.t32[0x20 / 4])); | |
290 | PMD_DRV_LOG(INFO, "Arkville HW Commit_ID: %08x\n", | |
291 | rte_be_to_cpu_32(ark->sysctrl.t32[0x20 / 4])); | |
292 | ||
293 | /* If HW sanity test fails, return an error */ | |
294 | if (ark->sysctrl.t32[4] != 0xcafef00d) { | |
295 | PMD_DRV_LOG(ERR, | |
296 | "HW Sanity test has failed, expected constant" | |
297 | " 0x%x, read 0x%x (%s)\n", | |
298 | 0xcafef00d, | |
299 | ark->sysctrl.t32[4], __func__); | |
300 | return -1; | |
301 | } | |
302 | if (ark->sysctrl.t32[3] != 0) { | |
303 | if (ark_rqp_lasped(ark->rqpacing)) { | |
304 | PMD_DRV_LOG(ERR, "Arkville Evaluation System - " | |
305 | "Timer has Expired\n"); | |
306 | return -1; | |
307 | } | |
308 | PMD_DRV_LOG(WARNING, "Arkville Evaluation System - " | |
309 | "Timer is Running\n"); | |
310 | } | |
311 | ||
312 | PMD_DRV_LOG(INFO, | |
313 | "HW Sanity test has PASSED, expected constant" | |
314 | " 0x%x, read 0x%x (%s)\n", | |
315 | 0xcafef00d, ark->sysctrl.t32[4], __func__); | |
316 | ||
317 | /* We are a single function multi-port device. */ | |
318 | ret = ark_config_device(dev); | |
9f95a23c TL |
319 | if (ret) |
320 | return -1; | |
321 | ||
11fdf7f2 TL |
322 | dev->dev_ops = &ark_eth_dev_ops; |
323 | ||
f67539c2 | 324 | dev->data->mac_addrs = rte_zmalloc("ark", RTE_ETHER_ADDR_LEN, 0); |
11fdf7f2 TL |
325 | if (!dev->data->mac_addrs) { |
326 | PMD_DRV_LOG(ERR, | |
327 | "Failed to allocated memory for storing mac address" | |
328 | ); | |
329 | } | |
330 | ||
331 | if (ark->user_ext.dev_init) { | |
332 | ark->user_data[dev->data->port_id] = | |
333 | ark->user_ext.dev_init(dev, ark->a_bar, 0); | |
334 | if (!ark->user_data[dev->data->port_id]) { | |
335 | PMD_DRV_LOG(INFO, | |
336 | "Failed to initialize PMD extension!" | |
337 | " continuing without it\n"); | |
338 | memset(&ark->user_ext, 0, sizeof(struct ark_user_ext)); | |
339 | dlclose(ark->d_handle); | |
340 | } | |
341 | } | |
342 | ||
343 | if (pci_dev->device.devargs) | |
344 | ret = eth_ark_check_args(ark, pci_dev->device.devargs->args); | |
345 | else | |
346 | PMD_DRV_LOG(INFO, "No Device args found\n"); | |
347 | ||
348 | if (ret) | |
349 | goto error; | |
350 | /* | |
351 | * We will create additional devices based on the number of requested | |
352 | * ports | |
353 | */ | |
354 | if (ark->user_ext.dev_get_port_count) | |
355 | port_count = | |
356 | ark->user_ext.dev_get_port_count(dev, | |
357 | ark->user_data[dev->data->port_id]); | |
358 | ark->num_ports = port_count; | |
359 | ||
360 | for (p = 0; p < port_count; p++) { | |
361 | struct rte_eth_dev *eth_dev; | |
362 | char name[RTE_ETH_NAME_MAX_LEN]; | |
363 | ||
364 | snprintf(name, sizeof(name), "arketh%d", | |
365 | dev->data->port_id + p); | |
366 | ||
367 | if (p == 0) { | |
368 | /* First port is already allocated by DPDK */ | |
369 | eth_dev = ark->eth_dev; | |
370 | rte_eth_dev_probing_finish(eth_dev); | |
371 | continue; | |
372 | } | |
373 | ||
374 | /* reserve an ethdev entry */ | |
375 | eth_dev = rte_eth_dev_allocate(name); | |
376 | if (!eth_dev) { | |
377 | PMD_DRV_LOG(ERR, | |
378 | "Could not allocate eth_dev for port %d\n", | |
379 | p); | |
380 | goto error; | |
381 | } | |
382 | ||
383 | eth_dev->device = &pci_dev->device; | |
384 | eth_dev->data->dev_private = ark; | |
385 | eth_dev->dev_ops = ark->eth_dev->dev_ops; | |
386 | eth_dev->tx_pkt_burst = ark->eth_dev->tx_pkt_burst; | |
387 | eth_dev->rx_pkt_burst = ark->eth_dev->rx_pkt_burst; | |
388 | ||
389 | rte_eth_copy_pci_info(eth_dev, pci_dev); | |
390 | ||
f67539c2 TL |
391 | eth_dev->data->mac_addrs = rte_zmalloc(name, |
392 | RTE_ETHER_ADDR_LEN, 0); | |
11fdf7f2 TL |
393 | if (!eth_dev->data->mac_addrs) { |
394 | PMD_DRV_LOG(ERR, | |
395 | "Memory allocation for MAC failed!" | |
396 | " Exiting.\n"); | |
397 | goto error; | |
398 | } | |
399 | ||
400 | if (ark->user_ext.dev_init) { | |
401 | ark->user_data[eth_dev->data->port_id] = | |
402 | ark->user_ext.dev_init(dev, ark->a_bar, p); | |
403 | } | |
404 | ||
405 | rte_eth_dev_probing_finish(eth_dev); | |
406 | } | |
407 | ||
408 | return ret; | |
409 | ||
f67539c2 TL |
410 | error: |
411 | rte_free(dev->data->mac_addrs); | |
412 | dev->data->mac_addrs = NULL; | |
11fdf7f2 TL |
413 | return -1; |
414 | } | |
415 | ||
416 | /* | |
417 | *Initial device configuration when device is opened | |
418 | * setup the DDM, and UDM | |
419 | * Called once per PCIE device | |
420 | */ | |
421 | static int | |
422 | ark_config_device(struct rte_eth_dev *dev) | |
423 | { | |
f67539c2 | 424 | struct ark_adapter *ark = dev->data->dev_private; |
11fdf7f2 TL |
425 | uint16_t num_q, i; |
426 | struct ark_mpu_t *mpu; | |
427 | ||
428 | /* | |
429 | * Make sure that the packet director, generator and checker are in a | |
430 | * known state | |
431 | */ | |
432 | ark->start_pg = 0; | |
433 | ark->pg = ark_pktgen_init(ark->pktgen.v, 0, 1); | |
434 | if (ark->pg == NULL) | |
435 | return -1; | |
436 | ark_pktgen_reset(ark->pg); | |
437 | ark->pc = ark_pktchkr_init(ark->pktchkr.v, 0, 1); | |
438 | if (ark->pc == NULL) | |
439 | return -1; | |
440 | ark_pktchkr_stop(ark->pc); | |
441 | ark->pd = ark_pktdir_init(ark->pktdir.v); | |
442 | if (ark->pd == NULL) | |
443 | return -1; | |
444 | ||
445 | /* Verify HW */ | |
446 | if (ark_udm_verify(ark->udm.v)) | |
447 | return -1; | |
448 | if (ark_ddm_verify(ark->ddm.v)) | |
449 | return -1; | |
450 | ||
451 | /* UDM */ | |
452 | if (ark_udm_reset(ark->udm.v)) { | |
453 | PMD_DRV_LOG(ERR, "Unable to stop and reset UDM\n"); | |
454 | return -1; | |
455 | } | |
456 | /* Keep in reset until the MPU are cleared */ | |
457 | ||
458 | /* MPU reset */ | |
459 | mpu = ark->mpurx.v; | |
460 | num_q = ark_api_num_queues(mpu); | |
461 | ark->rx_queues = num_q; | |
462 | for (i = 0; i < num_q; i++) { | |
463 | ark_mpu_reset(mpu); | |
464 | mpu = RTE_PTR_ADD(mpu, ARK_MPU_QOFFSET); | |
465 | } | |
466 | ||
467 | ark_udm_stop(ark->udm.v, 0); | |
468 | ark_udm_configure(ark->udm.v, | |
469 | RTE_PKTMBUF_HEADROOM, | |
470 | RTE_MBUF_DEFAULT_DATAROOM, | |
471 | ARK_RX_WRITE_TIME_NS); | |
472 | ark_udm_stats_reset(ark->udm.v); | |
473 | ark_udm_stop(ark->udm.v, 0); | |
474 | ||
475 | /* TX -- DDM */ | |
476 | if (ark_ddm_stop(ark->ddm.v, 1)) | |
477 | PMD_DRV_LOG(ERR, "Unable to stop DDM\n"); | |
478 | ||
479 | mpu = ark->mputx.v; | |
480 | num_q = ark_api_num_queues(mpu); | |
481 | ark->tx_queues = num_q; | |
482 | for (i = 0; i < num_q; i++) { | |
483 | ark_mpu_reset(mpu); | |
484 | mpu = RTE_PTR_ADD(mpu, ARK_MPU_QOFFSET); | |
485 | } | |
486 | ||
487 | ark_ddm_reset(ark->ddm.v); | |
488 | ark_ddm_stats_reset(ark->ddm.v); | |
489 | ||
490 | ark_ddm_stop(ark->ddm.v, 0); | |
491 | ark_rqp_stats_reset(ark->rqpacing); | |
492 | ||
493 | return 0; | |
494 | } | |
495 | ||
496 | static int | |
497 | eth_ark_dev_uninit(struct rte_eth_dev *dev) | |
498 | { | |
f67539c2 | 499 | struct ark_adapter *ark = dev->data->dev_private; |
11fdf7f2 TL |
500 | |
501 | if (rte_eal_process_type() != RTE_PROC_PRIMARY) | |
502 | return 0; | |
503 | ||
504 | if (ark->user_ext.dev_uninit) | |
505 | ark->user_ext.dev_uninit(dev, | |
506 | ark->user_data[dev->data->port_id]); | |
507 | ||
508 | ark_pktgen_uninit(ark->pg); | |
509 | ark_pktchkr_uninit(ark->pc); | |
510 | ||
511 | dev->dev_ops = NULL; | |
512 | dev->rx_pkt_burst = NULL; | |
513 | dev->tx_pkt_burst = NULL; | |
11fdf7f2 TL |
514 | return 0; |
515 | } | |
516 | ||
517 | static int | |
518 | eth_ark_dev_configure(struct rte_eth_dev *dev) | |
519 | { | |
520 | PMD_FUNC_LOG(DEBUG, "\n"); | |
f67539c2 | 521 | struct ark_adapter *ark = dev->data->dev_private; |
11fdf7f2 TL |
522 | |
523 | eth_ark_dev_set_link_up(dev); | |
524 | if (ark->user_ext.dev_configure) | |
525 | return ark->user_ext.dev_configure(dev, | |
526 | ark->user_data[dev->data->port_id]); | |
527 | return 0; | |
528 | } | |
529 | ||
530 | static void * | |
531 | delay_pg_start(void *arg) | |
532 | { | |
533 | struct ark_adapter *ark = (struct ark_adapter *)arg; | |
534 | ||
535 | /* This function is used exclusively for regression testing, We | |
536 | * perform a blind sleep here to ensure that the external test | |
537 | * application has time to setup the test before we generate packets | |
538 | */ | |
539 | usleep(100000); | |
540 | ark_pktgen_run(ark->pg); | |
541 | return NULL; | |
542 | } | |
543 | ||
544 | static int | |
545 | eth_ark_dev_start(struct rte_eth_dev *dev) | |
546 | { | |
f67539c2 | 547 | struct ark_adapter *ark = dev->data->dev_private; |
11fdf7f2 TL |
548 | int i; |
549 | ||
550 | PMD_FUNC_LOG(DEBUG, "\n"); | |
551 | ||
552 | /* RX Side */ | |
553 | /* start UDM */ | |
554 | ark_udm_start(ark->udm.v); | |
555 | ||
556 | for (i = 0; i < dev->data->nb_rx_queues; i++) | |
557 | eth_ark_rx_start_queue(dev, i); | |
558 | ||
559 | /* TX Side */ | |
560 | for (i = 0; i < dev->data->nb_tx_queues; i++) | |
561 | eth_ark_tx_queue_start(dev, i); | |
562 | ||
563 | /* start DDM */ | |
564 | ark_ddm_start(ark->ddm.v); | |
565 | ||
566 | ark->started = 1; | |
567 | /* set xmit and receive function */ | |
568 | dev->rx_pkt_burst = ð_ark_recv_pkts; | |
569 | dev->tx_pkt_burst = ð_ark_xmit_pkts; | |
570 | ||
571 | if (ark->start_pg) | |
572 | ark_pktchkr_run(ark->pc); | |
573 | ||
574 | if (ark->start_pg && (dev->data->port_id == 0)) { | |
575 | pthread_t thread; | |
576 | ||
577 | /* Delay packet generatpr start allow the hardware to be ready | |
578 | * This is only used for sanity checking with internal generator | |
579 | */ | |
580 | if (pthread_create(&thread, NULL, delay_pg_start, ark)) { | |
581 | PMD_DRV_LOG(ERR, "Could not create pktgen " | |
582 | "starter thread\n"); | |
583 | return -1; | |
584 | } | |
585 | } | |
586 | ||
587 | if (ark->user_ext.dev_start) | |
588 | ark->user_ext.dev_start(dev, | |
589 | ark->user_data[dev->data->port_id]); | |
590 | ||
591 | return 0; | |
592 | } | |
593 | ||
594 | static void | |
595 | eth_ark_dev_stop(struct rte_eth_dev *dev) | |
596 | { | |
597 | uint16_t i; | |
598 | int status; | |
f67539c2 | 599 | struct ark_adapter *ark = dev->data->dev_private; |
11fdf7f2 TL |
600 | struct ark_mpu_t *mpu; |
601 | ||
602 | PMD_FUNC_LOG(DEBUG, "\n"); | |
603 | ||
604 | if (ark->started == 0) | |
605 | return; | |
606 | ark->started = 0; | |
607 | ||
608 | /* Stop the extension first */ | |
609 | if (ark->user_ext.dev_stop) | |
610 | ark->user_ext.dev_stop(dev, | |
611 | ark->user_data[dev->data->port_id]); | |
612 | ||
613 | /* Stop the packet generator */ | |
614 | if (ark->start_pg) | |
615 | ark_pktgen_pause(ark->pg); | |
616 | ||
617 | dev->rx_pkt_burst = ð_ark_recv_pkts_noop; | |
618 | dev->tx_pkt_burst = ð_ark_xmit_pkts_noop; | |
619 | ||
620 | /* STOP TX Side */ | |
621 | for (i = 0; i < dev->data->nb_tx_queues; i++) { | |
622 | status = eth_ark_tx_queue_stop(dev, i); | |
623 | if (status != 0) { | |
624 | uint16_t port = dev->data->port_id; | |
625 | PMD_DRV_LOG(ERR, | |
626 | "tx_queue stop anomaly" | |
627 | " port %u, queue %u\n", | |
628 | port, i); | |
629 | } | |
630 | } | |
631 | ||
632 | /* Stop DDM */ | |
633 | /* Wait up to 0.1 second. each stop is up to 1000 * 10 useconds */ | |
634 | for (i = 0; i < 10; i++) { | |
635 | status = ark_ddm_stop(ark->ddm.v, 1); | |
636 | if (status == 0) | |
637 | break; | |
638 | } | |
639 | if (status || i != 0) { | |
640 | PMD_DRV_LOG(ERR, "DDM stop anomaly. status:" | |
641 | " %d iter: %u. (%s)\n", | |
642 | status, | |
643 | i, | |
644 | __func__); | |
645 | ark_ddm_dump(ark->ddm.v, "Stop anomaly"); | |
646 | ||
647 | mpu = ark->mputx.v; | |
648 | for (i = 0; i < ark->tx_queues; i++) { | |
649 | ark_mpu_dump(mpu, "DDM failure dump", i); | |
650 | mpu = RTE_PTR_ADD(mpu, ARK_MPU_QOFFSET); | |
651 | } | |
652 | } | |
653 | ||
654 | /* STOP RX Side */ | |
655 | /* Stop UDM multiple tries attempted */ | |
656 | for (i = 0; i < 10; i++) { | |
657 | status = ark_udm_stop(ark->udm.v, 1); | |
658 | if (status == 0) | |
659 | break; | |
660 | } | |
661 | if (status || i != 0) { | |
662 | PMD_DRV_LOG(ERR, "UDM stop anomaly. status %d iter: %u. (%s)\n", | |
663 | status, i, __func__); | |
664 | ark_udm_dump(ark->udm.v, "Stop anomaly"); | |
665 | ||
666 | mpu = ark->mpurx.v; | |
667 | for (i = 0; i < ark->rx_queues; i++) { | |
668 | ark_mpu_dump(mpu, "UDM Stop anomaly", i); | |
669 | mpu = RTE_PTR_ADD(mpu, ARK_MPU_QOFFSET); | |
670 | } | |
671 | } | |
672 | ||
673 | ark_udm_dump_stats(ark->udm.v, "Post stop"); | |
674 | ark_udm_dump_perf(ark->udm.v, "Post stop"); | |
675 | ||
676 | for (i = 0; i < dev->data->nb_rx_queues; i++) | |
677 | eth_ark_rx_dump_queue(dev, i, __func__); | |
678 | ||
679 | /* Stop the packet checker if it is running */ | |
680 | if (ark->start_pg) { | |
681 | ark_pktchkr_dump_stats(ark->pc); | |
682 | ark_pktchkr_stop(ark->pc); | |
683 | } | |
684 | } | |
685 | ||
686 | static void | |
687 | eth_ark_dev_close(struct rte_eth_dev *dev) | |
688 | { | |
f67539c2 | 689 | struct ark_adapter *ark = dev->data->dev_private; |
11fdf7f2 TL |
690 | uint16_t i; |
691 | ||
692 | if (ark->user_ext.dev_close) | |
693 | ark->user_ext.dev_close(dev, | |
694 | ark->user_data[dev->data->port_id]); | |
695 | ||
696 | eth_ark_dev_stop(dev); | |
697 | eth_ark_udm_force_close(dev); | |
698 | ||
699 | /* | |
700 | * TODO This should only be called once for the device during shutdown | |
701 | */ | |
702 | ark_rqp_dump(ark->rqpacing); | |
703 | ||
704 | for (i = 0; i < dev->data->nb_tx_queues; i++) { | |
705 | eth_ark_tx_queue_release(dev->data->tx_queues[i]); | |
706 | dev->data->tx_queues[i] = 0; | |
707 | } | |
708 | ||
709 | for (i = 0; i < dev->data->nb_rx_queues; i++) { | |
710 | eth_ark_dev_rx_queue_release(dev->data->rx_queues[i]); | |
711 | dev->data->rx_queues[i] = 0; | |
712 | } | |
f67539c2 TL |
713 | |
714 | rte_free(dev->data->mac_addrs); | |
715 | dev->data->mac_addrs = 0; | |
11fdf7f2 TL |
716 | } |
717 | ||
f67539c2 | 718 | static int |
11fdf7f2 TL |
719 | eth_ark_dev_info_get(struct rte_eth_dev *dev, |
720 | struct rte_eth_dev_info *dev_info) | |
721 | { | |
f67539c2 | 722 | struct ark_adapter *ark = dev->data->dev_private; |
11fdf7f2 TL |
723 | struct ark_mpu_t *tx_mpu = RTE_PTR_ADD(ark->bar0, ARK_MPU_TX_BASE); |
724 | struct ark_mpu_t *rx_mpu = RTE_PTR_ADD(ark->bar0, ARK_MPU_RX_BASE); | |
725 | uint16_t ports = ark->num_ports; | |
726 | ||
727 | dev_info->max_rx_pktlen = ARK_RX_MAX_PKT_LEN; | |
728 | dev_info->min_rx_bufsize = ARK_RX_MIN_BUFSIZE; | |
729 | ||
730 | dev_info->max_rx_queues = ark_api_num_queues_per_port(rx_mpu, ports); | |
731 | dev_info->max_tx_queues = ark_api_num_queues_per_port(tx_mpu, ports); | |
732 | ||
733 | dev_info->rx_desc_lim = (struct rte_eth_desc_lim) { | |
734 | .nb_max = ARK_RX_MAX_QUEUE, | |
735 | .nb_min = ARK_RX_MIN_QUEUE, | |
736 | .nb_align = ARK_RX_MIN_QUEUE}; /* power of 2 */ | |
737 | ||
738 | dev_info->tx_desc_lim = (struct rte_eth_desc_lim) { | |
739 | .nb_max = ARK_TX_MAX_QUEUE, | |
740 | .nb_min = ARK_TX_MIN_QUEUE, | |
741 | .nb_align = ARK_TX_MIN_QUEUE}; /* power of 2 */ | |
742 | ||
743 | /* ARK PMD supports all line rates, how do we indicate that here ?? */ | |
744 | dev_info->speed_capa = (ETH_LINK_SPEED_1G | | |
745 | ETH_LINK_SPEED_10G | | |
746 | ETH_LINK_SPEED_25G | | |
747 | ETH_LINK_SPEED_40G | | |
748 | ETH_LINK_SPEED_50G | | |
749 | ETH_LINK_SPEED_100G); | |
f67539c2 TL |
750 | |
751 | return 0; | |
11fdf7f2 TL |
752 | } |
753 | ||
754 | static int | |
755 | eth_ark_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete) | |
756 | { | |
757 | PMD_DEBUG_LOG(DEBUG, "link status = %d\n", | |
758 | dev->data->dev_link.link_status); | |
f67539c2 | 759 | struct ark_adapter *ark = dev->data->dev_private; |
11fdf7f2 TL |
760 | |
761 | if (ark->user_ext.link_update) { | |
762 | return ark->user_ext.link_update | |
763 | (dev, wait_to_complete, | |
764 | ark->user_data[dev->data->port_id]); | |
765 | } | |
766 | return 0; | |
767 | } | |
768 | ||
769 | static int | |
770 | eth_ark_dev_set_link_up(struct rte_eth_dev *dev) | |
771 | { | |
772 | dev->data->dev_link.link_status = 1; | |
f67539c2 | 773 | struct ark_adapter *ark = dev->data->dev_private; |
11fdf7f2 TL |
774 | |
775 | if (ark->user_ext.dev_set_link_up) | |
776 | return ark->user_ext.dev_set_link_up(dev, | |
777 | ark->user_data[dev->data->port_id]); | |
778 | return 0; | |
779 | } | |
780 | ||
781 | static int | |
782 | eth_ark_dev_set_link_down(struct rte_eth_dev *dev) | |
783 | { | |
784 | dev->data->dev_link.link_status = 0; | |
f67539c2 | 785 | struct ark_adapter *ark = dev->data->dev_private; |
11fdf7f2 TL |
786 | |
787 | if (ark->user_ext.dev_set_link_down) | |
788 | return ark->user_ext.dev_set_link_down(dev, | |
789 | ark->user_data[dev->data->port_id]); | |
790 | return 0; | |
791 | } | |
792 | ||
793 | static int | |
794 | eth_ark_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) | |
795 | { | |
796 | uint16_t i; | |
f67539c2 | 797 | struct ark_adapter *ark = dev->data->dev_private; |
11fdf7f2 TL |
798 | |
799 | stats->ipackets = 0; | |
800 | stats->ibytes = 0; | |
801 | stats->opackets = 0; | |
802 | stats->obytes = 0; | |
803 | stats->imissed = 0; | |
804 | stats->oerrors = 0; | |
805 | ||
806 | for (i = 0; i < dev->data->nb_tx_queues; i++) | |
807 | eth_tx_queue_stats_get(dev->data->tx_queues[i], stats); | |
808 | for (i = 0; i < dev->data->nb_rx_queues; i++) | |
809 | eth_rx_queue_stats_get(dev->data->rx_queues[i], stats); | |
810 | if (ark->user_ext.stats_get) | |
811 | return ark->user_ext.stats_get(dev, stats, | |
812 | ark->user_data[dev->data->port_id]); | |
813 | return 0; | |
814 | } | |
815 | ||
f67539c2 | 816 | static int |
11fdf7f2 TL |
817 | eth_ark_dev_stats_reset(struct rte_eth_dev *dev) |
818 | { | |
819 | uint16_t i; | |
f67539c2 | 820 | struct ark_adapter *ark = dev->data->dev_private; |
11fdf7f2 TL |
821 | |
822 | for (i = 0; i < dev->data->nb_tx_queues; i++) | |
823 | eth_tx_queue_stats_reset(dev->data->tx_queues[i]); | |
824 | for (i = 0; i < dev->data->nb_rx_queues; i++) | |
825 | eth_rx_queue_stats_reset(dev->data->rx_queues[i]); | |
826 | if (ark->user_ext.stats_reset) | |
827 | ark->user_ext.stats_reset(dev, | |
828 | ark->user_data[dev->data->port_id]); | |
f67539c2 TL |
829 | |
830 | return 0; | |
11fdf7f2 TL |
831 | } |
832 | ||
833 | static int | |
834 | eth_ark_macaddr_add(struct rte_eth_dev *dev, | |
f67539c2 | 835 | struct rte_ether_addr *mac_addr, |
11fdf7f2 TL |
836 | uint32_t index, |
837 | uint32_t pool) | |
838 | { | |
f67539c2 | 839 | struct ark_adapter *ark = dev->data->dev_private; |
11fdf7f2 TL |
840 | |
841 | if (ark->user_ext.mac_addr_add) { | |
842 | ark->user_ext.mac_addr_add(dev, | |
843 | mac_addr, | |
844 | index, | |
845 | pool, | |
846 | ark->user_data[dev->data->port_id]); | |
847 | return 0; | |
848 | } | |
849 | return -ENOTSUP; | |
850 | } | |
851 | ||
852 | static void | |
853 | eth_ark_macaddr_remove(struct rte_eth_dev *dev, uint32_t index) | |
854 | { | |
f67539c2 | 855 | struct ark_adapter *ark = dev->data->dev_private; |
11fdf7f2 TL |
856 | |
857 | if (ark->user_ext.mac_addr_remove) | |
858 | ark->user_ext.mac_addr_remove(dev, index, | |
859 | ark->user_data[dev->data->port_id]); | |
860 | } | |
861 | ||
862 | static int | |
863 | eth_ark_set_default_mac_addr(struct rte_eth_dev *dev, | |
f67539c2 | 864 | struct rte_ether_addr *mac_addr) |
11fdf7f2 | 865 | { |
f67539c2 | 866 | struct ark_adapter *ark = dev->data->dev_private; |
11fdf7f2 TL |
867 | |
868 | if (ark->user_ext.mac_addr_set) { | |
869 | ark->user_ext.mac_addr_set(dev, mac_addr, | |
870 | ark->user_data[dev->data->port_id]); | |
871 | return 0; | |
872 | } | |
873 | return -ENOTSUP; | |
874 | } | |
875 | ||
876 | static int | |
877 | eth_ark_set_mtu(struct rte_eth_dev *dev, uint16_t size) | |
878 | { | |
f67539c2 | 879 | struct ark_adapter *ark = dev->data->dev_private; |
11fdf7f2 TL |
880 | |
881 | if (ark->user_ext.set_mtu) | |
882 | return ark->user_ext.set_mtu(dev, size, | |
883 | ark->user_data[dev->data->port_id]); | |
884 | ||
885 | return -ENOTSUP; | |
886 | } | |
887 | ||
888 | static inline int | |
889 | process_pktdir_arg(const char *key, const char *value, | |
890 | void *extra_args) | |
891 | { | |
892 | PMD_FUNC_LOG(DEBUG, "key = %s, value = %s\n", | |
893 | key, value); | |
894 | struct ark_adapter *ark = | |
895 | (struct ark_adapter *)extra_args; | |
896 | ||
897 | ark->pkt_dir_v = strtol(value, NULL, 16); | |
898 | PMD_FUNC_LOG(DEBUG, "pkt_dir_v = 0x%x\n", ark->pkt_dir_v); | |
899 | return 0; | |
900 | } | |
901 | ||
902 | static inline int | |
903 | process_file_args(const char *key, const char *value, void *extra_args) | |
904 | { | |
905 | PMD_FUNC_LOG(DEBUG, "key = %s, value = %s\n", | |
906 | key, value); | |
907 | char *args = (char *)extra_args; | |
908 | ||
909 | /* Open the configuration file */ | |
910 | FILE *file = fopen(value, "r"); | |
911 | char line[ARK_MAX_ARG_LEN]; | |
912 | int size = 0; | |
913 | int first = 1; | |
914 | ||
915 | if (file == NULL) { | |
916 | PMD_DRV_LOG(ERR, "Unable to open " | |
917 | "config file %s\n", value); | |
918 | return -1; | |
919 | } | |
920 | ||
921 | while (fgets(line, sizeof(line), file)) { | |
922 | size += strlen(line); | |
923 | if (size >= ARK_MAX_ARG_LEN) { | |
924 | PMD_DRV_LOG(ERR, "Unable to parse file %s args, " | |
925 | "parameter list is too long\n", value); | |
926 | fclose(file); | |
927 | return -1; | |
928 | } | |
929 | if (first) { | |
930 | strncpy(args, line, ARK_MAX_ARG_LEN); | |
931 | first = 0; | |
932 | } else { | |
933 | strncat(args, line, ARK_MAX_ARG_LEN); | |
934 | } | |
935 | } | |
936 | PMD_FUNC_LOG(DEBUG, "file = %s\n", args); | |
937 | fclose(file); | |
938 | return 0; | |
939 | } | |
940 | ||
941 | static int | |
942 | eth_ark_check_args(struct ark_adapter *ark, const char *params) | |
943 | { | |
944 | struct rte_kvargs *kvlist; | |
945 | unsigned int k_idx; | |
946 | struct rte_kvargs_pair *pair = NULL; | |
947 | int ret = -1; | |
948 | ||
949 | kvlist = rte_kvargs_parse(params, valid_arguments); | |
950 | if (kvlist == NULL) | |
951 | return 0; | |
952 | ||
953 | ark->pkt_gen_args[0] = 0; | |
954 | ark->pkt_chkr_args[0] = 0; | |
955 | ||
956 | for (k_idx = 0; k_idx < kvlist->count; k_idx++) { | |
957 | pair = &kvlist->pairs[k_idx]; | |
958 | PMD_FUNC_LOG(DEBUG, "**** Arg passed to PMD = %s:%s\n", | |
959 | pair->key, | |
960 | pair->value); | |
961 | } | |
962 | ||
963 | if (rte_kvargs_process(kvlist, | |
964 | ARK_PKTDIR_ARG, | |
965 | &process_pktdir_arg, | |
966 | ark) != 0) { | |
967 | PMD_DRV_LOG(ERR, "Unable to parse arg %s\n", ARK_PKTDIR_ARG); | |
968 | goto free_kvlist; | |
969 | } | |
970 | ||
971 | if (rte_kvargs_process(kvlist, | |
972 | ARK_PKTGEN_ARG, | |
973 | &process_file_args, | |
974 | ark->pkt_gen_args) != 0) { | |
975 | PMD_DRV_LOG(ERR, "Unable to parse arg %s\n", ARK_PKTGEN_ARG); | |
976 | goto free_kvlist; | |
977 | } | |
978 | ||
979 | if (rte_kvargs_process(kvlist, | |
980 | ARK_PKTCHKR_ARG, | |
981 | &process_file_args, | |
982 | ark->pkt_chkr_args) != 0) { | |
983 | PMD_DRV_LOG(ERR, "Unable to parse arg %s\n", ARK_PKTCHKR_ARG); | |
984 | goto free_kvlist; | |
985 | } | |
986 | ||
987 | PMD_DRV_LOG(INFO, "packet director set to 0x%x\n", ark->pkt_dir_v); | |
988 | /* Setup the packet director */ | |
989 | ark_pktdir_setup(ark->pd, ark->pkt_dir_v); | |
990 | ||
991 | /* Setup the packet generator */ | |
992 | if (ark->pkt_gen_args[0]) { | |
993 | PMD_DRV_LOG(INFO, "Setting up the packet generator\n"); | |
994 | ark_pktgen_parse(ark->pkt_gen_args); | |
995 | ark_pktgen_reset(ark->pg); | |
996 | ark_pktgen_setup(ark->pg); | |
997 | ark->start_pg = 1; | |
998 | } | |
999 | ||
1000 | /* Setup the packet checker */ | |
1001 | if (ark->pkt_chkr_args[0]) { | |
1002 | ark_pktchkr_parse(ark->pkt_chkr_args); | |
1003 | ark_pktchkr_setup(ark->pc); | |
1004 | } | |
1005 | ||
1006 | ret = 0; | |
1007 | ||
1008 | free_kvlist: | |
1009 | rte_kvargs_free(kvlist); | |
1010 | ||
1011 | return ret; | |
1012 | } | |
1013 | ||
1014 | RTE_PMD_REGISTER_PCI(net_ark, rte_ark_pmd); | |
1015 | RTE_PMD_REGISTER_KMOD_DEP(net_ark, "* igb_uio | uio_pci_generic "); | |
1016 | RTE_PMD_REGISTER_PCI_TABLE(net_ark, pci_id_ark_map); | |
1017 | RTE_PMD_REGISTER_PARAM_STRING(net_ark, | |
1018 | ARK_PKTGEN_ARG "=<filename> " | |
1019 | ARK_PKTCHKR_ARG "=<filename> " | |
1020 | ARK_PKTDIR_ARG "=<bitmap>"); | |
f67539c2 TL |
1021 | |
1022 | RTE_INIT(ark_init_log) | |
1023 | { | |
1024 | ark_logtype = rte_log_register("pmd.net.ark"); | |
1025 | if (ark_logtype >= 0) | |
1026 | rte_log_set_level(ark_logtype, RTE_LOG_NOTICE); | |
1027 | } |