net/ena: make Tx completion timeout configurable
[dpdk.git] / drivers / raw / cnxk_gpio / cnxk_gpio_selftest.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4
5 #include <fcntl.h>
6 #include <sys/ioctl.h>
7 #include <sys/stat.h>
8 #include <unistd.h>
9
10 #include <rte_cycles.h>
11 #include <rte_rawdev.h>
12 #include <rte_rawdev_pmd.h>
13 #include <rte_service.h>
14
15 #include "cnxk_gpio.h"
16 #include "rte_pmd_cnxk_gpio.h"
17
18 #define CNXK_GPIO_BUFSZ 128
19
20 #define OTX_IOC_MAGIC 0xF2
21 #define OTX_IOC_TRIGGER_GPIO_HANDLER                                           \
22         _IO(OTX_IOC_MAGIC, 3)
23
24 static int fd;
25
26 static int
27 cnxk_gpio_attr_exists(const char *attr)
28 {
29         struct stat st;
30
31         return !stat(attr, &st);
32 }
33
34 static int
35 cnxk_gpio_read_attr(char *attr, char *val)
36 {
37         FILE *fp;
38         int ret;
39
40         fp = fopen(attr, "r");
41         if (!fp)
42                 return -errno;
43
44         ret = fscanf(fp, "%s", val);
45         if (ret < 0)
46                 return -errno;
47         if (ret != 1)
48                 return -EIO;
49
50         ret = fclose(fp);
51         if (ret)
52                 return -errno;
53
54         return 0;
55 }
56
57 #define CNXK_GPIO_ERR_STR(err, str, ...) do {                                  \
58         if (err) {                                                             \
59                 RTE_LOG(ERR, PMD, "%s:%d: " str " (%d)\n", __func__, __LINE__, \
60                         ##__VA_ARGS__, err);                                   \
61                 goto out;                                                      \
62         }                                                                      \
63 } while (0)
64
65 static int
66 cnxk_gpio_validate_attr(char *attr, const char *expected)
67 {
68         char buf[CNXK_GPIO_BUFSZ];
69         int ret;
70
71         ret = cnxk_gpio_read_attr(attr, buf);
72         if (ret)
73                 return ret;
74
75         if (strncmp(buf, expected, sizeof(buf)))
76                 return -EIO;
77
78         return 0;
79 }
80
81 #define CNXK_GPIO_PATH_FMT "/sys/class/gpio/gpio%d"
82
83 static int
84 cnxk_gpio_test_input(uint16_t dev_id, int base, int gpio)
85 {
86         char buf[CNXK_GPIO_BUFSZ];
87         int ret, n;
88
89         n = snprintf(buf, sizeof(buf), CNXK_GPIO_PATH_FMT, base + gpio);
90         snprintf(buf + n, sizeof(buf) - n, "/direction");
91
92         ret = rte_pmd_gpio_set_pin_dir(dev_id, gpio, CNXK_GPIO_PIN_DIR_IN);
93         CNXK_GPIO_ERR_STR(ret, "failed to set dir to input");
94         ret = cnxk_gpio_validate_attr(buf, "in");
95         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
96
97         ret = rte_pmd_gpio_set_pin_value(dev_id, gpio, 1) |
98               rte_pmd_gpio_set_pin_value(dev_id, gpio, 0);
99         if (!ret) {
100                 ret = -EIO;
101                 CNXK_GPIO_ERR_STR(ret, "input pin overwritten");
102         }
103
104         snprintf(buf + n, sizeof(buf) - n, "/edge");
105
106         ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio,
107                                         CNXK_GPIO_PIN_EDGE_FALLING);
108         CNXK_GPIO_ERR_STR(ret, "failed to set edge to falling");
109         ret = cnxk_gpio_validate_attr(buf, "falling");
110         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
111
112         ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio,
113                                         CNXK_GPIO_PIN_EDGE_RISING);
114         CNXK_GPIO_ERR_STR(ret, "failed to change edge to rising");
115         ret = cnxk_gpio_validate_attr(buf, "rising");
116         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
117
118         ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio, CNXK_GPIO_PIN_EDGE_BOTH);
119         CNXK_GPIO_ERR_STR(ret, "failed to change edge to both");
120         ret = cnxk_gpio_validate_attr(buf, "both");
121         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
122
123         ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio, CNXK_GPIO_PIN_EDGE_NONE);
124         CNXK_GPIO_ERR_STR(ret, "failed to set edge to none");
125         ret = cnxk_gpio_validate_attr(buf, "none");
126         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
127
128         /*
129          * calling this makes sure kernel driver switches off inverted
130          * logic
131          */
132         rte_pmd_gpio_set_pin_dir(dev_id, gpio, CNXK_GPIO_PIN_DIR_IN);
133
134 out:
135         return ret;
136 }
137
138 static int
139 cnxk_gpio_trigger_irq(int gpio)
140 {
141         int ret;
142
143         ret = ioctl(fd, OTX_IOC_TRIGGER_GPIO_HANDLER, gpio);
144
145         return ret == -1 ? -errno : 0;
146 }
147
148 static void
149 cnxk_gpio_irq_handler(int gpio, void *data)
150 {
151         *(int *)data = gpio;
152 }
153
154 static int
155 cnxk_gpio_test_irq(uint16_t dev_id, int gpio)
156 {
157         int irq_data, ret;
158
159         ret = rte_pmd_gpio_set_pin_dir(dev_id, gpio, CNXK_GPIO_PIN_DIR_IN);
160         CNXK_GPIO_ERR_STR(ret, "failed to set dir to input");
161
162         irq_data = 0;
163         ret = rte_pmd_gpio_register_irq(dev_id, gpio, rte_lcore_id(),
164                                         cnxk_gpio_irq_handler, &irq_data);
165         CNXK_GPIO_ERR_STR(ret, "failed to register irq handler");
166
167         ret = rte_pmd_gpio_enable_interrupt(dev_id, gpio,
168                                             CNXK_GPIO_PIN_EDGE_RISING);
169         CNXK_GPIO_ERR_STR(ret, "failed to enable interrupt");
170
171         ret = cnxk_gpio_trigger_irq(gpio);
172         CNXK_GPIO_ERR_STR(ret, "failed to trigger irq");
173         rte_delay_ms(1);
174         ret = *(volatile int *)&irq_data == gpio ? 0 : -EIO;
175         CNXK_GPIO_ERR_STR(ret, "failed to test irq");
176
177         ret = rte_pmd_gpio_disable_interrupt(dev_id, gpio);
178         CNXK_GPIO_ERR_STR(ret, "failed to disable interrupt");
179
180         ret = rte_pmd_gpio_unregister_irq(dev_id, gpio);
181         CNXK_GPIO_ERR_STR(ret, "failed to unregister irq handler");
182 out:
183         rte_pmd_gpio_disable_interrupt(dev_id, gpio);
184         rte_pmd_gpio_unregister_irq(dev_id, gpio);
185
186         return ret;
187 }
188
189 static int
190 cnxk_gpio_test_output(uint16_t dev_id, int base, int gpio)
191 {
192         char buf[CNXK_GPIO_BUFSZ];
193         int ret, val, n;
194
195         n = snprintf(buf, sizeof(buf), CNXK_GPIO_PATH_FMT, base + gpio);
196
197         snprintf(buf + n, sizeof(buf) - n, "/direction");
198         ret = rte_pmd_gpio_set_pin_dir(dev_id, gpio, CNXK_GPIO_PIN_DIR_OUT);
199         CNXK_GPIO_ERR_STR(ret, "failed to set dir to out");
200         ret = cnxk_gpio_validate_attr(buf, "out");
201         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
202
203         snprintf(buf + n, sizeof(buf) - n, "/value");
204         ret = rte_pmd_gpio_set_pin_value(dev_id, gpio, 0);
205         CNXK_GPIO_ERR_STR(ret, "failed to set value to 0");
206         ret = cnxk_gpio_validate_attr(buf, "0");
207         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
208         ret = rte_pmd_gpio_get_pin_value(dev_id, gpio, &val);
209         CNXK_GPIO_ERR_STR(ret, "failed to read value");
210         if (val)
211                 ret = -EIO;
212         CNXK_GPIO_ERR_STR(ret, "read %d instead of 0", val);
213
214         ret = rte_pmd_gpio_set_pin_value(dev_id, gpio, 1);
215         CNXK_GPIO_ERR_STR(ret, "failed to set value to 1");
216         ret = cnxk_gpio_validate_attr(buf, "1");
217         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
218         ret = rte_pmd_gpio_get_pin_value(dev_id, gpio, &val);
219         CNXK_GPIO_ERR_STR(ret, "failed to read value");
220         if (val != 1)
221                 ret = -EIO;
222         CNXK_GPIO_ERR_STR(ret, "read %d instead of 1", val);
223
224         snprintf(buf + n, sizeof(buf) - n, "/direction");
225         ret = rte_pmd_gpio_set_pin_dir(dev_id, gpio, CNXK_GPIO_PIN_DIR_LOW);
226         CNXK_GPIO_ERR_STR(ret, "failed to set dir to low");
227         ret = cnxk_gpio_validate_attr(buf, "out");
228         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
229         snprintf(buf + n, sizeof(buf) - n, "/value");
230         ret = cnxk_gpio_validate_attr(buf, "0");
231         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
232
233         snprintf(buf + n, sizeof(buf) - n, "/direction");
234         ret = rte_pmd_gpio_set_pin_dir(dev_id, gpio, CNXK_GPIO_PIN_DIR_HIGH);
235         CNXK_GPIO_ERR_STR(ret, "failed to set dir to high");
236         ret = cnxk_gpio_validate_attr(buf, "out");
237         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
238         snprintf(buf + n, sizeof(buf) - n, "/value");
239         ret = cnxk_gpio_validate_attr(buf, "1");
240         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
241
242         snprintf(buf + n, sizeof(buf) - n, "/edge");
243         ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio,
244                                         CNXK_GPIO_PIN_EDGE_FALLING);
245         ret = ret == 0 ? -EIO : 0;
246         CNXK_GPIO_ERR_STR(ret, "changed edge to falling");
247         ret = cnxk_gpio_validate_attr(buf, "none");
248         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
249
250         ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio,
251                                         CNXK_GPIO_PIN_EDGE_RISING);
252         ret = ret == 0 ? -EIO : 0;
253         CNXK_GPIO_ERR_STR(ret, "changed edge to rising");
254         ret = cnxk_gpio_validate_attr(buf, "none");
255         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
256
257         ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio, CNXK_GPIO_PIN_EDGE_BOTH);
258         ret = ret == 0 ? -EIO : 0;
259         CNXK_GPIO_ERR_STR(ret, "changed edge to both");
260         ret = cnxk_gpio_validate_attr(buf, "none");
261         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
262
263         /* this one should succeed */
264         ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio, CNXK_GPIO_PIN_EDGE_NONE);
265         CNXK_GPIO_ERR_STR(ret, "failed to change edge to none");
266         ret = cnxk_gpio_validate_attr(buf, "none");
267         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
268
269         snprintf(buf + n, sizeof(buf) - n, "/active_low");
270         ret = rte_pmd_gpio_set_pin_active_low(dev_id, gpio, 1);
271         CNXK_GPIO_ERR_STR(ret, "failed to set active_low to 1");
272         ret = cnxk_gpio_validate_attr(buf, "1");
273         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
274
275         ret = rte_pmd_gpio_get_pin_active_low(dev_id, gpio, &val);
276         CNXK_GPIO_ERR_STR(ret, "failed to read active_low");
277         if (val != 1)
278                 ret = -EIO;
279         CNXK_GPIO_ERR_STR(ret, "read %d instead of 1", val);
280
281         snprintf(buf + n, sizeof(buf) - n, "/value");
282         ret = rte_pmd_gpio_set_pin_value(dev_id, gpio, 1);
283         CNXK_GPIO_ERR_STR(ret, "failed to set value to 1");
284         ret = cnxk_gpio_validate_attr(buf, "1");
285         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
286
287         ret = rte_pmd_gpio_set_pin_value(dev_id, gpio, 0);
288         CNXK_GPIO_ERR_STR(ret, "failed to set value to 0");
289         ret = cnxk_gpio_validate_attr(buf, "0");
290         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
291
292         snprintf(buf + n, sizeof(buf) - n, "/active_low");
293         ret = rte_pmd_gpio_set_pin_active_low(dev_id, gpio, 0);
294         CNXK_GPIO_ERR_STR(ret, "failed to set active_low to 0");
295         ret = cnxk_gpio_validate_attr(buf, "0");
296         CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
297
298 out:
299         return ret;
300 }
301
302 int
303 cnxk_gpio_selftest(uint16_t dev_id)
304 {
305         struct cnxk_gpio_queue_conf conf;
306         struct cnxk_gpiochip *gpiochip;
307         char buf[CNXK_GPIO_BUFSZ];
308         struct rte_rawdev *rawdev;
309         unsigned int queues, i;
310         struct cnxk_gpio *gpio;
311         int ret, ret2;
312
313         rawdev = rte_rawdev_pmd_get_named_dev("cnxk_gpio");
314         if (!rawdev)
315                 return -ENODEV;
316         gpiochip = rawdev->dev_private;
317
318         queues = rte_rawdev_queue_count(dev_id);
319         if (queues == 0)
320                 return -ENODEV;
321
322         ret = rte_rawdev_start(dev_id);
323         if (ret)
324                 return ret;
325
326         fd = open("/dev/otx-gpio-ctr", O_RDWR | O_SYNC);
327         if (fd < 0)
328                 return -errno;
329
330         for (i = 0; i < queues; i++) {
331                 ret = rte_rawdev_queue_conf_get(dev_id, i, &conf, sizeof(conf));
332                 if (ret) {
333                         RTE_LOG(ERR, PMD,
334                                 "failed to read queue configuration (%d)\n",
335                                 ret);
336                         goto out;
337                 }
338
339                 RTE_LOG(INFO, PMD, "testing queue%d (gpio%d)\n", i, conf.gpio);
340
341                 if (conf.size != 1) {
342                         RTE_LOG(ERR, PMD, "wrong queue size received\n");
343                         ret = -EIO;
344                         goto out;
345                 }
346
347                 ret = rte_rawdev_queue_setup(dev_id, i, NULL, 0);
348                 if (ret) {
349                         RTE_LOG(ERR, PMD, "failed to setup queue (%d)\n", ret);
350                         goto out;
351                 }
352
353                 gpio = gpiochip->gpios[conf.gpio];
354                 snprintf(buf, sizeof(buf), CNXK_GPIO_PATH_FMT, gpio->num);
355                 if (!cnxk_gpio_attr_exists(buf)) {
356                         RTE_LOG(ERR, PMD, "%s does not exist\n", buf);
357                         ret = -ENOENT;
358                         goto release;
359                 }
360
361                 ret = cnxk_gpio_test_input(dev_id, gpiochip->base, conf.gpio);
362                 if (ret)
363                         goto release;
364
365                 ret = cnxk_gpio_test_irq(dev_id, conf.gpio);
366                 if (ret)
367                         goto release;
368
369                 ret = cnxk_gpio_test_output(dev_id, gpiochip->base, conf.gpio);
370 release:
371                 ret2 = ret;
372                 ret = rte_rawdev_queue_release(dev_id, i);
373                 if (ret) {
374                         RTE_LOG(ERR, PMD, "failed to release queue (%d)\n",
375                                 ret);
376                         break;
377                 }
378
379                 if (cnxk_gpio_attr_exists(buf)) {
380                         RTE_LOG(ERR, PMD, "%s still exists\n", buf);
381                         ret = -EIO;
382                         break;
383                 }
384
385                 if (ret2) {
386                         ret = ret2;
387                         break;
388                 }
389         }
390
391 out:
392         close(fd);
393
394         return ret;
395 }