508ea0130f7e0d5617fc6c28c482ec37f1d557f2
[dpdk.git] / drivers / net / ipn3ke / ipn3ke_ethdev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019 Intel Corporation
3  */
4
5 #include <stdint.h>
6
7 #include <rte_bus_pci.h>
8 #include <rte_ethdev.h>
9 #include <rte_pci.h>
10 #include <rte_malloc.h>
11
12 #include <rte_mbuf.h>
13 #include <rte_sched.h>
14 #include <rte_ethdev_driver.h>
15
16 #include <rte_io.h>
17 #include <rte_rawdev.h>
18 #include <rte_rawdev_pmd.h>
19 #include <rte_bus_ifpga.h>
20 #include <ifpga_common.h>
21 #include <ifpga_logs.h>
22
23 #include "ipn3ke_rawdev_api.h"
24 #include "ipn3ke_logs.h"
25 #include "ipn3ke_ethdev.h"
26
27 int ipn3ke_afu_logtype;
28
29 static const struct rte_afu_uuid afu_uuid_ipn3ke_map[] = {
30         { MAP_UUID_10G_LOW,  MAP_UUID_10G_HIGH },
31         { IPN3KE_UUID_10G_LOW, IPN3KE_UUID_10G_HIGH },
32         { IPN3KE_UUID_VBNG_LOW, IPN3KE_UUID_VBNG_HIGH},
33         { IPN3KE_UUID_25G_LOW, IPN3KE_UUID_25G_HIGH },
34         { 0, 0 /* sentinel */ },
35 };
36
37 static int
38 ipn3ke_indirect_read(struct ipn3ke_hw *hw, uint32_t *rd_data,
39         uint32_t addr, uint32_t dev_sel, uint32_t eth_group_sel)
40 {
41         uint32_t i, try_cnt;
42         uint64_t indirect_value;
43         volatile void *indirect_addrs;
44         uint64_t target_addr;
45         uint64_t read_data = 0;
46
47         if (eth_group_sel != 0 && eth_group_sel != 1)
48                 return -1;
49
50         addr &= 0x3FF;
51         target_addr = addr | dev_sel << 17;
52
53         indirect_value = RCMD | target_addr << 32;
54         indirect_addrs = hw->eth_group_bar[eth_group_sel] + 0x10;
55
56         rte_delay_us(10);
57
58         rte_write64((rte_cpu_to_le_64(indirect_value)), indirect_addrs);
59
60         i = 0;
61         try_cnt = 10;
62         indirect_addrs = hw->eth_group_bar[eth_group_sel] +
63                 0x18;
64         do {
65                 read_data = rte_read64(indirect_addrs);
66                 if ((read_data >> 32) == 1)
67                         break;
68                 i++;
69         } while (i <= try_cnt);
70         if (i > try_cnt)
71                 return -1;
72
73         *rd_data = rte_le_to_cpu_32(read_data);
74         return 0;
75 }
76
77 static int
78 ipn3ke_indirect_write(struct ipn3ke_hw *hw, uint32_t wr_data,
79         uint32_t addr, uint32_t dev_sel, uint32_t eth_group_sel)
80 {
81         volatile void *indirect_addrs;
82         uint64_t indirect_value;
83         uint64_t target_addr;
84
85         if (eth_group_sel != 0 && eth_group_sel != 1)
86                 return -1;
87
88         addr &= 0x3FF;
89         target_addr = addr | dev_sel << 17;
90
91         indirect_value = WCMD | target_addr << 32 | wr_data;
92         indirect_addrs = hw->eth_group_bar[eth_group_sel] + 0x10;
93
94         rte_write64((rte_cpu_to_le_64(indirect_value)), indirect_addrs);
95         return 0;
96 }
97
98 static int
99 ipn3ke_indirect_mac_read(struct ipn3ke_hw *hw, uint32_t *rd_data,
100         uint32_t addr, uint32_t mac_num, uint32_t eth_group_sel)
101 {
102         uint32_t dev_sel;
103
104         if (mac_num >= hw->port_num)
105                 return -1;
106
107         mac_num &= 0x7;
108         dev_sel = mac_num * 2 + 3;
109
110         return ipn3ke_indirect_read(hw, rd_data, addr, dev_sel, eth_group_sel);
111 }
112
113 static int
114 ipn3ke_indirect_mac_write(struct ipn3ke_hw *hw, uint32_t wr_data,
115         uint32_t addr, uint32_t mac_num, uint32_t eth_group_sel)
116 {
117         uint32_t dev_sel;
118
119         if (mac_num >= hw->port_num)
120                 return -1;
121
122         mac_num &= 0x7;
123         dev_sel = mac_num * 2 + 3;
124
125         return ipn3ke_indirect_write(hw, wr_data, addr, dev_sel, eth_group_sel);
126 }
127
128 static void
129 ipn3ke_hw_cap_init(struct ipn3ke_hw *hw)
130 {
131         hw->hw_cap.version_number = IPN3KE_MASK_READ_REG(hw,
132                         (IPN3KE_HW_BASE + 0), 0, 0xFFFF);
133         hw->hw_cap.capability_registers_block_offset = IPN3KE_MASK_READ_REG(hw,
134                         (IPN3KE_HW_BASE + 0x8), 0, 0xFFFFFFFF);
135         hw->hw_cap.status_registers_block_offset = IPN3KE_MASK_READ_REG(hw,
136                         (IPN3KE_HW_BASE + 0x10), 0, 0xFFFFFFFF);
137         hw->hw_cap.control_registers_block_offset = IPN3KE_MASK_READ_REG(hw,
138                         (IPN3KE_HW_BASE + 0x18), 0, 0xFFFFFFFF);
139         hw->hw_cap.classify_offset = IPN3KE_MASK_READ_REG(hw,
140                         (IPN3KE_HW_BASE + 0x20), 0, 0xFFFFFFFF);
141         hw->hw_cap.classy_size = IPN3KE_MASK_READ_REG(hw,
142                         (IPN3KE_HW_BASE + 0x24), 0, 0xFFFF);
143         hw->hw_cap.policer_offset = IPN3KE_MASK_READ_REG(hw,
144                         (IPN3KE_HW_BASE + 0x28), 0, 0xFFFFFFFF);
145         hw->hw_cap.policer_entry_size = IPN3KE_MASK_READ_REG(hw,
146                         (IPN3KE_HW_BASE + 0x2C), 0, 0xFFFF);
147         hw->hw_cap.rss_key_array_offset = IPN3KE_MASK_READ_REG(hw,
148                         (IPN3KE_HW_BASE + 0x30), 0, 0xFFFFFFFF);
149         hw->hw_cap.rss_key_entry_size = IPN3KE_MASK_READ_REG(hw,
150                         (IPN3KE_HW_BASE + 0x34), 0, 0xFFFF);
151         hw->hw_cap.rss_indirection_table_array_offset = IPN3KE_MASK_READ_REG(hw,
152                         (IPN3KE_HW_BASE + 0x38), 0, 0xFFFFFFFF);
153         hw->hw_cap.rss_indirection_table_entry_size = IPN3KE_MASK_READ_REG(hw,
154                         (IPN3KE_HW_BASE + 0x3C), 0, 0xFFFF);
155         hw->hw_cap.dmac_map_offset = IPN3KE_MASK_READ_REG(hw,
156                         (IPN3KE_HW_BASE + 0x40), 0, 0xFFFFFFFF);
157         hw->hw_cap.dmac_map_size = IPN3KE_MASK_READ_REG(hw,
158                         (IPN3KE_HW_BASE + 0x44), 0, 0xFFFF);
159         hw->hw_cap.qm_offset = IPN3KE_MASK_READ_REG(hw,
160                         (IPN3KE_HW_BASE + 0x48), 0, 0xFFFFFFFF);
161         hw->hw_cap.qm_size = IPN3KE_MASK_READ_REG(hw,
162                         (IPN3KE_HW_BASE + 0x4C), 0, 0xFFFF);
163         hw->hw_cap.ccb_offset = IPN3KE_MASK_READ_REG(hw,
164                         (IPN3KE_HW_BASE + 0x50), 0, 0xFFFFFFFF);
165         hw->hw_cap.ccb_entry_size = IPN3KE_MASK_READ_REG(hw,
166                         (IPN3KE_HW_BASE + 0x54), 0, 0xFFFF);
167         hw->hw_cap.qos_offset = IPN3KE_MASK_READ_REG(hw,
168                         (IPN3KE_HW_BASE + 0x58), 0, 0xFFFFFFFF);
169         hw->hw_cap.qos_size = IPN3KE_MASK_READ_REG(hw,
170                         (IPN3KE_HW_BASE + 0x5C), 0, 0xFFFF);
171
172         hw->hw_cap.num_rx_flow = IPN3KE_MASK_READ_REG(hw,
173                         IPN3KE_CAPABILITY_REGISTERS_BLOCK_OFFSET,
174                         0, 0xFFFF);
175         hw->hw_cap.num_rss_blocks = IPN3KE_MASK_READ_REG(hw,
176                         IPN3KE_CAPABILITY_REGISTERS_BLOCK_OFFSET,
177                         4, 0xFFFF);
178         hw->hw_cap.num_dmac_map = IPN3KE_MASK_READ_REG(hw,
179                         IPN3KE_CAPABILITY_REGISTERS_BLOCK_OFFSET,
180                         8, 0xFFFF);
181         hw->hw_cap.num_tx_flow = IPN3KE_MASK_READ_REG(hw,
182                         IPN3KE_CAPABILITY_REGISTERS_BLOCK_OFFSET,
183                         0xC, 0xFFFF);
184         hw->hw_cap.num_smac_map = IPN3KE_MASK_READ_REG(hw,
185                         IPN3KE_CAPABILITY_REGISTERS_BLOCK_OFFSET,
186                         0x10, 0xFFFF);
187
188         hw->hw_cap.link_speed_mbps = IPN3KE_MASK_READ_REG(hw,
189                         IPN3KE_STATUS_REGISTERS_BLOCK_OFFSET,
190                         0, 0xFFFFF);
191 }
192
193 static int
194 ipn3ke_hw_init(struct rte_afu_device *afu_dev,
195         struct ipn3ke_hw *hw)
196 {
197         struct rte_rawdev *rawdev;
198         int ret;
199         int i;
200         uint64_t port_num, mac_type, index;
201
202         rawdev  = afu_dev->rawdev;
203
204         hw->afu_id.uuid.uuid_low = afu_dev->id.uuid.uuid_low;
205         hw->afu_id.uuid.uuid_high = afu_dev->id.uuid.uuid_high;
206         hw->afu_id.port = afu_dev->id.port;
207         hw->hw_addr = (uint8_t *)(afu_dev->mem_resource[0].addr);
208         hw->f_mac_read = ipn3ke_indirect_mac_read;
209         hw->f_mac_write = ipn3ke_indirect_mac_write;
210         hw->rawdev = rawdev;
211         rawdev->dev_ops->attr_get(rawdev,
212                                 "LineSideBARIndex", &index);
213         hw->eth_group_bar[0] = (uint8_t *)(afu_dev->mem_resource[index].addr);
214         rawdev->dev_ops->attr_get(rawdev,
215                                 "NICSideBARIndex", &index);
216         hw->eth_group_bar[1] = (uint8_t *)(afu_dev->mem_resource[index].addr);
217         rawdev->dev_ops->attr_get(rawdev,
218                                 "LineSideLinkPortNum", &port_num);
219         hw->retimer.port_num = (int)port_num;
220         hw->port_num = hw->retimer.port_num;
221         rawdev->dev_ops->attr_get(rawdev,
222                                 "LineSideMACType", &mac_type);
223         hw->retimer.mac_type = (int)mac_type;
224
225         if (afu_dev->id.uuid.uuid_low == IPN3KE_UUID_VBNG_LOW &&
226                 afu_dev->id.uuid.uuid_high == IPN3KE_UUID_VBNG_HIGH) {
227                 ipn3ke_hw_cap_init(hw);
228                 IPN3KE_AFU_PMD_DEBUG("UPL_version is 0x%x\n",
229                         IPN3KE_READ_REG(hw, 0));
230
231                 /* Reset FPGA IP */
232                 IPN3KE_WRITE_REG(hw, IPN3KE_CTRL_RESET, 1);
233                 IPN3KE_WRITE_REG(hw, IPN3KE_CTRL_RESET, 0);
234         }
235
236         if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_10GE_XFI) {
237                 /* Enable inter connect channel */
238                 for (i = 0; i < hw->port_num; i++) {
239                         /* Enable the TX path */
240                         ipn3ke_xmac_tx_enable(hw, i, 1);
241
242                         /* Disables source address override */
243                         ipn3ke_xmac_smac_ovd_dis(hw, i, 1);
244
245                         /* Enable the RX path */
246                         ipn3ke_xmac_rx_enable(hw, i, 1);
247
248                         /* Clear all TX statistics counters */
249                         ipn3ke_xmac_tx_clr_stcs(hw, i, 1);
250
251                         /* Clear all RX statistics counters */
252                         ipn3ke_xmac_rx_clr_stcs(hw, i, 1);
253                 }
254         }
255
256         ret = rte_eth_switch_domain_alloc(&hw->switch_domain_id);
257         if (ret)
258                 IPN3KE_AFU_PMD_WARN("failed to allocate switch domain for device %d",
259                 ret);
260
261         hw->tm_hw_enable = 0;
262         hw->flow_hw_enable = 0;
263         if (afu_dev->id.uuid.uuid_low == IPN3KE_UUID_VBNG_LOW &&
264                 afu_dev->id.uuid.uuid_high == IPN3KE_UUID_VBNG_HIGH) {
265                 ret = ipn3ke_hw_tm_init(hw);
266                 if (ret)
267                         return ret;
268                 hw->tm_hw_enable = 1;
269                 hw->flow_hw_enable = 1;
270         }
271
272         hw->acc_tm = 0;
273         hw->acc_flow = 0;
274
275         return 0;
276 }
277
278 static void
279 ipn3ke_hw_uninit(struct ipn3ke_hw *hw)
280 {
281         int i;
282
283         if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_10GE_XFI) {
284                 for (i = 0; i < hw->port_num; i++) {
285                         /* Disable the TX path */
286                         ipn3ke_xmac_tx_disable(hw, i, 1);
287
288                         /* Disable the RX path */
289                         ipn3ke_xmac_rx_disable(hw, i, 1);
290
291                         /* Clear all TX statistics counters */
292                         ipn3ke_xmac_tx_clr_stcs(hw, i, 1);
293
294                         /* Clear all RX statistics counters */
295                         ipn3ke_xmac_rx_clr_stcs(hw, i, 1);
296                 }
297         }
298 }
299
300 static int ipn3ke_vswitch_probe(struct rte_afu_device *afu_dev)
301 {
302         char name[RTE_ETH_NAME_MAX_LEN];
303         struct ipn3ke_hw *hw;
304         int i, retval;
305
306         /* check if the AFU device has been probed already */
307         /* allocate shared mcp_vswitch structure */
308         if (!afu_dev->shared.data) {
309                 snprintf(name, sizeof(name), "net_%s_hw",
310                         afu_dev->device.name);
311                 hw = rte_zmalloc_socket(name,
312                                         sizeof(struct ipn3ke_hw),
313                                         RTE_CACHE_LINE_SIZE,
314                                         afu_dev->device.numa_node);
315                 if (!hw) {
316                         IPN3KE_AFU_PMD_ERR("failed to allocate hardwart data");
317                                 retval = -ENOMEM;
318                                 return -ENOMEM;
319                 }
320                 afu_dev->shared.data = hw;
321
322                 rte_spinlock_init(&afu_dev->shared.lock);
323         } else {
324                 hw = afu_dev->shared.data;
325         }
326
327         retval = ipn3ke_hw_init(afu_dev, hw);
328         if (retval)
329                 return retval;
330
331         /* probe representor ports */
332         for (i = 0; i < hw->port_num; i++) {
333                 struct ipn3ke_rpst rpst = {
334                         .port_id = i,
335                         .switch_domain_id = hw->switch_domain_id,
336                         .hw = hw
337                 };
338
339                 /* representor port net_bdf_port */
340                 snprintf(name, sizeof(name), "net_%s_representor_%d",
341                         afu_dev->device.name, i);
342
343                 retval = rte_eth_dev_create(&afu_dev->device, name,
344                         sizeof(struct ipn3ke_rpst), NULL, NULL,
345                         ipn3ke_rpst_init, &rpst);
346
347                 if (retval)
348                         IPN3KE_AFU_PMD_ERR("failed to create ipn3ke representor %s.",
349                                                                 name);
350         }
351
352         return 0;
353 }
354
355 static int ipn3ke_vswitch_remove(struct rte_afu_device *afu_dev)
356 {
357         char name[RTE_ETH_NAME_MAX_LEN];
358         struct ipn3ke_hw *hw;
359         struct rte_eth_dev *ethdev;
360         int i, ret;
361
362         hw = afu_dev->shared.data;
363
364         /* remove representor ports */
365         for (i = 0; i < hw->port_num; i++) {
366                 /* representor port net_bdf_port */
367                 snprintf(name, sizeof(name), "net_%s_representor_%d",
368                         afu_dev->device.name, i);
369
370                 ethdev = rte_eth_dev_allocated(afu_dev->device.name);
371                 if (!ethdev)
372                         return -ENODEV;
373
374                 rte_eth_dev_destroy(ethdev, ipn3ke_rpst_uninit);
375         }
376
377         ret = rte_eth_switch_domain_free(hw->switch_domain_id);
378         if (ret)
379                 IPN3KE_AFU_PMD_WARN("failed to free switch domain: %d", ret);
380
381         /* hw uninit*/
382         ipn3ke_hw_uninit(hw);
383
384         return 0;
385 }
386
387 static struct rte_afu_driver afu_ipn3ke_driver = {
388         .id_table = afu_uuid_ipn3ke_map,
389         .probe = ipn3ke_vswitch_probe,
390         .remove = ipn3ke_vswitch_remove,
391 };
392
393 RTE_PMD_REGISTER_AFU(net_ipn3ke_afu, afu_ipn3ke_driver);
394
395 static const char * const valid_args[] = {
396 #define IPN3KE_AFU_NAME         "afu"
397                 IPN3KE_AFU_NAME,
398 #define IPN3KE_FPGA_ACCELERATION_LIST     "fpga_acc"
399                 IPN3KE_FPGA_ACCELERATION_LIST,
400 #define IPN3KE_I40E_PF_LIST     "i40e_pf"
401                 IPN3KE_I40E_PF_LIST,
402                 NULL
403 };
404
405 static int
406 ipn3ke_cfg_parse_acc_list(const char *afu_name,
407         const char *acc_list_name)
408 {
409         struct rte_afu_device *afu_dev;
410         struct ipn3ke_hw *hw;
411         const char *p_source;
412         char *p_start;
413         char name[RTE_ETH_NAME_MAX_LEN];
414
415         afu_dev = rte_ifpga_find_afu_by_name(afu_name);
416         if (!afu_dev)
417                 return -1;
418         hw = afu_dev->shared.data;
419         if (!hw)
420                 return -1;
421
422         p_source = acc_list_name;
423         while (*p_source) {
424                 while ((*p_source == '{') || (*p_source == '|'))
425                         p_source++;
426                 p_start = name;
427                 while ((*p_source != '|') && (*p_source != '}'))
428                         *p_start++ = *p_source++;
429                 *p_start = 0;
430                 if (!strcmp(name, "tm") && hw->tm_hw_enable)
431                         hw->acc_tm = 1;
432
433                 if (!strcmp(name, "flow") && hw->flow_hw_enable)
434                         hw->acc_flow = 1;
435
436                 if (*p_source == '}')
437                         return 0;
438         }
439
440         return 0;
441 }
442
443 static int
444 ipn3ke_cfg_parse_i40e_pf_ethdev(const char *afu_name,
445         const char *pf_name)
446 {
447         struct rte_eth_dev *i40e_eth, *rpst_eth;
448         struct rte_afu_device *afu_dev;
449         struct ipn3ke_rpst *rpst;
450         struct ipn3ke_hw *hw;
451         const char *p_source;
452         char *p_start;
453         char name[RTE_ETH_NAME_MAX_LEN];
454         uint16_t port_id;
455         int i;
456         int ret = -1;
457
458         afu_dev = rte_ifpga_find_afu_by_name(afu_name);
459         if (!afu_dev)
460                 return -1;
461         hw = afu_dev->shared.data;
462         if (!hw)
463                 return -1;
464
465         p_source = pf_name;
466         for (i = 0; i < hw->port_num; i++) {
467                 snprintf(name, sizeof(name), "net_%s_representor_%d",
468                         afu_name, i);
469                 ret = rte_eth_dev_get_port_by_name(name, &port_id);
470                 if (ret)
471                         return -1;
472                 rpst_eth = &rte_eth_devices[port_id];
473                 rpst = IPN3KE_DEV_PRIVATE_TO_RPST(rpst_eth);
474
475                 while ((*p_source == '{') || (*p_source == '|'))
476                         p_source++;
477                 p_start = name;
478                 while ((*p_source != '|') && (*p_source != '}'))
479                         *p_start++ = *p_source++;
480                 *p_start = 0;
481
482                 ret = rte_eth_dev_get_port_by_name(name, &port_id);
483                 if (ret)
484                         return -1;
485                 i40e_eth = &rte_eth_devices[port_id];
486
487                 rpst->i40e_pf_eth = i40e_eth;
488                 rpst->i40e_pf_eth_port_id = port_id;
489
490                 if ((*p_source == '}') || !(*p_source))
491                         break;
492         }
493
494         return 0;
495 }
496
497 static int
498 ipn3ke_cfg_probe(struct rte_vdev_device *dev)
499 {
500         struct rte_devargs *devargs;
501         struct rte_kvargs *kvlist = NULL;
502         char *afu_name = NULL;
503         char *acc_name = NULL;
504         char *pf_name = NULL;
505         int afu_name_en = 0;
506         int acc_list_en = 0;
507         int pf_list_en = 0;
508         int ret = -1;
509
510         devargs = dev->device.devargs;
511
512         kvlist = rte_kvargs_parse(devargs->args, valid_args);
513         if (!kvlist) {
514                 IPN3KE_AFU_PMD_ERR("error when parsing param");
515                 goto end;
516         }
517
518         if (rte_kvargs_count(kvlist, IPN3KE_AFU_NAME) == 1) {
519                 if (rte_kvargs_process(kvlist, IPN3KE_AFU_NAME,
520                                        &rte_ifpga_get_string_arg,
521                                        &afu_name) < 0) {
522                         IPN3KE_AFU_PMD_ERR("error to parse %s",
523                                      IPN3KE_AFU_NAME);
524                         goto end;
525                 } else {
526                         afu_name_en = 1;
527                 }
528         }
529
530         if (rte_kvargs_count(kvlist, IPN3KE_FPGA_ACCELERATION_LIST) == 1) {
531                 if (rte_kvargs_process(kvlist, IPN3KE_FPGA_ACCELERATION_LIST,
532                                        &rte_ifpga_get_string_arg,
533                                        &acc_name) < 0) {
534                         IPN3KE_AFU_PMD_ERR("error to parse %s",
535                                      IPN3KE_FPGA_ACCELERATION_LIST);
536                         goto end;
537                 } else {
538                         acc_list_en = 1;
539                 }
540         }
541
542         if (rte_kvargs_count(kvlist, IPN3KE_I40E_PF_LIST) == 1) {
543                 if (rte_kvargs_process(kvlist, IPN3KE_I40E_PF_LIST,
544                                        &rte_ifpga_get_string_arg,
545                                        &pf_name) < 0) {
546                         IPN3KE_AFU_PMD_ERR("error to parse %s",
547                                      IPN3KE_I40E_PF_LIST);
548                         goto end;
549                 } else {
550                         pf_list_en = 1;
551                 }
552         }
553
554         if (!afu_name_en) {
555                 IPN3KE_AFU_PMD_ERR("arg %s is mandatory for ipn3ke",
556                           IPN3KE_AFU_NAME);
557                 goto end;
558         }
559
560         if (!pf_list_en) {
561                 IPN3KE_AFU_PMD_ERR("arg %s is mandatory for ipn3ke",
562                           IPN3KE_I40E_PF_LIST);
563                 goto end;
564         }
565
566         if (acc_list_en) {
567                 ret = ipn3ke_cfg_parse_acc_list(afu_name, acc_name);
568                 if (ret) {
569                         IPN3KE_AFU_PMD_ERR("arg %s parse error for ipn3ke",
570                           IPN3KE_FPGA_ACCELERATION_LIST);
571                         goto end;
572                 }
573         } else {
574                 IPN3KE_AFU_PMD_INFO("arg %s is optional for ipn3ke, using i40e acc",
575                           IPN3KE_FPGA_ACCELERATION_LIST);
576         }
577
578         ret = ipn3ke_cfg_parse_i40e_pf_ethdev(afu_name, pf_name);
579         if (ret)
580                 goto end;
581 end:
582         if (kvlist)
583                 rte_kvargs_free(kvlist);
584         if (afu_name)
585                 free(afu_name);
586         if (acc_name)
587                 free(acc_name);
588
589         return ret;
590 }
591
592 static int
593 ipn3ke_cfg_remove(struct rte_vdev_device *dev)
594 {
595         struct rte_devargs *devargs;
596         struct rte_kvargs *kvlist = NULL;
597         char *afu_name = NULL;
598         struct rte_afu_device *afu_dev;
599         int ret = -1;
600
601         devargs = dev->device.devargs;
602
603         kvlist = rte_kvargs_parse(devargs->args, valid_args);
604         if (!kvlist) {
605                 IPN3KE_AFU_PMD_ERR("error when parsing param");
606                 goto end;
607         }
608
609         if (rte_kvargs_count(kvlist, IPN3KE_AFU_NAME) == 1) {
610                 if (rte_kvargs_process(kvlist, IPN3KE_AFU_NAME,
611                                        &rte_ifpga_get_string_arg,
612                                        &afu_name) < 0) {
613                         IPN3KE_AFU_PMD_ERR("error to parse %s",
614                                      IPN3KE_AFU_NAME);
615                 } else {
616                         afu_dev = rte_ifpga_find_afu_by_name(afu_name);
617                         if (!afu_dev)
618                                 goto end;
619                         ret = ipn3ke_vswitch_remove(afu_dev);
620                 }
621         } else {
622                 IPN3KE_AFU_PMD_ERR("Remove ipn3ke_cfg %p error", dev);
623         }
624
625 end:
626         if (kvlist)
627                 rte_kvargs_free(kvlist);
628
629         return ret;
630 }
631
632 static struct rte_vdev_driver ipn3ke_cfg_driver = {
633         .probe = ipn3ke_cfg_probe,
634         .remove = ipn3ke_cfg_remove,
635 };
636
637 RTE_PMD_REGISTER_VDEV(ipn3ke_cfg, ipn3ke_cfg_driver);
638 RTE_PMD_REGISTER_PARAM_STRING(ipn3ke_cfg,
639         "afu=<string> "
640         "fpga_acc=<string>"
641         "i40e_pf=<string>");
642
643 RTE_INIT(ipn3ke_afu_init_log)
644 {
645         ipn3ke_afu_logtype = rte_log_register("pmd.afu.ipn3ke");
646         if (ipn3ke_afu_logtype >= 0)
647                 rte_log_set_level(ipn3ke_afu_logtype, RTE_LOG_NOTICE);
648 }