vdpa/mlx5: support device cleanup callback
[dpdk.git] / drivers / raw / cnxk_gpio / cnxk_gpio.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4
5 #include <dirent.h>
6 #include <string.h>
7
8 #include <rte_bus_vdev.h>
9 #include <rte_eal.h>
10 #include <rte_kvargs.h>
11 #include <rte_lcore.h>
12 #include <rte_rawdev_pmd.h>
13
14 #include <roc_api.h>
15
16 #include "cnxk_gpio.h"
17 #include "rte_pmd_cnxk_gpio.h"
18
19 #define CNXK_GPIO_BUFSZ 128
20 #define CNXK_GPIO_CLASS_PATH "/sys/class/gpio"
21
22 static const char *const cnxk_gpio_args[] = {
23 #define CNXK_GPIO_ARG_GPIOCHIP "gpiochip"
24         CNXK_GPIO_ARG_GPIOCHIP,
25 #define CNXK_GPIO_ARG_ALLOWLIST "allowlist"
26         CNXK_GPIO_ARG_ALLOWLIST,
27         NULL
28 };
29
30 static char *allowlist;
31
32 static void
33 cnxk_gpio_format_name(char *name, size_t len)
34 {
35         snprintf(name, len, "cnxk_gpio");
36 }
37
38 static int
39 cnxk_gpio_filter_gpiochip(const struct dirent *dirent)
40 {
41         const char *pattern = "gpiochip";
42
43         return !strncmp(dirent->d_name, pattern, strlen(pattern));
44 }
45
46 static void
47 cnxk_gpio_set_defaults(struct cnxk_gpiochip *gpiochip)
48 {
49         struct dirent **namelist;
50         int n;
51
52         n = scandir(CNXK_GPIO_CLASS_PATH, &namelist, cnxk_gpio_filter_gpiochip,
53                     alphasort);
54         if (n < 0 || n == 0)
55                 return;
56
57         sscanf(namelist[0]->d_name, "gpiochip%d", &gpiochip->num);
58         while (n--)
59                 free(namelist[n]);
60         free(namelist);
61 }
62
63 static int
64 cnxk_gpio_parse_arg_gpiochip(const char *key __rte_unused, const char *value,
65                              void *extra_args)
66 {
67         long val;
68
69         errno = 0;
70         val = strtol(value, NULL, 10);
71         if (errno)
72                 return -errno;
73
74         *(int *)extra_args = (int)val;
75
76         return 0;
77 }
78
79 static int
80 cnxk_gpio_parse_arg_allowlist(const char *key __rte_unused, const char *value,
81                               void *extra_args __rte_unused)
82 {
83         allowlist = strdup(value);
84         if (!allowlist)
85                 return -ENOMEM;
86
87         return 0;
88 }
89
90 static int
91 cnxk_gpio_parse_args(struct cnxk_gpiochip *gpiochip, const char *args)
92 {
93         struct rte_kvargs *kvlist;
94         int ret;
95
96         kvlist = rte_kvargs_parse(args, cnxk_gpio_args);
97         if (!kvlist)
98                 return 0;
99
100         ret = rte_kvargs_count(kvlist, CNXK_GPIO_ARG_GPIOCHIP);
101         if (ret == 1) {
102                 ret = rte_kvargs_process(kvlist, CNXK_GPIO_ARG_GPIOCHIP,
103                                          cnxk_gpio_parse_arg_gpiochip,
104                                          &gpiochip->num);
105                 if (ret)
106                         goto out;
107         }
108
109         ret = rte_kvargs_count(kvlist, CNXK_GPIO_ARG_ALLOWLIST);
110         if (ret == 1) {
111                 ret = rte_kvargs_process(kvlist, CNXK_GPIO_ARG_ALLOWLIST,
112                                          cnxk_gpio_parse_arg_allowlist, NULL);
113                 if (ret)
114                         goto out;
115         }
116
117         ret = 0;
118 out:
119         rte_kvargs_free(kvlist);
120
121         return ret;
122 }
123
124 static int
125 cnxk_gpio_parse_allowlist(struct cnxk_gpiochip *gpiochip)
126 {
127         int i, ret, val, queue = 0;
128         char *token;
129         int *list;
130
131         list = rte_calloc(NULL, gpiochip->num_gpios, sizeof(*list), 0);
132         if (!list)
133                 return -ENOMEM;
134
135         /* replace brackets with something meaningless for strtol() */
136         allowlist[0] = ' ';
137         allowlist[strlen(allowlist) - 1] = ' ';
138
139         /* quiesce -Wcast-qual */
140         token = strtok((char *)(uintptr_t)allowlist, ",");
141         do {
142                 errno = 0;
143                 val = strtol(token, NULL, 10);
144                 if (errno) {
145                         RTE_LOG(ERR, PMD, "failed to parse %s\n", token);
146                         ret = -errno;
147                         goto out;
148                 }
149
150                 if (val < 0 || val >= gpiochip->num_gpios) {
151                         RTE_LOG(ERR, PMD, "gpio%d out of 0-%d range\n", val,
152                                 gpiochip->num_gpios - 1);
153                         ret = -EINVAL;
154                         goto out;
155                 }
156
157                 for (i = 0; i < queue; i++) {
158                         if (list[i] != val)
159                                 continue;
160
161                         RTE_LOG(WARNING, PMD, "gpio%d already allowed\n", val);
162                         break;
163                 }
164                 if (i == queue)
165                         list[queue++] = val;
166         } while ((token = strtok(NULL, ",")));
167
168         gpiochip->allowlist = list;
169         gpiochip->num_queues = queue;
170
171         return 0;
172 out:
173         rte_free(list);
174
175         return ret;
176 }
177
178 static int
179 cnxk_gpio_read_attr(char *attr, char *val)
180 {
181         int ret, ret2;
182         FILE *fp;
183
184         fp = fopen(attr, "r");
185         if (!fp)
186                 return -errno;
187
188         ret = fscanf(fp, "%s", val);
189         if (ret < 0) {
190                 ret = -errno;
191                 goto out;
192         }
193         if (ret != 1) {
194                 ret = -EIO;
195                 goto out;
196         }
197
198         ret = 0;
199 out:
200         ret2 = fclose(fp);
201         if (!ret)
202                 ret = ret2;
203
204         return ret;
205 }
206
207 static int
208 cnxk_gpio_read_attr_int(char *attr, int *val)
209 {
210         char buf[CNXK_GPIO_BUFSZ];
211         int ret;
212
213         ret = cnxk_gpio_read_attr(attr, buf);
214         if (ret)
215                 return ret;
216
217         ret = sscanf(buf, "%d", val);
218         if (ret < 0)
219                 return -errno;
220
221         return 0;
222 }
223
224 static int
225 cnxk_gpio_write_attr(const char *attr, const char *val)
226 {
227         FILE *fp;
228         int ret;
229
230         if (!val)
231                 return -EINVAL;
232
233         fp = fopen(attr, "w");
234         if (!fp)
235                 return -errno;
236
237         ret = fprintf(fp, "%s", val);
238         if (ret < 0) {
239                 fclose(fp);
240                 return ret;
241         }
242
243         ret = fclose(fp);
244         if (ret)
245                 return -errno;
246
247         return 0;
248 }
249
250 static int
251 cnxk_gpio_write_attr_int(const char *attr, int val)
252 {
253         char buf[CNXK_GPIO_BUFSZ];
254
255         snprintf(buf, sizeof(buf), "%d", val);
256
257         return cnxk_gpio_write_attr(attr, buf);
258 }
259
260 static bool
261 cnxk_gpio_queue_valid(struct cnxk_gpiochip *gpiochip, uint16_t queue)
262 {
263         return queue < gpiochip->num_queues;
264 }
265
266 static int
267 cnxk_queue_to_gpio(struct cnxk_gpiochip *gpiochip, uint16_t queue)
268 {
269         return gpiochip->allowlist ? gpiochip->allowlist[queue] : queue;
270 }
271
272 static struct cnxk_gpio *
273 cnxk_gpio_lookup(struct cnxk_gpiochip *gpiochip, uint16_t queue)
274 {
275         int gpio = cnxk_queue_to_gpio(gpiochip, queue);
276
277         return gpiochip->gpios[gpio];
278 }
279
280 static int
281 cnxk_gpio_queue_setup(struct rte_rawdev *dev, uint16_t queue_id,
282                       rte_rawdev_obj_t queue_conf, size_t queue_conf_size)
283 {
284         struct cnxk_gpiochip *gpiochip = dev->dev_private;
285         char buf[CNXK_GPIO_BUFSZ];
286         struct cnxk_gpio *gpio;
287         int num, ret;
288
289         RTE_SET_USED(queue_conf);
290         RTE_SET_USED(queue_conf_size);
291
292         if (!cnxk_gpio_queue_valid(gpiochip, queue_id))
293                 return -EINVAL;
294
295         gpio = cnxk_gpio_lookup(gpiochip, queue_id);
296         if (gpio)
297                 return -EEXIST;
298
299         gpio = rte_zmalloc(NULL, sizeof(*gpio), 0);
300         if (!gpio)
301                 return -ENOMEM;
302
303         num = cnxk_queue_to_gpio(gpiochip, queue_id);
304         gpio->num = num + gpiochip->base;
305         gpio->gpiochip = gpiochip;
306
307         snprintf(buf, sizeof(buf), "%s/export", CNXK_GPIO_CLASS_PATH);
308         ret = cnxk_gpio_write_attr_int(buf, gpio->num);
309         if (ret) {
310                 rte_free(gpio);
311                 return ret;
312         }
313
314         gpiochip->gpios[num] = gpio;
315
316         return 0;
317 }
318
319 static int
320 cnxk_gpio_queue_release(struct rte_rawdev *dev, uint16_t queue_id)
321 {
322         struct cnxk_gpiochip *gpiochip = dev->dev_private;
323         char buf[CNXK_GPIO_BUFSZ];
324         struct cnxk_gpio *gpio;
325         int num, ret;
326
327         if (!cnxk_gpio_queue_valid(gpiochip, queue_id))
328                 return -EINVAL;
329
330         gpio = cnxk_gpio_lookup(gpiochip, queue_id);
331         if (!gpio)
332                 return -ENODEV;
333
334         snprintf(buf, sizeof(buf), "%s/unexport", CNXK_GPIO_CLASS_PATH);
335         ret = cnxk_gpio_write_attr_int(buf, gpio->num);
336         if (ret)
337                 return ret;
338
339         num = cnxk_queue_to_gpio(gpiochip, queue_id);
340         gpiochip->gpios[num] = NULL;
341         rte_free(gpio);
342
343         return 0;
344 }
345
346 static int
347 cnxk_gpio_queue_def_conf(struct rte_rawdev *dev, uint16_t queue_id,
348                          rte_rawdev_obj_t queue_conf, size_t queue_conf_size)
349 {
350         struct cnxk_gpiochip *gpiochip = dev->dev_private;
351         struct cnxk_gpio_queue_conf *conf = queue_conf;
352
353         if (!cnxk_gpio_queue_valid(gpiochip, queue_id))
354                 return -EINVAL;
355
356         if (queue_conf_size != sizeof(*conf))
357                 return -EINVAL;
358
359         conf->size = 1;
360         conf->gpio = cnxk_queue_to_gpio(gpiochip, queue_id);
361
362         return 0;
363 }
364
365 static uint16_t
366 cnxk_gpio_queue_count(struct rte_rawdev *dev)
367 {
368         struct cnxk_gpiochip *gpiochip = dev->dev_private;
369
370         return gpiochip->num_queues;
371 }
372
373 static const struct {
374         enum cnxk_gpio_pin_edge edge;
375         const char *name;
376 } cnxk_gpio_edge_name[] = {
377         { CNXK_GPIO_PIN_EDGE_NONE, "none" },
378         { CNXK_GPIO_PIN_EDGE_FALLING, "falling" },
379         { CNXK_GPIO_PIN_EDGE_RISING, "rising" },
380         { CNXK_GPIO_PIN_EDGE_BOTH, "both" },
381 };
382
383 static const char *
384 cnxk_gpio_edge_to_name(enum cnxk_gpio_pin_edge edge)
385 {
386         unsigned int i;
387
388         for (i = 0; i < RTE_DIM(cnxk_gpio_edge_name); i++) {
389                 if (cnxk_gpio_edge_name[i].edge == edge)
390                         return cnxk_gpio_edge_name[i].name;
391         }
392
393         return NULL;
394 }
395
396 static enum cnxk_gpio_pin_edge
397 cnxk_gpio_name_to_edge(const char *name)
398 {
399         unsigned int i;
400
401         for (i = 0; i < RTE_DIM(cnxk_gpio_edge_name); i++) {
402                 if (!strcmp(cnxk_gpio_edge_name[i].name, name))
403                         break;
404         }
405
406         return cnxk_gpio_edge_name[i].edge;
407 }
408
409 static const struct {
410         enum cnxk_gpio_pin_dir dir;
411         const char *name;
412 } cnxk_gpio_dir_name[] = {
413         { CNXK_GPIO_PIN_DIR_IN, "in" },
414         { CNXK_GPIO_PIN_DIR_OUT, "out" },
415         { CNXK_GPIO_PIN_DIR_HIGH, "high" },
416         { CNXK_GPIO_PIN_DIR_LOW, "low" },
417 };
418
419 static const char *
420 cnxk_gpio_dir_to_name(enum cnxk_gpio_pin_dir dir)
421 {
422         unsigned int i;
423
424         for (i = 0; i < RTE_DIM(cnxk_gpio_dir_name); i++) {
425                 if (cnxk_gpio_dir_name[i].dir == dir)
426                         return cnxk_gpio_dir_name[i].name;
427         }
428
429         return NULL;
430 }
431
432 static enum cnxk_gpio_pin_dir
433 cnxk_gpio_name_to_dir(const char *name)
434 {
435         unsigned int i;
436
437         for (i = 0; i < RTE_DIM(cnxk_gpio_dir_name); i++) {
438                 if (!strcmp(cnxk_gpio_dir_name[i].name, name))
439                         break;
440         }
441
442         return cnxk_gpio_dir_name[i].dir;
443 }
444
445 static int
446 cnxk_gpio_register_irq(struct cnxk_gpio *gpio, struct cnxk_gpio_irq *irq)
447 {
448         int ret;
449
450         ret = cnxk_gpio_irq_request(gpio->num - gpio->gpiochip->base, irq->cpu);
451         if (ret)
452                 return ret;
453
454         gpio->handler = irq->handler;
455         gpio->data = irq->data;
456         gpio->cpu = irq->cpu;
457
458         return 0;
459 }
460
461 static int
462 cnxk_gpio_unregister_irq(struct cnxk_gpio *gpio)
463 {
464         return cnxk_gpio_irq_free(gpio->num - gpio->gpiochip->base);
465 }
466
467 static int
468 cnxk_gpio_process_buf(struct cnxk_gpio *gpio, struct rte_rawdev_buf *rbuf)
469 {
470         struct cnxk_gpio_msg *msg = rbuf->buf_addr;
471         enum cnxk_gpio_pin_edge edge;
472         enum cnxk_gpio_pin_dir dir;
473         char buf[CNXK_GPIO_BUFSZ];
474         void *rsp = NULL;
475         int ret, val, n;
476
477         n = snprintf(buf, sizeof(buf), "%s/gpio%d", CNXK_GPIO_CLASS_PATH,
478                      gpio->num);
479
480         switch (msg->type) {
481         case CNXK_GPIO_MSG_TYPE_SET_PIN_VALUE:
482                 snprintf(buf + n, sizeof(buf) - n, "/value");
483                 ret = cnxk_gpio_write_attr_int(buf, !!*(int *)msg->data);
484                 break;
485         case CNXK_GPIO_MSG_TYPE_SET_PIN_EDGE:
486                 snprintf(buf + n, sizeof(buf) - n, "/edge");
487                 edge = *(enum cnxk_gpio_pin_edge *)msg->data;
488                 ret = cnxk_gpio_write_attr(buf, cnxk_gpio_edge_to_name(edge));
489                 break;
490         case CNXK_GPIO_MSG_TYPE_SET_PIN_DIR:
491                 snprintf(buf + n, sizeof(buf) - n, "/direction");
492                 dir = *(enum cnxk_gpio_pin_dir *)msg->data;
493                 ret = cnxk_gpio_write_attr(buf, cnxk_gpio_dir_to_name(dir));
494                 break;
495         case CNXK_GPIO_MSG_TYPE_SET_PIN_ACTIVE_LOW:
496                 snprintf(buf + n, sizeof(buf) - n, "/active_low");
497                 val = *(int *)msg->data;
498                 ret = cnxk_gpio_write_attr_int(buf, val);
499                 break;
500         case CNXK_GPIO_MSG_TYPE_GET_PIN_VALUE:
501                 snprintf(buf + n, sizeof(buf) - n, "/value");
502                 ret = cnxk_gpio_read_attr_int(buf, &val);
503                 if (ret)
504                         break;
505
506                 rsp = rte_zmalloc(NULL, sizeof(int), 0);
507                 if (!rsp)
508                         return -ENOMEM;
509
510                 *(int *)rsp = val;
511                 break;
512         case CNXK_GPIO_MSG_TYPE_GET_PIN_EDGE:
513                 snprintf(buf + n, sizeof(buf) - n, "/edge");
514                 ret = cnxk_gpio_read_attr(buf, buf);
515                 if (ret)
516                         break;
517
518                 rsp = rte_zmalloc(NULL, sizeof(enum cnxk_gpio_pin_edge), 0);
519                 if (!rsp)
520                         return -ENOMEM;
521
522                 *(enum cnxk_gpio_pin_edge *)rsp = cnxk_gpio_name_to_edge(buf);
523                 break;
524         case CNXK_GPIO_MSG_TYPE_GET_PIN_DIR:
525                 snprintf(buf + n, sizeof(buf) - n, "/direction");
526                 ret = cnxk_gpio_read_attr(buf, buf);
527                 if (ret)
528                         break;
529
530                 rsp = rte_zmalloc(NULL, sizeof(enum cnxk_gpio_pin_dir), 0);
531                 if (!rsp)
532                         return -ENOMEM;
533
534                 *(enum cnxk_gpio_pin_dir *)rsp = cnxk_gpio_name_to_dir(buf);
535                 break;
536         case CNXK_GPIO_MSG_TYPE_GET_PIN_ACTIVE_LOW:
537                 snprintf(buf + n, sizeof(buf) - n, "/active_low");
538                 ret = cnxk_gpio_read_attr_int(buf, &val);
539                 if (ret)
540                         break;
541
542                 rsp = rte_zmalloc(NULL, sizeof(int), 0);
543                 if (!rsp)
544                         return -ENOMEM;
545
546                 *(int *)rsp = val;
547                 break;
548         case CNXK_GPIO_MSG_TYPE_REGISTER_IRQ:
549                 ret = cnxk_gpio_register_irq(gpio,
550                                              (struct cnxk_gpio_irq *)msg->data);
551                 break;
552         case CNXK_GPIO_MSG_TYPE_UNREGISTER_IRQ:
553                 ret = cnxk_gpio_unregister_irq(gpio);
554                 break;
555         default:
556                 return -EINVAL;
557         }
558
559         /* get rid of last response if any */
560         if (gpio->rsp) {
561                 RTE_LOG(WARNING, PMD, "previous response got overwritten\n");
562                 rte_free(gpio->rsp);
563         }
564         gpio->rsp = rsp;
565
566         return ret;
567 }
568
569 static bool
570 cnxk_gpio_valid(struct cnxk_gpiochip *gpiochip, int gpio)
571 {
572         return gpio < gpiochip->num_gpios && gpiochip->gpios[gpio];
573 }
574
575 static int
576 cnxk_gpio_enqueue_bufs(struct rte_rawdev *dev, struct rte_rawdev_buf **buffers,
577                        unsigned int count, rte_rawdev_obj_t context)
578 {
579         struct cnxk_gpiochip *gpiochip = dev->dev_private;
580         unsigned int gpio_num = (size_t)context;
581         struct cnxk_gpio *gpio;
582         int ret;
583
584         if (count == 0)
585                 return 0;
586
587         if (!cnxk_gpio_valid(gpiochip, gpio_num))
588                 return -EINVAL;
589         gpio = gpiochip->gpios[gpio_num];
590
591         ret = cnxk_gpio_process_buf(gpio, buffers[0]);
592         if (ret)
593                 return ret;
594
595         return 1;
596 }
597
598 static int
599 cnxk_gpio_dequeue_bufs(struct rte_rawdev *dev, struct rte_rawdev_buf **buffers,
600                        unsigned int count, rte_rawdev_obj_t context)
601 {
602         struct cnxk_gpiochip *gpiochip = dev->dev_private;
603         unsigned int gpio_num = (size_t)context;
604         struct cnxk_gpio *gpio;
605
606         if (count == 0)
607                 return 0;
608
609         if (!cnxk_gpio_valid(gpiochip, gpio_num))
610                 return -EINVAL;
611         gpio = gpiochip->gpios[gpio_num];
612
613         if (gpio->rsp) {
614                 buffers[0]->buf_addr = gpio->rsp;
615                 gpio->rsp = NULL;
616
617                 return 1;
618         }
619
620         return 0;
621 }
622
623 static int
624 cnxk_gpio_dev_close(struct rte_rawdev *dev)
625 {
626         RTE_SET_USED(dev);
627
628         return 0;
629 }
630
631 static const struct rte_rawdev_ops cnxk_gpio_rawdev_ops = {
632         .dev_close = cnxk_gpio_dev_close,
633         .enqueue_bufs = cnxk_gpio_enqueue_bufs,
634         .dequeue_bufs = cnxk_gpio_dequeue_bufs,
635         .queue_def_conf = cnxk_gpio_queue_def_conf,
636         .queue_count = cnxk_gpio_queue_count,
637         .queue_setup = cnxk_gpio_queue_setup,
638         .queue_release = cnxk_gpio_queue_release,
639         .dev_selftest = cnxk_gpio_selftest,
640 };
641
642 static int
643 cnxk_gpio_probe(struct rte_vdev_device *dev)
644 {
645         char name[RTE_RAWDEV_NAME_MAX_LEN];
646         struct cnxk_gpiochip *gpiochip;
647         struct rte_rawdev *rawdev;
648         char buf[CNXK_GPIO_BUFSZ];
649         int ret;
650
651         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
652                 return 0;
653
654         cnxk_gpio_format_name(name, sizeof(name));
655         rawdev = rte_rawdev_pmd_allocate(name, sizeof(*gpiochip),
656                                          rte_socket_id());
657         if (!rawdev) {
658                 RTE_LOG(ERR, PMD, "failed to allocate %s rawdev", name);
659                 return -ENOMEM;
660         }
661
662         rawdev->dev_ops = &cnxk_gpio_rawdev_ops;
663         rawdev->device = &dev->device;
664         rawdev->driver_name = dev->device.name;
665
666         gpiochip = rawdev->dev_private;
667         cnxk_gpio_set_defaults(gpiochip);
668
669         /* defaults may be overwritten by this call */
670         ret = cnxk_gpio_parse_args(gpiochip, rte_vdev_device_args(dev));
671         if (ret)
672                 goto out;
673
674         ret = cnxk_gpio_irq_init(gpiochip);
675         if (ret)
676                 goto out;
677
678         /* read gpio base */
679         snprintf(buf, sizeof(buf), "%s/gpiochip%d/base", CNXK_GPIO_CLASS_PATH,
680                  gpiochip->num);
681         ret = cnxk_gpio_read_attr_int(buf, &gpiochip->base);
682         if (ret) {
683                 RTE_LOG(ERR, PMD, "failed to read %s", buf);
684                 goto out;
685         }
686
687         /* read number of available gpios */
688         snprintf(buf, sizeof(buf), "%s/gpiochip%d/ngpio", CNXK_GPIO_CLASS_PATH,
689                  gpiochip->num);
690         ret = cnxk_gpio_read_attr_int(buf, &gpiochip->num_gpios);
691         if (ret) {
692                 RTE_LOG(ERR, PMD, "failed to read %s", buf);
693                 goto out;
694         }
695         gpiochip->num_queues = gpiochip->num_gpios;
696
697         if (allowlist) {
698                 ret = cnxk_gpio_parse_allowlist(gpiochip);
699                 free(allowlist);
700                 allowlist = NULL;
701                 if (ret)
702                         goto out;
703         }
704
705         gpiochip->gpios = rte_calloc(NULL, gpiochip->num_gpios,
706                                      sizeof(struct cnxk_gpio *), 0);
707         if (!gpiochip->gpios) {
708                 RTE_LOG(ERR, PMD, "failed to allocate gpios memory");
709                 ret = -ENOMEM;
710                 goto out;
711         }
712
713         return 0;
714 out:
715         free(allowlist);
716         rte_free(gpiochip->allowlist);
717         rte_rawdev_pmd_release(rawdev);
718
719         return ret;
720 }
721
722 static int
723 cnxk_gpio_remove(struct rte_vdev_device *dev)
724 {
725         char name[RTE_RAWDEV_NAME_MAX_LEN];
726         struct cnxk_gpiochip *gpiochip;
727         struct rte_rawdev *rawdev;
728         struct cnxk_gpio *gpio;
729         int i;
730
731         RTE_SET_USED(dev);
732
733         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
734                 return 0;
735
736         cnxk_gpio_format_name(name, sizeof(name));
737         rawdev = rte_rawdev_pmd_get_named_dev(name);
738         if (!rawdev)
739                 return -ENODEV;
740
741         gpiochip = rawdev->dev_private;
742         for (i = 0; i < gpiochip->num_gpios; i++) {
743                 gpio = gpiochip->gpios[i];
744                 if (!gpio)
745                         continue;
746
747                 if (gpio->handler)
748                         cnxk_gpio_unregister_irq(gpio);
749
750                 cnxk_gpio_queue_release(rawdev, gpio->num);
751         }
752
753         rte_free(gpiochip->allowlist);
754         rte_free(gpiochip->gpios);
755         cnxk_gpio_irq_fini();
756         rte_rawdev_pmd_release(rawdev);
757
758         return 0;
759 }
760
761 static struct rte_vdev_driver cnxk_gpio_drv = {
762         .probe = cnxk_gpio_probe,
763         .remove = cnxk_gpio_remove,
764 };
765
766 RTE_PMD_REGISTER_VDEV(cnxk_gpio, cnxk_gpio_drv);
767 RTE_PMD_REGISTER_PARAM_STRING(cnxk_gpio,
768                 "gpiochip=<int> "
769                 "allowlist=<list>");